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

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.LocalDateTimeUtil;
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.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.iotattachment.vo.IotAttachmentPageReqVO;
import cn.iocoder.yudao.module.pms.controller.admin.iotcarzhbd.vo.IotCarZhbdPageReqVO;
import cn.iocoder.yudao.module.pms.controller.admin.iotdailyreportattrs.vo.IotDailyReportAttrsPageReqVO;
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.iotprojecttask.vo.IotProjectTaskPlatformVO;
import cn.iocoder.yudao.module.pms.controller.admin.iotrddailyreport.vo.*;
import cn.iocoder.yudao.module.pms.controller.admin.iotrddailyreportdetail.vo.IotRdDailyReportDetailPageReqVO;
import cn.iocoder.yudao.module.pms.controller.admin.iotrddailyreportdetail.vo.IotRdDailyReportDetailRespVO;
import cn.iocoder.yudao.module.pms.controller.admin.vo.IotDevicePageReqVO;
import cn.iocoder.yudao.module.pms.controller.admin.vo.IotDeviceRespVO;
import cn.iocoder.yudao.module.pms.controller.admin.vo.IotDeviceSimpleRespVO;
import cn.iocoder.yudao.module.pms.dal.dataobject.IotDeviceDO;
import cn.iocoder.yudao.module.pms.dal.dataobject.iotattachment.IotAttachmentDO;
import cn.iocoder.yudao.module.pms.dal.dataobject.iotcarzhbd.IotCarZhbdDO;
import cn.iocoder.yudao.module.pms.dal.dataobject.iotdailyreportattrs.IotDailyReportAttrsDO;
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.iotrddailyreportdetail.IotRdDailyReportDetailDO;
import cn.iocoder.yudao.module.pms.dal.mysql.iotattachment.IotAttachmentMapper;
import cn.iocoder.yudao.module.pms.dal.mysql.iotcarzhbd.IotCarZhbdMapper;
import cn.iocoder.yudao.module.pms.dal.mysql.iotrddailyreport.IotRdDailyReportMapper;
import cn.iocoder.yudao.module.pms.dal.mysql.iotrddailyreportdetail.IotRdDailyReportDetailMapper;
import cn.iocoder.yudao.module.pms.enums.AttachmentCategoryEnum;
import cn.iocoder.yudao.module.pms.enums.AttachmentTypeEnum;
import cn.iocoder.yudao.module.pms.job.IotDeviceCarFuelVO;
import cn.iocoder.yudao.module.pms.service.IotDeviceService;
import cn.iocoder.yudao.module.pms.service.iotattachment.IotAttachmentService;
import cn.iocoder.yudao.module.pms.service.iotdailyreportattrs.IotDailyReportAttrsService;
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.util.ZHBDUtil;
import cn.iocoder.yudao.module.system.api.user.AdminUserApi;
import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO;
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 lombok.extern.log4j.Log4j;
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.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeParseException;
import java.time.temporal.ChronoUnit;
import java.util.*;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.stream.Collectors;
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-rd-daily-report")
@Validated
@Log4j
public class IotRdDailyReportController {

    @Resource
    private IotRdDailyReportService iotRdDailyReportService;

    @Resource
    private IotProjectInfoService iotProjectInfoService;

    @Resource
    private IotProjectTaskService iotProjectTaskService;

    @Resource
    private DeptService deptService;

    @Resource
    private IotDeviceService iotDeviceService;

    @Resource
    private IotDailyReportAttrsService iotDailyReportAttrsService;

    @Resource
    private IotAttachmentService iotAttachmentService;

    @Resource
    private AdminUserApi adminUserApi;

    @Resource
    private DictDataService dictDataService;
    @Resource
    private IotCarZhbdMapper iotCarZhbdMapper;
    @Resource
    private ZHBDUtil zhbdUtil;
    @Resource
    private IotDailyReportFuelService iotDailyReportFuelService;
    @Resource
    private IotAttachmentMapper iotAttachmentMapper;
    @Resource
    private IotRdDailyReportMapper iotRdDailyReportMapper;
    @Resource
    private IotRdDailyReportDetailMapper iotRdDailyReportDetailMapper;

    @PostMapping("/create")
    @Operation(summary = "创建瑞都日报")
    @PreAuthorize("@ss.hasPermission('pms:iot-rd-daily-report:create')")
    public CommonResult<Long> createIotRdDailyReport(@Valid @RequestBody IotRdDailyReportSaveReqVO createReqVO) {
        return success(iotRdDailyReportService.createIotRdDailyReport(createReqVO));
    }

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

    @PostMapping("/saveBatch")
    @Operation(summary = "批量更新瑞都日报 平台井")
    @PreAuthorize("@ss.hasPermission('pms:iot-rd-daily-report:update')")
    public CommonResult<Boolean> saveBatch(@Valid @RequestBody List<IotRdDailyReportSaveReqVO> reports) {
        iotRdDailyReportService.saveBatch(reports);
        return success(true);
    }

    @PostMapping("/repairHistoryProdStatus")
    @Operation(summary = "修复历史生产动态数据")
    @PreAuthorize("@ss.hasPermission('pms:iot-rd-daily-report:update')")
    public CommonResult<Boolean> repairHistoryProdStatus() {
        iotRdDailyReportService.repairHistoryProdStatus();
        return success(true);
    }

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

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

    @GetMapping("/get")
    @Operation(summary = "获得瑞都日报")
    @Parameter(name = "id", description = "编号", required = true, example = "1024")
    @PreAuthorize("@ss.hasPermission('pms:iot-rd-daily-report:query')")
    public CommonResult<IotRdDailyReportRespVO> getIotRdDailyReport(@RequestParam("id") Long id) {
        IotRdDailyReportDO iotRdDailyReport = iotRdDailyReportService.getIotRdDailyReport(id);
        // 查询日报相关的 项目 任务 施工工艺 车辆油耗...
        return success(buildDailyReport(iotRdDailyReport));
    }

