feat(shop): 优化VIP价格支持及线下付款兼容

- 结算页新增线下付款异常友好提示,避免支付配置中appid缺失错误
- 后端修复支付类型判断,防止线下付款仍试图创建微信支付订单
- 结算页默认支付方式调整为线下付款,货到付款选项注释
- 新增门店订单“修改金额”功能,支持弹窗输入新金额和修改原因
- 订单修改支持追加操作记录,接口复用updateShopOrder,无需新接口
- 重构多处页面和组件,使用响应式useVipStatus替代同步isVipMember缓存
- 新增OrderGoodsItem.price字段,下单时传VIP dealerPrice确保价格准确
- 购物车、商品详情、分类页、SkuSelector、商品卡片等支持动态VIP价格展示
- 修改购物车上下文calcPrice函数,响应VIP状态变更自动更新价格显示
- 提升前端VIP状态管理一致性,防止过期缓存导致VIP特权价格显示异常
- 验证构建通过,后端服务重启后生效线下付款修复和订单修改功能
This commit is contained in:
2026-07-15 02:45:19 +08:00
parent 747a2a1d3a
commit e47a0d3d3e
14 changed files with 556 additions and 41 deletions

View File

@@ -4,7 +4,7 @@ import Taro from '@tarojs/taro'
import type { ShopGoods, ShopGoodsSku } from '@/api/shop/shopGoods/model'
import type { ShopGoodsSpec } from '@/api/shop/shopGoodsSpec/model'
import Price from '@/components/common/Price'
import { isVipMember } from '@/utils/vip'
import { useVipStatus } from '@/hooks/useVipStatus'
import { getCompressedImageUrl } from '@/utils/image'
interface SkuSelectorProps {
@@ -49,6 +49,8 @@ const SkuSelector: React.FC<SkuSelectorProps> = ({
const [quantity, setQuantity] = useState(1)
const [showOverlay, setShowOverlay] = useState(false)
const [slideUp, setSlideUp] = useState(false)
// VIP 状态异步校验并更新缓存isVip 变化时触发重渲染
const { isVip } = useVipStatus()
// 控制动画
useEffect(() => {
@@ -157,7 +159,7 @@ const SkuSelector: React.FC<SkuSelectorProps> = ({
// 单规格商品无SKU列表 或 SKU列表为空数组
if ((!product?.goodsSkus || product.goodsSkus.length === 0) && product) {
// VIP 会员使用 dealerPrice 作为结算价
const vipPrice = isVipMember() && product.dealerPrice ? product.dealerPrice : undefined
const vipPrice = isVip && product.dealerPrice ? product.dealerPrice : undefined
const fakeSku: ShopGoodsSku = {
id: 0,
goodsId: product.goodsId!,
@@ -197,7 +199,7 @@ const SkuSelector: React.FC<SkuSelectorProps> = ({
// - product.price / sku.price : 实际"到手价"(详情页主价格)
// - product.dealerPrice : VIP 会员专享价
// VIP 会员优先使用 dealerPrice
const vipPrice = isVipMember() ? (product?.dealerPrice || selectedSku?.price) : null
const vipPrice = isVip ? (product?.dealerPrice || selectedSku?.price) : null
const currentPrice = vipPrice || selectedSku?.price || product?.price || selectedSku?.salePrice || product?.salePrice || '0'
const currentStock = selectedSku?.stock ?? product?.stock ?? 0
const currentImage = selectedSku?.image || product?.image || (product?.files?.split(',')[0]) || ''