feat(buyer): 更新电子卡券(E_COUPON)相关逻辑与展示

- 优化购物车与支付页面,确保电子卡券只能通过立即购买结算
- 增强商品详情页,添加限时折扣与第N件优惠展示
- 更新促销逻辑,支持拼团与积分购买选项
- 规范化商品类型与库存提示,提升用户体验
This commit is contained in:
田香琪
2026-08-02 13:55:19 +08:00
parent 1ae7ab3036
commit 1accdf5826
24 changed files with 920 additions and 311 deletions

View File

@@ -71,7 +71,7 @@
</div>
<!-- 限时秒杀 -->
<Promotion
v-if="!isECouponGoods && promotionMap['SECKILL']"
v-if="promotionMap['SECKILL']"
:time="promotionMap['SECKILL'].endTime"
></Promotion>
<!-- 商品详细 价格、优惠券、促销 -->
@@ -80,7 +80,7 @@
<!-- 秒杀价格 -->
<div
class="item-price-row"
v-if="skuDetail.promotionPrice && !isECouponGoods && promotionMap['SECKILL']"
v-if="skuDetail.promotionPrice && promotionMap['SECKILL']"
>
<p>
<span class="item-price-title" v-if="promotionMap['SECKILL']"
@@ -126,7 +126,7 @@
</div>
</div>
<!-- 优惠券展示 -->
<div class="item-price-coupon-row" v-if="!isECouponGoods && promotionMap['COUPON'].length">
<div class="item-price-coupon-row" v-if="promotionMap['COUPON'].length">
<div class="Ellipsis">
<span class="item-price-title">优 惠 券</span>
<span>
@@ -165,8 +165,38 @@
</div>
</div>
</div>
<!-- 限时折扣 -->
<div class="item-price-row" v-if="promotionMap['DISCOUNT']">
<p>
<span class="item-price-title">促&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;销</span>
<span class="item-promotion">限时折扣</span>
<span class="item-desc-pintuan" v-if="promotionMap['DISCOUNT'].discount">
享 {{ promotionMap["DISCOUNT"].discount }} 折
</span>
</p>
</div>
<!-- 第N件优惠 -->
<div class="item-price-row" v-if="promotionMap['NTH']">
<p>
<span class="item-price-title">促&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;销</span>
<span class="item-promotion">第N件</span>
<span class="item-desc-pintuan">
第 {{ promotionMap["NTH"].nthNum || promotionMap["NTH"].num }} 件优惠
</span>
</p>
</div>
<!-- 拼团 -->
<div class="item-price-row" v-if="promotionMap['PINTUAN']">
<p>
<span class="item-price-title">拼&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;团</span>
<span class="item-promotion">拼团价</span>
<span class="item-desc-pintuan" v-if="promotionMap['PINTUAN'].price">
{{ $filters.unitPrice(promotionMap["PINTUAN"].price, "¥") }}
</span>
</p>
</div>
<!-- 满减展示 -->
<div class="item-price-row" v-if="!isECouponGoods && promotionMap['FULL_DISCOUNT']">
<div class="item-price-row" v-if="promotionMap['FULL_DISCOUNT']">
<p>
<span class="item-price-title"
>促&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;销</span>
@@ -294,6 +324,14 @@
@click="addShoppingCartBtn"
>加入购物车</el-button
>
<el-button
class="goods-action-btn"
v-if="promotionMap['PINTUAN']"
:loading="loadingPintuan"
:disabled="isOutOfStock"
@click="pintuanBuy"
>拼团购买</el-button
>
<el-button
class="goods-action-btn"
:loading="loading1"
@@ -334,6 +372,11 @@ import {
isECoupon,
getECouponStock,
getECouponMaxBuyNum,
createEmptyPromotionMap,
resolveECouponCartType,
E_COUPON_CART_BUY_NOW,
E_COUPON_CART_PINTUAN,
E_COUPON_CART_POINTS,
} from "@/constants/goodsType";
export default {
@@ -377,15 +420,11 @@ export default {
specList: [],
}, // sku详情
goodsSpecList: this.detail.specs, // 商品spec
promotionMap: {
// 活动状态
SECKILL: null,
FULL_DISCOUNT: null,
COUPON: [],
}, // 促销活动
promotionMap: createEmptyPromotionMap(),
formatList: [], // 选择商品品类的数组
loading: false, // 立即购买loading
loading1: false, // 加入购物车loading
loadingPintuan: false,
isCollected: false, // 是否收藏
};
},
@@ -412,7 +451,7 @@ export default {
})
: [];
},
/** 卡密商品:禁加购/禁促销,仅立即购买,库存用 poolStock(FR-B-01 / P-06) */
/** 卡密商品:禁加购,仅立即购买;库存读 quantity(M-02 起支持促销) */
isECouponGoods() {
return isECoupon(this.skuDetail.goodsType);
},
@@ -539,21 +578,32 @@ export default {
});
},
buyNow() {
// 立即购买
this.startCheckout(E_COUPON_CART_BUY_NOW, "loading1");
},
pintuanBuy() {
this.startCheckout(E_COUPON_CART_PINTUAN, "loadingPintuan");
},
pointPay() {
this.startCheckout(E_COUPON_CART_POINTS, "loading");
},
startCheckout(action, loadingKey) {
const params = {
num: this.count,
skuId: this.skuDetail.id,
cartType: "BUY_NOW",
};
// 虚拟商品:cartType=VIRTUAL(核销码流程)
if (this.skuDetail.goodsType === "VIRTUAL_GOODS") {
params.cartType = "VIRTUAL";
} else if (this.isECouponGoods) {
params.cartType = resolveECouponCartType({
routeWay: this.$route.query.way,
action,
});
}
// E_COUPON 卡密商品:cartType 须保持 BUY_NOW,勿用 VIRTUAL(FR-B-01 / EC-24)
this.loading1 = true;
this[loadingKey] = true;
addCartGoods(params)
.then((res) => {
this.loading1 = false;
this[loadingKey] = false;
if (res.success) {
this.$router.push({
path: "/pay",
@@ -564,7 +614,7 @@ export default {
}
})
.catch(() => {
this.loading1 = false;
this[loadingKey] = false;
});
},
async collect() {
@@ -642,16 +692,20 @@ export default {
});
},
promotion() {
this.promotionMap = {SECKILL: null, FULL_DISCOUNT: null, COUPON: []};
// 格式化促销活动,返回当前促销的对象
if (!this.detail.promotionMap) return false;
let keysArr = Object.keys(this.detail.promotionMap);
this.promotionMap = createEmptyPromotionMap();
if (!this.detail || !this.detail.promotionMap) return false;
const keysArr = Object.keys(this.detail.promotionMap);
if (keysArr.length === 0) return false;
for (let i = 0; i < keysArr.length; i++) {
let key = keysArr[i].split("-")[0];
const key = keysArr[i].split("-")[0];
if (key === "COUPON") {
this.promotionMap[key].push(this.detail.promotionMap[keysArr[i]]);
if (!Array.isArray(this.promotionMap.COUPON)) {
this.promotionMap.COUPON = [];
}
this.promotionMap.COUPON.push(this.detail.promotionMap[keysArr[i]]);
} else if (Object.prototype.hasOwnProperty.call(this.promotionMap, key)) {
this.promotionMap[key] = this.detail.promotionMap[keysArr[i]];
} else {
this.promotionMap[key] = this.detail.promotionMap[keysArr[i]];
}