    /**
     * 查询日报对应的项目 任务信息
     * @param dailyReport
     * @return
     */
    private IotRdDailyReportRespVO buildDailyReport(IotRdDailyReportDO dailyReport) {
        // 如果 dailyReport 为空 返回空对象 有可能任务中安排的人员部门 与日报所在部门不同
        if (ObjUtil.isEmpty(dailyReport)) {
            return new IotRdDailyReportRespVO();
        }
        IotRdDailyReportRespVO dailyReportVO = BeanUtils.toBean(dailyReport, IotRdDailyReportRespVO.class);
        // 查询日报生产动态明细
        // 当前井及平台井的 taskId 依次查询有无 生产动态明细 哪个井有明细 用哪个任务井
        IotRdDailyReportDetailPageReqVO detailReqVO = new IotRdDailyReportDetailPageReqVO();
        detailReqVO.setPageSize(PageParam.PAGE_SIZE_NONE);
        detailReqVO.setReportId(dailyReport.getId());
        PageResult<IotRdDailyReportDetailDO> reportDetailPage = iotRdDailyReportDetailMapper.selectPage(detailReqVO);
        List<IotRdDailyReportDetailDO> reportDetails = reportDetailPage.getList();
        if (CollUtil.isNotEmpty(reportDetails)) {
            List<IotRdDailyReportDetailRespVO> dailyReportDetails = BeanUtils.toBean(reportDetails, IotRdDailyReportDetailRespVO.class);
            dailyReportVO.setReportDetails(dailyReportDetails);
        }
        // 查询施工工艺集合
        Set<Long> techniqueIds = dailyReportVO.getTechniqueIds();
        // List<DictDataDO> techniques = dictDataService.getDictDataListByDictType("rq_iot_project_technology_rd");
        if (CollUtil.isNotEmpty(techniqueIds)) {
            Set<String> stringTechniqueIds = techniqueIds.stream()
                    .map(lg -> lg.toString())
                    .collect(Collectors.toSet());
            IotDailyReportAttrsPageReqVO pageReqVO = new IotDailyReportAttrsPageReqVO();
            pageReqVO.setTechniqueIds(new ArrayList<>(stringTechniqueIds));
            List<IotDailyReportAttrsDO> attrs = iotDailyReportAttrsService.getIotDailyReportAttrs(pageReqVO);
            dailyReportVO.setDailyReportAttrs(attrs);
        }
        // 查询日报对应的项目信息
        if (ObjUtil.isNotEmpty(dailyReport.getProjectId())) {
            IotProjectInfoDO project = iotProjectInfoService.getIotProjectInfo(dailyReport.getProjectId());
            dailyReportVO.setContractName(project.getContractName());
            dailyReportVO.setManufactureName(project.getManufactureName());
            dailyReportVO.setCompanyId(project.getDeptId());
            // 虚拟项目标识
            dailyReportVO.setVirtualProject(project.getContractSubject());
        }
        // 查询当前日报是否已经绑定了油耗信息
        // 兼容主井完工 关联井 没有完工的情况 查询关联井的油耗信息
        boolean hasFuels = false;
        // 查询所有主井 关联井 油耗
        Map<Long, List<IotDailyReportFuelDO>> reportedFuelsPair = new HashMap<>();
        if (1 == dailyReport.getPlatformWell()) {
            // 查询相同平台井组关联的 日报
            IotRdDailyReportPageReqVO reportReqVO  = new IotRdDailyReportPageReqVO();
            reportReqVO.setPlatformGroup(dailyReport.getPlatformGroup());
            List<IotRdDailyReportDO> reports = iotRdDailyReportService.dailyReports(reportReqVO);
            List<Long> reportIds = convertList(reports, IotRdDailyReportDO::getId);
            // 兼容主井 完工 关联井未完工 的情况 查询关联井的油耗信息
            IotDailyReportFuelPageReqVO fuelReqVO = new IotDailyReportFuelPageReqVO();
            fuelReqVO.setType("RD");
            fuelReqVO.setReportIds(reportIds);
            List<IotDailyReportFuelDO> reportedFuels = iotDailyReportFuelService.getIotDailyReportFuels(fuelReqVO);
            if (CollUtil.isNotEmpty(reportedFuels)) {
                reportedFuels.forEach(fuel -> {
                    if (reportedFuelsPair.containsKey(fuel.getReportId())) {
                        List<IotDailyReportFuelDO> tempFuels = reportedFuelsPair.get(fuel.getReportId());
                        tempFuels.add(fuel);
                        reportedFuelsPair.put(fuel.getReportId(), tempFuels);
                    } else {
                        List<IotDailyReportFuelDO> tempFuels = new ArrayList<>();
                        tempFuels.add(fuel);
                        reportedFuelsPair.put(fuel.getReportId(), tempFuels);
                    }
                });
            }
        }

        if (CollUtil.isNotEmpty(reportedFuelsPair)) {
            hasFuels = true;
            reportedFuelsPair.forEach((reportId, fuels) -> {
                dailyReportVO.setReportedFuels(fuels);
            });
        }
        // 查询施工工艺字典数据
        List<DictDataDO> rdTechniquesDicts = dictDataService.getDictDataListByDictType("rq_iot_project_technology_rd");
        // 工作量单位 数据字典
        List<DictDataDO> measureUnitDicts = dictDataService.getDictDataListByDictType("rq_iot_project_measure_unit");
        // 施工状态 数据字典
        List<DictDataDO> rdStatusDicts = dictDataService.getDictDataListByDictType("rdStatus");
        //  施工状态 key字典键值     value字典标签
        Map<String, String> statusDictPair = new HashMap<>();
        // 停待状态 的字典数据集合
        Set<String> tdStatuses = new HashSet<>();
        //  施工工艺 key字典键值     value字典标签
        Map<String, String> techniqueDictPair = new HashMap<>();
        //  工作量单位 key字典键值     value字典标签
        Map<String, String> unitDictPair = new HashMap<>();
        if (CollUtil.isNotEmpty(rdTechniquesDicts)) {
            rdTechniquesDicts.forEach(tech -> {
                techniqueDictPair.put(tech.getValue(), tech.getLabel());
            });
        }
        if (CollUtil.isNotEmpty(measureUnitDicts)) {
            measureUnitDicts.forEach(tech -> {
                unitDictPair.put(tech.getValue(), tech.getLabel());
            });
        }
        if (CollUtil.isNotEmpty(rdStatusDicts)) {
            rdStatusDicts.forEach(status -> {
                statusDictPair.put(status.getValue(), status.getLabel());
                // 找到属于 停待状态 的字典数据
                if ("TD".equals(status.getRemark())) {
                    tdStatuses.add(status.getValue());
                }
            });
        }

        // 临时新建的任务 填报人
        String creatorIdStr = dailyReport.getCreator();
        if (StrUtil.isNotBlank(creatorIdStr)) {
            Long creatorId = Long.valueOf(creatorIdStr);
            Set<Long> submitterIds = new HashSet<>();
            submitterIds.add(creatorId);
            List<AdminUserRespDTO> users = adminUserApi.getUserList(submitterIds);
            String userNames = users.stream()
                    .map(AdminUserRespDTO::getNickname)
                    .collect(Collectors.joining(","));
            dailyReportVO.setSubmitterNames(userNames);
        }

        // 查询日报对应的任务信息
        if (ObjUtil.isNotEmpty(dailyReport.getTaskId())) {
            IotProjectTaskDO task = iotProjectTaskService.getIotProjectTask(dailyReport.getTaskId());
            dailyReportVO.setTaskName(StrUtil.join("-", task.getWellName(), task.getLocation()));
            dailyReportVO.setWellName(task.getWellName());
            dailyReportVO.setLocation(task.getLocation());
            // 任务施工工艺
            String techniqueValue = task.getTechnique();
            if (StrUtil.isNotBlank(techniqueValue)) {
                dailyReportVO.setTechniqueNames(techniqueDictPair.get(techniqueValue));
            }
            // 任务工作量
            String workloadDesign = task.getWorkloadDesign();
            // 任务工作量单位
            String workloadDesignUnit = task.getWorkloadUnit();
            if (StrUtil.isNotBlank(workloadDesignUnit)) {
                dailyReportVO.setWorkloadDesign(StrUtil.join(" ", workloadDesign, unitDictPair.get(workloadDesignUnit)));
            }

            Set<Long> deviceIds = task.getDeviceIds();
            Set<Long> responsiblePersonIds = task.getResponsiblePerson();
            Set<Long> submitterIds = task.getSubmitter();
            // 日报对应的任务中的设备列表
            Set<String> carDeviceCodes = new HashSet<>();
            // 中航北斗车辆id集合
            Set<String> zhbdCarIds = new HashSet<>();
            // key中航北斗carId   value设备编码
            Map<String, String> carIdDeviceCodePair = new HashMap<>();
            // key设备编码   value设备对象
            Map<String, IotDeviceRespVO> devicePair = new HashMap<>();
            // 生成 carId 与 IotDeviceDO 的对应关系Map
            Map<String, IotDeviceRespVO> carIdDevicePair = new HashMap<>();
            if (CollUtil.isNotEmpty(deviceIds)) {
                // 查询设备id集合对应的设备详情
                List<IotDeviceRespVO> devices = iotDeviceService.getDeviceList(deviceIds);
                if (CollUtil.isNotEmpty(devices)) {
                    String deviceNames = devices.stream()
                            .map(IotDeviceRespVO::getDeviceName) // 提取每个设备的deviceName
                            .collect(Collectors.joining(","));   // 用逗号拼接所有名称
                    dailyReportVO.setDeviceNames(deviceNames);

                    // 组装任务关联的 设备编码 进而查询 中航北斗carId集合
                    if (!hasFuels) {
                        devices.forEach(device -> {
                            carDeviceCodes.add(device.getDeviceCode());
                            if (ObjUtil.isNotEmpty(device.getCarId())) {
                                zhbdCarIds.add(String.valueOf(device.getCarId()));
                                carIdDeviceCodePair.put(String.valueOf(device.getCarId()), device.getDeviceCode());
                            }
                            devicePair.put(device.getDeviceCode(), device);
                        });
                        // 查询中航北斗表中的设备车辆
                        IotCarZhbdPageReqVO customDeviceReqVO = new IotCarZhbdPageReqVO();
                        // 设备表中存在的设备编码
                        customDeviceReqVO.setDeviceCodes(carDeviceCodes);
                        List<IotCarZhbdDO> deviceCars = iotCarZhbdMapper.selectList(customDeviceReqVO);
                        if (CollUtil.isNotEmpty(deviceCars)) {
                            deviceCars.forEach(car -> {
                                zhbdCarIds.add(car.getCarId());
                                carIdDeviceCodePair.put(car.getCarId(), car.getDeviceCode());
                            });
                        }
                        // 额外匹配的 RA 与 设备表对应的编码
                        customDeviceReqVO.setDeviceCodes(null);
                        customDeviceReqVO.setCustomDeviceCodes(carDeviceCodes);
                        List<IotCarZhbdDO> raCars = iotCarZhbdMapper.selectList(customDeviceReqVO);
                        if (CollUtil.isNotEmpty(raCars)) {
                            raCars.forEach(car -> {
                                zhbdCarIds.add(car.getCarId());
                                carIdDeviceCodePair.put(car.getCarId(), car.getUserName());
                            });
                        }
                        // 生成 carId 与 IotDeviceDO 的对应关系Map
                        carIdDevicePair = carIdDeviceCodePair.entrySet().stream()
                                .filter(entry -> devicePair.containsKey(entry.getValue()))
                                .collect(Collectors.toMap(
                                        Map.Entry::getKey,
                                        entry -> devicePair.get(entry.getValue())
                                ));
                    }
                }
                // 查询设备id集合关联的设备列表 施工队伍下的设备+瑞都所有设备
                IotDevicePageReqVO deviceReqVO = new IotDevicePageReqVO();
                deviceReqVO.setDeviceIds(new ArrayList<>(deviceIds));
                List<IotDeviceDO> selectedDevices = iotDeviceService.getDevicesByDepts(deviceReqVO);
                List<IotDeviceSimpleRespVO> simpleDevices = BeanUtils.toBean(selectedDevices, IotDeviceSimpleRespVO.class);
                dailyReportVO.setSelectedDevices(simpleDevices);
            }
            // 查询相同任务id的日报 查询开工日期 完工日期 施工周期
            IotRdDailyReportPageReqVO reportReqVO  = new IotRdDailyReportPageReqVO();
            reportReqVO.setTaskId(dailyReport.getTaskId());
            List<IotRdDailyReportDO> reports = iotRdDailyReportService.dailyReports(reportReqVO);
            if (CollUtil.isNotEmpty(reports)) {
                // 找出开工日期：最早创建时间
                Optional<LocalDateTime> startDateOpt = reports.stream()
                        .filter(report -> StrUtil.isNotBlank(report.getRdStatus()))
                        .map(IotRdDailyReportDO::getCreateTime)
                        .filter(Objects::nonNull)
                        .min(LocalDateTime::compareTo);
                // 找出完工日期：rdStatus='wg' 的日报创建时间（取最早的一个）
                Optional<LocalDateTime> endDateOpt = reports.stream()
                        .filter(report -> "wg".equals(report.getRdStatus()))
                        .map(IotRdDailyReportDO::getCreateTime)
                        .filter(Objects::nonNull)
                        .min(LocalDateTime::compareTo);
                startDateOpt.ifPresent(startDate ->
                        dailyReportVO.setCommencementDate(LocalDateTimeUtil.format(startDate, DatePattern.NORM_DATE_PATTERN))
                );
                endDateOpt.ifPresent(finishDate ->
                        dailyReportVO.setCompletionDate(LocalDateTimeUtil.format(finishDate, DatePattern.NORM_DATE_PATTERN))
                );
                // 计算施工周期（包含开工和完工日期）
                if (startDateOpt.isPresent() && endDateOpt.isPresent()) {
                    LocalDateTime startDate = startDateOpt.get();
                    LocalDateTime endDate = endDateOpt.get();

                    // 将LocalDateTime转换为LocalDate进行计算
                    LocalDate startLocalDate = startDate.toLocalDate();
                    LocalDate endLocalDate = endDate.toLocalDate();

                    // 计算天数（包含起始和结束日期）
                    long daysBetween = ChronoUnit.DAYS.between(startLocalDate, endLocalDate) + 1;
                    dailyReportVO.setConstructionPeriod(String.valueOf(daysBetween));
                }
                // 找到处于停待状态 的日报数据
                long tdStatusCount = reports.stream()
                        .filter(report -> StrUtil.isNotBlank(report.getRdStatus()) && tdStatuses.contains(report.getRdStatus()))
                        .count();
                dailyReportVO.setIdleTime(String.valueOf(tdStatusCount));
                // 当前日报关联任务的施工进度
                if (CollUtil.isNotEmpty(statusDictPair)) {
                    // 1. 过滤有效数据并排序（按时间升序）
                    List<IotRdDailyReportDO> validReports = reports.stream()
                            .filter(report -> StrUtil.isNotBlank(report.getRdStatus())
                                    && ObjUtil.isNotEmpty(report.getCreateTime())
                                    && statusDictPair.containsKey(report.getRdStatus()))
                            .sorted(Comparator.comparing(IotRdDailyReportDO::getCreateTime))
                            .collect(Collectors.toList());
                    Map<String, List<IotRdDailyReportDO>> rdStatusReportPair = new HashMap<>();
                    List<IotRdDailyReportDO> uniqueRdStatusReports = new ArrayList<>();
                    if (CollUtil.isNotEmpty(validReports)) {
                        validReports.forEach(report -> {
                            // 获取集合中的最后一个元素 如果最后一个元素的rdStatus 与当前日报 rdStatus 不同
                            // 则将 当前report 加入 集合 uniqueRdStatusReports
                            if (CollUtil.isEmpty(uniqueRdStatusReports)) {
                                uniqueRdStatusReports.add(report);
                            } else {
                                IotRdDailyReportDO lastElement = uniqueRdStatusReports.get(uniqueRdStatusReports.size() - 1);
                                if (ObjUtil.isNotEmpty(lastElement) && !lastElement.getRdStatus().equals(report.getRdStatus())) {
                                    uniqueRdStatusReports.add(report);
                                }
                            }
                        });
                    }
                    List<IotRdDailyReportTaskProgressVO> progresses = new ArrayList<>();
                    if (CollUtil.isNotEmpty(uniqueRdStatusReports)) {
                        uniqueRdStatusReports.forEach(report -> {
                            IotRdDailyReportTaskProgressVO progress = new IotRdDailyReportTaskProgressVO();
                            progress.setRdStatusLabel(statusDictPair.get(report.getRdStatus()));
                            progress.setCreateTime(LocalDateTimeUtil.format(report.getCreateTime(), DatePattern.NORM_DATE_PATTERN));
                            progresses.add(progress);
                        });
                        dailyReportVO.setTaskProgresses(progresses);
                    }
                }
            }

            if (CollUtil.isNotEmpty(responsiblePersonIds)) {
                List<AdminUserRespDTO> users = adminUserApi.getUserList(responsiblePersonIds);
                String userNames = users.stream()
                        .map(AdminUserRespDTO::getNickname) // 提取每个员工的nickName
                        .collect(Collectors.joining(","));   // 用逗号拼接所有名称
                dailyReportVO.setResponsiblePersonNames(userNames);
            }
            if (CollUtil.isNotEmpty(submitterIds)) {
                List<AdminUserRespDTO> users = adminUserApi.getUserList(submitterIds);
                String userNames = users.stream()
                        .map(AdminUserRespDTO::getNickname) // 提取每个员工的nickName
                        .collect(Collectors.joining(","));   // 用逗号拼接所有名称
                dailyReportVO.setSubmitterNames(userNames);
            }
            // 填报日报时 查询当前日报关联的任务中的车辆 查询中航北斗指定日报区间范围内的油耗数据 子表 主表
            List<IotDailyReportFuelDO> tobeAddedReportFuels = new ArrayList<>();
            if (!hasFuels) {
                // 取1个任务的车辆信息 就算是平台井 所有关联井的车辆信息是相同的
                // 获取中航北斗车辆的油耗信息
                LocalDateTime createTime = dailyReport.getCreateTime();
                // 日报开始日期
                LocalDateTime constructionStartDate = dailyReport.getConstructionStartDate();
                // 获得昨天的日期
                String yesterdayDateStr = StrUtil.EMPTY;
                LocalDateTime yesterday = createTime.minusDays(1);
                yesterdayDateStr = LocalDateTimeUtil.format(yesterday, DatePattern.NORM_DATE_PATTERN);
                // 需要根据日报的 construction_start_date 日期查询中航北斗油耗
                String constructionStartDateStr = LocalDateTimeUtil.format(constructionStartDate, DatePattern.NORM_DATE_PATTERN);

                // 当前日报总油耗
                BigDecimal totalOilUsage = BigDecimal.ZERO;
                if (CollUtil.isNotEmpty(zhbdCarIds)) {
                    if (StrUtil.isNotBlank(constructionStartDateStr)) {
                        try {
                            Map<Integer, IotDeviceCarFuelVO> carFuels = zhbdUtil.carFuels(StrUtil.join(",", zhbdCarIds),
                                    StrUtil.join(" ", constructionStartDateStr, "00:00:00"), StrUtil.join(" ", constructionStartDateStr, "23:59:59"));
                            System.out.println("请求参数：" + zhbdCarIds.size() + " -开始时间： "
                                    + StrUtil.join(" ", constructionStartDateStr, "00:00:00") + " -开始时间： "
                                    + StrUtil.join(" ", constructionStartDateStr, "23:59:59"));
                            if (CollUtil.isNotEmpty(carFuels)) {
                                DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
                                Map<String, IotDeviceRespVO> finalCarIdDevicePair = carIdDevicePair;
                                for (Map.Entry<Integer, IotDeviceCarFuelVO> carFuelEntry : carFuels.entrySet()) {
                                    Integer carId = carFuelEntry.getKey();
                                    IotDeviceCarFuelVO carFuel = carFuelEntry.getValue();
                                    // carId中航北斗车辆id   value车辆油耗
                                    IotDailyReportFuelDO reportFuel = new IotDailyReportFuelDO();
                                    reportFuel.setType("RD");
                                    reportFuel.setReportId(dailyReport.getId());
                                    reportFuel.setCarId(String.valueOf(carId));
                                    // 使用 carIdDeviceMap 获取对应的设备对象并设置deviceId
                                    IotDeviceRespVO device = finalCarIdDevicePair.get(String.valueOf(carId));
                                    reportFuel.setDeviceId(device.getId());
                                    reportFuel.setDeviceCode(device.getDeviceCode());
                                    reportFuel.setDeviceName(device.getDeviceName());
                                    BigDecimal tempOil = new BigDecimal(carFuel.getOil());
                                    totalOilUsage = totalOilUsage.add(tempOil);
                                    reportFuel.setZhbdFuel(tempOil);
                                    // 将字符串转换为LocalDateTime
                                    try {
                                        LocalDateTime queryDate = LocalDate.parse(constructionStartDateStr, formatter).atStartOfDay();;
                                        reportFuel.setQueryDate(queryDate);
                                    } catch (DateTimeParseException e) {
                                        log.error("瑞都日报-中航北斗油耗-日期格式解析失败: {}", e);
                                        // 根据业务需求设置默认值或抛出异常
                                        reportFuel.setQueryDate(null);
                                    }
                                    tobeAddedReportFuels.add(reportFuel);
                                }
                            }
                        } catch (Exception e) {
                            log.info("获取油耗数据失败！");
                        }
                    }
                }
            }
            dailyReportVO.setReportFuels(tobeAddedReportFuels);
        } else {
            // 临时新建的日报 没有关联项目 任务
            Set<Long> personIds = dailyReport.getResponsiblePerson();
            if (CollUtil.isNotEmpty(personIds)) {
                List<AdminUserRespDTO> users = adminUserApi.getUserList(personIds);
                String userNames = users.stream()
                        .map(AdminUserRespDTO::getNickname) // 提取每个员工的nickName
                        .collect(Collectors.joining(","));   // 用逗号拼接所有名称
                dailyReportVO.setResponsiblePersonNames(userNames);
            }
        }

        // 查询当前日报关联的附件信息
        IotAttachmentPageReqVO reqVO = new IotAttachmentPageReqVO();
        reqVO.setBizId(dailyReport.getId());
        reqVO.setCategory(AttachmentCategoryEnum.DAILY_REPORT.getCode());
        reqVO.setType(AttachmentTypeEnum.EXTERNAL_RENTAL.getCode());
        List<IotAttachmentDO> attachments = iotAttachmentService.getIotAttachments(reqVO);
        if (CollUtil.isNotEmpty(attachments)) {
            dailyReportVO.setAttachments(attachments);
        }
        // 查询日报对应的部门信息
        if (ObjUtil.isNotEmpty(dailyReport.getDeptId())) {
            DeptDO dept = deptService.getDept(dailyReport.getDeptId());
            dailyReportVO.setDeptName(dept.getName());
        }

        // 日报任务对应的平台井列表
        if (1 == dailyReport.getPlatformWell()) {
            // 查询未施工完成的平台井 关联井列表
            // 20260408 施工完成的平台井 也需要显示到 platforms 因为查询详情时需要显示
            IotProjectTaskPageReqVO pageReqVO = new IotProjectTaskPageReqVO();
            pageReqVO.setPlatformGroup(dailyReport.getTaskPlatform());
            pageReqVO.setJobFlag("Y");
            List<IotProjectTaskDO> tasks = iotProjectTaskService.projectTasks(pageReqVO);
            // 查询相同平台井组关联的 日报
            IotRdDailyReportPageReqVO reportReqVO  = new IotRdDailyReportPageReqVO();
            reportReqVO.setPlatformGroup(dailyReport.getPlatformGroup());
            List<IotRdDailyReportDO> reports = iotRdDailyReportService.dailyReports(reportReqVO);
            // 查询所有主井 关联井 附件
            Map<Long, List<IotAttachmentDO>> reportAttachmentsPair = new HashMap<>();
            // 查询所有主井 关联井 生产动态明细
            Map<Long, List<IotRdDailyReportDetailRespVO>> reportDetailsPair = new HashMap<>();

            if (CollUtil.isNotEmpty(reports)) {
                List<Long> reportIds = convertList(reports, IotRdDailyReportDO::getId);
                // 兼容主井 完工 关联井未完工 的情况 查询关联井的附件
                IotAttachmentPageReqVO attachmentReqVO = new IotAttachmentPageReqVO();
                attachmentReqVO.setBizIds(reportIds);
                attachmentReqVO.setCategory(AttachmentCategoryEnum.DAILY_REPORT.getCode());
                attachmentReqVO.setType(AttachmentTypeEnum.EXTERNAL_RENTAL.getCode());
                List<IotAttachmentDO> reportsAttachments = iotAttachmentMapper.attachments(attachmentReqVO);
                if (CollUtil.isNotEmpty(reportsAttachments)) {
                    reportsAttachments.forEach(attachment -> {
                        if (reportAttachmentsPair.containsKey(attachment.getBizId())) {
                            List<IotAttachmentDO> tempAttachments = reportAttachmentsPair.get(attachment.getBizId());
                            tempAttachments.add(attachment);
                            reportAttachmentsPair.put(attachment.getBizId(), tempAttachments);
                        } else {
                            List<IotAttachmentDO> tempAttachments = new ArrayList<>();
                            tempAttachments.add(attachment);
                            reportAttachmentsPair.put(attachment.getBizId(), tempAttachments);
                        }
                    });
                }

                // 查询多个日报对应的生产动态明细
                // 当前井及平台井的 taskId 依次查询有无 生产动态明细 哪个井有明细 用哪个任务井的生产动态明细
                IotRdDailyReportDetailPageReqVO relatedDetailReqVO = new IotRdDailyReportDetailPageReqVO();
                relatedDetailReqVO.setPageSize(PageParam.PAGE_SIZE_NONE);
                relatedDetailReqVO.setReportIds(reportIds);
                PageResult<IotRdDailyReportDetailDO> relatedReportDetailPage = iotRdDailyReportDetailMapper.selectPage(relatedDetailReqVO);
                List<IotRdDailyReportDetailDO> relatedReportDetails = relatedReportDetailPage.getList();
                if (CollUtil.isNotEmpty(relatedReportDetails)) {
                    relatedReportDetails.forEach(detail -> {
                        IotRdDailyReportDetailRespVO dailyReportDetail = BeanUtils.toBean(detail, IotRdDailyReportDetailRespVO.class);
                        if (reportDetailsPair.containsKey(detail.getReportId())) {
                            List<IotRdDailyReportDetailRespVO> tempDetails = reportDetailsPair.get(detail.getReportId());
                            tempDetails.add(dailyReportDetail);
                            reportDetailsPair.put(detail.getReportId(), tempDetails);
                        } else {
                            List<IotRdDailyReportDetailRespVO> tempDetails = new ArrayList<>();
                            tempDetails.add(dailyReportDetail);
                            reportDetailsPair.put(detail.getReportId(), tempDetails);
                        }
                    });
                }
            }
            // key任务id  value日报id
            Map<Long, Long> reportPair = new HashMap<>();
            // key任务id  value任务井对应日报当日油耗
            Map<Long, BigDecimal> reportFuelPair = new HashMap<>();
            // key任务id  value平台井日报已经设置的多种属性
            Map<Long, IotProjectTaskPlatformVO> platformPair = new HashMap<>();
            Set<Long> reportIds = new HashSet<>();
            if (CollUtil.isNotEmpty(reports)) {
                reports.forEach(report -> {
                    reportIds.add(report.getId());
                    // 保养平台井关联的多个日报使用
                    reportPair.put(report.getTaskId(), report.getId());
                    // 设置 平台关联井 已经设置的 属性 施工状态 施工工艺 工作量属性
                    // 查询 平台关联井详情使用
                    reportFuelPair.put(report.getTaskId(), report.getDailyFuel());
                    IotProjectTaskPlatformVO platformVO = new IotProjectTaskPlatformVO();
                    platformVO.setRdStatus(report.getRdStatus());
                    if (StrUtil.isNotBlank(report.getRdStatus()) && statusDictPair.containsKey(report.getRdStatus())) {
                        platformVO.setRdStatusLabel(statusDictPair.get(report.getRdStatus()));
                    }
                    if (CollUtil.isNotEmpty(report.getTechniqueIds())) {
                        String techniqueNames = report.getTechniqueIds().stream()
                                .map(lg -> ObjUtil.isNotEmpty(lg) ? lg.toString() : StrUtil.EMPTY) // 将Long转为String，匹配techniqueDictPair的key类型
                                .map(key -> techniqueDictPair.getOrDefault(key, key)) // 取label，无则用原key
                                .collect(Collectors.joining(",")); // 逗号拼接
                        platformVO.setTechniqueNames(techniqueNames);
                    } else {
                        platformVO.setTechniqueNames(""); // 空集合时设为空字符串（或null，根据业务需求）
                    }
                    platformVO.setTechniqueIds(report.getTechniqueIds());
                    platformVO.setExtProperty(report.getExtProperty());
                    platformVO.setProductionStatus(report.getProductionStatus());
                    // 当日施工简报
                    platformVO.setConstructionBrief(report.getConstructionBrief());
                    platformVO.setNextPlan(report.getNextPlan());
                    platformVO.setExternalRental(report.getExternalRental());
                    platformVO.setMalfunction(report.getMalfunction());
                    platformVO.setFaultDowntime(report.getFaultDowntime());
                    // 非生产时间
                    platformVO.setAccidentTime(report.getAccidentTime());
                    platformVO.setRepairTime(report.getRepairTime());
                    platformVO.setSelfStopTime(report.getSelfStopTime());
                    platformVO.setComplexityTime(report.getComplexityTime());
                    platformVO.setRelocationTime(report.getRelocationTime());
                    platformVO.setRectificationTime(report.getRectificationTime());
                    platformVO.setWaitingStopTime(report.getWaitingStopTime());
                    platformVO.setWinterBreakTime(report.getWinterBreakTime());
                    platformVO.setPartyaDesign(report.getPartyaDesign());
                    platformVO.setPartyaPrepare(report.getPartyaPrepare());
                    platformVO.setPartyaResource(report.getPartyaResource());
                    platformVO.setOtherNptTime(report.getOtherNptTime());
                    platformVO.setOtherNptReason(report.getOtherNptReason());
                    platformVO.setNptRate(report.getNptRate());

                    if (reportAttachmentsPair.containsKey(report.getId())) {
                        platformVO.setAttachments(reportAttachmentsPair.get(report.getId()));
                    }
                    if (reportDetailsPair.containsKey(report.getId())) {
                        platformVO.setReportDetails(reportDetailsPair.get(report.getId()));
                    }
                    platformPair.put(report.getTaskId(), platformVO);
                });
            }
            // 查询多个日报id 对应的 已经保存的油耗记录
            IotDailyReportFuelPageReqVO fuelReqVO = new IotDailyReportFuelPageReqVO();
            fuelReqVO.setType("RD");
            fuelReqVO.setReportIds(reportIds);
            List<IotDailyReportFuelDO> relatedReportFuels = iotDailyReportFuelService.getIotDailyReportFuels(fuelReqVO);
            Map<Long, List<IotDailyReportFuelDO>> reportFuelsPair = new HashMap<>();
            if (CollUtil.isNotEmpty(relatedReportFuels)) {
                relatedReportFuels.forEach(fuel -> {
                    if (reportFuelsPair.containsKey(fuel.getReportId())) {
                        List<IotDailyReportFuelDO> tempFuels = reportFuelsPair.get(fuel.getReportId());
                        tempFuels.add(fuel);
                        reportFuelsPair.put(fuel.getReportId(), tempFuels);
                    } else {
                        List<IotDailyReportFuelDO> tempFuels = new ArrayList<>();
                        tempFuels.add(fuel);
                        reportFuelsPair.put(fuel.getReportId(), tempFuels);
                    }
                });
            }

            // 如果主井已经 完工 则显示 首个关联井 的 生产动态 下步计划 ...
            List<IotProjectTaskPlatformVO> platforms = new ArrayList<>();
            if (CollUtil.isNotEmpty(tasks)) {
                tasks.forEach(task -> {
                    // 只有生成了主井关联井日报才能在查询平台井详情直接列表中出现
                    if (reportPair.containsKey(task.getId())) {
                        IotProjectTaskPlatformVO platform = new IotProjectTaskPlatformVO();
                        platform.setId(task.getId());
                        platform.setWellName(task.getWellName());
                        platform.setWorkloadDesign(task.getWorkloadDesign());
                        platform.setReportId(reportPair.get(task.getId()));
                        platform.setDailyFuel(reportFuelPair.get(task.getId()));
                        if (platformPair.containsKey(task.getId())) {
                            IotProjectTaskPlatformVO tempPlatform = platformPair.get(task.getId());
                            platform.setRdStatus(tempPlatform.getRdStatus());
                            platform.setRdStatusLabel(tempPlatform.getRdStatusLabel());
                            platform.setTechniqueIds(tempPlatform.getTechniqueIds());
                            platform.setTechniqueNames(tempPlatform.getTechniqueNames());
                            platform.setExtProperty(tempPlatform.getExtProperty());
                            platform.setProductionStatus(tempPlatform.getProductionStatus());
                            // 当日施工简报
                            platform.setConstructionBrief(tempPlatform.getConstructionBrief());
                            platform.setNextPlan(tempPlatform.getNextPlan());
                            platform.setExternalRental(tempPlatform.getExternalRental());
                            platform.setMalfunction(tempPlatform.getMalfunction());
                            platform.setFaultDowntime(tempPlatform.getFaultDowntime());
                            platform.setAttachments(tempPlatform.getAttachments());
                            platform.setReportDetails(tempPlatform.getReportDetails());
                            // 非生产时间
                            platform.setAccidentTime(tempPlatform.getAccidentTime());
                            platform.setRepairTime(tempPlatform.getRepairTime());
                            platform.setSelfStopTime(tempPlatform.getSelfStopTime());
                            platform.setComplexityTime(tempPlatform.getComplexityTime());
                            platform.setRelocationTime(tempPlatform.getRelocationTime());
                            platform.setRectificationTime(tempPlatform.getRectificationTime());
                            platform.setWaitingStopTime(tempPlatform.getWaitingStopTime());
                            platform.setWinterBreakTime(tempPlatform.getWinterBreakTime());
                            platform.setPartyaDesign(tempPlatform.getPartyaDesign());
                            platform.setPartyaPrepare(tempPlatform.getPartyaPrepare());
                            platform.setPartyaResource(tempPlatform.getPartyaResource());
                            platform.setOtherNptTime(tempPlatform.getOtherNptTime());
                            platform.setOtherNptReason(tempPlatform.getOtherNptReason());
                            platform.setNptRate(tempPlatform.getNptRate());
                        }
                        platforms.add(platform);
                    }
                });
                dailyReportVO.setPlatforms(platforms);
            }

            // 如果当前井id不存在集合 platforms 中 说明 主井已完工 关联井 未完工
            if (CollUtil.isEmpty(platforms)) {
                List<IotProjectTaskPlatformVO> finishedPlatforms = new ArrayList<>();
                // key任务井id   value任务井名称
                Map<Long, String> wellNamePair = new HashMap<>();
                // key任务id  value任务井对应日报当日油耗
                Map<Long, BigDecimal> finishedReportFuelPair = new HashMap<>();
                // 查询当前任务关联的平台井任务列表
                IotProjectTaskPageReqVO currentPlatformTaskReqVO = new IotProjectTaskPageReqVO();
                currentPlatformTaskReqVO.setPlatformGroup(dailyReport.getTaskPlatform());
                List<IotProjectTaskDO> currentPlatformTasks = iotProjectTaskService.projectTasks(currentPlatformTaskReqVO);
                if (CollUtil.isNotEmpty(currentPlatformTasks)) {
                    currentPlatformTasks.forEach(task -> {
                        wellNamePair.put(task.getId(), task.getWellName());
                    });
                }
                // 已经施工完成的主井/关联井 查询主井关联的日报列表 组装 finishedPlatforms
                IotRdDailyReportPageReqVO currentReportReqVO = new IotRdDailyReportPageReqVO();
                currentReportReqVO.setPlatformGroup(dailyReport.getPlatformGroup());
                List<IotRdDailyReportDO> currentRelatedReports = iotRdDailyReportService.dailyReports(currentReportReqVO);
                // 按照日报创建时间倒序排列
                if (CollUtil.isNotEmpty(currentRelatedReports)) {
                    currentRelatedReports = currentRelatedReports.stream()
                            .sorted(Comparator.comparing(IotRdDailyReportDO::getCreateTime).reversed())
                            .collect(Collectors.toList());
                }
                if (CollUtil.isNotEmpty(currentRelatedReports)) {
                    currentRelatedReports.forEach(report -> {
                        if (reportFuelsPair.containsKey(report.getId())) {
                            List<IotDailyReportFuelDO> finishedReportFuels = reportFuelsPair.get(report.getId());
                            dailyReportVO.setReportedFuels(finishedReportFuels);
                        }
                        if (StrUtil.isNotBlank(report.getRdStatus())) {
                            IotProjectTaskPlatformVO platform = new IotProjectTaskPlatformVO();
                            platform.setId(report.getTaskId());
                            platform.setDailyFuel(report.getDailyFuel());
                            if (wellNamePair.containsKey(report.getTaskId())) {
                                platform.setWellName(wellNamePair.get(report.getTaskId()));
                            }
                            platform.setReportId(report.getId());
                            platform.setRdStatus(report.getRdStatus());
                            if (statusDictPair.containsKey(report.getRdStatus())) {
                                platform.setRdStatusLabel(statusDictPair.get(report.getRdStatus()));
                            }
                            platform.setTechniqueIds(report.getTechniqueIds());
                            if (CollUtil.isNotEmpty(report.getTechniqueIds())) {
                                String techniqueNames = report.getTechniqueIds().stream()
                                        // 将Long转为String，匹配techniqueDictPair的key类型
                                        .map(lg -> ObjUtil.isNotEmpty(lg) ? lg.toString() : StrUtil.EMPTY)
                                        // 取label，无则用原key
                                        .map(key -> techniqueDictPair.getOrDefault(key, key))
                                        .collect(Collectors.joining(",")); // 逗号拼接
                                platform.setTechniqueNames(techniqueNames);
                            } else {
                                platform.setTechniqueNames(""); // 空集合时设为空字符串（或null，根据业务需求）
                            }
                            platform.setExtProperty(report.getExtProperty());
                            finishedPlatforms.add(platform);
                        }
                    });
                }
                dailyReportVO.setFinishedPlatforms(finishedPlatforms);
            } else {
                AtomicBoolean mainExist = new AtomicBoolean(false);
                // 如果当前井id不存在集合 platforms 中 说明 主井已完工 关联井 未完工
                platforms.forEach(platform -> {
                    if (dailyReportVO.getId().equals(platform.getReportId())) {
                        mainExist.set(true);
                    }
                });
                if (!mainExist.get()) {
                    // 主井不存在 需要显示 关联井的 主体信息 生产动态 计划 ...
                    platforms.forEach(platform -> {
                        dailyReportVO.setProductionStatus(platform.getProductionStatus());
                        // 当日施工简报
                        dailyReportVO.setConstructionBrief(platform.getConstructionBrief());
                        dailyReportVO.setNextPlan(platform.getNextPlan());
                        dailyReportVO.setExternalRental(platform.getExternalRental());
                        dailyReportVO.setMalfunction(platform.getMalfunction());
                        dailyReportVO.setFaultDowntime(platform.getFaultDowntime());
                        dailyReportVO.setAttachments(platform.getAttachments());
                        dailyReportVO.setReportDetails(platform.getReportDetails());
                    });
                }
            }
        }
        return dailyReportVO;
    }

