zxl
昨天 97b1e0d4820606bef726f60e459b66afb1e8eab1
优化与日志
2个文件已修改
87 ■■■■■ 已修改文件
ycl-server/src/main/java/com/ycl/platform/service/impl/TMonitorServiceImpl.java 80 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ycl-server/src/main/java/com/ycl/task/UYTask.java 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ycl-server/src/main/java/com/ycl/platform/service/impl/TMonitorServiceImpl.java
@@ -608,8 +608,8 @@
        List<TMonitorResult> onlineResult = mongoTemplate.find(query, TMonitorResult.class);
        log.info("大小:{}",onlineResult.size());
        //此处需要过滤掉设备全景在线 细节不在线的情况  可以按 point分组 分我许多组之后再做处理
        Map<String, List<TMonitorResult>> ipToDevices = onlineResult.stream()
                .collect(Collectors.groupingBy(TMonitorResult::getIp));
//        Map<String, List<TMonitorResult>> ipToDevices = onlineResult.stream()
//                .collect(Collectors.groupingBy(TMonitorResult::getIp)); //重要操作 按ip分组
//        onlineResult = ipToDevices.values().stream()
//                .map(devices -> {
@@ -632,7 +632,7 @@
        log.info("月份在线数据:{}条数", onlineResult.size());
        // 使用Collectors.toMap去重,保留每个No的第一个遇到的元素
        Map<String, TMonitorResult> uniqueResultsMap = onlineResult.stream()
        Map<String, TMonitorResult> fullDataMap = onlineResult.stream()
                .collect(Collectors.toMap(
                        TMonitorResult::getNo, // keyMapper,这里假设 getNo() 返回 No 字段
                        Function.identity(),  // valueMapper,直接使用对象本身
@@ -640,16 +640,14 @@
                ));
        // 将 Map 转换为 List
        List<TMonitorResult> tMonitorResults = new ArrayList<>(uniqueResultsMap.values());
        log.info("去重后大小:{}", tMonitorResults.size());
        // 将 Map 转换为 List  去重后减少数据库消耗
        List<TMonitorResult> tMonitorResults = new ArrayList<>(fullDataMap.values());
//        log.info("去重后大小:{}", tMonitorResults.size());
        // 获取动态列数据并构建缓存Map
        Map<Integer, List<DynamicColumnVO>> dynamicColumnMap = new HashMap<>();
        if (!tMonitorResults.isEmpty()) {
            //获取点位集合
            //获取ip集合
            List<Integer> pointIds = tMonitorResults.stream()
                    .map(TMonitorResult::getPointId)
                    .distinct() // 去重,减少数据库查询
@@ -664,36 +662,34 @@
            }
            // 补充动态列数据
            // 去重后的动态列信息
            for (TMonitorResult result : tMonitorResults) {
                result.setDynamicColumnList(dynamicColumnMap.getOrDefault(result.getPointId(), Collections.emptyList()));
            }
        }
        // 按部门分组,减少后续循环中的过滤操作
        Map<Integer, List<TMonitorResult>> deptMonitorMap = tMonitorResults.stream()
        Map<Integer, List<TMonitorResult>> deptMonitorMap = tMonitorResults.stream() //去重后指向 每个设备只有第一天的数据
                .collect(Collectors.groupingBy(TMonitorResult::getDeptId));
        // 按设备编号分组onlineResult,加速后续查找
        Map<String, List<TMonitorResult>> noToOnlineMap = onlineResult.stream()
        Map<String, List<TMonitorResult>> noToOnlineMap = onlineResult.stream() //这里值所以数据以设备标号分组,得到其详情 如 1号到31号的录像情况
                .collect(Collectors.groupingBy(TMonitorResult::getNo));
        // 并行处理各部门数据
        List<CompletableFuture<ExcelExp>> futures = new ArrayList<>(exportForm.getDeptIds().size());
        Map<Integer, List<VideoDailyExp>> deptExpMap = new ConcurrentHashMap<>();
        List<CompletableFuture<ExcelExp>> futures = new ArrayList<>(exportForm.getDeptIds().size());//按前端传入的 部门编号 来判断需要开多少个线程
        Map<Integer, List<VideoDailyExp>> deptExpMap = new ConcurrentHashMap<>();
        for (Integer deptId : exportForm.getDeptIds()) {
            // 使用部门ID的最终变量
            final Integer currentDeptId = deptId;
            CompletableFuture<ExcelExp> future = CompletableFuture.supplyAsync(() -> {
                // 直接从预分组的Map中获取,避免每次过滤
                //  deptMonitorMap上面已经在去重后分过组了(这里只是体现了去重的作用,下方每日数据是通过no在noToOnlineMap中取到的)
                List<TMonitorResult> monitors = deptMonitorMap.getOrDefault(currentDeptId, Collections.emptyList());
                if (monitors.isEmpty()) {
                    return null;
                }
                List<VideoDailyExp> videoDailyExps = new ArrayList<>(monitors.size());
                AreaDeptEnum areaDeptEnum = AreaDeptEnum.fromDept(currentDeptId);
                String areaName = areaDeptEnum == null ? "未知" : areaDeptEnum.getName();
@@ -726,21 +722,22 @@
                    }
                    videoDailyExp.setTag(tag.toString());
                    // 设置在线数据
                    //  设置在线数据重点位置
                    try {
                        // 从预构建的Map中获取,避免每次过滤
                        // 从预构建的Map中获取,避免每次过滤 正确获得在线数据位置
                        List<TMonitorResult> onlines = noToOnlineMap.getOrDefault(result.getNo(), Collections.emptyList());
                        // 重点查看下面这个方法 videoDailyExp 传入需要组装对象的 videoDailyExp 和 数据源result包含动态列信息的对象 和他对应1到31天的在离线状态
                        setOnlineDaily(videoDailyExp, result, onlines);
                    } catch (Exception e) {
                        log.error("设置在线数据异常", e);
                    }
//
                    videoDailyExps.add(videoDailyExp);
                }
                // 存储结果到线程安全的Map
//
                // 存储结果到线程安全的Map 结果如 按区分分组 对应设备的 1到31日的在离线详情
                deptExpMap.put(currentDeptId, videoDailyExps);
//
                return new ExcelExp(areaName, videoDailyExps, VideoDailyExp.class);
            }, threadPoolTaskExecutor);
