Răsfoiți Sursa

pms 瑞都 日报 单井 队伍 统计

zhangcl 5 zile în urmă
părinte
comite
0eca323c16

+ 1158 - 0
yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/iotrddailyreport/IotRdDailyReportController.java

@@ -12,6 +12,7 @@ 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;
@@ -34,6 +35,7 @@ import cn.iocoder.yudao.module.pms.dal.dataobject.iotprojecttaskattrs.IotTaskAtt
 import cn.iocoder.yudao.module.pms.dal.dataobject.iotrddailyreport.IotRdDailyReportDO;
 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.enums.AttachmentCategoryEnum;
 import cn.iocoder.yudao.module.pms.enums.AttachmentTypeEnum;
 import cn.iocoder.yudao.module.pms.job.IotDeviceCarFuelVO;
@@ -76,6 +78,7 @@ import java.util.stream.Collectors;
 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 = "管理后台 - 瑞都日报")
@@ -119,6 +122,8 @@ public class IotRdDailyReportController {
     private IotDailyReportFuelService iotDailyReportFuelService;
     @Resource
     private IotAttachmentMapper iotAttachmentMapper;
+    @Resource
+    private IotRdDailyReportMapper iotRdDailyReportMapper;
 
     @PostMapping("/create")
     @Operation(summary = "创建瑞都日报")
@@ -810,6 +815,1159 @@ public class IotRdDailyReportController {
         return success(result);
     }
 
+    @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<>();
+
+        // 查询 当前分页 所有部门 任务井 日报数据 小计工作量
+        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);
+                            }
+                        }
+                        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, tempTotalMixSand.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));
+                    }
+                });
+            }
+        });
+
+        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);
+
+            // 按照日报创建时间倒序排列
+            if (CollUtil.isNotEmpty(relatedWellReports)) {
+                relatedWellReports = relatedWellReports.stream()
+                        .sorted(Comparator.comparing(IotRdDailyReportDO::getCreateTime).reversed())
+                        .collect(Collectors.toList());
+            }
+
+            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 ("段数".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) -> {
+            // 部门信息 任务中关联的施工队伍
+            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<>();
+
+        // 查询 当前分页 所有部门 任务井 日报数据 小计工作量
+        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);
+                            }
+                        }
+                        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, tempTotalMixSand.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));
+                    }
+                });
+            }
+        });
+
+        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);
+
+            // 按照日报创建时间倒序排列
+            if (CollUtil.isNotEmpty(relatedWellReports)) {
+                relatedWellReports = relatedWellReports.stream()
+                        .sorted(Comparator.comparing(IotRdDailyReportDO::getCreateTime).reversed())
+                        .collect(Collectors.toList());
+            }
+
+            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 ("段数".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) -> {
+            // 部门信息 任务中关联的施工队伍
+            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));
+        });
+    }
+
+
     @GetMapping("/polylineStatistics")
     @Operation(summary = "瑞都日报 统计")
     @PreAuthorize("@ss.hasPermission('pms:iot-rd-daily-report:query')")

+ 23 - 0
yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/iotrddailyreport/vo/IotRdDailyReportRespVO.java

@@ -318,4 +318,27 @@ public class IotRdDailyReportRespVO {
 
     @Schema(description = "任务施工进度", example = "施工准备2025-12-01 -> 施工2025-12-02")
     private List<IotRdDailyReportTaskProgressVO> taskProgresses;
+
+    @Schema(description = "小组内累计 桥塞(个数)")
+    private BigDecimal groupIdBridgePlug;
+    @Schema(description = "小组内累计 趟数")
+    private BigDecimal groupIdRunCount;
+    @Schema(description = "小组内累计 井数")
+    private BigDecimal groupIdCumulativeWorkingWell;
+    @Schema(description = "小组内累计 小时H")
+    private BigDecimal groupIdHourCount;
+
+    @Schema(description = "小组内累计 油耗")
+    private BigDecimal groupIdFuel;
+    @Schema(description = "小组内累计 水方量(方)")
+    private BigDecimal groupIdWaterVolume;
+    @Schema(description = "小组内累计 泵车台次")
+    private BigDecimal groupIdPumpTrips;
+    @Schema(description = "小组内累计 段数  累计施工-层")
+    private BigDecimal groupIdCumulativeWorkingLayers;
+    @Schema(description = "小组内累计 台次 当日仪表/混砂")
+    private BigDecimal groupIdMixSand;
+
+    @Schema(description = "小组内最后1条记录标识 true false")
+    private boolean lastGroupIdFlag = false;
 }

+ 16 - 1
yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/stat/IotRepairController.java

