feat(exam): 优化考试判卷逻辑并完善相关接口

- 新增获取未完成判卷数量接口 getExamUnfinishedCount
- 修改定时任务 autoJudgeExamWords 使用未完成判卷数量判断
- Mapper 添加 selectUnfinishedCount 方法,SQL查询未完成记录数
- 优化文件上传判卷时日志输出,增加“上传文件成功”日志
- 修正判卷时未识别学生和考试的提示信息
- 移除学生查询页面中班级和年级ID显示,仅保留名称显示
- 测试类中添加判卷方法调用测试逻辑
- 配置文件增加 Sa-Token 相关日志调试配置
This commit is contained in:
lbw
2026-01-04 18:52:50 +08:00
parent 0802f6fe70
commit deabd5f7f5
10 changed files with 35 additions and 11 deletions

View File

@@ -19,6 +19,8 @@ public interface ExamWordsJudgeResultDOMapper {
Integer selectCount(); Integer selectCount();
Integer selectUnfinishedCount();
ExamWordsJudgeResultDO selectDetailById(@Param("id") Integer id); ExamWordsJudgeResultDO selectDetailById(@Param("id") Integer id);
List<ExamWordsJudgeResultDO> selectByStudentId(@Param("studentId") Integer studentId); List<ExamWordsJudgeResultDO> selectByStudentId(@Param("studentId") Integer studentId);

View File

@@ -13,6 +13,8 @@ public interface ExamWordsJudgeService {
Integer getExamWordsJudgeResultCount(); Integer getExamWordsJudgeResultCount();
Integer getExamUnfinishedCount();
ExamWordsJudgeResultDO getExamWordsJudgeResultDOById(Integer id); ExamWordsJudgeResultDO getExamWordsJudgeResultDOById(Integer id);
List<ExamWordsJudgeResultDO> getStudentExamWordsResultList(Integer studentId); List<ExamWordsJudgeResultDO> getStudentExamWordsResultList(Integer studentId);

View File

@@ -178,8 +178,9 @@ public class ExamWordsServiceImpl implements ExamWordsService {
File dest = new File(path); File dest = new File(path);
file.transferTo(dest); file.transferTo(dest);
int insert = examWordsJudgeResultDOMapper.insert(path);
return examWordsJudgeResultDOMapper.insert(path); log.info("上传文件成功");
return insert;
} catch (IOException e) { } catch (IOException e) {
throw new RuntimeException("上传失败", e); throw new RuntimeException("上传失败", e);
} }

View File

@@ -50,7 +50,6 @@ public class ExamWordsJudgeServiceImpl implements ExamWordsJudgeService {
private String tessdataPath; private String tessdataPath;
@Override @Override
@Transactional(rollbackFor = Exception.class)
public void judgeExamWords(int count) { public void judgeExamWords(int count) {
List<ExamWordsJudgeResultDO> examWordsJudgeResultDOS = examWordsJudgeResultDOMapper.selectUnfinishedExamWordsJudgeResultDOList(count); List<ExamWordsJudgeResultDO> examWordsJudgeResultDOS = examWordsJudgeResultDOMapper.selectUnfinishedExamWordsJudgeResultDOList(count);
for (ExamWordsJudgeResultDO examWordsJudgeResultDO : examWordsJudgeResultDOS) { for (ExamWordsJudgeResultDO examWordsJudgeResultDO : examWordsJudgeResultDOS) {
@@ -62,7 +61,7 @@ public class ExamWordsJudgeServiceImpl implements ExamWordsJudgeService {
Integer examWordsJudgeResultDOId = examWordsJudgeResultDO.getId(); Integer examWordsJudgeResultDOId = examWordsJudgeResultDO.getId();
if (studentExamId == null) { if (studentExamId == null) {
log.info("未找到学生 id 和考试 id"); log.info("未找到学生 id 和考试 id");
examWordsJudgeResultDOMapper.updateMsg(examWordsJudgeResultDOId, "未识别学生 id 和考试 id"); examWordsJudgeResultDOMapper.updateMsg(examWordsJudgeResultDOId, "未识别学生和考试");
continue; continue;
} }
@@ -351,6 +350,11 @@ public class ExamWordsJudgeServiceImpl implements ExamWordsJudgeService {
return examWordsJudgeResultDOMapper.selectCount(); return examWordsJudgeResultDOMapper.selectCount();
} }
@Override
public Integer getExamUnfinishedCount() {
return examWordsJudgeResultDOMapper.selectUnfinishedCount();
}
@Override @Override
public ExamWordsJudgeResultDO getExamWordsJudgeResultDOById(Integer id) { public ExamWordsJudgeResultDO getExamWordsJudgeResultDOById(Integer id) {
return examWordsJudgeResultDOMapper.selectDetailById(id); return examWordsJudgeResultDOMapper.selectDetailById(id);

View File

@@ -15,7 +15,7 @@ public class AutoJudgeExamWordsTask {
@Scheduled(fixedRate = 5000) @Scheduled(fixedRate = 5000)
public void autoJudgeExamWords() { public void autoJudgeExamWords() {
if (examWordsJudgeService.getExamWordsJudgeResultCount() != 0) { if (examWordsJudgeService.getExamUnfinishedCount() != 0) {
log.info("有试卷待检测,开始检测"); log.info("有试卷待检测,开始检测");
examWordsJudgeService.judgeExamWords(5); examWordsJudgeService.judgeExamWords(5);
} }

View File

@@ -9,6 +9,7 @@ mybatis:
# MyBatis xml 配置文件路径 # MyBatis xml 配置文件路径
mapper-locations: classpath:/mapper/**/*.xml mapper-locations: classpath:/mapper/**/*.xml
############## Sa-Token 配置 (文档: https://sa-token.cc) ############## ############## Sa-Token 配置 (文档: https://sa-token.cc) ##############
sa-token: sa-token:
# token 名称(同时也是 cookie 名称) # token 名称(同时也是 cookie 名称)
@@ -27,3 +28,6 @@ sa-token:
is-share: true is-share: true
# 是否输出操作日志 # 是否输出操作日志
is-log: true is-log: true
logging:
level:
com.yinlihupo.enlish.service.domain.mapper: debug

View File

@@ -61,7 +61,6 @@
<select id="selectCount" resultType="java.lang.Integer"> <select id="selectCount" resultType="java.lang.Integer">
select count(1) select count(1)
from exam_words_judge_result from exam_words_judge_result
where is_finished = 0
</select> </select>
<select id="selectDetailById" resultMap="ResultMapWithBLOBs"> <select id="selectDetailById" resultMap="ResultMapWithBLOBs">
@@ -95,4 +94,10 @@
limit #{startIndex}, #{pageSize} limit #{startIndex}, #{pageSize}
</select> </select>
<select id="selectUnfinishedCount" resultType="java.lang.Integer">
select count(*)
from exam_words_judge_result
where is_finished = 0
</select>
</mapper> </mapper>

View File

@@ -5,6 +5,7 @@ import com.deepoove.poi.config.Configure;
import com.deepoove.poi.plugin.table.LoopRowTableRenderPolicy; import com.deepoove.poi.plugin.table.LoopRowTableRenderPolicy;
import com.yinlihupo.enlish.service.domain.dataobject.ExamWordsDO; import com.yinlihupo.enlish.service.domain.dataobject.ExamWordsDO;
import com.yinlihupo.enlish.service.domain.dataobject.VocabularyBankDO; import com.yinlihupo.enlish.service.domain.dataobject.VocabularyBankDO;
import com.yinlihupo.enlish.service.domain.mapper.ExamWordsJudgeResultDOMapper;
import com.yinlihupo.enlish.service.model.bo.Word; import com.yinlihupo.enlish.service.model.bo.Word;
import com.yinlihupo.enlish.service.service.ExamWordsService; import com.yinlihupo.enlish.service.service.ExamWordsService;
import com.yinlihupo.enlish.service.service.VocabularyService; import com.yinlihupo.enlish.service.service.VocabularyService;
@@ -24,6 +25,8 @@ public class ExamTest {
private ExamWordsService examWordsService; private ExamWordsService examWordsService;
@Resource @Resource
private VocabularyService vocabularyService; private VocabularyService vocabularyService;
@Resource
private ExamWordsJudgeResultDOMapper examWordsJudgeResultDOMapper;
@Test @Test
public void test() { public void test() {
// ExamWordsDO examWordsDO = examWordsService.generateExamWords(5, 0); // ExamWordsDO examWordsDO = examWordsService.generateExamWords(5, 0);

View File

@@ -54,6 +54,11 @@ public class ExamWordsJudgeServiceTest {
// } // }
} }
@Test
public void judege() {
examWordsJudgeService.judgeExamWords(5);
}
@Test @Test
public void selectExamWordsJudgeResult() { public void selectExamWordsJudgeResult() {
// List<ExamWordsJudgeResultDO> examWordsJudgeResult = examWordsJudgeService.getExamWordsJudgeResult(1, 10); // List<ExamWordsJudgeResultDO> examWordsJudgeResult = examWordsJudgeService.getExamWordsJudgeResult(1, 10);

View File

@@ -43,10 +43,8 @@
<div class="text-lg font-semibold mb-4">学生查询</div> <div class="text-lg font-semibold mb-4">学生查询</div>
<div class="flex flex-wrap items-center gap-3 mb-4"> <div class="flex flex-wrap items-center gap-3 mb-4">
<el-input v-model="studentName" placeholder="按姓名查询" clearable style="max-width: 220px" /> <el-input v-model="studentName" placeholder="按姓名查询" clearable style="max-width: 220px" />
<el-tag v-if="selectedClassId" effect="plain">班级{{ selectedClassTitle }} (ID: {{ <el-tag v-if="selectedClassId" effect="plain">班级{{ selectedClassTitle }}</el-tag>
selectedClassId }})</el-tag> <el-tag v-if="selectedGradeId" effect="plain">年级{{ selectedGradeTitle }}</el-tag>
<el-tag v-if="selectedGradeId" effect="plain">年级{{ selectedGradeTitle }} (ID: {{
selectedGradeId }})</el-tag>
<el-button type="primary" @click="fetchStudents">查询</el-button> <el-button type="primary" @click="fetchStudents">查询</el-button>
<el-button @click="resetStudentFilters">重置</el-button> <el-button @click="resetStudentFilters">重置</el-button>
<el-button type="success" :disabled="selectedStudentIds.length !== 1" <el-button type="success" :disabled="selectedStudentIds.length !== 1"