zxl
4 天以前 c83101eb62f5d4906b9c01ceea6b21a37f9e84d8
bug修复
7个文件已修改
955 ■■■■ 已修改文件
ycl-pojo/src/main/java/com/ycl/platform/domain/result/HK/FaceDeviceInspectionResult.java 36 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ycl-server/src/main/java/com/ycl/platform/service/impl/DataCenterServiceImpl.java 865 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ycl-server/src/main/java/com/ycl/platform/service/impl/ReportServiceImpl.java 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ycl-server/src/main/java/com/ycl/task/DemeritRecordTask.java 8 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ycl-server/src/main/java/com/ycl/task/HKTask.java 26 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ycl-server/src/main/java/com/ycl/task/UYTask.java 8 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ycl-server/src/main/java/com/ycl/thread/OnlineCheckThread.java 6 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ycl-pojo/src/main/java/com/ycl/platform/domain/result/HK/FaceDeviceInspectionResult.java
@@ -3,6 +3,7 @@
import com.ycl.platform.domain.result.BaseResult;
import com.ycl.platform.domain.vo.DataCenter.SnapClockVO;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.data.mongodb.core.index.TextIndexed;
import org.springframework.data.mongodb.core.mapping.Document;
@@ -14,6 +15,7 @@
 */
@Data
@Document(collection = "hk_face_device_inspection")
@Slf4j
public class FaceDeviceInspectionResult extends BaseResult {
    /**
@@ -308,13 +310,33 @@
    public static SnapClockVO getVO(FaceDeviceInspectionResult result){
        SnapClockVO snapClockVO = new SnapClockVO();
        BeanUtils.copyProperties(result,snapClockVO);
        snapClockVO.setClockPercent(result.getSnapClock().getClockPercent());
        snapClockVO.setTodayClockCount(result.getSnapClock().getTodayClockCount());
        snapClockVO.setTodayClockResult(result.getSnapClock().getTodayClockResult());
        snapClockVO.setAllClockCount(result.getSnapClock().getAllClockCount());
        snapClockVO.setAllClockResult(result.getSnapClock().getAllClockResult());
        snapClockVO.setAllClockResultText(result.getSnapClock().getAllClockResultText());
        snapClockVO.setTodayClockResultText(result.getSnapClock().getTodayClockResultText());
        SnapClock snapClock = result.getSnapClock();
        if (snapClock != null) {
            snapClockVO.setClockPercent(snapClock.getClockPercent());
            snapClockVO.setTodayClockCount(snapClock.getTodayClockCount());
            snapClockVO.setTodayClockResult(snapClock.getTodayClockResult());
            snapClockVO.setAllClockCount(snapClock.getAllClockCount());
            snapClockVO.setAllClockResult(snapClock.getAllClockResult());
            snapClockVO.setAllClockResultText(snapClock.getAllClockResultText());
            snapClockVO.setTodayClockResultText(snapClock.getTodayClockResultText());
        } else {
            log.info("出现空数据值:{}",result);
            // 空值兜底:给 VO 字段赋默认值,防止前端接收 null 报错
            snapClockVO.setClockPercent(0.0f); // 数值型默认 0.0
            snapClockVO.setTodayClockCount(0); // 计数型默认 0
            snapClockVO.setTodayClockResult(0); // 结果状态默认 0(可根据业务调整)
            snapClockVO.setAllClockCount(0);
            snapClockVO.setAllClockResult(0);
            snapClockVO.setAllClockResultText(""); // 文本型默认空字符串
            snapClockVO.setTodayClockResultText("");
        }
//        snapClockVO.setClockPercent(result.getSnapClock().getClockPercent());
//        snapClockVO.setTodayClockCount(result.getSnapClock().getTodayClockCount());
//        snapClockVO.setTodayClockResult(result.getSnapClock().getTodayClockResult());
//        snapClockVO.setAllClockCount(result.getSnapClock().getAllClockCount());
//        snapClockVO.setAllClockResult(result.getSnapClock().getAllClockResult());
//        snapClockVO.setAllClockResultText(result.getSnapClock().getAllClockResultText());
//        snapClockVO.setTodayClockResultText(result.getSnapClock().getTodayClockResultText());
        return snapClockVO;
    }
}
ycl-server/src/main/java/com/ycl/platform/service/impl/DataCenterServiceImpl.java
@@ -6,6 +6,7 @@
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.mongodb.client.AggregateIterable;
import com.mongodb.client.DistinctIterable;
import com.mongodb.client.MongoCollection;
import com.mongodb.client.MongoDatabase;
import com.ycl.platform.domain.entity.*;
@@ -1918,6 +1919,7 @@
     */
    @Override
    public Result videoAssessmentFileRatio(DataCenterQuery params) {
        long startTIme = System.currentTimeMillis();
        List<String> likeFileds = Arrays.asList("ip.showValue", "name.showValue", "serialNumber.showValue");
        List<Criteria> andCriteria = MongoUtil.getAndCriteria(params, TIME_FIELD, likeFileds, null);
        Query query = new Query();
@@ -1925,6 +1927,7 @@
        and.andOperator(andCriteria);
        query = Query.query(and);
        long total = mongoTemplate.count(query, MonitorQualifyResult.class);
        MongoUtil.setPage(query, params, TIME_FIELD);
        List<MonitorQualifyResult> resultList = mongoTemplate.find(query, MonitorQualifyResult.class);
        List<MonitorQualifyResultVO> resultVOS = new ArrayList<>();
@@ -1932,43 +1935,45 @@
            MonitorQualifyResultVO vo = MonitorQualifyResult.getVO(result);
            resultVOS.add(vo);
        }
        // 统计数量
        MongoDatabase database = mongoTemplate.getDb();
        MongoCollection<Document> collection = database.getCollection("uy_monitor_qualify");
        //总数
        List<Document> dList1 = new ArrayList<>(2);
        DataCenterQuery totalParams = new DataCenterQuery();
        BeanUtils.copyProperties(params, totalParams);
        totalParams.setStartTime(null);
        setTag(totalParams, dList1);
        Document totalFilter = new Document("$and", dList1);
        //当日档案数
        List<Document> dList2 = new ArrayList<>(2);
        setTag(params, dList2);
        Document newFilter = new Document("$and", dList2);
        long endTime = System.currentTimeMillis();
        log.info("查询档案考核比使用时间:{}ms",endTime-startTIme);
//        // 统计数量
//        MongoDatabase database = mongoTemplate.getDb();
//        MongoCollection<Document> collection = database.getCollection("uy_monitor_qualify");
//        //总数
//        List<Document> dList1 = new ArrayList<>(2);
//        DataCenterQuery totalParams = new DataCenterQuery();
//        BeanUtils.copyProperties(params, totalParams);
//        totalParams.setStartTime(null);
//        setTag(totalParams, dList1);
//        Document totalFilter = new Document("$and", dList1);
//        //当日档案数
//        List<Document> dList2 = new ArrayList<>(2);
//        setTag(params, dList2);
//        Document newFilter = new Document("$and", dList2);
        List<Document> lists = Arrays.asList(totalFilter, newFilter);
        List<String> rList = lists.stream().map(filter -> {
            // 构建聚合管道
            List<Document> pipeline = Arrays.asList(
                    new Document("$match", filter),
                    // $group 去重
                    new Document("$group", new Document("_id", "$serialNumber.showValue")),
                    new Document("$count", "uniqueDeviceIds")
            );
            // 执行聚合查询并获取结果
            AggregateIterable<Document> result = collection.aggregate(pipeline);
            Integer uniqueDeviceIdCount = 0;
            for (Document doc : result) {
                uniqueDeviceIdCount = doc.getInteger("uniqueDeviceIds");
                break; // 不需要继续遍历,因为 $count 只会产生一个结果
            }
            return uniqueDeviceIdCount + "";
        }).collect(Collectors.toList());
        BigDecimal onlineRate = BigDecimal.ZERO;
        if (!StringUtils.isEmpty(rList.get(0)) && !"0".equals(rList.get(0))) {
            onlineRate = new BigDecimal(rList.get(1)).divide(new BigDecimal(rList.get(0)), 3,RoundingMode.DOWN).multiply(new BigDecimal("100"));
        }
        List<String> rlist = this.buildVideoAssessmentFileRatioCount(params);
//        List<String> rList = lists.stream().map(filter -> {
//            // 构建聚合管道
//            List<Document> pipeline = Arrays.asList(
//                    new Document("$match", filter),
//                    // $group 去重
//                    new Document("$group", new Document("_id", "$serialNumber.showValue")),
//                    new Document("$count", "uniqueDeviceIds")
//            );
//            // 执行聚合查询并获取结果
//            AggregateIterable<Document> result = collection.aggregate(pipeline);
//            Integer uniqueDeviceIdCount = 0;
//            for (Document doc : result) {
//                uniqueDeviceIdCount = doc.getInteger("uniqueDeviceIds");
//                break; // 不需要继续遍历,因为 $count 只会产生一个结果
//            }
//            return uniqueDeviceIdCount + "";
//        }).collect(Collectors.toList());
//        BigDecimal onlineRate = BigDecimal.ZERO;
//        if (!StringUtils.isEmpty(rList.get(0)) && !"0".equals(rList.get(0))) {
//            onlineRate = new BigDecimal(rList.get(1)).divide(new BigDecimal(rList.get(0)), 3,RoundingMode.DOWN).multiply(new BigDecimal("100"));
//        }
//        List<CheckIndexVideo> videoList = new LambdaQueryChainWrapper<>(checkIndexVideoService.getBaseMapper())
//                .select(CheckIndexVideo::getArchivesRate)
//                .eq(params.getDataType().equals(1), CheckIndexVideo::getExamineTag, CheckConstants.Examine_Tag_Province)
@@ -1981,12 +1986,121 @@
//            BigDecimal count = BigDecimal.valueOf(videoList.size());
//            onlineRate = sum.divide(count, 4, RoundingMode.HALF_UP).multiply(BigDecimal.valueOf(100));
//        }
        rList.add(this.remove0(onlineRate));
//        rList.add(this.remove0(onlineRate));
        HashMap<String, Object> map = new HashMap<>();
        map.put("count", rList);
        map.put("count", rlist);
        map.put("list", resultVOS);
        return Result.ok().data(map).total(total);
    }
    private List<String> buildVideoAssessmentFileRatioCount(DataCenterQuery params) {
        MongoDatabase database = mongoTemplate.getDb();
        MongoCollection<Document> collection = database.getCollection("uy_monitor_qualify");
        // 1. 构建基础过滤条件(依赖setTag,自动处理标签+时间)
        List<Document> baseFilterList = new ArrayList<>();
        setTag(params, baseFilterList);
        // 2. 总数统计(无时间限制)
        List<Document> totalFilterList = new ArrayList<>(baseFilterList);
        totalFilterList.removeIf(doc -> doc.containsKey(TIME_FIELD));
        int totalCount = 0;
        if (totalFilterList.isEmpty()) {
            // 全量统计:用distinct迭代计数(兼容所有驱动)
            totalCount = countDistinctUniqueDevices(collection);
        } else {
            // 条件统计:聚合管道(无AggregateOptions)
            Document totalMatch = buildSafeMatchCondition(totalFilterList, "total");
            totalCount = countUniqueDevices(collection, totalMatch);
        }
        // 3. 当日数统计(条件统计)
        Document currentDayMatch = buildSafeMatchCondition(baseFilterList, "currentDay");
        int currentDayCount = countUniqueDevices(collection, currentDayMatch);
        // 4. 计算在线率
        BigDecimal onlineRate = BigDecimal.ZERO;
        if (totalCount != 0) {
            onlineRate = new BigDecimal(currentDayCount)
                    .divide(new BigDecimal(totalCount), 3, RoundingMode.DOWN)
                    .multiply(new BigDecimal("100"));
        }
        List<String> rList = new ArrayList<>();
        rList.add(String.valueOf(totalCount));
        rList.add(String.valueOf(currentDayCount));
        rList.add(this.remove0(onlineRate));
        return rList;
    }
    private int countDistinctUniqueDevices(MongoCollection<Document> collection) {
        long start = System.currentTimeMillis();
        try {
            // 去重获取设备ID(指定类型为String)
            DistinctIterable<String> deviceIds = collection.distinct(
                    "serialNumber.showValue",
                    String.class
            );
            // 手动迭代计数(兼容所有驱动版本)
            long count = 0;
            for (String ignored : deviceIds) {
                count++;
            }
            log.info("全量唯一设备数统计耗时:{}ms,总数:{}", System.currentTimeMillis() - start, count);
            return (int) count;
        } catch (Exception e) {
            log.error("全量统计失败", e);
            return 0;
        }
    }
    /**
     * 带条件统计:无 AggregateOptions,仅基础聚合管道
     */
    private int countUniqueDevices(MongoCollection<Document> collection, Document match) {
        long start = System.currentTimeMillis();
        List<Document> pipeline = Arrays.asList(
                match, // $match 条件(确保包含索引字段,引导索引命中)
                new Document("$sort", new Document("serialNumber.showValue", 1)), // 利用索引排序
                new Document("$group", new Document("_id", "$serialNumber.showValue")), // 去重
                new Document("$count", "uniqueDeviceIds") // 统计数量
        );
        try {
            // 直接执行聚合,不使用 AggregateOptions
            AggregateIterable<Document> result = collection.aggregate(pipeline);
            Document doc = result.first();
            int count = doc != null ? doc.getInteger("uniqueDeviceIds", 0) : 0;
            log.info("带条件统计耗时:{}ms,结果:{}", System.currentTimeMillis() - start, count);
            return count;
        } catch (Exception e) {
            log.error("带条件统计失败,match:{}", match, e);
            return 0;
        }
    }
    /**
     * 安全构建$match条件:彻底避免$and空数组错误
     */
    private Document buildSafeMatchCondition(List<Document> filterList, String name) {
        // 过滤null+去重,确保条件合法
        List<Document> validConditions = filterList.stream()
                .filter(Objects::nonNull)
                .distinct()
                .collect(Collectors.toList());
        log.info("{}统计有效条件:{}", name, validConditions);
        if (validConditions.isEmpty()) {
            return new Document("$match", new Document()); // 空条件→匹配所有
        } else if (validConditions.size() == 1) {
            return new Document("$match", validConditions.get(0)); // 单条件→无需$and
        } else {
            return new Document("$match", new Document("$and", validConditions)); // 多条件→$and包裹
        }
    }
    private final ISysConfigService configService;
