fuliqi
2025-01-02 73caf5a7072976021f43a764ed2ad73404f4d040
ycl-server/src/main/java/com/ycl/platform/service/impl/TMonitorServiceImpl.java
@@ -3,6 +3,7 @@
import annotation.DataScope;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.mongodb.ExplainVerbosity;
import com.mongodb.client.AggregateIterable;
import com.mongodb.client.MongoCollection;
import com.mongodb.client.MongoDatabase;
@@ -54,6 +55,7 @@
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import pojo.ExcelExp;
@@ -72,6 +74,9 @@
import java.time.format.DateTimeFormatter;
import java.time.temporal.TemporalAdjusters;
import java.util.*;
import java.util.concurrent.*;
import java.util.function.BinaryOperator;
import java.util.function.Function;
import java.util.stream.Collectors;
/**
@@ -94,6 +99,8 @@
    private SysDictDataMapper dictDataMapper;
    @Autowired
    private DynamicColumnMapper dynamicColumnMapper;
    @Autowired
    private ThreadPoolTaskExecutor threadPoolTaskExecutor;
    /**
     * 查询设备资产
@@ -355,6 +362,7 @@
    /**
     *  查mongo查某个月设备总数
     *  查看工单数量查看异常的数
     *
     * @param monitorQuery 查询条件
     * @return
     */
