From 28c75d52c51f918adc4c8d84eadb7262b69935b9 Mon Sep 17 00:00:00 2001 From: dlaren Date: Mon, 11 Aug 2025 17:17:49 +0800 Subject: [PATCH] =?UTF-8?q?=E3=80=90=E4=BF=AE=E6=94=B9=E3=80=91=20?= =?UTF-8?q?=E8=80=83=E7=82=B9=E6=9C=8D=E5=8A=A1=E5=99=A8=E7=BB=91=E5=AE=9A?= =?UTF-8?q?=E4=B8=93=E4=B8=9Asql=E5=A2=9E=E5=8A=A0=E6=9F=A5=E8=AF=A2?= =?UTF-8?q?=E6=9D=A1=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../service/monitor/MonitorServiceImpl.java | 784 +++++++++--------- .../mapper/specialty/ExamSpecialtyMapper.xml | 2 +- 2 files changed, 390 insertions(+), 396 deletions(-) diff --git a/exam-module-exam/exam-module-exam-biz/src/main/java/pc/exam/pp/module/exam/service/monitor/MonitorServiceImpl.java b/exam-module-exam/exam-module-exam-biz/src/main/java/pc/exam/pp/module/exam/service/monitor/MonitorServiceImpl.java index fd2137a1..8563e410 100644 --- a/exam-module-exam/exam-module-exam-biz/src/main/java/pc/exam/pp/module/exam/service/monitor/MonitorServiceImpl.java +++ b/exam-module-exam/exam-module-exam-biz/src/main/java/pc/exam/pp/module/exam/service/monitor/MonitorServiceImpl.java @@ -48,485 +48,479 @@ import static pc.exam.pp.module.system.enums.ErrorCodeConstants.MONITOR_NOT_EXIS @Service @Validated public class MonitorServiceImpl implements MonitorService { - @Autowired - private RedisTemplate redisTemplate; - @Resource - private MonitorMapper monitorMapper; - @Resource - private StringRedisTemplate stringRedisTemplate; - @Resource - private ExamQuestionMapper examQuestionMapper; - @Resource - private EducationPaperMapper educationPaperMapper; - @Resource - private EducationPaperPersonMapper educationPaperPersonMapper; - @Resource - private EducationPaperTaskMapper educationPaperTaskMapper; - @Resource - private EducationPaperParamMapper educationPaperParamMapper; - @Resource - private EducationPaperSessionMapper educationPaperSessionMapper; - @Resource - private EducationPaperSchemeMapper educationPaperSchemeMapper; - @Resource - private ExamSpecialtyMapper examSpecialtyMapper; + @Autowired + private RedisTemplate redisTemplate; + @Resource + private MonitorMapper monitorMapper; + @Resource + private StringRedisTemplate stringRedisTemplate; + @Resource + private ExamQuestionMapper examQuestionMapper; + @Resource + private EducationPaperMapper educationPaperMapper; + @Resource + private EducationPaperPersonMapper educationPaperPersonMapper; + @Resource + private EducationPaperTaskMapper educationPaperTaskMapper; + @Resource + private EducationPaperParamMapper educationPaperParamMapper; + @Resource + private EducationPaperSessionMapper educationPaperSessionMapper; + @Resource + private EducationPaperSchemeMapper educationPaperSchemeMapper; + @Resource + private ExamSpecialtyMapper examSpecialtyMapper; -// @Resource + // @Resource // private FileService fileService; - @Override - public String createMonitor(MonitorSaveReqVO createReqVO) { + @Override + public String createMonitor(MonitorSaveReqVO createReqVO) { // 插入 MonitorDO monitor = BeanUtils.toBean(createReqVO, MonitorDO.class); monitorMapper.insert(monitor); // 返回 return monitor.getMonitorId(); - } + } - @Override - public void updateMonitor(MonitorSaveReqVO updateReqVO) { + @Override + public void updateMonitor(MonitorSaveReqVO updateReqVO) { // 校验存在 validateMonitorExists(updateReqVO.getMonitorId()); // 更新 MonitorDO updateObj = BeanUtils.toBean(updateReqVO, MonitorDO.class); monitorMapper.updateById(updateObj); - } + } - @Override - public void deleteMonitor(String id) { + @Override + public void deleteMonitor(String id) { // 校验存在 validateMonitorExists(id); // 删除 monitorMapper.deleteById(id); - } + } - private void validateMonitorExists(String id) { + private void validateMonitorExists(String id) { if (monitorMapper.selectById(id) == null) { - throw exception(MONITOR_NOT_EXISTS); - } + throw exception(MONITOR_NOT_EXISTS); } + } - @Override - public MonitorDO getMonitor(String id) { + @Override + public MonitorDO getMonitor(String id) { return monitorMapper.selectById(id); - } + } - @Override - public PageResult getMonitorPage(MonitorPageReqVO pageReqVO) { + @Override + public PageResult getMonitorPage(MonitorPageReqVO pageReqVO) { return monitorMapper.selectPage(pageReqVO); + } + + @Override + public long getStuMonitor(StuMonitorPaperVo stuMonitorPaperVo) throws RuntimeException { + String key = "userCache:" + stuMonitorPaperVo.getTaskId() + ":" + stuMonitorPaperVo.getStuId(); + MonitorDO info = JsonUtils.parseObject(stringRedisTemplate.opsForValue().get(key), MonitorDO.class); + if (info == null) { + return 0L; } - @Override - public long getStuMonitor(StuMonitorPaperVo stuMonitorPaperVo) throws RuntimeException { - String key = "userCache:"+stuMonitorPaperVo.getTaskId()+":" + stuMonitorPaperVo.getStuId(); - MonitorDO info = JsonUtils.parseObject(stringRedisTemplate.opsForValue().get(key),MonitorDO.class); - if (info==null){ - return 0L; - } - //获取属性 判断 专业/课程点位 - Long loginTenantId = SecurityFrameworkUtils.getLoginTenantId(); + //获取属性 判断 专业/课程点位 + Long loginTenantId = SecurityFrameworkUtils.getLoginTenantId(); - if (!"1".equals(String.valueOf(loginTenantId))) { - // 查询授权课程/专业列表 - List tentSpecialyList = monitorMapper.selectTent(loginTenantId); - List tentSpecialies = filterSpecialtyList(tentSpecialyList); + if (!"1".equals(String.valueOf(loginTenantId))) { + // 查询授权课程/专业列表 + List tentSpecialyList = monitorMapper.selectTent(loginTenantId); + List tentSpecialies = filterSpecialtyList(tentSpecialyList); - if (tentSpecialies.isEmpty()) { - throw new MonitorSpecialtyException("授权课程的点位为空,请增加课程点位!"); - } + if (tentSpecialies.isEmpty()) { + throw new MonitorSpecialtyException("授权课程的点位为空,请增加课程点位!"); + } - // 构建授权数量映射:specialtyId -> 授权个数 - Map authMap = tentSpecialies.stream() - .collect(Collectors.toMap( - TentSpecialy::getSpecialtyId, - t -> { - try { - return Integer.parseInt(t.getPoints()); - } catch (Exception e) { - return 0; - } + // 构建授权数量映射:specialtyId -> 授权个数 + Map authMap = tentSpecialies.stream() + .collect(Collectors.toMap( + TentSpecialy::getSpecialtyId, + t -> { + try { + return Integer.parseInt(t.getPoints()); + } catch (Exception e) { + return 0; } - )); + } + )); - // 查询 exam_specialty 所有 sp_id -> parent_id 映射(用来判断是否为专业) - List pairList = examSpecialtyMapper.selectAllIdToParent(loginTenantId); + // 查询 exam_specialty 所有 sp_id -> parent_id 映射(用来判断是否为专业) + List pairList = examSpecialtyMapper.selectAllIdToParent(loginTenantId); - // 转换为 Map - Map idToParentMap = pairList.stream() - .collect(Collectors.toMap( - p -> String.valueOf(p.getSpId()), - p -> p.getParentId() == null ? null : String.valueOf(p.getParentId()) - )); + // 转换为 Map + Map idToParentMap = pairList.stream() + .collect(Collectors.toMap( + p -> String.valueOf(p.getSpId()), + p -> p.getParentId() == null ? null : String.valueOf(p.getParentId()) + )); - // 分类授权:哪些是专业,哪些是课程 - Set authSpecialtyIds = new HashSet<>(); - Set authCourseIds = new HashSet<>(); - for (TentSpecialy t : tentSpecialies) { - String specialtyId = t.getSpecialtyId(); - String parentId = idToParentMap.get(specialtyId); - if (parentId == null || "0".equals(parentId)) { - authSpecialtyIds.add(specialtyId); // 是专业 - } else { - authCourseIds.add(specialtyId); // 是课程 - } - } - - - - // 只有授权了“专业”,才去查 taskInVo 并校验 - if (!authSpecialtyIds.isEmpty()) { - //查询 该试卷任务 设计的 专业 - List taskInVo = educationPaperTaskMapper.selectTaskCounts(stuMonitorPaperVo.getTaskId(),loginTenantId); - - for (SpecialtyVo specialtyVo : taskInVo) { - String specialtyId = specialtyVo.getSpecialtyId(); - if (!authSpecialtyIds.contains(specialtyId)) continue; - - String specialtyName = specialtyVo.getSpecialtyName(); - Integer currentCount = specialtyVo.getCounts(); - Integer authCount = authMap.getOrDefault(specialtyId, 0); - - if (currentCount > authCount) { - int over = currentCount - authCount; - throw new MonitorSpecialtyException("专业: " + specialtyName + " 正在考试数量(" + currentCount + ") 授权数量(" + authCount + "),超出:" + over); - } - } - } - - // 只有授权了“课程”,才去查 courseInVos 并校验 - if (!authCourseIds.isEmpty()) { - //查询所有正在考试的 试卷id - List allInPaperIds = educationPaperMapper.selectSpecilayCounts(loginTenantId); - // 所有正在考试的试卷中授权课程的统计信息 - List courseInVos = educationPaperTaskMapper.selectPaperCounts(allInPaperIds, loginTenantId); - - //获取当前学生正在考试的试卷 ID - String paperId = stuMonitorPaperVo.getPaperId(); - - //查询该试卷涉及的所有课程(课程ID + 名称) - List courseList = educationPaperTaskMapper.selectPaperCountBypaperId(paperId); - - //将 courseInVos 转为 Map,便于通过 courseId 查询次数 - Map courseCountMap = courseInVos.stream() - .collect(Collectors.toMap(CourseInVo::getCourseId, CourseInVo::getCounts, (a, b) -> b)); - - //校验当前试卷的每门课程是否超过授权限制 - for (CourseInVo course : courseList) { - String courseId = course.getCourseId(); - if (!authCourseIds.contains(courseId)) continue; - - String courseName = course.getCourseName(); - Integer currentCount = courseCountMap.getOrDefault(courseId, 0); - Integer authCount = authMap.getOrDefault(courseId, 0); - - if (currentCount > authCount) { - int over = currentCount - authCount; - throw new MonitorSpecialtyException("课程: " + courseName + " 正在考试数量(" + currentCount + ") 授权数量(" + authCount + "),超出:" + over); - } - } + // 分类授权:哪些是专业,哪些是课程 + Set authSpecialtyIds = new HashSet<>(); + Set authCourseIds = new HashSet<>(); + for (TentSpecialy t : tentSpecialies) { + String specialtyId = t.getSpecialtyId(); + String parentId = idToParentMap.get(specialtyId); + if (parentId == null || "0".equals(parentId)) { + authSpecialtyIds.add(specialtyId); // 是专业 + } else { + authCourseIds.add(specialtyId); // 是课程 } } - if (StringUtils.isNotBlank(stuMonitorPaperVo.getPaperId())){ - EducationPaper educationPaper = educationPaperMapper.selectEducationPaperByPaperId(stuMonitorPaperVo.getPaperId()); - String counts = educationPaper.getCounts(); - int count = 0; + // 只有授权了“专业”,才去查 taskInVo 并校验 + if (!authSpecialtyIds.isEmpty()) { + //查询 该试卷任务 设计的 专业 + List taskInVo = educationPaperTaskMapper.selectTaskCounts(stuMonitorPaperVo.getTaskId(), loginTenantId); - try { - count = Integer.parseInt(counts); - } catch (NumberFormatException | NullPointerException e) { - count = 0; // 默认从 0 开始 - } - count += 1; - educationPaper.setCounts(String.valueOf(count)); - educationPaperMapper.updateById(educationPaper); - info.setPaperNum(educationPaper.getNum()); + for (SpecialtyVo specialtyVo : taskInVo) { + String specialtyId = specialtyVo.getSpecialtyId(); + if (!authSpecialtyIds.contains(specialtyId)) continue; + + String specialtyName = specialtyVo.getSpecialtyName(); + Integer currentCount = specialtyVo.getCounts(); + Integer authCount = authMap.getOrDefault(specialtyId, 0); + + if (currentCount > authCount) { + int over = currentCount - authCount; + throw new MonitorSpecialtyException("专业: " + specialtyName + " 正在考试数量(" + currentCount + ") 授权数量(" + authCount + "),超出:" + over); + } } + } - info.setExamStatus("1"); + // 只有授权了“课程”,才去查 courseInVos 并校验 + if (!authCourseIds.isEmpty()) { + //查询所有正在考试的 试卷id + List allInPaperIds = educationPaperMapper.selectSpecilayCounts(loginTenantId); + // 所有正在考试的试卷中授权课程的统计信息 + List courseInVos = educationPaperTaskMapper.selectPaperCounts(allInPaperIds, loginTenantId); - info.setIp(stuMonitorPaperVo.getIp()); + //获取当前学生正在考试的试卷 ID + String paperId = stuMonitorPaperVo.getPaperId(); - if (info.getRemainingTime()==null){ - stringRedisTemplate.opsForValue().set("userCache:"+stuMonitorPaperVo.getTaskId()+":"+stuMonitorPaperVo.getStuId(), JsonUtils.toJsonString(info)); - monitorMapper.updateById(info); - return 24 * 60 * 60L; // (1天) - }else { - EducationPaperParam educationPaperParam = educationPaperParamMapper.selectEducationPaperParamByTaskId(stuMonitorPaperVo.getTaskId()); - //测评时长 - Time examTime = educationPaperParam.getExamTime(); + //查询该试卷涉及的所有课程(课程ID + 名称) + List courseList = educationPaperTaskMapper.selectPaperCountBypaperId(paperId); - //判断是否开启测评时长限制 - //开启测评时长限制 开启场次 判断场次时间 ,,,,没开启测评时长限制 开启场次 -判断场次时间 - if ("0".equals(educationPaperParam.getIsSession())){ - //获得场次开始时间, 结束时间 判断是否在 时间范围内 + //将 courseInVos 转为 Map,便于通过 courseId 查询次数 + Map courseCountMap = courseInVos.stream() + .collect(Collectors.toMap(CourseInVo::getCourseId, CourseInVo::getCounts, (a, b) -> b)); - EducationPaperPerson educationPaperPerson = educationPaperPersonMapper.selectByTaskIdAndPersonId(stuMonitorPaperVo.getTaskId(), stuMonitorPaperVo.getStuId()); - EducationPaperSession educationPaperSession = educationPaperSessionMapper.selectEducationPaperSessionBySessionId(educationPaperPerson.getSessionId()); + //校验当前试卷的每门课程是否超过授权限制 + for (CourseInVo course : courseList) { + String courseId = course.getCourseId(); + if (!authCourseIds.contains(courseId)) continue; - if (educationPaperSession == null) { - throw new MonitorSpecialtyException("未分配考场,请练习教师!"); - } - //结束时间 - Date endTime = educationPaperSession.getEndTime(); - //开始时间 - Date startTime = educationPaperSession.getStartTime(); - //开始考试前分钟,允许入场 - String allowEntry = educationPaperSession.getAllowEntry(); - //开始考试后分钟,禁止入场 - String endAllowEntry = educationPaperSession.getEndAllowEntry(); + String courseName = course.getCourseName(); + Integer currentCount = courseCountMap.getOrDefault(courseId, 0); + Integer authCount = authMap.getOrDefault(courseId, 0); - LocalDateTime now = LocalDateTime.now(); - LocalDateTime start = DateUtil.toLocalDateTime(startTime); - LocalDateTime end = DateUtil.toLocalDateTime(endTime); - - // 考试开始前允许入场时间(分钟) - int allowEntryMin = Integer.parseInt(allowEntry); - - // 考试开始后允许入场时间(分钟) - int endAllowEntryMin = Integer.parseInt(endAllowEntry); - - // 入场允许范围: [start-allowEntryMin , end + endAllowEntryMin] - LocalDateTime entryStart = start.minusMinutes(allowEntryMin); - LocalDateTime entryEnd = end.plusMinutes(endAllowEntryMin); - //包含边界值 - boolean isWithinEntryTime = !now.isBefore(entryStart) && !now.isAfter(entryEnd); - System.out.println("是否在允许入场时间段内:" + isWithinEntryTime); - - if (isWithinEntryTime){ - // 1. 计算剩余时间(秒) - long remainingSeconds = ChronoUnit.SECONDS.between(LocalDateTime.now(), DateUtil.toLocalDateTime(endTime)); - remainingSeconds = Math.max(remainingSeconds, 0); // 防止负数 - - // 2. 获取测评时长(examTime 是 java.sql.Time)并转换为秒 - long examDurationSeconds = examTime.toLocalTime().toSecondOfDay(); // 将 HH:mm:ss 转为秒数 - - // 3. 规则判断:如果 remainingSeconds > examTime,则限制最大值为 examTime - long finalRemaining = Math.min(remainingSeconds, examDurationSeconds); - - // 4. 设置和返回 - info.setRemainingTime(finalRemaining); - - // 判分后更新记录 - monitorMapper.updateById(info); - return finalRemaining; - }else { - return 0; - } - } - - //开启测评时长限制 没开启场次 -直接返回测评时长 - - if ("1".equals(educationPaperParam.getIsSession())&&"0".equals(educationPaperParam.getIsTime())){ - - info.setRemainingTime((long) examTime.toLocalTime().toSecondOfDay()); - stringRedisTemplate.opsForValue().set("userCache:"+stuMonitorPaperVo.getTaskId()+":"+stuMonitorPaperVo.getStuId(), JsonUtils.toJsonString(info)); - monitorMapper.updateById(info); - - return (long) examTime.toLocalTime().toSecondOfDay(); - - } - - return 0L; + if (currentCount > authCount) { + int over = currentCount - authCount; + throw new MonitorSpecialtyException("课程: " + courseName + " 正在考试数量(" + currentCount + ") 授权数量(" + authCount + "),超出:" + over); + } } - + } } - @Override - public Boolean updateStuMonitor(StuMonitorQuVo stuMonitorQuVo) { - String key = "userCache:"+stuMonitorQuVo.getTaskId()+":" + stuMonitorQuVo.getStuId(); - String keychoice = "keychoice:"+stuMonitorQuVo.getTaskId()+":" + stuMonitorQuVo.getStuId(); - MonitorDO info = JsonUtils.parseObject(stringRedisTemplate.opsForValue().get(key),MonitorDO.class); + if (StringUtils.isNotBlank(stuMonitorPaperVo.getPaperId())) { + EducationPaper educationPaper = educationPaperMapper.selectEducationPaperByPaperId(stuMonitorPaperVo.getPaperId()); + String counts = educationPaper.getCounts(); + int count = 0; - - if (info != null) { - if (!("1".equals(info.getExamStatus()))){ - return false; - } - stringRedisTemplate.opsForValue().set(keychoice, JsonUtils.toJsonString(stuMonitorQuVo)); - // 更新缓存 -// redisTemplate.opsForValue().set(key, info); -// monitorMapper.updateById(info); - } - return true; - + try { + count = Integer.parseInt(counts); + } catch (NumberFormatException | NullPointerException e) { + count = 0; // 默认从 0 开始 + } + count += 1; + educationPaper.setCounts(String.valueOf(count)); + educationPaperMapper.updateById(educationPaper); + info.setPaperNum(educationPaper.getNum()); } - @Override - public void endStuMonitor(StuMonitorPaperEndVo stuMonitorPaperEndVo) { - EducationPaper educationPaper = educationPaperMapper.selectEducationPaperByPaperId(stuMonitorPaperEndVo.getPaperId()); - String taskId = educationPaper.getTaskId(); - String key = "userCache:" + taskId + ":" + stuMonitorPaperEndVo.getStuId(); - double score =educationPaperMapper.selctStuScoreByStuIdAndPaperId(stuMonitorPaperEndVo.getStuId(),stuMonitorPaperEndVo.getPaperId()); - MonitorDO info = JsonUtils.parseObject(stringRedisTemplate.opsForValue().get(key),MonitorDO.class); - info.setRemainingTime(0L); - EducationPaperParam educationPaperParam = educationPaperParamMapper.selectEducationPaperParamByTaskId(taskId); - EducationPaperTask educationPaperTask = educationPaperTaskMapper.selectEducationPaperTaskByTaskId(taskId); - if ("1".equals(educationPaperParam.getSaveGrades())){ - info.setScore(String.valueOf(score)); - }else { - MonitorDO monitorDO = monitorMapper.selectById(info.getMonitorId()); - info.setScore(String.valueOf(score)); - if (StringUtils.isNotBlank(monitorDO.getScore())) { - try { - double oldScore = Double.parseDouble(monitorDO.getScore()); - if (score > oldScore) { - info.setScore(String.valueOf(score)); - } else { - info.setScore(monitorDO.getScore()); // 保留旧成绩 - } - } catch (NumberFormatException e) { - // 如果旧分数格式错误,则直接设置新分数 - info.setScore(String.valueOf(score)); - } - } else { - // 如果没有旧成绩,则直接设置 - info.setScore(String.valueOf(score)); - } + info.setExamStatus("1"); + info.setIp(stuMonitorPaperVo.getIp()); + if (info.getRemainingTime() == null) { + stringRedisTemplate.opsForValue().set("userCache:" + stuMonitorPaperVo.getTaskId() + ":" + stuMonitorPaperVo.getStuId(), JsonUtils.toJsonString(info)); + monitorMapper.updateById(info); + return 24 * 60 * 60L; // (1天) + } else { + EducationPaperParam educationPaperParam = educationPaperParamMapper.selectEducationPaperParamByTaskId(stuMonitorPaperVo.getTaskId()); + //测评时长 + Time examTime = educationPaperParam.getExamTime(); + //判断是否开启测评时长限制 + //开启测评时长限制 开启场次 判断场次时间 ,,,,没开启测评时长限制 开启场次 -判断场次时间 + if ("0".equals(educationPaperParam.getIsSession())) { + //获得场次开始时间, 结束时间 判断是否在 时间范围内 + + EducationPaperPerson educationPaperPerson = educationPaperPersonMapper.selectByTaskIdAndPersonId(stuMonitorPaperVo.getTaskId(), stuMonitorPaperVo.getStuId()); + EducationPaperSession educationPaperSession = educationPaperSessionMapper.selectEducationPaperSessionBySessionId(educationPaperPerson.getSessionId()); + + if (educationPaperSession == null) { + throw new MonitorSpecialtyException("未分配考场,请练习教师!"); } - //考试下的任务 结束改为 结束 其他为待考 - if ("1".equals(educationPaperTask.getTaskType())){ - info.setExamStatus("2"); - redisTemplate.delete(key); + //结束时间 + Date endTime = educationPaperSession.getEndTime(); + //开始时间 + Date startTime = educationPaperSession.getStartTime(); + //开始考试前分钟,允许入场 + String allowEntry = educationPaperSession.getAllowEntry(); + //开始考试后分钟,禁止入场 + String endAllowEntry = educationPaperSession.getEndAllowEntry(); - }else { - info.setExamStatus("0"); - stringRedisTemplate.opsForValue().set(key, JsonUtils.toJsonString(info)); + LocalDateTime now = LocalDateTime.now(); + LocalDateTime start = DateUtil.toLocalDateTime(startTime); + LocalDateTime end = DateUtil.toLocalDateTime(endTime); + + // 考试开始前允许入场时间(分钟) + int allowEntryMin = Integer.parseInt(allowEntry); + + // 考试开始后允许入场时间(分钟) + int endAllowEntryMin = Integer.parseInt(endAllowEntry); + + // 入场允许范围: [start-allowEntryMin , end + endAllowEntryMin] + LocalDateTime entryStart = start.minusMinutes(allowEntryMin); + LocalDateTime entryEnd = end.plusMinutes(endAllowEntryMin); + //包含边界值 + boolean isWithinEntryTime = !now.isBefore(entryStart) && !now.isAfter(entryEnd); + System.out.println("是否在允许入场时间段内:" + isWithinEntryTime); + + if (isWithinEntryTime) { + // 1. 计算剩余时间(秒) + long remainingSeconds = ChronoUnit.SECONDS.between(LocalDateTime.now(), DateUtil.toLocalDateTime(endTime)); + remainingSeconds = Math.max(remainingSeconds, 0); // 防止负数 + + // 2. 获取测评时长(examTime 是 java.sql.Time)并转换为秒 + long examDurationSeconds = examTime.toLocalTime().toSecondOfDay(); // 将 HH:mm:ss 转为秒数 + + // 3. 规则判断:如果 remainingSeconds > examTime,则限制最大值为 examTime + long finalRemaining = Math.min(remainingSeconds, examDurationSeconds); + + // 4. 设置和返回 + info.setRemainingTime(finalRemaining); + + // 判分后更新记录 + monitorMapper.updateById(info); + return finalRemaining; + } else { + return 0; } + } + //开启测评时长限制 没开启场次 -直接返回测评时长 + + if ("1".equals(educationPaperParam.getIsSession()) && "0".equals(educationPaperParam.getIsTime())) { + + info.setRemainingTime((long) examTime.toLocalTime().toSecondOfDay()); + stringRedisTemplate.opsForValue().set("userCache:" + stuMonitorPaperVo.getTaskId() + ":" + stuMonitorPaperVo.getStuId(), JsonUtils.toJsonString(info)); monitorMapper.updateById(info); + return (long) examTime.toLocalTime().toSecondOfDay(); + + } + + return 0L; } - @Override - public List getPaperTaskList(String id) { - return educationPaperTaskMapper.selectEducationPaperTaskByTaskType(id); + } + + @Override + public Boolean updateStuMonitor(StuMonitorQuVo stuMonitorQuVo) { + String key = "userCache:" + stuMonitorQuVo.getTaskId() + ":" + stuMonitorQuVo.getStuId(); + String keychoice = "keychoice:" + stuMonitorQuVo.getTaskId() + ":" + stuMonitorQuVo.getStuId(); + MonitorDO info = JsonUtils.parseObject(stringRedisTemplate.opsForValue().get(key), MonitorDO.class); + + + if (info != null) { + if (!("1".equals(info.getExamStatus()))) { + return false; + } + stringRedisTemplate.opsForValue().set(keychoice, JsonUtils.toJsonString(stuMonitorQuVo)); + // 更新缓存 +// redisTemplate.opsForValue().set(key, info); +// monitorMapper.updateById(info); + } + return true; + + } + + @Override + public void endStuMonitor(StuMonitorPaperEndVo stuMonitorPaperEndVo) { + EducationPaper educationPaper = educationPaperMapper.selectEducationPaperByPaperId(stuMonitorPaperEndVo.getPaperId()); + String taskId = educationPaper.getTaskId(); + String key = "userCache:" + taskId + ":" + stuMonitorPaperEndVo.getStuId(); + double score = educationPaperMapper.selctStuScoreByStuIdAndPaperId(stuMonitorPaperEndVo.getStuId(), stuMonitorPaperEndVo.getPaperId()); + MonitorDO info = JsonUtils.parseObject(stringRedisTemplate.opsForValue().get(key), MonitorDO.class); + info.setRemainingTime(0L); + EducationPaperParam educationPaperParam = educationPaperParamMapper.selectEducationPaperParamByTaskId(taskId); + EducationPaperTask educationPaperTask = educationPaperTaskMapper.selectEducationPaperTaskByTaskId(taskId); + if ("1".equals(educationPaperParam.getSaveGrades())) { + info.setScore(String.valueOf(score)); + } else { + MonitorDO monitorDO = monitorMapper.selectById(info.getMonitorId()); + info.setScore(String.valueOf(score)); + if (StringUtils.isNotBlank(monitorDO.getScore())) { + try { + double oldScore = Double.parseDouble(monitorDO.getScore()); + if (score > oldScore) { + info.setScore(String.valueOf(score)); + } else { + info.setScore(monitorDO.getScore()); // 保留旧成绩 + } + } catch (NumberFormatException e) { + // 如果旧分数格式错误,则直接设置新分数 + info.setScore(String.valueOf(score)); + } + } else { + // 如果没有旧成绩,则直接设置 + info.setScore(String.valueOf(score)); + } + + + } + //考试下的任务 结束改为 结束 其他为待考 + if ("1".equals(educationPaperTask.getTaskType())) { + info.setExamStatus("2"); + redisTemplate.delete(key); + + } else { + info.setExamStatus("0"); + stringRedisTemplate.opsForValue().set(key, JsonUtils.toJsonString(info)); } - @Override - public Boolean updateMonitorStatus(StuMonitorStatusVo stuMonitorStatusVo) { - String status = stuMonitorStatusVo.getStatus(); - List monitorIds = stuMonitorStatusVo.getMonitorIds(); - if ("1".equals(status)||"0".equals(status)){ - //新增或更新 - for (String monitorId : monitorIds) { - MonitorDO monitorDO = monitorMapper.selectById(monitorId); - String taskId = monitorDO.getTaskId(); - String stuId = monitorDO.getStuId(); - String key = "userCache:" + taskId+":" +stuId; - monitorDO.setExamStatus(status); - monitorMapper.updateById(monitorDO); - MonitorDO info = JsonUtils.parseObject(stringRedisTemplate.opsForValue().get(key),MonitorDO.class); - EducationPaperParam educationPaperParam = educationPaperParamMapper.selectEducationPaperParamByTaskId(taskId); - Time examTime = educationPaperParam.getExamTime(); + monitorMapper.updateById(info); - if (info==null){ - MonitorDO monitorDO1 = monitorMapper.selectOne( - new QueryWrapper() - .eq("stu_id", stuId) - .eq("task_id", taskId) - ); - PersonRepDto personRepDto = educationPaperPersonMapper.selectUserById(stuId); - String name= educationPaperTaskMapper.selectEducationPaperTaskNameByid(taskId); - EducationPaperTask educationPaperTask = educationPaperTaskMapper.selectEducationPaperTaskByTaskId(taskId); - monitorDO1.setScore("0"); - monitorDO1.setTaskId(taskId); - monitorDO1.setTaskType(educationPaperTask.getTaskType()); - monitorDO1.setExamStatus(status); - monitorDO1.setPaperNum(""); - monitorDO1.setIp(""); - monitorDO1.setStuId(stuId); - monitorDO1.setUsername(personRepDto.getUsername()); - monitorDO1.setNickname(personRepDto.getNickname()); + } - //如果开启了 时长限制 或者考场 - if ("0".equals(educationPaperParam.getIsTime())||"0".equals(educationPaperParam.getIsSession())){ - monitorDO1.setRemainingTime((long) examTime.toLocalTime().toSecondOfDay()); - } - stringRedisTemplate.opsForValue().set(key, JsonUtils.toJsonString(monitorDO1)); - monitorMapper.updateById(monitorDO1); - }else { - //如果开启了 时长限制 或者考场 - if ("0".equals(educationPaperParam.getIsTime())||"0".equals(educationPaperParam.getIsSession())){ - info.setRemainingTime((long) examTime.toLocalTime().toSecondOfDay()); - } - info.setScore("0"); - info.setPaperNum(""); - info.setIp(""); - info.setExamStatus(status); - stringRedisTemplate.opsForValue().set(key, JsonUtils.toJsonString(info)); - } + @Override + public List getPaperTaskList(String id) { + return educationPaperTaskMapper.selectEducationPaperTaskByTaskType(id); + } + @Override + public Boolean updateMonitorStatus(StuMonitorStatusVo stuMonitorStatusVo) { + String status = stuMonitorStatusVo.getStatus(); + List monitorIds = stuMonitorStatusVo.getMonitorIds(); + if ("1".equals(status) || "0".equals(status)) { + //新增或更新 + for (String monitorId : monitorIds) { + MonitorDO monitorDO = monitorMapper.selectById(monitorId); + String taskId = monitorDO.getTaskId(); + String stuId = monitorDO.getStuId(); + String key = "userCache:" + taskId + ":" + stuId; + monitorDO.setExamStatus(status); + monitorMapper.updateById(monitorDO); + MonitorDO info = JsonUtils.parseObject(stringRedisTemplate.opsForValue().get(key), MonitorDO.class); + EducationPaperParam educationPaperParam = educationPaperParamMapper.selectEducationPaperParamByTaskId(taskId); + Time examTime = educationPaperParam.getExamTime(); + if (info == null) { + MonitorDO monitorDO1 = monitorMapper.selectOne( + new QueryWrapper() + .eq("stu_id", stuId) + .eq("task_id", taskId) + ); + PersonRepDto personRepDto = educationPaperPersonMapper.selectUserById(stuId); + String name = educationPaperTaskMapper.selectEducationPaperTaskNameByid(taskId); + EducationPaperTask educationPaperTask = educationPaperTaskMapper.selectEducationPaperTaskByTaskId(taskId); + monitorDO1.setScore("0"); + monitorDO1.setTaskId(taskId); + monitorDO1.setTaskType(educationPaperTask.getTaskType()); + monitorDO1.setExamStatus(status); + monitorDO1.setPaperNum(""); + monitorDO1.setIp(""); + monitorDO1.setStuId(stuId); + monitorDO1.setUsername(personRepDto.getUsername()); + monitorDO1.setNickname(personRepDto.getNickname()); - - } - + //如果开启了 时长限制 或者考场 + if ("0".equals(educationPaperParam.getIsTime()) || "0".equals(educationPaperParam.getIsSession())) { + monitorDO1.setRemainingTime((long) examTime.toLocalTime().toSecondOfDay()); + } + stringRedisTemplate.opsForValue().set(key, JsonUtils.toJsonString(monitorDO1)); + monitorMapper.updateById(monitorDO1); + } else { + //如果开启了 时长限制 或者考场 + if ("0".equals(educationPaperParam.getIsTime()) || "0".equals(educationPaperParam.getIsSession())) { + info.setRemainingTime((long) examTime.toLocalTime().toSecondOfDay()); + } + info.setScore("0"); + info.setPaperNum(""); + info.setIp(""); + info.setExamStatus(status); + stringRedisTemplate.opsForValue().set(key, JsonUtils.toJsonString(info)); } - if ("2".equals(status)){ - //删除 - for (String monitorId : monitorIds) { - MonitorDO monitorDO = monitorMapper.selectById(monitorId); - String taskId = monitorDO.getTaskId(); - String stuId = monitorDO.getStuId(); - String key = "userCache:" + taskId+":" +stuId; - monitorDO.setRemainingTime(0L); - if ("0".equals(monitorDO.getTaskType())){ - monitorDO.setExamStatus("0"); - stringRedisTemplate.opsForValue().set(key, JsonUtils.toJsonString(monitorDO)); - }else { - monitorDO.setExamStatus(status); - redisTemplate.delete(key); - } - - monitorMapper.updateById(monitorDO); - - - - } - } - - return true; + } } - public List filterSpecialtyList(List inputList) { - if (inputList == null || inputList.isEmpty()) { - return Collections.emptyList(); + + if ("2".equals(status)) { + //删除 + for (String monitorId : monitorIds) { + MonitorDO monitorDO = monitorMapper.selectById(monitorId); + String taskId = monitorDO.getTaskId(); + String stuId = monitorDO.getStuId(); + String key = "userCache:" + taskId + ":" + stuId; + monitorDO.setRemainingTime(0L); + if ("0".equals(monitorDO.getTaskType())) { + monitorDO.setExamStatus("0"); + stringRedisTemplate.opsForValue().set(key, JsonUtils.toJsonString(monitorDO)); + + } else { + monitorDO.setExamStatus(status); + redisTemplate.delete(key); } - // 构建传入列表中的 specialtyId Set(这些是传进来的 ID) - Set inputSpecialtyIds = inputList.stream() - .map(TentSpecialy::getSpecialtyId) - .collect(Collectors.toSet()); + monitorMapper.updateById(monitorDO); - // 查询所有课程 -> 专业 的关系 - List allRelations = examSpecialtyMapper.selectAllSpecialtyRelations(); - // 构建课程ID -> 父专业ID 的映射 - Map courseToParentMap = allRelations.stream() - .filter(r -> r.getParentId() != null) - .collect(Collectors.toMap(SpecialtyRelation::getSpId, SpecialtyRelation::getParentId)); - - // 开始过滤:只保留以下情况之一 - return inputList.stream() - .filter(item -> { - String specialtyId = item.getSpecialtyId(); - String parentId = courseToParentMap.get(specialtyId); - // 1. 如果这个是专业(它不是任何课程的 sp_id) → 保留 - if (parentId == null) return true; - // 2. 如果它是课程,但父级不在输入列表中 → 保留 - return !inputSpecialtyIds.contains(parentId); - }) - .collect(Collectors.toList()); + } } + return true; + } + + public List filterSpecialtyList(List inputList) { + if (inputList == null || inputList.isEmpty()) { + return Collections.emptyList(); + } + + // 构建传入列表中的 specialtyId Set(这些是传进来的 ID) + Set inputSpecialtyIds = inputList.stream() + .map(TentSpecialy::getSpecialtyId) + .collect(Collectors.toSet()); + + // 查询所有课程 -> 专业 的关系 + List allRelations = examSpecialtyMapper.selectAllSpecialtyRelations(); + + // 构建课程ID -> 父专业ID 的映射 + Map courseToParentMap = allRelations.stream() + .filter(r -> r.getParentId() != null) + .collect(Collectors.toMap(SpecialtyRelation::getSpId, SpecialtyRelation::getParentId)); + + // 开始过滤:只保留以下情况之一 + return inputList.stream() + .filter(item -> { + String specialtyId = item.getSpecialtyId(); + String parentId = courseToParentMap.get(specialtyId); + // 1. 如果这个是专业(它不是任何课程的 sp_id) → 保留 + if (parentId == null) return true; + // 2. 如果它是课程,但父级不在输入列表中 → 保留 + return !inputSpecialtyIds.contains(parentId); + }) + .collect(Collectors.toList()); + } } diff --git a/exam-module-exam/exam-module-exam-biz/src/main/resources/mapper/specialty/ExamSpecialtyMapper.xml b/exam-module-exam/exam-module-exam-biz/src/main/resources/mapper/specialty/ExamSpecialtyMapper.xml index 34290364..9b993190 100644 --- a/exam-module-exam/exam-module-exam-biz/src/main/resources/mapper/specialty/ExamSpecialtyMapper.xml +++ b/exam-module-exam/exam-module-exam-biz/src/main/resources/mapper/specialty/ExamSpecialtyMapper.xml @@ -126,7 +126,7 @@