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

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.pojo.CommonResult;
import cn.iocoder.yudao.framework.common.pojo.PageParam;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.framework.datapermission.core.annotation.DataPermission;
import cn.iocoder.yudao.framework.datapermission.core.util.DataPermissionUtils;
import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;
import cn.iocoder.yudao.framework.tenant.core.util.TenantUtils;
import cn.iocoder.yudao.module.pms.controller.admin.iotdailyreportfuel.vo.IotDailyReportFuelPageReqVO;
import cn.iocoder.yudao.module.pms.controller.admin.iotprojectinfo.vo.IotProjectInfoPageReqVO;
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.iotrddailyreport.vo.IotRdDailyReportSaveReqVO;
import cn.iocoder.yudao.module.pms.controller.admin.iotrhdailyreport.vo.*;
import cn.iocoder.yudao.module.pms.controller.admin.iotrydailyreport.vo.IotRyDailyReportPageReqVO;
import cn.iocoder.yudao.module.pms.controller.admin.iotrydailyreport.vo.IotRyDailyReportStatisticsVO;
import cn.iocoder.yudao.module.pms.controller.admin.vo.IotDevicePageReqVO;
import cn.iocoder.yudao.module.pms.dal.dataobject.IotDeviceDO;
import cn.iocoder.yudao.module.pms.dal.dataobject.iotdailyreportfuel.IotDailyReportFuelDO;
import cn.iocoder.yudao.module.pms.dal.dataobject.iotprojectinfo.IotProjectInfoDO;
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.mysql.IotDeviceMapper;
import cn.iocoder.yudao.module.pms.dal.mysql.iotrhdailyreport.IotRhDailyReportMapper;
import cn.iocoder.yudao.module.pms.service.iotdailyreportfuel.IotDailyReportFuelService;
import cn.iocoder.yudao.module.pms.service.iotprojectinfo.IotProjectInfoService;
import cn.iocoder.yudao.module.pms.service.iotprojecttask.IotProjectTaskService;
import cn.iocoder.yudao.module.pms.service.iotrddailyreport.IotRdDailyReportService;
import cn.iocoder.yudao.module.pms.service.iotrhdailyreport.IotRhDailyReportService;
import cn.iocoder.yudao.module.pms.service.iotrydailyreport.IotRyDailyReportService;
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 io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import java.io.IOException;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.DecimalFormat;
import java.time.LocalDateTime;
import java.time.temporal.ChronoUnit;
import java.util.*;
import java.util.concurrent.atomic.AtomicReference;
import java.util.stream.Stream;

import static cn.iocoder.yudao.framework.apilog.core.enums.OperateTypeEnum.EXPORT;
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.collection.CollectionUtils.convertSet;
import static cn.iocoder.yudao.framework.common.util.collection.MapUtils.findAndThen;

@Tag(name = "管理后台 - 瑞恒日报")
@RestController
@RequestMapping("/pms/iot-rh-daily-report")
@Validated
public class IotRhDailyReportController {

    @Resource
    private IotRhDailyReportService iotRhDailyReportService;
    @Resource
    private DeptService deptService;
    @Resource
    private IotProjectInfoService iotProjectInfoService;
    @Resource
    private IotProjectTaskService iotProjectTaskService;
    @Resource
    private IotRdDailyReportService iotRdDailyReportService;
    @Resource
    private IotRyDailyReportService iotRyDailyReportService;
    @Resource
    private IotDailyReportFuelService iotDailyReportFuelService;
    @Resource
    private DictDataService dictDataService;
    @Resource
    private IotRhDailyReportMapper iotRhDailyReportMapper;
    @Autowired
    private IotDeviceMapper iotDeviceMapper;

    @PostMapping("/create")
    @Operation(summary = "创建瑞恒日报")
    @PreAuthorize("@ss.hasPermission('pms:iot-rh-daily-report:create')")
    public CommonResult<Long> createIotRhDailyReport(@Valid @RequestBody IotRhDailyReportSaveReqVO createReqVO) {
        return success(iotRhDailyReportService.createIotRhDailyReport(createReqVO));
    }

    @PutMapping("/update")
    @Operation(summary = "更新瑞恒日报")
    @PreAuthorize("@ss.hasPermission('pms:iot-rh-daily-report:update')")
    public CommonResult<Boolean> updateIotRhDailyReport(@Valid @RequestBody IotRhDailyReportSaveReqVO updateReqVO) {
        iotRhDailyReportService.updateIotRhDailyReport(updateReqVO);
        return success(true);
    }

    @PutMapping("/approval")
    @Operation(summary = "审批日报")
    @PreAuthorize("@ss.hasPermission('pms:iot-rh-daily-report:update')")
    public CommonResult<Boolean> approvalRhDailyReport(@Valid @RequestBody IotRdDailyReportSaveReqVO updateReqVO) {
        iotRhDailyReportService.approvalRhDailyReport(updateReqVO);
        return success(true);
    }

    @DeleteMapping("/delete")
    @Operation(summary = "删除瑞恒日报")
    @Parameter(name = "id", description = "编号", required = true)
    @PreAuthorize("@ss.hasPermission('pms:iot-rh-daily-report:delete')")
    public CommonResult<Boolean> deleteIotRhDailyReport(@RequestParam("id") Long id) {
        iotRhDailyReportService.deleteIotRhDailyReport(id);
        return success(true);
    }

    @GetMapping("/get")
    @Operation(summary = "获得瑞恒日报")
    @Parameter(name = "id", description = "编号", required = true, example = "1024")
    @PreAuthorize("@ss.hasPermission('pms:iot-rh-daily-report:query')")
    public CommonResult<IotRhDailyReportRespVO> getIotRhDailyReport(@RequestParam("id") Long id) {
        IotRhDailyReportDO iotRhDailyReport = iotRhDailyReportService.getIotRhDailyReport(id);
        if (ObjUtil.isEmpty(iotRhDailyReport)) {
            return success(null);
        }
        // 查询当前日报关联的 部门下 增压机 的产能
        BigDecimal capacity = iotRhDailyReportService.queryCapacity(iotRhDailyReport.getDeptId());
        IotRhDailyReportRespVO result = BeanUtils.toBean(iotRhDailyReport, IotRhDailyReportRespVO.class);
        if (ObjUtil.isNotEmpty(iotRhDailyReport.getDeptId())) {
            DeptDO dept = deptService.getDept(iotRhDailyReport.getDeptId());
            result.setDeptName(dept.getName());
        }
        result.setCapacity(capacity);
        // 查询日报关联的项目 任务信息
        Long projectId = result.getProjectId();
        Long taskId = result.getTaskId();
        if (ObjUtil.isNotEmpty(projectId)) {
            IotProjectInfoDO project = iotProjectInfoService.getIotProjectInfo(projectId);
            result.setContractName(project.getContractName());
        }
        if (ObjUtil.isNotEmpty(taskId)) {
            IotProjectTaskDO task = iotProjectTaskService.getIotProjectTask(taskId);
            result.setTaskName(task.getWellName());
            result.setLocation(task.getLocation());
        }
        // 查询日报关联油耗记录
        IotDailyReportFuelPageReqVO reqVO = new IotDailyReportFuelPageReqVO();
        reqVO.setReportId(result.getId());
        reqVO.setType("RH");
        List<IotDailyReportFuelDO> reportFuels = iotDailyReportFuelService.getIotDailyReportFuels(reqVO);
        result.setReportFuels(reportFuels);
        return success(result);
    }

    @GetMapping("/page")
    @Operation(summary = "获得瑞恒日报分页")
    @PreAuthorize("@ss.hasPermission('pms:iot-rh-daily-report:query')")
    public CommonResult<PageResult<IotRhDailyReportRespVO>> getIotRhDailyReportPage(@Valid IotRhDailyReportPageReqVO pageReqVO) {
        // 根据查询参数筛选出 符合条件 的记录id 再传入 分页查询
        Set<Long> projectIds = new HashSet<>();
        Set<Long> taskIds = new HashSet<>();
        // 移动端搜索条件 标识 合同名称 任务井号 ... 移动端兼容：searchKey 不为空时 自动填充未填的 contractName / taskName
        String searchKey = pageReqVO.getSearchKey();
        if (StrUtil.isNotBlank(searchKey)) {
            if (StrUtil.isBlank(pageReqVO.getContractName())) {
                pageReqVO.setContractName(searchKey);
            }
            if (StrUtil.isBlank(pageReqVO.getTaskName())) {
                pageReqVO.setTaskName(searchKey);
            }
        }

        if (StrUtil.isNotBlank(pageReqVO.getContractName())) {
            IotProjectInfoPageReqVO reqVO = new IotProjectInfoPageReqVO();
            reqVO.setContractName(pageReqVO.getContractName());
            List<IotProjectInfoDO> projects = iotProjectInfoService.getIotProjectInfos(reqVO);
            if (CollUtil.isNotEmpty(projects)) {
                projects.forEach(project -> {
                    projectIds.add(project.getId());
                });
                pageReqVO.setProjectIds(projectIds);
            }
        }
        if (StrUtil.isNotBlank(pageReqVO.getTaskName())) {
            IotProjectTaskPageReqVO reqVO = new IotProjectTaskPageReqVO();
            reqVO.setSearchKey(pageReqVO.getTaskName());
            List<IotProjectTaskDO> tasks = iotProjectTaskService.projectTasks(reqVO);
            if (CollUtil.isNotEmpty(tasks)) {
                tasks.forEach(task -> {
                    taskIds.add(task.getId());
                });
                pageReqVO.setTaskIds(taskIds);
            }
        }
        PageResult<IotRhDailyReportDO> pageResult = iotRhDailyReportService.getIotRhDailyReportPage(pageReqVO);
        return success(new PageResult<>(buildRhDailyReports(pageResult.getList(), pageReqVO, "list"), pageResult.getTotal()));
    }

    @GetMapping("/teamReports")
    @Operation(summary = "根据井号查询瑞恒日报列表 按照队伍分组统计工作量")
    @PreAuthorize("@ss.hasPermission('pms:iot-rh-daily-report:query')")
    public CommonResult<PageResult<IotRhDailyReportRespVO>> teamReports(@Valid IotRhDailyReportPageReqVO pageReqVO) {
        // 根据查询参数筛选出 符合条件 的记录id 再传入 分页查询
        Set<Long> projectIds = new HashSet<>();
        Set<Long> taskIds = new HashSet<>();
        if (StrUtil.isNotBlank(pageReqVO.getContractName())) {
            IotProjectInfoPageReqVO reqVO = new IotProjectInfoPageReqVO();
            reqVO.setContractName(pageReqVO.getContractName());
            List<IotProjectInfoDO> projects = iotProjectInfoService.getIotProjectInfos(reqVO);
            if (CollUtil.isNotEmpty(projects)) {
                projects.forEach(project -> {
                    projectIds.add(project.getId());
                });
                pageReqVO.setProjectIds(projectIds);
            }
        }
        if (StrUtil.isNotBlank(pageReqVO.getTaskName())) {
            IotProjectTaskPageReqVO reqVO = new IotProjectTaskPageReqVO();
            reqVO.setSearchKey(pageReqVO.getTaskName());
            List<IotProjectTaskDO> tasks = iotProjectTaskService.projectTasks(reqVO);
            if (CollUtil.isNotEmpty(tasks)) {
                tasks.forEach(task -> {
                    taskIds.add(task.getId());
                });
                pageReqVO.setTaskIds(taskIds);
            }
        }
        PageResult<IotRhDailyReportDO> pageResult = iotRhDailyReportService.teamReports(pageReqVO);
        return success(new PageResult<>(buildSubtotalRhDailyReports(pageResult.getList(), pageReqVO), pageResult.getTotal()));
    }

    @GetMapping("/wellReports")
    @Operation(summary = "以队伍为维度 查询瑞恒日报列表 按照任务井分组统计工作量")
    @PreAuthorize("@ss.hasPermission('pms:iot-rh-daily-report:query')")
    public CommonResult<PageResult<IotRhDailyReportRespVO>> wellReports(@Valid IotRhDailyReportPageReqVO pageReqVO) {
        // 根据查询参数筛选出 符合条件 的记录id 再传入 分页查询
        Set<Long> projectIds = new HashSet<>();
        Set<Long> taskIds = new HashSet<>();
        if (StrUtil.isNotBlank(pageReqVO.getContractName())) {
            IotProjectInfoPageReqVO reqVO = new IotProjectInfoPageReqVO();
            reqVO.setContractName(pageReqVO.getContractName());
            List<IotProjectInfoDO> projects = iotProjectInfoService.getIotProjectInfos(reqVO);
            if (CollUtil.isNotEmpty(projects)) {
                projects.forEach(project -> {
                    projectIds.add(project.getId());
                });
                pageReqVO.setProjectIds(projectIds);
            }
        }
        if (StrUtil.isNotBlank(pageReqVO.getTaskName())) {
            IotProjectTaskPageReqVO reqVO = new IotProjectTaskPageReqVO();
            reqVO.setSearchKey(pageReqVO.getTaskName());
            List<IotProjectTaskDO> tasks = iotProjectTaskService.projectTasks(reqVO);
            if (CollUtil.isNotEmpty(tasks)) {
                tasks.forEach(task -> {
                    taskIds.add(task.getId());
                });
                pageReqVO.setTaskIds(taskIds);
            }
        }
        PageResult<IotRhDailyReportDO> pageResult = iotRhDailyReportService.wellReports(pageReqVO);
        return success(new PageResult<>(buildWellRhDailyReports(pageResult.getList(), pageReqVO), pageResult.getTotal()));
    }

