diff --git a/honey_box/pages/mall/detail.vue b/honey_box/pages/mall/detail.vue index fa681400..cbf01455 100644 --- a/honey_box/pages/mall/detail.vue +++ b/honey_box/pages/mall/detail.vue @@ -5,15 +5,20 @@ :statusBar="true" :border="false" @clickLeft="goBack"> - - - + + + - ¥ - {{ goodsInfo.price }} + + ¥ + {{ goodsInfo.price }} + + + {{ goodsInfo.price * 100 }}{{ $config.getAppSetting('currency2_name') }} + @@ -25,13 +30,13 @@ 库存 - {{ goodsInfo.goodslist_surplus_stock != null ? goodsInfo.goodslist_surplus_stock : (goodsInfo.stock || 0) }} + {{ goodsInfo.goodslist_surplus_stock != null ? goodsInfo.goodslist_surplus_stock : (goodsInfo.stock || 0) }} {{ $config.getAppSetting('currency2_name') }}{{ goodsInfo.price * 100 }} - (剩余:{{ orderData.score || 0 }}) + (剩余{{ orderData.score || 0 }}) @@ -51,13 +56,7 @@ - - - 商品详情 - - - - + @@ -205,6 +204,9 @@ export default { if (detailRes.status == 1 && detailRes.data) { // goods_detail 返回 { data: { goods: {...}, goodslist: [...] } } this.goodsInfo = detailRes.data.goods || detailRes.data; + // [调试日志] 详情页 - goods_detail 返回的库存数据 + const g = this.goodsInfo; + console.log(`[商城详情] goods_detail: id=${g.id} stock=${g.stock} sale_stock=${g.sale_stock} goodslist_stock=${g.goodslist_stock} goodslist_surplus_stock=${g.goodslist_surplus_stock} imgurl_banner=${g.imgurl_banner}`); } } catch (e) { console.log('获取商品详情失败', e); @@ -223,7 +225,13 @@ export default { this.orderData = res.data; // 用订单接口的数据补充商品信息(含 imgurl_detail、goods_describe 等) if (res.data.goods) { + // [调试日志] 详情页 - calcMallOrderMoney 返回的商品数据 + const mg = res.data.goods; + console.log(`[商城详情] mall_ordermoney: id=${mg.id} stock=${mg.stock} sale_stock=${mg.sale_stock} goodslist_surplus_stock=${mg.goodslist_surplus_stock} imgurl_banner=${mg.imgurl_banner}`); this.goodsInfo = { ...this.goodsInfo, ...res.data.goods }; + // [调试日志] 合并后的最终数据 + const fg = this.goodsInfo; + console.log(`[商城详情] 合并后: stock=${fg.stock} sale_stock=${fg.sale_stock} goodslist_surplus_stock=${fg.goodslist_surplus_stock} imgurl_banner=${fg.imgurl_banner}`); } const ext = res.data.goods_extend || {}; if (ext.pay_wechat == 1) { @@ -282,6 +290,8 @@ export default { const remainStock = this.goodsInfo.goodslist_surplus_stock != null ? this.goodsInfo.goodslist_surplus_stock : (this.goodsInfo.stock || 0) - (this.goodsInfo.sale_stock || 0); + // [调试日志] 兑换按钮 - 库存校验 + console.log(`[商城详情] 兑换校验: goodslist_surplus_stock=${this.goodsInfo.goodslist_surplus_stock} stock=${this.goodsInfo.stock} sale_stock=${this.goodsInfo.sale_stock} remainStock=${remainStock}`); if (remainStock <= 0) { this.$c.msg('库存不足,兑换失败'); return; @@ -396,6 +406,14 @@ export default { .price-section { padding: 30rpx 30rpx 10rpx; background: #fff; + display: flex; + justify-content: space-between; + align-items: baseline; + + .price-left { + display: flex; + align-items: baseline; + } .price-symbol { font-size: 28rpx; @@ -408,6 +426,12 @@ export default { color: #ff4d4f; font-weight: 600; } + + .price-coupon { + font-size: 26rpx; + color: #f5a623; + font-weight: 500; + } } .title-section { @@ -428,7 +452,6 @@ export default { .info-row { display: flex; - justify-content: space-between; align-items: center; } @@ -442,6 +465,10 @@ export default { color: #333; } + .info-value-inline { + margin-left: 20rpx; + } + .info-sub { color: #999; font-size: 24rpx; @@ -450,6 +477,7 @@ export default { .info-arrow { font-size: 36rpx; color: #999; + margin-left: auto; } } @@ -478,16 +506,16 @@ export default { background: #fff; .buy-btn { - width: 100%; - height: 88rpx; - background: #5CE5D5; - border-radius: 44rpx; + width: 694rpx; + height: 86rpx; + background: #03D8F4; + border-radius: 108rpx; display: flex; align-items: center; justify-content: center; font-size: 30rpx; font-weight: 500; - color: #333; + color: #fff; } } diff --git a/honey_box/pages/mall/index.vue b/honey_box/pages/mall/index.vue index 70bdea05..d6f5c1c5 100644 --- a/honey_box/pages/mall/index.vue +++ b/honey_box/pages/mall/index.vue @@ -194,6 +194,10 @@ export default { }); if (res.status == 1 && res.data && res.data.data) { + // [调试日志] 商城列表 - 接口返回的库存数据 + res.data.data.forEach(item => { + console.log(`[商城列表] id=${item.id} title=${item.title} stock=${item.stock} sale_stock=${item.sale_stock}`); + }); if (isWXPay) { if (this.datas.length > 0) { this.datas = this.datas.slice(0, this.datas.length); diff --git a/honey_box/pages/user/settings.vue b/honey_box/pages/user/settings.vue index 090a4e50..91361098 100644 --- a/honey_box/pages/user/settings.vue +++ b/honey_box/pages/user/settings.vue @@ -51,7 +51,7 @@ - + 注销账号 diff --git a/server/HoneyBox/src/HoneyBox.Admin.Business/Services/GoodsService.cs b/server/HoneyBox/src/HoneyBox.Admin.Business/Services/GoodsService.cs index 617660df..947c2648 100644 --- a/server/HoneyBox/src/HoneyBox.Admin.Business/Services/GoodsService.cs +++ b/server/HoneyBox/src/HoneyBox.Admin.Business/Services/GoodsService.cs @@ -550,6 +550,28 @@ public class GoodsService : IGoodsService // 更新商品奖品数量(按第一箱的奖品数计算) goods.PrizeNum = await _dbContext.GoodsItems.CountAsync(gi => gi.GoodsId == goodsId && gi.Num == 1); + + // 商城赏(type=10):同步 goods.stock/sale_stock 与 goods_items 汇总值 + // 商城赏的库存模型是多批次进货,每批一条 goods_items,需要保持 goods 表的汇总值同步 + if (goods.Type == 10) + { + var stockSummary = await _dbContext.GoodsItems + .Where(gi => gi.GoodsId == goodsId) + .GroupBy(gi => 1) + .Select(g => new + { + TotalStock = g.Sum(x => x.Stock), + TotalSold = g.Sum(x => x.Stock) - g.Sum(x => x.SurplusStock) + }) + .FirstOrDefaultAsync(); + + if (stockSummary != null) + { + goods.Stock = stockSummary.TotalStock; + goods.SaleStock = stockSummary.TotalSold; + } + } + goods.UpdatedAt = now; await _dbContext.SaveChangesAsync(); @@ -690,6 +712,28 @@ public class GoodsService : IGoodsService prize.IsLingzhu = (byte)request.IsLingzhu; prize.UpdatedAt = now; + // 商城赏(type=10):同步 goods.stock/sale_stock + var goods = await _dbContext.Goods.FirstOrDefaultAsync(g => g.Id == prize.GoodsId); + if (goods != null && goods.Type == 10) + { + var stockSummary = await _dbContext.GoodsItems + .Where(gi => gi.GoodsId == prize.GoodsId) + .GroupBy(gi => 1) + .Select(g => new + { + TotalStock = g.Sum(x => x.Stock), + TotalSold = g.Sum(x => x.Stock) - g.Sum(x => x.SurplusStock) + }) + .FirstOrDefaultAsync(); + + if (stockSummary != null) + { + goods.Stock = stockSummary.TotalStock; + goods.SaleStock = stockSummary.TotalSold; + goods.UpdatedAt = now; + } + } + var result = await _dbContext.SaveChangesAsync() > 0; _logger.LogInformation("更新奖品成功: PrizeId={PrizeId}, Title={Title}", prizeId, prize.Title); @@ -715,6 +759,24 @@ public class GoodsService : IGoodsService if (goods != null) { goods.PrizeNum = await _dbContext.GoodsItems.CountAsync(gi => gi.GoodsId == goodsId) - 1; + + // 商城赏(type=10):同步 goods.stock/sale_stock + if (goods.Type == 10) + { + var stockSummary = await _dbContext.GoodsItems + .Where(gi => gi.GoodsId == goodsId && gi.Id != prizeId) + .GroupBy(gi => 1) + .Select(g => new + { + TotalStock = g.Sum(x => x.Stock), + TotalSold = g.Sum(x => x.Stock) - g.Sum(x => x.SurplusStock) + }) + .FirstOrDefaultAsync(); + + goods.Stock = stockSummary?.TotalStock ?? 0; + goods.SaleStock = stockSummary?.TotalSold ?? 0; + } + goods.UpdatedAt = DateTime.Now; } diff --git a/server/HoneyBox/src/HoneyBox.Core/Services/OrderService.cs b/server/HoneyBox/src/HoneyBox.Core/Services/OrderService.cs index 157de6ce..bbeb4cb5 100644 --- a/server/HoneyBox/src/HoneyBox.Core/Services/OrderService.cs +++ b/server/HoneyBox/src/HoneyBox.Core/Services/OrderService.cs @@ -807,6 +807,17 @@ public class OrderService : IOrderService // 3. 获取商品扩展配置 var goodsExtend = await GetGoodsExtendAsync(request.GoodsId, goods.Type); + // 3.1 查询 goods_items 汇总库存(商城赏的真实库存在 goods_items 表) + var itemsStockSummary = await _dbContext.GoodsItems + .Where(gi => gi.GoodsId == request.GoodsId) + .GroupBy(gi => 1) + .Select(g => new + { + TotalStock = g.Sum(x => x.Stock), + SurplusStock = g.Sum(x => x.SurplusStock) + }) + .FirstOrDefaultAsync(); + // 4. 计算价格 // 商城订单使用积分(money2)支付,比例为1:100 var price = goods.Price; @@ -840,6 +851,8 @@ public class OrderService : IOrderService Price = goods.Price.ToString("0.##"), Stock = goods.Stock, SaleStock = goods.SaleStock, + GoodslistStock = itemsStockSummary?.TotalStock ?? 0, + GoodslistSurplusStock = itemsStockSummary?.SurplusStock ?? 0, Type = goods.Type, IsShouZhe = goods.IsShouZhe, PrizeNum = request.PrizeNum,