多库检索与存储修复: - RRF 融合去重改用 (collection, chunk_id) 复合键,修复同名文件结果被吞 - DocStore 存储路径加 collection 前缀,修复跨库同名切片数据覆盖 - search_multiple 去重改用复合键 - chunk_id 解析改用 rsplit 兼容下划线文件名 上传与版本管理修复: - 同名文件上传改为覆盖模式,自动清理旧切片 - 修复首次上传不创建版本记录 - 修复覆盖上传版本号回退到 v1 - sync ADDED 分支改用动态版本号生成 - _generate_version_id 改为基于全部版本递增 - 废止/恢复操作同步 SQLite 版本记录 - mark_document_as_superseded 改为仅更新 SQLite 删除清理修复: - 删除文档时同步清理 SQLite 版本记录和变更日志 - 删除向量库时同步清理该库所有版本记录 - cleanup 改为清理 SQLite 记录而非 ChromaDB 测试: - test_version_management.py: 27 条版本管理单元测试 - test_edge_cases.py: 28 条边界用例测试 - test_upload_dedup.py: 5 条上传去重测试 - e2e_risk_test.py: 27 条端到端风险测试 文档: - 新增风险边界问题修复注意事项.md(面向后端的对接文档) - 新增向量库边界风险分析.md - 更新多篇现有文档
636 lines
20 KiB
Markdown
636 lines
20 KiB
Markdown
# 出题批卷系统设计
|
||
|
||
> **文档类型**: 系统设计文档
|
||
> **创建日期**: 2026-04-10
|
||
> **最后更新**: 2026-06-04
|
||
> **状态**: 已实施
|
||
|
||
---
|
||
|
||
## 一、系统概述
|
||
|
||
### 1.1 背景
|
||
|
||
出题批卷系统是 RAG 知识库系统的扩展模块,支持:
|
||
- **按文件出题**:根据指定文档自动生成题目
|
||
- **智能批卷**:支持选择题、填空题、简答题的自动批改
|
||
- **溯源追踪**:每道题可追溯到来源文件和知识片段
|
||
|
||
### 1.2 模块结构
|
||
|
||
```
|
||
exam_pkg/ # 考试系统
|
||
├── generator.py # 出题逻辑(按文件/按主题生成题目)
|
||
├── grader.py # 批卷逻辑(选择题/填空题/简答题批改)
|
||
├── manager.py # 试卷管理与协调逻辑
|
||
├── api.py # Flask Blueprint (exam_bp)
|
||
└── local_db.py # 本地题库 (SQLite)
|
||
```
|
||
|
||
**认证模块**: `auth/gateway.py` - 网关认证
|
||
|
||
---
|
||
|
||
## 二、出题系统设计
|
||
|
||
### 2.1 按文件出题接口
|
||
|
||
**接口路径**:`POST /exam/generate-by-file`
|
||
|
||
**请求参数**:
|
||
```json
|
||
{
|
||
"file_path": "public/产品手册.pdf",
|
||
"collection": "public_kb",
|
||
"choice_count": 5,
|
||
"blank_count": 2,
|
||
"short_answer_count": 2,
|
||
"difficulty": 3,
|
||
"choice_score": 2,
|
||
"blank_score": 3
|
||
}
|
||
```
|
||
|
||
| 参数 | 类型 | 必填 | 默认值 | 说明 |
|
||
|------|------|------|--------|------|
|
||
| `file_path` | string | ✅ | - | 文件路径 |
|
||
| `collection` | string | ✅ | - | 向量库名称 |
|
||
| `choice_count` | int | ❌ | 3 | 选择题数量 |
|
||
| `blank_count` | int | ❌ | 2 | 填空题数量 |
|
||
| `short_answer_count` | int | ❌ | 2 | 简答题数量 |
|
||
| `difficulty` | int | ❌ | 3 | 难度等级 (1-5) |
|
||
| `choice_score` | int | ❌ | 2 | 每道选择题分值 |
|
||
| `blank_score` | int | ❌ | 3 | 每道填空题分值 |
|
||
|
||
**返回结果**:
|
||
```json
|
||
{
|
||
"exam_id": "uuid-xxxx-xxxx",
|
||
"source_file": {
|
||
"path": "public/产品手册.pdf",
|
||
"collection": "public_kb"
|
||
},
|
||
"choice_questions": [
|
||
{
|
||
"id": "q_choice_001",
|
||
"content": "根据保密制度,公司最高机密的处理原则是什么?",
|
||
"options": ["A. 可向客户透露", "B. 严禁外传", "C. 部门内共享", "D. 仅领导知晓"],
|
||
"answer": "B",
|
||
"analysis": "根据保密制度第1条规定...",
|
||
"knowledge_points": ["保密制度", "信息安全"],
|
||
"difficulty": 2,
|
||
"score": 2,
|
||
"source_file": "public/产品手册.pdf",
|
||
"source_snippet": "该题依据的知识片段..."
|
||
}
|
||
],
|
||
"blank_questions": [...],
|
||
"short_answer_questions": [...],
|
||
"total_count": 9,
|
||
"total_score": 22,
|
||
"generated_at": "2026-04-10T14:00:00"
|
||
}
|
||
```
|
||
|
||
### 2.2 试卷状态流程
|
||
|
||
```
|
||
生成试卷 → draft (草稿)
|
||
↓
|
||
提交审核 → pending_review (待审核)
|
||
↓
|
||
管理员审核 → approved (通过) / rejected (驳回)
|
||
↓
|
||
学生答题 → 批阅 → 生成报告
|
||
```
|
||
|
||
**状态说明**:
|
||
| 状态 | 说明 | 可见范围 |
|
||
|------|------|----------|
|
||
| `draft` | 草稿,刚生成尚未提交审核 | 创建者可见 |
|
||
| `pending_review` | 待审核,已提交等待管理员审核 | 管理员可见 |
|
||
| `approved` | 已通过,可用于学生答题 | 所有用户可见 |
|
||
| `rejected` | 已驳回,不可使用 | 创建者可见 |
|
||
|
||
---
|
||
|
||
## 三、题目格式规范
|
||
|
||
### 3.1 选择题
|
||
|
||
```json
|
||
{
|
||
"id": "q_choice_001",
|
||
"content": "根据保密制度,公司最高机密的处理原则是什么?",
|
||
"options": [
|
||
"A. 可向客户透露",
|
||
"B. 严禁外传",
|
||
"C. 部门内共享",
|
||
"D. 仅领导知晓"
|
||
],
|
||
"answer": "B",
|
||
"analysis": "根据保密制度第1条规定,公司最高机密严禁外传,仅限特定人员知晓。",
|
||
"knowledge_points": ["保密制度", "信息安全"],
|
||
"difficulty": 2,
|
||
"score": 2,
|
||
"source_file": "public/产品手册.pdf",
|
||
"source_snippet": "原文相关片段..."
|
||
}
|
||
```
|
||
|
||
**字段说明**:
|
||
|
||
| 字段 | 类型 | 必填 | 说明 |
|
||
|------|------|------|------|
|
||
| `id` | string | ✅ | 题目唯一标识 |
|
||
| `content` | string | ✅ | 题干内容 |
|
||
| `options` | array | ✅ | 选项列表,格式为 `["A. 选项内容", ...]` |
|
||
| `answer` | string | ✅ | 正确答案,单个字母(如 "A", "B") |
|
||
| `analysis` | string | ✅ | 答案解析 |
|
||
| `knowledge_points` | array | ❌ | 知识点标签 |
|
||
| `difficulty` | int | ❌ | 难度等级 1-5,默认 3 |
|
||
| `score` | int | ✅ | 题目分值 |
|
||
| `source_file` | string | ❌ | 来源文件路径 |
|
||
| `source_snippet` | string | ❌ | 来源文本片段 |
|
||
|
||
### 3.2 填空题
|
||
|
||
```json
|
||
{
|
||
"id": "q_blank_001",
|
||
"content": "公司财务报表应在每季度结束后______天内提交。",
|
||
"answer": "15",
|
||
"analysis": "根据财务管理制度第5条规定,季度报表需在季后15天内提交。",
|
||
"knowledge_points": ["财务管理"],
|
||
"difficulty": 3,
|
||
"score": 3
|
||
}
|
||
```
|
||
|
||
**字段说明**:
|
||
|
||
| 字段 | 类型 | 必填 | 说明 |
|
||
|------|------|------|------|
|
||
| `id` | string | ✅ | 题目唯一标识 |
|
||
| `content` | string | ✅ | 题干内容,空缺处用 `______` 表示 |
|
||
| `answer` | string | ✅ | 正确答案 |
|
||
| `analysis` | string | ✅ | 答案解析 |
|
||
| `knowledge_points` | array | ❌ | 知识点标签 |
|
||
| `difficulty` | int | ❌ | 难度等级 1-5 |
|
||
| `score` | int | ✅ | 题目分值 |
|
||
|
||
### 3.3 简答题
|
||
|
||
```json
|
||
{
|
||
"id": "q_short_001",
|
||
"content": "简述公司数据安全的三道防线。",
|
||
"reference_answer": {
|
||
"points": [
|
||
{"point": "技术防线(防火墙、加密、访问控制等)", "score": 3},
|
||
{"point": "制度防线(安全规定、审批流程、应急预案)", "score": 3},
|
||
{"point": "人员防线(安全培训、意识教育、考核机制)", "score": 4}
|
||
],
|
||
"total_score": 10
|
||
},
|
||
"analysis": "评分要点说明...",
|
||
"knowledge_points": ["数据安全"],
|
||
"difficulty": 4,
|
||
"score": 10
|
||
}
|
||
```
|
||
|
||
**字段说明**:
|
||
|
||
| 字段 | 类型 | 必填 | 说明 |
|
||
|------|------|------|------|
|
||
| `id` | string | ✅ | 题目唯一标识 |
|
||
| `content` | string | ✅ | 题干内容 |
|
||
| `reference_answer` | object | ✅ | 参考答案,包含评分要点 |
|
||
| `reference_answer.points` | array | ✅ | 得分点列表 |
|
||
| `reference_answer.points[].point` | string | ✅ | 得分点描述 |
|
||
| `reference_answer.points[].score` | int | ✅ | 该得分点分值 |
|
||
| `analysis` | string | ❌ | 整体解析 |
|
||
| `knowledge_points` | array | ❌ | 知识点标签 |
|
||
| `difficulty` | int | ❌ | 难度等级 1-5 |
|
||
| `score` | int | ✅ | 题目总分值 |
|
||
|
||
---
|
||
|
||
## 四、批卷系统设计
|
||
|
||
### 4.1 批卷输入格式
|
||
|
||
**接口路径**:`POST /exam/grade-from-mysql`
|
||
|
||
**当前格式(完整字段)**:
|
||
```json
|
||
{
|
||
"exam_id": "uuid-xxxx-xxxx",
|
||
"student_id": "STU_2023001",
|
||
"student_name": "张三",
|
||
"answers": [
|
||
{
|
||
"question_id": "q_choice_001",
|
||
"question_type": "choice",
|
||
"question_content": "根据保密制度,公司最高机密的处理原则是什么?",
|
||
"options": ["A. 可向客户透露", "B. 严禁外传", "C. 部门内共享", "D. 仅领导知晓"],
|
||
"correct_answer": "B",
|
||
"max_score": 2,
|
||
"student_answer": "B"
|
||
},
|
||
{
|
||
"question_id": "q_blank_001",
|
||
"question_type": "blank",
|
||
"question_content": "公司财务报表应在每季度结束后______天内提交。",
|
||
"correct_answer": "15",
|
||
"max_score": 3,
|
||
"student_answer": "10"
|
||
},
|
||
{
|
||
"question_id": "q_short_001",
|
||
"question_type": "short_answer",
|
||
"question_content": "简述公司数据安全的三道防线。",
|
||
"correct_answer": "{\"points\":[{\"point\":\"技术防线\",\"score\":3},{\"point\":\"制度防线\",\"score\":3},{\"point\":\"人员防线\",\"score\":4}]}",
|
||
"max_score": 10,
|
||
"student_answer": "第一道是技术防护,包括防火墙和加密;第二道是制度管理;第三道是员工培训。"
|
||
}
|
||
]
|
||
}
|
||
```
|
||
|
||
**优化后格式(最小字段)**:
|
||
```json
|
||
{
|
||
"exam_id": "uuid",
|
||
"student_id": "STU_001",
|
||
"student_name": "张三",
|
||
"answers": [
|
||
{
|
||
"question_id": "q_choice_001",
|
||
"question_type": "choice",
|
||
"student_answer": "B"
|
||
},
|
||
{
|
||
"question_id": "q_blank_001",
|
||
"question_type": "blank",
|
||
"student_answer": "15"
|
||
},
|
||
{
|
||
"question_id": "q_short_001",
|
||
"question_type": "short_answer",
|
||
"student_answer": "第一道是技术防护..."
|
||
}
|
||
]
|
||
}
|
||
```
|
||
|
||
### 4.2 批卷输出格式
|
||
|
||
```json
|
||
{
|
||
"report_id": "report-uuid-xxxx",
|
||
"exam_id": "uuid-xxxx-xxxx",
|
||
"student_id": "STU_2023001",
|
||
"student_name": "张三",
|
||
"total_score": 12,
|
||
"max_score": 15,
|
||
"score_rate": 80.0,
|
||
"graded_at": "2026-04-12T14:30:00",
|
||
"results": [
|
||
{
|
||
"question_id": "q_choice_001",
|
||
"question_type": "choice",
|
||
"correct": true,
|
||
"score": 2,
|
||
"max_score": 2,
|
||
"student_answer": "B",
|
||
"correct_answer": "B",
|
||
"feedback": "回答正确!"
|
||
},
|
||
{
|
||
"question_id": "q_blank_001",
|
||
"question_type": "blank",
|
||
"correct": false,
|
||
"score": 0,
|
||
"max_score": 3,
|
||
"student_answer": "10",
|
||
"correct_answer": "15",
|
||
"feedback": "正确答案是15天,请复习财务管理制度。"
|
||
},
|
||
{
|
||
"question_id": "q_short_001",
|
||
"question_type": "short_answer",
|
||
"score": 8,
|
||
"max_score": 10,
|
||
"student_answer": "第一道是技术防护...",
|
||
"score_details": [
|
||
{"point": "技术防线", "earned": 3, "max": 3},
|
||
{"point": "制度防线", "earned": 2, "max": 3},
|
||
{"point": "人员防线", "earned": 3, "max": 4}
|
||
],
|
||
"feedback": "整体回答较好,制度防线描述不够具体。",
|
||
"highlights": ["技术防线表述准确"],
|
||
"shortcomings": ["制度防线未具体说明"],
|
||
"suggestions": ["建议补充具体的制度名称"]
|
||
}
|
||
],
|
||
"summary": {
|
||
"strengths": ["选择题掌握较好", "简答题要点覆盖全面"],
|
||
"weaknesses": ["填空题记忆不准确"],
|
||
"recommendations": ["重点复习财务管理制度第3章"]
|
||
}
|
||
}
|
||
```
|
||
|
||
### 4.3 批改流程
|
||
|
||
```
|
||
┌─────────────────────────────────────────────────────────────────────┐
|
||
│ 批量批改流程 │
|
||
├─────────────────────────────────────────────────────────────────────┤
|
||
│ │
|
||
│ 1. 前端传入 answers (最小字段) │
|
||
│ └─ 只有 question_id + question_type + student_answer │
|
||
│ │
|
||
│ 2. 后端查询题目详情 │
|
||
│ └─ 从数据库/缓存获取 correct_answer, max_score, content │
|
||
│ │
|
||
│ 3. 按题型分组 │
|
||
│ ├─ choice 组 → 批量调用 Dify 代码执行节点 │
|
||
│ └─ blank/short_answer 组 → 批量调用 Dify LLM 节点 │
|
||
│ │
|
||
│ 4. 合并结果返回 │
|
||
│ └─ 统一格式返回所有批改结果 │
|
||
│ │
|
||
└─────────────────────────────────────────────────────────────────────┘
|
||
```
|
||
|
||
---
|
||
|
||
## 五、数据库设计
|
||
|
||
### 5.1 题目表 (questions)
|
||
|
||
```sql
|
||
CREATE TABLE questions (
|
||
id VARCHAR(64) PRIMARY KEY, -- 题目ID(UUID)
|
||
question_type ENUM('choice', 'blank', 'short_answer') NOT NULL,
|
||
content TEXT NOT NULL, -- 题干内容
|
||
options JSON, -- 选择题选项(JSON数组)
|
||
correct_answer TEXT NOT NULL, -- 正确答案
|
||
analysis TEXT, -- 解析
|
||
knowledge_points JSON, -- 知识点(JSON数组)
|
||
difficulty TINYINT DEFAULT 3, -- 难度(1-5)
|
||
score INT NOT NULL, -- 分值
|
||
|
||
-- 溯源字段(核心)
|
||
source_file VARCHAR(255) NOT NULL, -- 来源文件路径
|
||
source_collection VARCHAR(64) NOT NULL, -- 来源向量库
|
||
source_snippet TEXT, -- 来源知识片段
|
||
source_hash VARCHAR(64), -- 文件哈希(用于检测文件变更)
|
||
|
||
-- 审核状态
|
||
status ENUM('pending', 'approved', 'rejected') DEFAULT 'pending',
|
||
reviewed_by VARCHAR(64),
|
||
reviewed_at DATETIME,
|
||
|
||
-- 元数据
|
||
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
|
||
created_by VARCHAR(64),
|
||
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||
|
||
INDEX idx_source_file (source_file),
|
||
INDEX idx_source_collection (source_collection),
|
||
INDEX idx_question_type (question_type),
|
||
INDEX idx_status (status)
|
||
);
|
||
```
|
||
|
||
### 5.2 试卷表 (exams)
|
||
|
||
```sql
|
||
CREATE TABLE exams (
|
||
id VARCHAR(64) PRIMARY KEY, -- 试卷ID
|
||
name VARCHAR(255) NOT NULL, -- 试卷名称
|
||
description TEXT, -- 描述
|
||
total_score INT NOT NULL, -- 总分
|
||
total_count INT NOT NULL, -- 题目总数
|
||
duration INT DEFAULT 60, -- 考试时长(分钟)
|
||
|
||
-- 状态
|
||
status ENUM('draft', 'pending', 'published', 'archived') DEFAULT 'draft',
|
||
published_at DATETIME,
|
||
|
||
-- 元数据
|
||
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
|
||
created_by VARCHAR(64),
|
||
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||
|
||
INDEX idx_status (status)
|
||
);
|
||
```
|
||
|
||
### 5.3 试卷题目关联表 (exam_questions)
|
||
|
||
```sql
|
||
CREATE TABLE exam_questions (
|
||
exam_id VARCHAR(64) NOT NULL,
|
||
question_id VARCHAR(64) NOT NULL,
|
||
question_order INT NOT NULL, -- 题目顺序
|
||
|
||
PRIMARY KEY (exam_id, question_id),
|
||
FOREIGN KEY (exam_id) REFERENCES exams(id) ON DELETE CASCADE,
|
||
FOREIGN KEY (question_id) REFERENCES questions(id) ON DELETE CASCADE,
|
||
|
||
INDEX idx_exam_id (exam_id),
|
||
INDEX idx_question_id (question_id)
|
||
);
|
||
```
|
||
|
||
### 5.4 学生答卷表 (student_answers)
|
||
|
||
```sql
|
||
CREATE TABLE student_answers (
|
||
id VARCHAR(64) PRIMARY KEY,
|
||
exam_id VARCHAR(64) NOT NULL,
|
||
student_id VARCHAR(64) NOT NULL,
|
||
student_name VARCHAR(100),
|
||
|
||
question_id VARCHAR(64) NOT NULL,
|
||
question_type ENUM('choice', 'blank', 'short_answer') NOT NULL,
|
||
student_answer TEXT NOT NULL, -- 学生答案
|
||
|
||
-- 批阅结果
|
||
score INT DEFAULT 0,
|
||
max_score INT NOT NULL,
|
||
feedback TEXT,
|
||
score_details JSON, -- 评分详情(JSON)
|
||
|
||
-- 元数据
|
||
submitted_at DATETIME DEFAULT CURRENT_TIMESTAMP,
|
||
graded_at DATETIME,
|
||
|
||
FOREIGN KEY (exam_id) REFERENCES exams(id) ON DELETE CASCADE,
|
||
FOREIGN KEY (question_id) REFERENCES questions(id) ON DELETE CASCADE,
|
||
|
||
INDEX idx_exam_student (exam_id, student_id),
|
||
INDEX idx_student_id (student_id)
|
||
);
|
||
```
|
||
|
||
### 5.5 批阅报告表 (grade_reports)
|
||
|
||
```sql
|
||
CREATE TABLE grade_reports (
|
||
id VARCHAR(64) PRIMARY KEY,
|
||
exam_id VARCHAR(64) NOT NULL,
|
||
student_id VARCHAR(64) NOT NULL,
|
||
student_name VARCHAR(100),
|
||
|
||
total_score INT NOT NULL,
|
||
max_score INT NOT NULL,
|
||
score_rate DECIMAL(5,2),
|
||
|
||
-- 整卷分析(可选)
|
||
analysis JSON, -- AI生成的整卷分析
|
||
|
||
graded_at DATETIME DEFAULT CURRENT_TIMESTAMP,
|
||
|
||
FOREIGN KEY (exam_id) REFERENCES exams(id) ON DELETE CASCADE,
|
||
|
||
INDEX idx_exam_id (exam_id),
|
||
INDEX idx_student_id (student_id)
|
||
);
|
||
```
|
||
|
||
---
|
||
|
||
## 六、文件修改联动
|
||
|
||
### 6.1 触发条件
|
||
|
||
当文件被修改或删除时,通过 `source_file` 字段查找受影响的题目。
|
||
|
||
### 6.2 联动逻辑
|
||
|
||
```sql
|
||
-- 查找受影响的题目
|
||
SELECT id, source_file, source_hash
|
||
FROM questions
|
||
WHERE source_file = 'public/产品手册.pdf';
|
||
|
||
-- 如果文件哈希变更,标记题目需要重新审核
|
||
UPDATE questions
|
||
SET status = 'pending',
|
||
source_hash = 'new_hash_value'
|
||
WHERE source_file = 'public/产品手册.pdf';
|
||
```
|
||
|
||
### 6.3 联动接口
|
||
|
||
**接口路径**:`POST /exam/check-file-changes`
|
||
|
||
**请求参数**:
|
||
```json
|
||
{
|
||
"file_path": "public/产品手册.pdf",
|
||
"new_hash": "新的文件哈希"
|
||
}
|
||
```
|
||
|
||
**返回结果**:
|
||
```json
|
||
{
|
||
"success": true,
|
||
"file_path": "public/产品手册.pdf",
|
||
"affected_questions": ["q_uuid_001", "q_uuid_002", ...],
|
||
"count": 15,
|
||
"recommendation": "建议重新生成该文件的题目"
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## 七、API 接口汇总
|
||
|
||
### 7.1 出题接口
|
||
|
||
| 接口 | 方法 | 说明 |
|
||
|------|------|------|
|
||
| `/exam/generate` | POST | 按主题生成试卷 |
|
||
| `/exam/generate-by-file` | POST | 按文件生成题目 |
|
||
| `/exam/list` | GET | 获取试卷列表 |
|
||
| `/exam/<exam_id>` | GET | 获取试卷详情 |
|
||
| `/exam/<exam_id>` | PUT | 更新试卷 |
|
||
| `/exam/<exam_id>` | DELETE | 删除试卷 |
|
||
| `/exam/<exam_id>/submit` | POST | 提交审核 |
|
||
| `/exam/<exam_id>/review` | POST | 审核试卷(仅管理员) |
|
||
| `/exam/by-file` | GET | 查询文件关联的题目 |
|
||
|
||
### 7.2 批卷接口
|
||
|
||
| 接口 | 方法 | 说明 |
|
||
|------|------|------|
|
||
| `/exam/grade-from-mysql` | POST | 基于传入题目批卷 |
|
||
| `/exam/<exam_id>/grade` | POST | 批阅试卷 |
|
||
| `/exam/report/<report_id>` | GET | 获取批阅报告 |
|
||
| `/exam/report/list` | GET | 批阅报告列表 |
|
||
|
||
### 7.3 题库接口
|
||
|
||
| 接口 | 方法 | 说明 |
|
||
|------|------|------|
|
||
| `/exam/questions/search` | GET | 搜索题目 |
|
||
|
||
### 7.4 联动接口
|
||
|
||
| 接口 | 方法 | 说明 |
|
||
|------|------|------|
|
||
| `/exam/check-file-changes` | POST | 检查文件变更影响的题目 |
|
||
|
||
---
|
||
|
||
## 八、错误处理
|
||
|
||
### 8.1 错误响应格式
|
||
|
||
```json
|
||
{
|
||
"error": "错误类型",
|
||
"message": "详细错误信息",
|
||
"details": {}
|
||
}
|
||
```
|
||
|
||
### 8.2 常见错误码
|
||
|
||
| HTTP状态码 | 错误类型 | 说明 |
|
||
|-----------|---------|------|
|
||
| 400 | bad_request | 请求参数格式错误 |
|
||
| 401 | unauthorized | 未认证 |
|
||
| 403 | forbidden | 权限不足 |
|
||
| 404 | not_found | 资源不存在 |
|
||
| 500 | internal_error | 服务器内部错误 |
|
||
|
||
---
|
||
|
||
## 九、注意事项
|
||
|
||
1. **题目ID生成**:使用UUID,确保全局唯一
|
||
2. **文件哈希**:用于检测文件变更,建议使用MD5或SHA256
|
||
3. **批量批卷性能**:简答题批卷耗时,建议使用异步处理或并发
|
||
4. **错误处理**:批卷失败时返回默认结果,不影响整体流程
|
||
5. **认证方式**:出题系统使用 JWT Bearer Token 认证
|
||
|
||
---
|
||
|
||
## 十、变更记录
|
||
|
||
| 日期 | 版本 | 变更内容 |
|
||
|------|------|---------|
|
||
| 2026-06-04 | 2.1 | 更新模块结构:移除已删除的 analysis.py、question_hook.py,新增 generator.py、grader.py |
|
||
| 2026-04-13 | 2.0 | 合并出题批卷功能改造计划、批卷工作流优化计划、批卷接口规范 |
|
||
| 2026-04-12 | 1.2 | 新增最小字段输入格式,优化批量批改流程 |
|
||
| 2026-04-10 | 1.0 | 初始版本:按文件出题功能设计 |
|