- 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
13 KiB
13 KiB
教材(Textbooks)模块审计报告 v2
审计日期:2026-06-22 审计范围:
src/modules/textbooks/**、src/app/(dashboard)/teacher/textbooks/**、src/app/(dashboard)/student/learning/textbooks/**对比基准: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 | 1(P0-3 i18n) | 0 |
| P1 | 8 | 7 | 1(P1-6 类型断言) | 0 |
| P2 | 6 | 4 | 1(P2-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 完整性(P0,v1 遗留)
问题 v2-1 | chapter-sidebar-list.tsx 完全未接入 i18n(P0)
- 位置: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
- 现象:约 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 第 52/55/59 行
- 现象:默认 fallback
"区块加载失败"/"请重试或刷新页面"/"重试"硬编码 - 影响:英文用户看到中文默认值
2.2 学科/年级显示未本地化(P1)
问题 v2-4 | textbook-card.tsx 学科显示未本地化(P1)
- 位置:textbook-card.tsx 第 41 行
- 现象:
{textbook.subject}直接显示原始值(如 "Mathematics"),未通过t(\subject.${labelKey}`)` 转换
问题 v2-5 | 页面层学科/年级显示未本地化(P1)
- 位置:
- teacher/textbooks/[id]/page.tsx 第 64、66 行
- student/learning/textbooks/[id]/page.tsx 第 47、49 行
- 现象:
{textbook.subject}和{textbook.grade}直接显示原始值
2.3 类型安全(P2)
问题 v2-6 | 残留 as string 断言(P2)
- 位置:
- chapter-sidebar-list.tsx 第 226、257 行:
active.id as string - graph-layout.ts 第 123 行:
kp.parentId as string
- chapter-sidebar-list.tsx 第 226、257 行:
- 建议:用类型守卫或 narrowing 替代
2.4 重复代码(P2)
问题 v2-7 | findParent 与 utils.ts 的 findChapterParent 重复(P2)
- 位置: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 第 13-18 行
- 现象:本地定义
getParam,但@/shared/lib/search-params已导出 - 建议:统一从
@/shared/lib/search-params导入
2.5 a11y 改进(P2)
问题 v2-10 | 拖拽手柄无 aria-label(P2)
- 位置:chapter-sidebar-list.tsx 第 71-73 行
- 现象:
<div {...attributes} {...listeners}>拖拽手柄仅含GripVertical图标,无aria-label
问题 v2-11 | 知识点高亮 span 无可交互语义(P2)
- 位置:textbook-content-panel.tsx 第 133-148 行
- 现象:高亮的知识点
<span>仅data-kp-id+title,无role="button"/aria-label/tabIndex
问题 v2-12 | 移动端抽屉触发按钮无 aria-expanded(P2)
- 位置:textbook-reader.tsx 第 361-368 行
- 现象:
<Button>未关联aria-expanded/aria-controls
2.6 性能与状态管理(P2)
问题 v2-13 | textbook-reader.tsx textbookId 变化时未清理缓存(P2)
- 位置:textbook-reader.tsx 第 110-142 行
- 现象:
requestedChaptersRef是 ref,当 textbookId 变化(用户切换教材)时不会清理,可能导致缓存命中错误章节的数据 - 建议:在
useEffect中增加 textbookId 变化时清理kpsByChapter和requestedChaptersRef
问题 v2-14 | TextbookContentPanel 存在未使用的 props(P2)
- 位置:textbook-content-panel.tsx 第 23-46 行
- 现象:
knowledgePoints/createDialogOpen/isCreating/onCreateKnowledgePoint4 个 props 在接口中定义但函数体内未解构使用 - 建议:移除这 4 个 props 及对应的传参
2.7 架构图同步(P2,v1 遗留)
问题 v2-15 | 架构图 005 JSON 与 004 MD 同步不完整(P2)
- 005 JSON 未同步部分:
knownIssues数组仍列出所有 v1 的 P0/P1 问题为未解决uiDeps仍标注 "P0 待解耦",但代码已通过 render prop 解耦components数组仍列出已删除的组件,遗漏新增的SectionErrorBoundaryhooks签名函数名简写与实际不一致- 遗漏
analytics.tsx/constants.ts/utils.ts/graph-layout.ts等新文件
- 004 MD 未同步部分:
- §2.5 仍写 "⚠️ UI 层跨模块依赖(P0 待解耦)" — 已修复
- "已知问题"列表未更新
- 文件行数过期:
actions.ts317→377、data-access.ts514→619、组件数 11→12
三、v2 改进优先级建议
P0(紧急,i18n 完整性收尾)
chapter-sidebar-list.tsx接入 i18n:替换所有硬编码英文为t(...)调用actions.ts接入 i18n:使用getTranslations("textbooks.action")替换硬编码消息section-error-boundary.tsx默认文案 i18n:默认值改为从 i18n 获取或使用翻译键
P1(重要)
- 学科/年级显示本地化:
textbook-card.tsx、teacher/textbooks/[id]/page.tsx、student/learning/textbooks/[id]/page.tsx中{textbook.subject}/{textbook.grade}改为t(...)调用 - 架构图同步(P2-5 收尾):更新 005 JSON 的
knownIssues/uiDeps/components/hooks签名;更新 004 MD §2.5 的"已知问题"列表和文件清单行数 - 移除
TextbookContentPanel的 4 个未使用 props
P2(优化)
- 类型断言清理:
chapter-sidebar-list.tsx的as string、graph-layout.ts的as string - 重复代码消除:
findParent重复、4 个 error.tsx 重复、getParam重复 - a11y 补全:拖拽手柄 aria-label、高亮 span role/aria-label、移动端抽屉 aria-expanded
textbook-reader.tsxtextbookId 变化时清理缓存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)
- 架构解耦:P0-1 跨模块 UI 依赖通过 render prop 完全解耦
- 权限安全:P0-2 前端权限接入
usePermission,P0-4 Server Action 资源归属校验全覆盖,P1-1 学生端数据范围过滤 - 可维护性:P1-3 重复组件删除,P1-4 配置集中化,P1-5 纯函数抽离 + 单测
- 用户体验:P1-2 Error Boundary 全覆盖,P1-8 删除确认统一,P2-1 空状态统一,P2-2 高亮性能优化,P2-3 懒加载,P2-4 移动端抽屉
- 可扩展性:P2-6 埋点接口预留
主要遗留(v2 需解决)
- i18n 完整性:
chapter-sidebar-list.tsx、actions.ts、section-error-boundary.tsx三处未接入,学科/年级显示未本地化 - 架构图同步:005 JSON 的
knownIssues/uiDeps/components过期,004 MD §2.5 已知问题未更新 - 类型断言:3 处
as string可改善 - 重复代码:
findParent/error.tsx/getParam三处重复 - a11y:拖拽手柄 aria-label、高亮 span 可交互性、移动端抽屉 aria-expanded
- 未使用 props:
TextbookContentPanel的 4 个 props