浏览代码

考试记录新增预警记录未读数

wangliang 1 年之前
父节点
当前提交
8c7d0e519e

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

@@ -390,6 +390,7 @@ public class TIeInvigilateController {
             tIeExamInvigilateNoticeUpdateWrapper.lambda().set(TIeInvigilateWarnInfo::getApproveStatus, 1)
                     .eq(TIeInvigilateWarnInfo::getExamRecordId, examRecordId);
             tIeInvigilateWarnInfoService.update(tIeExamInvigilateNoticeUpdateWrapper);
+            tOeExamRecordService.updateWarningUnreadCache(examRecordId, 0);
         }
         invigilateListDetailBean.setMonitorVideoSource(examCacheBean.getMonitorVideoSource());
         invigilateListDetailBean.setMonitorRecord(examCacheBean.getMonitorRecord());

+ 19 - 5
themis-admin/src/main/java/com/qmth/themis/admin/api/TIeInvigilateWarnInfoController.java

@@ -11,16 +11,16 @@ import com.qmth.themis.business.dto.response.TIeWarningNotifyDto;
 import com.qmth.themis.business.entity.TBUser;
 import com.qmth.themis.business.entity.TIeInvigilateWarnInfo;
 import com.qmth.themis.business.enums.RoleEnum;
-import com.qmth.themis.business.service.ThemisCacheService;
 import com.qmth.themis.business.service.TIeInvigilateWarnInfoService;
 import com.qmth.themis.business.service.TOeExamRecordService;
+import com.qmth.themis.business.service.ThemisCacheService;
 import com.qmth.themis.business.util.ServletUtil;
 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.apache.commons.collections.CollectionUtils;
 import org.springframework.transaction.annotation.Transactional;
+import org.springframework.util.CollectionUtils;
 import org.springframework.validation.BindingResult;
 import org.springframework.validation.annotation.Validated;
 import org.springframework.web.bind.annotation.*;
@@ -28,9 +28,7 @@ import org.springframework.web.bind.annotation.*;
 import javax.annotation.Resource;
 import javax.validation.constraints.Max;
 import javax.validation.constraints.Min;
