From 15eb8be98a1bf334109ebb514d56be2a2d9c5c91 Mon Sep 17 00:00:00 2001 From: luogw <3132758203@qq.com> Date: Mon, 6 Jul 2026 09:03:45 +0800 Subject: [PATCH] =?UTF-8?q?=E5=AE=A1=E6=89=B9=E9=80=9A=E8=BF=87=EF=BC=8C?= =?UTF-8?q?=E7=BB=9F=E8=AE=A1=E9=94=99=E9=A2=98=E6=95=B0=E9=87=8F=E5=87=8F?= =?UTF-8?q?=E4=B8=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Impl/SaveAppealDomainServiceImpl.java | 14 ++++ .../StatisticsApplicationService.java | 5 ++ .../StatisticsApplicationServiceImpl.java | 5 ++ ...SaveErrorProneStatisticsDomainService.java | 10 +++ ...ErrorProneStatisticsDomainServiceImpl.java | 67 +++++++++++++++++++ 5 files changed, 101 insertions(+) diff --git a/src/main/java/com/project/appeal/domain/service/Impl/SaveAppealDomainServiceImpl.java b/src/main/java/com/project/appeal/domain/service/Impl/SaveAppealDomainServiceImpl.java index 5e4310b..2780842 100644 --- a/src/main/java/com/project/appeal/domain/service/Impl/SaveAppealDomainServiceImpl.java +++ b/src/main/java/com/project/appeal/domain/service/Impl/SaveAppealDomainServiceImpl.java @@ -15,6 +15,7 @@ import com.project.ding.utils.SecurityUtils; import com.project.exam.domain.dto.ExamRecordDTO; import com.project.exam.domain.entity.ExamRecordEntity; import com.project.exam.mapper.ExamRecordMapper; +import com.project.statistics.application.StatisticsApplicationService; import com.project.task.domain.entity.TaskEntity; import com.project.task.domain.entity.TaskUserEntity; import com.project.task.domain.enums.QuestionTypeEnum; @@ -44,6 +45,9 @@ public class SaveAppealDomainServiceImpl implements SaveAppealDomainService { @Autowired private DingUtil dingUtil; + @Autowired + private StatisticsApplicationService statisticsApplicationService; + @Override @Transactional(rollbackFor = BusinessErrorException.class) @@ -101,6 +105,16 @@ public class SaveAppealDomainServiceImpl implements SaveAppealDomainService { }else if(appealDTO.getStatus().equals(AppealStatusEnum.PASS_REVIEW.getValue()) && !Boolean.TRUE.equals(questionSnapshotDTO.getIsRight())){ //审批通过需要加分 calculateScore(appealDTO, examRecord, index, questionSnapshotDTO.getType()); + + //加分后试题变正确,减少错题数 + List snapshots = examRecord.getAnswerSnapshot(); + ExamRecordEntity.QuestionSnapshot updatedSnapshot = snapshots.get(index); + if (Boolean.TRUE.equals(updatedSnapshot.getIsRight())) { + TaskEntity taskEntity = taskMapper.getTaskByTaskUserId(examRecord.getTaskUserId()); + statisticsApplicationService.decreaseErrorCountAfterAppeal( + taskEntity.getId(), appealDTO.getQuestionId(), + updatedSnapshot.getType(), appealDTO.getRevisedScore()); + } } //通知用户 dingUtil.sendWorkNotice(appealDTO); diff --git a/src/main/java/com/project/statistics/application/StatisticsApplicationService.java b/src/main/java/com/project/statistics/application/StatisticsApplicationService.java index a473d6d..f942965 100644 --- a/src/main/java/com/project/statistics/application/StatisticsApplicationService.java +++ b/src/main/java/com/project/statistics/application/StatisticsApplicationService.java @@ -16,6 +16,11 @@ public interface StatisticsApplicationService { void collectShortAnswerErrorProneStatistics(TaskDTO taskDTO, List answerSnapshot); + /** + * 审批通过后减少错题数 + */ + void decreaseErrorCountAfterAppeal(Long taskId, Long questionId, Integer questionType, Double revisedScore); + Result> searchErrorProneTop(Long taskId); void singleExamStatistics(Long examRecordId) throws Exception; diff --git a/src/main/java/com/project/statistics/application/impl/StatisticsApplicationServiceImpl.java b/src/main/java/com/project/statistics/application/impl/StatisticsApplicationServiceImpl.java index b9d8f65..7889609 100644 --- a/src/main/java/com/project/statistics/application/impl/StatisticsApplicationServiceImpl.java +++ b/src/main/java/com/project/statistics/application/impl/StatisticsApplicationServiceImpl.java @@ -58,6 +58,11 @@ public class StatisticsApplicationServiceImpl implements StatisticsApplicationSe return searchErrorProneStatisticsDomainService.searchTopByTaskId(taskId); } + @Override + public void decreaseErrorCountAfterAppeal(Long taskId, Long questionId, Integer questionType, Double revisedScore) { + saveErrorProneStatisticsDomainService.decreaseErrorCountAfterAppeal(taskId, questionId, questionType, revisedScore); + } + @Override public void singleExamStatistics(Long examRecordId) throws Exception { ExamRecordDTO detail = getDetailExamRecordDomainService.getDetail(examRecordId).getData(); diff --git a/src/main/java/com/project/statistics/domain/service/SaveErrorProneStatisticsDomainService.java b/src/main/java/com/project/statistics/domain/service/SaveErrorProneStatisticsDomainService.java index b9eef2e..f1680b3 100644 --- a/src/main/java/com/project/statistics/domain/service/SaveErrorProneStatisticsDomainService.java +++ b/src/main/java/com/project/statistics/domain/service/SaveErrorProneStatisticsDomainService.java @@ -22,4 +22,14 @@ public interface SaveErrorProneStatisticsDomainService { * @param snapshots 已评分的简答题快照 */ void collectShortAnswerErrorProneStatistics(TaskDTO taskDTO, List snapshots); + + /** + * 审批通过后减少错题数 + * + * @param taskId 考试任务ID + * @param questionId 题目ID + * @param questionType 题目类型(用于判断是否为简答题) + * @param revisedScore 审批修改后的分数(简答题判断是否得满分用) + */ + void decreaseErrorCountAfterAppeal(Long taskId, Long questionId, Integer questionType, Double revisedScore); } diff --git a/src/main/java/com/project/statistics/domain/service/impl/SaveSaveErrorProneStatisticsDomainServiceImpl.java b/src/main/java/com/project/statistics/domain/service/impl/SaveSaveErrorProneStatisticsDomainServiceImpl.java index f96fe03..51e081b 100644 --- a/src/main/java/com/project/statistics/domain/service/impl/SaveSaveErrorProneStatisticsDomainServiceImpl.java +++ b/src/main/java/com/project/statistics/domain/service/impl/SaveSaveErrorProneStatisticsDomainServiceImpl.java @@ -47,6 +47,9 @@ public class SaveSaveErrorProneStatisticsDomainServiceImpl implements SaveErrorP @Autowired private StringRedisTemplate redisTemplate; + @Autowired + private TaskBaseService taskBaseService; + private static final String LOCK_PREFIX = "lock:error_prone:"; // 锁自动过期时间5秒,防止死锁(拿到锁后程序崩溃没释放,5s自动失效) private static final int LOCK_EXPIRE_SECONDS = 5; @@ -347,4 +350,68 @@ public class SaveSaveErrorProneStatisticsDomainServiceImpl implements SaveErrorP } return Boolean.FALSE.equals(snapshot.getIsRight()); } + + // ==================== 审批通过减少错题数 ==================== + + @Override + public void decreaseErrorCountAfterAppeal(Long taskId, Long questionId, Integer questionType, Double revisedScore) { + TaskEntity task = taskBaseService.getById(taskId); + if (task == null) return; + + if (ExamModeEnum.GENERATIVE.getValue().equals(task.getExamMode())) { + decreaseGenerativeErrorCount(taskId, questionId); + } else if (ExamModeEnum.CLASSIC.getValue().equals(task.getExamMode())) { + decreaseClassicErrorCount(taskId, questionId); + } + } + + /** + * 生成式:该题关联的所有知识点错题数减一 + */ + private void decreaseGenerativeErrorCount(Long taskId, Long questionId) { + QuestionEntity question = questionBaseService.getById(questionId); + if (question == null || CollUtil.isEmpty(question.getKpIdList())) return; + + for (Long kpId : question.getKpIdList()) { + String lockKey = LOCK_PREFIX + "gen:" + taskId + ":" + kpId; + boolean locked = tryLock(lockKey); + if (!locked) continue; + + try { + ErrorProneStatisticsEntity entity = errorProneStatisticsBaseService.lambdaQuery() + .eq(ErrorProneStatisticsEntity::getTaskId, taskId) + .eq(ErrorProneStatisticsEntity::getKpId, kpId) + .one(); + if (entity != null && entity.getErrorCount() != null && entity.getErrorCount() > 0) { + entity.setErrorCount(entity.getErrorCount() - 1); + errorProneStatisticsBaseService.updateById(entity); + } + } finally { + unlock(lockKey); + } + } + } + + /** + * 经典套题:该题错题数减一 + */ + private void decreaseClassicErrorCount(Long taskId, Long questionId) { + String lockKey = LOCK_PREFIX + "classic:" + taskId + ":" + questionId; + boolean locked = tryLock(lockKey); + if (!locked) return; + + try { + ErrorProneStatisticsEntity entity = errorProneStatisticsBaseService.lambdaQuery() + .eq(ErrorProneStatisticsEntity::getTaskId, taskId) + .eq(ErrorProneStatisticsEntity::getExamMode, ExamModeEnum.CLASSIC.getValue()) + .apply("JSON_CONTAINS(question_id_list, CAST({0} AS JSON))", questionId) + .one(); + if (entity != null && entity.getErrorCount() != null && entity.getErrorCount() > 0) { + entity.setErrorCount(entity.getErrorCount() - 1); + errorProneStatisticsBaseService.updateById(entity); + } + } finally { + unlock(lockKey); + } + } }