    @GetMapping("/completeRate")
    @Operation(summary = "查询各专业公司日报完成率")
    @DataPermission(enable = false)
    public CommonResult<List<Map<String, Object>>> completeRate(@Valid IotRhDailyReportPageReqVO pageReqVO) {
        List<Map<String, Object>> result = new ArrayList<>();
        DataPermissionUtils.executeIgnore(() -> {
            // 查询3家专业公司的日报完成率
            // 瑞都日报完成率
            Map<String, Object> rdRate = new HashMap<>();
            rdRate.put("department", "四川瑞都");
            IotRdDailyReportPageReqVO rdReqVO = new IotRdDailyReportPageReqVO();
            rdReqVO.setCreateTime(pageReqVO.getCreateTime());
            List<IotRdDailyReportDO> rdReports = iotRdDailyReportService.dailyReports(rdReqVO);
            // 瑞都日报总数
            Integer rdTotalReportCount = 0;
            // 瑞都已填报完成日报总数
            Integer rdFilledReportCount = 0;
            if (CollUtil.isNotEmpty(rdReports)) {
                for (IotRdDailyReportDO report : rdReports) {
                    if (1 == report.getPlatformWell() || 0 == report.getPlatformWell()) {
                        rdTotalReportCount++;
                        if (1 == report.getStatus()) {
                            // 已经填报完成的日报
                            rdFilledReportCount++;
                        }
                    }
                }
                // 计算瑞都日报填报率
                if (rdTotalReportCount != 0) {
                    BigDecimal filled = BigDecimal.valueOf(rdFilledReportCount);
                    BigDecimal total = BigDecimal.valueOf(rdTotalReportCount);
                    BigDecimal rate = filled.divide(total, 2, RoundingMode.HALF_UP);
                    rdRate.put("rate", rate);
                }
            }
            result.add(rdRate);
            // 计算瑞恒日报填报完成率
            Map<String, Object> rhRate = new HashMap<>();
            rhRate.put("department", "瑞恒兴域");
            long totalRhCount = 0;
            long completeRhCount = 0;
            List<IotRhDailyReportStatisticsVO> rhReports = iotRhDailyReportService.rhDailyReportStatistics(pageReqVO);
            if (CollUtil.isNotEmpty(rhReports)) {
                for (IotRhDailyReportStatisticsVO rhReport : rhReports) {
                    if ("总数".equals(rhReport.getGroupName())) {
                        totalRhCount = rhReport.getCount();
                    }
                    if ("已填报".equals(rhReport.getGroupName())) {
                        completeRhCount = rhReport.getCount();
                    }
                }
                if (totalRhCount != 0l) {
                    BigDecimal filled = BigDecimal.valueOf(completeRhCount);
                    BigDecimal total = BigDecimal.valueOf(totalRhCount);
                    BigDecimal rate = filled.divide(total, 2, RoundingMode.HALF_UP);
                    rhRate.put("瑞恒兴域", rate);
                }
            }
            result.add(rhRate);
            // 计算瑞鹰日报填报完成率
            Map<String, Object> ryRate = new HashMap<>();
            ryRate.put("department", "瑞鹰国际");
            long totalRyCount = 0;
            long completeRyCount = 0;
            IotRyDailyReportPageReqVO ryReqVO = new IotRyDailyReportPageReqVO();
            ryReqVO.setCreateTime(pageReqVO.getCreateTime());
            // 修井
            ryReqVO.setProjectClassification("2");
            List<IotRyDailyReportStatisticsVO> ryReports = iotRyDailyReportService.ryDailyReportStatistics(ryReqVO);
            // 钻井
            ryReqVO.setProjectClassification("1");
            List<IotRyDailyReportStatisticsVO> ryZjReports = iotRyDailyReportService.ryDailyReportStatistics(ryReqVO);
            // 钻井 修井 日报 总数 已填报 数 累加示平均值
            if (CollUtil.isNotEmpty(ryReports)) {
                for (IotRyDailyReportStatisticsVO ryReport : ryReports) {
                    if ("总数".equals(ryReport.getGroupName())) {
                        totalRyCount = ryReport.getCount();
                    }
                    if ("已填报".equals(ryReport.getGroupName())) {
                        completeRyCount = ryReport.getCount();
                    }
                }
            }
            if (CollUtil.isNotEmpty(ryZjReports)) {
                for (IotRyDailyReportStatisticsVO zjReport : ryZjReports) {
                    if ("总数".equals(zjReport.getGroupName())) {
                        totalRyCount = totalRyCount + zjReport.getCount();
                    }
                    if ("已填报".equals(zjReport.getGroupName())) {
                        completeRyCount = completeRyCount + zjReport.getCount();
                    }
                }
            }
            if (totalRyCount != 0l) {
                BigDecimal filled = BigDecimal.valueOf(completeRyCount);
                BigDecimal total = BigDecimal.valueOf(totalRyCount);
                BigDecimal rate = filled.divide(total, 2, RoundingMode.HALF_UP);
                ryRate.put("rate", rate);
            }
            result.add(ryRate);
        });
        return success(result);
    }

    @GetMapping("/statistics")
    @Operation(summary = "获得瑞恒日报汇总统计")
    @PreAuthorize("@ss.hasPermission('pms:iot-rh-daily-report:query')")
    public CommonResult<Map<String, Object>> statistics(@Valid IotRhDailyReportPageReqVO pageReqVO) {
        Map<String, Object> resultMap = new HashMap<>();
        List<IotRhDailyReportStatisticsRespVO> result = new ArrayList<>();
        // 根据查询参数筛选出 符合条件 的记录id 再传入 分页查询
        Set<Long> projectIds = new HashSet<>();
        Set<Long> taskIds = new HashSet<>();
        if (StrUtil.isNotBlank(pageReqVO.getContractName())) {
            IotProjectInfoPageReqVO reqVO = new IotProjectInfoPageReqVO();
            reqVO.setContractName(pageReqVO.getContractName());
            List<IotProjectInfoDO> projects = iotProjectInfoService.getIotProjectInfos(reqVO);
            if (CollUtil.isNotEmpty(projects)) {
                projects.forEach(project -> {
                    projectIds.add(project.getId());
                });
                pageReqVO.setProjectIds(projectIds);
            }
        }
        if (StrUtil.isNotBlank(pageReqVO.getTaskName())) {
            IotProjectTaskPageReqVO reqVO = new IotProjectTaskPageReqVO();
            reqVO.setSearchKey(pageReqVO.getTaskName());
            List<IotProjectTaskDO> tasks = iotProjectTaskService.projectTasks(reqVO);
            if (CollUtil.isNotEmpty(tasks)) {
                tasks.forEach(task -> {
                    taskIds.add(task.getId());
                });
                pageReqVO.setTaskIds(taskIds);
            }
        }
        List<IotRhDailyReportStatisticsRespVO> statistics = iotRhDailyReportService.statistics(pageReqVO);
        result.addAll(statistics);
        resultMap.put("list", result);
        resultMap.put("total", result.size());
        return success(resultMap);
    }

    @GetMapping("/nptStatistics")
    @Operation(summary = "获得瑞都日报汇总统计")
    @PreAuthorize("@ss.hasPermission('pms:iot-rh-daily-report:query')")
    public CommonResult<Map<String, Object>> nptStatistics(@Valid IotRhDailyReportPageReqVO pageReqVO) {
        Map<String, Object> resultMap = new HashMap<>();
        List<IotRhDailyReportNptStatisticsRespVO> result = new ArrayList<>();
        // 根据查询参数筛选出 符合条件 的记录id 再传入 分页查询
        Set<Long> projectIds = new HashSet<>();
        Set<Long> taskIds = new HashSet<>();
        if (StrUtil.isNotBlank(pageReqVO.getContractName())) {
            IotProjectInfoPageReqVO reqVO = new IotProjectInfoPageReqVO();
            reqVO.setContractName(pageReqVO.getContractName());
            List<IotProjectInfoDO> projects = iotProjectInfoService.getIotProjectInfos(reqVO);
            if (CollUtil.isNotEmpty(projects)) {
                projects.forEach(project -> {
                    projectIds.add(project.getId());
                });
                pageReqVO.setProjectIds(projectIds);
            }
        }
        if (StrUtil.isNotBlank(pageReqVO.getTaskName())) {
            IotProjectTaskPageReqVO reqVO = new IotProjectTaskPageReqVO();
            reqVO.setSearchKey(pageReqVO.getTaskName());
            List<IotProjectTaskDO> tasks = iotProjectTaskService.projectTasks(reqVO);
            if (CollUtil.isNotEmpty(tasks)) {
                tasks.forEach(task -> {
                    taskIds.add(task.getId());
                });
                pageReqVO.setTaskIds(taskIds);
            }
        }
        List<IotRhDailyReportNptStatisticsRespVO> statistics = iotRhDailyReportService.nptStatistics(pageReqVO);
        result.addAll(statistics);
        resultMap.put("list", result);
        resultMap.put("total", result.size());
        return success(resultMap);
    }

    @GetMapping("/polylineStatistics")
    @Operation(summary = "获得瑞恒日报汇总统计 折线图")
    @PreAuthorize("@ss.hasPermission('pms:iot-rh-daily-report:query')")
    public CommonResult<List<IotRhDailyReportPolylineVO>> polylineStatistics(@Valid IotRhDailyReportPageReqVO pageReqVO) {
        List<IotRhDailyReportPolylineVO> result = new ArrayList<>();
        // 根据查询参数筛选出 符合条件 的记录id 再传入 分页查询
        Set<Long> projectIds = new HashSet<>();
        Set<Long> taskIds = new HashSet<>();
        if (StrUtil.isNotBlank(pageReqVO.getContractName())) {
            IotProjectInfoPageReqVO reqVO = new IotProjectInfoPageReqVO();
            reqVO.setContractName(pageReqVO.getContractName());
            List<IotProjectInfoDO> projects = iotProjectInfoService.getIotProjectInfos(reqVO);
            if (CollUtil.isNotEmpty(projects)) {
                projects.forEach(project -> {
                    projectIds.add(project.getId());
                });
                pageReqVO.setProjectIds(projectIds);
            }
        }
        if (StrUtil.isNotBlank(pageReqVO.getTaskName())) {
            IotProjectTaskPageReqVO reqVO = new IotProjectTaskPageReqVO();
            reqVO.setSearchKey(pageReqVO.getTaskName());
            List<IotProjectTaskDO> tasks = iotProjectTaskService.projectTasks(reqVO);
            if (CollUtil.isNotEmpty(tasks)) {
                tasks.forEach(task -> {
                    taskIds.add(task.getId());
                });
                pageReqVO.setTaskIds(taskIds);
            }
        }
        List<IotRhDailyReportPolylineVO> statistics = iotRhDailyReportService.polylineStatistics(pageReqVO);
        result.addAll(statistics);
        return success(result);
    }

    @GetMapping("/totalWorkload")
    @Operation(summary = "累计工作量统计")
    @PreAuthorize("@ss.hasPermission('pms:iot-rh-daily-report:query')")
    public CommonResult<Map<String, BigDecimal>> totalWorkload(@Valid IotRhDailyReportPageReqVO pageReqVO) {
        // 查询所有数据不分页
        pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE);
        // 根据查询参数筛选出 符合条件 的记录id 再传入 分页查询
        Set<Long> projectIds = new HashSet<>();
        Set<Long> taskIds = new HashSet<>();
        if (StrUtil.isNotBlank(pageReqVO.getContractName())) {
            IotProjectInfoPageReqVO reqVO = new IotProjectInfoPageReqVO();
            reqVO.setContractName(pageReqVO.getContractName());
            List<IotProjectInfoDO> projects = iotProjectInfoService.getIotProjectInfos(reqVO);
            if (CollUtil.isNotEmpty(projects)) {
                projects.forEach(project -> {
                    projectIds.add(project.getId());
                });
                pageReqVO.setProjectIds(projectIds);
            }
        }
        if (StrUtil.isNotBlank(pageReqVO.getTaskName())) {
            IotProjectTaskPageReqVO reqVO = new IotProjectTaskPageReqVO();
            reqVO.setSearchKey(pageReqVO.getTaskName());
            List<IotProjectTaskDO> tasks = iotProjectTaskService.projectTasks(reqVO);
            if (CollUtil.isNotEmpty(tasks)) {
                tasks.forEach(task -> {
                    taskIds.add(task.getId());
                });
                pageReqVO.setTaskIds(taskIds);
            }
        }
        // 统计设备利用率
        Long deptId = pageReqVO.getDeptId();
        // 项目部名称集合
        Set<String> projectDeptNames = new HashSet<>();
        // 项目部id集合
        Set<Long> projectDeptIds = new HashSet<>();
        // 队伍id集合
        Set<Long> teamIds = new HashSet<>();
        // key项目部id   value项目部名称
        Map<Long, String> projectPair = new HashMap<>();
        // key施工队伍id   value状态为LY的项目部id
        Map<Long, Long> teamProjectIdPair = new HashMap<>();
        if (ObjUtil.isNotEmpty(deptId)) {
            // 筛选瑞恒 主设备 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> childDeptIds = deptService.getChildDeptIdListFromCache(deptId);
            childDeptIds.add(deptId);
            Map<Long, DeptDO> allDeptPair = deptService.getDeptMap(childDeptIds);
            // 查询 瑞恒 所有设备 只统计包含 施工 状态设备的队伍
            IotDevicePageReqVO deviceReqVO = new IotDevicePageReqVO();
            deviceReqVO.setDeptIds(new ArrayList<>(childDeptIds));
            List<IotDeviceDO> allRhDevices = iotDeviceMapper.selectListAlone(deviceReqVO);
            // 包含设备的部门id集合
            Set<Long> haveDeviceDeptIds = new HashSet<>();
            if (CollUtil.isNotEmpty(allRhDevices)) {
                // 筛选出包含设备的队伍部门集合
                allRhDevices.forEach(device -> {
                    // 20260605 筛选包含主设备的队伍
                    if (mainDeviceCategoryIds.contains(device.getAssetClass())) {
                        haveDeviceDeptIds.add(device.getDeptId());
                    }
                });
            }
            if (CollUtil.isNotEmpty(allDeptPair)) {
                allDeptPair.forEach((departmentId, dept) -> {
                    // 项目部 只统计 email = LY 的项目部的 设备利用率
                    if ("2".equals(dept.getType()) && "LY".equals(dept.getEmail())) {
                        projectDeptIds.add(departmentId);
                        projectDeptNames.add(dept.getName());
                        projectPair.put(departmentId, dept.getName());
                    }
                    if ("3".equals(dept.getType())) {
                        teamIds.add(departmentId);
                    }
                });
                // 遍历所有部门 只筛选出有设备的队伍
                allDeptPair.forEach((departmentId, dept) -> {
                    // 不需要找出每个项目部下的队伍 根据筛选的日期和部门 统计数据
                    if (haveDeviceDeptIds.contains(departmentId)) {
                        if (projectPair.containsKey(dept.getParentId()) && teamIds.contains(departmentId)) {
                            // 获得队伍的上级项目部(LY状态的项目部)
                            teamProjectIdPair.put(dept.getId(), dept.getParentId());
                        }
                        if (allDeptPair.size() == 1) {
                            // 查询单个队伍的情况
                            teamProjectIdPair.put(dept.getId(), dept.getParentId());
                        }
                    }
                });
            }
        }

        List<IotRhDailyReportDO> list = iotRhDailyReportService.getIotRhDailyReportPage(pageReqVO).getList();
        Map<String, BigDecimal> result = new HashMap<>();
        // 累计注气量
        BigDecimal totalGasInjection = BigDecimal.ZERO;
        // 累计氮气注气量
        BigDecimal totalN2GasInjection = BigDecimal.ZERO;
        // 累计天然气注气量
        BigDecimal totalNaturalGasInjection = BigDecimal.ZERO;