@@ -432,27 +440,48 @@
            }
            exportForm.setDeptIds(deptIds);
        }
        List<ExcelExp> mysheet = new ArrayList<>();
        exportForm.setCameraFunType(Integer.valueOf(CheckConstants.Rule_Category_Video + ""));
        List<ExcelExp> sheet = new ArrayList<>();
        //通过Collections静态方法,把list转为线程安全的list
        List mysheet = Collections.synchronizedList(sheet);
        VideoExportForm.convertTags(exportForm);
        List<TMonitorResult> tMonitorResults = tMonitorMapper.selectMonitorResult(exportForm);
        List<String> deviceIds = tMonitorResults.stream().map(BaseResult::getNo).collect(Collectors.toList());
        Query query = getQuery(deviceIds, exportForm.getMonth());
        Query query = getQuery(exportForm);
        //月份每日在线数据
        List<TMonitorResult> onlineResult = mongoTemplate.find(query, TMonitorResult.class);
        // 使用 Collectors.toMap 去重,保留每个 No 的第一个遇到的元素
        Map<String, TMonitorResult> uniqueResultsMap = onlineResult.stream()
                .collect(Collectors.toMap(
                        TMonitorResult::getNo, // keyMapper,这里假设 getNo() 返回 No 字段
                        Function.identity(),  // valueMapper,直接使用对象本身
                        (existing, replacement) -> existing // mergeFunction,如果有重复,保留第一个
                ));
        // 将 Map 转换为 List
        List<TMonitorResult> tMonitorResults = new ArrayList<>(uniqueResultsMap.values());
        List<String> deviceIds = tMonitorResults.stream().map(BaseResult::getNo).collect(Collectors.toList());
        // 将年月字符串解析为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 videoQuery = new Query(Criteria.where("statTime").gte(start).lt(end));
        videoQuery.addCriteria(Criteria.where("no").in(deviceIds));
        //月份每日录像数据
        List<RecordMetaDSumResult> recordResult = mongoTemplate.find(query, RecordMetaDSumResult.class);
        List<RecordMetaDSumResult> recordResult = mongoTemplate.find(videoQuery, RecordMetaDSumResult.class);
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
        String[] weeks = {"星期一", "星期二", "星期三", "星期四", "星期五", "星期六", "星期日"};
        // 创建一个Map来存储每天的累加数据
        Map<String, VideoTotalExp> totalMap = new HashMap<>();
        Map<String, VideoTotalExp> totalMap = new ConcurrentHashMap<>();
        List<CompletableFuture<Void>> futures = new ArrayList<>();
        //一个部门一个sheet
        for (Integer deptId : exportForm.getDeptIds()) {
            //从数据库集合筛选部门数据
            List<String> ids = tMonitorResults.stream().filter(tMonitorResult -> deptId.equals(tMonitorResult.getDeptId())).map(BaseResult::getNo).collect(Collectors.toList());
            if (CollectionUtils.isEmpty(ids)) continue;
            CompletableFuture<Void> future = CompletableFuture.runAsync(() -> {
            //筛选部门数据
            List<TMonitorResult> onlineList = onlineResult.stream().filter(tMonitorResult -> ids.contains(tMonitorResult.getNo())).collect(Collectors.toList());
                Set<String> ids = onlineResult.stream().filter(tMonitorResult -> deptId.equals(tMonitorResult.getDeptId())).map(BaseResult::getNo).collect(Collectors.toSet());
                if (CollectionUtils.isEmpty(ids)) return;
                //筛选部门数据
                List<TMonitorResult> onlineList = onlineResult.stream().filter(tMonitorResult -> deptId.equals(tMonitorResult.getDeptId())).collect(Collectors.toList());
            List<RecordMetaDSumResult> recordList = recordResult.stream().filter(result -> ids.contains(result.getNo())).collect(Collectors.toList());
            List<VideoTotalExp> videoTotalExps = new ArrayList<>();
            for (int i = 0; i < 31; i++) {
@@ -500,7 +529,13 @@
            AreaDeptEnum areaDeptEnum = AreaDeptEnum.fromDept(deptId);
            ExcelExp excelExp = new ExcelExp(areaDeptEnum == null ? "未知" : areaDeptEnum.getName(), videoTotalExps, VideoTotalExp.class);
            mysheet.add(excelExp);
            }, threadPoolTaskExecutor);
            futures.add(future);
        }
        // 等待所有任务完成
        CompletableFuture<Void> allFutures = CompletableFuture.allOf(futures.toArray(new CompletableFuture[0]));
        allFutures.join(); // 这将阻塞直到所有任务完成
        //添加全量表
        List<VideoTotalExp> totalExps = new ArrayList<>(totalMap.values());
        totalExps = totalExps.stream().sorted(Comparator.comparing(VideoTotalExp::getDate)).collect(Collectors.toList());
@@ -525,10 +560,22 @@
            }
            exportForm.setDeptIds(deptIds);
        }
        List<ExcelExp> mysheet = new ArrayList<>();
        exportForm.setCameraFunType(Integer.valueOf(CheckConstants.Rule_Category_Video + ""));
        List<ExcelExp> sheet = new ArrayList<>();
        //通过Collections静态方法,把list转为线程安全的list
        List mysheet = Collections.synchronizedList(sheet);
        VideoExportForm.convertTags(exportForm);
        List<TMonitorResult> tMonitorResults = tMonitorMapper.selectMonitorResult(exportForm);
        Query query = getQuery(exportForm);
        //月份每日在线数据
        List<TMonitorResult> onlineResult = mongoTemplate.find(query, TMonitorResult.class);
        // 使用 Collectors.toMap 去重,保留每个 No 的第一个遇到的元素
        Map<String, TMonitorResult> uniqueResultsMap = onlineResult.stream()
                .collect(Collectors.toMap(
                        TMonitorResult::getNo, // keyMapper,这里假设 getNo() 返回 No 字段
                        Function.identity(),  // valueMapper,直接使用对象本身
                        (existing, replacement) -> existing // mergeFunction,如果有重复,保留第一个
                ));
        // 将 Map 转换为 List
        List<TMonitorResult> tMonitorResults = new ArrayList<>(uniqueResultsMap.values());
        //获取动态列数据
        List<Integer> pointIds = tMonitorResults.stream().map(TMonitorResult::getPointId).collect(Collectors.toList());
        List<DynamicColumnVO> dynamics = dynamicColumnMapper.getDynamicsByIds("t_yw_point", pointIds);
