5dfb6f1236099c3f1d0a792500d70ce6ba8d96bd..3c02cf8bdc8181a1f8fc09bdd2608c7b004f942d
2024-11-19 fuliqi
避免下发页面的新增导致的重复工单
3c02cf 对比 | 目录
2024-11-19 fuliqi
合同考核调整+日志
89a405 对比 | 目录
2024-11-19 fuliqi
视频录像导出日期调整
1eb601 对比 | 目录
10个文件已修改
307 ■■■■■ 已修改文件
ycl-common/src/main/java/enumeration/ContractRule.java 19 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ycl-common/src/main/java/enumeration/ErrorType.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
ycl-server/src/main/java/com/ycl/handler/CustomCellWriteHandler.java 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ycl-server/src/main/java/com/ycl/platform/service/impl/TContractServiceImpl.java 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ycl-server/src/main/java/com/ycl/platform/service/impl/TMonitorServiceImpl.java 36 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ycl-server/src/main/java/com/ycl/platform/service/impl/WorkOrderServiceImpl.java 135 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ycl-server/src/main/java/com/ycl/task/ContractTask.java 72 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ycl-server/src/main/java/com/ycl/task/UYTask.java 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ycl-server/src/main/java/com/ycl/utils/DateUtils.java 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ycl-server/src/main/resources/logback.xml 14 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ycl-common/src/main/java/enumeration/ContractRule.java
@@ -19,18 +19,19 @@
    CONTRACT_RULE_Monitor_OSD(null,"OSD标识", 2),
    CONTRACT_RULE_Monitor_OneFile(null,"一机一档", 2),
    CONTRACT_RULE_Store(3,"存储故障", 0),
    CONTRACT_RULE_Store_24H(null,"因存储设备、云存储软件等引起平台不能正常查看历史图像,须在24小时排除故障,单次故障在24小时以内", 3),
    CONTRACT_RULE_Store_48H(null,"因存储设备、云存储软件等引起平台不能正常查看历史图像,须在24小时排除故障,单次故障在48小时以内", 3),
    CONTRACT_RULE_Store_Important(null,"因视频或者图片丢失导致重要案事件不能回放或查看", 3),
//    CONTRACT_RULE_Store(3,"存储故障", 0),
//    CONTRACT_RULE_Store_24H(null,"因存储设备、云存储软件等引起平台不能正常查看历史图像,须在24小时排除故障,单次故障在24小时以内", 3),
//    CONTRACT_RULE_Store_48H(null,"因存储设备、云存储软件等引起平台不能正常查看历史图像,须在24小时排除故障,单次故障在48小时以内", 3),
//    CONTRACT_RULE_Store_Important(null,"因视频或者图片丢失导致重要案事件不能回放或查看", 3),
    CONTRACT_RULE_Site(4,"对于前端点位异常情况的处理", 0),
    CONTRACT_RULE_Site_Error(null,"镜头故障或污染或树枝遮挡或枪机视角偏移正常角度或补光灯应亮未亮", 4),
    CONTRACT_RULE_Site(3,"对于前端点位异常情况的处理", 0),
    CONTRACT_RULE_Site_Error24(null,"镜头故障或污染或树枝遮挡或枪机视角偏移正常角度或补光灯应亮未亮,24小时后未修复的", 3),
    CONTRACT_RULE_Site_Error48(null,"镜头故障或污染或树枝遮挡或枪机视角偏移正常角度或补光灯应亮未亮,48小时后未修复的", 3),
    CONTRACT_RULE_VideoRecord(5,"确保录像完整不定期对所有点位录像完整性抽查", 0),
    CONTRACT_RULE_VideoRecord(4,"确保录像完整不定期对所有点位录像完整性抽查", 0),
    CONTRACT_RULE_PicComplete(6,"确保图片完整不定期对所有人脸车辆以及智能前端抓拍的图片完整性抽查", 0),
    CONTRACT_RULE_PicComplete_PicUnuseful(null,"发现后台存储不能调取前端设备图片", 6),
    CONTRACT_RULE_PicComplete(5,"确保图片完整不定期对所有人脸车辆以及智能前端抓拍的图片完整性抽查", 0),
    CONTRACT_RULE_PicComplete_PicUnuseful(null,"发现后台存储不能调取前端设备图片", 5),
    ;
    private final Integer id;
ycl-common/src/main/java/enumeration/ErrorType.java
@@ -27,7 +27,7 @@
    STRIPE_INTERFERENCE("SCREENSTRIP", "条纹干扰","VIDEO"),
    SCREEN_OCCLUSION("SCREENSHADE", "画面遮挡","VIDEO"),
    ABNORMAL_CLARITY("SCREENBLUR", "清晰度异常","VIDEO"),
    ABNORMAL_BRIGHTNESS("SCREENLIGHT", "亮度异常","VIDEO"),
//    ABNORMAL_BRIGHTNESS("SCREENLIGHT", "亮度异常","VIDEO"),
    OSD_ERROR("OSD", "osd异常","VIDEO"),
