feat(ECR-010): Ops-E 系统运营;修复登出解绑;P2 Complete
ci / h5 (push) Canceled after 0s
ci / api (push) Canceled after 0s
ci / ess-docs (push) Canceled after 0s

落地管理员 RBAC/封禁/推送任务 stub,logout 解绑 device 并统一各页 ensureAccount,同时收口 P2 生日生成与状态文档。

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
jackyu66git
2026-08-11 18:54:59 +08:00
co-authored by Cursor
parent 0ee4d4f5ae
commit 5ceb3ce749
85 changed files with 2098 additions and 103 deletions
+170
View File
@@ -0,0 +1,170 @@
# Feature Spec: 运营系统(Ops-E
> Status: `Active` · Map: `§7 Phase E` · Phase: `Ops-E` · ECR: `ECR-010`
> 规范:[../feature-design.md](../feature-design.md)
> 上游:Ops-ADECR-006009
---
## 1. 功能定义
| 字段 | 内容 |
|---|---|
| Name | 运营系统 Ops-E |
| Purpose | 两角色 RBAC、C 端用户封禁、推送任务占位,支撑安全运维 |
| Business Goal | 限制写权限;可处置违规账号;预留推送运营入口(不下发) |
| In | Out |
|---|---|
| `admin_accounts.role``super` \| `ops` | 细粒度权限矩阵 / 动态权限表 |
| 用户封禁 / 解封(`users.status` active↔banned | 设备级 / IP 封禁 |
| `push_jobs` 草稿 CRUDdraft / cancelled | 真推送通道 · Worker · 站内信 |
| Admin API 动作级 403 + admin-h5 导航裁剪 | UGC · 真支付 |
---
## 2. 用户价值
1. **为何需要:** 全员等同 Admin 风险高;无封禁只能改库。
2. **完成后获得:** ops 可查可封可建推送草稿;写会员/定价/内容仅 super。
3. **为何付费:** N/A(内部工具)。
---
## 3. 用户角色
| Actor | 能力 |
|---|---|
| Admin `super` | 全部读写;Admin 账号列表与改角色 |
| Admin `ops` | 读全模块;封禁/解封;推送草稿;**不可**授予会员、改价、内容写、管 Admin |
| C 端 User `banned` | DeviceAuth / 会话拒绝(40310 |
| Guest | 无后台入口 |
---
## 4. 用户流程
```text
Admin 登录 → Me 含 role
ops:导航隐藏「定价写 / 内容写入口仍可见只读?按表:内容写否」
→ 用户详情 → 封禁 → C 端下次请求 40310
→ 推送页 → 新建 draft → 可 cancelled
super:另开「管理员」改 role
失败:无权限 403;未登录 401
```
---
## 5. 页面设计
| 路由 | 页面 | 说明 |
|---|---|---|
| `/users/:id` | UserDetailPage | 封禁 / 解封按钮 |
| `/push` | PushJobsPage | 列表 + 新建草稿 |
| `/admins` | AdminsPage | 仅 super:列表改角色 |
```text
AdminShell Nav += 推送 | 管理员(super)
```
---
## 6. 状态
| 态 | 要求 |
|---|---|
| Loading | 列表/详情请求中 |
| Empty | 无推送任务 / 无管理员(不应发生) |
| Error | 403 提示无权限;封禁失败可感知 |
| Normal | 状态与角色展示正确 |
---
## 7. 业务规则
1. Bootstrap / 存量 admin 默认 `super`
2. `ops` 调用 grant / PUT plan-prices / 内容写 → HTTP 403。
3. 封禁写 `users.status='banned'` + audit `user.ban`;解封 `active` + `user.unban`
4. 被封用户:Bearer 会话与 DeviceAuth 解析后均拒绝(40310);可撤销 sessions。
5. 推送仅 `draft`/`cancelled`;创建不下发。
6.`super``PATCH` admin role**禁止**降级最后一个 `super`HTTP 409 / code 40901)。
7. 推送标题非空且 ≤128 字符(rune),否则 400。
---
## 8. 数据
- `admin_accounts.role` varchar CHECK (`super`,`ops`) DEFAULT `super`
- `users.status` CHECK (`active`,`banned`)(存量补齐)
- `push_jobs(id, title, body, audience, status, created_by, created_at, updated_at)`
---
## 9. API
| Method | Path | 说明 |
|---|---|---|
| GET | `/api/v1/admin/me` | 响应含 `role` |
| POST | `/api/v1/admin/users/{id}/ban` | super+ops |
| POST | `/api/v1/admin/users/{id}/unban` | super+ops |
| GET | `/api/v1/admin/admins` | super |
| PATCH | `/api/v1/admin/admins/{id}` | super · body `{role}` |
| GET | `/api/v1/admin/push-jobs` | super+ops |
| POST | `/api/v1/admin/push-jobs` | super+ops · draft |
| PATCH | `/api/v1/admin/push-jobs/{id}` | 改文案或 cancelled |
既有写接口对 `ops` 返回 403。
---
## 10. 埋点
N/A(内部);审计日志覆盖封禁与角色变更。
---
## 11. 事件
| Audit action | 何时 |
|---|---|
| `user.ban` / `user.unban` | 封禁变更 |
| `admin.role_update` | 改角色 |
| `push_job.create` / `push_job.update` | 推送占位 |
---
## 12. 验收
**Given** ops 账号
**When** PUT plan-prices 或 grant membership
**Then** 403
**Given** 用户被 ban
**When** C 端带该 user 的 DeviceAuth 请求
**Then** 40310
**Given** 唯一 super
**When** PATCH role=ops
**Then** 40901,角色不变
**Given** push title 超 128 字
**When** POST push-jobs
**Then** 40055
---
## 13. AI 开发前检查
- [x] Spec §4/7/9/12
- [x] ECR-010 · BD-2026-010
---
## 14. Implementation Notes
| 项 | 内容 |
|---|---|
| Packages | `middleware` · `service/admin` · `AdminRepo` · admin-h5 |
| Migration | `000016_ops_system` |
| Label | Feature CompleteOps-E MVP |