refactor(announcements,messaging,notifications): V1+V2 审计重构 — i18n 命名空间独立 + 通知标题 i18n 化 + 服务端过滤 + 编排下沉 + 表单错误展示 + 架构图同步
V1 改进(已完成): - P0-4/P1-4/P1-5: 通知组件和 CRUD Action 从 messaging 迁移至 notifications 模块 - P1-5: 新增 getMessagesPageData / getAdminAnnouncementsPageData 编排函数 - P1-6: announcements schema 添加 superRefine 条件校验 - P1-7: 新增 useMessageSearch hook(防抖 + 请求竞态取消)+ 客户端分页 UI - P1-9: deleteMessage 事务化 - P2-11: 全模块 trackEvent 埋点 - 全模块 i18n 接入 + Error Boundary + a11y 改进 V2 改进(本次完成): - V2-P0-1: 通知 i18n 命名空间独立(notifications.json),useTranslations 从 "messages" 切换到 "notifications" - V2-P0-2: 公告/消息通知标题 i18n 化,Server Action 中使用 getTranslations 生成通知标题 - V2-P1-1: AnnouncementList 纯服务端过滤,移除客户端 useState/useMemo - V2-P1-2: MessageList 客户端过滤仅在初始数据时执行,搜索结果由服务端按 tab 过滤 - V2-P1-3: 消息详情页编排下沉,新增 getMessageDetailPageData 编排函数 - V2-P1-4: 表单服务端校验错误展示(fieldErrors + aria-invalid) - V2-P2-1: 轮询间隔常量化(POLL_INTERVAL_MS) - V2-P2-2: 架构图同步(004 + 005)
This commit is contained in:
@@ -4086,6 +4086,12 @@
|
||||
"permission": "TEXTBOOK_UPDATE",
|
||||
"signature": "(chapterId, newIndex, parentId, textbookId) => Promise<ActionState>",
|
||||
"purpose": "章节排序"
|
||||
},
|
||||
{
|
||||
"name": "getKnowledgePointsByChapterAction",
|
||||
"permission": "TEXTBOOK_READ",
|
||||
"signature": "(chapterId, textbookId) => Promise<ActionState<KnowledgePoint[]>>",
|
||||
"purpose": "获取章节下的知识点列表(含资源归属校验)"
|
||||
}
|
||||
],
|
||||
"dataAccess": [
|
||||
@@ -4249,6 +4255,24 @@
|
||||
"updateKnowledgePointAction",
|
||||
"deleteKnowledgePointAction"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "getSubjectLabelKey",
|
||||
"signature": "(subject: string) => string",
|
||||
"purpose": "获取学科的 i18n 标签键",
|
||||
"usedBy": [
|
||||
"textbooks/components/textbook-filters.tsx",
|
||||
"textbooks/components/textbook-card.tsx"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "getGradeLabelKey",
|
||||
"signature": "(grade: string) => string",
|
||||
"purpose": "获取年级的 i18n 标签键",
|
||||
"usedBy": [
|
||||
"textbooks/components/textbook-filters.tsx",
|
||||
"textbooks/components/textbook-card.tsx"
|
||||
]
|
||||
}
|
||||
],
|
||||
"hooks": [
|
||||
@@ -4264,7 +4288,7 @@
|
||||
{
|
||||
"name": "useKnowledgePointActions",
|
||||
"file": "hooks/use-knowledge-point-actions.ts",
|
||||
"signature": "(textbookId, selectedChapterId, selectedChapterTextbookId, highlightedKpId, setHighlightedKpId, onKpCreated?) => { editingKp, setEditingKp, editKpDialogOpen, setEditKpDialogOpen, isUpdatingKp, questionDialogOpen, setQuestionDialogOpen, targetKpForQuestion, setTargetKpForQuestion, deleteConfirmOpen, setDeleteConfirmOpen, handleCreateKnowledgePoint, requestDeleteKP, confirmDeleteKP, handleUpdateKP }",
|
||||
"signature": "(textbookId, selectedChapterId, selectedChapterTextbookId, highlightedKpId, setHighlightedKpId, onKpCreated?) => { editingKp, setEditingKp, editKpDialogOpen, setEditKpDialogOpen, isUpdatingKp, questionDialogOpen, setQuestionDialogOpen, targetKpForQuestion, setTargetKpForQuestion, deleteConfirmOpen, setDeleteConfirmOpen, handleCreateKnowledgePoint, requestDeleteKnowledgePoint, confirmDeleteKnowledgePoint, handleUpdateKnowledgePoint }",
|
||||
"purpose": "知识点操作Hook(6参数)",
|
||||
"usedBy": [
|
||||
"textbook-reader.tsx"
|
||||
@@ -4361,6 +4385,105 @@
|
||||
]
|
||||
}
|
||||
],
|
||||
"constants": [
|
||||
{
|
||||
"name": "SUBJECTS",
|
||||
"file": "constants.ts",
|
||||
"purpose": "学科常量数组"
|
||||
},
|
||||
{
|
||||
"name": "GRADES",
|
||||
"file": "constants.ts",
|
||||
"purpose": "年级常量数组"
|
||||
},
|
||||
{
|
||||
"name": "SUBJECT_COLORS",
|
||||
"file": "constants.ts",
|
||||
"purpose": "学科颜色映射"
|
||||
},
|
||||
{
|
||||
"name": "getSubjectColor",
|
||||
"file": "constants.ts",
|
||||
"signature": "(subject: string) => string",
|
||||
"purpose": "获取学科对应颜色"
|
||||
},
|
||||
{
|
||||
"name": "getSubjectLabelKey",
|
||||
"file": "constants.ts",
|
||||
"signature": "(subject: string) => string",
|
||||
"purpose": "获取学科 i18n 标签键"
|
||||
},
|
||||
{
|
||||
"name": "getGradeLabelKey",
|
||||
"file": "constants.ts",
|
||||
"signature": "(grade: string) => string",
|
||||
"purpose": "获取年级 i18n 标签键"
|
||||
}
|
||||
],
|
||||
"utils": [
|
||||
{
|
||||
"name": "sortChapters",
|
||||
"file": "utils.ts",
|
||||
"purpose": "章节排序"
|
||||
},
|
||||
{
|
||||
"name": "buildChapterTree",
|
||||
"file": "utils.ts",
|
||||
"purpose": "构建章节树(返回 ChapterTreeNode[])"
|
||||
},
|
||||
{
|
||||
"name": "buildChapterIndex",
|
||||
"file": "utils.ts",
|
||||
"purpose": "构建章节索引 Map"
|
||||
},
|
||||
{
|
||||
"name": "findChapterParent",
|
||||
"file": "utils.ts",
|
||||
"purpose": "查找章节父节点"
|
||||
},
|
||||
{
|
||||
"name": "filterKnowledgePointsByChapter",
|
||||
"file": "utils.ts",
|
||||
"purpose": "按章节过滤知识点"
|
||||
},
|
||||
{
|
||||
"name": "normalizeOptional",
|
||||
"file": "utils.ts",
|
||||
"purpose": "可选字段归一化"
|
||||
},
|
||||
{
|
||||
"name": "highlightKnowledgePoints",
|
||||
"file": "utils.ts",
|
||||
"purpose": "高亮知识点"
|
||||
}
|
||||
],
|
||||
"graphLayout": [
|
||||
{
|
||||
"name": "computeGraphLayout",
|
||||
"file": "graph-layout.ts",
|
||||
"purpose": "知识图谱布局计算纯函数"
|
||||
}
|
||||
],
|
||||
"analytics": [
|
||||
{
|
||||
"name": "TextbookAnalytics",
|
||||
"file": "analytics.tsx",
|
||||
"type": "context",
|
||||
"purpose": "教材分析 Context"
|
||||
},
|
||||
{
|
||||
"name": "TextbookAnalyticsProvider",
|
||||
"file": "analytics.tsx",
|
||||
"type": "component",
|
||||
"purpose": "教材分析 Provider"
|
||||
},
|
||||
{
|
||||
"name": "useTextbookAnalytics",
|
||||
"file": "analytics.tsx",
|
||||
"type": "hook",
|
||||
"purpose": "教材分析 Hook"
|
||||
}
|
||||
],
|
||||
"components": [
|
||||
{
|
||||
"name": "ChapterSidebarList",
|
||||
@@ -4370,10 +4493,6 @@
|
||||
"name": "CreateChapterDialog",
|
||||
"purpose": "创建章节对话框"
|
||||
},
|
||||
{
|
||||
"name": "CreateKnowledgePointDialog",
|
||||
"purpose": "创建知识点对话框"
|
||||
},
|
||||
{
|
||||
"name": "KnowledgeGraph",
|
||||
"purpose": "知识图谱可视化"
|
||||
@@ -4387,8 +4506,8 @@
|
||||
"purpose": "知识点列表"
|
||||
},
|
||||
{
|
||||
"name": "KnowledgePointPanel",
|
||||
"purpose": "知识点面板"
|
||||
"name": "SectionErrorBoundary",
|
||||
"purpose": "章节内容错误边界(class component + i18n + router.refresh 重试)"
|
||||
},
|
||||
{
|
||||
"name": "TextbookCard",
|
||||
@@ -4415,27 +4534,25 @@
|
||||
"purpose": "教材设置对话框"
|
||||
}
|
||||
],
|
||||
"uiDeps": [
|
||||
{
|
||||
"from": "textbooks/components/knowledge-point-dialogs.tsx",
|
||||
"to": "questions/components/create-question-dialog",
|
||||
"status": "P0 待解耦(直接 import 跨模块业务组件,应改为 props/Context 注入)",
|
||||
"auditRef": "audit/textbooks-audit-report.md §2.1.1"
|
||||
}
|
||||
],
|
||||
"uiDeps": [],
|
||||
"uiDepsNote": "已通过 render prop 解耦,不再直接 import questions 模块组件",
|
||||
"knownIssues": [
|
||||
"P0 跨模块 UI 依赖:knowledge-point-dialogs.tsx 直接 import questions 模块 CreateQuestionDialog",
|
||||
"P0 前端权限硬编码:canEdit={true} 按路由写死,未用 usePermission().hasPermission()",
|
||||
"P0 全模块零 i18n:中英文文案硬编码,未接入 next-intl",
|
||||
"P1 Server Action 未校验资源归属(chapterId 是否属于 textbookId)",
|
||||
"P1 data-access 缺数据范围过滤(学生端未按年级过滤)",
|
||||
"P1 缺 Error Boundary(无 error.tsx)",
|
||||
"P1 知识点列表/弹窗重复实现(knowledge-point-panel.tsx 无调用方)",
|
||||
"P1 学科/年级选项硬编码三处且彼此不一致",
|
||||
"P1 纯逻辑未导出,零单测",
|
||||
"P2 类型断言:chapter-sidebar-list.tsx 用 ! 、knowledge-graph.tsx 用 as+!",
|
||||
"P2 删除确认不一致:textbook-settings-dialog 用 confirm(),其余用 AlertDialog"
|
||||
"i18n 覆盖率约 95%(chapter-sidebar-list 已接入,actions.ts 已接入,section-error-boundary 默认值已改英文)",
|
||||
"类型断言残留 3 处 as string",
|
||||
"P2 图谱方向键导航未实现"
|
||||
],
|
||||
"files": {
|
||||
"actions.ts": 377,
|
||||
"data-access.ts": 619,
|
||||
"types.ts": 45,
|
||||
"schema.ts": 64,
|
||||
"constants.ts": 91,
|
||||
"utils.ts": 181,
|
||||
"graph-layout.ts": 141,
|
||||
"analytics.tsx": 43,
|
||||
"hooks/use-knowledge-point-actions.ts": 121,
|
||||
"hooks/use-text-selection.ts": 57
|
||||
},
|
||||
"auditReport": "audit/textbooks-audit-report.md"
|
||||
}
|
||||
},
|
||||
@@ -5804,6 +5921,24 @@
|
||||
{
|
||||
"name": "AcademicYearClient",
|
||||
"purpose": "学年管理客户端"
|
||||
},
|
||||
{
|
||||
"name": "SchoolErrorBoundary",
|
||||
"file": "components/school-error-boundary.tsx",
|
||||
"purpose": "school 模块共享 Error Boundary(class component + i18n + router.refresh 重试),4 个页面均包裹",
|
||||
"props": "children, fallback?"
|
||||
},
|
||||
{
|
||||
"name": "SchoolListSkeleton",
|
||||
"file": "components/school-skeleton.tsx",
|
||||
"purpose": "表格加载骨架屏(animate-pulse)",
|
||||
"props": "rows?"
|
||||
},
|
||||
{
|
||||
"name": "SchoolCardSkeleton",
|
||||
"file": "components/school-skeleton.tsx",
|
||||
"purpose": "卡片加载骨架屏(animate-pulse)",
|
||||
"props": ""
|
||||
}
|
||||
],
|
||||
"hooks": [
|
||||
@@ -12938,7 +13073,13 @@
|
||||
"P1-7": "新增 4 个角色配置(TEACHER/ADMIN/STUDENT/PARENT)+ ROLE_CONFIGS 注册表",
|
||||
"P1-8": "新增 BLOCK_REGISTRY 注册表,node-edit-panel 配置驱动渲染",
|
||||
"P2-1": "5 个组件添加 role=dialog/aria-modal/aria-label",
|
||||
"P2-4": "预留 LessonPlanTracker 接口 + noopTracker 默认实现"
|
||||
"P2-4": "预留 LessonPlanTracker 接口 + noopTracker 默认实现",
|
||||
"V2-1": "Server Actions i18n + 错误码模式:12 个 Action 通过 getTranslations 翻译错误消息;Service/DataAccess 层抛出 PublishServiceError/LessonPlanDataError 错误码,Actions 层通过 PUBLISH_ERROR_KEY_MAP 翻译",
|
||||
"V2-2": "SYSTEM_TEMPLATES i18n 化:name/title 改为 i18n 键,createLessonPlan 接受 translateTitle 函数在服务端翻译后存储到 DB",
|
||||
"V2-3": "as unknown as 类型断言清零:8 处替换为显式类型映射函数(mapRowToLessonPlan/mapRowToListItem/mapRowToTemplate/mapRowToVersion)+ 类型守卫(isLessonPlanStatus/isTemplateType/isTemplateScope)",
|
||||
"V2-4": "MiniMap nodeColor 复用 lib/node-summary.ts 的 getNodeColor",
|
||||
"V2-5": "a11y 深度修复:lesson-plan-filters/exercise-block/inline-question-editor 的 select 添加 label htmlFor 关联;exercise-block 题目列表改为 ul/li;node-editor 画布添加 role=application + 键盘导航配置",
|
||||
"V2-6": "Tracker 埋点接入:新增 useLessonPlanTrackerSafe hook,在 create/save/publish/revert/duplicate/archive 6 处调用 tracker.track"
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user