@@ -540,47 +587,73 @@
                tMonitorResult.setDynamicColumnList(map.get(pointId));
            }
        }
        List<String> deviceIds = tMonitorResults.stream().map(BaseResult::getNo).collect(Collectors.toList());
        Query query = getQuery(deviceIds, exportForm.getMonth());
        //月份每日在线数据
        List<TMonitorResult> onlineResult = mongoTemplate.find(query, TMonitorResult.class);
        //全量表
        List<VideoDailyExp> totalExps = new ArrayList<>();
        List<CompletableFuture<List<VideoDailyExp>>> futures = new ArrayList<>();
        for (Integer deptId : exportForm.getDeptIds()) {
            CompletableFuture<List<VideoDailyExp>> future = CompletableFuture.supplyAsync(() -> {
            List<VideoDailyExp> videoDailyExps = new ArrayList<>();
            //从数据库集合筛选部门数据
            List<TMonitorResult> monitors = tMonitorResults.stream().filter(tMonitorResult -> deptId.equals(tMonitorResult.getDeptId())).collect(Collectors.toList());
            if (CollectionUtils.isEmpty(monitors)) continue;
            List<String> ids = monitors.stream().map(BaseResult::getNo).collect(Collectors.toList());
                //筛选部门数据
                List<TMonitorResult> monitors = tMonitorResults.stream()
                        .filter(tMonitorResult -> deptId.equals(tMonitorResult.getDeptId()))
                        .collect(Collectors.toList());
                if (CollectionUtils.isEmpty(monitors)) return videoDailyExps;
                List<String> ids = monitors.stream()
                        .map(BaseResult::getNo)
                        .collect(Collectors.toList());
            //筛选mongo区县数据
            List<TMonitorResult> onlines = onlineResult.stream().filter(result -> ids.contains(result.getNo())).collect(Collectors.toList());
                List<TMonitorResult> onlines = onlineResult.stream()
                        .filter(result -> ids.contains(result.getNo()))
                        .collect(Collectors.toList());
            AreaDeptEnum areaDeptEnum = AreaDeptEnum.fromDept(deptId);
            for (TMonitorResult result : monitors) {
                VideoDailyExp videoDailyExp = new VideoDailyExp();
                videoDailyExp.setSerialNumber(result.getNo());
                videoDailyExp.setDeviceName(result.getName());
                videoDailyExp.setArea(areaDeptEnum == null ? "未知" : areaDeptEnum.getName());
                StringBuilder tag = new StringBuilder("" + (result.getProvinceTag() ? "省厅、" : "") + (result.getImportantTag() ? "重点点位、" : "") + (result.getImportantCommandImageTag() ? "重点指挥图像、" : "") + (result.getDeptTag() ? "部级、" : ""));
                    StringBuilder tag = new StringBuilder("" +
                            (result.getProvinceTag() ? "省厅、" : "") +
                            (result.getImportantTag() ? "重点点位、" : "") +
                            (result.getImportantCommandImageTag() ? "重点指挥图像、" : "") +
                            (result.getDeptTag() ? "部级、" : ""));
                //动态列处理加在标签里
                if (!CollectionUtils.isEmpty(result.getDynamicColumnList())) {
                    List<DynamicColumnVO> dynamicColumnList = result.getDynamicColumnList();
                    for (DynamicColumnVO dynamicColumnVO : dynamicColumnList) {
                        for (DynamicColumnVO dynamicColumnVO : result.getDynamicColumnList()) {
                        tag.append(dynamicColumnVO.getColumnValue()).append("、");
                    }
                }
                // 删除字符串末尾的“、”
                    // 删除字符串末尾的"、"
                if (tag.toString().endsWith("、")) {
                    tag = new StringBuilder(tag.substring(0, tag.length() - 1));
                }
                videoDailyExp.setTag(tag.toString());
                    try {
                setOnlineDaily(videoDailyExp, result, onlines);
                    } catch (Exception e) {
                        log.error(e.getMessage());
                    }
                videoDailyExps.add(videoDailyExp);
                //全量表
                totalExps.add(videoDailyExp);
            }
            ExcelExp excelExp = new ExcelExp(areaDeptEnum == null ? "未知" : areaDeptEnum.getName(), videoDailyExps, VideoDailyExp.class);
                ExcelExp excelExp = new ExcelExp(
                        areaDeptEnum == null ? "未知" : areaDeptEnum.getName(),
                        videoDailyExps,
                        VideoDailyExp.class
                );
            mysheet.add(excelExp);
                return videoDailyExps;
            }, threadPoolTaskExecutor);
            futures.add(future);
        }
        // 获取全量数据
        List<VideoDailyExp> totalExps = futures.stream()
                .map(CompletableFuture::join)
                .flatMap(List::stream)
                .collect(Collectors.toList());
        ExcelExp excelExp = new ExcelExp("全量", totalExps, VideoDailyExp.class);
        mysheet.add(excelExp);
        ExcelUtilManySheet<List<ExcelExp>> util = new ExcelUtilManySheet<>(mysheet);
@@ -601,10 +674,22 @@
            }
            exportForm.setDeptIds(deptIds);
        }
        List<ExcelExp> mysheet = new ArrayList<>();
        exportForm.setCameraFunType(Integer.valueOf(CheckConstants.Rule_Category_Video + ""));
        VideoExportForm.convertTags(exportForm);
        List<TMonitorResult> tMonitorResults = tMonitorMapper.selectMonitorResult(exportForm);
        Query query = getQuery(exportForm);
        //月份每日在线数据
        List<TMonitorResult> onlineResult = mongoTemplate.find(query, TMonitorResult.class);
        // 使用 Collectors.toMap 去重,保留每个 No 的第一个遇到的元素
        Map<String, TMonitorResult> uniqueResultsMap = onlineResult.stream()
                .collect(Collectors.toMap(
                        TMonitorResult::getNo, // keyMapper,这里假设 getNo() 返回 No 字段
                        Function.identity(),  // valueMapper,直接使用对象本身
                        (existing, replacement) -> existing // mergeFunction,如果有重复,保留第一个
                ));
        // 将 Map 转换为 List
        List<TMonitorResult> tMonitorResults = new ArrayList<>(uniqueResultsMap.values());
        List<String> deviceIds = tMonitorResults.stream().map(BaseResult::getNo).collect(Collectors.toList());
        //获取动态列数据
        List<Integer> pointIds = tMonitorResults.stream().map(TMonitorResult::getPointId).collect(Collectors.toList());
        List<DynamicColumnVO> dynamics = dynamicColumnMapper.getDynamicsByIds("t_yw_point", pointIds);
