管理员套餐管理页面对接文档
本文档用于前端设计与接入管理员“套餐管理”页面。
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 annual→pro-annualdisplay_name:默认展示名display_name_i18n/description_i18n:三语文案,可为空对象,但建议前端始终传全price_cents:价格分,前端自行格式化currency:币种代码,后端会自动转成大写,缺省时默认为CNYcluster_quota:套餐允许创建的集群配额,必须大于 0active:是否对普通用户可见;false时不会出现在/api/console/plans
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
}
必填约束
namedisplay_nameprice_centscluster_quotaactive
响应
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. 前端建议调用顺序
列表页初始化
- 调
GET /api/console/admin/plans - 渲染状态徽标:
active=true→ 启用active=false→ 停用
新建
- 打开弹窗
- 提交
POST - 成功后关闭弹窗并更新列表
编辑
- 打开弹窗前可先调
GET /{planID},也可直接用列表数据回填 - 提交
PUT - 用返回的
plan覆盖当前列表行
删除
- 打开确认框
- 提交
DELETE - 成功后移除本地列表项
7. 建议前端封装
仓库内已经补充以下调用函数,可直接复用:
listAdminPlans()getAdminPlan(planID)createAdminPlan(input)updateAdminPlan(planID, input)deleteAdminPlan(planID)
位置:web/lib/console-api.ts