- 全项目逐文件审查: 4 份审计报告(shared/core-business/management/new-modules) - 重写 004 架构影响地图: 图优先 + 模块依赖图 + 数据流 + 调用链 + 问题分级 - 更新 005 结构化数据: 新增 architectureOverview/moduleDependencyGraph/knownIssues/dbTables 节点 - 更新 006 功能清单: 143 项功能标注实现状态, P0 覆盖率 80%->92% - 更新 007 差距审计: v2->v3, P0 完成 69%->84%, 新增架构技术债章节 - 更新 001 项目概览: 6 角色/54 权限/26 模块/54 表 - 新增 docs/README.md 文档索引 - 归档 11 份过时文档(002x2/003/designx8) 标注 - 更新 work_log
27 KiB
新增模块与其他模块架构审查报告
审查范围:elective / proctoring / diagnostic / notifications / dashboard / messaging / parent / settings / files / auth / layout / student 审查日期:2026-06-17 审查依据:源码全量扫描 + 架构影响地图(004/005) + 差距审计报告(007) 审查目标:识别职责不单一、过耦合、边界模糊、幽灵路由等问题
一、总体评估
| 维度 | 模块数 | 严重问题 | 中等问题 | 轻微问题 | 总体评价 |
|---|---|---|---|---|---|
| 新增模块 | 4 | 3 | 5 | 3 | ⚠️ 职责基本清晰,但存在跨模块耦合与未集成代码 |
| 其他模块 | 8 | 1 | 4 | 3 | ⚠️ dashboard 跨模块直查问题突出 |
| 合计 | 12 | 4 | 9 | 6 | 需重点修复 4 项严重问题 |
严重问题清单(必须修复)
- messaging 与 notifications 边界模糊、双向依赖 — 两个模块都写入
messageNotifications表,notifications 反向依赖 messaging,类型系统不一致 - dashboard/data-access.ts 直查 11 张跨模块表 — 违反模块封装原则
- proctoring/exam-mode-config.tsx 未集成到考试表单 — DB schema 有 examMode 等字段但无 UI 录入入口,组件成为死代码
- proctoring 事件上报存在 Server Action 与 REST API 双通道重复 — 同一逻辑两份代码
二、新增模块审查
2.1 elective 模块(选课管理)
模块结构
| 文件 | 行数 | 职责 |
|---|---|---|
actions.ts |
304 | 11 个 Server Action(CRUD + 选课 + 抽签 + 查询) |
data-access.ts |
242 | 课程 CRUD + 查询 + scope 过滤 |
data-access-operations.ts |
217 | 选课操作(select/drop/lottery) |
data-access-selections.ts |
189 | 选课记录查询 + 学生可用课程查询 |
schema.ts |
132 | Zod 校验 schema |
types.ts |
108 | 类型定义 + 标签常量 |
拆分为 3 个 data-access 文件是否合理?
结论:⚠️ 拆分意图合理,但存在代码重复
- 拆分意图合理:operations(写操作)与 selections(读查询)职责分明,符合"按职责划分"原则
- 代码重复问题:
data-access.ts与data-access-selections.ts重复定义了mapCourseRow和buildCourseSelect两个函数(共约 60 行重复代码)data-access.ts第 47-108 行data-access-selections.ts第 28-88 行- 两份代码完全相同,维护时易产生不一致
建议:
- 抽取共享的
mapCourseRow/buildCourseSelect到data-access.ts并导出,data-access-selections.ts复用 - 或合并
data-access-selections.ts到data-access.ts(文件仅 189 行,合并后仍在 800 行上限内)
权限校验
✅ 全部 Server Action 均使用 requirePermission:
- 管理 Action 使用
ELECTIVE_MANAGE - 选课 Action 使用
ELECTIVE_SELECT - 查询 Action 使用
ELECTIVE_READ - 学生查看他人选课记录有额外 dataScope 校验(actions.ts 第 283-288 行)
其他发现
- ✅ schema.ts 使用 Zod transform 统一处理空字符串转 null,规范
- ⚠️
data-access-operations.ts的runLottery使用Math.random()排序(第 40 行),结果不可复现,建议改用 DB 的ORDER BY RAND()或记录种子 - ⚠️
selectCourse在 FCFS 模式下先查后写(第 119-128 行),存在并发超卖风险,建议加事务或乐观锁
2.2 proctoring 模块(考试监考)
模块结构
| 文件 | 行数 | 职责 |
|---|---|---|
actions.ts |
144 | 2 个 Server Action(上报事件 + 获取面板) |
data-access.ts |
388 | 事件记录 + 查询 + 摘要统计 + 学生状态 |
types.ts |
136 | 类型定义 + 标签常量 + 阈值常量 |
components/anti-cheat-monitor.tsx |
- | 学生端防作弊监控 |
components/exam-mode-config.tsx |
- | 考试模式配置表单(未集成) |
components/proctoring-dashboard.tsx |
- | 教师监考面板 |
职责清晰度
结论:⚠️ 职责基本清晰,但存在 3 个严重问题
严重问题 1:exam-mode-config.tsx 未集成到考试表单(死代码)
- DB schema 已有
examMode/durationMinutes/shuffleQuestions/allowLateStart/antiCheatEnabled字段(schema.ts 第 457-462 行) proctoring/components/exam-mode-config.tsx提供了完整的配置 UI 组件- 但
exams/components/exam-form.tsx并未导入该组件(grep 确认无ExamModeConfig引用) exams/components/exam-mode-selector.tsx是"手动组卷 vs AI 生成"的选择器,与考试模式(homework/timed/proctored)无关,命名易混淆- 结果:创建考试时无法设置监考模式,proctoring 模块的
getExamForProctoring读取的examMode永远是默认值"homework"
建议:将 exam-mode-config.tsx 集成到 exam-form.tsx,或迁移到 exams 模块
严重问题 2:事件上报存在 Server Action 与 REST API 双通道重复
proctoring/actions.ts第 58-105 行:recordProctoringEventAction(Server Action)app/api/proctoring/event/route.ts第 27-90 行:POST handler(REST API)- 两者逻辑完全相同:都校验 submission 归属、调用
recordProctoringEvent AntiCheatMonitor组件使用 Server Action(第 58 行),REST API 路由无调用方
建议:删除未使用的 /api/proctoring/event 路由,或让组件改用 REST API(适用于客户端轮询场景)
中等问题 3:跨模块读取 exams 表
data-access.ts第 326-353 行:getExamForProctoring直接查询exams表- 第 178-185 行:
getExamProctoringSummary直接查询examSubmissions表 - 第 249-256 行:
getStudentProctoringStatuses直接 joinexamSubmissions和users
建议:可接受(监考本质是考试模块的扩展),但应在架构图中标注依赖关系
其他发现
- ✅
recordProctoringEventAction使用requireAuth()而非requirePermission,符合"学生上报自己事件"场景 - ✅
getProctoringDashboardAction使用EXAM_PROCTOR权限 - ✅ 异常阈值
ABNORMAL_EVENT_THRESHOLD = 3提取为常量,便于调整 - ⚠️
actions.ts第 11-13 行直接 importdb和examSubmissions,应在 data-access 层封装 submission 校验逻辑
2.3 diagnostic 模块(学情诊断)
模块结构
| 文件 | 行数 | 职责 |
|---|---|---|
actions.ts |
148 | 6 个 Server Action(生成/发布/删除/查询报告) |
data-access.ts |
254 | 知识点掌握度查询 + 从提交更新掌握度 |
data-access-reports.ts |
202 | 诊断报告 CRUD |
types.ts |
97 | 类型定义 |
components/ |
4 个 | 学生/班级诊断视图 + 雷达图 + 报告列表 |
与 grades 模块的边界
结论:✅ 无职责重叠,但存在跨模块耦合
- grades 模块:管理
gradeRecords表(分数记录),维度是"学生-班级-科目-考试" - diagnostic 模块:管理
knowledgePointMastery表(知识点掌握度),维度是"学生-知识点" - 两者数据来源不同:grades 是教师录入的分数,diagnostic 是从
submissionAnswers推导的正确率 - 无任何代码重叠:grep 确认 grades 模块无
knowledgePoint/mastery/diagnostic关键字
中等问题 1:data-access.ts 跨模块直查 4 张表
- 第 87-92 行:查询
examSubmissions表(属 exams 模块) - 第 95-101 行:查询
submissionAnswers表(属 exams/homework 模块) - 第 106-112 行:查询
questionsToKnowledgePoints表(属 questions 模块) - 第 150-158 行:查询
classEnrollments+classes+users表(属 classes 模块)
updateMasteryFromSubmission 函数(第 87-147 行)直接读取提交答案和题目-知识点关联,将 diagnostic 模块与 exams/homework/questions 模块紧耦合。
建议:
- 短期:在架构图中标注此依赖关系
- 长期:由 exams/homework 模块在提交评分后主动调用 diagnostic 模块的更新接口(事件驱动)
轻微问题 2:data-access-reports.ts 有未使用代码
- 第 20 行定义
round2函数 - 第 201 行
void round2仅为消除 lint 警告 - 建议:删除未使用的
round2函数
轻微问题 3:班级报告字段复用不当
data-access-reports.ts第 107 行:studentId: generatedBy— 班级报告将生成者 ID 存入studentId字段- 注释说明"schema 要求 NOT NULL",但这是 schema 设计缺陷的 workaround
- 建议:修改
learningDiagnosticReportsschema,将studentId改为可空,或增加classId字段
权限校验
✅ 全部 Action 使用 DIAGNOSTIC_MANAGE 或 DIAGNOSTIC_READ 权限
2.4 notifications 模块(通知分发)
模块结构
| 文件 | 行数 | 职责 |
|---|---|---|
actions.ts |
119 | 2 个 Server Action(单发 + 班级群发) |
data-access.ts |
86 | 用户偏好 + 联系方式 + 日志 |
dispatcher.ts |
152 | 渠道选择 + 并行分发 |
types.ts |
70 | 通知负载 + 渠道配置类型 |
index.ts |
38 | 对外导出入口 |
channels/ |
5 个 | SMS/Email/WeChat/InApp 渠道实现 |
严重问题 1:与 messaging 模块双向依赖、边界模糊
详见下文"三、messaging vs notifications 边界分析"。
中等问题 2:sendClassNotificationAction 跨模块直查
actions.ts第 83-96 行:直接查询classes和classEnrollments表- 应通过 classes 模块的 data-access 获取班级学生列表
建议:调用 classes 模块的 data-access 函数获取学生 ID 列表
中等问题 3:发送日志仅 console 输出
data-access.ts第 71-77 行:logNotificationSend使用console.info- 代码注释承认"当前项目无 notification_logs 表"
- 影响:无法查询历史发送记录、无法统计发送成功率、无法排查发送失败
建议:新增 notification_logs 表,记录 channel/userId/payload/success/error/sentAt
轻微问题 4:复用 MESSAGE_SEND 权限
actions.ts第 34、67 行:使用Permissions.MESSAGE_SEND- 代码注释说明"项目无独立 NOTIFICATION_SEND 权限点"
- 影响:无法单独控制"谁能发通知"vs"谁能发私信"
建议:新增 NOTIFICATION_SEND 权限点,或确认复用是设计意图
设计亮点
- ✅ 渠道抽象优秀:
NotificationChannelSender接口 + 工厂函数,新增渠道只需实现接口 - ✅ Mock 实现完善:SMS/Email/WeChat 均有 Mock 实现,开发环境零配置可用
- ✅ 动态 import 第三方 SDK(阿里云/腾讯云/nodemailer),避免增加构建体积
- ✅ 渠道选择逻辑清晰(dispatcher.ts 第 59-95 行)
三、messaging vs notifications 边界分析(重点)
3.1 现状对比
| 维度 | messaging 模块 | notifications 模块 |
|---|---|---|
| 核心职责 | 站内私信 + 站内通知列表 | 多渠道通知分发 |
| 管理的表 | messages + messageNotifications + notificationPreferences |
无独有表(借用 messaging 的表) |
| 写入 messageNotifications | ✅ 直接写(createNotification) |
✅ 通过 in-app 渠道写 |
| 通知类型枚举 | NotificationType = "message" | "announcement" | "homework" | "grade" |
NotificationPayload.type = "info" | "warning" | "error" | "success" |
| UI 组件 | message-list / message-detail / message-compose / notification-dropdown / notification-list | 无 UI 组件 |
| 偏好管理 | ✅ notification-preferences.ts |
❌ 借用 messaging 的 |
| 渠道支持 | 仅站内 | 站内 + SMS + Email + WeChat |
3.2 严重问题:双向依赖与职责重叠
问题 1:notifications 反向依赖 messaging
notifications/data-access.ts
→ import { getNotificationPreferences } from "@/modules/messaging/notification-preferences"
→ import type { NotificationPreferences } from "@/modules/messaging/types"
notifications/channels/in-app-channel.ts
→ import { createNotification } from "@/modules/messaging/data-access"
notifications 模块不拥有任何数据,全部依赖 messaging 模块。这违背了"模块应拥有自己的数据"原则。
问题 2:messaging 绕过 notifications 直接写通知
messaging/actions.ts 第 66-72 行:
// Notify the receiver about the new message
await createNotification({
userId: input.receiverId,
type: "message",
title: input.subject ? `New message: ${input.subject}` : "New message",
content: input.content.slice(0, 200),
link: `/messages/${id}`,
})
这直接调用 messaging/data-access.ts 的 createNotification,完全绕过 notifications 模块的 dispatcher,导致:
- 用户设置的 SMS/Email 偏好被忽略
- 新消息不会触发邮件/短信提醒
- notifications 模块的多渠道能力形同虚设
问题 3:类型系统不一致
messaging/types.ts第 23 行:NotificationType = "message" | "announcement" | "homework" | "grade"(按业务类别)notifications/types.ts第 20 行:type: "info" | "warning" | "error" | "success"(按严重级别)in-app-channel.ts第 49 行:type: payload.type as "message" | "announcement" | "homework" | "grade"— 强制类型转换,运行时可能写入非法值
DB schema 中 messageNotifications.type 为 varchar(128),虽然不会报错,但语义混乱。
问题 4:notification-preferences 归属不清
notificationPreferences表的 data-access 在 messaging 模块- 但 notifications 模块的 dispatcher 依赖此偏好决定渠道
- settings 模块的
notification-preferences-form.tsx调用messaging/actions.ts的updateNotificationPreferencesAction - 三个模块都在操作同一份数据,职责归属不清
3.3 建议方案
方案 A(推荐):notifications 吞并 messaging 的通知部分
- 将
messageNotifications表和notificationPreferences表的所有权移交给 notifications 模块 - messaging 模块仅保留
messages表(私信) - messaging 的
sendMessageAction改为调用notifications.sendNotification - messaging 的 UI 组件(notification-dropdown / notification-list)迁移到 notifications 模块
- 统一
NotificationType枚举,支持业务类别 + 严重级别两个维度
方案 B:保持现状,明确依赖方向
- 在架构图中标注 notifications → messaging 的单向依赖
- messaging 不再直接调用
createNotification,改为调用notifications.sendNotification - 消除双向依赖,但 notifications 仍不拥有数据
四、dashboard 模块审查(重点)
4.1 严重问题:data-access.ts 直查 11 张跨模块表
dashboard/data-access.ts 的 getAdminDashboardData 函数直接查询以下表:
| 表名 | 所属模块 | 查询内容 |
|---|---|---|
sessions |
auth | 活跃会话数 |
users |
users | 用户总数 + 最近注册用户 |
usersToRoles |
users | 用户角色统计 |
roles |
users | 角色名 |
classes |
classes | 班级总数 |
textbooks |
textbooks | 教材总数 |
chapters |
textbooks | 章节总数 |
questions |
questions | 题目总数 |
exams |
exams | 考试总数(含 scope 过滤) |
homeworkAssignments |
homework | 作业总数 + 已发布数 |
homeworkSubmissions |
homework | 提交数 + 待批改数 |
问题分析:
- 违反模块封装原则:dashboard 直接依赖其他模块的 DB schema
- 任何模块的表结构变更都需要同步修改 dashboard
- 无法复用其他模块的 scope 过滤逻辑(dashboard 自己实现了 exam/homework 的 scope 过滤,第 31-73 行)
4.2 学生/教师仪表盘的对比
学生仪表盘(app/(dashboard)/student/dashboard/page.tsx):
- ✅ 正确做法:调用
classes/data-access的getStudentClasses/getStudentSchedule - ✅ 调用
homework/data-access的getStudentDashboardGrades/getStudentHomeworkAssignments - ✅ 不直接查询任何表
教师仪表盘(app/(dashboard)/teacher/dashboard/page.tsx):
- ✅ 调用
classes/data-access的getClassSchedule/getTeacherClasses - ✅ 调用
homework/data-access的getHomeworkAssignments/getHomeworkSubmissions/getTeacherGradeTrends - ⚠️ 第 18-21 行直接查询
users表获取教师姓名:db.query.users.findFirst(...)— 应使用 users 模块的 data-access
4.3 建议方案
方案 A(理想):聚合 API 模式
为每个模块添加 getModuleStats(scope?) 函数,dashboard 聚合调用:
const [userStats, classStats, textbookStats, ...] = await Promise.all([
getUsersStats(scope),
getClassStats(scope),
getTextbookStats(),
...
])
方案 B(务实):接受 dashboard 作为跨模块聚合层
- 在架构图中明确标注 dashboard 对所有业务模块的依赖
- 将 scope 过滤逻辑下沉到各模块的
getStats函数 - 至少消除 dashboard 中重复实现的 exam/homework scope 过滤(第 31-73 行)
五、其他模块审查
5.1 messaging 模块
模块结构
| 文件 | 行数 | 职责 |
|---|---|---|
actions.ts |
245 | 9 个 Server Action(私信 + 通知 + 偏好) |
data-access.ts |
252 | 私信 CRUD + 通知 CRUD + 收件人查询 |
notification-preferences.ts |
166 | 通知偏好 CRUD |
schema.ts |
17 | 私信发送校验 |
types.ts |
108 | 私信 + 通知 + 偏好类型 |
问题
- ❌ 职责过多:同时管理私信(messages)、站内通知(messageNotifications)、通知偏好(notificationPreferences)三类数据
- ❌ 与 notifications 模块边界模糊:详见第三节
- ⚠️
getRecipients函数(第 227-251 行)根据 dataScope 查询收件人,逻辑较复杂,可考虑下沉到 users 模块
5.2 parent 模块
模块结构
| 文件 | 行数 | 职责 |
|---|---|---|
data-access.ts |
234 | 子女关系 + 子女仪表盘数据聚合 |
types.ts |
57 | 类型定义 |
components/ |
7 个 | 子女卡片 + 详情 + 仪表盘 |
评价
- ✅ 职责单一:仅负责家长视角的子女数据聚合与展示
- ✅ 正确复用其他模块:
- 调用
classes/data-access的getStudentClasses/getStudentSchedule - 调用
homework/data-access的getStudentDashboardGrades/getStudentHomeworkAssignments - 调用
grades/data-access的getStudentGradeSummary
- 调用
- ✅ 不直接查询业务表(仅查询
parentStudentRelations自有表 +users/classes/classEnrollments/grades用于基本信息) - ⚠️
getChildBasicInfo第 74-105 行多次串行查询(grade → class),可优化为 join
5.3 settings 模块
模块结构
| 文件 | 行数 | 职责 |
|---|---|---|
actions.ts |
205 | AI Provider CRUD + 测试连通性 |
actions-password.ts |
113 | 修改密码 |
components/ |
8 个 | 通用设置 + AI 配置 + 密码 + 主题 + 通知偏好 |
问题:职责混杂但可接受
settings 模块混合了 5 类职责:
- AI Provider 管理(
actions.ts+ai-provider-settings-card.tsx) - 密码修改(
actions-password.ts+password-change-form.tsx) - 个人资料(
profile-settings-form.tsx) - 主题偏好(
theme-preferences-card.tsx) - 通知偏好表单(
notification-preferences-form.tsx— 调用 messaging 模块的 Action)
评价:
- ⚠️ AI Provider 管理与"用户设置"语义距离较远,可考虑独立为
ai-config模块 - ⚠️
notification-preferences-form.tsx第 14 行 importupdateNotificationPreferencesActionfrom@/modules/messaging/actions— 跨模块 UI 依赖 - ✅ 密码修改有速率限制(
actions-password.ts第 33-37 行) - ✅ AI Provider 操作有
AI_CONFIGURE权限校验 - ✅ 密码修改仅要求
requireAuth()(自助操作),符合最小权限原则 - ⚠️ 无
data-access.ts文件,actions.ts直接使用db— 建议抽取 data-access 层
5.4 files 模块
模块结构
| 文件 | 行数 | 职责 |
|---|---|---|
data-access.ts |
267 | 文件附件 CRUD + 批量删除 + 统计 |
types.ts |
- | 类型定义 |
components/ |
6 个 | 上传 + 列表 + 预览 + 管理 |
评价
- ✅ 职责单一:仅管理
fileAttachments表 - ✅ 不跨模块查询
- ✅ 批量删除有容错处理(第 152-177 行,失败时回退到逐条删除)
- ⚠️ 所有函数都用 try-catch 吞掉错误返回空数组/null,可能掩盖真实问题
- ⚠️ 无 actions.ts 文件 — 文件上传通过
app/api/upload/route.ts和app/api/files/[id]/route.ts实现,data-access 被路由直接调用
5.5 auth 模块
模块结构
| 文件 | 职责 |
|---|---|
components/auth-layout.tsx |
认证页面布局 |
components/login-form.tsx |
登录表单 |
components/register-form.tsx |
注册表单 |
评价
- ✅ 纯 UI 模块:无 data-access / actions / types 文件
- ✅ 认证逻辑由 NextAuth +
shared/lib/auth-guard统一处理 - ✅ 职责清晰
5.6 layout 模块
模块结构
| 文件 | 职责 |
|---|---|
components/app-sidebar.tsx |
侧边栏(根据权限渲染导航) |
components/sidebar-provider.tsx |
侧边栏状态 Context |
components/site-header.tsx |
顶部导航(含通知下拉) |
config/navigation.ts |
导航配置(4 个角色) |
navigation.ts 幽灵路由审查
结论:✅ 无幽灵路由(007 报告中提到的 13 个幽灵路由已全部修复)
逐一核对导航配置中的所有 href 与 src/app/ 下的实际页面:
| 角色 | 导航项数 | 全部存在 | 备注 |
|---|---|---|---|
| admin | 19 | ✅ | 包括子菜单项 |
| teacher | 22 | ✅ | 包括子菜单项 |
| student | 12 | ✅ | 包括子菜单项 |
| parent | 5 | ✅ | 包括子菜单项 |
存在但未纳入导航的页面
| 路由 | 说明 | 建议 |
|---|---|---|
/admin/attendance |
管理员考勤页面 | 如需管理员查看全校考勤,应加入 admin 导航 |
/admin/files |
管理员文件管理 | 应加入 admin 导航 |
/parent/children/[studentId] |
子女详情页 | 通过仪表盘卡片跳转,可不加入导航 |
/settings/security |
安全设置子页 | 通过 settings 页 Tab 切换,无需独立导航 |
/profile |
个人主页 | 通过 header 头像菜单跳转,无需独立导航 |
其他发现
- ✅
app-sidebar.tsx第 36-43 行根据权限动态选择角色导航配置,符合 RBAC - ⚠️ 第 39 行判断学生逻辑:
permissions.includes(Permissions.HOMEWORK_SUBMIT) && !permissions.includes(Permissions.EXAM_CREATE)— 用权限反推角色,不够直观,建议改用hasRole("student")
5.7 student 模块
模块结构
| 文件 | 职责 |
|---|---|
components/student-courses-view.tsx |
学生课程视图 |
components/student-schedule-filters.tsx |
课表筛选器 |
components/student-schedule-view.tsx |
学生课表视图 |
评价
- ✅ 纯 UI 模块:无 data-access / actions / types
- ✅ 数据由
app/(dashboard)/student/learning/courses/page.tsx和app/(dashboard)/student/schedule/page.tsx通过 classes 模块的 data-access 获取 - ⚠️ 与 classes 模块的
schedule-view.tsx/schedule-filters.tsx可能存在功能重叠,建议核查
六、跨模块依赖关系图
dashboard ──直查──> users, classes, textbooks, questions, exams, homework (11 张表)
parent ──调用──> classes, homework, grades (data-access)
diagnostic ──直查──> examSubmissions, submissionAnswers, questionsToKnowledgePoints, classes
notifications ──依赖──> messaging (偏好 + in-app 渠道)
messaging ──绕过──> notifications (直接写 messageNotifications)
proctoring ──直查──> exams, examSubmissions, users
settings ──调用──> messaging (通知偏好 Action)
七、修复优先级
P0(严重,应立即修复)
| 序号 | 问题 | 模块 | 工作量 | 影响 |
|---|---|---|---|---|
| 1 | messaging 绕过 notifications 直接写通知 | messaging | 小 | 用户通知偏好失效,多渠道通知无效 |
| 2 | proctoring/exam-mode-config.tsx 未集成 | proctoring | 小 | 监考功能无法启用,组件为死代码 |
| 3 | proctoring 事件上报双通道重复 | proctoring | 小 | 代码重复,维护成本 |
| 4 | notifications 反向依赖 messaging | notifications | 中 | 架构耦合,难以独立演进 |
P1(中等问题,下个迭代修复)
| 序号 | 问题 | 模块 | 工作量 |
|---|---|---|---|
| 5 | dashboard 直查 11 张跨模块表 | dashboard | 大 |
| 6 | diagnostic 跨模块直查 4 张表 | diagnostic | 中 |
| 7 | notifications 无 notification_logs 表 | notifications | 中 |
| 8 | sendClassNotificationAction 直查 classes 表 | notifications | 小 |
| 9 | elective 两个 data-access 文件代码重复 | elective | 小 |
| 10 | settings/notification-preferences-form 跨模块依赖 | settings | 小 |
P2(轻微问题,机会修复)
| 序号 | 问题 | 模块 |
|---|---|---|
| 11 | diagnostic/data-access-reports.ts 有未使用代码 | diagnostic |
| 12 | diagnostic 班级报告 studentId 字段复用 | diagnostic |
| 13 | elective runLottery 使用 Math.random | elective |
| 14 | teacher dashboard 直查 users 表 | dashboard |
| 15 | files 模块 try-catch 吞错误 | files |
| 16 | layout 用权限反推角色 | layout |
八、总结
新增模块质量
- elective:✅ 质量较好,拆分合理但有代码重复
- proctoring:⚠️ 有死代码(exam-mode-config 未集成)和重复实现(双通道上报)
- diagnostic:✅ 与 grades 无重叠,但跨模块耦合较重
- notifications:⚠️ 渠道抽象优秀,但与 messaging 边界模糊、反向依赖
重点问题回答
-
elective 拆分为 3 个 data-access 文件是否合理? 合理,但需消除
data-access.ts与data-access-selections.ts之间的代码重复 -
proctoring 模块职责是否清晰? 基本清晰,但
exam-mode-config.tsx应属于 exams 模块或集成到考试表单 -
diagnostic 与 grades 是否有职责重叠? 无重叠。grades 管分数记录,diagnostic 管知识点掌握度,数据来源和维度均不同
-
notifications 与 messaging 边界是否清晰? 不清晰。存在双向依赖、类型不一致、职责重叠三个问题,建议按方案 A 合并
-
dashboard 是否直查其他模块的表? 是。
getAdminDashboardData直查 11 张跨模块表,是本次审查最严重的封装违规 -
settings 是否混入太多职责? 混合了 5 类职责,但作为"设置"聚合点尚可接受。AI Provider 管理可考虑独立
-
navigation.ts 是否有幽灵路由? 无。007 报告中的 13 个幽灵路由已全部修复