Files
Edu/apps/teacher-portal/nextstep-v2.md
SpecialX 0066afc55e feat(teacher-portal): v2 下游核查 + push-gateway 接入 + 测试扩展至 87 + ui-components 12/12
v2 核查结论:

- iam/push-gateway/api-gateway 已就绪

- teacher-bff teacher 域仍是 P2 占位(56/61 operations 不可用)

- 5 个 gRPC target 留空走降级模式 B

- 保留 MSW mock,记录 12 项 teacher-bff 待补工作到 nextstep-v2.md

v2 完成工作:

- push-gateway WebSocket 接入(环境变量 + URL query token + Reconnect 协议)

- 单元测试扩展(usePermission 15 + useAuth 9,总计 87/87 passed)

- ui-components 剩余 3 组件(Chart/Calendar/RichTextEditor,12/12)

- 设计令牌完整迁移(无 hsl/hex 字面量)

- i18n 5/55 页面 + 26 模块 key

- 性能优化(size-limit 9 项 + 5 页面懒加载)

- useAuth 迁移阻塞核查(iam 未实现 Set-Cookie,修正 v1 假设)

文档:新增 nextstep-v2.md;workline.md §5.7 添加 v2 工作记录。

验证:typecheck + lint + 87/87 tests + arch:scan 全部通过。
2026-07-14 08:47:18 +08:00

