diff --git a/docs/superpowers/plans/2026-09-01-account-package-cards-qr-pay.md b/docs/superpowers/plans/2026-09-01-account-package-cards-qr-pay.md new file mode 100644 index 0000000..2f4a1bf --- /dev/null +++ b/docs/superpowers/plans/2026-09-01-account-package-cards-qr-pay.md @@ -0,0 +1,490 @@ +# Account Package Cards + QR Pay Implementation Plan + +> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. + +**Goal:** 把账户中心流量/SIM 套餐选择改成卡片网格,并在支付成功后弹出可展示 AgPay 二维码、可手动刷新状态的独立支付弹窗。 + +**Architecture:** 全部落在 `src/views/AccountView/AccountView.vue`。保留 `t-radio-group`/`t-radio` 的选择语义,用 class + `:deep` 做成卡片网格;支付结果统一走 `openPaymentDialog(payment, meta)`,把 `providerPayload` 解析成 `` src,共用一个 `t-dialog`。刷新走已有 `GET /v1/account/payments/:id`。 + +**Tech Stack:** Vue 3 + TDesign Vue Next (`t-radio-group`/`t-radio`/`t-dialog`/`t-button`) + axios `request` + `urls.PAYMENTS`/`urls.PAYMENT` + +**Spec:** `docs/superpowers/specs/2026-09-01-account-package-cards-qr-pay-design.md` + +--- + +## File map + +| File | Responsibility | +|---|---| +| Modify: `src/views/AccountView/AccountView.vue` | 套餐卡片 DOM/样式;支付弹窗;payload 解析;购买/去支付/SIM 充值接线 | +| No new files | 保持与现有 AccountView 模式一致,不拆组件(单文件已承载账户域) | + +--- + +### Task 1: 套餐卡片网格(流量 + SIM) + +**Files:** +- Modify: `src/views/AccountView/AccountView.vue`(流量 radio 块约 L55–70;SIM radio 块约 L270–278;scoped style 尾部) + +- [ ] **Step 1: 改流量套餐 markup 为卡片结构** + +把: + +```vue + + + {{ pkg.name }} · {{ (Number(pkg.amountBytes) / 1024 / 1024 / 1024).toFixed(0) }}GB · {{ money(pkg.price) }} + / {{ pkg.validityDays }}天 + + +``` + +换成: + +```vue + + + + {{ pkg.name }} + {{ (Number(pkg.amountBytes) / 1024 / 1024 / 1024).toFixed(0) }} GB + {{ money(pkg.price) }} + 有效期 {{ pkg.validityDays }} 天 + 长期有效 + + + +``` + +可选增强(同一 Step):订单概要显示选中套餐价: + +```vue +{{ money(selectedTrafficPackage.price) }} +``` + +并加 computed: + +```js +const selectedTrafficPackage = computed(() => + trafficPackages.value.find((pkg) => String(pkg.id) === String(selectedTrafficPackageId.value)) || null +) +``` + +- [ ] **Step 2: 改 SIM 充值弹窗套餐为同一卡片结构** + +```vue + + + + {{ pkg.name }} + {{ pkg.amountGb }} GB + {{ moneyFromFen(pkg.saleFeeFen) }} + 有效期 {{ pkg.validityMonths }} 个月 + 按运营商规则 + + + +``` + +- [ ] **Step 3: 加卡片网格样式(scoped + recharge-modal 全局补丁)** + +在 `