22 KiB
student-portal 工作排期
负责人:ai14 关联:workline.md、coord.md §1 ARB-001、coord.md §2 ARB-002、contracts/student-portal_contract.md、matrix.md 模式:全并行(各 AI 一口气完成 P2-P6 全部代码,开发期间用 mock,最后统一集成测试) 依据:president-final-rulings.md §3.6(ai14 P3 功能范围)+ §7.14(ai14 工作内容最终清单)+ ARB-002 §2.3(P3 首个 Remote)+ 02-architecture-design.md v2 阶段能力累积矩阵
§1 总览
student-portal 是学生端微前端(MF Remote),通过 Module Federation 接入 teacher-portal Shell,覆盖考试作答、作业提交、学情查看等场景。全阶段目标:P2 MF Remote 骨架预埋 → P3 考试作答 + 作业提交 + 基础页面 → P4 知识图谱 + 学情诊断 → P5 实时通知 + AI 辅助 → P6 可观测性硬化 + A11y + 性能。
全并行模式:ai14 一口气完成 P2-P6 全部代码,开发期间用 MSW mock 上游(student-bff GraphQL / api-gateway HTTP / push-gateway WebSocket),上游就绪后在 matrix.md §8 更新就绪信号,最后统一集成测试。
批次归属(见 workline.md §1):
- 批次 2(P3):ai14 与 ai07 + ai08 + ai04 + ai03扩展 并行启动(
b2d, after b1d, 8d) - 批次 3(P4):与 ai09 + ai11 + ai05 + ai15 并行
- 批次 4(P5):与 ai10 + ai02 + ai12 + ai03扩展 并行
- 批次 5(P6):与 ai16 + 持续优化 并行
§2 全阶段甘特图(P2-P6)
gantt
title ai14 student-portal 全阶段排期(全并行)
dateFormat YYYY-MM-DD
axisFormat %m-%d
section P2 预埋
项目骨架+设计令牌三层+独立壳路由 :crit, a14p0, 2026-07-10, 2d
MF Remote配置(NextFederationPlugin remotes) :crit, a14a, after a14p0, 2d
MSW基础设施+GraphQL请求层骨架 :a14b, after a14a, 2d
section P3 学生核心
AppShell复用+学生端导航+路由守卫 :crit, a14c, after a14b, 2d
Dashboard页(studentDashboard query) :a14d, after a14c, 2d
我的班级页+我的考试列表+我的作业列表 :a14e, after a14d, 3d
考试作答页(状态机+服务器时间同步) :crit, a14f, after a14e, 4d
IDB断网恢复队列+自动保存+DraftRecovery :crit, a14g, after a14f, 3d
防作弊采集+BroadcastChannel多标签检测 :a14h, after a14g, 2d
作业提交页(submitHomework mutation+乐观更新) :a14i, after a14h, 2d
我的成绩页+我的考勤页 :a14j, after a14i, 2d
section P4 知识与学情
学习路径页(learningPath query+知识点卡片) :a14k, after a14j, 3d
学情诊断页(myWeakness+myTrend query+图表) :a14l, after a14k, 3d
教材章节浏览页(textbooks+chapters) :a14m, after a14l, 2d
section P5 推送与AI
WebSocket通知中心(myNotifications+markAsRead) :a14n, after a14m, 2d
跨Tab通知同步(BroadcastChannel) :a14o, after a14n, 1d
AI辅助答疑(SSE流式,可选) :a14p, after a14o, 3d
section P6 硬化
Sentry+RUM+OTel browser :a14q, after a14p, 2d
A11y审计(WCAG 2.2 AA) :a14r, after a14q, 2d
性能优化+bundle门禁(Remote <80KB) :a14s, after a14r, 2d
P3未尽事项补全+降级策略验证 :a14t, after a14s, 2d
§3 详细任务
P2:MF Remote 骨架预埋
- 负责人:ai14
- 裁决依据:ARB-002 §2.3(P3 首个 Remote,但 P2 可预埋骨架)+ 总裁裁决 §3.6(ai14 P3 起步)+ §2.17(MF GraphQL client 单例方案 A)
- 交付物:
- 项目骨架(
apps/student-portal/目录结构:src/app/、src/components/、src/lib/、src/hooks/、src/mocks/) - 设计令牌三层(primitive.css / semantic.css / tailwind-theme.ts,与 teacher-portal Shell 一致)
- 独立壳路由(next.config.js + app/layout.tsx + app/page.tsx,MF 关闭时可独立渲染)
- NextFederationPlugin 配置(
remotes: { teacher: 'teacher@http://localhost:4000/_next/static/chunks/remoteEntry.js' },exposes: { './StudentApp': './src/app/student-app.tsx' }) - MF shared singleton 配置(react/react-dom/urql/graphql/@tanstack/react-query/zustand/nuqs/@edu/* 全部 singleton)
- MSW 基础设施(
src/mocks/handlers.ts+src/mocks/fixtures/*.json+NEXT_PUBLIC_API_MOCKING=enabled) - GraphQL 请求层骨架(
src/lib/graphql.ts复用 ShelluseGraphQLClient(),不重复创建 client)
- 项目骨架(
- 依赖:
- packages 骨架(ui-tokens/ui-components/hooks,ai13 批次 0.15 已完成)
- teacher-portal MF Shell 配置(ai13 P2,exposes 就绪)
- Mock 策略:MSW 拦截
POST /api/v1/student/graphql+POST /api/auth/login - 验收标准:
pnpm dev启动 :4001 可访问- MF 配置不破坏独立壳渲染(
NEXT_PUBLIC_MF_ENABLED=false时独立渲染首页) - MSW 拦截 GraphQL 请求返回 mock 数据
- lint + typecheck 零错误
P3:考试作答 + 作业提交 + 基础页面(核心)
- 负责人:ai14
- 裁决依据:总裁裁决 §3.6(ai14 P3 功能范围)+ ARB-001 §1.3(ActionState 信封 + 降级模式方案 B)+ ARB-002 §2.2(复用 Shell 暴露清单)+ 02-architecture-design.md v2 §14(考试作答架构设计)
- 交付物:
- AppShell 复用 + 学生端导航:从 Shell 导入
AppShell,覆写学生端视口(myClasses/myExams/myHomework/myGrades/myAttendance/learningPath/dashboard/notifications) - 路由守卫:未登录跳转
http://localhost:4000/login?redirect=student,登录后回跳 - Dashboard 页(
/dashboard):消费studentDashboardquery(upcomingHomework + upcomingExams + recentGrades + attendanceRate + learningStreakDays) - 我的班级页(
/my-classes):消费myClassesquery - 我的考试列表页(
/my-exams):消费myExamsquery,按状态分组(未开始/进行中/已提交/已批改) - 我的作业列表页(
/my-homework):消费myHomeworkquery,按状态分组 - 考试作答页(
/my-exams/[id]/take):- 状态机(NotStarted → InProgress → AutoSaving → Submitting → Submitted,见 02 §14 状态机图)
- 服务器时间同步(
useServerTimeSynchook,5 分钟重新同步,倒计时基于服务器时间) - IDB 断网恢复队列(
idb-keyval存草稿 + 队列,网络恢复后重试) - 自动保存(每 30s + blur 事件触发,乐观更新本地状态)
- DraftRecovery 草稿恢复(进入作答页时检查 IDB 草稿,提示恢复)
- 防作弊采集(visibilitychange/copy/paste/fullscreen/contextmenu 事件监听 + 记录)
- BroadcastChannel 多标签检测(
edu-exam-sessionchannel,检测到多标签警告) - 提交防重复(idempotency key + 提交按钮 disabled + 提交中状态)
- 作业提交页(
/my-homework/[id]/submit):- 消费
submitHomeworkmutation - 乐观更新(useMutation onMutate 回滚 + invalidateQueries)
- 附件上传(ARB-019 §21.5 方案 A 已裁决,暂走 mock)
- 消费
- 我的成绩页(
/my-grades):消费myGradesquery,成绩列表 + 趋势图 - 我的考勤页(
/my-attendance):消费myAttendancequery,考勤日历
- AppShell 复用 + 学生端导航:从 Shell 导入
- 依赖:
- student-bff GraphQL schema(ai04 P3,
packages/shared-ts/contracts/graphql/student-bff.graphql,ARB-019 §21 已裁决) - api-gateway 路由(ai01 P3,
/api/v1/student/*反向代理 student-bff,ARB-019 §21 已裁决) - core-edu gRPC(ai08 P3,提供 ExamService/HomeworkService/GradeService/AttendanceService/ClassService)
- iam gRPC(ai06 P2,GetUserInfo + GetEffectivePermissions + GetViewports)
- data-ana gRPC(ai11 P4,但 studentDashboard 聚合需要,P3 用 mock)
- student-bff GraphQL schema(ai04 P3,
- Mock 策略:
- MSW 拦截
POST /api/v1/student/graphql,按 operationName 返回 mock 响应 - mock-socket 模拟 WebSocket 推送(考试延长/强制提交事件)
- IDB 草稿恢复用真实 idb-keyval(前端可独立测试)
- MSW 拦截
- 验收标准:
- Dashboard 页渲染(mock 数据):upcomingHomework + upcomingExams + recentGrades 三栏
- 考试作答页状态机完整:进入 → 作答 → 自动保存 → 提交 → 跳转结果页
- 断网恢复:手动 offline → 作答 → 恢复网络 → 草稿自动提交
- 防作弊采集:visibilitychange hidden 触发记录(mock 上报)
- 多标签检测:开第二个 Tab 作答,第一个 Tab 收到警告
- 作业提交乐观更新:提交后立即 UI 反馈,失败回滚
- lint + typecheck 零错误
P4:知识图谱 + 学情诊断
- 负责人:ai14
- 交付物:
- 学习路径页(
/learning-path):消费learningPathquery,知识点卡片列表 + 掌握度进度条 - 学情诊断页(
/dashboard/weakness):消费myWeaknessquery,薄弱点雷达图(recharts) - 学习趋势页(
/dashboard/trend):消费myTrendquery,趋势折线图(recharts) - 教材章节浏览页(
/textbooks、/textbooks/[id]/chapters):消费textbooks+chaptersquery
- 学习路径页(
- 依赖:
- student-bff 扩展 content + data-ana gRPC 调用(ai04 P4)
- content gRPC(ai09 P4,TextbookService + ChapterService + KnowledgeGraphService)
- data-ana gRPC(ai11 P4,AnalyticsService.GetStudentWeakness + GetLearningTrend)
- Mock 策略:MSW 返回固定知识点 + 薄弱点 + 趋势数据
- 验收标准:
- 学习路径页渲染知识点卡片 + 掌握度(mock)
- 学情诊断页雷达图 + 趋势折线图渲染(mock)
- 教材章节树形导航可用
P5:实时通知 + AI 辅助
- 负责人:ai14
- 交付物:
- WebSocket 通知中心(
/notifications):- 消费
myNotificationsquery +markAsReadmutation - WebSocket 连接
ws://push-gateway:8081/ws,实时接收通知 - 通知分类(作业/考试/成绩/系统),未读计数
- 消费
- 跨 Tab 通知同步(BroadcastChannel
edu-notificationchannel,新通知在所有 Tab 同步) - AI 辅助答疑(可选,
/ai-tutor):- SSE 流式接收 AI 回答
- 消费 ai 服务(待 ai12 P5 就绪)
- WebSocket 通知中心(
- 依赖:
- push-gateway WebSocket(ai02 P5,
/ws端点) - msg gRPC(ai10 P5,NotificationService)
- ai 服务 gRPC(ai12 P5,AiService.Chat,可选)
- push-gateway WebSocket(ai02 P5,
- Mock 策略:mock-socket 模拟 WS 推送(每 30 秒 1 条通知)+ MSW 返回固定 AI 响应(SSE 用 ReadableStream mock)
- 验收标准:
- 通知中心实时接收 WS 推送(mock)
- 多 Tab 同步:Tab A 收到通知,Tab B 未读计数同步更新
- AI 辅助答疑流式输出(mock)
P6:可观测性硬化 + A11y + 性能
- 负责人:ai14
- 交付物:
- Sentry 错误追踪(
NEXT_PUBLIC_SENTRY_DSN+ beforeSend PII 过滤,学生隐私合规) - Web Vitals RUM(LCP/INP/CLS/TTFB →
/api/v1/admin/web-vitals) - OTel browser SDK(自动埋点 fetch/XHR/document load → OTLP collector)
- A11y 审计(WCAG 2.2 AA:eslint-plugin-jsx-a11y + @axe-core/playwright + 对比度审计)
- 性能优化(bundle analyzer + size-limit CI 门禁:Remote < 80KB / CSS < 50KB)
- P3 未尽事项补全(根据 ISSUE-014-03/04/05/06/07 仲裁结果补全防作弊策略、附件上传、实时事件响应、DataScope 强制执行)
- 降级策略验证(02 §18.2 降级策略矩阵的 12 个场景端到端验证)
- Sentry 错误追踪(
- 依赖:
- push-gateway WebSocket 真实就绪(ai02 P5)
- Sentry DSN + OTel collector(基础设施)
- 全部上游就绪(统一集成测试)
- 验收标准:
- 99.9% 可用 + WCAG 2.2 AA + LCP < 2.5s / INP < 200ms / CLS < 0.1(P75)
- Remote bundle < 80KB / CSS < 50KB
- 12 个降级场景全部验证通过
§4 依赖与就绪信号
§4.1 我依赖的上游就绪标志
| 上游 | 就绪标志 | 阻塞阶段 | 状态 |
|---|---|---|---|
| packages 骨架(ai13 批次 0.15) | ui-tokens/ui-components/hooks 可 import | P2 启动 | ✅ 已就绪 |
| teacher-portal MF Shell(ai13 P2) | exposes AppShell/GraphQLProvider/useGraphQLClient/useAuth/usePermission + shared singleton | P2 启动 | ⏳ 待 ai13 P2 |
| api-gateway HTTP :8080(ai01 P3) | /api/v1/student/* 反向代理 student-bff 可用 |
P3 启动 | ⏳ 待 ai01 P3 |
| student-bff GraphQL(ai04 P3) | POST /graphql :3009 + 核心 Query/Mutation 可执行 |
P3 启动 | ⏳ 待 ai04 P3 |
| student-bff GraphQL schema(ai04 + ISSUE-014-02 仲裁) | packages/shared-ts/contracts/graphql/student-bff.graphql 创建 |
P3 启动 | ✅ 已裁决(ARB-019) |
| core-edu gRPC 50053(ai08 P3) | ExamService/HomeworkService/GradeService/AttendanceService/ClassService 全部 RPC | P3 启动 | ⏳ 待 ai08 P3 |
| iam gRPC 50052(ai06 P2) | GetUserInfo + GetEffectivePermissions + GetViewports | P3 启动 | ⏳ 待 ai06 P2 |
| student-bff content/data-ana 扩展(ai04 P4) | learningPath/myWeakness/myTrend/textbooks/chapters query 可用 | P4 启动 | ⏳ 待 ai04 P4 |
| content gRPC 50054(ai09 P4) | TextbookService + ChapterService + KnowledgeGraphService | P4 启动 | ⏳ 待 ai09 P4 |
| data-ana gRPC 50055(ai11 P4) | AnalyticsService.GetStudentWeakness + GetLearningTrend | P4 启动 | ⏳ 待 ai11 P4 |
| push-gateway WebSocket :8081/ws(ai02 P5) | WS 连接可建立 + 推送可接收 | P5 启动 | ⏳ 待 ai02 P5 |
| msg gRPC 50056(ai10 P5) | NotificationService.ListNotifications + MarkAsRead | P5 启动 | ⏳ 待 ai10 P5 |
| ai 服务 gRPC 50057(ai12 P5,可选) | AiService.Chat(SSE 流式) | P5 启动 | ⏳ 待 ai12 P5 |
| Sentry DSN + OTel collector(基础设施) | Sentry 项目创建 + OTel collector 可接收 OTLP | P6 启动 | ⏳ 待基础设施 |
§4.2 我的就绪信号(供下游消费)
| 信号 | 就绪标志 | 消费方 |
|---|---|---|
| student-portal dev server :4001 | pnpm dev 启动 + 首页可访问 |
无(最前端,但 teacher-portal Shell 需加载 Remote) |
| MF Remote 可加载 | teacher-portal Shell 可加载 student-portal/StudentApp |
teacher-portal(ai13 P3 集成测试) |
| 登录流程可用 | 未登录跳转 Shell /login,登录后回跳 student |
无 |
| GraphQL 查询可执行 | currentUser/studentDashboard/myClasses 返回数据 | 无 |
| 考试作答链路通 | 进入作答 → 自动保存 → 提交 → 跳转结果页 | 无 |
| WebSocket 通知可接收 | 通知中心实时更新(mock) | 无 |
§5 全并行开发说明
按 matrix.md §全并行模式:
- ai14 一口气完成 P2-P6 全部代码,开发期间用 MSW mock 上游
- 上游就绪后在 matrix.md §8 更新就绪信号(
student-portal | ai14 | :4001 可访问 + MF Remote | ⏳ → ✅) - 所有模块就绪后统一集成测试(matrix.md §9 检查清单)
- Mock 切换:
NEXT_PUBLIC_API_MOCKING=enabled→disabled - MF 切换:
NEXT_PUBLIC_MF_ENABLED=false(P2 独立壳)→true(P3 接入 Shell)
§6 阶段能力累积矩阵(与 02-architecture-design.md v2 §20 对齐)
| 阶段 | 能力 | 关键页面/功能 |
|---|---|---|
| P2 | 项目骨架 + MF Remote 配置 + MSW 基础设施 | 独立壳首页(占位) |
| P3 | + 考试作答 + 作业提交 + 基础页面 | Dashboard / myClasses / myExams / myHomework / myGrades / myAttendance |
| P4 | + 知识图谱 + 学情诊断 + 教材章节 | learningPath / myWeakness / myTrend / textbooks / chapters |
| P5 | + 实时通知 + 跨 Tab 同步 + AI 辅助(可选) | notifications / ai-tutor |
| P6 | + 可观测性 + A11y + 性能 + 降级验证 + 尽事项补全 | Sentry / RUM / OTel / WCAG 2.2 AA / bundle 门禁 |
§7 关键风险与缓解
| 风险 | 影响 | 缓解措施 |
|---|---|---|
| student-bff GraphQL schema 未就绪(ai04 P3 延迟) | 高 | MSW mock 全量 query/mutation,schema 就绪后切换;ai14 自行维护 mock schema 用于 codegen |
| 考试作答断网恢复逻辑复杂(IDB 队列 + 服务器时间对齐) | 高 | 02 §14 已设计完整状态机 + 时间同步算法;P3 优先实现核心链路,P6 验证降级场景 |
| MF Remote 加载失败(Shell 未就绪或版本不兼容) | 中 | 02 §3.2 已设计独立壳回退(NEXT_PUBLIC_MF_ENABLED=false 时独立渲染) |
| 防作弊策略未仲裁(ISSUE-014-03/04) | 中 | ✅ 已裁决(ARB-019 §21.4);02 §14.5 已补全全屏策略 + visibilitychange + 多标签 + 粘贴题型分层 |
| 附件上传协议未仲裁(ISSUE-014-05) | 中 | ✅ 已裁决(ARB-019 §21.5 方案 A);02 §4.2 已更新为 REST upload + GraphQL 提交 URL |
| 实时事件命名未确认(ISSUE-014-06) | 低 | ✅ 已裁决(ARB-019 §21.6);02 §5.1/§5.2 已补全 ExamExtended + ExamForceSubmitted |
§8 工作进度跟踪
§8.1 ARB-019 §21.8 ai14 执行项落实情况(2026-07-11 审计)
| # | 执行项 | ISSUE | 状态 | 说明 |
|---|---|---|---|---|
| 1 | contract.md §2.3 路径统一为 POST /api/v1/student/graphql |
014-01 | ✅ 已落实 | contract.md v2 已包含 |
| 2 | 02 §4.2 GraphQL query 移除所有 studentId 参数 |
014-07 | ✅ 已落实 | 全部 query 无 studentId 参数 |
| 3 | 02 §14 防作弊策略补全(全屏 + visibilitychange + 多标签 + 事件上报) | 014-03 | ✅ 已落实 | §14.5 已补全;mutation 名对齐为 recordExamViolation |
| 4 | 02 §14 粘贴策略题型分层(客观题禁止/主观题允许记录/作文题允许不记录) | 014-04 | ✅ 已落实 | §14.5 已补全分层策略 + recordPasteEvent mutation |
| 5 | 02 §5.1 实时事件补 ExamExtended + ExamForceSubmitted 命名 | 014-06 | ✅ 已落实 | §5.1 事件表 + §5.2 handlePushMessage 已补全 |
| 6 | 02 §4.2 mutation 域确认 recordExamViolation + recordPasteEvent 参数 | 014-03/04 | ✅ 已落实 | §4.2 已对齐 contract.md,补全 markAllAsRead + updateNotificationPreference |
§8.2 额外修复项(2026-07-11)
| # | 修复项 | 说明 |
|---|---|---|
| 1 | SAVE_EXAM_ANSWER → SAVE_EXAM_DRAFT |
对齐 contract.md §2.4.2 mutation 命名 |
| 2 | RECORD_SUSPICIOUS_BEHAVIOR → RECORD_EXAM_VIOLATION |
对齐 contract.md §2.4.2 mutation 命名 |
| 3 | uploadAttachment mutation 移除 |
改为 REST 端点(ARB-019 §21.5 方案 A) |
| 4 | SuspiciousBehaviorRecord.type 更新 |
copy-paste 拆分为 copy/paste/paste-essay |
| 5 | §11.3 未决设计决策表更新 | 4 项 ⚠️ → ✅ 已裁决 |
| 6 | §12.3 契约表更新 | WebSocket 事件名已裁决 |
| 7 | §11.1 假设 6 更新 | 事件名已由 ARB-019 §21.6 裁决确认 |
| 8 | §20.5 技术债务表更新 | WebSocket 事件名已裁决 |
| 9 | contract.md 过时"待仲裁"标注更新 | 10 处"待 ISSUE-014-XX 仲裁"更新为"已裁决 ARB-019 §XX" |
| 10 | workline.md 过时"待仲裁"标注更新 | 4 处"待仲裁"更新为"已裁决 ARB-019" |
§8.3 当前阶段状态
- 文档阶段:✅ 完成(01-understanding + 02-architecture-design + contract + workline + issue 全部对齐 ARB-019 裁决)
- 代码实现阶段:✅ 已完成(通过
606acb6合并到 main,包含 P2-P6 全部代码) - 集成测试阶段:✅ 已完成(通过
61d8249+a6b0c54修复全部集成测试 bug) - 待办:无未完成的架构工作项(contract.md + workline.md + 02-architecture-design.md 全部对齐 ARB-019 裁决)
AI Agent: ai14(student-portal) Branch: feat-review-student-portal-docs-9yN6Av Coordinator: coord-ai