Quellcode durchsuchen

监考端接口

wangliang vor 4 Jahren
Ursprung
Commit
151853dd28

+ 63 - 0
themis-business/src/main/java/com/qmth/themis/business/dto/WarningDto.java

@@ -0,0 +1,63 @@
+package com.qmth.themis.business.dto;
+
+import com.qmth.themis.business.enums.WarningEnum;
+
+import java.io.Serializable;
+
+/**
+ * @Description: 预警dto
+ * @Param:
+ * @return:
+ * @Author: wangliang
+ * @Date: 2020/8/18
+ */
+public class WarningDto implements Serializable {
+
+    private WarningEnum warningEnum;//预警类型
+    private Integer faceCount;//人脸数量,0:没有人脸,大于1:多张人脸
+    private Double realness;//真实性结果,-1:没有,0:异常,1:正常
+    private Long recordId;//考试记录id
+
+    public WarningDto() {
+
+    }
+
+    public WarningDto(WarningEnum warningEnum, Integer faceCount, Double realness, Long recordId) {
+        this.warningEnum = warningEnum;
+        this.faceCount = faceCount;
+        this.realness = realness;
+        this.recordId = recordId;
+    }
+
+    public WarningEnum getWarningEnum() {
+        return warningEnum;
+    }
+
+    public void setWarningEnum(WarningEnum warningEnum) {
+        this.warningEnum = warningEnum;
+    }
+
+    public Integer getFaceCount() {
+        return faceCount;
+    }
+
+    public void setFaceCount(Integer faceCount) {
+        this.faceCount = faceCount;
+    }
+
+    public Double getRealness() {
+        return realness;
+    }
+
+    public void setRealness(Double realness) {
+        this.realness = realness;
+    }
+
+    public Long getRecordId() {
+        return recordId;
+    }
+
+    public void setRecordId(Long recordId) {
+        this.recordId = recordId;
+    }
+}

+ 60 - 0
themis-business/src/main/java/com/qmth/themis/business/entity/TEConfig.java

