374 lines
9.0 KiB
Markdown
374 lines
9.0 KiB
Markdown
# 答案显示格式优化说明
|
||
|
||
## 🎯 **问题描述**
|
||
|
||
### **当前显示**
|
||
```
|
||
我的答案:B. 阿萨德放到 ✅(有选项字母+内容)
|
||
正确答案:A ❌(只有选项字母)
|
||
```
|
||
|
||
### **期望显示**
|
||
```
|
||
我的答案:B. 阿萨德放到 ✅
|
||
正确答案:A. 选项内容1 ✅(选项字母+内容)
|
||
```
|
||
|
||
---
|
||
|
||
## ✅ **解决方案**
|
||
|
||
### **核心思路**
|
||
在后端返回成绩详情时,将答案字母(如"A")转换为完整格式(如"A. 选项内容")
|
||
|
||
### **修改位置**
|
||
**文件:** `StudyScoreController.java`
|
||
|
||
---
|
||
|
||
## 🔧 **代码修改**
|
||
|
||
### **修改1:在返回成绩详情时格式化答案**
|
||
|
||
**位置:** `getScoreDetail` 方法
|
||
|
||
```java
|
||
if (question != null)
|
||
{
|
||
detail.setQuestionContent(question.getQuestionContent());
|
||
|
||
// 转换正确答案格式:将字母(A)转换为完整格式(A. 选项内容)
|
||
String formattedCorrectAnswer = formatAnswerWithContent(
|
||
question.getCorrectAnswer(),
|
||
question.getOptions(),
|
||
question.getQuestionType()
|
||
);
|
||
detail.setCorrectAnswer(formattedCorrectAnswer);
|
||
|
||
// 转换学生答案格式(如果还没有完整格式)
|
||
String studentAnswer = detail.getStudentAnswer();
|
||
if (studentAnswer != null && !studentAnswer.contains(".")) {
|
||
// 如果学生答案是纯字母(如"A"),转换为完整格式
|
||
String formattedStudentAnswer = formatAnswerWithContent(
|
||
studentAnswer,
|
||
question.getOptions(),
|
||
question.getQuestionType()
|
||
);
|
||
detail.setStudentAnswer(formattedStudentAnswer);
|
||
}
|
||
|
||
detail.setQuestionType(question.getQuestionType());
|
||
detail.setQuestionScore(question.getScore());
|
||
detail.setOptions(question.getOptions());
|
||
}
|
||
```
|
||
|
||
### **修改2:添加格式化方法**
|
||
|
||
```java
|
||
/**
|
||
* 将答案转换为完整格式(字母 + 选项内容)
|
||
* @param answer 答案字母,如"A"或"A,B,C"
|
||
* @param optionsJson 选项JSON,如["选项1", "选项2"]
|
||
* @param questionType 题目类型
|
||
* @return 格式化后的答案,如"A. 选项1"或"A. 选项1, B. 选项2"
|
||
*/
|
||
private String formatAnswerWithContent(String answer, String optionsJson, String questionType)
|
||
{
|
||
if (StringUtils.isBlank(answer))
|
||
{
|
||
return "";
|
||
}
|
||
|
||
// 判断题直接返回
|
||
if ("judge".equals(questionType))
|
||
{
|
||
return answer;
|
||
}
|
||
|
||
// 填空题和简答题直接返回
|
||
if ("fill".equals(questionType) || "essay".equals(questionType))
|
||
{
|
||
return answer;
|
||
}
|
||
|
||
// 解析选项列表
|
||
java.util.List<String> optionsList = parseOptionsList(optionsJson);
|
||
if (optionsList == null || optionsList.isEmpty())
|
||
{
|
||
return answer;
|
||
}
|
||
|
||
// 单选题或多选题
|
||
String trimmedAnswer = answer.trim();
|
||
|
||
// 如果答案已经包含".",说明已经是完整格式,直接返回
|
||
if (trimmedAnswer.contains("."))
|
||
{
|
||
return trimmedAnswer;
|
||
}
|
||
|
||
// 处理多选题(答案可能是"A,B,C")
|
||
if (trimmedAnswer.contains(","))
|
||
{
|
||
String[] answerParts = trimmedAnswer.split(",");
|
||
java.util.List<String> formattedParts = new java.util.ArrayList<>();
|
||
|
||
for (String part : answerParts)
|
||
{
|
||
String letter = part.trim();
|
||
if (letter.length() == 1 && letter.matches("[A-Fa-f]"))
|
||
{
|
||
int index = letter.toUpperCase().charAt(0) - 'A';
|
||
if (index >= 0 && index < optionsList.size())
|
||
{
|
||
formattedParts.add(letter.toUpperCase() + ". " + optionsList.get(index));
|
||
}
|
||
else
|
||
{
|
||
formattedParts.add(letter);
|
||
}
|
||
}
|
||
else
|
||
{
|
||
formattedParts.add(part);
|
||
}
|
||
}
|
||
|
||
return String.join(", ", formattedParts);
|
||
}
|
||
|
||
// 处理单选题(答案是单个字母,如"A")
|
||
if (trimmedAnswer.length() == 1 && trimmedAnswer.matches("[A-Fa-f]"))
|
||
{
|
||
int index = trimmedAnswer.toUpperCase().charAt(0) - 'A';
|
||
if (index >= 0 && index < optionsList.size())
|
||
{
|
||
return trimmedAnswer.toUpperCase() + ". " + optionsList.get(index);
|
||
}
|
||
}
|
||
|
||
return answer;
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## 📋 **支持的题型**
|
||
|
||
### **1. 单选题**
|
||
**输入:** `"A"`
|
||
**输出:** `"A. 选项内容1"`
|
||
|
||
### **2. 多选题**
|
||
**输入:** `"A,B,C"`
|
||
**输出:** `"A. 选项1, B. 选项2, C. 选项3"`
|
||
|
||
### **3. 判断题**
|
||
**输入:** `"正确"`
|
||
**输出:** `"正确"`(不转换)
|
||
|
||
### **4. 填空题/简答题**
|
||
**输入:** `"答案内容"`
|
||
**输出:** `"答案内容"`(不转换)
|
||
|
||
---
|
||
|
||
## 🔄 **转换逻辑**
|
||
|
||
### **转换规则**
|
||
1. **检查是否需要转换**
|
||
- 判断题、填空题、简答题:不转换,直接返回
|
||
- 单选题、多选题:进行转换
|
||
|
||
2. **检查是否已经是完整格式**
|
||
- 如果答案包含".":已是完整格式,直接返回
|
||
- 如果答案不包含".":需要转换
|
||
|
||
3. **解析选项列表**
|
||
- 从JSON字符串解析为List
|
||
- 如果解析失败:返回原答案
|
||
|
||
4. **转换单选题答案**
|
||
- 提取字母(如"A")
|
||
- 计算索引:`'A' - 'A' = 0`
|
||
- 获取选项:`optionsList.get(0)`
|
||
- 拼接:`"A. " + 选项内容`
|
||
|
||
5. **转换多选题答案**
|
||
- 分割答案:`"A,B,C"` → `["A", "B", "C"]`
|
||
- 逐个转换每个字母
|
||
- 用逗号+空格连接:`"A. 内容1, B. 内容2, C. 内容3"`
|
||
|
||
---
|
||
|
||
## 🧪 **测试案例**
|
||
|
||
### **测试1:单选题**
|
||
```
|
||
题目:阿萨德发多少分
|
||
选项:["阿斯蒂芬都是阿凡达", "撒旦法的发"]
|
||
正确答案:A
|
||
学生答案:B
|
||
|
||
转换后:
|
||
正确答案:A. 阿斯蒂芬都是阿凡达
|
||
学生答案:B. 撒旦法的发
|
||
```
|
||
|
||
### **测试2:多选题**
|
||
```
|
||
题目:"汉"这个字的读音是?
|
||
选项:["han", "han2", "han3"]
|
||
正确答案:A,B
|
||
学生答案:A,C
|
||
|
||
转换后:
|
||
正确答案:A. han, B. han2
|
||
学生答案:A. han, C. han3
|
||
```
|
||
|
||
### **测试3:判断题**
|
||
```
|
||
正确答案:正确
|
||
学生答案:错误
|
||
|
||
转换后:
|
||
正确答案:正确
|
||
学生答案:错误
|
||
```
|
||
|
||
### **测试4:填空题**
|
||
```
|
||
正确答案:zi
|
||
学生答案:zi
|
||
|
||
转换后:
|
||
正确答案:zi
|
||
学生答案:zi
|
||
```
|
||
|
||
---
|
||
|
||
## ⚠️ **注意事项**
|
||
|
||
### **1. 学生答案格式兼容**
|
||
- 如果学生答案已经是完整格式(如"B. 内容"),不再转换
|
||
- 如果学生答案是纯字母(如"B"),进行转换
|
||
- 通过检查是否包含"."来判断
|
||
|
||
### **2. 选项索引范围检查**
|
||
```java
|
||
if (index >= 0 && index < optionsList.size())
|
||
{
|
||
// 索引有效,进行转换
|
||
}
|
||
else
|
||
{
|
||
// 索引无效,返回原字母
|
||
}
|
||
```
|
||
|
||
### **3. 大小写处理**
|
||
- 答案字母统一转换为大写
|
||
- 正则匹配:`[A-Fa-f]`(支持大小写)
|
||
|
||
### **4. 空值处理**
|
||
```java
|
||
if (StringUtils.isBlank(answer))
|
||
{
|
||
return "";
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## 🎨 **前端显示效果**
|
||
|
||
### **修改前**
|
||
```
|
||
第 1 题 0/5分
|
||
|
||
阿萨德发多少分
|
||
|
||
我的答案: B. 撒旦法的发
|
||
正确答案: A ❌ 只显示字母
|
||
```
|
||
|
||
### **修改后**
|
||
```
|
||
第 1 题 0/5分
|
||
|
||
阿萨德发多少分
|
||
|
||
我的答案: B. 撒旦法的发
|
||
正确答案: A. 阿斯蒂芬都是阿凡达 ✅ 显示完整
|
||
```
|
||
|
||
---
|
||
|
||
## 🚀 **部署步骤**
|
||
|
||
### **1. 重新编译后端**
|
||
```bash
|
||
cd C:\Users\Administrator\Desktop\Project\ry_study-v_03\Study-Vue-redis
|
||
mvn clean package -DskipTests
|
||
```
|
||
|
||
### **2. 重启后端服务**
|
||
停止当前服务,启动新编译的jar包
|
||
|
||
### **3. 测试验证**
|
||
1. 在App中完成一份试卷
|
||
2. 提交试卷
|
||
3. 查看成绩详情
|
||
4. 检查答案显示格式:
|
||
- ✅ 正确答案显示完整格式
|
||
- ✅ 学生答案显示完整格式
|
||
- ✅ 多选题用逗号分隔
|
||
|
||
---
|
||
|
||
## 📝 **验收标准**
|
||
|
||
- [ ] 单选题正确答案显示:"A. 选项内容"
|
||
- [ ] 单选题学生答案显示:"B. 选项内容"
|
||
- [ ] 多选题正确答案显示:"A. 内容1, B. 内容2"
|
||
- [ ] 多选题学生答案显示:"A. 内容1, C. 内容3"
|
||
- [ ] 判断题正确显示:"正确"或"错误"
|
||
- [ ] 填空题正确显示答案内容
|
||
- [ ] 简答题正确显示答案内容
|
||
- [ ] 没有出现格式错误或显示异常
|
||
|
||
---
|
||
|
||
## 🐛 **可能的问题**
|
||
|
||
### **问题1:选项内容显示为空**
|
||
**原因:** 选项JSON解析失败或索引超出范围
|
||
**解决:** 检查数据库中的`options`字段格式是否正确
|
||
|
||
### **问题2:答案显示乱码**
|
||
**原因:** 字符编码问题
|
||
**解决:** 确保数据库和Java代码使用UTF-8编码
|
||
|
||
### **问题3:多选题逗号显示异常**
|
||
**原因:** 分隔符问题
|
||
**解决:** 检查`String.join(", ", formattedParts)`的分隔符
|
||
|
||
---
|
||
|
||
## ✅ **总结**
|
||
|
||
### **核心改进**
|
||
1. ✅ 答案显示更直观(字母+内容)
|
||
2. ✅ 学生更容易理解错误原因
|
||
3. ✅ 支持所有题型
|
||
4. ✅ 兼容已有数据格式
|
||
|
||
### **技术要点**
|
||
- 后端动态格式化答案
|
||
- 根据题型选择不同处理逻辑
|
||
- 兼容已存在的完整格式答案
|
||
- 统一学生答案和正确答案的显示格式
|