@@ -2492,6 +2606,7 @@
     */
    @Override
    public Result videoImportantPointLabelingAccuracy(DataCenterQuery params) {
        long startTime = System.currentTimeMillis();
        List<String> likeFileds = Arrays.asList("deviceNo", "osdName");
        SysDept sysDept = getSysDeptByLoginUser();
        List<Criteria> andCriteria;
@@ -2507,147 +2622,248 @@
            andCriteria = MongoUtil.getAndCriteria(params, "checkTime", likeFileds, null);
        }
        Query query = new Query();
        Criteria and = new Criteria();
        and.andOperator(andCriteria);
        query = Query.query(and);
        query.addCriteria(Criteria.where("importantTag").is(Boolean.TRUE));
        List<Criteria> allCriteria  = new ArrayList<>(andCriteria);
        allCriteria.add(Criteria.where("importantTag").is(Boolean.TRUE)); // 基础标签条件
        // 下拉框标注正确查询条件
        if (params.getOption() != null) {
            if (params.getOption() == 1) {
                andCriteria.add(Criteria.where("osdNameCorrect").is(1));
                andCriteria.add(Criteria.where("osdTimeCorrect").is(1));
                andCriteria.add(Criteria.where("osdProvinceCorrect").is(1));
                andCriteria.add(Criteria.where("osdCityCorrect").is(1));
                andCriteria.add(Criteria.where("osdPartCorrect").is(1));
                Criteria and2 = new Criteria();
                and2.andOperator(andCriteria);
                query = Query.query(and2);
                // 叠加:所有字段必须为1(正确)
                allCriteria.add(new Criteria().andOperator(
                        Criteria.where("osdNameCorrect").is(1),
                        Criteria.where("osdTimeCorrect").is(1),
                        Criteria.where("osdProvinceCorrect").is(1),
                        Criteria.where("osdCityCorrect").is(1),
                        Criteria.where("osdPartCorrect").is(1)
                ));
            } else if (params.getOption() == -1) {
                // 使用$or条件连接多个字段检查,每个字段检查是否等于-1
                Criteria c1 = Criteria.where("osdNameCorrect").is(-1);
                Criteria c2 = Criteria.where("osdTimeCorrect").is(-1);
                Criteria c3 = Criteria.where("osdProvinceCorrect").is(-1);
                Criteria c4 = Criteria.where("osdCityCorrect").is(-1);
                Criteria c5 = Criteria.where("osdPartCorrect").is(-1);
                Criteria orOperator = new Criteria().orOperator(c1, c2, c3, c4, c5);
                orOperator.andOperator(andCriteria);
                query = Query.query(orOperator);
                // 叠加:任一字段为-1(异常)
                allCriteria.add(new Criteria().orOperator(
                        Criteria.where("osdNameCorrect").is(-1),
                        Criteria.where("osdTimeCorrect").is(-1),
                        Criteria.where("osdProvinceCorrect").is(-1),
                        Criteria.where("osdCityCorrect").is(-1),
                        Criteria.where("osdPartCorrect").is(-1)
                ));
            } else {
                Criteria c1 = Criteria.where("osdNameCorrect").is(0);
                Criteria c2 = Criteria.where("osdTimeCorrect").is(0);
                Criteria c3 = Criteria.where("osdProvinceCorrect").is(0);
                Criteria c4 = Criteria.where("osdCityCorrect").is(0);
                Criteria c5 = Criteria.where("osdPartCorrect").is(0);
                Criteria orOperator = new Criteria().orOperator(c1, c2, c3, c4, c5);
                orOperator.andOperator(andCriteria);
                query = Query.query(orOperator);
                // 叠加:任一字段为0(未知)
                allCriteria.add(new Criteria().orOperator(
                        Criteria.where("osdNameCorrect").is(0),
                        Criteria.where("osdTimeCorrect").is(0),
                        Criteria.where("osdProvinceCorrect").is(0),
                        Criteria.where("osdCityCorrect").is(0),
                        Criteria.where("osdPartCorrect").is(0)
                ));
            }
        }
        Criteria finalCriteria = new Criteria().andOperator(allCriteria);
        Query query = Query.query(finalCriteria);
        long total = mongoTemplate.count(query, OsdCheckResult.class);
        MongoUtil.setPage(query, params, "checkTime");
        List<OsdCheckResult> resultList = mongoTemplate.find(query, OsdCheckResult.class);
        log.info("分页查询条件:importantTag=true, option={}, startTime={}, endTime={}",
                params.getOption(), params.getStartTime(), params.getEndTime());
        for (OsdCheckResult osdCheckResult : resultList) {
            OsdCheckResult.getError(osdCheckResult);
        }
        // 统计数量
        MongoDatabase database = mongoTemplate.getDb();
        MongoCollection<Document> collection = database.getCollection("osd_check_result");
        // 确保在统计查询中也应用相同的过滤条件
        Document areDocument = null;
        if (areaDeptEnum != null) {
            String areaCodePrefix = areaDeptEnum.getCode();
            areDocument = new Document("deviceNo", new Document("$regex", "^" + areaCodePrefix));
        }
        // 总数
        List<Document> dList = new ArrayList<>(2);
        if (areDocument != null){
            dList.add(areDocument);
        }
        dList.add(new Document("importantTag", Boolean.TRUE));
        setTag(params, dList);
        long endTime = System.currentTimeMillis();
        log.info("查询分页所用时间:{}ms",endTime -startTime);
        Document osdFilter = new Document("$and", dList);
        // 正常数
        List<Document> dList1 = new ArrayList<>(2);
        if (areDocument != null){
            dList1.add(areDocument);
        }
        dList1.add(new Document("importantTag", Boolean.TRUE));
        dList1.add(new Document("osdNameCorrect", new Document("$eq", 1)));
        dList1.add(new Document("osdTimeCorrect", new Document("$eq", 1)));
        dList1.add(new Document("osdProvinceCorrect", new Document("$eq", 1)));
        dList1.add(new Document("osdCityCorrect", new Document("$eq", 1)));
        dList1.add(new Document("osdPartCorrect", new Document("$eq", 1)));
        setTag(params, dList1);
        Document osdCorrectFilter = new Document("$and", dList1);
        //异常数
        List<Document> dList2 = new ArrayList<>(2);
        if (areDocument != null){
            dList2.add(areDocument);
        }
        setTag(params, dList2);
        Document importantTagCondition = new Document("importantTag", Boolean.TRUE);
        dList2.add(importantTagCondition);
        List<Document> errorConditions = new ArrayList<>();
        errorConditions.add(new Document("osdNameCorrect", new Document("$eq", -1)));
        errorConditions.add(new Document("osdTimeCorrect", new Document("$eq", -1)));
        errorConditions.add(new Document("osdProvinceCorrect", new Document("$eq", -1)));
        errorConditions.add(new Document("osdCityCorrect", new Document("$eq", -1)));
        errorConditions.add(new Document("osdPartCorrect", new Document("$eq", -1)));
        Document errorFilter = new Document("$or", errorConditions);
        dList2.add(errorFilter);
        Document osdErrorFilter = new Document("$and", dList2);
        // 未知数
        List<Document> dList3 = new ArrayList<>(2);
        if (areDocument != null){
            dList3.add(areDocument);
        }
        setTag(params, dList3);
        dList3.add(importantTagCondition);
        List<Document> unknownConditions = new ArrayList<>();
        unknownConditions.add(new Document("osdNameCorrect", new Document("$eq", 0)));
        unknownConditions.add(new Document("osdTimeCorrect", new Document("$eq", 0)));
        unknownConditions.add(new Document("osdProvinceCorrect", new Document("$eq", 0)));
        unknownConditions.add(new Document("osdCityCorrect", new Document("$eq", 0)));
        unknownConditions.add(new Document("osdPartCorrect", new Document("$eq", 0)));
        Document unknownFilter = new Document("$or", unknownConditions);
        dList3.add(unknownFilter);
        Document osdUnknownFilter = new Document("$and", dList3);
        List<Document> lists = Arrays.asList(osdFilter, osdCorrectFilter, osdErrorFilter, osdUnknownFilter);
        List<String> rList = lists.stream().map(filter -> {
            // 构建聚合管道
            List<Document> pipeline = Arrays.asList(
                    new Document("$match", filter),
                    // $group 去重
                    new Document("$group", new Document("_id", "$deviceNo")),
                    new Document("$count", "uniqueDeviceIds")
            );
            // 执行聚合查询并获取结果
            AggregateIterable<Document> result = collection.aggregate(pipeline);
            Integer uniqueDeviceIdCount = 0;
            for (Document doc : result) {
                uniqueDeviceIdCount = doc.getInteger("uniqueDeviceIds");
                break; // 不需要继续遍历,因为 $count 只会产生一个结果
            }
            return uniqueDeviceIdCount + "";
        }).collect(Collectors.toList());
        BigDecimal onlineRate = BigDecimal.ZERO;
        if (!StringUtils.isEmpty(rList.get(0)) && !"0".equals(rList.get(0))) {
            onlineRate = new BigDecimal(rList.get(1)).divide(new BigDecimal(rList.get(0)), 3,RoundingMode.DOWN).multiply(new BigDecimal("100"));
        }
        rList.add(this.remove0(onlineRate));
