管理员套餐管理页面对接文档

本文档用于前端设计与接入管理员“套餐管理”页面。

1. 适用范围

  • 仅管理员可访问
  • 所有接口都要求已登录
  • 接口前缀统一为 /api/console/admin/plans

普通用户调用这些接口时,后端返回:

  • 403 Forbidden

2. 套餐数据模型

{
  "id": "plan_xxx",
  "name": "pro-annual",
  "display_name": "专业版年度",
  "display_name_i18n": {
    "zh-CN": "专业版年度",
    "zh-TW": "專業版年度",
    "en": "Pro Annual"
  },
  "description": "按年订阅",
  "description_i18n": {
    "zh-CN": "按年订阅",
    "zh-TW": "按年訂閱",
    "en": "Annual subscription"
  },
  "price_cents": 129900,
  "currency": "USD",
  "cluster_quota": 5,
  "active": false,
  "created_at": "2026-03-30T10:30:00Z",
  "updated_at": "2026-03-30T10:35:00Z"
}

字段说明

  • name:机器名,后端会自动规范化为 slug,例如 pro annualpro-annual
  • display_name:默认展示名
  • display_name_i18n / description_i18n:三语文案,可为空对象,但建议前端始终传全
  • price_cents:价格分,前端自行格式化
  • currency:币种代码,后端会自动转成大写,缺省时默认为 CNY
  • cluster_quota:套餐允许创建的集群配额,必须大于 0
  • active:是否对普通用户可见;false 时不会出现在 /api/console/plans

3. 页面建议结构

建议拆成三部分:

  1. 套餐列表页
    • 展示名称、价格、币种、配额、状态、更新时间
  2. 创建 / 编辑弹窗
    • 支持中/繁/英文案输入
  3. 操作区
    • 新建
    • 编辑
    • 删除
    • 启用 / 停用(也可以直接走编辑接口修改 active

4. 接口清单

4.1 获取套餐列表

GET /api/console/admin/plans

响应

{
  "plans": [
    {
      "id": "plan_starter",
      "name": "starter",
      "display_name": "基础套餐",
      "price_cents": 19900,
      "currency": "CNY",
      "cluster_quota": 1,
      "active": true,
      "created_at": "2026-03-30T10:00:00Z",
      "updated_at": "2026-03-30T10:00:00Z"
    }
  ]
}

前端用途

  • 表格/卡片列表
  • 状态筛选
  • 编辑前初始化数据

4.2 获取单个套餐详情

GET /api/console/admin/plans/{planID}

响应

{
  "plan": {
    "id": "plan_xxx",
    "name": "pro-annual",
    "display_name": "专业版年度",
    "display_name_i18n": {
      "zh-CN": "专业版年度",
      "zh-TW": "專業版年度",
      "en": "Pro Annual"
    },
    "description": "按年订阅",
    "description_i18n": {
      "zh-CN": "按年订阅",
      "zh-TW": "按年訂閱",
      "en": "Annual subscription"
    },
    "price_cents": 129900,
    "currency": "USD",
    "cluster_quota": 5,
    "active": false,
    "created_at": "2026-03-30T10:30:00Z",
    "updated_at": "2026-03-30T10:35:00Z"
  }
}

前端用途

  • 编辑弹窗回填
  • 删除前确认展示

4.3 创建套餐

POST /api/console/admin/plans

请求体

建议前端始终传完整字段。

{
  "name": "pro annual",
  "display_name": "专业版年度",
  "display_name_i18n": {
    "zh-CN": "专业版年度",
    "zh-TW": "專業版年度",
    "en": "Pro Annual"
  },
  "description": "按年订阅",
  "description_i18n": {
    "zh-CN": "按年订阅",
    "zh-TW": "按年訂閱",
    "en": "Annual subscription"
  },
  "price_cents": 129900,
  "currency": "usd",
  "cluster_quota": 5,
  "active": true
}

必填约束

  • name
  • display_name
  • price_cents
  • cluster_quota
  • active

响应

  • 201 Created
  • 响应体:{ "plan": ... }

交互建议

  • 创建成功后直接把返回对象插入列表
  • name 输入允许自然语言,最终以返回结果中的 name 为准

4.4 更新套餐

PUT /api/console/admin/plans/{planID}

请求体

与创建接口相同,按“完整编辑表单”提交。

响应

  • 200 OK
  • 响应体:{ "plan": ... }

注意

  • 这是“整单更新”接口,前端不要只传局部字段
  • 若希望下架套餐,可把 active 设为 false

4.5 删除套餐

DELETE /api/console/admin/plans/{planID}

响应

  • 204 No Content

删除限制

以下情况后端会拒绝删除:

  • 删除系统内置 starter 套餐
  • 删除已经产生过订单的套餐

前端交互建议

  • 删除前弹确认框
  • 删除成功后从当前列表移除该项
  • 若返回 400,直接展示后端错误文案即可

5. 常见错误码

  • 400 Bad Request
    • 字段缺失
    • cluster_quota <= 0
    • 套餐名重复
    • 删除内置套餐
    • 删除已有订单的套餐
  • 403 Forbidden
    • 当前用户不是管理员
  • 404 Not Found
    • 套餐不存在

错误体统一为:

{
  "error": "plan already has orders and cannot be deleted"
}

6. 前端建议调用顺序

列表页初始化

  1. GET /api/console/admin/plans
  2. 渲染状态徽标:
    • active=true → 启用
    • active=false → 停用

新建

  1. 打开弹窗
  2. 提交 POST
  3. 成功后关闭弹窗并更新列表

编辑

  1. 打开弹窗前可先调 GET /{planID},也可直接用列表数据回填
  2. 提交 PUT
  3. 用返回的 plan 覆盖当前列表行

删除

  1. 打开确认框
  2. 提交 DELETE
  3. 成功后移除本地列表项

7. 建议前端封装

仓库内已经补充以下调用函数,可直接复用:

  • listAdminPlans()
  • getAdminPlan(planID)
  • createAdminPlan(input)
  • updateAdminPlan(planID, input)
  • deleteAdminPlan(planID)

位置:web/lib/console-api.ts