Files
CICD/docs/design/004_question_bank_implementation.md
SpecialX f8e39f518d feat(teacher): 题库模块(QuestionBank)
工作内容

- 新增 /teacher/questions 页面,支持 Suspense/空状态/加载态

- 题库 CRUD Server Actions:创建/更新/递归删除子题,变更后 revalidatePath

- getQuestions 支持 q/type/difficulty/knowledgePointId 筛选与分页返回 meta

- UI:表格列/筛选器/创建编辑弹窗,content JSON 兼容组卷

- 更新中文设计文档:docs/design/004_question_bank_implementation.md
2025-12-30 19:04:22 +08:00

4.4 KiB
Raw Permalink Blame History

题库模块实现

1. 概述

题库模块(src/modules/questions)是教师管理考试资源的核心组件,提供完整的 CRUD 能力,并支持搜索/筛选等常用管理能力。

状态:已实现
日期2025-12-23
作者:前端高级工程师


2. 架构与技术栈

2.1 垂直切片Vertical Slice架构

遵循项目的架构规范,所有与题库相关的逻辑都收敛在 src/modules/questions 下:

  • components/UI 组件(表格、弹窗、筛选器)
  • actions.tsServer Actions数据变更
  • data-access.ts:数据库查询逻辑
  • schema.tsZod 校验 Schema
  • types.tsTypeScript 类型定义

2.2 关键技术

  • 数据表格@tanstack/react-table(高性能表格渲染)
  • 状态管理nuqs(基于 URL Query 的筛选/搜索状态)
  • 表单react-hook-form + zod + shadcn/ui 表单组件
  • 校验Zod 提供严格的服务端/客户端校验

3. 组件设计

3.1 QuestionDataTablequestion-data-table.tsx

  • 能力:分页、排序、行选择
  • 性能:尽可能采用与 React.memo 兼容的写法(useReactTable 本身不做 memo
  • 响应式:移动端优先;复杂列支持横向滚动

3.2 QuestionColumnsquestion-columns.tsx

用于增强单元格展示的自定义渲染:

  • 题型 Badge:不同题型的颜色/样式区分(单选、多选等)
  • 难度展示:难度标签 + 数值
  • 行操作:下拉菜单(编辑、删除、查看详情、复制 ID

3.3 创建/编辑弹窗(create-question-dialog.tsx

创建与编辑共用同一个弹窗组件:

  • 动态字段:根据题型显示/隐藏“选项”区域
  • 选项编辑:支持添加/删除选项(选择题)
  • 交互反馈:提交中 Loading 状态

3.4 筛选器(question-filters.tsx

  • URL 同步:搜索、题型、难度等筛选条件与 URL 参数保持同步
  • 无 Debounce当前:搜索输入每次变更都会更新 URL
  • 服务端筛选:在服务端组件中通过 getQuestions 执行筛选查询

4. 实现细节

4.1 数据流

  1. 读取page.tsxServer Component根据 searchParams 拉取数据
  2. 写入:客户端组件调用 Server Actions -> revalidatePath -> UI 更新
  3. 筛选:用户操作 -> 更新 URL -> 服务端组件重新渲染 -> 返回新数据

4.2 类型安全

共享的 Question 类型用于保证前后端一致:

export interface Question {
  id: string
  content: unknown
  type: QuestionType
  difficulty: number
  // ... 关联字段
}

4.3 UI/UX 规范

  • 空状态:无数据时展示 EmptyState
  • 加载态:表格加载使用 Skeleton
  • 反馈Sonner toast 展示成功/失败提示
  • 确认弹窗:删除等破坏性操作使用 AlertDialog

5. 后续计划

  • 接入真实数据库(替换 Mock Data
  • 为题目内容引入富文本编辑器Slate.js / Tiptap
  • 增加“批量导入”能力
  • 增加知识点“标签”管理能力

6. 实现更新2025-12-30

6.1 教师路由与加载态

  • 实现 /teacher/questions 页面Suspense + 空状态)
  • 新增路由级加载 UI/teacher/questions/loading.tsx

6.2 Content JSON 约定

为与考试组卷/预览组件保持一致,questions.content 采用最小 JSON 结构:

type ChoiceOption = {
  id: string
  text: string
  isCorrect?: boolean
}

type QuestionContent = {
  text: string
  options?: ChoiceOption[]
}

6.3 数据访问层(getQuestions

  • 新增服务端筛选:qcontent LIKEtypedifficultyknowledgePointId
  • 默认仅返回根题(parentId IS NULL),除非显式按 ids 查询
  • 返回 { data, meta }(包含分页统计),并为 UI 映射关联数据

6.4 Server ActionsCRUD

  • createNestedQuestion 支持 FormData字段 json)与递归 subQuestions
  • updateQuestionAction 更新题目与知识点关联
  • deleteQuestionAction 递归删除子题
  • 所有变更都会对 /teacher/questions 做缓存再验证

6.5 UI 集成

  • CreateQuestionDialog 提交 QuestionContent JSON并支持选择题正确答案勾选
  • QuestionActions 在编辑/删除后刷新列表
  • 表格内容预览优先展示 content.text

6.6 校验

  • npm run lint0 errors仓库其他位置仍存在 warnings
  • npm run typecheck:通过