//        // 统计数量
//        MongoDatabase database = mongoTemplate.getDb();
//        MongoCollection<Document> collection = database.getCollection("osd_check_result");
//        // 确保在统计查询中也应用相同的过滤条件
//        Document areDocument = null;
//        if (areaDeptEnum != null) {
//            String areaCodePrefix = areaDeptEnum.getCode();
//            areDocument = new Document("deviceNo", new Document("$regex", "^" + areaCodePrefix));
//        }
//        // 总数
//        List<Document> dList = new ArrayList<>(2);
//        if (areDocument != null){
//            dList.add(areDocument);
//        }
//        dList.add(new Document("importantTag", Boolean.TRUE));
//        setTag(params, dList);
//
//        Document osdFilter = new Document("$and", dList);
//        // 正常数
//        List<Document> dList1 = new ArrayList<>(2);
//        if (areDocument != null){
//            dList1.add(areDocument);
//        }
//        dList1.add(new Document("importantTag", Boolean.TRUE));
//        dList1.add(new Document("osdNameCorrect", new Document("$eq", 1)));
//        dList1.add(new Document("osdTimeCorrect", new Document("$eq", 1)));
//        dList1.add(new Document("osdProvinceCorrect", new Document("$eq", 1)));
//        dList1.add(new Document("osdCityCorrect", new Document("$eq", 1)));
//        dList1.add(new Document("osdPartCorrect", new Document("$eq", 1)));
//        setTag(params, dList1);
//
//        Document osdCorrectFilter = new Document("$and", dList1);
//        //异常数
//        List<Document> dList2 = new ArrayList<>(2);
//        if (areDocument != null){
//            dList2.add(areDocument);
//        }
//        setTag(params, dList2);
//        Document importantTagCondition = new Document("importantTag", Boolean.TRUE);
//        dList2.add(importantTagCondition);
//        List<Document> errorConditions = new ArrayList<>();
//        errorConditions.add(new Document("osdNameCorrect", new Document("$eq", -1)));
//        errorConditions.add(new Document("osdTimeCorrect", new Document("$eq", -1)));
//        errorConditions.add(new Document("osdProvinceCorrect", new Document("$eq", -1)));
//        errorConditions.add(new Document("osdCityCorrect", new Document("$eq", -1)));
//        errorConditions.add(new Document("osdPartCorrect", new Document("$eq", -1)));
//        Document errorFilter = new Document("$or", errorConditions);
//        dList2.add(errorFilter);
//
//        Document osdErrorFilter = new Document("$and", dList2);
//
//        // 未知数
//        List<Document> dList3 = new ArrayList<>(2);
//        if (areDocument != null){
//            dList3.add(areDocument);
//        }
//        setTag(params, dList3);
//        dList3.add(importantTagCondition);
//        List<Document> unknownConditions = new ArrayList<>();
//        unknownConditions.add(new Document("osdNameCorrect", new Document("$eq", 0)));
//        unknownConditions.add(new Document("osdTimeCorrect", new Document("$eq", 0)));
//        unknownConditions.add(new Document("osdProvinceCorrect", new Document("$eq", 0)));
//        unknownConditions.add(new Document("osdCityCorrect", new Document("$eq", 0)));
//        unknownConditions.add(new Document("osdPartCorrect", new Document("$eq", 0)));
//        Document unknownFilter = new Document("$or", unknownConditions);
//        dList3.add(unknownFilter);
//
//        Document osdUnknownFilter = new Document("$and", dList3);
//        //todo 修改查询逻辑不走循环 连接三次 走一次查询
//        List<Document> lists = Arrays.asList(osdFilter, osdCorrectFilter, osdErrorFilter, osdUnknownFilter);
//        List<String> rList = lists.stream().map(filter -> {
//            // 构建聚合管道
//            List<Document> pipeline = Arrays.asList(
//                    new Document("$match", filter),
//                    // $group 去重
//                    new Document("$group", new Document("_id", "$deviceNo")),
//                    new Document("$count", "uniqueDeviceIds")
//            );
//            // 执行聚合查询并获取结果
//            AggregateIterable<Document> result = collection.aggregate(pipeline);
//            Integer uniqueDeviceIdCount = 0;
//            for (Document doc : result) {
//                uniqueDeviceIdCount = doc.getInteger("uniqueDeviceIds");
//                break; // 不需要继续遍历,因为 $count 只会产生一个结果
//            }
//            return uniqueDeviceIdCount + "";
//        }).collect(Collectors.toList());
//
//        BigDecimal onlineRate = BigDecimal.ZERO;
//        if (!StringUtils.isEmpty(rList.get(0)) && !"0".equals(rList.get(0))) {
//            onlineRate = new BigDecimal(rList.get(1)).divide(new BigDecimal(rList.get(0)), 3,RoundingMode.DOWN).multiply(new BigDecimal("100"));
//        }
//        rList.add(this.remove0(onlineRate));
        List<String> countList = this.buildPointLabelingAccuracyCount(areaDeptEnum,params,likeFileds);
        HashMap<String, Object> map = new HashMap<>();
        map.put("count", rList);
        map.put("count", countList);
        map.put("list", resultList);
        return Result.ok().data(map).total(total);
    }
    private List<String> buildPointLabelingAccuracyCount(AreaDeptEnum areaDeptEnum,DataCenterQuery params,List<String> likeFileds){
        MongoDatabase database = mongoTemplate.getDb();
        MongoCollection<Document> collection = database.getCollection("osd_check_result");
        List<Document> baseFilterList = new ArrayList<>();
        baseFilterList.add(new Document("importantTag",new Document("$eq", Boolean.TRUE)));
        if (areaDeptEnum != null){
            baseFilterList.add(new Document("deviceNo",new Document("$regex","^" + areaDeptEnum.getCode())));
        }
        setTag(params, baseFilterList,"checkTime");
        Document matchStage = new Document("$match",new Document("$and",baseFilterList));
        List<Document> pipeline = new ArrayList<>();
        pipeline.add(matchStage);
        Document groupByDeviceStage = new Document("$group",
                new Document("_id","$deviceNo")
                        .append("correctFlag",new Document("$sum",
                                new Document("$cond",Arrays.asList(
                                        new Document("$and",Arrays.asList(
                                        new Document("$eq",Arrays.asList("$osdNameCorrect",1)),
                                        new Document("$eq", Arrays.asList("$osdTimeCorrect", 1)),
                                        new Document("$eq", Arrays.asList("$osdProvinceCorrect", 1)),
                                        new Document("$eq", Arrays.asList("$osdCityCorrect", 1)),
                                        new Document("$eq", Arrays.asList("$osdPartCorrect", 1))
                                )),
                                1,0
                        ))
        ))
                        // 标记:是否任一字段为-1(异常)
                        .append("errorFlag", new Document("$sum",
                                new Document("$cond", Arrays.asList(
                                        new Document("$or", Arrays.asList(
                                                new Document("$eq", Arrays.asList("$osdNameCorrect", -1)),
                                                new Document("$eq", Arrays.asList("$osdTimeCorrect", -1)),
                                                new Document("$eq", Arrays.asList("$osdProvinceCorrect", -1)),
                                                new Document("$eq", Arrays.asList("$osdCityCorrect", -1)),
                                                new Document("$eq", Arrays.asList("$osdPartCorrect", -1))
                                        )),
                                        1, 0
                                ))
                        ))
                        // 标记:是否任一字段为0(未知)
                        .append("unknownFlag", new Document("$sum",
                                new Document("$cond", Arrays.asList(
                                        new Document("$or", Arrays.asList(
                                                new Document("$eq", Arrays.asList("$osdNameCorrect", 0)),
                                                new Document("$eq", Arrays.asList("$osdTimeCorrect", 0)),
                                                new Document("$eq", Arrays.asList("$osdProvinceCorrect", 0)),
                                                new Document("$eq", Arrays.asList("$osdCityCorrect", 0)),
                                                new Document("$eq", Arrays.asList("$osdPartCorrect", 0))
                                        )),
                                        1, 0
                                ))
                        ))
        );
        pipeline.add(groupByDeviceStage);
        Document groupGlobalStage = new Document("$group",
                new Document("_id", null)
                        .append("totalCount", new Document("$sum", 1)) // 核心修改:直接累加设备分组数
                        .append("correctCount", new Document("$sum", "$correctFlag"))
                        .append("errorCount", new Document("$sum", "$errorFlag"))
                        .append("unknownCount", new Document("$sum", "$unknownFlag"))
        );
        pipeline.add(groupGlobalStage);
        // 执行聚合查询
        AggregateIterable<Document> aggregateResult = collection.aggregate(pipeline);
        Document statDoc = null;
        for (Document doc : aggregateResult) {
            statDoc = doc;
            break;
        }
        // 解析结果(默认值0避免空指针)
        int totalCount = 0, correctCount = 0, errorCount = 0, unknownCount = 0;
        if (statDoc != null) {
            totalCount = statDoc.getInteger("totalCount", 0);
            correctCount = statDoc.getInteger("correctCount", 0);
            errorCount = statDoc.getInteger("errorCount", 0);
            unknownCount = statDoc.getInteger("unknownCount", 0);
        }
        BigDecimal accuracyRate = BigDecimal.ZERO;
        if (totalCount != 0) {
            accuracyRate = new BigDecimal(correctCount)
                    .divide(new BigDecimal(totalCount), 3, RoundingMode.DOWN)
                    .multiply(new BigDecimal("100"));
        }
        // 按原格式返回统计结果(total, correct, error, unknown, rate)
        List<String> countList = new ArrayList<>();
        countList.add(String.valueOf(totalCount));
        countList.add(String.valueOf(correctCount));
        countList.add(String.valueOf(errorCount));
        countList.add(String.valueOf(unknownCount));
        countList.add(this.remove0(accuracyRate));
        return countList;
    }
    @Override
    public void videoImportantPointLabelingAccuracyExport(HttpServletResponse response, DataCenterQuery params) {
@@ -2777,116 +2993,225 @@
        long total = mongoTemplate.count(query, OsdCheckResult.class);
        MongoUtil.setPage(query, params, "checkTime");
        List<OsdCheckResult> resultList = mongoTemplate.find(query, OsdCheckResult.class);
        Document areDocument = null;
        if (areaDeptEnum != null) {
            String areaCodePrefix = areaDeptEnum.getCode();
            areDocument = new Document("deviceNo", new Document("$regex", "^" + areaCodePrefix));
        }
//        Document areDocument = null;
//        if (areaDeptEnum != null) {
//            String areaCodePrefix = areaDeptEnum.getCode();
//            areDocument = new Document("deviceNo", new Document("$regex", "^" + areaCodePrefix));
//        }
        for (OsdCheckResult osdCheckResult : resultList) {
            OsdCheckResult.getError(osdCheckResult);
        }
        // 统计数量
        MongoDatabase database = mongoTemplate.getDb();
        MongoCollection<Document> collection = database.getCollection("osd_check_result");
        //总数
        List<Document> dList = new ArrayList<>(3);
        if (areDocument != null){
            dList.add(areDocument);
        }
        dList.add(new Document("importantTag", Boolean.TRUE));
        setTag(params, dList);
        Document osdFilter = new Document("$and", dList);
        //正常数
        List<Document> dList1 = new ArrayList<>(2);
        dList1.add(new Document("importantTag", Boolean.TRUE));
        dList1.add(new Document("osdNameCorrect", new Document("$eq", 1)));
        dList1.add(new Document("osdTimeCorrect", new Document("$eq", 1)));
        dList1.add(new Document("osdProvinceCorrect", new Document("$eq", 1)));
        dList1.add(new Document("osdCityCorrect", new Document("$eq", 1)));
        dList1.add(new Document("osdPartCorrect", new Document("$eq", 1)));
        if (areDocument != null){
            dList1.add(areDocument);
        }
        setTag(params, dList1);
        Document osdCorrectFilter = new Document("$and", dList1);
        //异常数
        List<Document> dList2 = new ArrayList<>(2);
        if (areDocument != null){
            dList2.add(areDocument);
        }
        setTag(params, dList2);
        Document importantTagCondition = new Document("importantTag", Boolean.TRUE);
        dList2.add(importantTagCondition);
        List<Document> errorConditions = new ArrayList<>();
        errorConditions.add(new Document("osdNameCorrect", new Document("$eq", -1)));
        errorConditions.add(new Document("osdTimeCorrect", new Document("$eq", -1)));
        errorConditions.add(new Document("osdProvinceCorrect", new Document("$eq", -1)));
        errorConditions.add(new Document("osdCityCorrect", new Document("$eq", -1)));
        errorConditions.add(new Document("osdPartCorrect", new Document("$eq", -1)));
        Document errorFilter = new Document("$or", errorConditions);
        dList2.add(errorFilter);
        Document osdErrorFilter = new Document("$and", dList2);
        //未知数
        List<Document> dList3 = new ArrayList<>(2);
        if (areDocument != null){
            dList3.add(areDocument);
        }
        setTag(params, dList3);
        dList3.add(importantTagCondition);
        List<Document> unknownConditions = new ArrayList<>();
        unknownConditions.add(new Document("osdNameCorrect", new Document("$eq", 0)));
        unknownConditions.add(new Document("osdTimeCorrect", new Document("$eq", 0)));
        unknownConditions.add(new Document("osdProvinceCorrect", new Document("$eq", 0)));
        unknownConditions.add(new Document("osdCityCorrect", new Document("$eq", 0)));
        unknownConditions.add(new Document("osdPartCorrect", new Document("$eq", 0)));
        // 使用$or逻辑组合剩余的条件
        Document unknownFilter = new Document("$or", unknownConditions);
        dList3.add(unknownFilter);
        Document osdUnknownFilter = new Document("$and", dList3);
        List<Document> lists = Arrays.asList(osdFilter, osdCorrectFilter, osdErrorFilter, osdUnknownFilter);
        List<String> rList = lists.stream().map(filter -> {
            // 构建聚合管道
            List<Document> pipeline = Arrays.asList(
                    new Document("$match", filter),
                    // $group 去重
                    new Document("$group", new Document("_id", "$deviceNo")),
                    new Document("$count", "uniqueDeviceIds")
            );
            // 执行聚合查询并获取结果
            AggregateIterable<Document> result = collection.aggregate(pipeline);
            Integer uniqueDeviceIdCount = 0;
            for (Document doc : result) {
                uniqueDeviceIdCount = doc.getInteger("uniqueDeviceIds");
                break; // 不需要继续遍历,因为 $count 只会产生一个结果
            }
            return uniqueDeviceIdCount + "";
        }).collect(Collectors.toList());
//        List<CheckIndexVideo> videoList = new LambdaQueryChainWrapper<>(checkIndexVideoService.getBaseMapper())
//                .select(CheckIndexVideo::getKeyTimingAccuracy)
//                .eq(params.getDataType().equals(1), CheckIndexVideo::getExamineTag, CheckConstants.Examine_Tag_Province)
//                .eq(params.getDataType().equals(2), CheckIndexVideo::getExamineTag, CheckConstants.Examine_Tag_Dept)
//                .between(CheckIndexVideo::getCreateTime, DateUtils.getDayStart(params.getStartTime()), DateUtils.getDayEnd(params.getEndTime()))
//                .list();
//        BigDecimal onlineRate = BigDecimal.ZERO;
//        if (CollectionUtils.isNotEmpty(videoList)) {
//            BigDecimal sum = videoList.stream().map(CheckIndexVideo::getKeyTimingAccuracy).reduce(BigDecimal.ZERO, BigDecimal::add);
//            BigDecimal count = BigDecimal.valueOf(videoList.size());
//            onlineRate = sum.divide(count, 4, RoundingMode.HALF_UP).multiply(BigDecimal.valueOf(100));
//        // 统计数量
//        MongoDatabase database = mongoTemplate.getDb();
//        MongoCollection<Document> collection = database.getCollection("osd_check_result");
//        //总数
//        List<Document> dList = new ArrayList<>(3);
//        if (areDocument != null){
//            dList.add(areDocument);
//        }
        BigDecimal onlineRate = BigDecimal.ZERO;
        if (!StringUtils.isEmpty(rList.get(0)) && !"0".equals(rList.get(0))) {
            onlineRate = new BigDecimal(rList.get(1)).divide(new BigDecimal(rList.get(0)), 3,RoundingMode.DOWN).multiply(new BigDecimal("100"));
        }
        rList.add(this.remove0(onlineRate));
//        dList.add(new Document("importantTag", Boolean.TRUE));
//        setTag(params, dList);
//        Document osdFilter = new Document("$and", dList);
//        //正常数
//        List<Document> dList1 = new ArrayList<>(2);
//        dList1.add(new Document("importantTag", Boolean.TRUE));
//        dList1.add(new Document("osdNameCorrect", new Document("$eq", 1)));
//        dList1.add(new Document("osdTimeCorrect", new Document("$eq", 1)));
//        dList1.add(new Document("osdProvinceCorrect", new Document("$eq", 1)));
//        dList1.add(new Document("osdCityCorrect", new Document("$eq", 1)));
//        dList1.add(new Document("osdPartCorrect", new Document("$eq", 1)));
//        if (areDocument != null){
//            dList1.add(areDocument);
//        }
//        setTag(params, dList1);
//        Document osdCorrectFilter = new Document("$and", dList1);
//        //异常数
//        List<Document> dList2 = new ArrayList<>(2);
//        if (areDocument != null){
//            dList2.add(areDocument);
//        }
//        setTag(params, dList2);
//        Document importantTagCondition = new Document("importantTag", Boolean.TRUE);
//        dList2.add(importantTagCondition);
//        List<Document> errorConditions = new ArrayList<>();
//        errorConditions.add(new Document("osdNameCorrect", new Document("$eq", -1)));
//        errorConditions.add(new Document("osdTimeCorrect", new Document("$eq", -1)));
//        errorConditions.add(new Document("osdProvinceCorrect", new Document("$eq", -1)));
//        errorConditions.add(new Document("osdCityCorrect", new Document("$eq", -1)));
//        errorConditions.add(new Document("osdPartCorrect", new Document("$eq", -1)));
//        Document errorFilter = new Document("$or", errorConditions);
//        dList2.add(errorFilter);
//        Document osdErrorFilter = new Document("$and", dList2);
//        //未知数
//        List<Document> dList3 = new ArrayList<>(2);
//        if (areDocument != null){
//            dList3.add(areDocument);
//        }
//        setTag(params, dList3);
//        dList3.add(importantTagCondition);
//        List<Document> unknownConditions = new ArrayList<>();
//        unknownConditions.add(new Document("osdNameCorrect", new Document("$eq", 0)));
//        unknownConditions.add(new Document("osdTimeCorrect", new Document("$eq", 0)));
//        unknownConditions.add(new Document("osdProvinceCorrect", new Document("$eq", 0)));
//        unknownConditions.add(new Document("osdCityCorrect", new Document("$eq", 0)));
//        unknownConditions.add(new Document("osdPartCorrect", new Document("$eq", 0)));
//        // 使用$or逻辑组合剩余的条件
//        Document unknownFilter = new Document("$or", unknownConditions);
//        dList3.add(unknownFilter);
//        Document osdUnknownFilter = new Document("$and", dList3);
//
//        List<Document> lists = Arrays.asList(osdFilter, osdCorrectFilter, osdErrorFilter, osdUnknownFilter);
//        List<String> rList = lists.stream().map(filter -> {
//            // 构建聚合管道
//            List<Document> pipeline = Arrays.asList(
//                    new Document("$match", filter),
//                    // $group 去重
//                    new Document("$group", new Document("_id", "$deviceNo")),
//                    new Document("$count", "uniqueDeviceIds")
//            );
//            // 执行聚合查询并获取结果
//            AggregateIterable<Document> result = collection.aggregate(pipeline);
//            Integer uniqueDeviceIdCount = 0;
//            for (Document doc : result) {
//                uniqueDeviceIdCount = doc.getInteger("uniqueDeviceIds");
//                break; // 不需要继续遍历,因为 $count 只会产生一个结果
//            }
//            return uniqueDeviceIdCount + "";
//        }).collect(Collectors.toList());
//
////        List<CheckIndexVideo> videoList = new LambdaQueryChainWrapper<>(checkIndexVideoService.getBaseMapper())
////                .select(CheckIndexVideo::getKeyTimingAccuracy)
////                .eq(params.getDataType().equals(1), CheckIndexVideo::getExamineTag, CheckConstants.Examine_Tag_Province)
////                .eq(params.getDataType().equals(2), CheckIndexVideo::getExamineTag, CheckConstants.Examine_Tag_Dept)
////                .between(CheckIndexVideo::getCreateTime, DateUtils.getDayStart(params.getStartTime()), DateUtils.getDayEnd(params.getEndTime()))
////                .list();
////        BigDecimal onlineRate = BigDecimal.ZERO;
////        if (CollectionUtils.isNotEmpty(videoList)) {
////            BigDecimal sum = videoList.stream().map(CheckIndexVideo::getKeyTimingAccuracy).reduce(BigDecimal.ZERO, BigDecimal::add);
////            BigDecimal count = BigDecimal.valueOf(videoList.size());
////            onlineRate = sum.divide(count, 4, RoundingMode.HALF_UP).multiply(BigDecimal.valueOf(100));
////        }
//        BigDecimal onlineRate = BigDecimal.ZERO;
//        if (!StringUtils.isEmpty(rList.get(0)) && !"0".equals(rList.get(0))) {
//            onlineRate = new BigDecimal(rList.get(1)).divide(new BigDecimal(rList.get(0)), 3,RoundingMode.DOWN).multiply(new BigDecimal("100"));
//        }
//        rList.add(this.remove0(onlineRate));
        List<String> rList = this.buildTimeAccuracyCount(areaDeptEnum,params,likeFileds);
        HashMap<String, Object> map = new HashMap<>();
        map.put("count", rList);
        map.put("list", resultList);
        return Result.ok().data(map).total(total);
    }
    private List<String> buildTimeAccuracyCount(AreaDeptEnum areaDeptEnum, DataCenterQuery params, List<String> likeFileds) {
        MongoDatabase database = mongoTemplate.getDb();
        MongoCollection<Document> collection = database.getCollection("osd_check_result");
        List<Document> baseFilterList = new ArrayList<>();
        // 基础过滤条件(与列表查询一致)
        baseFilterList.add(new Document("importantTag", new Document("$eq", Boolean.TRUE))); // 重要标签
        if (areaDeptEnum != null) {
            // 设备号前缀匹配(区域过滤)
            baseFilterList.add(new Document("deviceNo", new Document("$regex", "^" + areaDeptEnum.getCode())));
        }
        // 时间过滤:使用 checkTime,与列表查询、索引统一(调用改造后的 setTag)
        this.setTag(params, baseFilterList, "checkTime");
        // 模糊查询(deviceNo、osdName,与列表查询一致)
//        if (StringUtils.hasText(params.getKeyword()) && !CollectionUtils.isEmpty(likeFileds)) {
//            String keyword = Pattern.quote(params.getKeyword());
//            List<Document> likeConditions = new ArrayList<>();
//            for (String field : likeFileds) {
//                likeConditions.add(new Document(field, new Document("$regex", ".*?" + keyword + ".*")));
//            }
//            baseFilterList.add(new Document("$or", likeConditions));
//        }
        // 构建聚合管道
        List<Document> pipeline = new ArrayList<>();
        // 阶段1:基础过滤
        pipeline.add(new Document("$match", new Document("$and", baseFilterList)));
        // 阶段2:按 deviceNo 分组去重,标记时间字段的状态
        pipeline.add(new Document("$group", new Document("_id", "$deviceNo")
                // 标记:所有字段均为1(正确)→ $and 组合5个条件
                .append("timeCorrectFlag", new Document("$sum",
                        new Document("$cond", Arrays.asList(
                                new Document("$and", Arrays.asList( // 条件:5个字段全部为1
                                        new Document("$eq", Arrays.asList("$osdTimeCorrect", 1)),
                                        new Document("$eq", Arrays.asList("$osdNameCorrect", 1)),
                                        new Document("$eq", Arrays.asList("$osdProvinceCorrect", 1)),
                                        new Document("$eq", Arrays.asList("$osdCityCorrect", 1)),
                                        new Document("$eq", Arrays.asList("$osdPartCorrect", 1))
                                )),
                                1, 0
                        ))
                ))
                // 标记:时间错误(osdTimeCorrect=-1)
                .append("timeErrorFlag", new Document("$sum",
                        new Document("$cond", Arrays.asList(
                                new Document("$or", Arrays.asList( // 条件:5个字段任一为-1
                                        new Document("$eq", Arrays.asList("$osdTimeCorrect", -1)),
                                        new Document("$eq", Arrays.asList("$osdNameCorrect", -1)),
                                        new Document("$eq", Arrays.asList("$osdProvinceCorrect", -1)),
                                        new Document("$eq", Arrays.asList("$osdCityCorrect", -1)),
                                        new Document("$eq", Arrays.asList("$osdPartCorrect", -1))
                                )),
                                1, 0
                        ))
                ))
                // 标记:时间未知(osdTimeCorrect=0)
                .append("timeUnknownFlag", new Document("$sum",
                        new Document("$cond", Arrays.asList(
                                new Document("$or", Arrays.asList( // 条件:5个字段任一为0
                                        new Document("$eq", Arrays.asList("$osdTimeCorrect", 0)),
                                        new Document("$eq", Arrays.asList("$osdNameCorrect", 0)),
                                        new Document("$eq", Arrays.asList("$osdProvinceCorrect", 0)),
                                        new Document("$eq", Arrays.asList("$osdCityCorrect", 0)),
                                        new Document("$eq", Arrays.asList("$osdPartCorrect", 0))
                                )),
                                1, 0
                        ))
                ))
        ));
        // 阶段3:全局统计(汇总设备数)
        pipeline.add(new Document("$group", new Document("_id", null)
                .append("totalCount", new Document("$sum", 1)) // 总设备数(去重后)
                .append("correctCount", new Document("$sum", "$timeCorrectFlag")) // 时间正确的设备数
                .append("errorCount", new Document("$sum", "$timeErrorFlag")) // 时间错误的设备数
                .append("unknownCount", new Document("$sum", "$timeUnknownFlag")) // 时间未知的设备数
        ));
        // 执行聚合查询
        AggregateIterable<Document> aggregateResult = collection.aggregate(pipeline);
        Document statDoc = aggregateResult.first(); // 全局分组仅返回一条结果
        // 解析结果(默认0避免空指针)
        int totalCount = 0, correctCount = 0, errorCount = 0, unknownCount = 0;
        if (statDoc != null) {
            totalCount = statDoc.getInteger("totalCount", 0);
            correctCount = statDoc.getInteger("correctCount", 0);
            errorCount = statDoc.getInteger("errorCount", 0);
            unknownCount = statDoc.getInteger("unknownCount", 0);
        }
        // 计算时间准确率(正确数/总数)
        BigDecimal accuracyRate = BigDecimal.ZERO;
        if (totalCount != 0) {
            accuracyRate = new BigDecimal(correctCount)
                    .divide(new BigDecimal(totalCount), 3, RoundingMode.DOWN)
                    .multiply(new BigDecimal("100"));
        }
        // 按格式返回:[总数, 正确数, 错误数, 未知数, 准确率]
        List<String> countList = new ArrayList<>();
        countList.add(String.valueOf(totalCount));
        countList.add(String.valueOf(correctCount));
        countList.add(String.valueOf(errorCount));
        countList.add(String.valueOf(unknownCount));
        countList.add(this.remove0(accuracyRate));
        return countList;
    }
    /**
     * 车辆:视图库对接稳定性
@@ -3263,6 +3588,8 @@
            );
            // 执行聚合查询并获取结果
            AggregateIterable<Document> result = collection.aggregate(pipeline);
//            Document explain = collection.aggregate(pipeline).explain();
//            log.info("打印计划:{}",explain);
            Integer uniqueDeviceIdCount = 0;
            for (Document doc : result) {
                uniqueDeviceIdCount = doc.getInteger("uniqueDeviceIds");
@@ -4398,6 +4725,8 @@
            );
            // 执行聚合查询并获取结果
            AggregateIterable<Document> result = collection.aggregate(pipeline);
//            Document explain = collection.aggregate(pipeline).explain();
//            log.info("打印执行计划设备抓拍图片时钟准确性:{}",explain);
            Integer uniqueDeviceIdCount = 0;
            for (Document doc : result) {
                uniqueDeviceIdCount = doc.getInteger("uniqueDeviceIds");
@@ -4639,4 +4968,22 @@
        if (params.getEndTime() != null) mongoCreateTimeRange.append("$lt", params.getEndTime());
        dList.add(new Document("mongoCreateTime", mongoCreateTimeRange));
    }
    private void setTag(DataCenterQuery params, List<Document> dList, String timeField) {
        // 数据类型过滤(保持原有逻辑)
        if (params.getDataType() != null) { // 加空判断,避免NPE
            if (params.getDataType().equals(1)) {
                dList.add(new Document("provinceTag", new Document("$eq", Boolean.TRUE)));
            } else if (params.getDataType().equals(2)) {
                dList.add(new Document("deptTag", new Document("$eq", Boolean.TRUE)));
            }
        }
        // 时间过滤:使用传入的时间字段名(不再硬编码mongoCreateTime)
        if (params.getStartTime() != null || params.getEndTime() != null) {
            Document timeRange = new Document();
            if (params.getStartTime() != null) timeRange.append("$gte", params.getStartTime());
            if (params.getEndTime() != null) timeRange.append("$lt", params.getEndTime());
            dList.add(new Document(timeField, timeRange)); // 动态时间字段
        }
    }
}
ycl-server/src/main/java/com/ycl/platform/service/impl/ReportServiceImpl.java
@@ -289,7 +289,13 @@
                        sb.append(s).append("、");
                    }
                });
                if (sb.length() > 0) {
                item.setErrorType(sb.substring(0, sb.length() - 1));
                } else {
                    // 无匹配标签时,可设为空字符串或保留原始 errorType
                    item.setErrorType("");
                    // 或 item.setErrorType(item.getErrorType()); // 保留原始编码
                }
            }
        });
        log.info("组装信息耗时:{}ms", dictEndTime);
ycl-server/src/main/java/com/ycl/task/DemeritRecordTask.java
@@ -204,8 +204,12 @@
        List<Report> list = new LambdaQueryChainWrapper<>(reportMapper)
                .eq(Report::getStatus, 1)
                .ge(Report::getBeginCreateTime, DateUtils.getDayStart(yesterday))
                .le(Report::getEndCreateTime,  DateUtils.getDayEnd(yesterday))
                // getEndCreateTime getEndCreateTime  01 00:00:00 - 30 11:59:59
                .le(Report::getBeginCreateTime,
                        DateUtils.getDayStart(yesterday))
                //>=
                .ge(Report::getEndCreateTime, DateUtils.getDayEnd(yesterday))
                .list();
        log.info("报备记录:{}",list);
ycl-server/src/main/java/com/ycl/task/HKTask.java
@@ -77,7 +77,7 @@
    @Autowired
    private CheckIndexFaceMapper faceMapper;
    //车辆设备全检指标监测结果
    //车辆设备全检指标监测结果 车辆(车辆卡口设备时钟准确性、)
    public void vehicleDeviceInspectionTask() {
        log.info("开始执行车辆设备全检指标监测结果数据同步");
        VehicleDeviceInspectionParam param = new VehicleDeviceInspectionParam();
@@ -107,7 +107,7 @@
        log.info("结束车辆设备全检指标监测结果数据同步");
    }
    //人脸设备全检指标监测结果
    //人脸设备全检指标监测结果 人脸(设备抓拍图片时钟准确性)
    public void faceDeviceInspectionTask() {
        log.info("开始执行人脸设备全检指标监测结果数据同步");
        FaceDeviceInspectionParam param = new FaceDeviceInspectionParam();
@@ -136,7 +136,7 @@
    }
    // 抓拍数据量监测结果
    // 抓拍数据量监测结果 车辆人脸(视图库对接稳定性、点位在线率)
    public void snapshotDataMonitorTask() {
        log.info("开始执行抓拍数据量检测结果数据同步");
        /** 车辆数据 */
