From e06a4b9f89011173a0ebc3ae3032d2b68866b582 Mon Sep 17 00:00:00 2001 From: Lqc Date: Wed, 27 Aug 2025 21:40:42 +0800 Subject: [PATCH] =?UTF-8?q?=E6=8F=90=E4=BA=A4=E7=AD=94=E6=A1=88=EF=BC=8C?= =?UTF-8?q?=E6=8F=90=E4=BA=A4=E8=80=83=E8=AF=95=EF=BC=8C=E8=8E=B7=E5=8F=96?= =?UTF-8?q?=E8=AF=95=E5=8D=B7=E5=88=9D=E5=A7=8B=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../biz/controller/ExamBizController.java | 189 +++++++++++++++++- 1 file changed, 179 insertions(+), 10 deletions(-) diff --git a/jeecg-boot/jeecg-boot-module/jeecg-module-learn/src/main/java/org/jeecg/modules/biz/controller/ExamBizController.java b/jeecg-boot/jeecg-boot-module/jeecg-module-learn/src/main/java/org/jeecg/modules/biz/controller/ExamBizController.java index 27548cb6..4b0c40b2 100644 --- a/jeecg-boot/jeecg-boot-module/jeecg-module-learn/src/main/java/org/jeecg/modules/biz/controller/ExamBizController.java +++ b/jeecg-boot/jeecg-boot-module/jeecg-module-learn/src/main/java/org/jeecg/modules/biz/controller/ExamBizController.java @@ -1,14 +1,18 @@ package org.jeecg.modules.biz.controller; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; import com.baomidou.mybatisplus.core.toolkit.CollectionUtils; +import com.baomidou.mybatisplus.core.toolkit.StringUtils; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; import lombok.extern.slf4j.Slf4j; import org.jeecg.common.api.vo.Result; import org.jeecg.modules.gen.exam.entity.Exam; import org.jeecg.modules.gen.exam.service.IExamService; +import org.jeecg.modules.gen.examanswer.entity.ExamAnswer; import org.jeecg.modules.gen.examanswer.service.IExamAnswerService; +import org.jeecg.modules.gen.examrecord.entity.ExamRecord; import org.jeecg.modules.gen.examrecord.service.IExamRecordService; import org.jeecg.modules.gen.paper.entity.Paper; import org.jeecg.modules.gen.paper.service.IPaperService; @@ -19,15 +23,10 @@ import org.jeecg.modules.gen.question.service.IQuestionService; import org.jeecg.modules.gen.questionrepo.entity.QuestionRepo; import org.jeecg.modules.gen.questionrepo.service.IQuestionRepoService; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.web.bind.annotation.PathVariable; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RequestParam; -import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.bind.annotation.*; -import java.util.ArrayList; -import java.util.Comparator; -import java.util.List; -import java.util.Map; +import javax.servlet.http.HttpServletRequest; +import java.util.*; import java.util.stream.Collectors; @RestController @@ -101,9 +100,179 @@ public class ExamBizController { .map(paperQuestion -> questionMap.get(paperQuestion.getQuestionId())) .collect(Collectors.toList()); } - // 返回排序后的试题列表 - return Result.OK(sortedQuestions); + //获取复选题id + List type5Ids = sortedQuestions.stream() + .filter(question -> question.getType() == 5) + .map(Question::getId) + .collect(Collectors.toList()); + //获取复选题所包含的题目 + List type5Questions = new ArrayList<>(); + if (!type5Ids.isEmpty()) { + type5Questions = questionService.list( + new LambdaQueryWrapper() + .in(Question::getParentId, type5Ids) + ); + } + // 创建一个映射,用于快速查找父ID对应的子题目 + Map> parentToChildrenMap = type5Questions.stream() + .collect(Collectors.groupingBy(Question::getParentId)); + + // 将子题目添加到原始列表中,保持原有顺序 + List resultQuestions = new ArrayList<>(); + for (Question question : questions) { + resultQuestions.add(question); + if (question.getType() == 5) { + List children = parentToChildrenMap.getOrDefault(question.getId(), Collections.emptyList()); + resultQuestions.addAll(children); + } + } + //创建考试答题初始化记录 + List examAnswerList = new ArrayList<>(); + for (Question resultQuestion : resultQuestions) { + ExamAnswer examAnswer = new ExamAnswer(); + examAnswer.setExamId(examId); + examAnswer.setUserId(studentId); + if (resultQuestion != null && StringUtils.isNotEmpty(resultQuestion.getParentId())) { + examAnswer.setParentQuestionId(resultQuestion.getParentId()); + } + examAnswer.setQuestionId(resultQuestion.getId()); + examAnswerList.add(examAnswer); + } + examAnswerService.saveBatch(examAnswerList); + //创建考试记录 + ExamRecord examRecord = new ExamRecord(); + examRecord.setExamId(examId); + examRecord.setUserId(studentId); + examRecord.setStatus(0); + examRecordService.save(examRecord); + // 返回排序后的试题总列表 + return Result.OK(resultQuestions); + } + + @PostMapping("/submitAnswer") + @Operation(summary = "提交答案") + public Result submitAnswer(@RequestBody ExamAnswer examAnswer) { + // 创建查询条件 + LambdaUpdateWrapper updateWrapper = new LambdaUpdateWrapper<>(); + updateWrapper.eq(ExamAnswer::getExamId, examAnswer.getExamId()) + .eq(ExamAnswer::getUserId, examAnswer.getUserId()) + .eq(ExamAnswer::getQuestionId, examAnswer.getQuestionId()); + + // 更新答案 + if (examAnswer.getAnswer() != null) { + updateWrapper.set(ExamAnswer::getAnswer, examAnswer.getAnswer()); + } + // 执行更新 + return examAnswerService.update(updateWrapper) ? Result.OK() : Result.error("提交答案失败"); + } + + @PostMapping("/submitExam") + @Operation(summary = "提交考试") + public Result submitExam(@RequestBody ExamRecord examRecord, + HttpServletRequest req) { + examRecord.setIpAddress(getClientIp(req)); + examRecord.setDeviceInfo(getDeviceInfo(req)); + //修改状态 + examRecord.setStatus(1); + // 创建更新条件 + LambdaUpdateWrapper updateWrapper = new LambdaUpdateWrapper<>(); + updateWrapper.eq(ExamRecord::getExamId, examRecord.getExamId()) + .eq(ExamRecord::getUserId, examRecord.getUserId()); + // 更新ip + if (examRecord.getIpAddress() != null) { + updateWrapper.set(ExamRecord::getIpAddress, examRecord.getIpAddress()); + } + // 更新设备信息 + if (examRecord.getDeviceInfo() != null) { + updateWrapper.set(ExamRecord::getDeviceInfo, examRecord.getDeviceInfo()); + } + // 更新考试状态,提交时间 + updateWrapper. + set(ExamRecord::getStatus,1). + set(ExamRecord::getSubmittedAt, new Date()); + // 更新 + return examRecordService.update(updateWrapper) ? Result.OK() : Result.error("提交考试失败"); + } + + public String getClientIp(HttpServletRequest request) { + String ip = request.getHeader("X-Forwarded-For"); + + if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { + ip = request.getHeader("Proxy-Client-IP"); + } + if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { + ip = request.getHeader("WL-Proxy-Client-IP"); + } + if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { + ip = request.getHeader("HTTP_CLIENT_IP"); + } + if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { + ip = request.getHeader("HTTP_X_FORWARDED_FOR"); + } + if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { + ip = request.getRemoteAddr(); + } + // 对于通过多个代理的情况,第一个IP为客户端真实IP,多个IP按照','分割 + if (ip != null && ip.contains(",")) { + ip = ip.split(",")[0].trim(); + } + return ip; + } + + public String getDeviceInfo(HttpServletRequest request) { + // 获取User-Agent + String userAgent = request.getHeader("User-Agent"); + // 解析设备信息 + String deviceInfo = parseDeviceInfo(userAgent); + return deviceInfo; + } + + private String parseDeviceInfo(String userAgent) { + if (userAgent == null) { + return "Unknown"; + } + StringBuilder deviceInfo = new StringBuilder(); + // 判断操作系统 + if (userAgent.indexOf("Windows") > -1) { + deviceInfo.append("Windows"); + } else if (userAgent.indexOf("Mac") > -1) { + deviceInfo.append("Mac"); + } else if (userAgent.indexOf("X11") > -1) { + deviceInfo.append("Unix"); + } else if (userAgent.indexOf("Android") > -1) { + deviceInfo.append("Android"); + } else if (userAgent.indexOf("iPhone") > -1 || userAgent.indexOf("iPad") > -1) { + deviceInfo.append("iOS"); + } else { + deviceInfo.append("Unknown OS"); + } + deviceInfo.append(" | "); + // 判断浏览器 + if (userAgent.indexOf("MSIE") > -1) { + deviceInfo.append("MSIE"); + } else if (userAgent.indexOf("Firefox") > -1) { + deviceInfo.append("Firefox"); + } else if (userAgent.indexOf("Chrome") > -1) { + deviceInfo.append("Chrome"); + } else if (userAgent.indexOf("Safari") > -1) { + deviceInfo.append("Safari"); + } else if (userAgent.indexOf("Opera") > -1) { + deviceInfo.append("Opera"); + } else { + deviceInfo.append("Unknown Browser"); + } + // 可以添加更多设备信息的判断,如: + // 判断是否是移动设备 + boolean isMobile = userAgent.indexOf("Mobile") > -1 || + userAgent.indexOf("Android") > -1 || + userAgent.indexOf("iPhone") > -1; + deviceInfo.append(" | ").append(isMobile ? "Mobile" : "PC"); + return deviceInfo.toString(); } + + + + }