Files
NextEdu/src/shared/i18n/messages/en/textbooks.json
SpecialX 58656da983 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 一致性。
2026-06-23 00:13:03 +08:00

253 lines
9.4 KiB
JSON

{
"list": {
"title": "Textbooks",
"subtitle": "Manage your digital curriculum resources and chapters.",
"add": "Add Textbook",
"empty": {
"withFilters": "No textbooks match your filters",
"withoutFilters": "No textbooks yet",
"withFiltersDesc": "Try clearing filters or adjusting keywords.",
"withoutFiltersDesc": "Create your first textbook to start organizing chapters."
},
"clearFilters": "Clear filters",
"chapters": "Chapters"
},
"student": {
"list": {
"title": "Textbooks",
"subtitle": "Browse your course textbooks.",
"empty": {
"withFilters": "No textbooks match your filters",
"withoutFilters": "No textbooks yet",
"withFiltersDesc": "Try clearing filters or adjusting keywords.",
"withoutFiltersDesc": "No textbooks are available right now."
}
},
"noUser": "No user found",
"noUserDesc": "Create a student user to see textbooks."
},
"reader": {
"back": "Back to textbooks",
"tabs": {
"chapters": "Chapters",
"knowledge": "Knowledge Points",
"graph": "Graph"
},
"selectChapter": "Please select a chapter to start reading.",
"selectChapterDesc": "Choose a chapter from the sidebar to view its content.",
"selectChapterKnowledge": "Please select a chapter to view knowledge points.",
"selectChapterKnowledgeDesc": "Choose a chapter from the sidebar to see its knowledge points.",
"selectChapterGraph": "Please select a chapter to view the knowledge graph.",
"selectChapterGraphDesc": "Choose a chapter from the sidebar to see its knowledge graph.",
"emptyKnowledge": "No knowledge points in this chapter yet.",
"emptyKnowledgeDesc": "Select text while reading to create a knowledge point.",
"emptyContent": "No content yet",
"emptyContentDesc": "Click \"Edit Content\" to start writing this chapter.",
"loadingKnowledge": "Loading knowledge points...",
"editContent": "Edit Content",
"cancel": "Cancel",
"save": "Save",
"saving": "Saving...",
"addKnowledgePoint": "Add Knowledge Point",
"clickToViewKp": "Click to view knowledge point details",
"noChapters": "No chapters",
"noChaptersDesc": "This textbook has no chapters yet.",
"sidebar": "Chapters & Knowledge",
"openSidebar": "Open Sidebar"
},
"dialog": {
"create": {
"title": "Add New Textbook",
"description": "Create a new digital textbook. Click save when you're done.",
"submit": "Save changes",
"saving": "Saving..."
},
"settings": {
"title": "Textbook Settings",
"description": "Update textbook details or delete this textbook.",
"delete": "Delete Textbook",
"deleteConfirmTitle": "Delete Textbook?",
"deleteConfirmDesc": "This action cannot be undone. This will permanently delete the textbook and all its chapters and knowledge points.",
"save": "Save Changes",
"processing": "Processing...",
"trigger": "Settings"
},
"chapter": {
"createTitle": "Add New Chapter",
"createDesc": "Create a new chapter or section.",
"submit": "Create Chapter",
"creating": "Creating...",
"deleteTitle": "Delete Chapter?",
"deleteDesc": "This will permanently delete {title}. This action cannot be undone.",
"delete": "Delete",
"deleting": "Deleting...",
"cannotDeleteWithSubchapters": "Cannot delete chapter with subchapters",
"addSubchapter": "Add Subchapter",
"titlePlaceholder": "e.g. Chapter 1: Introduction",
"toggle": "Toggle",
"orderUpdated": "Order updated",
"cancel": "Cancel",
"dragHandle": "Drag to reorder"
},
"knowledge": {
"createTitle": "Add Knowledge Point",
"createDesc": "Create a knowledge point from the selected text.",
"editTitle": "Edit Knowledge Point",
"editDesc": "Modify the knowledge point name and description.",
"name": "Name",
"description": "Description (optional)",
"descriptionPlaceholder": "Enter description...",
"displayName": "Display Name",
"anchorText": "Advanced: Anchor Text (affects highlighting)",
"anchorTextHint": "Changing this field will change the text highlighted in the content. Usually keep it consistent with the original.",
"create": "Create",
"creating": "Creating...",
"save": "Save",
"saving": "Saving...",
"cancel": "Cancel",
"deleteTitle": "Confirm Delete",
"deleteDesc": "Are you sure you want to delete this knowledge point? This action cannot be undone.",
"delete": "Delete",
"createQuestion": "Create Related Question",
"editKp": "Edit Knowledge Point",
"deleteKp": "Delete Knowledge Point"
}
},
"field": {
"title": "Title",
"subject": "Subject",
"grade": "Grade",
"publisher": "Publisher",
"titlePlaceholder": "e.g. Advanced Calculus",
"publisherPlaceholder": "e.g. Next Education",
"subjectPlaceholder": "Select subject",
"gradePlaceholder": "Select grade"
},
"filters": {
"searchPlaceholder": "Search by title, publisher...",
"allSubjects": "All Subjects",
"allGrades": "All Grades"
},
"card": {
"chapters": "Chapters",
"updated": "Updated",
"gradeNA": "Grade N/A",
"publisherNA": "Publisher N/A",
"editContent": "Edit Content",
"delete": "Delete",
"moreOptions": "More options"
},
"panel": {
"knowledgePoints": "Knowledge Points",
"noPointsYet": "No points yet",
"noPointsDesc": "Add knowledge points to tag content in this chapter.",
"selectChapter": "Select a chapter to manage knowledge points",
"level": "Lv."
},
"subject": {
"chinese": "Chinese",
"mathematics": "Mathematics",
"physics": "Physics",
"chemistry": "Chemistry",
"biology": "Biology",
"english": "English",
"history": "History",
"geography": "Geography"
},
"grade": {
"grade1": "Grade 1",
"grade2": "Grade 2",
"grade7": "Grade 7",
"grade8": "Grade 8",
"grade9": "Grade 9",
"grade10": "Grade 10",
"grade11": "Grade 11",
"grade12": "Grade 12"
},
"error": {
"loadFailed": "Failed to load textbook",
"loadFailedDesc": "An error occurred while loading the textbook content. Please try again.",
"retry": "Retry"
},
"action": {
"createSuccess": "Textbook created successfully.",
"createFailed": "Failed to create textbook.",
"updateSuccess": "Textbook updated successfully.",
"updateFailed": "Failed to update textbook.",
"deleteSuccess": "Textbook deleted successfully.",
"textbookDeleteFailed": "Failed to delete textbook.",
"chapterCreateSuccess": "Chapter created successfully",
"chapterCreateFailed": "Failed to create chapter",
"chapterDeleteSuccess": "Chapter deleted successfully",
"chapterDeleteFailed": "Failed to delete chapter",
"contentUpdateSuccess": "Content updated successfully",
"contentUpdateFailed": "Failed to update content",
"kpCreateSuccess": "Knowledge point created successfully",
"kpCreateFailed": "Failed to create knowledge point",
"kpUpdateSuccess": "Knowledge point updated successfully",
"kpUpdateFailed": "Failed to update knowledge point",
"kpDeleteSuccess": "Knowledge point deleted successfully",
"kpDeleteFailed": "Failed to delete knowledge point",
"reorderSuccess": "Order updated",
"reorderFailed": "Failed to reorder chapters",
"fillRequired": "Please fill in all required fields.",
"titleRequired": "Title is required",
"nameRequired": "Name is required",
"invalidContent": "Invalid chapter content data",
"errorOccurred": "An error occurred",
"deleteFailed": "Deletion failed",
"updateFailedGeneric": "Update failed",
"chapterNotBelong": "Chapter does not belong to this textbook",
"kpNotBelong": "Knowledge point does not belong to this textbook",
"chaptersReordered": "Chapters reordered successfully",
"ok": "OK",
"kpLoadFailed": "Failed to load knowledge points",
"graphLoadFailed": "Graph failed to load",
"invalidInput": "Invalid input",
"cyclicDependency": "Cannot add cyclic dependency",
"prerequisiteCreated": "Prerequisite added",
"prerequisiteCreateFailed": "Failed to add prerequisite",
"prerequisiteDeleted": "Prerequisite removed",
"prerequisiteDeleteFailed": "Failed to remove prerequisite"
},
"graph": {
"viewMode": {
"structure": "Structure",
"studentMastery": "My Mastery",
"classMastery": "Class Mastery"
},
"node": {
"questions": "Questions",
"mastery": "Mastery",
"prerequisite": "Prerequisite",
"successor": "Successor"
},
"detail": {
"title": "Knowledge Point Details",
"noDescription": "No description",
"viewAllQuestions": "View all questions",
"editPrerequisite": "Edit prerequisites",
"addPrerequisite": "Add prerequisite",
"removePrerequisite": "Remove",
"noPrerequisites": "No prerequisite knowledge points",
"noSuccessors": "No successor knowledge points",
"masteryNotAssessed": "Not assessed",
"correctRate": "Correct rate",
"totalQuestions": "Total questions"
},
"toolbar": {
"search": "Search knowledge points",
"filterByChapter": "Filter by chapter",
"resetView": "Reset view"
},
"empty": {
"noPrerequisites": "No prerequisite relationships",
"noData": "No graph data"
},
"error": {
"cyclicDependency": "Cannot add cyclic dependency",
"loadFailed": "Graph failed to load"
}
}
}