package cn.iocoder.yudao.module.pms.controller.admin.stat;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.LocalDateTimeUtil;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.ObjUtil;
import cn.hutool.core.util.StrUtil;
import cn.iocoder.yudao.framework.apilog.core.annotation.ApiAccessLog;
import cn.iocoder.yudao.framework.common.exception.ErrorCode;
import cn.iocoder.yudao.framework.common.exception.ServiceException;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.common.pojo.PageParam;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.pojo.Pms;
import cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils;
import cn.iocoder.yudao.framework.common.util.number.NumberUtils;
import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;
import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils;
import cn.iocoder.yudao.module.pms.ThingsModelDTO;
import cn.iocoder.yudao.module.pms.controller.admin.TableDataInfo;
import cn.iocoder.yudao.module.pms.controller.admin.depttype.vo.IotDeptTypePageReqVO;
import cn.iocoder.yudao.module.pms.controller.admin.failure.vo.IotFailureReportPageReqVO;
import cn.iocoder.yudao.module.pms.controller.admin.inspect.order.vo.IotInspectOrderPageReqVO;
import cn.iocoder.yudao.module.pms.controller.admin.inspect.plan.vo.IotInspectPlanPageReqVO;
import cn.iocoder.yudao.module.pms.controller.admin.iotdeviceassociate.vo.IotDeviceAssociatePageReqVO;
import cn.iocoder.yudao.module.pms.controller.admin.iotdevicerunlog.vo.IotDeviceRunLogPageReqVO;
import cn.iocoder.yudao.module.pms.controller.admin.iotdevicerunlog.vo.IotDeviceRunLogRespVO;
import cn.iocoder.yudao.module.pms.controller.admin.iotmainworkorder.vo.IotMainWorkOrderPageReqVO;
import cn.iocoder.yudao.module.pms.controller.admin.iotopeationfill.vo.IotOpeationFillPageReqVO;
import cn.iocoder.yudao.module.pms.controller.admin.iotprojecttask.vo.IotProjectTaskPageReqVO;
import cn.iocoder.yudao.module.pms.controller.admin.iotrddailyreport.vo.IotRdDailyReportPageReqVO;
import cn.iocoder.yudao.module.pms.controller.admin.iotrhdailyreport.vo.IotRhDailyReportPageReqVO;
import cn.iocoder.yudao.module.pms.controller.admin.iotrydailyreport.vo.IotRyDailyReportPageReqVO;
import cn.iocoder.yudao.module.pms.controller.admin.iotrydailyreport.vo.IotRyDailyReportTaskCountVO;
import cn.iocoder.yudao.module.pms.controller.admin.iotryhidailyreport.vo.IotRyHiDailyReportPageReqVO;
import cn.iocoder.yudao.module.pms.controller.admin.maintain.vo.IotMaintainPageReqVO;
import cn.iocoder.yudao.module.pms.controller.admin.stat.vo.*;
import cn.iocoder.yudao.module.pms.controller.admin.vo.DeviceVO;
import cn.iocoder.yudao.module.pms.controller.admin.vo.IotDevicePageReqVO;
import cn.iocoder.yudao.module.pms.controller.admin.vo.IotProductClassifyListReqVO;
import cn.iocoder.yudao.module.pms.dal.dataobject.IotDeviceDO;
import cn.iocoder.yudao.module.pms.dal.dataobject.IotProductClassifyDO;
import cn.iocoder.yudao.module.pms.dal.dataobject.depttype.IotDeptTypeDO;
import cn.iocoder.yudao.module.pms.dal.dataobject.failure.IotFailureReportDO;
import cn.iocoder.yudao.module.pms.dal.dataobject.inspect.IotInspectOrderDO;
import cn.iocoder.yudao.module.pms.dal.dataobject.inspect.IotInspectOrderDetailDO;
import cn.iocoder.yudao.module.pms.dal.dataobject.inspect.IotInspectPlanDO;
import cn.iocoder.yudao.module.pms.dal.dataobject.iotcountdata.IotCountDataDO;
import cn.iocoder.yudao.module.pms.dal.dataobject.iotdeviceassociate.IotDeviceAssociateDO;
import cn.iocoder.yudao.module.pms.dal.dataobject.iotmainworkorder.IotMainWorkOrderDO;
import cn.iocoder.yudao.module.pms.dal.dataobject.iotoutbound.IotOutboundDO;
import cn.iocoder.yudao.module.pms.dal.dataobject.iotprojecttask.IotProjectTaskDO;
import cn.iocoder.yudao.module.pms.dal.dataobject.iotprojecttaskattrs.IotTaskAttrModelProperty;
import cn.iocoder.yudao.module.pms.dal.dataobject.iotrddailyreport.IotRdDailyReportDO;
import cn.iocoder.yudao.module.pms.dal.dataobject.iotrhdailyreport.IotRhDailyReportDO;
import cn.iocoder.yudao.module.pms.dal.dataobject.iotrydailyreport.IotRyDailyReportDO;
import cn.iocoder.yudao.module.pms.dal.dataobject.iotryhidailyreport.IotRyHiDailyReportDO;
import cn.iocoder.yudao.module.pms.dal.dataobject.iotsapstock.IotSapStockDO;
import cn.iocoder.yudao.module.pms.dal.dataobject.maintain.IotMaintainDO;
import cn.iocoder.yudao.module.pms.dal.dataobject.yfclass.IotYfClassifyDO;
import cn.iocoder.yudao.module.pms.dal.mysql.IotDeviceMapper;
import cn.iocoder.yudao.module.pms.dal.mysql.IotProductClassifyMapper;
import cn.iocoder.yudao.module.pms.dal.mysql.TDDeviceMapper;
import cn.iocoder.yudao.module.pms.dal.mysql.depttype.IotDeptTypeMapper;
import cn.iocoder.yudao.module.pms.dal.mysql.failure.IotFailureReportMapper;
import cn.iocoder.yudao.module.pms.dal.mysql.inspect.IotInspectOrderDetailMapper;
import cn.iocoder.yudao.module.pms.dal.mysql.inspect.IotInspectOrderMapper;
import cn.iocoder.yudao.module.pms.dal.mysql.inspect.IotInspectPlanMapper;
import cn.iocoder.yudao.module.pms.dal.mysql.iotdeviceassociate.IotDeviceAssociateMapper;
import cn.iocoder.yudao.module.pms.dal.mysql.iotdevicerunlog.IotDeviceRunLogMapper;
import cn.iocoder.yudao.module.pms.dal.mysql.iotmainworkorder.IotMainWorkOrderMapper;
import cn.iocoder.yudao.module.pms.dal.mysql.iotopeationfill.IotOpeationFillMapper;
import cn.iocoder.yudao.module.pms.dal.mysql.iotoutbound.IotOutboundMapper;
import cn.iocoder.yudao.module.pms.dal.mysql.iotrddailyreport.IotRdDailyReportMapper;
import cn.iocoder.yudao.module.pms.dal.mysql.iotrhdailyreport.IotRhDailyReportMapper;
import cn.iocoder.yudao.module.pms.dal.mysql.iotrydailyreport.IotRyDailyReportMapper;
import cn.iocoder.yudao.module.pms.dal.mysql.iotsapstock.IotSapStockMapper;
import cn.iocoder.yudao.module.pms.dal.mysql.maintain.IotMaintainMapper;
import cn.iocoder.yudao.module.pms.dal.mysql.tdparams.IotTdParamsMapper;
import cn.iocoder.yudao.module.pms.dal.mysql.yfclass.IotYfClassifyMapper;
import cn.iocoder.yudao.module.pms.service.DeviceServiceImpl;
import cn.iocoder.yudao.module.pms.service.inspect.IotInspectOrderService;
import cn.iocoder.yudao.module.pms.service.iotmainworkorder.IotMainWorkOrderService;
import cn.iocoder.yudao.module.pms.service.iotprojecttask.IotProjectTaskService;
import cn.iocoder.yudao.module.pms.service.iotrydailyreport.IotRyDailyReportService;
import cn.iocoder.yudao.module.pms.service.iotryhidailyreport.IotRyHiDailyReportService;
import cn.iocoder.yudao.module.pms.service.maintain.IotMaintainService;
import cn.iocoder.yudao.module.system.api.dept.DeptApi;
import cn.iocoder.yudao.module.system.api.dept.dto.DeptRespDTO;
import cn.iocoder.yudao.module.system.api.user.AdminUserApi;
import cn.iocoder.yudao.module.system.controller.admin.dept.vo.dept.DeptListReqVO;
import cn.iocoder.yudao.module.system.dal.dataobject.dept.DeptDO;
import cn.iocoder.yudao.module.system.dal.dataobject.dict.DictDataDO;
import cn.iocoder.yudao.module.system.service.dept.DeptService;
import cn.iocoder.yudao.module.system.service.dict.DictDataService;
import cn.iocoder.yudao.module.system.service.dict.DictTypeService;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.client.RestTemplate;

import javax.annotation.Resource;
import javax.annotation.security.PermitAll;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import java.io.IOException;
import java.io.Serializable;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.sql.Timestamp;
import java.text.DecimalFormat;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.YearMonth;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicReference;
import java.util.stream.Collectors;

import static cn.iocoder.yudao.framework.apilog.core.enums.OperateTypeEnum.EXPORT;
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList;
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.*;
import static cn.iocoder.yudao.module.pms.enums.ErrorCodeConstant.IOT_DAILY_REPORT_DEPT_NOT_EXISTS;
import static cn.iocoder.yudao.module.pms.enums.ErrorCodeConstant.IOT_DAILY_REPORT_TIME_NOT_EXISTS;

@Tag(name = "统计接口")
@RestController
@RequestMapping("/rq/stat")
@Validated
@Slf4j
public class IotStaticController {
    @Resource
    private IotFailureReportMapper iotFailureReportMapper;
    @Resource
    private IotMaintainMapper iotMaintainMapper;
    @Autowired
    private IotInspectOrderMapper iotInspectOrderMapper;
    @Autowired
    private IotInspectOrderService iotInspectOrderService;
    @Autowired
    private IotMainWorkOrderMapper iotMainWorkOrderMapper;
    @Autowired
    private DeviceServiceImpl deviceServiceImpl;
    @Autowired
    private IotDeviceMapper iotDeviceMapper;
    @Autowired
    private IotProductClassifyMapper iotProductClassifyMapper;
    @Autowired
    private DeptApi deptApi;
    @Autowired
    private AdminUserApi adminUserApi;
    @Autowired
    private IotSapStockMapper iotSapStockMapper;
    @Autowired
    private RestTemplate restTemplate;
    @Autowired
    private IotMaintainService iotMaintainService;
    @Value("${yanfan.url}")
    private String yanfanUrl;
    @Autowired
    private IotInspectOrderDetailMapper iotInspectOrderDetailMapper;
    @Autowired
    private DeptService deptService;
    @Autowired
    private IotOpeationFillMapper iotOpeationFillMapper;
    @Autowired
    private IotDeviceRunLogMapper iotDeviceRunLogMapper;
    @Autowired
    private TDDeviceMapper deviceMapper;
    @Autowired
    private IotOutboundMapper iotOutboundMapper;
    @Autowired
    private IotInspectPlanMapper iotInspectPlanMapper;
    @Autowired
    private IotRhDailyReportMapper iotRhDailyReportMapper;
    @Autowired
    private IotRyDailyReportService iotRyDailyReportService;
    @Autowired
    private IotRyDailyReportMapper iotRyDailyReportMapper;
    @Autowired
    private IotRdDailyReportMapper iotRdDailyReportMapper;
    @Resource
    private IotDeptTypeMapper iotDeptTypeMapper;
    @Autowired
    private DeptUtil deptUtil;
    @Autowired
    private IotMainWorkOrderService iotMainWorkOrderService;
    @Autowired
    private IotRyHiDailyReportService iotRyHiDailyReportService;
    @Resource
    private IotDeviceAssociateMapper iotDeviceAssociateMapper;
    @Resource
    private IotProjectTaskService iotProjectTaskService;
    @Autowired
    private IotYfClassifyMapper iotYfClassifyMapper;
    @Resource
    private DictTypeService dictTypeService;


    @GetMapping("/main/day")
    public CommonResult<Map<String, Object>> getMaintainDay() {
        ImmutableMap<String, LocalDateTime> beginEndDay = getBeginEndDay(1);
        IotFailureReportPageReqVO iotFailureReportPageReqVO = new IotFailureReportPageReqVO();
        iotFailureReportPageReqVO.setCreateTime(new LocalDateTime[]{beginEndDay.get("start"), beginEndDay.get("end")});
        Long failure = iotFailureReportMapper.selectCountByTimeAndStatus(iotFailureReportPageReqVO);
        IotMaintainPageReqVO iotMaintainPageReqVO = new IotMaintainPageReqVO();
        iotMaintainPageReqVO.setCreateTime(new LocalDateTime[]{beginEndDay.get("start"), beginEndDay.get("end")});
        Long maintain = iotMaintainMapper.selectCountByTimeAndStatus(iotMaintainPageReqVO);
        return success(ImmutableMap.of("failureDay", failure, "maintainDay", maintain));
    }

    @GetMapping("/notice")
    @PermitAll
    public CommonResult<PageResult<OrderVo>> getNotice(@Valid OrderVo pageReqVO) {
        PageResult<OrderVo> notice = iotMaintainService.getNotice(pageReqVO);
        if (CollUtil.isEmpty(notice.getList())) {
            return success(new PageResult<>(notice.getTotal()));
        }
        return success(notice);
    }

    @GetMapping("/main/week")
    public CommonResult<Map<String, Object>> getMaintainWeek() {
        ImmutableMap<String, LocalDateTime> beginEndWeek = getBeginEndWeek();
        IotFailureReportPageReqVO iotFailureReportPageReqVO = new IotFailureReportPageReqVO();
        iotFailureReportPageReqVO.setCreateTime(new LocalDateTime[]{beginEndWeek.get("start"), beginEndWeek.get("end")});
        Long failure = iotFailureReportMapper.selectCountByTimeAndStatus(iotFailureReportPageReqVO);
        IotMaintainPageReqVO iotMaintainPageReqVO = new IotMaintainPageReqVO();
        iotMaintainPageReqVO.setCreateTime(new LocalDateTime[]{beginEndWeek.get("start"), beginEndWeek.get("end")});
        Long maintain = iotMaintainMapper.selectCountByTimeAndStatus(iotMaintainPageReqVO);
        return success(ImmutableMap.of("failureWeek", failure, "maintainWeek", maintain));
    }

    @GetMapping("/main/month")
    public CommonResult<Map<String, Object>> getMaintainMonth() {
        ImmutableMap<String, LocalDateTime> beginEndMonth = getBeginEndMonth();
        IotFailureReportPageReqVO iotFailureReportPageReqVO = new IotFailureReportPageReqVO();
        iotFailureReportPageReqVO.setCreateTime(new LocalDateTime[]{beginEndMonth.get("start"), beginEndMonth.get("end")});
        Long failure = iotFailureReportMapper.selectCountByTimeAndStatus(iotFailureReportPageReqVO);
        IotMaintainPageReqVO iotMaintainPageReqVO = new IotMaintainPageReqVO();
        iotMaintainPageReqVO.setCreateTime(new LocalDateTime[]{beginEndMonth.get("start"), beginEndMonth.get("end")});
        Long maintain = iotMaintainMapper.selectCountByTimeAndStatus(iotMaintainPageReqVO);
        return success(ImmutableMap.of("failureMonth", failure, "maintainMonth", maintain));
    }

    @GetMapping("/main/total")
    public CommonResult<Map<String, Object>> getMaintainTotal() {
        Long failure = iotFailureReportMapper.selectCount();
        Long maintain = iotMaintainMapper.selectCount();
            return success(ImmutableMap.of("failureTotal", failure, "maintainTotal", maintain));
    }

    @GetMapping("/main/status")
    public CommonResult<Map<String, Object>> getMaintainStatusInfo() {
        List<IotFailureReportDO> iotFailureReportDOS = iotFailureReportMapper.selectList();
        Map<String, Long> failure = iotFailureReportDOS.stream().collect(Collectors.groupingBy(IotFailureReportDO::getStatus, Collectors.counting()));
        List<IotMaintainDO> iotMaintainDOS = iotMaintainMapper.selectList();
        Map<String, Long> maintain = iotMaintainDOS.stream().collect(Collectors.groupingBy(IotMaintainDO::getStatus, Collectors.counting()));
        return success(ImmutableMap.of("failureStatus", failure, "maintainStatus", maintain));
    }

    @GetMapping("/main/year")
    public CommonResult<List<MonthRange>> getMaintainYear() {
        List<MonthRange> lastYearMonths = getLastYearMonthRanges();
        List<MonthRange> collect = lastYearMonths.stream().map(e -> {
            IotFailureReportPageReqVO iotFailureReportPageReqVO = new IotFailureReportPageReqVO();
            iotFailureReportPageReqVO.setCreateTime(new LocalDateTime[]{e.getStart(), e.getEnd()});
            Long l = iotFailureReportMapper.selectCountByTimeAndStatus(iotFailureReportPageReqVO);
            e.setCount(Integer.valueOf(String.valueOf(l)));
            return e;
        }).collect(Collectors.toList());

        return success(collect);
    }

    @GetMapping("/inspect/day")
    public CommonResult<Map<String, Object>> getInspectDay() {
        ImmutableMap<String, LocalDateTime> beginEndDay = getBeginEndDay(1);
        IotInspectOrderPageReqVO iotInspectOrderPageReqVO = new IotInspectOrderPageReqVO();
        iotInspectOrderPageReqVO.setCreateTime(new LocalDateTime[]{beginEndDay.get("start"), beginEndDay.get("end")});
        Long inspectDayTotal = iotInspectOrderMapper.selectCountByTimeAndStatus(iotInspectOrderPageReqVO);
        iotInspectOrderPageReqVO.setStatus("todo");
        Long inspectDayTodo = iotInspectOrderMapper.selectCountByTimeAndStatus(iotInspectOrderPageReqVO);

        return success(ImmutableMap.of("total", inspectDayTotal,"todo", inspectDayTodo));
    }

    @GetMapping("/inspect/week")
    public CommonResult<Map<String, Object>> getInspectWeek() {
        IotInspectOrderPageReqVO iotInspectOrderPageReqVO = new IotInspectOrderPageReqVO();
        ImmutableMap<String, LocalDateTime> beginEndWeek = getBeginEndWeek();
        iotInspectOrderPageReqVO.setCreateTime(new LocalDateTime[]{beginEndWeek.get("start"), beginEndWeek.get("end")});
        Long inspectWeekTotal = iotInspectOrderMapper.selectCountByTimeAndStatus(iotInspectOrderPageReqVO);
        iotInspectOrderPageReqVO.setStatus("todo");
        Long inspectWeekTodo = iotInspectOrderMapper.selectCountByTimeAndStatus(iotInspectOrderPageReqVO);

        return success(ImmutableMap.of("total", inspectWeekTotal,"todo", inspectWeekTodo));
    }

    @GetMapping("/inspect/month")
    public CommonResult<Map<String, Object>> getInspectMonth() {
        IotInspectOrderPageReqVO iotInspectOrderPageReqVO = new IotInspectOrderPageReqVO();
        ImmutableMap<String, LocalDateTime> beginEndMonth = getBeginEndMonth();
        iotInspectOrderPageReqVO.setCreateTime(new LocalDateTime[]{beginEndMonth.get("start"), beginEndMonth.get("end")});
        Long inspectWeekTotal = iotInspectOrderMapper.selectCountByTimeAndStatus(iotInspectOrderPageReqVO);
        iotInspectOrderPageReqVO.setStatus("todo");
        Long inspectWeekTodo = iotInspectOrderMapper.selectCountByTimeAndStatus(iotInspectOrderPageReqVO);

        return success(ImmutableMap.of("total", inspectWeekTotal,"todo", inspectWeekTodo));
    }

    @GetMapping("/inspect/total")
    public CommonResult<Map<String, Object>> getInspectTotal() {
        Long total = iotInspectOrderMapper.selectCount();
        Long todo = iotInspectOrderMapper.selectCount("status", "todo");

        return success(ImmutableMap.of("total", total,"todo", todo));
    }


    @GetMapping("/inspect/status")
    public CommonResult<Map<String, Long>> getInspectStatusInfo(IotCountDataDO vo) {
        Set<Long> ids = new HashSet<>();
        if (Objects.nonNull(vo.getDeptId())) {
            ids = deptService.getChildDeptIdListFromCache(vo.getDeptId());
            ids.add(vo.getDeptId());
        }
        List<IotInspectOrderDO> iotInspectOrderDOS = iotInspectOrderMapper.selectListStat(vo, ids);
        Map<String, Long> order = iotInspectOrderDOS.stream().collect(Collectors.groupingBy(IotInspectOrderDO::getStatus, Collectors.counting()));
        return success(order);
    }

    @GetMapping("/report/inspect/status")
    public CommonResult<Map<String, Long>> getInspectStatusInfoReport(IotCountDataDO vo) {
        Set<Long> ids;
        if (Objects.isNull(vo.getDeptId())){
            Long loginUserDeptId = SecurityFrameworkUtils.getLoginUserDeptId();
            String companyCode = deptUtil.getCompanyCode(loginUserDeptId);
            ids = deptUtil.getDeptIds(companyCode);
        } else {
            ids = deptService.getChildDeptIdListFromCache(vo.getDeptId());
            ids.add(vo.getDeptId());
        }
        Long todo = iotInspectOrderMapper.selectCount(vo, ids,"todo");
        Long finished = iotInspectOrderMapper.selectCount(vo, ids,"finished");
        Long ignore = iotInspectOrderMapper.selectCount(vo, ids,"ignore");
//        Map<String, Long> order = iotInspectOrderDOS.stream().collect(Collectors.groupingBy(IotInspectOrderDO::getStatus, Collectors.counting()));
        return success(ImmutableMap.of("todo",todo,"finished",finished,"ignore",ignore));
    }

    @GetMapping("/inspect/statuss/{dept}")
    public CommonResult<Map<String, Long>> getInspectStatusInfos(@PathVariable("dept") String dept) {
        Set<Long> ids = getDeptIds(dept);
        IotCountDataDO vo = new IotCountDataDO();
        List<IotInspectOrderDO> iotInspectOrderDOS = iotInspectOrderMapper.selectListStat(vo, ids);
        Map<String, Long> order = iotInspectOrderDOS.stream().collect(Collectors.groupingBy(IotInspectOrderDO::getStatus, Collectors.counting()));
        return success(order);
    }

    @GetMapping("/inspect/today/status")
    public CommonResult<Map<String, Long>> getInspectTodayStatusInfo() {
        ImmutableMap<String, LocalDateTime> beginEndDay = getBeginEndDay(0);
        IotInspectOrderPageReqVO iotInspectOrderPageReqVO = new IotInspectOrderPageReqVO();
        iotInspectOrderPageReqVO.setCreateTime(new LocalDateTime[]{beginEndDay.get("start"), beginEndDay.get("end")});
        List<IotInspectOrderDO> iotInspectOrderDOS = iotInspectOrderMapper.selectListByCreateTime(iotInspectOrderPageReqVO, new HashSet<>());
        Map<String, Long> order = iotInspectOrderDOS.stream().collect(Collectors.groupingBy(IotInspectOrderDO::getStatus, Collectors.counting()));
        return success(order);
    }

    @GetMapping("/inspect/year")
    public CommonResult<List<MonthRange>> getInspectYear() {
        List<MonthRange> lastYearMonths = getLastYearMonthRanges();
        List<MonthRange> collect = lastYearMonths.stream().map(e -> {
            IotInspectOrderPageReqVO iotInspectOrderPageReqVO = new IotInspectOrderPageReqVO();
            iotInspectOrderPageReqVO.setCreateTime(new LocalDateTime[]{e.getStart(), e.getEnd()});
            Long l = iotInspectOrderMapper.selectCountByTimeAndStatus(iotInspectOrderPageReqVO);
            e.setCount(Integer.valueOf(String.valueOf(l)));
            return e;
        }).collect(Collectors.toList());

        return success(collect);
    }


    @GetMapping("/maintenance/day")
    public CommonResult<Map<String, Object>> getMaintenanceDay() {
        ImmutableMap<String, LocalDateTime> beginEndDay = getBeginEndDay(1);
        IotMainWorkOrderPageReqVO iotMainWorkOrderPageReqVO = new IotMainWorkOrderPageReqVO();
        iotMainWorkOrderPageReqVO.setCreateTime(new LocalDateTime[]{beginEndDay.get("start"), beginEndDay.get("end")});
        Long inspectDayTotal = iotMainWorkOrderMapper.selectCountByTimeAndStatus(iotMainWorkOrderPageReqVO);
        iotMainWorkOrderPageReqVO.setResult(1);
        Long inspectDayTodo = iotMainWorkOrderMapper.selectCountByTimeAndStatus(iotMainWorkOrderPageReqVO);

        return success(ImmutableMap.of("total", inspectDayTotal,"todo", inspectDayTodo));
    }

    @GetMapping("/maintenance/week")
    public CommonResult<Map<String, Object>> getMaintenanceWeek() {
        IotMainWorkOrderPageReqVO iotMainWorkOrderPageReqVO = new IotMainWorkOrderPageReqVO();
        ImmutableMap<String, LocalDateTime> beginEndWeek = getBeginEndWeek();
        iotMainWorkOrderPageReqVO.setCreateTime(new LocalDateTime[]{beginEndWeek.get("start"), beginEndWeek.get("end")});
        Long inspectWeekTotal = iotMainWorkOrderMapper.selectCountByTimeAndStatus(iotMainWorkOrderPageReqVO);
        iotMainWorkOrderPageReqVO.setResult(1);
        Long inspectWeekTodo = iotMainWorkOrderMapper.selectCountByTimeAndStatus(iotMainWorkOrderPageReqVO);

        return success(ImmutableMap.of("total", inspectWeekTotal,"todo", inspectWeekTodo));
    }

    @GetMapping("/maintenance/month")
    public CommonResult<Map<String, Object>> getMaintenanceMonth() {
        IotMainWorkOrderPageReqVO iotMainWorkOrderPageReqVO = new IotMainWorkOrderPageReqVO();
        ImmutableMap<String, LocalDateTime> beginEndMonth = getBeginEndMonth();
        iotMainWorkOrderPageReqVO.setCreateTime(new LocalDateTime[]{beginEndMonth.get("start"), beginEndMonth.get("end")});
        Long inspectWeekTotal = iotMainWorkOrderMapper.selectCountByTimeAndStatus(iotMainWorkOrderPageReqVO);
        iotMainWorkOrderPageReqVO.setResult(1);
        Long inspectWeekTodo = iotMainWorkOrderMapper.selectCountByTimeAndStatus(iotMainWorkOrderPageReqVO);

        return success(ImmutableMap.of("total", inspectWeekTotal,"todo", inspectWeekTodo));
    }

    @GetMapping("/maintenance/total")
    public CommonResult<Map<String, Object>> getMaintenanceTotal() {
        Long total = iotMainWorkOrderMapper.selectCount();
        Long todo = iotMainWorkOrderMapper.selectCount("result", 1);

        return success(ImmutableMap.of("total", total,"todo", todo));
    }

    @GetMapping("/maintenance/status/{dept}")
    public CommonResult<Map<String, Long>> getMaintenanceStatusInfo(@PathVariable("dept") String dept) {
        Set<Long> ids = getDeptIds(dept);
        IotMainWorkOrderPageReqVO reqVO = new IotMainWorkOrderPageReqVO();
        reqVO.setDeptIds(ids);
        List<IotMainWorkOrderDO> iotMainWorkOrderDOS = iotMainWorkOrderMapper.selectList(reqVO);
        Map<Integer, Long> order = iotMainWorkOrderDOS.stream().collect(Collectors.groupingBy(IotMainWorkOrderDO::getResult, Collectors.counting()));
        Map<String, Long> resultMap = new HashMap<>(order.size());
        order.forEach((k,v)->{
            if (k==1) {
                resultMap.put("todo", v);
            }else if (k==2) {
                resultMap.put("finished", v);
            }
        });
        return success(resultMap);
    }

    @GetMapping("/maintenance/today/status")
    public CommonResult<Map<String, Long>> getMaintenanceTodayStatusInfo() {
        ImmutableMap<String, LocalDateTime> beginEndDay = getBeginEndDay(0);
        IotMainWorkOrderPageReqVO iotMainWorkOrderPageReqVO = new IotMainWorkOrderPageReqVO();
        iotMainWorkOrderPageReqVO.setCreateTime(new LocalDateTime[]{beginEndDay.get("start"), beginEndDay.get("end")});
        List<IotMainWorkOrderDO> iotInspectOrderDOS = iotMainWorkOrderMapper.selectListByCreateTime(iotMainWorkOrderPageReqVO, new HashSet<>());
        Map<Integer, Long> order = iotInspectOrderDOS.stream().collect(Collectors.groupingBy(IotMainWorkOrderDO::getResult, Collectors.counting()));
        Map<String, Long> resultMap = new HashMap<>(order.size());
        order.forEach((k,v)->{
            if (k==1) {
                resultMap.put("todo", v);
            }else if (k==2) {
                resultMap.put("finished", v);
            }
        });
        return success(resultMap);
    }

    @GetMapping("/maintenance/type")
    public CommonResult<Map<String, Long>> getMaintenanceType() {
        List<IotMainWorkOrderDO> iotMainWorkOrderDOS = iotMainWorkOrderMapper.selectList();
        Map<Integer, Long> order = iotMainWorkOrderDOS.stream().collect(Collectors.groupingBy(IotMainWorkOrderDO::getType, Collectors.counting()));
        Map<String, Long> resultMap = new HashMap<>(order.size());
        order.forEach((k,v)->{
            if (k==1) {
                resultMap.put("计划生成", v);
            }else if (k==2) {
                resultMap.put("临时新建", v);
            }
        });
        return success(resultMap);
    }

    @Resource
    private TDDeviceMapper tdDeviceMapper;
    @GetMapping("/td/chart/{deviceName}/{identifier}")
    public CommonResult<List<DeviceVO>> getTdChart(@PathVariable("deviceName") String deviceName, @PathVariable("identifier") String identifier, @RequestParam("beginTime") String beginTime, @RequestParam("endTime") String endTime) {
        if (StringUtils.isBlank(identifier)) {
            return null;
        }
        Timestamp start1 = generateTimestamp(beginTime);
        Timestamp end1 = generateTimestamp(endTime);
        Integer i = deviceMapper.tableIfExist(deviceName.toLowerCase());
        if (i==1) {
            List<DeviceVO> deviceVOS = tdDeviceMapper.selectAllBtTimeAndIdentifier(deviceName.toLowerCase(), identifier, start1, end1);
            deviceVOS.forEach(deviceVO->{
                deviceVO.setTimestamp(deviceVO.getTs().getTime());
                deviceVO.setValue(Objects.nonNull(deviceVO.getLogValue())?Double.valueOf(deviceVO.getLogValue()):null);
            });
            return success(deviceVOS.stream().sorted(Comparator.comparing(DeviceVO::getTimestamp).reversed()).collect(Collectors.toList()));
        } else {
            List<DeviceVO> deviceVOS = new ArrayList<>();
            return success(deviceVOS);
        }
    }
    @GetMapping("/td/chart/ly/{deviceName}/{identifier}")
    public CommonResult<List<DeviceVO>> getLyTdChart(@PathVariable("deviceName") String deviceName, @PathVariable("identifier") String identifier, @RequestParam("beginTime") String beginTime, @RequestParam("endTime") String endTime) {
        if (StringUtils.isBlank(identifier)) {
            return null;
        }
        Timestamp start1 = generateTimestamp(beginTime);
        Timestamp end1 = generateTimestamp(endTime);
        Integer i = deviceMapper.tableIfExist(deviceName.toLowerCase());
        if (i==1) {
            List<DeviceVO> deviceVOS = tdDeviceMapper.selectAllBtTimeAndIdentifierNoInterval(deviceName.toLowerCase(), identifier, start1, end1);
            deviceVOS.forEach(deviceVO->{
                deviceVO.setTimestamp(deviceVO.getTs().getTime());
                deviceVO.setValue(Objects.nonNull(deviceVO.getLogValue())?Double.valueOf(deviceVO.getLogValue()):null);
            });
            return success(deviceVOS.stream().sorted(Comparator.comparing(DeviceVO::getTimestamp).reversed()).collect(Collectors.toList()));
        } else {
            List<DeviceVO> deviceVOS = new ArrayList<>();
            return success(deviceVOS);
        }
    }

