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,301 @@
# 学情诊断Diagnostic模块审计报告
> 审计日期2026-06-22
> 审计范围:`src/modules/diagnostic/**`、`src/app/(dashboard)/teacher/diagnostic/**`、`src/app/(dashboard)/student/diagnostic/**`、`src/app/(dashboard)/parent/diagnostic/**`
> 参照规则:`docs/architecture/004_architecture_impact_map.md` §2.22、`docs/architecture/005_architecture_data.json`、`.trae/rules/project_rules.md`
> 前置文档:[grades-diagnostic-audit-report-v4.md](./grades-diagnostic-audit-report-v4.md)v4 已完成 12 项 P1 数据安全修复)
---
## 一、现有实现概要
### 1.1 文件分布
| 层 | 文件 | 行数 | 职责 |
|------|------|------|------|
| 类型 | [types.ts](file:///e:/Desktop/CICD/src/modules/diagnostic/types.ts) | 109 | DiagnosticReport / Mastery / Summary 类型定义 |
| 数据访问 | [data-access.ts](file:///e:/Desktop/CICD/src/modules/diagnostic/data-access.ts) | 477 | 掌握度查询 + 从提交/成绩更新掌握度 |
| 数据访问 | [data-access-reports.ts](file:///e:/Desktop/CICD/src/modules/diagnostic/data-access-reports.ts) | 256 | 诊断报告 CRUD + DataScope 过滤 |
| 统计服务 | [stats-service.ts](file:///e:/Desktop/CICD/src/modules/diagnostic/stats-service.ts) | 388 | 12 个纯统计函数 |
| Server Actions | [actions.ts](file:///e:/Desktop/CICD/src/modules/diagnostic/actions.ts) | 274 | 5 个 Action生成/发布/删除/导出/按知识点筛选) |
| 校验 | [schema.ts](file:///e:/Desktop/CICD/src/modules/diagnostic/schema.ts) | 31 | 4 个 Zod schema |
| 导出 | [export.ts](file:///e:/Desktop/CICD/src/modules/diagnostic/export.ts) | 122 | Excel 导出 |
| 组件 | [components/class-diagnostic-view.tsx](file:///e:/Desktop/CICD/src/modules/diagnostic/components/class-diagnostic-view.tsx) | 448 | 班级诊断视图(热力图+筛选+排名+关注列表+生成) |
| 组件 | [components/student-diagnostic-view.tsx](file:///e:/Desktop/CICD/src/modules/diagnostic/components/student-diagnostic-view.tsx) | 293 | 学生诊断视图(概览+雷达+强弱项+报告+历史) |
| 组件 | [components/report-list.tsx](file:///e:/Desktop/CICD/src/modules/diagnostic/components/report-list.tsx) | 445 | 报告列表(过滤+表格+发布/删除/导出/分享) |
| 组件 | [components/mastery-radar-chart.tsx](file:///e:/Desktop/CICD/src/modules/diagnostic/components/mastery-radar-chart.tsx) | 85 | 雷达图封装 |
| 组件 | [components/confidence-utils.ts](file:///e:/Desktop/CICD/src/modules/diagnostic/components/confidence-utils.ts) | 31 | 置信度计算 |
| 页面 | [teacher/diagnostic/page.tsx](file:///e:/Desktop/CICD/src/app/(dashboard)/teacher/diagnostic/page.tsx) | 67 | 教师报告列表页 |
| 页面 | [teacher/diagnostic/student/[studentId]/page.tsx](file:///e:/Desktop/CICD/src/app/(dashboard)/teacher/diagnostic/student/[studentId]/page.tsx) | 86 | 教师查看学生诊断 |
| 页面 | [teacher/diagnostic/class/[classId]/page.tsx](file:///e:/Desktop/CICD/src/app/(dashboard)/teacher/diagnostic/class/[classId]/page.tsx) | 50 | 教师班级诊断 |
| 页面 | [student/diagnostic/page.tsx](file:///e:/Desktop/CICD/src/app/(dashboard)/student/diagnostic/page.tsx) | 40 | 学生自我诊断 |
| 页面 | [parent/diagnostic/page.tsx](file:///e:/Desktop/CICD/src/app/(dashboard)/parent/diagnostic/page.tsx) | 128 | 家长多子女诊断 |
| 骨架屏 | 5 个 `loading.tsx` | — | 各路由骨架屏 |
| 错误边界 | 5 个 `error.tsx` | — | 各路由错误边界 |
| i18n | [diagnostic.json](file:///e:/Desktop/CICD/src/shared/i18n/messages/zh-CN/diagnostic.json) | 204 | 中文翻译 |
### 1.2 数据流
```
page.tsx (RSC)
├─ getStudentMasterySummary / getClassMasterySummary / getKnowledgePointStats (data-access)
│ └─ db (drizzle) → knowledgePointMastery / knowledgePoints 表
├─ getDiagnosticReports (data-access-reports, 含 DataScope 过滤)
│ └─ db → learningDiagnosticReports 表
└─ <StudentDiagnosticView> / <ClassDiagnosticView> / <ReportList> (client)
└─ generateStudentReportAction / generateClassReportAction / publishReportAction / deleteReportAction / exportDiagnosticReportAction / getClassStudentsByKnowledgePointAction
```
### 1.3 架构图记录完整性
经核对 [004_architecture_impact_map.md](file:///e:/Desktop/CICD/docs/architecture/004_architecture_impact_map.md) §2.22 与 [005_architecture_data.json](file:///e:/Desktop/CICD/docs/architecture/005_architecture_data.json),架构图对诊断模块的记录**基本完整**,但存在以下偏差:
- 行数统计略有滞后:图记 `data-access.ts 179 行`,实际为 477 行(含 `updateMasteryFromHomeworkSubmission``updateMasteryFromExamScore` 两个大函数)。
- 未记录 `export.ts` 的存在(架构图文件清单缺少此文件)。
- 未记录 `confidence-utils.ts` 组件文件。
- 未记录跨模块 UI 依赖:`teacher/diagnostic/student/[studentId]/page.tsx``teacher/diagnostic/class/[classId]/page.tsx` 直接 import `@/modules/grades/components/widget-boundary`,架构图未标注此跨模块 UI 依赖。
---
## 二、现存问题与原因分析
### 2.1 架构解耦
#### 问题 2.1.1 跨模块直接 import UI 组件 WidgetBoundaryP0
- **位置**
- [teacher/diagnostic/student/[studentId]/page.tsx#L13](file:///e:/Desktop/CICD/src/app/(dashboard)/teacher/diagnostic/student/[studentId]/page.tsx#L13)
- [teacher/diagnostic/class/[classId]/page.tsx#L8](file:///e:/Desktop/CICD/src/app/(dashboard)/teacher/diagnostic/class/[classId]/page.tsx#L8)
- **现象**`import { WidgetBoundary } from "@/modules/grades/components/widget-boundary"`
- **违反规则**:项目规则"模块间只能通过对方 data-access 通信,禁止跨模块直接查询数据库表"的精神延伸——UI 组件跨模块直接 import 同样破坏模块独立性。WidgetBoundary 是通用错误边界组件,不应属于 grades 业务模块。
- **原因**WidgetBoundary 最初为 grades 模块创建diagnostic 模块复用时直接 import 了 grades 模块的实现,而非将其提升到 shared 层。
- **后果**grades 模块对 WidgetBoundary 的任何变更重命名、删除、props 修改)都会破坏 diagnostic 模块编译diagnostic 模块无法独立测试、独立部署。
#### 问题 2.1.2 组件直接 import actions无服务接口抽象P1
- **位置**
- [components/report-list.tsx#L42](file:///e:/Desktop/CICD/src/modules/diagnostic/components/report-list.tsx#L42)`import { publishReportAction, deleteReportAction, exportDiagnosticReportAction } from "../actions"`
- [components/class-diagnostic-view.tsx#L33](file:///e:/Desktop/CICD/src/modules/diagnostic/components/class-diagnostic-view.tsx#L33)`import { generateClassReportAction, getClassStudentsByKnowledgePointAction } from "../actions"`
- **现象**:客户端组件直接 import 并调用 Server Actions未通过接口抽象或依赖注入。
- **违反规则**:项目规则"通过定义 TypeScript 接口抽象数据依赖,使用 React Context 注入数据服务,模块内部组件绝不直接 import 其他业务模块的 actions 或 data-access"。
- **原因**:模块未采用依赖注入模式,组件与 actions 紧耦合。
- **后果**:组件无法独立测试(测试时必须 mock 整个 actions 模块);无法在不修改组件代码的情况下替换 actions 实现。
### 2.2 国际化
#### 问题 2.2.1 教师页面标题硬编码英文P0
- **位置**
- [teacher/diagnostic/page.tsx#L59-62](file:///e:/Desktop/CICD/src/app/(dashboard)/teacher/diagnostic/page.tsx#L59)`<h1>Learning Diagnostic</h1>` + `<p>View and manage diagnostic reports based on knowledge point mastery.</p>`
- [teacher/diagnostic/student/[studentId]/page.tsx#L70-74](file:///e:/Desktop/CICD/src/app/(dashboard)/teacher/diagnostic/student/[studentId]/page.tsx#L70)`Student Diagnostic` + `Knowledge point mastery analysis and diagnostic reports.`
- [teacher/diagnostic/class/[classId]/page.tsx#L38-42](file:///e:/Desktop/CICD/src/app/(dashboard)/teacher/diagnostic/class/[classId]/page.tsx#L38)`Class Diagnostic` + `Class-level knowledge point mastery overview and student attention list.`
- **违反规则**:项目规则"所有用户可见文本必须适配 i18n使用 next-intl提取翻译键"。
- **原因**:教师端 3 个页面未使用 `getTranslations` 获取翻译,直接硬编码英文文案。学生端和家端已正确使用 i18n。
- **后果**:中文环境下教师看到英文标题,与系统其他页面风格不一致。
#### 问题 2.2.2 teacher/diagnostic/error.tsx 硬编码中文P0
- **位置**[teacher/diagnostic/error.tsx#L17-22](file:///e:/Desktop/CICD/src/app/(dashboard)/teacher/diagnostic/error.tsx#L17)
- **现象**`title="学情诊断页面加载失败"` `description="抱歉,页面加载时发生了意外错误。请稍后重试。"` `label="重试"` 全部硬编码。
- **违反规则**:项目规则"所有用户可见文本必须适配 i18n"。
- **原因**error.tsx 是客户端组件但未使用 `useTranslations`
- **后果**:英文环境下错误页显示中文,国际化不一致。对比 student/diagnostic/error.tsx 已正确使用 i18n。
#### 问题 2.2.3 parent/diagnostic/page.tsx 错误卡片中英文混用P1
- **位置**[parent/diagnostic/page.tsx#L116-119](file:///e:/Desktop/CICD/src/app/(dashboard)/parent/diagnostic/page.tsx#L116)
- **现象**`{t("error.loadFailed")} for {item.studentName}.``Please refresh the page or contact the school administrator if the problem persists.` 混用 i18n key 和硬编码英文。
- **违反规则**:项目规则"所有用户可见文本必须适配 i18n"。
- **后果**:中文环境下显示"加载失败 for 张三.",中英文混杂,用户体验差。
#### 问题 2.2.4 报告内容硬编码中文P1
- **位置**[stats-service.ts#L280-353](file:///e:/Desktop/CICD/src/modules/diagnostic/stats-service.ts#L280)
- **现象**`buildStudentReportContent``buildClassReportContent` 生成中文报告内容,如 `"建议复习「${m.knowledgePointName}」知识点"``"学生 ${summary.studentName} 在 ${period} 期间整体掌握度"` 等。
- **违反规则**:项目规则"所有用户可见文本必须适配 i18n"。
- **原因**:纯函数层生成报告内容时直接硬编码中文,未通过 i18n。
- **后果**:英文环境下生成的诊断报告内容为中文,无法国际化。报告内容存储在数据库中,已生成的历史报告无法回溯翻译。
#### 问题 2.2.5 Excel 导出表头硬编码中文P1
- **位置**[export.ts#L40-99](file:///e:/Desktop/CICD/src/modules/diagnostic/export.ts#L40)
- **现象**Excel 表头如 `"学生姓名"``"报告周期"``"综合得分"``"知识点掌握度"` 等硬编码中文;文件名 `诊断报告_${safePeriod}_${formatDateForFile()}.xlsx` 也硬编码。
- **违反规则**:项目规则"所有用户可见文本必须适配 i18n"。
- **后果**:英文环境下导出的 Excel 文件表头和文件名为中文。
### 2.3 类型安全
#### 问题 2.3.1 as 类型断言P1
- **位置**[teacher/diagnostic/page.tsx#L24, L28](file:///e:/Desktop/CICD/src/app/(dashboard)/teacher/diagnostic/page.tsx#L24)
- **现象**`(v as DiagnosticReportType)``(v as DiagnosticReportStatus)` 使用 as 断言。
- **违反规则**:项目规则"禁止 as 断言(除非从 unknown 转换或测试中,需注释原因)"。
- **原因**:虽有类型守卫 `VALID_REPORT_TYPES.has(v)` 校验,但转换时使用了 as 而非类型守卫函数返回值收窄。
- **后果**:绕过 TypeScript 严格类型检查,潜在类型不安全。
### 2.4 错误处理与边界
#### 问题 2.4.1 分享链接指向不存在的路由P1
- **位置**[components/report-list.tsx#L157, L208](file:///e:/Desktop/CICD/src/modules/diagnostic/components/report-list.tsx#L157)
- **现象**`const url = \`${window.location.origin}/teacher/diagnostic/reports/${shareId}\`` 指向 `/teacher/diagnostic/reports/[id]` 路由,但该路由在项目中不存在(无对应 page.tsx
- **原因**:分享功能开发时未创建对应路由页面。
- **后果**:用户点击分享链接后得到 404 页面,功能不可用。
#### 问题 2.4.2 班级报告导出缺少明细P2
- **位置**[export.ts#L85-113](file:///e:/Desktop/CICD/src/modules/diagnostic/export.ts#L85)
- **现象**:班级报告仅导出概览 Sheet缺少知识点统计和需关注学生明细。代码注释明确说明"班级报告的 studentId 为 null需要从 period 反查 classId 不现实"。
- **原因**v4-P1 已为 `learningDiagnosticReports` 表新增 `classId` 字段,但 export.ts 未同步更新使用该字段查询班级明细。
- **后果**:教师导出班级报告时只能看到概览,无法获取知识点统计和需关注学生列表,导出功能不完整。
### 2.5 可复用性与配置驱动
#### 问题 2.5.1 角色差异通过 props 硬编码而非配置驱动P2
- **位置**[components/student-diagnostic-view.tsx#L32](file:///e:/Desktop/CICD/src/modules/diagnostic/components/student-diagnostic-view.tsx#L32)
- **现象**`practiceHrefBase` prop 区分角色(学生默认 `/student/learning/assignments`,教师传 `/teacher/questions`,家长传 `null`)。
- **违反规则**:项目规则"采用配置驱动设计,例如通过角色配置决定该模块渲染哪些 Widget/子模块"。
- **原因**:角色差异通过 props 传递,而非通过角色配置对象统一管理。
- **后果**:新增角色需修改组件 props 传递逻辑,而非仅修改配置。
#### 问题 2.5.2 无年级诊断报告生成入口P2
- **位置**[types.ts#L3](file:///e:/Desktop/CICD/src/modules/diagnostic/types.ts#L3)
- **现象**`DiagnosticReportType` 定义了 `"grade"` 类型,但 [actions.ts](file:///e:/Desktop/CICD/src/modules/diagnostic/actions.ts) 无 `generateGradeReportAction`[data-access-reports.ts](file:///e:/Desktop/CICD/src/modules/diagnostic/data-access-reports.ts) 无 `generateGradeDiagnosticReport` 函数。
- **原因**:年级报告功能定义了类型但未实现。
- **后果**管理员无法生成年级级别的诊断报告功能不完整。report-list 过滤器中可选"年级"类型但永远无数据。
### 2.6 可访问性
#### 问题 2.6.1 热力图色块缺少键盘导航P2
- **位置**[components/class-diagnostic-view.tsx#L190-201](file:///e:/Desktop/CICD/src/modules/diagnostic/components/class-diagnostic-view.tsx#L190)
- **现象**:热力图色块为 `<div>` 且仅有 `role="img"`,无 `tabIndex` 和键盘焦点样式,键盘用户无法逐个聚焦查看详情。
- **违反规则**:项目规则"可访问性a11y语义化标签、ARIA 属性、键盘导航"。
- **后果**:键盘用户无法通过 Tab 遍历热力图色块查看 tooltip/title 详情。
---
## 三、行业差距对比
对标 PowerSchool、Infinite Campus、Skyward、Alma、智学网、班级小管家等 K12 系统,本模块在以下方面存在差距:
| 维度 | 优秀实践 | 本模块现状 | 影响 |
|------|---------|-----------|------|
| **诊断趋势分析** | PowerSchool/智学网支持掌握度时间线,展示知识点掌握度随时间的变化趋势 | 仅展示当前快照,无历史趋势对比 | 教师无法判断学生是否在进步或退步 |
| **年级诊断报告** | Infinite Campus 支持年级级别诊断,对比班级间差异 | 类型已定义但无实现入口 | 管理员无法做年级层面决策 |
| **报告详情页** | 所有同类系统都有独立的报告详情页,支持分享链接 | 分享链接指向不存在的路由 | 分享功能不可用 |
| **班级报告导出明细** | PowerSchool/Infinite Campus 导出含知识点统计+学生列表 | 班级报告仅导出概览 | 教师无法离线分析 |
| **掌握度时间线** | 智学网展示每个知识点的掌握度变化曲线 | 无时间维度数据 | 无法评估教学干预效果 |
| **个性化学习路径** | Alma/智学网基于弱项推荐学习路径和资源 | 仅提供练习按钮跳转题目库 | 推荐不够精准 |
| **诊断报告模板** | PowerSchool 支持自定义报告模板 | 报告内容固定硬编码 | 无法按学校需求定制 |
| **多维度诊断** | Infinite Campus 结合成绩+出勤+行为做多维诊断 | 仅基于知识点掌握度 | 诊断维度单一 |
---
## 四、改进优先级建议
### P0紧急影响功能正确性或核心规范
| 编号 | 问题 | 改进方向 |
|------|------|---------|
| P0-1 | 跨模块 import WidgetBoundary | 将 WidgetBoundary 提升到 `shared/components/`diagnostic 和 grades 模块统一从 shared 引用 |
| P0-2 | 教师页面标题硬编码英文 | 3 个教师页面使用 `getTranslations("diagnostic")` 获取标题和描述 |
| P0-3 | teacher/diagnostic/error.tsx 硬编码中文 | 接入 `useTranslations("diagnostic")`,与其他 error.tsx 一致 |
### P1重要影响用户体验或类型安全
| 编号 | 问题 | 改进方向 |
|------|------|---------|
| P1-1 | parent 错误卡片中英文混用 | 提取完整 i18n 键,消除硬编码英文 |
| P1-2 | as 类型断言 | 改用类型守卫函数返回值收窄,消除 as |
| P1-3 | 分享链接指向不存在路由 | 移除分享功能或创建对应路由页面。鉴于当前无报告详情页需求,移除分享按钮避免 404 |
| P1-4 | 报告内容硬编码中文 | stats-service 的报告内容生成改为接收 i18n 翻译函数参数,或在 actions 层调用时注入翻译后的模板 |
| P1-5 | Excel 导出表头硬编码 | export.ts 接收 i18n 翻译参数,表头和文件名使用翻译键 |
### P2增强提升完整性
| 编号 | 问题 | 改进方向 |
|------|------|---------|
| P2-1 | 班级报告导出缺少明细 | 利用 v4-P1 新增的 classId 字段查询班级掌握度,导出知识点统计+需关注学生 Sheet |
| P2-2 | 角色差异通过 props 硬编码 | 定义角色配置对象,通过配置驱动 practiceHrefBase 等角色差异 |
| P2-3 | 无年级诊断报告入口 | 实现 generateGradeDiagnosticReport + 对应 Action中长期 |
| P2-4 | 热力图色块缺少键盘导航 | 添加 tabIndex={0} 和 focus-visible 样式 |
| P2-5 | 架构图行数统计滞后 | 同步 data-access.ts 实际行数,补充 export.ts 和 confidence-utils.ts 记录 |
---
## 五、架构图同步说明
本次审计发现架构图需同步以下内容:
### 004_architecture_impact_map.md §2.22
1. **文件清单更新**
- `data-access.ts` 行数从 179 更新为 477`updateMasteryFromHomeworkSubmission``updateMasteryFromExamScore`
- 补充 `export.ts`122 行Excel 导出)
- 补充 `components/confidence-utils.ts`31 行,置信度计算)
2. **已知问题新增**
- 记录 P0-1 跨模块 import WidgetBoundary 问题及修复
- 记录 P0-2/P0-3 i18n 遗漏问题及修复
- 记录 P1-3 分享链接 404 问题及修复
3. **依赖关系更新**:标注 WidgetBoundary 已从 grades 模块提升到 shared 层
### 005_architecture_data.json
1. `modules.diagnostic.exports` 补充 `export.ts``confidence-utils.ts` 文件记录
2. `modules.diagnostic.dependencies` 更新:移除对 `grades/components/widget-boundary` 的 UI 依赖,改为 `shared/components/widget-boundary`
3. `modules.diagnostic.fileList` 行数同步更新
---
## 六、实施状态2026-06-24 全部完成)
> 本章节记录审计报告中所有 P0/P1/P2 项的实施完成情况。所有项均已通过 `npx tsc --noEmit` 与 `npm run lint` 校验(诊断模块零错误)。
### 6.1 P0 项实施状态
| 编号 | 状态 | 实施内容 | 涉及文件 |
|------|------|---------|---------|
| P0-1 | ✅ 已完成 | WidgetBoundary 已从 `modules/grades/components/widget-boundary.tsx` 提升到 `shared/components/widget-boundary.tsx`diagnostic 与 grades 模块统一从 `@/shared/components/widget-boundary` 引用grades 模块原文件已删除 | `src/shared/components/widget-boundary.tsx`(新建)、`src/modules/grades/components/widget-boundary.tsx`(删除)、`src/app/(dashboard)/teacher/diagnostic/student/[studentId]/page.tsx``src/app/(dashboard)/teacher/diagnostic/class/[classId]/page.tsx` |
| P0-2 | ✅ 已完成 | 3 个教师页面(`teacher/diagnostic/page.tsx``teacher/diagnostic/student/[studentId]/page.tsx``teacher/diagnostic/class/[classId]/page.tsx`)均使用 `getTranslations("diagnostic")` 获取标题与描述,新增对应 i18n 键 `teacherTitle``teacherDescription``studentTitle``studentDescription``classTitle``classDescription` | 上述 3 个页面 + `src/shared/i18n/messages/zh-CN/diagnostic.json` + `src/shared/i18n/messages/en/diagnostic.json` |
| P0-3 | ✅ 已完成 | `teacher/diagnostic/error.tsx` 接入 `useTranslations("diagnostic")`,与 `student/diagnostic/error.tsx` 风格一致;新增 i18n 键 `errorTitle``errorDescription``errorRetry` | `src/app/(dashboard)/teacher/diagnostic/error.tsx` + 两个 i18n 文件 |
### 6.2 P1 项实施状态
| 编号 | 状态 | 实施内容 | 涉及文件 |
|------|------|---------|---------|
| P1-1 | ✅ 已完成 | `parent/diagnostic/page.tsx` 错误卡片中英文混用已消除;新增 i18n 键 `errorForStudent``errorContactAdmin`,使用 `t("errorForStudent", { name: item.studentName })` 替代硬编码 | `src/app/(dashboard)/parent/diagnostic/page.tsx` + 两个 i18n 文件 |
| P1-2 | ✅ 已完成 | `teacher/diagnostic/page.tsx``(v as DiagnosticReportType)``(v as DiagnosticReportStatus)` 已替换为类型守卫函数返回值收窄:`VALID_REPORT_TYPES.has(v) ? v : DEFAULT_REPORT_TYPE` 模式,消除 `as` 断言 | `src/app/(dashboard)/teacher/diagnostic/page.tsx` |
| P1-3 | ✅ 已完成 | `components/report-list.tsx` 中分享按钮与相关逻辑已移除(包括 `shareReportAction` 调用、`window.location.origin` URL 构造、分享对话框),避免 404保留发布/删除/导出三个核心操作 | `src/modules/diagnostic/components/report-list.tsx` |
| P1-4 | ✅ 已完成 | `stats-service.ts``buildStudentReportContent``buildClassReportContent` 已重构为接收 `ReportContentTranslations` 接口参数;新增 `getReportContentTranslations()` 在 data-access-reports 层调用 `getTranslations` 注入翻译;报告内容生成改为 i18n 驱动 | `src/modules/diagnostic/stats-service.ts``src/modules/diagnostic/data-access-reports.ts`、两个 i18n 文件 |
| P1-5 | ✅ 已完成 | `export.ts` 中 Excel 表头和文件名已改为接收 i18n 翻译参数;`exportDiagnosticReportAction` 在调用 `exportDiagnosticReportToExcel` 前通过 `getTranslations("diagnostic")` 注入翻译;新增 i18n 键 `sheetOverview``sheetClassStats``sheetAttentionStudents``colStudentName``colPeriod``colReportType``colStatus``colScore``colGeneratedAt``colSummary``colStrengths``colWeaknesses``colRecommendations``filenameDiagnosticReport` 等 | `src/modules/diagnostic/export.ts``src/modules/diagnostic/actions.ts`、两个 i18n 文件 |
### 6.3 P2 项实施状态
| 编号 | 状态 | 实施内容 | 涉及文件 |
|------|------|---------|---------|
| P2-1 | ✅ 已完成 | 班级报告导出已利用 v4-P1 新增的 `classId` 字段调用 `getClassMasterySummary`,导出包含三个 Sheet概览、知识点统计、需关注学生明细新增 i18n 键 `sheetClassStats``sheetAttentionStudents``metricClass``metricStudentCount``metricAttentionCount``colMasteredCount``colNotMasteredCount``colTotalStudents``colAverageMastery``colWeakCount``noAttentionStudents` | `src/modules/diagnostic/export.ts` + 两个 i18n 文件 |
| P2-2 | ✅ 已完成 | 新建 `src/modules/diagnostic/role-config.ts`,定义 `DiagnosticRole` 类型、`DiagnosticRoleConfig` 接口、`DIAGNOSTIC_ROLE_CONFIG` 记录student/teacher/parent 三角色配置)和 `getDiagnosticRoleConfig` 辅助函数;`StudentDiagnosticView` 组件新增 `role` prop内部通过 `getDiagnosticRoleConfig(role).practiceHrefBase` 解析配置;原 `practiceHrefBase` prop 标记 `@deprecated` 保留向后兼容(同时传入时 `role` 优先3 个调用点已迁移为 `role="student"` / `role="teacher"` / `role="parent"` | `src/modules/diagnostic/role-config.ts`(新建)、`src/modules/diagnostic/components/student-diagnostic-view.tsx``src/app/(dashboard)/student/diagnostic/page.tsx``src/app/(dashboard)/teacher/diagnostic/student/[studentId]/page.tsx``src/app/(dashboard)/parent/diagnostic/page.tsx` |
| P2-3 | ✅ 已完成 | 完整实现年级诊断报告纵向切片:① DB schema 新增 `gradeId` 字段 + `gradeIdx` 索引 + 迁移 SQL `0012_diagnostic_grade_id.sql`;② 类型新增 `GradeMasterySummary` 接口,`DiagnosticReport` 接口新增 `gradeId: string \| null`;③ data-access 新增 `getGradeMasterySummary`(缓存,并行查询年级名+学生 ID+掌握度行);④ stats-service 新增 `buildGradeMasterySummary``buildGradeReportContent` 纯函数;⑤ data-access-reports 新增 `generateGradeDiagnosticReport`,含 `GRADE_NOT_FOUND` / `GRADE_NO_MASTERY_DATA` 错误码;⑥ schema 新增 `GenerateGradeReportSchema`;⑦ actions 新增 `generateGradeReportAction` Server Action`requirePermission` + `revalidatePath`);⑧ i18n 新增 `gradeSummary``gradeRecommendation``gradeNoWeakness` 键 | `src/shared/db/schema.ts``drizzle/0012_diagnostic_grade_id.sql`(新建)、`src/modules/diagnostic/types.ts``src/modules/diagnostic/data-access.ts``src/modules/diagnostic/stats-service.ts``src/modules/diagnostic/data-access-reports.ts``src/modules/diagnostic/schema.ts``src/modules/diagnostic/actions.ts`、两个 i18n 文件 |
| P2-4 | ✅ 已完成 | 班级诊断视图热力图色块新增 `tabIndex={0}``focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2` 样式;外层容器 `role``"img"` 改为 `"group"`(因容器内现含可聚焦元素);保留每个色块的 `aria-label` 提供完整描述 | `src/modules/diagnostic/components/class-diagnostic-view.tsx` |
| P2-5 | ✅ 已完成 | 架构图 004 和 005 已同步:① `data-access.ts` 行数更新为实际值;② 补充 `export.ts``role-config.ts``confidence-utils.ts` 文件记录;③ 已知问题章节新增 11 条 P0-1 至 P2-4 修复记录;④ 依赖矩阵新增 `school` 模块依赖(`getGradeNameById``getUserIdsByGradeId`)和 `shared/components/widget-boundary`;⑤ `learningDiagnosticReports` 表描述补充 `gradeId` 字段;⑥ `modules.diagnostic.exports` 新增 `getGradeMasterySummary``generateGradeDiagnosticReport``buildGradeMasterySummary``buildGradeReportContent``generateGradeReportAction``GenerateGradeReportSchema` 等 | `docs/architecture/004_architecture_impact_map.md``docs/architecture/005_architecture_data.json` |
### 6.4 验证结果
- **TypeScript**`npx tsc --noEmit` 通过,诊断模块零错误(仅 `dashboard/services/dashboard-service.ts` 存在与本模块无关的预存语法错误)。
- **ESLint**`npm run lint` 通过,诊断模块零警告。
- **架构图一致性**004 与 005 两份架构文档已与源码同步,所有新增/修改的导出函数、类型、依赖关系、DB 表字段均已记录。
### 6.5 后续建议(未列入本次实施范围)
以下为审计过程中识别但未列入本次实施的长期增强项,建议后续按需推进:
1. **掌握度时间线**:新增 `knowledgePointMasteryHistory` 表记录每次掌握度变化,前端展示时间线图表。
2. **个性化学习路径推荐**:基于弱项知识点推荐具体学习资源(题目、视频、文档),而非仅跳转题目库。
3. **多维度诊断**:结合成绩、出勤、行为数据做多维综合诊断。
4. **报告模板自定义**:允许学校配置报告内容模板(如自定义推荐话术、评分区间)。
5. **报告详情页**:若未来需要分享功能,创建 `/teacher/diagnostic/reports/[id]` 路由页面。
6. **可测试性增强**:为 `stats-service.ts` 中 12 个纯函数补充单元测试,导出 `ReportContentTranslations` 接口便于 mock。
7. **依赖注入抽象**:将 `report-list.tsx``class-diagnostic-view.tsx` 中直接 import actions 的模式重构为通过 React Context 注入数据服务接口,提升可测试性。