From 8b729a710fe00d79d77e98af2aefd6714a38050f Mon Sep 17 00:00:00 2001 From: SpecialX <47072643+wangxiner55@users.noreply.github.com> Date: Mon, 13 Jul 2026 16:52:13 +0800 Subject: [PATCH] =?UTF-8?q?feat(teacher-portal):=20Docker=20Desktop=20?= =?UTF-8?q?=E9=AA=8C=E8=AF=81=E9=80=9A=E8=BF=87=20+=20=E5=88=87=E6=8D=A2?= =?UTF-8?q?=20standalone=20=E6=A8=A1=E5=BC=8F=20+=20nextstep.md?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Dockerfile 切换为 Next.js output:standalone 模式 - 解决 pnpm symlink 在 runtime 下无法解析 react/jsx-runtime 的问题 - 修复 tsconfig.base.json 未 COPY 到 builder 阶段的问题 - next.config.js 添加 output:"standalone" 配置 - Docker Desktop 验证通过: - 镜像构建成功 (1.32GB) - 容器启动 Ready in 69ms - /api/health 健康检查返回 200 - 27 静态路由 + 11 动态路由全部 HTTP 200 - 新增 nextstep.md: - 下游依赖清单(teacher-bff 61 GraphQL operations + iam + push-gateway) - 本模块待补工作(单元测试/设计令牌硬化/i18n/ui-components 扩展/性能/A11y) - Docker 部署注意事项 + 路由清单 + 已知问题 - workline.md §5.6 记录 Docker 验证结果 --- apps/teacher-portal/Dockerfile | 20 +- apps/teacher-portal/next.config.js | 4 + apps/teacher-portal/nextstep.md | 280 ++++++++++++++++++ .../worklines/teacher-portal_workline.md | 29 ++ 4 files changed, 323 insertions(+), 10 deletions(-) create mode 100644 apps/teacher-portal/nextstep.md diff --git a/apps/teacher-portal/Dockerfile b/apps/teacher-portal/Dockerfile index baac88a..16b6d94 100644 --- a/apps/teacher-portal/Dockerfile +++ b/apps/teacher-portal/Dockerfile @@ -1,4 +1,4 @@ -# 多阶段构建:Next.js 生产镜像 +# 多阶段构建:Next.js 生产镜像(standalone 模式) # 用法:docker build -t edu/teacher-portal:latest -f apps/teacher-portal/Dockerfile . # 端口规范:teacher-portal :4000(matrix.md §1 微前端层) @@ -10,7 +10,7 @@ WORKDIR /app RUN corepack enable && corepack prepare pnpm@9.12.0 --activate # 先拷依赖清单,利用缓存(含 workspace 共享包) -COPY package.json pnpm-lock.yaml* pnpm-workspace.yaml* ./ +COPY package.json pnpm-lock.yaml* pnpm-workspace.yaml* tsconfig.base.json* ./ COPY apps/teacher-portal/package.json ./apps/teacher-portal/ COPY packages/ui-tokens/package.json ./packages/ui-tokens/ COPY packages/ui-components/package.json ./packages/ui-components/ @@ -24,7 +24,7 @@ COPY packages/ui-tokens ./packages/ui-tokens COPY packages/ui-components ./packages/ui-components COPY packages/hooks ./packages/hooks -# 构建(禁用 telemetry,生产模式) +# 构建(禁用 telemetry,生产模式,standalone 输出) ENV NEXT_TELEMETRY_DISABLED=1 RUN pnpm --filter @edu/teacher-portal run build @@ -39,12 +39,10 @@ ENV PORT=4000 # 非 root 用户运行 RUN addgroup -g 1001 -S nodejs && adduser -S nextjs -u 1001 -# 拷构建产物与必要清单 -COPY --from=builder /app/apps/teacher-portal/package.json ./package.json -COPY --from=builder /app/apps/teacher-portal/.next ./.next -COPY --from=builder /app/apps/teacher-portal/public ./public -COPY --from=builder /app/node_modules ./node_modules -COPY --from=builder /app/apps/teacher-portal/next.config.js ./next.config.js +# 拷 standalone 产物(已含 node_modules 和 server.js,自包含) +COPY --from=builder --chown=nextjs:nodejs /app/apps/teacher-portal/.next/standalone ./ +COPY --from=builder --chown=nextjs:nodejs /app/apps/teacher-portal/.next/static ./.next/static +COPY --from=builder --chown=nextjs:nodejs /app/apps/teacher-portal/public ./public USER nextjs EXPOSE 4000 @@ -53,4 +51,6 @@ EXPOSE 4000 HEALTHCHECK --interval=30s --timeout=5s --start-period=20s --retries=3 \ CMD wget --quiet --spider http://localhost:4000/api/health || exit 1 -CMD ["node_modules/.bin/next", "start", "-p", "4000"] +# standalone 模式下直接用 node server.js 启动(已自包含所有依赖) +WORKDIR /app/apps/teacher-portal +CMD ["node", "server.js"] diff --git a/apps/teacher-portal/next.config.js b/apps/teacher-portal/next.config.js index fe40421..cce119a 100644 --- a/apps/teacher-portal/next.config.js +++ b/apps/teacher-portal/next.config.js @@ -78,6 +78,10 @@ function buildShared() { const nextConfig = { reactStrictMode: true, + // standalone 模式:Next.js 自动打包所有依赖到 .next/standalone + // 解决 pnpm symlink 在 Docker runtime 下无法解析 react/jsx-runtime 的问题 + output: "standalone", + // ESM 模式:transpilePackages 对齐 NestJS ESM 规范 // @edu/hooks 等包使用 .js 后缀导入源码,需 transpile + extensionAlias transpilePackages: [ diff --git a/apps/teacher-portal/nextstep.md b/apps/teacher-portal/nextstep.md new file mode 100644 index 0000000..155dcf1 --- /dev/null +++ b/apps/teacher-portal/nextstep.md @@ -0,0 +1,280 @@ +# teacher-portal 模块 Next Steps + +> 维护者:ai13(teacher-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-bff(ai03)— 最高优先级 + +**依赖内容**: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 | +| 通知/AI(P5) | 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 iam(ai06)— 高优先级 + +**依赖内容**:JWT refresh token cookie 模式(F12 裁决) +**影响范围**:teacher-portal 长会话保活 +**协调方式**:iam 的 refresh cookie 端点上线后,teacher-portal 的 useAuth hook 需配合调整 + +### 2.3 push-gateway(ai09)— 中优先级 + +**依赖内容**: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.5s(Sentry / WebVitals 监控) +- [ ] 路由懒加载(动态 import 重型页面,如 grades/analytics、knowledge-graph) +- [ ] 图片优化(`next/image` 替换 ``) +- [ ] 字体优化(`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 mock(true 时浏览器端拦截 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 仅浏览器端生效**:服务端渲染(SSR)时,urql 发起的 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 中记录审计结果。 diff --git a/docs/architecture/issues/worklines/teacher-portal_workline.md b/docs/architecture/issues/worklines/teacher-portal_workline.md index bbb22a4..e602469 100644 --- a/docs/architecture/issues/worklines/teacher-portal_workline.md +++ b/docs/architecture/issues/worklines/teacher-portal_workline.md @@ -311,6 +311,35 @@ gantt 8. 全局搜索(参考项目有 /search API) 9. 全局消息中心增强(参考项目有 /messages 页面) +### §5.6 Docker Desktop 验证(2026-07-13) + +**构建**: + +- Dockerfile 切换为 Next.js `output: "standalone"` 模式(解决 pnpm symlink 在 runtime 下无法解析 react/jsx-runtime 的问题) +- 修复 `tsconfig.base.json` 未 COPY 到 builder 阶段的问题 +- 基础镜像:`node:20-alpine`(本地测试可 retag `node:22-alpine`) +- 镜像大小:1.32GB + +**容器运行**: + +- 启动时间:Ready in 69ms +- 健康检查:`/api/health` → `{"status":"ok","service":"teacher-portal"}` +- 首页:HTTP 200,length=5921(登录页正常渲染) + +**路由验证**: + +| 类型 | 通过/总数 | 结果 | +| ---- | --------- | ---- | +| 静态路由 | 27/27 | 全部 HTTP 200 ✅ | +| 动态路由 | 11/11 | 全部 HTTP 200 ✅ | +| GraphQL 端点 | N/A | 服务端代理到 api-gateway(未启动时预期 500) | + +**已知限制**: + +- MSW mock 仅浏览器端生效,SSR 阶段 GraphQL 请求走 next.config.js rewrites 到 api-gateway +- 生产部署时必须先启动 api-gateway +- 详细下游依赖清单见 `apps/teacher-portal/nextstep.md` + --- ## §6 全并行开发说明