# 批阅接口测试文档

## 一、接口说明

| 接口       | 地址                                                            | 功能                    |
| -------- | ------------------------------------------------------------- | --------------------- |
| 后端通用接口   | POST <http://localhost:8080/api/exam/grade>                   | 批阅答案（日常练习/模拟考/正式考试通用） |
| 后端正式考试接口 | POST <http://localhost:8080/api/exam/record/{recordId}/grade> | 正式考试专用批阅接口            |
| AI端接口    | POST <http://localhost:5001/exam/grade>                       | AI端批阅答案               |

**answerType 参数说明**：后端接口支持 `answerType` 字段区分答题类型，前端传入什么值后端就使用什么值。

| answerType 值  | 说明   | 重复答题        |
| ------------- | ---- | ----------- |
| `practice`    | 日常练习 | 允许（更新记录）    |
| `mock_exam`   | 模拟考  | 允许（更新记录）    |
| `formal_exam` | 正式考试 | 不允许（唯一索引保护） |

***

## 二、接口路径规范

**注意**：所有接口路径都在 `/api` 前缀下，实际完整路径为：

- `http://localhost:8080/api/exam/grade`
- `http://localhost:8080/api/exam/record/{recordId}/grade`

***

## 三、获取 Token

在测试前，需要先获取有效的访问令牌：

```bash
curl -X POST http://localhost:8080/api/auth/login -H "Content-Type: application/json" -d '{"username":"admin","password":"123456"}'
```

**新 Token**（有效期2小时）：

```
eyJhbGciOiJIUzUxMiJ9.eyJzdWIiOiIxIiwidXNlcm5hbWUiOiJhZG1pbiIsImlhdCI6MTc4MDAzMTgyNSwiZXhwIjoxNzgwMDM5MDI1fQ.an_bqtorziJ5Yb-otGPIIg400fCM1-VLLfX7mgQYHspOgSsTczcSY70evxsMUnfGmOr_euXgXwf2VkMQoXpG5w
```

***

## 四、后端接口测试

### 4.1 单选题测试（日常练习）

```bash
curl -X POST http://localhost:8080/api/exam/grade -H "Content-Type: application/json" -H "Authorization: Bearer eyJhbGciOiJIUzUxMiJ9.eyJzdWIiOiIxIiwidXNlcm5hbWUiOiJhZG1pbiIsImlhdCI6MTc4MDAzMTgyNSwiZXhwIjoxNzgwMDM5MDI1fQ.an_bqtorziJ5Yb-otGPIIg400fCM1-VLLfX7mgQYHspOgSsTczcSY70evxsMUnfGmOr_euXgXwf2VkMQoXpG5w" -d '{"answerType":"practice","requestId":"test_001","answers":[{"questionId":"9d05c475-b4fe-4679-a450-ee88a94b3b34","questionType":"single_choice","questionContent":{"stem":"根据文档内容，务求实效原则的核心要求聚焦于哪一根本目标？","data":{"options":[{"key":"A","content":"扩大终端数量规模"},{"key":"B","content":"提升终端信息化系统覆盖率"},{"key":"C","content":"着眼于终端功能发挥和服务水平提升"},{"key":"D","content":"统一各类终端建设外观标准"}]},"answer":"C"},"studentAnswer":"C","maxScore":2.0}]}'
```

### 4.2 多选题测试（日常练习）

```bash
curl -X POST http://localhost:8080/api/exam/grade -H "Content-Type: application/json" -H "Authorization: Bearer eyJhbGciOiJIUzUxMiJ9.eyJzdWIiOiIxIiwidXNlcm5hbWUiOiJhZG1pbiIsImlhdCI6MTc4MDAzMTgyNSwiZXhwIjoxNzgwMDM5MDI1fQ.an_bqtorziJ5Yb-otGPIIg400fCM1-VLLfX7mgQYHspOgSsTczcSY70evxsMUnfGmOr_euXgXwf2VkMQoXpG5w" -d '{"answerType":"practice","requestId":"test_002","answers":[{"questionId":"ee652f7e-da5e-4129-8766-c113277332f4","questionType":"multiple_choice","questionContent":{"stem":"依据务求实效原则，以下哪些做法符合其核心要求？（可多选）","data":{"options":[{"key":"A","content":"科学设定终端投入标准"},{"key":"B","content":"严格执行终端投入标准"},{"key":"C","content":"优先采购高配置但非必需的智能设备"},{"key":"D","content":"坚决杜绝不必要的支出和浪费"}]},"answer":["A","B","D"]},"studentAnswer":["A","B"],"maxScore":4.0}]}'
```

