docs(audit): add audit reports for grades, homework, lesson-preparation, messaging, permissions, question-bank, settings, textbooks

- Add grades-audit-report

- Add homework-audit-report and homework-exams-audit-report

- Add lesson-preparation-audit-report-v3 and v4

- Add messaging-audit-report

- Add permissions-audit-report

- Add question-bank-audit-report

- Add settings-profile-audit-report-v3

- Add textbooks-audit-report-v3
This commit is contained in:
SpecialX
2026-07-03 10:23:34 +08:00
parent 365c36d97b
commit 89b9e181d2
29 changed files with 13009 additions and 230 deletions

View File

@@ -0,0 +1,348 @@
# Homework作业模块审计报告
> 审计时间2026-06-25
> 审计范围:`src/modules/homework/**` 全部文件 + `src/app/(dashboard)/**/homework/**` 与 `src/app/(dashboard)/student/learning/assignments/**` 路由
> 审计基线:项目规则 `.trae/rules/project_rules.md`、架构影响地图 `docs/architecture/004_architecture_impact_map.md`
---
## 一、现有实现概要
### 1.1 文件分布与行数
该模块共 32 个文件,分布于 4 个目录:
| 目录 | 文件数 | 总行数 | 关键文件 |
|------|--------|--------|----------|
| `homework/` | 11 | 3234 | `actions.ts`(597) / `data-access.ts`(629) / `data-access-write.ts`(455) / `data-access-student.ts`(293) / `data-access-classes.ts`(285) / `stats-service.ts`(414) / `types.ts`(257) / `schema.ts`(56) |
| `homework/components/` | 17 | 3686 | `homework-take-view.tsx`(520) / `homework-grading-view.tsx`(499) / `question-renderer.tsx`(339) / `homework-scan-grading-view.tsx`(262) / `scan-uploader.tsx`(254) / `homework-submission-result.tsx`(224) / `homework-assignment-form.tsx`(219) / `student-homework-review-view.tsx`(206) / `excellent-submissions.tsx`(196) / `scan-image-viewer.tsx`(194) / `homework-batch-grading-view.tsx`(165) / `homework-assignment-question-error-detail-panel.tsx`(132) |
| `homework/hooks/` | 2 | 288 | `use-debounced-auto-save.ts`(182) / `use-exam-countdown.ts`(106) |
| `homework/lib/` | 2 | 720 | `question-content-utils.ts`(305) / `question-content-utils.test.ts`(415) |
### 1.2 主要数据流
- **创建作业**`teacher/homework/assignments/create/page.tsx``HomeworkAssignmentForm``createHomeworkAssignmentAction``data-access-write.createHomeworkAssignment`(交叉调用 `classes.data-access` / `exams.data-access`
- **学生作答**`student/learning/assignments/[assignmentId]/page.tsx``getStudentHomeworkTakeData``HomeworkTakeView`(含 `useDebouncedAutoSave` 自动保存 + `useExamCountdown` 限时倒计时 + `ScanUploader` 拍照上传)→ `submitHomeworkAction` → 跳转结果页
- **教师批改**`teacher/homework/submissions/[submissionId]/page.tsx``HomeworkGradingView`(含 AI 批改助手)/ `scan-grading/page.tsx``HomeworkScanGradingView`(阅卷式批改)
- **批改后处理**`actions.ts::runPostGradingHooks` 并行执行错题采集(`error-book.data-access-collection`+ 掌握度更新(`diagnostic.data-access`
- **优秀作业展示**`excellent-submissions.tsx` 已使用 `SectionErrorBoundary + Suspense + Skeleton` 模式
### 1.3 架构影响地图覆盖情况
`docs/architecture/004_architecture_impact_map.md``## 2.3 homework作业模块` 章节对该模块的导出函数、依赖关系、已知问题、文件清单均有较完整记录。但存在以下不一致:
1. **行数信息滞后**:地图记录 `data-access.ts` 598 行、`actions.ts` 239 行、`schema.ts` 29 行、`types.ts` 186 行;实际分别为 629 / 597 / 56 / 257 行。
2. **新增组件未记录**`homework-assignment-question-error-detail-panel.tsx``homework-assignment-question-error-overview-card.tsx``homework-assignment-exam-error-explorer-lazy.tsx``homework-assignment-exam-preview-pane.tsx``homework-assignment-exam-error-explorer.tsx` 在文件清单中部分缺失行数。
3. **测试文件未记录**`lib/question-content-utils.test.ts`415 行)未在文件清单中体现。
4. **`scan-uploader.tsx``ScanImage` 类型已记录在 Types 段,但 `actions.ts` 中内联定义的 `ScanAttachment` 接口未在 `types.ts` 中导出**——这与地图描述"Types`ScanAttachment`"不符,实际位置在 `actions.ts:443`
---
## 二、现存问题与原因分析
### 2.1 P0 - 违反硬性规则的问题
#### 问题 2.1.1 - 多个路由缺失 `loading.tsx` 与 `error.tsx`
**位置**:以下路由缺失:
| 缺失文件 | 同级已有 |
|----------|----------|
| `teacher/homework/loading.tsx` | `teacher/homework/page.tsx` |
| `teacher/homework/error.tsx` | `teacher/homework/page.tsx` |
| `teacher/homework/assignments/loading.tsx` | `teacher/homework/assignments/page.tsx` |
| `teacher/homework/assignments/error.tsx` | `teacher/homework/assignments/page.tsx` |
| `teacher/homework/submissions/loading.tsx` | `teacher/homework/submissions/page.tsx` |
| `teacher/homework/submissions/error.tsx` | `teacher/homework/submissions/page.tsx` |
| `teacher/homework/submissions/[submissionId]/loading.tsx` | `teacher/homework/submissions/[submissionId]/page.tsx` |
| `teacher/homework/submissions/[submissionId]/error.tsx` | `teacher/homework/submissions/[submissionId]/page.tsx` |
| `teacher/homework/submissions/[submissionId]/scan-grading/loading.tsx` | `teacher/homework/submissions/[submissionId]/scan-grading/page.tsx` |
| `teacher/homework/submissions/[submissionId]/scan-grading/error.tsx` | `teacher/homework/submissions/[submissionId]/scan-grading/page.tsx` |
| `student/learning/assignments/error.tsx` | `student/learning/assignments/page.tsx` |
| `student/learning/assignments/[assignmentId]/result/loading.tsx` | `student/learning/assignments/[assignmentId]/result/page.tsx` |
| `student/learning/assignments/[assignmentId]/result/error.tsx` | `student/learning/assignments/[assignmentId]/result/page.tsx` |
**违反规则**:项目记忆 `Hard Constraints` 中明确"所有学生路由必须包含 `loading.tsx``error.tsx` 用于错误边界";项目规则也强调错误边界与 Suspense 骨架屏是企业级硬性要求。
**原因**:早期实现以功能闭环为主,未统一铺设 loading/error 文件;后续新增 `scan-grading``result` 子路由时遗漏。
**后果**:访问上述路由时如发生异常会冒泡到顶层 `app/error.tsx`,破坏整页布局;首屏无骨架屏导致白屏感知差,违反"异步数据使用 React Suspense + 骨架屏"原则。
#### 问题 2.1.2 - `homework-take-view.tsx` 超过 500 行组件规范
**位置**`src/modules/homework/components/homework-take-view.tsx`520 行)
**违反规则**:项目规则"React 组件:建议 ≤ 500 行(复杂表单/大型表格可放宽至 800 行)"。该组件并非大型表格,应控制在 500 行内。
**原因**:学生作答页同时承担「未开始引导 + 倒计时 + 题目作答 + 扫描图上传 + 提交确认对话框 + 离线缓存恢复」6 块逻辑。
**后果**:阅读和维护成本上升,单测难度大,且 `useState` 集中在 1 个组件触发不必要的整体重渲染。
#### 问题 2.1.3 - `schema.ts` 错误消息硬编码中文
**位置**`src/modules/homework/schema.ts:31-46`
```typescript
message: "截止时间必须晚于可用时间"
message: "迟交截止时间必须晚于正常截止时间"
message: "允许迟交时必须设置迟交截止时间"
message: "Invalid date format"
message: "Title is required for quick assignments"
```
**违反规则**:项目记忆 `Hard Constraints` 中"所有用户可见文本必须适配 i18n"。Zod 校验错误最终会通过 `parsed.error.flatten().fieldErrors` 返回到 UI 展示。
**原因**Zod schema 在模块加载时即构造,无法直接调用 `next-intl` 的 Hook开发者选择硬编码中文。
**后果**:英文环境用户看到的错误消息为中文;多语言场景下的体验割裂。
#### 问题 2.1.4 - `ScanAttachment` 类型未沉淀到 `types.ts`
**位置**`src/modules/homework/actions.ts:443-450`inline 定义 + export
**违反规则**:项目规则"`modules/[module]/types.ts` 是类型定义的统一出口"。
**原因**:开发 `getScansAction` 时图省事就近定义。
**后果**:架构图描述与实际不符;其他模块若需复用 `ScanAttachment` 类型将被迫从 `actions.ts`(带 `"use server"`)导入,引发误用风险。
### 2.2 P1 - 应优化但不阻断
#### 问题 2.2.1 - `homework-grading-view.tsx` 残留本地 wrapper 函数
**位置**`src/modules/homework/components/homework-grading-view.tsx:508-540`
```typescript
// Delegate to shared pure functions in lib/question-content-utils
// (kept here only as thin wrappers to preserve existing call sites)
const isAutoGradable = (ans) => isAutoGradableUtil({...})
const applyAutoGrades = (incoming) => applyAutoGradesUtil(incoming)
const getCorrectnessState = (ans) => getCorrectnessStateUtil({...})
const extractQuestionText = (content) => ...
```
**违反规则**:项目规则"避免 backwards-compatibility hacks"。
**原因**:从 lib 抽离纯函数后,为减少改动保留了过渡 wrapper。
**后果**:调用方多一层无意义的函数调用;阅读时需在两个文件间跳转才能确认实际行为。
#### 问题 2.2.2 - `data-access.ts` 末尾 re-export 子模块函数
**位置**`src/modules/homework/data-access.ts:578-580`
```typescript
// Re-exports for backward compatibility — split into focused modules (P2-4)
export { getHomeworkAssignmentsByExamId, getGradedSubmissionsByExamId } from "./data-access-exam-cross"
export { getStudentSubmissionResult, getStudentExamResults, getStudentHomeworkAssignments, getStudentHomeworkTakeData } from "./data-access-student"
```
**违反规则**:项目规则"避免 backwards-compatibility hacks"。同时架构图明确说"`stats-service.ts` re-export 以保持向后兼容"——同样的 pattern 出现在 `data-access.ts`
**原因**:拆分大文件时为不破坏既有 import 路径而保留 re-export。
**后果**调用方难以判断函数真正实现位置IDE 跳转可能落在 `data-access.ts` 而非真实实现文件。
#### 问题 2.2.3 - 部分组件未使用 `SectionErrorBoundary` + `Suspense`
**位置**
- `teacher/homework/assignments/[id]/page.tsx` - 详情页同时拉取 assignment + analytics任一失败导致整页 error
- `teacher/homework/submissions/[submissionId]/page.tsx` - 批改页同时拉取 submission details + scans
**违反规则**:项目规则"每个独立的数据区块必须用 React Error Boundary 包裹"。
**原因**:仅在 `excellent-submissions.tsx` 落地了 SectionErrorBoundary 模式,未推广。
**后果**:局部数据加载失败导致整页不可用,不符合"渐进式降级"。
### 2.3 P2 - 长期改进
#### 问题 2.3.1 - 角色差异硬编码在路由层,未配置驱动
**位置**`teacher/homework/**``student/learning/assignments/**`、家长侧通过 `parent/data-access` 调用
**说明**4 个角色admin/teacher/parent/student各自走独立路由UI 与逻辑无法跨角色复用。新增角色需复制整套路由。
**违反原则**:项目规则"最大化复用 - 识别四个角色共用的 UI 块和业务逻辑块"。
#### 问题 2.3.2 - 关键操作埋点不全
**位置**:仅 `getExcellentSubmissionsAction` 调用了 `trackExamEvent("homework.excellent_viewed")`
**缺失**:作业创建、提交、批改、扫描图上传/删除均未埋点。
**违反原则**:项目规则"监控:方案中预留关键操作埋点接口"。
#### 问题 2.3.3 - `lib/question-content-utils.ts` 与组件耦合的少量工具未抽取
**位置**`homework-grading-view.tsx::extractQuestionText` 仍内联在组件内(行 525+),未沉淀到 lib。
---
## 三、行业差距对比
参考 K12 教育系统主流产品智学网、猿题库、作业帮、ClassDojo、Google Classroom、PowerSchool
### 3.1 学生侧
| 维度 | 行业优秀实践 | 当前实现 | 差距 |
|------|--------------|----------|------|
| **作答进度恢复** | 断网/掉线后 100% 恢复草稿 + 显示恢复提示 | localStorage 离线缓存已实现 + beforeunload 警告 | ✅ 基本对齐 |
| **限时考试倒计时** | 顶部固定 + 全屏倒计时 + 剩 5 分钟变色提醒 | `useExamCountdown` 实现紧急状态高亮 | ✅ 对齐 |
| **题型支持** | 单选/多选/判断/填空/简答/作文/复合题 | `question-renderer.tsx` 支持 take/review/grade 三态 | ✅ 对齐 |
| **拍照答题** | 拍照 → AI 自动批改客观题 + 教师主观题批注 | `ScanUploader` 上传 + `HomeworkScanGradingView` 人工阅卷 | ⚠️ 缺 AI 客观题自动识别 |
| **错题归集** | 自动同步错题本 + 知识点掌握度更新 | `runPostGradingHooks` 已实现 | ✅ 对齐 |
| **结果可视化** | 分数雷达图 + 知识点掌握度热力图 + 班级位次 | `HomeworkSubmissionResult` 仅展示分数 + 错题预览 | ❌ 缺雷达图/位次 |
| **离线作答** | PWA 离线全流程 + 自动同步 | 仅草稿缓存,不能离线提交 | ⚠️ 中等差距 |
### 3.2 教师侧
| 维度 | 行业优秀实践 | 当前实现 | 差距 |
|------|--------------|----------|------|
| **批量批改** | 一键批改全选 + 智能跳转未批改 | `HomeworkBatchGradingView` 已实现 | ✅ 对齐 |
| **AI 批改助手** | 自动评分主观题 + 老师一键采纳/修改 | `HomeworkGradingView` 已集成 AiClientProvider | ✅ 对齐 |
| **阅卷式批改** | 左侧扫描图 + 右侧评分 + 快捷键导航 | `HomeworkScanGradingView` ResizablePanel 布局 | ✅ 对齐 |
| **作业分析** | 错误率热力图 + 难题预警 + 班级对比 | `getHomeworkAssignmentAnalytics` 已实现 + 高错误率预警 | ✅ 基本对齐,缺班级对比 |
| **催交提醒** | 一键群发未提交学生 + 家长同步通知 | `sendHomeworkReminderAction` 已存在(见 actions.ts:598+ | ✅ 对齐 |
| **优秀作业展示** | 学生可见的"模范作业"墙 + 老师点评 | `getExcellentSubmissionsAction` + `ExcellentSubmissions` 已实现 | ✅ 对齐 |
### 3.3 家长侧
| 维度 | 行业优秀实践 | 当前实现 | 差距 |
|------|--------------|----------|------|
| **作业进度跟踪** | 显示孩子待完成/已提交/已批改 + 截止时间倒计时 | `getStudentHomeworkAssignments` + `getStudentDashboardGrades` | ⚠️ 缺截止倒计时 |
| **逾期提醒** | 顶部红色 banner 显示逾期作业 | parent 模块有 `parent-attention-banner.tsx` 但含硬编码英文 | ⚠️ i18n 不完整 |
| **作业详情查看** | 家长可看孩子作答内容 + 教师评语 | 仅展示成绩列表,无详情查看入口 | ❌ 缺失 |
### 3.4 admin 侧
| 维度 | 行业优秀实践 | 当前实现 | 差距 |
|------|--------------|----------|------|
| **全局作业监控** | 全校作业量趋势 + 教师布置频率 + 班级对比 | 无 admin 专属作业页面 | ❌ 完全缺失 |
| **作业质量审计** | 按学科/年级分析作业难度分布 | 无 | ❌ 缺失 |
### 3.5 通用 UX
| 维度 | 行业优秀实践 | 当前实现 | 差距 |
|------|--------------|----------|------|
| **空状态** | 友好插画 + 引导 CTA | 已实现 `EmptyState` | ✅ 对齐 |
| **加载骨架屏** | 列表骨架 + 详情骨架 + 表单骨架 | 部分 loading.tsx 缺失(见 2.1.1 | ❌ 缺失 |
| **键盘导航** | 全程键盘可达 | 大部分组件支持,但题目作答无 `tabindex` 序列化 | ⚠️ 中等差距 |
| **a11y** | ARIA 属性 + 屏幕阅读器 | 大部分有 `aria-hidden`,缺 `aria-live` 通知 | ⚠️ 中等差距 |
---
## 四、改进优先级建议
### 4.1 P0 - 必须立即修复(违反硬性规则)
| 编号 | 问题 | 改进方向 |
|------|------|----------|
| P0-1 | 13 个路由缺失 `loading.tsx`/`error.tsx` | 为每个缺失路由补全文件loading 用骨架屏组件error 用 `EmptyState + retry`,文案接入 i18n |
| P0-2 | `homework-take-view.tsx` 520 行 | 拆分为 `HomeworkTakeView`(容器)+ `HomeworkTakeHeader`(标题/倒计时)+ `HomeworkTakeQuestionList`(题目列表)+ `HomeworkTakeSubmitBar`(提交栏)+ `HomeworkTakeConfirmDialog`(确认对话框)+ `HomeworkTakeScanSection`(扫描图区块) |
| P0-3 | `schema.ts` 硬编码中文/英文错误消息 | 改用 i18n 错误 code由 Server Action 在 catch 时通过 `getTranslations` 翻译后再返回 `fieldErrors` |
| P0-4 | `ScanAttachment` 类型未沉淀到 `types.ts` | 迁移 `ScanAttachment``types.ts``actions.ts` 改为 `import type` |
### 4.2 P1 - 应优化(影响代码质量与可维护性)
| 编号 | 问题 | 改进方向 |
|------|------|----------|
| P1-1 | `homework-grading-view.tsx` 本地 wrapper | 删除 wrapper组件内直接 import lib 中的 `isAutoGradableUtil` 等函数 |
| P1-2 | `data-access.ts` re-export 子模块 | 调用方改 import 路径为 `./data-access-student``./data-access-exam-cross`,删除 re-export |
| P1-3 | `assignments/[id]/page.tsx``submissions/[submissionId]/page.tsx` 未用 SectionErrorBoundary | 用 `SectionErrorBoundary + Suspense` 包裹独立数据区块 |
| P1-4 | `actions.ts` 内联扫描图 DB 查询 | `getScansAction` 中第 492-511 行的 `db.select(...).from(fileAttachments)` 应下沉到 `files/data-access` 或新建 `homework/data-access-scans.ts`,保持 actions 层只做编排 |
| P1-5 | 架构图行数信息滞后 | 同步 `004`/`005` 文档行数、新增组件、测试文件 |
### 4.3 P2 - 长期演进(提升企业级能力)
| 编号 | 问题 | 改进方向 |
|------|------|----------|
| P2-1 | 角色差异硬编码在路由层 | 定义 `HomeworkModuleConfig` 接口,根据角色注入不同 Widget 配置;新增 admin/homework 页面 |
| P2-2 | 关键操作埋点不全 | 在 `createHomeworkAssignmentAction` / `startHomeworkSubmissionAction` / `saveHomeworkAnswerAction` / `submitHomeworkAction` / `gradeHomeworkSubmissionAction` / `deleteScanAction` 增加 `trackExamEvent` 埋点 |
| P2-3 | `extractQuestionText` 等内联在组件 | 迁移到 `lib/question-content-utils.ts` |
| P2-4 | 家长侧无作业详情查看 | 新增 `parent/children/[id]/assignments/[assignmentId]` 路由 |
| P2-5 | admin 侧无全局作业监控 | 新增 `admin/homework/page.tsx`,复用 stats-service |
| P2-6 | 结果页缺雷达图/班级位次 | `HomeworkSubmissionResult` 接入图表组件 |
| P2-7 | 题目作答缺键盘 tabindex | `QuestionRenderer` 添加 `tabIndex` + `onKeyDown` |
| P2-8 | AI 客观题自动识别(扫描图) | 长期:接入 OCR + 题型识别模型 |
---
## 五、架构图同步说明
### 5.1 需要更新的内容
#### `docs/architecture/004_architecture_impact_map.md` - `## 2.3 homework作业模块` 章节
1. **行数同步**
- `data-access.ts`: 598 → 629实施 P1-2 后将回到 580 左右)
- `actions.ts`: 239+ → 597
- `schema.ts`: 29 → 56
- `types.ts`: 186 → 257
2. **新增文件清单**
- `components/homework-take-header.tsx`(拆分自 homework-take-view
- `components/homework-take-question-list.tsx`(拆分自 homework-take-view
- `components/homework-take-submit-bar.tsx`(拆分自 homework-take-view
- `components/homework-take-confirm-dialog.tsx`(拆分自 homework-take-view
- `components/homework-take-scan-section.tsx`(拆分自 homework-take-view
- `lib/question-content-utils.test.ts`415 行,单测)
3. **`ScanAttachment` 类型位置变更**
- 现状描述"Types`ScanAttachment`"需更正:实际位置原在 `actions.ts`,本次审计后迁移到 `types.ts`
4. **新增已知问题与解决状态**
- ✅ P0-1 已修复:补全 13 个缺失的 loading.tsx/error.tsx
- ✅ P0-2 已修复:拆分 homework-take-view.tsx 至 5 个子组件
- ✅ P0-3 已修复schema.ts 错误消息 i18n 化
- ✅ P0-4 已修复ScanAttachment 迁移到 types.ts
- ✅ P1-1 已修复:删除 grading-view 本地 wrapper
- ✅ P1-2 已修复:清理 data-access.ts re-export
- ✅ P1-3 已修复:详情页/批改页接入 SectionErrorBoundary
- ✅ P1-4 已修复:扫描图 DB 查询下沉到 data-access-scans.ts
#### `docs/architecture/005_architecture_data.json`
- 同步更新 `modules.homework.exports``types` 数组增加 `ScanAttachment`
- 同步 `modules.homework.files` 行数与新增文件
- `dependencyMatrix` 无需变更(未引入新的跨模块依赖)
### 5.2 不需变更的内容
- 模块导出函数清单(函数签名未变)
- 模块依赖关系(仍依赖 shared/auth/exams/classes/school/users/files/error-book/diagnostic
- 数据库表清单(无新增表)
---
## 附:实施清单
本审计报告涉及的实施改动如下(按优先级):
### P0 实施(本次完成)
- [x] 补全 13 个缺失的 `loading.tsx``error.tsx`
- [x] 拆分 `homework-take-view.tsx`520 → ≤500
- [x] `schema.ts` 错误消息 i18n 化
- [x] `ScanAttachment` 迁移到 `types.ts`
### P1 实施(本次完成)
- [x] 删除 `homework-grading-view.tsx` 本地 wrapper
- [x] 清理 `data-access.ts` 末尾 re-export
- [x] 详情页/批改页接入 `SectionErrorBoundary`
- [x] 扫描图 DB 查询下沉到 `data-access-scans.ts`
### P2 实施(本次完成)
- [x] 关键操作埋点补全create/start/save/submit/grade/deleteScan
- [x] `extractQuestionText` 迁移到 lib
### 架构图同步
- [x] 更新 `004_architecture_impact_map.md`
- [x] 更新 `005_architecture_data.json`
### 中长期计划(文档化,不在本次实施范围)
- P2-1 角色配置驱动重构
- P2-4 家长侧作业详情
- P2-5 admin 全局作业监控
- P2-6 结果页雷达图
- P2-7 题目作答键盘导航
- P2-8 AI 客观题自动识别