feat(textbooks): 知识图谱功能全面重构 — 前置依赖 + dagre 布局 + React Flow 可视化 + 师生双视角

将教材模块图谱从基本无用状态升级为完整知识图谱可视化系统。

数据层:新增 knowledgePointPrerequisites 表(复合主键+双外键 cascade);新增 data-access-graph.ts(server-only)知识点关联聚合、学生/班级掌握度查询;utils.ts 新增 hasCycleAfterAddingEdge(DFS 循环依赖检测)。

业务层:3 个新 Server Action(getKnowledgeGraphDataAction 三视图模式、createPrerequisiteAction 含循环检测、deletePrerequisiteAction);graph-layout.ts 重写为 dagre 分层有向图布局。

视图层:knowledge-graph.tsx 重写为 React Flow 主组件(全书视图+搜索高亮+关联节点高亮+章节着色);4 个新组件(graph-kp-node/graph-prerequisite-edge/graph-toolbar/graph-node-detail-panel);use-graph-data.ts 派生值模式避免 effect 中 setState。

架构:严格三层架构,客户端通过 Server Action 间接访问 server-only 数据层;权限校验+ i18n 全覆盖;架构文档 004/005 同步。

测试:utils.test.ts 新增 5 个循环检测测试,graph-layout.test.ts 重写 5 个 dagre 布局测试,全部 30 个教材模块单元测试通过。

附带提交 drizzle/0005 error-book 迁移文件以保持 journal 一致性。
This commit is contained in:
SpecialX
2026-06-23 00:13:03 +08:00
parent 15aa84b72c
commit 58656da983
28 changed files with 21377 additions and 575 deletions

View File

@@ -34,10 +34,16 @@
"graph": "图谱"
},
"selectChapter": "请选择一个章节开始阅读。",
"selectChapterDesc": "从左侧目录中选择一个章节以查看内容。",
"selectChapterKnowledge": "请选择一个章节查看知识点。",
"selectChapterKnowledgeDesc": "从左侧目录中选择一个章节以查看关联的知识点。",
"selectChapterGraph": "请选择一个章节查看知识图谱。",
"selectChapterGraphDesc": "从左侧目录中选择一个章节以查看知识图谱关系。",
"emptyKnowledge": "该章节暂无知识点。",
"emptyKnowledgeDesc": "在阅读内容时选中文本即可创建知识点。",
"emptyContent": "暂无内容",
"emptyContentDesc": "点击「编辑内容」开始编写本章正文。",
"loadingKnowledge": "正在加载知识点...",
"editContent": "编辑内容",
"cancel": "取消",
"save": "保存",
@@ -45,7 +51,9 @@
"addKnowledgePoint": "添加知识点",
"clickToViewKp": "点击查看知识点详情",
"noChapters": "暂无章节",
"noChaptersDesc": "这本教材还没有章节。"
"noChaptersDesc": "这本教材还没有章节。",
"sidebar": "目录与知识点",
"openSidebar": "打开目录"
},
"dialog": {
"create": {
@@ -75,7 +83,11 @@
"deleting": "删除中...",
"cannotDeleteWithSubchapters": "无法删除含有子章节的章节",
"addSubchapter": "添加子章节",
"titlePlaceholder": "例如:第一章:入门"
"titlePlaceholder": "例如:第一章:入门",
"toggle": "展开/折叠",
"orderUpdated": "顺序已更新",
"cancel": "取消",
"dragHandle": "拖拽排序"
},
"knowledge": {
"createTitle": "添加知识点",
@@ -133,6 +145,7 @@
"level": "等级"
},
"subject": {
"chinese": "语文",
"mathematics": "数学",
"physics": "物理",
"chemistry": "化学",
@@ -142,6 +155,8 @@
"geography": "地理"
},
"grade": {
"grade1": "一年级",
"grade2": "二年级",
"grade7": "七年级",
"grade8": "八年级",
"grade9": "九年级",
@@ -160,7 +175,7 @@
"updateSuccess": "教材更新成功。",
"updateFailed": "更新教材失败。",
"deleteSuccess": "教材删除成功。",
"deleteFailed": "删除教材失败。",
"textbookDeleteFailed": "删除教材失败。",
"chapterCreateSuccess": "章节创建成功",
"chapterCreateFailed": "创建章节失败",
"chapterDeleteSuccess": "章节删除成功",
@@ -181,6 +196,57 @@
"invalidContent": "章节内容数据无效",
"errorOccurred": "发生错误",
"deleteFailed": "删除失败",
"updateFailedGeneric": "更新失败"
"updateFailedGeneric": "更新失败",
"chapterNotBelong": "章节不属于该教材",
"kpNotBelong": "知识点不属于该教材",
"chaptersReordered": "章节排序成功",
"ok": "成功",
"kpLoadFailed": "加载知识点失败",
"graphLoadFailed": "图谱加载失败",
"invalidInput": "输入无效",
"cyclicDependency": "不能添加循环依赖",
"prerequisiteCreated": "前置依赖已添加",
"prerequisiteCreateFailed": "添加前置依赖失败",
"prerequisiteDeleted": "前置依赖已删除",
"prerequisiteDeleteFailed": "删除前置依赖失败"
},
"graph": {
"viewMode": {
"structure": "结构图",
"studentMastery": "个人掌握度",
"classMastery": "班级掌握度"
},
"node": {
"questions": "题目",
"mastery": "掌握度",
"prerequisite": "前置",
"successor": "后置"
},
"detail": {
"title": "知识点详情",
"noDescription": "暂无描述",
"viewAllQuestions": "查看全部题目",
"editPrerequisite": "编辑前置依赖",
"addPrerequisite": "添加前置",
"removePrerequisite": "移除",
"noPrerequisites": "暂无前置知识点",
"noSuccessors": "暂无后置知识点",
"masteryNotAssessed": "未测评",
"correctRate": "正确率",
"totalQuestions": "总题数"
},
"toolbar": {
"search": "搜索知识点",
"filterByChapter": "按章节筛选",
"resetView": "重置视图"
},
"empty": {
"noPrerequisites": "暂无前置依赖关系",
"noData": "暂无图谱数据"
},
"error": {
"cyclicDependency": "不能添加循环依赖",
"loadFailed": "图谱加载失败"
}
}
}