### 4.3 判断题测试（日常练习）

```bash
curl -X POST http://localhost:8080/api/exam/grade -H "Content-Type: application/json" -H "Authorization: Bearer eyJhbGciOiJIUzUxMiJ9.eyJzdWIiOiIxIiwidXNlcm5hbWUiOiJhZG1pbiIsImlhdCI6MTc4MDAzMTgyNSwiZXhwIjoxNzgwMDM5MDI1fQ.an_bqtorziJ5Yb-otGPIIg400fCM1-VLLfX7mgQYHspOgSsTczcSY70evxsMUnfGmOr_euXgXwf2VkMQoXpG5w" -d '{"answerType":"practice","requestId":"test_003","answers":[{"questionId":"76913ad8-5325-4f30-a03a-6e19e434b59e","questionType":"true_false","questionContent":{"stem":"务求实效原则允许在终端建设中适度预留冗余预算，以应对未来可能的功能升级需求。","data":{},"answer":"false"},"studentAnswer":"false","maxScore":1.0}]}'
```

### 4.4 填空题测试（日常练习）

```bash
curl -X POST http://localhost:8080/api/exam/grade -H "Content-Type: application/json" -H "Authorization: Bearer eyJhbGciOiJIUzUxMiJ9.eyJzdWIiOiIxIiwidXNlcm5hbWUiOiJhZG1pbiIsImlhdCI6MTc4MDAzMTgyNSwiZXhwIjoxNzgwMDM5MDI1fQ.an_bqtorziJ5Yb-otGPIIg400fCM1-VLLfX7mgQYHspOgSsTczcSY70evxsMUnfGmOr_euXgXwf2VkMQoXpG5w" -d '{"answerType":"practice","requestId":"test_004","answers":[{"questionId":"7ae3daef-0345-4852-bd37-336e74498cc4","questionType":"fill_blank","questionContent":{"stem":"务求实效原则强调以___为出发点，通过科学设定和严格执行终端投入标准，实现___与___的双重提升。","data":{"blank_count":3},"answer":["终端功能发挥和服务水平提升","终端功能发挥","服务水平提升"]},"studentAnswer":["终端功能发挥和服务水平提升","终端功能发挥","服务水平"],"maxScore":2.0}]}'
```

### 4.5 主观题测试（日常练习）

```bash
curl -X POST http://localhost:8080/api/exam/grade -H "Content-Type: application/json" -H "Authorization: Bearer eyJhbGciOiJIUzUxMiJ9.eyJzdWIiOiIxIiwidXNlcm5hbWUiOiJhZG1pbiIsImlhdCI6MTc4MDAzMTgyNSwiZXhwIjoxNzgwMDM5MDI1fQ.an_bqtorziJ5Yb-otGPIIg400fCM1-VLLfX7mgQYHspOgSsTczcSY70evxsMUnfGmOr_euXgXwf2VkMQoXpG5w" -d '{"answerType":"practice","requestId":"test_005","answers":[{"questionId":"ea6ba220-43ff-44d8-8b24-cd350eeb8b53","questionType":"subjective","questionContent":{"stem":"请结合文档内容，简述\"务求实效原则\"在终端建设管理中的具体体现，并说明其与形式主义倾向的根本区别。","data":{"answer_length_hint":"150–200字"},"answer":"务求实效原则具体体现为：以终端功能发挥和服务水平提升为唯一导向，科学设定并严格执行投入标准，杜绝一切不必要的支出和浪费。"},"studentAnswer":"务求实效原则强调终端功能发挥和服务水平提升，杜绝浪费。形式主义只注重表面，不注重实际效果。","maxScore":6.0}]}'
```

### 4.6 批量测试（所有题型，包含错题，日常练习）

