瀏覽代碼

加入超过最大开考时间考试侯考退出

wangliang 1 年之前
父節點
當前提交
f7621082aa

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

@@ -59,7 +59,9 @@ public enum MqTagEnum {
     ONLINE_LOG("考生上下线标签", "考生上下线", "normal", 51),
 //    EXAM_AUDIO("考试语音任务标签", "考试语音任务", "normal", 52),
 //    EXAM_AUDIO_MOBILE("考试语音移动端任务标签", "考试语音移动端任务", "normal", 53)
-    CLOUD_MARK_DATA_PUSH("推送云阅卷数据标签", "推送云阅卷数据任务", "normal", 52);
+    CLOUD_MARK_DATA_PUSH("推送云阅卷数据标签", "推送云阅卷数据任务", "normal", 52),
+    EXAM_EXIT("考试退出标签", "考试退出", "broadcast", 53),
+    EXAM_ACTIVITY_FINAL_PREPARE_TIME("考场最后开考时间一次性延时任务标签", "考场最后开考时间一次性延时任务", "normal", 54);
 
     private MqTagEnum(String desc, String code, String type, int id) {
         this.desc = desc;

+ 3 - 1
themis-business/src/main/java/com/qmth/themis/business/enums/WebsocketTypeEnum.java

@@ -43,7 +43,9 @@ public enum WebsocketTypeEnum {
 
     MOBILE_MONITOR_STATUS("移动端监控状态", "mobileMonitorStatus"),
 
-    EXAM_AUDIO("考试语音", "examAudio");
+    EXAM_AUDIO("考试语音", "examAudio"),
+
+    EXAM_EXIT("考试退出", "examExit");
 
     private String code;
     private String desc;

+ 9 - 0
themis-business/src/main/java/com/qmth/themis/business/service/impl/TEExamActivityServiceImpl.java

@@ -421,6 +421,15 @@ public class TEExamActivityServiceImpl extends ServiceImpl<TEExamActivityMapper,
                     themisCacheService.removeTodayExamListCache(ac.getExamId().toString(), ac.getId());
                 }
                 themisCacheService.updateOrgExamListCache(teExam.getOrgId().toString(), ac.getExamId().toString(), ac.getId());
+
+                //最后开考时间发送定时任务
+                //删除再新增quartz任务,发送mq消息start
+                Map<String, Object> prop = new HashMap<>();
+                prop.put(SystemConstant.OPER, SystemConstant.INSERT);
+                prop.put(SystemConstant.EXAM, teExam);
+                MqDto mqDto = new MqDto(mqUtil.getTopic(), MqTagEnum.EXAM_ACTIVITY_FINAL_PREPARE_TIME.name(), JacksonUtil.parseJson(ac), MqTagEnum.EXAM_ACTIVITY_FINAL_PREPARE_TIME, String.valueOf(teExam.getId()), prop, tbUser.getName());
+                mqDtoService.assembleSendAsyncOrderMsg(mqDto);
+                //删除再新增quartz任务,发送mq消息end
             }
 
             if (!CollectionUtils.isEmpty(teAudioList)) {

+ 6 - 1
themis-exam/src/main/java/com/qmth/themis/exam/listener/service/impl/MqOeLogicServiceImpl.java

@@ -277,7 +277,8 @@ public class MqOeLogicServiceImpl implements MqOeLogicService {
                 || Objects.equals(MqTagEnum.OE_WEBSOCKET_EXAM_STOP.name(), tag)//考试结束
                 || Objects.equals(MqTagEnum.MONITOR_START.name(), tag)//监控开始
                 || Objects.equals(MqTagEnum.MONITOR_STOP.name(), tag)//监控结束
-                || Objects.equals(MqTagEnum.OE_WEBSOCKET_MOBILE_MONITOR_STATUS.name(), tag)) {//通知客户端移动端当前监控状态
+                || Objects.equals(MqTagEnum.OE_WEBSOCKET_MOBILE_MONITOR_STATUS.name(), tag)//通知客户端移动端当前监控状态
+                || Objects.equals(MqTagEnum.EXAM_EXIT.name(), tag)) {//考试退出
             Long recordId = Long.parseLong(String.valueOf(mqDto.getBody()));
             TOeExamRecord tOeExamRecord = null;
             String clientWebsocketId = ExamRecordCacheUtil.getClientWebsocketId(recordId);
@@ -381,6 +382,10 @@ public class MqOeLogicServiceImpl implements MqOeLogicService {
                             websocketDto = new WebsocketDto(WebsocketTypeEnum.MOBILE_MONITOR_STATUS.name(), prop);
                             webSocketOeServer.sendMessage(websocketDto);
                             break;
+                        case "EXAM_EXIT":
+                            websocketDto = new WebsocketDto(WebsocketTypeEnum.EXAM_EXIT.name(), prop);
+                            webSocketOeServer.sendMessage(websocketDto);
+                            break;
                         default:
                             break;
                     }

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

@@ -48,7 +48,7 @@ public class StartRunning implements CommandLineRunner {
         /**
          * websocket mq start
          */
-        rocketMessageConsumer.setRocketMQConsumer(nameServer, mqUtil.getMap().get(MqGroupEnum.WEBSOCKET_OE_GROUP.name()), mqUtil.getTopic(), MqTagEnum.OE_IM_BROADCASTING.name() + "||" + MqTagEnum.OE_IM_CLUSTERING.name() + "||" + MqTagEnum.OE_LIVENESS_VERIFY.name() + "||" + MqTagEnum.OE_MONITOR_FINISH.name() + "||" + MqTagEnum.OE_WARNING_FINISH.name() + "||" + MqTagEnum.OE_WEBSOCKET_MOBILE_ANSWER_READY.name() + "||" + MqTagEnum.OE_WEBSOCKET_MOBILE_ANSWER_UPLOAD.name() + "||" + MqTagEnum.OE_WEBSOCKET_EXAM_STOP.name() + "||" + MqTagEnum.MONITOR_START.name() + "||" + MqTagEnum.MONITOR_STOP.name() + "||" + MqTagEnum.OE_WEBSOCKET_MOBILE_MONITOR_STATUS.name(), MessageModel.BROADCASTING, SpringContextHolder.getBean(WebSocketOeServer.class));
+        rocketMessageConsumer.setRocketMQConsumer(nameServer, mqUtil.getMap().get(MqGroupEnum.WEBSOCKET_OE_GROUP.name()), mqUtil.getTopic(), MqTagEnum.OE_IM_BROADCASTING.name() + "||" + MqTagEnum.OE_IM_CLUSTERING.name() + "||" + MqTagEnum.OE_LIVENESS_VERIFY.name() + "||" + MqTagEnum.OE_MONITOR_FINISH.name() + "||" + MqTagEnum.OE_WARNING_FINISH.name() + "||" + MqTagEnum.OE_WEBSOCKET_MOBILE_ANSWER_READY.name() + "||" + MqTagEnum.OE_WEBSOCKET_MOBILE_ANSWER_UPLOAD.name() + "||" + MqTagEnum.OE_WEBSOCKET_EXAM_STOP.name() + "||" + MqTagEnum.MONITOR_START.name() + "||" + MqTagEnum.MONITOR_STOP.name() + "||" + MqTagEnum.OE_WEBSOCKET_MOBILE_MONITOR_STATUS.name() + "||" + MqTagEnum.EXAM_EXIT.name(), MessageModel.BROADCASTING, SpringContextHolder.getBean(WebSocketOeServer.class));
 //        rocketMessageConsumer.setRocketMQConsumer(nameServer, dictionaryConfig.mqConfigDomain().getMap().get(MqGroupEnum.WEBSOCKET_OE_MOBILE_GROUP.name()), dictionaryConfig.mqConfigDomain().getTopic(), MqTagEnum.EXAM_STOP.name() + "||" + MqTagEnum.EXAM_START.name() + "||" + MqTagEnum.EXAM_AUDIO_MOBILE.name(), MessageModel.BROADCASTING, SpringContextHolder.getBean(WebSocketMobileServer.class));
         rocketMessageConsumer.setRocketMQConsumer(nameServer, mqUtil.getMap().get(MqGroupEnum.WEBSOCKET_OE_MOBILE_GROUP.name()), mqUtil.getTopic(), MqTagEnum.EXAM_STOP.name() + "||" + MqTagEnum.EXAM_START.name(), MessageModel.BROADCASTING, SpringContextHolder.getBean(WebSocketMobileServer.class));
         SystemConstant.initTempFiles();

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

@@ -17,6 +17,8 @@ public enum QuartzTaskEnum {
 
     EXAM_STUDENT_JOB_GROUP_NAME("考生一次性延时job group"),
 
+    EXAM_ACTIVITY_FINAL_PREPARE_TIME_JOB_GROUP_NAME("考场最后开考时间一次性延时job group"),
+
 //    EXAM_AUDIO_JOB_GROUP_NAME("考试语音播报一次性延时job group"),
 
     MQ_ACTIVITY_JOB_NAME("mq_activity_job"),

+ 15 - 0
themis-task/src/main/java/com/qmth/themis/task/listener/service/impl/MqTaskLogicServiceImpl.java

@@ -14,6 +14,7 @@ import com.qmth.themis.business.service.TMRocketMessageService;
 import com.qmth.themis.business.util.JacksonUtil;
 import com.qmth.themis.task.enums.QuartzTaskEnum;
 import com.qmth.themis.task.listener.service.MqTaskLogicService;
+import com.qmth.themis.task.quartz.ExamActivityFinalPrepareTimeJob;
 import com.qmth.themis.task.quartz.ExamActivityJob;
 import com.qmth.themis.task.quartz.ExamStudentJob;
 import com.qmth.themis.task.service.QuartzService;
@@ -91,6 +92,20 @@ public class MqTaskLogicServiceImpl implements MqTaskLogicService {
                     this.setCron(ExamRecordCacheUtil.getExamFinalFinishTime(recordId), examStudentCacheBean.getId() + "-" + recordId, ExamStudentJob.class, QuartzTaskEnum.EXAM_STUDENT_JOB_GROUP_NAME);
                 }
             }
+        } else if (Objects.equals(tag, MqTagEnum.EXAM_ACTIVITY_FINAL_PREPARE_TIME.name())) {//考场最后开考时间任务
+            JSONObject jsonObject = JSONObject.parseObject(String.valueOf(mqDto.getBody()));
+            TEExamActivity teExamActivity = JSONObject.toJavaObject(jsonObject, TEExamActivity.class);
+            if (Objects.equals(SystemConstant.DELETE, oper)) {
+                quartzService.deleteJob(teExamActivity.getId() + "-" + teExamActivity.getExamId(), QuartzTaskEnum.EXAM_ACTIVITY_FINAL_PREPARE_TIME_JOB_GROUP_NAME.name());
+            } else if (Objects.equals(SystemConstant.INSERT, oper)) {
+                quartzService.deleteJob(teExamActivity.getId() + "-" + teExamActivity.getExamId(), QuartzTaskEnum.EXAM_ACTIVITY_FINAL_PREPARE_TIME_JOB_GROUP_NAME.name());
+                if (Objects.nonNull(teExamActivity.getEnable()) && teExamActivity.getEnable().intValue() == 1) {
+                    Integer openingSecondsTemp = teExamActivity.getOpeningSeconds();
+                    openingSecondsTemp = Objects.nonNull(openingSecondsTemp) && openingSecondsTemp.intValue() == 0 ? SystemConstant.DEFAULT_OPENING_SECONDS : openingSecondsTemp;
+                    Long finalPrepareTime = teExamActivity.getStartTime() + (openingSecondsTemp * 1000);
+                    this.setCron(finalPrepareTime, teExamActivity.getId() + "-" + teExamActivity.getExamId(), ExamActivityFinalPrepareTimeJob.class, QuartzTaskEnum.EXAM_ACTIVITY_FINAL_PREPARE_TIME_JOB_GROUP_NAME);
+                }
+            }
         }
 //        else if (Objects.equals(tag, MqTagEnum.EXAM_AUDIO.name())) {//考试语音
 //            JSONObject jsonObject = JSONObject.parseObject(String.valueOf(mqDto.getBody()));

+ 44 - 0
themis-task/src/main/java/com/qmth/themis/task/quartz/ExamActivityFinalPrepareTimeJob.java

@@ -0,0 +1,44 @@
+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 ExamActivityFinalPrepareTimeJob extends QuartzJobBean {
+    private final static Logger log = LoggerFactory.getLogger(ExamActivityFinalPrepareTimeJob.class);
+
+    @Resource
+    QuartzLogicService quartzLogicService;
+
+    /**
+     * 考试场次mq延时任务
+     *
+     * @param context
+     * @throws JobExecutionException
+     */
+    @Override
+    protected void executeInternal(JobExecutionContext context) throws JobExecutionException {
+        log.info("exam_acvitity_final_prepare_time_job进来了,context:{}", context);
+        JobDetail jobDetail = context.getJobDetail();
+        String key = String.valueOf(jobDetail.getKey());
+        if (Objects.nonNull(key)) {
+            quartzLogicService.execExamActivityFinalPrepareTimeJobLogic(key);
+        }
+    }
+}

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

@@ -23,6 +23,13 @@ public interface QuartzLogicService {
      */
     public void execExamStudentJobLogic(String key);
 
+    /**
+     * 考试最后开考时间quartz逻辑
+     *
+     * @param key
+     */
+    public void execExamActivityFinalPrepareTimeJobLogic(String key);
+
 //    /**
 //     * 考试语音quartz逻辑
 //     *

+ 36 - 3
themis-task/src/main/java/com/qmth/themis/task/quartz/service/impl/QuartzLogicServiceImpl.java

@@ -6,11 +6,14 @@ 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.constant.SystemConstant;
+import com.qmth.themis.business.dto.MqDto;
 import com.qmth.themis.business.entity.TOeExamRecord;
 import com.qmth.themis.business.enums.ExamRecordStatusEnum;
 import com.qmth.themis.business.enums.FinishTypeEnum;
+import com.qmth.themis.business.enums.MqTagEnum;
 import com.qmth.themis.business.enums.WebsocketStatusEnum;
 import com.qmth.themis.business.service.*;
+import com.qmth.themis.business.util.MqUtil;
 import com.qmth.themis.task.quartz.service.QuartzLogicService;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -19,9 +22,7 @@ import org.springframework.transaction.annotation.Transactional;
 import org.springframework.util.CollectionUtils;
 
 import javax.annotation.Resource;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Objects;
+import java.util.*;
 
 /**
  * @Description: quartz逻辑 impl
@@ -49,6 +50,12 @@ public class QuartzLogicServiceImpl implements QuartzLogicService {
     @Resource
     CommonService commonService;
 
+    @Resource
+    MqUtil mqUtil;
+
+    @Resource
+    MqDtoService mqDtoService;
+
     /**
      * 考试场次quartz逻辑
      *
@@ -202,6 +209,32 @@ public class QuartzLogicServiceImpl implements QuartzLogicService {
         }
     }
 
+    /**
+     * 考试最后开考时间quartz逻辑
+     *
+     * @param key
+     */
+    @Override
+    public void execExamActivityFinalPrepareTimeJobLogic(String key) {
+        String[] strings = key.split("\\.");
+        String[] exams = strings[1].split("-");
+        ExamActivityCacheBean examActivityCacheBean = teExamActivityService.getExamActivityCacheBean(Long.parseLong(exams[0]));
+        ExamCacheBean examCacheBean = teExamService.getExamCacheBean(Long.parseLong(exams[1]));
+        List<TOeExamRecord> tOeExamRecordList = tOeExamRecordService.list(new QueryWrapper<TOeExamRecord>().lambda()
+                .eq(TOeExamRecord::getExamId, examCacheBean.getId())
+                .eq(TOeExamRecord::getExamActivityId, examActivityCacheBean.getId())
+                .eq(TOeExamRecord::getStatus, ExamRecordStatusEnum.FIRST_PREPARE)
+                .eq(TOeExamRecord::getClientWebsocketStatus, WebsocketStatusEnum.ON_LINE));
+        if (!CollectionUtils.isEmpty(tOeExamRecordList)) {
+            for (TOeExamRecord t : tOeExamRecordList) {
+                Map<String, Object> properties = new HashMap<>();
+                properties.put(SystemConstant.RECORD_ID, t.getId());
+                MqDto clientMqDto = new MqDto(mqUtil.getTopic(), MqTagEnum.EXAM_EXIT.name(), t.getId(), MqTagEnum.EXAM_EXIT, String.valueOf(t.getId()), properties, String.valueOf(t.getId()));
+                mqDtoService.assembleSendAsyncOrderMsg(clientMqDto);
+            }
+        }
+    }
+
 //    /**
 //     * 考试语音quartz逻辑
 //     *

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

@@ -126,7 +126,7 @@ public class StartRunning implements CommandLineRunner {
          * quartz mq start
          */
 //        rocketMessageConsumer.setRocketMQConsumer(nameServer, mqUtil.getMap().get(MqGroupEnum.QUARTZ_GROUP.name()), mqUtil.getTopic(), MqTagEnum.EXAM_ACTIVITY.name() + "||" + MqTagEnum.EXAM_STUDENT.name() + "||" + MqTagEnum.EXAM_AUDIO.name(), MessageModel.CLUSTERING, SpringContextHolder.getBean(QuartzOrderlyImpl.class));
-        rocketMessageConsumer.setRocketMQConsumer(nameServer, mqUtil.getMap().get(MqGroupEnum.QUARTZ_GROUP.name()), mqUtil.getTopic(), MqTagEnum.EXAM_ACTIVITY.name() + "||" + MqTagEnum.EXAM_STUDENT.name(), MessageModel.CLUSTERING, SpringContextHolder.getBean(QuartzOrderlyImpl.class));
+        rocketMessageConsumer.setRocketMQConsumer(nameServer, mqUtil.getMap().get(MqGroupEnum.QUARTZ_GROUP.name()), mqUtil.getTopic(), MqTagEnum.EXAM_ACTIVITY.name() + "||" + MqTagEnum.EXAM_STUDENT.name() + "||" + MqTagEnum.EXAM_ACTIVITY_FINAL_PREPARE_TIME.name(), MessageModel.CLUSTERING, SpringContextHolder.getBean(QuartzOrderlyImpl.class));
         //计算客观分
 //        rocketMessageConsumer.setRocketMQConsumer(nameServer, mqUtil.getMap().get(MqGroupEnum.CALCULATE_OBJECTIVE_SCORE_GROUP.name()), mqUtil.getTopic(), MqTagEnum.CALCULATE_OBJECTIVE_SCORE.name(), MessageModel.CLUSTERING, SpringContextHolder.getBean(CalculateObjectiveScoreConcurrentlyImpl.class));
         //重新算分