|
|
@@ -0,0 +1,82 @@
|
|
|
+# 我的优惠券:已领取券按钮修复(转赠+使用)+ 使用按券类型跳转 — 需求变更说明(2026-11-06)
|
|
|
+
|
|
|
+> **版本:** v1.0(主理人裁定,TDD 编排器入池依据)
|
|
|
+> **来源:** 用户 2026-11-06 需求 @skill:tdd-orchestrator "我的优惠券中,显示的是已经领取的,当前还显示为'立即领取',点击会报优惠券不存在。已经领取的优惠券应该是转赠和使用两个按钮,如果是指定商品的优惠券,则直接跳到商品下单页面,并自动选上优惠券,如果是全品类的,跳到商城;如果是会员券,跳到开通会员。"
|
|
|
+> **关联台账:** `docs/superpowers/specs/2026-11-06-coupon-claimed-actions.md`(实现任务书)
|
|
|
+> **状态:** ✅ 已完成开发 + 独立核验 + 已合入 cfclub(`1392c7e0b`)
|
|
|
+> **范围:** 仅小程序 `cfc-frontend/pages/profile-extra/coupons.vue` + `cfc-frontend/pages/shop/checkout/checkout.vue`;后端零改动
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+## 一、需求清单(原话)
|
|
|
+
|
|
|
+1. **修复 bug**:「我的优惠券」已领取的券仍显示「立即领取」,点击报「优惠券不存在」→ 应为**「转赠」+「使用」**两个按钮。
|
|
|
+2. **使用按钮按券类型跳转**:指定商品券 → 商品下单页并**自动选上优惠券**;全品类 → 商城;会员券 → 开通会员。
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+## 二、现状与根因(cfclub @ 2026-11-06)
|
|
|
+
|
|
|
+| 项 | 定位 | 关键事实 |
|
|
|
+|----|------|---------|
|
|
|
+| 券实例 vs 券模板 | `CouponService.toCouponVO`(L100-128) | 返回 `{id(券实例id=family_coupon.id), userCouponId, couponId(模板id), applicableTo, productId, ...}`——**`id` 与 `userCouponId` 同值、`couponId` 是模板 id** |
|
|
|
+| bug 根源 | `coupons.vue` L82-85 + L247-251 | `canClaim(coupon)` 对 AVAILABLE 券返回 true → 显示「立即领取」→ `handleClaim` 调 `claimCoupon(coupon.id)`,而 `coupon.id` 是**券实例 id** 非模板 id → 后端查无模板 → 报「优惠券不存在」 |
|
|
|
+| 券类型分发 | `coupons.vue` 数据 | `applicableTo`(PRODUCT/ALL/MEMBERSHIP)+ `productId`(指定商品券)已随 toCouponVO 返回 |
|
|
|
+| 确认订单页 | `checkout.vue` L644 `onLoad`、L806 `selectCoupon`、L615 `ownedCoupons` computed | 未处理 `options.couponId`;`ownedCoupons` 已按商品/金额/可用性过滤(PRODUCT 券按 `c.productId===currentProductId` 匹配) |
|
|
|
+| 目标路由 | 已有 | 确认订单 `/pages/shop/checkout/checkout`;商城 `/pages/shop/index/index`;开通会员 `/pages/membership/upgrade`;赠送券 `/pages/membership/gift-coupon` |
|
|
|
+| 商品详情/下单 | `productDetail({id})`(api.js L1684)+ `product-detail.vue` L773 | 详情页写 `checkoutItems` storage 后跳 checkout——本任务改用 coupons.vue 直接组装 checkoutItems |
|
|
|
+
|
|
|
+**结论:** 根因是「已领取券误显『立即领取』」+「claimCoupon 用错 id(券实例当模板)」。后端契约已完备,**纯前端**改动(2 文件)。
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+## 三、需求变更定义(目标态)
|
|
|
+
|
|
|
+### 变更 C1 · 已领取券显示「转赠」+「使用」双按钮(删除「立即领取」)
|
|
|
+- `coupons.vue` 模板 L82-89 替换:删除 `canClaim`/`handleClaim` 分支(及 `claimCoupon` import),已领取券(可用 tab、status AVAILABLE/空)显示 `<view class="coupon-actions"><button class="use-btn">使用</button><button class="gift-btn">转赠</button></view>`。
|
|
|
+- 已使用/已过期券不显示操作按钮(保持状态徽标)。
|
|
|
+
|
|
|
+### 变更 C2 · 「使用」按券类型分派
|
|
|
+- `useCoupon(coupon)`:
|
|
|
+ - **PRODUCT**(指定商品):`productDetail({id: coupon.productId})` 取商品 → `uni.setStorageSync('checkoutItems', [{productId, productName, coverImage, unitPrice, quantity:1}])` → `uni.navigateTo('/pages/shop/checkout/checkout?from=coupon&id=<商品id>&couponId=<coupon.id>')`(**couponId 必须用券实例 id**)。
|
|
|
+ - **ALL**(全品类):`uni.navigateTo('/pages/shop/index/index')`。
|
|
|
+ - **MEMBERSHIP**(会员券):`uni.navigateTo('/pages/membership/upgrade')`。
|
|
|
+ - 兜底(ASSESSMENT/其他/null):跳商城 `/pages/shop/index/index`。
|
|
|
+ - 未登录:先 `openLoginSheet()`;`productId` 为空:兜底跳商城。
|
|
|
+- `giftCoupon(coupon)`:`uni.navigateTo('/pages/membership/gift-coupon')`。
|
|
|
+
|
|
|
+### 变更 C3 · checkout 自动选券(from=coupon 场景)
|
|
|
+- `checkout.vue` `onLoad`:`this._autoCouponId = options && options.couponId ? parseInt(options.couponId) : null`。
|
|
|
+- `loadCoupons` 回调后 `autoSelectCoupon()`:在 `ownedCoupons`(已按商品/金额过滤)中匹配 `c.id === this._autoCouponId`(券实例 id)→ 命中 `selectCoupon(matched)` 触发服务端重算折扣;**未命中静默忽略**(minSpend 不满足/券失效/被过滤不报错不强制)。
|
|
|
+- 只影响 `from=coupon` 场景;其他入口(购物车/商品详情/扫码特价)行为不变。
|
|
|
+- **验收口径**:已领取券显示「转赠/使用」不报「优惠券不存在」;指定商品券使用→确认订单页+自动选中;全品类→商城;会员券→开通会员;转赠→赠送页;已用/过期无操作按钮;构建 exit 0。
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+## 四、TDD 入池
|
|
|
+
|
|
|
+| 能力键 | 变更 | requirement 溯源 | design 溯源 |
|
|
|
+|--------|------|-----------------|------------|
|
|
|
+| `coupon.claimed.actions` | C1+C2 | 本文档需求 1+2 | `CouponService.toCouponVO`(券实例 id 契约,已合入)+ `productDetail` + 目标路由 |
|
|
|
+| `coupon.checkout.autoselect` | C3 | 本文档需求 2 | `checkout.vue ownedCoupons/selectCoupon`(已合入) |
|
|
|
+
|
|
|
+> RED 契约以「已合入 origin/cfclub 的 `CouponService.toCouponVO` 券实例 id 契约」为准。
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+## 五、风险与注意事项(主理人核实)
|
|
|
+
|
|
|
+1. **跳转必须用 `coupon.id`(券实例 id)作为 checkout 的 couponId 参数**,勿用 `coupon.couponId`(模板 id,会导致后端查无)——实现已遵循,核验通过。
|
|
|
+2. **自动选券只匹配 ownedCoupons 内**(避免选到不可用券),未命中静默忽略。
|
|
|
+3. **`ownedCoupons` 对 MEMBERSHIP 券会过滤**(checkout 不用于会员券),会员券走「使用→开通会员」不经 checkout,无冲突。
|
|
|
+4. **CF 值兑换 tab 与领券中心不受影响**(getExchangeableCoupons/exchangeCouponByCf 保留;coupon-center.vue 独立)。
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+## 六、关联记录
|
|
|
+
|
|
|
+- **实现任务书**:`docs/superpowers/specs/2026-11-06-coupon-claimed-actions.md`
|
|
|
+- **开发**:commit `1392c7e0b`(仅 coupons.vue +111/-19、checkout.vue +22;后端零改动)
|
|
|
+- **核验**:主理人独立核验通过(双按钮 ✓ / 按类型分派 ✓ / 券实例 id ✓ / 自动匹配静默忽略 ✓)
|
|
|
+- **合入**:已入 cfclub `1392c7e0b`
|
|
|
+- **backlog**:`DOC-2026-11-06-coupon-claimed-actions`(done)
|