@@ -4,10 +4,13 @@ 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.security.core.util.SecurityFrameworkUtils;
+import cn.iocoder.yudao.module.pms.controller.admin.iotmainworkorder.vo.IotMainWorkOrderPageReqVO;
 import cn.iocoder.yudao.module.pms.controller.admin.maintain.vo.IotMaintainPageReqVO;
 import cn.iocoder.yudao.module.pms.controller.admin.stat.vo.ReportCost;
+import cn.iocoder.yudao.module.pms.dal.dataobject.iotmainworkorder.IotMainWorkOrderDO;
 import cn.iocoder.yudao.module.pms.dal.dataobject.maintain.IotMaintainDO;
 import cn.iocoder.yudao.module.pms.dal.mysql.maintain.IotMaintainMapper;
+import cn.iocoder.yudao.module.pms.service.iotmainworkorder.IotMainWorkOrderService;
 import cn.iocoder.yudao.module.pms.service.maintain.IotMaintainService;
 import cn.iocoder.yudao.module.system.service.dept.DeptService;
 import com.google.common.collect.ImmutableMap;
@@ -21,6 +24,7 @@ import org.springframework.web.bind.annotation.RestController;
 import javax.annotation.security.PermitAll;
 import javax.validation.Valid;
 import java.math.BigDecimal;
+import java.util.List;
 import java.util.Objects;
 import java.util.Set;
 
@@ -38,6 +42,7 @@ public class IotRepairController {
     private final DeptUtil deptUtil;
     private final DeptService deptService;
     private final IotMaintainService iotMaintainService;
+    private final IotMainWorkOrderService iotMainWorkOrderService;
 
     @GetMapping("/fee")
     public CommonResult<ImmutableMap<String, BigDecimal>> getRepairFee(@Valid IotMaintainPageReqVO pageReqVO) {
@@ -52,6 +57,12 @@ public class IotRepairController {
         }
         pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE);
         PageResult<IotMaintainDO> iotMaintainDOPageResult = iotMaintainMapper.selectPage(pageReqVO, ids);
+        // 查询保养费用
+        IotMainWorkOrderPageReqVO workOrderReqVO = new IotMainWorkOrderPageReqVO();
+        workOrderReqVO.setDeptIds(ids);
+        workOrderReqVO.setCreateTime(pageReqVO.getCreateTime());
+        List<IotMainWorkOrderDO> workOrders = iotMainWorkOrderService.workOrders(workOrderReqVO);
+
         BigDecimal totalFee = iotMaintainDOPageResult.getList().stream()
                 .map(IotMaintainDO::getMaintainFee)
                 .map(fee -> Objects.isNull(fee) ? BigDecimal.ZERO : fee)
@@ -60,7 +71,11 @@ public class IotRepairController {
                 .map(IotMaintainDO::getMaintainFee)
                 .map(fee -> Objects.isNull(fee) ? BigDecimal.ZERO : fee)
                 .reduce(BigDecimal.ZERO, BigDecimal::add);
-        return CommonResult.success(ImmutableMap.of("repair", totalFee, "out", outFee));
+        BigDecimal byFee = workOrders.stream()
+                .map(IotMainWorkOrderDO::getCost)
+                .map(fee -> Objects.isNull(fee) ? BigDecimal.ZERO : fee)
+                .reduce(BigDecimal.ZERO, BigDecimal::add);
+        return CommonResult.success(ImmutableMap.of("repair", totalFee, "out", outFee, "byFee", byFee));
     }
 
 

+ 48 - 0
yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/dal/mysql/iotrddailyreport/IotRdDailyReportMapper.java

@@ -3,12 +3,15 @@ package cn.iocoder.yudao.module.pms.dal.mysql.iotrddailyreport;
 import cn.iocoder.yudao.framework.common.pojo.PageResult;
 import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
 import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
+import cn.iocoder.yudao.framework.tenant.core.aop.TenantIgnore;
 import cn.iocoder.yudao.module.pms.controller.admin.iotrddailyreport.vo.IotRdDailyReportPageReqVO;
 import cn.iocoder.yudao.module.pms.controller.admin.iotrddailyreport.vo.IotRdDailyReportTaskPeriodVO;
 import cn.iocoder.yudao.module.pms.dal.dataobject.iotrddailyreport.IotRdDailyReportDO;
+import com.baomidou.mybatisplus.core.metadata.IPage;
 import org.apache.ibatis.annotations.Mapper;
 import org.apache.ibatis.annotations.Param;
 
+import java.util.Collection;
 import java.util.List;
 
 /**
@@ -181,4 +184,49 @@ public interface IotRdDailyReportMapper extends BaseMapperX<IotRdDailyReportDO>
      */
     List<IotRdDailyReportTaskPeriodVO> taskConstructionPeriod();
 
+    /**
+     * 根据 井号 查询 瑞都日报 按照队伍分组 小计
+     * @param page
+     * @param reqVO
+     * @param projectIds
+     * @return
+     */
+    IPage<IotRdDailyReportDO> rdWellNameDailyReports(IPage<IotRdDailyReportDO> page, @Param("reqVO") IotRdDailyReportPageReqVO reqVO,
+                                                     @Param("taskIds") Collection<Long> taskIds,
+                                                     @Param("projectIds") Collection<Long> projectIds, @Param("deptIds") Collection<Long> deptIds);
+
+    /**
+     * 根据 井号 查询 瑞都日报 按照队伍分组 小计 查询小组内最后1条记录id
+     * @param page
+     * @param reqVO
+     * @param projectIds
+     * @return
+     */
+    @TenantIgnore
+    List<IotRdDailyReportDO> rdWellNameDailyReportsGroupIds(IPage<IotRdDailyReportDO> page, @Param("reqVO") IotRdDailyReportPageReqVO reqVO,
+                                                            @Param("taskIds") Collection<Long> taskIds,
+                                                            @Param("projectIds") Collection<Long> projectIds, @Param("deptIds") Collection<Long> deptIds);
+
+    /**
+     * 根据 队伍 查询 瑞都日报 按照任务井分组 小计
+     * @param page
+     * @param reqVO
+     * @param projectIds
+     * @return
+     */
+    IPage<IotRdDailyReportDO> rdDeptDailyReports(IPage<IotRdDailyReportDO> page, @Param("reqVO") IotRdDailyReportPageReqVO reqVO,
+                                                 @Param("taskIds") Collection<Long> taskIds,
+                                                 @Param("projectIds") Collection<Long> projectIds, @Param("deptIds") Collection<Long> deptIds);
+
+    /**
+     * 以队伍为维度 查询 井号 分组后的 瑞都日报 按照任务井分组 小计 查询小组内最后1条记录id
+     * @param page
+     * @param reqVO
+     * @param projectIds
+     * @return
+     */
+    List<IotRdDailyReportDO> rdDeptDailyReportsGroupIds(IPage<IotRdDailyReportDO> page, @Param("reqVO") IotRdDailyReportPageReqVO reqVO,
+                                                        @Param("taskIds") Collection<Long> taskIds,
+                                                        @Param("projectIds") Collection<Long> projectIds, @Param("deptIds") Collection<Long> deptIds);
+
 }

