Appearance
Admin MIS 管理后台(v1)
统一前缀:
/api/v1/admin/82 use case / 12 子域(auth / dashboard / user / content / order / withdrawal / review / interpret / release / channel / config / misc) 契约权威 = 代码本体:src/app/admin/interface/api/*.py(16 路由模块) Swagger 调试:{BASE_URL}/docs
子域文档索引
| 子域 | Phase | action 数 | 路径前缀 | 文档 |
|---|---|---|---|---|
| auth(adminLogin) | P0+P1 | 3 | /api/v1/admin/auth/* | auth |
| dashboard | P0+P1 | 5 | /api/v1/admin/dashboard/* | dashboard |
| user(C 端用户管理) | P1 | 10 | /api/v1/admin/user/* | users |
| content(内容管理) | P2-A | 8 | /api/v1/admin/content/* | content |
| order(订单管理) | P2-B | 10 | /api/v1/admin/order/* | orders |
| withdrawal(提现审批) | P2-B | 6 | /api/v1/admin/withdrawal/* | withdrawals |
| review(评价审核) | P2-A | 5 | /api/v1/admin/review/* | reviews |
| interpret(解读报告) | P3 | 5 | /api/v1/admin/interpret/* | interpret |
| release(App 版本发布) | P3 | 5 | /api/v1/admin/release/* | release |
| channel(支付/分发渠道) | P3 | 5 | /api/v1/admin/channel/* | channels |
| config(系统/业务/灰度/告警配置) | P3 | 12 | /api/v1/admin/config/* | config |
| misc(审计/操作/错误日志/字典/通知) | P3 | 5 | /api/v1/admin/misc/* | misc |
| agreement(协议发布 — 用户协议/隐私政策) | — | 1 | /api/v1/admin/agreement/* | agreement |
| storage(存储管理 — STS 直传链路) | R11 | 7 | /api/v1/admin/storage/* | storage |
公共约定(先读这节,后面不重复)
统一信封
- 成功:
{ "code": "0", "msg": "ok", "data": { ... } }(HTTP 200) - 业务失败:HTTP 200 +
{ "code": "40201xxx", "msg": "...", "data": null }(例外见下方「HTTP 状态映射」) - RBAC 权限不足:HTTP 403 +
{ "code": "40201004", "msg": "..." }
鉴权(admin token — 独立体系)
admin 是独立鉴权,不复用 OAuth 用户 JWT:
POST /api/v1/admin/auth/login(username + password)→ 返回tokens {access, refresh}- 后续全部请求带
Authorization: Bearer <access_token> - token 缺失/无效 → HTTP 401 +
{ "code": "40201002" }
GET /api/v1/admin/auth/me 可查当前角色 + 权限清单(前端刷新 role / permissions 用)。
响应字段命名约定 ⚠️
- admin 响应 data 为 snake_case(
asdict()语义)—— 与 OAuth / user / device 域的 camelCase 不同! 例:page_size/total_users/banned_until/new_role - 例外:
GET /dashboard/overview的 P0 存量字段为 camelCase (totalAdmins/roleDistribution/recentLogins24h),与 snake_case 新字段混合返回 - 请求侧:POST body 与 Query 参数均为 snake_case(前端需注意转换)
RBAC 权限矩阵(ADR-0009)
三角色 × 26 权限位,编译期冻结(src/app/admin/domain/entities/permissions.py):
| 子域 | 权限位 | super | operator | it |
|---|---|---|---|---|
| auth | admin:login / admin:logout / admin:me | ✅ | ✅ | ✅ |
| dashboard | dashboard:read | ✅ | ✅ | ✅ |
| user | user:read / user:ban / user:write | ✅ | ✅ | ❌ |
| content | content:read / content:write / content:review | ✅ | ✅ | ❌ |
| order | order:read / order:write / order:refund | ✅ | ✅ | ❌ |
| withdrawal | withdrawal:read / withdrawal:approve | ✅ | ✅ | ❌ |
| review | review:read / review:approve | ✅ | ✅ | ❌ |
| interpret | interpret:read / interpret:write | ✅ | ✅ | ✅ |
| release | release:read / release:write | ✅ | ❌ | ✅ |
| channel | channel:read / channel:write | ✅ | ❌ | ✅ |
| config | config:read / config:write | ✅ | ❌ | ✅ |
| misc | misc:read | ✅ | ❌ | ✅ |
权限不足响应:HTTP 403 + { "code": "40201004", "msg": "权限不足: <permission>" } (40201004 与 NOT_FOUND 同码 Enum 别名 — 靠 HTTP 状态区分:403=权限不足 / 404=资源不存在)
HTTP 状态映射
默认业务失败 HTTP 200(与 OAuth 同源),仅以下例外:
| code | HTTP | 场景 |
|---|---|---|
40201001 PARAM_INVALID | 400 | 参数非法(缺字段 / 格式错 / confirm_text 错) |
40201002 UNAUTHORIZED | 401 | 未登录 / token 无效 |
40201003 FORBIDDEN / 40201006 USER_BANNED | 403 | 无权限 / 账号封禁 |
40201004 | 403(RBAC 守卫)/ 404(NOT_FOUND 路径) | 双语义 |
40201007 INTERNAL_ERROR | 500 | 内部错误 |
错误码区段(40201xxx)
| 区段 | 子域 | 范围 |
|---|---|---|
| 通用 | — | 40201001-099 |
| user | §6.3 | 40201101-105 |
| content | §6.4 | 40201201-208 |
| order | §6.5 | 40201301-310 |
| withdrawal | §6.6 | 40201401-406 |
| auth / review | §6.7 | 40201501-504(40201501 与 LOGIN_FAILED 同码别名) |
| interpret | §6.8 | 40201601-604 |
| release | §6.9 | 40201701-706 |
| channel | §6.9 | 40201721-723 |
| config / dictionary | §6.9 | 40201741-744 |
| misc | §6.9 | 40201761-762 |
高敏感操作(confirm_text 双二次确认)
以下 6 个操作要求请求体携带逐字常量 confirm_text,不匹配 → 40201001(400):
| 操作 | confirm_text 值 | 文档 |
|---|---|---|
order/refund | "REFUND" | orders |
order/adjust-price | "ADJUST" | orders |
withdrawal/payout | "PAYOUT" | withdrawals |
user/delete | "DELETE" | users |
release/rollback | "ROLLBACK" | release |
channel/close | "CLOSE" | channels |
审计留痕(ADR-0010)
全部写操作必写 audit log(operator_id + before / after + ip + ua)。 ip 取 X-Forwarded-For 首段(nginx 代理后),ua 取 User-Agent —— 由服务端自动采集,不在请求体里传。 回查入口:GET /api/v1/admin/misc/audit-logs。
路由注册顺序(P0 兼容)
main.py 中 dashboard_v1(P1 superset)先于 P0 dashboard 注册(FastAPI 首匹配胜出)—— /dashboard/overview 实际命中 v1 版本,P0 字段合并在其中返回。存量前端无感。
P0 legacy 端点(保留兼容)
| 端点 | 说明 | 文档 |
|---|---|---|
GET /api/v1/admin/dashboard/overview | P0 版被 v1 superset 覆盖(同路径) | dashboard |
GET /api/v1/admin/users | admin 账号列表(require_role super/operator) | users |
GET /api/v1/admin/tenants/me | 当前租户(X-Tenant-Schema / X-Tenant-ID header 解析) | 本页 |
GET /api/v1/admin/sms-mock | mock 短信列表(?limit=N,dev only;非 mock 模式返回 409) | 本页 |
GET /api/v1/admin/sms-mock/{phone} | 指定手机号的最近 mock 短信(⚠️ 仅 dev;无记录 404) | 本页 |
实现参考
- 完整设计:
docs/internal-wiki/architecture/admin-mis-design.md(§2 RBAC / §3 行动表 / §6 错误码 / §7 验收) - 模块结构 + 端口契约:
src/app/admin/CLAUDE.md