diff --git a/jeecg-boot/jeecg-boot-module/jeecg-module-aiol/src/main/java/org/jeecg/modules/aiol/controller/AiolExamController.java b/jeecg-boot/jeecg-boot-module/jeecg-module-aiol/src/main/java/org/jeecg/modules/aiol/controller/AiolExamController.java index aaf96c2e..ff20414f 100644 --- a/jeecg-boot/jeecg-boot-module/jeecg-module-aiol/src/main/java/org/jeecg/modules/aiol/controller/AiolExamController.java +++ b/jeecg-boot/jeecg-boot-module/jeecg-module-aiol/src/main/java/org/jeecg/modules/aiol/controller/AiolExamController.java @@ -1,5 +1,7 @@ package org.jeecg.modules.aiol.controller; +import java.time.LocalDateTime; +import java.time.ZoneId; import java.util.*; import java.util.stream.Collectors; import java.io.IOException; @@ -17,6 +19,7 @@ import org.jeecg.common.api.vo.Result; import org.jeecg.common.system.query.QueryGenerator; import org.jeecg.common.system.query.QueryRuleEnum; import org.jeecg.common.util.oConvertUtils; +import org.jeecg.modules.aiol.dto.ExaminationResult; import org.jeecg.modules.aiol.dto.QuestionAnswerDTO; import org.jeecg.modules.aiol.dto.QuestionAnswerUser; import org.jeecg.modules.aiol.entity.*; @@ -317,11 +320,10 @@ public class AiolExamController extends JeecgController gradedAnswers = gradeExam(examRecord.getExamId(), examRecord.getUserId()); + List gradedAnswers = gradeExam(examRecord.getExamId(), examRecord.getUserId(), updateWrapper); examAnswerService.updateBatchById(gradedAnswers); // 更新考试状态,提交时间 updateWrapper. - set(AiolExamRecord::getStatus,1). set(AiolExamRecord::getSubmittedAt, new Date()); // 更新 return examRecordService.update(updateWrapper) ? Result.OK() : Result.error("提交考试失败"); @@ -522,7 +524,15 @@ public class AiolExamController extends JeecgController(). @@ -531,6 +541,113 @@ public class AiolExamController extends JeecgController queryExamResult(@RequestParam String examId, @RequestParam String userId) { + AiolExamRecord one = examRecordService.getOne( + new LambdaQueryWrapper() + .eq(AiolExamRecord::getExamId, examId) + .eq(AiolExamRecord::getUserId, userId) + ); + if(one == null){ + return Result.error("考试记录不存在"); + } + if(one.getStatus() != 2){ + return Result.error("考试未批改"); + } + // 获取学生的答题列表 + List examAnswerList = examAnswerService.list( + new LambdaQueryWrapper() + .eq(AiolExamAnswer::getExamId, examId) + .eq(AiolExamAnswer::getUserId, userId) + ); + //创建题目id到学生答案的映射 + Map examAnswerMap = examAnswerList.stream() + .collect(Collectors.toMap(AiolExamAnswer::getQuestionId, examAnswer -> examAnswer)); + // 提取所有题目ID + List questionIds = examAnswerList.stream() + .map(AiolExamAnswer::getQuestionId) + .collect(Collectors.toList()); + // 查询题目 + List questions = questionService.list( + new LambdaQueryWrapper() + .in(AiolQuestion::getId, questionIds) + ); + // 按父题目id分类 + Map> questionsByParentId = questions.stream() + .collect(Collectors.groupingBy( + q -> q.getParentId() != null ? q.getParentId() : "NULL_PARENT" + )); + // 按题目类型分组 + Map> questionsByType = questions.stream() + .collect(Collectors.groupingBy(AiolQuestion::getType)); + // 分离选择题(0、1、2) + List choiceQuestions = questionsByType.entrySet().stream() + .filter(entry -> entry.getKey() < 3) + .flatMap(entry -> entry.getValue().stream()) + .collect(Collectors.toList()); + // 获取填空题和简答题(3、4) + List fillAndEssayQuestions = new ArrayList<>(); + if (questionsByType.containsKey(3)) { + fillAndEssayQuestions.addAll(questionsByType.get(3)); + } + if (questionsByType.containsKey(4)) { + fillAndEssayQuestions.addAll(questionsByType.get(4)); + } + // 查询题目的选项 + List questionOptions = questionOptionService.list( + new LambdaQueryWrapper() + .in(AiolQuestionOption::getQuestionId, + choiceQuestions.stream() + .map(AiolQuestion::getId) + .collect(Collectors.toList())) + ); + // 查询填空题简答题的答案 + List questionAnswers = questionAnswerService.list( + new LambdaQueryWrapper() + .in(AiolQuestionAnswer::getQuestionId, + fillAndEssayQuestions.stream() + .map(AiolQuestion::getId) + .collect(Collectors.toList())) + ); + // 构建选择题选项映射:题目ID -> 选项列表 + Map> questionOptionMap = questionOptions.stream() + .collect(Collectors.groupingBy(AiolQuestionOption::getQuestionId)); + + // 构建填空题和简答题答案映射:题目ID -> 答案列表 + Map> questionAnswerMap = questionAnswers.stream() + .collect(Collectors.groupingBy(AiolQuestionAnswer::getQuestionId)); + + // 合并到一个映射中 + Map> questionOrIdMap = new HashMap<>(); + questionOrIdMap.putAll(questionOptionMap); + questionOrIdMap.putAll(questionAnswerMap); + List examinationResultList = new ArrayList<>(); + // 遍历没有父题目的题目 + questionsByParentId.get("NULL_PARENT").forEach(q -> { + ExaminationResult examinationResult = new ExaminationResult(); + examinationResult.setQuestion(q); + examinationResult.setUserAnswer(examAnswerMap.get(q.getId())); + examinationResult.setAnswer(questionOrIdMap.get(q.getId())); + // 检查当前题目是否是复合题目 + if (questionsByParentId.containsKey(q.getId())) { + // 如果是复合题目,查找其子题目 + List childResults = new ArrayList<>(); + questionsByParentId.get(q.getId()).forEach(childQ -> { + ExaminationResult childResult = new ExaminationResult(); + childResult.setQuestion(childQ); + childResult.setUserAnswer(examAnswerMap.get(childQ.getId())); + childResult.setAnswer(questionOrIdMap.get(childQ.getId())); + childResults.add(childResult); + }); + examinationResult.setChildren(childResults); + } + examinationResultList.add(examinationResult); + }); + return Result.OK(examinationResultList); + } + //根据考试规则随机组卷 public List random(List list, String rules) { JSONObject ruleJson = JSON.parseObject(rules); @@ -620,9 +737,10 @@ public class AiolExamController extends JeecgController gradeExam(String examId, String userId) { + private List gradeExam(String examId, String userId , LambdaUpdateWrapper updateWrapper) { //获取试卷信息 AiolExam exam = examService.getById(examId); //获取组卷信息 @@ -714,6 +832,7 @@ public class AiolExamController extends JeecgController 0 && score == (paper.getGenerateMode() == 0 ? questionScoreMap.get(question.getId()) : ruleJson.getDouble("type" + question.getType() + "_score")) ? 1 : 0); } - + if(paper.getRequireReview()==1){ + updateWrapper + .set(AiolExamRecord::getStatus, 1); + }else { + updateWrapper + .set(AiolExamRecord::getStatus, 2) + .set(AiolExamRecord::getTotalScore, totalPoint); + } return examAnswerList; } diff --git a/jeecg-boot/jeecg-boot-module/jeecg-module-aiol/src/main/java/org/jeecg/modules/aiol/dto/ExaminationResult.java b/jeecg-boot/jeecg-boot-module/jeecg-module-aiol/src/main/java/org/jeecg/modules/aiol/dto/ExaminationResult.java new file mode 100644 index 00000000..763a53a8 --- /dev/null +++ b/jeecg-boot/jeecg-boot-module/jeecg-module-aiol/src/main/java/org/jeecg/modules/aiol/dto/ExaminationResult.java @@ -0,0 +1,19 @@ +package org.jeecg.modules.aiol.dto; + +import lombok.Data; +import org.jeecg.modules.aiol.entity.AiolExamAnswer; +import org.jeecg.modules.aiol.entity.AiolQuestion; + +import java.util.List; + +@Data +public class ExaminationResult { + //题目内容 + private AiolQuestion question; + //选项答案 + private List answer; + //用户答案 + private AiolExamAnswer userAnswer; + //子题目列表 + private List children; +} diff --git a/jeecg-boot/jeecg-boot-module/jeecg-module-aiol/src/main/java/org/jeecg/modules/aiol/mapper/AiolRepoMapper.java b/jeecg-boot/jeecg-boot-module/jeecg-module-aiol/src/main/java/org/jeecg/modules/aiol/mapper/AiolRepoMapper.java index 1caf01ab..99788c63 100644 --- a/jeecg-boot/jeecg-boot-module/jeecg-module-aiol/src/main/java/org/jeecg/modules/aiol/mapper/AiolRepoMapper.java +++ b/jeecg-boot/jeecg-boot-module/jeecg-module-aiol/src/main/java/org/jeecg/modules/aiol/mapper/AiolRepoMapper.java @@ -2,6 +2,7 @@ package org.jeecg.modules.aiol.mapper; import java.util.List; +import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; import org.jeecg.modules.aiol.entity.AiolRepo; import com.baomidou.mybatisplus.core.mapper.BaseMapper; @@ -12,6 +13,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; * @Date: 2025-08-31 * @Version: V1.0 */ +@Mapper public interface AiolRepoMapper extends BaseMapper { }