    @Autowired
    private IotTdParamsMapper iotTdParamsMapper;
    @GetMapping("/td/ly/chart")
    public CommonResult<ImmutableMap> getTdChartLy( @RequestParam("pageSize") Integer pageSize, @RequestParam("deviceCode") String deviceCode, @RequestParam(value = "identifier", required = false) String identifier,
                                                   @RequestParam("beginTime") String beginTime, @RequestParam("endTime") String endTime) {
        List<IotDeviceDO> iotDeviceDOS = iotDeviceMapper.selectByCodeIn(Collections.singleton(deviceCode));
        if (CollUtil.isEmpty(iotDeviceDOS)) {
            throw new ServiceException(new ErrorCode(111,"不存在设备"));
        }
        IotDeviceDO iotDeviceDO = iotDeviceDOS.get(0);
        TableDataInfo tableDataInfo = restTemplate.getForObject(yanfanUrl + "/prod-api/iot/device/listThingsModel?deviceId="+iotDeviceDO.getYfDeviceId()+"&pageNum=1&pageSize=200", TableDataInfo.class);
        if (tableDataInfo == null) {
            throw new ServiceException(new ErrorCode(111,"不存在数采属性"));
        }
        List<ThingsModelDTO> rows = JSON.parseArray(JSON.toJSONString(tableDataInfo.getRows()), ThingsModelDTO.class);
        Timestamp start1 = generateTimestamp(beginTime);
        Timestamp end1 = generateTimestamp(endTime);
        Integer i = deviceMapper.tableIfExist(deviceCode.toLowerCase());
        if (i==1) {
            if (StringUtils.isNotBlank(identifier)&&!"undefined".equals(identifier)) {
                List<DeviceVO> deviceVOS = tdDeviceMapper.selectAllBtTimeAndidentifierAll(deviceCode.toLowerCase(), identifier, start1, end1,pageSize);
                deviceVOS.forEach(deviceVO->{
                    deviceVO.setTimestamp(deviceVO.getTs().getTime());
                    deviceVO.setValue(Objects.nonNull(deviceVO.getLogValue())?Double.valueOf(deviceVO.getLogValue()):null);
                    rows.stream().filter(e -> e.getIdentifier().equals(deviceVO.getIdentity())).findFirst().ifPresent(deviceVO1->{
                        deviceVO.setIdentity(deviceVO1.getModelName());
                    });
                    deviceVO.setSerialNumber(deviceCode);
                    deviceVO.setDeviceName(iotDeviceDO.getDeviceName());
                });
                List<DeviceVO> collect = deviceVOS.stream().sorted(Comparator.comparing(DeviceVO::getTimestamp).reversed()).collect(Collectors.toList());
                return success(ImmutableMap.of( "data",collect));
            } else {
                List<DeviceVO> deviceVOS = tdDeviceMapper.selectAllBtTime(deviceCode.toLowerCase(), start1, end1, pageSize);
                deviceVOS.forEach(deviceVO->{
                    deviceVO.setTimestamp(deviceVO.getTs().getTime());
                    deviceVO.setValue(Objects.nonNull(deviceVO.getLogValue())?Double.valueOf(deviceVO.getLogValue()):null);
                    rows.stream().filter(e -> e.getIdentifier().equals(deviceVO.getIdentity())).findFirst().ifPresent(deviceVO1->{
                        deviceVO.setIdentity(deviceVO1.getModelName());
                    });
                    deviceVO.setSerialNumber(deviceCode);
                    deviceVO.setDeviceName(iotDeviceDO.getDeviceName());
                });
                List<DeviceVO> collect = deviceVOS.stream().sorted(Comparator.comparing(DeviceVO::getTimestamp).reversed()).collect(Collectors.toList());
                return success(ImmutableMap.of( "data",collect));
            }

        } else {
            List<DeviceVO> deviceVOS = new ArrayList<>();
            return success(ImmutableMap.of( "data",deviceVOS));
        }
    }

    public Set<Long> getDeptIds(String dept) {
        Set<Long> ids = new HashSet<>();
        List<DeptRespDTO> depts = new ArrayList<>();
        if ("rd".equals(dept)) {
            depts = deptApi.getDeptByName("四川瑞都");
        } else if ("rh".equals(dept)) {
            depts = deptApi.getDeptByName("瑞恒兴域");
        } else if ("ry".equals(dept)) {
            depts = deptApi.getDeptByName("瑞鹰国际");
        } else if ("yf".equals(dept)) {
            depts = deptApi.getDeptByName("科瑞石油技术");
        } else {
            Long loginUserDeptId = SecurityFrameworkUtils.getLoginUserDeptId();
            DeptRespDTO dto = deptApi.getDept(loginUserDeptId);
            depts = deptApi.getDeptByName(dto.getName());
        }
        if (CollUtil.isNotEmpty(depts)) {
            Long deptId = depts.get(0).getId();
            if (Objects.nonNull(depts.get(0).getId())) {
                ids = deptService.getChildDeptIdListFromCache(depts.get(0).getId());
                ids.add(deptId);
            }
        }
        return  ids;
    }

    @GetMapping("/home/device/count/{dept}")
    public CommonResult<ImmutableMap<Object, Object>> getHomeDeviceCountStat(@PathVariable("dept") String dept) {
        Set<Long> ids = getDeptIds(dept);
        Long deviceCount = iotDeviceMapper.selectByDept(ids);
        ImmutableMap<String, LocalDateTime> beginEndDay = getBeginEndDay(0);
        IotDevicePageReqVO iotDevicePageReqVO = new IotDevicePageReqVO();
        iotDevicePageReqVO.setCreateTime(new LocalDateTime[]{beginEndDay.get("start"), beginEndDay.get("end")});
        Long deviceToday = iotDeviceMapper.selectCountByTimeAndStatus(iotDevicePageReqVO);
        return success(ImmutableMap.of("total", deviceCount,"today", deviceToday));
    }

    /**
     * 查询所有瑞鹰 钻井 进尺 修井完成总井口数
     * @return
     */
    @GetMapping("/home/ry/count/zjxj")
    public CommonResult<ImmutableMap<Object, Object>> getHomeZjXjStat(IotRyDailyReportPageReqVO reqVO) {
        // 查询所有钻井进尺
        IotRyDailyReportPageReqVO zjReqVO = new IotRyDailyReportPageReqVO();
        zjReqVO.setProjectClassification("1");
        zjReqVO.setCreateTime(reqVO.getCreateTime());
        BigDecimal totalFootage = BigDecimal.ZERO;
        List<IotRyDailyReportDO> dailyReports = iotRyDailyReportMapper.dailyReports(zjReqVO);
        // 使用Stream API计算总进尺
        if (CollUtil.isNotEmpty(dailyReports)) {
            totalFootage = dailyReports.stream()
                    .map(IotRyDailyReportDO::getDailyFootage)
                    .filter(Objects::nonNull)
                    .reduce(BigDecimal.ZERO, BigDecimal::add);
        }

        // 查询所有完工井数
        IotRyDailyReportPageReqVO xjReqVO = new IotRyDailyReportPageReqVO();
        xjReqVO.setCreateTime(reqVO.getCreateTime());
        List<IotRyDailyReportTaskCountVO> repairDeptTasks = iotRyDailyReportMapper.countRepairTasksByDept(xjReqVO);
        // Java8 Stream 简洁累加（核心优化）
        Integer completeWellCount = repairDeptTasks.stream()
                // 过滤null元素，避免空指针
                .filter(Objects::nonNull)
                // 转换为int流，处理属性为null的情况（null则取0）
                .mapToInt(task -> Optional.ofNullable(task.getCompletedTaskCount()).orElse(0))
                // 累加求和（空集合时sum()返回0，无需手动判空）
                .sum();

        return success(ImmutableMap.of("zj", totalFootage,"xj", completeWellCount));
    }

    @GetMapping("/home/maintain/count/{dept}")
    public CommonResult<ImmutableMap<Object, Object>> getHomeMaintainCountStat(@PathVariable("dept") String dept) {
        ImmutableMap<String, LocalDateTime> beginEndDay = getBeginEndDay(0);
        Set<Long> ids = getDeptIds(dept);

        Long maintainCount = iotMaintainMapper.selectByDept(ids);
        IotMaintainPageReqVO iotMaintainPageReqVO = new IotMaintainPageReqVO();
        iotMaintainPageReqVO.setCreateTime(new LocalDateTime[]{beginEndDay.get("start"), beginEndDay.get("end")});
        Long maintainToday = iotMaintainMapper.selectCountByTimeAndStatus(iotMaintainPageReqVO);
        return success(ImmutableMap.of("total", maintainCount, "today", maintainToday));
    }

    @GetMapping("/home/work/count")
    public CommonResult<ImmutableMap<Object, Object>> getHomeWorkCountStat() {
        ImmutableMap<String, LocalDateTime> beginEndDay = getBeginEndDay(0);
        Long workCount = iotMainWorkOrderMapper.selectCount();
        IotMainWorkOrderPageReqVO iotMainWorkOrderPageReqVO = new IotMainWorkOrderPageReqVO();
        iotMainWorkOrderPageReqVO.setCreateTime(new LocalDateTime[]{beginEndDay.get("start"), beginEndDay.get("end")});
        Long workToday = iotMainWorkOrderMapper.selectCountByTimeAndStatus(iotMainWorkOrderPageReqVO);
        return success(ImmutableMap.of("total", workCount, "today", workToday));
    }

    @GetMapping("/home/inspect/count")
    public CommonResult<ImmutableMap<Object, Object>> getHomeInspectCountStat() {
        ImmutableMap<String, LocalDateTime> beginEndDay = getBeginEndDay(0);
        Long inspectCount = iotInspectOrderMapper.selectCount();
        IotInspectOrderPageReqVO iotInspectOrderPageReqVO = new IotInspectOrderPageReqVO();
        iotInspectOrderPageReqVO.setCreateTime(new LocalDateTime[]{beginEndDay.get("start"), beginEndDay.get("end")});
        Long inspectToday = iotInspectOrderMapper.selectCountByTimeAndStatus(iotInspectOrderPageReqVO);
        return success(ImmutableMap.of("total", inspectCount, "today", inspectToday));
    }

    @Resource
    private DictDataService dictDataService;
    @GetMapping("/home/device/status/{dept}")
    public CommonResult<List<Map<String, Object>>> getDeviceStatusStat(@PathVariable("dept") String dept) {
        Set<Long> ids = getDeptIds(dept);
        IotDevicePageReqVO iotDevicePageReqVO = new IotDevicePageReqVO();
        iotDevicePageReqVO.setDeptIds(new ArrayList<>(ids));
        List<IotDeviceDO> iotDeviceDOS = iotDeviceMapper.selectList(iotDevicePageReqVO);
        Map<String, Long> order = iotDeviceDOS.stream().collect(Collectors.groupingBy(IotDeviceDO::getDeviceStatus, Collectors.counting()));
        List<Map<String, Object>> results = new ArrayList<>();
        List<DictDataDO> pmsDeviceStatus = dictDataService.getDictDataListByDictType("pms_device_status");
        order.forEach((k,v)->{
            pmsDeviceStatus.stream().filter(e -> e.getValue().equals(k)).findFirst().ifPresent(e -> {
                Map<String, Object> resultMap = new HashMap<>();
                resultMap.put("name", e.getLabel());
                resultMap.put("value", v);
                results.add(resultMap);
            });
        });
        return success(results);
    }

    @GetMapping("/home/device/type/{dept}")
    public CommonResult<List<Map<String, Object>>> getDeviceTypeStat(@PathVariable("dept") String dept) {
        Set<Long> ids = getDeptIds(dept);
        IotDevicePageReqVO iotDevicePageReqVO = new IotDevicePageReqVO();
        iotDevicePageReqVO.setDeptIds(new ArrayList<>(ids));
        List<IotDeviceDO> iotDeviceDOS = iotDeviceMapper.selectList(iotDevicePageReqVO);
        LinkedList<Map<String, Object>> results = new LinkedList<>();
        if ("rh".equals(dept)) {
            List<Map.Entry<Long, Long>> collect = iotDeviceDOS.stream().collect(Collectors.groupingBy(IotDeviceDO::getAssetClass, Collectors.counting())).entrySet().stream().sorted(Map.Entry.<Long, Long>comparingByValue().reversed()).collect(Collectors.toList());
            collect.forEach(e->{
                IotProductClassifyDO iotProductClassifyDO = iotProductClassifyMapper.selectById(e.getKey());
                if ("电驱增压机".equals(iotProductClassifyDO.getName())||"柴驱增压机".equals(iotProductClassifyDO.getName())||"液驱增压机".equals(iotProductClassifyDO.getName())||"电驱空压机".equals(iotProductClassifyDO.getName())||"柴驱空压机".equals(iotProductClassifyDO.getName())
                        ||"空气处理撬".equals(iotProductClassifyDO.getName())||"提纯撬".equals(iotProductClassifyDO.getName()) ||"膜组".equals(iotProductClassifyDO.getName())||"注水泵".equals(iotProductClassifyDO.getName())) {
                    Map<String, Object> map = new HashMap<>(4);
                    map.put("category", iotProductClassifyDO.getName());
                    map.put("value", e.getValue());
                    results.add(map);
                }
            });
        }else {
            List<Map.Entry<Long, Long>> collect = iotDeviceDOS.stream().collect(Collectors.groupingBy(IotDeviceDO::getAssetClass, Collectors.counting())).entrySet().stream().sorted(Map.Entry.<Long, Long>comparingByValue().reversed())
                    .limit(5)
                    .collect(Collectors.toList());
            collect.forEach(e ->{
                IotProductClassifyDO iotProductClassifyDO = iotProductClassifyMapper.selectById(e.getKey());
                Map<String, Object> map = new HashMap<>(4);
                map.put("category", iotProductClassifyDO.getName());
                map.put("value", e.getValue());
                results.add(map);
            });
        }

        return success(results);
    }

    @Data
    public static class ActiveDept {
        private String deptName;
        private Long active;
        private Long total;
    }

    @GetMapping("/home/dept")
    public CommonResult<List<Pms.deptStat>> getActiveDeptStat() {
        List<Pms.deptStat> userCountByDeptId = adminUserApi.getUserCountByDeptId(null);
        return success(userCountByDeptId);
    }

    @GetMapping("/home/safe")
    public CommonResult<String> getSafe() {
        List<IotSapStockDO> iotSapStockDOS = iotSapStockMapper.getSafeList();
        List<Long> ids = new ArrayList<>();
        iotSapStockDOS.forEach(e ->{
            if (e.getSafetyStock().compareTo(e.getQuantity())>0) {
                ids.add(e.getId());
            }
        });
        return success(String.valueOf(ids.size()));
    }

    @GetMapping("/inspect/device")
    public CommonResult<Map<String, Integer>> getDeviceStatus(IotCountDataDO vo) {
        Set<Long> ids = new HashSet<>();
        if (Objects.nonNull(vo.getDeptId())) {
            ids = deptService.getChildDeptIdListFromCache(vo.getDeptId());
            ids.add(vo.getDeptId());
        }
        List<IotInspectOrderDetailDO> detailDOList = iotInspectOrderDetailMapper.selectListStat(vo, ids);
        Map<Long, List<IotInspectOrderDetailDO>> collect = detailDOList.stream().collect(Collectors.groupingBy(IotInspectOrderDetailDO::getOrderId));
        AtomicInteger todo = new AtomicInteger();
        AtomicInteger finished = new AtomicInteger();
        AtomicInteger ignore = new AtomicInteger();
        collect.forEach( (k,v)->{
            Map<Long, List<IotInspectOrderDetailDO>> collect1 = v.stream().collect(Collectors.groupingBy(IotInspectOrderDetailDO::getDeviceId));
            collect1.forEach( (k1,v2)->{
                boolean b1 = v2.stream().allMatch(IotInspectOrderDetailDO::getIgnoreReason);
                if (b1) {
                    ignore.getAndIncrement();
                } else {
                    boolean b = v2.stream().anyMatch(f -> Objects.isNull(f.getIfNormal()));
                    if (b) {
                        todo.getAndIncrement();
                    }else {
                        finished.getAndIncrement();
                    }
                }
            });
        });
        return success(ImmutableMap.of("todo", todo.get(),"finished", finished.get(), "ignore", ignore.get()));
    }

    @GetMapping("/inspect/exception/device")
    public CommonResult<ImmutableMap<String, Long>> getDeviceException(IotCountDataDO vo) {
        Set<Long> ids;
        if (Objects.isNull(vo.getDeptId())){
            Long loginUserDeptId = SecurityFrameworkUtils.getLoginUserDeptId();
            String companyCode = deptUtil.getCompanyCode(loginUserDeptId);
            ids = deptUtil.getDeptIds(companyCode);
        } else {
            ids = deptService.getChildDeptIdListFromCache(vo.getDeptId());
            ids.add(vo.getDeptId());
        }
        Long deviceException = iotInspectOrderDetailMapper.selectDeviceException(vo, ids);
        return success(ImmutableMap.of("exceptionNum",deviceException));
    }

    @GetMapping("/rh/ywcb/{dept}")
    @PermitAll
    public CommonResult<Map<String, Object>> getRhYwcbStat(@PathVariable("dept") String dept) {
        Set<Long> ids = getDeptIds(dept);
        List<String> lastSevenDays = getLastSevenDays();
        String first = lastSevenDays.get(0);
        String last = lastSevenDays.get(lastSevenDays.size() - 1);
        LocalDateTime startOfDay = getStartOfDay(last);
        LocalDateTime endOfDay = getEndOfDay(first);
        LocalDateTime[] createTime = new LocalDateTime[]{startOfDay, endOfDay};
        //查询维修成本
        IotMaintainPageReqVO maintainPageReqVO = new IotMaintainPageReqVO();
        maintainPageReqVO.setDeptIds(ids);
        maintainPageReqVO.setExecuteDate(createTime);
        maintainPageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE);
        List<IotMaintainDO> repairOrders = iotMaintainService.getIotMaintainPage(maintainPageReqVO).getList();
        LinkedHashMap<String, Long> repairMap = countWxcbByDate(repairOrders, 7);

        // 查询保养成本
        IotMainWorkOrderPageReqVO workOrderReqVO = new IotMainWorkOrderPageReqVO();
        workOrderReqVO.setDeptIds(ids);
        workOrderReqVO.setCreateTime(createTime);
        List<IotMainWorkOrderDO> workOrders = iotMainWorkOrderService.workOrders(workOrderReqVO);
        LinkedHashMap<String, Long> byOutMap = countBycbByDate(workOrders, 7);
//        LinkedHashMap<String, Long> outMap = countYwcbByDate(outs, 7);
        LinkedList<Object> xAxis = new LinkedList<>();
        LinkedList<Object> outData = new LinkedList<>();
        repairMap.forEach( (k,v)->{
            xAxis.add(k);
            if (Objects.isNull(byOutMap.get(k))) {
                outData.add(v);
            } else {
                outData.add(v+byOutMap.get(k));
            }
        });

        return success(ImmutableMap.of("xAxis", xAxis, "series", outData));
    }

    @GetMapping("/rh/order/{dept}")
    @PermitAll
    public CommonResult<Map<String, Object>> getOrderNumberStat(@PathVariable("dept") String dept) {
        Set<Long> ids = getDeptIds(dept);
        List<String> lastSevenDays = getLastSevenDays();
        String first = lastSevenDays.get(0);
        String last = lastSevenDays.get(lastSevenDays.size() - 1);
        LocalDateTime startOfDay = getStartOfDay(last);
        LocalDateTime endOfDay = getEndOfDay(first);
        LocalDateTime[] createTime = new LocalDateTime[]{startOfDay, endOfDay};

        IotOpeationFillPageReqVO iotOpeationFillPageReqVO = new IotOpeationFillPageReqVO();
        iotOpeationFillPageReqVO.setCreateTime(createTime);
        iotOpeationFillPageReqVO.setDeptIds(new ArrayList<>(ids));
        List<Map<String, Object>> fills = iotOpeationFillMapper.selectListByCreateTime(iotOpeationFillPageReqVO).stream().map(e -> {
            Map<String, Object> abc = new HashMap<>();
            abc.put("id", e.getId());
            abc.put("createTime", e.getCreateTime());
            return abc;
        }).collect(Collectors.toList());
        LinkedHashMap<String, Long> fillMap = countRecordsByDate(fills, 7);
        LinkedList<Object> xAxis = new LinkedList<>();
        LinkedList<Object> fillData = new LinkedList<>();
        fillMap.forEach( (k,v)->{
            xAxis.add(k);
            fillData.add(v);
        });

        IotMaintainPageReqVO iotMaintainPageReqVO = new IotMaintainPageReqVO();
        iotMaintainPageReqVO.setCreateTime(createTime);
        List<Map<String, Object>> maintains = iotMaintainMapper.selectListByCreateTime(iotMaintainPageReqVO, ids).stream().map(e -> {
            Map<String, Object> abc = new HashMap<>();
            abc.put("id", e.getId());
            abc.put("createTime", e.getCreateTime());
            return abc;
        }).collect(Collectors.toList());
        Map<String, Long> maintainMap = countRecordsByDate(maintains, 7);
        LinkedList<Object> maintainData = new LinkedList<>();
        maintainMap.forEach( (k,v)->{
            maintainData.add(v);
        });

        IotMainWorkOrderPageReqVO iotMainWorkOrderPageReqVO = new IotMainWorkOrderPageReqVO();
        iotMainWorkOrderPageReqVO.setCreateTime(createTime);
        List<Map<String, Object>> works = iotMainWorkOrderMapper.selectListByCreateTime(iotMainWorkOrderPageReqVO,ids).stream().map(e -> {
            Map<String, Object> abc = new HashMap<>();
            abc.put("id", e.getId());
            abc.put("createTime", e.getCreateTime());
            return abc;
        }).collect(Collectors.toList());
        Map<String, Long> workMap = countRecordsByDate(works, 7);
        LinkedList<Object> workData = new LinkedList<>();
        workMap.forEach( (k,v)->{
            workData.add(v);
        });


        IotInspectOrderPageReqVO iotInspectOrderPageReqVO = new IotInspectOrderPageReqVO();
        iotInspectOrderPageReqVO.setCreateTime(createTime);
        List<Map<String, Object>> inspects = iotInspectOrderMapper.selectListByCreateTime(iotInspectOrderPageReqVO,ids).stream().map(e -> {
            Map<String, Object> abc = new HashMap<>();
            abc.put("id", e.getId());
            abc.put("createTime", e.getCreateTime());
            return abc;
        }).collect(Collectors.toList());
        Map<String, Long> inspectMap = countRecordsByDate(inspects, 7);
        LinkedList<Object> inspectData = new LinkedList<>();
        inspectMap.forEach( (k,v)->{
            inspectData.add(v);
        });

        ImmutableMap<String, Serializable> maintainResult = ImmutableMap.of("name", "维修工单~~en**repairOrder", "data", maintainData);
        ImmutableMap<String, Serializable> workResult = ImmutableMap.of("name", "保养工单~~en**maintenanceOrder", "data", workData);
        ImmutableMap<String, Serializable> inspectResult = ImmutableMap.of("name", "巡检工单~~en**inspectOrder", "data", inspectData);
        ImmutableMap<String, Serializable> fillResult = ImmutableMap.of("name", "运行记录~~en**operationRecord", "data", fillData);
        return success(ImmutableMap.of("xAxis", xAxis, "series", ImmutableList.of(maintainResult, workResult,inspectResult, fillResult)));
    }

    public static LinkedHashMap<String, Long> sumTotalByDate(List<Map<String, Object>> records, int days, String key) {
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
        LocalDate today = LocalDate.now();

        // 生成近days天的日期列表，初始值为0
        LinkedHashMap<String, Long> dateMap = new LinkedHashMap<>();
        for (int i = days - 1; i >= 0; i--) {
            LocalDate date = today.minusDays(i);
            dateMap.put(date.format(formatter), 0L);
        }

        // 统计每天的total字段之和
        Map<String, Long> sumMap = records.stream()
                .collect(Collectors.groupingBy(
                        record -> {
                            try {
                                // 提取日期部分（假设createTime格式为yyyy-MM-dd...）
                                return String.valueOf(record.get("createTime")).substring(0, 10);
                            } catch (Exception e) {
                                System.err.println("日期格式错误: " + record.get("createTime"));
                                return "invalid_date";
                            }
                        },
                        // 累加每天的total字段值，处理可能的格式问题
                        Collectors.summingLong(record -> {
                            try {
                                Object totalObj = record.get(key);
                                if (totalObj instanceof Number) {
                                    return ((Number) totalObj).longValue();
                                } else if (totalObj instanceof String) {
                                    String value = String.valueOf(totalObj).replace(".00","");
                                    return Long.parseLong(value);
                                } else {
//                                    System.err.println("total字段格式错误: " + totalObj);
                                    String value = String.valueOf(totalObj).replace(".00","");
                                    return Long.parseLong(value);
                                }
                            } catch (Exception e) {
                                System.err.println("处理total字段出错: " + e.getMessage());
                                return 0L;
                            }
                        })
                ));

        // 合并结果，确保所有日期都在返回结果中
        dateMap.forEach((date, sum) -> {
            if (sumMap.containsKey(date)) {
                dateMap.put(date, sumMap.get(date));
            }
        });

        return dateMap;
    }

    /**
     * 根据外部传入的有序日期轴汇总每日数据，统一转万方保留两位小数
     * @param records 原始报表数据
     * @param dateAxis 自定义有序日期列表（昨日起7天）
     * @param key 汇总字段名
     * @return 有序日期-汇总值Map，无数据默认0.0
     */
    public static LinkedHashMap<String, Double> sumTotalByDates(List<Map<String, Object>> records, List<String> dateAxis, String key) {
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
        List<String> sortedDateAxis = dateAxis.stream()
                .map(LocalDate::parse)
                .sorted()
                .map(d -> d.format(formatter))
                .collect(Collectors.toList());
        // 1. 使用外部传入的日期初始化有序Map，默认0
        LinkedHashMap<String, Double> dateMap = new LinkedHashMap<>();
        sortedDateAxis.forEach(date -> dateMap.put(date, 0.0));

        // 2. 按日期分组求和
        Map<String, Double> dateSum = records.stream()
                .collect(Collectors.groupingBy(
                        record -> {
                            try {
                                String timeStr = String.valueOf(record.get("createTime"));
                                return timeStr.substring(0, 10);
                            } catch (Exception e) {
                                System.err.println("日期解析异常：" + record.get("createTime"));
                                return "invalid_date";
                            }
                        },
                        Collectors.summingDouble(record -> {
                            try {
                                Object val = record.get(key);
                                if (val instanceof Number) {
                                    return ((Number) val).doubleValue();
                                }
                                return Double.parseDouble(String.valueOf(val));
                            } catch (Exception e) {
                                System.err.println("数值转换异常：" + e.getMessage());
                                return 0.0;
                            }
                        })
                ));

        // 3. 填充数据，单位转换万方，保留两位小数，使用Java8 replaceAll简化循环
        dateMap.replaceAll((date, oldVal) -> {
            if (!dateSum.containsKey(date)) {
                return 0.0;
            }
            double cubic = dateSum.get(date);
            double tenThousandCubic = cubic / 10000.0;
            return Math.round(tenThousandCubic * 100.0) / 100.0;
        });
        return dateMap;
    }

    public static LinkedHashMap<String, Long> countYwcbByDate(List<IotOutboundDO> records, int days) {
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
        LocalDate today = LocalDate.now();

        // 生成近七天的日期列表
        LinkedHashMap<String, Long> dateMap = new LinkedHashMap<>();
        for (int i = days-1; i >= 0; i--) {
            LocalDate date = today.minusDays(i);
            dateMap.put(date.format(formatter), 0L);
        }

        Map<String, Long> amountMap = records.stream()
                .collect(Collectors.groupingBy(
                        record -> {
                            try {
                                // 提取日期部分（假设createTime是类似"yyyy-MM-ddHH:mm:ss"的字符串）
                                return String.valueOf(record.getCreateTime()).substring(0, 10);
                            } catch (Exception e) {
                                System.err.println("日期格式错误: " + record.getCreateTime());
                                return "invalid_date";
                            }
                        },
                        // 对每个分组计算金额总和：quantity * price累加
                        Collectors.summingLong(record -> record.getQuantity().multiply(record.getUnitPrice()).longValue())
                ));

        // 合并两个映射，确保所有日期都存在
        dateMap.forEach((date, count) -> {
            if (amountMap.containsKey(date)) {
                dateMap.put(date, amountMap.get(date));
            }
        });

        return dateMap;
    }

    public static LinkedHashMap<String, Long> countBycbByDate(List<IotMainWorkOrderDO> records, int days) {
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
        LocalDate today = LocalDate.now();

        // 生成近七天的日期列表
        LinkedHashMap<String, Long> dateMap = new LinkedHashMap<>();
        for (int i = days-1; i >= 0; i--) {
            LocalDate date = today.minusDays(i);
            dateMap.put(date.format(formatter), 0L);
        }

        Map<String, Long> amountMap = records.stream()
                .collect(Collectors.groupingBy(
                        record -> {
                            try {
                                // 提取日期部分（假设createTime是类似"yyyy-MM-ddHH:mm:ss"的字符串）
                                return String.valueOf(record.getCreateTime()).substring(0, 10);
                            } catch (Exception e) {
                                System.err.println("日期格式错误: " + record.getCreateTime());
                                return "invalid_date";
                            }
                        },
                        // 对每个分组计算金额总和：quantity * price累加
                        Collectors.summingLong(record -> record.getCost().longValue())
                ));

        // 合并两个映射，确保所有日期都存在
        dateMap.forEach((date, count) -> {
            if (amountMap.containsKey(date)) {
                dateMap.put(date, amountMap.get(date));
            }
        });

        return dateMap;
    }

    public static LinkedHashMap<String, Long> countWxcbByDate(List<IotMaintainDO> records, int days) {
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
        LocalDate today = LocalDate.now();

        // 生成近七天的日期列表
        LinkedHashMap<String, Long> dateMap = new LinkedHashMap<>();
        for (int i = days-1; i >= 0; i--) {
            LocalDate date = today.minusDays(i);
            dateMap.put(date.format(formatter), 0L);
        }

        Map<String, Long> amountMap = records.stream()
                .collect(Collectors.groupingBy(
                        record -> {
                            try {
                                // 提取日期部分（假设createTime是类似"yyyy-MM-ddHH:mm:ss"的字符串）
                                return String.valueOf(record.getCreateTime()).substring(0, 10);
                            } catch (Exception e) {
                                System.err.println("日期格式错误: " + record.getCreateTime());
                                return "invalid_date";
                            }
                        },
                        // 对每个分组计算金额总和：quantity * price累加
                        Collectors.summingLong(record -> Objects.isNull(record.getMaintainFee())?0L:record.getMaintainFee().longValue())
                ));

        // 合并两个映射，确保所有日期都存在
        dateMap.forEach((date, count) -> {
            if (amountMap.containsKey(date)) {
                dateMap.put(date, amountMap.get(date));
            }
        });

        return dateMap;
    }
    public static LinkedHashMap<String, Long> countRecordsByDate(List<Map<String, Object>> records, int days) {
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
        LocalDate today = LocalDate.now();

        // 生成近七天的日期列表
        LinkedHashMap<String, Long> dateMap = new LinkedHashMap<>();
        for (int i = days-1; i >= 0; i--) {
            LocalDate date = today.minusDays(i);
            dateMap.put(date.format(formatter), 0L);
        }

        // 统计每天的记录数量
        Map<String, Long> countMap = records.stream()
                .collect(Collectors.groupingBy(
                        record -> {
                            try {
                                // 提取日期部分
                                return String.valueOf(record.get("createTime")).substring(0, 10);
                            } catch (Exception e) {
                                System.err.println("日期格式错误: " + record.get("createTime"));
                                return "invalid_date";
                            }
                        },
                        Collectors.counting()
                ));

        // 合并两个映射，确保所有日期都存在
        dateMap.forEach((date, count) -> {
            if (countMap.containsKey(date)) {
                dateMap.put(date, countMap.get(date));
            }
        });

        return dateMap;
    }

    @GetMapping("/rh/zql/{dept}")
    @PermitAll
    public CommonResult<Map<String, Object>> rhOrder(@PathVariable("dept") String dept) {
        Set<Long> ids = getDeptIds(dept);
        List<String> lastSevenDays = getLastSevenDays();
        String first = lastSevenDays.get(0);
        String last = lastSevenDays.get(lastSevenDays.size() - 1);
        LocalDateTime startOfDay = getStartOfDay(last);
        LocalDateTime endOfDay = getEndOfDay(first);
        LocalDateTime[] createTime = new LocalDateTime[]{startOfDay, endOfDay};

        IotDeviceRunLogPageReqVO iotDeviceRunLogPageReqVO = new IotDeviceRunLogPageReqVO();
        iotDeviceRunLogPageReqVO.setCreateTime(createTime);
        iotDeviceRunLogPageReqVO.setDeptIds(new ArrayList<>(ids));
        iotDeviceRunLogPageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE);
        iotDeviceRunLogPageReqVO.setPointName("累计注气量");
        List<IotDeviceRunLogRespVO> iotDeviceRunLogRespVOS = iotDeviceRunLogMapper.selectListByCreateTimeAndDeptList(iotDeviceRunLogPageReqVO);
        List<Map<String, Object>> fills = iotDeviceRunLogRespVOS
                .stream().map(e -> {
            Map<String, Object> abc = new HashMap<>();
            abc.put("id", e.getId());
            abc.put("createTime", e.getCreateTime());
            abc.put("total", e.getTotalRunTime());
            abc.put("today", e.getFillContent());
            return abc;
        }).collect(Collectors.toList());
        LinkedHashMap<String, Long> fillMap = sumTotalByDate(fills, 7,"total");
        LinkedList<Object> xAxis = new LinkedList<>();
        LinkedList<Object> fillData = new LinkedList<>();
        fillMap.forEach( (k,v)->{
            xAxis.add(k);
            fillData.add(v);
        });

        iotDeviceRunLogPageReqVO.setPointName("累计注水量");
        List<IotDeviceRunLogRespVO> waterDOs = iotDeviceRunLogMapper.selectListByCreateTimeAndDeptList(iotDeviceRunLogPageReqVO);
        List<Map<String, Object>> waters = waterDOs
                .stream().map(e -> {
                    Map<String, Object> abc = new HashMap<>();
                    abc.put("id", e.getId());
                    abc.put("createTime", e.getCreateTime());
                    abc.put("total", e.getTotalRunTime());
                    abc.put("today", e.getFillContent());
                    return abc;
                }).collect(Collectors.toList());
        LinkedHashMap<String, Long> waterMap = sumTotalByDate(waters, 7,"total");
        LinkedList<Object> waterXAxis = new LinkedList<>();
        LinkedList<Object> waterData = new LinkedList<>();
        waterMap.forEach( (k,v)->{
            waterXAxis.add(k);
            waterData.add(v);
        });

        ImmutableMap<String, Serializable> fillResult = ImmutableMap.of("name", "累计注气量~~en**cumulative gas injection", "data", fillData);
        ImmutableMap<String, Serializable> waterResult = ImmutableMap.of("name", "累计注水量~~en**cumulative water injection", "data", waterData);
        return success(ImmutableMap.of("xAxis", xAxis, "series", ImmutableList.of(fillResult,waterResult)));

    }
    @GetMapping("/rh/zql/today/{dept}")
    @PermitAll
    public CommonResult<Map<String, Object>> rhOrderToday(@PathVariable("dept") String dept) {
        Set<Long> ids = getDeptIds(dept);
        List<String> lastSevenDays = getLastSevenDays();
        String first = lastSevenDays.get(0);
        String last = lastSevenDays.get(lastSevenDays.size() - 1);
        LocalDateTime startOfDay = getStartOfDay(last);
        LocalDateTime endOfDay = getEndOfDay(first);
        LocalDateTime[] createTime = new LocalDateTime[]{startOfDay, endOfDay};

        IotDeviceRunLogPageReqVO iotDeviceRunLogPageReqVO = new IotDeviceRunLogPageReqVO();
        iotDeviceRunLogPageReqVO.setCreateTime(createTime);
        iotDeviceRunLogPageReqVO.setDeptIds(new ArrayList<>(ids));
        iotDeviceRunLogPageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE);
        iotDeviceRunLogPageReqVO.setPointName("当日注气量");
        List<Map<String, Object>> fills = iotDeviceRunLogMapper.selectListByCreateTimeAndDeptList(iotDeviceRunLogPageReqVO).stream().map(e -> {
            Map<String, Object> abc = new HashMap<>();
            abc.put("id", e.getId());
            abc.put("createTime", e.getCreateTime());
            abc.put("total", e.getTotalRunTime());
            abc.put("today", e.getFillContent());
            return abc;
        }).collect(Collectors.toList());
        LinkedHashMap<String, Long> fillMap = sumTotalByDate(fills, 7,"today");
        LinkedList<Object> xAxis = new LinkedList<>();
        LinkedList<Object> fillData = new LinkedList<>();
        fillMap.forEach( (k,v)->{
            xAxis.add(k);
            fillData.add(v);
        });

