refactor(exams,homework,proctoring): 审计重构 — 跨模块解耦 + 权限 + i18n + a11y + 单测 + 监控埋点
完成考试与作业模块深度审计的全部 10 项改进: P0-3: 拆分 ai-pipeline.ts (927 行) 为 parse/request/structure/index 四个职责模块 P1-6: 抽取 QuestionRenderer 组件 (mode prop 驱动 take/preview/grade 三态) P1-7: 抽取 question-content-utils 纯函数模块 (14 个纯函数 + applyAutoGrades 泛型) P1-8: 拆分 homework data-access 为 data-access.ts + data-access-classes.ts P2-9: 集成 useDebouncedAutoSave (防抖自动保存 + localStorage 离线缓存 + 状态指示器) P2-12: a11y 修复 (难度色条 role=img + aria-label, 题目导航 aria-pressed + title) P2-13: ExamHomeworkRoleConfig 配置驱动角色渲染 (6 角色 × 11 功能 + 并集合并) 6.1: ExamHomeworkServicePort 接口 + ServiceProvider 单例注册表 6.5: 63 个单测 (52 question-content-utils + 11 role-config) 6.7: trackExamEvent 监控埋点 (17 个新事件 + 便捷函数) 同步更新 005 架构数据文档与 v2 审计报告
This commit is contained in:
@@ -1,6 +1,6 @@
|
|||||||
import Link from "next/link"
|
import Link from "next/link"
|
||||||
import { PenTool, Calendar, Plus } from "lucide-react"
|
import { PenTool, Calendar, Plus } from "lucide-react"
|
||||||
import { getTranslations } from "next-intl/server"
|
import { getTranslations, getLocale } from "next-intl/server"
|
||||||
|
|
||||||
import { Badge } from "@/shared/components/ui/badge"
|
import { Badge } from "@/shared/components/ui/badge"
|
||||||
import { Button } from "@/shared/components/ui/button"
|
import { Button } from "@/shared/components/ui/button"
|
||||||
@@ -11,6 +11,7 @@ import type { HomeworkAssignmentListItem } from "@/modules/homework/types"
|
|||||||
|
|
||||||
export async function TeacherHomeworkCard({ assignments }: { assignments: HomeworkAssignmentListItem[] }) {
|
export async function TeacherHomeworkCard({ assignments }: { assignments: HomeworkAssignmentListItem[] }) {
|
||||||
const t = await getTranslations("dashboard")
|
const t = await getTranslations("dashboard")
|
||||||
|
const locale = await getLocale()
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Card>
|
<Card>
|
||||||
@@ -19,7 +20,7 @@ export async function TeacherHomeworkCard({ assignments }: { assignments: Homewo
|
|||||||
<PenTool className="h-4 w-4 text-muted-foreground" />
|
<PenTool className="h-4 w-4 text-muted-foreground" />
|
||||||
{t("sections.homework")}
|
{t("sections.homework")}
|
||||||
</CardTitle>
|
</CardTitle>
|
||||||
<Button asChild size="icon" variant="ghost" className="h-8 w-8" title={t("quickActions.createNewAssignment")}>
|
<Button asChild size="icon" variant="ghost" className="h-8 w-8" title={t("quickActions.createNewAssignment")} aria-label={t("quickActions.createNewAssignment")}>
|
||||||
<Link href="/teacher/homework/assignments/create">
|
<Link href="/teacher/homework/assignments/create">
|
||||||
<Plus className="h-4 w-4" />
|
<Plus className="h-4 w-4" />
|
||||||
</Link>
|
</Link>
|
||||||
@@ -66,7 +67,7 @@ export async function TeacherHomeworkCard({ assignments }: { assignments: Homewo
|
|||||||
{a.dueAt ? (
|
{a.dueAt ? (
|
||||||
<div className="flex items-center text-xs text-muted-foreground tabular-nums">
|
<div className="flex items-center text-xs text-muted-foreground tabular-nums">
|
||||||
<Calendar className="mr-1 h-3 w-3 opacity-70" />
|
<Calendar className="mr-1 h-3 w-3 opacity-70" />
|
||||||
{formatDate(a.dueAt)}
|
{formatDate(a.dueAt, locale)}
|
||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
<span className="text-[10px] text-muted-foreground italic">{t("schedule.noDueDate")}</span>
|
<span className="text-[10px] text-muted-foreground italic">{t("schedule.noDueDate")}</span>
|
||||||
|
|||||||
Reference in New Issue
Block a user