wangliang 4 vuotta sitten
vanhempi
commit
953f67e813
16 muutettua tiedostoa jossa 223 lisäystä ja 116 poistoa
  1. 22 0
      themis-backend/src/main/java/com/qmth/themis/backend/api/SysController.java
  2. 4 2
      themis-backend/src/main/java/com/qmth/themis/backend/api/TEExamActivityController.java
  3. 12 6
      themis-backend/src/main/java/com/qmth/themis/backend/api/TEExamController.java
  4. 3 3
      themis-backend/src/main/java/com/qmth/themis/backend/api/TEExamStudentController.java
  5. 94 32
      themis-backend/src/main/java/com/qmth/themis/backend/api/TIeInvigilateController.java
  6. 1 1
      themis-backend/src/main/resources/application.properties
  7. 16 0
      themis-business/src/main/java/com/qmth/themis/business/entity/TEExamBreachLog.java
  8. 3 3
      themis-business/src/main/java/com/qmth/themis/business/service/TEExamStudentService.java
  9. 2 2
      themis-business/src/main/java/com/qmth/themis/business/service/impl/TEExamServiceImpl.java
  10. 3 3
      themis-business/src/main/java/com/qmth/themis/business/service/impl/TEExamStudentServiceImpl.java
  11. 1 1
      themis-business/src/main/java/com/qmth/themis/business/service/impl/TOeExamRecordServiceImpl.java
  12. 7 1
      themis-business/src/main/resources/db/init.sql
  13. 6 0
      themis-common/src/main/java/com/qmth/themis/common/enums/ExceptionResultEnum.java
  14. 1 1
      themis-exam/src/main/java/com/qmth/themis/exam/api/TEStudentController.java
  15. 47 60
      themis-exam/src/main/java/com/qmth/themis/exam/listener/service/impl/MqOeLogicServiceImpl.java
  16. 1 1
      themis-task/src/main/java/com/qmth/themis/task/quartz/service/impl/QuartzLogicServiceImpl.java

+ 22 - 0
themis-backend/src/main/java/com/qmth/themis/backend/api/SysController.java

@@ -2,9 +2,12 @@ package com.qmth.themis.backend.api;
 
 import com.alibaba.fastjson.JSONObject;
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.google.common.reflect.TypeToken;
+import com.google.gson.Gson;
 import com.qmth.themis.backend.config.DictionaryConfig;
 import com.qmth.themis.business.config.SystemConfig;
 import com.qmth.themis.business.constant.SystemConstant;
+import com.qmth.themis.business.dto.response.TEExamQueryDto;
 import com.qmth.themis.business.entity.*;
 import com.qmth.themis.business.enums.DownloadFileEnum;
 import com.qmth.themis.business.enums.RoleEnum;
@@ -68,6 +71,9 @@ public class SysController {
     @Resource
     TEExamActivityService teExamActivityService;
 
+    @Resource
+    TEExamService teExamService;
+
     @ApiOperation(value = "菜单查询接口")
     @RequestMapping(value = "/getMenu", method = RequestMethod.POST)
     @ApiResponses({@ApiResponse(code = 200, message = "菜单信息", response = TBPrivilege.class)})
@@ -249,4 +255,20 @@ public class SysController {
         map.put(SystemConstant.RECORDS, teExamActivityList);
         return ResultUtil.ok(map);
     }
+
+    @ApiOperation(value = "考试批次查询接口")
+    @RequestMapping(value = "/exam/query", method = RequestMethod.POST)
+    @ApiResponses({@ApiResponse(code = 200, message = "角色信息", response = TEExamQueryDto.class)})
+    public Result examQuery() {
+        List<TEExam> teExamList = teExamService.list();
+        List<TEExamQueryDto> teExamQueryDtoList = null;
+        if (Objects.nonNull(teExamList)) {
+            Gson gson = new Gson();
+            teExamQueryDtoList = gson.fromJson(gson.toJson(teExamList), new TypeToken<List<TEExamQueryDto>>() {
+            }.getType());
+        }
+        Map map = new HashMap();
+        map.put(SystemConstant.RECORDS, teExamQueryDtoList);
+        return ResultUtil.ok(map);
+    }
 }

+ 4 - 2
themis-backend/src/main/java/com/qmth/themis/backend/api/TEExamActivityController.java