-import java.util.Collections;
-import java.util.List;
-import java.util.Objects;
+import java.util.*;
 import java.util.stream.Collectors;
 
 /**
@@ -134,9 +132,25 @@ public class TIeInvigilateWarnInfoController {
             tIeInvigilateWarnInfoUpdateWrapper.lambda().set(TIeInvigilateWarnInfo::getApproveStatus, warnInfoParams.getApproveStatus());
             if (!CollectionUtils.isEmpty(warnInfoParams.getWarningIds())) {
                 List<Long> warningTranIds = warnInfoParams.getWarningIds().stream().map(x -> Long.parseLong(x)).collect(Collectors.toList());
+                List<TIeInvigilateWarnInfo> tIeInvigilateWarnInfoList = tIeInvigilateWarnInfoService.listByIds(warningTranIds);
+                if (!CollectionUtils.isEmpty(tIeInvigilateWarnInfoList)) {
+                    Map<Long, Integer> map = new HashMap<>();
+                    for (TIeInvigilateWarnInfo t : tIeInvigilateWarnInfoList) {
+                        if (map.containsKey(t.getExamRecordId())) {
+                            Integer number = map.get(t.getExamRecordId());
+                            map.put(t.getExamRecordId(), number + 1);
+                        } else {
+                            map.put(t.getExamRecordId(), 1);
+                        }
+                    }
+                    map.forEach((k, v) -> {
+                        tOeExamRecordService.updateWarningUnreadCache(k, v);
+                    });
+                }
                 tIeInvigilateWarnInfoUpdateWrapper.lambda().in(TIeInvigilateWarnInfo::getId, warningTranIds);
             } else if (Objects.nonNull(warnInfoParams.getExamRecordId())) {
                 tIeInvigilateWarnInfoUpdateWrapper.lambda().eq(TIeInvigilateWarnInfo::getExamRecordId, warnInfoParams.getExamRecordId());
+                tOeExamRecordService.updateWarningUnreadCache(warnInfoParams.getExamRecordId(), 0);
             }
             tIeInvigilateWarnInfoService.update(tIeInvigilateWarnInfoUpdateWrapper);
         }

+ 12 - 2
themis-business/src/main/java/com/qmth/themis/business/cache/ExamRecordCacheUtil.java

@@ -6,9 +6,7 @@ import com.qmth.themis.business.cache.bean.ExamCacheBean;
 import com.qmth.themis.business.cache.bean.ExamCourseCacheBean;
 import com.qmth.themis.business.constant.SpringContextHolder;
 import com.qmth.themis.business.constant.SystemConstant;
-import com.qmth.themis.business.entity.TIeInvigilateWarnInfo;
 import com.qmth.themis.business.enums.*;
-import com.qmth.themis.business.service.TIeInvigilateWarnInfoService;
 import com.qmth.themis.business.service.TOeExamRecordService;
 import com.qmth.themis.business.util.RedisUtil;
 
@@ -315,6 +313,18 @@ public class ExamRecordCacheUtil {
                 .get(RedisKeyHelper.examRecordCacheKey(recordId), ExamRecordFieldEnum.warning_count.getCode());
     }
 
+    public static void setWarningUnread(Long recordId, Integer warningUnread) {
+        if (Objects.nonNull(getId(recordId))) {
+            redisUtil.set(RedisKeyHelper.examRecordCacheKey(recordId), ExamRecordFieldEnum.warning_unread.getCode(),
+                    warningUnread);
+        }
+    }
+
+    public static Integer getWarningUnread(Long recordId) {
+        return (Integer) redisUtil
+                .get(RedisKeyHelper.examRecordCacheKey(recordId), ExamRecordFieldEnum.warning_unread.getCode());
+    }
+
     public static void setBreachStatus(Long recordId, Integer breachStatus, Long timestamp) {
         BreachStatusBean breachStatusBean = getBreachStatusBean(recordId);
         if (Objects.isNull(breachStatusBean)) {

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

@@ -196,6 +196,7 @@ public class SystemConstant {
     public static final String FORM_USER_ID = "formUserId";
     public static final String OPER = "oper";
     public static final String EXAM = "exam";
+    public static final String WARNING_COUNT_UPDATE = "warning_count_update";
     //    public static final String EXEC_TIME = "execTime";
 //    public static final String REAL_EXEC_TIME = "realExecTime";
     public static final String INSERT = "insert";
@@ -412,6 +413,10 @@ public class SystemConstant {
 
     public static final String REDIS_LOCK_EXAM_STATUS_PREFIX = "lock:exam_status:record:";
 
+    public static final String REDIS_LOCK_EXAM_WARN_COUNT_PREFIX = "lock:exam_warn_count:record:";
+
+    public static final String REDIS_LOCK_EXAM_WARN_UNREAD_PREFIX = "lock:exam_warn_unread:record:";
+
     public static final long REDIS_LOCK_MQ_TIME_OUT = 60L;
 
     public static final long REDIS_LOCK_WEBSOCKET_TIME_OUT = 30L;
@@ -428,6 +433,10 @@ public class SystemConstant {
 
     public static final long REDIS_LOCK_PROBLEM_TIME_OUT = 30L;
 
+    public static final long REDIS_LOCK_EXAM_WARN_COUNT_TIME_OUT = 60L;
+
+    public static final long REDIS_LOCK_EXAM_WARN_UNREAD_TIME_OUT = 60L;
+
     //学生锁
     public static final String REDIS_LOCK_STUDENT_PREFIX = "lock:student:student_id_";
 

+ 7 - 0
themis-business/src/main/java/com/qmth/themis/business/dao/TOeExamRecordMapper.java

@@ -586,4 +586,11 @@ public interface TOeExamRecordMapper extends BaseMapper<TOeExamRecord> {
      * @return
      */
     List<MapDataCountBean> mapDataCount();
+
+    /**
+     * 根据id更新预警数量
+     *
+     * @param id
+     */
+    void updateWarningCount(@Param("id") Long id);
 }

+ 11 - 1
themis-business/src/main/java/com/qmth/themis/business/dto/MqDto.java

@@ -5,7 +5,6 @@ import com.qmth.themis.business.enums.MqTagEnum;
 
 import java.io.Serializable;
 import java.util.Map;
