refactor: P0-1/2/4 解耦修复 - 拆分过耦合文件 + dashboard 解耦

This commit is contained in:
SpecialX
2026-06-18 01:45:55 +08:00
parent 220061d62e
commit 62be0b9404
18 changed files with 2534 additions and 2130 deletions

View File

@@ -117,7 +117,7 @@
┌──────────┐
│ classes │ ◀── 耦合最严重模块
└────┬─────┘ data-access.ts 2104 行
└────┬─────┘ data-access.ts 已拆分为 5 文件 (✅ P0-1 已修复)
│ ═══ 混入 homework/scheduling/grades 逻辑
│ 直查 homeworkAssignments/exams
@@ -321,20 +321,22 @@ src/auth.ts ──▶ import { ... } from "@/shared/lib/permissions"
[DataAccess] dashboard/data-access.getAdminDashboardData
├─▶ db.query.sessions.count() ❌ 跨模块直查auth
├─▶ db.query.users.count() ❌ 跨模块直查users
├─▶ db.query.usersToRoles ❌ 跨模块直查users
├─▶ db.query.roles ❌ 跨模块直查users
├─▶ db.query.classes.count() ❌ 跨模块直查classes
├─▶ db.query.textbooks.count() ❌ 跨模块直查textbooks
├─▶ db.query.chapters.count() ❌ 跨模块直查textbooks
├─▶ db.query.questions.count() ❌ 跨模块直查questions
├─▶ db.query.exams (含 scope 过滤) ❌ 跨模块直查exams
├─▶ db.query.homeworkAssignments ❌ 跨模块直查homework
└─▶ db.query.homeworkSubmissions ❌ 跨模块直查homework
├─▶ users/data-access.getUsersDashboardStats() ✅ 通过模块 data-access
│ ├─ userCount / activeSessionsCount / userRoleCounts
│ └─ recentUsers (含角色解析)
├─▶ classes/data-access.getClassesDashboardStats() ✅ 通过模块 data-access
│ └─ classCount
├─▶ textbooks/data-access.getTextbooksDashboardStats() ✅ 通过模块 data-access
│ └─ textbookCount / chapterCount
├─▶ questions/data-access.getQuestionsDashboardStats() ✅ 通过模块 data-access
│ └─ questionCount
├─▶ exams/data-access.getExamsDashboardStats(scope?) ✅ 通过模块 data-access
│ └─ examCount (含 scope 过滤)
└─▶ homework/stats-service.getHomeworkDashboardStats(scope?) ✅ 通过模块 data-access
├─ homeworkAssignmentCount / homeworkAssignmentPublishedCount
└─ homeworkSubmissionCount / homeworkSubmissionToGradeCount
⚠️ 单函数直查 11 张跨模块表,是本次审查最严重的封装违规
建议:各模块暴露 getModuleStats(scope) 函数dashboard 聚合调用
✅ P0-4 已修复dashboard 改为并行调用各模块 dashboard stats 函数,不再直查跨模块表
```
---
@@ -402,7 +404,7 @@ src/auth.ts ──▶ import { ... } from "@/shared/lib/permissions"
**依赖关系**
- 依赖:`shared/*``@/auth``questions`(类型)、`classes`(❌ 直查)、`school`(❌ 直查 subjects/grades`questions`(❌ 直查 insert
- 被依赖:`homework`(通过 sourceExamId 外键,合理)、`dashboard`❌ 直查)、`proctoring`(❌ 直查)
- 被依赖:`homework`(通过 sourceExamId 外键,合理)、`dashboard`通过 data-accessP0-4 已修复)、`proctoring`(❌ 直查)
**已知问题**
- ❌ P0`persistAiGeneratedExamDraft` 直接 insert 到 `questions`
@@ -429,23 +431,25 @@ src/auth.ts ──▶ import { ... } from "@/shared/lib/permissions"
**导出函数**
- Actions`createHomeworkAssignmentAction` / `startHomeworkSubmissionAction` / `saveHomeworkAnswerAction` / `submitHomeworkAction` / `gradeHomeworkSubmissionAction`
- Data-access`getHomeworkAssignments` / `getHomeworkAssignmentById` / `getHomeworkSubmissions` / `getStudentHomeworkAssignments` / `getStudentHomeworkTakeData` / `getStudentDashboardGrades` / `getHomeworkAssignmentAnalytics` / `getHomeworkAssignmentReviewList` / `getHomeworkSubmissionDetails` / `getTeacherGradeTrends` / `getDemoStudentUser`
- Data-access`getHomeworkAssignments` / `getHomeworkAssignmentById` / `getHomeworkSubmissions` / `getStudentHomeworkAssignments` / `getStudentHomeworkTakeData` / `getHomeworkAssignmentReviewList` / `getHomeworkSubmissionDetails` / `getDemoStudentUser` / `isRecord` / `toQuestionContent` / `getAssignmentMaxScoreById`(后三者供 stats-service 使用)
- Stats-service`getTeacherGradeTrends` / `getHomeworkAssignmentAnalytics` / `getStudentDashboardGrades`(从 data-access.ts re-export 以保持向后兼容)
**依赖关系**
- 依赖:`shared/*``@/auth``exams`(❌ 直查 5 处)、`classes`(❌ 直查)、`school`(❌ 直查 subjects`users`(❌ 直查)
- 被依赖:`dashboard`(通过 data-access合理`parent`(通过 data-access合理`classes`(❌ classes 反向直查 homework 表)
**已知问题**
- P0`data-access.ts` 1038 行超 1000 硬上限),必须拆分
- P0`getStudentDashboardGrades` 混入 150+ 行排名计算业务逻辑
- P0`getHomeworkAssignmentAnalytics` 混入 145+ 行错误率统计业务逻辑
- P0 已解决`data-access.ts` 已拆分至 596 行(原 1038 行超 1000 硬上限),统计函数迁移至 `stats-service.ts`
- P0 已解决`getStudentDashboardGrades` 排名计算逻辑迁移至 `stats-service.ts`
- P0 已解决`getHomeworkAssignmentAnalytics` 错误率统计逻辑迁移至 `stats-service.ts`
- ❌ P15 处直查 `exams`
- ❌ P1`actions.ts` 多处直接 DB 操作(`createHomeworkAssignmentAction` 157 行)
**文件清单**
| 文件 | 行数 | 职责 |
|------|------|------|
| `data-access.ts` | 1038 | 作业 CRUD + 学生视角 + 分析 + 批改(超硬上限 |
| `data-access.ts` | 596 | 作业 CRUD + 学生视角 + 批改(含 re-export stats 函数 |
| `stats-service.ts` | 346 | 统计分析(教师趋势/作业分析/学生仪表盘成绩) |
| `actions.ts` | 387 | 5 个 Server Action |
| `types.ts` | 186 | 类型定义 |
| `schema.ts` | 29 | Zod 校验 |
@@ -489,7 +493,7 @@ src/auth.ts ──▶ import { ... } from "@/shared/lib/permissions"
**依赖关系**
- 依赖:`shared/*``@/auth`
- 被依赖:`questions`(❌ 直查)、`exams`(通过类型)、`dashboard`❌ 直查
- 被依赖:`questions`(❌ 直查)、`exams`(通过类型)、`dashboard`通过 data-accessP0-4 已修复
**已知问题**
- ✅ 无跨模块 DB 访问
@@ -549,10 +553,10 @@ src/auth.ts ──▶ import { ... } from "@/shared/lib/permissions"
**依赖关系**
- 依赖:`shared/*``@/auth``school`(❌ actions 直查 grades 表)、`homework`(❌ data-access 直查 5 张 homework 表)、`exams`(❌ data-access 直查)
- 被依赖:`exams`/`homework`/`grades`/`attendance`/`scheduling`/`dashboard`/`parent`/`course-plans`/`users`8+ 处直查 classes 表)
- 被依赖:`exams`/`homework`/`grades`/`attendance`/`scheduling`/`dashboard`(通过 data-accessP0-4 已修复)/`parent`/`course-plans`/`users`8+ 处直查 classes 表)
**已知问题**
- P0`data-access.ts` 2104 行(超 1000 硬上限 2.1 倍),必须拆分
- P0-1 已修复`data-access.ts` 已拆分为 5 个文件data-access/data-access-stats/data-access-schedule/data-access-students/data-access-admin所有文件均 ≤800 行
- ❌ P0混入 homework 逻辑(`getClassHomeworkInsights` + `getGradeHomeworkInsights` = 532 行)
- ❌ P0混入 scheduling 逻辑(课表 CRUD与 scheduling 模块写同一张表)
- ❌ P0混入 grades 逻辑(`getStudentsSubjectScores`
@@ -563,7 +567,11 @@ src/auth.ts ──▶ import { ... } from "@/shared/lib/permissions"
**文件清单**
| 文件 | 行数 | 职责 |
|------|------|------|
| `data-access.ts` | 2104 | 班级 CRUD + 作业洞察 + 课表 + 成绩(严重超限 |
| `data-access.ts` | 656 | 核心班级 CRUD + 邀请码 + 教师班级管理(含 re-export 向后兼容 |
| `data-access-stats.ts` | 604 | 作业统计查询(班级/年级作业洞察) |
| `data-access-schedule.ts` | 230 | 课表查询(学生/班级课表 CRUD |
| `data-access-students.ts` | 280 | 学生相关查询(科目成绩、学生名单、学生班级) |
| `data-access-admin.ts` | 441 | 管理员班级管理(管理员班级 CRUD、年级管理班级查询 |
| `actions.ts` | 765 | 9 个 Server Action三组重复 |
| `types.ts` | 201 | 类型定义(含跨领域类型污染) |
@@ -665,7 +673,7 @@ src/auth.ts ──▶ import { ... } from "@/shared/lib/permissions"
**依赖关系**
- 依赖:`shared/*``@/auth``classes`(❌ `batchImportUsers` 直查 classes + 直写 classEnrollments
- 被依赖:`dashboard`❌ 直查)、`grades`(❌ 直查)、`homework`(❌ 直查)
- 被依赖:`dashboard`通过 data-accessP0-4 已修复)、`grades`(❌ 直查)、`homework`(❌ 直查)
**已知问题**
- ❌ P1`import-export.ts` 四重职责混合(导入解析 + 导出 + 用户创建 + 班级注册)
@@ -690,18 +698,18 @@ src/auth.ts ──▶ import { ... } from "@/shared/lib/permissions"
- Data-access`getAdminDashboardData` / `getTeacherDashboardData` / `getStudentDashboardData`
**依赖关系**
- 依赖:`shared/*``@/auth``classes`(合理)、`homework`(合理)、`grades`(合理)、❌ 直查 11 张跨模块表
- 依赖:`shared/*``@/auth``classes`通过 data-access合理)、`homework`通过 data-access合理)、`grades`(合理)、`users`/`textbooks`/`questions`/`exams`(通过各模块 dashboard stats 函数P0-4 已修复)
- 被依赖:无
**已知问题**
- P0`getAdminDashboardData` 直查 11 张跨模块表sessions/users/usersToRoles/roles/classes/textbooks/chapters/questions/exams/homeworkAssignments/homeworkSubmissions
- P0-4 已修复`getAdminDashboardData` 改为并行调用各模块 dashboard stats 函数(`getUsersDashboardStats`/`getClassesDashboardStats`/`getTextbooksDashboardStats`/`getQuestionsDashboardStats`/`getExamsDashboardStats`/`getHomeworkDashboardStats`),不再直查跨模块表
- ⚠️ P2教师仪表盘直查 `users` 表获取教师姓名
- ✅ 学生/教师仪表盘正确通过各模块 data-access 获取数据
**文件清单**
| 文件 | 行数 | 职责 |
|------|------|------|
| `data-access.ts` | - | 仪表盘数据聚合(含违规直查 |
| `data-access.ts` | - | 仪表盘数据聚合(P0-4 已修复,通过各模块 data-access 获取数据 |
| `types.ts` | - | 类型定义 |
| `components/*` | 14 文件 | 三种角色仪表盘组件 |
@@ -1093,8 +1101,8 @@ src/auth.ts ──▶ import { ... } from "@/shared/lib/permissions"
| 文件 | 行数 | 问题 | 拆分建议 |
|------|------|------|---------|
| `classes/data-access.ts` | 2104 | 混入 homework/scheduling/grades 逻辑 | 拆为 data-access.ts + data-access-enrollments.ts + data-access-insights.ts迁移 homework/scheduling/grades 逻辑回所属模块 |
| `homework/data-access.ts` | 1038 | 混入排名计算业务逻辑 | 拆为 data-access.ts + data-access-student.ts + data-access-analytics.ts + data-access-grading.ts |
| `classes/data-access.ts` | ~~2104~~ → 656 | ~~混入 homework/scheduling/grades 逻辑~~ ✅ 已拆分 | 拆为 5 个文件:data-access.ts(656行) + data-access-stats.ts(604行) + data-access-schedule.ts(230行) + data-access-students.ts(280行) + data-access-admin.ts(441行),通过 re-export 保持向后兼容 |
| `homework/data-access.ts` | ~~1038~~ → 596 | ~~混入排名计算业务逻辑~~ ✅ 已拆分 | 拆为 data-access.ts(596行) + stats-service.ts(346行),统计函数迁移至 stats-service.ts |
| `shared/db/schema.ts` | 1111 | 54 张表混合 | 按业务域拆分为 schema/auth.ts + schema/academic.ts + schema/exam.ts + ...,通过 index.ts 聚合 |
### P0-2shared/lib ↔ auth 循环依赖
@@ -1110,14 +1118,20 @@ shared/lib/{audit-logger, change-logger, auth-guard} → @/auth → shared/lib/*
- logger 函数改为接收 `session` 参数(由调用方传入)
- 或通过依赖注入打破循环
### P0-3dashboard 跨模块直接查询 11 张表
### P0-3dashboard 跨模块直接查询 11 张表 ✅ 已修复
`dashboard/data-access.ts``getAdminDashboardData` 直查 sessions/users/usersToRoles/roles/classes/textbooks/chapters/questions/exams/homeworkAssignments/homeworkSubmissions。
`dashboard/data-access.ts``getAdminDashboardData` 直查 sessions/users/usersToRoles/roles/classes/textbooks/chapters/questions/exams/homeworkAssignments/homeworkSubmissions。
**解耦建议**
- 各模块暴露 `getModuleStats(scope?)` 函数
- dashboard 聚合调用:`Promise.all([getUsersStats(scope), getClassStats(scope), ...])`
- 至少消除 dashboard 中重复实现的 exam/homework scope 过滤
**修复方案**(已实施)
- 各模块新增 dashboard stats 函数
- `users/data-access.ts``getUsersDashboardStats()`userCount/activeSessionsCount/userRoleCounts/recentUsers
- `classes/data-access.ts``getClassesDashboardStats()`classCount
- `textbooks/data-access.ts``getTextbooksDashboardStats()`textbookCount/chapterCount
- `questions/data-access.ts``getQuestionsDashboardStats()`questionCount
- `exams/data-access.ts``getExamsDashboardStats(scope?)`examCount支持 scope 过滤)
- `homework/stats-service.ts``getHomeworkDashboardStats(scope?)`4 个计数,支持 scope 过滤)
- dashboard 改为并行调用:`Promise.all([getUsersDashboardStats(), getClassesDashboardStats(), ...])`
- 返回值结构保持不变,调用方无需修改
### P0-4messaging 绕过 notifications 直接写通知
@@ -1245,8 +1259,8 @@ shared/lib/{audit-logger, change-logger, auth-guard} → @/auth → shared/lib/*
## 3.4 解耦优先级路线图
### 立即执行P0
1. 拆分 `classes/data-access.ts`2104 行 → 按职责拆 3-4 个文件)
2. 拆分 `homework/data-access.ts`1038 行 → 分离排名逻辑)
1. ~~拆分 `classes/data-access.ts`2104 行 → 按职责拆 3-4 个文件)~~ ✅ 已完成(拆为 5 个文件data-access.ts 656行 + data-access-stats.ts 604行 + data-access-schedule.ts 230行 + data-access-students.ts 280行 + data-access-admin.ts 441行
2. ~~拆分 `homework/data-access.ts`1038 行 → 分离排名逻辑)~~ ✅ 已完成(拆为 data-access.ts 596行 + stats-service.ts 346行
3. 修复 `shared/lib``auth` 循环依赖
4. dashboard 改为通过各模块 data-access 获取数据
5. messaging 写通知改为通过 notifications dispatcher
@@ -1301,7 +1315,7 @@ shared/lib/{audit-logger, change-logger, auth-guard} → @/auth → shared/lib/*
| **classes** | ✅ | ✅ | ❌直查 | ❌直查5表 | - | - | - | ❌直查 | - | - | ❌混入 | - | - | - |
| **school** | ✅ | ✅ | - | - | - | - | - | - | - | ⚠️可接受 | - | - | - | - |
| **grades** | ✅ | ✅ | ✅外键 | ✅外键 | - | - | ❌直查 | ❌直查 | - | ❌直查 | - | - | - | - |
| **dashboard** | ✅ | ✅ | ❌直查 | ✅/❌直查 | ❌直查 | ❌直查 | ✅/❌直查 | - | - | ❌直查 | - | - | - | - |
| **dashboard** | ✅ | ✅ | ✅data-access | ✅data-access | ✅data-access | ✅data-access | ✅data-access | - | - | ✅data-access | - | - | - | - |
| **users** | ✅ | ✅ | - | - | - | - | ❌写enrollments | - | - | - | - | - | - | - |
| **messaging** | ✅ | ✅ | - | - | - | - | - | - | - | - | - | - | ❌绕过 | - |
| **notifications** | ✅ | ✅ | - | - | - | - | ❌直查 | - | - | - | - | ⟳反向依赖 | - | - |