Files
NextEdu/docs/architecture/audit/textbooks-audit-report-v2.md
SpecialX 27db170c0a docs: update architecture docs, audit reports, and bug tracking
- Update architecture impact map, data, feature checklist, gap audit

- Add audit reports for dashboard, exam-homework, grades-diagnostic, settings-profile, textbooks

- Update bug reports (admin, teacher, lesson-preparation, others, shared)

- Update coding standards, DR plan, design docs, and README
2026-06-23 17:36:18 +08:00

225 lines
13 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 教材Textbooks模块审计报告 v2
> 审计日期2026-06-22
> 审计范围:`src/modules/textbooks/**`、`src/app/(dashboard)/teacher/textbooks/**`、`src/app/(dashboard)/student/learning/textbooks/**`
> 对比基准:[textbooks-audit-report.md](./textbooks-audit-report.md)v1
> 参照规则:`docs/architecture/004_architecture_impact_map.md`、`docs/architecture/005_architecture_data.json`、`.trae/rules/project_rules.md`
---
## 一、v1 改进项完成状态总览
### 1.1 完成度统计
| 优先级 | 总数 | 已完成 | 部分完成 | 未完成 |
|--------|------|--------|----------|--------|
| P0 | 4 | 3 | 1P0-3 i18n | 0 |
| P1 | 8 | 7 | 1P1-6 类型断言) | 0 |
| P2 | 6 | 4 | 1P2-5 架构图同步) | 1图谱方向键导航 |
| **合计** | **18** | **14** | **3** | **1** |
### 1.2 各项状态明细
| 编号 | 标题 | 状态 | 关键证据 |
|------|------|------|----------|
| P0-1 | 跨模块 UI 依赖解耦 | ✅ 已完成 | `knowledge-point-dialogs.tsx` 改为 render prop页面层注入 |
| P0-2 | 前端权限硬编码 canEdit | ✅ 已完成 | `textbook-reader.tsx` 使用 `usePermission().hasPermission()` |
| P0-3 | 全模块 i18n 改造 | ⚠️ 部分完成 | 约 85%`chapter-sidebar-list.tsx`/`actions.ts`/`section-error-boundary.tsx` 未接入 |
| P0-4 | Server Action 资源归属校验 | ✅ 已完成 | `actions.ts` 全部写 Action 调用 `verify*` 函数 |
| P1-1 | data-access 数据范围过滤 | ✅ 已完成 | `getTextbooksWithScope` + 学生端按年级过滤 |
| P1-2 | Error Boundary | ✅ 已完成 | 4 个 `error.tsx` + `section-error-boundary.tsx` |
| P1-3 | 消除重复组件 | ✅ 已完成 | 删除 `knowledge-point-panel.tsx``create-knowledge-point-dialog.tsx` |
| P1-4 | 抽取学科/年级配置 | ✅ 已完成 | `constants.ts` 集中管理 `SUBJECTS`/`GRADES`/`SUBJECT_COLORS` |
| P1-5 | 导出纯函数并补单测 | ✅ 已完成 | `utils.ts` + `graph-layout.ts` + 两个测试文件 |
| P1-6 | 修复类型断言 | ⚠️ 部分完成 | v1 的 3 处已修复,残留 3 处 `as string` |
| P1-7 | 图谱 a11y | ✅ 已完成 | `role="img"`/`aria-label`/`<title>`/`aria-pressed` |
| P1-8 | 统一删除确认 | ✅ 已完成 | `textbook-settings-dialog.tsx``AlertDialog` |
| P2-1 | 统一空状态 | ✅ 已完成 | 全部使用 `EmptyState` |
| P2-2 | 知识点高亮性能优化 | ✅ 已完成 | 单遍 alternation 正则 + `useMemo` |
| P2-3 | 知识点懒加载 | ✅ 已完成 | 按章节懒加载 + 缓存 + 派生加载状态 |
| P2-4 | 移动端阅读优化 | ✅ 已完成 | `Sheet` 抽屉 + 桌面端内联复用 |
| P2-5 | 架构图同步 | ⚠️ 部分完成 | 005 JSON 新函数已加,`knownIssues`/`uiDeps`/`components` 过期 |
| P2-6 | 埋点接口预留 | ✅ 已完成 | `analytics.tsx` 定义接口 + Provider + Hook |
---
## 二、v2 新发现的问题
### 2.1 i18n 完整性P0v1 遗留)
#### 问题 v2-1 `chapter-sidebar-list.tsx` 完全未接入 i18nP0
- **位置**[chapter-sidebar-list.tsx](file:///e:/Desktop/CICD/src/modules/textbooks/components/chapter-sidebar-list.tsx)
- **现象**:第 90 行 `"Toggle"`、第 118 行 `"Add Subchapter"`、第 130 行 `"Delete Chapter"`、第 258 行 `"Order updated"`、第 278 行 `"Cannot delete chapter with subchapters"`、第 332-341 行删除对话框文案全部硬编码英文
- **翻译键已存在**`dialog.chapter.deleteTitle`/`delete`/`deleting`/`cannotDeleteWithSubchapters`/`addSubchapter`
- **影响**中文用户看到英文文案i18n 覆盖率不完整
#### 问题 v2-2 `actions.ts` 错误消息全部硬编码英文P0
- **位置**[actions.ts](file:///e:/Desktop/CICD/src/modules/textbooks/actions.ts)
- **现象**:约 20+ 条消息硬编码,如第 47 行 `"Chapter does not belong to this textbook"`、第 56 行 `"Failed to reorder chapters"`
- **影响**:用户看到的 toast 消息无法本地化
- **建议**Server Action 内使用 `getTranslations("textbooks.action")` 获取翻译
#### 问题 v2-3 `section-error-boundary.tsx` 默认文案硬编码中文P1
- **位置**[section-error-boundary.tsx](file:///e:/Desktop/CICD/src/modules/textbooks/components/section-error-boundary.tsx) 第 52/55/59 行
- **现象**:默认 fallback `"区块加载失败"` / `"请重试或刷新页面"` / `"重试"` 硬编码
- **影响**:英文用户看到中文默认值
### 2.2 学科/年级显示未本地化P1
#### 问题 v2-4 `textbook-card.tsx` 学科显示未本地化P1
- **位置**[textbook-card.tsx](file:///e:/Desktop/CICD/src/modules/textbooks/components/textbook-card.tsx) 第 41 行
- **现象**`{textbook.subject}` 直接显示原始值(如 "Mathematics"),未通过 `t(\`subject.${labelKey}\`)` 转换
#### 问题 v2-5 页面层学科/年级显示未本地化P1
- **位置**
- [teacher/textbooks/[id]/page.tsx](file:///e:/Desktop/CICD/src/app/(dashboard)/teacher/textbooks/[id]/page.tsx) 第 64、66 行
- [student/learning/textbooks/[id]/page.tsx](file:///e:/Desktop/CICD/src/app/(dashboard)/student/learning/textbooks/[id]/page.tsx) 第 47、49 行
- **现象**`{textbook.subject}``{textbook.grade}` 直接显示原始值
### 2.3 类型安全P2
#### 问题 v2-6 残留 `as string` 断言P2
- **位置**
- [chapter-sidebar-list.tsx](file:///e:/Desktop/CICD/src/modules/textbooks/components/chapter-sidebar-list.tsx) 第 226、257 行:`active.id as string`
- [graph-layout.ts](file:///e:/Desktop/CICD/src/modules/textbooks/graph-layout.ts) 第 123 行:`kp.parentId as string`
- **建议**:用类型守卫或 narrowing 替代
### 2.4 重复代码P2
#### 问题 v2-7 `findParent` 与 `utils.ts` 的 `findChapterParent` 重复P2
- **位置**[chapter-sidebar-list.tsx](file:///e:/Desktop/CICD/src/modules/textbooks/components/chapter-sidebar-list.tsx) 第 215-224 行
- **现象**:内联 `findParent` 函数与 `utils.ts` 导出的 `findChapterParent` 功能完全相同
- **建议**:替换为 `import { findChapterParent } from "../utils"`
#### 问题 v2-8 4 个 `error.tsx` 文件几乎完全相同P2
- **位置**4 个 `error.tsx` 文件
- **现象**:内容完全一致(仅函数名不同)
- **建议**:抽取为共享组件 `TextbookRouteError`
#### 问题 v2-9 `student/learning/textbooks/page.tsx` 重复定义 `getParam`P2
- **位置**[student/learning/textbooks/page.tsx](file:///e:/Desktop/CICD/src/app/(dashboard)/student/learning/textbooks/page.tsx) 第 13-18 行
- **现象**:本地定义 `getParam`,但 `@/shared/lib/search-params` 已导出
- **建议**:统一从 `@/shared/lib/search-params` 导入
### 2.5 a11y 改进P2
#### 问题 v2-10 拖拽手柄无 `aria-label`P2
- **位置**[chapter-sidebar-list.tsx](file:///e:/Desktop/CICD/src/modules/textbooks/components/chapter-sidebar-list.tsx) 第 71-73 行
- **现象**`<div {...attributes} {...listeners}>` 拖拽手柄仅含 `GripVertical` 图标,无 `aria-label`
#### 问题 v2-11 知识点高亮 span 无可交互语义P2
- **位置**[textbook-content-panel.tsx](file:///e:/Desktop/CICD/src/modules/textbooks/components/textbook-content-panel.tsx) 第 133-148 行
- **现象**:高亮的知识点 `<span>``data-kp-id` + `title`,无 `role="button"`/`aria-label`/`tabIndex`
#### 问题 v2-12 移动端抽屉触发按钮无 `aria-expanded`P2
- **位置**[textbook-reader.tsx](file:///e:/Desktop/CICD/src/modules/textbooks/components/textbook-reader.tsx) 第 361-368 行
- **现象**`<Button>` 未关联 `aria-expanded`/`aria-controls`
### 2.6 性能与状态管理P2
#### 问题 v2-13 `textbook-reader.tsx` textbookId 变化时未清理缓存P2
- **位置**[textbook-reader.tsx](file:///e:/Desktop/CICD/src/modules/textbooks/components/textbook-reader.tsx) 第 110-142 行
- **现象**`requestedChaptersRef` 是 ref当 textbookId 变化(用户切换教材)时不会清理,可能导致缓存命中错误章节的数据
- **建议**:在 `useEffect` 中增加 textbookId 变化时清理 `kpsByChapter``requestedChaptersRef`
#### 问题 v2-14 `TextbookContentPanel` 存在未使用的 propsP2
- **位置**[textbook-content-panel.tsx](file:///e:/Desktop/CICD/src/modules/textbooks/components/textbook-content-panel.tsx) 第 23-46 行
- **现象**`knowledgePoints`/`createDialogOpen`/`isCreating`/`onCreateKnowledgePoint` 4 个 props 在接口中定义但函数体内未解构使用
- **建议**:移除这 4 个 props 及对应的传参
### 2.7 架构图同步P2v1 遗留)
#### 问题 v2-15 架构图 005 JSON 与 004 MD 同步不完整P2
- **005 JSON 未同步部分**
- `knownIssues` 数组仍列出所有 v1 的 P0/P1 问题为未解决
- `uiDeps` 仍标注 "P0 待解耦",但代码已通过 render prop 解耦
- `components` 数组仍列出已删除的组件,遗漏新增的 `SectionErrorBoundary`
- `hooks` 签名函数名简写与实际不一致
- 遗漏 `analytics.tsx`/`constants.ts`/`utils.ts`/`graph-layout.ts` 等新文件
- **004 MD 未同步部分**
- §2.5 仍写 "⚠️ UI 层跨模块依赖P0 待解耦)" — 已修复
- "已知问题"列表未更新
- 文件行数过期:`actions.ts` 317→377、`data-access.ts` 514→619、组件数 11→12
---
## 三、v2 改进优先级建议
### P0紧急i18n 完整性收尾)
1. **`chapter-sidebar-list.tsx` 接入 i18n**:替换所有硬编码英文为 `t(...)` 调用
2. **`actions.ts` 接入 i18n**:使用 `getTranslations("textbooks.action")` 替换硬编码消息
3. **`section-error-boundary.tsx` 默认文案 i18n**:默认值改为从 i18n 获取或使用翻译键
### P1重要
1. **学科/年级显示本地化**`textbook-card.tsx``teacher/textbooks/[id]/page.tsx``student/learning/textbooks/[id]/page.tsx``{textbook.subject}`/`{textbook.grade}` 改为 `t(...)` 调用
2. **架构图同步**P2-5 收尾):更新 005 JSON 的 `knownIssues`/`uiDeps`/`components`/`hooks` 签名;更新 004 MD §2.5 的"已知问题"列表和文件清单行数
3. **移除 `TextbookContentPanel` 的 4 个未使用 props**
### P2优化
1. **类型断言清理**`chapter-sidebar-list.tsx``as string``graph-layout.ts``as string`
2. **重复代码消除**`findParent` 重复、4 个 error.tsx 重复、`getParam` 重复
3. **a11y 补全**:拖拽手柄 aria-label、高亮 span role/aria-label、移动端抽屉 aria-expanded
4. **`textbook-reader.tsx` textbookId 变化时清理缓存**
5. **`highlightKnowledgePoints` 补 Markdown 边界测试**
---
## 四、行业差距对比v1 第三节中仍未完成的项目)
以下 v1 报告中"行业差距对比"的项目在 v2 中仍未实现,作为长期路线图保留:
| 差距项 | 优先级 | 说明 |
|--------|--------|------|
| 富媒体嵌入(图片/音频/视频/公式/3D | 长期 | 仍仅 Markdown + RichTextEditor |
| 公式编辑LaTeX/MathML | 长期 | 无 |
| 翻阅式阅读(页码/书签/进度记忆) | 长期 | 仍滚动 + URL chapterId |
| 朗读/TTS | 长期 | 无 |
| 笔记/划线/高亮/书签 | 长期 | 仅有"选区创建知识点" |
| 知识图谱缩放/拖拽/力导向 | 长期 | 仍静态 SVG 树状布局 |
| 知识点多级层级/跨章节关联/前置后置依赖 | 长期 | 仅 parentId 树 + chapterId 归属 |
| admin 多教师协作编辑 + 版本历史 | 长期 | 无版本管理 |
| parent 角色教材查看 | 长期 | 无 parent 入口 |
| 章节跨级拖拽移动 | 长期 | reorderChapters 仅支持同级排序 |
| 全文搜索(标题+正文+知识点) | 长期 | 仅列表页按 title/subject/grade/publisher 模糊搜索 |
| 阅读进度条/章节完成度 | 长期 | 无 |
| 知识点难度标注/教师标注重点 | 长期 | 仅有 level 字段,无 UI 录入 |
---
## 五、总结
### 关键成果v1 → v2
1. **架构解耦**P0-1 跨模块 UI 依赖通过 render prop 完全解耦
2. **权限安全**P0-2 前端权限接入 `usePermission`P0-4 Server Action 资源归属校验全覆盖P1-1 学生端数据范围过滤
3. **可维护性**P1-3 重复组件删除P1-4 配置集中化P1-5 纯函数抽离 + 单测
4. **用户体验**P1-2 Error Boundary 全覆盖P1-8 删除确认统一P2-1 空状态统一P2-2 高亮性能优化P2-3 懒加载P2-4 移动端抽屉
5. **可扩展性**P2-6 埋点接口预留
### 主要遗留v2 需解决)
1. **i18n 完整性**`chapter-sidebar-list.tsx``actions.ts``section-error-boundary.tsx` 三处未接入,学科/年级显示未本地化
2. **架构图同步**005 JSON 的 `knownIssues`/`uiDeps`/`components` 过期004 MD §2.5 已知问题未更新
3. **类型断言**3 处 `as string` 可改善
4. **重复代码**`findParent`/`error.tsx`/`getParam` 三处重复
5. **a11y**:拖拽手柄 aria-label、高亮 span 可交互性、移动端抽屉 aria-expanded
6. **未使用 props**`TextbookContentPanel` 的 4 个 props