199 lines
4.1 KiB
Plaintext
199 lines
4.1 KiB
Plaintext
<template>
|
|
<cl-page>
|
|
<cl-topbar title="搜索" />
|
|
|
|
<view class="search-page">
|
|
<view class="search-bar">
|
|
<cl-icon class="search-icon" name="search" :size="32" color="#999" />
|
|
<input class="search-input" v-model="keyword" type="text" placeholder="请输入商品名称" @confirm="doSearch" />
|
|
<view v-if="keyword.length > 0" class="clear-btn" @click="clearKeyword">
|
|
<cl-icon name="close-circle" :size="32" color="#999" />
|
|
</view>
|
|
</view>
|
|
|
|
<view v-if="searched == false" class="history-section">
|
|
<view class="section-header">
|
|
<text class="section-title">搜索历史</text>
|
|
<view class="clear-history" @click="clearHistory">
|
|
<cl-icon name="delete" :size="28" color="#999" />
|
|
</view>
|
|
</view>
|
|
<view class="history-tags">
|
|
<view v-for="(item, index) in history" :key="index" class="history-tag" @click="searchByHistory(item)">
|
|
<text>{{ item }}</text>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
|
|
<view v-if="searched == true" class="result-section">
|
|
<view class="product-grid">
|
|
<view
|
|
v-for="product in results"
|
|
:key="product.id"
|
|
class="product-card"
|
|
@click="goDetail(product.id)"
|
|
>
|
|
<image class="product-image" :src="product.mainImage != null ? product.mainImage : '/static/images/product.png'" mode="aspectFill" />
|
|
<view class="product-info">
|
|
<text class="product-name">{{ product.name }}</text>
|
|
<text class="product-price">¥{{ product.price }}</text>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
|
|
<cl-empty v-if="results.length === 0" text="未找到商品" />
|
|
</view>
|
|
</view>
|
|
</cl-page>
|
|
</template>
|
|
|
|
<script setup lang="uts">
|
|
import { ref } from 'vue';
|
|
import { router, useCool } from '@/cool';
|
|
|
|
const { service } = useCool();
|
|
|
|
const keyword = ref('');
|
|
const searched = ref(false);
|
|
const history = ref<string[]>(['番茄', '草莓', '苹果']);
|
|
const results = ref<any[]>([]);
|
|
|
|
function clearKeyword() {
|
|
keyword.value = '';
|
|
searched.value = false;
|
|
}
|
|
|
|
async function doSearch() {
|
|
if (keyword.value.trim().length == 0) return;
|
|
|
|
// 添加到历史
|
|
if (history.value.includes(keyword.value) == false) {
|
|
history.value.unshift(keyword.value);
|
|
if (history.value.length > 10) history.value.pop();
|
|
}
|
|
|
|
searched.value = true;
|
|
try {
|
|
const res = await service.nongchuang.product.list({ keyword: keyword.value });
|
|
if (res != null) {
|
|
const data = res as UTSJSONObject;
|
|
const list = data.getArray<any>("list");
|
|
results.value = list != null ? list : (res as any[]);
|
|
}
|
|
} catch (e) {
|
|
results.value = [];
|
|
}
|
|
}
|
|
|
|
function searchByHistory(item: string) {
|
|
keyword.value = item;
|
|
doSearch();
|
|
}
|
|
|
|
function clearHistory() {
|
|
history.value = [];
|
|
}
|
|
|
|
function goDetail(id: number) {
|
|
router.push({ path: '/pages/mall/detail', query: { id } });
|
|
}
|
|
</script>
|
|
|
|
<style lang="scss" scoped>
|
|
.search-page {
|
|
padding: 20rpx;
|
|
}
|
|
|
|
.search-bar {
|
|
display: flex;
|
|
flex-direction: row;
|
|
align-items: center;
|
|
padding: 16rpx 24rpx;
|
|
background: #f5f5f5;
|
|
border-radius: 40rpx;
|
|
|
|
.search-icon {
|
|
margin-right: 16rpx;
|
|
}
|
|
|
|
.search-input {
|
|
flex: 1;
|
|
font-size: 28rpx;
|
|
}
|
|
}
|
|
|
|
.history-section {
|
|
margin-top: 30rpx;
|
|
|
|
.section-header {
|
|
display: flex;
|
|
flex-direction: row;
|
|
justify-content: space-between;
|
|
align-items: center;
|
|
|
|
.section-title {
|
|
font-size: 28rpx;
|
|
font-weight: bold;
|
|
color: #333;
|
|
}
|
|
}
|
|
|
|
.history-tags {
|
|
display: flex;
|
|
flex-direction: row;
|
|
flex-wrap: wrap;
|
|
margin-top: 20rpx;
|
|
|
|
.history-tag {
|
|
padding: 12rpx 24rpx;
|
|
background: #f5f5f5;
|
|
border-radius: 30rpx;
|
|
font-size: 26rpx;
|
|
color: #666;
|
|
margin-right: 16rpx;
|
|
margin-bottom: 16rpx;
|
|
}
|
|
}
|
|
}
|
|
|
|
.result-section {
|
|
margin-top: 20rpx;
|
|
}
|
|
|
|
.product-grid {
|
|
display: flex;
|
|
flex-direction: row;
|
|
flex-wrap: wrap;
|
|
justify-content: space-between;
|
|
}
|
|
|
|
.product-card {
|
|
width: 48%;
|
|
background: #fff;
|
|
border-radius: 16rpx;
|
|
overflow: hidden;
|
|
margin-bottom: 20rpx;
|
|
|
|
.product-image {
|
|
width: 100%;
|
|
height: 240rpx;
|
|
}
|
|
|
|
.product-info {
|
|
padding: 16rpx;
|
|
|
|
.product-name {
|
|
font-size: 28rpx;
|
|
color: #333;
|
|
}
|
|
|
|
.product-price {
|
|
font-size: 32rpx;
|
|
font-weight: bold;
|
|
color: #ff4d4f;
|
|
margin-top: 10rpx;
|
|
}
|
|
}
|
|
}
|
|
</style>
|