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