@@ -616,7 +701,7 @@
                tMonitorResult.setDynamicColumnList(map.get(pointId));
            }
        }
        List<String> deviceIds = tMonitorResults.stream().map(BaseResult::getNo).collect(Collectors.toList());
        // 将年月字符串解析为YearMonth对象
        YearMonth yearMonth = YearMonth.parse(exportForm.getMonth());
        // 获取当月的第一天
@@ -625,20 +710,24 @@
        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));
        Query videoQuery = new Query(Criteria.where("statTime").gte(start).lt(end));
        videoQuery.addCriteria(Criteria.where("no").in(deviceIds));
        //月份每日录像线数据
        List<RecordMetaDSumResult> recordResult = mongoTemplate.find(query, RecordMetaDSumResult.class);
        //全量表
        List<VideoDailyExp> totalExps = new ArrayList<>();
        List<RecordMetaDSumResult> recordResult = mongoTemplate.find(videoQuery, RecordMetaDSumResult.class);
        // 预先按部门ID分组
        Map<Integer, List<TMonitorResult>> monitorsByDept = tMonitorResults.stream()
                .collect(Collectors.groupingBy(TMonitorResult::getDeptId));
        // 预先构建映射
        Map<String, List<RecordMetaDSumResult>> recordMap = recordResult.stream()
                .collect(Collectors.groupingBy(RecordMetaDSumResult::getNo));
        List<CompletableFuture<List<VideoDailyExp>>> futures = new ArrayList<>();
        for (Integer deptId : exportForm.getDeptIds()) {
            CompletableFuture<List<VideoDailyExp>> future = CompletableFuture.supplyAsync(() -> {
            List<VideoDailyExp> videoDailyExps = new ArrayList<>();
            //从数据库集合筛选部门数据
            List<TMonitorResult> monitors = tMonitorResults.stream().filter(tMonitorResult -> deptId.equals(tMonitorResult.getDeptId())).collect(Collectors.toList());
            if (CollectionUtils.isEmpty(monitors)) continue;
            List<String> ids = monitors.stream().map(BaseResult::getNo).collect(Collectors.toList());
            //筛选mongo区县数据
            List<RecordMetaDSumResult> records = recordResult.stream().filter(result -> ids.contains(result.getNo())).collect(Collectors.toList());
                // 获取当前部门的数据
                List<TMonitorResult> monitors = monitorsByDept.getOrDefault(deptId, Collections.emptyList());
                if (CollectionUtils.isEmpty(monitors)) return videoDailyExps;
            AreaDeptEnum areaDeptEnum = AreaDeptEnum.fromDept(deptId);
            for (TMonitorResult result : monitors) {
                VideoDailyExp videoDailyExp = new VideoDailyExp();
@@ -658,15 +747,37 @@
                    tag = new StringBuilder(tag.substring(0, tag.length() - 1));
                }
                videoDailyExp.setTag(tag.toString());
                setRecordDaily(videoDailyExp, result, records);
                    // 使用Map直接获取记录,避免filter操作
                    List<RecordMetaDSumResult> recordsResult = recordMap.get(result.getNo());
                    try {
                        if(!CollectionUtils.isEmpty(recordsResult)) setRecordDaily(videoDailyExp, result, recordsResult);
                    } catch (Exception e) {
                        log.error(e.getMessage());
                    }
                //区县表
                videoDailyExps.add(videoDailyExp);
                //全量表
                totalExps.add(videoDailyExp);
            }
            ExcelExp excelExp = new ExcelExp(areaDeptEnum == null ? "未知" : areaDeptEnum.getName(), videoDailyExps, VideoDailyExp.class);
                return videoDailyExps;
            }, threadPoolTaskExecutor);
            futures.add(future);
        }
        // 等待所有任务完成
        CompletableFuture.allOf(futures.toArray(new CompletableFuture[0])).join();
        // 每个部门的数据单独保存
        List<List<VideoDailyExp>> results = futures.stream()
                .map(CompletableFuture::join)  // 获取每个Future的结果
                .collect(Collectors.toList());
        List<VideoDailyExp> totalExps = new ArrayList<>();
        List<ExcelExp> mysheet = new ArrayList<>();
        for (List<VideoDailyExp> result : results) {
            ExcelExp excelExp = new ExcelExp(
                    result.get(0).getArea() == null ? "未知" : result.get(0).getArea(),
                    result,
                    VideoDailyExp.class);
            mysheet.add(excelExp);
            totalExps.addAll(result);
        }
        ExcelExp excelExp = new ExcelExp("全量", totalExps, VideoDailyExp.class);
        mysheet.add(excelExp);
        ExcelUtilManySheet<List<ExcelExp>> util = new ExcelUtilManySheet<>(mysheet);
