Files
Edu/apps/admin-portal/docs/01-understanding.md
SpecialX e691cd267d docs(teacher-portal): ai07 阶段1+2 拆分到4端portal的docs目录
删除合并版README,按portal拆分8份文档(每端01-understanding+02-architecture-design)

teacher-portal(shell/P2)+student-portal(remote/P3)+parent-portal(remote/P4)+admin-portal(remote/P6)

AI Agent: ai07 (4 portals)

Branch: docs/portals-stage1-stage2-design-ai07
2026-07-09 18:23:27 +08:00

234 lines
18 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 模块理解确认书 — admin-portal
> AIai07TS/React · 管理场景域前端 remote
> 阶段:阶段 1 交付物
> 日期2026-07-09
> 关联:[004 架构影响地图](../../../docs/architecture/004_architecture_impact_map.md) §1.1a/1.1b/§5.4、[AI 分配方案](../../../docs/architecture/ai-allocation.md) §5 ai07、[pending-features P6](../../../docs/architecture/roadmap/pending-features.md)、[known-issues §2.12](../../../docs/troubleshooting/known-issues.md)、[teacher-portal 阶段1](../../teacher-portal/docs/01-understanding.md)、[teacher-portal 阶段2](../../teacher-portal/docs/02-architecture-design.md)
---
## 1. 我在架构中的位置
- **层级**L2 微前端层004 §3.1 六层架构中的前端层)
- **MF 角色****Remote 子应用**,挂载到 teacher-portal Shell主应用
- **上游(谁调用我)**:浏览器(系统管理员 / 校管理员)
- **下游(同步)**api-gatewayREST经 teacher-portal Shell 的 Next.js `rewrites` 代理 `/api/v1/*`
- **下游(推送)**:— **不消费推送**,管理端用轮询)
- **BFF 对接**teacher-bff 复用(`/admin/*` 聚合)+ iam 直连(`/iam/*` 用户/角色/权限/视口 CRUD
- **通信方式**HTTP/REST前端→Gateway
- **不直连**:前端不直连任何业务服务或 BFF 后端实例,全部经 api-gateway 代理
**说明**
- admin-portal 作为 Remote 子应用,挂载到 teacher-portal Shell 提供的 AppShell + 共享依赖react/react-dom/@tanstack/react-query/zustand/nuqs/ui-components/ui-tokens/contracts/hooks
- 路由前缀 `/admin/*` 由 teacher-portal Shell 动态加载 admin-portal Remote 模块
- 场景域 BFF 复用策略004 §5.4):系统/校管理员复用 teacher-portal Shell + teacher-bff`/admin/*` 视口)+ iam 直连,不单独建 portal 后端
- 全部业务请求经 api-gateway 代理admin-portal 本身不实现 rewrites依赖 Shell 的 rewrites
## 2. 我的限界上下文
### 2.1 我负责的聚合 / 实体(前端视图模型)
- 用户、角色、权限、视口(管理场景域前端视图)
- 组织(学校/年级/班级层级)
- 平台监控(运行时指标、用户活动、错误统计)
- 会话状态Session、视口Viewport、权限Permission与 teacher-portal 共享,引用 teacher-portal 文档)
### 2.2 业务领域
- **管理场景域**(前端场景域:管理场景域,对应后端 iam 限界上下文 + teacher-bff 管理视口)
### 2.3 不负责
- 教学业务编排(班级/考试/作业/成绩 CRUD归 teacher-portal
- 学生作答界面(归 student-portal
- 家长多子女切换(归 parent-portal
- 教师仪表盘(归 teacher-portaladmin-portal 仅有管理仪表盘)
### 2.4 数据范围
- DataScope L3-L5校管理员 L3 学校 / 区教研员 L4 / 系统管理员 L5 全平台)
- 不出现 L1班级/ L2年级级别的教师数据视角
## 3. 我与外部的契约
### 3.1 消费的后端 API经 api-gateway 代理)
| 路径前缀 | 下游 BFF/服务 | 关键端点 |
| ------------------------- | --------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------- |
| `/api/v1/iam/*`(管理用) | iam | `GET /iam/users``POST /iam/users``PUT /iam/users/:id``GET /iam/roles``GET /iam/permissions``GET /iam/viewports``PUT /iam/viewports/:id` |
| `/api/v1/admin/*` | teacher-bff 复用 + iam 直连 | `GET /admin/dashboard``GET /admin/monitoring/metrics``GET /admin/stats/users``GET /admin/stats/active-sessions` |
| `/api/v1/notifications/*` | msg | 通知中心P5 |
### 3.2 统一响应契约
所有后端响应遵循 `ActionState` 结构(迁移指南 §7.5
```typescript
type ActionState<T> =
| { success: true; data: T }
| {
success: false;
error: { code: string; message: string; details?: unknown };
};
```
错误码前缀按服务名大写admin-portal 涉及:`IAM_``BFF_TEACHER_``GW_``NETWORK_`)。前端 API 请求层根据 `error.code` 前缀路由到对应的 i18n key。
### 3.3 推送契约
**— N/A**
admin-portal **不消费** WebSocket 推送或 SSE 流式响应。管理端场景对实时性要求低,采用**轮询**策略:
- 平台监控页60s 轮询 `GET /api/v1/admin/monitoring/metrics`
- 用户活动统计5min 轮询 `GET /api/v1/admin/stats/active-sessions`
- 通知中心P5HTTP 长轮询或定时拉取 `GET /api/v1/notifications`(不走 push-gateway
> 长期监控指标推荐用 `<iframe>` 嵌入 Grafana 面板PlatformMonitor 组件),不经过 BFF。
### 3.4 proto 不直接消费
前端不调用 gRPCBFF 把 gRPC 聚合为 REST 暴露给前端。前端仅消费 `packages/contracts/src/permissions.ts` 中的权限点常量TS 文件,非 proto 生成)。
## 4. 我的技术栈
| 维度 | 选型 | 说明 |
| --------------------------- | -------------------------------------------------------- | ----------------------------------------------- |
| 框架 | Next.js 14+App Router | server components 默认client components 按需 |
| 语言 | TypeScript 5.5+strict | 沿用 tsconfig.base.json |
| 微前端 | Module Federation 2.0@module-federation/nextjs-mf | admin-portal = **Remote** |
| 样式 | Tailwind CSS 3.4+ | 配合设计令牌三层模型(与 teacher-portal 共享) |
| UI 组件库 | shadcn/ui迁移指南 §7.2 | 复用 Shell 暴露的 `packages/ui-components/` |
| 状态管理 L1 URL | nuqs | 可分享、可刷新状态 |
| 状态管理 L2 Server | TanStack Query v5 | 服务端数据缓存、重试、乐观更新 |
| 状态管理 L3 Client Business | Zustand slice | 客户端业务状态 |
| 状态管理 L4 Global UI | Zustand ui-store + ModalRoot复用 Shell | 全局 UI 状态 |
| 状态管理 L5 Form | react-hook-form + zodResolver | 表单状态 |
| 富文本 | — **不使用** | 管理端无富文本场景,不引入 Tiptap |
| 图表 | recharts | 管理仪表盘、用户活动统计 |
| i18n | next-intl | BFF/服务返回 i18n key + 参数,前端翻译 |
| A11y | eslint-plugin-jsx-a11yerror 级) | WCAG 2.2 AA |
| 字体 | Intersans/ Frauncesserif/ JetBrains Monomono | 复用 teacher-portal RootLayout 加载,不重复引入 |
> 技术栈与 teacher-portal **完全一致**差异仅在MF 角色Remote 而非 Shell、不使用 Tiptap、不消费 WebSocket/SSE 推送、数据范围 L3-L5。
## 5. 我的阶段归属
- **阶段**P6硬化阶段
- **当前状态**:❌ **全为待建**admin-portal 当前为空目录,无任何代码);📐 需设计(待全部业务服务稳定)
- **依赖上游阶段**P6依赖 teacher-portal Shell 已就绪 + iam 已实现用户/角色/权限/视口 CRUD + teacher-bff 已实现 `/admin/*` 复用)
## 6. 我需要对齐的黄金模板项(对照 classes 服务)
> 前端无 `@RequirePermission` 装饰器(后端概念),对齐项改造为前端等价物。
| 对齐项 | classes后端黄金模板 | admin-portal 前端等价 | 当前状态 |
| --------------------- | ------------------------------------- | ------------------------------------------------------------------------ | -------------------------- |
| 权限校验 | `@RequirePermission(Permissions.XXX)` | `usePermission().hasPermission("XXX")` Hook + `<RequirePermission>` 组件 | ❌ 待建(无现有代码) |
| 错误码前缀统一 | `CLASSES_*``IAM_*` | API 请求层根据 `error.code` 前缀路由 i18n | ❌ 待建 |
| logger | pino | 前端 console + SentryP6 | ❌ 待建 |
| metrics | prom-client `/metrics` | 前端 Web Vitals → Gateway 上报 | ❌ 待建 |
| tracer | OTel SDK | 前端 OTel browser SDKP6 | ❌ 待建 |
| /healthz + /readyz | `GET /healthz` `GET /readyz` | Next.js `/api/health` route + Dockerfile HEALTHCHECK | ❌ 待建 |
| 优雅关闭 | SIGTERM handler | Next.js 无长连接,无需 | ✅ N/A |
| 测试覆盖率 ≥ 80% | Vitest | Vitest + @testing-library/react + Playwright E2E | ❌ 待建0% |
| Dockerfile 多阶段构建 | builder + runtime | builder + runtime | ❌ 待建 |
| Zod 输入验证 | class-validator + Zod schema | react-hook-form + zodResolver | ❌ 待建 |
| GlobalErrorFilter | NestJS 全局异常过滤器 | React ErrorBoundary + API 请求层统一错误处理 | ❌ 待建 |
| 设计令牌三层 | — | primitive.css / semantic-light/dark.css / tailwind-theme.css复用 | ❌ 待建(复用 Shell 暴露) |
| A11y 工具集 | — | useA11yId / mergeA11yProps / describeInput / focus-trap复用 Shell | ❌ 待建(复用 Shell 暴露) |
---
## 附admin-portal 现状审计(对齐黄金模板)
### 审计表
| 维度 | 状态 | 说明 |
| ------------------------------------ | ------ | ------------------------------------------------------------------------- |
| 权限装饰器(前端等价 usePermission | ❌ | 待建,复用 Shell 暴露的 `usePermission` Hook + `<RequirePermission>` 组件 |
| 错误码前缀 | ❌ | 待建,复用 Shell 暴露的 ApiClient统一请求层 |
| logger | ❌ | 待建,复用 `packages/shared-ts/src/logger.ts` |
| metrics | ❌ | 待建Web Vitals 上报 `admin_portal_*` |
| tracer | ❌ | 待建OTel browser SDKP6 |
| /healthz | ❌ | 待建Next.js Route Handler |
| /readyz | ❌ | 待建Next.js Route Handler |
| 优雅关闭 | ✅ N/A | Next.js 无长连接 |
| 测试覆盖率 | ❌ | 待建,目标 ≥ 80% |
| Dockerfile 多阶段 | ❌ | 待建builder + runtime |
| Zod 输入验证 | ❌ | 待建react-hook-form + zodResolver |
| GlobalErrorFilterErrorBoundary | ❌ | 待建,复用 Shell 暴露的 ErrorBoundary |
| 设计令牌三层 | ❌ | 待建,复用 Shell 暴露的 `packages/ui-tokens/` |
| A11y 工具集 | ❌ | 待建,复用 Shell 暴露的 `packages/ui-components/` |
| Module Federation 配置 | ❌ | 待建next.config.js 配置 Remote 角色 |
| 5 层状态管理 | ❌ | 待建,复用 Shell 暴露的 nuqs/TanStack Query/Zustand |
| 共享组件库 | ❌ | 待建,复用 Shell 暴露 + admin 特有 4 个组件 |
| i18n | ❌ | 待建next-intl |
| API 请求层 | ❌ | 待建,复用 Shell 暴露的 ApiClient |
| ESLint flat config 自定义规则 | ❌ | 待建no-hardcoded-fonts / design-tokens 规则 |
### 现有文件清单
```
apps/admin-portal/ # 空目录(待建)
```
**说明**admin-portal 当前为空目录,所有维度均为 ❌ 待建状态。无现有文件、无现有代码、无现有违规点。P6 阶段从零开始搭建。
### L1 导航菜单(视口)
| 视口 key | 标签i18n key | 路由 | 权限 |
| -------------- | ------------------------ | --------------------- | ----------------------- |
| `dashboard` | `admin.nav.dashboard` | `/admin/dashboard` | `ADMIN_DASHBOARD_VIEW` |
| `users` | `admin.nav.users` | `/admin/users` | `IAM_USER_READ` |
| `roles` | `admin.nav.roles` | `/admin/roles` | `IAM_ROLE_READ` |
| `permissions` | `admin.nav.permissions` | `/admin/permissions` | `IAM_PERMISSION_READ` |
| `viewports` | `admin.nav.viewports` | `/admin/viewports` | `IAM_VIEWPORT_READ` |
| `organization` | `admin.nav.organization` | `/admin/organization` | `ORG_MANAGE` |
| `monitoring` | `admin.nav.monitoring` | `/admin/monitoring` | `ADMIN_MONITORING_VIEW` |
### L2 路由表
| 路由 | 页面 | 权限 |
| --------------------- | ---------- | ----------------------- |
| `/admin/dashboard` | 管理仪表盘 | `ADMIN_DASHBOARD_VIEW` |
| `/admin/users` | 用户管理 | `IAM_USER_READ` |
| `/admin/users/new` | 新建用户 | `IAM_USER_CREATE` |
| `/admin/users/:id` | 用户编辑 | `IAM_USER_UPDATE` |
| `/admin/roles` | 角色管理 | `IAM_ROLE_READ` |
| `/admin/permissions` | 权限管理 | `IAM_PERMISSION_READ` |
| `/admin/viewports` | 视口配置 | `IAM_VIEWPORT_READ` |
| `/admin/organization` | 组织管理 | `ORG_MANAGE` |
| `/admin/monitoring` | 平台监控 | `ADMIN_MONITORING_VIEW` |
### L3 组件级差异admin-portal 特有)
**复用 Shell 暴露的组件**AppShell、RequirePermission、ErrorBoundary、Loading、Empty、DataTable、Form、Chart、Toast、Modal、Button/Input/Select/Textarea、A11y 工具集
**admin-portal 特有组件**
| 组件 | 用途 | 来源 |
| ---------------------- | --------------------------------------- | ---- |
| `UserManagementTable` | 用户管理表格(列表/筛选/分页/批量操作) | 新建 |
| `RolePermissionMatrix` | 角色-权限矩阵编辑器checkbox 网格) | 新建 |
| `ViewportConfigEditor` | 视口配置编辑器(拖拽排序 + 权限绑定) | 新建 |
| `PlatformMonitor` | 平台监控Grafana iframe embed | 新建 |
**不使用的组件**RichTextEditorTiptap、ExamTaking、SSEViewer、ChildSwitcher 等(这些归 teacher-portal / student-portal / parent-portal
### L4 数据层差异
| 维度 | admin-portal | teacher-portal |
| ------------ | --------------------------------- | -------------------------------------- |
| 主要数据来源 | iam 直连 + teacher-bff 复用 | teacher-bff 聚合 + core-edu/content/ai |
| 缓存策略 | **5min 长缓存**(管理数据低频变) | 5min / 30s 混合(实时性差异) |
| 实时性要求 | 低(轮询 60s / 5min | 高WebSocket 推送 + SSE 流式) |
| 推送消费 | ❌ 不消费 | ✅ 消费 WebSocket + SSE |
---
**AI Agent**: ai07 (admin-portal remote)
**Branch**: docs/admin-portal-stage1-stage2-design-ai07
**Coordinator**: coord-ai