```bash
curl -X POST http://localhost:8080/api/exam/grade -H "Content-Type: application/json" -H "Authorization: Bearer eyJhbGciOiJIUzUxMiJ9.eyJzdWIiOiIxIiwidXNlcm5hbWUiOiJhZG1pbiIsImlhdCI6MTc4MDMwNDMwOCwiZXhwIjoxNzgwMzExNTA4fQ.5NLIrXfK-7MVrrmU7TZ7L_z2TXxc4OzaYIOmoFKBLOAkX9pjCBtxz915QQ1SGLekHTj5DBcgF-NhIZDSw-CPtQ" -d '{"answerType":"practice","requestId":"batch_test_001","answers":[{"questionId":"9d05c475-b4fe-4679-a450-ee88a94b3b34","questionType":"single_choice","questionContent":{"stem":"根据文档内容，务求实效原则的核心要求聚焦于哪一根本目标？","data":{"options":[{"key":"A","content":"扩大终端数量规模"},{"key":"B","content":"提升终端信息化系统覆盖率"},{"key":"C","content":"着眼于终端功能发挥和服务水平提升"},{"key":"D","content":"统一各类终端建设外观标准"}]},"answer":"C"},"studentAnswer":"","maxScore":2.0},{"questionId":"ee652f7e-da5e-4129-8766-c113277332f4","questionType":"multiple_choice","questionContent":{"stem":"依据务求实效原则，以下哪些做法符合其核心要求？（可多选）","data":{"options":[{"key":"A","content":"科学设定终端投入标准"},{"key":"B","content":"严格执行终端投入标准"},{"key":"C","content":"优先采购高配置但非必需的智能设备"},{"key":"D","content":"坚决杜绝不必要的支出和浪费"}]},"answer":["A","B","D"]},"studentAnswer":[],"maxScore":4.0},{"questionId":"76913ad8-5325-4f30-a03a-6e19e434b59e","questionType":"true_false","questionContent":{"stem":"务求实效原则允许在终端建设中适度预留冗余预算，以应对未来可能的功能升级需求。","data":{},"answer":"false"},"studentAnswer":"false","maxScore":1.0}]}'
```

**错题说明**：

- 单选题：学生选A（正确答案是C）
- 多选题：学生选A、B、C（正确答案是A、B、D，C选项违背务求实效原则）
- 判断题：学生选true（正确答案是false）

### 4.7 模拟考测试（answerType = mock\_exam）

```bash
curl -X POST http://localhost:8080/api/exam/grade -H "Content-Type: application/json" -H "Authorization: Bearer eyJhbGciOiJIUzUxMiJ9.eyJzdWIiOiIxIiwidXNlcm5hbWUiOiJhZG1pbiIsImlhdCI6MTc4MDAzMTgyNSwiZXhwIjoxNzgwMDM5MDI1fQ.an_bqtorziJ5Yb-otGPIIg400fCM1-VLLfX7mgQYHspOgSsTczcSY70evxsMUnfGmOr_euXgXwf2VkMQoXpG5w" -d '{"answerType":"mock_exam","requestId":"mock_test_001","answers":[{"questionId":"9d05c475-b4fe-4679-a450-ee88a94b3b34","questionType":"single_choice","questionContent":{"stem":"根据文档内容，务求实效原则的核心要求聚焦于哪一根本目标？","data":{"options":[{"key":"A","content":"扩大终端数量规模"},{"key":"B","content":"提升终端信息化系统覆盖率"},{"key":"C","content":"着眼于终端功能发挥和服务水平提升"},{"key":"D","content":"统一各类终端建设外观标准"}]},"answer":"C"},"studentAnswer":"C","maxScore":2.0},{"questionId":"ee652f7e-da5e-4129-8766-c113277332f4","questionType":"multiple_choice","questionContent":{"stem":"依据务求实效原则，以下哪些做法符合其核心要求？（可多选）","data":{"options":[{"key":"A","content":"科学设定终端投入标准"},{"key":"B","content":"严格执行终端投入标准"},{"key":"C","content":"优先采购高配置但非必需的智能设备"},{"key":"D","content":"坚决杜绝不必要的支出和浪费"}]},"answer":["A","B","D"]},"studentAnswer":["A","B","D"],"maxScore":4.0}]}'
```

### 4.8 正式考测试（通过 recordId 接口，推荐方式）

> **注意**：正式考试推荐使用 `/api/exam/record/{recordId}/grade` 接口提交。这种方式会关联已存在的考试记录。

