From ef3d5894557ef4bf0dd9ecc5d37e477b96e99d79 Mon Sep 17 00:00:00 2001 From: dlaren Date: Tue, 16 Sep 2025 23:01:08 +0800 Subject: [PATCH] =?UTF-8?q?=E3=80=90=E4=BF=AE=E6=94=B9=E3=80=91=201?= =?UTF-8?q?=E3=80=81=E6=97=B6=E9=97=B4=E9=97=AA=E7=83=81=E9=97=AE=E9=A2=98?= =?UTF-8?q?=EF=BC=9B2=E3=80=81=E5=AD=A6=E7=94=9F=E7=AB=AF=E7=99=BB?= =?UTF-8?q?=E5=BD=95=E6=A6=82=E7=8E=87=E6=B2=A1=E6=9C=89=E6=A3=80=E6=B5=8B?= =?UTF-8?q?=E5=88=B0=E8=80=83=E8=AF=95=E4=B8=AD=EF=BC=9B3=E3=80=81?= =?UTF-8?q?=E7=9B=91=E6=8E=A7=E9=A1=B5=E9=9D=A2=E5=81=9C=E6=AD=A2=E8=80=83?= =?UTF-8?q?=E8=AF=95=EF=BC=8C=E5=A2=9E=E5=8A=A0=E8=80=83=E8=AF=95=E6=97=B6?= =?UTF-8?q?=E9=97=B4=E6=93=8D=E4=BD=9C=E6=9B=B4=E6=96=B0ws?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../admin/autoTools/AutoToolsController.java | 220 ++++++++++++++---- .../admin/autoTools/vo/StuInTheExam.java | 2 +- 2 files changed, 179 insertions(+), 43 deletions(-) diff --git a/exam-module-judgement/exam-module-judgement-biz/src/main/java/pc/exam/pp/module/judgement/controller/admin/autoTools/AutoToolsController.java b/exam-module-judgement/exam-module-judgement-biz/src/main/java/pc/exam/pp/module/judgement/controller/admin/autoTools/AutoToolsController.java index 75fe55c4..8b6a1597 100644 --- a/exam-module-judgement/exam-module-judgement-biz/src/main/java/pc/exam/pp/module/judgement/controller/admin/autoTools/AutoToolsController.java +++ b/exam-module-judgement/exam-module-judgement-biz/src/main/java/pc/exam/pp/module/judgement/controller/admin/autoTools/AutoToolsController.java @@ -33,6 +33,7 @@ import pc.exam.pp.module.exam.service.stuPaperScore.StuPaperScoreService; import pc.exam.pp.module.exam.service.stu_paper_file.StuPaperFileService; import pc.exam.pp.module.judgement.controller.admin.autoTools.vo.*; import pc.exam.pp.module.judgement.service.TaskManager; +import pc.exam.pp.module.system.dal.dataobject.oauth2.OAuth2AccessTokenDO; import java.time.Duration; import java.time.Instant; @@ -48,7 +49,7 @@ import java.util.stream.Collectors; */ @RestController @RequestMapping("/tool") -@Tag(name = "测试判分") +@Tag(name = "学生端WS交互") @Validated public class AutoToolsController { @Resource @@ -144,6 +145,7 @@ public class AutoToolsController { */ @PostMapping("/startExam") public CommonResult startExam(@RequestBody StuInTheExam stuInTheExam) { + HttpServletRequest request = ServletUtils.getRequest(); // 获取登录token String token = null; @@ -152,6 +154,12 @@ public class AutoToolsController { securityProperties.getTokenHeader(), securityProperties.getTokenParameter()); // 获取登录用户 LoginUser loginUser = SecurityFrameworkUtils.getLoginUser(); + // userId 是否存在 + String wsKey = taskManager.getTaskById(String.valueOf(loginUser.getId())); + if (wsKey != null) { + // 停止任务 + taskManager.stopTask(wsKey); + } int startTime = 0; // 查找对应的task EducationPaperParam educationPaperParam = educationPaperParamService.selectEducationPaperParamByTaskId(stuInTheExam.getTaskId()); @@ -202,9 +210,7 @@ public class AutoToolsController { // 返回数据-网络状态 stuTheExamInfo.setNetwork("强"); // 创建对应的线程池 - if (loginUser != null) { - taskManager.startTask(stuInTheExam, stuTheExamInfo, token, countdown, new AtomicInteger(0), loginUser.getId() + "_" + stuInTheExam.getTaskId() + "_" + stuInTheExam.getPaperId()); - } + taskManager.startTask(stuInTheExam, stuTheExamInfo, token, countdown, new AtomicInteger(0), loginUser.getId() + "_" + stuInTheExam.getTaskId() + "_" + stuInTheExam.getPaperId()); return CommonResult.success(token); } return CommonResult.success("未登录"); @@ -235,8 +241,6 @@ public class AutoToolsController { key = loginUser.getId() + "_" + monitorDO.getTaskId() + "_" + paperId; return CommonResult.success(key); } - } else { - return CommonResult.success("0"); } } } @@ -256,19 +260,20 @@ public class AutoToolsController { // 如果继续考试,需要关闭之前的,重新开始ws String taskManagerId = loginUser.getId() + "_" + stuInTheExam.getTaskId() + "_" + stuInTheExam.getPaperId(); taskManager.stopTask(taskManagerId); - if (loginUser != null) { - // 获取试卷详情 - ExamPaperVo examPaperVo = educationPaperQuService.selectPaperQuListByPaperId(stuInTheExam.getPaperId()); - // 获取剩余的时间 - String key = "userCache:" + stuInTheExam.getTaskId() + ":" + loginUser.getId(); - MonitorDO info = JsonUtils.parseObject(stringRedisTemplate.opsForValue().get(key), MonitorDO.class); - if (info != null) { - // 获取随机ID - String temporaryId = info.getTemporaryId(); - // 获取开始时间 - String startTimeExam = info.getStartTime(); + // 获取试卷详情 + ExamPaperVo examPaperVo = educationPaperQuService.selectPaperQuListByPaperId(stuInTheExam.getPaperId()); + // 获取剩余的时间 + String key = "userCache:" + stuInTheExam.getTaskId() + ":" + loginUser.getId(); + MonitorDO info = JsonUtils.parseObject(stringRedisTemplate.opsForValue().get(key), MonitorDO.class); + if (info != null) { + // 获取随机ID + String temporaryId = info.getTemporaryId(); + // 获取交互时间,作用:暂停时间,仅限于非考试 + long times = 0; + if (!info.getTaskType().equals("1")) { + String interactiveTime = info.getInteractiveTime(); DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); - LocalDateTime targetTime = LocalDateTime.parse(startTimeExam, formatter); + LocalDateTime targetTime = LocalDateTime.parse(interactiveTime, formatter); LocalDateTime currentTime = LocalDateTime.now(); Duration duration = Duration.between(currentTime, targetTime); // 两者相差的时间 @@ -276,7 +281,159 @@ public class AutoToolsController { // 获取一共要考试多长时间 long remainingTime = info.getRemainingTime(); // 判断剩余时间是否大于等于两者相差的时间 - long times = remainingTime - Math.abs(secondsDifference); + times = remainingTime - Math.abs(secondsDifference); + } else { + // 考试状态下的 + // 自动计算剩余的考试时间,就是不进行暂停时间,想要增加时间需要手动添加 + // 获取考试结束时间 + String endTime = info.getEndTime(); + DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); + LocalDateTime targetTime = LocalDateTime.parse(endTime, formatter); + LocalDateTime currentTime = LocalDateTime.now(); + Duration duration = Duration.between(currentTime, targetTime); + // 两者相差的时间 + long secondsDifference = duration.getSeconds(); + if (secondsDifference > 0) { + return CommonResult.error(1_0001_003,"考试已经结束,无法继续考试"); + } + // 判断剩余时间是否大于等于两者相差的时间 + times = secondsDifference; + } + // 开启ws + // 获取上传文件时间 + String time = examPaperVo.getEducationPaperParam().getUploadTime(); + // 将分钟继续转换成秒 + stuInTheExam.setTimes(Integer.parseInt(time) * 60); + // 倒计时 + AtomicInteger countdown = new AtomicInteger((int) times); + // 创建初始返回数据 + StuTheExamInfo stuTheExamInfo = new StuTheExamInfo(); + // 返回数据-剩余时间 + stuTheExamInfo.setTime(formatLongDuration(countdown.get())); + // 返回数据-上传文件状态 0:上传;1:不上传 + stuTheExamInfo.setUpload(1); + // 返回数据-结束考试 0:结束;1:不结束 + stuTheExamInfo.setEndStatus(1); + // 返回数据-网络状态 + stuTheExamInfo.setNetwork("强"); + taskManager.startTask(stuInTheExam, stuTheExamInfo, token, countdown, new AtomicInteger(0), loginUser.getId() + "_" + stuInTheExam.getTaskId() + "_" + stuInTheExam.getPaperId()); + // 将数组的值进行复制 + BeanUtils.copyProperties(examPaperVo, examRestartPaperVo); + examRestartPaperVo.setWsToken(token); + // 查询学生文件下载地址 + examRestartPaperVo.setTemporaryId(temporaryId); + List stuPaperFileS = stuPaperFileService.findByStuIDAndPaperId(loginUser.getId(), stuInTheExam.getPaperId(), temporaryId); + stuPaperFileS.forEach(stuPaperFileDO -> { + if (stuPaperFileDO.getType() == 0) { + // 将文件地址存放,方便前端继续下载处理 + examRestartPaperVo.setFileUrl(stuPaperFileDO.getUrl()); + } + }); + return CommonResult.success(examRestartPaperVo); + } else { + return CommonResult.error(1_0001_001,"没有找到对应的考试信息"); + } + } + + + /** + * 停止考试 + * + * @return true + */ + @GetMapping("/stopExam") + public CommonResult stopExam(@RequestParam("taskId") String taskId, @RequestParam("paperId") String paperId) { + String userId = null; + userId = String.valueOf(SecurityFrameworkUtils.getLoginUserId()); + // 将userId 拼接 taskId 作为key + // 防止不同试卷ID冲突 + userId += "_" + taskId + "_" + paperId; + // 删除对应的线程池 + taskManager.stopTask(userId); + return CommonResult.success(true); + } + + + /** + * 停止考试(更改考试状态,管理员操作) + * + * @return true + */ + @GetMapping("/stopExamForAdmin") + public CommonResult stopExamForAdmin(@RequestParam("userId") String userId, @RequestParam("taskId") String taskId, @RequestParam("paperNum") String paperNum) { + String paperId = educationPaperService.selectPaperByPaperNum(paperNum); + // 将userId 拼接 taskId 作为key + // 防止不同试卷ID冲突 + userId += "_" + taskId + "_" + paperId; + // 删除对应的线程池 + taskManager.stopTask(userId); + return CommonResult.success(true); + } + + + // 学生端考试没有结束对出,继续进行开始(需要返回下载文件地址,任务ID) + @PostMapping("/reStartExamForAdmin") + public CommonResult reStartExamForAdmin(@RequestBody StuInTheExam stuInTheExam) { + // 获取学生ID + String stuId = stuInTheExam.getStuId(); + String taskId = stuInTheExam.getTaskId(); + String token = ""; + // 通过学生ID查询token + Set oauth2_access_token_set = stringRedisTemplate.keys("oauth2_access_token:*"); + for (String oauth2_access_token : oauth2_access_token_set) { + OAuth2AccessTokenDO oAuth2AccessTokenDO = JsonUtils.parseObject(stringRedisTemplate.opsForValue().get(oauth2_access_token), OAuth2AccessTokenDO.class); + // 判断账号是否登录过 + if (oAuth2AccessTokenDO != null && String.valueOf(oAuth2AccessTokenDO.getUserId()).equals(stuId)) { + // 说明登录了,别的地方登录了,请重新登录 + token = oAuth2AccessTokenDO.getAccessToken(); + } + } + String paperId = educationPaperService.selectPaperByPaperNum(stuInTheExam.getPaperId()); + HttpServletRequest request = ServletUtils.getRequest(); + ExamRestartPaperVo examRestartPaperVo = new ExamRestartPaperVo(); + // 如果继续考试,需要关闭之前的,重新开始ws + String taskManagerId = stuId + "_" + taskId + "_" + paperId; + taskManager.stopTask(taskManagerId); + if (stuId != null) { + // 获取试卷详情 + ExamPaperVo examPaperVo = educationPaperQuService.selectPaperQuListByPaperId(paperId); + // 获取剩余的时间 + String key = "userCache:" + taskId + ":" + stuId; + MonitorDO info = JsonUtils.parseObject(stringRedisTemplate.opsForValue().get(key), MonitorDO.class); + if (info != null) { + // 获取随机ID + String temporaryId = info.getTemporaryId(); + // 获取交互时间,作用:暂停时间,仅限于非考试 + long times = 0; + if (!info.getTaskType().equals("1")) { + String interactiveTime = info.getInteractiveTime(); + DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); + LocalDateTime targetTime = LocalDateTime.parse(interactiveTime, formatter); + LocalDateTime currentTime = LocalDateTime.now(); + Duration duration = Duration.between(currentTime, targetTime); + // 两者相差的时间 + long secondsDifference = duration.getSeconds(); + // 获取一共要考试多长时间 + long remainingTime = info.getRemainingTime(); + // 判断剩余时间是否大于等于两者相差的时间 + times = remainingTime - Math.abs(secondsDifference); + } else { + // 考试状态下的 + // 自动计算剩余的考试时间,就是不进行暂停时间,想要增加时间需要手动添加 + // 获取考试结束时间 + String endTime = info.getEndTime(); + DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); + LocalDateTime targetTime = LocalDateTime.parse(endTime, formatter); + LocalDateTime currentTime = LocalDateTime.now(); + Duration duration = Duration.between(currentTime, targetTime); + // 两者相差的时间 + long secondsDifference = duration.getSeconds(); + if (secondsDifference > 0) { + return CommonResult.error(1_0001_003,"考试已经结束,无法继续考试"); + } + // 判断剩余时间是否大于等于两者相差的时间 + times = secondsDifference; + } // 开启ws // 获取上传文件时间 String time = examPaperVo.getEducationPaperParam().getUploadTime(); @@ -294,13 +451,13 @@ public class AutoToolsController { stuTheExamInfo.setEndStatus(1); // 返回数据-网络状态 stuTheExamInfo.setNetwork("强"); - taskManager.startTask(stuInTheExam, stuTheExamInfo, token, countdown, new AtomicInteger(0), loginUser.getId() + "_" + stuInTheExam.getTaskId() + "_" + stuInTheExam.getPaperId()); + taskManager.startTask(stuInTheExam, stuTheExamInfo, token, countdown, new AtomicInteger(0), stuId + "_" + stuInTheExam.getTaskId() + "_" + paperId); // 将数组的值进行复制 BeanUtils.copyProperties(examPaperVo, examRestartPaperVo); examRestartPaperVo.setWsToken(token); // 查询学生文件下载地址 examRestartPaperVo.setTemporaryId(temporaryId); - List stuPaperFileS = stuPaperFileService.findByStuIDAndPaperId(loginUser.getId(), stuInTheExam.getPaperId(), temporaryId); + List stuPaperFileS = stuPaperFileService.findByStuIDAndPaperId(Long.valueOf(stuId), paperId, temporaryId); stuPaperFileS.forEach(stuPaperFileDO -> { if (stuPaperFileDO.getType() == 0) { // 将文件地址存放,方便前端继续下载处理 @@ -315,27 +472,6 @@ public class AutoToolsController { return CommonResult.error(1_0001_002,"没有找到对应的学生信息"); } - /** - * 停止考试 - * - * @return true - */ - @GetMapping("/stopExam") - public CommonResult stopExam(@RequestParam("taskId") String taskId, @RequestParam("paperId") String paperId) { - HttpServletRequest request = ServletUtils.getRequest(); - String userId = null; - if (request != null) { - userId = String.valueOf(SecurityFrameworkUtils.getLoginUserId()); - // 将userId 拼接 taskId 作为key - // 防止不同试卷ID冲突 - userId += "_" + taskId + "_" + paperId; - // 删除对应的线程池 - taskManager.stopTask(userId); - return CommonResult.success(true); - } - return CommonResult.success(false); - } - // 时间转换 public static String formatLongDuration(int totalSeconds) { return TaskManager.formatLongDuration(totalSeconds); diff --git a/exam-module-judgement/exam-module-judgement-biz/src/main/java/pc/exam/pp/module/judgement/controller/admin/autoTools/vo/StuInTheExam.java b/exam-module-judgement/exam-module-judgement-biz/src/main/java/pc/exam/pp/module/judgement/controller/admin/autoTools/vo/StuInTheExam.java index 28529e52..c526e05b 100644 --- a/exam-module-judgement/exam-module-judgement-biz/src/main/java/pc/exam/pp/module/judgement/controller/admin/autoTools/vo/StuInTheExam.java +++ b/exam-module-judgement/exam-module-judgement-biz/src/main/java/pc/exam/pp/module/judgement/controller/admin/autoTools/vo/StuInTheExam.java @@ -6,7 +6,7 @@ import lombok.Data; @Data public class StuInTheExam { // 学生ID - // private String stuId; + private String stuId; // 倒计时开始时间 单位秒 private int startTimes; // 定时上传文件时间