//    VIDEO_LOSS("VIDEOMISS", "录像缺失","VIDEO"),
//    VIDEO_NONE("NOVIDEO", "无录像","VIDEO"),
ycl-server/src/main/java/com/ycl/handler/CustomCellWriteHandler.java
@@ -207,20 +207,16 @@
        setTemplateRule(list,null,"前端感知源治理工作","OSD标识",null,null,RuleDeductCategoryEnum.MULTIPLY_POINTS_BY_QUANTITY,0.1);
        setTemplateRule(list,null,"前端感知源治理工作","一机一档",null,null,RuleDeductCategoryEnum.MULTIPLY_POINTS_BY_QUANTITY,0.1);
        setTemplateRule(list,3,"存储故障","因存储设备、云存储软件等引起平台不能正常查看历史图像,单次故障时长在24小时以内的",24D,null,RuleDeductCategoryEnum.MULTIPLY_POINTS_BY_QUANTITY,0.5);
        setTemplateRule(list,null,"存储故障","因存储设备、云存储软件等引起平台不能正常查看历史图像,单次故障时长若超出24小时以上。",null,24D,RuleDeductCategoryEnum.MULTIPLY_POINTS_BY_QUANTITY,1.0);
        setTemplateRule(list,null,"存储故障","因视频或者图片丢失导致重要案事件不能回放或查看",null,null,RuleDeductCategoryEnum.MULTIPLY_POINTS_BY_QUANTITY,2.0);
        setTemplateRule(list,4,"对于前端点位异常情况的处理","镜头故障或污染或树枝遮挡或枪机视角偏移正常角度或补光灯应亮未亮,24小时后未修复的",null,24D,RuleDeductCategoryEnum.MULTIPLY_POINTS_BY_QUANTITY,0.5);
        setTemplateRule(list,3,"对于前端点位异常情况的处理","镜头故障或污染或树枝遮挡或枪机视角偏移正常角度或补光灯应亮未亮,24小时后未修复的",null,24D,RuleDeductCategoryEnum.MULTIPLY_POINTS_BY_QUANTITY,0.5);
        setTemplateRule(list,null,"对于前端点位异常情况的处理","镜头故障或污染或树枝遮挡或枪机视角偏移正常角度或补光灯应亮未亮,48小时后未修复的",null,48D,RuleDeductCategoryEnum.MULTIPLY_POINTS_BY_QUANTITY,1.0);
        setTemplateRule(list,5,"确保录像完整不定期对所有点位录像完整性抽查","每路视频累计丢失10分钟以内",10D,null,RuleDeductCategoryEnum.MULTIPLY_POINTS_BY_QUANTITY,0.2);
        setTemplateRule(list,4,"确保录像完整不定期对所有点位录像完整性抽查","每路视频累计丢失10分钟以内",10D,null,RuleDeductCategoryEnum.MULTIPLY_POINTS_BY_QUANTITY,0.2);
        setTemplateRule(list,null,"确保录像完整不定期对所有点位录像完整性抽查","丢失10-60 分钟",10D,60D,RuleDeductCategoryEnum.MULTIPLY_POINTS_BY_QUANTITY,0.5);
        setTemplateRule(list,null,"确保录像完整不定期对所有点位录像完整性抽查","丢失1 小时-4 小时(含)",60D,240D,RuleDeductCategoryEnum.MULTIPLY_POINTS_BY_QUANTITY,1.0);
        setTemplateRule(list,null,"确保录像完整不定期对所有点位录像完整性抽查","丢失4 小时-12 小时(含)",240D,720D,RuleDeductCategoryEnum.MULTIPLY_POINTS_BY_QUANTITY,1.5);
        setTemplateRule(list,null,"确保录像完整不定期对所有点位录像完整性抽查","丢失12 小时以上",null,720D,RuleDeductCategoryEnum.MULTIPLY_POINTS_BY_QUANTITY,2.0);
        setTemplateRule(list,6,"确保图片完整不定期对所有人脸车辆以及智能前端抓拍的图片完整性抽查","发现后台存储不能调取前端设备图片",null,null,RuleDeductCategoryEnum.MULTIPLY_POINTS_BY_QUANTITY,2.0);
        setTemplateRule(list,5,"确保图片完整不定期对所有人脸车辆以及智能前端抓拍的图片完整性抽查","发现后台存储不能调取前端设备图片",null,null,RuleDeductCategoryEnum.MULTIPLY_POINTS_BY_QUANTITY,2.0);
        return list;
