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

133 lines
4.4 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 题库模块实现
## 1. 概述
题库模块(`src/modules/questions`)是教师管理考试资源的核心组件,提供完整的 CRUD 能力,并支持搜索/筛选等常用管理能力。
**状态**:已实现
**日期**2025-12-23
**作者**:前端高级工程师
---
## 2. 架构与技术栈
### 2.1 垂直切片Vertical Slice架构
遵循项目的架构规范,所有与题库相关的逻辑都收敛在 `src/modules/questions` 下:
- `components/`UI 组件(表格、弹窗、筛选器)
- `actions.ts`Server Actions数据变更
- `data-access.ts`:数据库查询逻辑
- `schema.ts`Zod 校验 Schema
- `types.ts`TypeScript 类型定义
### 2.2 关键技术
- **数据表格**`@tanstack/react-table`(高性能表格渲染)
- **状态管理**`nuqs`(基于 URL Query 的筛选/搜索状态)
- **表单**`react-hook-form` + `zod` + `shadcn/ui` 表单组件
- **校验**Zod 提供严格的服务端/客户端校验
---
## 3. 组件设计
### 3.1 QuestionDataTable`question-data-table.tsx`
- **能力**:分页、排序、行选择
- **性能**:尽可能采用与 `React.memo` 兼容的写法(`useReactTable` 本身不做 memo
- **响应式**:移动端优先;复杂列支持横向滚动
### 3.2 QuestionColumns`question-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.tsx`Server Component根据 `searchParams` 拉取数据
2. **写入**:客户端组件调用 Server Actions -> `revalidatePath` -> UI 更新
3. **筛选**:用户操作 -> 更新 URL -> 服务端组件重新渲染 -> 返回新数据
### 4.2 类型安全
共享的 `Question` 类型用于保证前后端一致:
```typescript
export interface Question {
id: string
content: unknown
type: QuestionType
difficulty: number
// ... 关联字段
}
```
### 4.3 UI/UX 规范
- **空状态**:无数据时展示 `EmptyState`
- **加载态**:表格加载使用 Skeleton
- **反馈**`Sonner` toast 展示成功/失败提示
- **确认弹窗**:删除等破坏性操作使用 `AlertDialog`
---
## 5. 后续计划
- [x] 接入真实数据库(替换 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 结构:
```typescript
type ChoiceOption = {
id: string
text: string
isCorrect?: boolean
}
type QuestionContent = {
text: string
options?: ChoiceOption[]
}
```
### 6.3 数据访问层(`getQuestions`
- 新增服务端筛选:`q`content LIKE`type``difficulty``knowledgePointId`
- 默认仅返回根题(`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 lint`0 errors仓库其他位置仍存在 warnings
- `npm run typecheck`:通过