```bash
curl -X POST http://localhost:8080/api/exam/record/59759c40-ee4e-4ff5-ab03-4819a0499beb/grade -H "Content-Type: application/json" -H "Authorization: Bearer eyJhbGciOiJIUzUxMiJ9.eyJzdWIiOiIxIiwidXNlcm5hbWUiOiJhZG1pbiIsImlhdCI6MTc4MDAzMTgyNSwiZXhwIjoxNzgwMDM5MDI1fQ.an_bqtorziJ5Yb-otGPIIg400fCM1-VLLfX7mgQYHspOgSsTczcSY70evxsMUnfGmOr_euXgXwf2VkMQoXpG5w" -d '{"answers":[{"questionId":"9d05c475-b4fe-4679-a450-ee88a94b3b34","questionType":"single_choice","answer":"C"},{"questionId":"ee652f7e-da5e-4129-8766-c113277332f4","questionType":"multiple_choice","answer":["A","B","D"]}]}'
```

### 4.9 正式考测试（通过通用接口 + recordId 参数）

```bash
curl -X POST http://localhost:8080/api/exam/grade -H "Content-Type: application/json" -H "Authorization: Bearer eyJhbGciOiJIUzUxMiJ9.eyJzdWIiOiIxIiwidXNlcm5hbWUiOiJhZG1pbiIsImlhdCI6MTc4MDAzMTgyNSwiZXhwIjoxNzgwMDM5MDI1fQ.an_bqtorziJ5Yb-otGPIIg400fCM1-VLLfX7mgQYHspOgSsTczcSY70evxsMUnfGmOr_euXgXwf2VkMQoXpG5w" -d '{"answerType":"formal_exam","recordId":"59759c40-ee4e-4ff5-ab03-4819a0499beb","requestId":"formal_test_001","paperId":"0ef70443-67d3-48cd-9309-f5088c092fe1","answers":[{"questionId":"9d05c475-b4fe-4679-a450-ee88a94b3b34","questionType":"single_choice","questionContent":{"stem":"根据文档内容，务求实效原则的核心要求聚焦于哪一根本目标？","data":{"options":[{"key":"A","content":"扩大终端数量规模"},{"key":"B","content":"提升终端信息化系统覆盖率"},{"key":"C","content":"着眼于终端功能发挥和服务水平提升"},{"key":"D","content":"统一各类终端建设外观标准"}]},"answer":"C"},"studentAnswer":"C","maxScore":2.0}]}'
```

### 4.10 空白试卷测试 - 日常练习（answers 为空数组）

```bash
curl -X POST http://localhost:8080/api/exam/grade -H "Content-Type: application/json" -H "Authorization: Bearer eyJhbGciOiJIUzUxMiJ9.eyJzdWIiOiIxIiwidXNlcm5hbWUiOiJhZG1pbiIsImlhdCI6MTc4MDAzMTgyNSwiZXhwIjoxNzgwMDM5MDI1fQ.an_bqtorziJ5Yb-otGPIIg400fCM1-VLLfX7mgQYHspOgSsTczcSY70evxsMUnfGmOr_euXgXwf2VkMQoXpG5w" -d '{"answerType":"practice","requestId":"blank_test_001","answers":[]}'
```

### 4.11 空白试卷测试 - 模拟考（answers 为空数组）

```bash
curl -X POST http://localhost:8080/api/exam/grade -H "Content-Type: application/json" -H "Authorization: Bearer eyJhbGciOiJIUzUxMiJ9.eyJzdWIiOiIxIiwidXNlcm5hbWUiOiJhZG1pbiIsImlhdCI6MTc4MDAzMTgyNSwiZXhwIjoxNzgwMDM5MDI1fQ.an_bqtorziJ5Yb-otGPIIg400fCM1-VLLfX7mgQYHspOgSsTczcSY70evxsMUnfGmOr_euXgXwf2VkMQoXpG5w" -d '{"answerType":"mock_exam","requestId":"blank_test_002","answers":[]}'
```

### 4.12 空白试卷测试 - 正式考试（通过 recordId 接口）

```bash
curl -X POST http://localhost:8080/api/exam/record/4e34c752-1e0e-4207-8fdb-b0027b30521e/grade -H "Content-Type: application/json" -H "Authorization: Bearer eyJhbGciOiJIUzUxMiJ9.eyJzdWIiOiIxIiwidXNlcm5hbWUiOiJhZG1pbiIsImlhdCI6MTc4MDAzMTgyNSwiZXhwIjoxNzgwMDM5MDI1fQ.an_bqtorziJ5Yb-otGPIIg400fCM1-VLLfX7mgQYHspOgSsTczcSY70evxsMUnfGmOr_euXgXwf2VkMQoXpG5w" -d '{"answers":[]}'
```