ycl-server/src/main/java/com/ycl/platform/service/impl/TContractServiceImpl.java
@@ -89,20 +89,16 @@
        setTemplateRule(list,null,"前端感知源治理工作","OSD标识",24D,null,RuleDeductCategoryEnum.MULTIPLY_POINTS_BY_QUANTITY,0.1);
        setTemplateRule(list,null,"前端感知源治理工作","一机一档",24D,null,RuleDeductCategoryEnum.MULTIPLY_POINTS_BY_QUANTITY,0.1);
        setTemplateRule(list,3,"存储故障","因存储设备、云存储软件等引起平台不能正常查看历史图像,须在24小时排除故障,单次故障在24小时以内",24D,null,RuleDeductCategoryEnum.MULTIPLY_POINTS_BY_QUANTITY,0.5);
        setTemplateRule(list,null,"存储故障","因存储设备、云存储软件等引起平台不能正常查看历史图像,须在24小时排除故障,单次故障在48小时以内",48D,25D,RuleDeductCategoryEnum.MULTIPLY_POINTS_BY_QUANTITY,1.0);
        setTemplateRule(list,null,"存储故障","因视频或者图片丢失导致重要案事件不能回放或查看",null,null,RuleDeductCategoryEnum.MULTIPLY_POINTS_BY_QUANTITY,2.0);
        setTemplateRule(list,4,"对于前端点位异常情况的处理","镜头故障或污染或树枝遮挡或枪机视角偏移正常角度或补光灯应亮未亮,24小时后未修复的",48D,25D,RuleDeductCategoryEnum.MULTIPLY_POINTS_BY_QUANTITY,0.5);
        setTemplateRule(list,3,"对于前端点位异常情况的处理","镜头故障或污染或树枝遮挡或枪机视角偏移正常角度或补光灯应亮未亮,24小时后未修复的",48D,25D,RuleDeductCategoryEnum.MULTIPLY_POINTS_BY_QUANTITY,0.5);
        setTemplateRule(list,null,"对于前端点位异常情况的处理","镜头故障或污染或树枝遮挡或枪机视角偏移正常角度或补光灯应亮未亮,48小时后未修复的",null,49D,RuleDeductCategoryEnum.MULTIPLY_POINTS_BY_QUANTITY,1.0);
        setTemplateRule(list,5,"确保录像完整不定期对所有点位录像完整性抽查","每路视频累计丢失10分钟(含)以内",10D,null,RuleDeductCategoryEnum.MULTIPLY_POINTS_BY_QUANTITY,0.2);
        setTemplateRule(list,4,"确保录像完整不定期对所有点位录像完整性抽查","每路视频累计丢失10分钟(含)以内",10D,null,RuleDeductCategoryEnum.MULTIPLY_POINTS_BY_QUANTITY,0.2);
        setTemplateRule(list,null,"确保录像完整不定期对所有点位录像完整性抽查","丢失10-60 分钟(含)",60D,9D,RuleDeductCategoryEnum.MULTIPLY_POINTS_BY_QUANTITY,0.5);
        setTemplateRule(list,null,"确保录像完整不定期对所有点位录像完整性抽查","丢失1 小时-4 小时(含)",240D,59D,RuleDeductCategoryEnum.MULTIPLY_POINTS_BY_QUANTITY,1.0);
        setTemplateRule(list,null,"确保录像完整不定期对所有点位录像完整性抽查","丢失4 小时-12 小时(含)",720D,539D,RuleDeductCategoryEnum.MULTIPLY_POINTS_BY_QUANTITY,1.5);
        setTemplateRule(list,null,"确保录像完整不定期对所有点位录像完整性抽查","丢失12 小时以上",null,719D,RuleDeductCategoryEnum.MULTIPLY_POINTS_BY_QUANTITY,2.0);
        setTemplateRule(list,6,"确保图片完整不定期对所有人脸车辆以及智能前端抓拍的图片完整性抽查","发现后台存储不能调取前端设备图片",null,null,RuleDeductCategoryEnum.MULTIPLY_POINTS_BY_QUANTITY,2.0);
        setTemplateRule(list,5,"确保图片完整不定期对所有人脸车辆以及智能前端抓拍的图片完整性抽查","发现后台存储不能调取前端设备图片",null,null,RuleDeductCategoryEnum.MULTIPLY_POINTS_BY_QUANTITY,2.0);
        return list;
    }
ycl-server/src/main/java/com/ycl/platform/service/impl/TMonitorServiceImpl.java
@@ -610,7 +610,16 @@
            }
        }
        List<String> deviceIds = tMonitorResults.stream().map(BaseResult::getNo).collect(Collectors.toList());
        Query query = getQuery(deviceIds, exportForm.getMonth());
        // 将年月字符串解析为YearMonth对象
        YearMonth yearMonth = YearMonth.parse(exportForm.getMonth());
        // 获取当月的第一天
        LocalDate start = yearMonth.atDay(1);
        // 获取下个月的第一天(通过加上1个月并设置日为1)
        YearMonth nextMonth = yearMonth.plusMonths(1);
        LocalDate end = nextMonth.atDay(1);
        //获取这个月份的部门数据,录像由于是前一天的所以不用createTime字段
        Query query = new Query(Criteria.where("statTime").gte(start).lt(end));
        query.addCriteria(Criteria.where("no").in(deviceIds));
        //月份每日录像线数据
        List<RecordMetaDSumResult> recordResult = mongoTemplate.find(query, RecordMetaDSumResult.class);
        //全量表
@@ -686,7 +695,16 @@
            }
        }
        List<String> deviceIds = tMonitorResults.stream().map(BaseResult::getNo).collect(Collectors.toList());
        Query query = getQuery(deviceIds, exportForm.getMonth());
        // 将年月字符串解析为YearMonth对象
        YearMonth yearMonth = YearMonth.parse(exportForm.getMonth());
        // 获取当月的第一天
        LocalDate start = yearMonth.atDay(1);
        // 获取下个月的第一天(通过加上1个月并设置日为1)
        YearMonth nextMonth = yearMonth.plusMonths(1);
        LocalDate end = nextMonth.atDay(1);
        //获取这个月份的部门数据,录像由于是前一天的所以不用createTime字段
        Query query = new Query(Criteria.where("statTime").gte(start).lt(end));
        query.addCriteria(Criteria.where("no").in(deviceIds));
        //月份每日录像线数据
        List<RecordMetaDSumResult> recordResult = mongoTemplate.find(query, RecordMetaDSumResult.class);
        //全量表
