Files
Edu/apps/teacher-portal/nextstep.md
SpecialX 0b42302a64 docs(admin-portal): 新增 nextstep-v2.md 记录下游核查结果
v1 声称完成的下游工作经核查实际未完成:
- api-gateway: /api/admin/graphql 路由未注册,go vet 编译失败
- teacher-bff: resolver 已完成但 schema 未同步(命名空间 vs 扁平)
- iam: proto 缺 BatchGetUsers rpc 声明

v2 记录详细核查证据和修复要求
2026-07-14 08:26:27 +08:00

281 lines
22 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.
# teacher-portal 模块 Next Steps
> 维护者ai13teacher-portal
> 最后更新2026-07-13
> 关联:
>
> - [workline.md](../../docs/architecture/issues/worklines/teacher-portal_workline.md)
> - [contract.md](../../docs/architecture/issues/contracts/teacher-portal_contract.md)
> - [issue.md](../../docs/architecture/issues/objections/teacher-portal_issue.md)
---
## 1. 当前状态总览
| 阶段 | 状态 | 说明 |
| ------------------------ | --------- | --------------------------------------------------- |
| P2 MF Shell + 基础页面 | ✅ 完成 | AppShell + urql GraphQL Provider + 6 基础页面 |
| P3 考试/作业/成绩 | ✅ 完成 | 详情 + 批改 + 乐观更新 + 多 Tab 同步 |
| P4 知识图谱 + 学情分析 | ✅ 完成 | SVG 可视化 + 班级/单生学情 |
| P5 通知 + AI 助手 | ✅ 完成 | WebSocket + SSE 流式 AI 出题/教案/学情报告 |
| P6 可观测性硬化 | ✅ 完成 | Sentry + WebVitals + OTel + A11y + 性能预算 |
| P7 参考项目差距闭环 | ✅ 完成 | 新增 35 页面,覆盖参考项目全部 16 业务模块 |
| Docker Desktop 验证 | ✅ 通过 | standalone 模式构建 + 27 静态 + 11 动态路由全部 200 |
| MSW mock → 真实 API 切换 | ⏳ 待上游 | 需 teacher-bff GraphQL schema 上线 |
| 单元测试 | ⏳ 待补 | vitest 配置 + 关键 hook/组件测试 |
| 设计令牌硬化 | ⏳ 待补 | globals.css hsl() 字面量修复 |
| i18n 集成 | ⏳ 待补 | 中文硬编码 → next-intl |
---
## 2. 下游依赖工作(需协调 AI / 其他 AI 推进)
### 2.1 teacher-bffai03— 最高优先级
**依赖内容**GraphQL schema 落地
**影响范围**teacher-portal 全部 61 个 GraphQL operation 切换真实数据
**协调方式**teacher-bff GraphQL schema 第一版ARB-001 §1需在 main 上发布
**具体清单**
| 模块 | GraphQL operations 数 | 上游要求 |
| ---------------------------------------- | --------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| 基础P2 | 5 Query + 1 Mutation | MeQuery / ViewportsQuery / ClassesQuery / ExamsQuery / HomeworkQuery / GradesQuery / LoginMutation |
| 考试/作业/成绩P3 | 5 Query + 3 Mutation | ExamDetailQuery / HomeworkDetailQuery / CreateExamMutation / AssignHomeworkMutation / RecordGradeMutation |
| 知识图谱/学情P4 | 3 Query | KnowledgeGraphQuery / ClassAnalyticsQuery / StudentAnalyticsQuery |
| 通知/AIP5 | 2 Query + 3 Mutation | MyNotificationsQuery / MarkAsReadMutation / GenerateQuestionMutation / GenerateLessonPlanMutation / GenerateReportMutation |
| 成绩增强P7-A | 4 Query + 1 Mutation | GradeEntryQuery / SaveGradeEntriesMutation / GradeStatsQuery / GradeAnalyticsQuery / ReportCardQuery |
| 作业批改P7-A | 3 Query + 1 Mutation | HomeworkSubmissionsQuery / HomeworkAssignmentSubmissionsQuery / GradeSubmissionMutation |
| 考试组卷P7-B | 2 Query + 1 Mutation | ExamBuildQuery / SaveExamBuildMutation / ExamAnalyticsQuery |
| 题库/教材P7-B | 5 Query + 4 Mutation | QuestionsLibraryQuery / QuestionCreate/Update/DeleteMutation / QuestionBatchImportMutation / QuestionBatchExportQuery / TextbooksQuery / TextbookDetailQuery / TextbookCreateMutation |
| 考勤/班级/请假/调课P7-C | 8 Query + 4 Mutation | AttendanceListQuery / AttendanceSheetQuery / SaveAttendanceSheetMutation / AttendanceStatsQuery / AttendanceReportQuery / ClassDetailQuery / ClassScheduleQuery / LeaveRequestsQuery / ApproveLeaveRequestMutation / SubmitLeaveRequestMutation / SubmitScheduleChangeMutation / ScheduleChangesQuery |
| 备课/诊断/错题/练习P7-D | 12 Query + 5 Mutation | LessonPlansQuery / LessonPlanDetailQuery / CreateLessonPlanMutation / UpdateLessonPlanMutation / AIGenerateLessonPlanMutation / LessonPlanLibraryQuery / ForkLessonPlanMutation / LessonPlanCalendarQuery / LessonPlanHeatmapQuery / CoursePlansQuery / CoursePlanDetailQuery / CreateCoursePlanMutation / UpdateCoursePlanMutation / DiagnosticReportsQuery / ClassDiagnosticQuery / StudentDiagnosticQuery / ErrorBookQuery / PracticeAnalyticsQuery |
| 选课/富文本/监考/扫描批改/热力图P7-E | 8 Query + 5 Mutation | ElectiveCoursesQuery / ElectiveCourseDetailQuery / CreateElectiveCourseMutation / UpdateElectiveCourseMutation / PublishElectiveCourseMutation / CancelElectiveCourseMutation / ExamRichEditorQuery / SaveExamRichContentMutation / ProctoringStatusQuery / ProctoringEventMutation / SubmissionScanGradingQuery / SaveScanGradingMutation / LessonPlanHeatmapQuery |
**切换步骤**
1. 等待 teacher-bff schema 上线 main
2. 在 teacher-portal 设置 `NEXT_PUBLIC_API_MOCKING=false`
3. 删除或停用 `src/mocks/handlers-p*.ts`
4. 端到端测试每个页面,校对字段映射
### 2.2 iamai06— 高优先级
**依赖内容**JWT refresh token cookie 模式F12 裁决)
**影响范围**teacher-portal 长会话保活
**协调方式**iam 的 refresh cookie 端点上线后teacher-portal 的 useAuth hook 需配合调整
### 2.3 push-gatewayai09— 中优先级
**依赖内容**WebSocket 通知通道
**影响范围**teacher-portal `/notifications` 页面的实时推送
**协调方式**P5 阶段 push-gateway WebSocket 协议确定后,调整 `src/hooks/use-notifications-websocket.ts`
### 2.4 content / data-ana / msg / ai 服务 — 中优先级
**依赖内容**:各自域的 GraphQL query resolver
**影响范围**P4 学情分析 / P7 知识图谱 / 错题本 / 练习 等数据消费
**协调方式**:等 teacher-bff 完成聚合后,通过 BFF 调用下游服务
---
## 3. 本模块待补工作
### 3.1 单元测试P1
**目标**:覆盖关键 hooks / 组件 / GraphQL 操作
**清单**
- [ ] 配置 vitest`vitest.config.ts` + `vitest.setup.ts`
- [ ] 测试 `usePermission` hook权限矩阵
- [ ] 测试 `useAuth` hook登录/登出/会话保活)
- [ ] 测试 `useCrossTabSync` hook多 Tab 会话同步)
- [ ] 测试 `useNotificationsWebSocket` hook指数退避
- [ ] 测试 MSW handlers每个 operationName 的 mock 响应)
- [ ] 测试关键页面组件AppShell / grades/entry / homework/submissions/[submissionId]
- [ ] 配置 CI 运行 `pnpm --filter @edu/teacher-portal test`
### 3.2 设计令牌硬化P1
**问题**`globals.css``tailwind.config.js` 中存在 `hsl(0 0% 100%)` 等字面量
**清单**
- [ ] `src/app/styles/globals.css`:将所有 `hsl(...)` 字面量迁移到 `primitive.css`
- [ ] `tailwind.config.js`:将所有 `hsl(...)` 字面量迁移到 `@theme inline`
- [ ] ESLint 规则 `no-restricted-syntax` 强制禁止 `#hex`
- [ ] ESLint 规则 `design-tokens/no-hardcoded-fonts` 强制禁止字体字面量
### 3.3 i18n 集成P2
**问题**:所有页面中文文本硬编码
**清单**
- [ ] 安装 `next-intl`
- [ ] 创建 `messages/zh-CN.json`(按模块分组)
- [ ] 修改 `next.config.js` 添加 i18n 插件
- [ ] 修改 `app/layout.tsx` 添加 `NextIntlClientProvider`
- [ ] 替换所有页面中文硬编码为 `t("...")` 调用
- [ ] 配置英文翻译(可选)
### 3.4 packages/ui-components 扩展P2
**清单**
- [ ] 抽取 `DataTable` 组件grades/stats、questions、textbooks 等表格页复用)
- [ ] 抽取 `FilterBar` 组件(统一筛选栏样式)
- [ ] 抽取 `StatusBadge` 组件(统一状态徽章)
- [ ] 抽取 `Form` 组件(基于 react-hook-form
- [ ] 抽取 `RichTextEditor` 组件Tiptap 封装lesson-plans/edit + exams/edit-rich 复用)
- [ ] 抽取 `Chart` 组件SVG 图表统一封装)
- [ ] 抽取 `Modal` 组件(统一弹窗样式)
- [ ] 抽取 `Calendar` 组件lesson-plans/calendar 复用)
### 3.5 性能优化P2
**清单**
- [ ] 配置 `size-limit.json`(已建)并接入 CI 阻断
- [ ] 首页 LCP < 2.5sSentry / WebVitals 监控)
- [ ] 路由懒加载(动态 import 重型页面,如 grades/analytics、knowledge-graph
- [ ] 图片优化(`next/image` 替换 `<img>`
- [ ] 字体优化(`next/font` 替换 CSS @font-face
### 3.6 A11y 硬化P2
**清单**
- [ ] 配置 `eslint-plugin-jsx-a11y`(已建)
- [ ] 修复所有 jsx-a11y 警告
- [ ] 键盘导航测试Tab/Shift+Tab/Enter/Esc
- [ ] 屏幕阅读器测试NVDA / VoiceOver
- [ ] WCAG 2.2 AA 颜色对比度验证
---
## 4. Docker 部署注意事项
### 4.1 当前配置
- **Dockerfile**`apps/teacher-portal/Dockerfile`
- **构建模式**Next.js standalone`output: "standalone"` in `next.config.js`
- **基础镜像**`node:20-alpine`(与 lockfile 对齐;本地测试可用 `node:22-alpine` retag
- **端口**4000
- **健康检查**`/api/health` 端点30s 间隔
### 4.2 必需环境变量
| 变量 | 用途 | 默认值 |
| --------------------------- | -------------------------------------------- | --------------------------------------------------------------------------- |
| `NEXT_PUBLIC_API_MOCKING` | 启用 MSW mocktrue 时浏览器端拦截 GraphQL | `true`mock 阶段)/ `false`(接入上游后) |
| `NEXT_PUBLIC_MF_ENABLED` | 启用 Module Federation Remote 加载 | `false`P2 阶段)/ `true`P3+ Remote 上线后) |
| `API_GATEWAY_URL` | rewrites 代理目标 | `http://localhost:8080`dev/ `http://api-gateway:8080`docker compose |
| `NODE_ENV` | Node 环境 | `production` |
| `PORT` | 监听端口 | `4000` |
| `NEXT_PUBLIC_SENTRY_DSN` | Sentry DSN可选 | — |
| `NEXT_PUBLIC_OTEL_ENDPOINT` | OpenTelemetry OTLP 端点(可选) | — |
### 4.3 已知限制
1. **MSW 仅浏览器端生效**服务端渲染SSRurql 发起的 GraphQL 请求会通过 `next.config.js` rewrites 代理到 `API_GATEWAY_URL`。若 api-gateway 未启动SSR 会 500。生产部署时必须先启动 api-gateway。
2. **MF Remote 未启用**`NEXT_PUBLIC_MF_ENABLED=false`student/parent/admin Remote 不会加载。需等 Remote 应用上线后开启。
3. **standalone 模式限制**`output: "standalone"` 已自动打包依赖,但 `public/``.next/static/` 需单独 COPY已在 Dockerfile 中处理)。
---
## 5. 路由清单
### 5.1 静态路由27 个,全部 HTTP 200 验证通过)
| 路径 | 模块 | 阶段 |
| ------------------------ | --------------------------------------- | ----- |
| `/` | 重定向 | P2 |
| `/login` | 登录 | P2 |
| `/dashboard` | 仪表盘 | P2 |
| `/classes` | 班级列表 | P2 |
| `/exams` | 考试列表 | P2 |
| `/exams/new` | 新建考试 | P3 |
| `/homework` | 作业列表 | P2 |
| `/homework/new` | 布置作业 | P3 |
| `/grades` | 成绩列表(含录入/统计/分析/报告卡入口) | P2+P7 |
| `/grades/entry` | 批量录入成绩 | P7 |
| `/grades/stats` | 班级成绩统计 | P7 |
| `/grades/analytics` | 成绩分析仪表盘 | P7 |
| `/grades/report-card` | 学生成绩报告卡 | P7 |
| `/analytics` | 学情分析 | P4 |
| `/knowledge-graph` | 知识图谱 | P4 |
| `/notifications` | 通知中心 | P5 |
| `/ai-assist` | AI 辅助出题 | P5 |
| `/ai-lesson-plan` | AI 教案 | P5 |
| `/ai-report` | AI 学情报告 | P5 |
| `/attendance` | 考勤记录 | P7 |
| `/attendance/sheet` | 批量录入考勤 | P7 |
| `/attendance/stats` | 考勤统计 | P7 |
| `/attendance/report` | 考勤报告 | P7 |
| `/questions` | 题库 | P7 |
| `/textbooks` | 教材列表 | P7 |
| `/lesson-plans` | 课案列表 | P7 |
| `/lesson-plans/new` | 新建课案 | P7 |
| `/lesson-plans/library` | 校内课案库 | P7 |
| `/lesson-plans/calendar` | 课案日历 | P7 |
| `/lesson-plans/heatmap` | 课标覆盖热力图 | P7 |
| `/course-plans` | 课程计划列表 | P7 |
| `/diagnostic` | 诊断报告列表 | P7 |
| `/error-book` | 错题本 | P7 |
| `/practice` | 练习分析 | P7 |
| `/elective` | 选修课列表 | P7 |
| `/elective/create` | 创建选修课 | P7 |
| `/leave` | 请假审批 | P7 |
| `/schedule-changes` | 调课申请 | P7 |
| `/settings` | 个人设置 | P2 |
| `/students` | 学生列表 | P2 |
### 5.2 动态路由11 个,全部 HTTP 200 验证通过)
| 路径 | 模块 | 阶段 |
| --------------------------------------------------- | --------------- | ---- |
| `/exams/[id]` | 考试详情 | P3 |
| `/exams/[id]/build` | 组卷 | P7 |
| `/exams/[id]/analytics` | 考后分析 | P7 |
| `/exams/[id]/edit-rich` | 富文本编辑 | P7 |
| `/exams/[id]/proctoring` | 监考 | P7 |
| `/homework/[id]` | 作业详情 + 批改 | P3 |
| `/homework/assignments/[id]/submissions` | 批量批改 | P7 |
| `/homework/submissions/[submissionId]` | 单份批改 | P7 |
| `/homework/submissions/[submissionId]/scan-grading` | 扫描批改 | P7 |
| `/classes/[id]` | 班级详情聚合页 | P7 |
| `/classes/schedule` | 班级课表 | P7 |
| `/analytics/[studentId]` | 单生学情 | P4 |
| `/diagnostic/class/[classId]` | 班级诊断 | P7 |
| `/textbooks/[id]` | 教材阅读器 | P7 |
| `/lesson-plans/[planId]/edit` | 课案编辑器 | P7 |
| `/course-plans/[id]` | 课程计划详情 | P7 |
| `/elective/[id]/edit` | 编辑选修课 | P7 |
### 5.3 API 路由
| 路径 | 用途 |
| ------------------------- | --------------------------------------- |
| `/api/health` | liveness 健康检查 |
| `/api/ready` | readiness 健康检查 |
| `/api/v1/teacher/graphql` | GraphQL 端点rewrites 到 api-gateway |
| `/api/auth/*` | 登录端点rewrites 到 iam |
---
## 6. 已知问题
| 问题 | 影响 | 临时方案 |
| ------------------------------------------------ | ----------------------- | ------------------------------------------------- |
| GraphQL SSR 请求在 api-gateway 未启动时 500 | 首次加载 SSR 阶段会报错 | 部署时确保 api-gateway 先启动 |
| pnpm symlink 在 Docker runtime 下 react 解析失败 | 容器无法启动 | 已用 `output: "standalone"` 解决 |
| `tsconfig.base.json` 未在 Dockerfile 中 COPY | 构建阶段报 TS5083 | 已在 Dockerfile line 13 修复 |
| MSW mock 在 production 模式下仅浏览器端生效 | SSR 阶段无法 mock | 接入真实 API 后自动解决 |
| `node:20-alpine` 镜像在 Docker Hub 被墙 | 国内构建失败 | 配置 registry-mirror 或 retag 本地 node:22-alpine |
---
**本文件维护规则**:每次完成一项 Next Step 后,将对应条目标记为 ✅ 并在 workline.md §4 或 §5 中记录审计结果。