@@ -79,8 +79,10 @@ public class TEExamActivityController {
             Map<String, Object> prop = new HashMap<>();
             prop.put("oper", "insert");
             prop.put("exam", teExam);
-            MqDto mqDto = new MqDto(MqTopicEnum.themisTopic.getCode(), MqTagEnum.examActivity.name(), JacksonUtil.parseJson(teExamActivityList), MqEnum.QUARTZ_LOG, String.valueOf(teExam.getId()), prop, tbUser.getName());
-            mqDtoService.assembleSendOneWayMsg(mqDto);
+            if (Objects.nonNull(teExamActivityList.get(0)) && teExamActivityList.get(0).getEnable() == 1) {
+                MqDto mqDto = new MqDto(MqTopicEnum.themisTopic.getCode(), MqTagEnum.examActivity.name(), JacksonUtil.parseJson(teExamActivityList), MqEnum.QUARTZ_LOG, String.valueOf(teExam.getId()), prop, tbUser.getName());
+                mqDtoService.assembleSendOneWayMsg(mqDto);
+            }
             //新增quartz任务,发送mq消息end
             teExamActivityList.forEach(s -> {
                 teExamActivityService.updateExamActivityCacheBean(s.getId());

+ 12 - 6
themis-backend/src/main/java/com/qmth/themis/backend/api/TEExamController.java

@@ -100,8 +100,10 @@ public class TEExamController {
                 //删除quartz任务,发送mq消息start
                 Map<String, Object> prop = new HashMap<>();
                 prop.put("oper", "delete");
-                MqDto mqDto = new MqDto(MqTopicEnum.themisTopic.getCode(), MqTagEnum.examActivity.name(), JacksonUtil.parseJson(teExamActivityList), MqEnum.QUARTZ_LOG, String.valueOf(teExam.getId()), prop, tbUser.getName());
-                mqDtoService.assembleSendOneWayMsg(mqDto);
+                if (Objects.nonNull(teExamActivityList.get(0)) && teExamActivityList.get(0).getEnable() == 1) {
+                    MqDto mqDto = new MqDto(MqTopicEnum.themisTopic.getCode(), MqTagEnum.examActivity.name(), JacksonUtil.parseJson(teExamActivityList), MqEnum.QUARTZ_LOG, String.valueOf(teExam.getId()), prop, tbUser.getName());
+                    mqDtoService.assembleSendOneWayMsg(mqDto);
+                }
                 //删除quartz任务,发送mq消息end
 
                 //删除数据
@@ -117,8 +119,10 @@ public class TEExamController {
                     Map<String, Object> prop = new HashMap<>();
                     prop.put("oper", "insert");
                     prop.put("exam", teExam);
-                    MqDto mqDto = new MqDto(MqTopicEnum.themisTopic.getCode(), MqTagEnum.examActivity.name(), JacksonUtil.parseJson(Arrays.asList(teExamActivity)), MqEnum.QUARTZ_LOG, String.valueOf(teExam.getId()), prop, tbUser.getName());
-                    mqDtoService.assembleSendOneWayMsg(mqDto);
+                    if (Objects.nonNull(teExamActivity) && teExamActivity.getEnable() == 1) {
+                        MqDto mqDto = new MqDto(MqTopicEnum.themisTopic.getCode(), MqTagEnum.examActivity.name(), JacksonUtil.parseJson(Arrays.asList(teExamActivity)), MqEnum.QUARTZ_LOG, String.valueOf(teExam.getId()), prop, tbUser.getName());
+                        mqDtoService.assembleSendOneWayMsg(mqDto);
+                    }
                     //新增quartz任务,发送mq消息end
                 } else {//修改需删除之前生成的全部quartz任务
                     QueryWrapper<TEExamActivity> teExamActivityQueryWrapper = new QueryWrapper<>();
@@ -139,8 +143,10 @@ public class TEExamController {
                     Map<String, Object> prop = new HashMap<>();
                     prop.put("oper", "insert");
                     prop.put("exam", teExam);
-                    MqDto mqDto = new MqDto(MqTopicEnum.themisTopic.getCode(), MqTagEnum.examActivity.name(), JacksonUtil.parseJson(teExamActivityList), MqEnum.QUARTZ_LOG, String.valueOf(teExam.getId()), prop, tbUser.getName());
-                    mqDtoService.assembleSendOneWayMsg(mqDto);
+                    if (Objects.nonNull(teExamActivityList.get(0)) && teExamActivityList.get(0).getEnable() == 1) {
+                        MqDto mqDto = new MqDto(MqTopicEnum.themisTopic.getCode(), MqTagEnum.examActivity.name(), JacksonUtil.parseJson(teExamActivityList), MqEnum.QUARTZ_LOG, String.valueOf(teExam.getId()), prop, tbUser.getName());
+                        mqDtoService.assembleSendOneWayMsg(mqDto);
+                    }
                     //新增quartz任务,发送mq消息end
                     teExamActivityList.forEach(s -> {
                         teExamActivityService.updateExamActivityCacheBean(s.getId());

+ 3 - 3
themis-backend/src/main/java/com/qmth/themis/backend/api/TEExamStudentController.java

@@ -108,7 +108,7 @@ public class TEExamStudentController {
         }
         teExamStudentService.updateBatchById(teExamStudentList);
         teExamStudentList.forEach(s -> {
-            teExamStudentService.updateExamStudnetCacheBean(s.getId());
+            teExamStudentService.updateExamStudentCacheBean(s.getId());
         });
         return ResultUtil.ok(JacksonUtil.parseJson(SystemConstant.SUCCESS));
     }
@@ -123,7 +123,7 @@ public class TEExamStudentController {
         }
         teExamStudentService.updateBatchById(teExamStudentList);
         teExamStudentList.forEach(s -> {
-            teExamStudentService.updateExamStudnetCacheBean(s.getId());
+            teExamStudentService.updateExamStudentCacheBean(s.getId());
         });
         return ResultUtil.ok(JacksonUtil.parseJson(SystemConstant.SUCCESS));
     }
@@ -138,7 +138,7 @@ public class TEExamStudentController {
         }
         teExamStudentService.removeByIds(ids);
         ids.forEach(s -> {
-            teExamStudentService.deleteExamStudnetCacheBean(s);
+            teExamStudentService.deleteExamStudentCacheBean(s);
         });
         return ResultUtil.ok(JacksonUtil.parseJson(SystemConstant.SUCCESS));
     }

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

@@ -1,42 +1,37 @@
 package com.qmth.themis.backend.api;
 
-import java.util.List;
-import java.util.Map;
-import java.util.Objects;
-
-import javax.annotation.Resource;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.validation.annotation.Validated;
-import org.springframework.web.bind.annotation.RequestBody;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RequestMethod;
-import org.springframework.web.bind.annotation.RestController;
-
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.qmth.themis.business.annotation.ApiJsonObject;
 import com.qmth.themis.business.annotation.ApiJsonProperty;
 import com.qmth.themis.business.bean.backend.InvigilateListQueryBean;
+import com.qmth.themis.business.cache.RedisKeyHelper;
 import com.qmth.themis.business.constant.SystemConstant;
 import com.qmth.themis.business.dto.MqDto;
 import com.qmth.themis.business.entity.TBUser;
-import com.qmth.themis.business.enums.FinishTypeEnum;
-import com.qmth.themis.business.enums.MqEnum;
-import com.qmth.themis.business.enums.MqTagEnum;
-import com.qmth.themis.business.enums.MqTopicEnum;
+import com.qmth.themis.business.entity.TEExamBreachLog;
+import com.qmth.themis.business.enums.*;
 import com.qmth.themis.business.service.MqDtoService;
+import com.qmth.themis.business.service.TEExamBreachLogService;
 import com.qmth.themis.business.util.JacksonUtil;
+import com.qmth.themis.business.util.RedisUtil;
 import com.qmth.themis.business.util.ServletUtil;
 import com.qmth.themis.common.enums.ExceptionResultEnum;
 import com.qmth.themis.common.exception.BusinessException;
 import com.qmth.themis.common.util.Result;
 import com.qmth.themis.common.util.ResultUtil;
+import io.swagger.annotations.*;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.bind.annotation.RestController;
 
-import io.swagger.annotations.Api;
-import io.swagger.annotations.ApiOperation;
-import io.swagger.annotations.ApiParam;
-import io.swagger.annotations.ApiResponse;
-import io.swagger.annotations.ApiResponses;
+import javax.annotation.Resource;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
 
 /**
  * @Description: 监考信息 前端控制器
@@ -54,6 +49,12 @@ public class TIeInvigilateController {
     @Resource
     MqDtoService mqDtoService;
 
+    @Resource
+    TEExamBreachLogService teExamBreachLogService;
+
+    @Resource
+    RedisUtil redisUtil;
+
     @ApiOperation(value = "实时监控台列表接口")
     @RequestMapping(value = "/list", method = RequestMethod.POST)
     public Result list(@RequestBody InvigilateListQueryBean param) {
@@ -72,21 +73,76 @@ public class TIeInvigilateController {
     @RequestMapping(value = "/finish", method = RequestMethod.POST)
     @ApiResponses({@ApiResponse(code = 200, message = "{\"success\":true}", response = Result.class)})
     public Result finish(@ApiJsonObject(name = "invigilateFinish", value = {
-            @ApiJsonProperty(key = "examRecordId", description = "考试记录id"),
+            @ApiJsonProperty(key = "examRecordId", type = "long", example = "1", description = "考试记录id"),
             @ApiJsonProperty(key = "type", description = "收卷类型,手动/强制")
     }) @ApiParam(value = "考试记录信息", required = true) @RequestBody Map<String, Object> mapParameter) {
-        if (Objects.isNull(mapParameter.get("recordId")) || Objects.equals(mapParameter.get("recordId"), "")) {
+        if (Objects.isNull(mapParameter.get("examRecordId")) || Objects.equals(mapParameter.get("examRecordId"), "")) {
             throw new BusinessException(ExceptionResultEnum.RECORD_ID_IS_NULL);
         }
-        List<Long> recordIdList = (List<Long>) mapParameter.get("recordId");
+        List<Long> recordIdList = (List<Long>) mapParameter.get("examRecordId");
         if (Objects.isNull(mapParameter.get("type")) || Objects.equals(mapParameter.get("type"), "")) {
             throw new BusinessException(ExceptionResultEnum.FINISH_TYPE_IS_NULL);
         }
         FinishTypeEnum type = FinishTypeEnum.valueOf(String.valueOf(mapParameter.get("type")));
         TBUser tbUser = (TBUser) ServletUtil.getRequestAccount();
-        //发送mq给客户端强制收卷
+        //发送mq给客户端强制收卷start
         MqDto mqDto = new MqDto(MqTopicEnum.themisTopic.getCode(), MqTagEnum.oe.name(), JacksonUtil.parseJson(recordIdList), type.ordinal() == FinishTypeEnum.INTERRUPT.ordinal() ? MqEnum.WEBSOCKET_MONITOR_FINISH_LOG : MqEnum.WEBSOCKET_HAND_FINISH_LOG, String.valueOf(tbUser.getId()), mapParameter, tbUser.getName());
         mqDtoService.assembleSendOneWayMsg(mqDto);
+        //发送mq给客户端强制收卷end
+        return ResultUtil.ok(SystemConstant.SUCCESS);
+    }
+
+    @ApiOperation(value = "违纪处理接口")
+    @RequestMapping(value = "/breach", method = RequestMethod.POST)
+    @ApiResponses({@ApiResponse(code = 200, message = "{\"success\":true}", response = Result.class)})
+    public Result breach(@ApiJsonObject(name = "invigilateBreach", value = {
+            @ApiJsonProperty(key = "examRecordId", type = "long", example = "1", description = "考试记录id"),
+            @ApiJsonProperty(key = "type", description = "违规类型"),
+            @ApiJsonProperty(key = "description", description = "描述"),
+            @ApiJsonProperty(key = "status", type = "int", example = "1", description = "新建/撤销")
+    }) @ApiParam(value = "考试记录信息", required = true) @RequestBody Map<String, Object> mapParameter) {
+        if (Objects.isNull(mapParameter.get("examRecordId")) || Objects.equals(mapParameter.get("examRecordId"), "")) {
+            throw new BusinessException(ExceptionResultEnum.RECORD_ID_IS_NULL);
+        }
+        List<Long> recordIdList = (List<Long>) mapParameter.get("examRecordId");
+        if (Objects.isNull(mapParameter.get("type")) || Objects.equals(mapParameter.get("type"), "")) {
+            throw new BusinessException(ExceptionResultEnum.BREACH_TYPE_IS_NULL);
+        }
+        BreachTypeEnum type = BreachTypeEnum.valueOf(String.valueOf(mapParameter.get("type")));
+        if (Objects.isNull(mapParameter.get("description")) || Objects.equals(mapParameter.get("description"), "")) {
+            throw new BusinessException(ExceptionResultEnum.BREACH_DESC_IS_NULL);
+        }
+        String description = String.valueOf(mapParameter.get("description"));
+        if (Objects.isNull(mapParameter.get("status")) || Objects.equals(mapParameter.get("status"), "")) {
+            throw new BusinessException(ExceptionResultEnum.BREACH_STATUS_IS_NULL);
+        }
+        Integer status = Integer.parseInt(String.valueOf(mapParameter.get("status")));
+        TBUser tbUser = (TBUser) ServletUtil.getRequestAccount();
+        List<TEExamBreachLog> teExamBreachLogList = new ArrayList<>();
+        if (status == 1) {//新建违纪
+            List<TEExamBreachLog> finalTeExamBreachLogList = teExamBreachLogList;
+            recordIdList.forEach(s -> {
+                Map<String, Object> objectMap = redisUtil.getHashEntries(RedisKeyHelper.examRecordCacheKey(s));
+                Long examId = Long.parseLong(String.valueOf(objectMap.get("examId")));
+                Long examStudentId = Long.parseLong(String.valueOf(objectMap.get("examStudentId")));
+                Long examActivityId = Long.parseLong(String.valueOf(objectMap.get("examActivityId")));
+                TEExamBreachLog teExamBreachLog = new TEExamBreachLog(examId, examActivityId, s, examStudentId, type, description, status);
+                teExamBreachLog.setCreateId(tbUser.getId());
+                finalTeExamBreachLogList.add(teExamBreachLog);
+            });
+        } else {//撤销违纪
+            QueryWrapper<TEExamBreachLog> teExamBreachLogQueryWrapper = new QueryWrapper<>();
+            teExamBreachLogQueryWrapper.lambda().in(TEExamBreachLog::getExamRecordId, recordIdList);
+            teExamBreachLogList = teExamBreachLogService.list(teExamBreachLogQueryWrapper);
+            teExamBreachLogList.forEach(s -> {
+                s.setType(type);
+                s.setDescription(description);
+                s.setStatus(status);
+                s.setUpdateId(tbUser.getId());
+            });
+        }
+        teExamBreachLogService.saveOrUpdateBatch(teExamBreachLogList);
+        //todo 这里是否需要收卷处理
         return ResultUtil.ok(SystemConstant.SUCCESS);
     }
 
@@ -94,16 +150,22 @@ public class TIeInvigilateController {
     @RequestMapping(value = "/notice", method = RequestMethod.POST)
     @ApiResponses({@ApiResponse(code = 200, message = "{\"success\":true}", response = Result.class)})
     public Result notice(@ApiJsonObject(name = "invigilateNotice", value = {
-            @ApiJsonProperty(key = "recordId", description = "考试记录id"),
-            @ApiJsonProperty(key = "type", description = "消息类型,text/audio")
+            @ApiJsonProperty(key = "examRecordId", type = "long", example = "1", description = "考试记录id"),
+            @ApiJsonProperty(key = "type", description = "消息类型,text/audio"),
+            @ApiJsonProperty(key = "content", description = "消息内容")
     }) @ApiParam(value = "考试记录信息", required = true) @RequestBody Map<String, Object> mapParameter) {
-        if (Objects.isNull(mapParameter.get("recordId")) || Objects.equals(mapParameter.get("recordId"), "")) {
+        if (Objects.isNull(mapParameter.get("examRecordId")) || Objects.equals(mapParameter.get("examRecordId"), "")) {
             throw new BusinessException(ExceptionResultEnum.RECORD_ID_IS_NULL);
         }
-        Long recordId = Long.parseLong(String.valueOf(mapParameter.get("recordId")));
+        Long recordId = Long.parseLong(String.valueOf(mapParameter.get("examRecordId")));
         if (Objects.isNull(mapParameter.get("type")) || Objects.equals(mapParameter.get("type"), "")) {
-            throw new BusinessException(ExceptionResultEnum.FINISH_TYPE_IS_NULL);
+            throw new BusinessException(ExceptionResultEnum.MESSAGE_TYPE_IS_NULL);
         }
+        TBUser tbUser = (TBUser) ServletUtil.getRequestAccount();
+        //发送mq给客户端监考消息start
+        MqDto mqDto = new MqDto(MqTopicEnum.themisTopic.getCode(), MqTagEnum.oe.name(), recordId, MqEnum.WEBSOCKET_IM_CLUSTERING_LOG, String.valueOf(tbUser.getId()), mapParameter, tbUser.getName());
+        mqDtoService.assembleSendOneWayMsg(mqDto);
+        //发送mq给客户端监考消息end
         return ResultUtil.ok(SystemConstant.SUCCESS);
     }
 }

+ 1 - 1
themis-backend/src/main/resources/application.properties

@@ -160,4 +160,4 @@ prefix.url.admin=api/admin
 
 #\u65E0\u9700\u9274\u6743\u7684url
 no.auth.urls=/webjars/**,/druid/**,/swagger-ui.html,/doc.html,/swagger-resources/**,/v2/api-docs,/webjars/springfox-swagger-ui/**,/api/admin/user/login/account,/api/admin/sys/org/queryByOrgCode,/file/**,/upload/**,/client/**,/base_photo/**,/frontend/**
-common.system.urls=/api/admin/sys/getMenu,/api/admin/user/logout,/api/admin/sys/env,/api/admin/sys/file/upload,/api/admin/sys/file/download,/api/admin/sys/org/query,/api/admin/sys/role/query,/api/admin/sys/examActivity/query
+common.system.urls=/api/admin/sys/getMenu,/api/admin/user/logout,/api/admin/sys/env,/api/admin/sys/file/upload,/api/admin/sys/file/download,/api/admin/sys/org/query,/api/admin/sys/role/query,/api/admin/sys/examActivity/query,/api/admin/sys/exam/query

+ 16 - 0
themis-business/src/main/java/com/qmth/themis/business/entity/TEExamBreachLog.java

@@ -3,6 +3,7 @@ package com.qmth.themis.business.entity;
 import com.baomidou.mybatisplus.annotation.TableField;
 import com.qmth.themis.business.base.BaseEntity;
 import com.qmth.themis.business.enums.BreachTypeEnum;
+import com.qmth.themis.common.contanst.Constants;
 import io.swagger.annotations.ApiModel;
 import io.swagger.annotations.ApiModelProperty;
 
@@ -48,6 +49,21 @@ public class TEExamBreachLog extends BaseEntity {
     @TableField(value = "remark")
     private String remark;
 
+    public TEExamBreachLog(Long examId, Long examActivityId, Long examRecordId, Long examStudentId, BreachTypeEnum type, String description, Integer status) {
+        setId(Constants.idGen.next());
+        this.examId = examId;
+        this.examActivityId = examActivityId;
+        this.examRecordId = examRecordId;
+        this.examStudentId = examStudentId;
+        this.type = type;
+        this.description = description;
+        this.status = status;
+    }
+
+    public TEExamBreachLog() {
+
+    }
+
     public Long getExamId() {
         return examId;
     }

+ 3 - 3
themis-business/src/main/java/com/qmth/themis/business/service/TEExamStudentService.java

@@ -33,7 +33,7 @@ public interface TEExamStudentService extends IService<TEExamStudent> {
      */
     public IPage<TEExamStudentDto> examStudentQuery(IPage<Map> iPage, Long examId, Long activityId, String identity, String name, String roomCode, String courseCode, String grade, Integer enable);
 
-    ExamStudentCacheBean getExamStudnetCacheBean(Long examStudentId);
+    ExamStudentCacheBean getExamStudentCacheBean(Long examStudentId);
 
     /**
      * 更新考生缓存
@@ -41,12 +41,12 @@ public interface TEExamStudentService extends IService<TEExamStudent> {
      * @param examStudentId
      * @return
      */
-    ExamStudentCacheBean updateExamStudnetCacheBean(Long examStudentId);
+    ExamStudentCacheBean updateExamStudentCacheBean(Long examStudentId);
 
     /**
      * 删除考生缓存
      *
      * @param examStudentId
      */
-    void deleteExamStudnetCacheBean(Long examStudentId);
+    void deleteExamStudentCacheBean(Long examStudentId);
 }

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

@@ -140,7 +140,7 @@ public class TEExamServiceImpl extends ServiceImpl<TEExamMapper, TEExam> impleme
                     } else {
                         v.setMonitorVideoSource(null);
                     }
-                    ExamStudentCacheBean examStudentCacheBean = teExamStudentService.getExamStudnetCacheBean(v.getExamStudentId());
+                    ExamStudentCacheBean examStudentCacheBean = teExamStudentService.getExamStudentCacheBean(v.getExamStudentId());
                     v.setLeftExamCount(examStudentCacheBean.getLeftExamCount());
                 });
                 s.setActivities(teExamActivityList);
@@ -165,7 +165,7 @@ public class TEExamServiceImpl extends ServiceImpl<TEExamMapper, TEExam> impleme
     @Transactional
     @Override
     public ExamPrepareBean prepare(Long studentId, Long examStudentId) {
-        ExamStudentCacheBean es = teExamStudentService.getExamStudnetCacheBean(examStudentId);
+        ExamStudentCacheBean es = teExamStudentService.getExamStudentCacheBean(examStudentId);
         if (es == null) {
             throw new BusinessException("未找到考生");
         }

+ 3 - 3
themis-business/src/main/java/com/qmth/themis/business/service/impl/TEExamStudentServiceImpl.java

@@ -49,7 +49,7 @@ public class TEExamStudentServiceImpl extends ServiceImpl<TEExamStudentMapper, T
 
     @Cacheable(value = "exam_student", key = "#examStudentId", unless = "#result == null")
     @Override
-    public ExamStudentCacheBean getExamStudnetCacheBean(Long examStudentId) {
+    public ExamStudentCacheBean getExamStudentCacheBean(Long examStudentId) {
         return cacheOperation(examStudentId);
     }
 
@@ -61,7 +61,7 @@ public class TEExamStudentServiceImpl extends ServiceImpl<TEExamStudentMapper, T
      */
     @Override
     @CachePut(value = "exam_student", key = "#examStudentId", unless = "#result == null")
-    public ExamStudentCacheBean updateExamStudnetCacheBean(Long examStudentId) {
+    public ExamStudentCacheBean updateExamStudentCacheBean(Long examStudentId) {
         return cacheOperation(examStudentId);
     }
 
@@ -72,7 +72,7 @@ public class TEExamStudentServiceImpl extends ServiceImpl<TEExamStudentMapper, T
      */
     @Override
     @CacheEvict(value = "exam_student", key = "#examStudentId")
-    public void deleteExamStudnetCacheBean(Long examStudentId) {
+    public void deleteExamStudentCacheBean(Long examStudentId) {
 
     }
 

+ 1 - 1
themis-business/src/main/java/com/qmth/themis/business/service/impl/TOeExamRecordServiceImpl.java

@@ -337,7 +337,7 @@ public class TOeExamRecordServiceImpl extends ServiceImpl<TOeExamRecordMapper, T
         		examAnswerService.saveOrUpdate(answer);
         	}
         	//更新考生信息
-        	ExamStudentCacheBean examStudentCache = examStudentService.getExamStudnetCacheBean(er.getExamStudentId());
+        	ExamStudentCacheBean examStudentCache = examStudentService.getExamStudentCacheBean(er.getExamStudentId());
         	TEExamStudent examStudent=new TEExamStudent();
     		BeanUtils.copyProperties(examStudentCache, examStudent);
     		examStudentService.saveOrUpdate(examStudent);

+ 7 - 1
themis-business/src/main/resources/db/init.sql

@@ -476,6 +476,9 @@ INSERT INTO `t_b_privilege` VALUES (82, '考场导出', '/api/admin/invigilateUs
 INSERT INTO `t_b_privilege` VALUES (83, '任务查询', '/api/admin/task/query', 'LINK', 6, 6, NULL, '2020-08-01 12:08:31');
 INSERT INTO `t_b_privilege` VALUES (84, '考试批次详情', '/api/admin/exam/detail', 'LINK', 5, 8, NULL, '2020-08-01 12:08:31');
 INSERT INTO `t_b_privilege` VALUES (85, '学生考试记录查询', '/api/admin/student/exam_record/query', 'LINK', 8, 4, NULL, '2020-08-01 12:08:31');
+INSERT INTO `t_b_privilege` VALUES (86, '考试场次修改', '/api/admin/activity/save', 'LINK', 5, 9, NULL, '2020-08-01 12:08:31');
+INSERT INTO `t_b_privilege` VALUES (87, '监考违纪处理', '/api/admin/invigilate/breach', 'LINK', NULL, 2, NULL, '2020-08-01 12:08:31');
+INSERT INTO `t_b_privilege` VALUES (88, '监考消息通知', '/api/admin/invigilate/notice', 'LINK', NULL, 3, NULL, '2020-08-01 12:08:31');
 COMMIT;
 
 -- ----------------------------
@@ -593,6 +596,9 @@ INSERT INTO `t_b_role_privilege` VALUES (73, 'ADMIN', 82);
 INSERT INTO `t_b_role_privilege` VALUES (74, 'ADMIN', 83);
 INSERT INTO `t_b_role_privilege` VALUES (75, 'ADMIN', 84);
 INSERT INTO `t_b_role_privilege` VALUES (76, 'ADMIN', 85);
+INSERT INTO `t_b_role_privilege` VALUES (77, 'ADMIN', 86);
+INSERT INTO `t_b_role_privilege` VALUES (78, 'INVIGILATE', 87);
+INSERT INTO `t_b_role_privilege` VALUES (79, 'INVIGILATE', 88);
 COMMIT;
 
 -- ----------------------------
@@ -853,7 +859,7 @@ CREATE TABLE `t_e_exam_breach_log` (
   `type` varchar(30) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL COMMENT '类型',
   `description` mediumtext COMMENT '描述',
   `status` tinyint(4) DEFAULT NULL COMMENT '状态,0:处理,1:撤销',
-  `remark` varchar(1000) DEFAULT NULL COMMENT '备注',
+  `remark` mediumtext COMMENT '备注',
   `create_time` datetime DEFAULT NULL COMMENT '创建时间',
   `create_id` bigint(20) DEFAULT NULL COMMENT '创建人',
   `update_time` datetime DEFAULT NULL COMMENT '更新时间',

+ 6 - 0
themis-common/src/main/java/com/qmth/themis/common/enums/ExceptionResultEnum.java

@@ -120,6 +120,12 @@ public enum ExceptionResultEnum {
 
     BREACH_TYPE_IS_NULL(400, 400046, "违纪类型不能为空"),
 
+    BREACH_DESC_IS_NULL(400, 400047, "违纪描述不能为空"),
+
+    BREACH_STATUS_IS_NULL(400, 400048, "违纪状态不能为空"),
+
+    MESSAGE_TYPE_IS_NULL(400, 400049, "消息类型不能为空"),
+
     /**
      * 401
      */

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

@@ -211,7 +211,7 @@ public class TEStudentController {
             }
             ExamCacheBean ec = teExamService.getExamCacheBean(examIdMap);//考试缓存
             ExamActivityCacheBean examActivityCacheBean = teExamActivityService.getExamActivityCacheBean(examActivityId);//考试场次缓存
-            ExamStudentCacheBean examStudentCacheBean = teExamStudentService.getExamStudnetCacheBean(examStudentId);
+            ExamStudentCacheBean examStudentCacheBean = teExamStudentService.getExamStudentCacheBean(examStudentId);
 
             //获取最近同步时间
             Date clientLastSyncTime = ExamRecordCacheUtil.getClientLastSyncTime(recordId);

+ 47 - 60
themis-exam/src/main/java/com/qmth/themis/exam/listener/service/impl/MqOeLogicServiceImpl.java

@@ -3,11 +3,11 @@ package com.qmth.themis.exam.listener.service.impl;
 import com.alibaba.fastjson.JSONArray;
 import com.google.gson.Gson;
 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.entity.TMRocketMessage;
 import com.qmth.themis.business.enums.FinishTypeEnum;
 import com.qmth.themis.business.enums.MqEnum;
-import com.qmth.themis.business.enums.SystemOperationEnum;
 import com.qmth.themis.business.enums.WebsocketTypeEnum;
 import com.qmth.themis.business.service.TEExamStudentLogService;
 import com.qmth.themis.business.service.TMRocketMessageService;
@@ -15,7 +15,6 @@ import com.qmth.themis.business.util.JacksonUtil;
 import com.qmth.themis.business.util.RedisUtil;
 import com.qmth.themis.exam.listener.service.MqOeLogicService;
 import com.qmth.themis.exam.websocket.WebSocketOeServer;
-import com.qmth.themis.business.dto.MqDto;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.stereotype.Service;
@@ -101,73 +100,61 @@ public class MqOeLogicServiceImpl implements MqOeLogicService {
 //        } else
         if (MqEnum.WEBSOCKET_MONITOR_FINISH_LOG.ordinal() == mqEnum.ordinal()) {//强制离线交卷
             Set examRecordId = JacksonUtil.readJson(String.valueOf(mqDto.getBody()), Set.class);
-                examRecordId.forEach(s -> {
-                    Long recordId = Long.parseLong(String.valueOf(s));
-                    if (Objects.nonNull(webSocketMap.get(recordId))) {
-                        WebSocketOeServer webSocketOeServer = webSocketMap.get(recordId);
-                        Map map = new HashMap<>();
-                        map.put("form", mqDto.getObjName());
-                        map.put(SystemConstant.RECORD_ID, recordId);
-                        map.put(SystemConstant.MESSAGE, FinishTypeEnum.valueOf(String.valueOf(mqDto.getProperties().get("type"))).getCode());
-                        WebsocketDto websocketDto = new WebsocketDto(WebsocketTypeEnum.INVIGILATE_STOP_EXAM.name(), map);
-                        webSocketOeServer.sendMessage(websocketDto);
-                    }
-                });
+            examRecordId.forEach(s -> {
+                Long recordId = Long.parseLong(String.valueOf(s));
+                if (Objects.nonNull(webSocketMap.get(recordId))) {
+                    WebSocketOeServer webSocketOeServer = webSocketMap.get(recordId);
+                    Map map = new HashMap<>();
+                    map.put("form", mqDto.getObjName());
+                    map.put(SystemConstant.RECORD_ID, recordId);
+                    map.put(SystemConstant.MESSAGE, FinishTypeEnum.valueOf(String.valueOf(mqDto.getProperties().get("type"))).getCode());
+                    WebsocketDto websocketDto = new WebsocketDto(WebsocketTypeEnum.INVIGILATE_STOP_EXAM.name(), map);
+                    webSocketOeServer.sendMessage(websocketDto);
+                }
+            });
         } else if (MqEnum.WEBSOCKET_HAND_FINISH_LOG.ordinal() == mqEnum.ordinal()) {//手动交卷
             Set examRecordId = JacksonUtil.readJson(String.valueOf(mqDto.getBody()), Set.class);
-                examRecordId.forEach(s -> {
-                    Long recordId = Long.parseLong(String.valueOf(s));
-                    if (Objects.nonNull(webSocketMap.get(recordId))) {
-                        WebSocketOeServer webSocketOeServer = webSocketMap.get(recordId);
-                        Map map = new HashMap<>();
-                        map.put(SystemConstant.RECORD_ID, recordId);
-                        map.put(SystemConstant.MESSAGE, FinishTypeEnum.valueOf(String.valueOf(mqDto.getProperties().get("type"))).getCode());
-                        WebsocketDto websocketDto = new WebsocketDto(WebsocketTypeEnum.HAND_STOP_EXAM.name(), map);
-                        webSocketOeServer.sendMessage(websocketDto);
-                    }
-                });
+            examRecordId.forEach(s -> {
+                Long recordId = Long.parseLong(String.valueOf(s));
+                if (Objects.nonNull(webSocketMap.get(recordId))) {
+                    WebSocketOeServer webSocketOeServer = webSocketMap.get(recordId);
+                    Map map = new HashMap<>();
+                    map.put(SystemConstant.RECORD_ID, recordId);
+                    map.put(SystemConstant.MESSAGE, FinishTypeEnum.valueOf(String.valueOf(mqDto.getProperties().get("type"))).getCode());
+                    WebsocketDto websocketDto = new WebsocketDto(WebsocketTypeEnum.HAND_STOP_EXAM.name(), map);
+                    webSocketOeServer.sendMessage(websocketDto);
+                }
+            });
         } else if (MqEnum.WEBSOCKET_WARNING_FINISH_LOG.ordinal() == mqEnum.ordinal()) {//预警交卷
             Set examRecordId = JacksonUtil.readJson(String.valueOf(mqDto.getBody()), Set.class);
-                examRecordId.forEach(s -> {
-                    Long recordId = Long.parseLong(String.valueOf(s));
-                    if (Objects.nonNull(webSocketMap.get(recordId))) {
-                        WebSocketOeServer webSocketOeServer = webSocketMap.get(recordId);
-                        Map map = new HashMap<>();
-                        map.put(SystemConstant.RECORD_ID, recordId);
-                        map.put(SystemConstant.BREACH_STATUS, FinishTypeEnum.valueOf(String.valueOf(mqDto.getProperties().get("type"))).getCode());
-                        WebsocketDto websocketDto = new WebsocketDto(WebsocketTypeEnum.BREACH_STOP_EXAM.name(), map);
-                        webSocketOeServer.sendMessage(websocketDto);
-                    }
-                });
+            examRecordId.forEach(s -> {
+                Long recordId = Long.parseLong(String.valueOf(s));
+                if (Objects.nonNull(webSocketMap.get(recordId))) {
+                    WebSocketOeServer webSocketOeServer = webSocketMap.get(recordId);
+                    Map map = new HashMap<>();
+                    map.put(SystemConstant.RECORD_ID, recordId);
+                    map.put(SystemConstant.BREACH_STATUS, FinishTypeEnum.valueOf(String.valueOf(mqDto.getProperties().get("type"))).getCode());
+                    WebsocketDto websocketDto = new WebsocketDto(WebsocketTypeEnum.BREACH_STOP_EXAM.name(), map);
+                    webSocketOeServer.sendMessage(websocketDto);
+                }
+            });
         } else if (MqEnum.WEBSOCKET_IM_CLUSTERING_LOG.ordinal() == mqEnum.ordinal()) {//点对点消息
-            JSONArray jsonArray = JSONArray.parseArray(String.valueOf(mqDto.getBody()));
-            Set<String> examStudentIdentitySet = jsonArray.toJavaObject(Set.class);
-            log.info("examStudentIdentitySet:{}", JacksonUtil.parseJson(examStudentIdentitySet));
-//            webSocketMap.forEach((k, v) -> {
-//                examStudentIdentitySet.forEach(s -> {
-//                    if (k.contains(s)) {
-//                        Map map = new HashMap<>();
-//                        map.put("message", k);
-//                        WebsocketDto websocketDto = new WebsocketDto("message", map);
-//                        v.sendMessage(websocketDto);
-//                        return;
-//                    }
-//                });
-//            });
+            Long recordId = Long.parseLong(String.valueOf(mqDto.getBody()));
+            if (Objects.nonNull(webSocketMap.get(recordId))) {
+                WebSocketOeServer webSocketOeServer = webSocketMap.get(recordId);
+                Map<String, Object> prop = mqDto.getProperties();
+                Map map = new HashMap<>();
+                map.put(SystemConstant.RECORD_ID, prop.get("examRecordId"));
+                map.put("from", mqDto.getObjName());
+                map.put("type", prop.get("type"));
+                map.put("content", prop.get("content"));
+                WebsocketDto websocketDto = new WebsocketDto(WebsocketTypeEnum.INVIGILATE_NOTICE.name(), map);
+                webSocketOeServer.sendMessage(websocketDto);
+            }
         } else if (MqEnum.WEBSOCKET_IM_BROADCASTING_LOG.ordinal() == mqEnum.ordinal()) {//广播消息
             JSONArray jsonArray = JSONArray.parseArray(String.valueOf(mqDto.getBody()));
             Set<String> examStudentIdentitySet = jsonArray.toJavaObject(Set.class);
             log.info("examStudentIdentitySet:{}", JacksonUtil.parseJson(examStudentIdentitySet));
-//            webSocketMap.forEach((k, v) -> {
-//                examStudentIdentitySet.forEach(s -> {
-//                    if (k.contains(s)) {
-//                        Map map = new HashMap<>();
-//                        map.put("message", k);
-//                        WebsocketDto websocketDto = new WebsocketDto("message", map);
-//                        v.sendMessage(websocketDto);
-//                    }
-//                });
-//            });
         }
         mqDto.setAck(SystemConstant.STANDARD_ACK_TYPE);
         teExamStudentLogService.saveStudentLogInfo(mqDto.getTimestamp(), MqEnum.valueOf(String.valueOf(mqDto.getType())).getId(), mqDto.getType().getCode(), JacksonUtil.parseJson(mqDto));

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

@@ -68,7 +68,7 @@ public class QuartzLogicServiceImpl implements QuartzLogicService {
         QueryWrapper<TEExamActivity> teExamActivityQueryWrapper = new QueryWrapper<>();
         teExamActivityQueryWrapper.lambda().eq(TEExamActivity::getCode, strings[1]);
         TEExamActivity teExamActivity = teExamActivityService.getOne(teExamActivityQueryWrapper);
-        if (Objects.nonNull(teExamActivity)) {
+        if (Objects.nonNull(teExamActivity) && teExamActivity.getEnable() == 1) {
             //TODO 获取该考试批次下所有考生
             //获取该考试批次下所有未交卷的考生的考试记录
 //            QueryWrapper<TOeExamRecord> tOeExamRecordQueryWrapper = new QueryWrapper<>();