feat(lesson-preparation): 备课模块审计重构 — 跨模块解耦 + i18n + 纯函数抽取 + 错误边界
P0-1 跨模块直查修复:publish-service 不再直查 examQuestions 表,新增 exams/data-access.addExamQuestions 接口,复用 classes/data-access.getStudentIdsByClassIds P0-2 i18n 接入:新增 zh-CN/en 翻译文件,注册 lessonPreparation 命名空间,17 个组件改造为 useTranslations/getTranslations P1 纯函数抽取:lib/document-migration.ts(类型守卫替代 as 断言)、lib/node-summary.ts(翻译函数注入)、lib/rf-mappers.ts P1 错误边界+骨架屏:新增 LessonPlanErrorBoundary 和 4 个 Skeleton 组件 P1 Block 注册表:新增 config/block-registry.tsx(BlockRenderer 组件),node-edit-panel 重构为配置驱动渲染 P1 其他修复:exercise-block 改用 router.refresh(),node-editor/lesson-node 复用 lib/ 纯函数 架构图同步:更新 004 和 005 文档 Refs: docs/architecture/audit/lesson-preparation-audit-report.md
This commit is contained in:
110
src/modules/lesson-preparation/config/block-registry.tsx
Normal file
110
src/modules/lesson-preparation/config/block-registry.tsx
Normal file
@@ -0,0 +1,110 @@
|
||||
import type { ReactElement } from "react";
|
||||
import type {
|
||||
BlockType,
|
||||
ExerciseBlockData,
|
||||
RichTextBlockData,
|
||||
TextStudyBlockData,
|
||||
} from "../types";
|
||||
import { RichTextBlock } from "../components/blocks/rich-text-block";
|
||||
import { ExerciseBlock } from "../components/blocks/exercise-block";
|
||||
import { TextStudyBlock } from "../components/blocks/text-study-block";
|
||||
import { ReflectionBlock } from "../components/blocks/reflection-block";
|
||||
|
||||
/**
|
||||
* Block 注册表:配置驱动渲染。
|
||||
* 新增 Block 类型只需在此注册,无需修改 NodeEditPanel。
|
||||
*/
|
||||
|
||||
export interface BlockRenderProps {
|
||||
blockId: string;
|
||||
data: RichTextBlockData | ExerciseBlockData | TextStudyBlockData;
|
||||
textbookId?: string;
|
||||
chapterId?: string;
|
||||
classes?: { id: string; name: string }[];
|
||||
onUpdate: (data: RichTextBlockData | ExerciseBlockData | TextStudyBlockData) => void;
|
||||
}
|
||||
|
||||
export interface BlockRegistryEntry {
|
||||
/** 是否为富文本类(共享 RichTextBlock 编辑器) */
|
||||
isRichText?: boolean;
|
||||
}
|
||||
|
||||
const RICH_TEXT_TYPES: BlockType[] = [
|
||||
"objective",
|
||||
"key_point",
|
||||
"import",
|
||||
"new_teaching",
|
||||
"consolidation",
|
||||
"summary",
|
||||
"homework",
|
||||
"blackboard",
|
||||
"rich_text",
|
||||
];
|
||||
|
||||
/**
|
||||
* Block 注册表元数据(用于查询 isRichText 等属性)。
|
||||
* 组件渲染由 BlockRenderer 统一处理,避免在 render 中动态获取组件引用。
|
||||
*/
|
||||
export const BLOCK_REGISTRY: Record<BlockType, BlockRegistryEntry> = {
|
||||
objective: { isRichText: true },
|
||||
key_point: { isRichText: true },
|
||||
import: { isRichText: true },
|
||||
new_teaching: { isRichText: true },
|
||||
consolidation: { isRichText: true },
|
||||
summary: { isRichText: true },
|
||||
homework: { isRichText: true },
|
||||
blackboard: { isRichText: true },
|
||||
rich_text: { isRichText: true },
|
||||
exercise: {},
|
||||
text_study: {},
|
||||
reflection: {},
|
||||
};
|
||||
|
||||
export function isRichTextBlock(type: BlockType): boolean {
|
||||
return RICH_TEXT_TYPES.includes(type);
|
||||
}
|
||||
|
||||
/**
|
||||
* 静态 Block 渲染组件。
|
||||
* 根据 type 从注册表查找并渲染对应 Block,所有组件引用均为模块顶层静态声明,
|
||||
* 满足 react-hooks/static-components 规则。
|
||||
* 新增 Block 类型时,在此 switch 中添加对应 case 即可。
|
||||
*/
|
||||
export function BlockRenderer(props: BlockRenderProps & { type: BlockType }): ReactElement | null {
|
||||
const { type, ...rest } = props;
|
||||
switch (type) {
|
||||
case "exercise":
|
||||
return (
|
||||
<ExerciseBlock
|
||||
blockId={rest.blockId}
|
||||
data={rest.data as ExerciseBlockData}
|
||||
classes={rest.classes ?? []}
|
||||
textbookId={rest.textbookId}
|
||||
chapterId={rest.chapterId}
|
||||
/>
|
||||
);
|
||||
case "text_study":
|
||||
return <TextStudyBlock blockId={rest.blockId} data={rest.data as TextStudyBlockData} />;
|
||||
case "reflection":
|
||||
return <ReflectionBlock data={rest.data as RichTextBlockData} onUpdate={rest.onUpdate} />;
|
||||
case "objective":
|
||||
case "key_point":
|
||||
case "import":
|
||||
case "new_teaching":
|
||||
case "consolidation":
|
||||
case "summary":
|
||||
case "homework":
|
||||
case "blackboard":
|
||||
case "rich_text":
|
||||
return (
|
||||
<RichTextBlock
|
||||
data={rest.data as RichTextBlockData}
|
||||
textbookId={rest.textbookId}
|
||||
chapterId={rest.chapterId}
|
||||
onUpdate={rest.onUpdate}
|
||||
/>
|
||||
);
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user