-import java.util.UUID;
 
 /**
  * @Description: mq dto
@@ -64,6 +63,17 @@ public class MqDto implements Serializable {
         this.id = SystemConstant.getNanoId();
     }
 
+    public MqDto(String topic, String tag, String objId, String objName, Long timestamp) {
+        this.topic = topic;
+        this.tag = tag;
+        this.body = tag;
+        this.type = MqTagEnum.valueOf(tag);
+        this.objId = objId;
+        this.objName = objName;
+        this.timestamp = timestamp;
+        this.id = SystemConstant.getNanoId();
+    }
+
     public MqDto(String topic, String tag, Object body, MqTagEnum type, String objId, String objName) {
         this.topic = topic;
         this.tag = tag;

+ 11 - 0
themis-business/src/main/java/com/qmth/themis/business/entity/TOeExamRecord.java

@@ -113,6 +113,9 @@ public class TOeExamRecord implements Serializable {
     @TableField(value = "warning_count")
     private Integer warningCount;
 
+    @ApiModelProperty(value = "预警记录未读数")
+    private Integer warningUnread;
+
     @ApiModelProperty(value = "审核结果,pass:通过,no_pass:不通过")
     @TableField(value = "review_result")
     private ReviewResultEnum reviewResult;
@@ -284,6 +287,14 @@ public class TOeExamRecord implements Serializable {
     @ApiModelProperty(value = "视频删除状态,false:未删除,true:已删除")
     private Boolean videoStatus;
 
+    public Integer getWarningUnread() {
+        return warningUnread;
+    }
+
+    public void setWarningUnread(Integer warningUnread) {
+        this.warningUnread = warningUnread;
+    }
+
     public Boolean getVideoStatus() {
         return videoStatus;
     }

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

@@ -51,6 +51,8 @@ public enum ExamRecordFieldEnum {
 
     warning_count("warningCount"),
 
+    warning_unread("warningUnread"),
+
     review_result("reviewResult"),
 
     objective_score("objectiveScore"),

+ 30 - 0
themis-business/src/main/java/com/qmth/themis/business/service/TOeExamRecordService.java

@@ -60,6 +60,14 @@ public interface TOeExamRecordService extends IService<TOeExamRecord> {
      */
     void sendExamRecordDataSaveMq(Long recordId, Long timestamp);
 
+    /**
+     * 发送mq更新考试预警数量记录
+     *
+     * @param recordId
+     * @param timestamp
+     */
+    void sendExamRecordDataUpdateWarningCountMq(Long recordId, Long timestamp);
+
     /**
      * 发送mq更新考试记录
      *
@@ -610,4 +618,26 @@ public interface TOeExamRecordService extends IService<TOeExamRecord> {
      * @return
      */
     TOeExamRecord getExamRecordForDb(Long examId, Long activityId, Long examStudentId, ExamRecordStatusEnum examRecordStatusEnum);
+
+    /**
+     * 根据id更新预警数量
+     *
+     * @param id
+     */
+    void updateWarningCount(Long id);
+
+    /**
+     * 更新预警总数
+     *
+     * @param id
+     */
+    void updateWarningCountCache(Long id);
+
+    /**
+     * 更新预警未读数
+     *
+     * @param id
+     * @param number
+     */
+    void updateWarningUnreadCache(Long id, Integer number);
 }

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

@@ -4,6 +4,7 @@ import cn.hutool.core.date.DateUtil;
 import com.alibaba.fastjson.JSONArray;
 import com.alibaba.fastjson.JSONObject;
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import com.google.common.reflect.TypeToken;
@@ -103,6 +104,9 @@ public class TOeExamRecordServiceImpl extends ServiceImpl<TOeExamRecordMapper, T
     @Resource
     TSyncExamStudentScoreService tSyncExamStudentScoreService;
 
+    @Resource
+    TOeExamRecordService tOeExamRecordService;
+
     @Transactional
     @Override
     public Long saveByPrepare(Long examId, Long examActivityId, Long examStudentId, Long paperId,
@@ -499,6 +503,113 @@ public class TOeExamRecordServiceImpl extends ServiceImpl<TOeExamRecordMapper, T
         return this.getOne(tOeExamRecordQueryWrapper);
     }
 
