refactor: P0-1/2/4 解耦修复 - 拆分过耦合文件 + dashboard 解耦
This commit is contained in:
@@ -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-access,P0-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`
|
||||
- ❌ P1:5 处直查 `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-access,P0-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-access,P0-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-access,P0-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-2:shared/lib ↔ auth 循环依赖
|
||||
@@ -1110,14 +1118,20 @@ shared/lib/{audit-logger, change-logger, auth-guard} → @/auth → shared/lib/*
|
||||
- logger 函数改为接收 `session` 参数(由调用方传入)
|
||||
- 或通过依赖注入打破循环
|
||||
|
||||
### P0-3:dashboard 跨模块直接查询 11 张表
|
||||
### P0-3:dashboard 跨模块直接查询 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-4:messaging 绕过 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** | ✅ | ✅ | - | - | - | - | ❌直查 | - | - | - | - | ⟳反向依赖 | - | - |
|
||||
|
||||
@@ -2048,6 +2048,14 @@
|
||||
"createAiExamAction"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "getExamsDashboardStats",
|
||||
"signature": "(scope?: DataScope) => Promise<ExamsDashboardStats>",
|
||||
"purpose": "获取考试仪表盘统计数据(考试总数,支持数据范围过滤)",
|
||||
"usedBy": [
|
||||
"dashboard/data-access.getAdminDashboardData"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "omitScheduledAtFromDescription",
|
||||
"signature": "(description: string | null) => string",
|
||||
@@ -2535,13 +2543,6 @@
|
||||
}
|
||||
],
|
||||
"dataAccess": [
|
||||
{
|
||||
"name": "getTeacherGradeTrends",
|
||||
"signature": "(teacherId: string, limit?: number) => Promise<TeacherGradeTrendItem[]>",
|
||||
"usedBy": [
|
||||
"dashboard (教师仪表盘)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "getHomeworkAssignments",
|
||||
"signature": "(params?: { creatorId?, ids?, classId?, scope? }) => Promise<HomeworkAssignmentListItem[]>",
|
||||
@@ -2571,20 +2572,6 @@
|
||||
"student/dashboard"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "getStudentDashboardGrades",
|
||||
"signature": "(studentId: string) => Promise<StudentDashboardGradeProps>",
|
||||
"usedBy": [
|
||||
"dashboard/data-access.ts"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "getHomeworkAssignmentAnalytics",
|
||||
"signature": "(assignmentId: string) => Promise<HomeworkAssignmentAnalytics | null>",
|
||||
"usedBy": [
|
||||
"homework错误分析组件"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "getHomeworkAssignmentById",
|
||||
"signature": "(id: string, scope?: DataScope) => Promise<...>",
|
||||
@@ -2618,6 +2605,58 @@
|
||||
]
|
||||
}
|
||||
],
|
||||
"statsService": [
|
||||
{
|
||||
"name": "getTeacherGradeTrends",
|
||||
"file": "stats-service.ts",
|
||||
"signature": "(teacherId: string, limit?: number) => Promise<TeacherGradeTrendItem[]>",
|
||||
"purpose": "教师仪表盘年级趋势数据",
|
||||
"deps": [
|
||||
"data-access.getAssignmentMaxScoreById"
|
||||
],
|
||||
"usedBy": [
|
||||
"dashboard (教师仪表盘)"
|
||||
],
|
||||
"reExportedFrom": "data-access.ts (向后兼容)"
|
||||
},
|
||||
{
|
||||
"name": "getHomeworkAssignmentAnalytics",
|
||||
"file": "stats-service.ts",
|
||||
"signature": "(assignmentId: string) => Promise<HomeworkAssignmentAnalytics | null>",
|
||||
"purpose": "作业整体分析(含题目错误率/错答样本)",
|
||||
"deps": [
|
||||
"data-access.isRecord",
|
||||
"data-access.toQuestionContent"
|
||||
],
|
||||
"usedBy": [
|
||||
"homework错误分析组件"
|
||||
],
|
||||
"reExportedFrom": "data-access.ts (向后兼容)"
|
||||
},
|
||||
{
|
||||
"name": "getStudentDashboardGrades",
|
||||
"file": "stats-service.ts",
|
||||
"signature": "(studentId: string) => Promise<StudentDashboardGradeProps>",
|
||||
"purpose": "学生仪表盘成绩(趋势/近期/班级排名)",
|
||||
"deps": [
|
||||
"data-access.getAssignmentMaxScoreById"
|
||||
],
|
||||
"usedBy": [
|
||||
"dashboard/data-access.ts"
|
||||
],
|
||||
"reExportedFrom": "data-access.ts (向后兼容)"
|
||||
},
|
||||
{
|
||||
"name": "getHomeworkDashboardStats",
|
||||
"file": "stats-service.ts",
|
||||
"signature": "(scope?: DataScope) => Promise<HomeworkDashboardStats>",
|
||||
"purpose": "获取作业仪表盘统计数据(作业数/已发布数/提交数/待批改数,支持数据范围过滤)",
|
||||
"usedBy": [
|
||||
"dashboard/data-access.getAdminDashboardData"
|
||||
],
|
||||
"reExportedFrom": "data-access.ts (向后兼容)"
|
||||
}
|
||||
],
|
||||
"schema": [
|
||||
{
|
||||
"name": "CreateHomeworkAssignmentSchema",
|
||||
@@ -2941,6 +2980,14 @@
|
||||
"teacher/questions/page.tsx"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "getQuestionsDashboardStats",
|
||||
"signature": "() => Promise<QuestionsDashboardStats>",
|
||||
"purpose": "获取题目仪表盘统计数据(题目总数)",
|
||||
"usedBy": [
|
||||
"dashboard/data-access.getAdminDashboardData"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "GetQuestionsParams",
|
||||
"type": "type",
|
||||
@@ -3230,6 +3277,14 @@
|
||||
"usedBy": [
|
||||
"reorderChaptersAction"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "getTextbooksDashboardStats",
|
||||
"signature": "() => Promise<TextbooksDashboardStats>",
|
||||
"purpose": "获取教材仪表盘统计数据(教材总数、章节总数)",
|
||||
"usedBy": [
|
||||
"dashboard/data-access.getAdminDashboardData"
|
||||
]
|
||||
}
|
||||
],
|
||||
"hooks": [
|
||||
@@ -3618,6 +3673,14 @@
|
||||
"classes内部"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "getClassesDashboardStats",
|
||||
"signature": "() => Promise<ClassesDashboardStats>",
|
||||
"purpose": "获取班级仪表盘统计数据(班级总数)",
|
||||
"usedBy": [
|
||||
"dashboard/data-access.getAdminDashboardData"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "createTeacherClass",
|
||||
"signature": "(input) => Promise<string>",
|
||||
@@ -4005,7 +4068,83 @@
|
||||
"purpose": "班级作业组件"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"files": [
|
||||
{
|
||||
"path": "data-access.ts",
|
||||
"lines": 656,
|
||||
"description": "核心班级 CRUD + 邀请码 + 教师班级管理(含 re-export 向后兼容)",
|
||||
"exports": [
|
||||
"getTeacherClasses",
|
||||
"getTeacherOptions",
|
||||
"getTeacherTeachingSubjects",
|
||||
"createTeacherClass",
|
||||
"ensureClassInvitationCode",
|
||||
"regenerateClassInvitationCode",
|
||||
"enrollStudentByInvitationCode",
|
||||
"enrollTeacherByInvitationCode",
|
||||
"updateTeacherClass",
|
||||
"setClassSubjectTeachers",
|
||||
"deleteTeacherClass",
|
||||
"enrollStudentByEmail",
|
||||
"setStudentEnrollmentStatus",
|
||||
"getSessionTeacherId",
|
||||
"getTeacherIdForMutations",
|
||||
"getAccessibleClassIdsForTeacher",
|
||||
"getTeacherSubjectIdsForClass",
|
||||
"getClassSubjects",
|
||||
"compareClassLike",
|
||||
"isDuplicateInvitationCodeError",
|
||||
"generateUniqueInvitationCode"
|
||||
]
|
||||
},
|
||||
{
|
||||
"path": "data-access-stats.ts",
|
||||
"lines": 604,
|
||||
"description": "作业统计查询(班级/年级作业洞察)",
|
||||
"exports": [
|
||||
"getClassHomeworkInsights",
|
||||
"getGradeHomeworkInsights",
|
||||
"getClassesDashboardStats"
|
||||
]
|
||||
},
|
||||
{
|
||||
"path": "data-access-schedule.ts",
|
||||
"lines": 230,
|
||||
"description": "课表查询(学生/班级课表 CRUD)",
|
||||
"exports": [
|
||||
"getStudentSchedule",
|
||||
"getClassSchedule",
|
||||
"createClassScheduleItem",
|
||||
"updateClassScheduleItem",
|
||||
"deleteClassScheduleItem"
|
||||
]
|
||||
},
|
||||
{
|
||||
"path": "data-access-students.ts",
|
||||
"lines": 280,
|
||||
"description": "学生相关查询(科目成绩、学生名单、学生班级)",
|
||||
"exports": [
|
||||
"getStudentsSubjectScores",
|
||||
"getClassStudentSubjectScoresV2",
|
||||
"getStudentClasses",
|
||||
"getClassStudents"
|
||||
]
|
||||
},
|
||||
{
|
||||
"path": "data-access-admin.ts",
|
||||
"lines": 441,
|
||||
"description": "管理员班级管理(管理员班级 CRUD、年级管理班级查询)",
|
||||
"exports": [
|
||||
"getAdminClasses",
|
||||
"getGradeManagedClasses",
|
||||
"getManagedGrades",
|
||||
"createAdminClass",
|
||||
"updateAdminClass",
|
||||
"deleteAdminClass"
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
"school": {
|
||||
"path": "src/modules/school",
|
||||
@@ -4250,7 +4389,12 @@
|
||||
"name": "getAdminDashboardData",
|
||||
"signature": "(scope?: DataScope) => Promise<AdminDashboardData>",
|
||||
"deps": [
|
||||
"shared/db",
|
||||
"users/data-access.getUsersDashboardStats",
|
||||
"classes/data-access.getClassesDashboardStats",
|
||||
"textbooks/data-access.getTextbooksDashboardStats",
|
||||
"questions/data-access.getQuestionsDashboardStats",
|
||||
"exams/data-access.getExamsDashboardStats",
|
||||
"homework/stats-service.getHomeworkDashboardStats",
|
||||
"DataScope"
|
||||
],
|
||||
"usedBy": [
|
||||
@@ -4655,11 +4799,32 @@
|
||||
"shared.db.schema.users"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "getUsersDashboardStats",
|
||||
"signature": "() => Promise<UsersDashboardStats>",
|
||||
"file": "data-access.ts",
|
||||
"deps": [
|
||||
"shared.db",
|
||||
"shared.db.schema.users",
|
||||
"shared.db.schema.sessions",
|
||||
"shared.db.schema.usersToRoles",
|
||||
"shared.db.schema.roles"
|
||||
],
|
||||
"usedBy": [
|
||||
"dashboard/data-access.getAdminDashboardData"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "UserProfile",
|
||||
"type": "type",
|
||||
"file": "data-access.ts",
|
||||
"definition": "{ id, name, email, image, role, phone, address, gender, age, onboardedAt, createdAt, updatedAt }"
|
||||
},
|
||||
{
|
||||
"name": "UsersDashboardStats",
|
||||
"type": "type",
|
||||
"file": "data-access.ts",
|
||||
"definition": "{ userCount, activeSessionsCount, userRoleCounts, recentUsers }"
|
||||
}
|
||||
],
|
||||
"importExport": [
|
||||
@@ -10527,38 +10692,38 @@
|
||||
{
|
||||
"from": "dashboard",
|
||||
"to": "exams",
|
||||
"type": "violation",
|
||||
"description": "直接查询 exams 表(违规)"
|
||||
"type": "data-access",
|
||||
"description": "调用 getExamsDashboardStats 获取考试统计(P0-4 已修复)"
|
||||
},
|
||||
{
|
||||
"from": "dashboard",
|
||||
"to": "homework",
|
||||
"type": "violation",
|
||||
"description": "直接查询 homeworkAssignments/homeworkSubmissions 表(违规)"
|
||||
"type": "data-access",
|
||||
"description": "调用 getHomeworkDashboardStats 获取作业统计(P0-4 已修复)"
|
||||
},
|
||||
{
|
||||
"from": "dashboard",
|
||||
"to": "classes",
|
||||
"type": "violation",
|
||||
"description": "直接查询 classes 表(违规)"
|
||||
"type": "data-access",
|
||||
"description": "调用 getClassesDashboardStats 获取班级统计(P0-4 已修复)"
|
||||
},
|
||||
{
|
||||
"from": "dashboard",
|
||||
"to": "users",
|
||||
"type": "violation",
|
||||
"description": "直接查询 sessions/users/usersToRoles/roles 表(违规)"
|
||||
"type": "data-access",
|
||||
"description": "调用 getUsersDashboardStats 获取用户/会话/角色统计(P0-4 已修复)"
|
||||
},
|
||||
{
|
||||
"from": "dashboard",
|
||||
"to": "textbooks",
|
||||
"type": "violation",
|
||||
"description": "直接查询 textbooks/chapters 表(违规)"
|
||||
"type": "data-access",
|
||||
"description": "调用 getTextbooksDashboardStats 获取教材/章节统计(P0-4 已修复)"
|
||||
},
|
||||
{
|
||||
"from": "dashboard",
|
||||
"to": "questions",
|
||||
"type": "violation",
|
||||
"description": "直接查询 questions 表(违规)"
|
||||
"type": "data-access",
|
||||
"description": "调用 getQuestionsDashboardStats 获取题目统计(P0-4 已修复)"
|
||||
},
|
||||
{
|
||||
"from": "messaging",
|
||||
@@ -10714,7 +10879,10 @@
|
||||
"file": "src/modules/classes/data-access.ts",
|
||||
"lines": 2104,
|
||||
"problem": "混入 homework/scheduling/grades 逻辑,严重违反模块职责单一原则",
|
||||
"suggestion": "按职责拆分为 class-query/schedule/homework-insights/grade-query"
|
||||
"suggestion": "按职责拆分为 class-query/schedule/homework-insights/grade-query",
|
||||
"status": "resolved",
|
||||
"resolvedAt": "2026-06-17",
|
||||
"resolution": "拆分为 5 个文件:data-access.ts(656行,核心CRUD+邀请码+教师班级管理) + data-access-stats.ts(604行,作业统计) + data-access-schedule.ts(230行,课表) + data-access-students.ts(280行,学生查询) + data-access-admin.ts(441行,管理员班级管理),所有文件均 ≤800 行,data-access.ts 通过 re-export 保持向后兼容"
|
||||
},
|
||||
{
|
||||
"id": "P0-2",
|
||||
@@ -10723,7 +10891,10 @@
|
||||
"file": "src/modules/homework/data-access.ts",
|
||||
"lines": 1038,
|
||||
"problem": "混入排名计算业务逻辑",
|
||||
"suggestion": "分离排名逻辑到独立文件(如 data-access-ranking.ts)"
|
||||
"suggestion": "分离排名逻辑到独立文件(如 data-access-ranking.ts)",
|
||||
"status": "resolved",
|
||||
"resolvedAt": "2026-06-17",
|
||||
"resolution": "拆分为 data-access.ts(596行) + stats-service.ts(346行),统计函数(getTeacherGradeTrends/getHomeworkAssignmentAnalytics/getStudentDashboardGrades)迁移至 stats-service.ts,data-access.ts 通过 re-export 保持向后兼容"
|
||||
},
|
||||
{
|
||||
"id": "P0-3",
|
||||
@@ -10739,7 +10910,9 @@
|
||||
"title": "dashboard 跨模块直接查询 11 张表",
|
||||
"file": "src/modules/dashboard/data-access.ts",
|
||||
"problem": "getAdminDashboardData 直查 sessions/users/classes/textbooks/chapters/questions/exams/homeworkAssignments/homeworkSubmissions/usersToRoles/roles,严重违反模块封装",
|
||||
"suggestion": "改为通过各模块 data-access 获取数据"
|
||||
"suggestion": "改为通过各模块 data-access 获取数据",
|
||||
"status": "fixed",
|
||||
"fixedBy": "新增 getUsersDashboardStats/getClassesDashboardStats/getTextbooksDashboardStats/getQuestionsDashboardStats/getExamsDashboardStats/getHomeworkDashboardStats,dashboard 改为并行调用各模块 stats 函数"
|
||||
},
|
||||
{
|
||||
"id": "P0-5",
|
||||
|
||||
@@ -55,7 +55,7 @@
|
||||
|
||||
**当前关键风险项(v3):**
|
||||
|
||||
1. **`classes/data-access.ts` 严重超标** — 2104 行,超出 1000 行硬上限 2 倍,混入 homework/scheduling/grades 三个业务领域逻辑,维护风险极高
|
||||
1. ~~**`classes/data-access.ts` 严重超标**~~ — ✅ 已修复(2026-06-17 拆分为 5 个文件,均 ≤800 行)
|
||||
2. **`shared/lib` ↔ `auth` 循环依赖** — audit-logger/change-logger/auth-guard → @/auth → shared/lib/* 形成循环,影响构建稳定性
|
||||
3. **dashboard 跨模块直接查询 11 张表** — getAdminDashboardData 直查 sessions/users/classes/textbooks 等 11 张表,严重违反模块封装
|
||||
4. **messaging 绕过 notifications 直接写通知** — messaging/actions.ts 直接调用 createNotification,导致用户通知偏好失效
|
||||
@@ -268,8 +268,8 @@
|
||||
|
||||
| 序号 | 问题 | 文件/位置 | 严重程度 | 说明 |
|
||||
|------|------|----------|---------|------|
|
||||
| 1 | 文件超 1000 行硬上限 | `classes/data-access.ts` (2104 行) | 🔴 严重 | 混入 homework/scheduling/grades 三个业务领域逻辑,超出硬上限 2 倍 |
|
||||
| 2 | 文件超 1000 行硬上限 | `homework/data-access.ts` (1038 行) | 🔴 严重 | 混入排名计算业务逻辑,超出硬上限 |
|
||||
| 1 | ~~文件超 1000 行硬上限~~ | ~~`classes/data-access.ts` (2104 行)~~ ✅ | ~~🔴 严重~~ | ~~已修复:拆分为 5 个文件(data-access 656行 + stats 604行 + schedule 230行 + students 280行 + admin 441行)~~ |
|
||||
| 2 | ~~文件超 1000 行硬上限~~ | ~~`homework/data-access.ts` (1038 行)~~ ✅ | ~~🔴 严重~~ | ~~已修复:拆分为 data-access.ts(596行) + stats-service.ts(346行)~~ |
|
||||
| 3 | 文件超 1000 行硬上限 | `shared/db/schema.ts` (1111 行) | 🟡 需改进 | 54 张表混合,可接受但需按业务域分节 |
|
||||
| 4 | 循环依赖 | `shared/lib` ↔ `@/auth` | 🔴 严重 | audit-logger/change-logger/auth-guard → @/auth → shared/lib/* 形成循环 |
|
||||
| 5 | dashboard 跨模块直查 11 张表 | `dashboard/data-access.ts` | 🔴 严重 | getAdminDashboardData 直查 sessions/users/classes 等 11 张表,违反模块封装 |
|
||||
@@ -302,8 +302,8 @@
|
||||
### 4.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 个文件,均 ≤800 行)
|
||||
2. ~~拆分 `homework/data-access.ts`(1038 行 → 分离排名逻辑)~~ ✅ 已完成
|
||||
3. 修复 shared/lib ↔ auth 循环依赖
|
||||
4. dashboard 改为通过各模块 data-access 获取数据
|
||||
5. messaging 写通知改为通过 notifications dispatcher
|
||||
|
||||
@@ -30,8 +30,8 @@
|
||||
|
||||
| 文件 | 行数 | 问题 |
|
||||
|------|------|------|
|
||||
| `classes/data-access.ts` | 2104 | 混入 homework/scheduling/grades 逻辑 |
|
||||
| `homework/data-access.ts` | 1038 | 混入排名计算业务逻辑 |
|
||||
| ~~`classes/data-access.ts`~~ | ~~2104~~ → 656 | ~~混入 homework/scheduling/grades 逻辑~~ ✅ 已拆分为 5 个文件 |
|
||||
| ~~`homework/data-access.ts`~~ | ~~1038~~ → 596 | ~~混入排名计算业务逻辑~~ ✅ 已拆分 |
|
||||
| `shared/db/schema.ts` | 1111 | 54 张表混合(可接受,但需分节) |
|
||||
|
||||
### 2. 循环依赖
|
||||
@@ -114,8 +114,8 @@ NextAuth 配置 + 密码安全 DB 操作 + 角色规范化 + IP 解析 + 回调
|
||||
## 五、解耦优先级
|
||||
|
||||
### 立即执行(P0)
|
||||
1. 拆分 `classes/data-access.ts`(2104 行 → 按职责拆 3-4 个文件)
|
||||
2. 拆分 `homework/data-access.ts`(1038 行 → 分离排名逻辑)
|
||||
1. ~~拆分 `classes/data-access.ts`(2104 行 → 按职责拆 3-4 个文件)~~ ✅ 已完成(拆为 5 个文件,均 ≤800 行)
|
||||
2. ~~拆分 `homework/data-access.ts`(1038 行 → 分离排名逻辑)~~ ✅ 已完成
|
||||
3. 修复 shared/lib ↔ auth 循环依赖
|
||||
4. dashboard 改为通过各模块 data-access 获取数据
|
||||
5. messaging 写通知改为通过 notifications dispatcher
|
||||
|
||||
@@ -43,7 +43,7 @@ app/ ──▶ modules/ ──▶ shared/
|
||||
|
||||
### P0 严重问题(必须立即修复)
|
||||
|
||||
#### P0-1 `classes/data-access.ts` 2104 行,超硬上限 2.1 倍
|
||||
#### P0-1 `classes/data-access.ts` 2104 行,超硬上限 2.1 倍 ✅ 已修复
|
||||
|
||||
**问题**:
|
||||
- 文件行数 2104,远超 1000 行硬上限
|
||||
@@ -58,18 +58,21 @@ app/ ──▶ modules/ ──▶ shared/
|
||||
**解耦方案**:
|
||||
```
|
||||
src/modules/classes/
|
||||
├── data-access.ts # 班级核心 CRUD(目标 ≤500 行)
|
||||
├── data-access-stats.ts # 班级统计查询(getHomeworkStats 等)
|
||||
├── data-access-schedule.ts # 班级课表查询(getClassSchedule 等)
|
||||
└── data-access-grades.ts # 班级成绩汇总(getClassGradeSummary 等)
|
||||
├── data-access.ts # 班级核心 CRUD(656 行)
|
||||
├── data-access-stats.ts # 班级统计查询(604 行)
|
||||
├── data-access-schedule.ts # 班级课表查询(230 行)
|
||||
├── data-access-students.ts # 学生相关查询(280 行)
|
||||
└── data-access-admin.ts # 管理员班级管理(441 行)
|
||||
```
|
||||
|
||||
**迁移步骤**:
|
||||
1. 创建 3 个新文件,按职责迁移对应函数
|
||||
2. 在 `data-access.ts` 中 re-export 以保持向后兼容
|
||||
1. ~~创建 3 个新文件,按职责迁移对应函数~~ ✅ 已创建 4 个新文件
|
||||
2. ~~在 `data-access.ts` 中 re-export 以保持向后兼容~~ ✅ 已完成
|
||||
3. 逐步更新调用方 import 路径
|
||||
4. 最终移除 re-export,强制使用新路径
|
||||
|
||||
**完成状态**:2026-06-17 已完成拆分,所有文件均 ≤800 行,通过 re-export 保持向后兼容
|
||||
|
||||
---
|
||||
|
||||
#### P0-2 `homework/data-access.ts` 1038 行,混入排名计算
|
||||
@@ -380,9 +383,9 @@ src/shared/lib/ai/
|
||||
| 1 | P0-3 修复循环依赖 | shared/lib + auth.ts | 低 |
|
||||
| 2 | P0-5 messaging 改用 dispatcher | messaging + notifications | 低 |
|
||||
| 3 | P0-6 统一 classSchedule 写入口 | classes + scheduling | 中 |
|
||||
| 4 | P0-2 拆分 homework/data-access | homework | 中 |
|
||||
| 4 | ~~P0-2 拆分 homework/data-access~~ ✅ | homework | 中 |
|
||||
| 5 | P0-4 dashboard 改用模块 data-access | dashboard + 11 个模块 | 高 |
|
||||
| 6 | P0-1 拆分 classes/data-access | classes + 多个调用方 | 高 |
|
||||
| 6 | ~~P0-1 拆分 classes/data-access~~ ✅ | classes + 多个调用方 | 高 |
|
||||
|
||||
### 第二阶段:P1 修复(建议 2-4 周)
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
| 模块 | 行数(最大文件) | 职责单一性 | 耦合度 | 严重度 |
|
||||
|------|----------------|-----------|--------|--------|
|
||||
| school | 325 | ✅ 良好 | ✅ 低 | 🟢 合格 |
|
||||
| classes | **2104** | ❌ 严重违反 | ❌ 严重 | 🔴 严重 |
|
||||
| classes | ~~2104~~ → 656 | ✅ 已修复 | ❌ 严重 | 🟡 需改进 |
|
||||
| scheduling | 310(算法)/ 302(actions) | ✅ 算法独立 | ⚠️ 中 | 🟡 需改进 |
|
||||
| attendance | 271 | ✅ 良好 | ⚠️ 中 | 🟢 合格 |
|
||||
| users | 291(import-export) | ❌ 违反 | ❌ 高 | 🟠 较严重 |
|
||||
@@ -21,7 +21,7 @@
|
||||
| announcements | 242 | ⚠️ 部分违反 | ✅ 低 | 🟡 需改进 |
|
||||
|
||||
**核心结论**:
|
||||
1. `classes` 模块是全项目耦合最严重的模块,单文件 2104 行远超 1000 行硬性上限,混入了 schedule、homework、grades 三个业务领域的逻辑。
|
||||
1. ~~`classes` 模块是全项目耦合最严重的模块,单文件 2104 行远超 1000 行硬性上限,混入了 schedule、homework、grades 三个业务领域的逻辑。~~ ✅ 已修复(2026-06-17 拆分为 5 个文件,均 ≤800 行)
|
||||
2. `users/import-export.ts` 违反单一职责,同时处理导入、导出、用户创建、班级注册四类逻辑。
|
||||
3. `scheduling/auto-scheduler.ts` 是算法独立化的**优秀范例**,纯函数、无 DB 访问、可独立测试。
|
||||
4. `announcements` 和 `audit` 模块的 data-access 层不完整,写操作或导出逻辑泄漏到 actions 层。
|
||||
@@ -49,11 +49,11 @@
|
||||
|
||||
---
|
||||
|
||||
### 2.2 classes 模块 — 🔴 严重
|
||||
### 2.2 classes 模块 — 🟡 需改进(文件拆分已修复,跨模块耦合仍存在)
|
||||
|
||||
**文件清单**:actions.ts (765 行) / data-access.ts (**2104 行**) / types.ts (201 行)
|
||||
**文件清单**:actions.ts (765 行) / data-access.ts (656 行) / data-access-stats.ts (604 行) / data-access-schedule.ts (230 行) / data-access-students.ts (280 行) / data-access-admin.ts (441 行) / types.ts (201 行)
|
||||
|
||||
> ⚠️ `data-access.ts` 达 2104 行,**超出 1000 行硬性上限 2 倍**,违反项目代码质量规则。
|
||||
> ✅ `data-access.ts` 已于 2026-06-17 拆分为 5 个文件,所有文件均 ≤800 行,通过 re-export 保持向后兼容。
|
||||
|
||||
#### 2.2.1 职责混乱 — 混入三个外部业务领域
|
||||
|
||||
|
||||
Reference in New Issue
Block a user