feat: auto committed

This commit is contained in:
SpecialX
2026-07-10 15:05:39 +08:00
parent 9ba368477d
commit 02d09c47fa
3 changed files with 424 additions and 80 deletions

View File

@@ -1,49 +1,71 @@
# admin-portal 对接契约
> 负责人ai16
> 关联:[matrix.md](./matrix.md)、[iam.proto](../../../packages/shared-proto/proto/iam.proto)、[events.proto](../../../packages/shared-proto/proto/events.proto)
> 关联:[matrix.md](./matrix.md)、[coord.md](./coord.md)、[ai-allocation.md §5 ai16](../../ai-allocation.md)、[iam.proto](../../../packages/shared-proto/proto/iam.proto)、[events.proto](../../../packages/shared-proto/proto/events.proto)
> 说明:本契约基于 GraphQLARB-001 admin 命名空间)+ 端口 4003 + ai16 归属,作为 01/02 文档修订基准(见 [objections/admin-portal_issue.md](../objections/admin-portal_issue.md) ISSUE-001~006
---
## §1 我提供什么(对外接口)
### 1.1 gRPC 接口(如有)
### 1.1 gRPC 接口
无。admin-portal 是前端微前端 Remote。
无。admin-portal 是前端微前端 Remote,不提供 gRPC
### 1.2 HTTP 端点(如有
### 1.2 前端路由MF Remote 暴露给 Shell 动态加载
| Method | Path | 用途 | 认证 |
| ------ | ----------- | ---------------- | --------------------- |
| GET | / | 管理后台首页 | JWT 必需 + admin 角色 |
| GET | /users | 用户管理 | JWT 必需 + admin |
| GET | /roles | 角色权限管理 | JWT 必需 + admin |
| GET | /classes | 班级管理(全局) | JWT 必需 + admin |
| GET | /teachers | 教师管理 | JWT 必需 + admin |
| GET | /students | 学生管理 | JWT 必需 + admin |
| GET | /audit-logs | 审计日志 | JWT 必需 + admin |
| GET | /dashboard | 管理员仪表盘 | JWT 必需 + admin |
| GET | /system | 系统配置 | JWT 必需 + admin |
> admin-portal 是前端,**不对外提供 HTTP 端点**。此处列出的是 admin-portal 在 Shell 路由树 `/admin/*` 下注册的前端页面路由,由 Shell 动态 import admin Remote 加载。
### 1.3 GraphQL schema如 BFF
| 路由 | 页面 | 权限点 | 数据范围 |
| ------------------- | ---------------- | ---------------------- | --------------- |
| `/admin/dashboard` | 管理员仪表盘 | `ADMIN_DASHBOARD_VIEW` | L3-L5 |
| `/admin/users` | 用户管理 | `IAM_USER_READ` | L3-L5 |
| `/admin/roles` | 角色权限管理 | `IAM_ROLE_READ` | L3-L5 |
| `/admin/permissions`| 权限点管理 | `IAM_PERMISSION_READ` | L5 |
| `/admin/viewports` | 视口配置 | `IAM_VIEWPORT_READ` | L5 |
| `/admin/organization` | 组织管理 | `ORG_MANAGE` | L3-L5 |
| `/admin/system` | 学校设置 | `ADMIN_SYSTEM_MANAGE` | L5 |
| `/admin/classes` | 班级管理(全局) | `ADMIN_CLASS_READ` | L3-L5 |
| `/admin/teachers` | 教师管理 | `ADMIN_TEACHER_READ` | L3-L5 |
| `/admin/students` | 学生管理 | `ADMIN_STUDENT_READ` | L3-L5 |
| `/admin/audit-logs` | 审计日志 | `ADMIN_AUDIT_READ` | L5 |
不适用。admin-portal 消费 teacher-bff GraphQL admin namespace自身不提供 schema
> 权限点使用 `ADMIN_` / `IAM_` / `ORG_` 前缀ai-allocation §5admin 权限点 `ADMIN_` 前缀)。`ADMIN_*` 常量由 coord 维护于 `packages/contracts/src/permissions.ts`,前端不硬编码
### 1.4 Kafka 事件发布(如有)
### 1.3 GraphQL schema
不适用。admin-portal **消费** teacher-bff GraphQL admin 命名空间,自身不提供 schema
### 1.4 Kafka 事件发布
无。前端不发布 Kafka 事件。
### 1.5 错误码前缀
无(前端不定义错误码前缀,透传 BFF 错误码)。
无(前端不定义错误码前缀,透传 BFF/网关错误码)。消费的错误码前缀见 §2.5。
### 1.6 微前端架构(补充)
### 1.6 微前端架构
| 角色 | 说明 |
| ---------------------- | ----------------------------------------------- |
| MF Remote | 管理后台是微前端远程模块 |
| 暴露的 remote 模块 | AdminApp管理后台完整应用、shared 管理端组件 |
| module federation 配置 | `apps/admin-portal/module-federation.config.ts` |
| 角色 | 说明 |
| ---- | ---- |
| MF Remote | admin-portal 是微前端远程模块,挂载到 teacher-portal Shell |
| Remote 名称 | `admin_app`Shell `remotes` 中引用为 `admin: 'admin_app@http://localhost:4003/_next/static/chunks/remoteEntry.js'` |
| 暴露模块 | `./AdminApp`(管理后台应用入口,供 Shell 动态 import |
| MF 配置位置 | `apps/admin-portal/next.config.js`NextFederationPlugin对齐 ARB-002 §2.2 配置风格) |
| sharedsingleton | react / react-dom / urql / graphql / @edu/ui-tokens / @edu/ui-components / @edu/hooks / @edu/contracts |
| 复用 Shell 暴露 | `GraphQLProvider` / `AppShell` / `useAuth` / `usePermission` / `useGraphQLClient` / `ErrorBoundary` / `RequirePermission`ARB-002 §2.2 |
> admin-portal **不暴露共享组件给 Shell**(共享组件由 Shell 统一暴露,对齐 ARB-002。admin 特有组件UserManagementTable / RolePermissionMatrix / ViewportConfigEditor仅 admin-portal 内部使用。
### 1.7 i18n 命名空间
| 命名空间 | 用途 |
| -------- | ---- |
| `admin.*` | 管理端 UI 文案(导航/按钮/表单标签等) |
| `iam.error.*` | iam 服务错误码 i18n透传 |
| `bff.error.*` | teacher-bff 错误码 i18n透传 |
| `gateway.error.*` | api-gateway 错误码 i18n透传 |
| `network.error.*` | 前端网络层错误 i18n |
---
@@ -55,28 +77,49 @@
### 2.2 Kafka 事件订阅(异步)
无。前端不直接订阅 Kafka审计日志通过 GraphQL 查询,非直接订阅)。
无。前端不直接订阅 Kafka审计日志经 teacher-bff 聚合后通过 GraphQL `auditLogs` Query 消费链路iam → Kafka `edu.iam.audit.created`**teacher-bff 消费** → GraphQL → admin-portal)。
### 2.3 HTTP 调用(如有)
> 注:[matrix.md §4](../matrix.md) 将 admin-portal 列为 `edu.iam.audit.created` 消费方,表述不精确,已提请 coord 修正为 teacher-bff见 [objections ISSUE-007](../objections/admin-portal_issue.md))。
| 被调用方 | Method.Path | 用途 | mock 策略 |
| ------------------- | ----------------------- | ------------------------------------------------------------- | ----------------------------------------------------------------- |
| api-gateway (ai01) | POST /api/admin/graphql | 管理 GraphQL 查询(经网关代理到 teacher-bff admin namespace | api-gateway/teacher-bff 就绪前使用 MSW 拦截返回 mock GraphQL 响应 |
| api-gateway (ai01) | POST /api/auth/login | 管理员登录 | api-gateway 就绪前使用 MSW 返回固定 JWTadmin 角色) |
| push-gateway (ai02) | GET /ws | WebSocket 实时通知 | push-gateway 就绪前使用 mock-socket 模拟 WS 推送 |
### 2.3 HTTP 调用
### 2.4 GraphQL 查询域(经 api-gateway 代理到 teacher-bff admin namespace
| 被调用方 | Method.Path | 用途 | mock 策略 |
| -------- | ----------- | ---- | --------- |
| api-gateway (ai01) | POST /api/admin/graphql | 管理 GraphQL 查询(经网关代理到 teacher-bff admin 命名空间) | api-gateway/teacher-bff 就绪前使用 MSW 拦截返回 mock GraphQL 响应 |
| push-gateway (ai02) | GET /ws | WebSocket 实时通知(审计告警/异常登录/系统异常) | push-gateway 就绪前使用 mock-socket 模拟 WS 推送(**ISSUE-006 待 coord 仲裁** |
| Query/Mutation | 用途 | mock 策略 |
| ------------------------------------------------- | ------------------------------- | ----------------------------------------------------------------------------------- |
| currentUser | 当前管理员信息 | MSW 返回固定管理员admin 角色) |
| adminUsers / createUser / updateUser / deleteUser | 用户管理 | MSW 返回固定 50 个用户 + CRUD success |
| adminRoles / updateRolePermissions | 角色权限管理 | MSW 返回固定 5 个角色 + 权限矩阵 |
| adminClasses | 班级管理(全局) | MSW 返回固定 20 个班级 |
| adminTeachers | 教师管理 | MSW 返回固定 50 个教师 |
| adminStudents | 学生管理 | MSW 返回固定 1200 个学生 |
| auditLogs | 审计日志(聚合 iam AuditEvent | MSW 返回固定 100 条审计日志 |
| adminDashboard | 管理员仪表盘 | MSW 返回固定仪表盘total_teachers=50, total_students=1200, school_avg_score=80.0 |
> **登录不自行实现**admin-portal 复用 Shell 统一登录入口 `/login`ARB-002 §2.3:登录页 P2 不走 MFShell 独占)。管理员登录后按 admin 角色重定向到 `/admin/dashboard`。开发期 mock 登录由 Shell 的 MSW handler 提供admin 角色 JWT + permissions=["*"])。
### 2.4 GraphQL 查询域(经 api-gateway 代理到 teacher-bff admin 命名空间)
> 依赖 teacher-bff admin 命名空间 schemaARB-001**ISSUE-005 待 ai03 补齐**)。以下为 admin-portal 消费的 Query/Mutation 清单,作为 ai03 补齐 schema 的输入。
| Query/Mutation | 类型 | 用途 | mock 策略 |
| -------------- | ---- | ---- | --------- |
| `currentUser` | Query | 当前管理员信息 | MSW 返回固定管理员admin 角色) |
| `adminUsers` | Query | 用户列表(含筛选/分页) | MSW 返回固定 50 个用户 |
| `adminUser(id)` | Query | 用户详情 | MSW 返回对应用户 |
| `createUser` / `updateUser` / `deleteUser` / `toggleUserStatus` | Mutation | 用户 CRUD | MSW 返回 CRUD success |
| `adminRoles` | Query | 角色列表(含权限) | MSW 返回固定 5 个角色 + 权限矩阵 |
| `createRole` / `updateRolePermissions` | Mutation | 角色 CRUD + 权限矩阵 | MSW 返回 success |
| `adminPermissions` | Query | 全量权限点(按 resource 分组) | MSW 返回固定权限矩阵 |
| `adminViewports(scope)` | Query | 视口配置列表 | MSW 返回固定 7 个视口 |
| `updateViewport` | Mutation | 视口配置更新 | MSW 返回 success |
| `adminOrganization(parentId)` | Query | 组织树 | MSW 返回固定 school/grade/class 树 |
| `adminClasses` | Query | 班级管理(全局) | MSW 返回固定 20 个班级 |
| `adminTeachers` | Query | 教师管理 | MSW 返回固定 50 个教师 |
| `adminStudents` | Query | 学生管理 | MSW 返回固定 1200 个学生 |
| `auditLogs(filter)` | Query | 审计日志(聚合 iam AuditEvent | MSW 返回固定 100 条审计日志 |
| `adminDashboard` | Query | 管理员仪表盘聚合 | MSW 返回固定仪表盘total_teachers=50, total_students=1200, school_avg_score=80.0 |
### 2.5 消费的错误码前缀(前端 i18n 路由)
| 前缀 | 来源服务 | i18n key 模式 |
| ---- | -------- | ------------- |
| `IAM_` | iam | `iam.error.{{code}}` |
| `BFF_TEACHER_` | teacher-bff | `bff.error.{{code}}` |
| `GW_` | api-gateway | `gateway.error.{{code}}` |
| `NETWORK_` | 前端网络层 | `network.error.{{code}}` |
---
@@ -85,18 +128,21 @@
### 3.1 我依赖的上游就绪标志
- [ ] api-gateway HTTP :8080 启用ai01—— 前端请求入口 + admin 角色校验
- [ ] teacher-bff GraphQL :3003 启用ai03—— admin namespace 可用
- [ ] teacher-portal Shell MF exposes/shared 就绪ai13ARB-002—— Remote 挂载前提
- [ ] teacher-bff GraphQL :3003 启用 + **admin 命名空间 schema 就绪**ai03—— **ISSUE-005 待 ai03 补齐**
- [ ] iam gRPC 50052 启用ai06—— 用户/角色/审计日志数据来源
- [ ] edu.iam.audit.created topic 有事件发布ai06—— 审计日志来源
- [ ] data-ana gRPC 50055 启用ai11)—— adminDashboard 数据来源
- [ ] push-gateway WebSocket :8081/ws 启用ai02—— 实时通知
- [ ] `edu.iam.audit.created` topic 有事件发布ai06—— 审计日志来源(经 teacher-bff 消费)
- [ ] push-gateway WebSocket :8081/ws 启用ai02)—— 实时通知(**ISSUE-006 待 coord 仲裁**
- [ ] `packages/contracts` admin 权限点 `ADMIN_*` 常量就绪coord
> adminDashboard 的数据聚合由 teacher-bff 完成teacher-bff 内部聚合 iam + core-edu + data-ana。admin-portal **不直连 data-ana / core-edu gRPC**,统一经 teacher-bff GraphQL。原 contract 误列 data-ana gRPC 50055 为直接依赖,已修正。
### 3.2 我的就绪标志(供下游消费)
- [ ] admin-portal dev server :4003 启用
- [ ] MF Remote 可被 AppShell 加载(暴露 AdminApp 模块)
- [ ] MF Remote 可被 AppShell 加载(暴露 `./AdminApp` 模块)
- [ ] 独立壳渲染(首页 + 导航 + 路由守卫 + admin 角色校验)
- [ ] 登录流程可用(POST /api/auth/login 获取 JWT前端校验 admin 角色
- [ ] 登录流程可用(复用 Shell `/login`admin 角色校验后重定向 `/admin/dashboard`
- [ ] GraphQL 查询可执行currentUser / adminDashboard / auditLogs 返回数据)
- [ ] 用户/角色 CRUD 可执行createUser / updateRolePermissions
- [ ] WebSocket 通知可接收
@@ -117,13 +163,25 @@ admin-portal 是前端,无下游消费方。但对开发体验提供:
在真实上游就绪前admin-portal 使用以下 mock
- **HTTP/GraphQL mock**:使用 MSW 拦截所有请求
- POST /api/auth/login → 返回固定 JWT + UserInfoadmin 角色permissions=["*"]
- POST /api/admin/graphql → 根据 operationName 返回对应 mock 响应(与 teacher-bff admin namespace mock 数据一致)
- POST /api/admin/graphql → 按 operationName 返回对应 mock 响应(与 teacher-bff admin namespace mock 数据一致
- auditLogs mock 返回固定 100 条审计日志(含 action: create/update/delete/login/logout/permission_change
- adminDashboard mock 返回固定全校统计仪表盘
- 所有 mock 响应定义在 `apps/admin-portal/src/mocks/fixtures/*.json`
- **WebSocket mock**:使用 mock-socket 库
- 连接后每 30 秒推送 1 条 mock 系统通知
- **JWT mock**:使用固定 mock JWTadmin 角色),存入 httpOnly cookie
- 连接后每 30 秒推送 1 条 mock 系统通知(审计告警/异常登录)
- **JWT mock**:使用固定 mock JWTadmin 角色permissions=["*"]),由 Shell MSW handler 写入 httpOnly cookie复用 Shell 登录 mock
- **权限矩阵 mock**:内置固定 5 个角色 + 完整权限矩阵teacher/student/parent/admin/super_admin
- **环境切换**:通过 `NEXT_PUBLIC_API_MOCKING=enabled` 环境变量控制,上游就绪后设为 `disabled`
---
## §5 跨模块契约确认清单(需对应 AI 确认)
| 契约 | 提供方 | 当前状态 |
| ---- | ------ | -------- |
| teacher-bff admin 命名空间 schema§2.4 全部 Query/Mutation | ai03 | ⚠️ 待补齐ISSUE-005 |
| Shell 暴露 GraphQLProvider / useGraphQLClient / AppShell / useAuth / usePermission | ai13 | ⏳ P2 交付ARB-002 |
| iam 用户/角色/权限/视口 CRUD gRPC + AuditEvent Kafka | ai06 | ⏳ P2.1 |
| api-gateway /api/admin/graphql 代理路由 + admin 角色校验 | ai01 | ⏳ |
| push-gateway GET /wsadmin-portal 实时通知) | ai02 | ⚠️ 待 coord 仲裁ISSUE-006 |
| `packages/contracts` ADMIN_* 权限点常量 | coord | ⏳ |

View File

@@ -1,24 +1,109 @@
# admin-portal 问题记录
> 负责人ai16
> 关联:[coord.md](../coord.md)、[contracts/admin-portal_contract.md](../contracts/admin-portal_contract.md)
> 关联:[coord.md](../coord.md)、[contracts/admin-portal_contract.md](../contracts/admin-portal_contract.md)、[matrix.md](../matrix.md)、[ai-allocation.md §5 ai16](../../ai-allocation.md)
> 规则AI 遇到问题时在此追加条目coord 仲裁后更新状态
---
## §0 已有仲裁核查ai16 复核)
> 任务要求:对 coord 已有仲裁进行核查。以下为 ai16 对照 admin-portal 实际职责逐条复核结论。
### 0.1 ARB-001teacher-bff GraphQL schema 第一版)— 核查结论:✅ 通过,但存在依赖缺口
- **核查点**ARB-001 §1.3 裁决"admin 命名空间 P2 不包含P6 admin-portal 阶段新增 admin 命名空间"。
- **核查结论**裁决方向正确admin-portal 复用 teacher-bff + admin schema 命名空间,与 ai-allocation §5 ai16 设计重点一致)。
- **发现的缺口**teacher-bff 当前 [02-architecture-design.md](../../../services/teacher-bff/docs/02-architecture-design.md) **未定义 admin 命名空间的 GraphQL schema**(全文仅 1 处 audit 提及,无 adminUsers/adminRoles/auditLogs/adminDashboard 等 Query。admin-portal P6 的全部业务查询依赖该 schema属前置依赖缺失。
- **建议**:请 coord 仲裁 admin 命名空间 schema 的归属与时间点——是否由 ai03teacher-bff在 P6 启动前补齐 `packages/shared-ts/contracts/graphql/teacher-bff.graphql` 的 admin 命名空间部分(参照本模块 [contract §2.4](../contracts/admin-portal_contract.md) 的 Query 清单)。
- **状态**:待 coord 仲裁(见新异议 ISSUE-005
### 0.2 ARB-002MF Shell 暴露清单)— 核查结论:✅ 通过,但 01/02 文档未跟进
- **核查点**ARB-002 §2.2 Shell 暴露清单含 `GraphQLProvider` / `useGraphQLClient` / `useAuth` / `usePermission` / `AppShell` / `ErrorBoundary` / `Loading` / `Empty` / `RequirePermission`**不含** `useApi` / `ApiClient`
- **核查结论**裁决正确。admin-portal 应通过 `useGraphQLClient()` 消费 teacher-bff GraphQL而非 REST ApiClient。
- **发现的问题**:本模块 [01-understanding.md](../../../apps/admin-portal/docs/01-understanding.md) 与 [02-architecture-design.md](../../../apps/admin-portal/docs/02-architecture-design.md) 仍基于 REST `useApi()` / `ApiClient` 编写,未跟进 ARB-002。属本模块文档与仲裁不同步见新异议 ISSUE-003
- **状态**:本模块文档待修订(见 ISSUE-003
### 0.3 未仲裁但影响 admin-portal 的关键项
ARB-001/ARB-002 均未明确仲裁以下三项,而它们直接影响 admin-portal 实现,建议 coord 补充裁决:
| 待裁决项 | 当前依据 | 影响 |
| -------- | -------- | ---- |
| admin-portal 端口 | matrix.md / ai-allocation.md = 4003 | 01/02 文档误用 3003与 teacher-bff 冲突) |
| admin-portal 是否消费 push-gateway WebSocket | 同类 portalparent-portal契约 = 消费 | 01/02 文档误声明"不消费推送" |
| 审计日志消费机制iam Kafka → teacher-bff → GraphQL auditLogs | matrix.md §4 列 admin-portal 为 edu.iam.audit.created 消费方 | 前端不直连 Kafka需经 teacher-bff 聚合matrix.md 表述不精确 |
---
## 问题列表
<!--
追加条目格式:
### ISSUE-001-ai1601/02 模块文档归属错误ai07 → ai16
### ISSUE-[编号]-[AI标识][标题]
- **提请方**ai16
- **日期**2026-07-10
- **类型**:编号冲突 / 文档归属
- **描述**[01-understanding.md](../../../apps/admin-portal/docs/01-understanding.md) 与 [02-architecture-design.md](../../../apps/admin-portal/docs/02-architecture-design.md) 头部均标注"AIai07TS/React · 管理场景域前端 remote",分支名 `docs/admin-portal-stage1-stage2-design-ai07`。但 [ai-allocation.md §5](../../ai-allocation.md) 第 54/97/118/159/278 行明确 admin-portal 归属 **ai16**ai07 实际负责 classes → core-edu 交接(见 [workline.md §4.7](../workline.md))。
- **建议方案**:将 01/02 文档头部 AI 标识与分支命名更正为 ai16ai07 在 admin-portal 的产出视为历史草稿,由 ai16 接管修订。
- **状态**:待 coord 仲裁
- **提请方**aiXX
- **日期**YYYY-MM-DD
- **类型**:契约不明确 / 工作量超批 / 前置依赖缺失 / 编号冲突 / 其他
- **描述**[详细描述问题]
- **建议方案**[AI 的建议]
- **状态**:待 coord 仲裁 / 已裁决(见 coord.md §X
-->
### ISSUE-002-ai1601/02 文档端口错误3003 → 4003且 3003 与 teacher-bff 冲突
(暂无问题)
- **提请方**ai16
- **日期**2026-07-10
- **类型**:契约不明确 / 编号冲突
- **描述**01 §1 与 02 §12.1 声明 admin-portal 端口 3003并称"与 [full-stack-runbook](../../../docs/standards/full-stack-runbook.md) 端口矩阵对齐"。但 full-stack-runbook §2.1 中 **3003 = teacher-bff**admin-portal 未列入该 runbook。coord 维护的 [matrix.md §1](../matrix.md) 与 ai-allocation.md 统一采用 4000 段teacher-portal :4000 / student-portal :4001 / parent-portal :4002 / admin-portal :4003。
- **建议方案**:确认 admin-portal 端口为 **4003**;同步更新 full-stack-runbook §2.1 补齐 4 个 portal 的 4000 段端口(消除 runbook 与 matrix.md 的端口双轨制)。
- **状态**:待 coord 仲裁
### ISSUE-003-ai1601/02 文档通信协议与 ARB-001/ARB-002 不一致REST → GraphQL
- **提请方**ai16
- **日期**2026-07-10
- **类型**:契约不明确 / 前置依赖缺失
- **描述**01 §3.1 / 02 §1、§4 全文基于 REST`/api/v1/iam/*` + `/api/v1/admin/*` + `useApi()` + `ApiClient`)。但 ARB-001 已裁决 admin-portal 复用 teacher-bff GraphQL **admin 命名空间**ARB-002 已裁决 Shell 暴露 `GraphQLProvider` + `useGraphQLClient`(不含 `useApi`。02 §11.3 仍将"GraphQL vs REST"列为未决与仲裁结论冲突。根因01/02 文档参照的 teacher-portal 02 文档(同样基于 REST、将 GraphQL 列为未决)早于 ARB-001/0022026-07-09未跟进仲裁。
- **建议方案**admin-portal 通信协议统一为 GraphQL`POST /api/admin/graphql` → teacher-bff admin 命名空间);删除 `useApi`/`ApiClient` 依赖,改用 `useGraphQLClient()`02 §11.3 移除已裁决项。本模块 [contract.md](../contracts/admin-portal_contract.md) 已按 GraphQL 编写,作为修订基准。
- **状态**:待 coord 仲裁
### ISSUE-004-ai1601/02 文档遗漏审计日志与学校设置ai-allocation §5 明确职责)
- **提请方**ai16
- **日期**2026-07-10
- **类型**:工作量超批 / 契约不明确
- **描述**[ai-allocation.md §5 ai16](../../ai-allocation.md) 第 282 行明确 admin-portal 设计重点含"用户管理 + 角色权限管理 + 学校设置 + 组织管理 + **审计日志消费**"。但 01 §2.1/§L1 导航/§L2 路由表均**无审计日志、无学校设置**(仅有 dashboard/users/roles/permissions/viewports/organization/monitoring 7 个视口)。本模块 [contract.md §1.2/§2.4](../contracts/admin-portal_contract.md) 已含 audit-logs / system 路由与 auditLogs Query与 01/02 不一致。
- **建议方案**admin-portal 视口补齐为 9 个dashboard / users / roles / permissions / viewports / organization / classes / teachers / students / audit-logs / system按 ai-allocation §5 + contract §1.2 对齐);审计日志经 teacher-bff GraphQL `auditLogs` Query 消费(聚合 iam `AuditEvent`)。
- **状态**:待 coord 仲裁
### ISSUE-005-ai16teacher-bff 缺 admin 命名空间 GraphQL schema前置依赖缺失
- **提请方**ai16
- **日期**2026-07-10
- **类型**:前置依赖缺失
- **描述**ARB-001 裁决 P6 新增 admin 命名空间,但 teacher-bff [02-architecture-design.md](../../../services/teacher-bff/docs/02-architecture-design.md) 未定义该 schema无 adminUsers / adminRoles / adminClasses / adminTeachers / adminStudents / auditLogs / adminDashboard 等 Query/Mutation。admin-portal P6 全部业务查询依赖此 schema且需 SDL-first 存放于 `packages/shared-ts/contracts/graphql/teacher-bff.graphql`ARB-001 §1.3)。
- **建议方案**:请 coord 仲裁——由 ai03 在 P6 启动前补齐 teacher-bff admin 命名空间 schema参照本模块 contract §2.4 Query 清单),作为 admin-portal P6 的前置就绪信号;并更新 [matrix.md §3](../matrix.md) teacher-bff 行的 schema 文件状态。
- **状态**:待 coord 仲裁
### ISSUE-006-ai1601/02 文档推送策略与同类 portal 契约不一致(轮询 → WebSocket
- **提请方**ai16
- **日期**2026-07-10
- **类型**:契约不明确
- **描述**01 §3.3 / 02 §5 声明 admin-portal"不消费 WebSocket/SSE采用轮询"。但同类 portal 契约([parent-portal_contract.md §2.3](./parent-portal_contract.md))消费 push-gateway `GET /ws`,本模块 [contract.md §2.3](../contracts/admin-portal_contract.md) 亦声明消费 WebSocket 实时通知。matrix.md §5 列 push-gateway WS 消费方含全部 portal。管理端审计告警/异常登录等场景对实时性有合理需求。
- **建议方案**admin-portal 接入 push-gateway WebSocket与同类 portal 一致用于审计告警、异常登录、系统异常等实时通知保留轮询仅用于监控指标60s与统计5min这类天然适合轮询的低频数据。
- **状态**:待 coord 仲裁
### ISSUE-007-ai16matrix.md §4 将 admin-portal 列为 Kafka 直消费方,与前端层级矛盾
- **提请方**ai16
- **日期**2026-07-10
- **类型**:契约不明确
- **描述**[matrix.md §4](../matrix.md) 第 111 行将 admin-portal 列为 `edu.iam.audit.created` 的消费方。但前端不直连 Kafka[contract.md §2.2](../contracts/admin-portal_contract.md) 已明确审计日志经 GraphQL 查询。实际链路应为iam → Kafka → **teacher-bff** 消费 → GraphQL `auditLogs` Query → admin-portal。
- **建议方案**matrix.md §4 该行消费方更正为 **teacher-bff**admin-portal 经 teacher-bff 间接消费),避免误导架构分层。
- **状态**:待 coord 仲裁
---
## §1 历史问题
(暂无已裁决问题)

