init: RAG 知识库服务初始提交
- 后端 API(Flask + Gunicorn) - RAG 引擎(混合检索 + 云端 Reranker + 引用溯源) - 文档解析(MinerU + 多格式支持) - Docker 生产部署配置 - 排除前端项目、敏感配置、模型文件
This commit is contained in:
634
docs/出题批卷系统设计.md
Normal file
634
docs/出题批卷系统设计.md
Normal file
@@ -0,0 +1,634 @@
|
||||
# 出题批卷系统设计
|
||||
|
||||
> **文档类型**: 系统设计文档
|
||||
> **创建日期**: 2026-04-10
|
||||
> **最后更新**: 2026-04-13
|
||||
> **状态**: 已实施
|
||||
|
||||
---
|
||||
|
||||
## 一、系统概述
|
||||
|
||||
### 1.1 背景
|
||||
|
||||
出题批卷系统是 RAG 知识库系统的扩展模块,支持:
|
||||
- **按文件出题**:根据指定文档自动生成题目
|
||||
- **智能批卷**:支持选择题、填空题、简答题的自动批改
|
||||
- **溯源追踪**:每道题可追溯到来源文件和知识片段
|
||||
|
||||
### 1.2 模块结构
|
||||
|
||||
```
|
||||
exam_pkg/ # 考试系统
|
||||
├── manager.py # 出题与批卷核心逻辑
|
||||
├── api.py # Flask Blueprint (exam_bp)
|
||||
├── analysis.py # 考试分析
|
||||
├── local_db.py # 本地题库 (SQLite)
|
||||
└── question_hook.py # 题目维护钩子
|
||||
```
|
||||
|
||||
**认证模块**: `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-04-13 | 2.0 | 合并出题批卷功能改造计划、批卷工作流优化计划、批卷接口规范 |
|
||||
| 2026-04-12 | 1.2 | 新增最小字段输入格式,优化批量批改流程 |
|
||||
| 2026-04-10 | 1.0 | 初始版本:按文件出题功能设计 |
|
||||
Reference in New Issue
Block a user