feat(商品): 添加商品使用说明字段并支持商品名称搜索
在商品类型、存储和页面中添加`usageInstruction`字段,用于展示商品使用说明。同时,在商品列表页面新增搜索功能,支持根据商品名称进行筛选。
This commit is contained in:
parent
7318c773c1
commit
999625ccd0
|
@ -7,6 +7,7 @@ export type Goods = {
|
||||||
status: number,
|
status: number,
|
||||||
coverImg: string,
|
coverImg: string,
|
||||||
goodsDetail: string,
|
goodsDetail: string,
|
||||||
|
usageInstruction: string,
|
||||||
cellId: number
|
cellId: number
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -42,6 +42,8 @@ const currentProduct = computed(() =>
|
||||||
// 购物车弹窗控制
|
// 购物车弹窗控制
|
||||||
const showCartPopup = ref(false)
|
const showCartPopup = ref(false)
|
||||||
|
|
||||||
|
const searchQuery = ref('')
|
||||||
|
|
||||||
// 点击分类导航
|
// 点击分类导航
|
||||||
function handleCategoryClick(index: number) {
|
function handleCategoryClick(index: number) {
|
||||||
activeCategory.value = index
|
activeCategory.value = index
|
||||||
|
@ -99,8 +101,16 @@ function getCartItemCount(cellId: number) {
|
||||||
return item ? item.quantity : 0
|
return item ? item.quantity : 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function filterProductsByName(products: Product[], query: string) {
|
||||||
|
if (!query) return products
|
||||||
|
return products.filter(p =>
|
||||||
|
p.name.toLowerCase().includes(query.toLowerCase())
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
const currentProducts = computed(() => {
|
const currentProducts = computed(() => {
|
||||||
return categories.value.filter(c => c.label === labels.value[activeCategory.value].id)
|
const filteredByCategory = categories.value.filter(c => c.label === labels.value[activeCategory.value].id)
|
||||||
|
return filterProductsByName(filteredByCategory, searchQuery.value)
|
||||||
})
|
})
|
||||||
|
|
||||||
// 组件挂载时添加滚动监听
|
// 组件挂载时添加滚动监听
|
||||||
|
@ -143,6 +153,12 @@ watch(() => route.path, (newPath) => {
|
||||||
|
|
||||||
<!-- 右侧商品列表 -->
|
<!-- 右侧商品列表 -->
|
||||||
<div ref="scrollContainer" class="product-list">
|
<div ref="scrollContainer" class="product-list">
|
||||||
|
<van-search
|
||||||
|
v-model="searchQuery"
|
||||||
|
placeholder="搜索商品名称"
|
||||||
|
shape="round"
|
||||||
|
class="search-box"
|
||||||
|
/>
|
||||||
<div :ref="el => categoryRefs[0] = el as HTMLElement" class="category-section">
|
<div :ref="el => categoryRefs[0] = el as HTMLElement" class="category-section">
|
||||||
<van-cell v-for="product in currentProducts" :key="product.id" class="product-item">
|
<van-cell v-for="product in currentProducts" :key="product.id" class="product-item">
|
||||||
<template #icon>
|
<template #icon>
|
||||||
|
|
|
@ -154,41 +154,40 @@ async function handleSubmit() {
|
||||||
<div class="content-wrapper">
|
<div class="content-wrapper">
|
||||||
<!-- 原有商品列表等代码保持不动 -->
|
<!-- 原有商品列表等代码保持不动 -->
|
||||||
<van-cell-group class="product-list">
|
<van-cell-group class="product-list">
|
||||||
<van-cell v-for="item in cartItems" :key="item.product.id" class="product-item">
|
<template v-for="item in cartItems" :key="item.product.id">
|
||||||
<template #icon>
|
<van-cell class="product-item">
|
||||||
<van-image :src="item.product.image" width="60" height="60" class="product-image" />
|
<template #icon>
|
||||||
</template>
|
<van-image :src="item.product.image" width="60" height="60" class="product-image" />
|
||||||
|
</template>
|
||||||
|
|
||||||
<div class="product-info">
|
<div class="product-info">
|
||||||
<div class="product-name van-ellipsis">
|
<div class="product-name van-ellipsis">
|
||||||
{{ item.product.name }}
|
{{ item.product.name }}
|
||||||
|
</div>
|
||||||
|
<div class="price-row">
|
||||||
|
<span class="product-price">
|
||||||
|
¥{{ item.product.price.toFixed(2) }}
|
||||||
|
</span>
|
||||||
|
<span class="quantity">
|
||||||
|
×{{ item.quantity }}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="price-row">
|
</van-cell>
|
||||||
<span class="product-price">
|
<van-cell v-if="item.product.usageInstruction" class="usage-instruction">
|
||||||
¥{{ item.product.price.toFixed(2) }}
|
<div class="instruction-content">
|
||||||
</span>
|
使用说明:{{ item.product.usageInstruction }}
|
||||||
<span class="quantity">
|
|
||||||
×{{ item.quantity }}
|
|
||||||
</span>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</van-cell>
|
||||||
</van-cell>
|
</template>
|
||||||
<van-cell>
|
<van-cell>
|
||||||
<van-field
|
<van-field v-model="tel" label="手机号" placeholder="请输入联系电话" required class="tel-input" />
|
||||||
v-model="tel"
|
|
||||||
label="手机号"
|
|
||||||
placeholder="请输入联系电话"
|
|
||||||
required
|
|
||||||
class="tel-input"
|
|
||||||
/>
|
|
||||||
</van-cell>
|
</van-cell>
|
||||||
</van-cell-group>
|
</van-cell-group>
|
||||||
|
|
||||||
<van-cell-group class="contact-form">
|
<van-cell-group class="contact-form">
|
||||||
<van-cell v-if="!corpidLogin"
|
<van-cell v-if="!corpidLogin" :class="['payment-option', { selected: selectedPayment === 'wechat' }]"
|
||||||
:class="['payment-option', { selected: selectedPayment === 'wechat' }]"
|
@click="selectedPayment = 'wechat'">
|
||||||
@click="selectedPayment = 'wechat'"
|
|
||||||
>
|
|
||||||
<van-icon name="wechat" class="method-icon" />
|
<van-icon name="wechat" class="method-icon" />
|
||||||
<span class="method-label">微信支付</span>
|
<span class="method-label">微信支付</span>
|
||||||
<div class="empty"></div>
|
<div class="empty"></div>
|
||||||
|
@ -197,8 +196,7 @@ async function handleSubmit() {
|
||||||
|
|
||||||
<van-cell
|
<van-cell
|
||||||
:class="['payment-option', { selected: selectedPayment === 'balance', disabled: balance < totalPrice }]"
|
:class="['payment-option', { selected: selectedPayment === 'balance', disabled: balance < totalPrice }]"
|
||||||
@click="selectedPayment = 'balance'"
|
@click="selectedPayment = 'balance'">
|
||||||
>
|
|
||||||
<van-icon name="balance-o" class="method-icon" />
|
<van-icon name="balance-o" class="method-icon" />
|
||||||
<span class="method-label">
|
<span class="method-label">
|
||||||
余额支付
|
余额支付
|
||||||
|
|
|
@ -10,6 +10,7 @@ export interface Product {
|
||||||
image: string // 商品图片URL
|
image: string // 商品图片URL
|
||||||
label: number // 商品标签
|
label: number // 商品标签
|
||||||
cellId: number // 商品所在的格子ID
|
cellId: number // 商品所在的格子ID
|
||||||
|
usageInstruction: string // 商品使用说明
|
||||||
}
|
}
|
||||||
|
|
||||||
export const useProductStore = defineStore("product", () => {
|
export const useProductStore = defineStore("product", () => {
|
||||||
|
@ -48,7 +49,8 @@ export const useProductStore = defineStore("product", () => {
|
||||||
description: g.goodsDetail || "暂无描述",
|
description: g.goodsDetail || "暂无描述",
|
||||||
image: g.coverImg,
|
image: g.coverImg,
|
||||||
label: g.categoryId,
|
label: g.categoryId,
|
||||||
cellId: g.cellId
|
cellId: g.cellId,
|
||||||
|
usageInstruction: g.usageInstruction || ""
|
||||||
}))
|
}))
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("获取商品数据失败:", error)
|
console.error("获取商品数据失败:", error)
|
||||||
|
|
|
@ -27,6 +27,7 @@ declare module 'vue' {
|
||||||
VanNavBar: typeof import('vant/es')['NavBar']
|
VanNavBar: typeof import('vant/es')['NavBar']
|
||||||
VanPicker: typeof import('vant/es')['Picker']
|
VanPicker: typeof import('vant/es')['Picker']
|
||||||
VanPopup: typeof import('vant/es')['Popup']
|
VanPopup: typeof import('vant/es')['Popup']
|
||||||
|
VanSearch: typeof import('vant/es')['Search']
|
||||||
VanSidebar: typeof import('vant/es')['Sidebar']
|
VanSidebar: typeof import('vant/es')['Sidebar']
|
||||||
VanSidebarItem: typeof import('vant/es')['SidebarItem']
|
VanSidebarItem: typeof import('vant/es')['SidebarItem']
|
||||||
VanTabbar: typeof import('vant/es')['Tabbar']
|
VanTabbar: typeof import('vant/es')['Tabbar']
|
||||||
|
|
Loading…
Reference in New Issue