+    /**
+     * 根据id更新预警数量
+     *
+     * @param id
+     */
+    @Override
+    @Transactional
+    public void updateWarningCount(Long id) {
+        this.baseMapper.updateWarningCount(id);
+    }
+
+    /**
+     * 更新预警总数
+     *
+     * @param id
+     */
+    @Override
+    public void updateWarningCountCache(Long id) {
+        boolean lock = false;
+        for (int i = 0; i < SystemConstant.MAX_EXAM_STATUS_COUNT; i++) {
+            lock = redisUtil.lock(SystemConstant.REDIS_LOCK_EXAM_WARN_COUNT_PREFIX + id, SystemConstant.REDIS_LOCK_EXAM_WARN_COUNT_TIME_OUT);
+            if (lock) {
+                try {
+                    Integer warningCount = ExamRecordCacheUtil.getWarningCount(id);
+                    if (Objects.nonNull(warningCount)) {
+                        warningCount++;
+                        ExamRecordCacheUtil.setWarningCount(id, warningCount);
+                    } else {
+                        ExamRecordCacheUtil.setWarningCount(id, 1);
+                    }
+                    Integer warningUnread = ExamRecordCacheUtil.getWarningUnread(id);
+                    if (Objects.nonNull(warningUnread)) {
+                        warningUnread++;
+                        ExamRecordCacheUtil.setWarningUnread(id, warningUnread);
+                    } else {
+                        ExamRecordCacheUtil.setWarningUnread(id, 1);
+                    }
+                    this.sendExamRecordDataUpdateWarningCountMq(id, System.currentTimeMillis());
+                } catch (Exception e) {
+                    log.error(SystemConstant.LOG_ERROR, e);
+                    if (e instanceof BusinessException) {
+                        throw new BusinessException(e.getMessage());
+                    } else {
+                        throw new RuntimeException(e);
+                    }
+                } finally {
+                    if (Objects.nonNull(id)) {
+                        redisUtil.releaseLock(SystemConstant.REDIS_LOCK_EXAM_WARN_COUNT_PREFIX + id);
+                    }
+                }
+            } else {
+                try {
+                    Thread.sleep(500);
+                } catch (InterruptedException e) {
+                    e.printStackTrace();
+                }
+            }
+        }
+        if (!lock) {
+            tgErrorService.saveExamTgError(id, "updateWarningCountCache");
+        }
+    }
+
+    /**
+     * 更新预警未读数
+     *
+     * @param id
+     * @param number
+     */
+    @Override
+    @Transactional
+    public void updateWarningUnreadCache(Long id, Integer number) {
+        boolean lock = false;
+        for (int i = 0; i < SystemConstant.MAX_EXAM_STATUS_COUNT; i++) {
+            lock = redisUtil.lock(SystemConstant.REDIS_LOCK_EXAM_WARN_UNREAD_PREFIX + id, SystemConstant.REDIS_LOCK_EXAM_WARN_UNREAD_TIME_OUT);
+            if (lock) {
+                try {
+                    Integer warningUnread = ExamRecordCacheUtil.getWarningUnread(id);
+                    if (Objects.nonNull(warningUnread)) {
+                        ExamRecordCacheUtil.setWarningUnread(id, number);
+                    }
+                    tOeExamRecordService.update(new UpdateWrapper<TOeExamRecord>().lambda().eq(TOeExamRecord::getId, id).set(TOeExamRecord::getWarningUnread, 0));
+                } catch (Exception e) {
+                    log.error(SystemConstant.LOG_ERROR, e);
+                    if (e instanceof BusinessException) {
+                        throw new BusinessException(e.getMessage());
+                    } else {
+                        throw new RuntimeException(e);
+                    }
+                } finally {
+                    if (Objects.nonNull(id)) {
+                        redisUtil.releaseLock(SystemConstant.REDIS_LOCK_EXAM_WARN_UNREAD_PREFIX + id);
+                    }
+                }
+            } else {
+                try {
+                    Thread.sleep(500);
+                } catch (InterruptedException e) {
+                    e.printStackTrace();
+                }
+            }
+        }
+        if (!lock) {
+            tgErrorService.saveExamTgError(id, "updateWarningUnreadCache");
+        }
+    }
+
     @Override
     public void saveFaceVerify(ExamTypeEnum type, Long recordId, Long entryAuthenticationId,
                                VerifyExceptionEnum entryAuthenticationResult) {
@@ -557,6 +668,23 @@ public class TOeExamRecordServiceImpl extends ServiceImpl<TOeExamRecordMapper, T
         }
     }
 
