forked from wangziqi/gongxue-base
feat: support composite practice questions
This commit is contained in:
@@ -254,6 +254,11 @@ GET /api/learning/practice-sessions/detail?practiceSessionId=<sessionId>
|
||||
"<questionId>": {
|
||||
"selectedOptions": ["1"],
|
||||
"answerText": null,
|
||||
"answerPayload": {
|
||||
"mode": "composite",
|
||||
"subAnswers": [],
|
||||
"subResults": []
|
||||
},
|
||||
"isCorrect": true,
|
||||
"answeredAt": "..."
|
||||
}
|
||||
@@ -268,6 +273,7 @@ GET /api/learning/practice-sessions/detail?practiceSessionId=<sessionId>
|
||||
- 继续练习入口优先从 `GET /api/learning/practice-sessions/history?status=active` 获取未完成 session,再带 `practiceSessionId` 进入练习页。
|
||||
- 练习页如果 URL 有 `practiceSessionId`,先调用 detail 恢复后端题目快照和最新答案,不要新建 session。
|
||||
- `answersByQuestion` 是同一题的最新答题记录,答题卡、正确/错误统计和解析展示以它为准。
|
||||
- 阅读理解、案例分析等复合题会在 `answerPayload.subAnswers/subResults` 中返回子题作答、判分、解析和分值;继续练习时按该结构恢复每个子题状态。
|
||||
- 倒计时以 `expiresAt` 计算剩余时间;不要用本地启动时间重新生成考试时长。
|
||||
- detail 只返回当前用户自己的 session;跨用户或跨租户读取会返回 `PRACTICE_SESSION_NOT_FOUND`。
|
||||
|
||||
@@ -310,6 +316,61 @@ POST /api/learning/answers
|
||||
}
|
||||
```
|
||||
|
||||
阅读理解、案例分析、组合题等带 `subQuestions` 的复合题必须使用 `subAnswers`,不能混用顶层 `selectedOptions/answerText/selfJudgedCorrect`:
|
||||
|
||||
```json
|
||||
{
|
||||
"practiceSessionId": "...",
|
||||
"questionId": "...",
|
||||
"subAnswers": [
|
||||
{
|
||||
"subQuestionId": "main-idea",
|
||||
"selectedOptions": ["1"]
|
||||
},
|
||||
{
|
||||
"subQuestionId": "reason",
|
||||
"answerText": "学生自己的作答或备注",
|
||||
"selfJudgedCorrect": true
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
复合题响应会额外返回:
|
||||
|
||||
```json
|
||||
{
|
||||
"item": {
|
||||
"isCorrect": true,
|
||||
"answerPayload": {
|
||||
"mode": "composite",
|
||||
"subAnswers": [
|
||||
{ "subQuestionId": "main-idea", "selectedOptions": ["1"], "answerText": null },
|
||||
{ "subQuestionId": "reason", "selectedOptions": [], "answerText": "学生自己的作答或备注", "selfJudgedCorrect": true }
|
||||
],
|
||||
"subResults": [
|
||||
{
|
||||
"subQuestionId": "main-idea",
|
||||
"order": 1,
|
||||
"type": "choice",
|
||||
"selectedOptions": ["1"],
|
||||
"isCorrect": true,
|
||||
"correctOptionIndices": [1],
|
||||
"explanation": "..."
|
||||
}
|
||||
],
|
||||
"summary": {
|
||||
"answeredCount": 2,
|
||||
"correctCount": 2,
|
||||
"wrongCount": 0,
|
||||
"unansweredCount": 0
|
||||
}
|
||||
},
|
||||
"subResults": []
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
响应关键字段:
|
||||
|
||||
```json
|
||||
@@ -329,6 +390,8 @@ POST /api/learning/answers
|
||||
前端处理规则:
|
||||
|
||||
- 客观题不要传 `selfJudgedCorrect`。后端会用题库标准答案判分,传了会返回 `SELF_JUDGMENT_NOT_ALLOWED`。
|
||||
- 客观子题同样不要传 `selfJudgedCorrect`;主观子题可以传 `selfJudgedCorrect`。
|
||||
- 复合题如果缺少 `subAnswers` 会返回 `SUB_ANSWERS_REQUIRED`;空提交会返回 `SUB_ANSWERS_EMPTY`;未知子题 id 会返回 `UNKNOWN_SUB_ANSWER`。
|
||||
- 主观题自评也由后端落库为 `answer_records.is_correct`,错题本、练习统计、模考报告都以后端返回为准。
|
||||
- 前端可以在本地缓存当前 session 的答题卡和当前题号,用于刷新恢复体验;但交卷报告只以后端 `answer_records` 和 session 快照计算。
|
||||
- `answerText` 只保存学生作答或备注,不要为了让后端判对而把参考答案塞进去。
|
||||
@@ -430,6 +493,13 @@ POST /api/tenant-admin/badge-grants
|
||||
}
|
||||
```
|
||||
|
||||
复合题报告规则:
|
||||
|
||||
- `totalQuestions` 仍按顶层大题计数,阅读理解/案例分析不会按子题拆成多题。
|
||||
- `questionResults[].subResults` 返回每个子题的 `selectedOptions/answerText/isCorrect/explanation/score/totalScore`。
|
||||
- 若导入数据没有给子题分值,后端默认把该大题分值平均分给所有子题;如果后续导入模板提供子题 `score`,报告会按子题分值再缩放到大题配置分。
|
||||
- 顶层 `isCorrect=true` 表示所有子题都判为正确;若部分正确,顶层为 `false`,但 `score` 会保留部分得分。
|
||||
|
||||
前端处理规则:
|
||||
|
||||
- 重复交卷是幂等的,后端会返回同一份报告。
|
||||
|
||||
Reference in New Issue
Block a user