320 lines
7.7 KiB
Markdown
320 lines
7.7 KiB
Markdown
|
|
# 修复答案重复显示和成绩排序问题
|
|||
|
|
|
|||
|
|
## 🎯 **问题描述**
|
|||
|
|
|
|||
|
|
### **问题1:试卷详情答案重复显示**
|
|||
|
|
|
|||
|
|
**现象:**
|
|||
|
|
```
|
|||
|
|
我的答案:A. 阿斯蒂芬地方
|
|||
|
|
正确答案:B. B. 阿斯蒂芬都是放到 ❌ 重复了
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**应该是:**
|
|||
|
|
```
|
|||
|
|
正确答案:B. 阿斯蒂芬都是放到
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
### **问题2:成绩管理排序**
|
|||
|
|
|
|||
|
|
**需求:** 按提交时间倒序排列(从最近到最远)
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## ✅ **修复内容**
|
|||
|
|
|
|||
|
|
### **1. 修复答案格式化逻辑**
|
|||
|
|
|
|||
|
|
**文件:** `Study-Vue-redis/ry-study-admin/src/main/java/com/ddnai/web/controller/study/StudyScoreController.java`
|
|||
|
|
|
|||
|
|
**修改位置:** `formatAnswerWithContent` 方法(第406-445行)
|
|||
|
|
|
|||
|
|
**修复说明:**
|
|||
|
|
- 检测答案是否已包含完整格式(如 "B. 选项内容")
|
|||
|
|
- 如果已包含,先提取纯字母(B),再重新格式化
|
|||
|
|
- 避免重复格式化导致 "B. B. 选项内容"
|
|||
|
|
|
|||
|
|
**核心代码:**
|
|||
|
|
```java
|
|||
|
|
// 如果答案已经包含".",说明可能已经是完整格式(如"B. 选项内容")
|
|||
|
|
// 需要提取纯字母,避免重复格式化导致"B. B. 选项内容"
|
|||
|
|
if (trimmedAnswer.contains("."))
|
|||
|
|
{
|
|||
|
|
// 提取纯字母答案(去除". "后面的内容)
|
|||
|
|
if (trimmedAnswer.contains(","))
|
|||
|
|
{
|
|||
|
|
// 多选题:提取每个选项的字母部分
|
|||
|
|
String[] parts = trimmedAnswer.split(",");
|
|||
|
|
java.util.List<String> letters = new java.util.ArrayList<>();
|
|||
|
|
for (String part : parts)
|
|||
|
|
{
|
|||
|
|
String p = part.trim();
|
|||
|
|
if (p.contains("."))
|
|||
|
|
{
|
|||
|
|
String letter = p.substring(0, p.indexOf(".")).trim();
|
|||
|
|
if (letter.matches("[A-Fa-f]"))
|
|||
|
|
{
|
|||
|
|
letters.add(letter);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
if (!letters.isEmpty())
|
|||
|
|
{
|
|||
|
|
trimmedAnswer = String.join(",", letters);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
// 单选题:提取字母部分
|
|||
|
|
String letter = trimmedAnswer.substring(0, trimmedAnswer.indexOf(".")).trim();
|
|||
|
|
if (letter.matches("[A-Fa-f]"))
|
|||
|
|
{
|
|||
|
|
trimmedAnswer = letter;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
### **2. 修复成绩排序逻辑**
|
|||
|
|
|
|||
|
|
**文件:** `Study-Vue-redis/ry-study-system/src/main/resources/mapper/study/StudyScoreMapper.xml`
|
|||
|
|
|
|||
|
|
**修改位置:** `selectScoreList` 查询的 `order by` 子句(第64行)
|
|||
|
|
|
|||
|
|
**修改前:**
|
|||
|
|
```sql
|
|||
|
|
order by
|
|||
|
|
IFNULL(s.exam_name, '') asc, -- 考试名称
|
|||
|
|
IFNULL(s.subject_name, '') asc, -- 科目名称
|
|||
|
|
s.obtained_score desc, -- 得分
|
|||
|
|
s.submit_time desc -- 提交时间
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**修改后:**
|
|||
|
|
```sql
|
|||
|
|
order by s.submit_time desc -- 只按提交时间倒序
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**说明:**
|
|||
|
|
- 移除了考试名称、科目名称、得分等排序字段
|
|||
|
|
- 直接按提交时间倒序(DESC)
|
|||
|
|
- 最新的成绩记录显示在最前面
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
### **3. 清理数据库错误数据**
|
|||
|
|
|
|||
|
|
**文件:** `log/Sql/fix_answer_format.sql`
|
|||
|
|
|
|||
|
|
**执行的SQL:**
|
|||
|
|
```sql
|
|||
|
|
-- 修复单选题(将 "B. 选项内容" 改为 "B")
|
|||
|
|
UPDATE question
|
|||
|
|
SET correct_answer = SUBSTRING(correct_answer, 1, LOCATE('.', correct_answer) - 1)
|
|||
|
|
WHERE correct_answer LIKE '%. %'
|
|||
|
|
AND correct_answer NOT LIKE '%,%';
|
|||
|
|
|
|||
|
|
-- 修复多选题(将 "A. 选项1, B. 选项2" 改为 "A,B,C")
|
|||
|
|
UPDATE question
|
|||
|
|
SET correct_answer = 'A,B,C'
|
|||
|
|
WHERE id = 184;
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**修复结果:**
|
|||
|
|
```
|
|||
|
|
ID 37: "A. [ ]1" → "A" ✅
|
|||
|
|
ID 164: "A. 第三方" → "A" ✅
|
|||
|
|
ID 166: "B. ASDFADSFAS" → "B" ✅
|
|||
|
|
ID 184: "A. 选项1, B. 选项2, C. 选项3" → "A,B,C" ✅
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 📊 **测试验证**
|
|||
|
|
|
|||
|
|
### **1. 答案重复问题**
|
|||
|
|
|
|||
|
|
**测试步骤:**
|
|||
|
|
1. 重启后端服务
|
|||
|
|
2. 打开APP或管理后台
|
|||
|
|
3. 查看试卷详情
|
|||
|
|
4. 检查正确答案显示
|
|||
|
|
|
|||
|
|
**预期结果:**
|
|||
|
|
```
|
|||
|
|
✅ 正确答案:B. 阿斯蒂芬都是放到
|
|||
|
|
❌ 不再是:B. B. 阿斯蒂芬都是放到
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
### **2. 成绩排序**
|
|||
|
|
|
|||
|
|
**测试步骤:**
|
|||
|
|
1. 打开管理后台 → 学习管理 → 成绩管理
|
|||
|
|
2. 查看成绩列表
|
|||
|
|
|
|||
|
|
**预期结果:**
|
|||
|
|
```
|
|||
|
|
序号 提交时间 考试名称
|
|||
|
|
1 2025-12-05 17:45 Test3 ✅ 最新
|
|||
|
|
2 2025-12-05 14:02 Test2
|
|||
|
|
3 2025-12-05 13:43 Test
|
|||
|
|
4 2025-12-03 12:01 汉字训练 ✅ 最旧
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 🔍 **根本原因分析**
|
|||
|
|
|
|||
|
|
### **答案重复问题的根本原因:**
|
|||
|
|
|
|||
|
|
1. **数据录入错误**
|
|||
|
|
- 管理员在后台创建题目时
|
|||
|
|
- 正确答案字段输入了完整格式:"B. 选项内容"
|
|||
|
|
- 应该只输入字母:"B"
|
|||
|
|
|
|||
|
|
2. **代码未做防护**
|
|||
|
|
- `formatAnswerWithContent` 方法未考虑答案已格式化的情况
|
|||
|
|
- 直接对已格式化的答案再次格式化
|
|||
|
|
- 导致重复:"B. " + "B. 选项内容" = "B. B. 选项内容"
|
|||
|
|
|
|||
|
|
### **解决方案:**
|
|||
|
|
|
|||
|
|
1. ✅ **修复代码**(已完成)
|
|||
|
|
- 检测并提取纯字母
|
|||
|
|
- 再重新格式化
|
|||
|
|
|
|||
|
|
2. ✅ **清理数据**(已完成)
|
|||
|
|
- 将错误数据修正为纯字母格式
|
|||
|
|
|
|||
|
|
3. 🔔 **未来预防**
|
|||
|
|
- 前端表单验证:正确答案只允许输入字母(A、B、C等)
|
|||
|
|
- 后端数据验证:保存前检查格式
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 📝 **后续优化建议**
|
|||
|
|
|
|||
|
|
### **1. 前端表单优化**
|
|||
|
|
|
|||
|
|
**位置:** 题目编辑页面
|
|||
|
|
|
|||
|
|
**建议:**
|
|||
|
|
```vue
|
|||
|
|
<!-- 正确答案输入框 -->
|
|||
|
|
<el-form-item label="正确答案" required>
|
|||
|
|
<el-select v-model="form.correctAnswer" placeholder="请选择">
|
|||
|
|
<el-option label="A" value="A" />
|
|||
|
|
<el-option label="B" value="B" />
|
|||
|
|
<el-option label="C" value="C" />
|
|||
|
|
<el-option label="D" value="D" />
|
|||
|
|
</el-select>
|
|||
|
|
<span class="form-tip">只需选择字母,系统会自动关联选项内容</span>
|
|||
|
|
</el-form-item>
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
### **2. 数据验证**
|
|||
|
|
|
|||
|
|
**位置:** 题目保存接口
|
|||
|
|
|
|||
|
|
**建议:**
|
|||
|
|
```java
|
|||
|
|
// 验证正确答案格式
|
|||
|
|
if ("single".equals(question.getQuestionType()) || "multiple".equals(question.getQuestionType()))
|
|||
|
|
{
|
|||
|
|
String correctAnswer = question.getCorrectAnswer();
|
|||
|
|
if (correctAnswer.contains("."))
|
|||
|
|
{
|
|||
|
|
// 如果包含".",提取纯字母
|
|||
|
|
correctAnswer = extractLettersOnly(correctAnswer);
|
|||
|
|
question.setCorrectAnswer(correctAnswer);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 验证格式:单选题应该是单个字母,多选题应该是逗号分隔的字母
|
|||
|
|
if (!correctAnswer.matches("^[A-F](,[A-F])*$"))
|
|||
|
|
{
|
|||
|
|
return error("正确答案格式错误,应为字母(如:A 或 A,B,C)");
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## ✅ **完成清单**
|
|||
|
|
|
|||
|
|
- [x] 修复 `formatAnswerWithContent` 方法
|
|||
|
|
- [x] 修改成绩排序逻辑
|
|||
|
|
- [x] 清理数据库错误数据
|
|||
|
|
- [x] 验证数据修复结果
|
|||
|
|
- [ ] 重启后端服务(需手动)
|
|||
|
|
- [ ] 测试试卷详情页面(需手动)
|
|||
|
|
- [ ] 测试成绩管理排序(需手动)
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 🚀 **部署步骤**
|
|||
|
|
|
|||
|
|
### **1. 编译后端**
|
|||
|
|
|
|||
|
|
在IDEA中:
|
|||
|
|
```
|
|||
|
|
1. 打开 ry-study-admin 模块
|
|||
|
|
2. Maven → clean → compile
|
|||
|
|
3. 运行 RyStudyApplication
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### **2. 验证修复**
|
|||
|
|
|
|||
|
|
**验证1:答案重复问题**
|
|||
|
|
```
|
|||
|
|
1. 打开APP
|
|||
|
|
2. 进入"我的考试"
|
|||
|
|
3. 选择Test3
|
|||
|
|
4. 查看第1题的正确答案
|
|||
|
|
5. ✅ 应显示:"B. 阿斯蒂芬都是放到"
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**验证2:成绩排序**
|
|||
|
|
```
|
|||
|
|
1. 打开管理后台
|
|||
|
|
2. 学习管理 → 成绩管理
|
|||
|
|
3. 查看列表排序
|
|||
|
|
4. ✅ 最新的成绩在最上面
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 📞 **问题反馈**
|
|||
|
|
|
|||
|
|
如果修复后仍有问题,请检查:
|
|||
|
|
|
|||
|
|
1. **答案仍然重复?**
|
|||
|
|
- 检查数据库中的 `question.correct_answer` 字段
|
|||
|
|
- 确认是否为纯字母格式(A、B、A,B,C)
|
|||
|
|
- 如不是,执行 `log/Sql/fix_answer_format.sql`
|
|||
|
|
|
|||
|
|
2. **排序未生效?**
|
|||
|
|
- 检查 XML 文件是否已保存
|
|||
|
|
- 确认后端服务是否已重启
|
|||
|
|
- 检查数据库 `score.submit_time` 字段是否有值
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
**修复完成时间:** 2025-12-05 17:50
|
|||
|
|
|
|||
|
|
**修复文件:**
|
|||
|
|
1. `StudyScoreController.java` - 答案格式化逻辑
|
|||
|
|
2. `StudyScoreMapper.xml` - 成绩排序逻辑
|
|||
|
|
3. `fix_answer_format.sql` - 数据清理脚本
|
|||
|
|
|
|||
|
|
**影响范围:**
|
|||
|
|
- 试卷详情页面(APP端和管理后台)
|
|||
|
|
- 成绩管理列表(管理后台)
|