wangliang 4 anos atrás
pai
commit
53f07ae499
19 arquivos alterados com 290 adições e 44 exclusões
  1. BIN
      .DS_Store
  2. 33 0
      themis-backend/src/main/java/com/qmth/themis/backend/api/TIeInvigilateCallMobileController.java
  3. 1 0
      themis-business/src/main/java/com/qmth/themis/business/constant/SystemConstant.java
  4. 25 0
      themis-business/src/main/java/com/qmth/themis/business/entity/TIeExamInvigilateCall.java
  5. 149 14
      themis-business/src/main/java/com/qmth/themis/business/entity/TIeExamInvigilateCallLog.java
  6. 1 1
      themis-business/src/main/java/com/qmth/themis/business/enums/ExamTypeEnum.java
  7. 2 2
      themis-business/src/main/java/com/qmth/themis/business/enums/FinishTypeEnum.java
  8. 1 1
      themis-business/src/main/java/com/qmth/themis/business/enums/LivenessTypeEnum.java
  9. 2 0
      themis-business/src/main/java/com/qmth/themis/business/enums/MonitorCallStatusSourceEnum.java
  10. 13 6
      themis-business/src/main/java/com/qmth/themis/business/enums/WarningLevelEnum.java
  11. 13 0
      themis-business/src/main/java/com/qmth/themis/business/service/impl/TEExamServiceImpl.java
  12. 7 8
      themis-business/src/main/java/com/qmth/themis/business/service/impl/WarningServiceImpl.java
  13. 2 0
      themis-business/src/main/resources/db/init.sql
  14. 0 3
      themis-business/src/main/resources/mapper/TOeExamRecordMapper.xml
  15. 3 1
      themis-common/src/main/java/com/qmth/themis/common/enums/ExceptionResultEnum.java
  16. 2 1
      themis-exam/src/main/java/com/qmth/themis/exam/api/TIeInvigilateCallMobileController.java
  17. 2 1
      themis-exam/src/main/java/com/qmth/themis/exam/api/TIeInvigilateCallOeController.java
  18. BIN
      themis-mq/src/main/java/com/qmth/themis/mq/service/.DS_Store
  19. 34 6
      themis-mq/src/main/java/com/qmth/themis/mq/service/impl/MqLogicServiceImpl.java

BIN
.DS_Store


+ 33 - 0
themis-backend/src/main/java/com/qmth/themis/backend/api/TIeInvigilateCallMobileController.java

@@ -127,6 +127,38 @@ public class TIeInvigilateCallMobileController {
         return ResultUtil.ok(tIeExamInvigilateCallService.list(tIeExamInvigilateCallQueryWrapper));
     }
 
+    @ApiOperation(value = "通话中接口")
+    @RequestMapping(value = "/call/calling", method = RequestMethod.POST)
+    @ApiResponses({@ApiResponse(code = 200, message = "{\"success\":true}", response = Result.class)})
+    @Transactional
+    public Result callCalling(@ApiJsonObject(name = "callCallingBackendMobile", value = {
+            @ApiJsonProperty(key = "recordId", type = "long", example = "1", description = "考试记录id", required = true),
+            @ApiJsonProperty(key = "source", description = "监考视频源", required = true)
+    }) @ApiParam(value = "监控信息", required = true) @RequestBody Map<String, Object> mapParameter) {
+        if (Objects.isNull(mapParameter.get("recordId")) || Objects.equals(mapParameter.get("recordId"), "")) {
+            throw new BusinessException(ExceptionResultEnum.RECORD_ID_IS_NULL);
+        }
+        Long recordId = Long.parseLong(String.valueOf(mapParameter.get("recordId")));
+        if (Objects.isNull(mapParameter.get("source")) || Objects.equals(mapParameter.get("source"), "")) {
+            throw new BusinessException("来源不能为空!");
+        }
+        MonitorVideoSourceEnum source = MonitorVideoSourceEnum.valueOf(String.valueOf(mapParameter.get("source")));
+        //获取考试记录缓存
+        String liveUrl = null;
+        if (Objects.isNull(ExamRecordCacheUtil.getMonitorStatus(recordId, source.name()))) {
+            throw new BusinessException("推流状态为空");
+        }
+        ExamRecordCacheUtil.setMonitorCallStatus(recordId, source.name(), MonitorCallStatusSourceEnum.CALLING);
+        String monitorKey = ExamRecordCacheUtil.getMonitorKey(recordId);
+        MonitorStatusSourceEnum status = ExamRecordCacheUtil.getMonitorStatus(recordId, source.name());
+        TIeExamInvigilateCallLog tIeExamInvigilateCallLog = new TIeExamInvigilateCallLog(recordId, source, liveUrl, status, monitorKey, MonitorCallStatusSourceEnum.CALLING);
+        //监考监控通话信息 发送mq start
+        MqDto mqDto = new MqDto(MqTopicEnum.THEMIS_TOPIC.getCode(), MqTagEnum.MONITOR_LOG.name(), tIeExamInvigilateCallLog, MqTagEnum.MONITOR_LOG, String.valueOf(tIeExamInvigilateCallLog.getId()), source.name());
+        mqDtoService.assembleSendOneWayMsg(mqDto);
+        //监考监控通话信息 发送mq end
+        return ResultUtil.ok(Collections.singletonMap("success", true));
+    }
+
     @ApiOperation(value = "撤销通话申请接口")
     @RequestMapping(value = "/call/cancel", method = RequestMethod.POST)
     @ApiResponses({@ApiResponse(code = 200, message = "{\"success\":true}", response = Result.class)})