@@ -778,8 +775,9 @@
        log.info("car数:{}", car);
        log.info("video数:{}", video);
        // 处理离线数统计和在线率统计
        // 离线数统计
        List<VideoTypeOffOnlineExp> videoTypeOffOnlineExps = new ArrayList<>();
        // 在线率统计
        List<VideoOnlineRateExp> videoOnlineRateExps = new ArrayList<>();
        for (Map.Entry<Integer, List<VideoDailyExp>> entry : deptExpMap.entrySet()) {
@@ -787,7 +785,7 @@
            List<VideoDailyExp> list = entry.getValue();
            AreaDeptEnum areaDeptEnum = AreaDeptEnum.fromDept(deptId);
            // 批量处理三种设备类型
            // 批量处理三种设备类型 每个设备1到31号在离线情况
            addDeviceStats(list, areaDeptEnum, "1", "人脸", videoTypeOffOnlineExps, videoOnlineRateExps);
            addDeviceStats(list, areaDeptEnum, "2", "卡口", videoTypeOffOnlineExps, videoOnlineRateExps);
            addDeviceStats(list, areaDeptEnum, "3", "视频", videoTypeOffOnlineExps, videoOnlineRateExps);
@@ -893,7 +891,7 @@
        videoTypeOffOnlineExp.setArea("自贡市");
        videoTypeOffOnlineExp.setType(type + "合计");
    }
    //在线设备数据,合计对象,信息装配
//    在线设备数据,合计对象,信息装配
    public void setAllVideoTypeOnlineExpCount(
            long allVideoCount,List<VideoOnlineRateExp> videoOnlineRateExps,
                                              VideoOnlineRateExp videoOnlineRateExp,
@@ -1069,18 +1067,27 @@
            String fieldName = "day" + i;
            String countName = "count" + i;
            for(VideoDailyExp videoDailyExp: videoDailyExps){
                // 构造字段名
                Field field = videoDailyExp.getClass().getDeclaredField(fieldName);
                // 确保字段是私有的可以访问
                field.setAccessible(true);
                // 获取字段值
                String value = (String) field.get(videoDailyExp);
                if ("在线".equals(value)) {
                    count ++;
                try {
                    // 构造字段名
                    Field field = videoDailyExp.getClass().getDeclaredField(fieldName);
                    // 确保字段是私有的可以访问
                    field.setAccessible(true);
                    // 获取字段值
                    String value = (String) field.get(videoDailyExp);
                    if ("在线".equals(value)) {
                        count ++;
                    }
                } catch (NoSuchFieldException e) {
                    // 字段不存在时跳过当前循环,记录日志
                    log.warn("VideoDailyExp 不存在字段: {}", fieldName, e);
                } catch (IllegalAccessException e) {
                    // 字段访问异常时跳过,记录日志
                    log.error("访问字段 {} 失败", fieldName, e);
                }
            }
            //每日在线率
            double rate = (double) count / videoDailyExps.size();
            log.info("打印计算出的count:{}",count);
            //反射添加到对象属性中
            Field field = videoOnlineRateExp.getClass().getDeclaredField(fieldName);
            Field countField = videoOnlineRateExp.getClass().getDeclaredField(countName);
@@ -1898,6 +1905,7 @@
        List<TMonitorResult> onlineResult = onlines.stream().filter(online -> online.getNo().equals(result.getNo())).collect(Collectors.toList());
        videoDailyExp.setOnlineStateList(onlineResult);
        for (TMonitorResult monitorResult : onlineResult) {
            //为空白的原因 如进入第1号时 monitorResult没有对应一号的数据,就是一号mongodb里面没有对应该设备的数据
            int dayOfMonth = monitorResult.getMongoCreateTime().getDayOfMonth();
            String online = "";
            if (ApiConstants.UY_OnlineSite_Online.equals(monitorResult.getOnline())) {
@@ -1912,8 +1920,6 @@
            field.setAccessible(true);
            field.set(videoDailyExp, online);
        }
    }
    //设置每日录像数据
ycl-server/src/main/java/com/ycl/task/UYTask.java
@@ -324,6 +324,13 @@
                .values()
                .stream()
                .map(TMonitorResult::getWorkOrder)
                .collect(Collectors.toMap(
                        WorkOrder::getSerialNumber,  // 按serialNumber去重
                        Function.identity(),
                        (existing, replacement) -> replacement  // 重复时保留最后一个,可根据业务调整
                ))
                .values()
                .stream()
                .collect(Collectors.toList());
        if (!CollectionUtils.isEmpty(workOrderList)) {
            log.error("pointOnline获得插入工单:{}",workOrderList);