wangliang 4 éve
szülő
commit
02aba0b42e

+ 1 - 1
themis-backend/src/main/java/com/qmth/themis/backend/api/TIeInvigilateController.java

@@ -531,7 +531,7 @@ public class TIeInvigilateController {
                 Calendar calendar = Calendar.getInstance();
                 if (Objects.nonNull(finalMaxDurationSeconds)) {
                     calendar.setTime(startTime);
-                    calendar.add(Calendar.SECOND, activityMaxDurationSeconds.intValue());
+                    calendar.add(Calendar.SECOND, finalMaxDurationSeconds.intValue());
                 }
 //                Date now = new Date();
 //                if (now.getTime() >= calendar.getTime().getTime() && now.getTime() <= finishTime.getTime()) {

+ 2 - 1
themis-business/src/main/java/com/qmth/themis/business/enums/MqTagEnum.java

@@ -43,7 +43,8 @@ public enum MqTagEnum {
     EXAM_STUDNET_UPDATE("考生数据更新标签", "考生数据更新", "normal", 31),
     EXAM_BREAK("考试断点标签", "考试断点", "normal", 32),
     EXAM_STOP("考试移动端监控退出标签", "考试移动端退出暂停", "normal", 33),
-    EXAM_RECORD_UPDATE_COLUMNS("考试记录多字段数据更新标签", "考试记录多字段数据更新", "normal", 34);
+    EXAM_RECORD_UPDATE_COLUMNS("考试记录多字段数据更新标签", "考试记录多字段数据更新", "normal", 34),
+    EXAM_STUDENT("考生一次性延时任务标签", "考生一次性延时任务", "normal", 35);
 
     private MqTagEnum(String desc, String code, String type, int id) {
         this.desc = desc;

+ 12 - 7
themis-business/src/main/java/com/qmth/themis/business/service/impl/TEExamServiceImpl.java

@@ -459,19 +459,24 @@ public class TEExamServiceImpl extends ServiceImpl<TEExamMapper, TEExam> impleme
         if (Objects.nonNull(exam.getForceFinish()) && exam.getForceFinish().intValue() == 0) {
             Date date = ExamRecordCacheUtil.getExamFinalFinishTime(recordId);
             if (Objects.isNull(date)) {
-                Date finalFinishTime = Objects.nonNull(ac.getFinishTime()) ? ac.getFinishTime() : exam.getEndTime();
+                Date startTime = ExamRecordCacheUtil.getStartTime(recordId);
+                Integer activityMaxDurationSeconds = Objects.nonNull(ac.getMaxDurationSeconds()) ? ac.getMaxDurationSeconds() : null;
+                Integer maxDurationSeconds = Objects.nonNull(exam.getMaxDurationSeconds()) ? exam.getMaxDurationSeconds() : null;
+                Integer finalMaxDurationSeconds = Objects.nonNull(activityMaxDurationSeconds) ? activityMaxDurationSeconds : maxDurationSeconds;
+                Calendar calendar = Calendar.getInstance();
+                if (Objects.nonNull(finalMaxDurationSeconds)) {
+                    calendar.setTime(startTime);
+                    calendar.add(Calendar.SECOND, finalMaxDurationSeconds.intValue());
+                }
                 Integer breakResumeCount = exam.getBreakResumeCount();
-                Long l = (finalFinishTime.getTime() / 1000 + (breakResumeCount * breakExpireSeconds) + (breakResumeCount * 180)) * 1000;
-                finalFinishTime.setTime(l);
+                Long l = (calendar.getTime().getTime() / 1000 + (breakResumeCount * breakExpireSeconds) + (breakResumeCount * 180)) * 1000;
+                Date finalFinishTime = new Date(l);
                 ExamRecordCacheUtil.setExamFinalFinishTime(recordId, finalFinishTime);
                 //新增quartz任务,发送mq消息start
                 Map<String, Object> prop = new HashMap<>();
                 prop.put("oper", "insert");
                 prop.put("exam", exam);
-                ExamActivityCacheBean examActivityCacheBean = new ExamActivityCacheBean();
-                BeanUtils.copyProperties(ac, examActivityCacheBean);
-                examActivityCacheBean.setFinishTime(finalFinishTime);
-                MqDto mqDto = new MqDto(MqTopicEnum.THEMIS_TOPIC.getCode(), MqTagEnum.EXAM_ACTIVITY.name(), JacksonUtil.parseJson(examActivityCacheBean), MqTagEnum.EXAM_ACTIVITY, String.valueOf(exam.getId()), prop, es.getName());
+                MqDto mqDto = new MqDto(MqTopicEnum.THEMIS_TOPIC.getCode(), MqTagEnum.EXAM_STUDENT.name(), JacksonUtil.parseJson(examStudentCacheBean), MqTagEnum.EXAM_STUDENT, String.valueOf(recordId), prop, es.getName());
                 mqDtoService.assembleSendOneWayMsg(mqDto);
                 //新增quartz任务,发送mq消息end
             }

+ 5 - 19
themis-exam/src/main/java/com/qmth/themis/exam/api/TEExamController.java

@@ -9,12 +9,14 @@ import com.qmth.themis.business.cache.ExamBreakCacheUtil;
 import com.qmth.themis.business.cache.ExamRecordCacheUtil;
 import com.qmth.themis.business.constant.SystemConstant;
 import com.qmth.themis.business.dto.MqDto;
-import com.qmth.themis.business.dto.WebsocketDto;
 import com.qmth.themis.business.dto.cache.TEStudentCacheDto;
 import com.qmth.themis.business.dto.response.TEExamDto;
 import com.qmth.themis.business.dto.response.TEExamResultDto;
 import com.qmth.themis.business.entity.TEExam;
-import com.qmth.themis.business.enums.*;
+import com.qmth.themis.business.enums.ExceptionEnum;
+import com.qmth.themis.business.enums.MqTagEnum;
+import com.qmth.themis.business.enums.MqTopicEnum;
+import com.qmth.themis.business.enums.SystemOperationEnum;
 import com.qmth.themis.business.service.MqDtoService;
 import com.qmth.themis.business.service.TEExamService;
 import com.qmth.themis.business.service.TEExamStudentService;
@@ -26,7 +28,6 @@ import com.qmth.themis.common.exception.BusinessException;
 import com.qmth.themis.common.util.Result;
 import com.qmth.themis.common.util.ResultUtil;
 import com.qmth.themis.exam.config.ExamConstant;
-import com.qmth.themis.exam.websocket.WebSocketMobileServer;
 import io.swagger.annotations.*;
 import org.springframework.web.bind.annotation.*;
 import org.springframework.web.multipart.MultipartFile;
@@ -36,7 +37,6 @@ import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.Objects;
-import java.util.concurrent.ConcurrentHashMap;
 
 @Api(tags = "考试Controller")
 @RestController
@@ -144,21 +144,7 @@ public class TEExamController {
                 teExamService.sendOeLogMessage(SystemOperationEnum.ANSWERING, ExamRecordCacheUtil.getExamStudentId(param.getRecordId()), param.getRecordId(), mqDto);
                 //mq发送消息end
             }
-            ConcurrentHashMap<String, WebSocketMobileServer> webSocketMap = WebSocketMobileServer.getWebSocketMap();
-            if (Objects.nonNull(webSocketMap.get(param.getRecordId() + "-" + MonitorVideoSourceEnum.MOBILE_FIRST.name()))) {
-                WebSocketMobileServer webSocketMobileServer = webSocketMap.get(param.getRecordId() + "-" + MonitorVideoSourceEnum.MOBILE_FIRST.name());
-                Map map = new HashMap<>();
-                map.put(SystemConstant.RECORD_ID, param.getRecordId());
-                WebsocketDto websocketDto = new WebsocketDto(WebsocketTypeEnum.EXAM_START.name(), map);
-                webSocketMobileServer.sendMessage(websocketDto);
-            }
-            if (Objects.nonNull(webSocketMap.get(param.getRecordId() + "-" + MonitorVideoSourceEnum.MOBILE_SECOND.name()))) {
-                WebSocketMobileServer webSocketMobileServer = webSocketMap.get(param.getRecordId() + "-" + MonitorVideoSourceEnum.MOBILE_SECOND.name());
-                Map map = new HashMap<>();
-                map.put(SystemConstant.RECORD_ID, param.getRecordId());
-                WebsocketDto websocketDto = new WebsocketDto(WebsocketTypeEnum.EXAM_START.name(), map);
-                webSocketMobileServer.sendMessage(websocketDto);
-            }
+            ExamConstant.sendExamStartMsg(param.getRecordId());
             return ResultUtil.ok(examStartBean);
         } finally {
             redisUtil.releaseLock(lockKey);

+ 1 - 0
themis-exam/src/main/java/com/qmth/themis/exam/api/TEStudentController.java

@@ -341,6 +341,7 @@ public class TEStudentController {
         ExamRecordCacheUtil.setMinDurationSeconds(recordId, ec.getMinDurationSeconds(), false);
         ExamRecordCacheUtil.setMaxDurationSeconds(recordId, examActivityCacheBean.getMaxDurationSeconds(), false);
         ExamRecordCacheUtil.setForceFinish(recordId, ec.getForceFinish(), false);
+        ExamRecordCacheUtil.setExamFinalFinishTime(recordId, null);
         String[] columns = new String[]{ExamRecordFieldEnum.start_time.name(), ExamRecordFieldEnum.end_time.name(), ExamRecordFieldEnum.opening_seconds.name(), ExamRecordFieldEnum.min_duration_seconds.name(), ExamRecordFieldEnum.max_duration_seconds.name(), ExamRecordFieldEnum.force_finish.name()};
         Object[] values = new Object[]{examActivityUnFinishBean.getStartTime(), examActivityCacheBean.getFinishTime(), examActivityCacheBean.getOpeningSeconds(), ec.getMinDurationSeconds(), examActivityCacheBean.getMaxDurationSeconds(), ec.getForceFinish()};
         tOeExamRecordService.dataUpdatesMq(recordId, columns, values);

+ 24 - 0
themis-exam/src/main/java/com/qmth/themis/exam/config/ExamConstant.java

@@ -57,4 +57,28 @@ public class ExamConstant {
             webSocketMobileServer.sendMessage(websocketDto);
         }
     }
+
+    /**
+     * 发送考试开始msg
+     *
+     * @param recordId
+     */
+    public static void sendExamStartMsg(Long recordId) {
+        //移动端考试开始
+        ConcurrentHashMap<String, WebSocketMobileServer> webSocketMap = WebSocketMobileServer.getWebSocketMap();
+        if (Objects.nonNull(webSocketMap.get(recordId + "-" + MonitorVideoSourceEnum.MOBILE_FIRST.name()))) {
+            WebSocketMobileServer webSocketMobileServer = webSocketMap.get(recordId + "-" + MonitorVideoSourceEnum.MOBILE_FIRST.name());
+            Map map = new HashMap<>();
+            map.put(SystemConstant.RECORD_ID, recordId);
+            WebsocketDto websocketDto = new WebsocketDto(WebsocketTypeEnum.EXAM_START.name(), map);
+            webSocketMobileServer.sendMessage(websocketDto);
+        }
+        if (Objects.nonNull(webSocketMap.get(recordId + "-" + MonitorVideoSourceEnum.MOBILE_SECOND.name()))) {
+            WebSocketMobileServer webSocketMobileServer = webSocketMap.get(recordId + "-" + MonitorVideoSourceEnum.MOBILE_SECOND.name());
+            Map map = new HashMap<>();
+            map.put(SystemConstant.RECORD_ID, recordId);
+            WebsocketDto websocketDto = new WebsocketDto(WebsocketTypeEnum.EXAM_START.name(), map);
+            webSocketMobileServer.sendMessage(websocketDto);
+        }
+    }
 }

+ 2 - 0
themis-task/src/main/java/com/qmth/themis/task/enums/QuartzTaskEnum.java

@@ -15,6 +15,8 @@ public enum QuartzTaskEnum {
 
     EXAM_ACTIVITY_JOB_GROUP_NAME("考场一次性延时job group"),
 
+    EXAM_STUDENT_JOB_GROUP_NAME("考生一次性延时job group"),
+
     MQ_ACTIVITY_JOB_NAME("mq_activity_job"),
 
     MQ_ACTIVITY_JOB_GROUP_NAME("mq_activity_job group"),;

+ 1 - 1
themis-task/src/main/java/com/qmth/themis/task/listener/service/MqTaskLogicService.java

@@ -27,5 +27,5 @@ public interface MqTaskLogicService {
      * @param mqDto
      * @param key
      */
-    public void execMqQuartzLogic(MqDto mqDto, String key) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException;
+    public void execMqQuartzLogic(MqDto mqDto, String key);
 }

+ 53 - 30
themis-task/src/main/java/com/qmth/themis/task/listener/service/impl/MqTaskLogicServiceImpl.java

@@ -4,12 +4,14 @@ import com.alibaba.fastjson.JSON;
 import com.alibaba.fastjson.JSONArray;
 import com.alibaba.fastjson.JSONObject;
 import com.google.gson.Gson;
-import com.qmth.themis.business.cache.bean.ExamCacheBean;
+import com.qmth.themis.business.cache.ExamRecordCacheUtil;
+import com.qmth.themis.business.cache.bean.ExamStudentCacheBean;
 import com.qmth.themis.business.constant.SystemConstant;
 import com.qmth.themis.business.dto.MqDto;
 import com.qmth.themis.business.entity.TEExam;
 import com.qmth.themis.business.entity.TEExamActivity;
 import com.qmth.themis.business.entity.TMRocketMessage;
+import com.qmth.themis.business.enums.MqTagEnum;
 import com.qmth.themis.business.service.TEExamService;
 import com.qmth.themis.business.service.TMRocketMessageService;
 import com.qmth.themis.business.util.JacksonUtil;
@@ -17,6 +19,7 @@ import com.qmth.themis.business.util.RedisUtil;
 import com.qmth.themis.task.enums.QuartzTaskEnum;
 import com.qmth.themis.task.listener.service.MqTaskLogicService;
 import com.qmth.themis.task.quartz.ExamActivityJob;
+import com.qmth.themis.task.quartz.ExamStudentJob;
 import com.qmth.themis.task.service.QuartzService;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -24,7 +27,6 @@ import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 
 import javax.annotation.Resource;
-import java.lang.reflect.InvocationTargetException;
 import java.util.*;
 
 /**
@@ -70,47 +72,68 @@ public class MqTaskLogicServiceImpl implements MqTaskLogicService {
 
     @Override
     @Transactional
-    public void execMqQuartzLogic(MqDto mqDto, String key) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {
+    public void execMqQuartzLogic(MqDto mqDto, String key) {
         Gson gson = new Gson();
         Map<String, Object> tranMap = mqDto.getProperties();
         String oper = String.valueOf(tranMap.get("oper"));
         Object o = JacksonUtil.parseJson(tranMap.get("exam"));
+        String tag = mqDto.getTag();
         TEExam teExam = JSONObject.toJavaObject(JSONObject.parseObject(String.valueOf(o)), TEExam.class);
         mqDto.setAck(SystemConstant.STANDARD_ACK_TYPE);
-        JSONArray jsonArray = (JSONArray) JSONArray.parse(String.valueOf(mqDto.getBody()));
-        for (int i = 0; i < jsonArray.size(); i++) {
-            TEExamActivity teExamActivity = JSONObject.toJavaObject((JSON) jsonArray.get(i), TEExamActivity.class);
-            ExamCacheBean examCacheBean = teExamService.getExamCacheBean(teExamActivity.getExamId());
-            if (Objects.equals("delete", oper)) {
-                quartzService.deleteJob(teExamActivity.getCode(), QuartzTaskEnum.EXAM_ACTIVITY_JOB_GROUP_NAME.name());
-            } else {
-                if (Objects.nonNull(teExam.getEnable()) && teExam.getEnable().intValue() == 1 && Objects.nonNull(teExamActivity.getEnable()) && teExamActivity.getEnable().intValue() == 1) {
-                    Date finishTime = teExamActivity.getFinishTime();
-                    Calendar calendar = Calendar.getInstance();
-                    calendar.setTime(finishTime);
-//                    calendar.add(Calendar.SECOND, 30);
-                    if (calendar.getTime().getTime() > System.currentTimeMillis()) {
-                        int year = calendar.get(Calendar.YEAR);//获取年份
-                        int month = calendar.get(Calendar.MONTH) + 1;//获取月份
-                        int day = calendar.get(Calendar.DATE);//获取日
-                        int hour = calendar.get(Calendar.HOUR_OF_DAY);//小时
-                        int minute = calendar.get(Calendar.MINUTE);//分
-                        int second = calendar.get(Calendar.SECOND);//秒
-                        String cron = second + " " + minute + " " + hour + " " + day + " " + month + " ? " + year;
-                        log.info("cron:{}", cron);
-                        String activityCode = teExamActivity.getCode();
-                        //执行一次性延时任务
-                        Map mapJob = new HashMap();
-                        mapJob.put("name", examCacheBean.getId() + "-" + activityCode);
-                        quartzService.deleteJob(activityCode, QuartzTaskEnum.EXAM_ACTIVITY_JOB_GROUP_NAME.name());
-                        quartzService.addJob(ExamActivityJob.class, examCacheBean.getId() + "-" + activityCode, QuartzTaskEnum.EXAM_ACTIVITY_JOB_GROUP_NAME.name(), cron, mapJob);
+        if (Objects.equals(tag, MqTagEnum.EXAM_ACTIVITY.name())) {
+            JSONArray jsonArray = (JSONArray) JSONArray.parse(String.valueOf(mqDto.getBody()));
+            for (int i = 0; i < jsonArray.size(); i++) {
+                TEExamActivity teExamActivity = JSONObject.toJavaObject((JSON) jsonArray.get(i), TEExamActivity.class);
+                if (Objects.equals("delete", oper)) {
+                    quartzService.deleteJob(String.valueOf(teExamActivity.getId()), QuartzTaskEnum.EXAM_ACTIVITY_JOB_GROUP_NAME.name());
+                } else {
+                    if (Objects.nonNull(teExam.getEnable()) && teExam.getEnable().intValue() == 1 && Objects.nonNull(teExamActivity.getEnable()) && teExamActivity.getEnable().intValue() == 1) {
+                        this.setCron(teExamActivity.getFinishTime(), String.valueOf(teExamActivity.getId()), ExamActivityJob.class, QuartzTaskEnum.EXAM_ACTIVITY_JOB_GROUP_NAME);
                     }
                 }
             }
+        } else if (Objects.equals(tag, MqTagEnum.EXAM_STUDENT.name())) {
+            JSONObject jsonObject = JSONObject.parseObject(String.valueOf(mqDto.getBody()));
+            ExamStudentCacheBean examStudentCacheBean = JSONObject.toJavaObject(jsonObject, ExamStudentCacheBean.class);
+            Long recordId = Long.parseLong(String.valueOf(mqDto.getObjId()));
+            if (Objects.equals("delete", oper)) {
+                quartzService.deleteJob(examStudentCacheBean.getId() + "-" + recordId, QuartzTaskEnum.EXAM_STUDENT_JOB_GROUP_NAME.name());
+            } else {
+                this.setCron(ExamRecordCacheUtil.getExamFinalFinishTime(recordId), examStudentCacheBean.getId() + "-" + recordId, ExamStudentJob.class, QuartzTaskEnum.EXAM_STUDENT_JOB_GROUP_NAME);
+            }
         }
         TMRocketMessage tmRocketMessage = gson.fromJson(gson.toJson(mqDto), TMRocketMessage.class);
         tmRocketMessage.setBody(JacksonUtil.parseJson(tmRocketMessage.getBody()));
         tmRocketMessageService.saveOrUpdate(tmRocketMessage);
         redisUtil.delete(key, mqDto.getId());
     }
+
+    /**
+     * 设置quart cron
+     *
+     * @param finishTime
+     * @param jobId
+     * @param cls
+     * @param quartzTaskEnum
+     */
+    public void setCron(Date finishTime, String jobName, Class cls, QuartzTaskEnum quartzTaskEnum) {
+        Calendar calendar = Calendar.getInstance();
+        calendar.setTime(finishTime);
+//                    calendar.add(Calendar.SECOND, 30);
+        if (calendar.getTime().getTime() > System.currentTimeMillis()) {
+            int year = calendar.get(Calendar.YEAR);//获取年份
+            int month = calendar.get(Calendar.MONTH) + 1;//获取月份
+            int day = calendar.get(Calendar.DATE);//获取日
+            int hour = calendar.get(Calendar.HOUR_OF_DAY);//小时
+            int minute = calendar.get(Calendar.MINUTE);//分
+            int second = calendar.get(Calendar.SECOND);//秒
+            String cron = second + " " + minute + " " + hour + " " + day + " " + month + " ? " + year;
+            log.info("cron:{}", cron);
+            //执行一次性延时任务
+            Map mapJob = new HashMap();
+            mapJob.put("name", jobName);
+            quartzService.deleteJob(jobName, quartzTaskEnum.name());
+            quartzService.addJob(cls, jobName, quartzTaskEnum.name(), cron, mapJob);
+        }
+    }
 }

+ 38 - 0
themis-task/src/main/java/com/qmth/themis/task/quartz/ExamStudentJob.java

@@ -0,0 +1,38 @@
+package com.qmth.themis.task.quartz;
+
+import com.qmth.themis.task.quartz.service.QuartzLogicService;
+import org.quartz.JobDetail;
+import org.quartz.JobExecutionContext;
+import org.quartz.JobExecutionException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.scheduling.quartz.QuartzJobBean;
+import org.springframework.stereotype.Component;
+
+import javax.annotation.Resource;
+import java.util.Objects;
+
+/**
+ * @Description: examActivity job,一次性延时任务
+ * @Param:
+ * @return:
+ * @Author: wangliang
+ * @Date: 2020/7/27
+ */
+@Component
+public class ExamStudentJob extends QuartzJobBean {
+    private final static Logger log = LoggerFactory.getLogger(ExamStudentJob.class);
+
+    @Resource
+    QuartzLogicService quartzLogicService;
+
+    @Override
+    protected void executeInternal(JobExecutionContext context) throws JobExecutionException {
+        log.info("exam_acvitity_job进来了,context:{}", context);
+        JobDetail jobDetail = context.getJobDetail();
+        String key = String.valueOf(jobDetail.getKey());
+        if (Objects.nonNull(key)) {
+            quartzLogicService.execExamActivityJobLogic(key);
+        }
+    }
+}

+ 7 - 0
themis-task/src/main/java/com/qmth/themis/task/quartz/service/QuartzLogicService.java

@@ -15,4 +15,11 @@ public interface QuartzLogicService {
      * @param key
      */
     public void execExamActivityJobLogic(String key);
+
+    /**
+     * 考生quartz逻辑
+     *
+     * @param key
+     */
+    public void execExamStudentJobLogic(String key);
 }

+ 48 - 21
themis-task/src/main/java/com/qmth/themis/task/quartz/service/impl/QuartzLogicServiceImpl.java

@@ -1,11 +1,10 @@
 package com.qmth.themis.task.quartz.service.impl;
 
-import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.qmth.themis.business.cache.ExamRecordCacheUtil;
 import com.qmth.themis.business.cache.RedisKeyHelper;
+import com.qmth.themis.business.cache.bean.ExamActivityCacheBean;
 import com.qmth.themis.business.cache.bean.ExamCacheBean;
 import com.qmth.themis.business.cache.bean.ExamStudentCacheBean;
-import com.qmth.themis.business.entity.TEExamActivity;
 import com.qmth.themis.business.enums.ExamRecordStatusEnum;
 import com.qmth.themis.business.enums.FinishTypeEnum;
 import com.qmth.themis.business.service.TEExamActivityService;
@@ -19,6 +18,7 @@ import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 
 import javax.annotation.Resource;
+import java.util.Date;
 import java.util.Map;
 import java.util.Objects;
 
@@ -53,17 +53,13 @@ public class QuartzLogicServiceImpl implements QuartzLogicService {
     @Override
     @Transactional
     public void execExamActivityJobLogic(String key) {
-        log.info("key:{}", key);
+        log.info("execExamActivityJobLogic key:{}", key);
         String[] strings = key.split("\\.");
-        String[] exams = strings[1].split("-");
-        QueryWrapper<TEExamActivity> teExamActivityQueryWrapper = new QueryWrapper<>();
-        teExamActivityQueryWrapper.lambda().eq(TEExamActivity::getCode, exams[1])
-                .eq(TEExamActivity::getExamId, Long.parseLong(exams[0]));
-        TEExamActivity teExamActivity = teExamActivityService.getOne(teExamActivityQueryWrapper);
-        ExamCacheBean examCacheBean = teExamService.getExamCacheBean(teExamActivity.getExamId());
-        if (Objects.nonNull(examCacheBean) && examCacheBean.getEnable() == 1 && Objects.nonNull(teExamActivity) && teExamActivity.getEnable() == 1) {
+        ExamActivityCacheBean examActivityCacheBean = teExamActivityService.getExamActivityCacheBean(Long.parseLong(strings[1]));
+        ExamCacheBean examCacheBean = teExamService.getExamCacheBean(examActivityCacheBean.getExamId());
+        if (Objects.nonNull(examCacheBean) && examCacheBean.getEnable() == 1 && Objects.nonNull(examActivityCacheBean) && examActivityCacheBean.getEnable() == 1) {
             Integer forceFinish = examCacheBean.getForceFinish();
-            Map<String, Object> objectMap = redisUtil.getHashEntries(RedisKeyHelper.examActivityRecordCacheKey(teExamActivity.getId()));
+            Map<String, Object> objectMap = redisUtil.getHashEntries(RedisKeyHelper.examActivityRecordCacheKey(examActivityCacheBean.getId()));
             if (Objects.nonNull(forceFinish) && forceFinish.intValue() == 1) {//强制收卷
                 if (Objects.nonNull(objectMap) && objectMap.size() > 0) {
                     objectMap.forEach((k, v) -> {
@@ -71,11 +67,14 @@ public class QuartzLogicServiceImpl implements QuartzLogicService {
                         //获取该考试批次下所有未交卷的考生的考试记录
                         if (Objects.nonNull(examRecordStatusEnum) && !Objects.equals(ExamRecordStatusEnum.FINISHED, examRecordStatusEnum)) {
                             Long recordId = Long.parseLong(k);
-                            Integer durationSeconds = ExamRecordCacheUtil.getDurationSeconds(recordId);
-                            Long examStudentId = ExamRecordCacheUtil.getExamStudentId(recordId);
-                            ExamStudentCacheBean examStudentCacheBean = teExamStudentService.getExamStudentCacheBean(examStudentId);
-                            //交卷
-                            teExamService.finish(examStudentCacheBean.getStudentId(), Long.parseLong(k), FinishTypeEnum.AUTO.name(), durationSeconds);
+                            Date recordEndTime = ExamRecordCacheUtil.getEndTime(recordId);
+                            if (examActivityCacheBean.getFinishTime().getTime() == recordEndTime.getTime()) {
+                                Integer durationSeconds = ExamRecordCacheUtil.getDurationSeconds(recordId);
+                                Long examStudentId = ExamRecordCacheUtil.getExamStudentId(recordId);
+                                ExamStudentCacheBean examStudentCacheBean = teExamStudentService.getExamStudentCacheBean(examStudentId);
+                                //交卷
+                                teExamService.finish(examStudentCacheBean.getStudentId(), Long.parseLong(k), FinishTypeEnum.AUTO.name(), durationSeconds);
+                            }
                         }
                     });
                 }
@@ -86,15 +85,43 @@ public class QuartzLogicServiceImpl implements QuartzLogicService {
                         //获取该考试批次下所有未交卷的考生的考试记录
                         if (Objects.nonNull(examRecordStatusEnum) && !Objects.equals(ExamRecordStatusEnum.FINISHED, examRecordStatusEnum) && !Objects.equals(ExamRecordStatusEnum.ANSWERING, examRecordStatusEnum)) {
                             Long recordId = Long.parseLong(k);
-                            Integer durationSeconds = ExamRecordCacheUtil.getDurationSeconds(recordId);
-                            Long examStudentId = ExamRecordCacheUtil.getExamStudentId(recordId);
-                            ExamStudentCacheBean examStudentCacheBean = teExamStudentService.getExamStudentCacheBean(examStudentId);
-                            //交卷
-                            teExamService.finish(examStudentCacheBean.getStudentId(), Long.parseLong(k), FinishTypeEnum.AUTO.name(), durationSeconds);
+                            Date recordEndTime = ExamRecordCacheUtil.getEndTime(recordId);
+                            if (examActivityCacheBean.getFinishTime().getTime() == recordEndTime.getTime()) {
+                                Integer durationSeconds = ExamRecordCacheUtil.getDurationSeconds(recordId);
+                                Long examStudentId = ExamRecordCacheUtil.getExamStudentId(recordId);
+                                ExamStudentCacheBean examStudentCacheBean = teExamStudentService.getExamStudentCacheBean(examStudentId);
+                                //交卷
+                                teExamService.finish(examStudentCacheBean.getStudentId(), Long.parseLong(k), FinishTypeEnum.AUTO.name(), durationSeconds);
+                            }
                         }
                     });
                 }
             }
         }
     }
+
+    /**
+     * 考生quartz逻辑
+     *
+     * @param key
+     */
+    @Override
+    public void execExamStudentJobLogic(String key) {
+        log.info("execExamStudentJobLogic key:{}", key);
+        String[] strings = key.split("\\.");
+        String[] exams = strings[1].split("-");
+        ExamStudentCacheBean examStudentCacheBean = teExamStudentService.getExamStudentCacheBean(Long.parseLong(exams[0]));
+        Long recordId = Long.parseLong(exams[1]);
+        ExamRecordStatusEnum examRecordStatusEnum = ExamRecordCacheUtil.getStatus(recordId);
+        ExamActivityCacheBean examActivityCacheBean = teExamActivityService.getExamActivityCacheBean(examStudentCacheBean.getExamActivityId());
+        //获取该考试批次下所有未交卷的考生的考试记录
+        if (Objects.nonNull(examRecordStatusEnum) && !Objects.equals(ExamRecordStatusEnum.FINISHED, examRecordStatusEnum) && !Objects.equals(ExamRecordStatusEnum.ANSWERING, examRecordStatusEnum)) {
+            Date recordEndTime = ExamRecordCacheUtil.getEndTime(recordId);
+            if (examActivityCacheBean.getFinishTime().getTime() == recordEndTime.getTime()) {
+                Integer durationSeconds = ExamRecordCacheUtil.getDurationSeconds(recordId);
+                //交卷
+                teExamService.finish(examStudentCacheBean.getStudentId(), recordId, FinishTypeEnum.AUTO.name(), durationSeconds);
+            }
+        }
+    }
 }

+ 1 - 1
themis-task/src/main/java/com/qmth/themis/task/start/StartRunning.java

@@ -86,7 +86,7 @@ public class StartRunning implements CommandLineRunner {
         /**
          * quartz mq start
          */
-        rocketMessageConsumer.setRocketMQConsumer(nameServer, MqGroupEnum.QUARTZ_GROUP.getCode(), MqTopicEnum.THEMIS_TOPIC.getCode(), MqTagEnum.EXAM_ACTIVITY.name(), MessageModel.CLUSTERING, SpringContextHolder.getBean(QuartzOrderlyImpl.class));
+        rocketMessageConsumer.setRocketMQConsumer(nameServer, MqGroupEnum.QUARTZ_GROUP.getCode(), MqTopicEnum.THEMIS_TOPIC.getCode(), MqTagEnum.EXAM_ACTIVITY.name() + "||" + MqTagEnum.EXAM_STUDENT.name(), MessageModel.CLUSTERING, SpringContextHolder.getBean(QuartzOrderlyImpl.class));
         /**
          * quartz mq end
          */