Skip to content

v0.0.15 — 管理员订单管理后台与订阅诊断端点 ​

管理员可在后台「订单」页面集中管理全部用户订单(套餐订阅 + 充值),支持多维筛选、状态流转(标记已付 / 退款 / 删除)与详情查看;同步新增 /api/diag/subscriptions 诊断端点,配套 UserPlan.Insert 防御性校验,方便排查 plan_id 异常问题。

中文 ​

✨ 新增功能 ​

后端(Go) ​

  • 新增管理员诊断端点 GET /api/diag/subscriptions(controller/diag.go,AdminAuth):
    • 拉取 user_plans 表前 100 行(GetAllUserPlans(0, 100, 0, -1)),逐行对比 orders 表中对应订单的 plan_id / type,并嵌入用户摘要。
    • 返回体含 total_user_plans(扫描行数)、missing_plan_id(plan_id<=0 的疑似脏数据行数)、rows(逐行明细:user_plan + order_no + order_plan_id + order_type + user)。
    • 用户信息复用 GetUsersBriefByIds 单次 WHERE IN 查询,无 N+1。
    • router/api.go 注册 /api/diag/subscriptions 路由(AdminAuth 中间件兜底)。
  • model/user 增加 UserBrief 与批量查询(model/user.go):
    • 新增 UserBrief 结构体(id / username / display_name 三个字段),用于列表嵌入场景。
    • 新增 GetUsersBriefByIds(ids []int) (map[int]*UserBrief, error):空 ids 短路不查 DB,否则单条 WHERE IN 查询,并对缺失 id 容错。
  • 订单管理接口支持多维过滤 + 用户嵌入(controller/order + model/order):
    • 新增 model.OrderAdminFilter 结构体与 applyTo helper;GetAllOrders / SearchOrders 改用 *OrderAdminFilter 参数。
    • model.Order 新增 User *UserBrief(gorm:"-")瞬时字段,admin 列表响应中作为 user 字段返回。
    • controller 新增 parseOrderAdminFilter:从 query 解析 type / status / source / user_id / plan_id / keyword 六个过滤维度。
    • status 空字符串表示「全部」,避免与 OrderStatusPending(0) 值重叠。
    • 新增 enrichOrdersWithUserBrief 批量补全 User 字段:单次 WHERE IN 查询全部目标 user id,无 N+1。
  • UserPlan.Insert 防御性校验拒绝 plan_id<=0(model/user_plan.go):
    • Insert 入口新增前置校验:PlanId <= 0 时直接返回错误 user_plan.plan_id 不能为空,杜绝脏数据写入。
    • 配套新增 model/subscription_defense_test.go,覆盖 Insert 与 ActivatePackageByOrder 两处防御路径。

前端(web/default-pro/) ​

  • 新增管理员订单列表页 views/admin/AdminOrders.vue:
    • 顶部欢迎条显示总条数 meta-chip。
    • 独立搜索卡:订单号 / 支付流水号搜索 + 类型(套餐 / 充值)/ 状态(待支付 / 已支付 / 已取消 / 已退款)/ 来源(用户自助 / 管理员)三个 <a-select> 下拉筛选 + 重置 / 刷新按钮。
    • 11 列 grid 行展示:ID / 订单号 / 类型 / 用户 / 套餐 / 金额 / 支付方式 / 状态 / 来源 / 创建时间 / 操作,用户列渲染嵌入的 user.display_name。
    • 操作列支持:查看详情 / 标记已付(status=0→1)/ 退款(status=1→3)/ 删除(root 限定,仅 status≠1 可删)。
    • 详情弹窗展示完整字段,并异步拉取最新 user 信息;标记已付弹窗选择 pay_method + 可选 pay_trade_no。
    • <a-spin> 设置 style="width:100%" 避免布局塌陷(AGENTS.md §10.4)。
  • 注册 /admin/orders 路由与侧边栏菜单:
    • router/index.js:注册 /admin/orders 路由;isAdminRoute 加入 AdminOrders 判断。
    • layouts/AdminLayout.vue:在渠道与兑换码之间插入「订单」菜单项(icon icon-storage)。
    • api/order.js 扩展:orderApi.list(params) 接受分页与多过滤参数;search 扩展支持 status / source / user_id / plan_id。
    • 新增 buildAdminParams helper,仅透传非零 / 非空字段,避免污染 query。

🐛 问题修复 ​

  • 修复 UserPlan.Insert 写入 plan_id=0 导致 admin 列表套餐列空白的脏数据问题:通过新增 PlanId<=0 前置校验防御(见上),异常来源追溯到 ActivatePackageByOrder 流程同样增加防御。
  • 修复 dashboard 与 admin 之间因缺乏统一订单管理入口导致的运维盲区:通过新增 AdminOrders 页面 + /api/diag/subscriptions 端点,提供集中可视化的订单与订阅诊断能力。

🧪 测试 ​

  • 新增 model/order_admin_filter_test.go(order_admin_filter_test 测试集):
    • setupOrderAdminTestDB 用 glebarez/sqlite 内存库 + gorm.AutoMigrate 建 users + orders 表。
    • seedUsersAndOrders 通用夹具 helper:每个 user 必须设 AccessToken / AffCode 以满足 unique 索引。
    • TestOrderAdminFilter_ApplyTo:验证零值全字段为 no-op。
    • TestGetAllOrders_FilterMatrix:9 个 subtest 覆盖 type / status / source / user_id / plan_id / keyword 五个过滤维度及组合。
    • TestSearchOrders_StatusFilter:验证搜索结果也按 status 过滤。
    • TestGetUsersBriefByIds_EmptyAndIn:验证空 ids 短路 + WHERE IN 查询 + 缺失 id 容错。
  • 新增 model/subscription_defense_test.go:覆盖 UserPlan.Insert 与 ActivatePackageByOrder 两处防御性校验路径。

📚 文档 ​

  • README.md 新增 QQ 群信息(979158b add qq group)。

⚠️ 升级注意事项 ​

  • 零数据库迁移:UserBrief 是新类型、Order.User 是 gorm:"-" 瞬时字段、OrderAdminFilter 仅是 controller 层的解析结构;不涉及表结构变更。
  • 新增 admin 路由:
    • GET /api/diag/subscriptions(AdminAuth):诊断端点,生产环境视情况可关闭或仅暴露给 root。
    • admin 订单接口 /api/order/ 与 /api/order/search 新增可选 query 参数 status / source / user_id / plan_id / keyword,向后兼容(不传则忽略)。
  • 防御性变更:UserPlan.Insert 与 ActivatePackageByOrder 在 plan_id<=0 时会直接拒绝;若有历史代码路径依赖此容错行为,需同步修复上游调用方(理论上不应有此类调用)。
  • 前端:新增 views/admin/AdminOrders.vue 与侧边栏菜单项;api/order.js 扩展,无破坏性变更。
  • 后端构建:go build ./...;测试运行 go test ./model/ ./controller/ ./middleware/。