### 4.13 空白试卷测试 - 正式考试（通过通用接口 + recordId）

```bash
curl -X POST http://localhost:8080/api/exam/grade -H "Content-Type: application/json" -H "Authorization: Bearer eyJhbGciOiJIUzUxMiJ9.eyJzdWIiOiIxIiwidXNlcm5hbWUiOiJhZG1pbiIsImlhdCI6MTc4MDAzMTgyNSwiZXhwIjoxNzgwMDM5MDI1fQ.an_bqtorziJ5Yb-otGPIIg400fCM1-VLLfX7mgQYHspOgSsTczcSY70evxsMUnfGmOr_euXgXwf2VkMQoXpG5w" -d '{"answerType":"formal_exam","recordId":"4e34c752-1e0e-4207-8fdb-b0027b30521e","requestId":"blank_test_003","answers":[]}'
```

### 4.14 正式考试 - 只提交一道题（通过 recordId 接口）

```bash
curl -X POST http://localhost:8080/api/exam/record/2fa88db4-bc90-4096-9970-3286639c5b5b/grade -H "Content-Type: application/json" -H "Authorization: Bearer eyJhbGciOiJIUzUxMiJ9.eyJzdWIiOiIxIiwidXNlcm5hbWUiOiJhZG1pbiIsImlhdCI6MTc4MDMxOTgzMiwiZXhwIjoxNzgwMzI3MDMyfQ.azBEWs7-LiicNDA_O0qdm-TPmBtKLBUeCplRPnkGl7NFUhn-JMP5-G9gboP7eHxsaIvowoY6B2TVlB4z8bDIuQ" -d '{"answers":[{"questionId":"5af6fdce-dbf2-4a57-9ef4-bef176be6fb8","questionType":"single_choice","answer":"C"}]}'
```

### 4.15 正式考试 - 一道题没选（通过 recordId 接口）

```bash
curl -X POST http://localhost:8080/api/exam/record/389806c8-3b42-4b5a-adb8-23d166bb1053/grade -H "Content-Type: application/json" -H "Authorization: Bearer eyJhbGciOiJIUzUxMiJ9.eyJzdWIiOiIxIiwidXNlcm5hbWUiOiJhZG1pbiIsImlhdCI6MTc4MDMxOTgzMiwiZXhwIjoxNzgwMzI3MDMyfQ.azBEWs7-LiicNDA_O0qdm-TPmBtKLBUeCplRPnkGl7NFUhn-JMP5-G9gboP7eHxsaIvowoY6B2TVlB4z8bDIuQ" -d '{"answers":[{"questionId":"5af6fdce-dbf2-4a57-9ef4-bef176be6fb8","questionType":"single_choice","answer":""},{"questionId":"5e069067-a10d-4230-9564-e7503d72d738","questionType":"multiple_choice","answer":["A","B"]},{"questionId":"e6bb2566-90a8-4651-b553-083a1d695b3c","questionType":"true_false","answer":"true"}]}'
```

**answerType 测试总结**：

| answerType 值  | 场景   | 重复提交同一题目 | 数据库行为        |
| ------------- | ---- | -------- | ------------ |
| `practice`    | 日常练习 | 允许       | UPDATE 已有记录  |
| `mock_exam`   | 模拟考  | 允许       | UPDATE 已有记录  |
| `formal_exam` | 正式考试 | 不允许      | 抛出异常（唯一索引保护） |

***

## 五、AI端接口测试

AI端接口**支持** **`explanation`** **字段**，可以直接使用包含完整题目信息的JSON。

### 5.1 单选题测试

```bash
curl -X POST http://localhost:5001/exam/grade -H "Content-Type: application/json" -d '{"answers":[{"questionId":"q1","questionType":"single_choice","questionContent":{"stem":"根据文档内容，务求实效原则的核心要求聚焦于哪一根本目标？","data":{"options":[{"key":"A","content":"扩大终端数量规模"},{"key":"B","content":"提升终端信息化系统覆盖率"},{"key":"C","content":"着眼于终端功能发挥和服务水平提升"},{"key":"D","content":"统一各类终端建设外观标准"}]},"answer":"C","explanation":"文档明确指出要着眼于终端功能发挥和服务水平提升"},"studentAnswer":"C","maxScore":2}]}'
```