        BigDecimal totalWaterInjection = BigDecimal.ZERO;
        BigDecimal totalPowerConsumption = BigDecimal.ZERO;
        BigDecimal totalFuelConsumption = BigDecimal.ZERO;
        double rate = 0.0;
        Integer reportCount = 0;
        if (CollUtil.isNotEmpty(list)) {
            // 筛选出指定搜索条件下日报关联任务的工艺 类别 N2 或 天然气
            Set<Long> filteredTaskIds = new HashSet<>();
            list.forEach(report -> {
                if (ObjUtil.isNotEmpty(report.getTaskId())) {
                    filteredTaskIds.add(report.getTaskId());
                }
            });
            // 查询日报对应的任务列表 获得 任务的施工工艺 N2(2) 或 天然气(15)
            IotProjectTaskPageReqVO taskReqVO = new IotProjectTaskPageReqVO();
            taskReqVO.setTaskIds(new ArrayList<>(filteredTaskIds));
            List<IotProjectTaskDO> tasks = iotProjectTaskService.projectTasks(taskReqVO);
            Map<Long, String> taskTechniquePair = new HashMap<>();
            if (CollUtil.isNotEmpty(tasks)) {
                tasks.forEach(task -> {
                    if (StrUtil.isNotBlank(task.getTechnique())) {
                        taskTechniquePair.put(task.getId(), task.getTechnique());
                    }
                });
            }

            for (IotRhDailyReportDO report : list) {
                // 统计出状态为 LY 的项目部下的施工队伍的日报数量
                // 20260604 设备利用率计算逻辑调整 分子 注气量或注水量>0 的日报数量
                if (teamProjectIdPair.containsKey(report.getDeptId()) &&
                        (report.getDailyGasInjection().compareTo(BigDecimal.ZERO)>0 || report.getDailyWaterInjection().compareTo(BigDecimal.ZERO)>0)) {
                    ++reportCount;
                }
                BigDecimal dailyGasInjection = report.getDailyGasInjection();
                BigDecimal dailyWaterInjection = report.getDailyWaterInjection();
                BigDecimal powerConsumption = report.getDailyPowerUsage();
                BigDecimal oilConsumption = report.getDailyOilUsage();
                if (ObjUtil.isNotEmpty(dailyGasInjection)) {
                    totalGasInjection = totalGasInjection.add(dailyGasInjection);
                    if (taskTechniquePair.containsKey(report.getTaskId())) {
                        String technique = taskTechniquePair.get(report.getTaskId());
                        if ("2".equals(technique)) {
                            // 注氮气
                            totalN2GasInjection = totalN2GasInjection.add(dailyGasInjection);
                        }
                        if ("15".equals(technique)) {
                            // 注天然气
                            totalNaturalGasInjection = totalNaturalGasInjection.add(dailyGasInjection);
                        }
                    }
                }
                if (ObjUtil.isNotEmpty(dailyWaterInjection)) {
                    totalWaterInjection = totalWaterInjection.add(dailyWaterInjection);
                }
                if (ObjUtil.isNotEmpty(powerConsumption)) {
                    totalPowerConsumption = totalPowerConsumption.add(powerConsumption);
                }
                if (ObjUtil.isNotEmpty(oilConsumption)) {
                    totalFuelConsumption = totalFuelConsumption.add(oilConsumption);
                }
            }
            // 计算筛选时间范围内 指定部门的设备利用率
            long daysCount = 0l;
            if (ObjUtil.isNotEmpty(pageReqVO.getCreateTime()) && pageReqVO.getCreateTime().length >= 2) {
                LocalDateTime start = pageReqVO.getCreateTime()[0];
                LocalDateTime end = pageReqVO.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;
                }
            }
            // 所有LY状态的项目部包含的队伍数量>0 并且 指定时间区间天数大于0
            if (daysCount > 0 && teamProjectIdPair.size() > 0) {
                // 指定部门(公司or项目部or队伍) 设备利用率 公式 reportCount/(currentTeamNum*daysCount)
                // 计算设备利用率（处理除数为0的情况）
                rate = new BigDecimal((double) reportCount / (teamProjectIdPair.size() * daysCount))
                        .setScale(4, RoundingMode.HALF_UP)  // 保留4位小数，四舍五入
                        .doubleValue();
            }
            // 汇总 指定搜索时间段内的 累计注气量 累计注水量 累计用电量 累计油耗
            result.put("totalGasInjection", totalGasInjection);
            // 区分出 累计注气量 中的 氮气/天然气 注气量
            result.put("totalN2GasInjection", totalN2GasInjection);
            result.put("totalNaturalGasInjection", totalNaturalGasInjection);

