|
|
@@ -2,6 +2,8 @@
|
|
|
商品列表页
|
|
|
从店铺首页金刚区进入;支持搜索、分页触底加载、筛选弹窗(配送占位/价格/分类/场景)
|
|
|
按钮配色与店铺首页统一:#FF4D6D / linear-gradient(135deg, #FF8FA3, #FF4D6D)
|
|
|
+ 右侧购物车:单规格直接加购,多规格跳转详情选规格(与首页 goodsSection 一致)
|
|
|
+ 左下角悬浮购物车:展示当前店铺购物车数量,点击跳转 pages/home/cart
|
|
|
-->
|
|
|
<template>
|
|
|
<view class="goods-list-page">
|
|
|
@@ -47,12 +49,18 @@
|
|
|
>{{ tag }}</text>
|
|
|
</view>
|
|
|
<view class="bottom-row">
|
|
|
- <text class="price">
|
|
|
- <text class="price-symbol">¥</text>
|
|
|
- {{ formatPrice(item.price) }}
|
|
|
- <text class="price-suffix">起</text>
|
|
|
- </text>
|
|
|
- <text class="sold">已售{{ formatSold(item.totalSold) }}件</text>
|
|
|
+ <view class="price-sold-col">
|
|
|
+ <text class="price">
|
|
|
+ <text class="price-symbol">¥</text>
|
|
|
+ {{ formatPrice(item.price) }}
|
|
|
+ <text class="price-suffix">起</text>
|
|
|
+ </text>
|
|
|
+ <text class="sold">已售{{ formatSold(item.totalSold) }}件</text>
|
|
|
+ </view>
|
|
|
+ <!-- 加购:圆形底 + 白色购物车 SVG,与首页商品区一致 -->
|
|
|
+ <view class="cart-icon" @click.stop="handleCartClick(item)">
|
|
|
+ <zui-svg-icon icon="general-cartFull" :width="16" :height="16" color="#fff" style="margin-top: 6upx" />
|
|
|
+ </view>
|
|
|
</view>
|
|
|
</view>
|
|
|
</view>
|
|
|
@@ -62,6 +70,14 @@
|
|
|
<app-wrapper-empty title="暂无商品" :is-empty="true" />
|
|
|
</block>
|
|
|
|
|
|
+ <!-- 左下角悬浮购物车:白底圆形 + 角标数量,点击进店铺购物车页 -->
|
|
|
+ <view class="float-cart" @click="goToCart">
|
|
|
+ <zui-svg-icon icon="general-cartFull" :width="26" :height="26" color="#333" />
|
|
|
+ <view v-if="cartBadgeCount > 0" class="float-cart-badge">
|
|
|
+ <text class="float-cart-badge-text">{{ cartBadgeText }}</text>
|
|
|
+ </view>
|
|
|
+ </view>
|
|
|
+
|
|
|
<!-- 筛选弹窗 -->
|
|
|
<bottom-popup :show="filterShow" bgcolor="#f5f5f5" :height="0" @close="closeFilter">
|
|
|
<view class="filter-panel">
|
|
|
@@ -157,6 +173,7 @@ import AppWrapperEmpty from '@/components/app-wrapper-empty'
|
|
|
import BottomPopup from '@/components/plugin/bottom-popup'
|
|
|
import { getClass, getList, getUseCaseList } from '@/api/category'
|
|
|
import { list } from '@/mixins'
|
|
|
+import productMins from '@/mixins/cgProduct'
|
|
|
|
|
|
const PRICE_PRESETS = [
|
|
|
{ key: 'lt50', label: '50元以下', min: '', max: '50' },
|
|
|
@@ -189,9 +206,12 @@ export default {
|
|
|
AppWrapperEmpty,
|
|
|
BottomPopup
|
|
|
},
|
|
|
- mixins: [list],
|
|
|
+ mixins: [list, productMins],
|
|
|
data() {
|
|
|
return {
|
|
|
+ // 购物车 pageType;关闭 mixin 自动拉花材列表,本页只复用加购能力
|
|
|
+ pageType: 'cg',
|
|
|
+ autoLoad: false,
|
|
|
searchText: '',
|
|
|
searchTimer: null,
|
|
|
filterShow: false,
|
|
|
@@ -212,12 +232,55 @@ export default {
|
|
|
draft: emptyDraft()
|
|
|
}
|
|
|
},
|
|
|
+ computed: {
|
|
|
+ /** 悬浮购物车角标:扎数 + 支数,与详情页/店铺 tab 统计口径一致 */
|
|
|
+ cartBadgeCount() {
|
|
|
+ if (!this.selectList || !this.selectList.length) {
|
|
|
+ return 0
|
|
|
+ }
|
|
|
+ const count = this.allCount || {}
|
|
|
+ return (Number(count.bigLength) || 0) + (Number(count.smallLength) || 0)
|
|
|
+ },
|
|
|
+ /** 角标文案:超过 99 显示 99+ */
|
|
|
+ cartBadgeText() {
|
|
|
+ return this.cartBadgeCount > 99 ? '99+' : String(this.cartBadgeCount)
|
|
|
+ }
|
|
|
+ },
|
|
|
+ /** 从详情/购物车返回时刷新角标,避免仍显示旧数量 */
|
|
|
+ onShow() {
|
|
|
+ this.restoreCartFromStorage()
|
|
|
+ },
|
|
|
methods: {
|
|
|
init() {
|
|
|
this.applyRouteFilter()
|
|
|
+ // autoLoad=false 时需主动按店铺 account 恢复购物车,否则悬浮角标为 0
|
|
|
+ this.restoreCartFromStorage()
|
|
|
this.loadFilterOptions()
|
|
|
this.loadGoods()
|
|
|
},
|
|
|
+ /**
|
|
|
+ * 从本地缓存恢复当前店铺购物车到 Vuex
|
|
|
+ * 缓存 key 与分类/详情/购物车页一致:selectListcg_hd_{account}
|
|
|
+ * 空数组也要写入,避免从购物车清空后返回仍显示旧角标
|
|
|
+ */
|
|
|
+ restoreCartFromStorage() {
|
|
|
+ const account = (this.option && this.option.account) || uni.getStorageSync('account') || ''
|
|
|
+ if (!account) {
|
|
|
+ return
|
|
|
+ }
|
|
|
+ const cached = uni.getStorageSync('selectListcg_hd_' + account)
|
|
|
+ if (Array.isArray(cached)) {
|
|
|
+ this.setSelectInfoByType({ type: this.pageType || 'cg', info: cached })
|
|
|
+ }
|
|
|
+ },
|
|
|
+ /** 跳转店铺购物车页 */
|
|
|
+ goToCart() {
|
|
|
+ const account = (this.option && this.option.account) || uni.getStorageSync('account') || ''
|
|
|
+ const hdId = (this.option && this.option.hdId) || uni.getStorageSync('hdId') || 0
|
|
|
+ this.pageTo({
|
|
|
+ url: '/pages/home/cart?account=' + account + '&hdId=' + hdId
|
|
|
+ })
|
|
|
+ },
|
|
|
/**
|
|
|
* 解析路由带入的 filterType / filterValue
|
|
|
* type=2 商品ID列表、type=3 分类、type=4 场景(首页轮播/金刚区跳转)
|
|
|
@@ -405,6 +468,44 @@ export default {
|
|
|
this.pageTo({
|
|
|
url: `/pages/goods/detail?id=${item.id}&account=${account}&hdId=${hdId}`
|
|
|
})
|
|
|
+ },
|
|
|
+ /**
|
|
|
+ * 列表加购:单规格(普通)直接加入购物车;多规格跳转详情选规格后再加购
|
|
|
+ * @param {Object} item 列表商品行(含 specEnabled / price)
|
|
|
+ */
|
|
|
+ handleCartClick(item) {
|
|
|
+ if (!item || !item.id) return
|
|
|
+ // 多规格:进入详情页选择规格
|
|
|
+ if (Number(item.specEnabled) === 1) {
|
|
|
+ this.goDetail(item)
|
|
|
+ return
|
|
|
+ }
|
|
|
+ if (!(Number(item.price) > 0)) {
|
|
|
+ this.$msg('商品还没有价格哦')
|
|
|
+ return
|
|
|
+ }
|
|
|
+ const account = (this.option && this.option.account) || uni.getStorageSync('account') || ''
|
|
|
+ const hdId = (this.option && this.option.hdId) || uni.getStorageSync('hdId') || ''
|
|
|
+ // rememberProduct 依赖 option.account,保证按店铺维度记忆购物车
|
|
|
+ if (!this.option) {
|
|
|
+ this.option = { account, hdId }
|
|
|
+ } else if (!this.option.account) {
|
|
|
+ this.option.account = account
|
|
|
+ }
|
|
|
+ const goods = {
|
|
|
+ ...item,
|
|
|
+ priceType: item.priceType != null ? item.priceType : 1,
|
|
|
+ cover: item.smallCover || item.cover,
|
|
|
+ smallCover: item.smallCover || item.cover
|
|
|
+ }
|
|
|
+ const ok = this.addBouquetToCart(goods, null, 1)
|
|
|
+ if (ok) {
|
|
|
+ uni.showToast({
|
|
|
+ title: '已加入购物车',
|
|
|
+ icon: 'none',
|
|
|
+ duration: 1500
|
|
|
+ })
|
|
|
+ }
|
|
|
}
|
|
|
},
|
|
|
async onPullDownRefresh() {
|
|
|
@@ -430,7 +531,46 @@ export default {
|
|
|
.goods-list-page {
|
|
|
min-height: 100vh;
|
|
|
background: #f5f5f5;
|
|
|
- padding-bottom: 40upx;
|
|
|
+ /* 底部预留悬浮购物车高度,避免列表最后一项被遮挡 */
|
|
|
+ padding-bottom: calc(140upx + env(safe-area-inset-bottom));
|
|
|
+}
|
|
|
+
|
|
|
+/* 左下角悬浮购物车:白底圆形阴影 + 右上角数量红点 */
|
|
|
+.float-cart {
|
|
|
+ position: fixed;
|
|
|
+ left: 32upx;
|
|
|
+ bottom: calc(48upx + env(safe-area-inset-bottom));
|
|
|
+ z-index: 100;
|
|
|
+ width: 92upx;
|
|
|
+ height: 92upx;
|
|
|
+ border-radius: 50%;
|
|
|
+ background: #fff;
|
|
|
+ box-shadow: 0 8upx 24upx rgba(0, 0, 0, 0.12);
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ justify-content: center;
|
|
|
+}
|
|
|
+
|
|
|
+.float-cart-badge {
|
|
|
+ position: absolute;
|
|
|
+ top: -4upx;
|
|
|
+ right: -4upx;
|
|
|
+ min-width: 36upx;
|
|
|
+ height: 36upx;
|
|
|
+ padding: 0 8upx;
|
|
|
+ border-radius: 18upx;
|
|
|
+ background: #FF3B30;
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ justify-content: center;
|
|
|
+ box-sizing: border-box;
|
|
|
+}
|
|
|
+
|
|
|
+.float-cart-badge-text {
|
|
|
+ font-size: 20upx;
|
|
|
+ color: #fff;
|
|
|
+ line-height: 1;
|
|
|
+ font-weight: 600;
|
|
|
}
|
|
|
|
|
|
.search-bar {
|
|
|
@@ -553,12 +693,19 @@ export default {
|
|
|
|
|
|
.bottom-row {
|
|
|
display: flex;
|
|
|
- align-items: baseline;
|
|
|
+ align-items: center;
|
|
|
justify-content: space-between;
|
|
|
margin-top: auto;
|
|
|
padding-top: 12upx;
|
|
|
}
|
|
|
|
|
|
+.price-sold-col {
|
|
|
+ flex: 1;
|
|
|
+ min-width: 0;
|
|
|
+ display: flex;
|
|
|
+ flex-direction: column;
|
|
|
+}
|
|
|
+
|
|
|
.price {
|
|
|
font-size: 34upx;
|
|
|
font-weight: 700;
|
|
|
@@ -577,10 +724,24 @@ export default {
|
|
|
}
|
|
|
|
|
|
.sold {
|
|
|
+ margin-top: 4upx;
|
|
|
font-size: 22upx;
|
|
|
color: #999;
|
|
|
}
|
|
|
|
|
|
+/* 加购按钮:圆形底 + 白色购物车,与首页商品区一致 */
|
|
|
+.cart-icon {
|
|
|
+ flex-shrink: 0;
|
|
|
+ margin-left: 16upx;
|
|
|
+ width: 52upx;
|
|
|
+ height: 52upx;
|
|
|
+ border-radius: 50%;
|
|
|
+ background: #FF4D6D;
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ justify-content: center;
|
|
|
+}
|
|
|
+
|
|
|
.list-end {
|
|
|
padding: 30upx 0 20upx;
|
|
|
text-align: center;
|