### 5.2 多选题测试

```bash
curl -X POST http://localhost:5001/exam/grade -H "Content-Type: application/json" -d '{"answers":[{"questionId":"q2","questionType":"multiple_choice","questionContent":{"stem":"依据务求实效原则，以下哪些做法符合其核心要求？（可多选）","data":{"options":[{"key":"A","content":"科学设定终端投入标准"},{"key":"B","content":"严格执行终端投入标准"},{"key":"C","content":"优先采购高配置但非必需的智能设备"},{"key":"D","content":"坚决杜绝不必要的支出和浪费"}]},"answer":["A","B","D"],"explanation":"A、B、D均符合务求实效原则"},"studentAnswer":["A","B","D"],"maxScore":4}]}'
```

### 5.3 空白试卷测试（answers 为空数组）

```bash
curl -X POST http://localhost:5001/exam/grade -H "Content-Type: application/json" -d '{"answers":[]}'
```

**预期响应**：

- **正常情况**（Python AI 已做空值防御）：
  ```json
  {
    "data": {
      "requestId": null,
      "results": [],
      "scoreRate": 0.0,
      "success": true,
      "totalMaxScore": 0,
      "totalScore": 0
    },
    "message": "批阅完成",
    "status": "success",
    "statusCode": 2012,
    "success": true
  }
  ```
- **异常情况**（Python AI 未做空值防御）：
  ```json
  {
    "error_code": "GRADE_ERROR",
    "message": "'NoneType' object has no attribute 'get'",
    "status": "failed",
    "status_code": 5021,
    "success": false
  }
  ```

### 5.4 填空题空答案测试

```bash
curl -X POST http://localhost:5001/exam/grade -H "Content-Type: application/json" -d '{"answers":[{"questionId":"q3","questionType":"fill_blank","questionContent":{"stem":"务求实效原则强调以___为出发点，通过科学设定和严格执行终端投入标准，实现___与___的双重提升。","data":{"blank_count":3},"answer":["终端功能发挥和服务水平提升","终端功能发挥","服务水平提升"]},"studentAnswer":null,"maxScore":3}]}'
```

### 5.5 主观题空答案测试

```bash
curl -X POST http://localhost:5001/exam/grade -H "Content-Type: application/json" -d '{"answers":[{"questionId":"q4","questionType":"subjective","questionContent":{"stem":"请简述\"务求实效原则\"的核心要求。","data":{"scoring_points":[{"point":"功能发挥","weight":0.5},{"point":"服务水平","weight":0.3},{"point":"杜绝浪费","weight":0.2}]},"answer":"以终端功能发挥和服务水平提升为唯一导向"},"studentAnswer":"","maxScore":5}]}'
```

### 5.6 判断题空答案测试（studentAnswer 为空字符串）

```bash
curl -X POST http://localhost:5001/exam/grade -H "Content-Type: application/json" -d '{"answers":[{"questionId":"q5","questionType":"true_false","questionContent":{"stem":"务求实效原则允许在终端建设中适度预留冗余预算，以应对未来可能的功能升级需求。","answer":"false"},"studentAnswer":"","maxScore":2}]}'
```

### 5.7 判断题空答案测试（studentAnswer 为 null）

```bash
curl -X POST http://localhost:5001/exam/grade -H "Content-Type: application/json" -d '{"answers":[{"questionId":"q6","questionType":"true_false","questionContent":{"stem":"务求实效原则强调以终端功能发挥和服务水平提升为唯一导向。","answer":"true"},"studentAnswer":null,"maxScore":2}]}'
```

### 5.8 单选题空答案测试

```bash
curl -X POST http://localhost:5001/exam/grade -H "Content-Type: application/json" -d '{"answers":[{"questionId":"q7","questionType":"single_choice","questionContent":{"stem":"根据文档内容，务求实效原则的核心要求聚焦于哪一根本目标？","data":{"options":[{"key":"A","content":"扩大终端数量规模"},{"key":"B","content":"提升终端信息化系统覆盖率"},{"key":"C","content":"着眼于终端功能发挥和服务水平提升"},{"key":"D","content":"统一各类终端建设外观标准"}]},"answer":"C"},"studentAnswer":null,"maxScore":2}]}'
```

### 5.9 多选题空答案测试