    @GetMapping("/page")
    @Operation(summary = "获得瑞都日报分页")
    @PreAuthorize("@ss.hasPermission('pms:iot-rd-daily-report:query')")
    public CommonResult<PageResult<IotRdDailyReportRespVO>> getIotRdDailyReportPage(@Valid IotRdDailyReportPageReqVO 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<IotRdDailyReportDO> pageResult = iotRdDailyReportService.getIotRdDailyReportPage(pageReqVO);
        // 设置日报的关联信息 部门(施工队伍) 项目 任务 带班干部 日报填报人
        return success(new PageResult<>(buildDailyReportList(pageResult.getList()), pageResult.getTotal()));
    }

    @GetMapping("/reportSummary")
    @Operation(summary = "移动端 瑞都日报汇总 分别按照 年 月 日 汇总")
    @PreAuthorize("@ss.hasPermission('pms:iot-rd-daily-report:query')")
    public CommonResult<List<IotRdDailyReportSummaryYearRespVO>> reportSummary(@Valid IotRdDailyReportPageReqVO 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);
            }
        }
        List<IotRdDailyReportSummaryYearRespVO> reportSummaries = iotRdDailyReportService.reportSummary(pageReqVO);
        // 设置日报的关联信息 部门(施工队伍) 项目 任务 带班干部 日报填报人
        return success(reportSummaries);
    }

    @GetMapping("/statistics")
    @Operation(summary = "瑞都日报 统计")
    @PreAuthorize("@ss.hasPermission('pms:iot-rd-daily-report:query')")
    public CommonResult<List<IotRdDailyReportStatisticsRespVO>> statistics(@Valid IotRdDailyReportPageReqVO 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);
            }
        }
        List<IotRdDailyReportStatisticsRespVO> result = iotRdDailyReportService.statistics(pageReqVO);
        return success(result);
    }

    @GetMapping("/totalWorkload")
    @Operation(summary = "瑞都日报 汇总 统计 卡片")
    @PreAuthorize("@ss.hasPermission('pms:iot-rd-daily-report:query')")
    public CommonResult<Map<String, BigDecimal>> totalWorkload(@Valid IotRdDailyReportPageReqVO pageReqVO) {
        Map<String, BigDecimal> resultMap = new HashMap<>();
        // 根据查询参数筛选出 符合条件 的记录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<IotRdDailyReportStatisticsRespVO> statistics = iotRdDailyReportService.totalWorkload(pageReqVO);
        if (CollUtil.isNotEmpty(statistics)) {
            final BigDecimal[] taici = {BigDecimal.ZERO};
            statistics.forEach(stat -> {
                if ("utilizationRate".equals(stat.getDeptName())) {
                    resultMap.put("utilizationRate", stat.getUtilizationRate());
                }
                // 循环遍历 获取 每个 维度 工作量的值
                if ("cumulativeBridgePlug".equals(stat.getDeptName())) {
                    resultMap.put("cumulativeBridgePlug", stat.getCumulativeBridgePlug());
                }
                if ("cumulativeRunCount".equals(stat.getDeptName())) {
                    resultMap.put("cumulativeRunCount", stat.getCumulativeRunCount());
                }
                if ("cumulativeWorkingWell".equals(stat.getDeptName())) {
                    resultMap.put("cumulativeWorkingWell", stat.getCumulativeWorkingWell());
                }
                if ("cumulativeHourCount".equals(stat.getDeptName())) {
                    resultMap.put("cumulativeHourCount", stat.getCumulativeHourCount());
                }
                if ("cumulativeWaterVolume".equals(stat.getDeptName())) {
                    resultMap.put("cumulativeWaterVolume", stat.getCumulativeWaterVolume());
                }
                if ("cumulativeWorkingLayers".equals(stat.getDeptName())) {
                    resultMap.put("cumulativeWorkingLayers", stat.getCumulativeWorkingLayers());
                }
                if ("cumulativeMixSand".equals(stat.getDeptName())) {
                    taici[0] = taici[0].add(stat.getCumulativeMixSand());
                }
                if ("cumulativePumpTrips".equals(stat.getDeptName())) {
                    taici[0] = taici[0].add(stat.getCumulativePumpTrips());
                }
                resultMap.put("taici", taici[0]);
                if ("cumulativeFuels".equals(stat.getDeptName())) {
                    resultMap.put("cumulativeFuels", stat.getTotalDailyFuel());
                }
            });
            // 没有统计到的工作量设置为0
            if (!resultMap.containsKey("utilizationRate")) {
                resultMap.put("utilizationRate", BigDecimal.ZERO);
            }
            if (!resultMap.containsKey("cumulativeBridgePlug")) {
                resultMap.put("cumulativeBridgePlug", BigDecimal.ZERO);
            }
            if (!resultMap.containsKey("cumulativeRunCount")) {
                resultMap.put("cumulativeRunCount", BigDecimal.ZERO);
            }
            if (!resultMap.containsKey("cumulativeWorkingWell")) {
                resultMap.put("cumulativeWorkingWell", BigDecimal.ZERO);
            }
            if (!resultMap.containsKey("cumulativeHourCount")) {
                resultMap.put("cumulativeHourCount", BigDecimal.ZERO);
            }
            if (!resultMap.containsKey("cumulativeWaterVolume")) {
                resultMap.put("cumulativeWaterVolume", BigDecimal.ZERO);
            }
            if (!resultMap.containsKey("cumulativeWorkingLayers")) {
                resultMap.put("cumulativeWorkingLayers", BigDecimal.ZERO);
            }
            if (!resultMap.containsKey("cumulativeFuels")) {
                resultMap.put("cumulativeFuels", BigDecimal.ZERO);
            }
        }
        return success(resultMap);
    }

    @GetMapping("/summaryStatistics")
    @Operation(summary = "瑞都日报 汇总 统计")
    @PreAuthorize("@ss.hasPermission('pms:iot-rd-daily-report:query')")
    public CommonResult<Map<String, Object>> summaryStatistics(@Valid IotRdDailyReportPageReqVO pageReqVO) {
        List<IotRdDailyReportStatisticsRespVO> result = new ArrayList<>();
        Map<String, Object> resultMap = new HashMap<>();
        // 根据查询参数筛选出 符合条件 的记录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<IotRdDailyReportStatisticsRespVO> statistics = iotRdDailyReportService.summaryStatistics(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-rd-daily-report:query')")
    public CommonResult<Map<String, Object>> nptStatistics(@Valid IotRdDailyReportPageReqVO pageReqVO) {
        List<IotRdDailyReportNptStatisticsRespVO> result = new ArrayList<>();
        Map<String, Object> resultMap = new HashMap<>();
        // 根据查询参数筛选出 符合条件 的记录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<IotRdDailyReportNptStatisticsRespVO> statistics = iotRdDailyReportService.nptStatistics(pageReqVO);
        result.addAll(statistics);
        resultMap.put("list", result);
        resultMap.put("total", result.size());
        return success(resultMap);
    }

    @GetMapping("/abnormalAlert")
    @Operation(summary = "瑞都日报 看板 异常警示")
    @PreAuthorize("@ss.hasPermission('pms:iot-rd-daily-report:query')")
    public CommonResult<List<IotRdDailyReportAbnormalRespVO>> abnormalAlert(@Valid IotRdDailyReportPageReqVO pageReqVO) {
        Map<String, Object> resultMap = new HashMap<>();
        // 根据查询参数筛选出 符合条件 的记录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<IotRdDailyReportAbnormalRespVO> result = iotRdDailyReportService.abnormalAlert(pageReqVO);
        return success(result);
    }

    @GetMapping("/constructionBriefing")
    @Operation(summary = "瑞都日报 看板 施工简报")
    @PreAuthorize("@ss.hasPermission('pms:iot-rd-daily-report:query')")
    public CommonResult<Map<String, Object>> constructionBriefing(@Valid IotRdDailyReportPageReqVO pageReqVO) {
        // 查询昨日 和 前天的日报数据
        List<IotRdDailyReportBriefRespVO> result = new ArrayList<>();
        Map<String, Object> resultMap = new HashMap<>();
        List<IotRdDailyReportBriefRespVO> statistics = iotRdDailyReportService.constructionBriefing(pageReqVO);
        result.addAll(statistics);
        resultMap.put("list", result);
        resultMap.put("total", result.size());
        return success(resultMap);
    }

    @GetMapping("/teamReports")
    @Operation(summary = "根据井号查询瑞都日报列表 按照队伍分组统计工作量")
    @PreAuthorize("@ss.hasPermission('pms:iot-rd-daily-report:query')")
    public CommonResult<PageResult<IotRdDailyReportRespVO>> teamReports(@Valid IotRdDailyReportPageReqVO 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<IotRdDailyReportDO> pageResult = iotRdDailyReportService.teamReports(pageReqVO);
        return success(new PageResult<>(buildSubtotalRdDailyReports(pageResult.getList(), pageReqVO), pageResult.getTotal()));
    }

    @GetMapping("/wellReports")
    @Operation(summary = "以队伍为维度 按照任务井分组查询瑞都日报列表统计工作量")
    @PreAuthorize("@ss.hasPermission('pms:iot-rd-daily-report:query')")
    public CommonResult<PageResult<IotRdDailyReportRespVO>> wellReports(@Valid IotRdDailyReportPageReqVO 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<IotRdDailyReportDO> pageResult = iotRdDailyReportService.wellReports(pageReqVO);
        return success(new PageResult<>(buildWellRdDailyReports(pageResult.getList(), pageReqVO), pageResult.getTotal()));
    }

    /**
     * 设置日报的关联信息 部门(施工队伍) 项目 任务 带班干部 日报填报人
     * @param reports
     * @return
     */
    private List<IotRdDailyReportRespVO> buildSubtotalRdDailyReports(List<IotRdDailyReportDO> reports, IotRdDailyReportPageReqVO pageReqVO) {
        if (CollUtil.isEmpty(reports)) {
            return Collections.emptyList();
        }
        // key项目id   value项目合同号
        Map<Long, String> projectPair = new HashMap<>();
        //  key任务id     value任务井号-施工区域
        Map<Long, String> taskPair = new HashMap<>();
        //  key任务id     value任务关联的带班干部名称
        Map<Long, String> taskResponsiblePair = new HashMap<>();
        //  key任务id     value任务关联的填报人名称
        Map<Long, String> taskSubmitterPair = new HashMap<>();
        //  key任务id     value工作量数据集合
        Map<Long, List<IotTaskAttrModelProperty>> taskWorkloadPair = new HashMap<>();
        //  key任务id     value任务关联的施工队伍名称 多个逗号分隔
        Map<Long, String> taskTeamsPair = new HashMap<>();
        Set<Long> userIds = new HashSet<>();
        // 当前页所有日报关联任务的 施工队伍id 集合
        Set<Long> currentPageDeptIds = new HashSet<>();
        // key主井任务platformGroup/taskPlatform     value关联井号名称
        Map<String, String> relatedPlatformPair = new HashMap<>();
        // key主井任务id     value关联井任务施工状态
        Map<String, String> relatedWellStatusPair = new HashMap<>();
        // key关联井任务id     value关联井号
        Map<Long, String> relatedPlatformsPair = new HashMap<>();

        // key 部门id-队伍id   value 任务关联的日报油耗总和
        Map<String, BigDecimal> groupFuelPair = new HashMap<>();
        // key 部门id-队伍id      value队伍工作量数据 桥塞(个数)
        Map<String, BigDecimal> groupBridgePlugPair = new HashMap<>();
        // key 部门id-队伍id      value队伍工作量数据 趟数
        Map<String, BigDecimal> groupRunCountPair = new HashMap<>();
        // key 部门id-队伍id      value队伍工作量数据 井数
        Map<String, BigDecimal> groupCumulativeWorkingWellPair = new HashMap<>();
        // key 部门id-队伍id      value队伍工作量数据 小时H
        Map<String, BigDecimal> groupHourCountPair = new HashMap<>();
        // key 部门id-队伍id      value队伍工作量数据 水方量(方)
        Map<String, BigDecimal> groupWaterVolumePair = new HashMap<>();
        // key 部门id-队伍id      value队伍工作量数据 台次
        Map<String, BigDecimal> groupPumpTripsPair = new HashMap<>();
        // key 部门id-队伍id      value队伍工作量数据 段数
        Map<String, BigDecimal> groupCumulativeWorkingLayersPair = new HashMap<>();
        // key 部门id-队伍id      value队伍工作量数据 台次 当日泵车台次 当日仪表/混砂
        Map<String, BigDecimal> groupMixSandPair = new HashMap<>();

        // key小组最后1条记录id   value 桥塞(个数)
        Map<Long, BigDecimal> groupIdBridgePlugPair = new HashMap<>();
        // key小组最后1条记录id      value趟数
        Map<Long, BigDecimal> groupIdRunCountPair = new HashMap<>();
        // key小组最后1条记录id      value井数
        Map<Long, BigDecimal> groupIdCumulativeWorkingWellPair = new HashMap<>();
        // key小组最后1条记录id      value小时H
        Map<Long, BigDecimal> groupIdHourCountPair = new HashMap<>();
        // key小组最后1条记录id      value油耗
        Map<Long, BigDecimal> groupIdFuelPair = new HashMap<>();
        // key小组最后1条记录id      value水方量(方)
        Map<Long, BigDecimal> groupIdWaterVolumePair = new HashMap<>();
        // key小组最后1条记录id      value泵车台次
        Map<Long, BigDecimal> groupIdPumpTripsPair = new HashMap<>();
        // key小组最后1条记录id      value段数  累计施工-层
        Map<Long, BigDecimal> groupIdCumulativeWorkingLayersPair = new HashMap<>();
        // key小组最后1条记录id      value台次 当日仪表/混砂
        Map<Long, BigDecimal> groupIdMixSandPair = new HashMap<>();
        // 已经完工的任务id集合
        Set<Long> finishedTaskIds = new HashSet<>();
        // key日报id   value生产动态明细
        Map<Long, List<IotRdDailyReportDetailRespVO>> reportDetailsPair = new HashMap<>();

        DataPermissionUtils.executeIgnore(() -> {
            IotProjectTaskPageReqVO taskReqVO = new IotProjectTaskPageReqVO();
            taskReqVO.setTaskIds(convertList(reports, IotRdDailyReportDO::getTaskId));
            List<IotProjectTaskDO> tasks = iotProjectTaskService.projectTasks(taskReqVO);
            if (CollUtil.isNotEmpty(tasks)) {
                tasks.forEach(task -> {
                    // 筛选出 完工 的任务集合 任务完工 施工井数 +1
                    if ("wg".equals(task.getRdStatus())) {
                        finishedTaskIds.add(task.getId());
                    }
                });
            }
        });

        // 查询 当前分页 所有部门 任务井 日报数据 小计工作量
        IotRdDailyReportPageReqVO currentTaskReqVO = new IotRdDailyReportPageReqVO();
        currentTaskReqVO.setTaskIds(convertSet(reports, IotRdDailyReportDO::getTaskId));
        currentTaskReqVO.setDeptIds(convertSet(reports, IotRdDailyReportDO::getDeptId));
        currentTaskReqVO.setCreateTime(pageReqVO.getCreateTime());
        currentTaskReqVO.setProjectIds(pageReqVO.getProjectIds());
        currentTaskReqVO.setTaskIds(pageReqVO.getTaskIds());
        List<IotRdDailyReportDO> deptTaskDailyReports = iotRdDailyReportMapper.dailyReports(currentTaskReqVO);
        // 以 deptId-taskId 为唯一键 小计日报工作量
        if (CollUtil.isNotEmpty(deptTaskDailyReports)) {
            deptTaskDailyReports.forEach(report -> {
                String uniqueKey = StrUtil.join("-", report.getDeptId(), report.getTaskId());

                BigDecimal dailyFuel = report.getDailyFuel();
                dailyFuel = ObjUtil.isEmpty(dailyFuel) ? BigDecimal.ZERO : dailyFuel;
                if (groupFuelPair.containsKey(uniqueKey)) {
                    BigDecimal existTotalFuel = groupFuelPair.get(uniqueKey);
                    BigDecimal tempTotalFuel = existTotalFuel.add(dailyFuel);
                    groupFuelPair.put(uniqueKey, tempTotalFuel);
                } else {
                    groupFuelPair.put(uniqueKey, dailyFuel);
                }

                // 设置每个任务的工作量数据  单位相同的工作量值作合并处理
                List<IotTaskAttrModelProperty> taskAttrs = report.getExtProperty();
                // 暂存不同单位的工作量属性值
                // 桥塞(个数)
                BigDecimal tempTotalBridgePlug = BigDecimal.ZERO;
                // 趟数
                BigDecimal tempTotalRunCount = BigDecimal.ZERO;
                // 井数
                BigDecimal tempTotalCumulativeWorkingWell = BigDecimal.ZERO;
                // 小时H
                BigDecimal tempTotalHourCount = BigDecimal.ZERO;
                // 水方量(方)
                BigDecimal tempTotalWaterVolume = BigDecimal.ZERO;
                // 台次
                BigDecimal tempTotalPumpTrips = BigDecimal.ZERO;
                // 段数  累计施工-层
                BigDecimal tempTotalCumulativeWorkingLayers = BigDecimal.ZERO;
                // 台次 当日泵车台次 当日仪表/混砂
                BigDecimal tempTotalMixSand = BigDecimal.ZERO;
                if (CollUtil.isNotEmpty(taskAttrs)) {
                    for (IotTaskAttrModelProperty attr : taskAttrs) {
                        // 工作量单位
                        String unit = attr.getUnit();
                        // 工作量属性的实际值
                        String actualValueStr = attr.getActualValue();
                        // 处理实际值：避免null或非数字字符串导致的异常
                        BigDecimal actualValue = BigDecimal.ZERO;
                        if (StrUtil.isNotBlank(actualValueStr)) {
                            try {
                                actualValue = new BigDecimal(actualValueStr);
                            } catch (NumberFormatException e) {
                                // 若字符串格式错误，默认按0处理
                                actualValue = BigDecimal.ZERO;
                            }
                        }
                        if ("个数".equals(unit)) {
                            // 钻可溶桥塞  钻复合桥塞
                            tempTotalBridgePlug = tempTotalBridgePlug.add(actualValue);
                            if (groupBridgePlugPair.containsKey(uniqueKey)) {
                                BigDecimal tempBridgePlug = groupBridgePlugPair.get(uniqueKey);
                                groupBridgePlugPair.put(uniqueKey, tempTotalBridgePlug.add(tempBridgePlug));
                            } else {
                                groupBridgePlugPair.put(uniqueKey, tempTotalBridgePlug);
                            }
                        }
                        if ("趟数".equals(unit)) {
                            tempTotalRunCount = tempTotalRunCount.add(actualValue);
                            if (groupRunCountPair.containsKey(uniqueKey)) {
                                BigDecimal tempRunCount = groupRunCountPair.get(uniqueKey);
                                groupRunCountPair.put(uniqueKey, tempTotalRunCount.add(tempRunCount));
                            } else {
                                groupRunCountPair.put(uniqueKey, tempTotalRunCount);
                            }
                        }
                        if ("小时".equals(unit)) {
                            tempTotalHourCount = tempTotalHourCount.add(actualValue);
                            if (groupHourCountPair.containsKey(uniqueKey)) {
                                BigDecimal tempHourCount = groupHourCountPair.get(uniqueKey);
                                groupHourCountPair.put(uniqueKey, tempTotalHourCount.add(tempHourCount));
                            } else {
                                groupHourCountPair.put(uniqueKey, tempTotalHourCount);
                            }
                        }
                        if ("天数".equals(unit)) {
                            // 将 actualValue 换算成 H
                            BigDecimal hours = actualValue.multiply(new BigDecimal("24"));
                            tempTotalHourCount = tempTotalHourCount.add(hours);
                            if (groupHourCountPair.containsKey(uniqueKey)) {
                                BigDecimal tempHourCount = groupHourCountPair.get(uniqueKey);
                                groupHourCountPair.put(uniqueKey, tempTotalHourCount.add(tempHourCount));
                            } else {
                                groupHourCountPair.put(uniqueKey, tempTotalHourCount);
                            }
                        }
                        if ("方".equals(unit)) {
                            tempTotalWaterVolume = tempTotalWaterVolume.add(actualValue);
                            if (groupWaterVolumePair.containsKey(uniqueKey)) {
                                BigDecimal tempWaterVolume = groupWaterVolumePair.get(uniqueKey);
                                groupWaterVolumePair.put(uniqueKey, tempTotalWaterVolume.add(tempWaterVolume));
                            } else {
                                groupWaterVolumePair.put(uniqueKey, tempTotalWaterVolume);
                            }
                        }
                        /* if ("井数".equals(unit)) {
                            tempTotalCumulativeWorkingWell = tempTotalCumulativeWorkingWell.add(actualValue);
                            if (groupCumulativeWorkingWellPair.containsKey(uniqueKey)) {
                                BigDecimal tempWorkingWell = groupCumulativeWorkingWellPair.get(uniqueKey);
                                groupCumulativeWorkingWellPair.put(uniqueKey, tempTotalCumulativeWorkingWell.add(tempWorkingWell));
                            } else {
                                groupCumulativeWorkingWellPair.put(uniqueKey, tempTotalCumulativeWorkingWell);
                            }
                        } */
                        // 施工完成的井累计计数 1
                        if (finishedTaskIds.contains(report.getTaskId())) {
                            groupCumulativeWorkingWellPair.put(uniqueKey, new BigDecimal("1"));
                        } else {
                            groupCumulativeWorkingWellPair.put(uniqueKey, BigDecimal.ZERO);
                        }
                        if ("段数".equals(unit)) {
                            // 累计施工层
                            tempTotalCumulativeWorkingLayers = tempTotalCumulativeWorkingLayers.add(actualValue);
                            if (groupCumulativeWorkingLayersPair.containsKey(uniqueKey)) {
                                BigDecimal tempWorkingLayer = groupCumulativeWorkingLayersPair.get(uniqueKey);
                                groupCumulativeWorkingLayersPair.put(uniqueKey, tempTotalCumulativeWorkingLayers.add(tempWorkingLayer));
                            } else {
                                groupCumulativeWorkingLayersPair.put(uniqueKey, tempTotalCumulativeWorkingLayers);
                            }
                        }
                        if ("台次".equals(unit) && "当日泵车台次".equals(attr.getName())) {
                            tempTotalPumpTrips = tempTotalPumpTrips.add(actualValue);
                            if (groupPumpTripsPair.containsKey(uniqueKey)) {
                                BigDecimal tempPumpTrips = groupPumpTripsPair.get(uniqueKey);
                                groupPumpTripsPair.put(uniqueKey, tempTotalPumpTrips.add(tempPumpTrips));
                            } else {
                                groupPumpTripsPair.put(uniqueKey, tempTotalPumpTrips);
                            }
                        }
                        if ("台次".equals(unit) && ("当日仪表/混砂".equals(attr.getName())
                                || "当日混砂".equals(attr.getName()) || "当日仪表".equals(attr.getName()))) {
                            tempTotalMixSand = tempTotalMixSand.add(actualValue);
                            if (groupMixSandPair.containsKey(uniqueKey)) {
                                BigDecimal tempMixSand = groupMixSandPair.get(uniqueKey);
                                groupMixSandPair.put(uniqueKey, actualValue.add(tempMixSand));
                            } else {
                                groupMixSandPair.put(uniqueKey, tempTotalMixSand);
                            }
                        }
                    }
                }
            });
        }

        TenantUtils.executeIgnore(() -> {
            currentTaskReqVO.setDeptId(pageReqVO.getDeptId());
            // 查询 deptId-taskId 分组内最后1条记录id 设置展开列标识
            List<IotRdDailyReportDO> currentGroupIds = iotRdDailyReportService.rdWellNameDailyReportsGroupIds(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 (groupBridgePlugPair.containsKey(uniqueKey)) {
                        groupIdBridgePlugPair.put(groupId, groupBridgePlugPair.get(uniqueKey));
                    }
                    if (groupRunCountPair.containsKey(uniqueKey)) {
                        groupIdRunCountPair.put(groupId, groupRunCountPair.get(uniqueKey));
                    }
                    if (groupCumulativeWorkingWellPair.containsKey(uniqueKey)) {
                        groupIdCumulativeWorkingWellPair.put(groupId, groupCumulativeWorkingWellPair.get(uniqueKey));
                    }
                    if (groupHourCountPair.containsKey(uniqueKey)) {
                        groupIdHourCountPair.put(groupId, groupHourCountPair.get(uniqueKey));
                    }
                    if (groupFuelPair.containsKey(uniqueKey)) {
                        groupIdFuelPair.put(groupId, groupFuelPair.get(uniqueKey));
                    }
                    if (groupWaterVolumePair.containsKey(uniqueKey)) {
                        groupIdWaterVolumePair.put(groupId, groupWaterVolumePair.get(uniqueKey));
                    }
                    if (groupPumpTripsPair.containsKey(uniqueKey)) {
                        groupIdPumpTripsPair.put(groupId, groupPumpTripsPair.get(uniqueKey));
                    }
                    if (groupCumulativeWorkingLayersPair.containsKey(uniqueKey)) {
                        groupIdCumulativeWorkingLayersPair.put(groupId, groupCumulativeWorkingLayersPair.get(uniqueKey));
                    }
                    if (groupMixSandPair.containsKey(uniqueKey)) {
                        groupIdMixSandPair.put(groupId, groupMixSandPair.get(uniqueKey));
                    }
                });
            }
        });

        // key施工状态数据字典value   value施工状态数据字典label
        Map<String, String> constructStatusPair = new HashMap<>();
        // 施工状态 字典数据
        List<DictDataDO> rdStatusData = dictDataService.getDictDataListByDictType("rdStatus");
        if (CollUtil.isNotEmpty(rdStatusData)) {
            rdStatusData.forEach(data -> {
                constructStatusPair.put(data.getValue(), data.getLabel());
            });
        }

        DataPermissionUtils.executeIgnore(() -> {
            // 查询日报关联的项目信息
            IotProjectInfoPageReqVO reqVO = new IotProjectInfoPageReqVO();
            reqVO.setProjectIds(convertList(reports, IotRdDailyReportDO::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, IotRdDailyReportDO::getTaskId));
            List<IotProjectTaskDO> tasks = iotProjectTaskService.projectTasks(taskReqVO);
            // 已经施工完成的主井任务 platformGroup
            Set<String> finishedPlatformGroups = new HashSet<>();
            // 已经施工完成的主井任务 id
            Set<Long> finishedMainPlatformIds = new HashSet<>();
            // 施工状态为空的主井任务 id
            Set<Long> nullStatusPlatformIds = new HashSet<>();
            // 查询主井的关联井列表 当主井已经施工完成时，显示 关联井的井号 施工状态
            // 如果主井已经施工完成，并且主井日报 ‘施工状态’ 字段为空值，则显示关联井的井号、施工状态
            IotRdDailyReportPageReqVO relatedWellReqVO = new IotRdDailyReportPageReqVO();
            relatedWellReqVO.setPlatformGroups(convertList(reports, IotRdDailyReportDO::getPlatformGroup));
            // relatedWellReqVO.setPlatformWell(2);
            List<IotRdDailyReportDO> relatedWellReports = iotRdDailyReportService.dailyReports(relatedWellReqVO);

            // key日报id  value平台井platformGroup
            Map<Long, String> platformWellPair = new HashMap<>();

            // 查询每个日报的生产动态明细 平台井查询 主井 的生产动态明细
            IotRdDailyReportDetailPageReqVO detailReqVO = new IotRdDailyReportDetailPageReqVO();
            detailReqVO.setPageSize(PageParam.PAGE_SIZE_NONE);
            detailReqVO.setReportIds(convertList(relatedWellReports, IotRdDailyReportDO::getId));
            PageResult<IotRdDailyReportDetailDO> reportDetailsPage = iotRdDailyReportDetailMapper.selectPage(detailReqVO);
            List<IotRdDailyReportDetailDO> reportDetails = reportDetailsPage.getList();
            if (CollUtil.isNotEmpty(reportDetails)) {
                // 设置每个日报的生产动态明细
                reportDetails.forEach(detail -> {
                    if (reportDetailsPair.containsKey(detail.getReportId())) {
                        List<IotRdDailyReportDetailRespVO> tempDetails = reportDetailsPair.get(detail.getReportId());
                        tempDetails.add(BeanUtils.toBean(detail, IotRdDailyReportDetailRespVO.class));
                        reportDetailsPair.put(detail.getReportId(), tempDetails);
                    } else {
                        List<IotRdDailyReportDetailRespVO> tempDetails = new ArrayList<>();
                        tempDetails.add(BeanUtils.toBean(detail, IotRdDailyReportDetailRespVO.class));
                        reportDetailsPair.put(detail.getReportId(), tempDetails);
                    }
                });
            }

            // 按照日报创建时间倒序排列
            if (CollUtil.isNotEmpty(relatedWellReports)) {
                relatedWellReports = relatedWellReports.stream()
                        .sorted(Comparator.comparing(IotRdDailyReportDO::getCreateTime).reversed())
                        .collect(Collectors.toList());
                // 筛选 平台井 类型的日报
                platformWellPair = relatedWellReports.stream()
                        .collect(Collectors.toMap(
                                IotRdDailyReportDO::getId,        // key：日报ID
                                IotRdDailyReportDO::getPlatformGroup, // value：platformGroup
                                (oldValue, newValue) -> oldValue  // 重复key时保留旧值（避免重复ID报错）
                        ));
            }
            // 组装没有关联生产动态明细的 日报
            // 1. 按 platformGroup 分组，存储每组的明细列表
            Map<String, List<IotRdDailyReportDetailRespVO>> platformGroupDetailsMap = new HashMap<>();
            // 2. 把已有明细的日报，按 platformGroup 汇总明细
            if (CollUtil.isNotEmpty(platformWellPair) && CollUtil.isNotEmpty(reportDetailsPair)) {
                platformWellPair.forEach((reportId, platformGroup) -> {
                    List<IotRdDailyReportDetailRespVO> details = reportDetailsPair.get(reportId);
                    if (CollUtil.isNotEmpty(details)) {
                        platformGroupDetailsMap
                                .computeIfAbsent(platformGroup, k -> new ArrayList<>())
                                .addAll(details);
                    }
                });
            }
            // 3. 给没有明细的日报，赋值同平台组的明细（实现共享）
            for (IotRdDailyReportDO report : reports) {
                Long reportId = report.getId();
                String platformGroup = platformWellPair.get(reportId);

                // 如果当前日报没有明细 && 同组有共享明细 → 赋值
                if (!reportDetailsPair.containsKey(reportId)
                        && StrUtil.isNotBlank(platformGroup)
                        && platformGroupDetailsMap.containsKey(platformGroup)) {

                    List<IotRdDailyReportDetailRespVO> sharedDetails = platformGroupDetailsMap.get(platformGroup);
                    if (CollUtil.isNotEmpty(sharedDetails)) {
                        reportDetailsPair.put(reportId, sharedDetails);
                    }
                }
            }

            if (CollUtil.isNotEmpty(tasks)) {
                tasks.forEach(task -> {
                    Set<Long> personIds = task.getResponsiblePerson();
                    Set<Long> submitterIds = task.getSubmitter();
                    // 施工队伍id集合
                    Set<Long> deptIds = task.getDeptIds();
                    currentPageDeptIds.addAll(Optional.ofNullable(deptIds).orElse(Collections.emptySet()));
                    taskPair.put(task.getId(), task.getWellName());
                    userIds.addAll(Optional.ofNullable(personIds).orElse(Collections.emptySet()));
                    userIds.addAll(Optional.ofNullable(submitterIds).orElse(Collections.emptySet()));
                    // 获取所有任务的工作量数据
                    List<IotTaskAttrModelProperty> extProperties = task.getExtProperty();
                    taskWorkloadPair.put(task.getId(), extProperties);
                    // 找到已经施工完成的主井任务 查询对应的关联井任务 用关联井号作为日报任务井号
                    if (1 == task.getPlatformWell() && "wg".equals(task.getStatus())) {
                        finishedPlatformGroups.add(task.getPlatformGroup());
                        finishedMainPlatformIds.add(task.getId());
                    }
                });
                // 查询 finishedPlatformGroups 相关的未施工完成的关联井任务井
                if (CollUtil.isNotEmpty(finishedPlatformGroups)) {
                    IotProjectTaskPageReqVO unfinishedTaskReqVO = new IotProjectTaskPageReqVO();
                    unfinishedTaskReqVO.setPlatformGroups(new ArrayList<>(finishedPlatformGroups));
                    unfinishedTaskReqVO.setPlatformWell(2);
                    // unfinishedTaskReqVO.setJobFlag("Y");
                    List<IotProjectTaskDO> unfinishedRelatedTasks = iotProjectTaskService.projectTasks(unfinishedTaskReqVO);
                    if (CollUtil.isNotEmpty(unfinishedRelatedTasks)) {
                        unfinishedRelatedTasks.forEach(task -> {
                            // relatedPlatformPair.put(task.getPlatformGroup(), task.getWellName());
                            relatedPlatformsPair.put(task.getId(), task.getWellName());
                        });
                    }
                }
            }
            // 平台井 主井施工完成 需要显示 关联井的施工状态 井号
            if (CollUtil.isNotEmpty(relatedWellReports)) {
                Map<String, IotRdDailyReportDO> relatedPlatformGroupPair = new HashMap<>();
                relatedWellReports.forEach(report -> {
                    if (2 == report.getPlatformWell()) {
                        // 找到当前页所有的关联井 如果有多个关联井 取排列在最前面的关联井
                        if (!relatedPlatformGroupPair.containsKey(report.getPlatformGroup())) {
                            relatedPlatformGroupPair.put(report.getPlatformGroup(), report);
                        }
                    }
                });
                relatedWellReports.forEach(report -> {
                    // 找到施工状态为空的主井
                    if (1 == report.getPlatformWell() && StrUtil.isBlank(report.getRdStatus())
                            && finishedMainPlatformIds.contains(report.getTaskId())) {
                        nullStatusPlatformIds.add(report.getTaskId());
                        // 找到当前主井对应的关联井
                        if (relatedPlatformGroupPair.containsKey(report.getPlatformGroup())) {
                            IotRdDailyReportDO tempReport = relatedPlatformGroupPair.get(report.getPlatformGroup());
                            tempReport.getRdStatus();
                            tempReport.getTaskId();
                            if (relatedPlatformsPair.containsKey(tempReport.getTaskId())) {
                                String wellName = relatedPlatformsPair.get(tempReport.getTaskId());
                                relatedPlatformPair.put(tempReport.getPlatformGroup(), wellName);
                                relatedWellStatusPair.put(tempReport.getPlatformGroup(), tempReport.getRdStatus());
                            }
                        }
                    }

                });
            }

            // 查询当前页所有日报关联的任务的施工队伍名称
            Map<Long, DeptDO> deptMap = deptService.getDeptMap(currentPageDeptIds);
            // 查询所有 带班干部 填报人 的姓名
            Map<Long, AdminUserRespDTO> userMap;
            if (CollUtil.isNotEmpty(userIds)) {
                userMap = adminUserApi.getUserMap(userIds);
            } else {
                userMap = Collections.emptyMap();
            }
            if (CollUtil.isNotEmpty(tasks)) {
                tasks.forEach(task -> {
                    // 安全获取施工队伍ID集合（避免null）
                    Set<Long> deptIds = Optional.ofNullable(task.getDeptIds())
                            .orElse(Collections.emptySet());
                    // 转换ID集合为队伍名称字符串（用逗号分隔）
                    String deptNames = deptIds.stream()
                            // 映射ID到队伍名称（队伍不存在时用空字符串）
                            .map(deptId -> Optional.ofNullable(deptMap.get(deptId))
                                    .map(DeptDO::getName)
                                    .orElse(""))
                            // 过滤空字符串（避免多余逗号）
                            .filter(name -> !name.isEmpty())
                            // 拼接部门名称
                            .collect(Collectors.joining(","));
                    // 存入映射关系
                    taskTeamsPair.put(task.getId(), deptNames);
                    // 安全获取带班干部ID集合（避免null）
                    Set<Long> responsibleIds = Optional.ofNullable(task.getResponsiblePerson())
                            .orElse(Collections.emptySet());
                    // 转换ID集合为姓名字符串（用逗号分隔）
                    String responsibleNames = responsibleIds.stream()
                            // 映射ID到姓名（用户不存在时用空字符串）
                            .map(userId -> Optional.ofNullable(userMap.get(userId))
                                    .map(AdminUserRespDTO::getNickname)
                                    .orElse(""))
                            // 过滤空字符串（避免多余逗号）
                            .filter(name -> !name.isEmpty())
                            // 拼接姓名
                            .collect(Collectors.joining(","));
                    // 存入映射关系
                    taskResponsiblePair.put(task.getId(), responsibleNames);
                    // 工单填报人
                    Set<Long> submitterIds = Optional.ofNullable(task.getSubmitter())
                            .orElse(Collections.emptySet());
                    // 转换ID集合为姓名字符串（用逗号分隔）
                    String submitterNames = submitterIds.stream()
                            // 映射ID到姓名（用户不存在时用空字符串）
                            .map(userId -> Optional.ofNullable(userMap.get(userId))
                                    .map(AdminUserRespDTO::getNickname)
                                    .orElse(""))
                            // 过滤空字符串（避免多余逗号）
                            .filter(name -> !name.isEmpty())
                            // 拼接姓名
                            .collect(Collectors.joining(","));
                    // 存入映射关系
                    taskSubmitterPair.put(task.getId(), submitterNames);
                });
            }
            // 查询所有任务的工作量数据 单位相同的工作量属性值合并处理
            for (IotRdDailyReportDO report : reports) {
                // 设置每个任务的工作量数据  单位相同的工作量值作合并处理
                List<IotTaskAttrModelProperty> taskAttrs = report.getExtProperty();
                // 这里暂时使用枚举 统计每个单位下的 工作量
                // 桥塞(个数)      钻可溶桥塞  钻复合桥塞           bridge_plug
                // 趟数           通刮洗 冲砂                    run_count
                // 井数           累计施工-井                    cumulative_working_well
                // 小时H                                       hour_count
                // 天数D
                // 水方量(方)                                   water_volume
                // 台次           当日泵车台次 当日仪表/混砂        daily_tools_sand   daily_pump_trips
                // 段数           累计施工-层                    cumulative_working_layers
                // 暂存不同单位的工作量属性值
                BigDecimal tempTotalBridgePlug = BigDecimal.ZERO;
                BigDecimal tempTotalRunCount = BigDecimal.ZERO;
                BigDecimal tempTotalCumulativeWorkingWell = BigDecimal.ZERO;
                BigDecimal tempTotalHourCount = BigDecimal.ZERO;
                BigDecimal tempTotalWaterVolume = BigDecimal.ZERO;
                BigDecimal tempTotalPumpTrips = BigDecimal.ZERO;
                BigDecimal tempTotalCumulativeWorkingLayers = BigDecimal.ZERO;
                BigDecimal tempTotalMixSand = BigDecimal.ZERO;
                if (CollUtil.isNotEmpty(taskAttrs)) {
                    for (IotTaskAttrModelProperty attr : taskAttrs) {
                        String unit = attr.getUnit();   // 工作量单位
                        String actualValueStr = attr.getActualValue();  // 工作量属性的实际值
                        // 处理实际值：避免null或非数字字符串导致的异常
                        BigDecimal actualValue = BigDecimal.ZERO;
                        if (StrUtil.isNotBlank(actualValueStr)) {  // 假设使用Hutool的StrUtil，或自行判断null/空
                            try {
                                actualValue = new BigDecimal(actualValueStr);
                            } catch (NumberFormatException e) {
                                // 若字符串格式错误，默认按0处理（可根据业务调整）
                                actualValue = BigDecimal.ZERO;
                            }
                        }
                        if ("个数".equals(unit)) {
                            // 钻可溶桥塞  钻复合桥塞
                            tempTotalBridgePlug = tempTotalBridgePlug.add(actualValue);
                        }
                        if ("趟数".equals(unit)) {
                            tempTotalRunCount = tempTotalRunCount.add(actualValue);
                        }
                        if ("小时".equals(unit)) {
                            tempTotalHourCount = tempTotalHourCount.add(actualValue);
                        }
                        if ("天数".equals(unit)) {
                            // 将 actualValue 换算成 H
                            BigDecimal hours = actualValue.multiply(new BigDecimal("24"));
                            tempTotalHourCount = tempTotalHourCount.add(hours);
                        }
                        if ("方".equals(unit)) {
                            tempTotalWaterVolume = tempTotalWaterVolume.add(actualValue);
                        }
                        /* if ("井数".equals(unit)) {
                            tempTotalCumulativeWorkingWell = tempTotalCumulativeWorkingWell.add(actualValue);
                        } */
                        if (finishedTaskIds.contains(report.getTaskId()) && "wg".equals(report.getRdStatus())) {
                            // 只有任务完工且日报施工状态为 完工 才统计 井数为 1
                            tempTotalCumulativeWorkingWell = new BigDecimal("1");
                        }
                        if ("段数".equals(unit)) {
                            tempTotalCumulativeWorkingLayers = tempTotalCumulativeWorkingLayers.add(actualValue);
                        }
                        if ("台次".equals(unit) && "当日泵车台次".equals(attr.getName())) {
                            tempTotalPumpTrips = tempTotalPumpTrips.add(actualValue);
                        }
                        if ("台次".equals(unit) && ("当日仪表/混砂".equals(attr.getName()) || "当日仪表".equals(attr.getName()) || "当日混砂".equals(attr.getName()))) {
                            tempTotalMixSand = tempTotalMixSand.add(actualValue);
                        }
                    }
                    report.setCumulativeWorkingWell(tempTotalCumulativeWorkingWell);
                    report.setCumulativeWorkingLayers(tempTotalCumulativeWorkingLayers);
                    report.setDailyPumpTrips(tempTotalPumpTrips);
                    report.setDailyToolsSand(tempTotalMixSand);
                    report.setRunCount(tempTotalRunCount);
                    report.setBridgePlug(tempTotalBridgePlug);
                    report.setWaterVolume(tempTotalWaterVolume);
                    report.setHourCount(tempTotalHourCount);
                }
            }
        });
        return BeanUtils.toBean(reports, IotRdDailyReportRespVO.class, (reportVO) -> {
            // 施工状态 导出使用
            if (StrUtil.isNotBlank(reportVO.getRdStatus())) {
                if (constructStatusPair.containsKey(reportVO.getRdStatus())) {
                    reportVO.setRdStatusLabel(constructStatusPair.get(reportVO.getRdStatus()));
                }
            }
            // 创建时间 格式化 yyyy-MM-dd
            if (ObjUtil.isNotEmpty(reportVO.getCreateTime())) {
                reportVO.setCreateTimeStr(LocalDateTimeUtil.format(reportVO.getCreateTime(), DatePattern.NORM_DATE_PATTERN));
            }
            // 生产动态明细
            findAndThen(reportDetailsPair, reportVO.getId(), details -> reportVO.setReportDetails(details));
            // 部门信息 任务中关联的施工队伍
            findAndThen(taskTeamsPair, reportVO.getTaskId(), deptNames -> reportVO.setDeptName(deptNames));
            // 日报关联的项目信息
            findAndThen(projectPair, reportVO.getProjectId(), contractName -> reportVO.setContractName(contractName));
            // 日报关联的任务信息
            findAndThen(taskPair, reportVO.getTaskId(), taskName -> reportVO.setTaskName(taskName));
            // 日报关联的任务信息（兼容主井完工 关联井未完工的情况）
            findAndThen(relatedPlatformPair, reportVO.getPlatformGroup(), relatedTaskName -> reportVO.setTaskName(relatedTaskName));
            // 日报关联的任务施工状态（兼容主井完工 关联井未完工的情况）
            findAndThen(relatedWellStatusPair, reportVO.getPlatformGroup(), rdStatus -> reportVO.setRdStatus(rdStatus));
            // 日报关联的责任人
            findAndThen(taskResponsiblePair, reportVO.getTaskId(), responsibleNames -> reportVO.setResponsiblePersonNames(responsibleNames));
            // 日报关联的填报人
            findAndThen(taskSubmitterPair, reportVO.getTaskId(), submitterNames -> reportVO.setSubmitterNames(submitterNames));
            // 以井维度查询时 以任务分组后的小计工作量
            // 小组内最后1条记录标识
            if (groupIdBridgePlugPair.containsKey(reportVO.getId()) || groupIdRunCountPair.containsKey(reportVO.getId()) || groupIdCumulativeWorkingWellPair.containsKey(reportVO.getId())
            || groupIdHourCountPair.containsKey(reportVO.getId()) || groupIdFuelPair.containsKey(reportVO.getId()) || groupIdWaterVolumePair.containsKey(reportVO.getId())
                    || groupIdPumpTripsPair.containsKey(reportVO.getId()) || groupIdCumulativeWorkingLayersPair.containsKey(reportVO.getId()) || groupIdMixSandPair.containsKey(reportVO.getId())) {
                reportVO.setLastGroupIdFlag(true);
            }
            // 桥塞(个数)
            findAndThen(groupIdBridgePlugPair, reportVO.getId(), bridgePlug -> reportVO.setGroupIdBridgePlug(bridgePlug));
            // 趟数
            findAndThen(groupIdRunCountPair, reportVO.getId(), runCount -> reportVO.setGroupIdRunCount(runCount));
            // 井数
            findAndThen(groupIdCumulativeWorkingWellPair, reportVO.getId(), workingWell -> reportVO.setGroupIdCumulativeWorkingWell(workingWell));
            // 小时H
            findAndThen(groupIdHourCountPair, reportVO.getId(), hourCount -> reportVO.setGroupIdHourCount(hourCount));
            // 油耗
            findAndThen(groupIdFuelPair, reportVO.getId(), fuel -> reportVO.setGroupIdFuel(fuel));
            // 水方量(方)
            findAndThen(groupIdWaterVolumePair, reportVO.getId(), waterVolume -> reportVO.setGroupIdWaterVolume(waterVolume));
            // 泵车台次
            findAndThen(groupIdPumpTripsPair, reportVO.getId(), pumpTrips -> reportVO.setGroupIdPumpTrips(pumpTrips));
            // 段数  累计施工-层
            findAndThen(groupIdCumulativeWorkingLayersPair, reportVO.getId(), workingLayer -> reportVO.setGroupIdCumulativeWorkingLayers(workingLayer));
            // 台次 当日仪表/混砂
            findAndThen(groupIdMixSandPair, reportVO.getId(), mixSand -> reportVO.setGroupIdMixSand(mixSand));
        });
    }

    /**
     * 以队伍为维度 按照任务井分组查询瑞都日报列表统计工作量
     * @param reports
     * @return
     */
    private List<IotRdDailyReportRespVO> buildWellRdDailyReports(List<IotRdDailyReportDO> reports, IotRdDailyReportPageReqVO pageReqVO) {
        if (CollUtil.isEmpty(reports)) {
            return Collections.emptyList();
        }
        // key项目id   value项目合同号
        Map<Long, String> projectPair = new HashMap<>();
        //  key任务id     value任务井号-施工区域
        Map<Long, String> taskPair = new HashMap<>();
        //  key任务id     value任务关联的带班干部名称
        Map<Long, String> taskResponsiblePair = new HashMap<>();
        //  key任务id     value任务关联的填报人名称
        Map<Long, String> taskSubmitterPair = new HashMap<>();
        //  key任务id     value工作量数据集合
        Map<Long, List<IotTaskAttrModelProperty>> taskWorkloadPair = new HashMap<>();
        //  key任务id     value任务关联的施工队伍名称 多个逗号分隔
        Map<Long, String> taskTeamsPair = new HashMap<>();
        Set<Long> userIds = new HashSet<>();
        // 当前页所有日报关联任务的 施工队伍id 集合
        Set<Long> currentPageDeptIds = new HashSet<>();
        // key主井任务platformGroup/taskPlatform     value关联井号名称
        Map<String, String> relatedPlatformPair = new HashMap<>();
        // key主井任务id     value关联井任务施工状态
        Map<String, String> relatedWellStatusPair = new HashMap<>();
        // key关联井任务id     value关联井号
        Map<Long, String> relatedPlatformsPair = new HashMap<>();

        // key 部门id-队伍id   value 任务关联的日报油耗总和
        Map<String, BigDecimal> groupFuelPair = new HashMap<>();
        // key 部门id-队伍id      value队伍工作量数据 桥塞(个数)
        Map<String, BigDecimal> groupBridgePlugPair = new HashMap<>();
        // key 部门id-队伍id      value队伍工作量数据 趟数
        Map<String, BigDecimal> groupRunCountPair = new HashMap<>();
        // key 部门id-队伍id      value队伍工作量数据 井数
        Map<String, BigDecimal> groupCumulativeWorkingWellPair = new HashMap<>();
        // key 部门id-队伍id      value队伍工作量数据 小时H
        Map<String, BigDecimal> groupHourCountPair = new HashMap<>();
        // key 部门id-队伍id      value队伍工作量数据 水方量(方)
        Map<String, BigDecimal> groupWaterVolumePair = new HashMap<>();
        // key 部门id-队伍id      value队伍工作量数据 台次
        Map<String, BigDecimal> groupPumpTripsPair = new HashMap<>();
        // key 部门id-队伍id      value队伍工作量数据 段数
        Map<String, BigDecimal> groupCumulativeWorkingLayersPair = new HashMap<>();
        // key 部门id-队伍id      value队伍工作量数据 台次 当日泵车台次 当日仪表/混砂
        Map<String, BigDecimal> groupMixSandPair = new HashMap<>();

        // key小组最后1条记录id   value 桥塞(个数)
        Map<Long, BigDecimal> groupIdBridgePlugPair = new HashMap<>();
        // key小组最后1条记录id      value趟数
        Map<Long, BigDecimal> groupIdRunCountPair = new HashMap<>();
        // key小组最后1条记录id      value井数
        Map<Long, BigDecimal> groupIdCumulativeWorkingWellPair = new HashMap<>();
        // key小组最后1条记录id      value小时H
        Map<Long, BigDecimal> groupIdHourCountPair = new HashMap<>();
        // key小组最后1条记录id      value油耗
        Map<Long, BigDecimal> groupIdFuelPair = new HashMap<>();
        // key小组最后1条记录id      value水方量(方)
        Map<Long, BigDecimal> groupIdWaterVolumePair = new HashMap<>();
        // key小组最后1条记录id      value泵车台次
        Map<Long, BigDecimal> groupIdPumpTripsPair = new HashMap<>();
        // key小组最后1条记录id      value段数  累计施工-层
        Map<Long, BigDecimal> groupIdCumulativeWorkingLayersPair = new HashMap<>();
        // key小组最后1条记录id      value台次 当日仪表/混砂
        Map<Long, BigDecimal> groupIdMixSandPair = new HashMap<>();
        // 已经完工的任务id集合
        Set<Long> finishedTaskIds = new HashSet<>();
        // key日报id   value生产动态明细
        Map<Long, List<IotRdDailyReportDetailRespVO>> reportDetailsPair = new HashMap<>();

        DataPermissionUtils.executeIgnore(() -> {
            IotProjectTaskPageReqVO taskReqVO = new IotProjectTaskPageReqVO();
            taskReqVO.setTaskIds(convertList(reports, IotRdDailyReportDO::getTaskId));
            List<IotProjectTaskDO> tasks = iotProjectTaskService.projectTasks(taskReqVO);
            if (CollUtil.isNotEmpty(tasks)) {
                tasks.forEach(task -> {
                    // 筛选出 完工 的任务集合 任务完工 施工井数 +1
                    if ("wg".equals(task.getRdStatus())) {
                        finishedTaskIds.add(task.getId());
                    }
                });
            }
        });

        // 没有工作量的日报 也需要体现出部门 施工队伍
        Map<Long, DeptDO> noWorkDeptMap = deptService.getDeptMap(convertList(reports, IotRdDailyReportDO::getDeptId));

        // 查询 当前分页 所有部门 任务井 日报数据 小计工作量
        IotRdDailyReportPageReqVO currentTaskReqVO = new IotRdDailyReportPageReqVO();
        currentTaskReqVO.setTaskIds(convertSet(reports, IotRdDailyReportDO::getTaskId));
        currentTaskReqVO.setDeptIds(convertSet(reports, IotRdDailyReportDO::getDeptId));
        currentTaskReqVO.setCreateTime(pageReqVO.getCreateTime());
        currentTaskReqVO.setProjectIds(pageReqVO.getProjectIds());
        currentTaskReqVO.setTaskIds(pageReqVO.getTaskIds());
        List<IotRdDailyReportDO> deptTaskDailyReports = iotRdDailyReportMapper.dailyReports(currentTaskReqVO);
        // 以 deptId-taskId 为唯一键 小计日报工作量
        if (CollUtil.isNotEmpty(deptTaskDailyReports)) {
            deptTaskDailyReports.forEach(report -> {
                String uniqueKey = StrUtil.join("-", report.getDeptId(), report.getTaskId());

                BigDecimal dailyFuel = report.getDailyFuel();
                dailyFuel = ObjUtil.isEmpty(dailyFuel) ? BigDecimal.ZERO : dailyFuel;
                if (groupFuelPair.containsKey(uniqueKey)) {
                    BigDecimal existTotalFuel = groupFuelPair.get(uniqueKey);
                    BigDecimal tempTotalFuel = existTotalFuel.add(dailyFuel);
                    groupFuelPair.put(uniqueKey, tempTotalFuel);
                } else {
                    groupFuelPair.put(uniqueKey, dailyFuel);
                }

                // 设置每个任务的工作量数据  单位相同的工作量值作合并处理
                List<IotTaskAttrModelProperty> taskAttrs = report.getExtProperty();
                // 暂存不同单位的工作量属性值
                // 桥塞(个数)
                BigDecimal tempTotalBridgePlug = BigDecimal.ZERO;
                // 趟数
                BigDecimal tempTotalRunCount = BigDecimal.ZERO;
                // 井数
                BigDecimal tempTotalCumulativeWorkingWell = BigDecimal.ZERO;
                // 小时H
                BigDecimal tempTotalHourCount = BigDecimal.ZERO;
                // 水方量(方)
                BigDecimal tempTotalWaterVolume = BigDecimal.ZERO;
                // 台次
                BigDecimal tempTotalPumpTrips = BigDecimal.ZERO;
                // 段数  累计施工-层
                BigDecimal tempTotalCumulativeWorkingLayers = BigDecimal.ZERO;
                // 台次 当日泵车台次 当日仪表/混砂
                BigDecimal tempTotalMixSand = BigDecimal.ZERO;
                if (CollUtil.isNotEmpty(taskAttrs)) {
                    for (IotTaskAttrModelProperty attr : taskAttrs) {
                        // 工作量单位
                        String unit = attr.getUnit();
                        // 工作量属性的实际值
                        String actualValueStr = attr.getActualValue();
                        // 处理实际值：避免null或非数字字符串导致的异常
                        BigDecimal actualValue = BigDecimal.ZERO;
                        if (StrUtil.isNotBlank(actualValueStr)) {
                            try {
                                actualValue = new BigDecimal(actualValueStr);
                            } catch (NumberFormatException e) {
                                // 若字符串格式错误，默认按0处理
                                actualValue = BigDecimal.ZERO;
                            }
                        }
                        if ("个数".equals(unit)) {
                            // 钻可溶桥塞  钻复合桥塞
                            tempTotalBridgePlug = tempTotalBridgePlug.add(actualValue);
                            if (groupBridgePlugPair.containsKey(uniqueKey)) {
                                BigDecimal tempBridgePlug = groupBridgePlugPair.get(uniqueKey);
                                groupBridgePlugPair.put(uniqueKey, tempTotalBridgePlug.add(tempBridgePlug));
                            } else {
                                groupBridgePlugPair.put(uniqueKey, tempTotalBridgePlug);
                            }
                        }
                        if ("趟数".equals(unit)) {
                            tempTotalRunCount = tempTotalRunCount.add(actualValue);
                            if (groupRunCountPair.containsKey(uniqueKey)) {
                                BigDecimal tempRunCount = groupRunCountPair.get(uniqueKey);
                                groupRunCountPair.put(uniqueKey, tempTotalRunCount.add(tempRunCount));
                            } else {
                                groupRunCountPair.put(uniqueKey, tempTotalRunCount);
                            }
                        }
                        if ("小时".equals(unit)) {
                            tempTotalHourCount = tempTotalHourCount.add(actualValue);
                            if (groupHourCountPair.containsKey(uniqueKey)) {
                                BigDecimal tempHourCount = groupHourCountPair.get(uniqueKey);
                                groupHourCountPair.put(uniqueKey, tempTotalHourCount.add(tempHourCount));
                            } else {
                                groupHourCountPair.put(uniqueKey, tempTotalHourCount);
                            }
                        }
                        if ("天数".equals(unit)) {
                            // 将 actualValue 换算成 H
                            BigDecimal hours = actualValue.multiply(new BigDecimal("24"));
                            tempTotalHourCount = tempTotalHourCount.add(hours);
                            if (groupHourCountPair.containsKey(uniqueKey)) {
                                BigDecimal tempHourCount = groupHourCountPair.get(uniqueKey);
                                groupHourCountPair.put(uniqueKey, tempTotalHourCount.add(tempHourCount));
                            } else {
                                groupHourCountPair.put(uniqueKey, tempTotalHourCount);
                            }
                        }
                        if ("方".equals(unit)) {
                            tempTotalWaterVolume = tempTotalWaterVolume.add(actualValue);
                            if (groupWaterVolumePair.containsKey(uniqueKey)) {
                                BigDecimal tempWaterVolume = groupWaterVolumePair.get(uniqueKey);
                                groupWaterVolumePair.put(uniqueKey, tempTotalWaterVolume.add(tempWaterVolume));
                            } else {
                                groupWaterVolumePair.put(uniqueKey, tempTotalWaterVolume);
                            }
                        }
                        /* if ("井数".equals(unit)) {
                            tempTotalCumulativeWorkingWell = tempTotalCumulativeWorkingWell.add(actualValue);
                            if (groupCumulativeWorkingWellPair.containsKey(uniqueKey)) {
                                BigDecimal tempWorkingWell = groupCumulativeWorkingWellPair.get(uniqueKey);
                                groupCumulativeWorkingWellPair.put(uniqueKey, tempTotalCumulativeWorkingWell.add(tempWorkingWell));
                            } else {
                                groupCumulativeWorkingWellPair.put(uniqueKey, tempTotalCumulativeWorkingWell);
                            }
                        } */
                        // 施工完成的井累计计数 1
                        if (finishedTaskIds.contains(report.getTaskId())) {
                            groupCumulativeWorkingWellPair.put(uniqueKey, new BigDecimal("1"));
                        } else {
                            groupCumulativeWorkingWellPair.put(uniqueKey, BigDecimal.ZERO);
                        }
                        if ("段数".equals(unit)) {
                            // 累计施工层
                            tempTotalCumulativeWorkingLayers = tempTotalCumulativeWorkingLayers.add(actualValue);
                            if (groupCumulativeWorkingLayersPair.containsKey(uniqueKey)) {
                                BigDecimal tempWorkingLayer = groupCumulativeWorkingLayersPair.get(uniqueKey);
                                groupCumulativeWorkingLayersPair.put(uniqueKey, tempTotalCumulativeWorkingLayers.add(tempWorkingLayer));
                            } else {
                                groupCumulativeWorkingLayersPair.put(uniqueKey, tempTotalCumulativeWorkingLayers);
                            }
                        }
                        if ("台次".equals(unit) && "当日泵车台次".equals(attr.getName())) {
                            tempTotalPumpTrips = tempTotalPumpTrips.add(actualValue);
                            if (groupPumpTripsPair.containsKey(uniqueKey)) {
                                BigDecimal tempPumpTrips = groupPumpTripsPair.get(uniqueKey);
                                groupPumpTripsPair.put(uniqueKey, tempTotalPumpTrips.add(tempPumpTrips));
                            } else {
                                groupPumpTripsPair.put(uniqueKey, tempTotalPumpTrips);
                            }
                        }
                        if ("台次".equals(unit) && ("当日仪表/混砂".equals(attr.getName())
                                || "当日混砂".equals(attr.getName()) || "当日仪表".equals(attr.getName()))) {
                            tempTotalMixSand = tempTotalMixSand.add(actualValue);
                            if (groupMixSandPair.containsKey(uniqueKey)) {
                                BigDecimal tempMixSand = groupMixSandPair.get(uniqueKey);
                                groupMixSandPair.put(uniqueKey, actualValue.add(tempMixSand));
                            } else {
                                groupMixSandPair.put(uniqueKey, tempTotalMixSand);
                            }
                        }
                    }
                }
            });
        }

        TenantUtils.executeIgnore(() -> {
            currentTaskReqVO.setDeptId(pageReqVO.getDeptId());
            // 查询 deptId-taskId 分组内最后1条记录id 设置展开列标识
            List<IotRdDailyReportDO> currentGroupIds = iotRdDailyReportService.rdDeptDailyReportsGroupIds(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 (groupBridgePlugPair.containsKey(uniqueKey)) {
                        groupIdBridgePlugPair.put(groupId, groupBridgePlugPair.get(uniqueKey));
                    }
                    if (groupRunCountPair.containsKey(uniqueKey)) {
                        groupIdRunCountPair.put(groupId, groupRunCountPair.get(uniqueKey));
                    }
                    if (groupCumulativeWorkingWellPair.containsKey(uniqueKey)) {
                        groupIdCumulativeWorkingWellPair.put(groupId, groupCumulativeWorkingWellPair.get(uniqueKey));
                    }
                    if (groupHourCountPair.containsKey(uniqueKey)) {
                        groupIdHourCountPair.put(groupId, groupHourCountPair.get(uniqueKey));
                    }
                    if (groupFuelPair.containsKey(uniqueKey)) {
                        groupIdFuelPair.put(groupId, groupFuelPair.get(uniqueKey));
                    }
                    if (groupWaterVolumePair.containsKey(uniqueKey)) {
                        groupIdWaterVolumePair.put(groupId, groupWaterVolumePair.get(uniqueKey));
                    }
                    if (groupPumpTripsPair.containsKey(uniqueKey)) {
                        groupIdPumpTripsPair.put(groupId, groupPumpTripsPair.get(uniqueKey));
                    }
                    if (groupCumulativeWorkingLayersPair.containsKey(uniqueKey)) {
                        groupIdCumulativeWorkingLayersPair.put(groupId, groupCumulativeWorkingLayersPair.get(uniqueKey));
                    }
                    if (groupMixSandPair.containsKey(uniqueKey)) {
                        groupIdMixSandPair.put(groupId, groupMixSandPair.get(uniqueKey));
                    }
                });
            }
        });

        // key施工状态数据字典value   value施工状态数据字典label
        Map<String, String> constructStatusPair = new HashMap<>();
        // 施工状态 字典数据
        List<DictDataDO> rdStatusData = dictDataService.getDictDataListByDictType("rdStatus");
        if (CollUtil.isNotEmpty(rdStatusData)) {
            rdStatusData.forEach(data -> {
                constructStatusPair.put(data.getValue(), data.getLabel());
            });
        }

        DataPermissionUtils.executeIgnore(() -> {
            // 查询日报关联的项目信息
            IotProjectInfoPageReqVO reqVO = new IotProjectInfoPageReqVO();
            reqVO.setProjectIds(convertList(reports, IotRdDailyReportDO::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, IotRdDailyReportDO::getTaskId));
            List<IotProjectTaskDO> tasks = iotProjectTaskService.projectTasks(taskReqVO);
            // 已经施工完成的主井任务 platformGroup
            Set<String> finishedPlatformGroups = new HashSet<>();
            // 已经施工完成的主井任务 id
            Set<Long> finishedMainPlatformIds = new HashSet<>();
            // 施工状态为空的主井任务 id
            Set<Long> nullStatusPlatformIds = new HashSet<>();
            // 查询主井的关联井列表 当主井已经施工完成时，显示 关联井的井号 施工状态
            // 如果主井已经施工完成，并且主井日报 ‘施工状态’ 字段为空值，则显示关联井的井号、施工状态
            IotRdDailyReportPageReqVO relatedWellReqVO = new IotRdDailyReportPageReqVO();
            relatedWellReqVO.setPlatformGroups(convertList(reports, IotRdDailyReportDO::getPlatformGroup));
            // relatedWellReqVO.setPlatformWell(2);
            List<IotRdDailyReportDO> relatedWellReports = iotRdDailyReportService.dailyReports(relatedWellReqVO);

            // key日报id  value平台井platformGroup
            Map<Long, String> platformWellPair = new HashMap<>();

            // 查询每个日报的生产动态明细 平台井查询 主井 的生产动态明细
            IotRdDailyReportDetailPageReqVO detailReqVO = new IotRdDailyReportDetailPageReqVO();
            detailReqVO.setPageSize(PageParam.PAGE_SIZE_NONE);
            detailReqVO.setReportIds(convertList(relatedWellReports, IotRdDailyReportDO::getId));
            PageResult<IotRdDailyReportDetailDO> reportDetailsPage = iotRdDailyReportDetailMapper.selectPage(detailReqVO);
            List<IotRdDailyReportDetailDO> reportDetails = reportDetailsPage.getList();
            if (CollUtil.isNotEmpty(reportDetails)) {
                // 设置每个日报的生产动态明细
                reportDetails.forEach(detail -> {
                    if (reportDetailsPair.containsKey(detail.getReportId())) {
                        List<IotRdDailyReportDetailRespVO> tempDetails = reportDetailsPair.get(detail.getReportId());
                        tempDetails.add(BeanUtils.toBean(detail, IotRdDailyReportDetailRespVO.class));
                        reportDetailsPair.put(detail.getReportId(), tempDetails);
                    } else {
                        List<IotRdDailyReportDetailRespVO> tempDetails = new ArrayList<>();
                        tempDetails.add(BeanUtils.toBean(detail, IotRdDailyReportDetailRespVO.class));
                        reportDetailsPair.put(detail.getReportId(), tempDetails);
                    }
                });
            }

            // 按照日报创建时间倒序排列
            if (CollUtil.isNotEmpty(relatedWellReports)) {
                relatedWellReports = relatedWellReports.stream()
                        .sorted(Comparator.comparing(IotRdDailyReportDO::getCreateTime).reversed())
                        .collect(Collectors.toList());
                // 筛选 平台井 类型的日报
                platformWellPair = relatedWellReports.stream()
                        .collect(Collectors.toMap(
                                IotRdDailyReportDO::getId,        // key：日报ID
                                IotRdDailyReportDO::getPlatformGroup, // value：platformGroup
                                (oldValue, newValue) -> oldValue  // 重复key时保留旧值（避免重复ID报错）
                        ));
            }
            // 组装没有关联生产动态明细的 日报
            // 1. 按 platformGroup 分组，存储每组的明细列表
            Map<String, List<IotRdDailyReportDetailRespVO>> platformGroupDetailsMap = new HashMap<>();
            // 2. 把已有明细的日报，按 platformGroup 汇总明细
            if (CollUtil.isNotEmpty(platformWellPair) && CollUtil.isNotEmpty(reportDetailsPair)) {
                platformWellPair.forEach((reportId, platformGroup) -> {
                    List<IotRdDailyReportDetailRespVO> details = reportDetailsPair.get(reportId);
                    if (CollUtil.isNotEmpty(details)) {
                        platformGroupDetailsMap
                                .computeIfAbsent(platformGroup, k -> new ArrayList<>())
                                .addAll(details);
                    }
                });
            }
            // 3. 给没有明细的日报，赋值同平台组的明细（实现共享）
            for (IotRdDailyReportDO report : reports) {
                Long reportId = report.getId();
                String platformGroup = platformWellPair.get(reportId);

                // 如果当前日报没有明细 && 同组有共享明细 → 赋值
                if (!reportDetailsPair.containsKey(reportId)
                        && StrUtil.isNotBlank(platformGroup)
                        && platformGroupDetailsMap.containsKey(platformGroup)) {

                    List<IotRdDailyReportDetailRespVO> sharedDetails = platformGroupDetailsMap.get(platformGroup);
                    if (CollUtil.isNotEmpty(sharedDetails)) {
                        reportDetailsPair.put(reportId, sharedDetails);
                    }
                }
            }

            if (CollUtil.isNotEmpty(tasks)) {
                tasks.forEach(task -> {
                    Set<Long> personIds = task.getResponsiblePerson();
                    Set<Long> submitterIds = task.getSubmitter();
                    // 施工队伍id集合
                    Set<Long> deptIds = task.getDeptIds();
                    currentPageDeptIds.addAll(Optional.ofNullable(deptIds).orElse(Collections.emptySet()));
                    taskPair.put(task.getId(), task.getWellName());
                    userIds.addAll(Optional.ofNullable(personIds).orElse(Collections.emptySet()));
                    userIds.addAll(Optional.ofNullable(submitterIds).orElse(Collections.emptySet()));
                    // 获取所有任务的工作量数据
                    List<IotTaskAttrModelProperty> extProperties = task.getExtProperty();
                    taskWorkloadPair.put(task.getId(), extProperties);
                    // 找到已经施工完成的主井任务 查询对应的关联井任务 用关联井号作为日报任务井号
                    if (1 == task.getPlatformWell() && "wg".equals(task.getStatus())) {
                        finishedPlatformGroups.add(task.getPlatformGroup());
                        finishedMainPlatformIds.add(task.getId());
                    }
                });
                // 查询 finishedPlatformGroups 相关的未施工完成的关联井任务井
                if (CollUtil.isNotEmpty(finishedPlatformGroups)) {
                    IotProjectTaskPageReqVO unfinishedTaskReqVO = new IotProjectTaskPageReqVO();
                    unfinishedTaskReqVO.setPlatformGroups(new ArrayList<>(finishedPlatformGroups));
                    unfinishedTaskReqVO.setPlatformWell(2);
                    // unfinishedTaskReqVO.setJobFlag("Y");
                    List<IotProjectTaskDO> unfinishedRelatedTasks = iotProjectTaskService.projectTasks(unfinishedTaskReqVO);
                    if (CollUtil.isNotEmpty(unfinishedRelatedTasks)) {
                        unfinishedRelatedTasks.forEach(task -> {
                            // relatedPlatformPair.put(task.getPlatformGroup(), task.getWellName());
                            relatedPlatformsPair.put(task.getId(), task.getWellName());
                        });
                    }
                }
            }
            // 平台井 主井施工完成 需要显示 关联井的施工状态 井号
            if (CollUtil.isNotEmpty(relatedWellReports)) {
                Map<String, IotRdDailyReportDO> relatedPlatformGroupPair = new HashMap<>();
                relatedWellReports.forEach(report -> {
                    if (2 == report.getPlatformWell()) {
                        // 找到当前页所有的关联井 如果有多个关联井 取排列在最前面的关联井
                        if (!relatedPlatformGroupPair.containsKey(report.getPlatformGroup())) {
                            relatedPlatformGroupPair.put(report.getPlatformGroup(), report);
                        }
                    }
                });
                relatedWellReports.forEach(report -> {
                    // 找到施工状态为空的主井
                    if (1 == report.getPlatformWell() && StrUtil.isBlank(report.getRdStatus())
                            && finishedMainPlatformIds.contains(report.getTaskId())) {
                        nullStatusPlatformIds.add(report.getTaskId());
                        // 找到当前主井对应的关联井
                        if (relatedPlatformGroupPair.containsKey(report.getPlatformGroup())) {
                            IotRdDailyReportDO tempReport = relatedPlatformGroupPair.get(report.getPlatformGroup());
                            tempReport.getRdStatus();
                            tempReport.getTaskId();
                            if (relatedPlatformsPair.containsKey(tempReport.getTaskId())) {
                                String wellName = relatedPlatformsPair.get(tempReport.getTaskId());
                                relatedPlatformPair.put(tempReport.getPlatformGroup(), wellName);
                                relatedWellStatusPair.put(tempReport.getPlatformGroup(), tempReport.getRdStatus());
                            }
                        }
                    }

                });
            }

            // 查询当前页所有日报关联的任务的施工队伍名称
            Map<Long, DeptDO> deptMap = deptService.getDeptMap(currentPageDeptIds);
            // 查询所有 带班干部 填报人 的姓名
            Map<Long, AdminUserRespDTO> userMap;
            if (CollUtil.isNotEmpty(userIds)) {
                userMap = adminUserApi.getUserMap(userIds);
            } else {
                userMap = Collections.emptyMap();
            }
            if (CollUtil.isNotEmpty(tasks)) {
                tasks.forEach(task -> {
                    // 安全获取施工队伍ID集合（避免null）
                    Set<Long> deptIds = Optional.ofNullable(task.getDeptIds())
                            .orElse(Collections.emptySet());
                    // 转换ID集合为队伍名称字符串（用逗号分隔）
                    String deptNames = deptIds.stream()
                            // 映射ID到队伍名称（队伍不存在时用空字符串）
                            .map(deptId -> Optional.ofNullable(deptMap.get(deptId))
                                    .map(DeptDO::getName)
                                    .orElse(""))
                            // 过滤空字符串（避免多余逗号）
                            .filter(name -> !name.isEmpty())
                            // 拼接部门名称
                            .collect(Collectors.joining(","));
                    // 存入映射关系
                    taskTeamsPair.put(task.getId(), deptNames);
                    // 安全获取带班干部ID集合（避免null）
                    Set<Long> responsibleIds = Optional.ofNullable(task.getResponsiblePerson())
                            .orElse(Collections.emptySet());
                    // 转换ID集合为姓名字符串（用逗号分隔）
                    String responsibleNames = responsibleIds.stream()
                            // 映射ID到姓名（用户不存在时用空字符串）
                            .map(userId -> Optional.ofNullable(userMap.get(userId))
                                    .map(AdminUserRespDTO::getNickname)
                                    .orElse(""))
                            // 过滤空字符串（避免多余逗号）
                            .filter(name -> !name.isEmpty())
                            // 拼接姓名
                            .collect(Collectors.joining(","));
                    // 存入映射关系
                    taskResponsiblePair.put(task.getId(), responsibleNames);
                    // 工单填报人
                    Set<Long> submitterIds = Optional.ofNullable(task.getSubmitter())
                            .orElse(Collections.emptySet());
                    // 转换ID集合为姓名字符串（用逗号分隔）
                    String submitterNames = submitterIds.stream()
                            // 映射ID到姓名（用户不存在时用空字符串）
                            .map(userId -> Optional.ofNullable(userMap.get(userId))
                                    .map(AdminUserRespDTO::getNickname)
                                    .orElse(""))
                            // 过滤空字符串（避免多余逗号）
                            .filter(name -> !name.isEmpty())
                            // 拼接姓名
                            .collect(Collectors.joining(","));
                    // 存入映射关系
                    taskSubmitterPair.put(task.getId(), submitterNames);
                });
            }
            // 查询所有任务的工作量数据 单位相同的工作量属性值合并处理
            for (IotRdDailyReportDO report : reports) {
                // 设置每个任务的工作量数据  单位相同的工作量值作合并处理
                List<IotTaskAttrModelProperty> taskAttrs = report.getExtProperty();
                // 这里暂时使用枚举 统计每个单位下的 工作量
                // 桥塞(个数)      钻可溶桥塞  钻复合桥塞           bridge_plug
                // 趟数           通刮洗 冲砂                    run_count
                // 井数           累计施工-井                    cumulative_working_well
                // 小时H                                       hour_count
                // 天数D
                // 水方量(方)                                   water_volume
                // 台次           当日泵车台次 当日仪表/混砂        daily_tools_sand   daily_pump_trips
                // 段数           累计施工-层                    cumulative_working_layers
                // 暂存不同单位的工作量属性值
                BigDecimal tempTotalBridgePlug = BigDecimal.ZERO;
                BigDecimal tempTotalRunCount = BigDecimal.ZERO;
                BigDecimal tempTotalCumulativeWorkingWell = BigDecimal.ZERO;
                BigDecimal tempTotalHourCount = BigDecimal.ZERO;
                BigDecimal tempTotalWaterVolume = BigDecimal.ZERO;
                BigDecimal tempTotalPumpTrips = BigDecimal.ZERO;
                BigDecimal tempTotalCumulativeWorkingLayers = BigDecimal.ZERO;
                BigDecimal tempTotalMixSand = BigDecimal.ZERO;
                if (CollUtil.isNotEmpty(taskAttrs)) {
                    for (IotTaskAttrModelProperty attr : taskAttrs) {
                        String unit = attr.getUnit();   // 工作量单位
                        String actualValueStr = attr.getActualValue();  // 工作量属性的实际值
                        // 处理实际值：避免null或非数字字符串导致的异常
                        BigDecimal actualValue = BigDecimal.ZERO;
                        if (StrUtil.isNotBlank(actualValueStr)) {  // 假设使用Hutool的StrUtil，或自行判断null/空
                            try {
                                actualValue = new BigDecimal(actualValueStr);
                            } catch (NumberFormatException e) {
                                // 若字符串格式错误，默认按0处理（可根据业务调整）
                                actualValue = BigDecimal.ZERO;
                            }
                        }
                        if ("个数".equals(unit)) {
                            // 钻可溶桥塞  钻复合桥塞
                            tempTotalBridgePlug = tempTotalBridgePlug.add(actualValue);
                        }
                        if ("趟数".equals(unit)) {
                            tempTotalRunCount = tempTotalRunCount.add(actualValue);
                        }
                        if ("小时".equals(unit)) {
                            tempTotalHourCount = tempTotalHourCount.add(actualValue);
                        }
                        if ("天数".equals(unit)) {
                            // 将 actualValue 换算成 H
                            BigDecimal hours = actualValue.multiply(new BigDecimal("24"));
                            tempTotalHourCount = tempTotalHourCount.add(hours);
                        }
                        if ("方".equals(unit)) {
                            tempTotalWaterVolume = tempTotalWaterVolume.add(actualValue);
                        }
                        /* if ("井数".equals(unit)) {
                            tempTotalCumulativeWorkingWell = tempTotalCumulativeWorkingWell.add(actualValue);
                        } */
                        if (finishedTaskIds.contains(report.getTaskId()) && "wg".equals(report.getRdStatus())) {
                            // 只有任务完工且日报施工状态为 完工 才统计 井数为 1
                            tempTotalCumulativeWorkingWell = new BigDecimal("1");
                        }
                        if ("段数".equals(unit)) {
                            tempTotalCumulativeWorkingLayers = tempTotalCumulativeWorkingLayers.add(actualValue);
                        }
                        if ("台次".equals(unit) && "当日泵车台次".equals(attr.getName())) {
                            tempTotalPumpTrips = tempTotalPumpTrips.add(actualValue);
                        }
                        if ("台次".equals(unit) && ("当日仪表/混砂".equals(attr.getName()) || "当日仪表".equals(attr.getName()) || "当日混砂".equals(attr.getName()))) {
                            tempTotalMixSand = tempTotalMixSand.add(actualValue);
                        }
                    }
                    report.setCumulativeWorkingWell(tempTotalCumulativeWorkingWell);
                    report.setCumulativeWorkingLayers(tempTotalCumulativeWorkingLayers);
                    report.setDailyPumpTrips(tempTotalPumpTrips);
                    report.setDailyToolsSand(tempTotalMixSand);
                    report.setRunCount(tempTotalRunCount);
                    report.setBridgePlug(tempTotalBridgePlug);
                    report.setWaterVolume(tempTotalWaterVolume);
                    report.setHourCount(tempTotalHourCount);
                }
            }
        });
        return BeanUtils.toBean(reports, IotRdDailyReportRespVO.class, (reportVO) -> {
            // 创建时间格式化 yyyy-MM-dd 导出
            if (ObjUtil.isNotEmpty(reportVO.getCreateTime())) {
                reportVO.setCreateTimeStr(LocalDateTimeUtil.format(reportVO.getCreateTime(), DatePattern.NORM_DATE_PATTERN));
            }
            // 生产动态明细
            findAndThen(reportDetailsPair, reportVO.getId(), details -> reportVO.setReportDetails(details));
            // 施工状态 导出使用
            if (StrUtil.isNotBlank(reportVO.getRdStatus())) {
                if (constructStatusPair.containsKey(reportVO.getRdStatus())) {
                    reportVO.setRdStatusLabel(constructStatusPair.get(reportVO.getRdStatus()));
                }
            }
            // 部门信息 任务中关联的施工队伍
            findAndThen(taskTeamsPair, reportVO.getTaskId(), deptNames -> reportVO.setDeptName(deptNames));
            // 无工作量日报 设置部门 施工队伍
            if (StrUtil.isBlank(reportVO.getDeptName())) {
                if (noWorkDeptMap.containsKey(reportVO.getDeptId())) {
                    reportVO.setDeptName(noWorkDeptMap.get(reportVO.getDeptId()).getName());
                }
            }
            // 日报关联的项目信息
            findAndThen(projectPair, reportVO.getProjectId(), contractName -> reportVO.setContractName(contractName));
            // 日报关联的任务信息
            findAndThen(taskPair, reportVO.getTaskId(), taskName -> reportVO.setTaskName(taskName));
            // 日报关联的任务信息（兼容主井完工 关联井未完工的情况）
            findAndThen(relatedPlatformPair, reportVO.getPlatformGroup(), relatedTaskName -> reportVO.setTaskName(relatedTaskName));
            // 日报关联的任务施工状态（兼容主井完工 关联井未完工的情况）
            findAndThen(relatedWellStatusPair, reportVO.getPlatformGroup(), rdStatus -> reportVO.setRdStatus(rdStatus));
            // 日报关联的责任人
            findAndThen(taskResponsiblePair, reportVO.getTaskId(), responsibleNames -> reportVO.setResponsiblePersonNames(responsibleNames));
            // 日报关联的填报人
            findAndThen(taskSubmitterPair, reportVO.getTaskId(), submitterNames -> reportVO.setSubmitterNames(submitterNames));
            // 以井维度查询时 以任务分组后的小计工作量
            // 小组内最后1条记录标识
            if (groupIdBridgePlugPair.containsKey(reportVO.getId()) || groupIdRunCountPair.containsKey(reportVO.getId()) || groupIdCumulativeWorkingWellPair.containsKey(reportVO.getId())
                    || groupIdHourCountPair.containsKey(reportVO.getId()) || groupIdFuelPair.containsKey(reportVO.getId()) || groupIdWaterVolumePair.containsKey(reportVO.getId())
                    || groupIdPumpTripsPair.containsKey(reportVO.getId()) || groupIdCumulativeWorkingLayersPair.containsKey(reportVO.getId()) || groupIdMixSandPair.containsKey(reportVO.getId())) {
                reportVO.setLastGroupIdFlag(true);
            }
            // 桥塞(个数)
            findAndThen(groupIdBridgePlugPair, reportVO.getId(), bridgePlug -> reportVO.setGroupIdBridgePlug(bridgePlug));
            // 趟数
            findAndThen(groupIdRunCountPair, reportVO.getId(), runCount -> reportVO.setGroupIdRunCount(runCount));
            // 井数
            findAndThen(groupIdCumulativeWorkingWellPair, reportVO.getId(), workingWell -> reportVO.setGroupIdCumulativeWorkingWell(workingWell));
            // 小时H
            findAndThen(groupIdHourCountPair, reportVO.getId(), hourCount -> reportVO.setGroupIdHourCount(hourCount));
            // 油耗
            findAndThen(groupIdFuelPair, reportVO.getId(), fuel -> reportVO.setGroupIdFuel(fuel));
            // 水方量(方)
            findAndThen(groupIdWaterVolumePair, reportVO.getId(), waterVolume -> reportVO.setGroupIdWaterVolume(waterVolume));
            // 泵车台次
            findAndThen(groupIdPumpTripsPair, reportVO.getId(), pumpTrips -> reportVO.setGroupIdPumpTrips(pumpTrips));
            // 段数  累计施工-层
            findAndThen(groupIdCumulativeWorkingLayersPair, reportVO.getId(), workingLayer -> reportVO.setGroupIdCumulativeWorkingLayers(workingLayer));
            // 台次 当日仪表/混砂
            findAndThen(groupIdMixSandPair, reportVO.getId(), mixSand -> reportVO.setGroupIdMixSand(mixSand));
        });
    }


    @GetMapping("/polylineStatistics")
    @Operation(summary = "瑞都日报 统计")
    @PreAuthorize("@ss.hasPermission('pms:iot-rd-daily-report:query')")
    public CommonResult<List<IotRdDailyReportPolylineVO>> polylineStatistics(@Valid IotRdDailyReportPageReqVO 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);
            }
        }
        List<IotRdDailyReportPolylineVO> result = iotRdDailyReportService.polylineStatistics(pageReqVO);
        return success(result);
    }

    @GetMapping("/workloadKanban")
    @Operation(summary = "瑞都 看板 日报统计折线图 以公司为维度 不区分 项目部 队伍")
    @PreAuthorize("@ss.hasPermission('pms:iot-rd-daily-report:query')")
    public CommonResult<List<IotRdDailyReportPolylineVO>> workloadKanban(@Valid IotRdDailyReportPageReqVO 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);
            }
        }
        List<IotRdDailyReportPolylineVO> result = iotRdDailyReportService.workloadKanban(pageReqVO);
        return success(result);
    }

    /**
     * 设置日报的关联信息 部门(施工队伍) 项目 任务 带班干部 日报填报人
     * @param reports
     * @return
     */
    private List<IotRdDailyReportRespVO> buildDailyReportList(List<IotRdDailyReportDO> reports) {
        if (CollUtil.isEmpty(reports)) {
            return Collections.emptyList();
        }
        // 设备部门信息
        Map<Long, DeptDO> tempDeptMap = deptService.getDeptMap(convertList(reports, IotRdDailyReportDO::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> taskLocationPair = new HashMap<>();
        //  key任务id     value任务关联的带班干部名称
        Map<Long, String> taskResponsiblePair = new HashMap<>();
        //  key任务id     value临时新建日报的带班干部名称 多个逗号分隔
        Map<Long, String> tempReportResponsiblePair = new HashMap<>();
        //  key任务id     value任务关联的填报人名称
        Map<Long, String> taskSubmitterPair = new HashMap<>();
        //  key任务id     value临时新建的日报的填报人名称
        Map<Long, String> tempSubmitterPair = new HashMap<>();
        //  key任务id     value工作量数据集合
        Map<Long, List<IotTaskAttrModelProperty>> taskWorkloadPair = new HashMap<>();
        //  key任务id     value任务关联的施工队伍名称 多个逗号分隔
        Map<Long, String> taskTeamsPair = new HashMap<>();

        Set<Long> userIds = new HashSet<>();
        // 当前页所有日报关联任务的 施工队伍id 集合
        Set<Long> currentPageDeptIds = new HashSet<>();
        // key主井任务platformGroup/taskPlatform     value关联井号名称
        Map<String, String> relatedPlatformPair = new HashMap<>();
        // key主井任务id     value关联井任务施工状态
        Map<String, String> relatedWellStatusPair = new HashMap<>();
        // key关联井任务id     value关联井号
        Map<Long, String> relatedPlatformsPair = new HashMap<>();
        // key施工状态数据字典value   value施工状态数据字典label
        Map<String, String> constructStatusPair = new HashMap<>();
        // key日报id   value生产动态明细
        Map<Long, List<IotRdDailyReportDetailRespVO>> reportDetailsPair = new HashMap<>();

        // 施工状态 字典数据
        List<DictDataDO> rdStatusData = dictDataService.getDictDataListByDictType("rdStatus");
        if (CollUtil.isNotEmpty(rdStatusData)) {
            rdStatusData.forEach(data -> {
                constructStatusPair.put(data.getValue(), data.getLabel());
            });
        }
        // 设置非生产时间标识
        Map<String, Boolean> reportNonProductFlagPair = new HashMap<>();
        // key平台井标识  value非生产时间累计和列表
        Map<String, List<BigDecimal>> platformNonProductPair = new HashMap<>();
        // key平台井标识  value平台井非生产时效集合
        Map<String, BigDecimal> platformNptPair = new HashMap<>();
        // key项目部id  value项目部排序值
        Map<Long, Integer> projectSortPair = new HashMap<>();
        // key项目部id  value项目部名称
        Map<Long, String> projectNamePair = new HashMap<>();
        // key施工队伍id  value队伍所属项目部
        Map<Long, Long> projectIdPair = new HashMap<>();
        //  施工工艺 key字典键值     value字典标签
        Map<String, String> techniqueDictPair = new HashMap<>();
        // key日报id  value日报关联的施工工艺名称集合
        Map<Long, String> techniqueNamesPair = new HashMap<>();
        // key设备id  value日报关联的设备名称集合
        Map<String, String> deviceNamesPair = new HashMap<>();
        // key日报id  value日报关联的设备名称集合
        Map<Long, String> reportDeviceNamesPair = new HashMap<>();

        // 设备id集合
        Set<Long> deviceIds = new HashSet<>();

        // 查询施工工艺字典数据
        List<DictDataDO> rdTechniques = dictDataService.getDictDataListByDictType("rq_iot_project_technology_rd");
        if (CollUtil.isNotEmpty(rdTechniques)) {
            rdTechniques.forEach(tech -> {
                techniqueDictPair.put(tech.getValue(), tech.getLabel());
            });
        }

        // 平台井 筛选关联的井的生产动态明细 赋值到 平台井列表 的 日报对象

        DataPermissionUtils.executeIgnore(() -> {
            // 查询日报关联的项目信息
            IotProjectInfoPageReqVO reqVO = new IotProjectInfoPageReqVO();
            reqVO.setProjectIds(convertList(reports, IotRdDailyReportDO::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, IotRdDailyReportDO::getTaskId));
            List<IotProjectTaskDO> tasks = iotProjectTaskService.projectTasks(taskReqVO);
            // 已经施工完成的主井任务 platformGroup
            Set<String> finishedPlatformGroups = new HashSet<>();
            // 已经施工完成的主井任务 id
            Set<Long> finishedMainPlatformIds = new HashSet<>();
            // 施工状态为空的主井任务 id
            Set<Long> nullStatusPlatformIds = new HashSet<>();
            // 施工完成的任务id集合
            Set<Long> finishedTaskIds = new HashSet<>();
            // 查询主井的关联井列表 当主井已经施工完成时，显示 关联井的井号 施工状态
            // 如果主井已经施工完成，并且主井日报 ‘施工状态’ 字段为空值，则显示关联井的井号、施工状态
            IotRdDailyReportPageReqVO relatedWellReqVO = new IotRdDailyReportPageReqVO();
            relatedWellReqVO.setPlatformGroups(convertList(reports, IotRdDailyReportDO::getPlatformGroup));
            // relatedWellReqVO.setPlatformWell(2);
            List<IotRdDailyReportDO> relatedWellReports = iotRdDailyReportService.dailyReports(relatedWellReqVO);

            // key日报id  value平台井platformGroup
            Map<Long, String> platformWellPair = new HashMap<>();

            // 查询每个日报的生产动态明细 平台井查询 主井 的生产动态明细
            IotRdDailyReportDetailPageReqVO detailReqVO = new IotRdDailyReportDetailPageReqVO();
            detailReqVO.setPageSize(PageParam.PAGE_SIZE_NONE);
            detailReqVO.setReportIds(convertList(relatedWellReports, IotRdDailyReportDO::getId));
            PageResult<IotRdDailyReportDetailDO> reportDetailsPage = iotRdDailyReportDetailMapper.selectPage(detailReqVO);
            List<IotRdDailyReportDetailDO> reportDetails = reportDetailsPage.getList();
            if (CollUtil.isNotEmpty(reportDetails)) {
                // 设置每个日报的生产动态明细
                reportDetails.forEach(detail -> {
                    if (reportDetailsPair.containsKey(detail.getReportId())) {
                        List<IotRdDailyReportDetailRespVO> tempDetails = reportDetailsPair.get(detail.getReportId());
                        tempDetails.add(BeanUtils.toBean(detail, IotRdDailyReportDetailRespVO.class));
                        reportDetailsPair.put(detail.getReportId(), tempDetails);
                    } else {
                        List<IotRdDailyReportDetailRespVO> tempDetails = new ArrayList<>();
                        tempDetails.add(BeanUtils.toBean(detail, IotRdDailyReportDetailRespVO.class));
                        reportDetailsPair.put(detail.getReportId(), tempDetails);
                    }
                });
            }

            // 按照日报创建时间倒序排列
            if (CollUtil.isNotEmpty(relatedWellReports)) {
                relatedWellReports = relatedWellReports.stream()
                        .sorted(Comparator.comparing(IotRdDailyReportDO::getCreateTime).reversed())
                        .collect(Collectors.toList());
                // 筛选 平台井 类型的日报
                platformWellPair = relatedWellReports.stream()
                        .collect(Collectors.toMap(
                                IotRdDailyReportDO::getId,        // key：日报ID
                                IotRdDailyReportDO::getPlatformGroup, // value：platformGroup
                                (oldValue, newValue) -> oldValue  // 重复key时保留旧值（避免重复ID报错）
                        ));
            }

            // 组装没有关联生产动态明细的 日报
            // 1. 按 platformGroup 分组，存储每组的明细列表
            Map<String, List<IotRdDailyReportDetailRespVO>> platformGroupDetailsMap = new HashMap<>();
            // 2. 把已有明细的日报，按 platformGroup 汇总明细
            if (CollUtil.isNotEmpty(platformWellPair) && CollUtil.isNotEmpty(reportDetailsPair)) {
                platformWellPair.forEach((reportId, platformGroup) -> {
                    List<IotRdDailyReportDetailRespVO> details = reportDetailsPair.get(reportId);
                    if (CollUtil.isNotEmpty(details)) {
                        platformGroupDetailsMap
                                .computeIfAbsent(platformGroup, k -> new ArrayList<>())
                                .addAll(details);
                    }
                });
            }

            // 3. 给没有明细的日报，赋值同平台组的明细（实现共享）
            for (IotRdDailyReportDO report : reports) {
                Long reportId = report.getId();
                String platformGroup = platformWellPair.get(reportId);

                Set<Long> thisDeviceIds = report.getDeviceIds();
                if (CollUtil.isNotEmpty(thisDeviceIds)) {
                    deviceIds.addAll(thisDeviceIds);
                }

                Set<Long> techniqueIds = report.getTechniqueIds();
                String thisTechniqueNames = Optional.ofNullable(techniqueIds)
                        .filter(CollUtil::isNotEmpty)
                        .map(techIds -> techIds.stream()
                                .map(String::valueOf)  // 将 Long 转为 String
                                .map(techniqueDictPair::get)  // 从字典获取名称
                                .filter(Objects::nonNull)  // 过滤空值
                                .filter(StrUtil::isNotBlank)  // 过滤空白值
                                .collect(Collectors.joining(",")))  // 用逗号连接
                        .orElse("");  // 如果为空，返回空字符串
                techniqueNamesPair.put(report.getId(), thisTechniqueNames);
                // 如果当前日报没有明细 && 同组有共享明细 → 赋值
                if (!reportDetailsPair.containsKey(reportId)
                        && StrUtil.isNotBlank(platformGroup)
                        && platformGroupDetailsMap.containsKey(platformGroup)) {

                    List<IotRdDailyReportDetailRespVO> sharedDetails = platformGroupDetailsMap.get(platformGroup);
                    if (CollUtil.isNotEmpty(sharedDetails)) {
                        reportDetailsPair.put(reportId, sharedDetails);
                    }
                }
            }

            if (CollUtil.isNotEmpty(tasks)) {
                tasks.forEach(task -> {
                    Set<Long> personIds = task.getResponsiblePerson();
                    Set<Long> submitterIds = task.getSubmitter();
                    // 施工队伍id集合
                    Set<Long> deptIds = task.getDeptIds();
                    currentPageDeptIds.addAll(Optional.ofNullable(deptIds).orElse(Collections.emptySet()));
                    taskPair.put(task.getId(), task.getWellName());
                    taskLocationPair.put(task.getId(), task.getLocation());
                    userIds.addAll(Optional.ofNullable(personIds).orElse(Collections.emptySet()));
                    userIds.addAll(Optional.ofNullable(submitterIds).orElse(Collections.emptySet()));
                    // 获取所有任务的工作量数据
                    List<IotTaskAttrModelProperty> extProperties = task.getExtProperty();
                    taskWorkloadPair.put(task.getId(), extProperties);
                    // 找到已经施工完成的主井任务 查询对应的关联井任务 用关联井号作为日报任务井号
                    if (1 == task.getPlatformWell() && "wg".equals(task.getStatus())) {
                        finishedPlatformGroups.add(task.getPlatformGroup());
                        finishedMainPlatformIds.add(task.getId());
                    }
                    // 收集施工完成的任务id集合
                    if ("wg".equals(task.getStatus())) {
                        finishedTaskIds.add(task.getId());
                    }
                });
                // 查询 finishedPlatformGroups 相关的未施工完成的关联井任务井
                if (CollUtil.isNotEmpty(finishedPlatformGroups)) {
                    IotProjectTaskPageReqVO unfinishedTaskReqVO = new IotProjectTaskPageReqVO();
                    unfinishedTaskReqVO.setPlatformGroups(new ArrayList<>(finishedPlatformGroups));
                    unfinishedTaskReqVO.setPlatformWell(2);
                    // unfinishedTaskReqVO.setJobFlag("Y");
                    List<IotProjectTaskDO> unfinishedRelatedTasks = iotProjectTaskService.projectTasks(unfinishedTaskReqVO);
                    if (CollUtil.isNotEmpty(unfinishedRelatedTasks)) {
                        unfinishedRelatedTasks.forEach(task -> {
                            // relatedPlatformPair.put(task.getPlatformGroup(), task.getWellName());
                            relatedPlatformsPair.put(task.getId(), task.getWellName());
                        });
                    }
                }
            }

            // 平台井 主井施工完成 需要显示 关联井的施工状态 井号
            if (CollUtil.isNotEmpty(relatedWellReports)) {
                Map<String, IotRdDailyReportDO> relatedPlatformGroupPair = new HashMap<>();
                relatedWellReports.forEach(report -> {
                    if (2 == report.getPlatformWell()) {
                        // 找到当前页所有的关联井 如果有多个关联井 取排列在最前面的关联井
                        if (!relatedPlatformGroupPair.containsKey(report.getPlatformGroup())) {
                            relatedPlatformGroupPair.put(report.getPlatformGroup(), report);
                        }
                        // 查询关联井的 非生产时间填写情况 只要有1个关联井填写了 非生产时间 就显示为 已填写
                        IotRdDailyReportRespVO reportRespVO = BeanUtils.toBean(report, IotRdDailyReportRespVO.class);
                        Boolean flag = setNoProductFlag(reportRespVO);
                        if (flag) {
                            reportNonProductFlagPair.put(report.getPlatformGroup(), true);
                        }
                        // 设置平台井 的非生产时效 所有 井数据 累加平均
                        if (CollUtil.isNotEmpty(report.getExtProperty()) || StrUtil.isNotBlank(report.getRdStatus())) {
                            // 说明当前日报设置过 工作量 施工状态
                            IotRdDailyReportRespVO rdDailyReportResp = BeanUtils.toBean(report, IotRdDailyReportRespVO.class);
                            BigDecimal nonProductTime = calculateNonProductTime(rdDailyReportResp);
                            if (platformNonProductPair.containsKey(report.getPlatformGroup())) {
                                List<BigDecimal> tempSumNpts = platformNonProductPair.get(report.getPlatformGroup());
                                tempSumNpts.add(nonProductTime);
                                platformNonProductPair.put(report.getPlatformGroup(), tempSumNpts);
                            } else {
                                List<BigDecimal> tempSumNpts = new ArrayList<>();
                                tempSumNpts.add(nonProductTime);
                                platformNonProductPair.put(report.getPlatformGroup(), tempSumNpts);
                            }
                        }
                    }
                });
                relatedWellReports.forEach(report -> {
                    // 找到施工状态为空的主井
                    if (1 == report.getPlatformWell() && StrUtil.isBlank(report.getRdStatus())
                            && finishedMainPlatformIds.contains(report.getTaskId())) {
                        nullStatusPlatformIds.add(report.getTaskId());
                        // 找到当前主井对应的关联井
                        if (relatedPlatformGroupPair.containsKey(report.getPlatformGroup())) {
                            IotRdDailyReportDO tempReport = relatedPlatformGroupPair.get(report.getPlatformGroup());
                            tempReport.getRdStatus();
                            tempReport.getTaskId();
                            if (relatedPlatformsPair.containsKey(tempReport.getTaskId())) {
                                String wellName = relatedPlatformsPair.get(tempReport.getTaskId());
                                relatedPlatformPair.put(tempReport.getPlatformGroup(), wellName);
                                relatedWellStatusPair.put(tempReport.getPlatformGroup(), tempReport.getRdStatus());
                            }
                        }
                    }

                });
            }

            // 添加临时创建的日报相关的 带班干部 创建人 id
            reports.forEach(report -> {
                if (CollUtil.isNotEmpty(report.getResponsiblePerson())) {
                    userIds.addAll(report.getResponsiblePerson());
                }
                if (StrUtil.isNotBlank(report.getCreator())) {
                    userIds.add(Long.valueOf(report.getCreator()));
                }
                // 查询所有设备信息 设备名称 设备编码
                if (CollUtil.isNotEmpty(deviceIds)) {
                    Map<Long, IotDeviceRespVO> deviceMap = iotDeviceService.getDeviceMap(new ArrayList<>(deviceIds));
                    deviceMap.forEach((deviceId, device) -> {
                        deviceNamesPair.put(String.valueOf(deviceId), StrUtil.join("-", device.getDeviceCode(), device.getDeviceName()));
                    });
                }

            });

            // 查询当前页所有日报关联的任务的施工队伍名称
            Map<Long, DeptDO> deptMap = deptService.getDeptMap(currentPageDeptIds);
            // 查询所有 带班干部 填报人 的姓名
            Map<Long, AdminUserRespDTO> userMap;
            if (CollUtil.isNotEmpty(userIds)) {
                userMap = adminUserApi.getUserMap(userIds);
            } else {
                userMap = Collections.emptyMap();
            }
            if (CollUtil.isNotEmpty(tasks)) {
                tasks.forEach(task -> {
                    // 安全获取施工队伍ID集合（避免null）
                    Set<Long> deptIds = Optional.ofNullable(task.getDeptIds())
                            .orElse(Collections.emptySet());
                    // 转换ID集合为队伍名称字符串（用逗号分隔）
                    String deptNames = deptIds.stream()
                            // 映射ID到队伍名称（队伍不存在时用空字符串）
                            .map(deptId -> Optional.ofNullable(deptMap.get(deptId))
                                    .map(DeptDO::getName)
                                    .orElse(""))
                            // 过滤空字符串（避免多余逗号）
                            .filter(name -> !name.isEmpty())
                            // 拼接部门名称
                            .collect(Collectors.joining(","));
                    // 存入映射关系
                    taskTeamsPair.put(task.getId(), deptNames);
                    // 安全获取带班干部ID集合（避免null）
                    Set<Long> responsibleIds = Optional.ofNullable(task.getResponsiblePerson())
                            .orElse(Collections.emptySet());
                    // 转换ID集合为姓名字符串（用逗号分隔）
                    String responsibleNames = responsibleIds.stream()
                            // 映射ID到姓名（用户不存在时用空字符串）
                            .map(userId -> Optional.ofNullable(userMap.get(userId))
                                    .map(AdminUserRespDTO::getNickname)
                                    .orElse(""))
                            // 过滤空字符串（避免多余逗号）
                            .filter(name -> !name.isEmpty())
                            // 拼接姓名
                            .collect(Collectors.joining(","));
                    // 存入映射关系
                    taskResponsiblePair.put(task.getId(), responsibleNames);
                    // 工单填报人
                    Set<Long> submitterIds = Optional.ofNullable(task.getSubmitter())
                            .orElse(Collections.emptySet());
                    // 转换ID集合为姓名字符串（用逗号分隔）
                    String submitterNames = submitterIds.stream()
                            // 映射ID到姓名（用户不存在时用空字符串）
                            .map(userId -> Optional.ofNullable(userMap.get(userId))
                                    .map(AdminUserRespDTO::getNickname)
                                    .orElse(""))
                            // 过滤空字符串（避免多余逗号）
                            .filter(name -> !name.isEmpty())
                            // 拼接姓名
                            .collect(Collectors.joining(","));
                    // 存入映射关系
                    taskSubmitterPair.put(task.getId(), submitterNames);
                });
            } else {
                // 临时新建的日报 没有关联项目 任务
            }
            // 统计计算出平台井中每个井的 非生产时效
            if (CollUtil.isNotEmpty(platformNonProductPair)) {
                platformNonProductPair.forEach((platformGroup, npts) -> {
                    // npts是各平台井的非生产时间累计和集合
                    // 1. 计算分子：集合中所有BigDecimal元素的总和
                    BigDecimal numerator = npts.stream()
                            .reduce(BigDecimal.ZERO, BigDecimal::add);
                    int denominatorInt = npts.size() * 24;
                    BigDecimal denominator = BigDecimal.valueOf(denominatorInt);
                    BigDecimal nonProductionRate;
                    if (denominator.compareTo(BigDecimal.ZERO) == 0) {
                        nonProductionRate = BigDecimal.ZERO; // 分母为0时比率设为0
                    } else {
                        // 除法：指定精度（保留4位小数）和舍入模式（四舍五入），可根据业务调整
                        nonProductionRate = numerator.divide(denominator, 4, RoundingMode.HALF_UP);
                    }
                    platformNptPair.put(platformGroup, nonProductionRate);
                } );
            }
            // 查询所有任务的工作量数据 单位相同的工作量属性值合并处理
            for (IotRdDailyReportDO report : reports) {
                // 设置每个日报关联的 设备信息集合
                Set<Long> thisDeviceIds = report.getDeviceIds();
                String thisDeviceCodeNames = Optional.ofNullable(thisDeviceIds)
                        .filter(CollUtil::isNotEmpty)
                        .map(devIds -> devIds.stream()
                                .map(String::valueOf)  // 将 Long 转为 String
                                .map(deviceNamesPair::get)  // 从字典获取名称
                                .filter(Objects::nonNull)  // 过滤空值
                                .filter(StrUtil::isNotBlank)  // 过滤空白值
                                .collect(Collectors.joining(",")))  // 用逗号连接
                        .orElse("");  // 如果为空，返回空字符串
                reportDeviceNamesPair.put(report.getId(), thisDeviceCodeNames);

                // 处理临时创建的日报 带班干部 填报人 有单独的逻辑规则
                Set<Long> personIds = report.getResponsiblePerson();
                if (CollUtil.isNotEmpty(personIds)) {
                    // tempRespPersonIds.addAll(personIds);
                    // 转换ID集合为姓名字符串（用逗号分隔）
                    String respNames = personIds.stream()
                            // 映射ID到姓名（用户不存在时用空字符串）
                            .map(userId -> Optional.ofNullable(userMap.get(userId))
                                    .map(AdminUserRespDTO::getNickname)
                                    .orElse(""))
                            // 过滤空字符串（避免多余逗号）
                            .filter(name -> !name.isEmpty())
                            // 拼接姓名
                            .collect(Collectors.joining(","));
                    tempReportResponsiblePair.put(report.getId(), respNames);
                }
                String creator = report.getCreator();
                if (StrUtil.isNotBlank(creator)) {
                    Long creatorId = Long.valueOf(creator);
                    Set<Long> creatorIds = new HashSet<>();
                    creatorIds.add(creatorId);
                    String creatorNames = creatorIds.stream()
                            // 映射ID到姓名（用户不存在时用空字符串）
                            .map(userId -> Optional.ofNullable(userMap.get(userId))
                                    .map(AdminUserRespDTO::getNickname)
                                    .orElse(""))
                            // 过滤空字符串（避免多余逗号）
                            .filter(name -> !name.isEmpty())
                            // 拼接姓名
                            .collect(Collectors.joining(","));
                    tempSubmitterPair.put(report.getId(), creatorNames);
                }
                // 设置每个任务的工作量数据  单位相同的工作量值作合并处理
                List<IotTaskAttrModelProperty> taskAttrs = report.getExtProperty();
                // 这里暂时使用枚举 统计每个单位下的 工作量
                // 桥塞(个数)      钻可溶桥塞  钻复合桥塞           bridge_plug
                // 趟数           通刮洗 冲砂                    run_count
                // 井数           累计施工-井                    cumulative_working_well
                // 小时H                                       hour_count
                // 天数D
                // 水方量(方)                                   water_volume
                // 台次           当日泵车台次 当日仪表/混砂        daily_tools_sand   daily_pump_trips
                // 段数           累计施工-层                    cumulative_working_layers
                // 暂存不同单位的工作量属性值
                BigDecimal tempTotalBridgePlug = BigDecimal.ZERO;
                BigDecimal tempTotalRunCount = BigDecimal.ZERO;
                BigDecimal tempTotalCumulativeWorkingWell = BigDecimal.ZERO;
                BigDecimal tempTotalHourCount = BigDecimal.ZERO;
                BigDecimal tempTotalWaterVolume = BigDecimal.ZERO;
                BigDecimal tempTotalPumpTrips = BigDecimal.ZERO;
                BigDecimal tempTotalCumulativeWorkingLayers = BigDecimal.ZERO;
                BigDecimal tempTotalMixSand = BigDecimal.ZERO;
                if (CollUtil.isNotEmpty(taskAttrs)) {
                    for (IotTaskAttrModelProperty attr : taskAttrs) {
                        String unit = attr.getUnit();   // 工作量单位
                        String actualValueStr = attr.getActualValue();  // 工作量属性的实际值
                        // 处理实际值：避免null或非数字字符串导致的异常
                        BigDecimal actualValue = BigDecimal.ZERO;
                        if (StrUtil.isNotBlank(actualValueStr)) {  // 假设使用Hutool的StrUtil，或自行判断null/空
                            try {
                                actualValue = new BigDecimal(actualValueStr);
                            } catch (NumberFormatException e) {
                                // 若字符串格式错误，默认按0处理（可根据业务调整）
                                actualValue = BigDecimal.ZERO;
                            }
                        }
                        if ("个数".equals(unit)) {
                            // 钻可溶桥塞  钻复合桥塞
                            tempTotalBridgePlug = tempTotalBridgePlug.add(actualValue);
                        }
                        if ("趟数".equals(unit)) {
                            tempTotalRunCount = tempTotalRunCount.add(actualValue);
                        }
                        if ("小时".equals(unit)) {
                            tempTotalHourCount = tempTotalHourCount.add(actualValue);
                        }
                        if ("天数".equals(unit)) {
                            // 将 actualValue 换算成 H
                            BigDecimal hours = actualValue.multiply(new BigDecimal("24"));
                            tempTotalHourCount = tempTotalHourCount.add(hours);
                        }
                        if ("方".equals(unit)) {
                            tempTotalWaterVolume = tempTotalWaterVolume.add(actualValue);
                        }
                        if ("井数".equals(unit)) {
                            tempTotalCumulativeWorkingWell = tempTotalCumulativeWorkingWell.add(actualValue);
                        }
                        if ("段数".equals(unit)) {
                            tempTotalCumulativeWorkingLayers = tempTotalCumulativeWorkingLayers.add(actualValue);
                        }
                        if ("台次".equals(unit) && "当日泵车台次".equals(attr.getName())) {
                            tempTotalPumpTrips = tempTotalPumpTrips.add(actualValue);
                        }
                        if ("台次".equals(unit) && ("当日仪表/混砂".equals(attr.getName()) || "当日仪表".equals(attr.getName()) || "当日混砂".equals(attr.getName()))) {
                            tempTotalMixSand = tempTotalMixSand.add(actualValue);
                        }
                    }
                    // 关联的任务完工 井数 +1
                    if (finishedTaskIds.contains(report.getTaskId())) {
                        report.setCumulativeWorkingWell(new BigDecimal(1));
                    }
                    report.setCumulativeWorkingLayers(tempTotalCumulativeWorkingLayers);
                    report.setDailyPumpTrips(tempTotalPumpTrips);
                    report.setDailyToolsSand(tempTotalMixSand);
                    report.setRunCount(tempTotalRunCount);
                    report.setBridgePlug(tempTotalBridgePlug);
                    report.setWaterVolume(tempTotalWaterVolume);
                    report.setHourCount(tempTotalHourCount);
                }
            }
            // 查询所有队伍对应的上级部门 sort
            Set<Long> parentDeptIds = new HashSet<>();
            if (CollUtil.isNotEmpty(tempDeptMap)) {
                tempDeptMap.forEach((deptId, dept) -> {
                    parentDeptIds.add(dept.getParentId());
                    projectIdPair.put(deptId, dept.getParentId());
                });
                // 查询所有上级项目部信息
                Map<Long, DeptDO> projectDeptMap = deptService.getDeptMap(parentDeptIds);
                if (CollUtil.isNotEmpty(projectDeptMap)) {
                    projectDeptMap.forEach((deptId, dept) -> {
                        projectSortPair.put(deptId, dept.getSort());
                        projectNamePair.put(deptId, dept.getName());
                    });
                }
            }
        });
        return BeanUtils.toBean(reports, IotRdDailyReportRespVO.class, (reportVO) -> {
            // 施工状态 导出使用
            if (StrUtil.isNotBlank(reportVO.getRdStatus())) {
                if (constructStatusPair.containsKey(reportVO.getRdStatus())) {
                    reportVO.setRdStatusLabel(constructStatusPair.get(reportVO.getRdStatus()));
                }
            }
            // 计算非生产时效 如果是平台井 需要计算 所有平台井 的 非生产时效
            BigDecimal nonProductionTimes = calculateNonProductTime(reportVO);
            reportVO.setNonProductionRate(nonProductionTimes.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);
            }

            // 设置非生产时间填写标识 noProductFlag 为 true 或者 processInstanceId 为 2 的时候 显示 已填写
            reportVO.setNonProductFlag(setNoProductFlag(reportVO));
            // 创建时间 格式化 yyyy-MM-dd
            if (ObjUtil.isNotEmpty(reportVO.getCreateTime())) {
                reportVO.setCreateTimeStr(LocalDateTimeUtil.format(reportVO.getCreateTime(), DatePattern.NORM_DATE_PATTERN));
            }

            // 日报 关联的施工工艺名称集合
            findAndThen(techniqueNamesPair, reportVO.getId(), techniqueNames -> reportVO.setTechniqueNames(techniqueNames));
            // 日报 关联的设备名称集合
            findAndThen(reportDeviceNamesPair, reportVO.getId(), deviceNames -> reportVO.setDeviceNames(deviceNames));
            // 日报 所属 上级项目部
            findAndThen(projectIdPair, reportVO.getDeptId(), projectId -> reportVO.setProjectDeptId(projectId));
            // 生产动态明细
            findAndThen(reportDetailsPair, reportVO.getId(), details -> reportVO.setReportDetails(details));
            // 平台井 非生产时效
            findAndThen(platformNptPair, reportVO.getPlatformGroup(), npt -> reportVO.setNonProductionRate(npt));
            // 部门信息 任务中关联的施工队伍
            findAndThen(taskTeamsPair, reportVO.getTaskId(), deptNames -> reportVO.setDeptName(deptNames));
            // 临时新建的日报的 施工队伍
            findAndThen(tempDeptMap, reportVO.getDeptId(), dept -> reportVO.setDeptName(dept.getName()));
            // 所有施工队伍的排序值
            findAndThen(tempDeptMap, reportVO.getDeptId(), dept -> reportVO.setTeamSort(dept.getSort()));
            // 所有施工队伍所属项目部的名称
            findAndThen(projectNamePair, reportVO.getProjectDeptId(), name -> reportVO.setProjectName(name));
            // 所有施工队伍所属项目部的排序值
            findAndThen(projectSortPair, reportVO.getProjectDeptId(), sort -> reportVO.setProjectSort(sort));
            // 日报关联的项目信息
            findAndThen(projectPair, reportVO.getProjectId(), contractName -> reportVO.setContractName(contractName));
            // 日报关联的任务井号
            findAndThen(taskPair, reportVO.getTaskId(), taskName -> reportVO.setTaskName(taskName));
            // 日报关联的任务施工区域
            findAndThen(taskLocationPair, reportVO.getTaskId(), location -> reportVO.setLocation(location));
            // 日报关联的任务信息（兼容主井完工 关联井未完工的情况）
            findAndThen(relatedPlatformPair, reportVO.getPlatformGroup(), relatedTaskName -> reportVO.setTaskName(relatedTaskName));
            // 平台井相关的非生产时间标识
            findAndThen(reportNonProductFlagPair, reportVO.getPlatformGroup(), nonProductFlag -> reportVO.setNonProductFlag(nonProductFlag));
            // 日报关联的任务施工状态（兼容主井完工 关联井未完工的情况）
            findAndThen(relatedWellStatusPair, reportVO.getPlatformGroup(), rdStatus -> reportVO.setRdStatus(rdStatus));
            // 日报关联的责任人
            findAndThen(taskResponsiblePair, reportVO.getTaskId(), responsibleNames -> reportVO.setResponsiblePersonNames(responsibleNames));
            // 临时新增日报关联的带班干部
            findAndThen(tempReportResponsiblePair, reportVO.getId(), responsibleNames -> reportVO.setResponsiblePersonNames(responsibleNames));
            // 日报关联的填报人
            findAndThen(taskSubmitterPair, reportVO.getTaskId(), submitterNames -> reportVO.setSubmitterNames(submitterNames));
            // 临时新建的日报关联的填报人
            findAndThen(tempSubmitterPair, reportVO.getId(), submitterNames -> reportVO.setSubmitterNames(submitterNames));
            if (ObjUtil.isEmpty(reportVO.getProjectId()) && ObjUtil.isEmpty(reportVO.getTaskId())) {
                reportVO.setContractName("无工作量");
                reportVO.setTaskName("无工作量");
            }
        });
    }

    /**
     *  检测是否已经维护了生产时效
     * @param dailyReport
     * @return
     */
    private Boolean setNoProductFlag(IotRdDailyReportRespVO dailyReport){
        BigDecimal accidentTime = dailyReport.getAccidentTime();
        BigDecimal repairTime = dailyReport.getRepairTime();
        BigDecimal selfStopTime = dailyReport.getSelfStopTime();
        BigDecimal complexityTime = dailyReport.getComplexityTime();
        BigDecimal relocationTime = dailyReport.getRelocationTime();
        BigDecimal rectificationTime = dailyReport.getRectificationTime();
        BigDecimal waitingStopTime = dailyReport.getWaitingStopTime();
        BigDecimal winterBreakTime = dailyReport.getWinterBreakTime();
        BigDecimal partyaDesignTime = dailyReport.getPartyaDesign();
        BigDecimal partyaPrepareTime = dailyReport.getPartyaPrepare();
        BigDecimal partyaResourceTime = dailyReport.getPartyaResource();
        BigDecimal otherNptTime = dailyReport.getOtherNptTime();
        if (accidentTime.compareTo(BigDecimal.ZERO) > 0 || repairTime.compareTo(BigDecimal.ZERO) > 0 || selfStopTime.compareTo(BigDecimal.ZERO) > 0
                || complexityTime.compareTo(BigDecimal.ZERO) > 0 || relocationTime.compareTo(BigDecimal.ZERO) > 0 || rectificationTime.compareTo(BigDecimal.ZERO) > 0
                || waitingStopTime.compareTo(BigDecimal.ZERO) > 0 || winterBreakTime.compareTo(BigDecimal.ZERO) > 0 || partyaDesignTime.compareTo(BigDecimal.ZERO) > 0
                || partyaPrepareTime.compareTo(BigDecimal.ZERO) > 0 || partyaResourceTime.compareTo(BigDecimal.ZERO) > 0 || otherNptTime.compareTo(BigDecimal.ZERO) > 0) {
            // 设置非生产时间填写标识
            return true;
        }
        return false;
    }

    /**
     *  计算非生产时间累加值 计算非生产时效
     *  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(IotRdDailyReportRespVO 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);
    }

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

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

    @GetMapping("/export-excel")
    @Operation(summary = "导出瑞都日报汇总 Excel")
    @PreAuthorize("@ss.hasPermission('pms:iot-rd-daily-report:export')")
    @ApiAccessLog(operateType = EXPORT)
    public void exportIotRdDailyReportExcel(@Valid IotRdDailyReportPageReqVO 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<IotRdDailyReportStatisticsRespVO> result = iotRdDailyReportService.statistics(pageReqVO);
        // 提取出所有工作量数据
        if (CollUtil.isNotEmpty(result)) {
            // key施工状态数据字典value   value施工状态数据字典label
            Map<String, String> constructStatusPair = new HashMap<>();
            // 施工状态 字典数据
            List<DictDataDO> rdStatusData = dictDataService.getDictDataListByDictType("rdStatus");
            if (CollUtil.isNotEmpty(rdStatusData)) {
                rdStatusData.forEach(data -> {
                    constructStatusPair.put(data.getValue(), data.getLabel());
                });
            }

            result.forEach(well -> {
                // 施工状态
                if (constructStatusPair.containsKey(well.getRdStatus())) {
                    well.setRdStatusLabel(constructStatusPair.get(well.getRdStatus()));
                }
                // 统计了井信息
                List<IotRdDailyReportStatisticsItemVO> items = well.getItems();
                if (CollUtil.isNotEmpty(items)) {
                    items.forEach(item -> {
                        // 设置每个工作量的值
                        if ("个数".equals(item.getUnit())) {
                            well.setCumulativeBridgePlug(item.getWorkload());
                        }
                        if ("趟数".equals(item.getUnit())) {
                            well.setCumulativeRunCount(item.getWorkload());
                        }
                        if ("小时".equals(item.getUnit())) {
                            well.setCumulativeHourCount(item.getWorkload());
                        }
                        if ("方".equals(item.getUnit())) {
                            well.setCumulativeWaterVolume(item.getWorkload());
                        }
                        if ("井数".equals(item.getUnit())) {
                            well.setCumulativeWorkingWell(item.getWorkload());
                        }
                        if ("段数".equals(item.getUnit())) {
                            well.setCumulativeWorkingLayers(item.getWorkload());
                        }
                        if ("台次".equals(item.getUnit())) {
                            well.setTaici(item.getWorkload());
                        }
                    });
                }
            });
        }
        // 导出 Excel
        ExcelUtils.write(response, "瑞都日报汇总.xls", "日报汇总", IotRdDailyReportStatisticsRespVO.class,
                result);
    }

    @GetMapping("/exportStatistics")
    @Operation(summary = "导出瑞都日报工作量汇总 Excel")
    @PreAuthorize("@ss.hasPermission('pms:iot-rd-daily-report:export')")
    @ApiAccessLog(operateType = EXPORT)
    public void exportStatistics(@Valid IotRdDailyReportPageReqVO 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<IotRdDailyReportStatisticsRespVO> statistics = iotRdDailyReportService.summaryStatistics(pageReqVO);
        // 修改油耗单位 为 万升
        if (CollUtil.isNotEmpty(statistics)) {
            statistics.forEach(stat -> {
                BigDecimal totalDailyFuel = stat.getTotalDailyFuel();
                BigDecimal fuelWan = totalDailyFuel
                        .divide(BigDecimal.valueOf(10000), 2, RoundingMode.HALF_UP);
                stat.setTotalDailyFuel(fuelWan);
            });
        }
        // 导出 Excel
        ExcelUtils.write(response, "瑞都日报汇总.xls", "日报汇总数据",
                IotRdDailyReportStatisticsRespExportVO.class, BeanUtils.toBean(statistics, IotRdDailyReportStatisticsRespExportVO.class));
    }

    @GetMapping("/export-detail")
    @Operation(summary = "导出瑞都日报明细 Excel")
    @PreAuthorize("@ss.hasPermission('pms:iot-rd-daily-report:export')")
    @ApiAccessLog(operateType = EXPORT)
    public void exportIotRdDailyReportExcelDetail(@Valid IotRdDailyReportPageReqVO 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<IotRdDailyReportDO> result = iotRdDailyReportService.getIotRdDailyReportPage(pageReqVO).getList();
        // 导出 Excel
        ExcelUtils.write(response, "瑞都日报明细.xls", "日报明细", IotRdDailyReportRespVO.class,
                buildDailyReportList(result));
    }

    @GetMapping("/exportSingleWells")
    @Operation(summary = "导出瑞都日报 单井 统计 Excel")
    @PreAuthorize("@ss.hasPermission('pms:iot-rd-daily-report:export')")
    @ApiAccessLog(operateType = EXPORT)
    public void exportSingleWells(@Valid IotRdDailyReportPageReqVO 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<IotRdDailyReportDO> result = iotRdDailyReportService.teamReports(pageReqVO).getList();
        // 导出 Excel
        ExcelUtils.write(response, "瑞都日报单井统计.xls", "瑞都日报单井统计", IotRdDailyReportRespVO.class,
                buildSubtotalRdDailyReports(result, pageReqVO));
    }

    @GetMapping("/exportSingleTeams")
    @Operation(summary = "导出瑞都日报 单队伍 统计 Excel")
    @PreAuthorize("@ss.hasPermission('pms:iot-rd-daily-report:export')")
    @ApiAccessLog(operateType = EXPORT)
    public void exportSingleTeams(@Valid IotRdDailyReportPageReqVO 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<IotRdDailyReportDO> result = iotRdDailyReportService.wellReports(pageReqVO).getList();
        // 导出 Excel
        ExcelUtils.write(response, "瑞都日报单队伍统计.xls", "瑞都日报单队伍统计", IotRdDailyReportRespVO.class,
                buildWellRdDailyReports(result, pageReqVO));
    }

}