fix(shop): 始终显示商品详情销量,避免销量隐藏

- 修改商品详情页销量展示,去除销量大于0的判断
- 销量字段不存在或为0时统一显示为0,提升信息一致性
- 列表页仍保持销量为0时不显示的原有逻辑
- 适配后端新增销量累加方式配置,支持显示和回滚逻辑调整
This commit is contained in:
2026-08-01 21:19:06 +08:00
parent f1c0349f64
commit f532b3923d
2 changed files with 30 additions and 3 deletions
+29
View File
@@ -0,0 +1,29 @@
# 2026-08-01 工作记录
## 销量累加方式后台可配置功能
- 用户需求:商品详情页缺销量字段(实际是销量为0时隐藏)、下单后销量不累计;希望后台可配置「销量累加方式」:默认支付累加、可选下单累加。
- 确认项:1) 销量为0展示「销量:0」;2) 用户已加 `shop_order.sales_accumulated` 字段;3) 取消订单回滚销量;4) 退款不扣减销量(本次预留结构,不实现);5) 列表页不显示已售0。
### 后端改动(guilixu-java
- `ShopGoodsMapper.addSaleCount`:改为 `GREATEST(IFNULL(sales,0)+saleCount, 0)`,支持负数回滚且不为负。
- `ShopOrder` 实体新增 `salesAccumulated` 字段(Integer,用户已加表字段)。
- `ShopSettingService` 新增 `getSalesAccumulateType()`(默认10=支付累加,20=下单累加),读取 order 分类下 `salesAccumulateType`
- `ShopOrderServiceImpl.updateGoodsSales(order, rollback)`:改造支持幂等(按 salesAccumulated 标记)+ 回滚(delta 取负)。`updateSingleGoodsSales` 接收 delta。
- `handlePaymentSuccess`:仅当配置=10 时才累加销量。
- 新增公开方法 `accumulateSalesOnOrderCreated(order)`(配置=20时下单累加)、`handlePaidSuccess(order)`(复用 handlePaymentSuccess,供非微信支付路径触发)、`rollbackSalesOnCancel(order)`
- `OrderBusinessService.createOrder`:保存订单商品后调 `accumulateSalesOnOrderCreated`;货到付款、余额支付分支补调 `handlePaidSuccess`(修复此前非微信支付不累加销量的 bug)。
- `ShopOrderServiceImpl.confirmOfflinePayment`:确认线下收款成功后调 `handlePaymentSuccess`(覆盖线下付款场景)。
- `OrderCancelServiceImpl.cancelOrder`:已累加销量时调 `rollbackSalesOnCancel` 回滚。
### 前端改动(xinlong-shop-taro
- `pages/shop/product-detail.tsx`:销量展示去掉 `>0` 判断,改为 `{product.sales || 0}` 始终显示。列表页(首页/分类/卡片)保持原逻辑(销量为0不显示)。
### 后台管理(guilixu-admin
- `views/shop/shopSetting/components/order.vue`:新增「销量累加方式」单选(10支付/20下单),默认值10load 解析 salesAccumulateType。保存复用 batchSaveShopSetting。
### 配置初始化
- 新增 `guilixu-java/sql/sales_accumulate_config.sql`(可选,代码默认已是10),并补充 `UPDATE shop_goods SET sales=0 WHERE sales IS NULL`
- 注意:数据库字段名需与实体 `salesAccumulated` 对应(下划线 `sales_accumulated`MyBatis-Plus 默认映射)。
### 编译
- `mvn -o compile` 通过(exit 0)。
+1 -3
View File
@@ -327,9 +327,7 @@ const ProductDetailPage: React.FC = () => {
</View> </View>
)} )}
<View className='flex gap-2 mt-2'> <View className='flex gap-2 mt-2'>
{Number(product.sales) > 0 && ( <Text className='text-xs text-gray-400'>: {product.sales || 0}</Text>
<Text className='text-xs text-gray-400'>: {product.sales}</Text>
)}
<Text className='text-xs text-gray-400'>: {product.stock || 0}</Text> <Text className='text-xs text-gray-400'>: {product.stock || 0}</Text>
{product.unitName && ( {product.unitName && (
<Text className='text-xs text-gray-400'>: {product.unitName}</Text> <Text className='text-xs text-gray-400'>: {product.unitName}</Text>