```bash
curl -X POST http://localhost:5001/exam/grade -H "Content-Type: application/json" -d '{"answers":[{"questionId":"q8","questionType":"multiple_choice","questionContent":{"stem":"依据务求实效原则，以下哪些做法符合其核心要求？（可多选）","data":{"options":[{"key":"A","content":"科学设定终端投入标准"},{"key":"B","content":"严格执行终端投入标准"},{"key":"C","content":"优先采购高配置但非必需的智能设备"},{"key":"D","content":"坚决杜绝不必要的支出和浪费"}]},"answer":["A","B","D"]},"studentAnswer":[],"maxScore":4}]}'
```

***

## 六、接口对比总结

| 特性              | 后端通用接口 (/api/exam/grade)               | 后端正式考试接口 (/api/exam/record/{recordId}/grade)             | AI端接口 (/exam/grade)                |
| --------------- | -------------------------------------- | -------------------------------------------------------- | ---------------------------------- |
| 地址              | <http://localhost:8080/api/exam/grade> | <http://localhost:8080/api/exam/record/{recordId}/grade> | <http://localhost:5001/exam/grade> |
| 认证              | 需要 Bearer Token                        | 需要 Bearer Token                                          | 不需要认证                              |
| requestId       | 必需                                     | 不需要                                                      | 不需要                                |
| recordId        | 可选（正式考试时使用）                            | 路径参数（必需）                                                 | 不支持                                |
| answerType      | 前端传入，后端原样使用                            | 固定为 "formal\_exam"                                       | 不支持                                |
| questionId      | 使用数据库UUID                              | 使用数据库UUID                                                | 可自定义ID                             |
| maxScore        | 小数 (2.0)                               | 不需要（从数据库获取）                                              | 整数 (2)                             |
| explanation字段   | **不支持**                                | **不支持**                                                  | 支持                                 |
| questionContent | 日常练习/模拟考时必需                            | 不需要                                                      | 支持                                 |

**recordId 参数说明**：

- 当在通用接口中传入 `recordId` 时，系统会尝试查找并更新对应的考试记录
- 这种方式主要用于正式考试场景，配合 `answerType: "formal_exam"` 使用
- 对于日常练习或模拟考，可以不传入 `recordId`
- 推荐使用专门的 `/api/exam/record/{recordId}/grade` 接口进行正式考试

***

## 七、预期响应格式

### 7.1 后端通用接口响应示例（日常练习/模拟考）

```json
{
  "code": 200,
  "message": "批阅成功",
  "data": {
    "requestId": "test_001",
    "results": [
      {
        "questionId": "9d05c475-b4fe-4679-a450-ee88a94b3b34",
        "correct": true,
        "feedback": "回答正确！",
        "score": 2.0,
        "maxScore": 2.0
      }
    ],
    "totalScore": 2.0,
    "totalMaxScore": 2.0,
    "scoreRate": 100.0
  }
}
```

### 7.2 后端正式考试接口响应示例

```json
{
  "code": 200,
  "message": "提交成功",
  "data": {
    "recordId": "59759c40-ee4e-4ff5-ab03-4819a0499beb",
    "paperId": "0ef70443-67d3-48cd-9309-f5088c092fe1",
    "userId": 1,
    "answerType": "formal_exam",
    "status": "graded",
    "totalScore": 12.0,
    "paperTitle": "测试试卷",
    "answers": [
      {
        "questionId": "9d05c475-b4fe-4679-a450-ee88a94b3b34",
        "score": 2.0,
        "isCorrect": true,
        "feedback": "回答正确！"
      }
    ],
    "startTime": "2024-05-20T10:00:00",
    "submitTime": "2024-05-20T10:30:00",
    "gradedTime": "2024-05-20T10:30:05"
  }
}
```

### 7.3 AI端接口响应示例

```json
{
  "data": {
    "requestId": null,
    "results": [
      {
        "correct": true,
        "feedback": "正确！",
        "maxScore": 2,
        "questionId": "9d05c475-b4fe-4679-a450-ee88a94b3b34",
        "score": 2
      }
    ],
    "scoreRate": 100.0,
    "success": true,
    "totalMaxScore": 2,
    "totalScore": 2
  },
  "message": "批阅完成",
  "status": "success",
  "statusCode": 2021,
  "success": true
}
```

### 7.4 空白试卷响应示例（日常练习/模拟考）