@@ -170,7 +170,9 @@
        faceParam.setDate(DateUtils.getDate());
        faceParam.setDataType(ApiConstants.HK_DataType_FACE);
        List<SnapshotDataMonitorResult> faceList = HkApiUtil.sendAPI(host, appKey, appSecret, "/api/dqd/service/rs/v1/data/snapCountDetail/query", faceParam, SnapshotDataMonitorResult.class);
        log.info("打印人脸(视图库对接稳定性、点位在线率)HK接口获得任务信息:{}",faceList);
        if (!CollectionUtils.isEmpty(faceList)) {
            //如果今天存在之前的数据先删除
            Query query = new Query(Criteria
                    .where("mongoCreateTime").gte(DateUtils.getDayStart(new Date())).lt(DateUtils.getDayEnd(new Date()))
@@ -184,6 +186,7 @@
            pointService.setDeviceTagByGB(faceList, CheckConstants.Rule_Category_Face);
            //存放在mongo中
            faceList.forEach(item -> item.setDataType(ApiConstants.HK_DataType_FACE));
            log.info("打印人脸(视图库对接稳定性、点位在线率)设置tag并插入mongodb数据:{}",faceList);
            mongoTemplate.insertAll(faceList);
        }
        //修改online状态
@@ -217,6 +220,7 @@
                        willUpdateList.add(vo);
                    }
                });
                log.info("修改设备将要更新入sql中数据:{}",willUpdateList);
                if(!CollectionUtils.isEmpty(willUpdateList)) monitorMapper.updateOnlineFromHk(willUpdateList);