View File

@@ -1,45 +1,246 @@
# admin-portal 工作排期
> 负责人ai16
> 关联:[workline.md](../workline.md)、[coord.md](../coord.md)、[contracts/admin-portal_contract.md](../contracts/admin-portal_contract.md)
> 模式:全并行(各 AI 一口气完成 P2-P6 全部代码,最后统一集成测试)
> 关联:[workline.md](../workline.md)、[coord.md](../coord.md)、[contracts/admin-portal_contract.md](../contracts/admin-portal_contract.md)、[ai-allocation.md §5 ai16](../../ai-allocation.md)
> 模式:全并行(各 AI 一口气完成 P2-P6 全部代码,开发期间用 mock最后统一集成测试)
> 说明:本排期基于 GraphQLARB-001 admin 命名空间)+ 端口 4003 + ai16 归属,已对齐 [matrix.md](../matrix.md) 与 ai-allocation.md。01/02 文档中 REST/3003/ai07 表述待 coord 仲裁后修订(见 [objections/admin-portal_issue.md](../objections/admin-portal_issue.md))。
---
## §1 总览
admin-portal 是管理端微前端,通过 MF Remote 接入主应用,覆盖用户管理角色权限、审计日志等场景。全阶段目标P2 MF Remote 骨架 → P3 用户管理+角色权限+审计日志 → P4-P6 持续优化
admin-portal 是管理端微前端MF Remote),挂载到 teacher-portal Shell,覆盖**用户管理 / 角色权限管理 / 学校设置 / 组织管理 / 审计日志消费**等管理场景ai-allocation §5 ai16。复用 teacher-bff GraphQL endpoint 的 **admin 命名空间**ARB-001admin 权限点使用 `ADMIN_` 前缀ai-allocation §5
全阶段目标:
- **P2**MF Remote 骨架next.config.js + MF 配置 + 独立壳渲染 + MSW mock
- **P3**:用户管理 + 角色权限管理admin 命名空间 Query/Mutation
- **P4**:组织管理 + 学校设置 + 班级/教师/学生全局管理
- **P5**审计日志消费auditLogs Query 聚合 iam AuditEvent+ WebSocket 实时通知
- **P6**硬化A11y WCAG 2.2 AA / Web Vitals / OTel / 测试覆盖率 ≥ 80% / Dockerfile 多阶段)
> 跨阶段:开发期间全部经 MSW mock见 [contract §4](../contracts/admin-portal_contract.md)),上游就绪后逐项切换真实。
---
## §2 全阶段甘特图P2-P6,各 AI 自行细化
## §2 全阶段甘特图P2-P6
```mermaid
gantt
title ai16 admin-portal 全阶段排期
title ai16 admin-portal 全阶段排期P2-P6
dateFormat YYYY-MM-DD
axisFormat %m-%d
section P2-P6
[阶段任务] :a16a, 2026-07-10, Xd
section P2 骨架
16.1 MF Remote 骨架(next.config+独立壳) :crit, a16a, 2026-07-10, 2d
16.2 MSW handlers+fixtures+mock JWT :a16b, after a16a, 2d
16.3 接入Shell共享(GraphQLProvider/AppShell/useAuth) :crit, a16c, after a16a, 2d
section P3 用户/角色权限
16.4 用户管理页(users CRUD+UserManagementTable) :crit, a16d, after a16c, 3d
16.5 角色权限矩阵(RolePermissionMatrix+updateRolePermissions) :a16e, after a16d, 3d
16.6 权限点管理+视口配置(ADMIN_前缀) :a16f, after a16e, 2d
section P4 组织/学校/全局实体
16.7 组织树管理(organization) :a16g, after a16f, 2d
16.8 学校设置(system) :a16h, after a16g, 2d
16.9 班级/教师/学生全局管理(adminClasses/Teachers/Students) :a16i, after a16h, 3d
section P5 审计日志/实时通知
16.10 审计日志页(auditLogs Query+筛选/导出) :crit, a16j, after a16i, 3d
16.11 WebSocket实时通知(审计告警/异常登录) :a16k, after a16j, 2d
16.12 管理仪表盘(adminDashboard聚合) :a16l, after a16k, 2d
section P6 硬化
16.13 A11y WCAG 2.2 AA审计+修复 :crit, a16m, after a16l, 3d
16.14 Web Vitals+OTel browser SDK接入 :a16n, after a16m, 2d
16.15 Vitest单测+Playwright E2E(≥80%) :crit, a16o, after a16n, 3d
16.16 Dockerfile多阶段+/api/health+/api/ready :a16p, after a16o, 2d
```
> **注意**:以上为 coord 初始规划ai16 接管后必须自行细化为完整 P2-P6 排期
> 关键路径crit16.1 → 16.3 → 16.4 → 16.10 → 16.13 → 16.15。总工期约 34 个工作日
---
## §3 详细任务
### 全阶段任务
### P2 阶段
#### 16.1 MF Remote 骨架next.config + 独立壳)
- **负责人**ai16
- **交付物**:⚠️ 由 ai16 自行补充
- **依赖**:见 [contracts/admin-portal_contract.md](../contracts/admin-portal_contract.md)
- **验收标准**:⚠️ 由 ai16 自行补充
- **依赖**teacher-portal Shell MF exposes/shared 配置就绪ARB-002ai13 P2 交付)
- **交付物**
- `apps/admin-portal/next.config.js`NextFederationPluginRemote 角色,`name: 'admin_app'``filename: 'static/chunks/remoteEntry.js'``exposes: { './AdminApp': './src/app/admin-app.tsx' }`shared 全部 singleton
- `apps/admin-portal/src/app/admin-app.tsx`(独立壳入口,供 Shell 动态加载 + 独立 dev 渲染)
- `apps/admin-portal/src/app/standalone.tsx`(独立 dev 壳:自实现 AppShell 占位 + mock providers`pnpm --filter admin-portal dev` 在 :4003 独立预览)
- `tsconfig.json`(沿用 tsconfig.base.json`tailwind.config.js`(引入 `@edu/ui-tokens`)、`package.json`
- **验收标准**
- `pnpm --filter admin-portal dev` 在 :4003 启动,独立壳渲染首页 + 导航占位
- MF `remoteEntry.js` 可被 Shell `dynamic import` 加载feature flag `NEXT_PUBLIC_MF_ENABLED` 控制)
- shared 单例配置通过react/react-dom/urql/graphql/@edu/* 全 singleton
#### 16.2 MSW handlers + fixtures + mock JWT
- **负责人**ai16
- **依赖**mock 先行)
- **交付物**
- `apps/admin-portal/src/mocks/handlers.ts`(拦截 `POST /api/admin/graphql` + `POST /api/auth/login` + `GET /ws`
- `apps/admin-portal/src/mocks/fixtures/*.json`50 用户 / 5 角色 / 20 班级 / 50 教师 / 1200 学生 / 100 审计日志 / 仪表盘统计)
- mock JWTadmin 角色permissions=["*"]httpOnly cookie
- **验收标准**
- `NEXT_PUBLIC_API_MOCKING=enabled` 时所有请求被 MSW 拦截返回 mock
- GraphQL mock 按 operationName 返回对应 fixture与 teacher-bff admin namespace mock 数据一致)
#### 16.3 接入 Shell 共享GraphQLProvider/AppShell/useAuth
- **负责人**ai16
- **依赖**ARB-002 Shell 暴露清单就绪ai13
- **交付物**
- `AdminApp` 通过 MF `import from 'teacher/GraphQLProvider'``'teacher/AppShell'``'teacher/useAuth'``'teacher/usePermission'``'teacher/useGraphQLClient'`
- `<AppShell scope="admin">` 渲染管理端视口导航
- GraphQL client 经 `useGraphQLClient()` 获取(**不使用 useApi/ApiClient**,对齐 ARB-002
- **验收标准**
- urql client 单例跨 Remote 共享(与 Shell 同一实例)
- `currentUser` Query 返回 mock 管理员信息
- admin 角色校验:非 admin 角色重定向到登录页
### P3 阶段
#### 16.4 用户管理页users CRUD + UserManagementTable
- **负责人**ai16
- **依赖**teacher-bff admin 命名空间 `adminUsers`/`createUser`/`updateUser`/`deleteUser` schemaISSUE-005 待 coord 仲裁 ai03 补齐)
- **交付物**
- `/admin/users` 列表页UserManagementTable邮箱/姓名/角色/状态/数据范围/最后登录 + 筛选/分页/批量操作)
- `/admin/users/new` + `/admin/users/:id` 表单页react-hook-form + zodResolver
- admin 业务 Hooks`useUsers` / `useUser` / `useCreateUser` / `useUpdateUser` / `useToggleUserStatus`urql query/mutation
- **验收标准**
- 列表筛选/分页正常mutation 后 invalidate 刷新
- DataScope L3-L5 越权由后端强制,前端 `AdminDataScopeFilter` 仅作 UI 提示
- 权限:`IAM_USER_READ` / `IAM_USER_CREATE` / `IAM_USER_UPDATE`
#### 16.5 角色权限矩阵RolePermissionMatrix + updateRolePermissions
- **负责人**ai16
- **依赖**teacher-bff `adminRoles` / `updateRolePermissions` schema
- **交付物**
- `/admin/roles`RolePermissionMatrix行=角色,列=权限按 resource 分组checkbox 网格)
- 系统预置角色只读isSystem=true 不可编辑/删除)
- Hooks`useRoles` / `useRole` / `useCreateRole` / `useUpdateRolePermissions`
- **验收标准**
- 勾选触发 `updateRolePermissions` Mutation乐观更新 + 失败回滚
- 删除前校验 userCount > 0 时禁用删除并提示
#### 16.6 权限点管理 + 视口配置ADMIN_ 前缀)
- **负责人**ai16
- **依赖**`packages/contracts/src/permissions.ts`coord 维护admin 权限点 `ADMIN_*` 前缀)
- **交付物**
- `/admin/permissions` 只读列表DataTable按 resource 分组)
- `/admin/viewports` 视口配置编辑器ViewportConfigEditor@dnd-kit 拖拽排序 + 权限绑定 + scope/isVisible
- Hooks`usePermissions`30min 缓存)/ `useViewportsConfig` / `useUpdateViewport`
- **验收标准**
- 权限点常量来自 `@edu/contracts`(不硬编码)
- 视口配置保存后 AppShell 导航即时刷新invalidate viewports queryKey
### P4 阶段
#### 16.7 组织树管理organization
- **交付物**`/admin/organization` 页(树形 + DataTableschool/grade/class 层级 CRUD
- **验收标准**:树形展开/折叠 + 拖拽调整层级(后端校验)+ DataScope 过滤
#### 16.8 学校设置system
- **交付物**`/admin/system` 页(学校基础信息 / 学年学期 / 系统参数表单)
- **验收标准**:表单 zod 校验 + 保存后 toast 反馈;仅 L5 系统管理员可编辑
#### 16.9 班级/教师/学生全局管理
- **交付物**`/admin/classes` / `/admin/teachers` / `/admin/students` 三个全局管理页adminClasses/adminTeachers/adminStudents Query
- **验收标准**:跨班级/跨年级全局视角(区别于 teacher-portal 的教师自身视角DataScope 控制可见范围
### P5 阶段
#### 16.10 审计日志页auditLogs Query + 筛选/导出)
- **负责人**ai16
- **依赖**teacher-bff 消费 `edu.iam.audit.created` Kafka 并暴露 `auditLogs` QueryISSUE-007 待 coord 修正 matrix.md §4 消费方为 teacher-bff
- **交付物**
- `/admin/audit-logs`DataTable时间/操作人/action/resource/ip + 筛选action/user/dateRange + 导出 CSV
- Hooks`useAuditLogs`(含游标分页)
- **验收标准**
- 审计日志经 GraphQL 查询(**非直接订阅 Kafka**,对齐 contract §2.2
- 100 条 mock 审计日志覆盖 create/update/delete/login/logout/permission_change
#### 16.11 WebSocket 实时通知(审计告警/异常登录)
- **交付物**
- 接入 push-gateway `GET /ws`(与 parent-portal 同类契约一致,对齐 ISSUE-006
- 审计告警 / 异常登录 / 系统异常 toast + 通知中心入口
- **验收标准**
- mock-socket 每 30s 推送 1 条 mock 系统通知
- WebSocket 断线自动重连
#### 16.12 管理仪表盘adminDashboard 聚合)
- **交付物**`/admin/dashboard`rechartstotal_teachers / total_students / school_avg_score / 趋势图)
- **验收标准**adminDashboard Query 返回聚合数据60s 轮询监控指标 + 5min 轮询统计
### P6 阶段(硬化)
#### 16.13 A11y WCAG 2.2 AA 审计 + 修复
- **交付物**eslint-plugin-jsx-a11yerror 级)+ 手动审计修复
- **验收标准**0 个 error 级违规
#### 16.14 Web Vitals + OTel browser SDK 接入
- **交付物**`next/web-vitals``POST /api/admin/web-vitals`OTel browser SDK复用 Shell TracerProviderscope='admin'
- **验收标准**LCP/CLS/FID/TTFB 上报 + trace 上报 collector
#### 16.15 Vitest 单测 + Playwright E2E覆盖率 ≥ 80%
- **交付物**`apps/admin-portal/src/**/*.test.tsx` + `e2e/*.spec.ts`
- **验收标准**:覆盖率 ≥ 80%E2E 覆盖登录 → dashboard → 用户 CRUD → 审计日志主链路
#### 16.16 Dockerfile 多阶段 + /api/health + /api/ready
- **交付物**`apps/admin-portal/Dockerfile`builder + runtime非 root+ `src/app/api/health/route.ts` + `src/app/api/ready/route.ts`
- **验收标准**`/api/health` 返回 200`/api/ready` 检查 Shell URL 可达Dockerfile HEALTHCHECK 配置
---
## §4 依赖与就绪信号
- **我依赖**:⚠️ 由 ai16 自行补充(见 contract.md
- **我的就绪信号**:⚠️ 由 ai16 自行补充
### 4.1 我依赖(上游就绪标志
- [ ] teacher-portal Shell MF exposes/shared 就绪ai13ARB-002—— Remote 挂载前提
- [ ] teacher-bff GraphQL :3003 启用ai03—— admin 命名空间可用(**ISSUE-005 待 ai03 补齐 schema**
- [ ] api-gateway HTTP :8080 启用 + JWT 验签 + admin 角色校验ai01
- [ ] iam gRPC 50052 启用ai06—— 用户/角色/审计日志数据来源
- [ ] `edu.iam.audit.created` topic 有事件发布ai06—— 审计日志来源(经 teacher-bff 消费)
- [ ] push-gateway WebSocket :8081/ws 启用ai02—— 实时通知(**ISSUE-006 待 coord 仲裁**
- [ ] `packages/contracts` admin 权限点 `ADMIN_*` 常量就绪coord
### 4.2 我的就绪信号(供下游消费)
- [ ] admin-portal dev server :4003 启用
- [ ] MF Remote 可被 AppShell 加载(暴露 `./AdminApp` 模块)
- [ ] 独立壳渲染(首页 + 导航 + 路由守卫 + admin 角色校验)
- [ ] 登录流程可用(复用 Shell `/login`admin 角色校验后重定向 `/admin/dashboard`)—— **不自行实现登录页**(对齐 ARB-002 §2.3
- [ ] GraphQL 查询可执行currentUser / adminDashboard / auditLogs 返回数据)
- [ ] 用户/角色 CRUD 可执行createUser / updateRolePermissions
- [ ] WebSocket 通知可接收
---
## §5 风险跟踪
| 风险 | 影响 | 缓解 | 状态 |
| ---- | ---- | ---- | ---- |
| teacher-bff admin namespace schema 缺失ISSUE-005 | P3+ 全部业务页阻塞 | 提请 coord 仲裁 ai03 在 P3 启动前补齐P2 用 MSW mock 推进 | ⏳ 待仲裁 |
| 01/02 文档 REST/3003/ai07 与仲裁不一致 | 误导实现 | 已提 7 项异议ISSUE-001~007以 contract.md 为修订基准 | ⏳ 待仲裁 |
| Shell 延迟暴露 GraphQLProvider | P2 骨架阻塞 | P2 用独立壳 + mock providersShell 就绪后切换 | ⏳ |
| MF SSR 对齐复杂 | Remote SSR 上下文依赖 Shell | 优先 CSRSSR 仅首屏 dashboard | ⏳ |