refactor(lesson-preparation): V2 审计深度修复 — Server Actions i18n + 错误码模式 + 类型断言清零 + a11y 深度修复 + Tracker 埋点接入
V2-1: 12 个 Server Action 通过 getTranslations 翻译错误消息;Service/DataAccess 层抛出错误码异常(PublishServiceError/LessonPlanDataError),Actions 层通过 PUBLISH_ERROR_KEY_MAP 翻译为 i18n 消息 V2-2: SYSTEM_TEMPLATES name/title 改为 i18n 键,createLessonPlan 接受 translateTitle 函数在服务端翻译后存储到 DB V2-3: 8 处 as unknown as 断言替换为显式类型映射函数(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 同步更新架构图 004 和 005 文档
This commit is contained in:
@@ -52,8 +52,12 @@ export function ExerciseBlock({ blockId, data, classes, textbookId, chapterId }:
|
||||
|
||||
return (
|
||||
<div className="space-y-2">
|
||||
<div className="flex gap-2">
|
||||
<div className="flex gap-2 items-center">
|
||||
<label htmlFor={`exercise-purpose-${blockId}`} className="text-sm font-medium">
|
||||
{t("exercise.purposeLabel")}
|
||||
</label>
|
||||
<select
|
||||
id={`exercise-purpose-${blockId}`}
|
||||
value={data.purpose}
|
||||
onChange={(e) =>
|
||||
update({ purpose: e.target.value as ExercisePurpose })
|
||||
@@ -69,9 +73,9 @@ export function ExerciseBlock({ blockId, data, classes, textbookId, chapterId }:
|
||||
{t("questionBank.empty")}
|
||||
</p>
|
||||
) : (
|
||||
<div className="space-y-1">
|
||||
<ul className="space-y-1 list-none p-0" role="list">
|
||||
{data.items.map((item, idx) => (
|
||||
<div
|
||||
<li
|
||||
key={item.questionId}
|
||||
className="flex items-center gap-2 border rounded p-2"
|
||||
>
|
||||
@@ -87,9 +91,9 @@ export function ExerciseBlock({ blockId, data, classes, textbookId, chapterId }:
|
||||
<button onClick={() => removeItem(idx)} aria-label={t("action.delete")}>
|
||||
<Trash2 className="w-3 h-3 text-error" aria-hidden="true" />
|
||||
</button>
|
||||
</div>
|
||||
</li>
|
||||
))}
|
||||
</div>
|
||||
</ul>
|
||||
)}
|
||||
<div className="flex gap-2 flex-wrap">
|
||||
<Button
|
||||
|
||||
Reference in New Issue
Block a user