feat(admin): Phase 0 平台超管基础 — is_platform_admin + IsPlatformAdmin + create_platform_admin(admin/admin123) + AdminAuditLog + Admin 后台外壳与路由 gating

后端:User.is_platform_admin + migration;权限类 IsPlatformAdmin;管理命令建 admin/admin123(幂等);
AdminAuditLog 模型 + log_admin_action() helper;me/login 对无团队超管优雅返回 team=null;UserSerializer 暴露标志。
前端:routes/admin 后台外壳(分组侧栏 + 概览 + 占位)、/admin 路由解析与 gating(超管直落、非超管纠回)、
侧栏平台入口、admin-page.css(仅 token)、IconKitSvg 补图标。
测试:accounts 11/11 单测过;无头 e2e _admin-p0.mjs 全断言过 + 0 console error;tsc+build 绿。

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
seaislee1209
2026-06-19 20:49:34 +08:00
co-authored by Claude Opus 4.8
parent 8fc3870fa3
commit 443023a1a9
21 changed files with 907 additions and 12 deletions
+64
View File
@@ -0,0 +1,64 @@
# Plan · 平台 Admin 后台(全量)+ 注册邀请码逻辑
> **范围:全做 —— 下面 Phase 0–9 全部,一块不落。** 参考 AirDrama 后台、复用其壳/权限/组件/审计;AirShelf 多商品 + 多资产类型 + 火山审核 + 模型供应商,更重。**视觉一律套 AirShelf restraint(冷灰 + 单橙),不抄 AirDrama 的样子。**
## 已拍板决策
- **范围:全铺**(Phase 09 全做)。
- **平台超管:加 `User.is_platform_admin`**;第一个超管 = **`admin` / `admin123`**(管理命令 bootstrap)。
- **质量词:全平台统一单层**(所有团队共用一套;团队单独覆盖以后再说)。
- **注册:邀请码优先**(码必填,`kind` 分流 create_team / join_team)。
## 复用 AirDrama(别重写,只换皮)
布局壳(AdminLayout 折叠侧栏+分组导航)· 权限类模式(IsSuperAdmin→IsPlatformAdmin)· 表格+行内操作/弹窗/手风琴/**标签编辑 UI**/状态徽章 · `AdminAuditLog` 审计日志 · API 分层(adminApi/teamApi)。
---
## Phase 0 · 基础(角色 + 壳 + 审计)
- 后端:`User.is_platform_admin` + migration;权限类 `IsPlatformAdmin`;管理命令 `create_platform_admin`**admin/admin123**;`AdminAuditLog` 模型 + 写日志 helper;`/api/auth/me/` 返回 `is_platform_admin`
- 前端:Admin 外壳 `routes/admin/`(AdminLayout 折叠侧栏+分组导航,套 restraint);路由 `/admin/*` + 超管 gating;侧栏分组:概览/团队·用户/内容/生成/财务/系统。
## Phase 1 · 注册邀请码逻辑(本线驱动 · 最优先)
- 后端:Invitation 加 `kind`(join_team/create_team)+ `team` 可空 + migration;端点 `validate-invite`(免登录验码→{有效,类型,团队名});RegisterSerializer 改**码必填**+ 按 kind 分流;**删「空码=开团队」**。
- 前端:注册页重做(码优先→验过才展开:加入=只读团队名+账号 / 开团队=团队名+账号),不暴露团队列表;邀请链接自动验;`api.validateInvite`
## Phase 2 · Admin 壳实功能:邀请码发放管理
- 后端:平台超管发 create_team 码 / 列所有码 / 撤销端点(替掉 Phase 1 的临时命令)。
- 前端:Admin「邀请码」页(发码弹窗 + 码列表 + 状态 + 复制邀请链接)。
## Phase 3 · 平台团队管理 + 平台用户管理
- 后端:列所有团队(名/owner/成员数/余额/状态)+ 启停 + 详情;列所有用户(跨团队)+ 启停 + 强制改密;全 `IsPlatformAdmin` + 写审计。
- 前端:Admin「团队」页 + 「用户」页(表格 + 启停 + 详情弹窗,复用 AirDrama 表格/弹窗/徽章)。
## Phase 4 · 质量词 Admin(平台单层)
- 后端:模型 `QualityWord`(stage + slot + text + sort,平台级单层无 team)+ 增删改查端点;生成侧(`build_person_frontal_prompt` 等)改读配置、无配置回落现写死值(兼容)。
- 前端:Admin「质量词」页,**复用 AirDrama 标签编辑 UI**(按 stage 分组 + 行内增删改 + 编辑模式开关防误删)。
## Phase 5 · 火山人像审核队列(AirShelf 特有)
- 后端:全局 person 资产按 `review_status`(空/processing/active绿/failed红)筛;批量送审 / 轮询 / 重试,复用现有 `assets/review.py` + `assets_client.py`
- 前端:Admin「资产审核」页(队列 + 绿/红盾徽章 + 批量送审/重试)。
## Phase 6 · AI 任务监控 + 成本异常
- 后端:全局 AITask 列表(按 status/team/type 筛)+ 详情(request/response payload)+ 成本 >> 预估告警 + 失败重投端点。
- 前端:Admin「任务监控」页(可筛表格 + 详情抽屉 + 异常标 + 重投)。
## Phase 7 · 计费审计 + 4 层额度策略
- 后端:全局 CreditLedger 浏览(按 type/team 筛)+ 手动调额(争议/补偿,写审计)+ QuotaPolicy(月/项目/单任务 4 层)编辑端点。
- 前端:Admin「计费审计」页(流水表 + 调额弹窗)+「额度策略」页。
## Phase 8 · 模型供应商管理(从 Django admin 搬前端)
- 后端:ModelProvider / ModelConfig 增删改启停 + 定价 + 默认模型选择端点(热插拔中转站)。
- 前端:Admin「模型供应商」页(provider/model 表格 + 编辑弹窗 + 启停 + 设默认)。
## Phase 9 · 收尾治理(商品 / 通知 / 项目监控 / 数据完整性)
- 商品治理(孤儿商品 / 分类管理)· 通知管理(全局 Notification 筛/批量)· 项目流水线监控(全局项目按 stage/status)· 数据完整性工具(孤儿记录检查 / 缓存)。
---
## 实施顺序
**0 → 1 → 2 → 3 → 4 → 5 → 6 → 7 → 8 → 9。** 每 Phase 后端先于前端;每块完即真跑验证再进下一块;**不 push**。Phase 0+1 先落(注册逻辑本线驱动、立刻见效)。
## 验证(每阶段)
- 注册:admin/admin123 登录→发 create_team 码→新用户凭码开团队当团管;团管发 join 码→成员加入;邀请链接自动验;**无码注册被拒**。
- 质量词:Admin 改某阶段质量词→重新生成→提示词用新词。
- 各 Admin 页:超管能进、非超管被拒;表格/弹窗/启停/审核/调额/热插拔真生效 + 写审计。
- 基线:tsc + build 全绿;既有团管页 / 生成链路零回归。
+40
View File
@@ -0,0 +1,40 @@
# 平台 Admin 后台 + 注册邀请码 · 落地进度
> 计划:`C:/Users/Air-work/.claude/plans/gleaming-sleeping-ullman.md`(Phase 09 全做)。
> 每个 Phase 走完「★测试底座」(后端单测 + 无头浏览器 e2e + tsc/build + 回归)才 commit。
> 全程本地、不 push;测试服 DB 可动。
---
## 测试基线(回归红线)
- `apps.accounts / apps.billing / apps.products`:全绿(Phase 0 后 15/15 OK)。
- `apps.projects`:**进 Phase 0 前已有 3 failures + 1 error**(均为 AI provider `image_edit` mock 相关,与本工程无关)——**非本次引入**,Phase 0 改动仅在 accounts + 前端,未触碰 projects/ai。后续 Phase 不得新增 fail。
---
## ✅ Phase 0 · 基础(角色 + 壳 + 审计)— 完成 2026-06-19
**后端**
- `User.is_platform_admin`(bool)+ migration `0004_user_is_platform_admin_adminauditlog`(已 apply 到测试 MySQL)。
- `apps/accounts/permissions.py` · `IsPlatformAdmin`(超管放行 / 普通拒 / 停用拒)。
- `apps/accounts/management/commands/create_platform_admin.py` · 建 **admin/admin123**(幂等;`--reset-password` 才重置;也置 `is_staff`)。已对测试 MySQL 执行,真账号可登。
- `AdminAuditLog` 模型(operator/operator_name/action/target_*/before/after/ip)+ `apps/accounts/audit.py` `log_admin_action()`(失败不阻断主流程)。
- `me` / `login` 对**无团队的平台超管**优雅返回 `team=null`(新增 `current_team_or_none`);`UserSerializer` 暴露 `is_platform_admin`
**前端**
-`routes/admin/admin-app.tsx`:超管后台外壳(折叠分组侧栏 6 组 11 项 + 顶栏 + 概览 + 占位页),全程复用 restraint 共享类。
- 路由:`route-config.ts` 解析 `/admin``/admin/<section>`;`App.tsx` 分流渲染 `AdminApp` + gating(超管无团队登录直落 /admin、非超管访问 /admin 纠回工作台)。
- `app-shell.tsx` 侧栏「平台」入口(仅超管可见)。
- `admin-page.css`(仅 token,无裸 hex)+ `IconKitSvg` 补 8 个 Lucide-line 图标。
**测试底座(全过)**
- 后端单测:`apps.accounts` **11/11 OK**(新增 `PlatformAdminTests`:建超管命令幂等/权限类放行拒绝/登录+me 返回标志且 team 为空/普通注册非超管)。
- 无头 e2e:`core/qa/visual-parity/_admin-p0.mjs` —— **全部断言通过 + 0 console error**:
- admin/admin123 真登录 → 落 /admin;
- 超管壳:6 分组 / 11 导航 / `[ PLATFORM ADMIN ]` 徽标 / 概览标题 / 点「邀请码」→ /admin/invites 占位「模块即将上线」;
- 普通用户访问 /admin → 纠回 /dashboard、admin 壳不渲染。
- 截图:`output/admin/p0-*.png`
- 类型/构建:`tsc --noEmit` + `npm run build` 全绿。
- 视觉:概览截图核对 —— 冷灰底 + 单橙 accent + 8px 圆角 + 准星,符合 design.md 克制调性。
**测试账号**:平台超管 `admin/admin123`(测试 MySQL 已建);普通 demo `airshelf/Restraint2026`