@@ -686,10 +797,18 @@
            }
            exportForm.setDeptIds(deptIds);
        }
        List<ExcelExp> mysheet = new ArrayList<>();
        exportForm.setCameraFunType(Integer.valueOf(CheckConstants.Rule_Category_Video + ""));
        VideoExportForm.convertTags(exportForm);
        List<TMonitorResult> tMonitorResults = tMonitorMapper.selectMonitorResult(exportForm);
        Query query = getQuery(exportForm);
        //月份每日在线数据
        List<TMonitorResult> onlineResult = mongoTemplate.find(query, TMonitorResult.class);
        // 使用 Collectors.toMap 去重,保留每个 No 的第一个遇到的元素
        Map<String, TMonitorResult> uniqueResultsMap = onlineResult.stream()
                .collect(Collectors.toMap(
                        TMonitorResult::getNo, // keyMapper,这里假设 getNo() 返回 No 字段
                        Function.identity(),  // valueMapper,直接使用对象本身
                        (existing, replacement) -> existing // mergeFunction,如果有重复,保留第一个
                ));
        // 将 Map 转换为 List
        List<TMonitorResult> tMonitorResults = new ArrayList<>(uniqueResultsMap.values());
        //获取动态列数据
        List<Integer> pointIds = tMonitorResults.stream().map(TMonitorResult::getPointId).collect(Collectors.toList());
        List<DynamicColumnVO> dynamics = dynamicColumnMapper.getDynamicsByIds("t_yw_point", pointIds);