```json
{
  "code": 200,
  "message": "批阅成功",
  "data": {
    "requestId": "blank_test_001",
    "results": [],
    "totalScore": 0.0,
    "totalMaxScore": 0.0,
    "scoreRate": 0.0
  }
}
```

### 7.5 空白试卷响应示例（正式考试）

```json
{
  "code": 200,
  "message": "提交成功",
  "data": {
    "recordId": "59759c40-ee4e-4ff5-ab03-4819a0499beb",
    "paperId": "0ef70443-67d3-48cd-9309-f5088c092fe1",
    "userId": 1,
    "answerType": "formal_exam",
    "status": "graded",
    "totalScore": 0.0,
    "paperTitle": "测试试卷",
    "answers": [],
    "startTime": "2024-05-20T10:00:00",
    "submitTime": "2024-05-20T10:30:00",
    "gradedTime": "2024-05-20T10:30:05"
  }
}
```

***

## 八、测试数据来源说明

本测试文档中的题目数据均来源于数据库表 `question`，具体来源如下：

| questionId                             | 题目类型             | 文档来源                |
| -------------------------------------- | ---------------- | ------------------- |
| `9d05c475-b4fe-4679-a450-ee88a94b3b34` | single\_choice   | public\_kb - 务求实效原则 |
| `ee652f7e-da5e-4129-8766-c113277332f4` | multiple\_choice | public\_kb - 务求实效原则 |
| `76913ad8-5325-4f30-a03a-6e19e434b59e` | true\_false      | public\_kb - 务求实效原则 |
| `7ae3daef-0345-4852-bd37-336e74498cc4` | fill\_blank      | public\_kb - 务求实效原则 |
| `ea6ba220-43ff-44d8-8b24-cd350eeb8b53` | subjective       | public\_kb - 务求实效原则 |

数据库文件路径：[knowledge\_management\_system.sql](file:///d:/Users/19211/Desktop/demo/docs/sql/knowledge_management_system.sql)

### 8.1 数据库题目查询 SQL

如需从数据库获取更多测试题目，可使用以下 SQL 查询：

```sql
-- 查询所有已审核通过的题目
SELECT question_id, question_type, difficulty, score, content 
FROM question 
WHERE status = 'approved' 
ORDER BY question_type, id;

-- 查询指定类型的题目
SELECT question_id, question_type, content 
FROM question 
WHERE status = 'approved' 
  AND question_type = 'single_choice' 
LIMIT 10;

-- 查询指定难度的题目
SELECT question_id, question_type, difficulty, content 
FROM question 
WHERE status = 'approved' 
  AND difficulty = 3;
```

***

## 九、重要提示

**后端接口 QuestionContent 字段定义**：

```java
private String stem;
private Map<String, Object> data;
private Object answer;
```

**注意**：后端接口**不支持** **`explanation`** **字段**，如果传入会导致JSON解析错误。

**字段命名规范**：

- 所有字段使用驼峰命名（camelCase），而不是下划线命名（snake\_case）
- 例如：`answerType`、`recordId`、`questionId`、`studentAnswer`、`maxScore`

**使用建议**：

1. **所有curl命令已改为单行格式**，可以直接复制使用
2. **Token有效期2小时**，过期后需要重新获取
3. **测试时请确保后端服务和AI服务都已启动**
4. **日常练习和模拟考可以重复提交**，会自动更新记录
5. **正式考试只能提交一次**，重复提交会报错

**空白试卷测试说明**：

- 空白试卷（`answers` 为空数组）测试用于验证系统在无答案情况下的处理能力
- 正常情况下，空白试卷应返回总分 0.0，不触发错误
- 若 Python AI 批改服务未做空值防御，可能会出现 `'NoneType' object has no attribute 'get'` 错误（500 状态码）
- 相关修复方案可参考：`后端问题诊断报告_考试提交AI批改服务崩溃.md`

**AI端空白试卷测试要点**：

- AI端接口（`http://localhost:5001/exam/grade`）**支持完整的题目信息**，包含 `explanation` 字段
- AI端采用**小写驼峰命名**（如 `questionId`、`questionType`、`questionContent`、`studentAnswer`、`maxScore`）
- 空白试卷测试重点验证 Python AI 服务的空值防御能力
- 填空题空答案（`studentAnswer: null`）和主观题空答案（`studentAnswer: ""`）也是常见的边界测试场景

***

**文档结束**