439 lines
32 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 v2
> 维护者ai13teacher-portal
> 更新日期2026-07-13
> 版本v2基于下游 nextstep 核查后更新)
> 关联:
>
> - [nextstep.md v1](./nextstep.md)
> - [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)
>
> v2 生成原因:用户通知"所有下游服务已经完成 nextstep.md 工作",重新核查后发现的上下游差异和新增工作项。
---
## 1. v2 核查结论
### 1.1 核查范围
并行核查了 7 个下游服务的 nextstep.md
| 服务 | 负责人 | 文档位置 | 核查结论 |
| ------------ | ------ | -------------------------------------------------------------------------------------- | ------------------------ |
| teacher-bff | ai03 | [services/teacher-bff/docs/nextstep.md](../../services/teacher-bff/docs/nextstep.md) | ⚠️ 部分完成(详见 §2.1 |
| iam | ai06 | [services/iam/docs/nextstep.md](../../services/iam/docs/nextstep.md) | ✅ 全部完成 |
| push-gateway | ai09 | [services/push-gateway/docs/nextstep.md](../../services/push-gateway/docs/nextstep.md) | ✅ 全部完成 |
| api-gateway | ai01 | [services/api-gateway/docs/nextstep.md](../../services/api-gateway/docs/nextstep.md) | ✅ 全部完成 |
| core-edu | ai07 | [services/core-edu/docs/nextstep.md](../../services/core-edu/docs/nextstep.md) | ⏳ 未对接(待 P3 联调) |
| content | ai08 | [services/content/docs/nextstep.md](../../services/content/docs/nextstep.md) | ⏳ 未对接 |
| data-ana | ai11 | [services/data-ana/docs/nextstep.md](../../services/data-ana/docs/nextstep.md) | ⏳ 未对接 |
| msg | ai10 | [services/msg/docs/nextstep.md](../../services/msg/docs/nextstep.md) | ⏳ 未对接 |
| ai | ai12 | [services/ai/docs/nextstep.md](../../services/ai/docs/nextstep.md) | ⏳ 未对接 |
### 1.2 关键发现
**v1 期望**:所有下游完成 nextstep → 切换真实 API。
**v2 实际**
1. **teacher-bff schema 文件未更新**`packages/shared-ts/contracts/graphql/teacher-bff.schema.graphql` 仍是 v1admin 命名空间结构,仅 19 个顶层 Query + 5 个顶层 Mutation。nextstep.md 声称的 v2 扁平命名41 Query + 20 Mutation未同步到 schema 文件。
2. **teacher-bff teacher 域仍是 P2 占位**`teacher.resolver.ts` 第 60-95 行,`exams` / `homework` / `grades` 查询仍抛 `BusinessError("not available in P2 (core-edu gRPC not ready, P3+)")`。teacher-bff v2 主要完成 admin 域扁平命名重构 + iam 联调,**teacher 域 P3+ 查询未实现**。
3. **teacher-portal 使用的 61 个 GraphQL operations 仅 5 个可用**dashboard / viewports / me / classes / class 这 5 个 P2 核心 Query 在 teacher-bff 真实可用;其他 56 个 operation含 P3+ 扩展、P7 参考项目补全、admin 域)在 teacher-bff 中**未实现或抛错**。
4. **接入真实 API 不可行**:若关闭 MSW`NEXT_PUBLIC_API_MOCKING=false`),浏览器端 GraphQL 请求会到 teacher-bff56 个查询会收到错误响应30+ 页面会显示错误或空数据。
**结论****v1 的"MSW mock → 真实 API 切换"工作无法在当前阶段完成**,需等待 teacher-bff 完成 teacher 域 P3+ 全部查询和 mutation 实现后才能切换。
### 1.3 v2 决策
- **保留 MSW mock**teacher-portal 继续使用 MSW 在浏览器端拦截 GraphQL 请求,所有页面正常工作。
- **SSR 阶段保留降级行为**next.config.js rewrites 仍将 SSR GraphQL 请求代理到 api-gateway但 api-gateway 未启动时 SSR 会 500仅开发模式。Docker 部署时需先启动 api-gateway或在生产环境关闭 SSR GraphQL 预取。
- **记录 v2 新工作项**:本文档记录所有发现的上下游依赖和待完成工作。
---
## 2. 下游依赖工作(需协调 AI / 其他 AI 推进)
### 2.1 teacher-bffai03— 最高优先级 ⚠️ 部分完成
**v1 期望**v1 列出 11 类 GraphQL operations详见 [nextstep.md §2.1](./nextstep.md#21-teacher-bffai03最高优先级)),期望 teacher-bff schema 上线后切换真实数据。
**v2 核查结果**
| teacher-bff 承诺nextstep §3.2 | 实际状态 | 影响 |
| --------------------------------------------------- | ------------------------------------------------------------------------------------------- | --------------------------------- |
| teacher 域 14 Query 全部实现 | ❌ 仅 5 个 P2 核心真实实现dashboard/viewports/me/classes/class其他 9 个抛 P2 占位错误 | 30+ 页面无法切换真实数据 |
| teacher 域 5 Mutation 全部实现 | ❓ 需核查createExam/assignHomework/recordGrade 抛 P2 占位错误) | 4 个创建页面无法切换 |
| admin 域 41 Query + 20 Mutation扁平命名 | ✅ v2 已实现admin.resolver.ts 扁平命名admin-portal 已联调) | 但 teacher-portal 不使用 admin 域 |
| GraphQL schema introspection 41 Query + 20 Mutation | ⚠️ 实际可用仅 5 个 teacher 域 P2 + 26 admin 域扁平命名 | introspection 通过但字段抛错 |
| Docker 镜像 + iam 真实联调 | ✅ 通过currentUser/me/adminRoles 等返回真实 iam 数据) | — |
| SSE `/v1/teacher/ai/chat/stream` | ✅ 已实现 | teacher-portal AI 助手页可联调 |
**v2 新发现 - teacher-bff 待补工作**
| # | 工作项 | 当前状态 | 阻塞影响 |
| --- | ---------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------- | ------------------------------ |
| 1 | 实现 teacher 域 `exams(classId)` 真实查询core-edu gRPC ListExamsByClass | ❌ 抛 "not available in P2" | /exams 列表页无法切换 |
| 2 | 实现 teacher 域 `homework(classId)` 真实查询core-edu gRPC ListHomeworkByClass | ❌ 抛 "not available in P2" | /homework 列表页无法切换 |
| 3 | 实现 teacher 域 `grades(examId)` 真实查询core-edu gRPC ListGradesByExam | ❌ 抛 "not available in P2" | /grades 列表页无法切换 |
| 4 | 实现 teacher 域 `classStudents(classId)` 查询iam 或 core-edu | ❌ 不在 schema 中 | /students 列表页无法切换 |
| 5 | 实现 teacher 域 `examDetail(id)` 查询 | ❌ 不在 schema 中 | /exams/[id] 详情页无法切换 |
| 6 | 实现 teacher 域 `homeworkDetail(id)` 查询 | ❌ 不在 schema 中 | /homework/[id] 详情页无法切换 |
| 7 | 实现 teacher 域 `updateUser(input)` mutation | ❌ 不在 schema 中(只有 admin.updateUser | /settings 编辑页无法切换 |
| 8 | 实现 P7 参考项目补全的 50+ 查询(成绩/作业批改/考试组卷/题库/教材/考勤/班级/请假/调课/备课/诊断/错题/练习/选修课/富文本/监考/扫描批改/热力图) | ❌ 不在 schema 中 | 30+ P7 页面无法切换 |
| 9 | 实现 P4 `knowledgeGraph` / `classAnalytics` / `studentAnalytics` 查询 | ❌ 不在 schema 中schema 中是 `knowledgePath`/`classPerformance`/`studentWeakness`/`learningTrend`,命名不一致) | P4 3 页面无法切换 |
| 10 | 实现 P5 `myNotifications` / `generateLessonPlan` / `generateReport` | ❌ 不在 schema 中schema 中是 `notifications` / 无 generateLessonPlan / 无 generateReport | P5 5 页面无法切换 |
| 11 | 同步 schema 文件为 v2 扁平命名 | ❌ schema 文件仍是 v1admin 命名空间) | 契约不一致 |
| 12 | 实现 core-edu gRPC 联调(`CORE_EDU_GRPC_TARGET` 当前留空走降级模式 B | ⏳ 待 core-edu 服务就绪 | teacher 域所有扩展查询无法实现 |
**协调方式**
1. ai03 完成 teacher 域 P3+ 扩展 query/mutation 实现后,通知 ai13 在 teacher-portal 设置 `NEXT_PUBLIC_API_MOCKING=false`
2. ai03 同步更新 `packages/shared-ts/contracts/graphql/teacher-bff.schema.graphql` 为 v2 扁平命名
3. teacher-portal 端到端测试每个页面字段映射
**预计切换步骤**(待 teacher-bff teacher 域补全后执行):
1. 设置 `NEXT_PUBLIC_API_MOCKING=false`
2. 启动 teacher-bff 容器(接入 iam + core-edu + content + data-ana + msg + ai 全部上游)
3. 逐页面测试 GraphQL 查询
4. 修复字段映射差异teacher-portal MSW fixture 字段 vs teacher-bff 实际返回字段)
5. 删除或停用 `src/mocks/handlers-p*.ts`(仅在切换全部成功后)
### 2.2 iamai06— 高优先级 ✅ 已完成
**v2 核查结果**iam 已完成全部 nextstep.md 工作,包括:
- 15 个 gRPC RPC 全部实现
- REST CRUD 完整(角色/权限/视口/用户/TOTP
- JWKS 端点(`/.well-known/jwks.json`)已就绪
- Redis 权限缓存(含指标)
- Outbox 事件发布
- Docker 镜像构建并验证通过
**对 teacher-portal 的影响**
- ✅ JWT RS256 签发可用teacher-portal 登录流程可走真实 iam
-`/api/auth/login` 通过 api-gateway → iam REST `/v1/iam/login` 可用
-`currentUser` / `me` 查询通过 teacher-bff → iam gRPC 可用
- ⏳ F12 裁决的 refresh cookie 端点(`POST /iam/auth/refresh` 返回 httpOnly cookieiam nextstep §1.2 提到 `RefreshToken` gRPC 已实现,但 teacher-portal 的 useAuth hook 当前用 localStorage JWT 模式,迁移到 httpOnly cookie 模式仍需 ai13 修改 useAuth
**v2 新发现 - iam 相关待补工作**
| # | 工作项 | 当前状态 | 阻塞影响 |
| --- | ------------------------------------------------------------------- | -------------------------------------- | ----------------------------------------- |
| 1 | teacher-portal useAuth hook 迁移到 httpOnly cookie 模式F12 裁决) | ⏳ 待 ai13 实现 | 长会话保活不安全localStorage XSS 风险) |
| 2 | teacher-portal 登录流程接入真实 iam `/api/auth/login` | ⏳ 待 teacher-bff teacher 域补全后切换 | 当前用 MSW mock 登录响应 |
### 2.3 push-gatewayai09— 中优先级 ✅ 已完成
**v2 核查结果**push-gateway 已完成全部 nextstep.md 工作:
- WebSocket `/ws` 端点JWT RS256 + DevMode dev-token
- `/internal/push` / `/internal/broadcast` / `/internal/online/:userID` HTTP API
- Kafka 消费 `edu.notification.requested`
- Redis Pub/Sub 跨实例消息扇出
- P6 Reconnect 协议session_id + last_seq + ring buffer
- 幂等性event_id Redis SETNX 24h 去重)
- Docker 镜像构建并验证通过
**对 teacher-portal 的影响**
- ✅ teacher-portal `/notifications` 页面的 WebSocket 通知通道可用
- ✅ teacher-portal `useNotificationsWebSocket` hookP5 实现)可直接接入 push-gateway
- ⏳ teacher-portal 当前 MSW mock WebSocket切换真实 push-gateway 需要配置 `NEXT_PUBLIC_PUSH_GATEWAY_WS_URL`
**v2 新发现 - push-gateway 相关待补工作**
| # | 工作项 | 当前状态 | 阻塞影响 |
| --- | ------------------------------------------------------------------------------- | --------------------- | ------------------------ |
| 1 | teacher-portal 配置 `NEXT_PUBLIC_PUSH_GATEWAY_WS_URL=ws://push-gateway:8081/ws` | ⏳ 待添加环境变量 | 通知中心无法接收真实推送 |
| 2 | teacher-portal `useNotificationsWebSocket` hook 接入真实 push-gateway | ⏳ 待切换 mock → 真实 | 通知中心仍是 mock 数据 |
| 3 | JWT token 传递给 WebSocket 连接(当前 dev-token 模式) | ⏳ 待生产环境配置 | 生产环境需要真实 JWT |
### 2.4 api-gatewayai01— ✅ 已完成
**v2 核查结果**api-gateway 已完成全部 nextstep.md 工作:
- `/api/v1/teacher/*` 反向代理到 teacher-bff:3003/*(路径重写剥离 /api/v1/teacher
- `/api/admin/graphql` 反向代理到 teacher-bff:3003/graphql
- `/api/v1/student/*` / `/api/v1/parent/*` 反向代理
- JWT RS256 验签中间件
- 限流 / 熔断 / CORS / X-Request-Id 注入
- Docker 镜像构建并验证通过
**对 teacher-portal 的影响**
- ✅ teacher-portal SSR 阶段 GraphQL 请求通过 next.config.js rewrites 到 api-gateway
- ✅ teacher-portal 登录流程 `POST /api/auth/login` → api-gateway → iam
**v2 新发现 - api-gateway 相关待补工作**api-gateway 已全部完成)。
### 2.5 core-edu / content / data-ana / msg / ai 服务 — ⏳ 未对接
**v2 核查结果**:这 5 个服务各自完成了 nextstep.md 列出的 P2-P6 工作,但 **teacher-bff 中 `CORE_EDU_GRPC_TARGET` / `CONTENT_GRPC_TARGET` / `DATA_ANA_GRPC_TARGET` / `MSG_GRPC_TARGET` / `AI_GRPC_TARGET` 全部留空**,走降级模式 B返回空结果 + warning
**对 teacher-portal 的影响**
- teacher-bff teacher 域扩展查询exams/homework/grades/knowledgePath/classPerformance 等)依赖这些下游服务
- 这些服务就绪后ai03 需要在 teacher-bff 配置 gRPC target 并实现真实查询
- 然后 ai13 才能切换 teacher-portal MSW mock → 真实 API
**v2 新发现 - 下游服务联调待补工作**
| # | 工作项 | 当前状态 | 阻塞影响 |
| --- | ---------------------------------------------------------------------------------------------------------------------------------- | ---------- | ----------------------------- |
| 1 | core-edu 服务暴露 gRPC `:50053` 并实现 ListExamsByClass/ListHomeworkByClass/ListGradesByExam/CreateExam/AssignHomework/RecordGrade | ⏳ 待 ai07 | teacher 域 P3 查询无法实现 |
| 2 | content 服务暴露 gRPC `:50054` 并实现 GetKnowledgePath/ListTextbooks/ListChapters | ⏳ 待 ai08 | teacher 域 P4 查询无法实现 |
| 3 | data-ana 服务暴露 gRPC `:50055` 并实现 GetClassPerformance/GetStudentWeakness/GetLearningTrend | ⏳ 待 ai11 | teacher 域 P4 查询无法实现 |
| 4 | msg 服务暴露 gRPC `:50056` 并实现 ListNotifications/MarkNotificationRead | ⏳ 待 ai10 | teacher 域 P5 查询无法实现 |
| 5 | ai 服务暴露 gRPC `:50058` 并实现 GenerateQuestion + SSE `/v1/ai/chat/stream` | ⏳ 待 ai12 | teacher 域 P5 AI 助手无法实现 |
| 6 | teacher-bff 配置 5 个 gRPC target从留空改为实际地址 | ⏳ 待 ai03 | 降级模式 B 持续生效 |
---
## 3. 本模块待补工作v2 更新)
### 3.1 v1 已完成项(详见 [nextstep.md §3](./nextstep.md#3-本模块待补工作)
- ✅ P1-A 单元测试63 tests passed
- ✅ P1-B 设计令牌硬化ESLint tokens 零违规)
- ✅ P2-C i18n 集成5 示范页面 + LocaleSwitcher
- ✅ P2-D ui-components 扩展5/8 组件)
- ✅ P2-E 性能 + A11yPerformanceDashboard + 5 核心页面 A11y 修复)
### 3.2 v2 新增待补工作
#### 3.2.1 MSW mock → 真实 API 切换(依赖 teacher-bff teacher 域补全)
**阻塞条件**teacher-bff 实现 teacher 域 P3+ 全部扩展 query/mutation详见 §2.1 表格 12 项)
**清单**
- [ ] 等待 teacher-bff teacher 域补全后设置 `NEXT_PUBLIC_API_MOCKING=false`
- [ ] 端到端测试 27 静态路由 + 11 动态路由
- [ ] 修复字段映射差异MSW fixture 字段 vs 实际返回字段)
- [ ] 删除或停用 `src/mocks/handlers-p*.ts`5 个 handlers 文件)
- [ ] 删除或停用 `src/mocks/fixtures/*.ts`13 个 fixtures 文件)
- [ ] 删除 `src/mocks/browser.ts` / `src/mocks/server.ts` / `src/mocks/init-mocks.ts`
- [ ]`package.json` 移除 `msw` devDependency
- [ ]`package.json` 移除 `"msw": { "workerDirectory": ["public"] }` 配置
- [ ]`src/app/providers.tsx` 移除 MSW 初始化逻辑
#### 3.2.2 useAuth hook 迁移到 httpOnly cookieF12 裁决)
**v2 核查更新2026-07-14**:阻塞条件已修正。
**阻塞条件**:⚠️ 阻塞于 iam 后端未实现 Set-Cookie
**核查发现**iam nextstep.md §1.1 确认登录接口 `POST /v1/iam/login` 返回 JWT token pairaccess_token + refresh_token在 response body 中,但**未在响应头设置 Set-Cookie**。F12 裁决要求 httpOnly cookie 模式需要 iam 后端配合:
- iam REST 登录接口需要设置 `Set-Cookie: refresh_token=...; HttpOnly; Secure; SameSite=Strict`
- teacher-portal 前端才能移除 localStorage JWT 存储
**当前状态**teacher-portal useAuth 仍使用 localStorage JWT 模式F12 裁决 P2 阶段方案),等待 iam 后端实现 Set-Cookie 后迁移。
**清单**(待 iam 后端支持后执行):
- [ ] 等待 iam REST 登录接口设置 `Set-Cookie: refresh_token=...; HttpOnly; Secure; SameSite=Strict`
- [ ] 修改 `packages/hooks/src/use-auth.ts`:从 localStorage JWT 改为 httpOnly cookie
- [ ] 修改 `src/app/(auth)/login/page.tsx`:登录成功后不再手动存 JWT 到 localStorage
- [ ] 修改 `src/lib/graphql-client.ts`urql fetcher 不再手动添加 Authorization header浏览器自动带 cookie
- [ ] 修改 `next.config.js` rewrites添加 credentials: 'include' 到 SSR fetcher
- [ ] 添加 CSRF 防护double-submit cookie 模式)
- [ ] 测试:登录 → Dashboard → 刷新页面 → 保持登录态
#### 3.2.3 push-gateway WebSocket 接入 ✅ 已完成2026-07-14
**阻塞条件**push-gateway 已就绪)
**v2 完成情况**
- ✅ 添加环境变量 `NEXT_PUBLIC_PUSH_GATEWAY_WS_URL`(默认 `ws://localhost:8081/ws`
- ✅ 修改 `src/hooks/use-notifications-websocket.ts`:从硬编码 URL 改为环境变量
- ✅ JWT token 传递URL query param `?token=<jwt>`(从 localStorage 读取 edu_access_token兼容 DevMode dev-token
- ✅ Reconnect 协议P6session_idcrypto.randomUUID+ last_seq消息序号追踪
- ✅ 手动重连生成新 session_id触发服务端 ring buffer 补发)
- ✅ 兼容 push-gateway 事件格式event_type + payload 结构)
- ✅ Mock 模式保留NEXT_PUBLIC_API_MOCKING=enabled 时用 setInterval mock
**验证**typecheck + lint + 87/87 tests passed
#### 3.2.4 i18n 扩展(剩余 30+ 页面)
**阻塞条件**:无
**v2 完成情况**:部分完成
-`src/messages/zh-CN.json` + `src/messages/en.json` 已包含全部 26 模块的 keycommon/dashboard/grades/settings 等)
- ✅ 5 个示范页面已迁移dashboard / grades / grades/entry / grades/stats / settings
- ✅ LocaleSwitcher 组件已实现cookie 驱动 + router.refresh
- ⏳ 剩余 50+ 页面未迁移classes/exams/homework/notifications/students 等)
- ⏳ 需要为剩余页面逐个添加 `useTranslations` + 替换中文硬编码
**清单**
- [ ] classes/page.tsx → t("classes.title")
- [ ] exams/page.tsx → t("exams.title")
- [ ] homework/page.tsx → t("homework.title")
- [ ] notifications/page.tsx → t("notifications.title")
- [ ] students/page.tsx → t("students.title")
- [ ] ... 其余 45+ 页面
#### 3.2.5 性能优化扩展 ✅ 基本完成2026-07-14
**阻塞条件**:无(非紧急)
**v2 完成情况**
-`size-limit.json` 已配置 9 项性能预算检查Shell/Remote/CSS/6 个路由)
- ✅ 5 个重型页面已懒加载lesson-plans/heatmap、grades/analytics、knowledge-graph、ParentPortalRemote、HeatmapMatrix
- ⏳ 图片优化next/image 替换 `<img>`)— 待配置 remotePatterns
- ⏳ 字体优化next/font 替换 CSS @font-face— 待配置
- ⏳ CI 阻断集成size-limit + bundle analyzer— 待 CI 配置
#### 3.2.6 单元测试扩展 ✅ 已完成2026-07-14
**阻塞条件**:无(非紧急)
**v2 完成情况**
- ✅ 测试 `usePermission` hook15 testshasPermission/hasAny/hasAll/hasRole/dataScope/context=null/useMemo 稳定性)
- ✅ 测试 `useAuth` hook9 tests初始状态/localStorage 恢复/login/logout/refreshUser/跨实例共享/JSON 损坏降级)
- ✅ 测试 MSW handlers10 tests+ handlers-p413 tests
- ✅ 测试 useCrossTabSync6 tests+ useNotificationsWebSocket6 tests
- ✅ 测试 fixturesexams17 tests+ viewports11 tests
- ✅ 总计 87/87 tests passed从 v1 的 63 tests 扩展到 87 tests
#### 3.2.7 设计令牌完整迁移 ✅ 已完成2026-07-14
**阻塞条件**:无(非紧急)
**v2 完成情况**
-`src/app/globals.css`:全部使用 `var(--*)` 引用,无 hsl() 字面量
-`tailwind.config.js`:全部使用 `var(--*)` 引用,无 hsl() 字面量
- ✅ ESLint `.eslintrc.tokens.js`flat config 格式,禁止 #hex 和字体字面量
- ✅ ESLint `.eslintrc.a11y.js`flat config 格式jsx-a11y 规则
- ✅ 源码扫描确认:`src/` 目录无 hsl() 或 #hex 字面量(仅 a11y.ts 注释中提到 hex 说明)
#### 3.2.8 ui-components 剩余组件 ✅ 已完成2026-07-14
**阻塞条件**:无(非紧急,待业务真实需求时抽取)
**v2 完成情况**
-`Chart` 组件SVG 图表统一封装):支持 bar/line/pie 三种类型,纯 SVG 实现无额外依赖
-`Calendar` 组件月视图日历支持前后月切换、日期点击回调、事件标记lesson/exam/meeting
-`RichTextEditor` 组件(富文本编辑器):基于 contentEditable 轻量实现,工具栏支持加粗/斜体/下划线/列表/标题/链接
-`index.ts` 已更新导出 3 个新组件
- ⏳ RichTextEditor 可在 P3+ 升级为 Tiptap 封装(需安装 @tiptap/core + @tiptap/react
---
## 4. v2 集成测试方案(待 teacher-bff 补全后执行)
### 4.1 前置条件
- [ ] teacher-bff teacher 域全部 query/mutation 实现§2.1 表格 12 项全部 ✅)
- [ ] teacher-bff schema 文件同步为 v2 扁平命名
- [ ] teacher-bff 配置 5 个 gRPC targetcore-edu / content / data-ana / msg / ai
- [ ] core-edu / content / data-ana / msg / ai 服务全部启动并健康
### 4.2 集成测试步骤
1. **启动顺序**docker compose up
- edu-mysql / edu-redis / edu-kafka
- iam :3002 :50052
- core-edu :50053 / content :50054 / data-ana :50055 / msg :50056 / ai :50058 :3008
- teacher-bff :3003
- push-gateway :8081
- api-gateway :8080
- teacher-portal :4000`NEXT_PUBLIC_API_MOCKING=false`
2. **验证项**
| # | 验证项 | 预期结果 |
| --- | ---------------- | ---------------------------------------------- |
| 1 | 登录流程 | `POST /api/auth/login` → JWT → Dashboard 渲染 |
| 2 | Dashboard 查询 | `query Dashboard` 返回真实 iam + core-edu 数据 |
| 3 | 班级列表 | `query Classes` 返回真实 iam 数据 |
| 4 | 考试列表 | `query ClassExams` 返回真实 core-edu 数据 |
| 5 | 作业列表 | `query ClassHomework` 返回真实 core-edu 数据 |
| 6 | 成绩列表 | `query ExamGrades` 返回真实 core-edu 数据 |
| 7 | 创建考试 | `mutation CreateExam` 写入 core-edu DB |
| 8 | 通知中心 | WebSocket 连接 push-gateway实时接收推送 |
| 9 | AI 助手 | SSE `/v1/teacher/ai/chat/stream` 流式响应 |
| 10 | 知识图谱 | `query KnowledgeGraph` 返回真实 content 数据 |
| 11 | 学情分析 | `query ClassAnalytics` 返回真实 data-ana 数据 |
| 12 | 所有 27 静态路由 | HTTP 200无 SSR 500 错误 |
| 13 | 所有 11 动态路由 | HTTP 200无 SSR 500 错误 |
3. **回滚策略**
- 若集成测试失败,设置 `NEXT_PUBLIC_API_MOCKING=true` 回退到 MSW mock
- 修复问题后重新测试
---
## 5. v2 已知问题(新增)
| 问题 | 影响 | 临时方案 |
| --------------------------------------------------------- | ----------------------------------------------------- | -------------------------------------------------------------- |
| teacher-bff schema 文件未同步为 v2 扁平命名 | 契约不一致teacher-portal 端无法基于 schema 生成类型 | 等待 ai03 同步 schema 文件 |
| teacher-bff teacher 域 P3+ 查询仍抛 "not available in P2" | 56 个 GraphQL operations 无法切换真实数据 | 继续使用 MSW mock |
| teacher-bff 5 个 gRPC target 留空走降级模式 B | teacher 域扩展查询返回空 | 等待 ai03 配置实际 gRPC 地址 |
| teacher-portal useAuth 使用 localStorage JWT | XSS 风险F12 裁决要求 httpOnly cookie | ⚠️ 阻塞于 iam 后端实现 Set-Cookie§3.2.2 |
| ~~teacher-portal WebSocket 使用 mock~~ | ~~通知中心无法接收真实推送~~ | ✅ 已接入 push-gateway§3.2.3,环境变量 + token + Reconnect |
---
## 6. v2 总结
### 6.1 已完成v1 + v2
| 工作项 | 完成度 |
| ----------------------- | ------------------------------------------------------------------------- |
| P2 MF Shell + 基础页面 | ✅ 100% |
| P3 考试/作业/成绩 | ✅ 100%MSW mock |
| P4 知识图谱 + 学情分析 | ✅ 100%MSW mock |
| P5 通知 + AI 助手 | ✅ 100%MSW mock |
| P6 可观测性硬化 | ✅ 100% |
| P7 参考项目差距闭环 | ✅ 100%35 页面MSW mock |
| Docker Desktop 验证 | ✅ 通过standalone 模式) |
| P1-A 单元测试 | ✅ 87/87 tests passedv1: 63 + v2: 24 |
| P1-B 设计令牌硬化 | ✅ ESLint tokens 零违规 + 无 hsl/hex 字面量 |
| P2-C i18n 集成 | ✅ 5/55 页面 + LocaleSwitcher + 26 模块 key |
| P2-D ui-components 扩展 | ✅ 12/12 组件v1: 9 + v2: Chart/Calendar/RichTextEditor |
| P2-E 性能 + A11y | ✅ PerformanceDashboard + 5 核心页面修复 + 5 页面懒加载 + size-limit 9 项 |
| v2 push-gateway 接入 | ✅ WebSocket 环境变量 + token + Reconnect 协议 |
### 6.2 待完成v2 剩余)
| 工作项 | 优先级 | 阻塞条件 |
| ------------------------------ | ------ | ------------------------------------------------ |
| MSW mock → 真实 API 切换 | P0 | teacher-bff teacher 域补全12 项) |
| useAuth 迁移到 httpOnly cookie | P1 | ⚠️ 阻塞于 iam 后端实现 Set-Cookiev2 核查修正) |
| i18n 扩展(剩余 50+ 页面) | P2 | 无(工作量:逐页替换中文硬编码为 t() 调用) |
| 图片优化next/image | P3 | 无(待配置 remotePatterns |
| 字体优化next/font | P3 | 无(待配置) |
| CI size-limit 阻断集成 | P3 | 无(待 CI 配置) |
### 6.3 阻塞分析
**teacher-portal 当前阻塞项**
1. **teacher-bff teacher 域 P3+ 扩展查询/mutation 未实现**(依赖 ai03 + ai07/08/11/10/12 联调)— 阻塞 MSW mock → 真实 API 切换
2. **iam REST 登录接口未设置 Set-Cookie**(依赖 ai06 实现 httpOnly cookie— 阻塞 useAuth 迁移
**解除阻塞后**
- teacher-bff teacher 域补全 → 可一次性完成 MSW mock → 真实 API 切换§3.2.1
- iam 实现 Set-Cookie → 可完成 useAuth httpOnly cookie 迁移§3.2.2
**无阻塞工作**i18n 扩展剩余页面、图片/字体优化、CI 集成等均可在任意时间推进。
---
**本文件维护规则**v2 基于 2026-07-13 下游 nextstep 核查生成。当下游状态变化时(特别是 teacher-bff teacher 域补全),更新本文档对应条目。