//            List<UpdateOnlineVO> willUpdateList = totalResult.stream().map(item -> {
//                UpdateOnlineVO vo = new UpdateOnlineVO();
@@ -240,7 +244,7 @@
        log.info("结束抓拍数据量检测结果数据同步");
    }
    //采集设备属性监测结果(人脸)
    //采集设备属性监测结果(人脸) 人脸(人脸卡口信息采集准确率)
    public void monitorDetailTask() {
        log.info("开始执行采集设备属性监测结果数据同步");
        //人脸卡口信息采集准确率
@@ -266,7 +270,7 @@
        log.info("结束采集设备属性监测结果数据同步");
    }
    //卡口属性监测结果
    //卡口属性监测结果 车辆(车辆卡口信息采集准确率、)
    public void crossDetailTask() {
        log.info("开始执行卡口属性监测结果数据同步");
        //车辆卡口信息采集准确率
@@ -292,7 +296,7 @@
        log.info("结束卡口属性监测结果数据同步");
    }
    //数据完整性监测结果
    //数据完整性监测结果 车量(车辆卡口设备抓拍数据完整性、)
    public void dataIntegrityMonitoringTask() {
        log.info("开始执行数据完整性监测结果数据同步");
        //车辆卡口设备抓拍数据完整性
@@ -320,7 +324,7 @@
        log.info("结束数据完整性监测结果数据同步");
    }
    //属性识别准确监测结果
    //属性识别准确监测结果 车辆(车辆卡口设备抓拍数据准确性、)
    public void attrRecognitionMonitorTask() {
        log.info("开始执行属性识别准确监测结果数据同步");
        //车辆卡口设备抓拍数据准确性
@@ -349,7 +353,7 @@
    }
    //抓拍数据时延监测结果
    //抓拍数据时延监测结果包含 车辆人脸(抓拍数据上传及时性)
    public void snapshopDelayMonitorTask() {
        log.info("开始执行抓拍数据时延监测结果数据同步");
        //车辆卡口设备抓拍数据上传及时性
@@ -405,7 +409,7 @@
        log.info("结束抓拍数据时延监测结果数据同步");
    }
    //图片访问监测结果
    //图片访问监测结果 车辆(车辆卡口信息采集准确率、车辆卡口设备url可用性)
    public void picAccessTask() {
        log.info("开始执行图片访问监测结果数据同步");
        //车辆卡口信息采集准确率、车辆卡口设备url可用性
@@ -433,7 +437,7 @@
        log.info("结束图片访问监测结果数据同步");
    }
    //车辆设备抽检指标监测结果
    //车辆设备抽检指标监测结果 车辆(车辆卡口信息采集准确率、车辆卡口设备url可用性)
    public void vehicleDeviceSamplingTask() {
        log.info("开始执行车辆设备抽检指标监测结果数据同步");
        //车辆卡口信息采集准确率、车辆卡口设备url可用性
@@ -462,7 +466,7 @@
    }
    //人脸设备抽检指标监测结果
    //人脸设备抽检指标监测结果 人脸(抓拍数据大图可用性,信息采集正确率)
    public void faceDeviceSamplingTask() {
        log.info("开始执行人脸设备抽检指标监测结果数据同步");
        FaceDeviceSamplingParam param = new FaceDeviceSamplingParam();
ycl-server/src/main/java/com/ycl/task/UYTask.java
@@ -251,10 +251,10 @@
        //查出数据库纯车辆或纯人脸设备
//        List<String> serialNumbers = monitorMapper.selectCarOrFace().stream().map(TMonitor::getSerialNumber).collect(Collectors.toList());
        dataList.forEach(item->{
            if ("DX_长征大道贡兴路路口东南方向_枪机_细节".equals(item.getName())){
                log.info("2.数据流入:{}",item);
                log.info("打印状态pingOnline:{}",item.getPingOnline());
            }
//            if ("DX_长征大道贡兴路路口东南方向_枪机_细节".equals(item.getName())){
//                log.info("2.数据流入:{}",item);
//                log.info("打印状态pingOnline:{}",item.getPingOnline());
//            }
            if(item.getPingOnline()) {
                onLineList.add(item.getIp());
            } else if(!item.getPingOnline()) {
ycl-server/src/main/java/com/ycl/thread/OnlineCheckThread.java
@@ -69,9 +69,9 @@
        }else {
            result.setPingOnlineStr("-1");
        }
        if ("DX_长征大道贡兴路路口东南方向_枪机_细节".equals(result.getName())){
            log.info("1.打印查出设备信息:{}",result);
        }
//        if ("DX_长征大道贡兴路路口东南方向_枪机_细节".equals(result.getName())){
//            log.info("1.打印查出设备信息:{}",result);
//        }
        // 现在需要查出状态为未知的设备
        if (result.getCreateWorkOrder()!=null && result.getCreateWorkOrder()) {
            WorkOrder workOrder = new WorkOrder();