+ 32 - 0
yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/service/iotrddailyreport/IotRdDailyReportService.java

@@ -105,4 +105,36 @@ public interface IotRdDailyReportService {
      * @return 从日报中提取任务的实际进度
      */
     List<IotRdDailyReportDO> taskActualProgress(IotRdDailyReportPageReqVO reqVO);
+
+    /**
+     * 获得瑞都日报分页 以井为维度统计工作量
+     *
+     * @param pageReqVO 分页查询
+     * @return 瑞都日报分页
+     */
+    PageResult<IotRdDailyReportDO> teamReports(IotRdDailyReportPageReqVO pageReqVO);
+
+    /**
+     * 根据 队伍 查询 瑞都日报 按照任务井分组 小计 查询小组内最后1条记录id
+     *
+     * @param pageReqVO 列表查询
+     * @return 瑞都日报 列表 小组内最后 的记录
+     */
+    List<IotRdDailyReportDO> rdDeptDailyReportsGroupIds(IotRdDailyReportPageReqVO pageReqVO);
+
+    /**
+     * 根据 井号 查询 瑞都日报 按照队伍分组 小计 查询小组内最后1条记录id
+     *
+     * @param pageReqVO 列表查询
+     * @return 瑞都日报 列表 小组内最后 的记录
+     */
+    List<IotRdDailyReportDO> rdWellNameDailyReportsGroupIds(IotRdDailyReportPageReqVO pageReqVO);
+
+    /**
+     * 获得瑞都日报分页 以队伍为维度统计工作量
+     *
+     * @param pageReqVO 分页查询
+     * @return 瑞都日报分页
+     */
+    PageResult<IotRdDailyReportDO> wellReports(IotRdDailyReportPageReqVO pageReqVO);
 }

+ 79 - 0
yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/service/iotrddailyreport/IotRdDailyReportServiceImpl.java

@@ -38,6 +38,8 @@ import cn.iocoder.yudao.module.system.service.dept.DeptService;
 import cn.iocoder.yudao.module.system.service.dict.DictDataService;
 import cn.iocoder.yudao.module.system.service.permission.RoleService;
 import cn.iocoder.yudao.module.system.service.user.AdminUserService;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.google.common.collect.ImmutableMap;
 import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
 import org.springframework.stereotype.Service;
@@ -920,4 +922,81 @@ public class IotRdDailyReportServiceImpl implements IotRdDailyReportService {
         return dailyReports;
     }
 