//        iotDeviceRunLogPageReqVO.setPointName("当日注水量");
//        List<Map<String, Object>> waters = iotDeviceRunLogMapper.selectListByCreateTimeAndDeptList(iotDeviceRunLogPageReqVO).stream().map(e -> {
//            Map<String, Object> abc = new HashMap<>();
//            abc.put("id", e.getId());
//            abc.put("createTime", e.getCreateTime());
//            abc.put("total", e.getTotalRunTime());
//            abc.put("today", e.getFillContent());
//            return abc;
//        }).collect(Collectors.toList());
//        LinkedHashMap<String, Long> waterMap = sumTotalByDate(waters, 7,"today");
//        LinkedList<Object> waterxAxis = new LinkedList<>();
//        LinkedList<Object> waterData = new LinkedList<>();
//        waterMap.forEach( (k,v)->{
//            waterxAxis.add(k);
//            waterData.add(v);
//        });

        ImmutableMap<String, Serializable> fillResult = ImmutableMap.of("name", "当日注气量~~en**daily gas injection", "data", fillData);
//        ImmutableMap<String, Serializable> waterResult = ImmutableMap.of("name", "当日注水量~~en**daily water injection", "data", waterData);
        return success(ImmutableMap.of("xAxis", xAxis, "series", ImmutableList.of(fillResult)));

    }


    @GetMapping("/rh/zql/daily/{dept}")
    @PermitAll
    public CommonResult<Map<String, Object>> rhOrderDaily(@PathVariable("dept") String dept) {
        Set<Long> ids = getDeptIds(dept);
        List<String> originSevenDays = getLastSevenDays();
        List<String> lastSevenDays = originSevenDays.stream()
                .map(dateStr -> LocalDate.parse(dateStr))
                .map(day -> day.minusDays(1))
                .map(day -> day.format(DateTimeFormatter.ofPattern("yyyy-MM-dd")))
                .collect(Collectors.toList());
        // List<String> lastSevenDays = getLastSevenDays();
        String first = lastSevenDays.get(0);
        String last = lastSevenDays.get(lastSevenDays.size() - 1);
        LocalDateTime startOfDay = getStartOfDay(last);
        LocalDateTime endOfDay = getEndOfDay(first);
        LocalDateTime[] createTime = new LocalDateTime[]{startOfDay, endOfDay};

        IotRhDailyReportPageReqVO iotRhDailyReportPageReqVO = new IotRhDailyReportPageReqVO();
        iotRhDailyReportPageReqVO.setCreateTime(createTime);
        iotRhDailyReportPageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE);
        List<Map<String, Object>> fills = iotRhDailyReportMapper.selectPage(iotRhDailyReportPageReqVO).getList().stream().map(e -> {
            Map<String, Object> abc = new HashMap<>();
            abc.put("id", e.getId());
            abc.put("createTime", e.getCreateTime());
            abc.put("today", e.getDailyGasInjection());
            return abc;
        }).collect(Collectors.toList());
        LinkedHashMap<String, Double> fillMap = sumTotalByDates(fills, lastSevenDays,"today");
        LinkedList<Object> xAxis = new LinkedList<>();
        LinkedList<Object> fillData = new LinkedList<>();
        fillMap.forEach( (k,v)->{
            xAxis.add(k);
            fillData.add(v);
        });

//        iotDeviceRunLogPageReqVO.setPointName("当日注水量");
//        List<Map<String, Object>> waters = iotDeviceRunLogMapper.selectListByCreateTimeAndDeptList(iotDeviceRunLogPageReqVO).stream().map(e -> {
//            Map<String, Object> abc = new HashMap<>();
//            abc.put("id", e.getId());
//            abc.put("createTime", e.getCreateTime());
//            abc.put("total", e.getTotalRunTime());
//            abc.put("today", e.getFillContent());
//            return abc;
//        }).collect(Collectors.toList());
//        LinkedHashMap<String, Long> waterMap = sumTotalByDate(waters, 7,"today");
//        LinkedList<Object> waterxAxis = new LinkedList<>();
//        LinkedList<Object> waterData = new LinkedList<>();
//        waterMap.forEach( (k,v)->{
//            waterxAxis.add(k);
//            waterData.add(v);
//        });

        ImmutableMap<String, Serializable> fillResult = ImmutableMap.of("name", "当日注气量~~en**daily gas injection", "data", fillData);
