Files
Edu/apps/student-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

410 lines
28 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.
# 模块理解确认书 — student-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 P3](../../../docs/architecture/roadmap/pending-features.md)、[teacher-portal 阶段 1](../../teacher-portal/docs/01-understanding.md)、[teacher-portal 阶段 2](../../teacher-portal/docs/02-architecture-design.md)、[known-issues §2.12](../../../docs/troubleshooting/known-issues.md)
---
## 1. 我在架构中的位置
- **层级**L2 微前端层004 §3.1 六层架构中的前端层)
- **MF 角色****Remote 子应用**,挂载到 teacher-portal Shell
- **上游(谁调用我)**:浏览器(学生)
- **下游(同步)**api-gatewayREST经 Next.js `rewrites` 代理 `/api/v1/*`
- **下游推送P5**push-gatewayWebSocket
- **BFF 对接**student-bff待 ai04 设计)
- **通信方式**HTTP/REST前端→Gateway+ WebSocket前端→push-gatewayP5
- **不直连**:前端不直连任何业务服务或 BFF 后端实例,全部经 api-gateway 代理
**说明**
- 通过 `next.config.js``rewrites``/api/v1/*` 代理到 `api-gateway`(与 Shell 一致的代理策略)
- MF 架构下student-portal 作为 Remote 暴露页面入口,由 teacher-portal Shell 的 AppShell 动态加载
- 复用 Shell 暴露的共享依赖react/react-dom/@tanstack/react-query/zustand/nuqs/ui-components/ui-tokens/contracts/hooks
- 不独立提供 RootLayout / 字体加载 / 设计令牌 / i18n Provider全部由 Shell 提供
## 2. 我的限界上下文
### 2.1 我负责的聚合 / 实体(前端视图模型)
- 作答、作业提交、学情诊断、错题本(学习场景域前端视图)
- 会话状态Session、视口Viewport、权限Permission— 与 Shell 共享,引用 teacher-portal 文档
### 2.2 业务领域
- **D3 教学核心领域**(前端场景域:学习场景域,学生视角)
### 2.3 不负责
- 教师批改界面(归 teacher-portal
- AI 出题(归 teacher-portal
- 班级/考试/作业 CRUD 管理(归 teacher-portal
- 用户/角色/权限 CRUD归 admin-portal
- 家长多子女切换(归 parent-portal
### 2.4 数据范围
- DataScope **L0仅本人**:学生只能看到自己的作业、考试、成绩、学情、错题
## 3. 我与外部的契约
### 3.1 消费的后端 API经 api-gateway 代理)
| 路径前缀 | 下游 BFF/服务 | 关键端点 |
| ------------------------- | ------------- | ------------------------------------------------------------------------------------------------------------------------------------------- |
| `/api/v1/student/*` | student-bff | `GET /student/viewports``GET /student/dashboard``GET /student/homework``POST /student/homework/:id/submit``GET /student/diagnostic` |
| `/api/v1/iam/*` | iam | `POST /iam/login``GET /iam/me``GET /iam/effective-permissions` |
| `/api/v1/notifications/*` | msg | 通知中心P5 |
> student-bff 由 ai04 设计,聚合 iam + core-edu + data-ana为学生场景提供聚合视图。student-portal 主要消费 student-bff少量直连 iam登录/权限/视口)。
### 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_``EXAMS_``HOMEWORK_``GRADES_``BFF_STUDENT_``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 | server components 默认client components 按需 |
| 语言 | TypeScript 5.5+strict | 沿用 tsconfig.base.json |
| 微前端 | Module Federation 2.0@module-federation/nextjs-mf | student-portal = Remote |
| 样式 | Tailwind CSS 3.4+ | 配合设计令牌三层模型(复用 Shell 提供的令牌) |
| 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 | 全局 UI 状态(复用 Shell |
| 状态管理 L5 Form | react-hook-form + zodResolver | 表单状态(作业提交表单) |
| 富文本 | **不使用**(学生不作答富文本,作业提交用表单) | 与 teacher-portal 差异点 |
| 图表 | recharts | 学情诊断、Dashboard |
| i18n | next-intl | 复用 Shell Provider按 scope=student 加载翻译 |
| A11y | eslint-plugin-jsx-a11yerror 级) | WCAG 2.2 AA |
| 字体 | Intersans/ Frauncesserif/ JetBrains Monomono | 复用 Shell 的 next/font/google 加载 |
## 5. 我的阶段归属
- **阶段**P3
- **当前状态**:📐 待设计(待 core-edu + student-bff 就绪),依赖上游阶段 P3
- **依赖上游阶段**P1api-gateway + iam+ P2teacher-portal Shell 就绪)+ P3core-edu + student-bff
## 6. 我需要对齐的黄金模板项(对照 classes 服务)
> 前端无 `@RequirePermission` 装饰器(后端概念),对齐项改造为前端等价物。
| 对齐项 | classes后端黄金模板 | student-portal 前端等价 | 当前状态 |
| --------------------- | ------------------------------------- | ------------------------------------------------------------------------ | ----------------------------------- |
| 权限校验 | `@RequirePermission(Permissions.XXX)` | `usePermission().hasPermission("XXX")` Hook + `<RequirePermission>` 组件 | ❌ 待建(复用 Shell 暴露的 hooks |
| 错误码前缀统一 | `CLASSES_*``IAM_*` | API 请求层根据 `error.code` 前缀路由 i18n | ❌ 待建(复用 Shell ApiClient |
| logger | pino | 前端 console + SentryP6 | ❌ 待建(复用 shared-ts Logger |
| 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 请求层统一错误处理 | ❌ 待建(复用 Shell ErrorBoundary |
| 设计令牌三层 | — | 复用 Shell 提供的 primitive/semantic-light/dark/tailwind-theme | ❌ 待建(依赖 ui-tokens 包) |
| A11y 工具集 | — | useA11yId / mergeA11yProps / describeInput / focus-trap | ❌ 待建(复用 Shell 暴露的 hooks |
---
## 附student-portal 现状审计(对齐黄金模板)
### 审计表
| 维度 | 状态 | 说明 |
| ------------------------------------ | ------ | ---------------------------------------------------- |
| 权限装饰器(前端等价 usePermission | ❌ | 待建,复用 Shell 暴露的 `usePermission` Hook |
| 错误码前缀 | ❌ | 待建,复用 Shell 暴露的 ApiClient |
| logger | ❌ | 待建,复用 shared-ts Logger |
| metrics | ❌ | 待建Web Vitals 上报 |
| tracer | ❌ | 待建OTel browser SDK |
| /healthz | ❌ | 待建Next.js `/api/health` route |
| /readyz | ❌ | 待建Next.js `/api/ready` route |
| 优雅关闭 | ✅ N/A | Next.js 无长连接 |
| 测试覆盖率 | ❌ | 待建,目标 ≥ 80% |
| Dockerfile 多阶段 | ❌ | 待建builder + runtime |
| Zod 输入验证 | ❌ | 待建react-hook-form + zodResolver |
| GlobalErrorFilterErrorBoundary | ❌ | 待建,复用 Shell ErrorBoundary |
| 设计令牌三层 | ❌ | 待建,复用 ui-tokens 包 |
| A11y 工具集 | ❌ | 待建,复用 hooks 包 |
| Module Federation 配置 | ❌ | 待建Remote 角色 |
| 5 层状态管理 | ❌ | 待建,复用 Shell Provider |
| 共享组件库 | ❌ | 待建,复用 Shell 暴露的 ui-components |
| i18n | ❌ | 待建,复用 Shell Provider + scope=student 翻译 |
| API 请求层 | ❌ | 待建,复用 Shell ApiClient仅注入不同 baseUrl/token |
| ESLint flat config 自定义规则 | ❌ | 待建,与 Shell 共用配置 |
### 现有文件清单
```
apps/student-portal/ # 空目录,待建
```
> student-portal 当前为空目录,所有维度均为 ❌ 待建状态。无现有文件清单。本设计文档作为 P3 起步的输入。
### 主要待建项(必须在 P3 起步时建立)
1. **MF Remote 配置**`next.config.js` 配置 `name: 'student_app'``exposes``remotes: { teacher: ... }`
2. **路由表**`/student/dashboard``/student/homework``/student/homework/:id/submit``/student/exams``/student/exams/:id/take``/student/diagnostic``/student/weakness``/student/notifications`
3. **ExamTaking 组件**:考试作答(倒计时 + 自动保存student-portal 特有
4. **作业提交表单**react-hook-form + zodResolver不用 Tiptap
5. **Dockerfile 多阶段构建**builder + runtime + HEALTHCHECK
6. **Vitest + Playwright 测试**:覆盖率 ≥ 80%
7. **`/api/health` + `/api/ready` route**:健康检查端点
---
## 7. L1 导航菜单(视口)
| 视口 key | 文案 | 路由 | 权限 | 阶段 |
| --------------- | --------- | ------------------------ | ------------------------ | ---- |
| `dashboard` | Dashboard | `/student/dashboard` | `STUDENT_DASHBOARD_VIEW` | P3 |
| `homework` | 我的作业 | `/student/homework` | `HOMEWORK_READ_OWN` | P3 |
| `exams` | 我的考试 | `/student/exams` | `EXAMS_READ_OWN` | P3 |
| `diagnostic` | 学情诊断 | `/student/diagnostic` | `DIAGNOSTIC_READ_OWN` | P4 |
| `weakness` | 错题本 | `/student/weakness` | `WEAKNESS_READ_OWN` | P4 |
| `notifications` | 通知中心 | `/student/notifications` | `NOTIFICATION_READ_OWN` | P5 |
> 来源:`GET /api/v1/student/viewports`student-bff 聚合 iam 视口配置AppShell 按 `scope=student` 过滤渲染。
## 8. L2 路由表
| 路由 | 页面 | 权限 | 阶段 |
| ------------------------------ | ---------- | ------------------------ | ---- |
| `/student/dashboard` | 学生仪表盘 | `STUDENT_DASHBOARD_VIEW` | P3 |
| `/student/homework` | 我的作业 | `HOMEWORK_READ_OWN` | P3 |
| `/student/homework/:id/submit` | 提交作业 | `HOMEWORK_SUBMIT` | P3 |
| `/student/exams` | 我的考试 | `EXAMS_READ_OWN` | P3 |
| `/student/exams/:id/take` | 作答考试 | `EXAMS_TAKE` | P3 |
| `/student/diagnostic` | 学情诊断 | `DIAGNOSTIC_READ_OWN` | P4 |
| `/student/weakness` | 错题本 | `WEAKNESS_READ_OWN` | P4 |
| `/student/notifications` | 通知中心 | `NOTIFICATION_READ_OWN` | P5 |
## 9. L3 组件级差异student-portal 特有)
### 9.1 复用 Shell 暴露的组件
- `AppShell`(左栏导航 + 主内容区)
- `RequirePermission`L3 组件级视口控制)
- `ErrorBoundary`React 渲染异常兜底)
- `Loading`(骨架屏)
- `Empty`(空态)
- `DataTable`(表格)
- `Form`react-hook-form + zodResolver 封装)
- `Chart`recharts 封装)
### 9.2 student-portal 特有组件
| 组件 | 用途 | 来源 |
| ----------------- | --------------------------------------------- | ---- |
| `ExamTaking` | 考试作答(倒计时 + 自动保存) | 新建 |
| `HomeworkSubmit` | 作业提交表单react-hook-form + zodResolver | 新建 |
| `DiagnosticChart` | 学情诊断图表recharts 多维雷达 + 趋势线) | 新建 |
| `WeaknessList` | 错题本列表(按知识点聚合 + 掌握度标签) | 新建 |
### 9.3 不使用的组件(与 teacher-portal 差异)
- **不使用 `RichTextEditor`Tiptap**:学生不作答富文本,作业提交用表单
- 不使用 `SSEViewer`:学生不参与 AI 出题
- 不使用 `ChildSwitcher`:学生无多子女切换(家长端特有)
- 不使用 `UserManagementTable`:学生不管理用户
## 10. L4 数据层差异
| 维度 | teacher-portal | student-portal |
| ---------- | ------------------------- | -------------------------------------------------- |
| 主要数据源 | teacher-bff聚合多服务 | student-bff聚合 iam + core-edu + data-ana |
| 缓存策略 | 5min 中等缓存 | 5-30s 短缓存,作业列表 30s |
| 数据范围 | L1-L5按角色 | L0仅本人 |
| 特殊状态 | — | 考试作答草稿Zustand L3断网恢复+ 倒计时L3 |
## 11. 与其他模块的交互点(契约清单)
| 方向 | 对方服务 | 协议 | 接口/事件 | 用途 | 阶段 |
| ------ | ------------ | ------------------ | ------------------------------------ | ---------------------------- | ---- |
| 调用 | api-gateway | HTTP/REST | `/api/v1/*` 代理 | 全部业务请求 | P1+ |
| 调用 | push-gateway | WebSocket | `ws://push-gateway/ws` | 实时推送 | P5 |
| 被调用 | — | — | — | 前端不暴露接口给其他服务 | — |
| 消费 | student-bff | HTTP经 Gateway | `GET /student/viewports` 等 | 学生场景聚合 | P3+ |
| 消费 | iam | HTTP经 Gateway | `/iam/*` | 登录/权限/视口 | P2+ |
| 消费 | core-edu | HTTP经 Gateway | `/exams/*` `/homework/*` `/grades/*` | 教学核心(学生视角) | P3+ |
| 消费 | data-ana | HTTP经 Gateway | `/analytics/*` | 学情分析 | P4+ |
| 消费 | msg | HTTP经 Gateway | `/notifications/*` | 通知中心 | P5+ |
| 依赖 | coord 维护 | — | `packages/shared-proto` | TS 类型(仅 contracts 部分) | P1+ |
| 依赖 | coord 维护 | — | `packages/shared-ts`(待建) | ApiClient/Logger/通用工具 | P3+ |
| 依赖 | ai07 维护 | — | `packages/ui-tokens`(待建) | 三层设计令牌 | P3+ |
| 依赖 | ai07 维护 | — | `packages/ui-components`(待建) | shadcn + 共享组件 | P3+ |
| 依赖 | ai07 维护 | — | `packages/hooks`(待建) | usePermission/useAuth 等 | P3+ |
| 依赖 | coord 维护 | — | `packages/contracts`(待建) | Permissions 常量 + 类型 | P3+ |
## 12. 事件设计P5 WebSocket 推送)
| 事件 | 触发 | student-portal 前端动作 |
| ----------------------------- | -------------- | ------------------------------ |
| `NotificationRequested` | msg 服务投递 | toast 提示 + 通知中心未读数 +1 |
| `ExamPublished` | 教师发布考试 | toast + dashboard invalidate |
| `GradeRecorded` | 教师录入成绩 | toast + 成绩列表 invalidate |
| `HomeworkDeadlineApproaching` | 作业截止前提醒 | toast + 作业列表高亮 |
## 13. 横切关注点对齐清单
### 13.1 权限(前端等价)
见 §8 L2 路由表权限列。完整权限点常量集中在 `packages/contracts/src/permissions.ts`待建立coord 负责 contractsai07 负责调用。L3 组件级视口用 `<RequirePermission perm="HOMEWORK_SUBMIT"><Button>提交作业</Button></RequirePermission>`
### 13.2 错误码清单(前端 i18n 路由)
| 前缀 | 来源服务 | i18n key 模式 |
| -------------- | ----------- | ------------------------- |
| `IAM_` | iam | `iam.error.{{code}}` |
| `CORE_EDU_` | core-edu | `coreEdu.error.{{code}}` |
| `EXAMS_` | core-edu | `exams.error.{{code}}` |
| `HOMEWORK_` | core-edu | `homework.error.{{code}}` |
| `GRADES_` | core-edu | `grades.error.{{code}}` |
| `BFF_STUDENT_` | student-bff | `bff.error.{{code}}` |
| `GW_` | api-gateway | `gateway.error.{{code}}` |
| `NETWORK_` | 前端网络层 | `network.error.{{code}}` |
### 13.3 Logger
复用 `packages/shared-ts/src/logger.ts`(同 teacher-portal开发环境 console + 结构化,生产环境 → SentryP6。必含字段trace_id、user_id、scope=student、path。
### 13.4 MetricsWeb Vitals
| 指标 | 类型 | 上报 |
| ----------------------------- | ---- | --------------------------------------------------- |
| `student_portal_lcp_seconds` | LCP | `next/web-vitals``POST /api/v1/admin/web-vitals` |
| `student_portal_cls` | CLS | 同上 |
| `student_portal_fid_seconds` | FID | 同上 |
| `student_portal_ttfb_seconds` | TTFB | 同上 |
P6 接入P3-P5 暂缓。
### 13.5 TracerOTel browser SDKP6
复用 `packages/shared-ts/src/tracer.ts`(同 teacher-portal。BatchSpanProcessor → OTLP exporter → collector → Tempo。自动埋点fetch、XMLHttpRequest、document load、user interaction。
### 13.6 健康检查
| 端点 | 用途 | 实现 |
| ----------------- | ---------------------- | -------------------------------------------------------------- |
| `GET /api/health` | Dockerfile HEALTHCHECK | Next.js Route Handler返回 `{ status: 'ok', ts: Date.now() }` |
| `GET /api/ready` | K8s readinessProbe | 检查 `process.env.API_GATEWAY_URL` 可达 + 内存 < 阈值 |
### 13.7 优雅关闭
Next.js 无长连接(除 SSE/WS无需特殊处理。WS 在 P5 由 push-gateway 管理,前端断线自动重连。
## 14. 风险与假设
### 14.1 假设
1. **假设 coord 建立 `packages/shared-ts`、`packages/contracts`**:包含 ApiClient、Logger、Permissions 常量、通用类型。若 coord 未建立ai07 自行在 `apps/student-portal/src/shared/` 内实现,后续提取到 packages。
2. **假设 ai04 student-bff 提供 `GET /student/viewports`、`GET /student/dashboard`、`GET /student/homework`、`POST /student/homework/:id/submit`、`GET /student/diagnostic`**:返回 `ActionState` 结构。错误码前缀 `BFF_STUDENT_`(待 ai04 确认)。
3. **假设 teacher-portal Shell 已就绪**AppShell + 共享依赖暴露 + MF 配置P2 收尾完成)。
4. **假设 Next.js 14+ Module Federation 2.0 稳定**`@module-federation/nextjs-mf` 在 Next.js App Router 下可用。
### 14.2 未决设计决策(需 coord 仲裁)
与 teacher-portal 相同的 4 项(详见 [teacher-portal 阶段 2 §11.3](../../teacher-portal/docs/02-architecture-design.md)
1. **packages 归属**`ui-tokens` / `ui-components` / `hooks` 是 ai07 维护还是 coord 维护?
2. **GraphQL vs REST**student-bff 是 REST 还是 GraphQL前端 API 请求层是否需要 GraphQL client
3. **i18n key 命名**`error.{{service}}.{{code_snake_case}}` 还是其他模式?
4. **MF 暴露粒度**Shell 暴露整个 AppShell 还是更细粒度的组件?
## 15. coord 交叉审查信息
### 15.1 端口矩阵
| 端 | dev 端口 | 生产端口 | 备注 |
| -------------- | -------- | -------- | ------------- |
| student-portal | 3001 | 3001 | Remote 子应用 |
### 15.2 依赖的共享包
| 包 | 路径 | 维护方 | 内容 |
| --------------- | ------------------------- | ------ | ------------------------------------------------- |
| `shared-ts` | `packages/shared-ts/` | coord | ApiClient、Logger、通用工具 |
| `contracts` | `packages/contracts/` | coord | Permissions 常量、ActionState 类型、UserInfo 类型 |
| `ui-tokens` | `packages/ui-tokens/` | ai07 | 三层设计令牌 |
| `ui-components` | `packages/ui-components/` | ai07 | shadcn + ErrorBoundary + RequirePermission |
| `hooks` | `packages/hooks/` | ai07 | usePermission、useAuth、useViewports |
### 15.3 依赖的后端契约(需对应 AI 确认)
| 契约 | 提供方 | 当前状态 |
| ------------------------------------------------------------------ | ------------------ | ------------------- |
| `POST /iam/login``GET /iam/effective-permissions``GET /iam/me` | iam | ✅ 已实现 |
| `GET /student/viewports``GET /student/dashboard` 等 | student-bff | 📐 待 ai04 设计 |
| `/exams/*` `/homework/*` `/grades/*` | core-edu | ✅ 已实现P3 |
| `/analytics/*` | data-ana | ✅ 已实现P4 CDC |
| `/notifications/*` + WebSocket 推送 | msg + push-gateway | 📐 待 P5 |
### 15.4 错误码前缀(前端 i18n 路由依赖)
| 前缀 | 服务 | 状态 |
| ------------------------------ | ----------- | --------------- |
| `IAM_` | iam | ✅ 已用 |
| `EXAMS_`/`HOMEWORK_`/`GRADES_` | core-edu | ⚠️ 待确认 |
| `BFF_STUDENT_` | student-bff | ⚠️ 待 ai04 确认 |
| `GW_` | api-gateway | ✅ 已用 |
| `NETWORK_` | 前端 | ai07 自有 |
### 15.5 不产生 Kafka 事件
前端不发布/消费 Kafka 事件。WebSocket 推送由 push-gateway 消费 Kafka 转发。
## 16. 实施路线ai07 自用)
### P3student-portal 起步)
1.`apps/student-portal/`Remote 角色)
2. 配置 MF`exposes` pages`remotes: { teacher: ... }`
3. 实现 Dashboard + 我的作业 + 提交作业 + 我的考试 + 作答考试
4. 复用 Shell 的 AppShell + 共享组件
5. SSE 接入(考试作答自动保存)
### P5推送接入
1. student-portal 接入 WebSocketpush-gateway
2. 通知中心 + 作业截止提醒
### P6硬化
1. Web Vitals + OTel browser SDK 接入
2. A11y WCAG 2.2 AA 审计
3. 性能优化MF shared 单例验证、bundle 分析)
---
**AI Agent**: ai07 (student-portal remote)
**Branch**: docs/student-portal-stage1-stage2-design-ai07
**Coordinator**: coord-ai