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
This commit is contained in:
SpecialX
2026-07-09 18:23:27 +08:00
parent fd5b6e19ae
commit e691cd267d
9 changed files with 3457 additions and 945 deletions

View File

@@ -0,0 +1,235 @@
# 模块理解确认书 — parent-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 ai05/ai07、[pending-features P4](../../../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经 Next.js `rewrites` 代理 `/api/v1/*`
- **下游推送P5**push-gatewayWebSocket
- **BFF 对接**parent-bff待 ai05 设计)
- **通信方式**HTTP/REST前端→Gateway+ WebSocket前端→push-gatewayP5
- **不直连**:前端不直连任何业务服务或 BFF 后端实例,全部经 api-gateway 代理
**说明**
- 通过 `next.config.js``rewrites``/api/v1/*` 代理到 `api-gateway`
- MF 架构下parent-portal 作为 Remote 子应用挂载到 teacher-portal Shell复用 Shell 的 AppShell、共享依赖、权限 Hook、API 请求层
- 不独立提供 RootLayout / 登录页 / 字体加载 / 令牌初始化,全部由 Shell 提供
- 与 teacher-portal 共享会话状态Session、视口Viewport、权限Permission三个核心模型
## 2. 我的限界上下文
### 2.1 我负责的聚合 / 实体(前端视图模型)
- 多子女切换、通知偏好、学情查看、成绩通知(家长场景域前端视图)
- 会话状态Session、视口Viewport、权限Permission—— 与 teacher-portal 共享
- 多子女状态ChildSwitcher—— 家长端特有
### 2.2 业务领域
- **D5 家长场景域**(前端场景域:家长场景域)
### 2.3 不负责
- 教师沟通(归 teacher-portal
- 学生作答(归 student-portal
- 用户/角色/权限 CRUD归 admin-portal
- 成绩录入(归 teacher-portal家长端仅查看
### 2.4 数据范围
- DataScope L0仅子女—— 家长只能查看自己子女的数据,不能跨家庭
## 3. 我与外部的契约
### 3.1 消费的后端 API经 api-gateway 代理)
| 路径前缀 | 下游 BFF/服务 | 关键端点 |
| ------------------------- | ------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- |
| `/api/v1/parent/*` | parent-bff | `GET /parent/viewports``GET /parent/children``POST /parent/switch-child``GET /parent/notifications``PUT /parent/notification-preferences` |
| `/api/v1/iam/*` | iam | `POST /iam/login``GET /iam/me``GET /iam/effective-permissions` |
| `/api/v1/notifications/*` | msg | 通知中心P5 |
> parent-bff 聚合 iam + core-edu + data-ana + msg对外暴露家长场景的统一接口子女关联、视口、学情聚合
### 3.2 统一响应契约
所有后端响应遵循 `ActionState` 结构(迁移指南 §7.5
```typescript
type ActionState<T> =
| { success: true; data: T }
| {
success: false;
error: { code: string; message: string; details?: unknown };
};
```
错误码前缀按服务名大写(如 `IAM_``CORE_EDU_``GRADES_``HOMEWORK_``BFF_PARENT_``GW_``NETWORK_`)。前端 API 请求层根据 `error.code` 前缀路由到对应的 i18n key。
### 3.3 推送契约P5
| 协议 | 场景 |
| ------------------------- | -------------------------------- |
| WebSocketpush-gateway | 子女成绩发布、教师沟通、学校通知 |
### 3.4 proto 不直接消费
前端不调用 gRPCBFF 把 gRPC 聚合为 REST 暴露给前端。前端仅消费 `packages/contracts/src/permissions.ts` 中的权限点常量TS 文件,非 proto 生成)。
## 4. 我的技术栈
| 维度 | 选型 | 说明 |
| --------------------------- | -------------------------------------------------------- | ------------------------------------------------------- |
| 框架 | Next.js 14+App Router | 与 teacher-portal 一致MF Remote 角色 |
| 语言 | TypeScript 5.5+strict | 沿用 tsconfig.base.json |
| 微前端 | Module Federation 2.0@module-federation/nextjs-mf | parent-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 | 客户端业务状态(含 ChildSwitcher 多子女状态) |
| 状态管理 L4 Global UI | Zustand ui-store + ModalRoot | 全局 UI 状态(复用 Shell 暴露) |
| 状态管理 L5 Form | react-hook-form + zodResolver | 表单状态(通知偏好设置) |
| 富文本 | N/A | 家长端不使用 Tiptap |
| 图表 | recharts | 子女学情、Dashboard |
| i18n | next-intl | BFF/服务返回 i18n key + 参数,前端翻译 |
| A11y | eslint-plugin-jsx-a11yerror 级) | WCAG 2.2 AA |
| 字体 | Intersans/ Frauncesserif/ JetBrains Monomono | 由 Shell RootLayout 加载parent-portal 仅消费 CSS 变量 |
## 5. 我的阶段归属
- **阶段**P4
- **当前状态**:📐 需设计(待 parent-bff + data-ana 就绪apps/parent-portal/ 目录为空(待建)
- **依赖上游阶段**P4parent-bff + data-ana
## 6. 我需要对齐的黄金模板项(对照 classes 服务)
> 前端无 `@RequirePermission` 装饰器后端概念对齐项改造为前端等价物。parent-portal 与 teacher-portal 共享前端等价物实现。
| 对齐项 | classes后端黄金模板 | parent-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 | ❌ 待建 |
| 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 | ❌ 待建 |
| A11y 工具集 | — | useA11yId / mergeA11yProps / describeInput / focus-trap | ❌ 待建 |
---
## 附parent-portal 现状审计(对齐黄金模板)
### 审计表
| 维度 | 状态 | 说明 |
| ------------------------------------ | ------ | --------------------------------------------- |
| 权限装饰器(前端等价 usePermission | ❌ | 待建,复用 Shell 暴露的 usePermission Hook |
| 错误码前缀 | ❌ | 待建,复用 Shell 暴露的 ApiClient |
| logger | ❌ | 待建,复用 packages/shared-ts/src/logger.ts |
| metrics | ❌ | 待建Web Vitals 上报 |
| tracer | ❌ | 待建OTel browser SDKP6 |
| /healthz | ❌ | 待建Next.js Route Handler |
| /readyz | ❌ | 待建 |
| 优雅关闭 | ✅ N/A | Next.js 无长连接 |
| 测试覆盖率 | ❌ | 0%,无测试文件(待建) |
| Dockerfile 多阶段 | ❌ | 待建builder + runtime |
| Zod 输入验证 | ❌ | 待建react-hook-form + zodResolver |
| GlobalErrorFilterErrorBoundary | ❌ | 待建,复用 Shell 暴露的 ErrorBoundary |
| 设计令牌三层 | ❌ | 待建,复用 packages/ui-tokens |
| A11y 工具集 | ❌ | 待建,复用 Shell 暴露的 A11y 工具集 |
| Module Federation 配置 | ❌ | 待建Remote 角色) |
| 5 层状态管理 | ❌ | 待建(含 ChildSwitcher 多子女 Zustand slice |
| 共享组件库 | ❌ | 待建(复用 Shell 暴露 + 新增 ChildSwitcher |
| i18n | ❌ | 待建next-intl |
| API 请求层 | ❌ | 待建,复用 Shell 暴露的 ApiClient |
| ESLint flat config 自定义规则 | ❌ | 待建,复用 teacher-portal 配置 |
### 现有文件清单
```
apps/parent-portal/
└─ (空目录,待建)
```
> parent-portal 当前为空目录,所有维度均为 ❌ 待建状态。基础设施Shell 暴露的 AppShell、共享依赖、权限 Hook、API 请求层、设计令牌、UI 组件、A11y 工具集)由 teacher-portal Shell 在 P2 收尾时建立parent-portal 在 P4 启动时直接复用。
---
## 7. L1 导航菜单(视口)
家长端 L1 导航菜单由 parent-bff 通过 `GET /parent/viewports` 返回AppShell 按 `scope: 'parent'` 过滤渲染:
- Dashboard家长仪表盘
- 子女切换
- 成绩查看
- 作业查看
- 通知中心P5
- 通知偏好设置
## 8. L2 路由表
| 路由 | 页面 | 权限 |
| ----------------------- | -------------- | --------------------------- |
| `/parent/dashboard` | 家长仪表盘 | `PARENT_DASHBOARD_VIEW` |
| `/parent/children` | 子女列表 | `PARENT_CHILDREN_VIEW` |
| `/parent/grades` | 子女成绩 | `GRADES_READ_CHILD` |
| `/parent/homework` | 子女作业 | `HOMEWORK_READ_CHILD` |
| `/parent/notifications` | 通知中心P5 | `NOTIFICATION_READ_OWN` |
| `/parent/preferences` | 通知偏好 | `PARENT_PREFERENCES_UPDATE` |
> L3 组件级视口用 `<RequirePermission perm="PARENT_PREFERENCES_UPDATE"><Button>保存</Button></RequirePermission>`。
## 9. L3 组件级差异parent-portal 特有)
### 9.1 复用 Shell 暴露的组件
- AppShell左栏导航 + 主内容区)
- RequirePermissionL3 组件级视口控制)
- ErrorBoundaryReact 渲染异常兜底)
- Loading骨架屏
- Empty空态
- DataTable表格
- Formreact-hook-form + zodResolver 封装)
- Chartrecharts 封装)
### 9.2 parent-portal 特有组件
| 组件 | 用途 | 来源 |
| --------------- | ---------------------------------------------------------- | ---- |
| `ChildSwitcher` | 多子女切换组件(顶部 Tab切换后 invalidate 子女相关查询 | 新建 |
### 9.3 不使用的组件
- RichTextEditorTiptap—— 家长端不编辑富文本
- ExamTaking —— 学生考试专用
- SSEViewer —— AI 流式响应查看器(教师端专用)
- UserManagementTable —— 管理员端专用
## 10. L4 数据层差异
| 维度 | teacher-portal | parent-portal |
| ---------- | -------------- | -------------------------------------------------------------- |
| 主要数据源 | teacher-bff | parent-bff聚合 iam + core-edu + data-ana + msg |
| 缓存策略 | 5-30s 短缓存 | 5-30s 短缓存,**子女切换 invalidate** 子女相关查询 |
| 多子女状态 | N/A | ChildSwitcher Zustand slice当前子女 ID 持久化到 localStorage |
---
**AI Agent**: ai07 (parent-portal remote)
**Branch**: docs/parent-portal-stage1-stage2-design-ai07