+    @Override
+    public PageResult<IotRdDailyReportDO> teamReports(IotRdDailyReportPageReqVO pageReqVO) {
+        // 查询选择部门下面所有子部门
+        Set<Long> ids = new HashSet<>();
+        if (Objects.nonNull(pageReqVO.getDeptId())) {
+            ids = deptService.getChildDeptIdListFromCache(pageReqVO.getDeptId());
+            ids.add(pageReqVO.getDeptId());
+            pageReqVO.setDeptIds(ids);
+        }
+        // 检查contractName不为空但projectIds为空的情况
+        if (StrUtil.isNotBlank(pageReqVO.getContractName()) && (CollUtil.isEmpty(pageReqVO.getProjectIds()))) {
+            return new PageResult<>(Collections.emptyList(), 0L);
+        }
+        // 检查taskName不为空但taskIds为空的情况
+        if (StrUtil.isNotBlank(pageReqVO.getTaskName()) && (CollUtil.isEmpty(pageReqVO.getTaskIds()))) {
+            return new PageResult<>(Collections.emptyList(), 0L);
+        }
+        IPage<IotRdDailyReportDO> page = iotRdDailyReportMapper.rdWellNameDailyReports(
+                new Page<>(pageReqVO.getPageNo(), pageReqVO.getPageSize()), pageReqVO,
+                pageReqVO.getTaskIds(), pageReqVO.getProjectIds(), ids);
+        return new PageResult<>(page.getRecords(), page.getTotal());
+    }
+
+    @Override
+    public List<IotRdDailyReportDO> rdDeptDailyReportsGroupIds(IotRdDailyReportPageReqVO pageReqVO) {
+        // 查询选择部门下面所有子部门
+        Set<Long> ids = new HashSet<>();
+        if (Objects.nonNull(pageReqVO.getDeptId())) {
+            ids = deptService.getChildDeptIdListFromCache(pageReqVO.getDeptId());
+            ids.add(pageReqVO.getDeptId());
+            pageReqVO.setDeptIds(ids);
+        }
+        List<IotRdDailyReportDO> groupIds = iotRdDailyReportMapper.rdDeptDailyReportsGroupIds(
+                new Page<>(pageReqVO.getPageNo(), pageReqVO.getPageSize()), pageReqVO,
+                pageReqVO.getTaskIds(), pageReqVO.getProjectIds(), ids);
+        return groupIds;
+    }
+
+    @Override
+    public List<IotRdDailyReportDO> rdWellNameDailyReportsGroupIds(IotRdDailyReportPageReqVO pageReqVO) {
+        // 查询选择部门下面所有子部门
+        Set<Long> ids = new HashSet<>();
+        if (Objects.nonNull(pageReqVO.getDeptId())) {
+            ids = deptService.getChildDeptIdListFromCache(pageReqVO.getDeptId());
+            ids.add(pageReqVO.getDeptId());
+            pageReqVO.setDeptIds(ids);
+        }
+        List<IotRdDailyReportDO> groupIds = iotRdDailyReportMapper.rdWellNameDailyReportsGroupIds(
+                new Page<>(pageReqVO.getPageNo(), pageReqVO.getPageSize()), pageReqVO,
+                pageReqVO.getTaskIds(), pageReqVO.getProjectIds(), ids);
+        return groupIds;
+    }
+
+    @Override
+    public PageResult<IotRdDailyReportDO> wellReports(IotRdDailyReportPageReqVO pageReqVO) {
+        // 查询选择部门下面所有子部门
+        Set<Long> ids = new HashSet<>();
+        if (Objects.nonNull(pageReqVO.getDeptId())) {
+            ids = deptService.getChildDeptIdListFromCache(pageReqVO.getDeptId());
+            ids.add(pageReqVO.getDeptId());
+            pageReqVO.setDeptIds(ids);
+        }
+        // 检查contractName不为空但projectIds为空的情况
+        if (StrUtil.isNotBlank(pageReqVO.getContractName()) && (CollUtil.isEmpty(pageReqVO.getProjectIds()))) {
+            return new PageResult<>(Collections.emptyList(), 0L);
+        }
+        // 检查taskName不为空但taskIds为空的情况
+        if (StrUtil.isNotBlank(pageReqVO.getTaskName()) && (CollUtil.isEmpty(pageReqVO.getTaskIds()))) {
+            return new PageResult<>(Collections.emptyList(), 0L);
+        }
+        IPage<IotRdDailyReportDO> page = iotRdDailyReportMapper.rdDeptDailyReports(
+                new Page<>(pageReqVO.getPageNo(), pageReqVO.getPageSize()), pageReqVO,
+                pageReqVO.getTaskIds(), pageReqVO.getProjectIds(), ids);
+
+        return new PageResult<>(page.getRecords(), page.getTotal());
+    }
+
 }

