Răsfoiți Sursa

pms 瑞都 日报统计 设备利用率

zhangcl 9 ore în urmă
părinte
comite
184e03d01a

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

@@ -20,6 +20,7 @@ import cn.iocoder.yudao.module.pms.controller.admin.iotdevicerunlog.vo.IotDevice
 import cn.iocoder.yudao.module.pms.controller.admin.iotmainworkorder.vo.IotMainWorkOrderPageReqVO;
 import cn.iocoder.yudao.module.pms.controller.admin.iotopeationfill.vo.IotOpeationFillPageReqVO;
 import cn.iocoder.yudao.module.pms.controller.admin.iotoutbound.vo.IotOutboundPageReqVO;
+import cn.iocoder.yudao.module.pms.controller.admin.iotrddailyreport.vo.IotRdDailyReportPageReqVO;
 import cn.iocoder.yudao.module.pms.controller.admin.iotrhdailyreport.vo.IotRhDailyReportPageReqVO;
 import cn.iocoder.yudao.module.pms.controller.admin.iotrydailyreport.vo.IotRyDailyReportPageReqVO;
 import cn.iocoder.yudao.module.pms.controller.admin.iotrydailyreport.vo.IotRyDailyReportTaskCountVO;
@@ -30,6 +31,7 @@ import cn.iocoder.yudao.module.pms.controller.admin.stat.vo.TeamUtilizationRateV
 import cn.iocoder.yudao.module.pms.controller.admin.stat.vo.YearTotalGas;
 import cn.iocoder.yudao.module.pms.controller.admin.vo.DeviceVO;
 import cn.iocoder.yudao.module.pms.controller.admin.vo.IotDevicePageReqVO;
+import cn.iocoder.yudao.module.pms.controller.admin.vo.IotProductClassifyListReqVO;
 import cn.iocoder.yudao.module.pms.dal.dataobject.IotDeviceDO;
 import cn.iocoder.yudao.module.pms.dal.dataobject.IotProductClassifyDO;
 import cn.iocoder.yudao.module.pms.dal.dataobject.failure.IotFailureReportDO;
@@ -39,6 +41,7 @@ import cn.iocoder.yudao.module.pms.dal.dataobject.inspect.IotInspectPlanDO;
 import cn.iocoder.yudao.module.pms.dal.dataobject.iotcountdata.IotCountDataDO;
 import cn.iocoder.yudao.module.pms.dal.dataobject.iotmainworkorder.IotMainWorkOrderDO;
 import cn.iocoder.yudao.module.pms.dal.dataobject.iotoutbound.IotOutboundDO;
+import cn.iocoder.yudao.module.pms.dal.dataobject.iotrddailyreport.IotRdDailyReportDO;
 import cn.iocoder.yudao.module.pms.dal.dataobject.iotrhdailyreport.IotRhDailyReportDO;
 import cn.iocoder.yudao.module.pms.dal.dataobject.iotrydailyreport.IotRyDailyReportDO;
 import cn.iocoder.yudao.module.pms.dal.dataobject.iotsapstock.IotSapStockDO;
@@ -54,6 +57,7 @@ import cn.iocoder.yudao.module.pms.dal.mysql.iotdevicerunlog.IotDeviceRunLogMapp
 import cn.iocoder.yudao.module.pms.dal.mysql.iotmainworkorder.IotMainWorkOrderMapper;
 import cn.iocoder.yudao.module.pms.dal.mysql.iotopeationfill.IotOpeationFillMapper;
 import cn.iocoder.yudao.module.pms.dal.mysql.iotoutbound.IotOutboundMapper;
+import cn.iocoder.yudao.module.pms.dal.mysql.iotrddailyreport.IotRdDailyReportMapper;
 import cn.iocoder.yudao.module.pms.dal.mysql.iotrhdailyreport.IotRhDailyReportMapper;
 import cn.iocoder.yudao.module.pms.dal.mysql.iotrydailyreport.IotRyDailyReportMapper;
 import cn.iocoder.yudao.module.pms.dal.mysql.iotsapstock.IotSapStockMapper;