@@ -710,20 +829,24 @@
        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));
        Query videoQuery = new Query(Criteria.where("statTime").gte(start).lt(end));
        videoQuery.addCriteria(Criteria.where("no").in(deviceIds));
        //月份每日录像线数据
        List<RecordMetaDSumResult> recordResult = mongoTemplate.find(query, RecordMetaDSumResult.class);
        //全量表
        List<VideoDailyExp> totalExps = new ArrayList<>();
        List<RecordMetaDSumResult> recordResult = mongoTemplate.find(videoQuery, RecordMetaDSumResult.class);
        // 预先按部门ID分组
        Map<Integer, List<TMonitorResult>> monitorsByDept = tMonitorResults.stream()
                .collect(Collectors.groupingBy(TMonitorResult::getDeptId));
        // 预先构建映射
        Map<String, List<RecordMetaDSumResult>> recordMap = recordResult.stream()
                .collect(Collectors.groupingBy(RecordMetaDSumResult::getNo));
        List<CompletableFuture<List<VideoDailyExp>>> futures = new ArrayList<>();
        for (Integer deptId : exportForm.getDeptIds()) {
            CompletableFuture<List<VideoDailyExp>> future = CompletableFuture.supplyAsync(() -> {
            List<VideoDailyExp> videoDailyExps = new ArrayList<>();
            //从数据库集合筛选部门数据
            List<TMonitorResult> monitors = tMonitorResults.stream().filter(tMonitorResult -> deptId.equals(tMonitorResult.getDeptId())).collect(Collectors.toList());
            if (CollectionUtils.isEmpty(monitors)) continue;
            List<String> ids = monitors.stream().map(BaseResult::getNo).collect(Collectors.toList());
            //筛选mongo区县数据
            List<RecordMetaDSumResult> records = recordResult.stream().filter(result -> ids.contains(result.getNo())).collect(Collectors.toList());
                // 获取当前部门的数据
                List<TMonitorResult> monitors = monitorsByDept.getOrDefault(deptId, Collections.emptyList());
                if (CollectionUtils.isEmpty(monitors)) return videoDailyExps;
            AreaDeptEnum areaDeptEnum = AreaDeptEnum.fromDept(deptId);
            for (TMonitorResult result : monitors) {
                VideoDailyExp videoDailyExp = new VideoDailyExp();
@@ -743,13 +866,35 @@
                    tag = new StringBuilder(tag.substring(0, tag.length() - 1));
                }
                videoDailyExp.setTag(tag.toString());
                setLoseDaily(videoDailyExp, result, records);
                videoDailyExps.add(videoDailyExp);
                //全量表
                totalExps.add(videoDailyExp);
                    // 使用Map直接获取记录,避免filter操作
                    List<RecordMetaDSumResult> recordsResult = recordMap.get(result.getNo());
                    try {
                        if(!CollectionUtils.isEmpty(recordsResult)) setLoseDaily(videoDailyExp, recordsResult);
                    } catch (Exception e) {
                        log.error(e.getMessage());
            }
            ExcelExp excelExp = new ExcelExp(areaDeptEnum == null ? "未知" : areaDeptEnum.getName(), videoDailyExps, VideoDailyExp.class);
                    videoDailyExps.add(videoDailyExp);
                }
                return videoDailyExps;
            }, threadPoolTaskExecutor);
            futures.add(future);
        }
        // 等待所有任务完成
        CompletableFuture.allOf(futures.toArray(new CompletableFuture[0])).join();
        // 每个部门的数据单独保存
        List<List<VideoDailyExp>> results = futures.stream()
                .map(CompletableFuture::join)  // 获取每个Future的结果
                .collect(Collectors.toList());
        List<VideoDailyExp> totalExps = new ArrayList<>();
        List<ExcelExp> mysheet = new ArrayList<>();
        for (List<VideoDailyExp> result : results) {
            ExcelExp excelExp = new ExcelExp(
                    result.get(0).getArea() == null ? "未知" : result.get(0).getArea(),
                    result,
                    VideoDailyExp.class);
            mysheet.add(excelExp);
            totalExps.addAll(result);
        }
        ExcelExp excelExp = new ExcelExp("全量", totalExps, VideoDailyExp.class);
        mysheet.add(excelExp);