@@ -894,7 +912,15 @@
            monitor.setTag(tag.toString());
        });
        ExcelUtil<TMonitorExp> util = new ExcelUtil<>(TMonitorExp.class);
        util.exportExcel(response, monitors, "2".equals(tMonitor.getCameraFunType()) ? "车辆" : "人脸");
        String sheetName = "";
        if("1".equals(tMonitor.getCameraFunType())){
            sheetName = "视频";
        }else if("2".equals(tMonitor.getCameraFunType())){
            sheetName = "车辆";
        }else if("3".equals(tMonitor.getCameraFunType())){
            sheetName = "人脸";
        }
        util.exportExcel(response, monitors,sheetName);
    }
@@ -1172,7 +1198,7 @@
        //一个设备当月在线情况
        List<RecordMetaDSumResult> recordResults = records.stream().filter(online -> online.getNo().equals(result.getNo())).collect(Collectors.toList());
        for (RecordMetaDSumResult recordResult : recordResults) {
            int dayOfMonth = recordResult.getMongoCreateTime().getDayOfMonth();
            int dayOfMonth = DateUtils.getDayOfMonth(recordResult.getStatTime());
            Integer status = recordResult.getRecordStatus();
            String text = "";
            if (ApiConstants.UY_RecordStatus_Interval.equals(status)) {
@@ -1194,7 +1220,7 @@
        //一个设备当月在线情况
        List<RecordMetaDSumResult> recordResults = records.stream().filter(online -> online.getNo().equals(result.getNo())).collect(Collectors.toList());
        for (RecordMetaDSumResult recordResult : recordResults) {
            int dayOfMonth = recordResult.getMongoCreateTime().getDayOfMonth();
            int dayOfMonth = DateUtils.getDayOfMonth(recordResult.getStatTime());
            //反射赋值,字段统一定义为day+1,2,3...
            Field field = videoDailyExp.getClass().getDeclaredField("day" + dayOfMonth);
            field.setAccessible(true);
ycl-server/src/main/java/com/ycl/platform/service/impl/WorkOrderServiceImpl.java
@@ -171,18 +171,18 @@
                    //避免代下发的工单直接变成下发
                    if (!databaseWorkOrder.getStatus().equals(WorkOrderStatusEnum.WAIT_DISTRIBUTE)) {
                        databaseWorkOrder.setStatus(WorkOrderStatusEnum.DISTRIBUTED);
                        // 同时新增一个运维处理信息,表明此工单被调整
                        WorkOrderYwConditionRecord ywRecord = new WorkOrderYwConditionRecord();
                        ywRecord.setWorkOrderNo(databaseWorkOrder.getWorkOrderNo());
                        ywRecord.setCommitUser(1);
                        ywRecord.setYwCondition("故障类型更新,工单状态调整为待处理");
                        ywRecord.setCreateTime(new Date());
                        ywRecord.setSysMsg(Boolean.TRUE);
                        willAddMsg.add(ywRecord);
                    }
                    databaseWorkOrder.setUpdateTime(now);
                    willUpdateStatusWorkOrderList.add(databaseWorkOrder);
                    updateNum++;
                    // 同时新增一个运维处理信息,表明此工单被调整
                    WorkOrderYwConditionRecord ywRecord = new WorkOrderYwConditionRecord();
                    ywRecord.setWorkOrderNo(databaseWorkOrder.getWorkOrderNo());
                    ywRecord.setCommitUser(1);
                    ywRecord.setYwCondition("故障类型更新,工单状态调整为待处理");
                    ywRecord.setCreateTime(new Date());
                    ywRecord.setSysMsg(Boolean.TRUE);
                    willAddMsg.add(ywRecord);
                }
            } else {
                workOrder.setCreateTime(new Date());
@@ -319,46 +319,109 @@
     */
    @Override
    public Result add(WorkOrderForm form) {
        //TODO:同个国标工单增加故障类型
        //检查白名单
        List<WorkOrder> data = new ArrayList<>();
        WorkOrder workOrder = WorkOrderForm.getEntityByForm(form, null);
        data.add(workOrder);
        //校验白名单并排除在白名单的故障类型
        data = checkWhite(data);
        if (CollectionUtils.isEmpty(data)) {
            return Result.error("该设备的故障类型在白名单中,不能添加工单");
        }
        WorkOrder entity = data.get(0);
        //查redis今日工单数量
        int workOrderNum = 0;
        //UUID作为value,保证上锁的线程自己解锁
        String requestId = IdUtils.fastSimpleUUID();
        boolean result = redisCache.acquireLock(RedisConstant.WORKORDER_NUM_LOCK, requestId, 10000);
        if (result) {
            //查今日工单量
            Object redisNum = redisCache.getCacheObject(RedisConstant.WORKORDER_NUM);
            workOrderNum = redisNum == null ? 0 : (Integer) redisNum;
            workOrderNum++;
            redisCache.setCacheObject(RedisConstant.WORKORDER_NUM, workOrderNum);
            redisCache.releaseLock(RedisConstant.WORKORDER_NUM_LOCK, requestId);
        } else {
            return Result.error("工单正在添加,请稍后再试");
        }
        entity.setCreateTime(DateUtils.getNowDate());
        entity.setStatus(WorkOrderStatusEnum.WAIT_DISTRIBUTE);
        String serialNumber = entity.getSerialNumber();
        Date now = new Date();
        entity.setCreateTime(now);
        entity.setUpdateTime(now);
        entity.setWorkOrderNo(IdUtils.workOrderNO(now, String.format("%05d", workOrderNum)));
        entity.setErrorType(String.join(",", form.getErrorType()));
        List<WorkOrderErrorType> workOrderErrorTypes = form.getErrorType().stream().map(errorType -> new WorkOrderErrorType(entity.getWorkOrderNo(), errorType)).toList();
        workOrderErrorTypeService.getBaseMapper().insertWorkOrderErrorTypeList(workOrderErrorTypes);
        if (baseMapper.insert(entity) > 0) {
        List<WorkOrder> inDatabaseWorkOrderList = baseMapper.getNotFinishedWorkOrders(Arrays.asList(serialNumber));
        inDatabaseWorkOrderList.stream().forEach(item -> {
            if (StringUtils.hasText(item.getErrorType())) {
                item.setErrorTypeList(List.of(item.getErrorType().split(",")));
            } else {
                item.setErrorTypeList(new ArrayList<>(1));
            }
        });
        // 因故障类型不一致而要更新状态的工单
        List<WorkOrder> willUpdateStatusWorkOrderList = new ArrayList<>(48);
        // 更改工单类型而要增加的系统运维处理信息
        List<WorkOrderYwConditionRecord> willAddMsg = new ArrayList<>(48);
        // 即将要添加的错误类型
        List<WorkOrderErrorType> willAddErrorType = new ArrayList<>(96);
        if(!CollectionUtils.isEmpty(inDatabaseWorkOrderList)){
            WorkOrder workOrderInDB = inDatabaseWorkOrderList.get(0);
            List<String> errorNameList = workOrderInDB.getErrorTypeList();
            List<String> errorTypes = entity.getErrorTypeList();
            if(errorNameList.containsAll(errorTypes)){
                return Result.error("已有同种故障类型工单");
            }else {
                for (String errorType : errorTypes) {
                    if(!errorNameList.contains(errorType)){
                        // 错误类型不一样,就新增一个错误类型,并且重置工单状态为待处理
                        WorkOrderErrorType workOrderErrorType = new WorkOrderErrorType();
                        workOrderErrorType.setWorkOrderNo(workOrderInDB.getWorkOrderNo());
                        workOrderErrorType.setCreateTime(now);
                        workOrderErrorType.setUpdateTime(now);
                        workOrderErrorType.setErrorName(errorType);
                        willAddErrorType.add(workOrderErrorType);
                    }
                }
                //避免代下发的工单直接变成下发
                if (!workOrderInDB.getStatus().equals(WorkOrderStatusEnum.WAIT_DISTRIBUTE)) {
                    workOrderInDB.setStatus(WorkOrderStatusEnum.DISTRIBUTED);
                    // 同时新增一个运维处理信息,表明此工单被调整
                    WorkOrderYwConditionRecord ywRecord = new WorkOrderYwConditionRecord();
                    ywRecord.setWorkOrderNo(workOrderInDB.getWorkOrderNo());
                    ywRecord.setCommitUser(1);
                    ywRecord.setYwCondition("故障类型更新,工单状态调整为待处理");
                    ywRecord.setCreateTime(new Date());
                    ywRecord.setSysMsg(Boolean.TRUE);
                    willAddMsg.add(ywRecord);
                }
                workOrderInDB.setUpdateTime(now);
                willUpdateStatusWorkOrderList.add(workOrderInDB);
                //修改故障类型
                if (willAddErrorType.size() > 0) {
                    workOrderErrorTypeService.getBaseMapper().addMany(willAddErrorType);
                }
                //增加运维情况
                if (willAddMsg.size() > 0) {
                    workOrderYwConditionRecordMapper.insertMany(willAddMsg);
                }
                //更改工单状态
                if (willUpdateStatusWorkOrderList.size() > 0) {
                    this.baseMapper.updateMany(willUpdateStatusWorkOrderList);
                }
            }
            return Result.ok("添加成功");
        }else {
            //数据库没有正在进行的工单
            //查redis今日工单数量
            int workOrderNum = 0;
            //UUID作为value,保证上锁的线程自己解锁
            String requestId = IdUtils.fastSimpleUUID();
            boolean result = redisCache.acquireLock(RedisConstant.WORKORDER_NUM_LOCK, requestId, 10000);
            if (result) {
                //查今日工单量
                Object redisNum = redisCache.getCacheObject(RedisConstant.WORKORDER_NUM);
                workOrderNum = redisNum == null ? 0 : (Integer) redisNum;
                workOrderNum++;
                redisCache.setCacheObject(RedisConstant.WORKORDER_NUM, workOrderNum);
                redisCache.releaseLock(RedisConstant.WORKORDER_NUM_LOCK, requestId);
            } else {
                return Result.error("工单正在添加,请稍后再试");
            }
            entity.setCreateTime(DateUtils.getNowDate());
            entity.setStatus(WorkOrderStatusEnum.WAIT_DISTRIBUTE);
            entity.setCreateTime(now);
            entity.setUpdateTime(now);
            entity.setWorkOrderNo(IdUtils.workOrderNO(now, String.format("%05d", workOrderNum)));
            entity.setErrorType(String.join(",", form.getErrorType()));
            List<WorkOrderErrorType> workOrderErrorTypes = form.getErrorType().stream().map(errorType -> new WorkOrderErrorType(entity.getWorkOrderNo(), errorType)).toList();
            workOrderErrorTypeService.getBaseMapper().insertWorkOrderErrorTypeList(workOrderErrorTypes);
            if (baseMapper.insert(entity) > 0) {
                return Result.ok("添加成功");
            }else {
                return Result.error("添加失败");
            }
        }
        return Result.error("添加失败");
    }
ycl-server/src/main/java/com/ycl/task/ContractTask.java
@@ -8,10 +8,8 @@
import com.ycl.platform.domain.entity.WorkOrder;
import com.ycl.platform.domain.entity.YwPoint;
import com.ycl.platform.domain.result.HK.PicAccessResult;
import com.ycl.platform.domain.result.HK.SnapshotDataMonitorResult;
import com.ycl.platform.domain.result.SYS.TMonitorResult;
import com.ycl.platform.domain.result.UY.RecordMetaDSumResult;
import com.ycl.platform.domain.result.UY.VideoOnlineResult;
import com.ycl.platform.domain.vo.CalculateRuleVO;
import com.ycl.platform.domain.vo.WorkOrderVO;
import com.ycl.platform.mapper.*;
@@ -36,6 +34,7 @@
import java.math.RoundingMode;
import java.time.LocalDateTime;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;
@@ -44,6 +43,7 @@
 */
@Slf4j
@Component("contractTask")
//TODO:重新看下逻辑
public class ContractTask {
    @Autowired
    private MongoTemplate mongoTemplate;
@@ -71,7 +71,6 @@
     * 合同考核 在线率每日任务检测
     * 查生效的合同关联的公司,获取unitId集合
     * 根据unitId查询对应点位获取各个公司管理的设备Ids
     * 查询三种设备在线不在线情况,封装为一个map<国标码,在线状态>
     * 计算每日每家公司的在线率存入mysql
     * 月底计算平均值,根据在线率和合同标准扣减分数
     */
@@ -83,46 +82,31 @@
        List<Integer> unitIds = ruleVos.stream().map(CalculateRuleVO::getUnitId).collect(Collectors.toList());
        List<YwPoint> ywPoints = ywPointMapper.selectList(new QueryWrapper<YwPoint>().in("unit_id", unitIds));
        //key是unitId value是设备编码集合
        Map<Long, List<String>> unitMap = ywPoints.stream()
        Map<Long, List<YwPoint>> unitMap = ywPoints.stream().filter(point -> point.getUnitId() != null)
                .collect(Collectors.groupingBy(
                        YwPoint::getUnitId,
                        Collectors.mapping(
                                YwPoint::getSerialNumber,
                                Collectors.toList()
                        YwPoint::getUnitId
                        )
                ));
        Map<String, Integer> onlineStatusMap = new HashMap<>();
        Date date = new Date();
        //车辆、人脸
        Query query = new Query();
        query.addCriteria(Criteria
                .where("mongoCreateTime").gte(DateUtils.getDayStart(date)).lt(DateUtils.getDayEnd(date)));
        List<TMonitorResult> tMonitorResults = mongoTemplate.find(query, TMonitorResult.class);
        for (TMonitorResult result : tMonitorResults) {
            if(result.getPingOnline()){
                onlineStatusMap.put(result.getNo(), Online);
            }else {
                onlineStatusMap.put(result.getNo(), Offline);
            }
        }
                );
        //查询报备列表
        List<String> reportNumbers = reportMapper.selectNumberList(AuditStatus_Pass, DateUtils.getDate());
        //计算每个公司的点位在线率
        List<ContractRuleRecord> ruleRecordList = new ArrayList<>();
        unitMap.forEach((unitId, serialNumberList) -> {
        unitMap.forEach((unitId, pointList) -> {
            int totalSite = 0;
            int onlineSite = 0;
            for (String number : serialNumberList) {
            for (YwPoint point : pointList) {
                //报备过不纳入计算
                if (!CollectionUtils.isEmpty(reportNumbers) && reportNumbers.contains(number)) continue;
                Integer status = onlineStatusMap.get(number);
                if (!CollectionUtils.isEmpty(reportNumbers) && reportNumbers.contains(point.getSerialNumber()))
                    continue;
                totalSite++;
                if (Online.equals(status)) {
                if (ApiConstants.UY_OnlineSite_Online.equals(point.getOnline())) {
                    onlineSite++;
                }
            }
            BigDecimal online = new BigDecimal(onlineSite).divide(new BigDecimal(totalSite), 2, RoundingMode.DOWN);
            BigDecimal online = BigDecimal.ONE;
            if (totalSite != 0) {
                online = new BigDecimal(onlineSite).divide(new BigDecimal(totalSite), 2, RoundingMode.DOWN);
            }
            ContractRuleRecord contractRuleRecord = new ContractRuleRecord();
            contractRuleRecord.setSiteOnline(online);
            contractRuleRecord.setCreateTime(new Date());
@@ -138,16 +122,14 @@
    public void calculateOnlineScore() {
        //TODO:检查表
        log.info("开始计算合同点位在线率分数");
        //如果是月底,需要统计平均在线率然后进行积分扣除
//        String now = DateUtils.getDate();
        //月底需要统计平均在线率然后进行积分扣除
        String mouthStart = DateUtils.getMouthStart(new Date());
        String mouthEnd = DateUtils.getMouthEnd(new Date());
//        if (now.equals(mouthEnd)) {
        //查一个月的记录
        List<ContractRuleRecord> ruleMonthRecords = recordMapper.selectMonth(mouthStart, mouthEnd);
        //通过unitId分单位
        //通过unitId分单位,获取当月数据map
        Map<Long, List<ContractRuleRecord>> unitMap = ruleMonthRecords.stream().collect(Collectors.groupingBy(ContractRuleRecord::getUnitId));
        //查在线率规则 获取key为合同id,value为在线率规则的map
        //查在线率规则 获取key为合同id,value为在线率规则集合
        Map<Integer, List<CalculateRuleVO>> contractMap = contractMapper.getCalculateRule(new Date()).stream()
                .filter(calculateRuleVO -> ContractRule.CONTRACT_RULE_Online.getName().equals(calculateRuleVO.getRuleName()))
                .collect(Collectors.groupingBy(CalculateRuleVO::getContractId));
@@ -159,7 +141,7 @@
            CalculateRuleVO calculateRuleVO = ruleList.get(0);
            Integer unitId = calculateRuleVO.getUnitId();
            List<ContractRuleRecord> ruleRecordList = unitMap.get(Long.parseLong(unitId + ""));
            if (!CollectionUtils.isEmpty(ruleMonthRecords)) {
            if (!CollectionUtils.isEmpty(ruleRecordList)) {
                BigDecimal siteOnlineTotal = ruleRecordList.stream().map(ContractRuleRecord::getSiteOnline).reduce(BigDecimal.ZERO, BigDecimal::add);
                BigDecimal siteOnline = siteOnlineTotal.divide(new BigDecimal(ruleRecordList.size()), 2, RoundingMode.DOWN);
                for (CalculateRuleVO ruleVO : ruleList) {
@@ -175,7 +157,6 @@
                }
            }
        });
//        }
        contractScoreService.saveBatch(contractScoreList);
        log.info("结束计算合同点位在线率分数");
    }
@@ -203,8 +184,8 @@
                ));
        //前端感知源治理工作(时钟同步规则、OSD规则、一机一档规则) 获取key为合同id,value为规则的map
        Map<Integer, List<CalculateRuleVO>> monitorRuleMap = ruleMap.get(ContractRule.CONTRACT_RULE_Monitor.getName());
        //存储故障(24小时以内,48小时以内) 获取key为合同id,value为规则的map
        Map<Integer, List<CalculateRuleVO>> storeRuleMap = ruleMap.get(ContractRule.CONTRACT_RULE_Store.getName());
        //存储故障(24小时以内,48小时以内) 获取key为合同id,value为规则的map   (改成手动的了)
//        Map<Integer, List<CalculateRuleVO>> storeRuleMap = ruleMap.get(ContractRule.CONTRACT_RULE_Store.getName());
        //点位异常情况处理 获取key为合同id,value为规则的map
        Map<Integer, List<CalculateRuleVO>> siteRuleMap = ruleMap.get(ContractRule.CONTRACT_RULE_Site.getName());
        //查询报备列表
@@ -221,7 +202,7 @@
                if (reportNumbers.contains(workOrder.getSerialNumber())) continue;
            }
            String errorType = workOrder.getErrorType();
            //存储故障 录像或图片访问异常
            //存储故障 录像或图片访问异常 (改成手动打分了)
//            if (ErrorType.VIDEO_NONE.getValue().equals(errorType) || ErrorType.PIC_URLABNORMAL.getValue().equals(errorType)) {
//                if (!CollectionUtils.isEmpty(storeRuleMap)) {
//                    storeRuleMap.forEach((contractId, rules) -> {
@@ -246,7 +227,7 @@
//                }
//            }
            //前端感知源治理工作(时钟同步规则、OSD规则、一机一档规则)
            if (ErrorType.POINT_INFO_ERROR.getValue().equals(errorType) || ErrorType.OSD_ERROR.getValue().equals(errorType) || ErrorType.CLOCK_SKEW.getValue().equals(errorType)) {
            if (ErrorType.OSD_ERROR.getValue().equals(errorType) || ErrorType.CLOCK_SKEW.getValue().equals(errorType) || ErrorType.CLOCK_RIGHT.getValue().equals(errorType)) {
                if (!CollectionUtils.isEmpty(monitorRuleMap)) {
                    monitorRuleMap.forEach((contractId, rules) -> {
                        Integer unitId = rules.get(0).getUnitId();
@@ -270,7 +251,7 @@
                }
            }
            //点位异常情况处理(镜头异常、摄像头遮挡等)
            if (ErrorType.SCREEN_COLOR_DEVIATION.getValue().equals(errorType) || ErrorType.SNOW_STORM.getValue().equals(errorType) || ErrorType.STRIPE_INTERFERENCE.getValue().equals(errorType) || ErrorType.SCREEN_OCCLUSION.getValue().equals(errorType) || ErrorType.ABNORMAL_CLARITY.getValue().equals(errorType) || ErrorType.ABNORMAL_BRIGHTNESS.getValue().equals(errorType)) {
            if (ErrorType.SCREEN_OCCLUSION.getValue().equals(errorType)) {
                if (!CollectionUtils.isEmpty(monitorRuleMap)) {
                    siteRuleMap.forEach((contractId, rules) -> {
                        Integer unitId = rules.get(0).getUnitId();
@@ -284,7 +265,7 @@
                            for (CalculateRuleVO rule : rules) {
                                if (checkRange(rule.getMin(), rule.getMax(), new BigDecimal(diffTime))) {
                                    double deductScore = 0d;
                                    if (ContractRule.CONTRACT_RULE_Store_48H.getName().equals(rule.getRuleCondition())) {
                                    if (ContractRule.CONTRACT_RULE_Site_Error48.getName().equals(rule.getRuleCondition())) {
                                        //计算超时天数
                                        int day = (int) ((diffTime - 48) / 24 + 1);
                                        deductScore = rule.getCalcFraction() * (day);
@@ -371,8 +352,8 @@
                        }
                        //判断是否是该公司运维
                        if (monitorList.contains(picAccessResult.getExternalIndexCode())) {
                            //存在大图不可用数据量,需要扣减
                            if (picAccessResult.getBigDisableCount() > 0) {
                            //存在图片访问异常数据量,需要扣减
                            if (picAccessResult.getExpCount() > 0) {
                                deduct = true;
                                serialNumber = picAccessResult.getExternalIndexCode();
                                break;
@@ -417,6 +398,7 @@
            List<ContractScore> contractScoreList = new ArrayList<>();
            //查询报备列表
            List<String> reportNumbers = reportMapper.selectNumberList(AuditStatus_Pass, DateUtils.getDate());
            //TODO:测试日期
            Date date = DateUtils.getDay(2024, 7, 13);
            //查图片完整性规则 获取key为合同id,value为规则的map
            Map<Integer, List<CalculateRuleVO>> contractMap = contractMapper.getCalculateRule(new Date()).stream()
ycl-server/src/main/java/com/ycl/task/UYTask.java
@@ -175,6 +175,8 @@
    /**
     * 点位在线PING检测
     * 任务会先执行一次优云同步,然后执行ping检测
     * online字段来自于优云,pingOnline为主动ping检测的。存入mongo给数据中心查阅
     */
    public void pointOnline() throws ExecutionException, InterruptedException {
        log.info("开始检测点位在线");
ycl-server/src/main/java/com/ycl/utils/DateUtils.java
@@ -298,4 +298,11 @@
        Date date = calendar.getTime();
        return date;
    }
    public static Integer getDayOfMonth(Date date) {
        // 创建一个Calendar对象并设置为当前日期和时间
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        // 获取当前日期是当月中的第几天
        return calendar.get(Calendar.DAY_OF_MONTH);
    }
}
ycl-server/src/main/resources/logback.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <!-- 日志存放路径 -->
    <property name="log.path" value="./logs" />
    <property name="log.path" value="/home/java/logs" />
    <!-- 日志输出格式 -->
    <property name="log.pattern" value="%d{HH:mm:ss.SSS} [%thread] %-5level %logger{20} - [%method,%line] - %msg%n" />
@@ -19,8 +19,8 @@
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <!-- 日志文件名格式 -->
            <fileNamePattern>${log.path}/sys-info.%d{yyyy-MM-dd}.log</fileNamePattern>
            <!-- 日志最大的历史 60天 -->
            <maxHistory>60</maxHistory>
            <!-- 日志最大的历史 20天 -->
            <maxHistory>20</maxHistory>
        </rollingPolicy>
        <encoder>
            <pattern>${log.pattern}</pattern>
@@ -41,8 +41,8 @@
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <!-- 日志文件名格式 -->
            <fileNamePattern>${log.path}/sys-error.%d{yyyy-MM-dd}.log</fileNamePattern>
            <!-- 日志最大的历史 60天 -->
            <maxHistory>60</maxHistory>
            <!-- 日志最大的历史 20天 -->
            <maxHistory>20</maxHistory>
        </rollingPolicy>
        <encoder>
            <pattern>${log.pattern}</pattern>
@@ -63,8 +63,8 @@
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <!-- 按天回滚 daily -->
            <fileNamePattern>${log.path}/sys-user.%d{yyyy-MM-dd}.log</fileNamePattern>
            <!-- 日志最大的历史 60天 -->
            <maxHistory>60</maxHistory>
            <!-- 日志最大的历史 20天 -->
            <maxHistory>20</maxHistory>
        </rollingPolicy>
        <encoder>
            <pattern>${log.pattern}</pattern>