模块理解确认书 — student-portal
AI:ai07(TS/React · 学习场景域前端 remote)
阶段:阶段 1 交付物
日期:2026-07-09
关联:004 架构影响地图 §1.1a/1.1b/§5.4、AI 分配方案 §5 ai07、pending-features P3、teacher-portal 阶段 1、teacher-portal 阶段 2、known-issues §2.12
1. 我在架构中的位置
- 层级:L2 微前端层(004 §3.1 六层架构中的前端层)
- MF 角色:Remote 子应用,挂载到 teacher-portal Shell
- 上游(谁调用我):浏览器(学生)
- 下游(同步):api-gateway(REST,经 Next.js
rewrites 代理 /api/v1/*)
- 下游(推送,P5):push-gateway(WebSocket)
- BFF 对接:student-bff(待 ai04 设计)
- 通信方式:HTTP/REST(前端→Gateway)+ WebSocket(前端→push-gateway,P5)
- 不直连:前端不直连任何业务服务或 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):
错误码前缀按服务名大写(如 IAM_、CORE_EDU_、EXAMS_、HOMEWORK_、GRADES_、BFF_STUDENT_、GW_、NETWORK_)。前端 API 请求层根据 error.code 前缀路由到对应的 i18n key。
3.3 推送契约(P5)
| 协议 |
场景 |
| WebSocket(push-gateway) |
考试发布通知、成绩发布、作业截止提醒 |
3.4 proto 不直接消费
前端不调用 gRPC,BFF 把 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-a11y(error 级) |
WCAG 2.2 AA |
| 字体 |
Inter(sans)/ Fraunces(serif)/ JetBrains Mono(mono) |
复用 Shell 的 next/font/google 加载 |
5. 我的阶段归属
- 阶段:P3
- 当前状态:📐 待设计(待 core-edu + student-bff 就绪),依赖上游阶段 P3
- 依赖上游阶段:P1(api-gateway + iam)+ P2(teacher-portal Shell 就绪)+ P3(core-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 + Sentry(P6) |
❌ 待建(复用 shared-ts Logger) |
| metrics |
prom-client /metrics |
前端 Web Vitals → Gateway 上报 |
❌ 待建 |
| tracer |
OTel SDK |
前端 OTel browser SDK(P6) |
❌ 待建 |
| /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 |
| GlobalErrorFilter(ErrorBoundary) |
❌ |
待建,复用 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 共用配置 |
现有文件清单
student-portal 当前为空目录,所有维度均为 ❌ 待建状态。无现有文件清单。本设计文档作为 P3 起步的输入。
主要待建项(必须在 P3 起步时建立)
- MF Remote 配置:
next.config.js 配置 name: 'student_app'、exposes、remotes: { teacher: ... }
- 路由表:
/student/dashboard、/student/homework、/student/homework/:id/submit、/student/exams、/student/exams/:id/take、/student/diagnostic、/student/weakness、/student/notifications
- ExamTaking 组件:考试作答(倒计时 + 自动保存),student-portal 特有
- 作业提交表单:react-hook-form + zodResolver,不用 Tiptap
- Dockerfile 多阶段构建:builder + runtime + HEALTHCHECK
- Vitest + Playwright 测试:覆盖率 ≥ 80%
/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 负责 contracts,ai07 负责调用)。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 + 结构化,生产环境 → Sentry(P6)。必含字段:trace_id、user_id、scope=student、path。
13.4 Metrics(Web 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 Tracer(OTel browser SDK,P6)
复用 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 假设
- 假设 coord 建立
packages/shared-ts、packages/contracts:包含 ApiClient、Logger、Permissions 常量、通用类型。若 coord 未建立,ai07 自行在 apps/student-portal/src/shared/ 内实现,后续提取到 packages。
- 假设 ai04 student-bff 提供
GET /student/viewports、GET /student/dashboard、GET /student/homework、POST /student/homework/:id/submit、GET /student/diagnostic:返回 ActionState 结构。错误码前缀 BFF_STUDENT_(待 ai04 确认)。
- 假设 teacher-portal Shell 已就绪:AppShell + 共享依赖暴露 + MF 配置(P2 收尾完成)。
- 假设 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):
- packages 归属:
ui-tokens / ui-components / hooks 是 ai07 维护还是 coord 维护?
- GraphQL vs REST:student-bff 是 REST 还是 GraphQL?前端 API 请求层是否需要 GraphQL client?
- i18n key 命名:
error.{{service}}.{{code_snake_case}} 还是其他模式?
- 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 自用)
P3(student-portal 起步)
- 建
apps/student-portal/(Remote 角色)
- 配置 MF(
exposes pages,remotes: { teacher: ... })
- 实现 Dashboard + 我的作业 + 提交作业 + 我的考试 + 作答考试
- 复用 Shell 的 AppShell + 共享组件
- SSE 接入(考试作答自动保存)
P5(推送接入)
- student-portal 接入 WebSocket(push-gateway)
- 通知中心 + 作业截止提醒
P6(硬化)
- Web Vitals + OTel browser SDK 接入
- A11y WCAG 2.2 AA 审计
- 性能优化(MF shared 单例验证、bundle 分析)
AI Agent: ai07 (student-portal remote)
Branch: docs/student-portal-stage1-stage2-design-ai07
Coordinator: coord-ai