Files
CICD/docs/design/005_exam_module_implementation.md
SpecialX e7c902e8e1
Some checks failed
CI / build-and-test (push) Failing after 1m31s
CI / deploy (push) Has been skipped
Module Update
2025-12-30 14:42:30 +08:00

3.7 KiB
Raw Blame History

考试模块实现设计文档

1. 概述

考试模块提供了一个完整的评估管理生命周期,使教师能够创建考试、组卷(支持嵌套分组)、发布评估以及对学生的提交进行评分。

2. 数据架构

2.1 核心实体

  • Exams: 根实体,包含元数据(标题、时间安排)和结构信息。
  • ExamQuestions: 关系链接,用于查询题目的使用情况(扁平化表示)。
  • ExamSubmissions: 学生的考试尝试记录。
  • SubmissionAnswers: 链接到特定题目的单个答案。

2.2 structure 字段

为了支持层级布局(如章节/分组),我们在 exams 表中引入了一个 JSON 列 structure。这作为考试布局的“单一事实来源”Source of Truth

JSON Schema:

type ExamNode = {
  id: string;              // 节点的唯一 UUID
  type: 'group' | 'question';
  title?: string;          // 'group' 类型必填
  questionId?: string;     // 'question' 类型必填
  score?: number;          // 在此考试上下文中的分值
  children?: ExamNode[];   // 'group' 类型的递归子节点
}

3. 组件架构

3.1 组卷(构建器)

位于 /teacher/exams/[id]/build

  • ExamAssembly (客户端组件)
    • 管理 structure 状态树。
    • 处理“添加题目”、“添加章节”、“移除”和“重新排序”操作。
    • 实时计算总分和进度。
  • StructureEditor (客户端组件)
    • 基于 @dnd-kit 构建。
    • 提供嵌套的可排序Sortable界面。
    • 支持在组内/组间拖拽题目(当前优化为 2 层深度)。
  • QuestionBankList
    • 可搜索/筛选的可用题目列表。
    • “添加”操作将节点追加到结构树中。

3.2 阅卷界面

位于 /teacher/exams/grading/[submissionId]

  • GradingView (客户端组件)
    • 左侧面板: 只读视图,显示学生的答案与题目内容。
    • 右侧面板: 评分和反馈的输入字段。
    • 状态: 在提交前管理本地更改。
  • Actions: gradeSubmissionAction 更新 submissionAnswers 并将总分聚合到 examSubmissions

4. 关键工作流

4.1 创建与构建考试

  1. 创建: 教师输入基本信息(标题、科目)。数据库创建记录(草稿状态)。
  2. 构建:
    • 教师打开“构建”页面。
    • 服务器从数据库 Hydrate注水initialStructure
    • 教师从题库拖拽题目到结构树。
    • 教师创建章节(分组)。
    • 保存: 同时提交 questionsJson(扁平化,用于索引)和 structureJson(树状,用于布局)到 updateExamAction
  3. 发布: 状态变更为 published

4.2 阅卷流程

  1. 列表: 教师查看 submission-data-table
  2. 评分: 打开特定提交。
  3. 审查: 遍历题目。
    • 系统显示学生答案。
    • 教师输入分数(上限为满分)和反馈。
  4. 提交: 服务器更新单个答案记录并重新计算提交总分。

5. 技术决策

5.1 混合存储策略

我们在存储考试题目时采用了 混合方法

  • 关系型 (exam_questions): 用于“查找所有使用题目 X 的考试”查询和外键约束。
  • 文档型 (exams.structure): 用于渲染嵌套 UI 和保留任意排序/分组。 理由: 这结合了 SQL 的完整性和 NoSQL 在 UI 布局上的灵活性。

5.2 拖拽功能

使用 @dnd-kit 代替旧库,因为:

  • 更好的无障碍支持(键盘支持)。
  • 模块化架构Sensors, Modifiers
  • 面向未来(现代 React Hooks 模式)。

5.3 Server Actions

所有变更操作(保存草稿、发布、评分)均使用 Next.js Server Actions以确保类型安全并自动重新验证缓存。