+ 20 - 20
yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/service/iotrhdailyreport/IotRhDailyReportServiceImpl.java

@@ -1,6 +1,5 @@
 package cn.iocoder.yudao.module.pms.service.iotrhdailyreport;
 
-import cn.hutool.core.bean.BeanUtil;
 import cn.hutool.core.collection.CollUtil;
 import cn.hutool.core.date.DatePattern;
 import cn.hutool.core.date.LocalDateTimeUtil;
@@ -10,6 +9,7 @@ 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.tenant.core.context.TenantContextHolder;
 import cn.iocoder.yudao.module.pms.constant.PmsConstants;
 import cn.iocoder.yudao.module.pms.controller.admin.iotcarzhbd.vo.IotCarZhbdPageReqVO;
 import cn.iocoder.yudao.module.pms.controller.admin.iotdevicecategorytemplateattrs.vo.IotDeviceProperty;
@@ -37,7 +37,6 @@ import cn.iocoder.yudao.module.pms.message.PmsMessage;
 import cn.iocoder.yudao.module.pms.util.ZHBDUtil;
 import cn.iocoder.yudao.module.supplier.enums.common.SupplierAuditStatusEnum;
 import cn.iocoder.yudao.module.system.api.dept.DeptApi;
-import cn.iocoder.yudao.module.system.api.dept.dto.DeptRespDTO;
 import cn.iocoder.yudao.module.system.api.user.AdminUserApi;
 import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO;
 import cn.iocoder.yudao.module.system.controller.admin.dept.vo.dept.DeptListReqVO;
@@ -46,6 +45,7 @@ import cn.iocoder.yudao.module.system.dal.dataobject.dict.DictTypeDO;
 import cn.iocoder.yudao.module.system.dal.dataobject.permission.RoleDO;
 import cn.iocoder.yudao.module.system.dal.dataobject.permission.UserRoleDO;
 import cn.iocoder.yudao.module.system.dal.dataobject.user.AdminUserDO;
+import cn.iocoder.yudao.module.system.dal.mysql.dept.DeptMapper;
 import cn.iocoder.yudao.module.system.dal.mysql.permission.UserRoleMapper;
 import cn.iocoder.yudao.module.system.service.dept.DeptService;
 import cn.iocoder.yudao.module.system.service.dict.DictTypeService;
