Files
NextEdu/bugs/back_bug_v2.md
SpecialX 978d9a8309
Some checks failed
Security / deep-security-scan (push) Failing after 20m5s
DR Drill / dr-drill (push) Failing after 1m31s
CI / scheduled-backup (push) Failing after 1m31s
CI / backup-verify (push) Has been skipped
CI / weekly-dr-drill (push) Failing after 0s
CI / build-deploy (push) Has been cancelled
CI / security-scan (push) Has been cancelled
feat: 新增备课模块并修复全模块 P0/P1/P2 缺陷
主要变更:

- 新增 lesson-preparation 模块: 备课编辑器、节点编辑、AI 建议、知识点选择、版本历史、作业发布

- 新增 shared 通用组件: charts/question-bank-filters/schedule-list/ui (chip-nav/filter-bar/page-header/stat-card/stat-item)

- 新增 student/admin 端 loading.tsx 与 error.tsx, 优化加载与错误态体验

- 新增 teacher/lesson-plans 页面 (列表/新建/编辑)

- 新增 drizzle 迁移 0002_tiny_lionheart 及 snapshot

- 新增 textbooks/schema.ts 与 exams/utils/normalize-structure.ts

- 修复 Tiptap v3 SSR hydration 崩溃 (rich-text-block immediatelyRender: false)

- 重构多模块 data-access/actions/组件, 修复权限校验与类型规范

- 同步架构文档 004/005 反映新增模块、导出、依赖关系