@@ -38,6 +38,66 @@ public class TEConfig implements Serializable {
     @TableField(value = "liveness_action_limit_seconds")
     private Integer livenessActionLimitSeconds;
 
+    @ApiModelProperty(value = "一个考试场次中未检测到人脸或有违规动作(左顾右盼、低头、转身、离开座位、人脸移除、遮挡等)次数超过3次(持续30秒连续帧画面违规记为次数1次)")
+    @TableField(value = "no_face_count_error")
+    private Integer noFaceCountError;
+
+    @ApiModelProperty(value = "一个考试场次中检测到人脸与底照不符次数超过3次(持续30秒连续帧画面90%比对底照不符记为次数1次)")
+    @TableField(value = "match_face_compare_error_count")
+    private Integer matchFaceCompareErrorCount;
+
+    @ApiModelProperty(value = "真实性检测数量")
+    @TableField(value = "realness_count")
+    private Integer realnessCount;
+
+    @ApiModelProperty(value = "一个考试场次中检测到多张人脸超过3次(持续15秒连续帧画面90%存在多张人脸记为次数1次)")
+    @TableField(value = "multiple_face_count_error")
+    private Integer multipleFaceCountError;
+
+    @ApiModelProperty(value = "一个考试场次内人脸抓拍检测(D12)失败累计次数超过6次")
+    @TableField(value = "total_face_compare_error_count")
+    private Integer totalFaceCompareErrorCount;
+
+    public Integer getNoFaceCountError() {
+        return noFaceCountError;
+    }
+
+    public void setNoFaceCountError(Integer noFaceCountError) {
+        this.noFaceCountError = noFaceCountError;
+    }
+
+    public Integer getMatchFaceCompareErrorCount() {
+        return matchFaceCompareErrorCount;
+    }
+
+    public void setMatchFaceCompareErrorCount(Integer matchFaceCompareErrorCount) {
+        this.matchFaceCompareErrorCount = matchFaceCompareErrorCount;
+    }
+
+    public Integer getRealnessCount() {
+        return realnessCount;
+    }
+
+    public void setRealnessCount(Integer realnessCount) {
+        this.realnessCount = realnessCount;
+    }
+
+    public Integer getMultipleFaceCountError() {
+        return multipleFaceCountError;
+    }
+
+    public void setMultipleFaceCountError(Integer multipleFaceCountError) {
+        this.multipleFaceCountError = multipleFaceCountError;
+    }
+
+    public Integer getTotalFaceCompareErrorCount() {
+        return totalFaceCompareErrorCount;
+    }
+
+    public void setTotalFaceCompareErrorCount(Integer totalFaceCompareErrorCount) {
+        this.totalFaceCompareErrorCount = totalFaceCompareErrorCount;
+    }
+
     public static long getSerialVersionUID() {
         return serialVersionUID;
     }

+ 17 - 0
themis-business/src/main/java/com/qmth/themis/business/entity/TIeInvigilateWarnInfo.java

@@ -4,6 +4,7 @@ import com.baomidou.mybatisplus.annotation.FieldFill;
 import com.baomidou.mybatisplus.annotation.TableField;
 import com.baomidou.mybatisplus.annotation.TableId;
 import com.qmth.themis.business.enums.WarningEnum;
+import com.qmth.themis.common.contanst.Constants;
 import io.swagger.annotations.ApiModel;
 import io.swagger.annotations.ApiModelProperty;
 
@@ -70,6 +71,22 @@ public class TIeInvigilateWarnInfo implements Serializable {
     @TableField(value = "update_time", fill = FieldFill.UPDATE)
     private Date updateTime;
 
+    public TIeInvigilateWarnInfo() {
+
+    }
+
+    public TIeInvigilateWarnInfo(Long examId, Long examActivityId, Long examRecordId, Long examStudentId, String level, String info, WarningEnum type) {
+        this.id = Constants.idGen.next();
+        this.examId = examId;
+        this.examActivityId = examActivityId;
+        this.examRecordId = examRecordId;
+        this.examStudentId = examStudentId;
+        this.level = level;
+        this.info = info;
+        this.type = type;
+        this.approveStatus = 0;
+    }
+
     public static long getSerialVersionUID() {
         return serialVersionUID;
     }

+ 30 - 8
themis-business/src/main/java/com/qmth/themis/business/enums/WarningEnum.java

@@ -1,23 +1,45 @@
 package com.qmth.themis.business.enums;
 
+import com.google.common.collect.Maps;
+
+import java.util.Arrays;
+import java.util.List;
+
 /**
-* @Description: 预警类型 enum
-* @Param:
-* @return:
-* @Author: wangliang
-* @Date: 2020/7/29
-*/
+ * @Description: 预警类型 enum
+ * @Param:
+ * @return:
+ * @Author: wangliang
+ * @Date: 2020/7/29
+ */
 public enum WarningEnum {
 
-    NET_TIME_OUT("网络超时");
+    FACE_COUNT_ERROR("人脸数量异常", Arrays.asList("D4", "D8")),
+
+    FACE_COMPARE_ERROR("人脸比对异常", Arrays.asList("D6", "D14")),
+
+    EYE_CLOSE_ERROR("闭眼检测异常", Arrays.asList(null)),
+
+    LIVENESS_ACTION_ERROR("活检动作错误", Arrays.asList(null)),
+
+    NONE("无异常", Arrays.asList(null)),
+
+    REALNESS("真实性检测", Arrays.asList("D15"));
 
     private String code;
 
-    private WarningEnum(String code){
+    private List<String> level;
+
+    private WarningEnum(String code, List<String> level) {
         this.code = code;
+        this.level = level;
     }
 
     public String getCode() {
         return code;
     }
+
+    public List<String> getLevel() {
+        return level;
+    }
 }

+ 31 - 0
themis-business/src/main/java/com/qmth/themis/business/enums/WarningLevelEnum.java

@@ -0,0 +1,31 @@
+package com.qmth.themis.business.enums;
+
+/**
+ * @Description: 预警信息说明
+ * @Param:
+ * @return:
+ * @Author: wangliang
+ * @Date: 2020/8/18
+ */
+public enum WarningLevelEnum {
+
+    D4("一个考试场次中未检测到人脸或有违规动作(左顾右盼、低头、转身、离开座位、人脸移除、遮挡等)次数超过3次(持续30秒连续帧画面违规记为次数1次)"),
+
+    D8("一个考试场次中检测到多张人脸超过3次(持续15秒连续帧画面90%存在多张人脸记为次数1次)"),
+
+    D6("一个考试场次中检测到人脸与底照不符次数超过3次(持续30秒连续帧画面90%比对底照不符记为次数1次)"),
+
+    D14("一个考试场次内人脸抓拍检测(D12)失败累计次数超过6次"),
+
+    D15("真实性检测失败1次以上");
+
+    private String desc;
+
+    private WarningLevelEnum(String desc) {
+        this.desc = desc;
+    }
+
+    public String getDesc() {
+        return desc;
+    }
+}

+ 48 - 0
themis-business/src/main/java/com/qmth/themis/business/service/WarningService.java

@@ -0,0 +1,48 @@
+package com.qmth.themis.business.service;
+
+import com.qmth.themis.business.dto.WarningDto;
+
+/**
+ * @Description: 预警规则公用
+ * @Param:
+ * @return:
+ * @Author: wangliang
+ * @Date: 2020/8/18
+ */
+public interface WarningService {
+
+    /**
+     * 人脸数量异常
+     *
+     * @param warningDto
+     */
+    public void faceCountError(WarningDto warningDto);
+
+    /**
+     * 人脸比对异常
+     *
+     * @param warningDto
+     */
+    public void faceCompareError(WarningDto warningDto);
+
+    /**
+     * 闭眼检测异常
+     *
+     * @param warningDto
+     */
+    public void eyeCloseError(WarningDto warningDto);
+
+    /**
+     * 活体动作异常
+     *
+     * @param warningDto
+     */
+    public void livenessActionError(WarningDto warningDto);
+
+    /**
+     * 真实性异常
+     *
+     * @param warningDto
+     */
+    public void realnessError(WarningDto warningDto);
+}

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

@@ -98,7 +98,7 @@ public class TEMobileServiceImpl implements TEMobileService {
 				ServletUtil.getRequest().getLocalAddr(), token, expire);
 		redisUtil.setUserSession(sessionId, tbSession, redisExpire);
 		ret.setSessionId(sessionId);
-		ret.setTime(new Date().getTime());
+		ret.setTime(System.currentTimeMillis());
 		ret.setMode(mode);
 		//测试
         String test = SignatureInfo.build(SignatureType.TOKEN, sessionId, token);
@@ -173,7 +173,7 @@ public class TEMobileServiceImpl implements TEMobileService {
         redisUtil.set(RedisKeyHelper.examAnswerKey(recordId),
                 RedisKeyHelper.examAnswerHashKey(mainNumber, subNumber, subIndex), answerCache);
         MobileAnswerSubmitReponseBean ret = new MobileAnswerSubmitReponseBean();
-        ret.setUpdateTime(new Date().getTime());
+        ret.setUpdateTime(System.currentTimeMillis());
         return ret;
     }
 }

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

@@ -57,7 +57,7 @@ public class TOeFaceVerifyHistoryServiceImpl extends ServiceImpl<TOeFaceVerifyHi
 		FaceVerifyCacheUtil.setFaceVerifyCacheBean(recordId, cache.getId(), cache);
 		FaceVerifyBean ret=new FaceVerifyBean();
 		ret.setId(cache.getId());
-		ret.setUpdateTime(new Date().getTime());
+		ret.setUpdateTime(System.currentTimeMillis());
 		if(ExamTypeEnum.RESUME_START.equals(cache.getType())) {
 			examBreakHistoryService.saveAuthenticationResult(recordId, cache.getId(), cache.getException());
 		}else {

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

@@ -55,7 +55,7 @@ public class TOeLivenessVerifyHistoryServiceImpl extends ServiceImpl<TOeLiveness
 		LivenessVerifyCacheUtil.setLivenessVerifyCacheBean(recordId,cache.getId(), cache);
 		LivenessVerifyBean ret=new LivenessVerifyBean();
 		ret.setId(cache.getId());
-		ret.setUpdateTime(new Date().getTime());
+		ret.setUpdateTime(System.currentTimeMillis());
 		if(LivenessTypeEnum.RESUME_START.equals(cache.getType())) {
 			examBreakHistoryService.saveAuthenticationResult(recordId, cache.getId(), cache.getException());
 		}else  {

+ 156 - 0
themis-business/src/main/java/com/qmth/themis/business/service/impl/WarningServiceImpl.java

@@ -0,0 +1,156 @@
+package com.qmth.themis.business.service.impl;
+
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.qmth.themis.business.cache.RedisKeyHelper;
+import com.qmth.themis.business.dto.WarningDto;
+import com.qmth.themis.business.entity.TEConfig;
+import com.qmth.themis.business.entity.TIeInvigilateWarnInfo;
+import com.qmth.themis.business.entity.TOeFaceVerifyHistory;
+import com.qmth.themis.business.enums.WarningEnum;
+import com.qmth.themis.business.enums.WarningLevelEnum;
+import com.qmth.themis.business.service.TEConfigService;
+import com.qmth.themis.business.service.TIeInvigilateWarnInfoService;
+import com.qmth.themis.business.service.TOeFaceVerifyHistoryService;
+import com.qmth.themis.business.service.WarningService;
+import com.qmth.themis.business.util.RedisUtil;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import javax.annotation.Resource;
+import java.util.Map;
+
+/**
+ * @Description: 预警规则公用
+ * @Param:
+ * @return:
+ * @Author: wangliang
+ * @Date: 2020/8/18
+ */
+@Service
+public class WarningServiceImpl implements WarningService {
+    private final static Logger log = LoggerFactory.getLogger(WarningServiceImpl.class);
+
+    @Resource
+    TEConfigService teConfigService;
+
+    @Resource
+    RedisUtil redisUtil;
+
+    @Resource
+    TOeFaceVerifyHistoryService faceVerifyHistoryService;
+
+    @Resource
+    TIeInvigilateWarnInfoService tIeInvigilateWarnInfoService;
+
+    /**
+     * 人脸数量异常
+     *
+     * @param warningDto
+     */
+    @Override
+    @Transactional
+    public void faceCountError(WarningDto warningDto) {
+        Long recordId = warningDto.getRecordId();
+        Integer faceCount = warningDto.getFaceCount();
+        WarningEnum warningEnum = warningDto.getWarningEnum();
+        TEConfig teConfig = teConfigService.getGlobalConfig();
+        Map<String, Object> objectMap = redisUtil.getHashEntries(RedisKeyHelper.examRecordCacheKey(recordId));
+        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")));
+        QueryWrapper<TOeFaceVerifyHistory> tOeFaceVerifyHistoryQueryWrapper = new QueryWrapper<>();
+        if (faceCount > 1) {//多张人脸
+            tOeFaceVerifyHistoryQueryWrapper.lambda().eq(TOeFaceVerifyHistory::getExamRecordId, recordId).ge(TOeFaceVerifyHistory::getFaceCount, 1).eq(TOeFaceVerifyHistory::getException, warningEnum.name());
+            int count = faceVerifyHistoryService.count(tOeFaceVerifyHistoryQueryWrapper);
+            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);
+                tIeInvigilateWarnInfoService.saveOrUpdate(tIeInvigilateWarnInfo);
+            }
+        } else if (faceCount <= 0) {//未检测到人脸
+            tOeFaceVerifyHistoryQueryWrapper.lambda().eq(TOeFaceVerifyHistory::getExamRecordId, recordId).le(TOeFaceVerifyHistory::getFaceCount, 0).eq(TOeFaceVerifyHistory::getException, warningEnum.name());
+            int count = faceVerifyHistoryService.count(tOeFaceVerifyHistoryQueryWrapper);
+            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);
+                tIeInvigilateWarnInfoService.saveOrUpdate(tIeInvigilateWarnInfo);
+            }
+        }
+    }
+
+    /**
+     * 人脸比对异常
+     *
+     * @param warningDto
+     */
+    @Override
+    @Transactional
+    public void faceCompareError(WarningDto warningDto) {
+        Long recordId = warningDto.getRecordId();
+        WarningEnum warningEnum = warningDto.getWarningEnum();
+        TEConfig teConfig = teConfigService.getGlobalConfig();
+        Map<String, Object> objectMap = redisUtil.getHashEntries(RedisKeyHelper.examRecordCacheKey(recordId));
+        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")));
+        QueryWrapper<TOeFaceVerifyHistory> tOeFaceVerifyHistoryQueryWrapper = new QueryWrapper<>();
+        tOeFaceVerifyHistoryQueryWrapper.lambda().eq(TOeFaceVerifyHistory::getExamRecordId, recordId).eq(TOeFaceVerifyHistory::getException, warningEnum.name());
+        int count = faceVerifyHistoryService.count(tOeFaceVerifyHistoryQueryWrapper);
+        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);
+            tIeInvigilateWarnInfoService.saveOrUpdate(tIeInvigilateWarnInfo);
+        }
+        if (count >= teConfig.getTotalFaceCompareErrorCount()) {
+            TIeInvigilateWarnInfo tIeInvigilateWarnInfo = new TIeInvigilateWarnInfo(examId, examActivityId, recordId, examStudentId, warningEnum.getLevel().get(1), WarningLevelEnum.valueOf(warningEnum.getLevel().get(1)).getDesc(), warningEnum);
+            tIeInvigilateWarnInfoService.saveOrUpdate(tIeInvigilateWarnInfo);
+        }
+    }
+
+    /**
+     * 闭眼检测异常
+     *
+     * @param warningDto
+     */
+    @Override
+    public void eyeCloseError(WarningDto warningDto) {
+
+    }
+
+    /**
+     * 活体动作异常
+     *
+     * @param warningDto
+     */
+    @Override
+    public void livenessActionError(WarningDto warningDto) {
+
+    }
+
+    /**
+     * 真实性异常
+     *
+     * @param warningDto
+     */
+    @Override
+    @Transactional
+    public void realnessError(WarningDto warningDto) {
+        Long recordId = warningDto.getRecordId();
+        WarningEnum warningEnum = warningDto.getWarningEnum();
+        TEConfig teConfig = teConfigService.getGlobalConfig();
+        Map<String, Object> objectMap = redisUtil.getHashEntries(RedisKeyHelper.examRecordCacheKey(recordId));
+        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")));
+        QueryWrapper<TOeFaceVerifyHistory> tOeFaceVerifyHistoryQueryWrapper = new QueryWrapper<>();
+        tOeFaceVerifyHistoryQueryWrapper.lambda().eq(TOeFaceVerifyHistory::getExamRecordId, recordId).eq(TOeFaceVerifyHistory::getException, warningEnum.name());
+        int count = faceVerifyHistoryService.count(tOeFaceVerifyHistoryQueryWrapper);
+        count++;
+        if (count > teConfig.getRealnessCount()) {
+            TIeInvigilateWarnInfo tIeInvigilateWarnInfo = new TIeInvigilateWarnInfo(examId, examActivityId, recordId, examStudentId, warningEnum.getLevel().get(0), WarningLevelEnum.valueOf(warningEnum.getLevel().get(0)).getDesc(), warningEnum);
+            tIeInvigilateWarnInfoService.saveOrUpdate(tIeInvigilateWarnInfo);
+        }
+    }
+}