@@ -124,10 +124,13 @@ public class IotRhDailyReportServiceImpl implements IotRhDailyReportService {
     private PmsMessage pmsMessage;
     @Resource
     private DeptApi deptApi;
+    @Resource
+    private DeptMapper deptMapper;
 
     @Override
     @Transactional(rollbackFor = Exception.class)
     public Long createIotRhDailyReport(IotRhDailyReportSaveReqVO createReqVO) {
+        System.out.println("新增日报方法开始:");
         // 插入
         IotRhDailyReportDO iotRhDailyReport = BeanUtils.toBean(createReqVO, IotRhDailyReportDO.class);
 
@@ -139,17 +142,20 @@ public class IotRhDailyReportServiceImpl implements IotRhDailyReportService {
         if (ObjUtil.isEmpty(deptId)) {
             throw exception(IOT_RH_DAILY_REPORT_NO_DEPT);
         }
-
-        // DeptDO currentDept = deptService.getDept(deptId);
-        DeptRespDTO currentDept = deptApi.getDept(deptId);
+        // 过滤掉数据权限 运行记录 中 没有使用 yudao 的数据权限
+        final DeptDO[] currentDept = new DeptDO[1];
+        DataPermissionUtils.executeIgnore(() -> {
+            currentDept[0] = deptMapper.selectById(deptId);
+        });
+        if (ObjUtil.isEmpty(currentDept[0])) {
+            System.out.println("查询到的部门是NULL:" + deptId);
+            System.out.println("当前租户:" + TenantContextHolder.getTenantId());
+            throw exception(IOT_RH_DAILY_REPORT_NO_DEPT);
+        }
         // 队伍下设备非施工状态,新增时需要向填报人发送 消息提醒
         // 查询当前队伍下的设备的施工状态 如果是非施工,就需要向 日报 创建人发送钉钉消息
         List<DeptDO> teams = new ArrayList<>();
-        BeanUtil.toBean(currentDept, DeptDO.class);
-        DeptDO dept = new DeptDO();
-        dept.setId(currentDept.getId());
-        dept.setName(currentDept.getName());
-        teams.add(dept);
+        teams.add(currentDept[0]);
         // 查询增压机状态为非施工的小队
         List<IotDeviceDO> teamStatusL = iotOpeationFillMapper.selectDevStatusBatch(teams);
         // System.out.println("无施工设备的队伍:" + currentDept.getName());
@@ -368,7 +374,7 @@ public class IotRhDailyReportServiceImpl implements IotRhDailyReportService {
                 // 给多个用户发送 相同 的 提醒消息
                 if (CollUtil.isNotEmpty(users)) {
                     // 生成消息提醒标题 部门名称-井号
-                    String msgTitle = currentDept.getName();
+                    String msgTitle = currentDept[0].getName();
                     if (StrUtil.isNotBlank(wellName)) {
                         msgTitle = StrUtil.join("-", msgTitle, wellName);
                     }
@@ -404,18 +410,11 @@ public class IotRhDailyReportServiceImpl implements IotRhDailyReportService {
         // 此时需要判断下当前队伍下有无增压机,如果 ‘当前队伍下无增压机’ 或 ‘增压机的状态不是施工’ 需要新增空白记录 向填报人推送消息。
         // 暂时添加判断条件 创建人 是 null 的话 不发送 站内信及钉钉消息
         if (StrUtil.isNotBlank(iotRhDailyReport.getCreator()) && !noDeviceTeam.get()) {
-
-            DeptRespDTO msgDept = deptApi.getDept(deptId);
-            DeptDO deptDO = new DeptDO();
-            deptDO.setId(msgDept.getId());
-            deptDO.setName(msgDept.getName());
-            deptDO.setParentId(msgDept.getParentId());
-            Long parentId = deptDO.getParentId();
+            Long parentId = currentDept[0].getParentId();
             if (ObjUtil.isNotEmpty(parentId)) {
                 AtomicReference<DeptDO> projectDept = new AtomicReference<>();
                 DataPermissionUtils.executeIgnore(() -> {
                     projectDept.set(deptService.getDept(parentId));
-
                     if (ObjUtil.isNotEmpty(projectDept) && "2".equals(projectDept.get().getType())) {
                         // 查询项目部下具有 项目部日报审批RH 角色的人员
                         Set<Long> projectIds = new HashSet<>();
@@ -447,7 +446,7 @@ public class IotRhDailyReportServiceImpl implements IotRhDailyReportService {
                                         // 给多个用户发送 相同 的 提醒消息
                                         if (CollUtil.isNotEmpty(users)) {
                                             // 生成消息提醒标题 部门名称-井号
-                                            String msgTitle = deptDO.getName();
+                                            String msgTitle = currentDept[0].getName();
                                             if (StrUtil.isNotBlank(wellName)) {
                                                 msgTitle = StrUtil.join("-", msgTitle, wellName);
                                             }
@@ -476,6 +475,7 @@ public class IotRhDailyReportServiceImpl implements IotRhDailyReportService {
                 });
             }
         }
+        System.out.println("新增日报方法结束:");
         return iotRhDailyReport.getId();
     }
 

+ 27 - 0
yudao-module-pms/yudao-module-pms-biz/src/main/resources/mapper/static/IotMaintainMapper.xml

@@ -70,5 +70,32 @@
                 </foreach>
             </if>
         </where>
+        UNION ALL
+        SELECT
+            CAST(wo.update_time AS CHAR) as date,
+            '保养' as type,
+            d.device_code as deviceCode,
+            d.device_name as deviceName,
+            wo.cost
+        FROM rq_iot_main_work_order wo
+        LEFT JOIN rq_iot_main_work_order_bom wob ON (wob.work_order_id = wo.id AND wob.deleted = 0)
+        LEFT JOIN rq_iot_device d ON (d.id = wob.device_id AND d.deleted = 0)
+        WHERE
+            wob.deleted = 0
+        AND wo.deleted = 0
+        AND d.deleted = 0
+        <if test="reqVO.createTime[0] != null">
+            AND wo.create_time &gt;= #{reqVO.createTime[0]}
+        </if>
+        <if test="reqVO.createTime.length > 1 and reqVO.createTime[1] != null">
+            AND wo.create_time &lt;= #{reqVO.createTime[1]}
+        </if>
+        <if test="reqVO.deptIds != null and reqVO.deptIds.size &gt; 0">
+            AND wo.dept_id IN
+            <foreach collection="reqVO.deptIds" index="index" item="key" open="(" separator="," close=")">
+                #{key}
+            </foreach>
+        </if>
+        GROUP BY wo.id, wob.device_id
     </select>
 </mapper>

+ 209 - 0
yudao-module-pms/yudao-module-pms-biz/src/main/resources/mapper/static/iotprojecttask/IotRdDailyReportMapper.xml

@@ -91,4 +91,213 @@
         GROUP BY task_id;
     </select>
 
+    <select id="rdWellNameDailyReports" resultMap="BaseResultMap"
+            parameterType="cn.iocoder.yudao.module.pms.controller.admin.iotrddailyreport.vo.IotRdDailyReportPageReqVO">
+        SELECT
+            rdr.*
+        FROM
+            rq_iot_rd_daily_report rdr
+        INNER JOIN system_dept d ON d.id = rdr.dept_id
+        LEFT JOIN system_dept pd ON pd.id = d.parent_id
+        WHERE
+            rdr.deleted = 0
+        AND rdr.dept_id IS NOT NULL
+        <if test="deptIds != null and deptIds.size &gt; 0">
+            AND rdr.dept_id IN
+            <foreach collection="deptIds" index="index" item="key" open="(" separator="," close=")">
+                #{key}
+            </foreach>
+        </if>
+        <if test="projectIds != null and projectIds.size &gt; 0">
+            AND rdr.project_id IN
+            <foreach collection="projectIds" index="index" item="key" open="(" separator="," close=")">
+                #{key}
+            </foreach>
+        </if>
+        <if test="taskIds != null and taskIds.size &gt; 0">
+            AND rdr.task_id IN
+            <foreach collection="taskIds" index="index" item="key" open="(" separator="," close=")">
+                #{key}
+            </foreach>
+        </if>
+        <if test="reqVO.createTime != null and reqVO.createTime.length > 0">
+            <!-- 处理“开始时间”(数组第1位,如 createTime[0] = 2024-01-01 00:00:00) -->
+            <if test="reqVO.createTime[0] != null">
+                AND rdr.create_time &gt;= #{reqVO.createTime[0]}
+            </if>
+            <!-- 处理“结束时间”(数组第2位,如 createTime[1] = 2024-01-31 23:59:59) -->
+            <if test="reqVO.createTime.length > 1 and reqVO.createTime[1] != null">
+                AND rdr.create_time &lt;= #{reqVO.createTime[1]}
+            </if>
+        </if>
+        ORDER BY
+            COALESCE(pd.sort, 999999) ASC,
+            d.sort ASC,
+            DATE(rdr.create_time) DESC;
+    </select>
+
+    <select id="rdWellNameDailyReportsGroupIds" resultMap="BaseResultMap"
+            parameterType="cn.iocoder.yudao.module.pms.controller.admin.iotrddailyreport.vo.IotRdDailyReportPageReqVO">
+        WITH sorted_data AS (
+        SELECT
+            rdr.id,
+            rdr.dept_id,
+            rdr.task_id,
+            ROW_NUMBER() OVER (
+                PARTITION BY rdr.dept_id, rdr.task_id
+                ORDER BY
+                COALESCE(pd.sort, 999999) DESC,  -- 反转:ASC -> DESC
+                d.sort DESC,                     -- 反转:ASC -> DESC
+                rdr.task_id ASC,                 -- 反转:DESC -> ASC
+                DATE(rdr.create_time) ASC        -- 反转:DESC -> ASC
+            ) AS rn
+        FROM
+            rq_iot_rd_daily_report rdr
+        INNER JOIN system_dept d ON d.id = rdr.dept_id
+        LEFT JOIN system_dept pd ON pd.id = d.parent_id
+        WHERE
+            rdr.deleted = 0
+        AND rdr.dept_id IS NOT NULL
+        <if test="deptIds != null and deptIds.size &gt; 0">
+            AND rdr.dept_id IN
+            <foreach collection="deptIds" index="index" item="key" open="(" separator="," close=")">
+                #{key}
+            </foreach>
+        </if>
+        <if test="projectIds != null and projectIds.size &gt; 0">
+            AND rdr.project_id IN
+            <foreach collection="projectIds" index="index" item="key" open="(" separator="," close=")">
+                #{key}
+            </foreach>
+        </if>
+        <if test="taskIds != null and taskIds.size &gt; 0">
+            AND rdr.task_id IN
+            <foreach collection="taskIds" index="index" item="key" open="(" separator="," close=")">
+                #{key}
+            </foreach>
+        </if>
+        <if test="reqVO.createTime != null and reqVO.createTime.length > 0">
+            <!-- 处理“开始时间”(数组第1位,如 createTime[0] = 2024-01-01 00:00:00) -->
+            <if test="reqVO.createTime[0] != null">
+                AND rdr.create_time &gt;= #{reqVO.createTime[0]}
+            </if>
+            <!-- 处理“结束时间”(数组第2位,如 createTime[1] = 2024-01-31 23:59:59) -->
+            <if test="reqVO.createTime.length > 1 and reqVO.createTime[1] != null">
+                AND rdr.create_time &lt;= #{reqVO.createTime[1]}
+            </if>
+        </if>
+        )
+        SELECT
+            id,
+            dept_id,
+            task_id
+        FROM sorted_data
+        WHERE rn = 1
+    </select>
+
+    <select id="rdDeptDailyReports" resultMap="BaseResultMap"
+            parameterType="cn.iocoder.yudao.module.pms.controller.admin.iotrddailyreport.vo.IotRdDailyReportPageReqVO">
+        SELECT
+            rdr.*
+        FROM
+            rq_iot_rd_daily_report rdr
+        INNER JOIN system_dept d ON d.id = rdr.dept_id
+        LEFT JOIN system_dept pd ON pd.id = d.parent_id
+        WHERE
+            rdr.deleted = 0
+        AND rdr.dept_id IS NOT NULL
+        <if test="deptIds != null and deptIds.size &gt; 0">
+            AND rdr.dept_id IN
+            <foreach collection="deptIds" index="index" item="key" open="(" separator="," close=")">
+                #{key}
+            </foreach>
+        </if>
+        <if test="projectIds != null and projectIds.size &gt; 0">
+            AND rdr.project_id IN
+            <foreach collection="projectIds" index="index" item="key" open="(" separator="," close=")">
+                #{key}
+            </foreach>
+        </if>
+        <if test="taskIds != null and taskIds.size &gt; 0">
+            AND rdr.task_id IN
+            <foreach collection="taskIds" index="index" item="key" open="(" separator="," close=")">
+                #{key}
+            </foreach>
+        </if>
+        <if test="reqVO.createTime != null and reqVO.createTime.length > 0">
+            <!-- 处理“开始时间”(数组第1位,如 createTime[0] = 2024-01-01 00:00:00) -->
+            <if test="reqVO.createTime[0] != null">
+                AND rdr.create_time &gt;= #{reqVO.createTime[0]}
+            </if>
+            <!-- 处理“结束时间”(数组第2位,如 createTime[1] = 2024-01-31 23:59:59) -->
+            <if test="reqVO.createTime.length > 1 and reqVO.createTime[1] != null">
+                AND rdr.create_time &lt;= #{reqVO.createTime[1]}
+            </if>
+        </if>
+        ORDER BY
+            rdr.task_id DESC,
+            COALESCE(pd.sort, 999999) ASC,
+            d.sort ASC,
+            DATE(rdr.create_time) DESC;
+    </select>
+
+    <select id="rdDeptDailyReportsGroupIds" resultMap="BaseResultMap"
+            parameterType="cn.iocoder.yudao.module.pms.controller.admin.iotrddailyreport.vo.IotRdDailyReportPageReqVO">
+        WITH sorted_data AS (
+        SELECT
+            rdr.id,
+            rdr.dept_id,
+            rdr.task_id,
+            ROW_NUMBER() OVER (
+                PARTITION BY rdr.dept_id, rdr.task_id
+                ORDER BY
+                rdr.task_id ASC,                 -- 反转:DESC -> ASC
+                COALESCE(pd.sort, 999999) DESC,  -- 反转:ASC -> DESC
+                d.sort DESC,                     -- 反转:ASC -> DESC
+                DATE(rdr.create_time) ASC        -- 反转:DESC -> ASC
+            ) AS rn
+        FROM
+            rq_iot_rd_daily_report rdr
+        INNER JOIN system_dept d ON d.id = rdr.dept_id
+        LEFT JOIN system_dept pd ON pd.id = d.parent_id
+        WHERE
+            rdr.deleted = 0
+        AND rdr.dept_id IS NOT NULL
+        <if test="deptIds != null and deptIds.size &gt; 0">
+            AND rdr.dept_id IN
+            <foreach collection="deptIds" index="index" item="key" open="(" separator="," close=")">
+                #{key}
+            </foreach>
+        </if>
+        <if test="projectIds != null and projectIds.size &gt; 0">
+            AND rdr.project_id IN
+            <foreach collection="projectIds" index="index" item="key" open="(" separator="," close=")">
+                #{key}
+            </foreach>
+        </if>
+        <if test="taskIds != null and taskIds.size &gt; 0">
+            AND rdr.task_id IN
+            <foreach collection="taskIds" index="index" item="key" open="(" separator="," close=")">
+                #{key}
+            </foreach>
+        </if>
+        <if test="reqVO.createTime != null and reqVO.createTime.length > 0">
+            <!-- 处理“开始时间”(数组第1位,如 createTime[0] = 2024-01-01 00:00:00) -->
+            <if test="reqVO.createTime[0] != null">
+                AND rdr.create_time &gt;= #{reqVO.createTime[0]}
+            </if>
+            <!-- 处理“结束时间”(数组第2位,如 createTime[1] = 2024-01-31 23:59:59) -->
+            <if test="reqVO.createTime.length > 1 and reqVO.createTime[1] != null">
+                AND rdr.create_time &lt;= #{reqVO.createTime[1]}
+            </if>
+        </if>
+        )
+        SELECT
+            id,
+            dept_id,
+            task_id
+        FROM sorted_data
+        WHERE rn = 1
+    </select>
+
 </mapper>