diff --git a/docs/superpowers/specs/2026-09-01-account-package-cards-qr-pay-design.md b/docs/superpowers/specs/2026-09-01-account-package-cards-qr-pay-design.md
new file mode 100644
index 0000000..b61dc69
--- /dev/null
+++ b/docs/superpowers/specs/2026-09-01-account-package-cards-qr-pay-design.md
@@ -0,0 +1,135 @@
+# 账户中心套餐卡片与支付二维码弹窗设计
+
+日期:2026-09-01
+范围:只改 `laic-frontend` 的 `AccountView`(及必要样式),不改后台、不改代理。
+
+## 背景
+
+账户中心流量购买与 SIM 充值已接上「选套餐 → 创建业务订单 → POST payments」主链路,但 UI 仍有两处缺口:
+
+1. 套餐选择仍是默认横排 `t-radio` 文本行,视觉上像未完成;卡片网格此前只定了方向,代码未落地。
+2. `POST /v1/account/payments` 已返回 `providerPayload`(实测为 AgPay 二维码 PNG),前端只 toast「请按返回凭证完成支付」,用户看不到码。
+
+## 目标
+
+1. 流量页与 SIM 充值弹窗的套餐选择改为**卡片网格**(名称 / 容量 / 价格 / 有效期分区;选中高亮)。
+2. 购买并支付 / 去支付成功后弹出**独立支付弹窗**:金额、业务类型、订单号、二维码、关闭;提供「我已支付,刷新状态」。
+3. 流量与 SIM 共用同一支付弹窗逻辑。
+4. 验收:本地看卡片样式;走通流量下单 → 弹窗出码;刷新状态可读支付/订单结果。
+
+## 非目标
+
+- 不引入微信支付 JS SDK / 原生扫码 SDK。
+- 不做自动轮询支付结果(仅手动刷新)。
+- 不改后端订单/支付协议、不修 `payment_idempotency_key` 空串唯一索引问题。
+- 不 seed SIM 卡/套餐;SIM 无数据时弹窗与卡片样式仍可用,但充值主路径可缺卡。
+- 不改发票、账号安全、概览其它区块。
+
+## 现状
+
+- 文件:`src/views/AccountView/AccountView.vue`
+- 流量套餐:`t-radio-group` + `t-radio`,文案单行 `名称 · GB · ¥x / 天`
+- SIM 套餐:充值弹窗内同样横排 radio
+- 支付:`createPayment` → `describePayment` toast;`urls.PAYMENT(id)` 已存在但未用于 UI 刷新
+- 原型参考:`jcWeb 3` 通信卡充值有 `carrier-package-grid` 按钮卡;流量页旧稿是按 GB 快捷量,不是套餐卡
+
+## 设计
+
+### 1. 套餐卡片网格
+
+保留 `t-radio-group` / `t-radio` 的无障碍选择与 `v-model`,只改结构与样式:
+
+```vue
+
+
+ {{ pkg.name }}
+ {{ amountLabel }}
+ {{ money(pkg.price) }}
+ 有效期 {{ pkg.validityDays }} 天
+
+
+```
+
+样式要点:
+
+- 网格:`repeat(auto-fill, minmax(140px, 1fr))`,间距 8–10px
+- 卡片:白底、细边框、圆角;选中态蓝边 + 浅蓝底(对齐现有 `--blue` / `#f3f8fc`)
+- 隐藏原生 radio 圆点,整卡可点
+- SIM 充值弹窗复用同一 class;字段映射:`amountGb`、`moneyFromFen(saleFeeFen)`、`validityMonths`
+
+右侧「订单概要」不变;选中卡片后摘要可显示当前套餐金额(可选增强:有则显示,无则保持现文案)。
+
+### 2. 支付二维码弹窗
+
+新增状态:
+
+```js
+payDialogOpen
+payDialogLoading
+payDialogRefreshing
+payDialogError
+payDialogMeta = {
+ businessType, // traffic_order | sim_recharge_order
+ businessOrderId,
+ transactionId,
+ amountText,
+ status,
+ qrSrc, // data:image/png;base64,... 或可直接用于
+ title
+}
+```
+
+触发:
+
+- `createTrafficOrderAndPay` / `payTrafficOrder`
+- SIM:`createSimRechargeAndPay` / `payPendingSimOrder`
+
+成功拿到 payment 后:
+
+1. 解析 `providerPayload` → `qrSrc`
+2. 打开 `t-dialog`(`header=微信支付` / `扫码支付`)
+3. toast 可保留一句短提示,或以弹窗为主、toast 降级为失败提示
+
+弹窗内容:
+
+- 金额(大字)
+- 业务说明(云媒体流量 / 通信卡充值)+ 订单号
+- 二维码 `
`;无图时展示错误文案与「重新拉起支付」
+- 底部:`关闭`、`我已支付,刷新状态`
+
+刷新:
+
+- `GET urls.PAYMENT(transactionId)`
+- 若 `status === 'paid' | 'success'`:toast 成功,关弹窗,刷新订单/余额/SIM
+- 若仍 `processing/unpaid`:更新文案「尚未到账,可稍后重试」
+- 同步刷新对应业务列表(`loadOrders` / `loadSim` / balance)
+
+### 3. providerPayload 解析
+
+实测 payload 为 PNG 二进制经 JSON 字符串化后的内容。前端兼容:
+
+1. 已是 `data:image/...` → 直接用
+2. 已是 `http(s)://` 或 `/...` URL → 直接用
+3. 看起来像 base64(无空白或标准 base64)→ `data:image/png;base64,` + 原文
+4. 其它:标记无图,弹窗提示「支付已创建,但二维码无法展示」
+
+不引入第三方 QR 库。
+
+## 验收
+
+1. 账户 → 云媒体流量:套餐为卡片网格,选中高亮,不再是单行默认 radio。
+2. 点击「购买并支付」:创建订单 + 支付成功后弹出二维码弹窗,图可见。
+3. 「去支付」同样弹窗。
+4. 「我已支付,刷新状态」会请求支付详情并刷新订单列表。
+5. SIM 充值弹窗套餐同为卡片;有支付结果时共用支付弹窗(无卡时不阻塞流量验收)。
+
+## 风险
+
+- 若后端偶发返回非 PNG/非 base64 的 payload,弹窗需有降级文案,不能白屏。
+- 取消订单后若仍写入空 `payment_idempotency_key`,可能再次误报「存在未付款订单」——属后端问题,本设计不修;测试前可清空串或取消后置 NULL。
+- 真机微信扫码入账依赖外部支付回调,本轮以「出码 + 刷新接口」为前端验收标准。