+ 1 - 1
themis-business/src/main/java/com/qmth/themis/business/util/OssUtil.java

@@ -195,7 +195,7 @@ public class OssUtil {
         String accessKeySecret = String.valueOf(map.get(SystemConstant.ACCESS_KEY_SECRET));
         String bucketName = String.valueOf(map.get(SystemConstant.BUCKET));
         OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);
-        Date expiration = new Date(new Date().getTime() + 60 * 1000);
+        Date expiration = new Date(System.currentTimeMillis() + 60 * 1000);
         GeneratePresignedUrlRequest generatePresignedUrlRequest ;
         generatePresignedUrlRequest =new GeneratePresignedUrlRequest(bucketName, objectPath);
         generatePresignedUrlRequest.setExpiration(expiration);

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

@@ -713,6 +713,11 @@ CREATE TABLE `t_e_config` (
   `liveness_action_count` int DEFAULT NULL COMMENT '活体动作个数',
   `liveness_action_retry_count` int DEFAULT NULL COMMENT '活体单个动作重试次数',
   `liveness_action_limit_seconds` int DEFAULT NULL COMMENT '活体单个动作限时秒数',
+  `no_face_count_error` int DEFAULT NULL COMMENT '一个考试场次中未检测到人脸或有违规动作(左顾右盼、低头、转身、离开座位、人脸移除、遮挡等)次数超过3次(持续30秒连续帧画面违规记为次数1次)',
+  `match_face_compare_error_count` int DEFAULT NULL COMMENT '一个考试场次中检测到人脸与底照不符次数超过3次(持续30秒连续帧画面90%比对底照不符记为次数1次)',
+  `realness_count` int DEFAULT NULL COMMENT '真实性检测数量',
+  `multiple_face_count_error` int DEFAULT NULL COMMENT '一个考试场次中检测到多张人脸超过3次(持续15秒连续帧画面90%存在多张人脸记为次数1次)',
+  `total_face_compare_error_count` int DEFAULT NULL COMMENT '一个考试场次内人脸抓拍检测(D12)失败累计次数超过6次',
   PRIMARY KEY (`id`)
 ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='全局配置';
 
@@ -720,7 +725,7 @@ CREATE TABLE `t_e_config` (
 -- Records of t_e_config
 -- ----------------------------
 BEGIN;
-INSERT INTO `t_e_config` VALUES (1, 0.1, 3, 3, 30);
+INSERT INTO `t_e_config` VALUES (1, 0.1, 3, 3, 30, 3, 3, 1, 3, 6);
 COMMIT;
 
 -- ----------------------------

+ 22 - 1
themis-mq/src/main/java/com/qmth/themis/mq/service/impl/MqLogicServiceImpl.java

@@ -3,13 +3,13 @@ package com.qmth.themis.mq.service.impl;
 import com.alibaba.fastjson.JSONObject;
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.google.gson.Gson;
-import com.qmth.themis.business.bean.exam.ExamStartParamBean;
 import com.qmth.themis.business.cache.ExamRecordCacheUtil;
 import com.qmth.themis.business.cache.RedisKeyHelper;
 import com.qmth.themis.business.cache.bean.ExamStudentCacheBean;
 import com.qmth.themis.business.constant.SpringContextHolder;
 import com.qmth.themis.business.constant.SystemConstant;
 import com.qmth.themis.business.dto.MqDto;
+import com.qmth.themis.business.dto.WarningDto;
 import com.qmth.themis.business.entity.*;
 import com.qmth.themis.business.enums.*;
 import com.qmth.themis.business.service.*;
@@ -90,6 +90,9 @@ public class MqLogicServiceImpl implements MqLogicService {
     @Resource
     TEExamStudentService teExamStudentService;
 
+    @Resource
+    WarningService warningService;
+
     /**
      * mq最大重试次数逻辑
      *
@@ -280,6 +283,17 @@ public class MqLogicServiceImpl implements MqLogicService {
         Long time = (Long) param.get("time");
         String exception = (String) param.get("exception");
         faceVerifyHistoryService.save(id, recordId, type, photoUrl, faceCount, similarity, realness, time, exception);
+        WarningEnum warningEnum = WarningEnum.valueOf(exception);
+        WarningDto warningDto = new WarningDto(warningEnum, faceCount, realness, recordId);
+        if (Objects.equals(WarningEnum.FACE_COUNT_ERROR, warningEnum)) {//人脸数量异常
+            warningService.faceCountError(warningDto);
+        } else if (Objects.equals(WarningEnum.FACE_COMPARE_ERROR, warningEnum)) {//人脸比对异常
+            warningService.faceCompareError(warningDto);
+        } else {
+            if (realness.intValue() == 0) {//真实性异常
+                warningService.realnessError(warningDto);
+            }
+        }
         mqDto.setAck(SystemConstant.STANDARD_ACK_TYPE);
         TMRocketMessage tmRocketMessage = gson.fromJson(gson.toJson(mqDto), TMRocketMessage.class);
         tmRocketMessage.setBody(JacksonUtil.parseJson(tmRocketMessage.getBody()));
@@ -307,6 +321,13 @@ public class MqLogicServiceImpl implements MqLogicService {
         Long finishTime = (Long) param.get("finishTime");
         String exception = (String) param.get("exception");
         livenessVerifyHistoryService.save(id, recordId, type, actions, retry, startTime, finishTime, exception);
+        WarningEnum warningEnum = WarningEnum.valueOf(exception);
+        if (Objects.equals(WarningEnum.FACE_COUNT_ERROR, warningEnum)) {//人脸数量异常
+            JSONObject jsonObject = JSONObject.parseObject(actions);
+            warningService.faceCountError(new WarningDto(warningEnum, Integer.parseInt(String.valueOf(jsonObject.get("faceCount"))), null, recordId));
+        } else if (Objects.equals(WarningEnum.FACE_COMPARE_ERROR, warningEnum)) {//人脸比对异常
+            warningService.faceCompareError(new WarningDto(warningEnum, null, null, recordId));
+        }
         mqDto.setAck(SystemConstant.STANDARD_ACK_TYPE);
         TMRocketMessage tmRocketMessage = gson.fromJson(gson.toJson(mqDto), TMRocketMessage.class);
         tmRocketMessage.setBody(JacksonUtil.parseJson(tmRocketMessage.getBody()));