            result.put("totalWaterInjection", totalWaterInjection);
            result.put("totalPowerConsumption", totalPowerConsumption);
            result.put("totalFuelConsumption", totalFuelConsumption);
            result.put("utilizationRate", BigDecimal.valueOf(rate));
        }
        return success(result);
    }

    @GetMapping("/rhDailyReportStatistics")
    @Operation(summary = "按照日期查询瑞恒日报统计数据 已填报 未填报 数量")
    @PreAuthorize("@ss.hasPermission('pms:iot-rh-daily-report:query')")
    public CommonResult<List<IotRhDailyReportStatisticsVO>> rhDailyReportStatistics(@Valid IotRhDailyReportPageReqVO pageReqVO) {
        List<IotRhDailyReportStatisticsVO> statistics = iotRhDailyReportService.rhDailyReportStatistics(pageReqVO);
        return success(statistics);
    }

    @GetMapping("/rhUnReportDetails")
    @Operation(summary = "按照日期查询瑞恒日报统计数据 未填报队伍明细")
    @PreAuthorize("@ss.hasPermission('pms:iot-rh-daily-report:query')")
    public CommonResult<List<IotRhDailyReportStatisticsVO>> rhUnReportDetails(@Valid IotRhDailyReportPageReqVO pageReqVO) {
        List<IotRhDailyReportStatisticsVO> statistics = iotRhDailyReportService.rhUnReportedDetails(pageReqVO);
        return success(statistics);
    }

    @GetMapping("/dailyReportSummary")
    @Operation(summary = "瑞恒日报汇总")
    @PreAuthorize("@ss.hasPermission('pms:iot-rh-daily-report:query')")
    public CommonResult<PageResult<IotRhDailyReportRespVO>> dailyReportSummary(@Valid IotRhDailyReportPageReqVO pageReqVO) {
        // 根据查询参数筛选出 符合条件 的记录id 再传入 颁布查询
        PageResult<IotRhDailyReportDO> pageResult = iotRhDailyReportService.dailyReportSummary(pageReqVO);

        // List<IotRhDailyReportRespVO> rhDailyReports = IotRhDailyReportConvert.INSTANCE.convertList(pageResult.getList(), deptMap);
        return success(new PageResult<>(buildRhDailyReports(pageResult.getList(), pageReqVO, "list"), pageResult.getTotal()));
        // return success(new PageResult<>(rhDailyReports, pageResult.getTotal()));
    }

    @GetMapping("/taskActualProgress")
    @Operation(summary = "查询日报所属任务的实际进度")
    @PreAuthorize("@ss.hasPermission('pms:iot-rh-daily-report:query')")
    public CommonResult<List<IotRhDailyReportRespVO>> taskActualProgress(@Valid IotRhDailyReportPageReqVO pageReqVO) {
        List<IotRhDailyReportDO> taskProgresses = iotRhDailyReportService.taskActualProgress(pageReqVO);

        return success(BeanUtils.toBean(taskProgresses, IotRhDailyReportRespVO.class));
    }

    /**
     * 瑞恒日报分页 设置关联查询信息
     * @param reports
     * @param type list列表展示  export导出列表数据
     * @return
     */
    private List<IotRhDailyReportRespVO> buildRhDailyReports(List<IotRhDailyReportDO> reports, IotRhDailyReportPageReqVO pageReqVO, String type) {
        if (CollUtil.isEmpty(reports)) {
            return Collections.emptyList();
        }
        // 设备部门信息
        Map<Long, DeptDO> deptMap = deptService.getDeptMap(convertList(reports, IotRhDailyReportDO::getDeptId));
        Set<Long> projectDeptIds = new HashSet<>();
        Map<Long, String> teamIdProjectNamePair = new HashMap<>();
        // 施工队伍id集合
        Set<Long> teamIds = new HashSet<>();
        // 查询施工队伍的上级项目部 计算气电比使用
        if (CollUtil.isNotEmpty(deptMap)) {
            deptMap.forEach((deptId, dept) -> {
                projectDeptIds.add(dept.getParentId());
                teamIds.add(deptId);
            });
        }
        // 查询所有项目部的名称
        Map<Long, DeptDO> projectDeptMap = new HashMap<>();
        if (CollUtil.isNotEmpty(projectDeptIds)) {
            projectDeptMap = deptService.getDeptMap(projectDeptIds);
        }
        // 查询每个队伍对应的项目部名称集合
        Map<Long, String> projectDeptNamePair = new HashMap<>();
        if (CollUtil.isNotEmpty(deptMap)) {
            Map<Long, DeptDO> finalProjectDeptMap1 = projectDeptMap;
            deptMap.forEach((deptId, dept) -> {
                if (finalProjectDeptMap1.containsKey(dept.getParentId())) {
                    DeptDO parentDept = finalProjectDeptMap1.get(dept.getParentId());
                    if (ObjUtil.isNotEmpty(parentDept)) {
                        projectDeptNamePair.put(deptId, parentDept.getName());
                    }
                }
            });
        }
        // 设置施工队伍与 上级项目部对应关系
        if (CollUtil.isNotEmpty(deptMap)) {
            Map<Long, DeptDO> finalProjectDeptMap = projectDeptMap;
            deptMap.forEach((deptId, dept) -> {
                if (finalProjectDeptMap.containsKey(dept.getParentId())) {
                    DeptDO projectDept = finalProjectDeptMap.get(dept.getParentId());
                    teamIdProjectNamePair.put(deptId, projectDept.getName());
                }
            });
        }

        // 筛选瑞恒 主设备 rq_iot_rh_main_device_category
        Set<Long> mainDeviceCategoryIds = new HashSet<>();
        List<DictDataDO> mainDeviceCategoryDictData = dictDataService.getDictDataListByDictType("rq_iot_rh_main_device_category");
        if (CollUtil.isNotEmpty(mainDeviceCategoryDictData)) {
            mainDeviceCategoryDictData.forEach(data -> {
                String value = data.getValue();
                if (NumberUtil.isNumber(value)) {
                    Long longValue = Long.valueOf(value);
                    mainDeviceCategoryIds.add(longValue);
                }
            });
        }
        // 包含设备的部门id集合
        Set<Long> haveDeviceDeptIds = new HashSet<>();
        IotDevicePageReqVO mainDeviceReqVO = new IotDevicePageReqVO();
        mainDeviceReqVO.setDeptIds(new ArrayList<>(teamIds));
        List<IotDeviceDO> devices = iotDeviceMapper.selectListAlone(mainDeviceReqVO);
        if (CollUtil.isNotEmpty(devices)) {
            // 筛选出包含设备的队伍部门集合
            devices.forEach(device -> {
                // 20260605 筛选包含主设备的队伍
                if (mainDeviceCategoryIds.contains(device.getAssetClass())) {
                    haveDeviceDeptIds.add(device.getDeptId());
                }
            });
        }

        // 查询每个队伍的 增压机 类型的设备 查询设备的 型号 device_no
        // 瑞恒 增压机 设备类别 字典数据
        Set<Long> deviceCategories = new HashSet<>();
        List<DictDataDO> deviceCategoryDictData = dictDataService.getDictDataListByDictType("rq_iot_rh_daily_report_device_no");
        if (CollUtil.isNotEmpty(deviceCategoryDictData)) {
            deviceCategoryDictData.forEach(data -> {
                // 瑞恒 增压机设备 类别
                String value = data.getValue();
                if (NumberUtil.isNumber(value)) {
                    deviceCategories.add(Long.valueOf(value));
                }
            });
        }
        Map<Long, String> deviceNoPair = new HashMap<>();
        // 查找日报部门下 设备类别对应的 设备型号 如果有部门队伍下有多个相关类别的增压机 随机取1个
        IotDevicePageReqVO deviceReqVO = new IotDevicePageReqVO();
        deviceReqVO.setDeptIds(new ArrayList<>(teamIds));
        deviceReqVO.setAssetClasses(new ArrayList<>(deviceCategories));
        List<IotDeviceDO> allRhDevices = iotDeviceMapper.selectListAlone(deviceReqVO);
        if (CollUtil.isNotEmpty(allRhDevices)) {
            allRhDevices.forEach(device -> {
                // 设备型号
                deviceNoPair.put(device.getDeptId(), device.getDeviceNo());
            });
        }

        // 运行时效 按小时统计的 设备利用率
        // key日报id     value包含  设备的队伍按小时统计的设备利用率
        Map<Long, BigDecimal> teamWorkTimePair = new HashMap<>();

        if (CollUtil.isNotEmpty(reports)) {
            reports.forEach(report -> {
                teamWorkTimePair.put(report.getId(), BigDecimal.ZERO);
                if (haveDeviceDeptIds.contains(report.getDeptId())) {
                    // 按照时间H统计设备利用率
                    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) {
                        // 取 注气时间 注水时间 的较大者
                        BigDecimal denominator = new BigDecimal(1 * 24);
                        BigDecimal utilization = workTime.divide(denominator, 4, RoundingMode.HALF_UP);
                        teamWorkTimePair.put(report.getId(), utilization);
                    }
                }
            });
        }

        // key项目id   value项目合同号
        Map<Long, String> projectPair = new HashMap<>();
        //  key任务id     value任务井号
        Map<Long, String> taskPair = new HashMap<>();
        //  key任务id     value任务施工区域
        Map<Long, String> taskLocationPair = new HashMap<>();
        // key任务id   value设计注气量
        Map<Long, String> taskExtPropertyPair = new HashMap<>();
        // key任务id   value设计注气量 冗余
        Map<Long, String> taskWorkloadDesignPair = new HashMap<>();
        // key施工状态数据字典value   value施工状态数据字典label
        Map<String, String> constructStatusPair = new HashMap<>();
        // key非生产时间原因数据字典value   value非生产时间原因数据字典label
        Map<String, String> nptReasonPair = new HashMap<>();
        // 搬迁安装天数
        Map<Long, BigDecimal> relocationDaysPair = new HashMap<>();

        // key部门id    value 部门相关日报列表
        Map<Long, List<IotRhDailyReportDO>> deptReportsPair = new HashMap<>();
        // key队伍id   value 队伍当年累计注气量
        Map<Long, BigDecimal> yearGasInjectionPair = new HashMap<>();
        // key队伍id   value 队伍当年累计注水量
        Map<Long, BigDecimal> yearWaterInjectionPair = new HashMap<>();
        // key队伍id   value 队伍当年累计用电量
        Map<Long, BigDecimal> yearPowerPair = new HashMap<>();
        // key队伍id   value 队伍当年累计油耗
        Map<Long, BigDecimal> yearFuelPair = new HashMap<>();

        // key任务井id    value 井累计注气量
        Map<Long, BigDecimal> wellGasInjectionPair = new HashMap<>();
        // key任务井id    value 井相关日报列表
        Map<Long, List<IotRhDailyReportDO>> wellReportsPair = new HashMap<>();
        // key日报id    value 井累计注水量
        Map<Long, BigDecimal> wellWaterInjectionPair = new HashMap<>();
        // key任务井id    value 井累计用电量
        Map<Long, BigDecimal> wellPowerPair = new HashMap<>();
        // key任务井id    value 井累计油耗
        Map<Long, BigDecimal> wellFuelPair = new HashMap<>();

        // 井累计 注气量 日报当天日期及之前所有日报累计注气量之和
        // 查询所有井日报数据
        IotRhDailyReportPageReqVO currentTaskReqVO = new IotRhDailyReportPageReqVO();
        currentTaskReqVO.setTaskIds(convertList(reports, IotRhDailyReportDO::getTaskId));
        List<IotRhDailyReportDO> taskDailyReports = iotRhDailyReportMapper.dailyReports(currentTaskReqVO);
        if (CollUtil.isNotEmpty(taskDailyReports)) {
            taskDailyReports.forEach(report -> {

                // 井相关的所有日报列表
                if (wellReportsPair.containsKey(report.getTaskId())) {
                    List<IotRhDailyReportDO> tempReports = wellReportsPair.get(report.getTaskId());
                    tempReports.add(report);
                    wellReportsPair.put(report.getTaskId(), tempReports);
                } else {
                    List<IotRhDailyReportDO> tempReports = new ArrayList<>();
                    tempReports.add(report);
                    wellReportsPair.put(report.getTaskId(), tempReports);
                }

                // 电量
                if (wellPowerPair.containsKey(report.getTaskId())) {
                    BigDecimal tempPower = wellPowerPair.get(report.getTaskId());
                    BigDecimal tempResult = tempPower.add(report.getDailyPowerUsage());
                    wellPowerPair.put(report.getTaskId(), tempResult);
                } else {
                    wellPowerPair.put(report.getTaskId(), report.getDailyPowerUsage());
                }
                // 油耗
                if (wellFuelPair.containsKey(report.getTaskId())) {
                    BigDecimal tempFuel = wellFuelPair.get(report.getTaskId());
                    BigDecimal tempResult = tempFuel.add(report.getDailyOilUsage());
                    wellFuelPair.put(report.getTaskId(), tempResult);
                } else {
                    wellFuelPair.put(report.getTaskId(), report.getDailyOilUsage());
                }
            });
        }

        // 基于 wellReportsPair 计算每个日报的截止到创建时间的累计注气量
        Map<Long, BigDecimal> reportCumulativeGasMap = new HashMap<>();
        if (CollUtil.isNotEmpty(wellReportsPair)) {
            for (Map.Entry<Long, List<IotRhDailyReportDO>> entry : wellReportsPair.entrySet()) {
                List<IotRhDailyReportDO> reportList = entry.getValue();
                // 按 createTime 升序排序（确保时间顺序）
                reportList.sort(Comparator.comparing(IotRhDailyReportDO::getCreateTime));
                BigDecimal cumulativeSum = BigDecimal.ZERO;
                // 累计注水量
                BigDecimal cumulativeSumWater = BigDecimal.ZERO;
                // 累计用电量
                BigDecimal cumulativeSumPower = BigDecimal.ZERO;
                // 累计油耗
                BigDecimal cumulativeSumFuel = BigDecimal.ZERO;
                for (IotRhDailyReportDO report : reportList) {
                    // 累加当前日报的注气量
                    cumulativeSum = cumulativeSum.add(Optional.ofNullable(report.getDailyGasInjection()).orElse(BigDecimal.ZERO));
                    // 存入 map，key=日报ID，value=截止到当前日报的累计注气量
                    reportCumulativeGasMap.put(report.getId(), cumulativeSum);
                    // 累计注水量
                    cumulativeSumWater = cumulativeSumWater.add(Optional.ofNullable(report.getDailyWaterInjection()).orElse(BigDecimal.ZERO));
                    // 存入 map，key=日报ID，value=截止到当前日报的累计注水量
                    wellWaterInjectionPair.put(report.getId(), cumulativeSumWater);
                    // 累计用电量
                    cumulativeSumPower = cumulativeSumPower.add(Optional.ofNullable(report.getDailyPowerUsage()).orElse(BigDecimal.ZERO));
                    // 存入 map，key=日报ID，value=截止到当前日报的累计用电量
                    wellPowerPair.put(report.getId(), cumulativeSumPower);
                    // 累计油耗
                    cumulativeSumFuel = cumulativeSumFuel.add(Optional.ofNullable(report.getDailyOilUsage()).orElse(BigDecimal.ZERO));
                    // 存入 map，key=日报ID，value=截止到当前日报的累计油耗
                    wellFuelPair.put(report.getId(), cumulativeSumFuel);
                }
            }
        }

        // 根据传递的时间筛选获取要查询的 yyyy
        if (ObjUtil.isNotEmpty(pageReqVO.getCreateTime())) {
            // 只有传递了 时间查询条件 才会查询 当年累计的工作量数据
            LocalDateTime[] createTimeAttr = pageReqVO.getCreateTime();
            if (createTimeAttr.length > 0) {
                LocalDateTime startTime = createTimeAttr[0];
                String year = String.valueOf(startTime.getYear());
                IotRhDailyReportPageReqVO reqVO = new IotRhDailyReportPageReqVO();
                reqVO.setYear(year);
                reqVO.setDeptIds(convertList(reports, IotRhDailyReportDO::getDeptId));
                List<IotRhDailyReportDO> dailyReports = iotRhDailyReportMapper.dailyReports(reqVO);
                if (CollUtil.isNotEmpty(dailyReports)) {
                    dailyReports.forEach(report -> {
                        // 组装每个部门的日报列表
                        if (deptReportsPair.containsKey(report.getDeptId())) {
                            List<IotRhDailyReportDO> tempReports = deptReportsPair.get(report.getDeptId());
                            tempReports.add(report);
                            deptReportsPair.put(report.getDeptId(), tempReports);
                        } else {
                            List<IotRhDailyReportDO> tempReports = new ArrayList<>();
                            tempReports.add(report);
                            deptReportsPair.put(report.getDeptId(), tempReports);
                        }
                    });

                    // 2. 对每个部门的日报列表按 createTime 排序，计算滚动累计
                    for (Map.Entry<Long, List<IotRhDailyReportDO>> entry : deptReportsPair.entrySet()) {
                        List<IotRhDailyReportDO> deptReports = entry.getValue();
                        deptReports.sort(Comparator.comparing(IotRhDailyReportDO::getCreateTime));
                        // 累计注气量
                        BigDecimal cumGas = BigDecimal.ZERO;
                        // 累计注水量
                        BigDecimal cumWater = BigDecimal.ZERO;
                        // 累计用电量
                        BigDecimal cumPower = BigDecimal.ZERO;
                        // 累计油耗
                        BigDecimal cumFuel = BigDecimal.ZERO;
                        for (IotRhDailyReportDO report : deptReports) {
                            cumGas = cumGas.add(Optional.ofNullable(report.getDailyGasInjection()).orElse(BigDecimal.ZERO));
                            cumWater = cumWater.add(Optional.ofNullable(report.getDailyWaterInjection()).orElse(BigDecimal.ZERO));
                            cumPower = cumPower.add(Optional.ofNullable(report.getDailyPowerUsage()).orElse(BigDecimal.ZERO));
                            cumFuel = cumFuel.add(Optional.ofNullable(report.getDailyOilUsage()).orElse(BigDecimal.ZERO));
                            // 存入以日报ID为键的Map
                            yearGasInjectionPair.put(report.getId(), cumGas);
                            yearWaterInjectionPair.put(report.getId(), cumWater);
                            yearPowerPair.put(report.getId(), cumPower);
                            yearFuelPair.put(report.getId(), cumFuel);
                        }
                    }
                }
            }
        }

        // key部门id  value产能
        AtomicReference<Map<Long, BigDecimal>> capacityPair = new AtomicReference<>(new HashMap<>());
        // 施工状态 字典数据
        List<DictDataDO> constructionStatusDictData = dictDataService.getDictDataListByDictType("constructionStatus");
        // 非生产时间原因 字典数据
        List<DictDataDO> nptReasonDictData = dictDataService.getDictDataListByDictType("nptReason");
        if (CollUtil.isNotEmpty(constructionStatusDictData)) {
            constructionStatusDictData.forEach(data -> {
                constructStatusPair.put(data.getValue(), data.getLabel());
            });
        }
        if (CollUtil.isNotEmpty(nptReasonDictData)) {
            nptReasonDictData.forEach(data -> {
                nptReasonPair.put(data.getValue(), data.getLabel());
            });
        }
        // 施工工艺数据字典集合 key施工工艺value    value施工工艺label
        Map<String, String> techniquePair = new HashMap<>();
        // 施工工艺数据字典集合 key任务id    value施工工艺label
        Map<Long, String> taskTechniqueNamePair = new HashMap<>();
        DataPermissionUtils.executeIgnore(() -> {
            // 查询日报关联的项目信息
            IotProjectInfoPageReqVO reqVO = new IotProjectInfoPageReqVO();
            reqVO.setProjectIds(convertList(reports, IotRhDailyReportDO::getProjectId));
            List<IotProjectInfoDO> projects = iotProjectInfoService.getIotProjectInfos(reqVO);
            if (CollUtil.isNotEmpty(projects)) {
                projects.forEach(project -> {
                    projectPair.put(project.getId(), project.getContractName());
                });
            }
            // 查询日报关联的任务信息
            IotProjectTaskPageReqVO taskReqVO = new IotProjectTaskPageReqVO();
            taskReqVO.setTaskIds(convertList(reports, IotRhDailyReportDO::getTaskId));
            List<IotProjectTaskDO> tasks = iotProjectTaskService.projectTasks(taskReqVO);

            // 查询 瑞恒 施工工艺 数据字典集合 匹配数据字典value 对应的 label
            List<DictDataDO> techniqueDictData = dictDataService.getDictDataListByDictType("rq_iot_project_technology_rh");
            if (CollUtil.isNotEmpty(techniqueDictData)) {
                techniqueDictData.forEach(data -> {
                    techniquePair.put(data.getValue(), data.getLabel());
                });
            }

            if (CollUtil.isNotEmpty(tasks)) {
                tasks.forEach(task -> {
                    taskPair.put(task.getId(), task.getWellName());
                    taskLocationPair.put(task.getId(), task.getLocation());
                    if (CollUtil.isNotEmpty(task.getExtProperty())) {
                        List<IotTaskAttrModelProperty> taskAttrs = task.getExtProperty();
                        if (CollUtil.isNotEmpty(taskAttrs)) {
                            // 找到 设计注气量 属性 对应的值
                            taskAttrs.forEach(attr -> {
                                if ("设计注气量".equals(attr.getName()) && StrUtil.isNotBlank(attr.getActualValue())) {
                                    taskExtPropertyPair.put(task.getId(), attr.getActualValue());
                                }
                            });
                        }
                    }
                    // 任务设计工作量 注气量 单位 方 转换成 万方
                    if (NumberUtil.isNumber(task.getWorkloadDesign())) {
                        BigDecimal workload = new BigDecimal(task.getWorkloadDesign());
                        BigDecimal convertedWorkload = workload.divide(BigDecimal.valueOf(10000), 2, RoundingMode.HALF_UP);
                        taskWorkloadDesignPair.put(task.getId(), convertedWorkload.toString());
                    }
                    // 设置每个任务对应的施工工艺数据字典label
                    if (techniquePair.containsKey(task.getTechnique())) {
                        String techniqueLabel = techniquePair.get(task.getTechnique());
                        taskTechniqueNamePair.put(task.getId(), techniqueLabel);
                    }
                });
            }
            // 查询当前日报所属施工队伍中包含 增压机 的产能
            capacityPair.set(iotRhDailyReportService.queryCapacities(convertList(reports, IotRhDailyReportDO::getDeptId)));
            // 查询每个任务的搬迁安装天数
            List<IotRhDailyReportDO> relocationDays = iotRhDailyReportService.relocationDays(null);
            if (CollUtil.isNotEmpty(relocationDays)) {
                relocationDays.forEach(day -> {
                    relocationDaysPair.put(day.getDeptId(), day.getRelocationDays());
                });
            }
        });
        // 2. 拼接数据
        return BeanUtils.toBean(reports, IotRhDailyReportRespVO.class, (reportVO) -> {

            // 气电比 塔里木、吐哈-气/电   气/电/1.07-其它  气单位：方   电单位：KWh
            if (teamIdProjectNamePair.containsKey(reportVO.getDeptId())) {
                String deptName = teamIdProjectNamePair.get(reportVO.getDeptId());
                BigDecimal power = reportVO.getDailyPowerUsage();
                BigDecimal gas = reportVO.getDailyGasInjection();
                if (power.compareTo(BigDecimal.ZERO) > 0) {
                    BigDecimal tempResult = gas.divide(power, 2, RoundingMode.HALF_UP);
                    if (deptName.contains("塔里木") || deptName.contains("吐哈")) {
                        reportVO.setGasElectricityRatio(tempResult);
                    } else {
                        reportVO.setGasElectricityRatio(tempResult.divide(BigDecimal.valueOf(1.07), 2, RoundingMode.HALF_UP));
                    }
                }
            }

            // 计算每个日报的 非生产时效
            BigDecimal sumNpt = calculateNonProductTime(reportVO);
            reportVO.setNonProductionRate(sumNpt.divide(BigDecimal.valueOf(24), 4, RoundingMode.HALF_UP ));

            // 非生产时效 百分比格式 导出使用
            if (ObjUtil.isNotEmpty(reportVO.getNonProductionRate())) {
                // 获取原始小数
                BigDecimal nptRate = reportVO.getNonProductionRate();
                // 乘以100转换为百分比数值
                BigDecimal percentage = nptRate.multiply(BigDecimal.valueOf(100));
                // 格式化保留2位小数
                DecimalFormat df = new DecimalFormat("0.00");
                String nonProductionRate = df.format(percentage) + "%";
                // 赋值
                reportVO.setNonProductionRateFormat(nonProductionRate);
            }

            // 运行时效 按小时统计的设备利用率
            findAndThen(teamWorkTimePair, reportVO.getId(), utilizationRate -> reportVO.setTransitTime(utilizationRate));

            if (ObjUtil.isNotEmpty(reportVO.getTransitTime())) {
                // 获取原始小数
                BigDecimal transitTime = reportVO.getTransitTime();
                // 乘以100转换为百分比数值
                BigDecimal percentage = transitTime.multiply(BigDecimal.valueOf(100));
                // 格式化保留2位小数
                DecimalFormat df = new DecimalFormat("0.00");
                String transitTimeRate = df.format(percentage) + "%";
                // 赋值
                reportVO.setTransitTimeRate(transitTimeRate);
            }

            // 导出列表时 格式化时间为 yyyy-MM-dd
            if (ObjUtil.isNotEmpty(reportVO.getCreateTime())) {
                reportVO.setCreateTimeStr(LocalDateTimeUtil.format(reportVO.getCreateTime(), DatePattern.NORM_DATE_PATTERN));
            }
            // 2.1 拼接部门信息
            findAndThen(deptMap, reportVO.getDeptId(), dept -> reportVO.setDeptName(dept.getName()));
            // 队伍下 增压机 设备型号
            findAndThen(deviceNoPair, reportVO.getDeptId(), deviceNo -> reportVO.setDeviceNo(deviceNo));
            // 2.1 拼接项目部信息
            findAndThen(projectDeptNamePair, reportVO.getDeptId(), projectDeptName -> reportVO.setProjectDeptName(projectDeptName));
            // 队伍当年累计注气量
            findAndThen(yearGasInjectionPair, reportVO.getId(), gasInjection -> {
                // 转换单位为 万方
                BigDecimal gasInjectionWanFang = gasInjection
                        .divide(BigDecimal.valueOf(10000), 4, RoundingMode.HALF_UP);
                reportVO.setYearTotalGasInjection(gasInjectionWanFang);
            });
            // 队伍当年累计注水量
            findAndThen(yearWaterInjectionPair, reportVO.getId(), waterInjection -> reportVO.setYearTotalWaterInjection(waterInjection));
            // 队伍当年累计用电量
            findAndThen(yearPowerPair, reportVO.getId(), power -> {
                // 换算单位为 MWh
                BigDecimal powerW = power
                        .divide(BigDecimal.valueOf(1000), 2, RoundingMode.HALF_UP);
                reportVO.setYearTotalPower(powerW);
            });
            // 队伍当年累计油耗
            findAndThen(yearFuelPair, reportVO.getId(), fuel -> reportVO.setYearTotalFuel(fuel));
            // 井当年累计注气量
            findAndThen(reportCumulativeGasMap, reportVO.getId(), gasInjection -> {
                // 转换单位为 万方
                BigDecimal gasInjectionWanFang = gasInjection
                        .divide(BigDecimal.valueOf(10000), 4, RoundingMode.HALF_UP);
                reportVO.setWellTotalGasInjection(gasInjectionWanFang);
            });
            // 井当年累计注水量
            findAndThen(wellWaterInjectionPair, reportVO.getId(), waterInjection -> reportVO.setWellTotalWaterInjection(waterInjection));
            // 井当年累计用电量
            findAndThen(wellPowerPair, reportVO.getId(), power -> {
                // 换算单位为 MWh
                BigDecimal powerW = power
                        .divide(BigDecimal.valueOf(1000), 2, RoundingMode.HALF_UP);
                reportVO.setWellTotalPower(powerW);
            });
            // 井当年累计油耗
            findAndThen(wellFuelPair, reportVO.getId(), fuel -> reportVO.setWellTotalFuel(fuel));
            // 2.2 日报关联的项目信息
            findAndThen(projectPair, reportVO.getProjectId(), contractName -> reportVO.setContractName(contractName));
            // 2.3 日报关联的任务井号
            findAndThen(taskPair, reportVO.getTaskId(), taskName -> reportVO.setTaskName(taskName));
            // 日报关联的任务施工地点
            findAndThen(taskLocationPair, reportVO.getTaskId(), location -> reportVO.setLocation(location));
            // 2.4 设计注气量
            findAndThen(taskExtPropertyPair, reportVO.getTaskId(), designInjection -> reportVO.setDesignInjection(designInjection));
            // 如果扩展属性中 设计注气量 为空 则使用 设计工作量 的值
            if (StrUtil.isBlank(reportVO.getDesignInjection())) {
                reportVO.setDesignInjection(taskWorkloadDesignPair.get(reportVO.getTaskId()));
            }
            // 2.5 搬迁安装天数
            findAndThen(relocationDaysPair, reportVO.getDeptId(), relocationDays -> {
                if (relocationDays.compareTo(BigDecimal.ZERO) < 0) {
                    reportVO.setRelocationDays(BigDecimal.ZERO);
                } else {
                    reportVO.setRelocationDays(relocationDays);
                }
            });
            // 2.6 产能
            findAndThen(capacityPair.get(), reportVO.getDeptId(), capacity -> reportVO.setCapacity(capacity));
            // 施工状态 数据字典
            findAndThen(constructStatusPair, reportVO.getConstructionStatus(), statusLabel -> reportVO.setConstructionStatusName(statusLabel));
            // 非生产时间原因 数据字典
            findAndThen(nptReasonPair, reportVO.getNptReason(), statusLabel -> reportVO.setNptReasonName(statusLabel));
            // 施工工艺字典 区分 注氮 注气
            findAndThen(taskTechniqueNamePair, reportVO.getTaskId(), techniqueName -> reportVO.setTechniqueNames(techniqueName));
        });
    }

    /**
     *  计算非生产时间累加值 计算非生产时效
     *  NPT 归类 设备故障repair_time 工程质量accident_time 技术受限complexity_time 生产组织rectification_time 不可抗力waiting_stop_time
     *      甲方设计partya_design 甲方准备partya_prepare 甲方资源partya_resource 其他非生产时间other_npt_time
     * @param dailyReport
     * @return
     */
    private BigDecimal calculateNonProductTime(IotRhDailyReportRespVO dailyReport){
        return Stream.of(
                        dailyReport.getAccidentTime(),
                        dailyReport.getRepairTime(),
                        dailyReport.getComplexityTime(),
                        dailyReport.getRectificationTime(),
                        dailyReport.getWaitingStopTime(),
                        dailyReport.getPartyaDesign(),    // 注：字段名虽无Time但属于非生产时间，保留
                        dailyReport.getPartyaPrepare(),
                        dailyReport.getPartyaResource(),
                        dailyReport.getOtherNptTime()
                )
                // 处理null值，避免调用add()时抛出NullPointerException
                .map(bd -> Objects.isNull(bd) ? BigDecimal.ZERO : bd)
                // Stream.reduce：从初始值0开始，依次累加所有元素
                .reduce(BigDecimal.ZERO, BigDecimal::add);
    }

    /**
     * 以井为维度 统计 瑞恒日报 分页数据 以队伍分组小计工作量
     * @param reports
     * @return
     */
    private List<IotRhDailyReportRespVO> buildSubtotalRhDailyReports(List<IotRhDailyReportDO> reports, IotRhDailyReportPageReqVO pageReqVO) {
        if (CollUtil.isEmpty(reports)) {
            return Collections.emptyList();
        }
        // 设备部门信息
        Map<Long, DeptDO> deptMap = deptService.getDeptMap(convertList(reports, IotRhDailyReportDO::getDeptId));
        // key项目id   value项目合同号
        Map<Long, String> projectPair = new HashMap<>();
        //  key任务id     value任务井号-施工区域
        Map<Long, String> taskPair = new HashMap<>();
        // key任务id   value设计注气量
        Map<Long, String> taskExtPropertyPair = new HashMap<>();
        // key施工状态数据字典value   value施工状态数据字典label
        Map<String, String> constructStatusPair = new HashMap<>();
        // key非生产时间原因数据字典value   value非生产时间原因数据字典label
        Map<String, String> nptReasonPair = new HashMap<>();
        // 搬迁安装天数
        Map<Long, BigDecimal> relocationDaysPair = new HashMap<>();

        // key部门id-队伍id   value 队伍当年累计注气量
        Map<String, BigDecimal> groupGasInjectionPair = new HashMap<>();
        // key部门id-队伍id   value 队伍当年累计注水量
        Map<String, BigDecimal> groupWaterInjectionPair = new HashMap<>();
        // key部门id-队伍id   value 队伍当年累计用电量
        Map<String, BigDecimal> groupPowerPair = new HashMap<>();
        // key部门id-队伍id   value 队伍当年累计油耗
        Map<String, BigDecimal> groupFuelPair = new HashMap<>();
        // key部门id-队伍id    value 注气时间小计
        Map<String, BigDecimal> groupGasTimePair = new HashMap<>();
        // key部门id-队伍id    value 非生产时间小计
        Map<String, BigDecimal> groupNoProductTimePair = new HashMap<>();
        // key部门id-队伍id    value 小计平均运行时效
        Map<String, BigDecimal> groupTransTimePair = new HashMap<>();

        // key小组最后1条记录id   value 队伍当年累计注气量
        Map<Long, BigDecimal> groupIdGasInjectionPair = new HashMap<>();
        // key小组最后1条记录id   value 队伍当年累计注水量
        Map<Long, BigDecimal> groupIdWaterInjectionPair = new HashMap<>();
        // key小组最后1条记录id   value 队伍当年累计用电量
        Map<Long, BigDecimal> groupIdPowerPair = new HashMap<>();
        // key小组最后1条记录id   value 队伍当年累计油耗
        Map<Long, BigDecimal> groupIdFuelPair = new HashMap<>();
        // key小组最后1条记录id    value 注气时间小计
        Map<Long, BigDecimal> groupIdGasTimePair = new HashMap<>();
        // key小组最后1条记录id    value 非生产时间小计
        Map<Long, BigDecimal> groupIdNoProductTimePair = new HashMap<>();
        // key小组最后1条记录id    value 小计平均运行时效
        Map<Long, BigDecimal> groupIdTransTimePair = new HashMap<>();

        // key队伍id   value 队伍当年累计注气量
        Map<Long, BigDecimal> yearGasInjectionPair = new HashMap<>();
        // key队伍id   value 队伍当年累计注水量
        Map<Long, BigDecimal> yearWaterInjectionPair = new HashMap<>();
        // key队伍id   value 队伍当年累计用电量
        Map<Long, BigDecimal> yearPowerPair = new HashMap<>();
        // key队伍id   value 队伍当年累计油耗
        Map<Long, BigDecimal> yearFuelPair = new HashMap<>();

        // key任务井id    value 井累计注气量
        Map<Long, BigDecimal> wellGasInjectionPair = new HashMap<>();
        // key任务井id    value 井累计注水量
        Map<Long, BigDecimal> wellWaterInjectionPair = new HashMap<>();
        // key任务井id    value 井累计用电量
        Map<Long, BigDecimal> wellPowerPair = new HashMap<>();
        // key任务井id    value 井累计油耗
        Map<Long, BigDecimal> wellFuelPair = new HashMap<>();

        // 查询所有井日报数据
        IotRhDailyReportPageReqVO wellTaskReqVO = new IotRhDailyReportPageReqVO();
        wellTaskReqVO.setTaskIds(convertList(reports, IotRhDailyReportDO::getTaskId));
        List<IotRhDailyReportDO> taskDailyReports = iotRhDailyReportMapper.dailyReports(wellTaskReqVO);

        if (CollUtil.isNotEmpty(taskDailyReports)) {
            taskDailyReports.forEach(report -> {
                // 注气量
                if (wellGasInjectionPair.containsKey(report.getTaskId())) {
                    BigDecimal tempGasInjection = wellGasInjectionPair.get(report.getTaskId());
                    BigDecimal tempResult = tempGasInjection.add(report.getDailyGasInjection());
                    wellGasInjectionPair.put(report.getTaskId(), tempResult);
                } else {
                    wellGasInjectionPair.put(report.getTaskId(), report.getDailyGasInjection());
                }
                // 注水量
                if (wellWaterInjectionPair.containsKey(report.getTaskId())) {
                    BigDecimal tempWaterInjection = wellWaterInjectionPair.get(report.getTaskId());
                    BigDecimal tempResult = tempWaterInjection.add(report.getDailyWaterInjection());
                    wellWaterInjectionPair.put(report.getTaskId(), tempResult);
                } else {
                    wellWaterInjectionPair.put(report.getTaskId(), report.getDailyWaterInjection());
                }
                // 电量
                if (wellPowerPair.containsKey(report.getTaskId())) {
                    BigDecimal tempPower = wellPowerPair.get(report.getTaskId());
                    BigDecimal tempResult = tempPower.add(report.getDailyPowerUsage());
                    wellPowerPair.put(report.getTaskId(), tempResult);
                } else {
                    wellPowerPair.put(report.getTaskId(), report.getDailyPowerUsage());
                }
                // 油耗
                if (wellFuelPair.containsKey(report.getTaskId())) {
                    BigDecimal tempFuel = wellFuelPair.get(report.getTaskId());
                    BigDecimal tempResult = tempFuel.add(report.getDailyOilUsage());
                    wellFuelPair.put(report.getTaskId(), tempResult);
                } else {
                    wellFuelPair.put(report.getTaskId(), report.getDailyOilUsage());
                }
            });
        }

        // 根据传递的时间筛选获取要查询的 yyyy
        // 如果没有传递时间区间 默认当年
        LocalDateTime nowDate = LocalDateTime.now();
        String year = StrUtil.EMPTY;
        if (ObjUtil.isNotEmpty(pageReqVO.getCreateTime())) {
            LocalDateTime[] createTimeAttr = pageReqVO.getCreateTime();
            if (createTimeAttr.length > 0) {
                LocalDateTime startTime = createTimeAttr[0];
                year = String.valueOf(startTime.getYear());
            }
        } else {
            year = String.valueOf(nowDate.getYear());
        }
        // 只有传递了 时间查询条件 才会查询 当年累计的工作量数据
        IotRhDailyReportPageReqVO yearReqVO = new IotRhDailyReportPageReqVO();
        yearReqVO.setYear(year);
        yearReqVO.setDeptIds(convertList(reports, IotRhDailyReportDO::getDeptId));
        List<IotRhDailyReportDO> dailyReports = iotRhDailyReportMapper.dailyReports(yearReqVO);
        if (CollUtil.isNotEmpty(dailyReports)) {
            dailyReports.forEach(report -> {
                // 注气量
                if (yearGasInjectionPair.containsKey(report.getDeptId())) {
                    BigDecimal tempGasInjection = yearGasInjectionPair.get(report.getDeptId());
                    BigDecimal tempResult = tempGasInjection.add(report.getDailyGasInjection());
                    yearGasInjectionPair.put(report.getDeptId(), tempResult);
                } else {
                    yearGasInjectionPair.put(report.getDeptId(), report.getDailyGasInjection());
                }
                // 注水量
                if (yearWaterInjectionPair.containsKey(report.getDeptId())) {
                    BigDecimal tempWaterInjection = yearWaterInjectionPair.get(report.getDeptId());
                    BigDecimal tempResult = tempWaterInjection.add(report.getDailyWaterInjection());
                    yearWaterInjectionPair.put(report.getDeptId(), tempResult);
                } else {
                    yearWaterInjectionPair.put(report.getDeptId(), report.getDailyWaterInjection());
                }
                // 电量
                if (yearPowerPair.containsKey(report.getDeptId())) {
                    BigDecimal tempPower = yearPowerPair.get(report.getDeptId());
                    BigDecimal tempResult = tempPower.add(report.getDailyPowerUsage());
                    yearPowerPair.put(report.getDeptId(), tempResult);
                } else {
                    yearPowerPair.put(report.getDeptId(), report.getDailyPowerUsage());
                }
                // 油耗
                if (yearFuelPair.containsKey(report.getDeptId())) {
                    BigDecimal tempFuel = yearFuelPair.get(report.getDeptId());
                    BigDecimal tempResult = tempFuel.add(report.getDailyOilUsage());
                    yearFuelPair.put(report.getDeptId(), tempResult);
                } else {
                    yearFuelPair.put(report.getDeptId(), report.getDailyOilUsage());
                }
            });
        }

        // 查询 当前分页 所有部门 任务井 日报数据 小计工作量
        IotRhDailyReportPageReqVO currentTaskReqVO = new IotRhDailyReportPageReqVO();
        currentTaskReqVO.setTaskIds(convertSet(reports, IotRhDailyReportDO::getTaskId));
        currentTaskReqVO.setDeptIds(convertSet(reports, IotRhDailyReportDO::getDeptId));
        currentTaskReqVO.setCreateTime(pageReqVO.getCreateTime());
        currentTaskReqVO.setProjectIds(pageReqVO.getProjectIds());
        currentTaskReqVO.setTaskIds(pageReqVO.getTaskIds());
        List<IotRhDailyReportDO> deptTaskDailyReports = iotRhDailyReportMapper.dailyReports(currentTaskReqVO);

        // 以 deptId-taskId 为唯一键 小计日报工作量
        if (CollUtil.isNotEmpty(deptTaskDailyReports)) {
            deptTaskDailyReports.forEach(report -> {
                String uniqueKey = StrUtil.join("-", report.getDeptId(), report.getTaskId());
                // 注气量
                if (groupGasInjectionPair.containsKey(uniqueKey)) {
                    BigDecimal tempGasInjection = groupGasInjectionPair.get(uniqueKey);
                    BigDecimal tempResult = tempGasInjection.add(report.getDailyGasInjection());
                    groupGasInjectionPair.put(uniqueKey, tempResult);
                } else {
                    groupGasInjectionPair.put(uniqueKey, report.getDailyGasInjection());
                }
                // 注水量
                if (groupWaterInjectionPair.containsKey(uniqueKey)) {
                    BigDecimal tempWaterInjection = groupWaterInjectionPair.get(uniqueKey);
                    BigDecimal tempResult = tempWaterInjection.add(report.getDailyWaterInjection());
                    groupWaterInjectionPair.put(uniqueKey, tempResult);
                } else {
                    groupWaterInjectionPair.put(uniqueKey, report.getDailyWaterInjection());
                }
                // 电量
                if (groupPowerPair.containsKey(uniqueKey)) {
                    BigDecimal tempPower = groupPowerPair.get(uniqueKey);
                    BigDecimal tempResult = tempPower.add(report.getDailyPowerUsage());
                    groupPowerPair.put(uniqueKey, tempResult);
                } else {
                    groupPowerPair.put(uniqueKey, report.getDailyPowerUsage());
                }
                // 油耗
                if (groupFuelPair.containsKey(uniqueKey)) {
                    BigDecimal tempFuel = groupFuelPair.get(uniqueKey);
                    BigDecimal tempResult = tempFuel.add(report.getDailyOilUsage());
                    groupFuelPair.put(uniqueKey, tempResult);
                } else {
                    groupFuelPair.put(uniqueKey, report.getDailyOilUsage());
                }
                // 注气时间
                if (groupGasTimePair.containsKey(uniqueKey)) {
                    BigDecimal tempGasTime = groupGasTimePair.get(uniqueKey);
                    BigDecimal tempResult = tempGasTime.add(report.getDailyInjectGasTime());
                    groupGasTimePair.put(uniqueKey, tempResult);
                } else {
                    groupGasTimePair.put(uniqueKey, report.getDailyInjectGasTime());
                }
                // 非生产时间
                if (groupNoProductTimePair.containsKey(uniqueKey)) {
                    BigDecimal tempNoProductTime = groupNoProductTimePair.get(uniqueKey);
                    BigDecimal tempResult = tempNoProductTime.add(report.getNonProductionTime());
                    groupNoProductTimePair.put(uniqueKey, tempResult);
                } else {
                    groupNoProductTimePair.put(uniqueKey, report.getNonProductionTime());
                }
            });
        }

        currentTaskReqVO.setDeptIds(pageReqVO.getDeptIds());
        // 查询 deptId-taskId 分组内最后1条记录id 设置展开列标识
        List<IotRhDailyReportDO> currentGroupIds = iotRhDailyReportService.rhWellNameDailyReportsGroupIds(currentTaskReqVO);
        // key部门id-任务id   value小组内最后1条记录id
        Map<String, Long> groupIdPair = new HashMap<>();
        if (CollUtil.isNotEmpty(currentGroupIds)) {
            currentGroupIds.forEach(groupId -> {
                String uniqueKey = StrUtil.join("-", groupId.getDeptId(), groupId.getTaskId());
                groupIdPair.put(uniqueKey, groupId.getId());
            });
        }

        // 设置 分组内最后1条记录id 与 deptId-taskId 唯一键的对应关系
        if (CollUtil.isNotEmpty(groupIdPair)) {
            groupIdPair.forEach((uniqueKey, groupId) -> {
                if (groupGasInjectionPair.containsKey(uniqueKey)) {
                    groupIdGasInjectionPair.put(groupId, groupGasInjectionPair.get(uniqueKey));
                }
                if (groupWaterInjectionPair.containsKey(uniqueKey)) {
                    groupIdWaterInjectionPair.put(groupId, groupWaterInjectionPair.get(uniqueKey));
                }
                if (groupPowerPair.containsKey(uniqueKey)) {
                    groupIdPowerPair.put(groupId, groupPowerPair.get(uniqueKey));
                }
                if (groupFuelPair.containsKey(uniqueKey)) {
                    groupIdFuelPair.put(groupId, groupFuelPair.get(uniqueKey));
                }
                if (groupGasTimePair.containsKey(uniqueKey)) {
                    groupIdGasTimePair.put(groupId, groupGasTimePair.get(uniqueKey));
                }
                if (groupNoProductTimePair.containsKey(uniqueKey)) {
                    groupIdNoProductTimePair.put(groupId, groupNoProductTimePair.get(uniqueKey));
                }

            });
        }

        // key部门id  value产能
        AtomicReference<Map<Long, BigDecimal>> capacityPair = new AtomicReference<>(new HashMap<>());
        // 施工状态 字典数据
        List<DictDataDO> constructionStatusDictData = dictDataService.getDictDataListByDictType("constructionStatus");
        // 非生产时间原因 字典数据
        List<DictDataDO> nptReasonDictData = dictDataService.getDictDataListByDictType("nptReason");
        if (CollUtil.isNotEmpty(constructionStatusDictData)) {
            constructionStatusDictData.forEach(data -> {
                constructStatusPair.put(data.getValue(), data.getLabel());
            });
        }
        if (CollUtil.isNotEmpty(nptReasonDictData)) {
            nptReasonDictData.forEach(data -> {
                nptReasonPair.put(data.getValue(), data.getLabel());
            });
        }
        DataPermissionUtils.executeIgnore(() -> {
            // 查询日报关联的项目信息
            IotProjectInfoPageReqVO reqVO = new IotProjectInfoPageReqVO();
            reqVO.setProjectIds(convertList(reports, IotRhDailyReportDO::getProjectId));
            List<IotProjectInfoDO> projects = iotProjectInfoService.getIotProjectInfos(reqVO);
            if (CollUtil.isNotEmpty(projects)) {
                projects.forEach(project -> {
                    projectPair.put(project.getId(), project.getContractName());
                });
            }
            // 查询日报关联的任务信息
            IotProjectTaskPageReqVO taskReqVO = new IotProjectTaskPageReqVO();
            taskReqVO.setTaskIds(convertList(reports, IotRhDailyReportDO::getTaskId));
            List<IotProjectTaskDO> tasks = iotProjectTaskService.projectTasks(taskReqVO);
            if (CollUtil.isNotEmpty(tasks)) {
                tasks.forEach(task -> {
                    taskPair.put(task.getId(), task.getWellName());
                    if (CollUtil.isNotEmpty(task.getExtProperty())) {
                        List<IotTaskAttrModelProperty> taskAttrs = task.getExtProperty();
                        if (CollUtil.isNotEmpty(taskAttrs)) {
                            // 找到 设计注气量 属性 对应的值
                            taskAttrs.forEach(attr -> {
                                if ("设计注气量".equals(attr.getName()) && StrUtil.isNotBlank(attr.getActualValue())) {
                                    taskExtPropertyPair.put(task.getId(), attr.getActualValue());
                                }
                            });
                        }
                    }
                });
            }
            // 查询当前日报所属施工队伍中包含 增压机 的产能
            capacityPair.set(iotRhDailyReportService.queryCapacities(convertList(reports, IotRhDailyReportDO::getDeptId)));
            // 查询每个任务的搬迁安装天数
            List<IotRhDailyReportDO> relocationDays = iotRhDailyReportService.relocationDays(null);
            if (CollUtil.isNotEmpty(relocationDays)) {
                relocationDays.forEach(day -> {
                    relocationDaysPair.put(day.getDeptId(), day.getRelocationDays());
                });
            }
        });
        // 2. 拼接数据
        return BeanUtils.toBean(reports, IotRhDailyReportRespVO.class, (reportVO) -> {
            if (ObjUtil.isNotEmpty(reportVO.getTransitTime())) {
                // 获取原始小数
                BigDecimal transitTime = reportVO.getTransitTime();
                // 乘以100转换为百分比数值
                BigDecimal percentage = transitTime.multiply(BigDecimal.valueOf(100));
                // 格式化保留2位小数
                DecimalFormat df = new DecimalFormat("0.00");
                String transitTimeRate = df.format(percentage) + "%";
                // 赋值
                reportVO.setTransitTimeRate(transitTimeRate);
            }

            // 导出列表时 格式化时间为 yyyy-MM-dd
            if (ObjUtil.isNotEmpty(reportVO.getCreateTime())) {
                reportVO.setCreateTimeStr(LocalDateTimeUtil.format(reportVO.getCreateTime(), DatePattern.NORM_DATE_PATTERN));
            }

            // 转换用电量 单位 kWh 转换成 MWh
            // 用电量 kWh 转换单位 MWh
            if (reportVO.getDailyPowerUsage().compareTo(BigDecimal.ZERO) > 0) {
                BigDecimal powerW = reportVO.getDailyPowerUsage()
                        .divide(BigDecimal.valueOf(1000), 2, RoundingMode.HALF_UP);
                reportVO.setDailyPowerUsage(powerW);
            }

            // 转换当日注气量 原始单位 方 转换成 万方
            if (reportVO.getDailyGasInjection().compareTo(BigDecimal.ZERO) > 0) {
                BigDecimal gasW = reportVO.getDailyGasInjection()
                        .divide(BigDecimal.valueOf(10000), 4, RoundingMode.HALF_UP);
                reportVO.setDailyGasInjection(gasW);
            }

            // 2.1 拼接部门信息
            findAndThen(deptMap, reportVO.getDeptId(), dept -> reportVO.setDeptName(dept.getName()));

            // 小组内最后1条记录标识
            findAndThen(groupIdGasInjectionPair, reportVO.getId(), gasInjection -> reportVO.setLastGroupIdFlag(true));
            // 小组内累计注气量 精确到单位 万方
            findAndThen(groupIdGasInjectionPair, reportVO.getId(), gasInjection -> {
                BigDecimal gasInjectionWanFang = gasInjection
                        .divide(BigDecimal.valueOf(10000), 4, RoundingMode.HALF_UP);
                reportVO.setGroupIdGasInjection(gasInjectionWanFang);
            });
            // 小组内累计注水量
            findAndThen(groupIdWaterInjectionPair, reportVO.getId(), waterInjection -> reportVO.setGroupIdWaterInjection(waterInjection));
            // 小组内累计用电量 MWh
            findAndThen(groupIdPowerPair, reportVO.getId(), power -> {
                BigDecimal powerWanFang = power
                        .divide(BigDecimal.valueOf(1000), 2, RoundingMode.HALF_UP);
                reportVO.setGroupIdPower(powerWanFang);
            });
            // 小组内累计油耗 L
            findAndThen(groupIdFuelPair, reportVO.getId(), fuel -> reportVO.setGroupIdFuel(fuel));
            // 小组内累计注气时间
            findAndThen(groupIdGasTimePair, reportVO.getId(), gasTime -> reportVO.setGroupIdGasTime(gasTime));
            // 小组内累计非生产时间
            findAndThen(groupIdNoProductTimePair, reportVO.getId(), noProductTime -> reportVO.setGroupIdNoProductTime(noProductTime));
            // 小组内累计运行时效
            // findAndThen(groupIdTransTimePair, reportVO.getId(), transitTime -> reportVO.setGroupIdTransitTime(transitTime));

            // 2.2 日报关联的项目信息
            findAndThen(projectPair, reportVO.getProjectId(), contractName -> reportVO.setContractName(contractName));
            // 2.3 日报关联的任务信息
            findAndThen(taskPair, reportVO.getTaskId(), taskName -> reportVO.setTaskName(taskName));
            // 2.4 设计注气量
            findAndThen(taskExtPropertyPair, reportVO.getTaskId(), designInjection -> reportVO.setDesignInjection(designInjection));
            // 2.5 搬迁安装天数
            findAndThen(relocationDaysPair, reportVO.getDeptId(), relocationDays -> {
                if (relocationDays.compareTo(BigDecimal.ZERO) < 0) {
                    reportVO.setRelocationDays(BigDecimal.ZERO);
                } else {
                    reportVO.setRelocationDays(relocationDays);
                }
            });
            // 2.6 产能
            findAndThen(capacityPair.get(), reportVO.getDeptId(), capacity -> reportVO.setCapacity(capacity));
            // 施工状态 数据字典
            findAndThen(constructStatusPair, reportVO.getConstructionStatus(), statusLabel -> reportVO.setConstructionStatusName(statusLabel));
            // 非生产时间原因 数据字典
            findAndThen(nptReasonPair, reportVO.getNptReason(), statusLabel -> reportVO.setNptReasonName(statusLabel));

            // 井当年累计注气量
            findAndThen(wellGasInjectionPair, reportVO.getTaskId(), gasInjection -> {
                // 转换单位为 万方
                BigDecimal gasInjectionWanFang = gasInjection
                        .divide(BigDecimal.valueOf(10000), 2, RoundingMode.HALF_UP);
                reportVO.setWellTotalGasInjection(gasInjectionWanFang);
            });
            // 井当年累计注水量
            findAndThen(wellWaterInjectionPair, reportVO.getTaskId(), waterInjection -> reportVO.setWellTotalWaterInjection(waterInjection));
            // 井当年累计用电量
            findAndThen(wellPowerPair, reportVO.getTaskId(), power -> {
                // 换算单位为 MWh
                BigDecimal powerW = power
                        .divide(BigDecimal.valueOf(1000), 2, RoundingMode.HALF_UP);
                reportVO.setWellTotalPower(powerW);
            });
            // 井当年累计油耗
            findAndThen(wellFuelPair, reportVO.getTaskId(), fuel -> reportVO.setWellTotalFuel(fuel));

            // 队伍当年累计注气量
            findAndThen(yearGasInjectionPair, reportVO.getDeptId(), gasInjection -> {
                // 转换单位为 万方
                BigDecimal gasInjectionWanFang = gasInjection
                        .divide(BigDecimal.valueOf(10000), 2, RoundingMode.HALF_UP);
                reportVO.setYearTotalGasInjection(gasInjectionWanFang);
            });
            // 队伍当年累计注水量
            findAndThen(yearWaterInjectionPair, reportVO.getDeptId(), waterInjection -> reportVO.setYearTotalWaterInjection(waterInjection));
            // 队伍当年累计用电量
            findAndThen(yearPowerPair, reportVO.getDeptId(), power -> {
                // 换算单位为 MWh
                BigDecimal powerW = power
                        .divide(BigDecimal.valueOf(1000), 2, RoundingMode.HALF_UP);
                reportVO.setYearTotalPower(powerW);
            });
            // 队伍当年累计油耗
            findAndThen(yearFuelPair, reportVO.getDeptId(), fuel -> reportVO.setYearTotalFuel(fuel));
        });
    }

    /**
     * 以队伍为维度 统计 瑞恒日报 分页数据 以任务井分组小计工作量
     * @param reports
     * @return
     */
    private List<IotRhDailyReportRespVO> buildWellRhDailyReports(List<IotRhDailyReportDO> reports, IotRhDailyReportPageReqVO pageReqVO) {
        if (CollUtil.isEmpty(reports)) {
            return Collections.emptyList();
        }
        // 设备部门信息
        Map<Long, DeptDO> deptMap = deptService.getDeptMap(convertList(reports, IotRhDailyReportDO::getDeptId));
        // key项目id   value项目合同号
        Map<Long, String> projectPair = new HashMap<>();
        //  key任务id     value任务井号-施工区域
        Map<Long, String> taskPair = new HashMap<>();
        // key任务id   value设计注气量
        Map<Long, String> taskExtPropertyPair = new HashMap<>();
        // key施工状态数据字典value   value施工状态数据字典label
        Map<String, String> constructStatusPair = new HashMap<>();
        // key非生产时间原因数据字典value   value非生产时间原因数据字典label
        Map<String, String> nptReasonPair = new HashMap<>();
        // 搬迁安装天数
        Map<Long, BigDecimal> relocationDaysPair = new HashMap<>();

        // key部门id-队伍id   value 任务井当年累计注气量
        Map<String, BigDecimal> groupGasInjectionPair = new HashMap<>();
        // key部门id-队伍id   value 任务井当年累计注水量
        Map<String, BigDecimal> groupWaterInjectionPair = new HashMap<>();
        // key部门id-队伍id   value 任务井当年累计用电量
        Map<String, BigDecimal> groupPowerPair = new HashMap<>();
        // key部门id-队伍id   value 任务井当年累计油耗
        Map<String, BigDecimal> groupFuelPair = new HashMap<>();
        // key部门id-队伍id    value 任务井注气时间小计
        Map<String, BigDecimal> groupGasTimePair = new HashMap<>();
        // key部门id-队伍id    value 任务井非生产时间小计
        Map<String, BigDecimal> groupNoProductTimePair = new HashMap<>();
        // key部门id-队伍id    value 任务井小计平均运行时效
        Map<String, BigDecimal> groupTransTimePair = new HashMap<>();

        // key小组最后1条记录id   value 任务井当年累计注气量
        Map<Long, BigDecimal> groupIdGasInjectionPair = new HashMap<>();
        // key小组最后1条记录id   value 任务井当年累计注水量
        Map<Long, BigDecimal> groupIdWaterInjectionPair = new HashMap<>();
        // key小组最后1条记录id   value 任务井当年累计用电量
        Map<Long, BigDecimal> groupIdPowerPair = new HashMap<>();
        // key小组最后1条记录id   value 任务井当年累计油耗
        Map<Long, BigDecimal> groupIdFuelPair = new HashMap<>();
        // key小组最后1条记录id    value 任务井注气时间小计
        Map<Long, BigDecimal> groupIdGasTimePair = new HashMap<>();
        // key小组最后1条记录id    value 任务井非生产时间小计
        Map<Long, BigDecimal> groupIdNoProductTimePair = new HashMap<>();
        // key小组最后1条记录id    value 任务井小计平均运行时效
        Map<Long, BigDecimal> groupIdTransTimePair = new HashMap<>();

        // key队伍id   value 队伍当年累计注气量
        Map<Long, BigDecimal> yearGasInjectionPair = new HashMap<>();
        // key队伍id   value 队伍当年累计注水量
        Map<Long, BigDecimal> yearWaterInjectionPair = new HashMap<>();
        // key队伍id   value 队伍当年累计用电量
        Map<Long, BigDecimal> yearPowerPair = new HashMap<>();
        // key队伍id   value 队伍当年累计油耗
        Map<Long, BigDecimal> yearFuelPair = new HashMap<>();

        // key任务井id    value 井累计注气量
        Map<Long, BigDecimal> wellGasInjectionPair = new HashMap<>();
        // key任务井id    value 井累计注水量
        Map<Long, BigDecimal> wellWaterInjectionPair = new HashMap<>();
        // key任务井id    value 井累计用电量
        Map<Long, BigDecimal> wellPowerPair = new HashMap<>();
        // key任务井id    value 井累计油耗
        Map<Long, BigDecimal> wellFuelPair = new HashMap<>();

        // 查询所有井日报数据
        IotRhDailyReportPageReqVO teamTaskReqVO = new IotRhDailyReportPageReqVO();
        teamTaskReqVO.setTaskIds(convertList(reports, IotRhDailyReportDO::getTaskId));
        List<IotRhDailyReportDO> taskDailyReports = iotRhDailyReportMapper.dailyReports(teamTaskReqVO);
        if (CollUtil.isNotEmpty(taskDailyReports)) {
            taskDailyReports.forEach(report -> {
                // 注气量
                if (wellGasInjectionPair.containsKey(report.getTaskId())) {
                    BigDecimal tempGasInjection = wellGasInjectionPair.get(report.getTaskId());
                    BigDecimal tempResult = tempGasInjection.add(report.getDailyGasInjection());
                    wellGasInjectionPair.put(report.getTaskId(), tempResult);
                } else {
                    wellGasInjectionPair.put(report.getTaskId(), report.getDailyGasInjection());
                }
                // 注水量
                if (wellWaterInjectionPair.containsKey(report.getTaskId())) {
                    BigDecimal tempWaterInjection = wellWaterInjectionPair.get(report.getTaskId());
                    BigDecimal tempResult = tempWaterInjection.add(report.getDailyWaterInjection());
                    wellWaterInjectionPair.put(report.getTaskId(), tempResult);
                } else {
                    wellWaterInjectionPair.put(report.getTaskId(), report.getDailyWaterInjection());
                }
                // 电量
                if (wellPowerPair.containsKey(report.getTaskId())) {
                    BigDecimal tempPower = wellPowerPair.get(report.getTaskId());
                    BigDecimal tempResult = tempPower.add(report.getDailyPowerUsage());
                    wellPowerPair.put(report.getTaskId(), tempResult);
                } else {
                    wellPowerPair.put(report.getTaskId(), report.getDailyPowerUsage());
                }
                // 油耗
                if (wellFuelPair.containsKey(report.getTaskId())) {
                    BigDecimal tempFuel = wellFuelPair.get(report.getTaskId());
                    BigDecimal tempResult = tempFuel.add(report.getDailyOilUsage());
                    wellFuelPair.put(report.getTaskId(), tempResult);
                } else {
                    wellFuelPair.put(report.getTaskId(), report.getDailyOilUsage());
                }
            });
        }

        // 根据传递的时间筛选获取要查询的 yyyy
        // 如果没有传递时间区间 默认当年
        LocalDateTime nowDate = LocalDateTime.now();
        String year = StrUtil.EMPTY;
        if (ObjUtil.isNotEmpty(pageReqVO.getCreateTime())) {
            LocalDateTime[] createTimeAttr = pageReqVO.getCreateTime();
            if (createTimeAttr.length > 0) {
                LocalDateTime startTime = createTimeAttr[0];
                year = String.valueOf(startTime.getYear());
            }
        } else {
            year = String.valueOf(nowDate.getYear());
        }
        // 只有传递了 时间查询条件 才会查询 当年累计的工作量数据
        IotRhDailyReportPageReqVO yearReqVO = new IotRhDailyReportPageReqVO();
        yearReqVO.setYear(year);
        yearReqVO.setDeptIds(convertList(reports, IotRhDailyReportDO::getDeptId));
        List<IotRhDailyReportDO> dailyReports = iotRhDailyReportMapper.dailyReports(yearReqVO);
        if (CollUtil.isNotEmpty(dailyReports)) {
            dailyReports.forEach(report -> {
                // 注气量
                if (yearGasInjectionPair.containsKey(report.getDeptId())) {
                    BigDecimal tempGasInjection = yearGasInjectionPair.get(report.getDeptId());
                    BigDecimal tempResult = tempGasInjection.add(report.getDailyGasInjection());
                    yearGasInjectionPair.put(report.getDeptId(), tempResult);
                } else {
                    yearGasInjectionPair.put(report.getDeptId(), report.getDailyGasInjection());
                }
                // 注水量
                if (yearWaterInjectionPair.containsKey(report.getDeptId())) {
                    BigDecimal tempWaterInjection = yearWaterInjectionPair.get(report.getDeptId());
                    BigDecimal tempResult = tempWaterInjection.add(report.getDailyWaterInjection());
                    yearWaterInjectionPair.put(report.getDeptId(), tempResult);
                } else {
                    yearWaterInjectionPair.put(report.getDeptId(), report.getDailyWaterInjection());
                }
                // 电量
                if (yearPowerPair.containsKey(report.getDeptId())) {
                    BigDecimal tempPower = yearPowerPair.get(report.getDeptId());
                    BigDecimal tempResult = tempPower.add(report.getDailyPowerUsage());
                    yearPowerPair.put(report.getDeptId(), tempResult);
                } else {
                    yearPowerPair.put(report.getDeptId(), report.getDailyPowerUsage());
                }
                // 油耗
                if (yearFuelPair.containsKey(report.getDeptId())) {
                    BigDecimal tempFuel = yearFuelPair.get(report.getDeptId());
                    BigDecimal tempResult = tempFuel.add(report.getDailyOilUsage());
                    yearFuelPair.put(report.getDeptId(), tempResult);
                } else {
                    yearFuelPair.put(report.getDeptId(), report.getDailyOilUsage());
                }
            });
        }

        // 查询 当前分页 所有部门 任务井 日报数据 小计工作量
        IotRhDailyReportPageReqVO currentTaskReqVO = new IotRhDailyReportPageReqVO();
        currentTaskReqVO.setTaskIds(convertSet(reports, IotRhDailyReportDO::getTaskId));
        currentTaskReqVO.setDeptIds(convertSet(reports, IotRhDailyReportDO::getDeptId));
        currentTaskReqVO.setCreateTime(pageReqVO.getCreateTime());
        currentTaskReqVO.setProjectIds(pageReqVO.getProjectIds());
        currentTaskReqVO.setTaskIds(pageReqVO.getTaskIds());
        List<IotRhDailyReportDO> deptTaskDailyReports = iotRhDailyReportMapper.dailyReports(currentTaskReqVO);

        // 以 deptId-taskId 为唯一键 小计日报工作量
        if (CollUtil.isNotEmpty(deptTaskDailyReports)) {
            deptTaskDailyReports.forEach(report -> {
                String uniqueKey = StrUtil.join("-", report.getDeptId(), report.getTaskId());
                // 注气量
                if (groupGasInjectionPair.containsKey(uniqueKey)) {
                    BigDecimal tempGasInjection = groupGasInjectionPair.get(uniqueKey);
                    BigDecimal tempResult = tempGasInjection.add(report.getDailyGasInjection());
                    groupGasInjectionPair.put(uniqueKey, tempResult);
                } else {
                    groupGasInjectionPair.put(uniqueKey, report.getDailyGasInjection());
                }
                // 注水量
                if (groupWaterInjectionPair.containsKey(uniqueKey)) {
                    BigDecimal tempWaterInjection = groupWaterInjectionPair.get(uniqueKey);
                    BigDecimal tempResult = tempWaterInjection.add(report.getDailyWaterInjection());
                    groupWaterInjectionPair.put(uniqueKey, tempResult);
                } else {
                    groupWaterInjectionPair.put(uniqueKey, report.getDailyWaterInjection());
                }
                // 电量
                if (groupPowerPair.containsKey(uniqueKey)) {
                    BigDecimal tempPower = groupPowerPair.get(uniqueKey);
                    BigDecimal tempResult = tempPower.add(report.getDailyPowerUsage());
                    groupPowerPair.put(uniqueKey, tempResult);
                } else {
                    groupPowerPair.put(uniqueKey, report.getDailyPowerUsage());
                }
                // 油耗
                if (groupFuelPair.containsKey(uniqueKey)) {
                    BigDecimal tempFuel = groupFuelPair.get(uniqueKey);
                    BigDecimal tempResult = tempFuel.add(report.getDailyOilUsage());
                    groupFuelPair.put(uniqueKey, tempResult);
                } else {
                    groupFuelPair.put(uniqueKey, report.getDailyOilUsage());
                }
                // 注气时间
                if (groupGasTimePair.containsKey(uniqueKey)) {
                    BigDecimal tempGasTime = groupGasTimePair.get(uniqueKey);
                    BigDecimal tempResult = tempGasTime.add(report.getDailyInjectGasTime());
                    groupGasTimePair.put(uniqueKey, tempResult);
                } else {
                    groupGasTimePair.put(uniqueKey, report.getDailyInjectGasTime());
                }
                // 非生产时间
                if (groupNoProductTimePair.containsKey(uniqueKey)) {
                    BigDecimal tempNoProductTime = groupNoProductTimePair.get(uniqueKey);
                    BigDecimal tempResult = tempNoProductTime.add(report.getNonProductionTime());
                    groupNoProductTimePair.put(uniqueKey, tempResult);
                } else {
                    groupNoProductTimePair.put(uniqueKey, report.getNonProductionTime());
                }
            });
        }

        TenantUtils.executeIgnore(() -> {
            currentTaskReqVO.setDeptId(pageReqVO.getDeptId());
            // 查询 deptId-taskId 分组内最后1条记录id 设置展开列标识
            List<IotRhDailyReportDO> currentGroupIds = iotRhDailyReportService.rhDeptDailyReportsGroupIds(currentTaskReqVO);
            // key部门id-任务id   value小组内最后1条记录id
            Map<String, Long> groupIdPair = new HashMap<>();
            if (CollUtil.isNotEmpty(currentGroupIds)) {
                currentGroupIds.forEach(groupId -> {
                    String uniqueKey = StrUtil.join("-", groupId.getDeptId(), groupId.getTaskId());
                    groupIdPair.put(uniqueKey, groupId.getId());
                });
            }

            // 设置 分组内最后1条记录id 与 deptId-taskId 唯一键的对应关系
            if (CollUtil.isNotEmpty(groupIdPair)) {
                groupIdPair.forEach((uniqueKey, groupId) -> {
                    if (groupGasInjectionPair.containsKey(uniqueKey)) {
                        groupIdGasInjectionPair.put(groupId, groupGasInjectionPair.get(uniqueKey));
                    }
                    if (groupWaterInjectionPair.containsKey(uniqueKey)) {
                        groupIdWaterInjectionPair.put(groupId, groupWaterInjectionPair.get(uniqueKey));
                    }
                    if (groupPowerPair.containsKey(uniqueKey)) {
                        groupIdPowerPair.put(groupId, groupPowerPair.get(uniqueKey));
                    }
                    if (groupFuelPair.containsKey(uniqueKey)) {
                        groupIdFuelPair.put(groupId, groupFuelPair.get(uniqueKey));
                    }
                    if (groupGasTimePair.containsKey(uniqueKey)) {
                        groupIdGasTimePair.put(groupId, groupGasTimePair.get(uniqueKey));
                    }
                    if (groupNoProductTimePair.containsKey(uniqueKey)) {
                        groupIdNoProductTimePair.put(groupId, groupNoProductTimePair.get(uniqueKey));
                    }

                });
            }
        });

        // key部门id  value产能
        AtomicReference<Map<Long, BigDecimal>> capacityPair = new AtomicReference<>(new HashMap<>());
        // 施工状态 字典数据
        List<DictDataDO> constructionStatusDictData = dictDataService.getDictDataListByDictType("constructionStatus");
        // 非生产时间原因 字典数据
        List<DictDataDO> nptReasonDictData = dictDataService.getDictDataListByDictType("nptReason");
        if (CollUtil.isNotEmpty(constructionStatusDictData)) {
            constructionStatusDictData.forEach(data -> {
                constructStatusPair.put(data.getValue(), data.getLabel());
            });
        }
        if (CollUtil.isNotEmpty(nptReasonDictData)) {
            nptReasonDictData.forEach(data -> {
                nptReasonPair.put(data.getValue(), data.getLabel());
            });
        }
        DataPermissionUtils.executeIgnore(() -> {
            // 查询日报关联的项目信息
            IotProjectInfoPageReqVO reqVO = new IotProjectInfoPageReqVO();
            reqVO.setProjectIds(convertList(reports, IotRhDailyReportDO::getProjectId));
            List<IotProjectInfoDO> projects = iotProjectInfoService.getIotProjectInfos(reqVO);
            if (CollUtil.isNotEmpty(projects)) {
                projects.forEach(project -> {
                    projectPair.put(project.getId(), project.getContractName());
                });
            }
            // 查询日报关联的任务信息
            IotProjectTaskPageReqVO taskReqVO = new IotProjectTaskPageReqVO();
            taskReqVO.setTaskIds(convertList(reports, IotRhDailyReportDO::getTaskId));
            List<IotProjectTaskDO> tasks = iotProjectTaskService.projectTasks(taskReqVO);
            if (CollUtil.isNotEmpty(tasks)) {
                tasks.forEach(task -> {
                    taskPair.put(task.getId(), task.getWellName());
                    if (CollUtil.isNotEmpty(task.getExtProperty())) {
                        List<IotTaskAttrModelProperty> taskAttrs = task.getExtProperty();
                        if (CollUtil.isNotEmpty(taskAttrs)) {
                            // 找到 设计注气量 属性 对应的值
                            taskAttrs.forEach(attr -> {
                                if ("设计注气量".equals(attr.getName()) && StrUtil.isNotBlank(attr.getActualValue())) {
                                    taskExtPropertyPair.put(task.getId(), attr.getActualValue());
                                }
                            });
                        }
                    }
                });
            }
            // 查询当前日报所属施工队伍中包含 增压机 的产能
            capacityPair.set(iotRhDailyReportService.queryCapacities(convertList(reports, IotRhDailyReportDO::getDeptId)));
            // 查询每个任务的搬迁安装天数
            List<IotRhDailyReportDO> relocationDays = iotRhDailyReportService.relocationDays(null);
            if (CollUtil.isNotEmpty(relocationDays)) {
                relocationDays.forEach(day -> {
                    relocationDaysPair.put(day.getDeptId(), day.getRelocationDays());
                });
            }
        });
        // 2. 拼接数据
        return BeanUtils.toBean(reports, IotRhDailyReportRespVO.class, (reportVO) -> {
            if (ObjUtil.isNotEmpty(reportVO.getTransitTime())) {
                // 获取原始小数
                BigDecimal transitTime = reportVO.getTransitTime();
                // 乘以100转换为百分比数值
                BigDecimal percentage = transitTime.multiply(BigDecimal.valueOf(100));
                // 格式化保留2位小数
                DecimalFormat df = new DecimalFormat("0.00");
                String transitTimeRate = df.format(percentage) + "%";
                // 赋值
                reportVO.setTransitTimeRate(transitTimeRate);
            }
            // 导出列表时 格式化时间为 yyyy-MM-dd
            if (ObjUtil.isNotEmpty(reportVO.getCreateTime())) {
                reportVO.setCreateTimeStr(LocalDateTimeUtil.format(reportVO.getCreateTime(), DatePattern.NORM_DATE_PATTERN));
            }
            // 用电量 kWh 转换单位 MWh
            if (reportVO.getDailyPowerUsage().compareTo(BigDecimal.ZERO) > 0) {
                BigDecimal powerW = reportVO.getDailyPowerUsage()
                        .divide(BigDecimal.valueOf(1000), 2, RoundingMode.HALF_UP);
                reportVO.setDailyPowerUsage(powerW);
            }

            // 转换当日注气量 原始单位 方 转换成 万方
            if (reportVO.getDailyGasInjection().compareTo(BigDecimal.ZERO) > 0) {
                BigDecimal gasW = reportVO.getDailyGasInjection()
                        .divide(BigDecimal.valueOf(10000), 4, RoundingMode.HALF_UP);
                reportVO.setDailyGasInjection(gasW);
            }

            // 2.1 拼接部门信息
            findAndThen(deptMap, reportVO.getDeptId(), dept -> reportVO.setDeptName(dept.getName()));

            // 小组内最后1条记录标识
            findAndThen(groupIdGasInjectionPair, reportVO.getId(), gasInjection -> reportVO.setLastGroupIdFlag(true));
            // 小组内累计注气量
            findAndThen(groupIdGasInjectionPair, reportVO.getId(), gasInjection -> {
                BigDecimal gasInjectionWanFang = gasInjection
                        .divide(BigDecimal.valueOf(10000), 4, RoundingMode.HALF_UP);
                reportVO.setGroupIdGasInjection(gasInjectionWanFang);
            });
            // 小组内累计注水量
            findAndThen(groupIdWaterInjectionPair, reportVO.getId(), waterInjection -> reportVO.setGroupIdWaterInjection(waterInjection));
            // 小组内累计用电量
            findAndThen(groupIdPowerPair, reportVO.getId(), power -> {
                BigDecimal powerW = power
                        .divide(BigDecimal.valueOf(1000), 2, RoundingMode.HALF_UP);
                reportVO.setGroupIdPower(powerW);
            });
            // 小组内累计油耗
            findAndThen(groupIdFuelPair, reportVO.getId(), fuel -> reportVO.setGroupIdFuel(fuel));
            // 小组内累计注气时间
            findAndThen(groupIdGasTimePair, reportVO.getId(), gasTime -> reportVO.setGroupIdGasTime(gasTime));
            // 小组内累计非生产时间
            findAndThen(groupIdNoProductTimePair, reportVO.getId(), noProductTime -> reportVO.setGroupIdNoProductTime(noProductTime));
            // 小组内累计运行时效
            // findAndThen(groupIdTransTimePair, reportVO.getId(), transitTime -> reportVO.setGroupIdTransitTime(transitTime));

            // 2.2 日报关联的项目信息
            findAndThen(projectPair, reportVO.getProjectId(), contractName -> reportVO.setContractName(contractName));
            // 2.3 日报关联的任务信息
            findAndThen(taskPair, reportVO.getTaskId(), taskName -> reportVO.setTaskName(taskName));
            // 2.4 设计注气量
            findAndThen(taskExtPropertyPair, reportVO.getTaskId(), designInjection -> reportVO.setDesignInjection(designInjection));
            // 2.5 搬迁安装天数
            findAndThen(relocationDaysPair, reportVO.getDeptId(), relocationDays -> {
                if (relocationDays.compareTo(BigDecimal.ZERO) < 0) {
                    reportVO.setRelocationDays(BigDecimal.ZERO);
                } else {
                    reportVO.setRelocationDays(relocationDays);
                }
            });
            // 2.6 产能
            findAndThen(capacityPair.get(), reportVO.getDeptId(), capacity -> reportVO.setCapacity(capacity));
            // 施工状态 数据字典
            findAndThen(constructStatusPair, reportVO.getConstructionStatus(), statusLabel -> reportVO.setConstructionStatusName(statusLabel));
            // 非生产时间原因 数据字典
            findAndThen(nptReasonPair, reportVO.getNptReason(), statusLabel -> reportVO.setNptReasonName(statusLabel));

            // 队伍当年累计注气量
            findAndThen(yearGasInjectionPair, reportVO.getDeptId(), gasInjection -> {
                // 转换单位为 万方
                BigDecimal gasInjectionWanFang = gasInjection
                        .divide(BigDecimal.valueOf(10000), 2, RoundingMode.HALF_UP);
                reportVO.setYearTotalGasInjection(gasInjectionWanFang);
            });
            // 队伍当年累计注水量
            findAndThen(yearWaterInjectionPair, reportVO.getDeptId(), waterInjection -> reportVO.setYearTotalWaterInjection(waterInjection));
            // 队伍当年累计用电量
            findAndThen(yearPowerPair, reportVO.getDeptId(), power -> {
                // 换算单位为 MWh
                BigDecimal powerW = power
                        .divide(BigDecimal.valueOf(1000), 2, RoundingMode.HALF_UP);
                reportVO.setYearTotalPower(powerW);
            });
            // 队伍当年累计油耗
            findAndThen(yearFuelPair, reportVO.getDeptId(), fuel -> reportVO.setYearTotalFuel(fuel));

            // 井当年累计注气量
            findAndThen(wellGasInjectionPair, reportVO.getTaskId(), gasInjection -> {
                // 转换单位为 万方
                BigDecimal gasInjectionWanFang = gasInjection
                        .divide(BigDecimal.valueOf(10000), 2, RoundingMode.HALF_UP);
                reportVO.setWellTotalGasInjection(gasInjectionWanFang);
            });
            // 井当年累计注水量
            findAndThen(wellWaterInjectionPair, reportVO.getTaskId(), waterInjection -> reportVO.setWellTotalWaterInjection(waterInjection));
            // 井当年累计用电量
            findAndThen(wellPowerPair, reportVO.getTaskId(), power -> {
                // 换算单位为 MWh
                BigDecimal powerW = power
                        .divide(BigDecimal.valueOf(1000), 2, RoundingMode.HALF_UP);
                reportVO.setWellTotalPower(powerW);
            });
            // 井当年累计油耗
            findAndThen(wellFuelPair, reportVO.getTaskId(), fuel -> reportVO.setWellTotalFuel(fuel));
        });
    }

    @GetMapping("/export-excel")
    @Operation(summary = "导出瑞恒日报 Excel")
    @PreAuthorize("@ss.hasPermission('pms:iot-rh-daily-report:export')")
    @ApiAccessLog(operateType = EXPORT)
    public void exportIotRhDailyReportExcel(@Valid IotRhDailyReportPageReqVO pageReqVO,
              HttpServletResponse response) throws IOException {
        pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE);
        // 根据查询参数筛选出 符合条件 的记录id 再传入 分页查询
        Set<Long> projectIds = new HashSet<>();
        Set<Long> taskIds = new HashSet<>();
        if (StrUtil.isNotBlank(pageReqVO.getContractName())) {
            IotProjectInfoPageReqVO reqVO = new IotProjectInfoPageReqVO();
            reqVO.setContractName(pageReqVO.getContractName());
            List<IotProjectInfoDO> projects = iotProjectInfoService.getIotProjectInfos(reqVO);
            if (CollUtil.isNotEmpty(projects)) {
                projects.forEach(project -> {
                    projectIds.add(project.getId());
                });
                pageReqVO.setProjectIds(projectIds);
            }
        }
        if (StrUtil.isNotBlank(pageReqVO.getTaskName())) {
            IotProjectTaskPageReqVO reqVO = new IotProjectTaskPageReqVO();
            reqVO.setSearchKey(pageReqVO.getTaskName());
            List<IotProjectTaskDO> tasks = iotProjectTaskService.projectTasks(reqVO);
            if (CollUtil.isNotEmpty(tasks)) {
                tasks.forEach(task -> {
                    taskIds.add(task.getId());
                });
                pageReqVO.setTaskIds(taskIds);
            }
        }
        List<IotRhDailyReportDO> list = iotRhDailyReportService.getIotRhDailyReportPage(pageReqVO).getList();
        // 导出 Excel
        ExcelUtils.write(response, "瑞恒日报.xls", "数据", IotRhDailyReportRespVO.class,
                buildRhDailyReports(list, pageReqVO, "export"));
    }

    @GetMapping("/exportStatistics")
    @Operation(summary = "导出瑞恒日报汇总 Excel")
    @PreAuthorize("@ss.hasPermission('pms:iot-rh-daily-report:export')")
    @ApiAccessLog(operateType = EXPORT)
    public void exportStatistics(@Valid IotRhDailyReportPageReqVO pageReqVO,
                                            HttpServletResponse response) throws IOException {
        pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE);
        // 根据查询参数筛选出 符合条件 的记录id 再传入 分页查询
        Set<Long> projectIds = new HashSet<>();
        Set<Long> taskIds = new HashSet<>();
        if (StrUtil.isNotBlank(pageReqVO.getContractName())) {
            IotProjectInfoPageReqVO reqVO = new IotProjectInfoPageReqVO();
            reqVO.setContractName(pageReqVO.getContractName());
            List<IotProjectInfoDO> projects = iotProjectInfoService.getIotProjectInfos(reqVO);
            if (CollUtil.isNotEmpty(projects)) {
                projects.forEach(project -> {
                    projectIds.add(project.getId());
                });
                pageReqVO.setProjectIds(projectIds);
            }
        }
        if (StrUtil.isNotBlank(pageReqVO.getTaskName())) {
            IotProjectTaskPageReqVO reqVO = new IotProjectTaskPageReqVO();
            reqVO.setSearchKey(pageReqVO.getTaskName());
            List<IotProjectTaskDO> tasks = iotProjectTaskService.projectTasks(reqVO);
            if (CollUtil.isNotEmpty(tasks)) {
                tasks.forEach(task -> {
                    taskIds.add(task.getId());
                });
                pageReqVO.setTaskIds(taskIds);
            }
        }
        List<IotRhDailyReportStatisticsRespVO> statistics = iotRhDailyReportService.statistics(pageReqVO);
        // 设置 运行时效 转换为 %
        if (CollUtil.isNotEmpty(statistics)) {
            statistics.forEach(stat -> {
                BigDecimal transitTime = stat.getTransitTime();
                if (ObjUtil.isEmpty(transitTime) || transitTime.compareTo(BigDecimal.ZERO) == 0) {
                    stat.setTransitTimePercent("0.00%");
                } else {
                    // 转换逻辑：乘以100 → 保留2位小数（四舍五入）→ 拼接%
                    BigDecimal percent = transitTime.multiply(new BigDecimal("100"))
                            .setScale(2, RoundingMode.HALF_UP);
                    stat.setTransitTimePercent(percent + "%");
                }
            });
        }
        // 导出 Excel
        ExcelUtils.write(response, "瑞恒日报汇总.xls", "日报汇总数据",
                IotRhDailyReportStatisticsRespVO.class, statistics);
    }

    @GetMapping("/exportSingleWells")
    @Operation(summary = "导出瑞恒日报 报表统计 单井 Excel")
    @PreAuthorize("@ss.hasPermission('pms:iot-rh-daily-report:export')")
    @ApiAccessLog(operateType = EXPORT)
    public void exportSingleWells(@Valid IotRhDailyReportPageReqVO pageReqVO,
                                 HttpServletResponse response) throws IOException {
        pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE);
        // 根据查询参数筛选出 符合条件 的记录id 再传入 分页查询
        Set<Long> projectIds = new HashSet<>();
        Set<Long> taskIds = new HashSet<>();
        if (StrUtil.isNotBlank(pageReqVO.getContractName())) {
            IotProjectInfoPageReqVO reqVO = new IotProjectInfoPageReqVO();
            reqVO.setContractName(pageReqVO.getContractName());
            List<IotProjectInfoDO> projects = iotProjectInfoService.getIotProjectInfos(reqVO);
            if (CollUtil.isNotEmpty(projects)) {
                projects.forEach(project -> {
                    projectIds.add(project.getId());
                });
                pageReqVO.setProjectIds(projectIds);
            }
        }
        if (StrUtil.isNotBlank(pageReqVO.getTaskName())) {
            IotProjectTaskPageReqVO reqVO = new IotProjectTaskPageReqVO();
            reqVO.setSearchKey(pageReqVO.getTaskName());
            List<IotProjectTaskDO> tasks = iotProjectTaskService.projectTasks(reqVO);
            if (CollUtil.isNotEmpty(tasks)) {
                tasks.forEach(task -> {
                    taskIds.add(task.getId());
                });
                pageReqVO.setTaskIds(taskIds);
            }
        }
        List<IotRhDailyReportDO> reports = iotRhDailyReportService.teamReports(pageReqVO).getList();
        // 导出 Excel
        ExcelUtils.write(response, "瑞恒日报单井统计.xls", "日报单井统计",
                IotRhDailyReportRespVO.class, buildSubtotalRhDailyReports(reports, pageReqVO));
    }

    @GetMapping("/exportSingleTeams")
    @Operation(summary = "导出瑞恒日报 报表统计 队伍 Excel")
    @PreAuthorize("@ss.hasPermission('pms:iot-rh-daily-report:export')")
    @ApiAccessLog(operateType = EXPORT)
    public void exportSingleTeams(@Valid IotRhDailyReportPageReqVO pageReqVO,
                                  HttpServletResponse response) throws IOException {
        pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE);
        // 根据查询参数筛选出 符合条件 的记录id 再传入 分页查询
        Set<Long> projectIds = new HashSet<>();
        Set<Long> taskIds = new HashSet<>();
        if (StrUtil.isNotBlank(pageReqVO.getContractName())) {
            IotProjectInfoPageReqVO reqVO = new IotProjectInfoPageReqVO();
            reqVO.setContractName(pageReqVO.getContractName());
            List<IotProjectInfoDO> projects = iotProjectInfoService.getIotProjectInfos(reqVO);
            if (CollUtil.isNotEmpty(projects)) {
                projects.forEach(project -> {
                    projectIds.add(project.getId());
                });
                pageReqVO.setProjectIds(projectIds);
            }
        }
        if (StrUtil.isNotBlank(pageReqVO.getTaskName())) {
            IotProjectTaskPageReqVO reqVO = new IotProjectTaskPageReqVO();
            reqVO.setSearchKey(pageReqVO.getTaskName());
            List<IotProjectTaskDO> tasks = iotProjectTaskService.projectTasks(reqVO);
            if (CollUtil.isNotEmpty(tasks)) {
                tasks.forEach(task -> {
                    taskIds.add(task.getId());
                });
                pageReqVO.setTaskIds(taskIds);
            }
        }
        List<IotRhDailyReportDO> reports = iotRhDailyReportService.wellReports(pageReqVO).getList();
        // 导出 Excel
        ExcelUtils.write(response, "瑞恒日报单队伍统计.xls", "日报单队伍统计",
                IotRhDailyReportRespVO.class, buildWellRhDailyReports(reports, pageReqVO));
    }

}