@@ -152,6 +184,7 @@ public class TIeInvigilateCallMobileController {
         String monitorKey = ExamRecordCacheUtil.getMonitorKey(recordId);
         MonitorStatusSourceEnum status = ExamRecordCacheUtil.getMonitorStatus(recordId, source.name());
         TIeExamInvigilateCallLog tIeExamInvigilateCallLog = new TIeExamInvigilateCallLog(recordId, source, liveUrl, status, monitorKey, MonitorCallStatusSourceEnum.STOP);
+        tIeExamInvigilateCallLog.setEndTime(System.currentTimeMillis());
         //监考监控通话信息 发送mq start
         MqDto mqDto = new MqDto(MqTopicEnum.THEMIS_TOPIC.getCode(), MqTagEnum.MONITOR_LOG.name(), tIeExamInvigilateCallLog, MqTagEnum.MONITOR_LOG, String.valueOf(tIeExamInvigilateCallLog.getId()), source.name());
         mqDtoService.assembleSendOneWayMsg(mqDto);

+ 1 - 0
themis-business/src/main/java/com/qmth/themis/business/constant/SystemConstant.java

@@ -125,6 +125,7 @@ public class SystemConstant {
     /**
      * rocket mq
      */
+    public static final String MQDTO_OBJ = "mqDtoObj";
     public static final int CONSUME_MESSAGE_BATCH_MAX_SIZE = 10;
     public static final int MAXRECONSUMETIMES = 3;
     //    public static final String MQDTO_OBJ = "mqDtoObj";

+ 25 - 0
themis-business/src/main/java/com/qmth/themis/business/entity/TIeExamInvigilateCall.java

@@ -1,5 +1,6 @@
 package com.qmth.themis.business.entity;
 
+import com.baomidou.mybatisplus.annotation.FieldFill;
 import com.baomidou.mybatisplus.annotation.TableField;
 import com.fasterxml.jackson.databind.annotation.JsonSerialize;
 import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
@@ -66,6 +67,14 @@ public class TIeExamInvigilateCall extends BaseEntity {
     @TableField(value = "monitor_key")
     private String monitorKey;
 
+    @TableField(value = "start_time")
+    @ApiModelProperty(value = "开始通话时间")
+    private Long startTime;
+
+    @TableField(value = "end_time")
+    @ApiModelProperty(value = "结束通话时间")
+    private Long endTime;
+
     public TIeExamInvigilateCall() {
 
     }
@@ -79,6 +88,22 @@ public class TIeExamInvigilateCall extends BaseEntity {
         this.monitorKey = monitorKey;
     }
 
+    public Long getStartTime() {
+        return startTime;
+    }
+
+    public void setStartTime(Long startTime) {
+        this.startTime = startTime;
+    }
+
+    public Long getEndTime() {
+        return endTime;
+    }
+
+    public void setEndTime(Long endTime) {
+        this.endTime = endTime;
+    }
+
     public MonitorCallStatusSourceEnum getCallStatus() {
         return callStatus;
     }

+ 149 - 14
themis-business/src/main/java/com/qmth/themis/business/entity/TIeExamInvigilateCallLog.java

@@ -1,6 +1,10 @@
 package com.qmth.themis.business.entity;
 
 import com.baomidou.mybatisplus.annotation.TableField;
+import com.fasterxml.jackson.databind.annotation.JsonSerialize;
+import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
+import com.qmth.themis.business.base.BaseEntity;
+import com.qmth.themis.business.enums.ExceptionEnum;
 import com.qmth.themis.business.enums.MonitorCallStatusSourceEnum;
 import com.qmth.themis.business.enums.MonitorStatusSourceEnum;
 import com.qmth.themis.business.enums.MonitorVideoSourceEnum;
@@ -16,12 +20,64 @@ import io.swagger.annotations.ApiModelProperty;
  * @Date: 2020/8/7
  */
 @ApiModel(value = "t_ie_exam_invigilate_call_log", description = "监控观看地址和通话申请日志")
-public class TIeExamInvigilateCallLog extends TIeExamInvigilateCall {
+public class TIeExamInvigilateCallLog extends BaseEntity {
+
+    @JsonSerialize(using = ToStringSerializer.class)
+    @ApiModelProperty(value = "考试记录ID")
+    @TableField(value = "exam_record_id")
+    private Long examRecordId;
+
+    @JsonSerialize(using = ToStringSerializer.class)
+    @ApiModelProperty(value = "考试ID")
+    @TableField(value = "exam_id")
+    private Long examId;
+
+    @JsonSerialize(using = ToStringSerializer.class)
+    @ApiModelProperty(value = "场次ID")
+    @TableField(value = "exam_activity_id")
+    private Long examActivityId;
+
+    @JsonSerialize(using = ToStringSerializer.class)
+    @ApiModelProperty(value = "考生ID")
+    @TableField(value = "exam_student_id")
+    private Long examStudentId;
+
+    @ApiModelProperty(value = "监考视频源")
+    @TableField(value = "source")
+    private MonitorVideoSourceEnum source;
+
+    @ApiModelProperty(value = "观看地址")
+    @TableField(value = "live_url")
+    private String liveUrl;
+
+    @ApiModelProperty(value = "状态")
+    @TableField(value = "status")
+    private MonitorStatusSourceEnum status;
+
+    @ApiModelProperty(value = "异常类型")
+    @TableField(value = "type")
+    private ExceptionEnum type;
+
+    @ApiModelProperty(value = "通话状态")
+    @TableField(value = "call_status")
+    private MonitorCallStatusSourceEnum callStatus;
+
+    @ApiModelProperty(value = "房间号")
+    @TableField(value = "monitor_key")
+    private String monitorKey;
 
     @ApiModelProperty(value = "备注")
     @TableField(value = "remark")
     private String remark;
 
+    @TableField(exist = false)
+    @ApiModelProperty(value = "开始通话时间")
+    private Long startTime;
+
+    @TableField(exist = false)
+    @ApiModelProperty(value = "结束通话时间")
+    private Long endTime;
+
     public TIeExamInvigilateCallLog() {
 
     }
@@ -45,21 +101,100 @@ public class TIeExamInvigilateCallLog extends TIeExamInvigilateCall {
         setMonitorKey(monitorKey);
     }
 
-    public TIeExamInvigilateCallLog(Long examRecordId, MonitorVideoSourceEnum source, String liveUrl) {
-        setId(Constants.idGen.next());
-        setExamRecordId(examRecordId);
-        setSource(source);
-        setLiveUrl(liveUrl);
+    public Long getStartTime() {
+        return startTime;
     }
 
-    public TIeExamInvigilateCallLog(Long examRecordId, MonitorVideoSourceEnum source, String liveUrl, MonitorStatusSourceEnum status, String remark, String monitorKey) {
-        setId(Constants.idGen.next());
-        setExamRecordId(examRecordId);
-        setSource(source);
-        setLiveUrl(liveUrl);
-        setStatus(status);
-        this.remark = remark;
-        setMonitorKey(monitorKey);
+    public void setStartTime(Long startTime) {
+        this.startTime = startTime;
+    }
+
+    public Long getEndTime() {
+        return endTime;
+    }
+
+    public void setEndTime(Long endTime) {
+        this.endTime = endTime;
+    }
+
+    public Long getExamRecordId() {
+        return examRecordId;
+    }
+
+    public void setExamRecordId(Long examRecordId) {
+        this.examRecordId = examRecordId;
+    }
+
+    public Long getExamId() {
+        return examId;
+    }
+
+    public void setExamId(Long examId) {
+        this.examId = examId;
+    }
+
+    public Long getExamActivityId() {
+        return examActivityId;
+    }
+
+    public void setExamActivityId(Long examActivityId) {
+        this.examActivityId = examActivityId;
+    }
+
+    public Long getExamStudentId() {
+        return examStudentId;
+    }
+
+    public void setExamStudentId(Long examStudentId) {
+        this.examStudentId = examStudentId;
+    }
+
+    public MonitorVideoSourceEnum getSource() {
+        return source;
+    }
+
+    public void setSource(MonitorVideoSourceEnum source) {
+        this.source = source;
+    }
+
+    public String getLiveUrl() {
+        return liveUrl;
+    }
+
+    public void setLiveUrl(String liveUrl) {
+        this.liveUrl = liveUrl;
+    }
+
+    public MonitorStatusSourceEnum getStatus() {
+        return status;
+    }
+
+    public void setStatus(MonitorStatusSourceEnum status) {
+        this.status = status;
+    }
+
+    public ExceptionEnum getType() {
+        return type;
+    }
+
+    public void setType(ExceptionEnum type) {
+        this.type = type;
+    }
+
+    public MonitorCallStatusSourceEnum getCallStatus() {
+        return callStatus;
+    }
+
+    public void setCallStatus(MonitorCallStatusSourceEnum callStatus) {
+        this.callStatus = callStatus;
+    }
+
+    public String getMonitorKey() {
+        return monitorKey;
+    }
+
+    public void setMonitorKey(String monitorKey) {
+        this.monitorKey = monitorKey;
     }
 
     public String getRemark() {

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

@@ -9,7 +9,7 @@ package com.qmth.themis.business.enums;
 */ 
 public enum ExamTypeEnum {
 
-	FIRST_START("次开考"),
+	FIRST_START("次开考"),
 
 	RESUME_START("恢复开考"),
 

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

@@ -9,9 +9,9 @@ package com.qmth.themis.business.enums;
 */
 public enum FinishTypeEnum {
 
-	MANUAL("手动"),
+	MANUAL("手动交卷"),
 
-    AUTO("自动"),
+    AUTO("自动交卷"),
 
     BREACH("违纪交卷"),
 

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

@@ -11,7 +11,7 @@ public enum LivenessTypeEnum {
 
 	FIRST_START("首次开考"),
 
-	RESUME_START("断点恢复"), IN_PROCESS("过程中"), WARNING_AUTO("预警自动加入"), INVIGILATE_MANUAL("监考手工加入");
+	RESUME_START("恢复开考"), IN_PROCESS("过程中"), WARNING_AUTO("预警自动加入"), INVIGILATE_MANUAL("监考手工加入");
 
 	private String title;
 

+ 2 - 0
themis-business/src/main/java/com/qmth/themis/business/enums/MonitorCallStatusSourceEnum.java

@@ -11,6 +11,8 @@ public enum MonitorCallStatusSourceEnum {
 
     STOP("停止"),
 
+    CALLING("通话中"),
+
     START("正常");
 
     private String code;

+ 13 - 6
themis-business/src/main/java/com/qmth/themis/business/enums/WarningLevelEnum.java

@@ -9,23 +9,30 @@ package com.qmth.themis.business.enums;
  */
 public enum WarningLevelEnum {
 
-    D4("一个考试场次中未检测到人脸或有违规动作(左顾右盼、低头、转身、离开座位、人脸移除、遮挡等)次数超过3次(持续30秒连续帧画面违规记为次数1次)"),
+    D4("一个考试场次中未检测到人脸或有违规动作(左顾右盼、低头、转身、离开座位、人脸移除、遮挡等)次数超过3次(持续30秒连续帧画面违规记为次数1次)","【疑似违规动作】考生较长时间离座或持续有违规动作"),
 
-    D8("一个考试场次中检测到多张人脸超过3次(持续15秒连续帧画面90%存在多张人脸记为次数1次)"),
+    D8("一个考试场次中检测到多张人脸超过3次(持续15秒连续帧画面90%存在多张人脸记为次数1次)","【疑似求助第三方】系统多次检测到镜头里有除考生之外的多张人脸"),
 
-    D6("一个考试场次中检测到人脸与底照不符次数超过3次(持续30秒连续帧画面90%比对底照不符记为次数1次)"),
+    D6("一个考试场次中检测到人脸与底照不符次数超过3次(持续30秒连续帧画面90%比对底照不符记为次数1次)","【疑似替考】系统多次检测到当前考生身份不符"),
 
-    D14("一个考试场次内人脸抓拍检测(D12)失败累计次数超过6次"),
+    D14("一个考试场次内人脸抓拍检测(D12)失败累计次数超过6次","疑似采用照片】系统检测到考生疑似在镜头前采用照片"),
 
-    D15("真实性检测失败1次以上");
+    D15("真实性检测失败1次以上","【疑似采用照片或虚拟摄像头】系统随机真实性检测失败");
 
     private String desc;
 
-    private WarningLevelEnum(String desc) {
+    private String title;
+
+    private WarningLevelEnum(String desc,String title) {
         this.desc = desc;
+        this.title = title;
     }
 
     public String getDesc() {
         return desc;
     }
+
+    public String getTitle() {
+        return title;
+    }
 }

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

@@ -26,6 +26,7 @@ import java.util.stream.Collectors;
 
 import javax.annotation.Resource;
 
+import com.qmth.themis.common.enums.ExceptionResultEnum;
 import org.apache.commons.codec.digest.DigestUtils;
 import org.apache.commons.lang3.StringUtils;
 import org.springframework.beans.BeanUtils;
@@ -278,6 +279,10 @@ public class TEExamServiceImpl extends ServiceImpl<TEExamMapper, TEExam> impleme
         if (!studentId.equals(es.getStudentId())) {
             throw new BusinessException("考生Id和当前登录用户不一致");
         }
+        //停用
+        if (es.getEnable().intValue() == 0) {
+            throw new BusinessException(ExceptionResultEnum.EXAM_STUDENT_ENABLE);
+        }
         ExamCacheBean examCache = getExamCacheBeanNative(es.getExamId());
 
         checkIp(examCache);
@@ -440,6 +445,10 @@ public class TEExamServiceImpl extends ServiceImpl<TEExamMapper, TEExam> impleme
         if (!studentId.equals(es.getStudentId())) {
             throw new BusinessException("考试记录的学生Id和当前登录用户不一致");
         }
+        //停用
+        if (es.getEnable().intValue() == 0) {
+            throw new BusinessException(ExceptionResultEnum.EXAM_STUDENT_ENABLE);
+        }
         ExamCacheBean exam = getExamCacheBeanNative(es.getExamId());
         Long activityId = es.getExamActivityId();
         ExamActivityCacheBean ac = teExamActivityService.getExamActivityCacheBean(activityId);
@@ -799,6 +808,10 @@ public class TEExamServiceImpl extends ServiceImpl<TEExamMapper, TEExam> impleme
         if (!studentId.equals(es.getStudentId())) {
             throw new BusinessException("考试记录的学生Id和当前登录用户不一致");
         }
+        //停用
+        if (es.getEnable().intValue() == 0) {
+            throw new BusinessException(ExceptionResultEnum.EXAM_STUDENT_ENABLE);
+        }
         Long examId = ExamRecordCacheUtil.getExamId(recordId);
         ExamCacheBean ec = getExamCacheBeanNative(examId);//考试缓存
         

+ 7 - 8
themis-business/src/main/java/com/qmth/themis/business/service/impl/WarningServiceImpl.java

@@ -13,7 +13,6 @@ import com.qmth.themis.business.enums.ExamTypeEnum;
 import com.qmth.themis.business.enums.VerifyExceptionEnum;
 import com.qmth.themis.business.enums.WarningLevelEnum;
 import com.qmth.themis.business.service.*;
-import com.qmth.themis.business.util.RedisUtil;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.stereotype.Service;
@@ -71,7 +70,7 @@ public class WarningServiceImpl implements WarningService {
                 Integer count = Integer.parseInt(String.valueOf(map.get("tmpCount")));
                 count = Objects.isNull(count) ? 0 : count;
                 if (count >= teConfig.getMultipleFaceCountError()) {
-                    TIeInvigilateWarnInfo tIeInvigilateWarnInfo = new TIeInvigilateWarnInfo(examId, examActivityId, recordId, examStudentId, warningEnum.getLevel().get(1), WarningLevelEnum.valueOf(warningEnum.getLevel().get(1)).getDesc(), warningEnum, photoUrl);
+                    TIeInvigilateWarnInfo tIeInvigilateWarnInfo = new TIeInvigilateWarnInfo(examId, examActivityId, recordId, examStudentId, warningEnum.getLevel().get(1), WarningLevelEnum.valueOf(warningEnum.getLevel().get(1)).getTitle(), warningEnum, photoUrl);
                     tIeInvigilateWarnInfoService.saveOrUpdate(tIeInvigilateWarnInfo);
                     this.setWarningCount(recordId);
                     this.setPhotoUrls(map, photoUrl, tIeInvigilateWarnInfo, examStudentCacheBean, recordId);
@@ -83,7 +82,7 @@ public class WarningServiceImpl implements WarningService {
                 Integer count = Integer.parseInt(String.valueOf(map.get("tmpCount")));
                 count = Objects.isNull(count) ? 0 : count;
                 if (count >= teConfig.getNoFaceCountError()) {
-                    TIeInvigilateWarnInfo tIeInvigilateWarnInfo = new TIeInvigilateWarnInfo(examId, examActivityId, recordId, examStudentId, warningEnum.getLevel().get(0), WarningLevelEnum.valueOf(warningEnum.getLevel().get(0)).getDesc(), warningEnum, photoUrl);
+                    TIeInvigilateWarnInfo tIeInvigilateWarnInfo = new TIeInvigilateWarnInfo(examId, examActivityId, recordId, examStudentId, warningEnum.getLevel().get(0), WarningLevelEnum.valueOf(warningEnum.getLevel().get(0)).getTitle(), warningEnum, photoUrl);
                     tIeInvigilateWarnInfoService.saveOrUpdate(tIeInvigilateWarnInfo);
                     this.setWarningCount(recordId);
                     this.setPhotoUrls(map, photoUrl, tIeInvigilateWarnInfo, examStudentCacheBean, recordId);
@@ -113,13 +112,13 @@ public class WarningServiceImpl implements WarningService {
             Integer count = Integer.parseInt(String.valueOf(map.get("tmpCount")));
             count = Objects.isNull(count) ? 0 : count;
             if (count >= teConfig.getMatchFaceCompareErrorCount()) {
-                TIeInvigilateWarnInfo tIeInvigilateWarnInfo = new TIeInvigilateWarnInfo(examId, examActivityId, recordId, examStudentId, warningEnum.getLevel().get(0), WarningLevelEnum.valueOf(warningEnum.getLevel().get(0)).getDesc(), warningEnum, photoUrl);
+                TIeInvigilateWarnInfo tIeInvigilateWarnInfo = new TIeInvigilateWarnInfo(examId, examActivityId, recordId, examStudentId, warningEnum.getLevel().get(0), WarningLevelEnum.valueOf(warningEnum.getLevel().get(0)).getTitle(), warningEnum, photoUrl);
                 tIeInvigilateWarnInfoService.saveOrUpdate(tIeInvigilateWarnInfo);
                 this.setWarningCount(recordId);
                 this.setPhotoUrls(map, photoUrl, tIeInvigilateWarnInfo, examStudentCacheBean, recordId);
             }
             if (count >= teConfig.getTotalFaceCompareErrorCount()) {
-                TIeInvigilateWarnInfo tIeInvigilateWarnInfo = new TIeInvigilateWarnInfo(examId, examActivityId, recordId, examStudentId, warningEnum.getLevel().get(1), WarningLevelEnum.valueOf(warningEnum.getLevel().get(1)).getDesc(), warningEnum, photoUrl);
+                TIeInvigilateWarnInfo tIeInvigilateWarnInfo = new TIeInvigilateWarnInfo(examId, examActivityId, recordId, examStudentId, warningEnum.getLevel().get(1), WarningLevelEnum.valueOf(warningEnum.getLevel().get(1)).getTitle(), warningEnum, photoUrl);
                 tIeInvigilateWarnInfoService.saveOrUpdate(tIeInvigilateWarnInfo);
                 this.setWarningCount(recordId);
                 this.setPhotoUrls(map, photoUrl, tIeInvigilateWarnInfo, examStudentCacheBean, recordId);
@@ -166,10 +165,10 @@ public class WarningServiceImpl implements WarningService {
         ExamStudentCacheBean examStudentCacheBean = teExamStudentService.getExamStudentCacheBean(examStudentId);
         int count = faceVerifyHistoryService.count(tOeFaceVerifyHistoryQueryWrapper);
         if (count > teConfig.getRealnessCount()) {
-            TIeInvigilateWarnInfo tIeInvigilateWarnInfo = new TIeInvigilateWarnInfo(examId, examActivityId, recordId, examStudentId, WarningLevelEnum.D15.name(), WarningLevelEnum.D15.getDesc(), warningEnum);
+            TIeInvigilateWarnInfo tIeInvigilateWarnInfo = new TIeInvigilateWarnInfo(examId, examActivityId, recordId, examStudentId, WarningLevelEnum.D15.name(), WarningLevelEnum.D15.getTitle(), warningEnum);
             tIeInvigilateWarnInfoService.saveOrUpdate(tIeInvigilateWarnInfo);
             this.setWarningCount(recordId);
-            TEExamStudentLog teExamStudentLog = new TEExamStudentLog(tIeInvigilateWarnInfo.getType().name(), tIeInvigilateWarnInfo.getType().getCode(), tIeInvigilateWarnInfo.getType().getCode(), examStudentCacheBean.getStudentId(), examStudentCacheBean.getId(), recordId);
+            TEExamStudentLog teExamStudentLog = new TEExamStudentLog(tIeInvigilateWarnInfo.getType().name(), WarningLevelEnum.valueOf(tIeInvigilateWarnInfo.getLevel()).getTitle(), tIeInvigilateWarnInfo.getType().getCode(), examStudentCacheBean.getStudentId(), examStudentCacheBean.getId(), recordId);
             teExamStudentLogService.saveOrUpdate(teExamStudentLog);
         }
     }
@@ -208,7 +207,7 @@ public class WarningServiceImpl implements WarningService {
         JSONObject jsonObject = new JSONObject();
         jsonObject.put("PHOTOS", photoUrls);
         jsonObject.put("MIN_CREATE_TIME", map.get("createTime"));
-        TEExamStudentLog teExamStudentLog = new TEExamStudentLog(tIeInvigilateWarnInfo.getType().name(), tIeInvigilateWarnInfo.getType().getCode(), jsonObject.toJSONString(), examStudentCacheBean.getStudentId(), examStudentCacheBean.getId(), recordId);
+        TEExamStudentLog teExamStudentLog = new TEExamStudentLog(tIeInvigilateWarnInfo.getType().name(), WarningLevelEnum.valueOf(tIeInvigilateWarnInfo.getLevel()).getTitle(), jsonObject.toJSONString(), examStudentCacheBean.getStudentId(), examStudentCacheBean.getId(), recordId);
         teExamStudentLogService.saveOrUpdate(teExamStudentLog);
     }
 }

+ 2 - 0
themis-business/src/main/resources/db/init.sql

@@ -1200,6 +1200,8 @@ CREATE TABLE `t_ie_exam_invigilate_call` (
   `type` varchar(100) DEFAULT NULL COMMENT '异常类型',
   `call_status` varchar(30) DEFAULT NULL COMMENT '通话状态',
   `monitor_key` varchar(50) DEFAULT NULL COMMENT '房间号',
+  `start_time` bigint DEFAULT NULL COMMENT '开始通话时间',
+  `end_time` bigint DEFAULT NULL COMMENT '结束通话时间',
   PRIMARY KEY (`id`),
   UNIQUE KEY `t_ie_exam_invigilate_call_recordId_source_Idx` (`exam_record_id`,`source`)
 ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='监控观看地址和通话申请表';

+ 0 - 3
themis-business/src/main/resources/mapper/TOeExamRecordMapper.xml

@@ -332,7 +332,6 @@
 			</if>
 			and tee.enable = 1
 			and teea.enable = 1
-			and tees.enable = 1
 		</where>
 		) t,(SELECT @i := 0) as i
 		<where>
@@ -403,7 +402,6 @@
 			</if>
 			and tee.enable = 1
 			and teea.enable = 1
-			and tees.enable = 1
 		</where>
 		order by tees.room_code
 	</select>
@@ -458,7 +456,6 @@
 			</if>
 			and tee.enable = 1
 			and teea.enable = 1
-			and tees.enable = 1
 		</where>
 		group by tee.id,tees.room_code,tee.name,teea.id,teea.code,tees.`identity`,tees.name,leftExamCount,status,tes.mobile_number
 		order by tees.room_code

+ 3 - 1
themis-common/src/main/java/com/qmth/themis/common/enums/ExceptionResultEnum.java

@@ -190,7 +190,9 @@ public enum ExceptionResultEnum {
 
     ATTACHMENT_ERROR(500, 500017,"上传文件失败"),
 
-    FINISH_TYPE_ERROR(500, 500018, "考试结束类型错误"),;
+    FINISH_TYPE_ERROR(500, 500018, "考试结束类型错误"),
+
+    EXAM_STUDENT_ENABLE(500, 500019, "考生已停用");
 
     private int statusCode;
     private int code;

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

@@ -127,7 +127,7 @@ public class TIeInvigilateCallMobileController {
         ExamRecordCacheUtil.setMonitorCallStatus(recordId, source.name(), MonitorCallStatusSourceEnum.START);
         String monitorKey = ExamRecordCacheUtil.getMonitorKey(recordId);
         TIeExamInvigilateCallLog tIeExamInvigilateCallLog = new TIeExamInvigilateCallLog(recordId, source, liveUrl, status, monitorKey, MonitorCallStatusSourceEnum.START);
-
+        tIeExamInvigilateCallLog.setStartTime(System.currentTimeMillis());
         //监考监控通话信息 发送mq start
         MqDto mqDto = new MqDto(MqTopicEnum.THEMIS_TOPIC.getCode(), MqTagEnum.MONITOR_LOG.name(), tIeExamInvigilateCallLog, MqTagEnum.MONITOR_LOG, String.valueOf(tIeExamInvigilateCallLog.getId()), source.name());
         mqDtoService.assembleSendOneWayMsg(mqDto);
@@ -230,6 +230,7 @@ public class TIeInvigilateCallMobileController {
         String monitorKey = ExamRecordCacheUtil.getMonitorKey(recordId);
         MonitorStatusSourceEnum status = ExamRecordCacheUtil.getMonitorStatus(recordId, source.name());
         TIeExamInvigilateCallLog tIeExamInvigilateCallLog = new TIeExamInvigilateCallLog(recordId, source, liveUrl, status, monitorKey, MonitorCallStatusSourceEnum.STOP);
+        tIeExamInvigilateCallLog.setEndTime(System.currentTimeMillis());
         //监考监控通话信息 发送mq start
         MqDto mqDto = new MqDto(MqTopicEnum.THEMIS_TOPIC.getCode(), MqTagEnum.MONITOR_LOG.name(), tIeExamInvigilateCallLog, MqTagEnum.MONITOR_LOG, String.valueOf(tIeExamInvigilateCallLog.getId()), source.name());
         mqDtoService.assembleSendOneWayMsg(mqDto);

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

@@ -172,7 +172,7 @@ public class TIeInvigilateCallOeController {
         ExamRecordCacheUtil.setMonitorCallStatus(recordId, source.name(), MonitorCallStatusSourceEnum.START);
         String monitorKey = ExamRecordCacheUtil.getMonitorKey(recordId);
         TIeExamInvigilateCallLog tIeExamInvigilateCallLog = new TIeExamInvigilateCallLog(recordId, source, liveUrl, status, monitorKey, MonitorCallStatusSourceEnum.START);
-
+        tIeExamInvigilateCallLog.setStartTime(System.currentTimeMillis());
         //监考监控通话信息 发送mq start
         MqDto mqDto = new MqDto(MqTopicEnum.THEMIS_TOPIC.getCode(), MqTagEnum.MONITOR_LOG.name(), tIeExamInvigilateCallLog, MqTagEnum.MONITOR_LOG, String.valueOf(tIeExamInvigilateCallLog.getId()), source.name());
         mqDtoService.assembleSendOneWayMsg(mqDto);
@@ -205,6 +205,7 @@ public class TIeInvigilateCallOeController {
         ExamRecordCacheUtil.setMonitorCallStatus(recordId, source.name(), MonitorCallStatusSourceEnum.STOP);
         String monitorKey = ExamRecordCacheUtil.getMonitorKey(recordId);
         TIeExamInvigilateCallLog tIeExamInvigilateCallLog = new TIeExamInvigilateCallLog(recordId, source, liveUrl, status, monitorKey, MonitorCallStatusSourceEnum.STOP);
+        tIeExamInvigilateCallLog.setEndTime(System.currentTimeMillis());
         //监考监控通话信息 发送mq start
         MqDto mqDto = new MqDto(MqTopicEnum.THEMIS_TOPIC.getCode(), MqTagEnum.MONITOR_LOG.name(), tIeExamInvigilateCallLog, MqTagEnum.MONITOR_LOG, String.valueOf(tIeExamInvigilateCallLog.getId()), source.name());
         mqDtoService.assembleSendOneWayMsg(mqDto);

BIN
themis-mq/src/main/java/com/qmth/themis/mq/service/.DS_Store


+ 34 - 6
themis-mq/src/main/java/com/qmth/themis/mq/service/impl/MqLogicServiceImpl.java

@@ -325,11 +325,17 @@ public class MqLogicServiceImpl implements MqLogicService {
         Long time = (Long) param.get("time");
         String exception = (String) param.get("exception");
         TEConfig teConfig = teConfigService.getGlobalConfig();
-        if (Objects.equals(type.toUpperCase(), ExamTypeEnum.IN_PROCESS.name())) {
+        Long examStudentId = ExamRecordCacheUtil.getExamStudentId(recordId);
+        ExamStudentCacheBean examStudentCacheBean = teExamStudentService.getExamStudentCacheBean(examStudentId);
+        if (Objects.nonNull(photoUrl) && (Objects.equals(type.toUpperCase(), ExamTypeEnum.FIRST_START.name()) || Objects.equals(type.toUpperCase(), ExamTypeEnum.RESUME_START.name()))) {
+            JSONObject jsonObject = new JSONObject();
+            jsonObject.put(PhotoTypeEnum.FACE_VERIFY_PHOTO.name(), photoUrl);
+            TEExamStudentLog teExamStudentLog = new TEExamStudentLog(type, ExamTypeEnum.valueOf(type).getCode(), jsonObject.toJSONString(), examStudentCacheBean.getStudentId(), examStudentCacheBean.getId(), recordId);
+            faceVerifyHistoryService.save(id, recordId, type, photoUrl, faceCount, similarity, realness, time, exception, null);
+            teExamStudentLogService.saveOrUpdate(teExamStudentLog);
+        } else if (Objects.equals(type.toUpperCase(), ExamTypeEnum.IN_PROCESS.name())) {
             VerifyExceptionEnum warningEnum = VerifyExceptionEnum.valueOf(exception);
             WarningDto warningDto = new WarningDto(warningEnum, faceCount, realness, recordId, photoUrl);
-            Long examStudentId = ExamRecordCacheUtil.getExamStudentId(recordId);
-            ExamStudentCacheBean examStudentCacheBean = teExamStudentService.getExamStudentCacheBean(examStudentId);
             if (Objects.equals(VerifyExceptionEnum.NONE, warningEnum)) {//无异常,往考生日志表里插一条
                 JSONObject jsonObject = new JSONObject();
                 jsonObject.put(PhotoTypeEnum.FACE_VERIFY_PHOTO.name(), photoUrl);
@@ -421,11 +427,26 @@ public class MqLogicServiceImpl implements MqLogicService {
         Long finishTime = (Long) param.get("finishTime");
         String exception = (String) param.get("exception");
         TEConfig teConfig = teConfigService.getGlobalConfig();
-        if (Objects.equals(type.toUpperCase(), ExamTypeEnum.IN_PROCESS.name())) {
+        Long examStudentId = ExamRecordCacheUtil.getExamStudentId(recordId);
+        ExamStudentCacheBean examStudentCacheBean = teExamStudentService.getExamStudentCacheBean(examStudentId);
+        if (Objects.equals(type.toUpperCase(), ExamTypeEnum.FIRST_START.name()) || Objects.equals(type.toUpperCase(), ExamTypeEnum.RESUME_START.name())) {
+            JSONArray jsonArray = JSONArray.parseArray(actions);
+            for (int i = 0; i < jsonArray.size(); i++) {
+                JSONObject jsonObject = jsonArray.getJSONObject(i);
+                String photoType = Objects.nonNull(jsonObject.get("type")) ? String.valueOf(jsonObject.get("type")) : null;
+                String photoUrl = Objects.nonNull(jsonObject.get("photoUrl")) ? String.valueOf(jsonObject.get("photoUrl")) : null;
+                if (Objects.nonNull(photoType) && Objects.nonNull(photoUrl) && Objects.equals(photoType.toLowerCase(), "startup")) {
+                    JSONObject object = new JSONObject();
+                    object.put(PhotoTypeEnum.LIVENESS_VERIFY_PHOTO.name(), photoUrl);
+                    TEExamStudentLog teExamStudentLog = new TEExamStudentLog(type, LivenessTypeEnum.valueOf(type).getTitle(), object.toJSONString(), examStudentCacheBean.getStudentId(), examStudentCacheBean.getId(), recordId);
+                    livenessVerifyHistoryService.save(id, recordId, type, actions, retry, startTime, finishTime, exception, null);
+                    teExamStudentLogService.saveOrUpdate(teExamStudentLog);
+                    break;
+                }
+            }
+        } else if (Objects.equals(type.toUpperCase(), ExamTypeEnum.IN_PROCESS.name())) {
             VerifyExceptionEnum warningEnum = VerifyExceptionEnum.valueOf(exception);
             JSONArray jsonArray = JSONArray.parseArray(actions);
-            Long examStudentId = ExamRecordCacheUtil.getExamStudentId(recordId);
-            ExamStudentCacheBean examStudentCacheBean = teExamStudentService.getExamStudentCacheBean(examStudentId);
             for (int i = 0; i < jsonArray.size(); i++) {
                 JSONObject jsonObject = jsonArray.getJSONObject(i);
                 if (Objects.equals(VerifyExceptionEnum.NONE, warningEnum)) {//无异常,往考生日志表里插一条
@@ -602,6 +623,13 @@ public class MqLogicServiceImpl implements MqLogicService {
                 tIeExamInvigilateCall.setLiveUrl(tIeExamInvigilateCallLog.getLiveUrl());
                 tIeExamInvigilateCall.setStatus(tIeExamInvigilateCallLog.getStatus());
                 tIeExamInvigilateCall.setCallStatus(tIeExamInvigilateCallLog.getCallStatus());
+                tIeExamInvigilateCall.setType(tIeExamInvigilateCallLog.getType());
+                if (Objects.equals(tIeExamInvigilateCallLog.getCallStatus(), MonitorCallStatusSourceEnum.START)) {
+                    tIeExamInvigilateCall.setStartTime(tIeExamInvigilateCallLog.getStartTime());
+                }
+                if (Objects.equals(tIeExamInvigilateCallLog.getCallStatus(), MonitorCallStatusSourceEnum.STOP)) {
+                    tIeExamInvigilateCall.setEndTime(tIeExamInvigilateCallLog.getEndTime());
+                }
             }
             if (Objects.nonNull(tIeExamInvigilateCall.getUpdateTime())) {
                 Long dbtimestamp = Objects.nonNull(tIeExamInvigilateCall.getUpdateTime()) ? tIeExamInvigilateCall.getUpdateTime() : 0L;