+    /**
+     * 发送mq更新考试预警数量记录
+     *
+     * @param recordId
+     * @param timestamp
+     */
+    @Override
+    public void sendExamRecordDataUpdateWarningCountMq(Long recordId, Long timestamp) {
+        try {
+            ExamRecordCacheUtil.setUpdateTime(recordId, timestamp);
+            MqDto mqDto = new MqDto(mqUtil.getTopic(), MqTagEnum.EXAM_RECORD_UPDATE.name(), recordId.toString(), SystemConstant.WARNING_COUNT_UPDATE, timestamp);
+            mqDtoService.assembleSendAsyncMsg(mqDto);
+        } catch (Exception e) {
+            log.error(SystemConstant.LOG_ERROR, e);
+        }
+    }
+
     /**
      * 发送mq更新考试记录
      *

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

@@ -245,14 +245,7 @@ public class WarningServiceImpl implements WarningService {
      * @param recordId
      */
     public void setWarningCount(Long recordId) {
-        Integer warningCount = ExamRecordCacheUtil.getWarningCount(recordId);
-        if (Objects.nonNull(warningCount)) {
-            warningCount++;
-            ExamRecordCacheUtil.setWarningCount(recordId, warningCount);
-        } else {
-            ExamRecordCacheUtil.setWarningCount(recordId, 1);
-        }
-        tOeExamRecordService.sendExamRecordDataSaveMq(recordId, System.currentTimeMillis());
+        tOeExamRecordService.updateWarningCountCache(recordId);
     }
 
     /**

+ 1 - 0
themis-business/src/main/resources/db/log/1.2.8.log

@@ -31,6 +31,7 @@ ALTER TABLE t_ie_exam_invigilate_call_log ADD form_user_id BIGINT NULL COMMENT '
 ALTER TABLE t_ie_exam_invigilate_call_log ADD receive_user_id BIGINT NULL COMMENT '接收人id';
 ALTER TABLE t_ie_exam_invigilate_call_log ADD start_time BIGINT NULL COMMENT '开始通话时间';
 ALTER TABLE t_ie_exam_invigilate_call_log ADD end_time BIGINT NULL COMMENT '结束通话时间';
+ALTER TABLE t_oe_exam_record ADD warning_unread INTEGER NULL COMMENT '预警记录未读数';
 
 /*删除进度查询菜单*/
 INSERT INTO t_b_role_privilege

+ 5 - 1
themis-business/src/main/resources/mapper/TOeExamRecordMapper.xml

@@ -1759,11 +1759,15 @@
                tir.province,
                count(toer.id) as onlineCount
         from t_ip_region tir
-            join t_oe_exam_record toer on tir.exam_record_id = toer.id
+                 join t_oe_exam_record toer on tir.exam_record_id = toer.id
         WHERE toer.client_websocket_status = 'ON_LINE'
           and tir.country != '0' and tir.province != '0'
         group by
             tir.country,
             tir.province
     </select>
+
+    <update id="updateWarningCount">
+        update t_oe_exam_record set warning_count = warning_count + 1, warning_unread = warning_unread + 1 where id = #{id}
+    </update>
 </mapper>

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

@@ -14,7 +14,6 @@ import com.qmth.themis.business.dto.response.TEExamDto;
 import com.qmth.themis.business.dto.response.TEExamWaitDto;
 import com.qmth.themis.business.entity.SysConfig;
 import com.qmth.themis.business.entity.TEExam;
-import com.qmth.themis.business.entity.TIeExamInvigilateCallLog;
 import com.qmth.themis.business.entity.TOeExamRecord;
 import com.qmth.themis.business.enums.*;
 import com.qmth.themis.business.service.*;

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

@@ -698,7 +698,11 @@ public class MqLogicServiceImpl implements MqLogicService {
         Long updateTime = ExamRecordCacheUtil.getUpdateTime(recordId);
         if (Objects.isNull(updateTime) || (Objects.nonNull(updateTime) &&
                 mqDto.getTimestamp().longValue() >= updateTime.longValue())) {
-            examRecordService.examRecordDataSave(recordId);
+            if (Objects.nonNull(mqDto.getObjName()) && Objects.equals(mqDto.getObjName(), SystemConstant.WARNING_COUNT_UPDATE)) {
+                examRecordService.updateWarningCount(recordId);
+            } else {
+                examRecordService.examRecordDataSave(recordId);
+            }
             tIpRegionService.saveIpRegion(recordId);
         }
         tmRocketMessageService.saveMqMessageSuccess(mqDto, key);