@@ -1170,7 +1315,8 @@
        return vo;
    }
    private Query getQuery(List<String> deviceIds, String month) {
    private Query getQuery(VideoExportForm exportForm) {
        String month = exportForm.getMonth();
        // 将年月字符串解析为YearMonth对象
        YearMonth yearMonth = YearMonth.parse(month);
        // 获取当月的第一天
@@ -1180,7 +1326,15 @@
        LocalDate end = nextMonth.atDay(1);
        //获取这个月份的部门数据
        Query query = new Query(Criteria.where("mongoCreateTime").gte(start).lt(end));
        query.addCriteria(Criteria.where("no").in(deviceIds));
        if (!CollectionUtils.isEmpty(exportForm.getDeptIds()))
            query.addCriteria(Criteria.where("deptId").in(exportForm.getDeptIds()));
        if (exportForm.getDeptTag() != null) query.addCriteria(Criteria.where("deptTag").is(exportForm.getDeptTag()));
        if (exportForm.getProvinceTag() != null)
            query.addCriteria(Criteria.where("provinceTag").is(exportForm.getProvinceTag()));
        if (exportForm.getImportantTag() != null)
            query.addCriteria(Criteria.where("importantTag").is(exportForm.getImportantTag()));
        if (exportForm.getImportantCommandImageTag() != null)
            query.addCriteria(Criteria.where("importantCommandImageTag").is(exportForm.getImportantCommandImageTag()));
        return query;
    }
@@ -1206,9 +1360,7 @@
    }
    //设置每日录像数据
    private void setRecordDaily(VideoDailyExp videoDailyExp, TMonitorResult result, List<RecordMetaDSumResult> records) throws NoSuchFieldException, IllegalAccessException {
        //一个设备当月在线情况
        List<RecordMetaDSumResult> recordResults = records.stream().filter(online -> online.getNo().equals(result.getNo())).collect(Collectors.toList());
    private void setRecordDaily(VideoDailyExp videoDailyExp, TMonitorResult result, List<RecordMetaDSumResult> recordResults) throws NoSuchFieldException, IllegalAccessException {
        for (RecordMetaDSumResult recordResult : recordResults) {
            int dayOfMonth = DateUtils.getDayOfMonth(recordResult.getStatTime());
            Integer status = recordResult.getRecordStatus();
@@ -1228,9 +1380,8 @@
    }
    //设置每日录像缺失时长数据
    private void setLoseDaily(VideoDailyExp videoDailyExp, TMonitorResult result, List<RecordMetaDSumResult> records) throws NoSuchFieldException, IllegalAccessException {
    private void setLoseDaily(VideoDailyExp videoDailyExp, List<RecordMetaDSumResult> recordResults) throws NoSuchFieldException, IllegalAccessException {
        //一个设备当月在线情况
        List<RecordMetaDSumResult> recordResults = records.stream().filter(online -> online.getNo().equals(result.getNo())).collect(Collectors.toList());
        for (RecordMetaDSumResult recordResult : recordResults) {
            int dayOfMonth = DateUtils.getDayOfMonth(recordResult.getStatTime());
            //反射赋值,字段统一定义为day+1,2,3...