//        ImmutableMap<String, Serializable> waterResult = ImmutableMap.of("name", "当日注水量~~en**daily water injection", "data", waterData);
        return success(ImmutableMap.of("xAxis", xAxis, "series", ImmutableList.of(fillResult)));

    }

    @Operation(summary = "近1周的设备利用率")
    @GetMapping("/rh/device/sevenDayUtilization")
    @PermitAll
    public CommonResult<Map<String, Object>> sevenDayUtilization() {
        List<String> originSevenDays = getLastSevenDays();
        List<String> lastSevenDays = originSevenDays.stream()
                .map(dateStr -> LocalDate.parse(dateStr))
                .map(day -> day.minusDays(1))
                .map(day -> day.format(DateTimeFormatter.ofPattern("yyyy-MM-dd")))
                .collect(Collectors.toList());
        String first = lastSevenDays.get(0);
        String last = lastSevenDays.get(lastSevenDays.size() - 1);
        LocalDateTime startOfDay = getStartOfDay(last);
        LocalDateTime endOfDay = getEndOfDay(first);
        LocalDateTime[] createTime = new LocalDateTime[]{startOfDay, endOfDay};

        IotRhDailyReportPageReqVO iotRhDailyReportPageReqVO = new IotRhDailyReportPageReqVO();
        iotRhDailyReportPageReqVO.setCreateTime(createTime);
        iotRhDailyReportPageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE);
        PageResult<IotRhDailyReportDO> pageReports = iotRhDailyReportMapper.selectPage(iotRhDailyReportPageReqVO);
        if (ObjUtil.isEmpty(pageReports)) {
            return buildEmptyResult(lastSevenDays);
        }
        List<IotRhDailyReportDO> reports = pageReports.getList();
        if (CollUtil.isEmpty(reports)) {
            return buildEmptyResult(lastSevenDays);
        }
        List<Map<String, Object>> fills = reports.stream().map(e -> {
            Map<String, Object> abc = new HashMap<>();
            abc.put("id", e.getId());
            abc.put("createTime", e.getCreateTime());
            abc.put("today", e.getDailyGasInjection());
            return abc;
        }).collect(Collectors.toList());

        // 计算最近7天公司整体的设备利用率
        // 筛选瑞恒 主设备 rq_iot_rh_main_device_category
        Set<Long> mainDeviceCategoryIds = new HashSet<>();
        List<DictDataDO> constructionStatusDictData = dictDataService.getDictDataListByDictType("rq_iot_rh_main_device_category");
        if (CollUtil.isNotEmpty(constructionStatusDictData)) {
            constructionStatusDictData.forEach(data -> {
                String value = data.getValue();
                if (NumberUtil.isNumber(value)) {
                    Long longValue = Long.valueOf(value);
                    mainDeviceCategoryIds.add(longValue);
                }
            });
        }
        Set<Long> allRhChildDeptIds = deptService.getChildDeptIdListFromCache(157l);
        // 包含设备的部门id集合
        Set<Long> haveDeviceDeptIds = new HashSet<>();
        IotDevicePageReqVO deviceReqVO = new IotDevicePageReqVO();
        deviceReqVO.setDeptIds(new ArrayList<>(allRhChildDeptIds));
        List<IotDeviceDO> devices = iotDeviceMapper.selectListAlone(deviceReqVO);
        if (CollUtil.isNotEmpty(devices)) {
            devices.forEach(device -> {
                // 20260605 筛选包含主设备的队伍
                if (mainDeviceCategoryIds.contains(device.getAssetClass())) {
                    haveDeviceDeptIds.add(device.getDeptId());
                }
            });
        }
        Map<Long, DeptDO> allDeptPair = deptService.getDeptMap(allRhChildDeptIds);
        Set<Long> teamIds = new HashSet<>();
        if (CollUtil.isNotEmpty(allDeptPair)) {
            allDeptPair.forEach((deptId, dept) -> {
                // 队伍
                if ("3".equals(dept.getType()) && haveDeviceDeptIds.contains(deptId)) {
                    teamIds.add(dept.getId());
                }
            });
        }
        // key日期2026-06-08   value日期对应的日报数量
        Map<String, Integer> dateReportCountPair = new HashMap<>();
        reports.forEach(report -> {
            // 按照日期维度统计各 工作量数据 累计用电量 累计油耗 累计注气量 累计注水量
            LocalDateTime reportLocalDate = report.getCreateTime();
            // 将日期格式转换成 字符串
            String reportDateStr = LocalDateTimeUtil.format(reportLocalDate, DatePattern.NORM_DATE_PATTERN);
            Long deptId = report.getDeptId();
            BigDecimal dailyGasInjection = report.getDailyGasInjection();
            BigDecimal dailyWaterInjection = report.getDailyWaterInjection();
            if (haveDeviceDeptIds.contains(deptId) && dailyGasInjection.compareTo(BigDecimal.ZERO)>0 || dailyWaterInjection.compareTo(BigDecimal.ZERO)>0) {
                if (dateReportCountPair.containsKey(reportDateStr)) {
                    Integer tempNum = dateReportCountPair.get(reportDateStr);
                    dateReportCountPair.put(reportDateStr, ++tempNum);
                } else {
                    dateReportCountPair.put(reportDateStr, 1);
                }
            }
        });
        // 计算每天的设备利用率
        Map<String, BigDecimal> dateReportUtilizationPair = new HashMap<>();
        if (CollUtil.isNotEmpty(dateReportCountPair)) {
            dateReportCountPair.forEach((reportDateStr, reportNum) -> {
                if (CollUtil.isNotEmpty(teamIds)) {
                    BigDecimal deviceUtilization = new BigDecimal((double) reportNum / (teamIds.size() * 1))
                            .setScale(4, RoundingMode.HALF_UP);
                    dateReportUtilizationPair.put(reportDateStr, deviceUtilization);
                }
            });
        }
        // 5. 按日期升序补全最近7天，缺失填0
        List<String> sortedDays = lastSevenDays.stream()
                .sorted()                                      // yyyy-MM-dd 字符串自然升序
                .collect(Collectors.toList());
        LinkedHashMap<String, BigDecimal> fillMap = new LinkedHashMap<>();
        sortedDays.forEach(day ->
                fillMap.put(day, dateReportUtilizationPair.getOrDefault(day, BigDecimal.ZERO))
        );

        LinkedList<Object> xAxis = new LinkedList<>(fillMap.keySet());
        LinkedList<Object> fillData = new LinkedList<>(fillMap.values());

        ImmutableMap<String, Serializable> fillResult = ImmutableMap.of("name", "设备利用率~~en**device utilization", "data", fillData);
        return success(ImmutableMap.of("xAxis", xAxis, "series", ImmutableList.of(fillResult)));

    }

    /**
     * 瑞恒 近6个月的设备利用率（包含当前月）
     */
    @Operation(summary = "瑞恒 近6个月的设备利用率")
    @GetMapping("/rh/device/sixMonthUtilization")
    @PermitAll
    public CommonResult<Map<String, Object>> rhSixMonthUtilization() {

        // 1. 获取最近6个月份（升序：最早月 ~ 当前月）
        List<String> lastSixMonths = getLastSixMonths();

        // 2. 获取瑞恒所有队伍ID（与 sevenDayUtilization 逻辑完全一致）
        Set<Long> mainDeviceCategoryIds = new HashSet<>();
        List<DictDataDO> constructionStatusDictData = dictDataService.getDictDataListByDictType("rq_iot_rh_main_device_category");
        if (CollUtil.isNotEmpty(constructionStatusDictData)) {
            constructionStatusDictData.forEach(data -> {
                String value = data.getValue();
                if (NumberUtil.isNumber(value)) {
                    mainDeviceCategoryIds.add(Long.valueOf(value));
                }
            });
        }

        Set<Long> allRhChildDeptIds = deptService.getChildDeptIdListFromCache(157L);
        Set<Long> haveDeviceDeptIds = new HashSet<>();
        IotDevicePageReqVO deviceReqVO = new IotDevicePageReqVO();
        deviceReqVO.setDeptIds(new ArrayList<>(allRhChildDeptIds));
        List<IotDeviceDO> devices = iotDeviceMapper.selectListAlone(deviceReqVO);
        if (CollUtil.isNotEmpty(devices)) {
            devices.forEach(device -> {
                if (mainDeviceCategoryIds.contains(device.getAssetClass())) {
                    haveDeviceDeptIds.add(device.getDeptId());
                }
            });
        }

        Map<Long, DeptDO> allDeptPair = deptService.getDeptMap(allRhChildDeptIds);
        Set<Long> teamIds = new HashSet<>();
        if (CollUtil.isNotEmpty(allDeptPair)) {
            allDeptPair.forEach((deptId, dept) -> {
                if ("3".equals(dept.getType()) && haveDeviceDeptIds.contains(deptId)) {
                    teamIds.add(dept.getId());
                }
            });
        }

        // 3. 按月统计设备利用率
        Map<String, BigDecimal> monthUtilizationMap = new LinkedHashMap<>(); // 保持月份顺序

        for (String month : lastSixMonths) {
            // 解析年月
            String[] parts = month.split("-");
            int year = Integer.parseInt(parts[0]);
            int monthValue = Integer.parseInt(parts[1]);
            YearMonth yearMonth = YearMonth.of(year, monthValue);

            // 当月起始时间
            LocalDateTime startOfMonth = yearMonth.atDay(1).atStartOfDay();
            LocalDateTime endOfMonth = yearMonth.atEndOfMonth().atTime(23, 59, 59);
            LocalDateTime[] createTime = new LocalDateTime[]{startOfMonth, endOfMonth};

            // 查询该月所有日报
            IotRhDailyReportPageReqVO pageReqVO = new IotRhDailyReportPageReqVO();
            pageReqVO.setCreateTime(createTime);
            pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE);
            PageResult<IotRhDailyReportDO> pageReports = iotRhDailyReportMapper.selectPage(pageReqVO);

            // 统计该月满足条件的日报数量
            int qualifiedCount = 0;
            if (ObjUtil.isNotEmpty(pageReports) && CollUtil.isNotEmpty(pageReports.getList())) {
                List<IotRhDailyReportDO> reports = pageReports.getList();
                for (IotRhDailyReportDO report : reports) {
                    Long deptId = report.getDeptId();
                    BigDecimal dailyGasInjection = report.getDailyGasInjection() != null ? report.getDailyGasInjection() : BigDecimal.ZERO;
                    BigDecimal dailyWaterInjection = report.getDailyWaterInjection() != null ? report.getDailyWaterInjection() : BigDecimal.ZERO;
                    if (haveDeviceDeptIds.contains(deptId) &&
                            (dailyGasInjection.compareTo(BigDecimal.ZERO) > 0 || dailyWaterInjection.compareTo(BigDecimal.ZERO) > 0)) {
                        qualifiedCount++;
                    }
                }
            }

            // 计算月利用率：分子=合格日报数，分母=队伍数 × 当月天数
            BigDecimal utilization = BigDecimal.ZERO;
            if (CollUtil.isNotEmpty(teamIds)) {
                int daysInMonth = yearMonth.lengthOfMonth();
                long denominator = (long) teamIds.size() * daysInMonth;
                if (denominator > 0) {
                    utilization = BigDecimal.valueOf(qualifiedCount)
                            .divide(BigDecimal.valueOf(denominator), 4, RoundingMode.HALF_UP);
                }
            }
            monthUtilizationMap.put(month, utilization);
        }

        // 4. 构建返回结果（与 sevenDayUtilization 结构完全一致）
        LinkedList<Object> xAxis = new LinkedList<>(monthUtilizationMap.keySet());
        LinkedList<Object> data = new LinkedList<>(monthUtilizationMap.values());

        ImmutableMap<String, Serializable> series = ImmutableMap.of(
                "name", "设备利用率~~en**device utilization",
                "data", data
        );

        return success(ImmutableMap.of(
                "xAxis", xAxis,
                "series", ImmutableList.of(series)
        ));
    }

    @Operation(summary = "瑞都 近1周的设备利用率")
    @GetMapping("/rd/device/sevenDayUtilization")
    @PermitAll
    public CommonResult<Map<String, Object>> rdSevenDayUtilization() {

        List<String> lastSevenDays = getLastSevenDays();
        String first = lastSevenDays.get(0);
        String last = lastSevenDays.get(lastSevenDays.size() - 1);
        LocalDateTime startOfDay = getStartOfDay(last);
        LocalDateTime endOfDay = getEndOfDay(first);
        LocalDateTime[] createTime = new LocalDateTime[]{startOfDay, endOfDay};

        IotRdDailyReportPageReqVO iotRdDailyReportPageReqVO = new IotRdDailyReportPageReqVO();
        iotRdDailyReportPageReqVO.setCreateTime(createTime);
        iotRdDailyReportPageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE);
        PageResult<IotRdDailyReportDO> pageReports = iotRdDailyReportMapper.selectPage(iotRdDailyReportPageReqVO);
        if (ObjUtil.isEmpty(pageReports)) {
            return buildEmptyResult(lastSevenDays);
        }
        List<IotRdDailyReportDO> reports = pageReports.getList();
        if (CollUtil.isEmpty(reports)) {
            return buildEmptyResult(lastSevenDays);
        }

        // 计算最近7天公司整体的设备利用率
        Set<Long> allRhChildDeptIds = deptService.getChildDeptIdListFromCache(163l);

        // 设备利用率逻辑调整 只筛选 压裂 连油 主设备 rq_iot_device_associate
        // 队伍日报中关联的主设备数量 /（队伍下所有主设备数量-封存设备数量）
        Set<Long> mainDeviceIds = new HashSet<>();
        Set<Long> fcMainDeviceIds = new HashSet<>();
        // key设备id   value设备所属部门id
        Map<Long, Long> mainDeviceIdPair = new HashMap<>();
        IotDeviceAssociatePageReqVO deviceAssocReqVO = new IotDeviceAssociatePageReqVO();
        deviceAssocReqVO.setPageSize(PageParam.PAGE_SIZE_NONE);
        deviceAssocReqVO.setDeptIds(allRhChildDeptIds);
        PageResult<IotDeviceAssociateDO> pageResult = iotDeviceAssociateMapper.selectPage(deviceAssocReqVO);
        if (ObjUtil.isNotEmpty(pageResult)) {
            List<IotDeviceAssociateDO> deviceAssociates = pageResult.getList();
            // 查询出所有瑞都压裂 连油主设备
            deviceAssociates.forEach(assoc -> {
                mainDeviceIds.add(assoc.getDeviceId());
                mainDeviceIdPair.put(assoc.getDeviceId(), assoc.getDeptId());
            });
        }
        // 所有压裂连油主设备
        Set<Long> abDeviceIds = new HashSet<>();
        // 查询瑞都 压裂 连油 主设备详情信息
        IotDevicePageReqVO deviceReqVO = new IotDevicePageReqVO();
        deviceReqVO.setDeviceIds(new ArrayList<>(mainDeviceIds));
        List<IotDeviceDO> mainDevices = iotDeviceMapper.selectListAlone(deviceReqVO);
        // 筛选出 封存 的主设备
        if (CollUtil.isNotEmpty(mainDevices)) {
            mainDevices.forEach(device -> {
                /* if ("fc".equals(device.getDeviceStatus())) {
                    fcMainDeviceIds.add(device.getId());
                } else { */
                    abDeviceIds.add(device.getId());
                // }
            });
        }

        // key日期2026-06-08   value日期对应的日报数量
        Map<String, Set<Long>> dateReportDeviceIdPair = new HashMap<>();
        reports.forEach(report -> {
            // 按照日期维度统计各 工作量数据 累计用电量 累计油耗 累计注气量 累计注水量
            LocalDateTime reportLocalDate = report.getCreateTime();
            // 将日期格式转换成 字符串
            String reportDateStr = LocalDateTimeUtil.format(reportLocalDate, DatePattern.NORM_DATE_PATTERN);
            // 统计日报关联施工AB类设备的利用率
            Set<Long> reportDeviceIds = report.getDeviceIds();
            if (CollUtil.isNotEmpty(reportDeviceIds)) {
                if (dateReportDeviceIdPair.containsKey(reportDateStr)) {
                    Set<Long> tempDeviceIds = dateReportDeviceIdPair.get(reportDateStr);
                    tempDeviceIds.addAll(reportDeviceIds);
                    dateReportDeviceIdPair.put(reportDateStr, tempDeviceIds);
                } else {
                    dateReportDeviceIdPair.put(reportDateStr, reportDeviceIds);
                }
            }
        });
        // 计算每天的设备利用率
        Map<String, BigDecimal> dateReportUtilizationPair = new HashMap<>();
        if (CollUtil.isNotEmpty(dateReportDeviceIdPair)) {
            dateReportDeviceIdPair.forEach((reportDateStr, deviceIds) -> {
                // 计算每天的所有日报涉及到的压裂连油主设备
                // 1. 求交集：实际使用的A B类设备
                Set<Long> utilizedDeviceIds = deviceIds.stream()
                        .filter(abDeviceIds::contains)
                        .collect(Collectors.toSet());
                if (CollUtil.isNotEmpty(abDeviceIds)) {
                    BigDecimal deviceUtilization = new BigDecimal((double) utilizedDeviceIds.size() / abDeviceIds.size())
                            .setScale(4, RoundingMode.HALF_UP);
                    dateReportUtilizationPair.put(reportDateStr, deviceUtilization);
                }
            });
        }
        // 5. 按日期升序补全最近7天，缺失填0
        List<String> sortedDays = lastSevenDays.stream()
                .sorted()                                      // yyyy-MM-dd 字符串自然升序
                .collect(Collectors.toList());
        LinkedHashMap<String, BigDecimal> fillMap = new LinkedHashMap<>();
        sortedDays.forEach(day ->
                fillMap.put(day, dateReportUtilizationPair.getOrDefault(day, BigDecimal.ZERO))
        );

        LinkedList<Object> xAxis = new LinkedList<>(fillMap.keySet());
        LinkedList<Object> fillData = new LinkedList<>(fillMap.values());

        ImmutableMap<String, Serializable> fillResult = ImmutableMap.of("name", "设备利用率~~en**device utilization", "data", fillData);
        return success(ImmutableMap.of("xAxis", xAxis, "series", ImmutableList.of(fillResult)));

    }

    /**
     * 获取最近6个月（包括当前月）的月份列表，按时间升序排列
     * 例如当前为 2026-07，则返回 ["2026-02", "2026-03", "2026-04", "2026-05", "2026-06", "2026-07"]
     */
    private List<String> getLastSixMonths() {
        List<String> months = new ArrayList<>();
        LocalDate now = LocalDate.now();
        for (int i = 5; i >= 0; i--) {
            LocalDate monthDate = now.minusMonths(i);
            String monthStr = monthDate.format(DateTimeFormatter.ofPattern("yyyy-MM"));
            months.add(monthStr);
        }
        return months;
    }

    /**
     * 瑞都 近6个月的设备利用率（包含当前月）
     */
    @Operation(summary = "瑞都 近6个月的设备利用率")
    @GetMapping("/rd/device/sixMonthUtilization")
    @PermitAll
    public CommonResult<Map<String, Object>> rdSixMonthUtilization() {

        // 1. 获取最近6个月份（升序，从最早到当前月）
        List<String> lastSixMonths = getLastSixMonths(); // 实现见下方

        // 2. 获取所有非封存的压裂/连油主设备（AB类设备）
        Set<Long> allRhChildDeptIds = deptService.getChildDeptIdListFromCache(163L);
        Set<Long> mainDeviceIds = new HashSet<>();
        IotDeviceAssociatePageReqVO deviceAssocReqVO = new IotDeviceAssociatePageReqVO();
        deviceAssocReqVO.setPageSize(PageParam.PAGE_SIZE_NONE);
        deviceAssocReqVO.setDeptIds(allRhChildDeptIds);
        PageResult<IotDeviceAssociateDO> pageResult = iotDeviceAssociateMapper.selectPage(deviceAssocReqVO);
        if (ObjUtil.isNotEmpty(pageResult) && CollUtil.isNotEmpty(pageResult.getList())) {
            pageResult.getList().forEach(assoc -> mainDeviceIds.add(assoc.getDeviceId()));
        }

        Set<Long> abDeviceIds = new HashSet<>();
        if (CollUtil.isNotEmpty(mainDeviceIds)) {
            IotDevicePageReqVO deviceReqVO = new IotDevicePageReqVO();
            deviceReqVO.setDeviceIds(new ArrayList<>(mainDeviceIds));
            List<IotDeviceDO> mainDevices = iotDeviceMapper.selectListAlone(deviceReqVO);
            if (CollUtil.isNotEmpty(mainDevices)) {
                mainDevices.forEach(device -> {
                    // 过滤掉封存设备（"fc"）
                    // if (!"fc".equals(device.getDeviceStatus())) {
                        abDeviceIds.add(device.getId());
                    // }
                });
            }
        }

        // 3. 按月统计设备利用率
        Map<String, BigDecimal> monthUtilizationMap = new LinkedHashMap<>(); // 保持顺序

        for (String month : lastSixMonths) {
            // 解析年月
            String[] parts = month.split("-");
            int year = Integer.parseInt(parts[0]);
            int monthValue = Integer.parseInt(parts[1]);
            YearMonth yearMonth = YearMonth.of(year, monthValue);

            // 当月第一天 00:00:00 和最后一天 23:59:59
            LocalDate firstDay = yearMonth.atDay(1);
            LocalDate lastDay = yearMonth.atEndOfMonth();
            LocalDateTime startOfMonth = firstDay.atStartOfDay();
            LocalDateTime endOfMonth = lastDay.atTime(23, 59, 59);
            LocalDateTime[] createTime = new LocalDateTime[]{startOfMonth, endOfMonth};

            // 查询该月所有日报
            IotRdDailyReportPageReqVO pageReqVO = new IotRdDailyReportPageReqVO();
            pageReqVO.setCreateTime(createTime);
            pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE);
            PageResult<IotRdDailyReportDO> pageReports = iotRdDailyReportMapper.selectPage(pageReqVO);

            // 收集该月所有日报中出现的AB设备ID（不去重，累加次数）
            List<Long> monthReportMainDeviceIds = new ArrayList<>();
            if (ObjUtil.isNotEmpty(pageReports) && CollUtil.isNotEmpty(pageReports.getList())) {
                List<IotRdDailyReportDO> reports = pageReports.getList();
                for (IotRdDailyReportDO report : reports) {
                    Set<Long> deviceIds = report.getDeviceIds();
                    if (CollUtil.isNotEmpty(deviceIds)) {
                        // 只保留AB类设备
                        deviceIds.stream()
                                .filter(abDeviceIds::contains)
                                .forEach(monthReportMainDeviceIds::add);
                    }
                }
            }

            // 计算当月设备利用率：分子=当月所有日报中AB设备出现总次数，分母=AB设备总数 × 当月天数
            BigDecimal utilization = BigDecimal.ZERO;
            if (CollUtil.isNotEmpty(abDeviceIds)) {
                int daysInMonth = yearMonth.lengthOfMonth();
                long denominator = (long) abDeviceIds.size() * daysInMonth;
                if (denominator > 0) {
                    utilization = BigDecimal.valueOf(monthReportMainDeviceIds.size())
                            .divide(BigDecimal.valueOf(denominator), 4, RoundingMode.HALF_UP);
                }
            }
            monthUtilizationMap.put(month, utilization);
        }

        // 4. 构建返回数据（与 rdSevenDayUtilization 结构一致）
        LinkedList<Object> xAxis = new LinkedList<>(monthUtilizationMap.keySet());
        LinkedList<Object> data = new LinkedList<>(monthUtilizationMap.values());

        ImmutableMap<String, Serializable> series = ImmutableMap.of(
                "name", "设备利用率~~en**device utilization",
                "data", data
        );

        return success(ImmutableMap.of(
                "xAxis", xAxis,
                "series", ImmutableList.of(series)
        ));
    }

    /**
     * 无日报时直接返回全0序列
     */
    private CommonResult<Map<String, Object>> buildEmptyResult(List<String> lastSevenDays) {
        List<String> sortedDays = lastSevenDays.stream().sorted().collect(Collectors.toList());
        LinkedList<Object> xAxis = new LinkedList<>(sortedDays);
        LinkedList<Object> fillData = sortedDays.stream()
                .map(d -> BigDecimal.ZERO)
                .collect(Collectors.toCollection(LinkedList::new));
        ImmutableMap<String, Serializable> fillResult = ImmutableMap.of(
                "name", "设备利用率~~en**device utilization",
                "data", fillData
        );
        return success(ImmutableMap.of("xAxis", xAxis, "series", ImmutableList.of(fillResult)));
    }

    @Operation(summary = "瑞恒当日注气量 累计注气量")
    @GetMapping("/rh/zql")
    @PermitAll
    public CommonResult<BigDecimal> dailyZql(IotRhDailyReportPageReqVO reqVO) {
        BigDecimal result = BigDecimal.ZERO;
        if (ObjUtil.isEmpty(reqVO)) {
            return success(result);
        }
        reqVO.setPageSize(PageParam.PAGE_SIZE_NONE);
        PageResult<IotRhDailyReportDO> pageReports = iotRhDailyReportMapper.selectPage(reqVO);
        if (ObjUtil.isEmpty(pageReports)) {
            return success(result);
        }
        List<IotRhDailyReportDO> reports = pageReports.getList();
        if (CollUtil.isEmpty(reports)) {
            return success(result);
        }
        for (IotRhDailyReportDO report : reports) {
            BigDecimal tempGasInjection = report.getDailyGasInjection();
            result = result.add(tempGasInjection);
        }
        // 注气量单位设置成 万方
        BigDecimal convertedGasInjection = result.divide(BigDecimal.valueOf(10000), 2, RoundingMode.HALF_UP);
        return success(convertedGasInjection);
    }

    @PermitAll
    @GetMapping("/project/{dept}")
    public CommonResult<List<ImmutableMap<String, ? extends Serializable>>> projectStat(@PathVariable("dept") String dept) {
        List<DeptRespDTO> deptByName = deptApi.getDeptByName("瑞鹰国际");
        if (CollUtil.isEmpty(deptByName)) {
            throw new ServiceException(new ErrorCode(122, "没有部门"));
        }
        List<DeptRespDTO> childDeptList = deptApi.getChildDeptList(deptByName.get(0).getId());
        List<DeptRespDTO> projects = childDeptList.stream().filter(e -> deptByName.get(0).getId().equals(e.getParentId())).collect(Collectors.toList());
        List<ImmutableMap<String, ? extends Serializable>> result = projects.stream().map(e -> {
            List<DeptRespDTO> allSubclasses = findAllSubclasses(childDeptList, e.getId());
            Set<Long> collect = allSubclasses.stream().map(DeptRespDTO::getId).collect(Collectors.toSet());
            collect.add(e.getId());
            Long l = iotDeviceMapper.selectByDept(collect);
            return ImmutableMap.of("name", e.getName(), "value", l);
        }).collect(Collectors.toList());
        return success(result);
    }


    private List<DeptRespDTO> findAllSubclasses(List<DeptRespDTO> allNodes, Long parentId) {
        List<DeptRespDTO> result = new ArrayList<>();

        // 先找到直接子节点
        for (DeptRespDTO node : allNodes) {
            if (parentId.equals(node.getParentId())) {
                result.add(node);
                // 递归查找子节点的子节点，并添加到结果中
                result.addAll(findAllSubclasses(allNodes, node.getId()));
            }
        }
        return result;
    }

    @PermitAll
    @GetMapping("/mttr")
    public CommonResult<String> getMttr() {
        List<IotFailureReportDO> failureReportDOS = iotFailureReportMapper.selectList();
        List<IotFailureReportDO> collect = failureReportDOS.stream().filter(e -> Objects.nonNull(e.getDealHour())&&(e.getDealHour().compareTo(BigDecimal.ZERO) > 0)).collect(Collectors.toList());
        if (CollUtil.isEmpty(collect)) {
            return success("0");
        } else {
            int size = collect.size();
            double sum = collect.stream().mapToDouble(re -> re.getDealHour().doubleValue()).sum();
            Double result = sum/size;
            DecimalFormat df = new DecimalFormat("#.0");
            String formattedResult = df.format(result);
            return success(formattedResult);
        }
    }


    @PermitAll
    @GetMapping("/year/total/gas/{dept}")
    public CommonResult<ImmutableMap> getYearTotalGas(@PathVariable("dept") String dept) {
        Set<Long> ids = getDeptIds(dept);
        //获取近一年的月份
        List<String> lastYearMonthRanges = getLastYearMonthRanges().stream().map(MonthRange::getYearMonth).collect(Collectors.toList());
        IotDeviceRunLogPageReqVO iotDeviceRunLogPageReqVO = new IotDeviceRunLogPageReqVO();
        iotDeviceRunLogPageReqVO.setDeptIds(new ArrayList<>(ids));
        iotDeviceRunLogPageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE);
        iotDeviceRunLogPageReqVO.setPointName("当日注气量");
        List<YearTotalGas> yearTotalGases = iotDeviceRunLogMapper.selectYearTotalGas(iotDeviceRunLogPageReqVO);
        LinkedList<String> result = new LinkedList<>();
        lastYearMonthRanges.forEach(lastYearMonthRange -> {
            YearTotalGas yearTotalGas = yearTotalGases.stream().filter(e -> e.getMonth().equals(lastYearMonthRange)).findAny().orElse(null);
            if (Objects.isNull(yearTotalGas)) {
                result.add("0");
            } else {
                result.add(NumberUtils.formatNumber(yearTotalGas.getTotalGas()));
            }
        });
        ImmutableMap<String, Serializable> fillResult = ImmutableMap.of("name", "累计注气量~~en**cumulative gas injection", "data", result);
        return success(ImmutableMap.of("xAxis", lastYearMonthRanges, "series", ImmutableList.of(fillResult)));

    }

    @PermitAll
    @GetMapping("/year/total/gases/{dept}")
    public CommonResult<ImmutableMap> getYearTotalGases(@PathVariable("dept") String dept) {
        Set<Long> ids = getDeptIds(dept);
        //获取近一年的月份
        List<String> lastYearMonthRanges = getLastYearMonthRanges().stream().map(MonthRange::getYearMonth).collect(Collectors.toList());
        IotRhDailyReportPageReqVO iotRhDailyReportPageReqVO = new IotRhDailyReportPageReqVO();
//        iotRhDailyReportPageReqVO.setDeptIds(new ArrayList<>(ids));
        iotRhDailyReportPageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE);
        List<YearTotalGas> yearTotalGases = iotRhDailyReportMapper.selectYearTotalGas(iotRhDailyReportPageReqVO);
        LinkedList<String> result = new LinkedList<>();
        lastYearMonthRanges.forEach(lastYearMonthRange -> {
            YearTotalGas yearTotalGas = yearTotalGases.stream().filter(e -> e.getMonth().equals(lastYearMonthRange)).findAny().orElse(null);
            if (Objects.isNull(yearTotalGas)) {
                result.add("0");
            } else {
                result.add(NumberUtils.formatNumber(yearTotalGas.getTotalGas()));
            }
        });
        ImmutableMap<String, Serializable> fillResult = ImmutableMap.of("name", "累计注气量~~en**cumulative gas injection", "data", result);
        return success(ImmutableMap.of("xAxis", lastYearMonthRanges, "series", ImmutableList.of(fillResult)));

    }

    @Operation(summary = "瑞都 近6个月的维修 保养次数")
    @PermitAll
    @GetMapping("/recent/wbcs/{dept}")
    public CommonResult<ImmutableMap> recentWbNum(@PathVariable("dept") String dept) {
        Set<Long> ids = getDeptIds(dept);
        // 获取近半年的月份
        List<String> lastYearMonthRanges = getRecentSixMonthRanges().stream().map(MonthRange::getYearMonth).collect(Collectors.toList());
        // 查询保养次数
        IotMainWorkOrderPageReqVO workOrderReqVO = new IotMainWorkOrderPageReqVO();
        workOrderReqVO.setDeptIds(ids);
        List<IotMainWorkOrderDO> workOrders = iotMainWorkOrderService.workOrders(workOrderReqVO);
        Map<String, Integer> workOrderPair = new HashMap<>();
        // key年月   value维修工单数量
        Map<String, Integer> mainOrderPair = new HashMap<>();
        if (CollUtil.isNotEmpty(workOrders)) {
            workOrders.forEach(order -> {
                LocalDateTime orderDate = order.getCreateTime();
                String yearMonth = LocalDateTimeUtil.format(orderDate, DatePattern.NORM_MONTH_PATTERN);
                if (workOrderPair.containsKey(yearMonth)) {
                    Integer tempNum = workOrderPair.get(yearMonth);
                    workOrderPair.put(yearMonth, ++tempNum);
                } else {
                    workOrderPair.put(yearMonth, 1);
                }
            });
        }
        // 查询维修工单数量
        IotMaintainPageReqVO maintainReqVO = new IotMaintainPageReqVO();
        maintainReqVO.setDeptId(163l);
        maintainReqVO.setPageSize(PageParam.PAGE_SIZE_NONE);
        PageResult<IotMaintainDO> pageMaintains = iotMaintainService.getIotMaintainPage(maintainReqVO);
        if (ObjUtil.isNotEmpty(pageMaintains)) {
            List<IotMaintainDO> maintains = pageMaintains.getList();
            if (CollUtil.isNotEmpty(maintains)) {
                maintains.forEach(maintain -> {
                    LocalDateTime orderDate = maintain.getCreateTime();
                    String yearMonth = LocalDateTimeUtil.format(orderDate, DatePattern.NORM_MONTH_PATTERN);
                    if (mainOrderPair.containsKey(yearMonth)) {
                        Integer tempNum = mainOrderPair.get(yearMonth);
                        mainOrderPair.put(yearMonth, ++tempNum);
                    } else {
                        mainOrderPair.put(yearMonth, 1);
                    }
                });
            }
        }
        // 保养工单
        List<OrderCount> orderCounts = new ArrayList<>();
        if (CollUtil.isNotEmpty(workOrderPair)) {
            workOrderPair.forEach((yearMonth, num) -> {
                OrderCount tempCount = new OrderCount();
                tempCount.setMonth(yearMonth);
                tempCount.setOrderNum(String.valueOf(num));
                orderCounts.add(tempCount);
            });
        }
        // 维修工单
        List<OrderCount> mainCounts = new ArrayList<>();
        if (CollUtil.isNotEmpty(mainOrderPair)) {
            mainOrderPair.forEach((yearMonth, num) -> {
                OrderCount tempCount = new OrderCount();
                tempCount.setMonth(yearMonth);
                tempCount.setOrderNum(String.valueOf(num));
                mainCounts.add(tempCount);
            });
        }

        // IotRhDailyReportPageReqVO iotRhDailyReportPageReqVO = new IotRhDailyReportPageReqVO();
        // iotRhDailyReportPageReqVO.setDeptIds(new ArrayList<>(ids));
        // iotRhDailyReportPageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE);
        // List<YearTotalGas> yearTotalGases = iotRhDailyReportMapper.selectYearTotalGas(iotRhDailyReportPageReqVO);
        LinkedList<String> result = new LinkedList<>();
        // 维修工单
        LinkedList<String> mainResult = new LinkedList<>();
        lastYearMonthRanges.forEach(lastYearMonthRange -> {
            // 保养工单
            OrderCount orderCount = orderCounts.stream().filter(e -> lastYearMonthRange.equals(e.getMonth())).findAny().orElse(null);
            if (Objects.isNull(orderCount)) {
                result.add("0");
            } else {
                result.add(NumberUtils.formatNumber(orderCount.getOrderNum()));
            }
            // 维修工单
            OrderCount mainCount = mainCounts.stream().filter(e -> lastYearMonthRange.equals(e.getMonth())).findAny().orElse(null);
            if (Objects.isNull(mainCount)) {
                mainResult.add("0");
            } else {
                mainResult.add(NumberUtils.formatNumber(mainCount.getOrderNum()));
            }
        });
        ImmutableMap<String, Serializable> fillResult = ImmutableMap.of("name", "保养次数~~en**maintenance count", "data", result);
        ImmutableMap<String, Serializable> mainFillResult = ImmutableMap.of("name", "维修次数~~en**maintenance count", "data", mainResult);
        return success(ImmutableMap.of("xAxis", lastYearMonthRanges, "series", ImmutableList.of(fillResult, mainFillResult)));

    }

    @GetMapping("/number")
    @Operation(summary = "获取巡检计划数量")
    @PermitAll
    public CommonResult<ImmutableMap> getPlanDeviceNumber() {
        Set<Long> rhids = getDeptIds("rh");
        Set<Long> rdids = getDeptIds("rd");
        Set<Long> ryids = getDeptIds("ry");
        IotInspectPlanPageReqVO rh = new IotInspectPlanPageReqVO();
        rh.setPageSize(PageParam.PAGE_SIZE_NONE);
        List<IotInspectPlanDO> rhplans = iotInspectPlanMapper.selectPage(rh, rhids).getList().stream().filter(e -> !e.getDeleted()).collect(Collectors.toList());
        List<IotInspectPlanDO> rdplans = iotInspectPlanMapper.selectPage(rh, rdids).getList().stream().filter(e -> !e.getDeleted()).collect(Collectors.toList());
        List<IotInspectPlanDO> ryplans = iotInspectPlanMapper.selectPage(rh, ryids).getList().stream().filter(e -> !e.getDeleted()).collect(Collectors.toList());

        AtomicInteger rhcount = new AtomicInteger();
        rhplans.forEach(e ->{
            JSONArray objects = JSON.parseArray(e.getDeviceIds());
            int size = objects.size();
            rhcount.set(rhcount.get() + size);
        });

        AtomicInteger rdcount = new AtomicInteger();
        rdplans.forEach(e ->{
            JSONArray objects = JSON.parseArray(e.getDeviceIds());
            int size = objects.size();
            rdcount.set(rdcount.get() + size);
        });

        AtomicInteger rycount = new AtomicInteger();
        ryplans.forEach(e ->{
            JSONArray objects = JSON.parseArray(e.getDeviceIds());
            int size = objects.size();
            rycount.set(rycount.get() + size);
        });

        return success(ImmutableMap.of("瑞恒", rhcount.get(),"瑞都",rdcount.get(),"瑞鹰",rycount.get()));
    }

    /**
     * 统计 瑞鹰 158 的 钻井 修井工作量
     * @param type drill钻井  repair修井
     * @return
     */
    @GetMapping("/ry/dailyReport/{type}")
    @PermitAll
    public CommonResult<Map<String, Object>> getRyDailyReportStat(@PathVariable("type") String type) {
        if (StrUtil.isBlank(type)) {
            return success(new HashMap<>());
        }
        // 查询瑞鹰所有 队伍 项目部
        Set<Long> rdChildDeptIds = deptService.getChildDeptIdListFromCache(158l);
        List<DeptDO> depts =deptService.getDeptList(rdChildDeptIds);
        // key队伍id      value队伍所属项目部id      包含队伍的项目部
        Map<Long, Long> teamProjectPair = new HashMap<>();
        // 项目部id集合
        Set<Long> projectDeptIds = new HashSet<>();
        // key项目部id     value项目部名称
        Map<Long, String> projectDeptPair = new HashMap<>();

        IotDeptTypePageReqVO deptTypeReqVO = new IotDeptTypePageReqVO();
        // 查询 钻井 修井 类型的部门
        if ("repair".equals(type)) {
            // 修井
            deptTypeReqVO.setType("xj");
        } else {
            // 钻井
            deptTypeReqVO.setType("zj");
        }
        // 找到钻井队伍对应的项目部 修井队伍对应的项目部
        Set<Long> zjDeptIds = new HashSet<>();
        Set<Long> xjDeptIds = new HashSet<>();
        Set<String> xjDeptNames = new HashSet<>();
        Set<String> zjDeptNames = new HashSet<>();
        List<IotDeptTypeDO> deptTypes = iotDeptTypeMapper.selectList(deptTypeReqVO);
        List<Long> zjOrXjDeptIds = new ArrayList<>();
        if (CollUtil.isNotEmpty(deptTypes)) {
            deptTypes.forEach(dept -> {
                zjOrXjDeptIds.add(dept.getDeptId());
                if ("zj".equals(dept.getType())) {
                    zjDeptIds.add(dept.getDeptId());
                }
                if ("xj".equals(dept.getType())) {
                    xjDeptIds.add(dept.getDeptId());
                }
            });
        }

        if (CollUtil.isNotEmpty(depts)) {
            depts.forEach(dept -> {
                // 类型(公司级1 项目部2 队伍3)
                if ("2".equals(dept.getType())) {
                    projectDeptIds.add(dept.getId());
                    projectDeptPair.put(dept.getId(), dept.getName());
                }
                if ("3".equals(dept.getType()) && zjOrXjDeptIds.contains(dept.getId())) {
                    teamProjectPair.put(dept.getId(), dept.getParentId());
                }
            });
            // 筛选出所有钻井项目部
            teamProjectPair.forEach((teamDeptId, projectDeptId) -> {
                if (zjDeptIds.contains(teamDeptId)) {
                    // 钻井部门
                    if (projectDeptPair.containsKey(projectDeptId)) {
                        zjDeptNames.add(projectDeptPair.get(projectDeptId));
                    }
                }
                if (xjDeptIds.contains(teamDeptId)) {
                    // 修井部门
                    if (projectDeptPair.containsKey(projectDeptId)) {
                        xjDeptNames.add(projectDeptPair.get(projectDeptId));
                    }
                }
            });
            // 筛选出所有修井项目部
        }
        IotRyDailyReportPageReqVO reqVO = new IotRyDailyReportPageReqVO();
        List<IotRyDailyReportTaskCountVO> repairTaskCounts = new ArrayList<>();
        if ("repair".equals(type)) {
            // 修井
            reqVO.setProjectClassification("2");
            // 修井日报统计 月完井数 年完井数
            List<IotRyDailyReportTaskCountVO> repairReports = iotRyDailyReportService.countDateRepairTasksByDept();
            Map<String, Integer> projectDeptMonthCountPair = new HashMap<>();
            Map<String, Integer> projectDeptYearCountPair = new HashMap<>();
            // 遍历 集合 repairReports 找到队伍对应的项目部
            if (CollUtil.isNotEmpty(repairReports)) {
                repairReports.forEach(report -> {
                    if (teamProjectPair.containsKey(report.getDeptId())) {
                        Long projectDeptId = teamProjectPair.get(report.getDeptId());
                        if (projectDeptPair.containsKey(projectDeptId)) {
                            // 项目部id 对应的项目部名称
                            String projectDeptName = projectDeptPair.get(projectDeptId);
                            // 设置月完井数
                            if (projectDeptMonthCountPair.containsKey(projectDeptName)) {
                                Integer tempCount = projectDeptMonthCountPair.get(projectDeptName);
                                Integer monthCompletedTaskCount = report.getMonthCompletedTaskCount();
                                projectDeptMonthCountPair.put(projectDeptName, tempCount+monthCompletedTaskCount);
                            } else {
                                Integer monthCompletedTaskCount = report.getMonthCompletedTaskCount();
                                projectDeptMonthCountPair.put(projectDeptName, monthCompletedTaskCount);
                            }
                            // 设置年完井数
                            if (projectDeptYearCountPair.containsKey(projectDeptName)) {
                                Integer tempCount = projectDeptYearCountPair.get(projectDeptName);
                                Integer yearCompletedTaskCount = report.getYearCompletedTaskCount();
                                projectDeptYearCountPair.put(projectDeptName, tempCount+yearCompletedTaskCount);
                            } else {
                                Integer yearCompletedTaskCount = report.getYearCompletedTaskCount();
                                projectDeptYearCountPair.put(projectDeptName, yearCompletedTaskCount);
                            }
                        }
                    }
                });
            }
            // 遍历所有项目部 没有产生运行数据的项目部 赋值 0
            // 钻井 时 只显示 钻井相关的项目部
            // 查询修井数据时，只显示修井相关的项目部
            projectDeptPair.forEach((projectDeptId, projectDeptName) -> {
                if (!projectDeptMonthCountPair.containsKey(projectDeptName)) {
                    projectDeptMonthCountPair.put(projectDeptName, 0);
                }
                if (!projectDeptYearCountPair.containsKey(projectDeptName)) {
                    projectDeptYearCountPair.put(projectDeptName, 0);
                }
            });

            LinkedList<Object> xAxis = new LinkedList<>();
            LinkedList<Object> monthData = new LinkedList<>();
            LinkedList<Object> yearData = new LinkedList<>();

            projectDeptMonthCountPair.forEach( (k,v)->{
                if (xjDeptNames.contains(k)) {
                    xAxis.add(k);
                    monthData.add(v);
                    if (projectDeptYearCountPair.containsKey(k)) {
                        Integer yearCount = projectDeptYearCountPair.get(k);
                        yearData.add(yearCount);
                    }
                }
            });
            ImmutableMap<String, Serializable> monthResult = ImmutableMap.of("name", "月完井数~~en**monthWell", "data", monthData);
            ImmutableMap<String, Serializable> yearResult = ImmutableMap.of("name", "年完井数~~en**YearWell", "data", yearData);
            return success(ImmutableMap.of("xAxis", xAxis, "series", ImmutableList.of(monthResult, yearResult)));
        } else {
            // 钻井
            reqVO.setProjectClassification("1");
            // 查询钻井的日报统计 日进尺 月累计进尺 年累计进尺
            List<IotRyDailyReportTaskCountVO> repairReports = iotRyDailyReportService.countDateDrillTasksByDept();
            Map<String, BigDecimal> projectDeptDailyFootagePair = new HashMap<>();
            Map<String, BigDecimal> projectDeptMonthFootagePair = new HashMap<>();
            Map<String, BigDecimal> projectDeptYearFootagePair = new HashMap<>();
            if (CollUtil.isNotEmpty(repairReports)) {
                repairReports.forEach(report -> {
                    if (teamProjectPair.containsKey(report.getDeptId())) {
                        Long projectDeptId = teamProjectPair.get(report.getDeptId());
                        if (projectDeptPair.containsKey(projectDeptId)) {
                            // 项目部id 对应的项目部名称
                            String projectDeptName = projectDeptPair.get(projectDeptId);
                            // 设置日进尺
                            if (projectDeptDailyFootagePair.containsKey(projectDeptName)) {
                                BigDecimal tempFootage = projectDeptDailyFootagePair.get(projectDeptName);
                                BigDecimal existFootage = report.getDailyFootage();
                                projectDeptDailyFootagePair.put(projectDeptName, tempFootage.add(existFootage));
                            } else {
                                BigDecimal tempFootage = report.getDailyFootage();
                                projectDeptDailyFootagePair.put(projectDeptName, tempFootage);
                            }
                            // 设置月累计进尺
                            if (projectDeptMonthFootagePair.containsKey(projectDeptName)) {
                                BigDecimal tempFootage = projectDeptMonthFootagePair.get(projectDeptName);
                                BigDecimal existFootage = report.getMonthlyFootage();
                                projectDeptMonthFootagePair.put(projectDeptName, tempFootage.add(existFootage));
                            } else {
                                BigDecimal tempFootage = report.getMonthlyFootage();
                                projectDeptMonthFootagePair.put(projectDeptName, tempFootage);
                            }
                            // 设置年累计进尺
                            if (projectDeptYearFootagePair.containsKey(projectDeptName)) {
                                BigDecimal tempFootage = projectDeptYearFootagePair.get(projectDeptName);
                                BigDecimal existFootage = report.getAnnualFootage();
                                projectDeptYearFootagePair.put(projectDeptName, tempFootage.add(existFootage));
                            } else {
                                BigDecimal tempFootage = report.getAnnualFootage();
                                projectDeptYearFootagePair.put(projectDeptName, tempFootage);
                            }
                        }
                    }
                });
            }
            // 遍历所有项目部 没有产生运行数据的项目部 进尺 赋值 0
            projectDeptPair.forEach((projectDeptId, projectDeptName) -> {
                if (!projectDeptDailyFootagePair.containsKey(projectDeptName)) {
                    projectDeptDailyFootagePair.put(projectDeptName, BigDecimal.ZERO);
                }
                if (!projectDeptMonthFootagePair.containsKey(projectDeptName)) {
                    projectDeptMonthFootagePair.put(projectDeptName, BigDecimal.ZERO);
                }
                if (!projectDeptYearFootagePair.containsKey(projectDeptName)) {
                    projectDeptYearFootagePair.put(projectDeptName, BigDecimal.ZERO);
                }
            });

            LinkedList<Object> xAxis = new LinkedList<>();
            LinkedList<Object> dailyData = new LinkedList<>();
            LinkedList<Object> monthData = new LinkedList<>();
            LinkedList<Object> yearData = new LinkedList<>();

            projectDeptDailyFootagePair.forEach( (k,v)->{
                if (zjDeptNames.contains(k)) {
                    xAxis.add(k);
                    dailyData.add(v);
                    if (projectDeptMonthFootagePair.containsKey(k)) {
                        BigDecimal monthlyFootage = projectDeptMonthFootagePair.get(k);
                        monthData.add(monthlyFootage);
                    }
                    if (projectDeptYearFootagePair.containsKey(k)) {
                        BigDecimal annualFootage = projectDeptYearFootagePair.get(k);
                        yearData.add(annualFootage);
                    }
                }
            });

            ImmutableMap<String, Serializable> dailyResult = ImmutableMap.of("name", "日进尺~~en**dailyFootage", "data", dailyData);
            ImmutableMap<String, Serializable> monthResult = ImmutableMap.of("name", "月累进尺~~en**monthlyFootage", "data", monthData);
            ImmutableMap<String, Serializable> yearResult = ImmutableMap.of("name", "年累进尺~~en**annualFootage", "data", yearData);
            return success(ImmutableMap.of("xAxis", xAxis, "series", ImmutableList.of(dailyResult, monthResult, yearResult)));
        }
    }

    /**
     * 按队伍 统计 瑞鹰 158 的 钻井 完井情况
     * @return
     */
    @GetMapping("/ry/dailyReport/rigFinished")
    @PermitAll
    public CommonResult<Map<String, Object>> getRyDailyReportRigFinished() {
        // 查询瑞鹰所有 队伍 项目部
        Set<Long> rdChildDeptIds = deptService.getChildDeptIdListFromCache(158l);
        List<DeptDO> depts =deptService.getDeptList(rdChildDeptIds);
        // key队伍id      value队伍所属项目部id      包含队伍的项目部
        Map<Long, Long> teamProjectPair = new HashMap<>();
        // key队伍id      value队伍名称
        Map<Long, String> teamPair = new HashMap<>();
        // 项目部id集合
        Set<Long> projectDeptIds = new HashSet<>();
        // key项目部id     value项目部名称
        Map<Long, String> projectDeptPair = new HashMap<>();

        // 查询 钻井 业务相关 部门
        IotDeptTypePageReqVO deptTypeReqVO = new IotDeptTypePageReqVO();
        deptTypeReqVO.setType("zj");
        List<IotDeptTypeDO> deptTypes = iotDeptTypeMapper.selectList(deptTypeReqVO);
        List<Long> zjOrXjDeptIds = new ArrayList<>();
        if (CollUtil.isNotEmpty(deptTypes)) {
            deptTypes.forEach(dept -> {
                zjOrXjDeptIds.add(dept.getDeptId());
            });
        }

        if (CollUtil.isNotEmpty(depts)) {
            depts.forEach(dept -> {
                // 类型(公司级1 项目部2 队伍3)
                if ("2".equals(dept.getType())) {
                    // 项目部
                    projectDeptIds.add(dept.getId());
                    projectDeptPair.put(dept.getId(), dept.getName());
                }
                if ("3".equals(dept.getType()) && zjOrXjDeptIds.contains(dept.getId())) {
                    // 队伍
                    teamProjectPair.put(dept.getId(), dept.getParentId());
                    teamPair.put(dept.getId(), dept.getName());
                }
            });
        }

        IotRyDailyReportPageReqVO reqVO = new IotRyDailyReportPageReqVO();
        // 钻井
        reqVO.setProjectClassification("1");
        // 钻井 日报统计 月完井数 年完井数
        List<IotRyDailyReportTaskCountVO> repairReports = iotRyDailyReportService.countDateRigTasksByDepartment();
        Map<String, Integer> deptDailyPair = new HashMap<>();
        Map<String, Integer> deptMonthlyPair = new HashMap<>();
        Map<String, Integer> deptAnnualPair = new HashMap<>();
        // 遍历集合 repairReports 找到对应的队伍
        if (CollUtil.isNotEmpty(repairReports)) {
            repairReports.forEach(report -> {
                if (teamPair.containsKey(report.getDeptId())) {
                    String deptName = teamPair.get(report.getDeptId());
                    // 设置日完井数
                    deptDailyPair.put(deptName, report.getCompletedTaskCount());
                    // 设置月完井数
                    deptMonthlyPair.put(deptName, report.getMonthCompletedTaskCount());
                    deptAnnualPair.put(deptName, report.getYearCompletedTaskCount());
                }
            });
        }
        // 遍历所有队伍 没有产生运行数据的队伍 赋值 0
        teamPair.forEach((deptId, deptName) -> {
            if (!deptDailyPair.containsKey(deptName)) {
                deptDailyPair.put(deptName, 0);
            }
            if (!deptMonthlyPair.containsKey(deptName)) {
                deptMonthlyPair.put(deptName, 0);
            }
            if (!deptAnnualPair.containsKey(deptName)) {
                deptAnnualPair.put(deptName, 0);
            }
        });

        LinkedList<Object> xAxis = new LinkedList<>();
        LinkedList<Object> dailyData = new LinkedList<>();
        LinkedList<Object> monthData = new LinkedList<>();
        LinkedList<Object> yearData = new LinkedList<>();

        deptDailyPair.forEach( (k,v)->{
            xAxis.add(k);
            dailyData.add(v);
            if (deptMonthlyPair.containsKey(k)) {
                Integer monthCount = deptMonthlyPair.get(k);
                monthData.add(monthCount);
            }
            if (deptAnnualPair.containsKey(k)) {
                Integer yearCount = deptAnnualPair.get(k);
                yearData.add(yearCount);
            }
        });
//        ImmutableMap<String, Serializable> dailyResult = ImmutableMap.of("name", "日累完成井数~~en**dailyFinished", "data", dailyData);
        ImmutableMap<String, Serializable> monthResult = ImmutableMap.of("name", "月累完成井数~~en**monthlyFinished", "data", monthData);
        ImmutableMap<String, Serializable> yearResult = ImmutableMap.of("name", "年累完井数~~en**annualFinished", "data", yearData);
        return success(ImmutableMap.of("xAxis", xAxis, "series", ImmutableList.of(monthResult, yearResult)));
    }

    /**
     * 查询瑞鹰历史日报数据
     * 钻井：进尺 完井数
     * @return
     */
    @GetMapping("/ry/hiZjDailyReports")
    @PermitAll
    public CommonResult<Map<String, Object>> hiZjDailyReports() {
        // 查询历史数据
        IotRyHiDailyReportPageReqVO pageReqVO = new IotRyHiDailyReportPageReqVO();
        pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE);
        PageResult<IotRyHiDailyReportDO> pageReports = iotRyHiDailyReportService.getIotRyHiDailyReportPage(pageReqVO);
        if (ObjUtil.isEmpty(pageReports)) {
            return success(emptyResult());
        }
        List<IotRyHiDailyReportDO> reports = pageReports.getList();
        if (CollUtil.isEmpty(reports)) {
            return success(emptyResult());
        }
        // 将历史日报数据按照年份 为维度 统计 进尺、完井数
        // key年份  value 钻井累计进尺m
        Map<Integer, BigDecimal> footagePair = new HashMap<>();
        // key年份  value 钻井累计完井数
        Map<Integer, BigDecimal> zjWellsPair = new HashMap<>();
        // key年份  value 修井累计完井数
        Map<Integer, BigDecimal> xjWellsPair = new HashMap<>();

        reports.forEach(report -> {
            LocalDateTime reportDate = report.getCreateTime();
            Integer year = reportDate.getYear();
            String classification = report.getProjectClassification();
            BigDecimal footage = report.getAnnualFootage();
            BigDecimal completedWells = report.getTotalCompletedWells();
            if ("1".equals(classification)) {
                // 钻井
                if (footagePair.containsKey(year)) {
                    BigDecimal existFootage = footagePair.get(year);
                    BigDecimal tempFootage = existFootage.add(footage);
                    footagePair.put(year, tempFootage);
                } else {
                    footagePair.put(year, footage);
                }
                if (zjWellsPair.containsKey(year)) {
                    BigDecimal existWells = zjWellsPair.get(year);
                    BigDecimal tempWells = existWells.add(completedWells);
                    zjWellsPair.put(year, tempWells);
                } else {
                    zjWellsPair.put(year, completedWells);
                }
            }
        });

        LinkedList<Object> xAxis = new LinkedList<>();
        LinkedList<Object> footageData = new LinkedList<>();
        LinkedList<Object> wellsData = new LinkedList<>();

        footagePair.forEach((k,v)->{
            xAxis.add(k);
            footageData.add(v);
            if (zjWellsPair.containsKey(k)) {
                BigDecimal wells = zjWellsPair.get(k);
                wellsData.add(wells);
            }
        });
        ImmutableMap<String, Serializable> footageResult = ImmutableMap.of("name", "累计进尺~~en**footage", "data", footageData);
        ImmutableMap<String, Serializable> wellsResult = ImmutableMap.of("name", "累计完井数~~en**finishedWells", "data", wellsData);
        return success(ImmutableMap.of("xAxis", xAxis, "series", ImmutableList.of(footageResult, wellsResult)));
    }

    /**
     * 查询瑞鹰历史日报数据
     * 修井：完井数
     * @return
     */
    @GetMapping("/ry/hiXjDailyReports")
    @PermitAll
    public CommonResult<Map<String, Object>> hiXjDailyReports() {
        // 查询历史数据
        IotRyHiDailyReportPageReqVO pageReqVO = new IotRyHiDailyReportPageReqVO();
        pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE);
        PageResult<IotRyHiDailyReportDO> pageReports = iotRyHiDailyReportService.getIotRyHiDailyReportPage(pageReqVO);
        if (ObjUtil.isEmpty(pageReports)) {
            return success(emptyResult());
        }
        List<IotRyHiDailyReportDO> reports = pageReports.getList();
        if (CollUtil.isEmpty(reports)) {
            return success(emptyResult());
        }
        // 将历史日报数据按照年份 为维度 统计 进尺、完井数
        // key年份  value 修井累计完井数
        Map<Integer, BigDecimal> xjWellsPair = new HashMap<>();

        reports.forEach(report -> {
            LocalDateTime reportDate = report.getCreateTime();
            Integer year = reportDate.getYear();
            String classification = report.getProjectClassification();
            BigDecimal footage = report.getAnnualFootage();
            BigDecimal completedWells = report.getTotalCompletedWells();
            if ("2".equals(classification)) {
                // 修井
                if (xjWellsPair.containsKey(year)) {
                    BigDecimal existWells = xjWellsPair.get(year);
                    BigDecimal tempWells = existWells.add(completedWells);
                    xjWellsPair.put(year, tempWells);
                } else {
                    xjWellsPair.put(year, completedWells);
                }
            }
        });
        LinkedList<Object> xAxis = new LinkedList<>();
        LinkedList<Object> wellsData = new LinkedList<>();
        xjWellsPair.forEach((k,v)->{
            xAxis.add(k);
            wellsData.add(v);
        });
        ImmutableMap<String, Serializable> wellsResult = ImmutableMap.of("name", "累计完井数~~en**finishedWells", "data", wellsData);
        return success(ImmutableMap.of("xAxis", xAxis, "series", ImmutableList.of(wellsResult)));
    }

    /**
     * 空数据返回结构
     */
    private Map<String, Object> emptyResult() {
        return ImmutableMap.of(
                "xAxis", Collections.emptyList(),
                "series", Collections.emptyList()
        );
    }

    /**
     * 瑞恒 设备利用率 按项目部统计
     * @return
     */
    @GetMapping("/rh/device/utilizationRate")
    @PermitAll
    public CommonResult<List<ProjectUtilizationRateVo>> utilizationRate(IotRhDailyReportPageReqVO reqVO) {
        List<ProjectUtilizationRateVo> productionStatuses = rhProductionStatusList(reqVO);
        return success(productionStatuses);
    }


    @GetMapping("/exportRhDashboard")
    @Operation(summary = "导出瑞恒看板生产动态列表")
    @PreAuthorize("@ss.hasPermission('pms:iot-rh-daily-report:export')")
    @ApiAccessLog(operateType = EXPORT)
    public void exportRhDashboard(@Valid IotRhDailyReportPageReqVO reqVO, HttpServletResponse response) throws IOException {
        List<ProjectUtilizationRateVo> productionStatuses = rhProductionStatusList(reqVO);
        // 汇总 注入量(日注气 累注气 日注水 累注水) 运行时效(当日运行时效 平均运行时效)
        if (CollUtil.isNotEmpty(productionStatuses)) {
            // 百分比格式化：保留2位小数，自动乘100加%
            DecimalFormat percentFormat = new DecimalFormat("#0.00%");
            percentFormat.setRoundingMode(RoundingMode.HALF_UP);

            productionStatuses.forEach(status -> {
                List<String> injectLines = new ArrayList<>();
                List<String> rateLines = new ArrayList<>();
                // 将 日注气 累注气 日注水 累注水 汇总到 注入量injectionVolume
                // 将 当日运行时效 平均运行时效 汇总到 运行时效runningAvailability
                BigDecimal gasInjection = status.getGasInjection();
                BigDecimal yearGasInjection = status.getYearGasInjection();
                BigDecimal waterInjection = status.getWaterInjection();
                BigDecimal yearWaterInjection = status.getYearWaterInjection();
                BigDecimal hourRate = status.getHourUtilizationRate();
                BigDecimal yearRate = status.getYearHourUtilizationRate();
                if (ObjUtil.isNotEmpty(gasInjection) && gasInjection.compareTo(BigDecimal.ZERO) > 0) {
                    injectLines.add("日注气：" + gasInjection);
                }
                if (ObjUtil.isNotEmpty(yearGasInjection) && yearGasInjection.compareTo(BigDecimal.ZERO) > 0) {
                    injectLines.add("累注气：" + yearGasInjection);
                }
                if (ObjUtil.isNotEmpty(waterInjection) && waterInjection.compareTo(BigDecimal.ZERO) > 0) {
                    injectLines.add("日注水：" + waterInjection);
                }
                if (ObjUtil.isNotEmpty(yearWaterInjection) && yearWaterInjection.compareTo(BigDecimal.ZERO) > 0) {
                    injectLines.add("累注水：" + yearWaterInjection);
                }
                String injectStr = injectLines.stream().collect(Collectors.joining("\n"));
                status.setInjectionVolume(injectStr);

                if (ObjUtil.isNotEmpty(hourRate) && hourRate.compareTo(BigDecimal.ZERO) > 0) {
                    // 原始4位小数，转百分比保留两位
                    String hourPercent = percentFormat.format(hourRate);
                    rateLines.add("当日运行时效：" + hourPercent);
                }
                if (ObjUtil.isNotEmpty(yearRate) && yearRate.compareTo(BigDecimal.ZERO) > 0) {
                    String yearPercent = percentFormat.format(yearRate);
                    rateLines.add("平均运行时效：" + yearPercent);
                }
                // 拼接外层星号
                String rateStr = rateLines.stream().collect(Collectors.joining("\n"));
                status.setRunningAvailability(rateStr);
            });
        }
        // 导出 Excel
        ExcelUtils.write(response, "瑞恒生产动态列表.xls", "瑞恒生产动态列表", ProjectUtilizationRateVo.class,
                productionStatuses);
    }

    /**
     * 查询 瑞恒看板 生产动态列表
     */
    private List<ProjectUtilizationRateVo> rhProductionStatusList(IotRhDailyReportPageReqVO reqVO) {
        if (ObjUtil.isEmpty(reqVO.getCreateTime())) {
            throw exception(IOT_DAILY_REPORT_TIME_NOT_EXISTS);
        }
        if (reqVO.getCreateTime().length < 2) {
            throw exception(IOT_DAILY_REPORT_TIME_NOT_EXISTS);
        }
        List<Long> sortedProjectIds = new ArrayList<>();
        sortedProjectIds.add(157l);
        sortedProjectIds.add(164l); // 塔河项目部
        sortedProjectIds.add(165l); // 塔里木项目部
        sortedProjectIds.add(160l); // 吐哈项目部
        sortedProjectIds.add(256l); // 川庆项目部
        sortedProjectIds.add(269l); // 非洲项目部
        sortedProjectIds.add(273l); // 南美项目部
        sortedProjectIds.add(275l); // 中东项目部
        sortedProjectIds.add(282l); // 中亚项目部
        // 各项目部的设备利用率集合
        List<ProjectUtilizationRateVo> rates = new ArrayList<>();
        // 查询瑞恒 157l 所有项目部
        Set<Long> childDeptIds = deptService.getChildDeptIdListFromCache(157l);
        Map<Long, DeptDO> allDeptPair = deptService.getDeptMap(childDeptIds);
        Set<String> projectDeptNames = new HashSet<>();
        Set<Long> projectDeptIds = new HashSet<>();
        // key项目部id   value项目部名称
        Map<Long, String> projectPair = new HashMap<>();
        // key项目部id   value项目部包含的队伍id集合
        Map<Long, Set<Long>> projectTeamPair = new HashMap<>();
        // 队伍id 集合
        Set<Long> teamDepartmentIds = new HashSet<>();

        // key施工队伍id   value状态为LY的项目部id
        Map<Long, Long> teamProjectIdPair = new HashMap<>();

        // key项目部id     value项目部年累计注气量
        Map<Long, BigDecimal> projectYearGasInjectionPair = new HashMap<>();
        // key项目部id     value项目部年累计注水量
        Map<Long, BigDecimal> projectYearWaterInjectionPair = new HashMap<>();

        // key项目部id   value项目部下包含的 施工 队伍数量
        Map<Long, Integer> sgTeamCountPair = new HashMap<>();
        // key项目部id   value项目部下包含的 施工准备 队伍数量
        Map<Long, Integer> zbTeamCountPair = new HashMap<>();
        // key项目部id   value项目部下包含的 驻地待命 队伍数量
        Map<Long, Integer> zddmTeamCountPair = new HashMap<>();

        // 筛选瑞恒 主设备 rq_iot_rh_main_device_category
        Set<Long> mainDeviceCategoryIds = new HashSet<>();
        List<DictDataDO> constructionStatusDictData = dictDataService.getDictDataListByDictType("rq_iot_rh_main_device_category");
        if (CollUtil.isNotEmpty(constructionStatusDictData)) {
            constructionStatusDictData.forEach(data -> {
                String value = data.getValue();
                if (NumberUtil.isNumber(value)) {
                    Long longValue = Long.valueOf(value);
                    mainDeviceCategoryIds.add(longValue);
                }
            });
        }

        // 查询 瑞恒 所有设备 只统计包含 施工 状态设备的队伍
        IotDevicePageReqVO deviceReqVO = new IotDevicePageReqVO();
        deviceReqVO.setDeptIds(new ArrayList<>(childDeptIds));
        List<IotDeviceDO> allRhDevices = iotDeviceMapper.selectListAlone(deviceReqVO);
        Set<Long> haveDeviceDeptIds = new HashSet<>();
        if (CollUtil.isNotEmpty(allRhDevices)) {
            // 筛选出包含设备的队伍部门集合
            // 20260608 修改成 包含瑞恒主设备的 部门队伍id集合
            allRhDevices.forEach(device -> {
                if (mainDeviceCategoryIds.contains(device.getAssetClass())) {
                    haveDeviceDeptIds.add(device.getDeptId());
                }
            });
        }
        if (CollUtil.isNotEmpty(allDeptPair)) {
            allDeptPair.forEach((deptId, dept) -> {
                // 项目部
                if ("2".equals(dept.getType())) {
                    projectDeptIds.add(deptId);
                    projectDeptNames.add(dept.getName());
                    projectPair.put(deptId, dept.getName());
                }
                // 队伍
                if ("3".equals(dept.getType())) {
                    teamDepartmentIds.add(dept.getId());
                }
            });
            // 遍历所有部门 只筛选出有设备的队伍
            allDeptPair.forEach((deptId, dept) -> {
                // 找出每个项目部下的队伍
                if (projectPair.containsKey(dept.getParentId())) {
                    // 获得当前部门的上级项目部
                    projectPair.forEach((projectDeptId, projectDeptName) -> {
                        if (projectDeptId.equals(dept.getParentId()) && haveDeviceDeptIds.contains(deptId) && teamDepartmentIds.contains(deptId)) {
                            if (projectTeamPair.containsKey(projectDeptId)) {
                                Set<Long> teamIds = projectTeamPair.get(projectDeptId);
                                teamIds.add(deptId);
                                projectTeamPair.put(projectDeptId, teamIds);
                            } else {
                                Set<Long> teamIds = new HashSet<>();
                                teamIds.add(deptId);
                                projectTeamPair.put(projectDeptId, teamIds);
                            }
                            // 设置队伍与上级项目部的关联关系集合
                            teamProjectIdPair.put(dept.getId(), dept.getParentId());
                        }
                    });
                }
            });
        }
        // 查询出指定时间区间内 已经填写的日报数量 存在注气时间是0 但是 注气量 不为0的情况
        // reqVO.setStatisticFlag("Y");
        List<IotRhDailyReportDO> dailyReports = iotRhDailyReportMapper.dailyReports(reqVO);

        // 查询时间所在年份所有日报 计算年累计注气 年累计注水
        IotRhDailyReportPageReqVO yearReqVO = new IotRhDailyReportPageReqVO();
        LocalDateTime[] timeRange = reqVO.getCreateTime();
        if (ObjUtil.isNotEmpty(timeRange) && timeRange.length >= 2) {
            LocalDateTime originalStart = timeRange[0];
            LocalDateTime originalEnd = timeRange[1];
            int statYear = originalStart.getYear();
            // 取当年1月1日零点 从去掉12月26日开始统计 工作量
            // LocalDateTime yearBegin = LocalDateTime.of(originalStart.getYear(), 1, 1, 0, 0);
            LocalDateTime yearBegin = LocalDateTime.of(statYear - 1, 12, 26, 0, 0);
            yearReqVO.setCreateTime(new LocalDateTime[]{yearBegin, originalEnd});
        }
        List<IotRhDailyReportDO> yearDailyReports = iotRhDailyReportMapper.dailyReports(yearReqVO);

        // key项目部id     value项目部下包含设备的队伍 年度 注气时间 或 注水时间 总和
        Map<Long, BigDecimal> projectYearWorkTimePair = new HashMap<>();

        if (CollUtil.isNotEmpty(yearDailyReports)) {
            yearDailyReports.forEach(yearReport -> {
                if (CollUtil.isNotEmpty(projectTeamPair)) {
                    projectTeamPair.forEach((projectDeptId, teamDeptIds) -> {
                        if (teamDeptIds.contains(yearReport.getDeptId())) {
                            BigDecimal dailyGasInjection = yearReport.getDailyGasInjection();
                            BigDecimal dailyWaterInjection = yearReport.getDailyWaterInjection();
                            // 项目部 年累计注气量
                            if (projectYearGasInjectionPair.containsKey(projectDeptId)) {
                                BigDecimal tempGasInjection = projectYearGasInjectionPair.get(projectDeptId);
                                BigDecimal subtotal = tempGasInjection.add(dailyGasInjection);
                                projectYearGasInjectionPair.put(projectDeptId, subtotal);
                            } else {
                                projectYearGasInjectionPair.put(projectDeptId, dailyGasInjection);
                            }
                            // 项目部 年累计注水量
                            if (projectYearWaterInjectionPair.containsKey(projectDeptId)) {
                                BigDecimal tempWaterInjection = projectYearWaterInjectionPair.get(projectDeptId);
                                BigDecimal subtotal = tempWaterInjection.add(dailyWaterInjection);
                                projectYearWaterInjectionPair.put(projectDeptId, subtotal);
                            } else {
                                projectYearWaterInjectionPair.put(projectDeptId, dailyWaterInjection);
                            }
                            // 各项目部年度 运行时效(按小时统计的设备利用率)
                            // 按小时数 统计设备利用率
                            BigDecimal gasInjectionTime = ObjUtil.defaultIfNull(yearReport.getDailyInjectGasTime(), BigDecimal.ZERO);
                            BigDecimal waterInjectionTime = ObjUtil.defaultIfNull(yearReport.getDailyInjectWaterTime(), BigDecimal.ZERO);
                            // 取 注气时间 注水时间 的较大者
                            BigDecimal workTime = gasInjectionTime.compareTo(BigDecimal.ZERO) > 0
                                    ? gasInjectionTime
                                    : waterInjectionTime.compareTo(BigDecimal.ZERO) > 0
                                    ? waterInjectionTime
                                    : BigDecimal.ZERO;
                            if (workTime.compareTo(BigDecimal.ZERO) > 0) {
                                projectYearWorkTimePair.merge(projectDeptId, workTime, BigDecimal::add);
                            }
                        }
                    });
                }
            });
        }

        // key项目部id     value项目部包含的队伍指定时间区域内日报数量
        Map<Long, Integer> projectReportPair = new HashMap<>();

        // 以施工区域为维度统计 队伍总数 施工队伍数 准备队伍数
        // key: 项目部ID -> key: 施工区域 -> Set<队伍ID>
        Map<Long, Map<String, Set<Long>>> projectLocationTeamSet = new HashMap<>();   // 总队伍
        Map<Long, Map<String, Set<Long>>> projectLocationSgTeamSet = new HashMap<>(); // 施工队伍（注气/注水>0）
        Map<Long, Map<String, Set<Long>>> projectLocationZbTeamSet = new HashMap<>(); // 准备队伍（zb/dq/wg）

        // key项目部id     value项目部注气量
        Map<Long, BigDecimal> projectGasInjectionPair = new HashMap<>();
        // key项目部id     value项目部注水量
        Map<Long, BigDecimal> projectWaterInjectionPair = new HashMap<>();

        // 查询所有日报关联的任务 井号 施工区域
        Map<Long, String> taskWellNamePair = new HashMap<>();
        Map<Long, String> taskLocationPair = new HashMap<>();

        // 生产动态临时存储
        Map<Long, Map<String, Map<String, List<String>>>> productionMap = new HashMap<>();

        // key项目部id     value项目部下包含设备的队伍注气时间或注水时间总和
        Map<Long, BigDecimal> projectWorkTimePair = new HashMap<>();

        if (CollUtil.isNotEmpty(dailyReports)) {
            IotProjectTaskPageReqVO taskReqVO = new IotProjectTaskPageReqVO();
            taskReqVO.setTaskIds(convertList(dailyReports, IotRhDailyReportDO::getTaskId));
            List<IotProjectTaskDO> tasks = iotProjectTaskService.projectTasks(taskReqVO);
            if (CollUtil.isNotEmpty(tasks)) {
                tasks.forEach(task -> {
                    taskWellNamePair.put(task.getId(), task.getWellName());
                    taskLocationPair.put(task.getId(), task.getLocation());
                });
            }

            // 整理出每个项目部下的队伍填报的日报数量
            dailyReports.forEach(report -> {
                if (CollUtil.isNotEmpty(projectTeamPair)) {
                    projectTeamPair.forEach((projectDeptId, teamDeptIds) -> {
                        if (teamDeptIds.contains(report.getDeptId())) {
                            // 以施工区域为维度统计 队伍总数 施工队伍数 准备队伍数 待命队伍数量
                            Long taskId = report.getTaskId();
                            String taskLocation = StrUtil.EMPTY;
                            if (ObjUtil.isNotEmpty(taskId) && taskLocationPair.containsKey(taskId)) {
                                taskLocation = taskLocationPair.get(taskId);
                            }

                            BigDecimal dailyGasInjection = report.getDailyGasInjection();
                            BigDecimal dailyWaterInjection = report.getDailyWaterInjection();

                            // 项目部下 施工区域内 队伍总数量
                            if (StrUtil.isNotBlank(taskLocation)) {
                                // 总队伍（去重）
                                projectLocationTeamSet
                                        .computeIfAbsent(projectDeptId, k -> new HashMap<>())
                                        .computeIfAbsent(taskLocation, k -> new HashSet<>())
                                        .add(report.getDeptId());
                            }

                            if (dailyGasInjection.compareTo(BigDecimal.ZERO) > 0 || dailyWaterInjection.compareTo(BigDecimal.ZERO) > 0) {
                                // 项目部日报数量 20260608 统计 注气量 or 注水量 > 0 的日报数量
                                if (projectReportPair.containsKey(projectDeptId)) {
                                    Integer tempCount = projectReportPair.get(projectDeptId);
                                    projectReportPair.put(projectDeptId, ++tempCount);
                                } else {
                                    projectReportPair.put(projectDeptId, 1);
                                }
                                // 施工队伍数量
                                if (haveDeviceDeptIds.contains(report.getDeptId())) {
                                    if (sgTeamCountPair.containsKey(projectDeptId)) {
                                        Integer tempCount = sgTeamCountPair.get(projectDeptId);
                                        sgTeamCountPair.put(projectDeptId, ++tempCount);
                                    } else {
                                        sgTeamCountPair.put(projectDeptId, 1);
                                    }
                                }
                                // 项目部下 施工区域内 施工队伍数量
                                if (StrUtil.isNotBlank(taskLocation)) {
                                    projectLocationSgTeamSet
                                            .computeIfAbsent(projectDeptId, k -> new HashMap<>())
                                            .computeIfAbsent(taskLocation, k -> new HashSet<>())
                                            .add(report.getDeptId());
                                }
                            }

                            // 统计 施工 准备 待命 队伍数量
                            // 准备
                            if ("zb".equals(report.getConstructionStatus()) || "dq".equals(report.getConstructionStatus()) || "wg".equals(report.getConstructionStatus())) {
                                if (zbTeamCountPair.containsKey(projectDeptId)) {
                                    Integer tempCount = zbTeamCountPair.get(projectDeptId);
                                    zbTeamCountPair.put(projectDeptId, ++tempCount);
                                } else {
                                    zbTeamCountPair.put(projectDeptId, 1);
                                }
                            }

                            // 项目部 指定时间的注气量
                            if (projectGasInjectionPair.containsKey(projectDeptId)) {
                                BigDecimal tempGasInjection = projectGasInjectionPair.get(projectDeptId);
                                BigDecimal subtotal = tempGasInjection.add(dailyGasInjection);
                                projectGasInjectionPair.put(projectDeptId, subtotal);
                            } else {
                                projectGasInjectionPair.put(projectDeptId, dailyGasInjection);
                            }
                            // 项目部 指定时间的注水量
                            if (projectWaterInjectionPair.containsKey(projectDeptId)) {
                                BigDecimal tempWaterInjection = projectWaterInjectionPair.get(projectDeptId);
                                BigDecimal subtotal = tempWaterInjection.add(dailyWaterInjection);
                                projectWaterInjectionPair.put(projectDeptId, subtotal);
                            } else {
                                projectWaterInjectionPair.put(projectDeptId, dailyWaterInjection);
                            }

                            // 日报关联的任务井号
                            Long reportTaskId = report.getTaskId();

                            // 提取 所有日报非生产时间和 = 24H 的队伍
                            List<BigDecimal> nptTimeList = Arrays.asList(
                                    report.getAccidentTime(),
                                    report.getRepairTime(),
                                    report.getSelfStopTime(),
                                    report.getComplexityTime(),
                                    report.getRelocationTime(),
                                    report.getRectificationTime(),
                                    report.getWaitingStopTime(),
                                    report.getWinterBreakTime(),
                                    report.getPartyaDesign(),
                                    report.getPartyaPrepare(),
                                    report.getPartyaResource(),
                                    report.getOtherNptTime()
                            );
                            BigDecimal totalNptTime = nptTimeList.stream()
                                    .map(time -> Optional.ofNullable(time).orElse(BigDecimal.ZERO))
                                    .reduce(BigDecimal.ZERO, BigDecimal::add);
                            BigDecimal twentyFour = new BigDecimal("24");
                            if (totalNptTime.compareTo(twentyFour) == 0) {
                                // 所有非生产时间和=24H 的队伍 提取生产动态
                                if (ObjUtil.isNotEmpty(reportTaskId)) {
                                    String wellName = taskWellNamePair.get(reportTaskId);
                                    String location = taskLocationPair.get(reportTaskId);
                                    if (StrUtil.isNotBlank(wellName) && StrUtil.isNotBlank(location)) {
                                        String dynamic = report.getProductionStatus();
                                        productionMap.computeIfAbsent(projectDeptId, k -> new HashMap<>())
                                                .computeIfAbsent(location, k -> new HashMap<>())
                                                .computeIfAbsent(wellName, k -> new ArrayList<>())
                                                .add(dynamic);
                                    }
                                }
                            }
                            // 按小时数 统计设备利用率
                            BigDecimal gasInjectionTime = ObjUtil.defaultIfNull(report.getDailyInjectGasTime(), BigDecimal.ZERO);
                            BigDecimal waterInjectionTime = ObjUtil.defaultIfNull(report.getDailyInjectWaterTime(), BigDecimal.ZERO);
                            // 取 注气时间 注水时间 的较大者
                            BigDecimal workTime = gasInjectionTime.compareTo(BigDecimal.ZERO) > 0
                                    ? gasInjectionTime
                                    : waterInjectionTime.compareTo(BigDecimal.ZERO) > 0
                                    ? waterInjectionTime
                                    : BigDecimal.ZERO;
                            if (workTime.compareTo(BigDecimal.ZERO) > 0) {
                                projectWorkTimePair.merge(projectDeptId, workTime, BigDecimal::add);
                            }
                        }
                    });
                }
            });
            // 计算指定时间区间内包含的天数
            long daysCount;
            if (ObjUtil.isNotEmpty(reqVO.getCreateTime()) && reqVO.getCreateTime().length >= 2) {
                LocalDateTime start = reqVO.getCreateTime()[0];
                LocalDateTime end = reqVO.getCreateTime()[1];

                if (ObjUtil.isNotEmpty(start) && ObjUtil.isNotEmpty(end) && !end.isBefore(start)) {
                    // 使用ChronoUnit.DAYS.between计算天数差，并+1包含首尾两天
                    daysCount = ChronoUnit.DAYS.between(
                            start.toLocalDate(),
                            end.toLocalDate()
                    ) + 1;
                } else {
                    daysCount = 0L;
                }
            } else {
                daysCount = 0L;
            }

            // 计算年度开始 当前年1.1到指定查询时间区间内包含的天数
            long yearTotalDay = 0L;
            List<Long> yearTotalDays = new ArrayList<>();
            if (ObjUtil.isNotEmpty(reqVO.getCreateTime()) && reqVO.getCreateTime().length >= 2) {
                // 取查询结束日期
                LocalDateTime queryEndTime = reqVO.getCreateTime()[1];
                int startYear = queryEndTime.getYear();
                // 当年1月1日 零点 从前一年12月26日统计 累计工作量
                LocalDate yearStartDate = LocalDate.of(startYear - 1, 12, 26);
                LocalDate queryEndDate = queryEndTime.toLocalDate();
                // 首尾都包含，+1
                yearTotalDay = ChronoUnit.DAYS.between(yearStartDate, queryEndDate) + 1;
                yearTotalDays.add(yearTotalDay);
            }

            // 计算每个项目部的设备利用率
            if (CollUtil.isNotEmpty(projectTeamPair)) {
                projectTeamPair.forEach((projectDeptId, teamIds) -> {
                    // 暂时不统计欧洲项目部 352
                    if (352 != projectDeptId) {
                        ProjectUtilizationRateVo rateVo = new ProjectUtilizationRateVo();
                        rateVo.setProjectDeptId(projectDeptId);
                        if (projectPair.containsKey(projectDeptId)) {
                            rateVo.setProjectDeptName(projectPair.get(projectDeptId));
                        }
                        if (allDeptPair.containsKey(projectDeptId)) {
                            DeptDO dept = allDeptPair.get(projectDeptId);
                            rateVo.setSort(dept.getSort());
                        }
                        // 设置每个项目部的注气量
                        if (projectGasInjectionPair.containsKey(projectDeptId)) {
                            BigDecimal gasInjection = projectGasInjectionPair.get(projectDeptId);
                            // 转换单位 万方
                            BigDecimal gasInjectionWanFang = gasInjection
                                    .divide(BigDecimal.valueOf(10000), 2, RoundingMode.HALF_UP);
                            rateVo.setGasInjection(gasInjectionWanFang);
                        }
                        // 设置每个项目部的年累计注气量
                        if (projectYearGasInjectionPair.containsKey(projectDeptId)) {
                            BigDecimal yearGasInjection = projectYearGasInjectionPair.get(projectDeptId);
                            // 转换单位 万方
                            BigDecimal gasInjectionWanFang = yearGasInjection
                                    .divide(BigDecimal.valueOf(10000), 2, RoundingMode.HALF_UP);
                            rateVo.setYearGasInjection(gasInjectionWanFang);
                        }
                        // 设置每个项目部的注水量
                        if (projectWaterInjectionPair.containsKey(projectDeptId)) {
                            BigDecimal waterInjection = projectWaterInjectionPair.get(projectDeptId);
                            // 转换单位 万方
                            BigDecimal waterInjectionWanFang = waterInjection
                                    .divide(BigDecimal.valueOf(10000), 2, RoundingMode.HALF_UP);
                            rateVo.setWaterInjection(waterInjectionWanFang);
                        }
                        // 设置每个项目部的年累计注水量
                        if (projectYearWaterInjectionPair.containsKey(projectDeptId)) {
                            BigDecimal yearWaterInjection = projectYearWaterInjectionPair.get(projectDeptId);
                            // 转换单位 万方
                            BigDecimal waterInjectionWanFang = yearWaterInjection
                                    .divide(BigDecimal.valueOf(10000), 2, RoundingMode.HALF_UP);
                            rateVo.setYearWaterInjection(waterInjectionWanFang);
                        }
                        // 遍历每个项目部 获取每个项目部下队伍数量
                        Integer currentTeamNum = teamIds.size();
                        rateVo.setTeamCount(currentTeamNum);
                        // 待命队伍数量 = 队伍总数 - 施工队伍数量 - 准备队伍数量
                        // 施工队伍数量
                        Integer sgTeamCount = sgTeamCountPair.getOrDefault(projectDeptId, 0);
                        // 施工准备队伍数量
                        Integer zbTeamCount = zbTeamCountPair.getOrDefault(projectDeptId, 0);
                        // 驻地待命 队伍数量 = 队伍总数 - 施工队伍 -  准备队伍
                        Integer dmTeamCount = Math.max(currentTeamNum - sgTeamCount - zbTeamCount, 0);
                        zddmTeamCountPair.put(projectDeptId, dmTeamCount);
                        rateVo.setSgTeamCount(sgTeamCount);
                        rateVo.setZbTeamCount(zbTeamCount);
                        rateVo.setDmTeamCount(dmTeamCount);

                        rateVo.setCumulativeDays(currentTeamNum * daysCount);
                        double rate = 0.0;
                        // 匹配出当前项目部下 日报数量
                        if (projectReportPair.containsKey(projectDeptId)) {
                            Integer reportCount = projectReportPair.getOrDefault(projectDeptId, 0);
                            rateVo.setConstructionDays(reportCount);
                            // 当前项目部 设备利用率 公式 reportCount/(currentTeamNum*daysCount)
                            // 计算设备利用率（处理除数为0的情况）
                            if (currentTeamNum > 0 && daysCount > 0) {
                                rate = new BigDecimal((double) reportCount / (currentTeamNum * daysCount))
                                        .setScale(4, RoundingMode.HALF_UP)  // 保留4位小数，四舍五入
                                        .doubleValue();
                            }
                        }
                        rateVo.setUtilizationRate(rate); // 设备利用率
                        // 计算项目部 按小时统计的设备利用率(运行时效)
                        if (projectWorkTimePair.containsKey(projectDeptId)) {
                            BigDecimal reportWorkTime = projectWorkTimePair.getOrDefault(projectDeptId, BigDecimal.ZERO);
                            // 统计所有项目部 当日 总工作时间 以便于计算 公司整体的当日运行时效
                            if (currentTeamNum > 0 && daysCount > 0) {
                                // 分母 = 队伍数 * 天数 * 24小时
                                BigDecimal denominator = new BigDecimal(currentTeamNum * daysCount * 24);
                                // 安全计算，避免除0
                                BigDecimal utilization = BigDecimal.ZERO;
                                if (denominator.compareTo(BigDecimal.ZERO) > 0) {
                                    utilization = reportWorkTime.divide(denominator, 4, RoundingMode.HALF_UP);
                                    rateVo.setHourUtilizationRate(utilization);
                                }
                            }
                        }
                        // 计算项目部 年度运行时效 按小时统计的设备利用率(运行时效)
                        if (projectYearWorkTimePair.containsKey(projectDeptId)) {
                            BigDecimal reportWorkTime = projectYearWorkTimePair.getOrDefault(projectDeptId, BigDecimal.ZERO);
                            // 统计所有项目部 年度的 总工作时间 以便于计算 公司整体的当日运行时效
                            if (currentTeamNum > 0 && CollUtil.isNotEmpty(yearTotalDays)) {
                                long tempYearTotalDay = yearTotalDays.get(0);
                                // 分母 = 队伍数 * 天数 * 24小时
                                BigDecimal denominator = new BigDecimal(currentTeamNum * tempYearTotalDay * 24);
                                // 安全计算，避免除0
                                BigDecimal utilization = BigDecimal.ZERO;
                                if (denominator.compareTo(BigDecimal.ZERO) > 0) {
                                    utilization = reportWorkTime.divide(denominator, 4, RoundingMode.HALF_UP);
                                    rateVo.setYearHourUtilizationRate(utilization);
                                }
                            }
                        }
                        rates.add(rateVo);
                    }
                });
            }

            // 公司汇总的 数据
            ProjectUtilizationRateVo rateVo = new ProjectUtilizationRateVo();
            // 计算公司汇总的设备利用率 日平均时效  年平均时效
            // teamProjectIdPair 有效的队伍集合
            // 公司当日总运行工时
            BigDecimal currentTotalWorkTime = projectWorkTimePair.values().stream()
                    .filter(Objects::nonNull)
                    .reduce(BigDecimal.ZERO, BigDecimal::add);

            // 公司年度总运行工时
            BigDecimal yearTotalWorkTime = projectYearWorkTimePair.values().stream()
                    .filter(Objects::nonNull)
                    .reduce(BigDecimal.ZERO, BigDecimal::add);

            if (CollUtil.isNotEmpty(teamProjectIdPair)) {
                int teamCount = teamProjectIdPair.size();
                // 公司 当日运行时效 分母 = 队伍数 * 天数 * 24小时
                BigDecimal denominator = new BigDecimal(teamCount * daysCount * 24);
                // 安全计算，避免除0
                BigDecimal utilization = BigDecimal.ZERO;
                if (denominator.compareTo(BigDecimal.ZERO) > 0) {
                    utilization = currentTotalWorkTime.divide(denominator, 4, RoundingMode.HALF_UP);
                    rateVo.setHourUtilizationRate(utilization);
                }

                // 公司 年运行时效 分母 = 队伍数 * 天数 * 24小时
                long tempYearTotalDay = yearTotalDays.get(0);
                BigDecimal yearDenominator = new BigDecimal(teamCount * tempYearTotalDay * 24);
                // 安全计算，避免除0
                BigDecimal yearUtilization = BigDecimal.ZERO;
                if (yearDenominator.compareTo(BigDecimal.ZERO) > 0) {
                    yearUtilization = yearTotalWorkTime.divide(yearDenominator, 4, RoundingMode.HALF_UP);
                    rateVo.setYearHourUtilizationRate(yearUtilization);
                }
            }

            // 公司年累计注气
            BigDecimal companyYearGasInjection = projectYearGasInjectionPair.values().stream()
                    .filter(Objects::nonNull)
                    .reduce(BigDecimal.ZERO, BigDecimal::add);
            // 单位转换成 万方
            BigDecimal companyGasInjectionWanFang = companyYearGasInjection
                    .divide(BigDecimal.valueOf(10000), 2, RoundingMode.HALF_UP);

            // 公司年累计注水
            BigDecimal companyYearWaterInjection = projectYearWaterInjectionPair.values().stream()
                    .filter(Objects::nonNull)
                    .reduce(BigDecimal.ZERO, BigDecimal::add);
            // 单位转换成 万方
            BigDecimal companyWaterInjectionWanFang = companyYearWaterInjection
                    .divide(BigDecimal.valueOf(10000), 2, RoundingMode.HALF_UP);

            // 公司当日累计注气
            BigDecimal companyCurrentGasInjection = projectGasInjectionPair.values().stream()
                    .filter(Objects::nonNull)
                    .reduce(BigDecimal.ZERO, BigDecimal::add);
            // 单位转换成 万方
            BigDecimal currentGasInjectionWanFang = companyCurrentGasInjection
                    .divide(BigDecimal.valueOf(10000), 2, RoundingMode.HALF_UP);

            // 公司当日累计注水
            BigDecimal companyCurrentWaterInjection = projectWaterInjectionPair.values().stream()
                    .filter(Objects::nonNull)
                    .reduce(BigDecimal.ZERO, BigDecimal::add);
            // 单位转换成 万方
            BigDecimal currentWaterInjectionWanFang = companyCurrentWaterInjection
                    .divide(BigDecimal.valueOf(10000), 2, RoundingMode.HALF_UP);


            // 公司队伍总数
            Integer companyTeamCount = teamProjectIdPair.size();
            // 公司待命队伍总数
            Integer companyDmTeamCount = zddmTeamCountPair.values().stream()
                    .filter(Objects::nonNull)
                    .reduce(0, Integer::sum);
            // 公司施工准备队伍总数
            Integer companyZbTeamCount = zbTeamCountPair.values().stream()
                    .filter(Objects::nonNull)
                    .reduce(0, Integer::sum);
            // 公司施工队伍总数
            Integer companySgTeamCount = sgTeamCountPair.values().stream()
                    .filter(Objects::nonNull)
                    .reduce(0, Integer::sum);
            rateVo.setProjectDeptName("合计");
            rateVo.setProjectDeptId(157l);
            rateVo.setSort(0);
            rateVo.setTeamCount(companyTeamCount);
            rateVo.setDmTeamCount(companyDmTeamCount);
            rateVo.setZbTeamCount(companyZbTeamCount);
            rateVo.setSgTeamCount(companySgTeamCount);
            rateVo.setGasInjection(currentGasInjectionWanFang);
            rateVo.setWaterInjection(currentWaterInjectionWanFang);
            rateVo.setYearGasInjection(companyGasInjectionWanFang);
            rateVo.setYearWaterInjection(companyWaterInjectionWanFang);
            rates.add(rateVo);

        }
        // rates.sort(Comparator.comparingDouble(ProjectUtilizationRateVo::getUtilizationRate).reversed());
        // 克拉玛依 加入到 吐哈项目部，两个项目部合并
        AtomicReference<Integer> mergeTeamCount = new AtomicReference<>(0);
        AtomicReference<Integer> mergeConstructionDays = new AtomicReference<>(0);
        AtomicReference<Long> mergeCumulativeDays = new AtomicReference<>(0l);
        rates.forEach(rate -> {
            // 克拉玛依 项目部数据
            if (rate.getProjectDeptId() == 166) {
                mergeTeamCount.set(rate.getTeamCount());
                mergeCumulativeDays.set(ObjUtil.isNotEmpty(rate.getCumulativeDays()) ? rate.getCumulativeDays() : 0);
                mergeConstructionDays.set(ObjUtil.isNotEmpty(rate.getConstructionDays()) ? rate.getConstructionDays() : 0);
            }
        });
        rates.forEach(rate -> {
            // 吐哈项目部 项目部数据
            if (rate.getProjectDeptId() == 160) {
                rate.setTeamCount((ObjUtil.isNotEmpty(rate.getTeamCount()) ? rate.getTeamCount() : 0) + mergeTeamCount.get());
                rate.setCumulativeDays((ObjUtil.isNotEmpty(rate.getCumulativeDays()) ? rate.getCumulativeDays() : 0l) + mergeCumulativeDays.get());
                rate.setConstructionDays((ObjUtil.isNotEmpty(rate.getConstructionDays()) ? rate.getConstructionDays() : 0) + mergeConstructionDays.get());
            }

            Map<String, Map<String, List<String>>> locationMap = productionMap.get(rate.getProjectDeptId());
            // 组装各项目部 按照施工区域维度统计 的 队伍数量 生产动态明细
            if (locationMap != null && !locationMap.isEmpty()) {
                Map<String, Set<Long>> teamMap = projectLocationTeamSet.getOrDefault(rate.getProjectDeptId(), Collections.emptyMap());
                Map<String, Set<Long>> sgTeamMap = projectLocationSgTeamSet.getOrDefault(rate.getProjectDeptId(), Collections.emptyMap());

                StringBuilder sb = new StringBuilder();
                List<String> sortedLocations = new ArrayList<>(locationMap.keySet());
                Collections.sort(sortedLocations);
                for (String location : sortedLocations) {
                    int total = teamMap.getOrDefault(location, Collections.emptySet()).size();
                    int sg = sgTeamMap.getOrDefault(location, Collections.emptySet()).size();
                    int zb = Math.max(total - sg, 0);
                    sb.append(location).append("：施工").append(sg).append("套设备，准备").append(zb).append("套设备（共").append(total).append("套设备）\n");

                    Map<String, List<String>> wellMap = locationMap.get(location);
                    List<String> sortedWells = new ArrayList<>(wellMap.keySet());
                    Collections.sort(sortedWells);
                    for (String well : sortedWells) {
                        List<String> dynamics = wellMap.get(well);
                        // 过滤掉空字符串（包括null和仅空白字符）
                        List<String> nonEmptyDynamics = dynamics.stream()
                                .filter(s -> s != null && !s.trim().isEmpty())
                                .collect(Collectors.toList());
                        if (nonEmptyDynamics.isEmpty()) {
                            // 无有效动态时，只显示井名和一个分号
                            sb.append(well).append("，；\n");
                        } else {
                            String dynamicsStr = String.join("；", nonEmptyDynamics);
                            sb.append(well).append("，").append(dynamicsStr).append("；\n");
                        }
                    }
                }
                rate.setProductionSummary(sb.toString());
            }
        });
        // 删除projectDeptId为166的对象 克拉玛依项目部
        rates.removeIf(rate -> rate.getProjectDeptId() == 166);
        // 暂时不统计欧洲项目部 352
        rates.sort(Comparator.comparingInt(vo -> {
            Long deptId = vo.getProjectDeptId();
            // 获取当前projectDeptId 在 sortedProjectIds中 的索引
            int index = sortedProjectIds.indexOf(deptId);
            // 若不在集合中，用集合长度作为索引（排在所有指定项目部之后）
            return index != -1 ? index : sortedProjectIds.size();
        }));
        return rates;
    }

    /**
     * 瑞恒 公司总体 设备利用率
     * @return
     */
    @GetMapping("/rh/device/totalUtilizationRate")
    @PermitAll
    public CommonResult<BigDecimal> totalUtilizationRate(IotRhDailyReportPageReqVO reqVO) {
        if (ObjUtil.isEmpty(reqVO.getCreateTime())) {
            throw exception(IOT_DAILY_REPORT_TIME_NOT_EXISTS);
        }
        if (reqVO.getCreateTime().length < 2) {
            throw exception(IOT_DAILY_REPORT_TIME_NOT_EXISTS);
        }
        // 计算公司整体的设备利用率
        BigDecimal totalDeviceUtilization = BigDecimal.ZERO;

        List<Long> sortedProjectIds = new ArrayList<>();
        sortedProjectIds.add(164l); // 塔河项目部
        sortedProjectIds.add(165l); // 塔里木项目部
        sortedProjectIds.add(160l); // 吐哈项目部
        sortedProjectIds.add(256l); // 川庆项目部
        sortedProjectIds.add(269l); // 非洲项目部
        sortedProjectIds.add(273l); // 南美项目部
        sortedProjectIds.add(275l); // 中东项目部
        sortedProjectIds.add(282l); // 中亚项目部
        // 各项目部的设备利用率集合
        List<ProjectUtilizationRateVo> rates = new ArrayList<>();
        // 查询瑞恒 157l 所有项目部
        Set<Long> childDeptIds = deptService.getChildDeptIdListFromCache(157l);
        Map<Long, DeptDO> allDeptPair = deptService.getDeptMap(childDeptIds);
        Set<String> projectDeptNames = new HashSet<>();
        Set<Long> projectDeptIds = new HashSet<>();
        // key项目部id   value项目部名称
        Map<Long, String> projectPair = new HashMap<>();
        // key项目部id   value项目部包含的队伍id集合
        Map<Long, Set<Long>> projectTeamPair = new HashMap<>();
        // 队伍id 集合
        Set<Long> teamDepartmentIds = new HashSet<>();

        // 筛选瑞恒 主设备 rq_iot_rh_main_device_category
        Set<Long> mainDeviceCategoryIds = new HashSet<>();
        List<DictDataDO> constructionStatusDictData = dictDataService.getDictDataListByDictType("rq_iot_rh_main_device_category");
        if (CollUtil.isNotEmpty(constructionStatusDictData)) {
            constructionStatusDictData.forEach(data -> {
                String value = data.getValue();
                if (NumberUtil.isNumber(value)) {
                    Long longValue = Long.valueOf(value);
                    mainDeviceCategoryIds.add(longValue);
                }
            });
        }

        // 查询 瑞恒 所有设备 只统计包含 施工 状态设备的队伍
        IotDevicePageReqVO deviceReqVO = new IotDevicePageReqVO();
        deviceReqVO.setDeptIds(new ArrayList<>(childDeptIds));
        List<IotDeviceDO> allRhDevices = iotDeviceMapper.selectListAlone(deviceReqVO);
        Set<Long> haveDeviceDeptIds = new HashSet<>();
        if (CollUtil.isNotEmpty(allRhDevices)) {
            // 筛选出包含设备的队伍部门集合
            // 20260608 修改成 包含瑞恒主设备的 部门队伍id集合
            allRhDevices.forEach(device -> {
                if (mainDeviceCategoryIds.contains(device.getAssetClass())) {
                    haveDeviceDeptIds.add(device.getDeptId());
                }
            });
        }
        if (CollUtil.isNotEmpty(allDeptPair)) {
            allDeptPair.forEach((deptId, dept) -> {
                // 项目部
                if ("2".equals(dept.getType())) {
                    projectDeptIds.add(deptId);
                    projectDeptNames.add(dept.getName());
                    projectPair.put(deptId, dept.getName());
                }
                // 队伍
                if ("3".equals(dept.getType())) {
                    teamDepartmentIds.add(dept.getId());
                }
            });
            // 遍历所有部门 只筛选出有设备的队伍
            allDeptPair.forEach((deptId, dept) -> {
                // 找出每个项目部下的队伍
                if (projectPair.containsKey(dept.getParentId())) {
                    // 获得当前部门的上级项目部
                    projectPair.forEach((projectDeptId, projectDeptName) -> {
                        if (projectDeptId.equals(dept.getParentId()) && haveDeviceDeptIds.contains(deptId) && teamDepartmentIds.contains(deptId)) {
                            if (projectTeamPair.containsKey(projectDeptId)) {
                                Set<Long> teamIds = projectTeamPair.get(projectDeptId);
                                teamIds.add(deptId);
                                projectTeamPair.put(projectDeptId, teamIds);
                            } else {
                                Set<Long> teamIds = new HashSet<>();
                                teamIds.add(deptId);
                                projectTeamPair.put(projectDeptId, teamIds);
                            }
                        }
                    });
                }
            });
        }

        // 时间查询区间内如果包含 未发生的时间段(今年 本季度) 则设置 结束时间为 当前日期
        // 【调用公共方法】矫正未来时间区间
        LocalDateTimeUtils.correctFutureTimeRange(reqVO.getCreateTime());
        // 查询出指定时间区间内 已经填写的日报数量 存在注气时间是0 但是 注气量 不为0的情况
        // reqVO.setStatisticFlag("Y");
        List<IotRhDailyReportDO> dailyReports = iotRhDailyReportMapper.dailyReports(reqVO);
        // key项目部id     value项目部包含的队伍指定时间区域内日报数量
        Map<Long, Integer> projectReportPair = new HashMap<>();
        // key项目部id     value项目部注气量
        Map<Long, BigDecimal> projectGasInjectionPair = new HashMap<>();
        if (CollUtil.isNotEmpty(dailyReports)) {
            // 整理出每个项目部下的队伍填报的日报数量
            dailyReports.forEach(report -> {
                if (CollUtil.isNotEmpty(projectTeamPair)) {
                    projectTeamPair.forEach((projectDeptId, teamDeptIds) -> {
                        if (teamDeptIds.contains(report.getDeptId())) {
                            if (report.getDailyGasInjection().compareTo(BigDecimal.ZERO)>0 || report.getDailyWaterInjection().compareTo(BigDecimal.ZERO)>0) {
                                // 项目部日报数量 20260608 统计 注气量 or 注水量 > 0 的日报数量
                                if (projectReportPair.containsKey(projectDeptId)) {
                                    Integer tempCount = projectReportPair.get(projectDeptId);
                                    projectReportPair.put(projectDeptId, ++tempCount);
                                } else {
                                    projectReportPair.put(projectDeptId, 1);
                                }
                            }
                            // 项目部 注气量
                            if (projectGasInjectionPair.containsKey(projectDeptId)) {
                                BigDecimal tempGasInjection = projectGasInjectionPair.get(projectDeptId);
                                BigDecimal subtotal = tempGasInjection.add(report.getDailyGasInjection());
                                projectGasInjectionPair.put(projectDeptId, subtotal);
                            } else {
                                projectGasInjectionPair.put(projectDeptId, report.getDailyGasInjection());
                            }
                        }
                    });
                }
            });
            // 计算指定时间区间内包含的天数
            long daysCount;
            if (ObjUtil.isNotEmpty(reqVO.getCreateTime()) && reqVO.getCreateTime().length >= 2) {
                LocalDateTime start = reqVO.getCreateTime()[0];
                LocalDateTime end = reqVO.getCreateTime()[1];

                if (ObjUtil.isNotEmpty(start) && ObjUtil.isNotEmpty(end) && !end.isBefore(start)) {
                    // 使用ChronoUnit.DAYS.between计算天数差，并+1包含首尾两天
                    daysCount = ChronoUnit.DAYS.between(
                            start.toLocalDate(),
                            end.toLocalDate()
                    ) + 1;
                } else {
                    daysCount = 0L;
                }
            } else {
                daysCount = 0L;
            }

            //时间查询区间内 公司总的日报数量
            Integer totalReportCount = 0;
            // 时间查询区间内 公司总的队伍数量
            Integer totalTeamNum = 0;

            // 计算每个项目部的设备利用率
            if (CollUtil.isNotEmpty(projectTeamPair)) {
                for (Map.Entry<Long, Set<Long>> longSetEntry : projectTeamPair.entrySet()) {
                    Long projectDeptId = longSetEntry.getKey();
                    Set<Long> teamIds = longSetEntry.getValue();
                    Integer currentTeamNum = teamIds.size();
                    totalTeamNum = totalTeamNum + currentTeamNum;
                    if (projectReportPair.containsKey(projectDeptId)) {
                        Integer reportCount = projectReportPair.getOrDefault(projectDeptId, 0);
                        totalReportCount = totalReportCount + reportCount;
                        // 公司总的 设备利用率 公式 totalReportCount/(totalTeamNum*daysCount)
                    }
                }
                // 计算公司总的设备利用率
                if (totalTeamNum > 0 && daysCount > 0) {
                    totalDeviceUtilization = new BigDecimal((double) totalReportCount / (totalTeamNum * daysCount))
                            .setScale(4, RoundingMode.HALF_UP);
                }
            }
        }
        return success(totalDeviceUtilization);
    }

    /**
     * 瑞恒 设备利用率 按 队伍 统计
     * @return
     */
    @GetMapping("/rh/device/teamUtilizationRate")
    @PermitAll
    public CommonResult<List<TeamUtilizationRateVo>> teamUtilizationRate(IotRhDailyReportPageReqVO reqVO) {
        if (ObjUtil.isEmpty(reqVO.getCreateTime())) {
            throw exception(IOT_DAILY_REPORT_TIME_NOT_EXISTS);
        }
        if (reqVO.getCreateTime().length < 2) {
            throw exception(IOT_DAILY_REPORT_TIME_NOT_EXISTS);
        }
        // 必须传递 项目部id 查询队伍数据
        if (ObjUtil.isEmpty(reqVO.getDeptId())) {
            throw exception(IOT_DAILY_REPORT_DEPT_NOT_EXISTS);
        }

        // 指定项目部的各队伍设备利用率集合
        List<TeamUtilizationRateVo> rates = new ArrayList<>();

        // 查询指定项目部下的 队伍集合
        DeptListReqVO deptReqVO = new DeptListReqVO();
        deptReqVO.setDeptId(reqVO.getDeptId());
        List<DeptDO> projectTeams = deptService.getDeptListByParentId(deptReqVO);

        // 指定项目部下的 队伍id集合
        Set<Long> projectTeamIds = new HashSet<>();
        if (CollUtil.isNotEmpty(projectTeams)) {
            projectTeams.forEach(team -> {
                if ("3".equals(team.getType())) {
                    projectTeamIds.add(team.getId());
                }
            });
            // 如果是吐哈 将克拉玛依的队伍合并过来
            if (160 == reqVO.getDeptId()) {
                deptReqVO.setDeptId(166l);
                List<DeptDO> klmyTeams = deptService.getDeptListByParentId(deptReqVO);
                if (CollUtil.isNotEmpty(klmyTeams)) {
                    klmyTeams.forEach(team -> {
                        projectTeamIds.add(team.getId());
                    });
                }
            }
        }

        // 筛选瑞恒 主设备 rq_iot_rh_main_device_category
        Set<Long> mainDeviceCategoryIds = new HashSet<>();
        List<DictDataDO> constructionStatusDictData = dictDataService.getDictDataListByDictType("rq_iot_rh_main_device_category");
        if (CollUtil.isNotEmpty(constructionStatusDictData)) {
            constructionStatusDictData.forEach(data -> {
                String value = data.getValue();
                if (NumberUtil.isNumber(value)) {
                    Long longValue = Long.valueOf(value);
                    mainDeviceCategoryIds.add(longValue);
                }
            });
        }

        // 查询 项目部下 包含 施工 状态设备的队伍
        IotDevicePageReqVO deviceReqVO = new IotDevicePageReqVO();
        deviceReqVO.setDeptIds(new ArrayList<>(projectTeamIds));
        List<IotDeviceDO> allRhDevices = iotDeviceMapper.selectListAlone(deviceReqVO);
        Set<Long> haveDeviceDeptIds = new HashSet<>();
        if (CollUtil.isNotEmpty(allRhDevices)) {
            // 筛选出包含设备的队伍部门集合
            allRhDevices.forEach(device -> {
                if (mainDeviceCategoryIds.contains(device.getAssetClass())) {
                    haveDeviceDeptIds.add(device.getDeptId());
                }
            });
        }

        Map<Long, DeptDO> allDeptPair = deptService.getDeptMap(projectTeamIds);

        // 求 projectTeamIds 与 haveDeviceDeptIds 的交集
        Set<Long> intersectionTeamIds = new HashSet<>();
        if (CollUtil.isNotEmpty(projectTeamIds)) {
            projectTeamIds.forEach(teamId -> {
                if (haveDeviceDeptIds.contains(teamId)) {
                    intersectionTeamIds.add(teamId);
                }
            });
        }

        Set<String> projectDeptNames = new HashSet<>();
        Set<Long> projectDeptIds = new HashSet<>();
        // key项目部id   value项目部名称
        Map<Long, String> projectPair = new HashMap<>();
        // key队伍id   value队伍名称
        Map<Long, String> teamPair = new HashMap<>();
        // key项目部id   value项目部包含的队伍id集合
        Map<Long, Set<Long>> projectTeamPair = new HashMap<>();
        // key队伍id   value队伍日报数量
        Map<Long, Long> teamReportCountPair = new HashMap<>();
        if (CollUtil.isNotEmpty(allDeptPair)) {
            allDeptPair.forEach((deptId, dept) -> {
                if ("2".equals(dept.getType())) {
                    projectDeptIds.add(deptId);
                    projectDeptNames.add(dept.getName());
                    projectPair.put(deptId, dept.getName());
                }
                teamPair.put(deptId, dept.getName());
            });
            // 遍历所有部门
            allDeptPair.forEach((deptId, dept) -> {
                // 找出每个项目部下的队伍
                if (projectPair.containsKey(dept.getParentId())) {
                    // 获得当前部门的上级项目部
                    projectPair.forEach((projectDeptId, projectDept) -> {
                        if (projectDeptId.equals(dept.getParentId())) {
                            if (projectTeamPair.containsKey(projectDeptId)) {
                                Set<Long> teamIds = projectTeamPair.get(projectDeptId);
                                teamIds.add(deptId);
                                projectTeamPair.put(projectDeptId, teamIds);
                            } else {
                                Set<Long> teamIds = new HashSet<>();
                                teamIds.add(deptId);
                                projectTeamPair.put(projectDeptId, teamIds);
                            }
                        }
                    });
                }
            });
        }
        if (CollUtil.isNotEmpty(intersectionTeamIds)) {
            // 查询出指定时间区间内 指定队伍id集合 已经填写的日报数量
            reqVO.setDeptIds(intersectionTeamIds);
            // reqVO.setStatisticFlag("Y");
            List<IotRhDailyReportDO> dailyReports = iotRhDailyReportMapper.dailyReports(reqVO);
            // 筛选出每个队伍的日报
            if (CollUtil.isNotEmpty(dailyReports)) {
                // 整理出每个项队伍填报的日报数量
                dailyReports.forEach(report -> {
                    if (teamReportCountPair.containsKey(report.getDeptId())) {
                        Long tempCount = teamReportCountPair.get(report.getDeptId());
                        teamReportCountPair.put(report.getDeptId(), ++tempCount);
                    } else {
                        teamReportCountPair.put(report.getDeptId(), 1l);
                    }
                });
                // 计算指定时间区间内包含的天数
                long daysCount;
                if (ObjUtil.isNotEmpty(reqVO.getCreateTime()) && reqVO.getCreateTime().length >= 2) {
                    LocalDateTime start = reqVO.getCreateTime()[0];
                    LocalDateTime end = reqVO.getCreateTime()[1];

                    if (ObjUtil.isNotEmpty(start) && ObjUtil.isNotEmpty(end) && !end.isBefore(start)) {
                        // 使用ChronoUnit.DAYS.between计算天数差，并+1包含首尾两天
                        daysCount = ChronoUnit.DAYS.between(
                                start.toLocalDate(),
                                end.toLocalDate()
                        ) + 1;
                    } else {
                        daysCount = 0L;
                    }
                } else {
                    daysCount = 0L;
                }
                // 计算每个队伍的设备利用率
                if (CollUtil.isNotEmpty(intersectionTeamIds)) {
                    intersectionTeamIds.forEach(teamId -> {
                        TeamUtilizationRateVo rateVo = new TeamUtilizationRateVo();
                        rateVo.setProjectDeptId(reqVO.getDeptId());
                        rateVo.setTeamId(teamId);
                        rateVo.setCumulativeDays(daysCount);
                        if (teamPair.containsKey(teamId)) {
                            rateVo.setTeamName(teamPair.get(teamId));
                        }
                        // 匹配出当前小队 日报数量
                        Long reportCount = 0l;
                        if (teamReportCountPair.containsKey(teamId)) {
                            reportCount = teamReportCountPair.getOrDefault(teamId, 0l);
                            rateVo.setConstructionDays(reportCount);
                        }
                        // 当前小队 设备利用率 公式 reportCount/daysCount
                        // 计算设备利用率（处理除数为0的情况）
                        double rate = 0.0;
                        if (reportCount > 0 && daysCount > 0) {
                            rate = new BigDecimal((double) reportCount /  daysCount)
                                    .setScale(4, RoundingMode.HALF_UP)  // 保留4位小数，四舍五入
                                    .doubleValue();;
                        }
                        rateVo.setUtilizationRate(rate); // 存储计算结果
                        rates.add(rateVo);
                    });
                }
            }
        }
        rates.sort(Comparator.comparingDouble(TeamUtilizationRateVo::getUtilizationRate).reversed());
        return success(rates);
    }

    /**
     * 瑞鹰 设备利用率 按项目部统计
     * @return
     */
    @GetMapping("/ry/device/utilizationRate")
    @PermitAll
    public CommonResult<List<ProjectUtilizationRateVo>> ryUtilizationRate(IotRyDailyReportPageReqVO reqVO) {
        if (ObjUtil.isEmpty(reqVO.getCreateTime())) {
            throw exception(IOT_DAILY_REPORT_TIME_NOT_EXISTS);
        }
        if (reqVO.getCreateTime().length < 2) {
            throw exception(IOT_DAILY_REPORT_TIME_NOT_EXISTS);
        }
        // 各项目部的设备利用率集合
        List<ProjectUtilizationRateVo> rates = new ArrayList<>();
        // 查询瑞鹰 158l 所有项目部
        Set<Long> childDeptIds = deptService.getChildDeptIdListFromCache(158l);
        Map<Long, DeptDO> allDeptPair = deptService.getDeptMap(childDeptIds);
        Set<String> projectDeptNames = new HashSet<>();
        Set<Long> projectDeptIds = new HashSet<>();
        // key项目部id   value项目部名称
        Map<Long, String> projectPair = new HashMap<>();
        // key项目部id   value项目部包含的队伍id集合
        Map<Long, Set<Long>> projectTeamPair = new HashMap<>();
        // 队伍id 集合
        Set<Long> crewIds = new HashSet<>();
        if (CollUtil.isNotEmpty(allDeptPair)) {
            allDeptPair.forEach((deptId, dept) -> {
                if ("2".equals(dept.getType())) {
                    projectDeptIds.add(deptId);
                    projectDeptNames.add(dept.getName());
                    projectPair.put(deptId, dept.getName());
                }
                if ("3".equals(dept.getType())) {
                    // 队伍
                    crewIds.add(dept.getId());
                }
            });
            // 遍历所有部门
            allDeptPair.forEach((deptId, dept) -> {
                // 找出每个项目部下的队伍
                if (projectPair.containsKey(dept.getParentId()) && 0==dept.getStatus()) {
                    // 获得当前部门的上级项目部
                    projectPair.forEach((projectDeptId, projectDept) -> {
                        if (projectDeptId.equals(dept.getParentId())) {
                            if (projectTeamPair.containsKey(projectDeptId)) {
                                Set<Long> teamIds = projectTeamPair.get(projectDeptId);
                                teamIds.add(deptId);
                                projectTeamPair.put(projectDeptId, teamIds);
                            } else {
                                Set<Long> teamIds = new HashSet<>();
                                teamIds.add(deptId);
                                projectTeamPair.put(projectDeptId, teamIds);
                            }
                        }
                    });
                }
            });
        }
        // 查询出指定时间区间内 已经填写的日报数量
        // 瑞鹰区分 钻井 修井 日报
        // 钻井：日报状态 过滤掉 ‘等停dt’    修井：日报状态过滤掉 ‘等停dt’、‘整修zx’
        List<String> statuses = new ArrayList<>();
        statuses.add("dt");
        statuses.add("zx");
        reqVO.setStatuses(statuses);
        List<IotRyDailyReportDO> dailyReports = iotRyDailyReportMapper.dailyReports(reqVO);
        // key项目部id     value项目部包含的队伍指定时间区域内日报数量
        Map<Long, Integer> projectReportPair = new HashMap<>();
        if (CollUtil.isNotEmpty(dailyReports)) {
            // 整理出每个项目部下的队伍填报的日报数量
            dailyReports.forEach(report -> {
                if (CollUtil.isNotEmpty(projectTeamPair)) {
                    projectTeamPair.forEach((projectDeptId, teamDeptIds) -> {
                        if (teamDeptIds.contains(report.getDeptId())) {
                            if (projectReportPair.containsKey(projectDeptId)) {
                                Integer tempCount = projectReportPair.get(projectDeptId);
                                projectReportPair.put(projectDeptId, ++tempCount);
                            } else {
                                projectReportPair.put(projectDeptId, 1);
                            }
                        }
                    });
                }

            });
            // 计算指定时间区间内包含的天数
            long daysCount;
            if (ObjUtil.isNotEmpty(reqVO.getCreateTime()) && reqVO.getCreateTime().length >= 2) {
                LocalDateTime start = reqVO.getCreateTime()[0];
                LocalDateTime end = reqVO.getCreateTime()[1];
                if (ObjUtil.isNotEmpty(start) && ObjUtil.isNotEmpty(end) && !end.isBefore(start)) {
                    // 使用ChronoUnit.DAYS.between计算天数差，并+1包含首尾两天
                    daysCount = ChronoUnit.DAYS.between(
                            start.toLocalDate(),
                            end.toLocalDate()
                    ) + 1;
                } else {
                    daysCount = 0L;
                }
            } else {
                daysCount = 0L;
            }
            // 计算每个项目部的设备利用率
            if (CollUtil.isNotEmpty(projectTeamPair)) {
                projectTeamPair.forEach((projectDeptId, teamIds) -> {
                    ProjectUtilizationRateVo rateVo = new ProjectUtilizationRateVo();
                    rateVo.setProjectDeptId(projectDeptId);
                    if (projectPair.containsKey(projectDeptId)) {
                        rateVo.setProjectDeptName(projectPair.get(projectDeptId));
                    }
                    // 遍历每个项目部 获取每个项目部下队伍数量
                    Integer currentTeamNum = teamIds.size();
                    rateVo.setTeamCount(currentTeamNum);
                    rateVo.setCumulativeDays(currentTeamNum * daysCount);
                    double rate = 0.0;
                    // 匹配出当前项目部下 日报数量
                    if (projectReportPair.containsKey(projectDeptId)) {
                        Integer reportCount = projectReportPair.getOrDefault(projectDeptId, 0);
                        rateVo.setConstructionDays(reportCount);
                        // 当前项目部 设备利用率 公式 reportCount/(currentTeamNum*daysCount)
                        // 计算设备利用率（处理除数为0的情况）
                        if (currentTeamNum > 0 && daysCount > 0) {
                            rate = new BigDecimal((double) reportCount / (currentTeamNum * daysCount))
                                    .setScale(4, RoundingMode.HALF_UP)  // 保留4位小数，四舍五入
                                    .doubleValue();;
                        }
                    }
                    rateVo.setUtilizationRate(rate); // 存储计算结果
                    rates.add(rateVo);
                });
            }
        }
        rates.sort(Comparator.comparingDouble(ProjectUtilizationRateVo::getUtilizationRate).reversed());
        return success(rates);
    }

    /**
     * 瑞鹰 公司总的设备利用率
     * @return
     */
    @GetMapping("/ry/device/totalUtilizationRate")
    @PermitAll
    public CommonResult<BigDecimal> totalUtilizationRate(IotRyDailyReportPageReqVO reqVO) {
        if (ObjUtil.isEmpty(reqVO.getCreateTime())) {
            throw exception(IOT_DAILY_REPORT_TIME_NOT_EXISTS);
        }
        if (reqVO.getCreateTime().length < 2) {
            throw exception(IOT_DAILY_REPORT_TIME_NOT_EXISTS);
        }
        // 计算公司整体的设备利用率
        BigDecimal totalDeviceUtilization = BigDecimal.ZERO;
        // 查询瑞鹰 158l 所有项目部
        Set<Long> childDeptIds = deptService.getChildDeptIdListFromCache(158l);
        Map<Long, DeptDO> allDeptPair = deptService.getDeptMap(childDeptIds);
        Set<String> projectDeptNames = new HashSet<>();
        Set<Long> projectDeptIds = new HashSet<>();
        // key项目部id   value项目部名称
        Map<Long, String> projectPair = new HashMap<>();
        // key项目部id   value项目部包含的队伍id集合
        Map<Long, Set<Long>> projectTeamPair = new HashMap<>();
        // 队伍id 集合
        Set<Long> crewIds = new HashSet<>();
        if (CollUtil.isNotEmpty(allDeptPair)) {
            allDeptPair.forEach((deptId, dept) -> {
                if ("2".equals(dept.getType())) {
                    projectDeptIds.add(deptId);
                    projectDeptNames.add(dept.getName());
                    projectPair.put(deptId, dept.getName());
                }
                if ("3".equals(dept.getType())) {
                    // 队伍
                    crewIds.add(dept.getId());
                }
            });
            // 遍历所有部门
            allDeptPair.forEach((deptId, dept) -> {
                // 找出每个项目部下的队伍
                if (projectPair.containsKey(dept.getParentId()) && 0==dept.getStatus()) {
                    // 获得当前部门的上级项目部
                    projectPair.forEach((projectDeptId, projectDept) -> {
                        if (projectDeptId.equals(dept.getParentId())) {
                            if (projectTeamPair.containsKey(projectDeptId)) {
                                Set<Long> teamIds = projectTeamPair.get(projectDeptId);
                                teamIds.add(deptId);
                                projectTeamPair.put(projectDeptId, teamIds);
                            } else {
                                Set<Long> teamIds = new HashSet<>();
                                teamIds.add(deptId);
                                projectTeamPair.put(projectDeptId, teamIds);
                            }
                        }
                    });
                }
            });
        }

        // 时间查询区间内如果包含 未发生的时间段(今年 本季度) 则设置 结束时间为 当前日期
        // 【调用公共方法】矫正未来时间区间
        LocalDateTimeUtils.correctFutureTimeRange(reqVO.getCreateTime());

        // 查询出指定时间区间内 已经填写的日报数量
        // 瑞鹰区分 钻井 修井 日报
        // 钻井：日报状态 过滤掉 ‘等停dt’    修井：日报状态过滤掉 ‘等停dt’、‘整修zx’
        List<String> statuses = new ArrayList<>();
        statuses.add("dt");
        statuses.add("zx");
        reqVO.setStatuses(statuses);
        List<IotRyDailyReportDO> dailyReports = iotRyDailyReportMapper.dailyReports(reqVO);
        // key项目部id     value项目部包含的队伍指定时间区域内日报数量
        Map<Long, Integer> projectReportPair = new HashMap<>();
        if (CollUtil.isNotEmpty(dailyReports)) {
            // 整理出每个项目部下的队伍填报的日报数量
            dailyReports.forEach(report -> {
                if (CollUtil.isNotEmpty(projectTeamPair)) {
                    projectTeamPair.forEach((projectDeptId, teamDeptIds) -> {
                        if (teamDeptIds.contains(report.getDeptId())) {
                            if (projectReportPair.containsKey(projectDeptId)) {
                                Integer tempCount = projectReportPair.get(projectDeptId);
                                projectReportPair.put(projectDeptId, ++tempCount);
                            } else {
                                projectReportPair.put(projectDeptId, 1);
                            }
                        }
                    });
                }

            });
            // 计算指定时间区间内包含的天数
            long daysCount;
            if (ObjUtil.isNotEmpty(reqVO.getCreateTime()) && reqVO.getCreateTime().length >= 2) {
                LocalDateTime start = reqVO.getCreateTime()[0];
                LocalDateTime end = reqVO.getCreateTime()[1];
                if (ObjUtil.isNotEmpty(start) && ObjUtil.isNotEmpty(end) && !end.isBefore(start)) {
                    // 使用ChronoUnit.DAYS.between计算天数差，并+1包含首尾两天
                    daysCount = ChronoUnit.DAYS.between(
                            start.toLocalDate(),
                            end.toLocalDate()
                    ) + 1;
                } else {
                    daysCount = 0L;
                }
            } else {
                daysCount = 0L;
            }

            //时间查询区间内 公司总的日报数量
            Integer totalReportCount = 0;
            // 时间查询区间内 公司总的队伍数量
            Integer totalTeamNum = 0;
            if (CollUtil.isNotEmpty(projectTeamPair)) {
                for (Map.Entry<Long, Set<Long>> longSetEntry : projectTeamPair.entrySet()) {
                    Long projectDeptId = longSetEntry.getKey();
                    Set<Long> teamIds = longSetEntry.getValue();
                    Integer currentTeamNum = teamIds.size();
                    totalTeamNum = totalTeamNum + currentTeamNum;
                    if (projectReportPair.containsKey(projectDeptId)) {
                        Integer reportCount = projectReportPair.getOrDefault(projectDeptId, 0);
                        totalReportCount = totalReportCount + reportCount;
                        // 公司总的 设备利用率 公式 totalReportCount/(totalTeamNum*daysCount)
                    }
                }
                // 计算公司总的设备利用率
                if (totalTeamNum > 0 && daysCount > 0) {
                    totalDeviceUtilization = new BigDecimal((double) totalReportCount / (totalTeamNum * daysCount))
                            .setScale(4, RoundingMode.HALF_UP);
                    System.out.println("瑞鹰设备利用率-分子：" + totalReportCount);
                    System.out.println("瑞鹰设备利用率-分母：" + totalTeamNum);
                }
            }
        }
        return success(totalDeviceUtilization);
    }

    /**
     * 瑞鹰 NPT 队伍数量
     * @return
     */
    @GetMapping("/ry/device/nptCount")
    @PermitAll
    public CommonResult<List<NptCountVo>> nptCount(IotRyDailyReportPageReqVO reqVO) {
        if (ObjUtil.isEmpty(reqVO.getCreateTime())) {
            throw exception(IOT_DAILY_REPORT_TIME_NOT_EXISTS);
        }
        if (reqVO.getCreateTime().length < 2) {
            throw exception(IOT_DAILY_REPORT_TIME_NOT_EXISTS);
        }
        // 计算公司整体的设备利用率
        BigDecimal totalDeviceUtilization = BigDecimal.ZERO;
        // 查询瑞鹰 158l 所有项目部
        Set<Long> childDeptIds = deptService.getChildDeptIdListFromCache(158l);
        Map<Long, DeptDO> allDeptPair = deptService.getDeptMap(childDeptIds);
        Set<String> projectDeptNames = new HashSet<>();
        Set<Long> projectDeptIds = new HashSet<>();
        // key项目部id   value项目部名称
        Map<Long, String> projectPair = new HashMap<>();
        // key项目部id   value项目部包含的队伍id集合
        Map<Long, Set<Long>> projectTeamPair = new HashMap<>();
        // 队伍id 集合
        Set<Long> crewIds = new HashSet<>();
        if (CollUtil.isNotEmpty(allDeptPair)) {
            allDeptPair.forEach((deptId, dept) -> {
                if ("2".equals(dept.getType())) {
                    projectDeptIds.add(deptId);
                    projectDeptNames.add(dept.getName());
                    projectPair.put(deptId, dept.getName());
                }
                if ("3".equals(dept.getType())) {
                    // 队伍
                    crewIds.add(dept.getId());
                }
            });
            // 遍历所有部门
            allDeptPair.forEach((deptId, dept) -> {
                // 找出每个项目部下的队伍
                if (projectPair.containsKey(dept.getParentId()) && 0==dept.getStatus()) {
                    // 获得当前部门的上级项目部
                    projectPair.forEach((projectDeptId, projectDept) -> {
                        if (projectDeptId.equals(dept.getParentId())) {
                            if (projectTeamPair.containsKey(projectDeptId)) {
                                Set<Long> teamIds = projectTeamPair.get(projectDeptId);
                                teamIds.add(deptId);
                                projectTeamPair.put(projectDeptId, teamIds);
                            } else {
                                Set<Long> teamIds = new HashSet<>();
                                teamIds.add(deptId);
                                projectTeamPair.put(projectDeptId, teamIds);
                            }
                        }
                    });
                }
            });
        }
        // 查询出指定时间区间内 已经填写的日报数量
        // 瑞鹰区分 钻井 修井 日报
        List<String> statuses = new ArrayList<>();
        // statuses.add("dt");
        // statuses.add("zx");
        reqVO.setStatuses(statuses);
        List<IotRyDailyReportDO> dailyReports = iotRyDailyReportMapper.dailyReports(reqVO);
        // key项目部id     value项目部包含的队伍指定时间区域内日报数量
        Map<Long, Integer> projectReportPair = new HashMap<>();
        // 过滤掉 ‘设备保养、生产配合、待命’ 之外的非生产时间集合
        Map<String, Integer> nptTeamPair = new HashMap<>();
        List<NptCountVo> resultNptCounts = new ArrayList<>();
        if (CollUtil.isNotEmpty(dailyReports)) {
            // 整理出每个项目部下的队伍填报的日报数量
            dailyReports.forEach(report -> {
                if (CollUtil.isNotEmpty(projectTeamPair)) {
                    projectTeamPair.forEach((projectDeptId, teamDeptIds) -> {
                        if (teamDeptIds.contains(report.getDeptId())) {
                            /* if (projectReportPair.containsKey(projectDeptId)) {
                                Integer tempCount = projectReportPair.get(projectDeptId);
                                projectReportPair.put(projectDeptId, ++tempCount);
                            } else {
                                projectReportPair.put(projectDeptId, 1);
                            } */
                            // 统计日报下的非生产时间集合
                            BigDecimal accidentTime = report.getAccidentTime();
                            if (ObjUtil.isNotEmpty(accidentTime) && accidentTime.compareTo(BigDecimal.ZERO)>0) {
                                if (nptTeamPair.containsKey("工程质量")) {
                                    Integer tempCount = nptTeamPair.get("工程质量");
                                    nptTeamPair.put("工程质量", ++tempCount);
                                } else {
                                    nptTeamPair.put("工程质量", 1);
                                }
                            }
                            BigDecimal repairTime = report.getRepairTime();
                            if (ObjUtil.isNotEmpty(repairTime) && repairTime.compareTo(BigDecimal.ZERO)>0) {
                                if (nptTeamPair.containsKey("设备故障")) {
                                    Integer tempCount = nptTeamPair.get("设备故障");
                                    nptTeamPair.put("设备故障", ++tempCount);
                                } else {
                                    nptTeamPair.put("设备故障", 1);
                                }
                            }
                            BigDecimal complexityTime = report.getComplexityTime();
                            if (ObjUtil.isNotEmpty(complexityTime) && complexityTime.compareTo(BigDecimal.ZERO)>0) {
                                if (nptTeamPair.containsKey("技术受限")) {
                                    Integer tempCount = nptTeamPair.get("技术受限");
                                    nptTeamPair.put("技术受限", ++tempCount);
                                } else {
                                    nptTeamPair.put("技术受限", 1);
                                }
                            }
                            BigDecimal rectificationTime = report.getRectificationTime();
                            if (ObjUtil.isNotEmpty(rectificationTime) && rectificationTime.compareTo(BigDecimal.ZERO)>0) {
                                if (nptTeamPair.containsKey("生产组织")) {
                                    Integer tempCount = nptTeamPair.get("生产组织");
                                    nptTeamPair.put("生产组织", ++tempCount);
                                } else {
                                    nptTeamPair.put("生产组织", 1);
                                }
                            }
                            BigDecimal waitingStopTime = report.getWaitingStopTime();
                            if (ObjUtil.isNotEmpty(waitingStopTime) && waitingStopTime.compareTo(BigDecimal.ZERO)>0) {
                                if (nptTeamPair.containsKey("不可抗力")) {
                                    Integer tempCount = nptTeamPair.get("不可抗力");
                                    nptTeamPair.put("不可抗力", ++tempCount);
                                } else {
                                    nptTeamPair.put("不可抗力", 1);
                                }
                            }
                            BigDecimal partyaDesign = report.getPartyaDesign();
                            if (ObjUtil.isNotEmpty(partyaDesign) && partyaDesign.compareTo(BigDecimal.ZERO)>0) {
                                if (nptTeamPair.containsKey("甲方设计")) {
                                    Integer tempCount = nptTeamPair.get("甲方设计");
                                    nptTeamPair.put("甲方设计", ++tempCount);
                                } else {
                                    nptTeamPair.put("甲方设计", 1);
                                }
                            }
                            BigDecimal partyaPrepare = report.getPartyaPrepare();
                            if (ObjUtil.isNotEmpty(partyaPrepare) && partyaPrepare.compareTo(BigDecimal.ZERO)>0) {
                                if (nptTeamPair.containsKey("甲方准备")) {
                                    Integer tempCount = nptTeamPair.get("甲方准备");
                                    nptTeamPair.put("甲方准备", ++tempCount);
                                } else {
                                    nptTeamPair.put("甲方准备", 1);
                                }
                            }
                            BigDecimal partyaResource = report.getPartyaResource();
                            if (ObjUtil.isNotEmpty(partyaResource) && partyaResource.compareTo(BigDecimal.ZERO)>0) {
                                if (nptTeamPair.containsKey("甲方资源")) {
                                    Integer tempCount = nptTeamPair.get("甲方资源");
                                    nptTeamPair.put("甲方资源", ++tempCount);
                                } else {
                                    nptTeamPair.put("甲方资源", 1);
                                }
                            }
                            BigDecimal otherNptTime = report.getOtherNptTime();
                            if (ObjUtil.isNotEmpty(otherNptTime) && otherNptTime.compareTo(BigDecimal.ZERO)>0) {
                                if (nptTeamPair.containsKey("其它非生产时间")) {
                                    Integer tempCount = nptTeamPair.get("其它非生产时间");
                                    nptTeamPair.put("其它非生产时间", ++tempCount);
                                } else {
                                    nptTeamPair.put("其它非生产时间", 1);
                                }
                            }
                        }
                    });
                }
            });

            if (CollUtil.isNotEmpty(nptTeamPair)) {
                nptTeamPair.forEach((nptName, teamCount) -> {
                    NptCountVo countVo = new NptCountVo();
                    countVo.setNptName(nptName);
                    countVo.setTeamCount(teamCount);
                    resultNptCounts.add(countVo);
                });
            }
        }
        // 按照每种非生产时间队伍数量 降序排列
        resultNptCounts.sort(Comparator.comparingInt(NptCountVo::getTeamCount).reversed());
        return success(resultNptCounts);
    }

    /**
     * 瑞都 生产异常 数量
     * 无工作量 井场待命 维修设备 物资影响 异常/复杂
     * @return
     */
    @GetMapping("/rd/device/productionAbnormality")
    @PermitAll
    public CommonResult<List<NptCountVo>> productionAbnormality(IotRdDailyReportPageReqVO reqVO) {
        if (ObjUtil.isEmpty(reqVO.getCreateTime())) {
            throw exception(IOT_DAILY_REPORT_TIME_NOT_EXISTS);
        }
        if (reqVO.getCreateTime().length < 2) {
            throw exception(IOT_DAILY_REPORT_TIME_NOT_EXISTS);
        }
        // 查询瑞鹰 158l 所有项目部
        Set<Long> childDeptIds = deptService.getChildDeptIdListFromCache(158l);
        Map<Long, DeptDO> allDeptPair = deptService.getDeptMap(childDeptIds);
        Set<String> projectDeptNames = new HashSet<>();
        Set<Long> projectDeptIds = new HashSet<>();
        // key项目部id   value项目部名称
        Map<Long, String> projectPair = new HashMap<>();
        // 队伍id 集合
        Set<Long> crewIds = new HashSet<>();
        if (CollUtil.isNotEmpty(allDeptPair)) {
            allDeptPair.forEach((deptId, dept) -> {
                if ("2".equals(dept.getType())) {
                    projectDeptIds.add(deptId);
                    projectDeptNames.add(dept.getName());
                    projectPair.put(deptId, dept.getName());
                }
                if ("3".equals(dept.getType())) {
                    // 队伍
                    crewIds.add(dept.getId());
                }
            });
        }
        // 查询出指定时间区间内 已经填写的日报数量
        List<IotRdDailyReportDO> dailyReports = iotRdDailyReportMapper.dailyReports(reqVO);

        List<NptCountVo> resultNptCounts = new ArrayList<>();
        // no 无工作量
        Map<String, Integer> noStatusPair = new HashMap<>();
        // xcdm 井场待命
        Map<String, Integer> dmStatusPair = new HashMap<>();
        // wxz 维修设备
        Map<String, Integer> wxStatusPair = new HashMap<>();
        // wz 物资影响
        Map<String, Integer> wzStatusPair = new HashMap<>();
        // yc 异常/复杂
        Map<String, Integer> ycStatusPair = new HashMap<>();

        if (CollUtil.isNotEmpty(dailyReports)) {
            // 整理出每个项目部下的队伍填报的日报数量
            dailyReports.forEach(report -> {
                String rdStatus = report.getRdStatus();
                if ("no".equals(rdStatus)) {
                    if (noStatusPair.containsKey("no")) {
                        Integer tempNum = noStatusPair.get("no");
                        noStatusPair.put("no", ++tempNum);
                    } else {
                        noStatusPair.put("no", 1);
                    }
                }
                if ("xcdm".equals(rdStatus)) {
                    if (dmStatusPair.containsKey("xcdm")) {
                        Integer tempNum = dmStatusPair.get("xcdm");
                        dmStatusPair.put("xcdm", ++tempNum);
                    } else {
                        dmStatusPair.put("xcdm", 1);
                    }
                }
                if ("wxz".equals(rdStatus)) {
                    if (wxStatusPair.containsKey("wxz")) {
                        Integer tempNum = wxStatusPair.get("wxz");
                        wxStatusPair.put("wxz", ++tempNum);
                    } else {
                        wxStatusPair.put("wxz", 1);
                    }
                }
                if ("wz".equals(rdStatus)) {
                    if (wzStatusPair.containsKey("wz")) {
                        Integer tempNum = wzStatusPair.get("wz");
                        wzStatusPair.put("wz", ++tempNum);
                    } else {
                        wzStatusPair.put("wz", 1);
                    }
                }
                if ("yc".equals(rdStatus)) {
                    if (ycStatusPair.containsKey("yc")) {
                        Integer tempNum = ycStatusPair.get("yc");
                        ycStatusPair.put("yc", ++tempNum);
                    } else {
                        ycStatusPair.put("yc", 1);
                    }
                }
            });
        }
        // 无工作量
        NptCountVo noVo = new NptCountVo();
        noVo.setNptName("no");
        if (CollUtil.isNotEmpty(noStatusPair)) {
            Integer noStatusNum = noStatusPair.get("no");
            noVo.setTeamCount(noStatusNum);
        } else {
            noVo.setTeamCount(0);
        }
        resultNptCounts.add(noVo);
        // 井场待命
        NptCountVo dmVo = new NptCountVo();
        dmVo.setNptName("xcdm");
        if (CollUtil.isNotEmpty(dmStatusPair)) {
            Integer dmStatusNum = dmStatusPair.get("xcdm");
            dmVo.setTeamCount(dmStatusNum);
        } else {
            dmVo.setTeamCount(0);
        }
        resultNptCounts.add(dmVo);
        // 维修设备
        NptCountVo wxVo = new NptCountVo();
        wxVo.setNptName("wxz");
        if (CollUtil.isNotEmpty(wxStatusPair)) {
            Integer wxStatusNum = wxStatusPair.get("wxz");
            wxVo.setTeamCount(wxStatusNum);
        } else {
            wxVo.setTeamCount(0);
        }
        resultNptCounts.add(wxVo);
        // 物资影响
        NptCountVo wzVo = new NptCountVo();
        wzVo.setNptName("wz");
        if (CollUtil.isNotEmpty(wzStatusPair)) {
            Integer wzStatusNum = wzStatusPair.get("wz");
            wzVo.setTeamCount(wzStatusNum);
        } else {
            wzVo.setTeamCount(0);
        }
        resultNptCounts.add(wzVo);
        // 异常/复杂
        NptCountVo ycVo = new NptCountVo();
        ycVo.setNptName("yc");
        if (CollUtil.isNotEmpty(ycStatusPair)) {
            Integer ycStatusNum = ycStatusPair.get("yc");
            ycVo.setTeamCount(ycStatusNum);
        } else {
            ycVo.setTeamCount(0);
        }
        resultNptCounts.add(ycVo);
        // 按照每种非生产时间队伍数量 降序排列
        resultNptCounts.sort(Comparator.comparingInt(NptCountVo::getTeamCount).reversed());
        return success(resultNptCounts);
    }

    /**
     * 瑞鹰 设备利用率 按 队伍 统计
     * @return
     */
    @GetMapping("/ry/device/teamUtilizationRate")
    @PermitAll
    public CommonResult<List<TeamUtilizationRateVo>> ryTeamUtilizationRate(IotRyDailyReportPageReqVO reqVO) {
        if (ObjUtil.isEmpty(reqVO.getCreateTime())) {
            throw exception(IOT_DAILY_REPORT_TIME_NOT_EXISTS);
        }
        if (reqVO.getCreateTime().length < 2) {
            throw exception(IOT_DAILY_REPORT_TIME_NOT_EXISTS);
        }
        // 必须传递 项目部id 查询队伍数据
        if (ObjUtil.isEmpty(reqVO.getDeptId())) {
            throw exception(IOT_DAILY_REPORT_DEPT_NOT_EXISTS);
        }

        // 指定项目部的各队伍设备利用率集合
        List<TeamUtilizationRateVo> rates = new ArrayList<>();

        // 查询指定项目部下的 队伍集合
        DeptListReqVO deptReqVO = new DeptListReqVO();
        deptReqVO.setDeptId(reqVO.getDeptId());
        List<DeptDO> projectTeams = deptService.getDeptListByParentId(deptReqVO);
        // 指定项目部下的 队伍id集合
        Set<Long> projectTeamIds = new HashSet<>();
        if (CollUtil.isNotEmpty(projectTeams)) {
            projectTeams.forEach(team -> {
                if ("3".equals(team.getType())) {
                    projectTeamIds.add(team.getId());
                }
            });
        }

        Map<Long, DeptDO> allDeptPair = deptService.getDeptMap(projectTeamIds);

        Set<String> projectDeptNames = new HashSet<>();
        Set<Long> projectDeptIds = new HashSet<>();
        // key项目部id   value项目部名称
        Map<Long, String> projectPair = new HashMap<>();
        // key队伍id   value队伍名称
        Map<Long, String> teamPair = new HashMap<>();
        // key项目部id   value项目部包含的队伍id集合
        Map<Long, Set<Long>> projectTeamPair = new HashMap<>();
        // key队伍id   value队伍日报数量
        Map<Long, Long> teamReportCountPair = new HashMap<>();
        if (CollUtil.isNotEmpty(allDeptPair)) {
            allDeptPair.forEach((deptId, dept) -> {
                if (dept.getName().contains("项目部") ) {
                    projectDeptIds.add(deptId);
                    projectDeptNames.add(dept.getName());
                    projectPair.put(deptId, dept.getName());
                }
                teamPair.put(deptId, dept.getName());
            });
            // 遍历所有部门
            allDeptPair.forEach((deptId, dept) -> {
                // 找出每个项目部下的队伍
                if (projectPair.containsKey(dept.getParentId())) {
                    // 获得当前部门的上级项目部
                    projectPair.forEach((projectDeptId, projectDept) -> {
                        if (projectDeptId.equals(dept.getParentId())) {
                            if (projectTeamPair.containsKey(projectDeptId)) {
                                Set<Long> teamIds = projectTeamPair.get(projectDeptId);
                                teamIds.add(deptId);
                                projectTeamPair.put(projectDeptId, teamIds);
                            } else {
                                Set<Long> teamIds = new HashSet<>();
                                teamIds.add(deptId);
                                projectTeamPair.put(projectDeptId, teamIds);
                            }
                        }
                    });
                }
            });
        }
        if (CollUtil.isNotEmpty(projectTeamIds)) {
            // 查询出指定时间区间内 指定队伍id集合 已经填写的日报数量
            reqVO.setDeptIds(projectTeamIds);
            // 瑞鹰区分 钻井 修井 日报
            // 钻井：日报状态 过滤掉 ‘等停dt’    修井：日报状态过滤掉 ‘等停dt’、‘整修zx’
            List<String> statuses = new ArrayList<>();
            statuses.add("dt");
            statuses.add("zx");
            reqVO.setStatuses(statuses);
            List<IotRyDailyReportDO> dailyReports = iotRyDailyReportMapper.dailyReports(reqVO);
            // 筛选出每个队伍的日报
            if (CollUtil.isNotEmpty(dailyReports)) {
                // 整理出每个项队伍填报的日报数量
                dailyReports.forEach(report -> {
                    if (teamReportCountPair.containsKey(report.getDeptId())) {
                        Long tempCount = teamReportCountPair.get(report.getDeptId());
                        teamReportCountPair.put(report.getDeptId(), ++tempCount);
                    } else {
                        teamReportCountPair.put(report.getDeptId(), 1l);
                    }
                });
                // 计算指定时间区间内包含的天数
                long daysCount;
                if (ObjUtil.isNotEmpty(reqVO.getCreateTime()) && reqVO.getCreateTime().length >= 2) {
                    LocalDateTime start = reqVO.getCreateTime()[0];
                    LocalDateTime end = reqVO.getCreateTime()[1];
                    if (ObjUtil.isNotEmpty(start) && ObjUtil.isNotEmpty(end) && !end.isBefore(start)) {
                        // 使用ChronoUnit.DAYS.between计算天数差，并+1包含首尾两天
                        daysCount = ChronoUnit.DAYS.between(
                                start.toLocalDate(),
                                end.toLocalDate()
                        ) + 1;
                    } else {
                        daysCount = 0L;
                    }
                } else {
                    daysCount = 0L;
                }
                // 计算每个队伍的设备利用率
                if (CollUtil.isNotEmpty(projectTeamIds)) {
                    projectTeamIds.forEach(teamId -> {
                        TeamUtilizationRateVo rateVo = new TeamUtilizationRateVo();
                        rateVo.setProjectDeptId(reqVO.getDeptId());
                        rateVo.setTeamId(teamId);
                        rateVo.setCumulativeDays(daysCount);
                        if (teamPair.containsKey(teamId)) {
                            rateVo.setTeamName(teamPair.get(teamId));
                        }
                        // 匹配出当前小队 日报数量
                        Long reportCount = 0l;
                        if (teamReportCountPair.containsKey(teamId)) {
                            reportCount = teamReportCountPair.getOrDefault(teamId, 0l);
                            rateVo.setConstructionDays(reportCount);
                        }
                        // 当前小队 设备利用率 公式 reportCount/daysCount
                        // 计算设备利用率（处理除数为0的情况）
                        double rate = 0.0;
                        if (reportCount > 0 && daysCount > 0) {
                            rate = new BigDecimal((double) reportCount /  daysCount)
                                    .setScale(4, RoundingMode.HALF_UP)  // 保留4位小数，四舍五入
                                    .doubleValue();;
                        }
                        rateVo.setUtilizationRate(rate); // 存储计算结果
                        rates.add(rateVo);
                    });
                }
            }
        }
        rates.sort(Comparator.comparingDouble(TeamUtilizationRateVo::getUtilizationRate).reversed());
        return success(rates);
    }

    /**
     * 瑞都 设备利用率 按 项目部 统计
     * @return
     */
    @GetMapping("/rd/device/utilizationRate")
    @PermitAll
    public CommonResult<List<ProjectUtilizationRateVo>> rdUtilizationRate(IotRdDailyReportPageReqVO reqVO) {
        if (ObjUtil.isEmpty(reqVO.getCreateTime())) {
            throw exception(IOT_DAILY_REPORT_TIME_NOT_EXISTS);
        }
        if (reqVO.getCreateTime().length < 2) {
            throw exception(IOT_DAILY_REPORT_TIME_NOT_EXISTS);
        }
        // 各项目部的设备利用率集合
        List<ProjectUtilizationRateVo> rates = new ArrayList<>();
        // 查询瑞都 163l 所有项目部
        Set<Long> childDeptIds = deptService.getChildDeptIdListFromCache(163l);
        Map<Long, DeptDO> allDeptPair = deptService.getDeptMap(childDeptIds);
        Set<String> projectDeptNames = new HashSet<>();
        Set<Long> projectDeptIds = new HashSet<>();
        // key项目部id   value项目部名称
        Map<Long, String> projectPair = new HashMap<>();
        // key项目部id   value项目部包含的队伍id集合
        Map<Long, Set<Long>> projectTeamPair = new HashMap<>();
        // 设备ID到其所属部门ID的映射
        Map<Long, Long> deviceIdToDeptIdMap = new HashMap<>();
        // key项目部id     value项目部下包含的队伍的 压裂 连油 设备数量
        Map<Long, Integer> projectDevicePair = new HashMap<>();

        // 设备利用率逻辑调整 只筛选 压裂 连油 主设备 rq_iot_device_associate
        // 队伍日报中关联的主设备数量 /（队伍下所有主设备数量-封存设备数量）
        Set<Long> mainDeviceIds = new HashSet<>();
        Set<Long> fcMainDeviceIds = new HashSet<>();
        // key设备id   value设备所属部门id
        Map<Long, Long> mainDeviceIdPair = new HashMap<>();
        IotDeviceAssociatePageReqVO deviceAssocReqVO = new IotDeviceAssociatePageReqVO();
        deviceAssocReqVO.setPageSize(PageParam.PAGE_SIZE_NONE);
        deviceAssocReqVO.setDeptIds(childDeptIds);
        PageResult<IotDeviceAssociateDO> pageResult = iotDeviceAssociateMapper.selectPage(deviceAssocReqVO);
        if (ObjUtil.isNotEmpty(pageResult)) {
            List<IotDeviceAssociateDO> deviceAssociates = pageResult.getList();
            // 查询出所有瑞都压裂 连油主设备
            deviceAssociates.forEach(assoc -> {
                mainDeviceIds.add(assoc.getDeviceId());
                mainDeviceIdPair.put(assoc.getDeviceId(), assoc.getDeptId());
            });
        }

        if (CollUtil.isNotEmpty(allDeptPair)) {
            allDeptPair.forEach((deptId, dept) -> {
                if ("2".equals(dept.getType())) {
                    projectDeptIds.add(deptId);
                    projectDeptNames.add(dept.getName());
                    projectPair.put(deptId, dept.getName());
                }
            });
            // 遍历所有部门
            allDeptPair.forEach((deptId, dept) -> {
                // 找出每个项目部下的队伍
                if (projectPair.containsKey(dept.getParentId())) {
                    // 获得当前部门的上级项目部
                    projectPair.forEach((projectDeptId, projectDept) -> {
                        if (projectDeptId.equals(dept.getParentId())) {
                            if (projectTeamPair.containsKey(projectDeptId)) {
                                Set<Long> teamIds = projectTeamPair.get(projectDeptId);
                                teamIds.add(deptId);
                                projectTeamPair.put(projectDeptId, teamIds);
                            } else {
                                Set<Long> teamIds = new HashSet<>();
                                teamIds.add(deptId);
                                projectTeamPair.put(projectDeptId, teamIds);
                            }
                        }
                    });
                }
            });
            // 查询不同项目部下 包含的 压裂泵车26 连油主车设备31
            // 查询 连油主车 或 压裂泵车 相应的设备类别 id集合
            Set<Long> utilizeDeviceCategoryIds = new HashSet<>();
            IotProductClassifyListReqVO categoryReqVO = new IotProductClassifyListReqVO();
            categoryReqVO.setName("连油主车");
            List<IotProductClassifyDO> deviceCategories = iotProductClassifyMapper.selectList(categoryReqVO);
            if (CollUtil.isNotEmpty(deviceCategories)) {
                utilizeDeviceCategoryIds.add(deviceCategories.get(0).getId());
            }
            // 查询 压裂泵车 的设备类别
            categoryReqVO.setName("压裂泵车");
            List<IotProductClassifyDO> pumpCategories = iotProductClassifyMapper.selectList(categoryReqVO);
            if (CollUtil.isNotEmpty(pumpCategories)) {
                pumpCategories.forEach(category -> {
                    utilizeDeviceCategoryIds.add(category.getId());
                });
            }
            IotDevicePageReqVO deviceReqVO = new IotDevicePageReqVO();
            deviceReqVO.setAssetClasses(new ArrayList<>(utilizeDeviceCategoryIds));
            List<IotDeviceDO> utilizeDevices = iotDeviceMapper.selectListAlone(deviceReqVO);
            // 筛选出项目部下包含的队伍的设备数量

            Set<Long> deviceIds = new HashSet<>();

            if (CollUtil.isNotEmpty(utilizeDevices)) {
                utilizeDevices.forEach(device -> {
                    // 存储设备ID与所属部门ID的映射
                    deviceIdToDeptIdMap.put(device.getId(), device.getDeptId());
                    // 筛选出各项目部下的 压裂 连油 设备
                    projectTeamPair.forEach((projectId, teamIds) -> {
                        if (projectId.equals(device.getDeptId()) || teamIds.contains(device.getDeptId())) {
                            if (projectDevicePair.containsKey(projectId)) {
                                Integer tempCount = projectDevicePair.get(projectId);
                                projectDevicePair.put(projectId, ++tempCount);
                            } else {
                                projectDevicePair.put(projectId, 1);
                            }
                            // 找出各项目部下的设备id集合 用来查询日报
                            deviceIds.add(device.getId());
                        }
                    });
                });
            }
        }
        // 查询出指定时间区间内 已经填写的日报 再根据设备id 进行筛选 通过设备id 建立项目部 与 日报数量之间的关联
        // 判断日报中 device_ids 字段中每个设备 是否属于需要统计的 压裂 连油 设备
        List<IotRdDailyReportDO> dailyReports = iotRdDailyReportMapper.dailyReports(reqVO);
        // key项目部id     value项目部包含的队伍指定时间区域内日报数量
        Map<Long, Integer> projectReportPair = new HashMap<>();
        if (CollUtil.isNotEmpty(dailyReports)) {
            // 整理出每个项目部下的队伍填报的日报数量
            dailyReports.forEach(report -> {
                if (CollUtil.isNotEmpty(projectTeamPair)) {
                    projectTeamPair.forEach((projectDeptId, teamDeptIds) -> {
                        Set<Long> tempDeviceIds = report.getDeviceIds();
                        // 判断 集合 tempDeviceIds 中的任意的 ‘设备id’ 是否包含在 集合 teamDeptIds 中
                        // 判断tempDeviceIds中的任意设备所属部门是否在当前项目部的队伍部门中
                        boolean hasMatchingDevice = CollUtil.isNotEmpty(tempDeviceIds) && tempDeviceIds.stream()
                                .map(deviceIdToDeptIdMap::get) // 通过映射表获取设备所属部门ID
                                .filter(Objects::nonNull) // 过滤掉非统计范围内的设备（避免空指针）
                                .anyMatch(teamDeptIds::contains); // 任意设备所属部门在队伍部门中则匹配
                        if (hasMatchingDevice) {
                            if (projectReportPair.containsKey(projectDeptId)) {
                                Integer tempCount = projectReportPair.get(projectDeptId);
                                projectReportPair.put(projectDeptId, ++tempCount);
                            } else {
                                projectReportPair.put(projectDeptId, 1);
                            }
                        }
                    });
                }
            });
            // 计算指定时间区间内包含的天数
            long daysCount;
            if (ObjUtil.isNotEmpty(reqVO.getCreateTime()) && reqVO.getCreateTime().length >= 2) {
                LocalDateTime start = reqVO.getCreateTime()[0];
                LocalDateTime end = reqVO.getCreateTime()[1];
                if (ObjUtil.isNotEmpty(start) && ObjUtil.isNotEmpty(end) && !end.isBefore(start)) {
                    // 使用ChronoUnit.DAYS.between计算天数差，并+1包含首尾两天
                    daysCount = ChronoUnit.DAYS.between(
                            start.toLocalDate(),
                            end.toLocalDate()
                    ) + 1;
                } else {
                    daysCount = 0L;
                }
            } else {
                daysCount = 0L;
            }
            // 计算每个项目部的设备利用率
            if (CollUtil.isNotEmpty(projectDevicePair)) {
                projectDevicePair.forEach((projectDeptId, deviceNum) -> {
                    ProjectUtilizationRateVo rateVo = new ProjectUtilizationRateVo();
                    rateVo.setProjectDeptId(projectDeptId);
                    if (projectPair.containsKey(projectDeptId)) {
                        rateVo.setProjectDeptName(projectPair.get(projectDeptId));
                    }
                    // 遍历每个项目部 获取每个项目部下 压裂 连油 设备数量
                    rateVo.setTeamCount(deviceNum);
                    rateVo.setCumulativeDays(deviceNum * daysCount);
                    double rate = 0.0;
                    // 匹配出当前项目部下 日报数量
                    if (projectReportPair.containsKey(projectDeptId)) {
                        Integer reportCount = projectReportPair.getOrDefault(projectDeptId, 0);
                        rateVo.setConstructionDays(reportCount);
                        // 当前项目部 设备利用率 公式 reportCount/(currentTeamNum*daysCount)
                        // 计算设备利用率（处理除数为0的情况）
                        if (deviceNum > 0 && daysCount > 0) {
                            rate = new BigDecimal((double) reportCount / (deviceNum * daysCount))
                                    .setScale(4, RoundingMode.HALF_UP)  // 保留4位小数，四舍五入
                                    .doubleValue();;
                        }
                    }
                    rateVo.setUtilizationRate(rate); // 存储计算结果
                    rates.add(rateVo);
                });
            }
        }
        // 将返回列表中的 部门名称 去除多语言标识
        // 处理projectDeptName，截取~~首次出现前的字符串
        if (CollUtil.isNotEmpty(rates)) {
            rates.forEach(rateVo -> {
                String originalName = rateVo.getProjectDeptName();
                if (StrUtil.isNotBlank(originalName) && originalName.contains("~~")) {
                    // 截取首次~~之前的部分
                    String processedName = originalName.substring(0, originalName.indexOf("~~"));
                    rateVo.setProjectDeptName(processedName);
                }
                // 空值或无~~标识时，保留原名称
            });
        }
        // 日报应用前先模拟数据
        rates.sort(Comparator.comparingDouble(ProjectUtilizationRateVo::getUtilizationRate).reversed());
        return success(rates);
    }

    /**
     * 瑞都 时间区间内整体的 设备利用率
     * @return
     */
    @GetMapping("/rd/device/totalUtilizationRate")
    @PermitAll
    public CommonResult<BigDecimal> rdTotalUtilizationRate(IotRdDailyReportPageReqVO reqVO) {
        if (ObjUtil.isEmpty(reqVO.getCreateTime())) {
            throw exception(IOT_DAILY_REPORT_TIME_NOT_EXISTS);
        }
        if (reqVO.getCreateTime().length < 2) {
            throw exception(IOT_DAILY_REPORT_TIME_NOT_EXISTS);
        }
        // 计算公司整体的设备利用率
        BigDecimal totalDeviceUtilization = BigDecimal.ZERO;

        // 查询瑞都 163l 所有项目部
        Set<Long> childDeptIds = deptService.getChildDeptIdListFromCache(163l);
        Map<Long, DeptDO> allDeptPair = deptService.getDeptMap(childDeptIds);
        Set<String> projectDeptNames = new HashSet<>();
        Set<Long> projectDeptIds = new HashSet<>();
        // key项目部id   value项目部名称
        Map<Long, String> projectPair = new HashMap<>();
        // key项目部id   value项目部包含的队伍id集合
        Map<Long, Set<Long>> projectTeamPair = new HashMap<>();
        // 设备ID到其所属部门ID的映射
        Map<Long, Long> deviceIdToDeptIdMap = new HashMap<>();

        // 20260611 设备利用率逻辑调整 只筛选 压裂 连油 主设备 rq_iot_device_associate
        // 队伍日报中关联的主设备数量 /（队伍下所有主设备数量-封存设备数量）
        Set<Long> mainDeviceIds = new HashSet<>();
        Set<Long> fcMainDeviceIds = new HashSet<>();
        // key设备id   value设备所属部门id
        Map<Long, Long> mainDeviceIdPair = new HashMap<>();
        IotDeviceAssociatePageReqVO deviceAssocReqVO = new IotDeviceAssociatePageReqVO();
        deviceAssocReqVO.setPageSize(PageParam.PAGE_SIZE_NONE);
        deviceAssocReqVO.setDeptIds(childDeptIds);
        PageResult<IotDeviceAssociateDO> pageResult = iotDeviceAssociateMapper.selectPage(deviceAssocReqVO);
        if (ObjUtil.isNotEmpty(pageResult)) {
            List<IotDeviceAssociateDO> deviceAssociates = pageResult.getList();
            // 查询出所有瑞都压裂 连油主设备
            deviceAssociates.forEach(assoc -> {
                mainDeviceIds.add(assoc.getDeviceId());
                mainDeviceIdPair.put(assoc.getDeviceId(), assoc.getDeptId());
            });
        }
        // 过滤掉 封存 的 压裂 连油 主设备id集合
        Set<Long> abDeviceIds = new HashSet<>();

        if (CollUtil.isNotEmpty(allDeptPair)) {
            allDeptPair.forEach((deptId, dept) -> {
                if ("2".equals(dept.getType())) {
                    projectDeptIds.add(deptId);
                    projectDeptNames.add(dept.getName());
                    projectPair.put(deptId, dept.getName());
                }
            });
            // 遍历所有部门
            allDeptPair.forEach((deptId, dept) -> {
                // 找出每个项目部下的队伍
                if (projectPair.containsKey(dept.getParentId())) {
                    // 获得当前部门的上级项目部
                    projectPair.forEach((projectDeptId, projectDept) -> {
                        if (projectDeptId.equals(dept.getParentId())) {
                            if (projectTeamPair.containsKey(projectDeptId)) {
                                Set<Long> teamIds = projectTeamPair.get(projectDeptId);
                                teamIds.add(deptId);
                                projectTeamPair.put(projectDeptId, teamIds);
                            } else {
                                Set<Long> teamIds = new HashSet<>();
                                teamIds.add(deptId);
                                projectTeamPair.put(projectDeptId, teamIds);
                            }
                        }
                    });
                }
            });

            IotDevicePageReqVO deviceReqVO = new IotDevicePageReqVO();
            deviceReqVO.setDeviceIds(new ArrayList<>(mainDeviceIds));
            List<IotDeviceDO> utilizeDevices = iotDeviceMapper.selectListAlone(deviceReqVO);
            // 筛选出项目部下包含的队伍的设备数量
            // 过滤掉 封存 的 压裂 连油 主设备
            if (CollUtil.isNotEmpty(utilizeDevices)) {
                utilizeDevices.forEach(device -> {
                    /* if ("fc".equals(device.getDeviceStatus())) {
                        fcMainDeviceIds.add(device.getId());
                    } else { */
                        abDeviceIds.add(device.getId());
                    // }
                });
            }
        }
        // 查询出指定时间区间内 已经填写的日报 再根据设备id 进行筛选 通过设备id 建立项目部 与 日报数量之间的关联
        // 判断日报中 device_ids 字段中每个设备 是否属于需要统计的 压裂 连油 设备
        List<IotRdDailyReportDO> dailyReports = iotRdDailyReportMapper.dailyReports(reqVO);
        // key项目部id     value项目部包含的队伍指定时间区域内日报数量
        Map<Long, Integer> projectReportPair = new HashMap<>();
        // 日报涉及到的施工设备id集合
        Set<Long> reportDeviceIds = new HashSet<>();
        if (CollUtil.isNotEmpty(dailyReports)) {
            // 整理出每个项目部下的队伍填报的日报数量
            dailyReports.forEach(report -> {
                // 筛选出日报中施工的 设备id集合
                if (CollUtil.isNotEmpty(report.getDeviceIds())) {
                    reportDeviceIds.addAll(report.getDeviceIds());
                }
                if (CollUtil.isNotEmpty(projectTeamPair)) {
                    projectTeamPair.forEach((projectDeptId, teamDeptIds) -> {
                        Set<Long> tempDeviceIds = report.getDeviceIds();
                        // 判断 集合 tempDeviceIds 中的任意的 ‘设备id’ 是否包含在 集合 teamDeptIds 中
                        // 判断tempDeviceIds中的任意设备所属部门是否在当前项目部的队伍部门中
                        boolean hasMatchingDevice = CollUtil.isNotEmpty(tempDeviceIds) && tempDeviceIds.stream()
                                .map(deviceIdToDeptIdMap::get) // 通过映射表获取设备所属部门ID
                                .filter(Objects::nonNull) // 过滤掉非统计范围内的设备（避免空指针）
                                .anyMatch(teamDeptIds::contains); // 任意设备所属部门在队伍部门中则匹配
                        if (hasMatchingDevice) {
                            if (projectReportPair.containsKey(projectDeptId)) {
                                Integer tempCount = projectReportPair.get(projectDeptId);
                                projectReportPair.put(projectDeptId, ++tempCount);
                            } else {
                                projectReportPair.put(projectDeptId, 1);
                            }
                        }
                    });
                }
            });

            // 计算公司整体的设备利用率
            // 指定时间范围内 日报中所有施工的设备数量/总设备数量 (A B类)
            // abDeviceIds所有AB类设备  reportDeviceIds日报中用到的所有设备 交集求出日报中使用到的AB类设备
            if (CollUtil.isNotEmpty(abDeviceIds) && CollUtil.isNotEmpty(reportDeviceIds)) {
                // 1. 求交集：实际使用的A B类设备
                Set<Long> utilizedDeviceIds = reportDeviceIds.stream()
                        .filter(abDeviceIds::contains)
                        .collect(Collectors.toSet());
                // 2. 计算设备利用率（实际使用设备数 / 总设备数）
                // 转换为BigDecimal进行计算，保留4位小数
                totalDeviceUtilization = BigDecimal.valueOf(utilizedDeviceIds.size())
                        .divide(BigDecimal.valueOf(abDeviceIds.size()), 4, RoundingMode.HALF_UP);
            }
        }

        return success(totalDeviceUtilization);
    }

    /**
     * 瑞都 时间区间内整体的 工作量统计
     * 压裂层数 连油井数
     * @return
     */
    @GetMapping("/rd/device/workloadStatistics")
    @PermitAll
    public CommonResult<Map<String, Object>> rdWorkloadStatistics(IotRdDailyReportPageReqVO reqVO) {
        if (ObjUtil.isEmpty(reqVO.getCreateTime())) {
            throw exception(IOT_DAILY_REPORT_TIME_NOT_EXISTS);
        }
        if (reqVO.getCreateTime().length < 2) {
            throw exception(IOT_DAILY_REPORT_TIME_NOT_EXISTS);
        }

        Map<String, Object> result = new HashMap<>();
        result.put("layers", 0.0);
        result.put("wells", 0.0);

        // 查询出指定时间区间内 已经填写的日报 再根据设备id 进行筛选 通过设备id 建立项目部 与 日报数量之间的关联
        // 判断日报中 device_ids 字段中每个设备 是否属于需要统计的 压裂 连油 设备
        List<IotRdDailyReportDO> dailyReports = iotRdDailyReportMapper.dailyReports(reqVO);
        // 日报涉及到的施工设备id集合
        Set<Long> reportDeviceIds = new HashSet<>();
        // key工作量标识   value累计 段数 累计施工-层
        Map<String, BigDecimal> cumulativeWorkingLayersPair = new HashMap<>();
        // 连油井数
        Set<Long> cumulativeWells = new HashSet<>();
        if (CollUtil.isNotEmpty(dailyReports)) {
            // 整理出每个项目部下的队伍填报的日报数量
            dailyReports.forEach(report -> {
                // 筛选出日报中施工的 设备id集合
                if (CollUtil.isNotEmpty(report.getDeviceIds())) {
                    reportDeviceIds.addAll(report.getDeviceIds());
                }
                // 设置每个任务的工作量数据  单位相同的工作量值作合并处理
                List<IotTaskAttrModelProperty> taskAttrs = report.getExtProperty();
                // 段数 累计施工-层
                BigDecimal tempTotalCumulativeWorkingLayers = BigDecimal.ZERO;
                if (CollUtil.isNotEmpty(taskAttrs)) {
                    for (IotTaskAttrModelProperty attr : taskAttrs) {
                        // 工作量单位
                        String unit = attr.getUnit();
                        // 工作量属性的实际值
                        String actualValueStr = attr.getActualValue();
                        // 处理实际值：避免null或非数字字符串导致的异常
                        BigDecimal actualValue = BigDecimal.ZERO;
                        if (StrUtil.isNotBlank(actualValueStr)) {
                            try {
                                actualValue = new BigDecimal(actualValueStr);
                            } catch (NumberFormatException e) {
                                // 若字符串格式错误，默认按0处理（可根据业务调整）
                                actualValue = BigDecimal.ZERO;
                            }
                        }
                        if ("段数".equals(unit)) {
                            // 累计施工层
                            tempTotalCumulativeWorkingLayers = tempTotalCumulativeWorkingLayers.add(actualValue);
                            if (cumulativeWorkingLayersPair.containsKey("cumulativeWorkingLayers")) {
                                BigDecimal tempWorkingLayer = cumulativeWorkingLayersPair.get("cumulativeWorkingLayers");
                                cumulativeWorkingLayersPair.put("cumulativeWorkingLayers", tempTotalCumulativeWorkingLayers.add(tempWorkingLayer));
                            } else {
                                cumulativeWorkingLayersPair.put("cumulativeWorkingLayers", tempTotalCumulativeWorkingLayers);
                            }
                        }
                    }
                }
                if (ObjUtil.isNotEmpty(report.getTaskId()) && "wg".equals(report.getRdStatus())) {
                    cumulativeWells.add(report.getTaskId());
                }
            });

        }
        // 压裂层数
        if (CollUtil.isNotEmpty(cumulativeWorkingLayersPair)) {
            cumulativeWorkingLayersPair.forEach((key, layers) -> {
                result.put("layers", layers);
            });
        }
        // 连油井数 完工 的任务井
        if (CollUtil.isNotEmpty(cumulativeWells)) {
            result.put("wells", cumulativeWells.size());
        }
        return success(result);
    }

    /**
     * 瑞都 设备利用率 按 项目部 统计
     * @return
     */
    @GetMapping("/rd/device/utilizationRates")
    @PermitAll
    public CommonResult<List<ProjectUtilizationRateVo>> rdUtilizationRates(IotRdDailyReportPageReqVO reqVO) {
        if (ObjUtil.isEmpty(reqVO.getCreateTime())) {
            throw exception(IOT_DAILY_REPORT_TIME_NOT_EXISTS);
        }
        if (reqVO.getCreateTime().length < 2) {
            throw exception(IOT_DAILY_REPORT_TIME_NOT_EXISTS);
        }
        // 各项目部的设备利用率集合
        List<ProjectUtilizationRateVo> rates = new ArrayList<>();
        // 查询瑞都 163l 所有项目部
        Set<Long> childDeptIds = deptService.getChildDeptIdListFromCache(163l);
        Map<Long, DeptDO> allDeptPair = deptService.getDeptMap(childDeptIds);
        Set<String> projectDeptNames = new HashSet<>();
        Set<Long> projectDeptIds = new HashSet<>();
        // key项目部id   value项目部名称
        Map<Long, String> projectPair = new HashMap<>();
        // key队伍id   value项目部id
        Map<Long, Long> teamIdProjectIdPair = new HashMap<>();
        // key项目部id   value A+B类设备id集合
        Map<Long, Set<Long>> projectABDeviceIdPair = new HashMap<>();
        // key项目部id   value 日报中A+B类设备id集合
        Map<Long, Set<Long>> projectReportABDeviceIdPair = new HashMap<>();
        // key项目部id   value项目部包含的队伍id集合
        Map<Long, Set<Long>> projectTeamPair = new HashMap<>();
        // 设备ID到其所属部门ID的映射
        Map<Long, Long> deviceIdToDeptIdMap = new HashMap<>();
        // key项目部id     value项目部下包含的队伍的 压裂 连油 设备数量
        Map<Long, Integer> projectDevicePair = new HashMap<>();
        // 瑞都 A B 类设备id 集合
        Set<Long> abDeviceCategoryIds = new HashSet<>();
        // 查询所有瑞都产品类别包含 A B 类
        IotProductClassifyListReqVO deviceCategoryReqVO = new IotProductClassifyListReqVO();
        List<IotProductClassifyDO> allDeviceCategories = iotProductClassifyMapper.selectList(deviceCategoryReqVO);
        if (CollUtil.isNotEmpty(allDeviceCategories)) {
            allDeviceCategories.forEach(category -> {
                if ("A".equals(category.getRemark())) {
                    abDeviceCategoryIds.add(category.getId());
                }
            });
        }
        // 查询 瑞都 施工状态 字典数据 筛选出施工设备为 LY 的记录
        Set<String> lyStatuses = new HashSet<>();
        List<DictDataDO> rdStatuses = dictDataService.getDictDataListByDictType("rdStatus");
        if (CollUtil.isNotEmpty(rdStatuses)) {
            rdStatuses.forEach(tech -> {
                if ("LY".equals(tech.getRemark())) {
                    lyStatuses.add(tech.getValue());
                }
            });
        }
        if (CollUtil.isNotEmpty(allDeptPair)) {
            allDeptPair.forEach((deptId, dept) -> {
                if ("2".equals(dept.getType())) {
                    projectDeptIds.add(deptId);
                    projectDeptNames.add(dept.getName());
                    projectPair.put(deptId, dept.getName());
                }
            });
            // 遍历所有部门
            allDeptPair.forEach((deptId, dept) -> {
                // 找出每个项目部下的队伍
                if (projectPair.containsKey(dept.getParentId())) {
                    // 获得当前部门的上级项目部
                    projectPair.forEach((projectDeptId, projectDept) -> {
                        if (projectDeptId.equals(dept.getParentId())) {
                            if (projectTeamPair.containsKey(projectDeptId)) {
                                Set<Long> teamIds = projectTeamPair.get(projectDeptId);
                                teamIds.add(deptId);
                                projectTeamPair.put(projectDeptId, teamIds);
                            } else {
                                Set<Long> teamIds = new HashSet<>();
                                teamIds.add(deptId);
                                projectTeamPair.put(projectDeptId, teamIds);
                            }
                        }
                    });
                    // 设置每个队伍与上级项目部对应关系
                    teamIdProjectIdPair.put(dept.getId(), dept.getParentId());
                }
            });
            // 查询瑞都所有设备
            IotDevicePageReqVO deviceReqVO = new IotDevicePageReqVO();
            deviceReqVO.setDeptIds(new ArrayList<>(childDeptIds));
            List<IotDeviceDO> rdDevices = iotDeviceMapper.selectListAlone(deviceReqVO);
            // 筛选每个项目部 A B 类设备id集合
            if (CollUtil.isNotEmpty(rdDevices)) {
                rdDevices.forEach(device -> {
                    Long projectId = 0l;
                    if (teamIdProjectIdPair.containsKey(device.getDeptId())) {
                        projectId = teamIdProjectIdPair.get(device.getDeptId());
                    }
                    if (projectDeptIds.contains(device.getDeptId())) {
                        projectId = device.getDeptId();
                    }
                    if (abDeviceCategoryIds.contains(device.getAssetClass())) {
                        if (projectABDeviceIdPair.containsKey(projectId)) {
                            Set<Long> tempDeviceIds = projectABDeviceIdPair.get(projectId);
                            tempDeviceIds.add(device.getId());
                            projectABDeviceIdPair.put(projectId, tempDeviceIds);
                        } else {
                            Set<Long> tempDeviceIds = new HashSet<>();
                            tempDeviceIds.add(device.getId());
                            projectABDeviceIdPair.put(projectId, tempDeviceIds);
                        }
                    }
                });
            }
        }
        // 查询出指定时间区间内 已经填写的日报 再根据设备id 进行筛选 通过设备id 建立项目部 与 日报数量之间的关联
        // 判断日报中 device_ids 字段中每个设备 是否属于需要统计的 压裂 连油 设备
        List<IotRdDailyReportDO> dailyReports = iotRdDailyReportMapper.dailyReports(reqVO);
        // key项目部id     value项目部包含的队伍指定时间区域内日报数量
        Map<Long, Integer> projectReportPair = new HashMap<>();
        if (CollUtil.isNotEmpty(dailyReports)) {
            // 整理出每个项目部下的队伍填报的日报数量
            dailyReports.forEach(report -> {
                // 筛选出 可以统计 设备利用率的 日报状态 动迁 施工 施工准备
                // 区分不同项目部的日报
                if (lyStatuses.contains(report.getRdStatus())) {
                    Set<Long> reportDeviceIds = report.getDeviceIds();
                    // 获得当前日报施工队伍的上级项目部
                    if (teamIdProjectIdPair.containsKey(report.getDeptId())) {
                        Long projectId = teamIdProjectIdPair.get(report.getDeptId());
                        if (projectABDeviceIdPair.containsKey(projectId)) {
                            // 项目部下所有的AB类设备id集合
                            Set<Long> tempReportDeviceIds = projectABDeviceIdPair.get(projectId);
                            Set<Long> crossDeviceIds = CollUtil.isNotEmpty(reportDeviceIds)
                                    && CollUtil.isNotEmpty(tempReportDeviceIds)
                                    ? reportDeviceIds.stream() // 流式处理reportDeviceIds
                                    .filter(tempReportDeviceIds::contains) // 筛选出在tempReportDeviceIds中存在的元素
                                    .collect(Collectors.toSet()) // 收集为新的Set集合
                                    : Collections.emptySet(); // 任意集合为空则返回空Set（避免返回null）
                            if (projectReportABDeviceIdPair.containsKey(projectId)) {
                                Set<Long> tempDeviceIds = projectReportABDeviceIdPair.get(projectId);
                                tempDeviceIds.addAll(crossDeviceIds);
                                projectReportABDeviceIdPair.put(projectId, tempDeviceIds);
                            } else {
                                Set<Long> tempDeviceIds = new HashSet<>();
                                tempDeviceIds.addAll(crossDeviceIds);
                                projectReportABDeviceIdPair.put(projectId, tempDeviceIds);
                            }
                        }
                    }
                }
            });

            // 计算每个项目部的设备利用率 施工的设备数量/设备总数量
            if (CollUtil.isNotEmpty(projectABDeviceIdPair)) {

                projectABDeviceIdPair.forEach((projectDeptId, deviceIds) -> {
                    // 项目部下所有AB类设备
                    Integer projectDeviceCount = deviceIds.size();
                    // 项目部日报中施工的AB类设备
                    Integer reportDeviceCount = 0;
                    if (projectReportABDeviceIdPair.containsKey(projectDeptId)) {
                        Set<Long> reportDeviceIds = projectReportABDeviceIdPair.get(projectDeptId);
                        reportDeviceCount = reportDeviceIds.size();
                    }
                    ProjectUtilizationRateVo rateVo = new ProjectUtilizationRateVo();
                    rateVo.setProjectDeptId(projectDeptId);
                    if (projectPair.containsKey(projectDeptId)) {
                        rateVo.setProjectDeptName(projectPair.get(projectDeptId));
                    }
                    double rate = 0.0;
                    // 计算设备利用率（处理除数为0的情况）
                    if (projectDeviceCount > 0 && reportDeviceCount > 0) {
                        rate = new BigDecimal((double) reportDeviceCount / (projectDeviceCount))
                                .setScale(4, RoundingMode.HALF_UP)  // 保留4位小数，四舍五入
                                .doubleValue();;
                    } else {
                        rate = 0;
                    }
                    rateVo.setUtilizationRate(rate); // 存储计算结果
                    rates.add(rateVo);
                });
            }
        }
        // 将返回列表中的 部门名称 去除多语言标识
        // 处理projectDeptName，截取~~首次出现前的字符串
        if (CollUtil.isNotEmpty(rates)) {
            rates.forEach(rateVo -> {
                String originalName = rateVo.getProjectDeptName();
                if (StrUtil.isNotBlank(originalName) && originalName.contains("~~")) {
                    // 截取首次~~之前的部分
                    String processedName = originalName.substring(0, originalName.indexOf("~~"));
                    rateVo.setProjectDeptName(processedName);
                }
                // 空值或无~~标识时，保留原名称
            });
        }
        rates.sort(Comparator.comparingDouble(ProjectUtilizationRateVo::getUtilizationRate).reversed());
        return success(rates);
    }

    /**
     * 瑞都 设备利用率 按 队伍 统计
     * @return
     */
    @GetMapping("/rd/device/teamUtilizationRate")
    @PermitAll
    public CommonResult<List<TeamUtilizationRateVo>> rdTeamUtilizationRate(IotRdDailyReportPageReqVO reqVO) {
        if (ObjUtil.isEmpty(reqVO.getCreateTime())) {
            throw exception(IOT_DAILY_REPORT_TIME_NOT_EXISTS);
        }
        if (reqVO.getCreateTime().length < 2) {
            throw exception(IOT_DAILY_REPORT_TIME_NOT_EXISTS);
        }
        // 必须传递 项目部id 查询队伍数据
        if (ObjUtil.isEmpty(reqVO.getDeptId())) {
            throw exception(IOT_DAILY_REPORT_DEPT_NOT_EXISTS);
        }

        // 指定项目部的各队伍设备利用率集合
        List<TeamUtilizationRateVo> rates = new ArrayList<>();

        // 查询指定项目部下的 队伍集合
        DeptListReqVO deptReqVO = new DeptListReqVO();
        deptReqVO.setDeptId(reqVO.getDeptId());
        List<DeptDO> projectTeams = deptService.getDeptListByParentId(deptReqVO);
        // 指定项目部下的 队伍id集合
        Set<Long> projectTeamIds = new HashSet<>();
        if (CollUtil.isNotEmpty(projectTeams)) {
            projectTeams.forEach(team -> {
                projectTeamIds.add(team.getId());
            });
        }

        Map<Long, DeptDO> allDeptPair = deptService.getDeptMap(projectTeamIds);

        Set<String> projectDeptNames = new HashSet<>();
        Set<Long> projectDeptIds = new HashSet<>();
        // key项目部id   value项目部名称
        Map<Long, String> projectPair = new HashMap<>();
        // key队伍id   value队伍名称
        Map<Long, String> teamPair = new HashMap<>();
        // key项目部id   value项目部包含的队伍id集合
        Map<Long, Set<Long>> projectTeamPair = new HashMap<>();
        // key队伍id   value队伍日报数量
        Map<Long, Long> teamReportCountPair = new HashMap<>();
        // key项目部id     value项目部下包含的队伍的 压裂 连油 设备数量
        Map<Long, Integer> projectDevicePair = new HashMap<>();
        // 设备ID到其所属部门ID的映射
        Map<Long, Long> deviceIdToDeptIdMap = new HashMap<>();

        if (CollUtil.isNotEmpty(allDeptPair)) {
            allDeptPair.forEach((deptId, dept) -> {
                if (dept.getName().contains("项目部") ) {
                    projectDeptIds.add(deptId);
                    projectDeptNames.add(dept.getName());
                    projectPair.put(deptId, dept.getName());
                }
                teamPair.put(deptId, dept.getName());
            });
            // 遍历所有部门
            allDeptPair.forEach((deptId, dept) -> {
                // 找出每个项目部下的队伍
                if (projectPair.containsKey(dept.getParentId())) {
                    // 获得当前部门的上级项目部
                    projectPair.forEach((projectDeptId, projectDept) -> {
                        if (projectDeptId.equals(dept.getParentId())) {
                            if (projectTeamPair.containsKey(projectDeptId)) {
                                Set<Long> teamIds = projectTeamPair.get(projectDeptId);
                                teamIds.add(deptId);
                                projectTeamPair.put(projectDeptId, teamIds);
                            } else {
                                Set<Long> teamIds = new HashSet<>();
                                teamIds.add(deptId);
                                projectTeamPair.put(projectDeptId, teamIds);
                            }
                        }
                    });
                }
            });
        }
        if (CollUtil.isNotEmpty(projectTeamIds)) {
            // 查询不同项目部下 包含的 压裂泵车26 连油主车设备31
            // 查询 连油主车 或 压裂泵车 相应的设备类别 id集合
            Set<Long> utilizeDeviceCategoryIds = new HashSet<>();
            IotProductClassifyListReqVO categoryReqVO = new IotProductClassifyListReqVO();
            categoryReqVO.setName("连油主车");
            List<IotProductClassifyDO> deviceCategories = iotProductClassifyMapper.selectList(categoryReqVO);
            if (CollUtil.isNotEmpty(deviceCategories)) {
                utilizeDeviceCategoryIds.add(deviceCategories.get(0).getId());
            }
            // 查询 压裂泵车 的设备类别
            categoryReqVO.setName("压裂泵车");
            List<IotProductClassifyDO> pumpCategories = iotProductClassifyMapper.selectList(categoryReqVO);
            if (CollUtil.isNotEmpty(pumpCategories)) {
                pumpCategories.forEach(category -> {
                    utilizeDeviceCategoryIds.add(category.getId());
                });
            }
            IotDevicePageReqVO deviceReqVO = new IotDevicePageReqVO();
            deviceReqVO.setAssetClasses(new ArrayList<>(utilizeDeviceCategoryIds));
            List<IotDeviceDO> utilizeDevices = iotDeviceMapper.selectListAlone(deviceReqVO);

            if (CollUtil.isNotEmpty(utilizeDevices)) {
                utilizeDevices.forEach(device -> {
                    // 存储设备ID与所属部门ID的映射
                    deviceIdToDeptIdMap.put(device.getId(), device.getDeptId());
                    // 筛选出各队伍下的 压裂 连油 设备
                    projectTeamIds.forEach(teamId -> {
                        if (projectTeamIds.contains(device.getDeptId())) {
                            if (projectDevicePair.containsKey(teamId)) {
                                Integer tempCount = projectDevicePair.get(teamId);
                                projectDevicePair.put(teamId, ++tempCount);
                            } else {
                                projectDevicePair.put(teamId, 1);
                            }
                        }
                    });
                });
            }
            // 查询出指定时间区间内 已经填写的日报 再根据设备id 进行筛选 通过设备id 建立队伍 与 日报数量之间的关联
            // 判断日报中 device_ids 字段中每个设备 是否属于需要统计的 压裂 连油 设备
            List<IotRdDailyReportDO> dailyReports = iotRdDailyReportMapper.dailyReports(reqVO);
            // 筛选出每个队伍的日报
            if (CollUtil.isNotEmpty(dailyReports)) {
                // 设置每个队伍 相关 压裂 连油 设备 的日报数量
                dailyReports.forEach(report -> {
                    projectTeamIds.forEach(teamId -> {
                        Set<Long> tempDeviceIds = report.getDeviceIds();
                        // 判断 集合 tempDeviceIds 中的任意的 ‘设备id’ 是否包含在 集合 teamDeptIds 中
                        // 判断tempDeviceIds中的任意设备所属部门是否在当前项目部的队伍部门中
                        boolean hasMatchingDevice = CollUtil.isNotEmpty(tempDeviceIds) && tempDeviceIds.stream()
                                .map(deviceIdToDeptIdMap::get) // 通过映射表获取设备所属部门ID
                                .filter(Objects::nonNull) // 过滤掉非统计范围内的设备（避免空指针）
                                .anyMatch(teamId::equals); // 任意设备所属部门在队伍部门中则匹配
                        if (hasMatchingDevice) {
                            if (teamReportCountPair.containsKey(teamId)) {
                                Long tempCount = teamReportCountPair.get(teamId);
                                teamReportCountPair.put(teamId, ++tempCount);
                            } else {
                                teamReportCountPair.put(teamId, 1l);
                            }
                        }
                    });
                });

                // 计算指定时间区间内包含的天数
                long daysCount;
                if (ObjUtil.isNotEmpty(reqVO.getCreateTime()) && reqVO.getCreateTime().length >= 2) {
                    LocalDateTime start = reqVO.getCreateTime()[0];
                    LocalDateTime end = reqVO.getCreateTime()[1];
                    if (ObjUtil.isNotEmpty(start) && ObjUtil.isNotEmpty(end) && !end.isBefore(start)) {
                        // 使用ChronoUnit.DAYS.between计算天数差，并+1包含首尾两天
                        daysCount = ChronoUnit.DAYS.between(
                                start.toLocalDate(),
                                end.toLocalDate()
                        ) + 1;
                    } else {
                        daysCount = 0L;
                    }
                } else {
                    daysCount = 0L;
                }
                // 计算每个队伍的设备利用率
                if (CollUtil.isNotEmpty(projectTeamIds)) {
                    projectTeamIds.forEach(teamId -> {
                        TeamUtilizationRateVo rateVo = new TeamUtilizationRateVo();
                        rateVo.setProjectDeptId(reqVO.getDeptId());
                        rateVo.setTeamId(teamId);
                        rateVo.setCumulativeDays(daysCount);
                        if (teamPair.containsKey(teamId)) {
                            rateVo.setTeamName(teamPair.get(teamId));
                        }
                        // 匹配出当前小队 日报数量
                        Long reportCount = 0l;
                        if (teamReportCountPair.containsKey(teamId)) {
                            reportCount = teamReportCountPair.getOrDefault(teamId, 0l);
                            rateVo.setConstructionDays(reportCount);
                        }
                        // 当前小队 设备利用率 公式 reportCount/daysCount
                        // 计算设备利用率（处理除数为0的情况）
                        double rate = 0.0;
                        if (reportCount > 0 && daysCount > 0) {
                            rate = new BigDecimal((double) reportCount /  daysCount)
                                    .setScale(4, RoundingMode.HALF_UP)  // 保留4位小数，四舍五入
                                    .doubleValue();;
                        }
                        rateVo.setUtilizationRate(rate); // 存储计算结果
                        rates.add(rateVo);
                    });
                }
            }
        }
        // 将返回列表中的 部门名称 去除多语言标识
        // 处理projectDeptName，截取~~首次出现前的字符串
        if (CollUtil.isNotEmpty(rates)) {
            rates.forEach(rateVo -> {
                String originalName = rateVo.getTeamName();
                if (StrUtil.isNotBlank(originalName) && originalName.contains("~~")) {
                    // 截取首次~~之前的部分
                    String processedName = originalName.substring(0, originalName.indexOf("~~"));
                    rateVo.setTeamName(processedName);
                }
                // 空值或无~~标识时，保留原名称
            });
        }
        rates.sort(Comparator.comparingDouble(TeamUtilizationRateVo::getUtilizationRate).reversed());
        return success(rates);
    }

    @GetMapping("/new/classify")
    @PermitAll
    public CommonResult<List<NewClassifyVo>> classifyStat() {
        Set<Long> allRhChildDeptIds = deptService.getChildDeptIdListFromCache(163l);
        allRhChildDeptIds.add(163L);
        // 包含设备的部门id集合
        IotDevicePageReqVO deviceReqVO = new IotDevicePageReqVO();
        deviceReqVO.setDeptIds(new ArrayList<>(allRhChildDeptIds));
        List<IotDeviceDO> devices = iotDeviceMapper.selectListAlone(deviceReqVO);
        Map<String, Long> assetCountMap = devices.stream().collect(Collectors.groupingBy(IotDeviceDO::getYfClass, Collectors.counting()));
        // 获取新分类编码集合 主设备类别前置
        List<DictDataDO> newClassifyDictData = dictDataService.getDictDataListByDictType("rq_iot_rd_device_new_classify");
        Set<String> newClassifies = newClassifyDictData.stream()
                .map(DictDataDO::getValue)
                .filter(StringUtils::isNotBlank)
                .collect(Collectors.toSet());

        // 流式处理：构建临时对象 → 排序 → 映射为 ImmutableMap
        List<NewClassifyVo> result = assetCountMap.entrySet().stream()
                .filter(e -> StringUtils.isNotBlank(e.getKey()))
                .map(e -> {
                    String code = StringUtils.substringAfterLast(e.getKey(), ",");
                    List<IotYfClassifyDO> yfClass = iotYfClassifyMapper.selectList("code", code);
                    if (CollUtil.isEmpty(yfClass)) {
                        return null; // 无对应分类名称则跳过
                    }
                    // 临时对象，携带 code、name、count
                    Map<String, Object> temp = new HashMap<>(3);
                    temp.put("code", code);
                    temp.put("code_new", e.getKey());
                    temp.put("name", yfClass.get(0).getName());
                    temp.put("count", e.getValue());
                    return temp;
                })
                .filter(Objects::nonNull)
                .sorted((a, b) -> {
                    boolean aIn = newClassifies.contains(a.get("code"));
                    boolean bIn = newClassifies.contains(b.get("code"));
                    // 优先排列在集合中的分类
                    if (aIn != bIn) {
                        return aIn ? -1 : 1;
                    }
                    // 同样状态按 count 降序
                    return Long.compare((Long) b.get("count"), (Long) a.get("count"));
                })
                .map(m -> {
                    NewClassifyVo vo = new NewClassifyVo();
                    vo.setClassName((String) m.get("name"));
                    // Long 转 Integer（假设数量在 int 范围内）
                    vo.setCount(((Long) m.get("count")).intValue());
                    // 根据 code 是否在主设备集合中设置 type
                    String code = (String) m.get("code");
                    String codeNew = (String) m.get("code_new");
                    vo.setType(newClassifies.contains(code) ? "top" : "");
                    vo.setCode(codeNew);
                    return vo;
                })
                .collect(Collectors.toList());

        return success(result);
    }
}

