21 KiB
student-bff 下游工作清单 V2(Next Steps v2)
负责人:ai04 更新日期:2026-07-14 基于版本:v1(nextstep.md)+ student-portal v2 审计(§9 二次核查)后的更新 关联:
0. v2 核查总结
| 工作项 | v1 状态 | v2 核查结果 | 阻断级别 |
|---|---|---|---|
| index.ts 装配 extended resolvers | ❌ 未装配 | ✅ 已修复 | P0 |
| shared-ts schema 补全 43 个操作 SDL | ❌ 未补全 | ✅ 已修复 | P0 |
| myAttendance resolver 实现 | ❌ 缺失 | ✅ 已实现 | P1 |
| startPracticeSession 类型修正(Query → Mutation) | ❌ 未修正 | ✅ 已修正 | P1 |
| RecordExamViolationInput schema 类型对齐 | ❌ 未发现 | ✅ 已修复 | P0 |
| Dockerfile 多阶段构建(对齐 teacher-bff 模式) | ❌ 失败 | ✅ 已修复 | P0 |
| shared-ts pino NodeNext 类型修复 | ❌ 未发现 | ✅ 已修复 | P0 |
| Docker 构建 + 容器启动 + GraphQL 60 操作验证 | ❌ 未验证 | ✅ 全部通过 | P0 |
结论: student-bff v2 全部 P0/P1 工作已完成并验证通过。60 个 GraphQL 操作(36 Query + 24 Mutation)全部注册并可响应。
1. student-bff v2 完成项详情
1.1 P0:index.ts 装配 extended resolvers
修复前: index.ts 仅装配 11 个基础 resolver,22 个 extended Query + 21 个 extended Mutation 已实现但未导入。
修复后:
import { extendedQueriesResolvers } from "./extended-queries.resolver.js";
import { extendedMutationsResolvers } from "./extended-mutations.resolver.js";
export const studentBffResolvers = {
Query: {
...(authResolvers.Query ?? {}),
// ... 其他基础 resolver
...(extendedQueriesResolvers.Query ?? {}), // ✅ 新增
},
Mutation: {
...(homeworkResolvers.Mutation ?? {}),
...(notificationsResolvers.Mutation ?? {}),
...(extendedMutationsResolvers.Mutation ?? {}), // ✅ 新增
},
Subscription: {
...(aiStreamResolvers.Subscription ?? {}),
},
};
验证: GraphQL introspection 查询返回 36 Query + 24 Mutation = 60 操作。
1.2 P0:shared-ts schema 补全
修复前: student-bff.schema.graphql 仅 822 行,定义 15 Query + 2 Mutation + 1 Subscription。
修复后: 1648 行,定义 36 Query + 24 Mutation + 1 Subscription,包含所有 input type / enum / payload type。
1.3 P1:myAttendance resolver 实现
调用 core-edu.AttendanceService.ListAttendanceByStudent,B4 强制 userId = studentId(DataScope SELF)。
1.4 P1:startPracticeSession 类型修正
从 Query 移到 Mutation(语义为创建会话)。
1.5 P0:RecordExamViolationInput schema 类型对齐
schema 引用 RecordExamViolationInput 但实际定义为 RecordViolationInput,已修正为 recordExamViolation(input: RecordViolationInput!)。
1.6 P0:Dockerfile 修复
问题: 原 Dockerfile 的 COPY 路径未包含 services/student-bff/ 前缀,且 runtime stage 使用 --ignore-workspace 导致 @edu/shared-ts 无法解析。
修复: 对齐 teacher-bff 模式:
- Builder stage:复制 workspace 配置 + shared-proto + shared-ts + student-bff,使用
--filter @edu/student-bff...过滤安装(避免 scripts/arch-scan 的 better-sqlite3 原生编译),先构建 shared-ts 再构建 student-bff - Runtime stage:保留 workspace 结构,
pnpm install --prod --filter @edu/student-bff... --ignore-scripts,复制 shared-ts dist 产物
1.7 P0:shared-ts pino NodeNext 类型修复
问题: pino 在 NodeNext + ESM 模式下 default import 丢失 callable 签名(declaration merging 失效)。
修复: 通过 namespace import + 显式类型断言恢复可调用性:
import * as pinoNs from "pino";
import type { Logger as PinoLogger, LoggerOptions } from "pino";
type PinoFn = (options?: LoggerOptions | unknown) => PinoLogger;
const pino = ((pinoNs as unknown as { default: PinoFn }).default ??
(pinoNs as unknown as PinoFn)) as PinoFn;
同时修复 src/bff/downstream-client.ts:351 的 IteratorResult 类型窄化问题。
2. v2 本地 Docker 验证结果(2026-07-14)
| 验证项 | 结果 | 说明 |
|---|---|---|
pnpm typecheck |
✅ | 0 errors |
pnpm lint |
✅ | 0 errors, 0 warnings |
pnpm test |
✅ | 70/70 passed(5 test files) |
packages/shared-ts typecheck |
✅ | 0 errors(pino 修复后) |
packages/shared-ts build |
✅ | dist 产物生成成功 |
| Docker 镜像构建 | ✅ | edu-student-bff:test 构建成功 |
| 容器启动 | ✅ | NestFactory + GraphQL Yoga 初始化完成 |
/healthz 健康检查 |
✅ | {"status":"ok","service":"student-bff"} |
GraphQL __typename 查询 |
✅ | {"data":{"__typename":"Query"}} |
| GraphQL introspection | ✅ | 36 Query + 24 Mutation = 60 操作全部注册 |
MOCK_UPSTREAM=true 降级模式 |
✅ | 所有下游调用返回 mock 数据 |
GraphQL 操作清单(60 个,全部已注册):
- Query(36): currentUser, myClasses, myExams, myHomework, myGrades, myAttendance, textbooks, chapters, learningPath, studentDashboard, myWeakness, myTrend, myNotifications, myNotificationUnreadCount, aiChat, examDetail, homeworkDetail, serverTime, mySchedule, studentGrowth, assignmentAnalysis, myProfile, myMasterySummary, myDiagnosticReports, myErrorBook, announcements, announcementDetail, myLeaveRequests, myElectiveSelections, availableElectiveCourses, myLessonPlans, lessonPlanDetail, myCoursePlans, coursePlanDetail, myReportCard, myPracticeSessions
- Mutation(24): submitHomework, markNotificationAsRead, markAsRead, markAllAsRead, updateNotificationPreference, submitExam, saveExamDraft, recordExamViolation, recordPasteEvent, updateProfile, changePassword, requestExtension, joinClass, leaveClass, addErrorBookItem, updateErrorBookItem, deleteErrorBookItem, markAnnouncementRead, createLeaveRequest, cancelLeaveRequest, selectElectiveCourse, dropElectiveCourse, startPracticeSession, submitPracticeAnswer
3. 上游依赖(api-gateway 路由)
3.1 api-gateway(ai01 负责)
v2 核查结果:✅ 路由已注册 + 路径重写已修复
services/api-gateway/main.go—registerBffProxy(api, "student", cfg.StudentBffURL)✅services/api-gateway/internal/config/config.go—StudentBffURL: getEnv("STUDENT_BFF_URL", "http://localhost:3009")✅- 路径前缀改写:
/api/v1/student/*→/v1/student/*(proxy.goregisterBffProxy)✅ - JWT 鉴权 +
x-user-id/x-user-roles/x-request-idheader 注入 ✅
3.2 待 SRE AI 修复(P0 部署阻断)
| # | 工作项 | 详情 |
|---|---|---|
| 1 | infra/docker-compose.deploy.yml 新增 student-bff |
服务定义缺失,需新增 build context + environment + ports + networks |
| 2 | infra/docker-compose.deploy.yml 新增 student-portal |
服务定义缺失 |
| 3 | api-gateway environment 补充 STUDENT_BFF_URL |
当前 deploy.yml 缺失,会回退到 http://localhost:3009,容器内无法访问 |
student-bff 建议的 deploy.yml 配置:
student-bff:
build:
context: ./repo
dockerfile: services/student-bff/Dockerfile
container_name: edu-student-bff
restart: unless-stopped
environment:
NODE_ENV: production
PORT: 3009
DEV_MODE: "false"
MOCK_UPSTREAM: "false"
REDIS_URL: redis://edu-redis:6379
KAFKA_BROKERS: edu-kafka:29092
# 下游 gRPC targets(Docker 服务名 + 端口)
IAM_GRPC_TARGET: iam:50052
CORE_EDU_GRPC_TARGET: core-edu:50053
CONTENT_GRPC_TARGET: content:50054
DATA_ANA_GRPC_TARGET: data-ana:50055
MSG_GRPC_TARGET: msg:50056
AI_GRPC_TARGET: ai:50058
ports:
- "${STUDENT_BFF_PORT:-3009}:3009"
depends_on:
iam:
condition: service_healthy
core-edu:
condition: service_healthy
networks:
- edu-net
- edu-shared
4. 下游依赖(gRPC 微服务)
4.1 iam 服务(ai06 负责)
v2 核查结果:✅ 全部就绪
iam 已实现 15 个 gRPC RPC,包含 student-bff 需要的全部方法:
| gRPC 方法 | 用途 | 状态 |
|---|---|---|
GetUserInfo |
currentUser Query |
✅ |
GetEffectivePermissions |
currentUser permissions |
✅ |
GetViewports |
currentUser viewport |
✅ |
GetUserProfile |
myProfile Query |
✅ |
UpdateProfile |
updateProfile Mutation |
✅ |
ChangePassword |
changePassword Mutation |
✅ |
4.2 core-edu 服务(ai08 负责)
v2 核查结果:✅ 全部就绪
core-edu 已完成 P3.13,9 Service / 40 RPC 全部就绪(24/24 smoke test 通过):
| gRPC 方法 | 用途 | 状态 |
|---|---|---|
ExamService.GetExam |
examDetail Query |
✅ |
ExamService.SubmitExam |
submitExam Mutation |
✅ |
ExamService.SaveExamDraft |
saveExamDraft Mutation |
✅ |
ExamService.RecordExamViolation |
recordExamViolation Mutation |
✅ |
HomeworkService.GetHomework |
homeworkDetail Query |
✅ |
HomeworkService.SubmitHomework |
submitHomework Mutation |
✅ |
GradeService.ListGradesByStudent |
myGrades Query |
✅ |
GradeService.GetReportCard |
myReportCard Query |
✅ |
ScheduleService.GetScheduleByStudent |
mySchedule Query |
✅ |
AttendanceService.ListAttendanceByStudent |
myAttendance Query |
✅ |
LeaveRequestService.ListLeaveRequestsByStudent |
myLeaveRequests Query |
✅ |
LeaveRequestService.CreateLeaveRequest |
createLeaveRequest Mutation |
✅ |
LeaveRequestService.CancelLeaveRequest |
cancelLeaveRequest Mutation |
✅ |
ClassService.GetClass |
myClasses Query |
✅ |
ClassService.ListStudentsByClass |
myClasses Query |
✅ |
4.3 content 服务(ai09 负责)
v2 核查结果:⚠️ 需确认
student-bff 需要 8 个 content RPC,需 ai09 确认以下 RPC 是否已实现:
| gRPC 方法 | 用途 | 状态 |
|---|---|---|
TextbookService.ListTextbooks |
textbooks Query |
需确认 |
ChapterService.ListChapters |
chapters Query |
需确认 |
KnowledgeGraphService.GetLearningPath |
learningPath Query |
需确认 |
ElectiveService.ListElectiveSelectionsByStudent |
myElectiveSelections Query |
需确认 |
ElectiveService.ListAvailableElectiveCourses |
availableElectiveCourses Query |
需确认 |
ElectiveService.SelectCourse |
selectElectiveCourse Mutation |
需确认 |
ElectiveService.DropCourse |
dropElectiveCourse Mutation |
需确认 |
LessonPlanService.ListLessonPlansByStudent |
myLessonPlans Query |
需确认 |
LessonPlanService.GetLessonPlan |
lessonPlanDetail Query |
需确认 |
CoursePlanService.ListCoursePlansByStudent |
myCoursePlans Query |
需确认 |
CoursePlanService.GetCoursePlan |
coursePlanDetail Query |
需确认 |
4.4 data-ana 服务(ai12 负责)
v2 核查结果:⚠️ 需确认
student-bff 需要 8 个 data-ana RPC,需 ai12 确认以下 RPC 是否已实现:
| gRPC 方法 | 用途 | 状态 |
|---|---|---|
AnalyticsService.GetStudentDashboard |
studentDashboard Query |
需确认 |
AnalyticsService.GetStudentWeakness |
myWeakness Query |
需确认 |
AnalyticsService.GetLearningTrend |
myTrend Query |
需确认 |
AnalyticsService.GetStudentGrowth |
studentGrowth Query |
需确认 |
AnalyticsService.GetAssignmentAnalysis |
assignmentAnalysis Query |
需确认 |
AnalyticsService.GetMasterySummary |
myMasterySummary Query |
需确认 |
AnalyticsService.ListDiagnosticReports |
myDiagnosticReports Query |
需确认 |
AnalyticsService.ListErrorBookItems |
myErrorBook Query |
需确认 |
PracticeService.ListPracticeSessionsByStudent |
myPracticeSessions Query |
需确认 |
PracticeService.StartPracticeSession |
startPracticeSession Mutation |
需确认 |
PracticeService.SubmitPracticeAnswer |
submitPracticeAnswer Mutation |
需确认 |
4.5 msg 服务(ai10 负责)
v2 核查结果:✅ 全部就绪(gRPC + REST 混合)
msg 已实现 13 个 gRPC RPC + 完整 REST API:
| gRPC / REST 方法 | 用途 | 状态 |
|---|---|---|
NotificationService.ListNotifications |
myNotifications Query |
✅ |
NotificationService.MarkAsRead |
markAsRead Mutation |
✅ |
NotificationService.MarkAllAsRead |
markAllAsRead Mutation |
✅ |
NotificationPreferenceService.GetPreferences |
通知偏好查询 | ✅ |
NotificationPreferenceService.UpdatePreferences |
updateNotificationPreference Mutation |
✅ |
REST GET /announcements |
announcements Query |
✅ |
REST GET /announcements/:id |
announcementDetail Query |
✅ |
REST POST /announcements/:id/read |
markAnnouncementRead Mutation |
✅ |
4.6 ai 服务(ai11 负责)
v2 核查结果:⚠️ 需确认
| gRPC 方法 | 用途 | 状态 |
|---|---|---|
ChatService.Chat |
aiChat Query |
需确认 |
ChatService.StreamChat |
aiStream Subscription |
需确认 |
4.7 push-gateway(ai13 负责)
v2 核查结果:✅ 已验证
push-gateway 采用通用事件透传机制,三个事件均已 Docker 验证通过:
ExamExtended✅ExamForceSubmitted✅ExamQuestionReordered✅
4.8 core-edu 事件发布(ai08 待修复)
v2 核查结果:❌ 未实现
ExamExtended / ExamForceSubmitted / ExamQuestionReordered 事件字面量在 core-edu 源码中仍未找到。这三个事件由教师端触发(延长考试/强制收卷/调整题目),需 core-edu 在相应业务操作中通过 Outbox 发布到 Kafka topic edu.exam.events。
影响: 考试实时推送功能不可用(非阻断,student-bff 可降级)。
5. student-bff 需要其他模块配合的工作
5.1 SRE AI(P0 部署阻断)
- 新增
infra/docker-compose.deploy.yml中 student-bff 服务定义(见 §3.2 模板) - 新增
infra/docker-compose.deploy.yml中 student-portal 服务定义 - api-gateway environment 补充
STUDENT_BFF_URL: http://student-bff:3009
5.2 ai09 content 服务(P0 功能阻断)
确认并实现以下 RPC(如尚未实现):
- ElectiveService 4 RPC(ListElectiveSelectionsByStudent / ListAvailableElectiveCourses / SelectCourse / DropCourse)
- LessonPlanService 2 RPC(ListLessonPlansByStudent / GetLessonPlan)
- CoursePlanService 2 RPC(ListCoursePlansByStudent / GetCoursePlan)
5.3 ai12 data-ana 服务(P0 功能阻断)
确认并实现以下 RPC(如尚未实现):
- AnalyticsService 8 RPC(GetStudentDashboard / GetStudentWeakness / GetLearningTrend / GetStudentGrowth / GetAssignmentAnalysis / GetMasterySummary / ListDiagnosticReports / ListErrorBookItems)
- PracticeService 3 RPC(ListPracticeSessionsByStudent / StartPracticeSession / SubmitPracticeAnswer)
5.4 ai11 ai 服务(P1 可降级)
确认并实现以下 RPC(如尚未实现):
- ChatService.Chat(同步 AI 答疑)
- ChatService.StreamChat(SSE 流式 AI 答疑)
5.5 ai08 core-edu 服务(P1 事件发布)
实现以下 Kafka 事件发布:
ExamExtended(延长考试时间时发布)ExamForceSubmitted(强制收卷时发布)ExamQuestionReordered(调整题目顺序时发布)
发布到 topic edu.exam.events,student-bff EventSubscriber 消费后转发到 push-gateway。
6. 联调就绪状态
student-portal ──✅──> api-gateway ──✅──> student-bff ──✅──> [60 操作全部注册]
│
├──✅──> core-edu (40 RPC 就绪)
├──✅──> iam (15 RPC 就绪)
├──✅──> msg (13 RPC + REST 就绪)
├──⚠️──> content (需确认)
├──⚠️──> data-ana (需确认)
├──⚠️──> ai (需确认)
└──❌──> docker-compose 未配置
结论: student-bff 自身已完全就绪(v2 全部 P0/P1 已修复并验证)。待 SRE AI 配置 docker-compose + content/data-ana/ai 服务确认 RPC 后,可进行端到端联调。
7. 已知限制
| # | 限制 | 说明 |
|---|---|---|
| 1 | Dockerfile 使用 --filter @edu/student-bff... |
过滤掉 scripts/arch-scan 的 better-sqlite3 原生编译依赖,避免 alpine 缺少 build-essential |
| 2 | Dockerfile 需先构建 shared-ts | student-bff 运行时依赖 @edu/shared-ts/bff 的 dist 产物,Dockerfile 已包含 shared-ts 构建步骤 |
| 3 | shared-ts pino 需 namespace import | pino 在 NodeNext + ESM 下 default import 丢失 callable 签名,已通过 namespace import 修复 |
| 4 | Kafka 未启动时 EventSubscriber 软失败 | 服务正常启动,但实时事件推送(通知/AI 流式响应)不工作 |
| 5 | 下游 gRPC 未就绪时进入降级模式 | 所有 Query 返回 degraded=true + 空数据;所有 Mutation 返回 success=false + BAD_GATEWAY |
| 6 | DEV_MODE=true 时跳过 B4 越权校验 | 生产环境必须 DEV_MODE=false,由 api-gateway 注入 x-user-id header |
本文件由 ai04 维护。student-bff v2 全部工作已完成,待下游服务确认 + SRE 部署配置后可联调。