- 归档 bugs/* 测试报告与 e2e 测试脚本 (admin/parent/student/teacher web_test)
2026-06-22 01:06:16 +08:00

37 KiB
Raw Blame History

后端模块规范核查报告 v2

核查日期2026-06-18 核查范围:src/modules/ 下所有后端 .ts 文件 核查依据:

  • .trae/rules/project_rules.md 项目规则
  • docs/standards/coding-standards.md 编码规范
  • docs/architecture/004_architecture_impact_map.md 架构影响地图
  • Vercel React Best Practices 性能优化规则
  • v1 报告 bugs/back_bug.md(对照修复状态)

本报告相比 v1 的核心变化:

  • 对每个问题标注 修复状态(已修复/未修复/部分修复/新问题)
  • 汇总 v1→v2 的修复进度
  • 列出 v2 新发现的问题

目录


一、v1→v2 修复进度总览

1.1 整体修复率

指标 v1 问题数 已修复 部分修复 未修复 修复率
数量 129 90 12 27 70% 已修复 + 9% 部分修复
P0 14 14 0 0 100%
P1 60 39 7 14 65% + 12%
P2 55 37 5 13 67% + 9%

1.2 按模块修复率

模块 v1 问题数 已修复 部分修复 未修复 修复率
homework 6 6 0 0 100%
parent 3 3 0 0 100%
proctoring 9 9 0 0 100%
settings 9 9 0 0 100%
dashboard 0 - - - 标杆模块
grades 8 7 1 0 88%
questions 5 4 0 1 80%
users 7 6 0 1 86%
exams 7 5 1 1 71%
messaging 7 5 0 2 71%
notifications 7 5 0 2 71%
audit 5 2 0 3 40%
textbooks 5 2 1 2 40%
classes 10 7 2 1 70%
announcements 6 5 1 0 83%
school 3 2 0 1 67%
scheduling 6 5 1 0 83%
attendance 1 1 0 0 100%
course-plans 3 1 1 1 33%
elective 7 6 1 0 86%
diagnostic 8 7 0 1 88%
files 5 3 1 1 60%
layout 2 0 0 2 0%

1.3 P0 问题修复情况(全部已修复)

编号 v1 P0 问题 修复状态
P0-1 exams/data-access.ts persistAiGeneratedExamDraft 直写 questions 表 已修复:改用 createQuestionWithRelations
P0-2 exams/data-access.ts getExams 等直查 classes 表 已修复:改用 getClassGradeIdsByClassIds
P0-3 questions/schema.ts z.any() 已修复:改为 z.unknown()
P0-4 questions/actions.ts 未返回 ActionState 已修复:包装为 ActionState
P0-5 textbooks 无 Zod 验证 + 14 处 as 断言 ⚠️ 部分修复as 断言已清理,但 Zod 验证仍未添加
P0-6 grades N+1 查询 已修复:改为 inArray 批量查询 + Map 分组
P0-7 classes 跨模块直查 homework/exams 表 已修复:改用 homework/data-access-classes
P0-8 school actions 层直接 DB 操作 已修复DB 操作下沉到 data-access
P0-9 proctoring actions 层直接 DB 操作 已修复:下沉到 data-access
P0-10 messaging↔notifications 循环依赖 已修复:表所有权移交 notifications
P0-11 notifications/in-app-channel.ts 非法 as 断言 已修复:新增 mapPayloadTypeToNotificationType
P0-12 users 硬编码弱密码 "123456" 已修复:改用 randomBytes 生成
P0-13 users/updateUserProfile 绕过权限 已修复:改用 requirePermission + Zod + ActionState
P0-14 scheduling 4 个函数缺返回类型 已修复:已添加返回类型标注

二、v2 当前问题汇总

2.1 按严重程度统计v2 当前状态)

严重程度 未修复 v1 问题 部分修复 v1 问题 v2 新发现问题 合计
P0 0 1textbooks Zod 0 1
P1 14 7 16 37
P2 13 5 25 43
合计 27 12 41 80

2.2 按问题类别统计v2 当前状态)

问题类别 数量 主要分布
架构违规 8 跨模块直查 DBexams→school、questions→textbooks、classes→scheduling、messaging→classes、elective→school/users
TS 规范 35 as 断言、缺返回类型标注、隐式 any[]、非空断言
Server Action 规范 6 textbooks 无 Zod、notifications 无 Zod、school 用 parse 非 safeParse、course-plans 缺 revalidatePath
性能 15 串行查询未并行化、循环内串行 await、未用 React.cache()、隐式 any[]
代码质量 12 try-catch 吞错误、重复 try/catch、死代码、重复代码
命名规范 3 布尔变量前缀、函数命名不一致
数据一致性 4 elective selectCourse/dropCourse 缺事务
文件行数 2 exams/ai-pipeline.ts 916 行、classes/data-access.ts 866 行

三、仍需优先修复的问题

3.1 P0 级别(立即修复)

P0-1textbooks 模块仍无 Zod 验证v1 未修复)

  • 文件src/modules/textbooks/actions.ts
  • 行号54-281所有 Action
  • 问题v1 报告的 P0 问题"actions.ts 完全无 Zod 验证"未修复。所有 Action 仍使用手动 if 校验textbooks 模块甚至没有 schema.ts 文件
  • 修复建议:新建 textbooks/schema.ts,定义 CreateTextbookSchemaUpdateTextbookSchemaCreateChapterSchemaCreateKnowledgePointSchema 等 Zod schema所有 Action 改用 schema.safeParse()

3.2 P1 级别(尽快修复)

P1-1exams/data-access.ts 直接查询 school 模块表v1 未修复)

  • 文件src/modules/exams/data-access.ts
  • 行号2, 208-228, 519-524, 529-534
  • 问题resolveSubjectGradeNamesgetExamSubjectsgetExamGrades 仍直接查询 subjects/gradesschool 模块)
  • 修复建议:在 school 模块暴露 getGradeOptions()getSubjectNameById(id)getGradeNameById(id) 接口

P1-2questions/data-access.ts 直接查询 textbooks 模块表v1 未修复)

  • 文件src/modules/questions/data-access.ts
  • 行号4, 266-299
  • 问题getKnowledgePointOptions 仍直接 LEFT JOIN 查询 knowledgePointschapterstextbooks 三张表
  • 修复建议:在 textbooks 模块暴露 getKnowledgePointOptionsForQuestions() 接口

P1-3classes/data-access-schedule.ts 直接查询 classSchedule 表v1 未修复)

  • 文件src/modules/classes/data-access-schedule.ts
  • 行号7-11, 31-46, 73-86
  • 问题:仍直接导入并查询 classSchedulescheduling 模块的表)
  • 修复建议:在 scheduling 模块暴露只读查询函数 getClassScheduleByClassIds

P1-4messaging/data-access.ts getRecipients 直接 JOIN 跨模块表v1 未修复)

  • 文件src/modules/messaging/data-access.ts
  • 行号26-27, 173-188
  • 问题getRecipients 直接 import 并 JOIN classEnrollmentsclasses
  • 修复建议:通过 classes 模块暴露 getStudentIdsByClassIdsgetStudentIdsByGradeIds 接口

P1-5notifications/actions.ts 参数未用 Zod 验证v1 未修复)

  • 文件src/modules/notifications/actions.ts
  • 行号28-50, 60-110
  • 问题sendNotificationActionsendClassNotificationAction 仅使用 TypeScript 类型标注和手动 if 检查
  • 修复建议:新增 NotificationPayloadSchemaClassNotificationSchema

P1-6textbooks/actions.ts 本地定义 ActionState 类型v1 未修复)

  • 文件src/modules/textbooks/actions.ts
  • 行号46-50
  • 问题:仍在本地定义 ActionState 类型,而非从 @/shared/types/action-state 导入
  • 修复建议:删除本地定义,改为 import type { ActionState } from "@/shared/types/action-state"

P1-7elective/data-access.ts 跨模块直查v2 新发现)

  • 文件src/modules/elective/data-access.ts
  • 行号77-106buildCourseSelect、231-242getSubjectOptions
  • 问题buildCourseSelect 直接 leftJoin(users/subjects/grades);本地 getSubjectOptions 直查 subjects 表且与 school 模块重复
  • 修复建议:移除 join改为先查主表再用 getUserNamesByIds/getSubjectOptions/getGradeOptions 批量解析;删除本地 getSubjectOptions 改用 school 模块

P1-8elective selectCourse/dropCourse 缺事务v2 新发现)

  • 文件src/modules/elective/data-access-operations.ts
  • 行号97-172selectCourse、174-241dropCourse
  • 问题FCFS 模式下 update + insert 两步无事务包裹dropCourse 最多 5 个连续写操作无事务
  • 修复建议:用 db.transaction 包裹所有写操作

P1-9classes/actions.ts as 断言v2 新发现)

  • 文件src/modules/classes/actions.ts
  • 行号47, 521, 565
  • 问题v as ClassSubjectweekday as 1|2|3|4|5|6|7 使用 as 断言
  • 修复建议:在 schema.ts 中使用 Zod transform 使解析后直接产出目标类型

P1-10school/actions.ts 使用 .parse() 而非 .safeParse()v2 新发现)

  • 文件src/modules/school/actions.ts
  • 行号33, 60, 98, 129, 171, 202, 256, 289
  • 问题:所有 action 使用 Schema.parse() 而非 safeParse(),验证失败抛 ZodError无法返回结构化 fieldErrors
  • 修复建议:改用 safeParse(),失败时返回 { success: false, errors: parsed.error.flatten().fieldErrors }

P1-11多个模块函数缺返回类型标注v2 新发现 + v1 部分未修复)

模块 文件 函数
classes data-access.ts:53,60,93,95,100,107 isDuplicateInvitationCodeError, generateInvitationCode, normalizeSortText, parseFirstInt, compareGradeLabel, compareClassLike
school data-access.ts:24 toIso
attendance data-access.ts:70 resolveRecorderNames
exams ai-pipeline.ts:68,177,309,453,480,499,571,712 sanitizeJsonCandidate, normalizeScores, buildAiMessages, splitStructureItems, mapWithConcurrency, parseQuestionDetail, buildQuestionContent, previewToDraft
exams data-access.ts:269 buildOrderedQuestionsFromStructure
grades data-access.ts:57, data-access-analytics.ts:34 buildScopeClassFilter
textbooks data-access.ts:19,25 normalizeOptional, sortChapters

P1-12files/data-access.ts conditions 隐式 any[]v1 未修复)

  • 文件src/modules/files/data-access.ts
  • 行号201
  • 问题const conditions = [] 无类型注解,推断为 any[]
  • 修复建议:改为 const conditions: SQL[] = []

P1-13course-plans updateCoursePlanItemAction 缺 revalidatePathv1 部分修复)

  • 文件src/modules/course-plans/actions.ts
  • 行号197-234
  • 问题v1 指出的 deleteCoursePlanItemAction 和 toggleCoursePlanItemCompletedAction 已修复,但 updateCoursePlanItemAction 仍缺 revalidatePath
  • 修复建议:在 await updateCoursePlanItem(id, parsed.data) 后添加 revalidatePlanPaths() 调用

3.3 P2 级别(迭代优化)

性能类

模块 文件 问题
grades data-access.ts:273,377,397 3 个查询函数未用 React.cache()
elective data-access.ts:231 getSubjectOptions 未用 cache()
course-plans data-access.ts:302-307 reorderCoursePlanItems 循环内串行 await
diagnostic data-access.ts:119-140 updateMasteryFromSubmission 循环内串行 await
proctoring data-access.ts:271-287 getStudentProctoringStatuses 串行查询未并行化
diagnostic data-access.ts:147-159 getClassMasterySummary 串行查询未并行化
grades export.ts:129 循环内 find O(n) 查找,应改用 Map
school data-access.ts:406-469 isGradeHead/isGradeManager/findGradeIdByHeadAndName 未用 cache()

代码质量类

模块 文件 问题
school data-access.ts:26-206 8 个函数 try-catch 吞错误返回空数组
files data-access.ts 10 处静默 catch 吞错误
classes data-access.ts:371-373, data-access-admin.ts:88-89,244-247, data-access-students.ts:159-160 多处 try-catch 吞错误
course-plans data-access.ts:143-162,166-189,312-323 3 处 try-catch 吞错误
announcements data-access.ts:88-91,119-122 catch 已加 console.error 但仍吞错误
announcements actions.ts:26-230 6 处重复 try/catch 块未抽取公共 helper
diagnostic data-access-reports.ts:22,207-208 void round2 死代码
scheduling data-access.ts:113-114 select 中 requesterName 字段冗余
elective data-access.ts:46-75, data-access-selections.ts:46-74 mapCourseRow 重复定义

TS 规范类

模块 文件 问题
users import-export.ts:14 as 断言未加注释
users import-export.ts:98 conditions 隐式 any[]
messaging data-access.ts:84 conds 隐式 any[]
audit data-access.ts:40,96,161 conditions 隐式 any[]
classes data-access.ts:675 非空断言 !
textbooks data-access.ts:314 非空断言 stack.pop()!
notifications external-sdk.d.ts 多处 any有 eslint-disable 注释)
notifications wechat-channel.ts:106 as 断言未加注释

命名规范类

模块 文件 问题
questions actions.ts:26 createNestedQuestion 命名不一致
settings actions.ts:60-63 getAiProviderSummaries 返回非 ActionState

架构/类型位置类

模块 文件 问题
layout navigation.ts:30-31 permission 字段为 string 而非 Permission 类型
layout navigation.ts:34 Role 类型应迁移至 shared/types
audit actions.ts:63-205 Excel 导出逻辑内联在 actions 层

文件行数类

模块 文件 行数 建议
exams ai-pipeline.ts 916 行 拆分为 prompts/json-parser/schemas/index
classes data-access.ts 866 行 拆分 enrollment 相关函数到 data-access-enrollment.ts

数据一致性/业务逻辑类

模块 文件 问题
elective data-access-operations.ts:139-148 FCFS 并发超卖风险(架构图 P2-15
elective data-access-operations.ts:49 runLottery 使用 Math.random 不可复现(架构图 P2-14
diagnostic data-access-reports.ts:113 班级报告 studentId 字段复用(架构图 P2-16

四、按模块详细核查

4.1 exams 模块

v1 修复情况

v1 问题 修复状态 说明
P0: persistAiGeneratedExamDraft 直写 questions 表 已修复 改用 createQuestionWithRelations
P0: getExams 等直查 classes 表 已修复 改用 getClassGradeIdsByClassIds
P1: 直接查询 subjects/grades 表 未修复 仍直查 school 模块表
P1: actions.ts as 断言 已修复 改用 as unknown + safeParse
P2: import { ActionState } 未用 import type 已修复 已改为 import type
P2: ai-pipeline.ts 912 行超长 未修复 当前 916 行
P2: data-access.ts as string[] 断言 已修复 改用 getStringArray 类型守卫

v2 新发现问题

严重程度 文件 问题
P2 ai-pipeline.ts:68,177,309,453,480,499,571,712 8 个函数缺少显式返回类型标注
P2 data-access.ts:269 buildOrderedQuestionsFromStructure 缺返回类型

4.2 homework 模块

v1 修复情况100% 修复)

v1 问题 修复状态 说明
P1: data-access.ts 直查 exams/classEnrollments/subjects/users 表 已修复 改用跨模块 data-access 接口
P1: data-access-write.ts 直查 classes/classEnrollments/classSubjectTeachers/exams 表 已修复 改用跨模块接口
P1: stats-service.ts 直查 classEnrollments/classes/exams/users 表 已修复 改用跨模块接口
P1: data-access.ts:39 as 断言 已修复 改用 isHomeworkQuestionContent 类型守卫
P2: data-access-write.ts 循环内串行 await 未用事务 已修复 已用 db.transaction 包裹
P2: data-access.ts 使用 auth() 而非 getAuthContext() 已修复 不再使用 auth()

v2 无新发现问题,模块状态良好。

4.3 questions 模块

v1 修复情况

v1 问题 修复状态 说明
P0: schema.ts z.any() 已修复 改为 z.unknown()
P0: actions.ts 未返回 ActionState 已修复 包装为 ActionState
P1: data-access.ts 直查 textbooks 模块表 未修复 仍直查 knowledgePoints/chapters/textbooks
P1: actions.ts import type 已修复 已改为 import type
P2: createNestedQuestion 命名不一致 未修复 仍为 createNestedQuestion

v2 无新发现问题。

4.4 grades 模块

v1 修复情况

v1 问题 修复状态 说明
P0: N+1 查询 已修复 改为 inArray 批量查询 + Map 分组
P1: 跨模块直查 已修复 改用跨模块 data-access 接口
P1: 动态 import 已修复 改为静态 import
P1: 除零 bug 已修复 添加 if (fullScores[i] <= 0) continue
P2: 未用 React.cache() ⚠️ 部分修复 4 个函数已用 cache()3 个仍未用
P2: includes O(n) 查找 已修复 改用 Set.has()
P2: 重复 filter 已修复 改用单次 reduce

v2 新发现问题

严重程度 文件 问题
P2 data-access.ts:57, data-access-analytics.ts:34 buildScopeClassFilter 缺返回类型
P2 export.ts:129 循环内 find O(n) 查找,应改用 Map

4.5 textbooks 模块

v1 修复情况

v1 问题 修复状态 说明
P0: 无 Zod 验证 未修复 仍无 schema.ts所有 Action 手动校验
P0: 14 处 as 断言 已修复 已清理所有 as 断言
P1: 本地定义 ActionState 未修复 仍在本地定义
P1: import type 已修复 已改为 import type
P1: data-access.ts as 断言 已修复 改用 isChapterNode 类型守卫
P2: 非空断言 ⚠️ 部分修复 原位置已修复,但 314 行仍有 stack.pop()!

v2 新发现问题

严重程度 文件 问题
P2 data-access.ts:19,25 normalizeOptional、sortChapters 缺返回类型

4.6 classes 模块

v1 修复情况

v1 问题 修复状态 说明
P0: actions.ts 直接 DB 操作 已修复 已下沉到 data-access
P0: getTeacherClasses 混入 homework/scheduling ⚠️ 部分修复 架构合规,但职责仍混合
P0: data-access-stats.ts 直查 homework/exams 已修复 改用 homework/data-access-classes
P0: data-access-students.ts 直查 homework/exams 已修复 同上
P1: 无 schema.ts 已修复 已创建 schema.ts
P1: as 断言 已修复 原位置已清理
P1: 箭头函数缺返回类型 ⚠️ 部分修复 6 个同步箭头函数仍缺
P1: data-access-schedule.ts 直查 classSchedule 未修复 仍直查 scheduling 模块表
P2: 不可达代码 已修复 已删除
P2: 串行查询未并行化 已修复 已用 Promise.all

v2 新发现问题

严重程度 文件 问题
P1 actions.ts:47,521,565 as 断言v as ClassSubject、weekday as 1|2|...|7
P2 data-access.ts:675 非空断言 !
P2 data-access.ts:371-373 等 多处 try-catch 吞错误
P2 data-access.ts 文件 866 行超 800 行建议上限

4.7 school 模块

v1 修复情况

v1 问题 修复状态 说明
P0: actions 层直接 DB 操作 已修复 DB 操作下沉到 data-access
P2: try-catch 吞错误 未修复 8 个函数仍吞错误
P2: logAudit 阻塞响应 已修复 已用 after() 异步执行

v2 新发现问题

严重程度 文件 问题
P1 actions.ts:33,60,98,129,171,202,256,289 使用 .parse() 而非 .safeParse()
P1 data-access.ts:24 toIso 缺返回类型
P2 data-access.ts:406-469 3 个跨模块查询函数未用 cache()

4.8 scheduling 模块

v1 修复情况

v1 问题 修复状态 说明
P0: actions.ts 直查 users 表 已修复 改用 getUserNamesByIds
P0: 4 个函数缺返回类型 已修复 已添加返回类型
P1: 非空断言3 处) 已修复 改用显式判空
P2: auto-scheduler.ts 310 行 ⚠️ 部分修复 311 行,多个函数超 40 行

v2 新发现问题

严重程度 文件 问题
P2 data-access.ts:113-114 select 中 requesterName 字段冗余
P2 data-access.ts:135-145 用户查询应使用 inArray 替代 or(...map(eq))

4.9 attendance 模块

v1 修复情况

v1 问题 修复状态 说明
P1: Record<string, unknown> 丢失类型安全 已修复 改用 Partial<typeof attendanceRecords.$inferSelect>

v2 新发现问题

严重程度 文件 问题
P1 data-access.ts:70 resolveRecorderNames 缺返回类型

4.10 course-plans 模块

v1 修复情况

v1 问题 修复状态 说明
P1: 缺 revalidatePath ⚠️ 部分修复 delete/toggle 已修复update 仍缺
P1: as 断言 已修复 已清理
P2: 循环内串行 await 未修复 仍串行

v2 新发现问题

严重程度 文件 问题
P2 data-access.ts:143-162,166-189,312-323 3 处 try-catch 吞错误

4.11 users 模块

v1 修复情况

v1 问题 修复状态 说明
P0: updateUserProfile 绕过权限 已修复 改用 requirePermission + Zod + ActionState
P0: 硬编码弱密码 已修复 改用 randomBytes 生成
P1: actions 层直接 DB 操作 已修复 下沉到 data-access
P1: batchImportUsers 无事务 已修复 每个用户创建包裹在 db.transaction
P2: rolePriority 命名 已修复 已移除,改用 resolvePrimaryRole
P2: normalizeRoleName 重复 已修复 改用 shared
P2: conditions 隐式 any[] 未修复 仍为 const conditions = []

v2 新发现问题

严重程度 文件 问题
P2 import-export.ts:14 as 断言未加注释

4.12 messaging 模块

v1 修复情况

v1 问题 修复状态 说明
P0: 循环依赖 已修复 表所有权移交 notifications
P1: 5 个 Action 用 requireAuth 已修复 改用 requirePermission
P1: getRecipients 直查跨模块表 未修复 仍 JOIN classEnrollments/classes
P1: 无 Zod 验证 已修复 已用 UpdateNotificationPreferencesSchema
P2: 非空断言 已修复 改用 ?? null
P2: 缺返回类型 已修复 已添加

v2 新发现问题

严重程度 文件 问题
P2 data-access.ts:84 conds 隐式 any[]

4.13 notifications 模块

v1 修复情况

v1 问题 修复状态 说明
P0: 反向依赖 messaging 已修复 表所有权归 notifications
P0: in-app-channel 动态 import messaging 已修复 改为静态 import
P0: 非法 as 断言 已修复 新增 mapPayloadTypeToNotificationType
P1: actions.ts 直查 classes 表 已修复 改用 classes data-access 函数
P1: 参数无 Zod 验证 未修复 仍用手动 if 检查
P2: 缺返回类型 已修复 已添加
P2: external-sdk.d.ts any 未修复 有 eslint-disable 注释

v2 新发现问题

严重程度 文件 问题
P2 wechat-channel.ts:106 as 断言未加注释

4.14 parent 模块

v1 修复情况100% 修复)

v1 问题 修复状态 说明
P1: getChildBasicInfo 直查跨模块表 已修复 改用各模块 data-access 函数
P2: as 断言 已修复 改用 isWeekday 类型守卫
P2: 串行查询 已修复 改用 Promise.all

v2 无新发现问题,模块状态良好,是跨模块通信的标杆实现。

4.15 audit 模块

v1 修复情况

v1 问题 修复状态 说明
P1: 导出函数数据截断 已修复 改用分页循环拉取全部数据
P2: as 断言 已修复 已清理
P2: Excel 导出逻辑内联 未修复 仍内联在 actions
P2: conditions 隐式 any[] 未修复 3 处仍为 const conditions = []

4.16 elective 模块

v1 修复情况

v1 问题 修复状态 说明
P1: data-access-selections.ts 直查 classes 表 已修复 改用跨模块接口
P1: runLottery 无事务 已修复 已用 db.transaction
P1: 循环内逐条 await 已修复 改用 inArray 批量更新
P1: as 断言 已修复 已清理
P2: 串行查询未并行化 已修复 改用 Promise.all
P2: 未用 React.cache() ⚠️ 部分修复 大部分已用getSubjectOptions 仍未用

v2 新发现问题

严重程度 文件 问题
P1 data-access.ts:77-106 buildCourseSelect 跨模块 join users/subjects/grades
P1 data-access.ts:231-242 本地 getSubjectOptions 直查 subjects 表且与 school 重复
P1 data-access-operations.ts:97-172 selectCourse 缺事务包裹
P1 data-access-operations.ts:174-241 dropCourse 缺事务包裹
P2 data-access-operations.ts:139-148 FCFS 并发超卖风险
P2 data-access-operations.ts:49 runLottery 使用 Math.random 不可复现
P2 data-access.ts:46-75, data-access-selections.ts:46-74 mapCourseRow 重复定义

4.17 proctoring 模块

v1 修复情况100% 修复)

v1 问题 修复状态 说明
P0: actions.ts 直接 DB 操作 已修复 下沉到 data-access
P1: import type 已修复 已改为 import type
P1: as 断言 已修复 改用类型守卫
P1: requireAuth 已修复 改用 requirePermission
P1: 直查 exams/examSubmissions 表 已修复 改用跨模块函数
P1: 多处 as 断言 已修复 改用 toExamMode/isSubmissionStatus
P2: 未调用 revalidatePath 已修复 已添加
P2: 串行查询 已修复 改用 Promise.all
P2: 重复 filter 已修复 改用单次循环

v2 新发现问题

严重程度 文件 问题
P2 data-access.ts:271-287 getStudentProctoringStatuses 串行查询未并行化

4.18 diagnostic 模块

v1 修复情况

v1 问题 修复状态 说明
P1: 4 个 Action 无 Zod 已修复 新增 schema.ts6 个 Action 全用 Zod
P1: 直查跨模块表 已修复 改用跨模块 data-access
P1: as 断言 已修复 改用 isStringArray 类型守卫
P2: 循环内 find 已修复 改用 Map
P2: 循环内串行 await 未修复 updateMasteryFromSubmission 仍串行
P2: 重复 filter 已修复 改用单次循环
P2: 动态 import 已修复 改为静态 import
P2: void round2 死代码 未修复 仍存在
P2: 未用 React.cache() 已修复 全部用 cache() 包装

v2 新发现问题

严重程度 文件 问题
P2 data-access.ts:147-159 getClassMasterySummary 串行查询未并行化

4.19 dashboard 模块

v1 无违规问题v2 仍为标杆模块。 正确使用 Promise.all 并行获取多模块数据,正确使用 cache(),正确通过各模块 data-access 通信。

4.20 files 模块

v1 修复情况

v1 问题 修复状态 说明
P1: conditions 隐式 any[] 未修复 仍为 const conditions = []
P1: or(...)! 非空断言 已修复 改用显式判断
P2: 循环内串行 await ⚠️ 部分修复 主路径已批量删除catch 回退仍串行
P2: 9 处静默 catch 未修复 实际 10 处
P2: 未用 React.cache() 已修复 全部用 cache() 包装

4.21 announcements 模块

v1 修复情况

v1 问题 修复状态 说明
P1: as string 断言 已修复 新增 toIso/toIsoRequired 工具函数
P2: 冗余 as 断言 已修复 已清理
P2: catch 吞错误 ⚠️ 部分修复 已加 console.error 但仍吞错误
P2: 类型重复定义 已修复 已修复
P2: requireAuth 已修复 改用 requirePermission
P2: 重复 try/catch 未修复 6 处仍重复

4.22 settings 模块

v1 修复情况100% 修复)

v1 问题 修复状态 说明
P1: 无 data-access.ts 已修复 新建 data-access.ts
P1: actions-password.ts 无 data-access 已修复 DB 操作下沉
P1: 无 Zod 验证 已修复 新增 ChangePasswordSchema
P2: 类型定义位置 已修复 新建 types.ts
P2: 缺返回类型 已修复 已添加
P2: 串行查询 已修复 改用 Promise.all
P2: 布尔命名 已修复 改为 hasDefault/isNextDefault/shouldMakeDefault
P2: requireAuth 已修复 改用 requirePermission
P2: 串行查询 已修复 改用 Promise.all

v2 新发现问题

严重程度 文件 问题
P2 actions.ts:60-63 getAiProviderSummaries 返回非 ActionState

4.23 layout 模块

v1 修复情况0% 修复)

v1 问题 修复状态 说明
P2: permission 字段为 string 未修复 仍为 string
P2: Role 类型位置 未修复 仍在 navigation.ts

五、v2 新发现问题清单

5.1 P1 级别新问题16 个)

编号 模块 文件 问题
N1 elective data-access.ts:77-106 buildCourseSelect 跨模块 join users/subjects/grades
N2 elective data-access.ts:231-242 本地 getSubjectOptions 直查 subjects 表且与 school 重复
N3 elective data-access-operations.ts:97-172 selectCourse 缺事务包裹
N4 elective data-access-operations.ts:174-241 dropCourse 缺事务包裹
N5 classes actions.ts:47,521,565 as 断言v as ClassSubject、weekday as 1|2|...|7
N6 school actions.ts:33 等 使用 .parse() 而非 .safeParse()
N7 school data-access.ts:24 toIso 缺返回类型
N8 attendance data-access.ts:70 resolveRecorderNames 缺返回类型
N9 exams ai-pipeline.ts 8 个函数缺返回类型
N10 exams data-access.ts:269 buildOrderedQuestionsFromStructure 缺返回类型
N11 grades data-access.ts:57, data-access-analytics.ts:34 buildScopeClassFilter 缺返回类型
N12 textbooks data-access.ts:19,25 normalizeOptional、sortChapters 缺返回类型
N13 settings actions.ts:60-63 getAiProviderSummaries 返回非 ActionState
N14 messaging data-access.ts:84 conds 隐式 any[]
N15 users import-export.ts:14 as 断言未加注释
N16 notifications wechat-channel.ts:106 as 断言未加注释

5.2 P2 级别新问题25 个)

编号 模块 文件 问题
N17 classes data-access.ts:675 非空断言 !
N18 classes data-access.ts:371-373 等 多处 try-catch 吞错误
N19 classes data-access.ts 文件 866 行超 800 行建议上限
N20 school data-access.ts:406-469 3 个跨模块查询函数未用 cache()
N21 scheduling data-access.ts:113-114 select 中 requesterName 字段冗余
N22 scheduling data-access.ts:135-145 用户查询应使用 inArray
N23 course-plans data-access.ts:143-162 等 3 处 try-catch 吞错误
N24 grades export.ts:129 循环内 find O(n) 查找
N25 proctoring data-access.ts:271-287 getStudentProctoringStatuses 串行查询
N26 diagnostic data-access.ts:147-159 getClassMasterySummary 串行查询
N27 elective data-access-operations.ts:139-148 FCFS 并发超卖风险
N28 elective data-access-operations.ts:49 runLottery 使用 Math.random
N29 elective data-access.ts:46-75 等 mapCourseRow 重复定义
N30 users import-export.ts:98 conditions 隐式 any[]
N31 audit data-access.ts:40,96,161 conditions 隐式 any[]

六、架构文档同步提醒

根据项目规则"改码必同步图",以下架构图信息需更新:

6.1 需更新的架构文档

文档 需更新内容
docs/architecture/004_architecture_impact_map.md 1. exams/actions.ts 行数v1 记录 691实际 771
2. exams/ai-pipeline.ts 行数v1 记录 857实际 916
3. settings 导出函数列表v1 记录 getAiProvidersAction 等,实际为 getAiProviderSummaries/upsertAiProviderAction/testAiProviderAction
4. P2-11 死代码 void wasPublished 状态(已修复)
5. announcements 依赖 school 模块(仅 components非后端
6. elective 依赖关系需补充 classes/school/users
7. messaging↔notifications 循环依赖已解决
8. classes 跨模块直查 homework/exams 已解决

6.2 需同步的代码变更

本轮修复涉及大量模块结构调整,必须同步更新 004 和 005 架构文档:

  • 新增模块文件classes/schema.ts、settings/data-access.ts、settings/types.ts、diagnostic/schema.ts
  • 新增跨模块接口classes 暴露 getClassGradeIdsByClassIds、getStudentIdsByClassId 等exams 暴露 getExamIdsByGradeIds、getExamWithQuestionsForHomework 等users 暴露 getUserNamesByIds、getUserBasicInfo 等school 暴露 getSubjectOptions、getGradeOptions 等
  • 表所有权迁移messageNotifications、notificationPreferences 表所有权从 messaging 移交至 notifications
  • 权限点新增USER_PROFILE_UPDATE、PASSWORD_SELF_CHANGE 等

七、总体评价与建议

7.1 修复成效

本次 v2 核查显示,项目在 v1 报告后进行了大规模且有成效的修复:

  1. 所有 P0 问题已全部修复14/14包括跨模块直写 DB、循环依赖、硬编码弱密码、N+1 查询等高危问题
  2. P1 问题修复率 65%:剩余 14 个未修复 + 7 个部分修复
  3. 4 个模块达到 100% 修复率homework、parent、proctoring、settings
  4. 架构层面显著改善
    • messaging↔notifications 循环依赖彻底消除
    • 跨模块直查 DB 大幅减少exams、homework、grades、classes、proctoring、diagnostic 等模块已改用 data-access 接口)
    • parent 模块成为跨模块通信的标杆实现

7.2 仍需改进的领域

  1. textbooks 模块P0 问题(无 Zod 验证)仍未修复,是所有模块中唯一未实现输入验证的 Server Action 文件
  2. 跨模块直查残留exams→school、questions→textbooks、classes→scheduling、messaging→classes 仍存在直查
  3. 函数返回类型标注多个模块仍存在箭头函数缺返回类型的问题classes、school、attendance、exams、grades、textbooks
  4. 隐式 any[]const conditions = [] 在 users、messaging、audit、files 等模块普遍存在
  5. 错误处理try-catch 吞错误在 school、files、classes、course-plans 等模块仍普遍存在
  6. elective 模块v2 新发现 selectCourse/dropCourse 缺事务、data-access.ts 跨模块直查等问题

7.3 下一阶段优先修复建议

第一优先级P0/P1 核心问题)

  1. textbooks 模块新建 schema.ts所有 Action 改用 Zod safeParse
  2. textbooks/actions.ts 改用共享 ActionState 类型
  3. exams、questions、classes、messaging 模块消除剩余跨模块直查
  4. elective selectCourse/dropCourse 加事务包裹
  5. school/actions.ts 改用 safeParse
  6. 补齐所有函数返回类型标注

第二优先级P2 系统性优化)

  1. 全项目统一修复 const conditions = [] 隐式 any[](改为 SQL[]
  2. 清理 try-catch 吞错误(至少加 console.error 或向上抛出)
  3. 补齐 React.cache() 包装
  4. 串行查询改用 Promise.all
  5. 同步架构文档

第三优先级(代码质量)

  1. 抽取重复代码mapCourseRow、handleActionError、buildExcelSheet 等)
  2. 清理死代码void round2 等)
  3. 拆分超长文件ai-pipeline.ts、classes/data-access.ts
  4. layout 模块类型规范修复