@@ -159,6 +163,8 @@ public class IotStaticController {
     private IotRyDailyReportService iotRyDailyReportService;
     @Autowired
     private IotRyDailyReportMapper iotRyDailyReportMapper;
+    @Autowired
+    private IotRdDailyReportMapper iotRdDailyReportMapper;
 
     @GetMapping("/main/day")
     public CommonResult<Map<String, Object>> getMaintainDay() {
@@ -1717,7 +1723,7 @@ public class IotStaticController {
         }
         // 各项目部的设备利用率集合
         List<ProjectUtilizationRateVo> rates = new ArrayList<>();
-        // 查询瑞 158l 所有项目部
+        // 查询瑞 158l 所有项目部
         Set<Long> childDeptIds = deptService.getChildDeptIdListFromCache(158l);
         Map<Long, DeptDO> allDeptPair = deptService.getDeptMap(childDeptIds);
         Set<String> projectDeptNames = new HashSet<>();
@@ -1980,5 +1986,405 @@ public class IotStaticController {
         return success(rates);
     }
 
+    /**
+     * 瑞都 设备利用率 按 项目部 统计
+     * @return
+     */
+    @GetMapping("/rd/device/utilizationRate")
+    @PermitAll
+    public CommonResult<List<ProjectUtilizationRateVo>> rdUtilizationRate(IotRdDailyReportPageReqVO reqVO) {
+        if (ObjUtil.isEmpty(reqVO.getCreateTime())) {
+            throw exception(IOT_DAILY_REPORT_TIME_NOT_EXISTS);
+        }
+        if (reqVO.getCreateTime().length < 2) {
+            throw exception(IOT_DAILY_REPORT_TIME_NOT_EXISTS);
+        }
+        // 各项目部的设备利用率集合
+        List<ProjectUtilizationRateVo> rates = new ArrayList<>();
+        // 查询瑞都 163l 所有项目部
+        Set<Long> childDeptIds = deptService.getChildDeptIdListFromCache(163l);
+        Map<Long, DeptDO> allDeptPair = deptService.getDeptMap(childDeptIds);
+        Set<String> projectDeptNames = new HashSet<>();
+        Set<Long> projectDeptIds = new HashSet<>();
+        // key项目部id   value项目部名称
+        Map<Long, String> projectPair = new HashMap<>();
+        // key项目部id   value项目部包含的队伍id集合
+        Map<Long, Set<Long>> projectTeamPair = new HashMap<>();
+        // 设备ID到其所属部门ID的映射
+        Map<Long, Long> deviceIdToDeptIdMap = new HashMap<>();
+        // key项目部id     value项目部下包含的队伍的 压裂 连油 设备数量
+        Map<Long, Integer> projectDevicePair = new HashMap<>();
+        if (CollUtil.isNotEmpty(allDeptPair)) {
+            allDeptPair.forEach((deptId, dept) -> {
+                if (dept.getName().contains("项目部") ) {
+                    projectDeptIds.add(deptId);
+                    projectDeptNames.add(dept.getName());
+                    projectPair.put(deptId, dept.getName());
+                }
+            });
+            // 遍历所有部门
+            allDeptPair.forEach((deptId, dept) -> {
+                // 找出每个项目部下的队伍
+                if (projectPair.containsKey(dept.getParentId())) {
+                    // 获得当前部门的上级项目部
+                    projectPair.forEach((projectDeptId, projectDept) -> {
+                        if (projectDeptId.equals(dept.getParentId())) {
+                            if (projectTeamPair.containsKey(projectDeptId)) {
+                                Set<Long> teamIds = projectTeamPair.get(projectDeptId);
+                                teamIds.add(deptId);
+                                projectTeamPair.put(projectDeptId, teamIds);
+                            } else {
+                                Set<Long> teamIds = new HashSet<>();
+                                teamIds.add(deptId);
+                                projectTeamPair.put(projectDeptId, teamIds);
+                            }
+                        }
+                    });
+                }
+            });
+            // 查询不同项目部下 包含的 压裂泵车26 连油主车设备31
+            // 查询 连油主车 或 压裂泵车 相应的设备类别 id集合
+            Set<Long> utilizeDeviceCategoryIds = new HashSet<>();
+            IotProductClassifyListReqVO categoryReqVO = new IotProductClassifyListReqVO();
+            categoryReqVO.setName("连油主车");
+            List<IotProductClassifyDO> deviceCategories = iotProductClassifyMapper.selectList(categoryReqVO);
+            if (CollUtil.isNotEmpty(deviceCategories)) {
+                utilizeDeviceCategoryIds.add(deviceCategories.get(0).getId());
+            }
+            // 查询 压裂泵车 的设备类别
+            categoryReqVO.setName("压裂泵车");
+            List<IotProductClassifyDO> pumpCategories = iotProductClassifyMapper.selectList(categoryReqVO);
+            if (CollUtil.isNotEmpty(pumpCategories)) {
+                pumpCategories.forEach(category -> {
+                    utilizeDeviceCategoryIds.add(category.getId());
+                });
+            }
+            IotDevicePageReqVO deviceReqVO = new IotDevicePageReqVO();
+            deviceReqVO.setAssetClasses(new ArrayList<>(utilizeDeviceCategoryIds));
+            List<IotDeviceDO> utilizeDevices = iotDeviceMapper.selectListAlone(deviceReqVO);
+            // 筛选出项目部下包含的队伍的设备数量
+
+            Set<Long> deviceIds = new HashSet<>();
+
+            if (CollUtil.isNotEmpty(utilizeDevices)) {
+                utilizeDevices.forEach(device -> {
+                    // 存储设备ID与所属部门ID的映射
+                    deviceIdToDeptIdMap.put(device.getId(), device.getDeptId());
+                    // 筛选出各项目部下的 压裂 连油 设备
+                    projectTeamPair.forEach((projectId, teamIds) -> {
+                        if (projectId.equals(device.getDeptId()) || teamIds.contains(device.getDeptId())) {
+                            if (projectDevicePair.containsKey(projectId)) {
+                                Integer tempCount = projectDevicePair.get(projectId);
+                                projectDevicePair.put(projectId, ++tempCount);
+                            } else {
+                                projectDevicePair.put(projectId, 1);
+                            }
+                            // 找出各项目部下的设备id集合 用来查询日报
+                            deviceIds.add(device.getId());
+                        }
+                    });
+                });
+            }
+        }
+        // 查询出指定时间区间内 已经填写的日报 再根据设备id 进行筛选 通过设备id 建立项目部 与 日报数量之间的关联
+        // 判断日报中 device_ids 字段中每个设备 是否属于需要统计的 压裂 连油 设备
+        List<IotRdDailyReportDO> dailyReports = iotRdDailyReportMapper.dailyReports(reqVO);
+        // key项目部id     value项目部包含的队伍指定时间区域内日报数量
+        Map<Long, Integer> projectReportPair = new HashMap<>();
+        if (CollUtil.isNotEmpty(dailyReports)) {
+            // 整理出每个项目部下的队伍填报的日报数量
+            dailyReports.forEach(report -> {
+                if (CollUtil.isNotEmpty(projectTeamPair)) {
+                    projectTeamPair.forEach((projectDeptId, teamDeptIds) -> {
+                        Set<Long> tempDeviceIds = report.getDeviceIds();
+                        // 判断 集合 tempDeviceIds 中的任意的 ‘设备id’ 是否包含在 集合 teamDeptIds 中
+                        // 判断tempDeviceIds中的任意设备所属部门是否在当前项目部的队伍部门中
+                        boolean hasMatchingDevice = CollUtil.isNotEmpty(tempDeviceIds) && tempDeviceIds.stream()
+                                .map(deviceIdToDeptIdMap::get) // 通过映射表获取设备所属部门ID
+                                .filter(Objects::nonNull) // 过滤掉非统计范围内的设备(避免空指针)
+                                .anyMatch(teamDeptIds::contains); // 任意设备所属部门在队伍部门中则匹配
+                        if (hasMatchingDevice) {
+                            if (projectReportPair.containsKey(projectDeptId)) {
+                                Integer tempCount = projectReportPair.get(projectDeptId);
+                                projectReportPair.put(projectDeptId, ++tempCount);
+                            } else {
+                                projectReportPair.put(projectDeptId, 1);
+                            }
+                        }
+                    });
+                }
+            });
+            // 计算指定时间区间内包含的天数
+            long daysCount;
+            if (ObjUtil.isNotEmpty(reqVO.getCreateTime()) && reqVO.getCreateTime().length >= 2) {
+                LocalDateTime start = reqVO.getCreateTime()[0];
+                LocalDateTime end = reqVO.getCreateTime()[1];
+                if (ObjUtil.isNotEmpty(start) && ObjUtil.isNotEmpty(end) && !end.isBefore(start)) {
+                    // 使用ChronoUnit.DAYS.between计算天数差,并+1包含首尾两天
+                    daysCount = ChronoUnit.DAYS.between(
+                            start.toLocalDate(),
+                            end.toLocalDate()
+                    ) + 1;
+                } else {
+                    daysCount = 0L;
+                }
+            } else {
+                daysCount = 0L;
+            }
+            // 计算每个项目部的设备利用率
+            if (CollUtil.isNotEmpty(projectDevicePair)) {
+                projectDevicePair.forEach((projectDeptId, deviceNum) -> {
+                    ProjectUtilizationRateVo rateVo = new ProjectUtilizationRateVo();
+                    rateVo.setProjectDeptId(projectDeptId);
+                    if (projectPair.containsKey(projectDeptId)) {
+                        rateVo.setProjectDeptName(projectPair.get(projectDeptId));
+                    }
+                    // 遍历每个项目部 获取每个项目部下 压裂 连油 设备数量
+                    rateVo.setTeamCount(deviceNum);
+                    rateVo.setCumulativeDays(deviceNum * daysCount);
+                    double rate = 0.0;
+                    // 匹配出当前项目部下 日报数量
+                    if (projectReportPair.containsKey(projectDeptId)) {
+                        Integer reportCount = projectReportPair.getOrDefault(projectDeptId, 0);
+                        rateVo.setConstructionDays(reportCount);
+                        // 当前项目部 设备利用率 公式 reportCount/(currentTeamNum*daysCount)
+                        // 计算设备利用率(处理除数为0的情况)
+                        if (deviceNum > 0 && daysCount > 0) {
+                            rate = new BigDecimal((double) reportCount / (deviceNum * daysCount))
+                                    .setScale(4, RoundingMode.HALF_UP)  // 保留4位小数,四舍五入
+                                    .doubleValue();;
+                        }
+                    }
+                    rateVo.setUtilizationRate(rate); // 存储计算结果
+                    rates.add(rateVo);
+                });
+            }
+        }
+        // 将返回列表中的 部门名称 去除多语言标识
+        // 处理projectDeptName,截取~~首次出现前的字符串
+        if (CollUtil.isNotEmpty(rates)) {
+            rates.forEach(rateVo -> {
+                String originalName = rateVo.getProjectDeptName();
+                if (StrUtil.isNotBlank(originalName) && originalName.contains("~~")) {
+                    // 截取首次~~之前的部分
+                    String processedName = originalName.substring(0, originalName.indexOf("~~"));
+                    rateVo.setProjectDeptName(processedName);
+                }
+                // 空值或无~~标识时,保留原名称
+            });
+        }
+        rates.sort(Comparator.comparingDouble(ProjectUtilizationRateVo::getUtilizationRate).reversed());
+        return success(rates);
+    }
+
+    /**
+     * 瑞都 设备利用率 按 队伍 统计
+     * @return
+     */
+    @GetMapping("/rd/device/teamUtilizationRate")
+    @PermitAll
+    public CommonResult<List<TeamUtilizationRateVo>> rdTeamUtilizationRate(IotRdDailyReportPageReqVO reqVO) {
+        if (ObjUtil.isEmpty(reqVO.getCreateTime())) {
+            throw exception(IOT_DAILY_REPORT_TIME_NOT_EXISTS);
+        }
+        if (reqVO.getCreateTime().length < 2) {
+            throw exception(IOT_DAILY_REPORT_TIME_NOT_EXISTS);
+        }
+        // 必须传递 项目部id 查询队伍数据
+        if (ObjUtil.isEmpty(reqVO.getDeptId())) {
+            throw exception(IOT_DAILY_REPORT_DEPT_NOT_EXISTS);
+        }
+
+        // 指定项目部的各队伍设备利用率集合
+        List<TeamUtilizationRateVo> rates = new ArrayList<>();
+
+        // 查询指定项目部下的 队伍集合
+        DeptListReqVO deptReqVO = new DeptListReqVO();
+        deptReqVO.setDeptId(reqVO.getDeptId());
+        List<DeptDO> projectTeams = deptService.getDeptListByParentId(deptReqVO);
+        // 指定项目部下的 队伍id集合
+        Set<Long> projectTeamIds = new HashSet<>();
+        if (CollUtil.isNotEmpty(projectTeams)) {
+            projectTeams.forEach(team -> {
+                projectTeamIds.add(team.getId());
+            });
+        }
+
+        Map<Long, DeptDO> allDeptPair = deptService.getDeptMap(projectTeamIds);
+
+        Set<String> projectDeptNames = new HashSet<>();
+        Set<Long> projectDeptIds = new HashSet<>();
+        // key项目部id   value项目部名称
+        Map<Long, String> projectPair = new HashMap<>();
+        // key队伍id   value队伍名称
+        Map<Long, String> teamPair = new HashMap<>();
+        // key项目部id   value项目部包含的队伍id集合
+        Map<Long, Set<Long>> projectTeamPair = new HashMap<>();
+        // key队伍id   value队伍日报数量
+        Map<Long, Long> teamReportCountPair = new HashMap<>();
+        // key项目部id     value项目部下包含的队伍的 压裂 连油 设备数量
+        Map<Long, Integer> projectDevicePair = new HashMap<>();
+        // 设备ID到其所属部门ID的映射
+        Map<Long, Long> deviceIdToDeptIdMap = new HashMap<>();
+
+        if (CollUtil.isNotEmpty(allDeptPair)) {
+            allDeptPair.forEach((deptId, dept) -> {
+                if (dept.getName().contains("项目部") ) {
+                    projectDeptIds.add(deptId);
+                    projectDeptNames.add(dept.getName());
+                    projectPair.put(deptId, dept.getName());
+                }
+                teamPair.put(deptId, dept.getName());
+            });
+            // 遍历所有部门
+            allDeptPair.forEach((deptId, dept) -> {
+                // 找出每个项目部下的队伍
+                if (projectPair.containsKey(dept.getParentId())) {
+                    // 获得当前部门的上级项目部
+                    projectPair.forEach((projectDeptId, projectDept) -> {
+                        if (projectDeptId.equals(dept.getParentId())) {
+                            if (projectTeamPair.containsKey(projectDeptId)) {
+                                Set<Long> teamIds = projectTeamPair.get(projectDeptId);
+                                teamIds.add(deptId);
+                                projectTeamPair.put(projectDeptId, teamIds);
+                            } else {
+                                Set<Long> teamIds = new HashSet<>();
+                                teamIds.add(deptId);
+                                projectTeamPair.put(projectDeptId, teamIds);
+                            }
+                        }
+                    });
+                }
+            });
+        }
+        if (CollUtil.isNotEmpty(projectTeamIds)) {
+            // 查询不同项目部下 包含的 压裂泵车26 连油主车设备31
+            // 查询 连油主车 或 压裂泵车 相应的设备类别 id集合
+            Set<Long> utilizeDeviceCategoryIds = new HashSet<>();
+            IotProductClassifyListReqVO categoryReqVO = new IotProductClassifyListReqVO();
+            categoryReqVO.setName("连油主车");
+            List<IotProductClassifyDO> deviceCategories = iotProductClassifyMapper.selectList(categoryReqVO);
+            if (CollUtil.isNotEmpty(deviceCategories)) {
+                utilizeDeviceCategoryIds.add(deviceCategories.get(0).getId());
+            }
+            // 查询 压裂泵车 的设备类别
+            categoryReqVO.setName("压裂泵车");
+            List<IotProductClassifyDO> pumpCategories = iotProductClassifyMapper.selectList(categoryReqVO);
+            if (CollUtil.isNotEmpty(pumpCategories)) {
+                pumpCategories.forEach(category -> {
+                    utilizeDeviceCategoryIds.add(category.getId());
+                });
+            }
+            IotDevicePageReqVO deviceReqVO = new IotDevicePageReqVO();
+            deviceReqVO.setAssetClasses(new ArrayList<>(utilizeDeviceCategoryIds));
+            List<IotDeviceDO> utilizeDevices = iotDeviceMapper.selectListAlone(deviceReqVO);
+
+            if (CollUtil.isNotEmpty(utilizeDevices)) {
+                utilizeDevices.forEach(device -> {
+                    // 存储设备ID与所属部门ID的映射
+                    deviceIdToDeptIdMap.put(device.getId(), device.getDeptId());
+                    // 筛选出各队伍下的 压裂 连油 设备
+                    projectTeamIds.forEach(teamId -> {
+                        if (projectTeamIds.contains(device.getDeptId())) {
+                            if (projectDevicePair.containsKey(teamId)) {
+                                Integer tempCount = projectDevicePair.get(teamId);
+                                projectDevicePair.put(teamId, ++tempCount);
+                            } else {
+                                projectDevicePair.put(teamId, 1);
+                            }
+                        }
+                    });
+                });
+            }
+            // 查询出指定时间区间内 已经填写的日报 再根据设备id 进行筛选 通过设备id 建立队伍 与 日报数量之间的关联
+            // 判断日报中 device_ids 字段中每个设备 是否属于需要统计的 压裂 连油 设备
+            List<IotRdDailyReportDO> dailyReports = iotRdDailyReportMapper.dailyReports(reqVO);
+            // 筛选出每个队伍的日报
+            if (CollUtil.isNotEmpty(dailyReports)) {
+                // 设置每个队伍 相关 压裂 连油 设备 的日报数量
+                dailyReports.forEach(report -> {
+                    projectTeamIds.forEach(teamId -> {
+                        Set<Long> tempDeviceIds = report.getDeviceIds();
+                        // 判断 集合 tempDeviceIds 中的任意的 ‘设备id’ 是否包含在 集合 teamDeptIds 中
+                        // 判断tempDeviceIds中的任意设备所属部门是否在当前项目部的队伍部门中
+                        boolean hasMatchingDevice = CollUtil.isNotEmpty(tempDeviceIds) && tempDeviceIds.stream()
+                                .map(deviceIdToDeptIdMap::get) // 通过映射表获取设备所属部门ID
+                                .filter(Objects::nonNull) // 过滤掉非统计范围内的设备(避免空指针)
+                                .anyMatch(teamId::equals); // 任意设备所属部门在队伍部门中则匹配
+                        if (hasMatchingDevice) {
+                            if (teamReportCountPair.containsKey(teamId)) {
+                                Long tempCount = teamReportCountPair.get(teamId);
+                                teamReportCountPair.put(teamId, ++tempCount);
+                            } else {
+                                teamReportCountPair.put(teamId, 1l);
+                            }
+                        }
+                    });
+                });
+
+                // 计算指定时间区间内包含的天数
+                long daysCount;
+                if (ObjUtil.isNotEmpty(reqVO.getCreateTime()) && reqVO.getCreateTime().length >= 2) {
+                    LocalDateTime start = reqVO.getCreateTime()[0];
+                    LocalDateTime end = reqVO.getCreateTime()[1];
+                    if (ObjUtil.isNotEmpty(start) && ObjUtil.isNotEmpty(end) && !end.isBefore(start)) {
+                        // 使用ChronoUnit.DAYS.between计算天数差,并+1包含首尾两天
+                        daysCount = ChronoUnit.DAYS.between(
+                                start.toLocalDate(),
+                                end.toLocalDate()
+                        ) + 1;
+                    } else {
+                        daysCount = 0L;
+                    }
+                } else {
+                    daysCount = 0L;
+                }
+                // 计算每个队伍的设备利用率
+                if (CollUtil.isNotEmpty(projectTeamIds)) {
+                    projectTeamIds.forEach(teamId -> {
+                        TeamUtilizationRateVo rateVo = new TeamUtilizationRateVo();
+                        rateVo.setProjectDeptId(reqVO.getDeptId());
+                        rateVo.setTeamId(teamId);
+                        rateVo.setCumulativeDays(daysCount);
+                        if (teamPair.containsKey(teamId)) {
+                            rateVo.setTeamName(teamPair.get(teamId));
+                        }
+                        // 匹配出当前小队 日报数量
+                        Long reportCount = 0l;
+                        if (teamReportCountPair.containsKey(teamId)) {
+                            reportCount = teamReportCountPair.getOrDefault(teamId, 0l);
+                            rateVo.setConstructionDays(reportCount);
+                        }
+                        // 当前小队 设备利用率 公式 reportCount/daysCount
+                        // 计算设备利用率(处理除数为0的情况)
+                        double rate = 0.0;
+                        if (reportCount > 0 && daysCount > 0) {
+                            rate = new BigDecimal((double) reportCount /  daysCount)
+                                    .setScale(4, RoundingMode.HALF_UP)  // 保留4位小数,四舍五入
+                                    .doubleValue();;
+                        }
+                        rateVo.setUtilizationRate(rate); // 存储计算结果
+                        rates.add(rateVo);
+                    });
+                }
+            }
+        }
+        // 将返回列表中的 部门名称 去除多语言标识
+        // 处理projectDeptName,截取~~首次出现前的字符串
+        if (CollUtil.isNotEmpty(rates)) {
+            rates.forEach(rateVo -> {
+                String originalName = rateVo.getTeamName();
+                if (StrUtil.isNotBlank(originalName) && originalName.contains("~~")) {
+                    // 截取首次~~之前的部分
+                    String processedName = originalName.substring(0, originalName.indexOf("~~"));
+                    rateVo.setTeamName(processedName);
+                }
+                // 空值或无~~标识时,保留原名称
+            });
+        }
+        rates.sort(Comparator.comparingDouble(TeamUtilizationRateVo::getUtilizationRate).reversed());
+        return success(rates);
+    }
+
 }
 

+ 3 - 0
yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/vo/IotDevicePageReqVO.java

@@ -146,4 +146,7 @@ public class IotDevicePageReqVO extends PageParam {
 
     @Schema(description = "油服设备编码")
     private String yfDeviceCode;
+
+    @Schema(description = "设备类别 集合")
+    private List<Long> assetClasses;
 }

+ 1 - 0
yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/dal/mysql/IotDeviceMapper.java

@@ -133,6 +133,7 @@ public interface IotDeviceMapper extends BaseMapperX<IotDeviceDO> {
                 .eqIfPresent(IotDeviceDO::getInfoId, reqVO.getInfoId())
                 .eqIfPresent(IotDeviceDO::getInfoType, reqVO.getInfoType())
                 .eqIfPresent(IotDeviceDO::getAssetClass, reqVO.getAssetClass())
+                .inIfPresent(IotDeviceDO::getAssetClass, reqVO.getAssetClasses())
                 .likeIfPresent(IotDeviceDO::getInfoName, reqVO.getInfoName())
                 .eqIfPresent(IotDeviceDO::getInfoRemark, reqVO.getInfoRemark())
                 .eqIfPresent(IotDeviceDO::getInfoUrl, reqVO.getInfoUrl())