v0.0.11 — 在线充值(topup)全链路打通
用户可在控制台「我的余额」卡片直接发起在线充值,复用同一套微信 / 支付宝支付通道;后台新增独立的「充值」设置 Tab,管理员可配置快捷金额、自定义金额与换算比例;同步沉淀《AGENTS.md》开发规范并更新全语种 README。
中文
✨ 新增功能
后端(Go)
- 新增「在线充值」业务模块(
OrderTypeTopup=2):- 新增
model/topup.go,定义TopupPreset、CreateTopupOrderInput、TopupOrderPlanInfo等结构,提供CreateTopupOrder、ActivateTopupByOrder、ResolveTopupAmount、GetTopupSettings、SaveTopupSettings等业务函数。 - 复用
GenerateOrderNo("TP")生成充值订单号(TP 前缀),写入与套餐订单同一张orders表的type=2记录,节省一张表。 ActivateTopupByOrder幂等:订单已支付直接返回;激活时调IncreaseUserQuota加额度并RecordTopupLog,TODO标注退款时不回退 quota(待统一订单管理上线)。- 启动时通过
model.AutoMigrate自动建表,无需手写 DDL。
- 新增
- 新增充值系统设置键(
model/system_setting.go):topup.enabled(总开关)、topup.allow_custom(是否允许自定义金额)、topup.presets(JSON 数组:[{amount, bonus_quota}, ...])、topup.exchange_rate(默认1,1 元 = = 1 quota,仅作用于自定义金额)。- 分类常量
SystemSettingCategoryTopup = "topup"。
- 新增 HTTP 接口:
POST /api/topup/order(CreateTopupOrder,用户认证):参数{ amount, preset_amount, pay_method },前置校验开关 / 通道 / 金额,命中预设或自定义规则后写订单,复用controller/buildPayInfo拿 pay_url / qr_code。GET /api/setting/topup与PUT /api/setting/topup(GetTopupSettings/PutTopupSettings,Root 权限):读写上述 4 个 key。
- 支付回调按订单类型分发(
controller/payment.go::processNotify):order.Type == OrderTypeTopup→ 调ActivateTopupByOrder给用户加 quota;- 其余 → 调
ActivatePackageByOrder激活套餐。 MockPay(admin 测试接口)同步按 type 分发,提示文案分别显示「余额已到账」/「套餐已激活」。
前端(web/default-pro/)
- 新增可复用组件
components/TopupModal.vue:- props:
modelValue、settings、title;emits:update:modelValue、success、error、pay。 - 顶部「选择金额」chip 列表:依次渲染所有
settings.presets,最后一个 chip 固定为「自定义」(当settings.allow_custom=true时显示),点击后才显示金额输入框。 - 中部支付方式选择器(
pay-picker-item微信#07C160/ 支付宝#1677FF官方品牌色),复用 Plans.vue 既有样式。 - 底部「支付金额」+「确认充值」按钮;选中自定义但未填金额时禁用提交。
- props:
- 新增设置页
views/setting/TopupSetting.vue(root 可见):表单竖排三段:①总开关(enabled)②允许自定义金额(allow_custom)③自定义金额 1 元 = X quota(exchange_rate,默认1);快捷金额用<a-table>行行内编辑(amount/bonus_quota),支持新增 / 删除;提交前前端预校验金额重复(validateTopupPresets)。 - 新增路由
/setting/topup:router/index.js注册子路由,Setting.vue菜单新增「充值」项(root 可见,iconicon-subscribe-add)。 - 新增
api/topup.js:topupApi.createOrder({ amount, preset_amount, pay_method })。 - 扩展
api/setting.js:getTopup()/putTopup(data)。 - 新增
utils/topup.js纯函数工具:formatNumber/formatAmount/validateTopupPresets/calcCustomBonus,可在 Node 环境下用node:test单测。 - 仪表盘接入充值弹窗:
- 控制台
Dashboard.vue余额卡的「充值」按钮改为弹出TopupModal,点击前预拉/api/setting/topup+/api/payment/status,任一失败给出明确 toast;<a-modal>使用:visible+@update:visible(踩坑修复:曾误用:model-value,导致弹窗永远不显示)。 - 同时弹出二维码 / 转账信息
<a-modal,刷新余额(/api/user/self)。
- 控制台
- 订单管理表格新增「订单类型」列(
Orders.vue):套餐 / 充值 两种两色 chip(type-plan蓝 /type-topup橙),方便用户区分。 - 移除运营 Tab 内的「允许余额充值」占位开关(
OperationSetting.vue):该字段已迁移到新充值 Tab,UI 与后端GetPlanSettings/PutPlanSettings同步删除读写;DB 中旧plan.allow_topup行保留无害。 - 修复套餐界面硬编码套餐名白名单(
Plans.vue):删除VALID_PLAN_NAMES = ['lite','air','pro','max']过滤逻辑,改为显示后端返回的所有套餐(用户反映该过滤导致测试套餐不可见)。
🐛 问题修复
- 修复仪表盘充值按钮点击无反应:原
<TopupModal>在TopupModal.vue内部把 arco<a-modal>的可见性绑定到了:model-value,而 arco 的<a-modal>可见性属性是visible,导致v-model="topupModalVisible=true时弹窗永远不显示。已改为:visible="modelValue"+@update:visible="(v) => emit('update:modelValue', v)"。 - 修复充值按钮缓存导致的「管理员开启充值但仪表盘无反应」:原代码仅在
topupSettings.value为 null 时拉取一次,admin 刚开启充值但仪表盘缓存旧值时按钮不会再次请求。已改为每次点击都强制重新拉取/api/setting/topup,并把错误提示文案改成「请联系管理员在「设置-充值」中开启」。 - 修复
<a-spin>在 TopupSetting 设置页父容器宽度异常:补齐style="width: 100%"。 - 修复 TopupSetting 表单横排三列不对齐:改为
layout="vertical"三段竖排。
🚀 数据完整性
- 快捷金额金额不能重复:后端
model.SaveTopupSettings用seenAmounts map检测重复金额,重复时返回「快捷金额重复:XX 元已存在」并整体拒绝保存;前端utils/topup.js::validateTopupPresets提前预校验,避免一次无效请求。
📚 文档
- 新增项目根目录
AGENTS.md(480 行):面向 Agent / 贡献者的开发规范速查,覆盖 TL;DR / 项目结构 / 开发环境 / 提交规范(Conventional Commits + 中英双语 body + 一文件一 commit 粒度)/ 版本号 / 命名(topup全局统一)/ 注释约定(文件级 4 行注释 + 导出符号注释 + TODO/XXX + 修改时如何更新)/ 后端规范(响应格式、model 不依赖 Gin、订单号前缀 TB/UP/TP)/ 前端规范(arco<a-modal>用:visible而非:model-value、<a-spin>必须style="width:100%"、工具函数用 node:test)/ 数据库 / 踩坑清单 / 工作流程(先 Plan 模式输出方案再编码)。 - 同步更新
README.md与 7 个语言版本(readme/README.{en,zh-TW,ja,ko,ar,de,ru}.md):新增「💰 在线充值(余额)」功能亮点章节;订单与支付章节补充订单类型列 +processNotify分发说明;开发计划「在线充值」「充值设置中心」从规划移入已完成,新增「充值退款闭环」为进行中。
🔧 重构
- 移除运营 Tab 的
plan.allow_topup字段读写(controller/setting_payment.go):精简GetPlanSettings/PutPlanSettings返回结构,DB 行保留(不会主动删除)。 - 清理调试日志:移除为排查充值按钮不响应问题加在
Dashboard.vue::onRechargeClick的console.log。
⚠️ 升级注意事项
- 数据库迁移:新增 4 个
system_settings键(topup.enabled/topup.allow_custom/topup.presets/topup.exchange_rate),无需迁移脚本,AutoMigrate+ 首次调用会按需写入。 orders表复用:本次新增 type=2 的充值订单与既有 type=1 套餐订单存同一张表,无 DDL 变更。- 运营 Tab 「套餐运营」小节:UI 上不再有「允许余额充值(仅占位)」开关;如需启用充值,请进入设置 → 充值。
- 充值功能默认关闭(
topup.enabled未设置时为 false),管理员需到「设置 → 充值」手动开启并配置至少 1 个 preset 或允许自定义金额,前端充值按钮才会触发弹窗。 - 退款:本期不支持;充值订单
status=3仅标记,quota 不回退,待统一订单管理上线后补全。 - 前端构建:新增依赖
qrcode(已在 pnpm-lock.yaml),建议pnpm install && npm run build后发布。