瀏覽代碼

pms 工单完成情况 日报

zhangcl 3 天之前
父節點
當前提交
e19d1c18aa

+ 165 - 5
yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/stat/IotReportOrderController.java

@@ -1,15 +1,29 @@
 package cn.iocoder.yudao.module.pms.controller.admin.stat;
 
+import cn.hutool.core.collection.CollUtil;
+import cn.hutool.core.util.StrUtil;
 import cn.iocoder.yudao.framework.common.pojo.CommonResult;
 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.iotmainworkorderbom.vo.IotMainWorkOrderBomPageReqVO;
+import cn.iocoder.yudao.module.pms.controller.admin.iotprojecttask.vo.IotProjectTaskPageReqVO;
 import cn.iocoder.yudao.module.pms.controller.admin.maintain.vo.IotMaintainPageReqVO;
 import cn.iocoder.yudao.module.pms.controller.admin.stat.vo.AllOrderResp;
+import cn.iocoder.yudao.module.pms.controller.admin.vo.IotDevicePageReqVO;
+import cn.iocoder.yudao.module.pms.dal.dataobject.IotDeviceDO;
+import cn.iocoder.yudao.module.pms.dal.dataobject.iotmainworkorderbom.IotMainWorkOrderBomDO;
 import cn.iocoder.yudao.module.pms.dal.dataobject.iotopeationfill.IotOpeationFillDO;
+import cn.iocoder.yudao.module.pms.dal.dataobject.iotprojecttask.IotProjectTaskDO;
+import cn.iocoder.yudao.module.pms.dal.mysql.IotDeviceMapper;
 import cn.iocoder.yudao.module.pms.dal.mysql.inspect.IotInspectOrderDeviceMapper;
 import cn.iocoder.yudao.module.pms.dal.mysql.inspect.IotInspectOrderMapper;
 import cn.iocoder.yudao.module.pms.dal.mysql.iotmainworkorder.IotMainWorkOrderMapper;
+import cn.iocoder.yudao.module.pms.dal.mysql.iotmainworkorderbom.IotMainWorkOrderBomMapper;
 import cn.iocoder.yudao.module.pms.dal.mysql.iotopeationfill.IotOpeationFillMapper;
+import cn.iocoder.yudao.module.pms.dal.mysql.iotprojecttask.IotProjectTaskMapper;
+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.maintain.IotMaintainMapper;
 import cn.iocoder.yudao.module.system.api.dept.DeptApi;
 import cn.iocoder.yudao.module.system.service.dept.DeptService;
@@ -26,10 +40,8 @@ import org.springframework.web.bind.annotation.RestController;
 
 import javax.annotation.security.PermitAll;
 import javax.validation.Valid;
-import java.util.List;
-import java.util.Objects;
-import java.util.Set;
-import java.util.StringJoiner;
+import java.util.*;
+import java.util.concurrent.atomic.AtomicReference;
 import java.util.stream.Collectors;
 
 import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
@@ -49,6 +61,12 @@ public class IotReportOrderController {
     private final DeptService deptService;
     private final DeptApi deptApi;
     private final IotInspectOrderDeviceMapper iotInspectOrderDeviceMapper;
+    private final IotMainWorkOrderBomMapper iotMainWorkOrderBomMapper;
+    private final IotDeviceMapper iotDeviceMapper;
+    private final IotRhDailyReportMapper iotRhDailyReportMapper;
+    private final IotRyDailyReportMapper iotRyDailyReportMapper;
+    private final IotRdDailyReportMapper iotRdDailyReportMapper;
+    private final IotProjectTaskMapper iotProjectTaskMapper;
 
     @Operation(summary = "各工单状态数量统计")
     @GetMapping("/number")
@@ -57,7 +75,49 @@ public class IotReportOrderController {
         List<AllOrderResp> inspects = iotInspectOrderMapper.selectStatusNumber(pageReqVO);
         List<AllOrderResp> operations = iotOpeationFillMapper.selectStatusNumber(pageReqVO);
         List<AllOrderResp> workOrders = iotMainWorkOrderMapper.selectStatusNumber(pageReqVO);
-        return CommonResult.success(ImmutableMap.of("wx", maintains, "xj", inspects, "yx", operations, "by", workOrders));
+        // 日报
+        List<AllOrderResp> dailyReports = iotRhDailyReportMapper.selectStatusNumber(pageReqVO);
+        List<AllOrderResp> ryDailyReports = iotRyDailyReportMapper.selectStatusNumber(pageReqVO);
+        List<AllOrderResp> rdDailyReports = iotRdDailyReportMapper.selectStatusNumber(pageReqVO);
+        List<AllOrderResp> reports = new ArrayList<>();
+        AtomicReference<Long> noStatus = new AtomicReference<>(0l);
+        AtomicReference<Long> yesStatus = new AtomicReference<>(0l);
+        if (CollUtil.isNotEmpty(dailyReports)) {
+            dailyReports.forEach(report -> {
+                if ("0".equals(report.getStatus())) {
+                    noStatus.set(noStatus.get() + report.getNum());
+                } else {
+                    yesStatus.set(yesStatus.get() + report.getNum());
+                }
+            });
+        }
+        if (CollUtil.isNotEmpty(ryDailyReports)) {
+            ryDailyReports.forEach(report -> {
+                if ("0".equals(report.getStatus())) {
+                    noStatus.set(noStatus.get() + report.getNum());
+                } else {
+                    yesStatus.set(yesStatus.get() + report.getNum());
+                }
+            });
+        }
+        if (CollUtil.isNotEmpty(rdDailyReports)) {
+            rdDailyReports.forEach(report -> {
+                if ("0".equals(report.getStatus())) {
+                    noStatus.set(noStatus.get() + report.getNum());
+                } else {
+                    yesStatus.set(yesStatus.get() + report.getNum());
+                }
+            });
+        }
+        AllOrderResp noReport = new AllOrderResp();
+        noReport.setStatus("0");
+        noReport.setNum(Long.valueOf(noStatus.get()));
+        reports.add(noReport);
+        AllOrderResp yesReport = new AllOrderResp();
+        yesReport.setStatus("1");
+        yesReport.setNum(Long.valueOf(yesStatus.get()));
+        reports.add(yesReport);
+        return CommonResult.success(ImmutableMap.of("wx", maintains, "xj", inspects, "yx", operations, "by", workOrders, "rb", reports));
     }
 
 
@@ -76,6 +136,97 @@ public class IotReportOrderController {
         pageReqVO.setDeptIds(ids);
         IPage<AllOrderResp> allOrder = iotMaintainMapper.getAllOrder(new Page<>(pageReqVO.getPageNo(), pageReqVO.getPageSize()), pageReqVO);
         PageResult<AllOrderResp> result = new PageResult<>(allOrder.getRecords(), allOrder.getTotal());
+        Map<Long, String> orderPair = new HashMap<>();
+        Map<Long, Long> orderDeviceIdPair = new HashMap<>();
+        Map<Long, String> devicePair = new HashMap<>();
+        // 任务列表
+        Set<Long> taskIds = new HashSet<>();
+        // 设备id列表
+        Set<Long> totalDeviceIds = new HashSet<>();
+        // 日报设备列表 key设备id   value设备信息
+        Map<Long, String> reportDevicePair = new HashMap<>();
+        // 日报设备列表 key任务id   value多个设备信息列表
+        Map<Long, Set<Long>> taskDevicesPair = new HashMap<>();
+        // 日报设备列表 key任务id   value多个设备信息 分号分隔
+        Map<Long,String> taskDevicesStrPair = new HashMap<>();
+        if (CollUtil.isNotEmpty(result.getList())) {
+            Set<Long> orderIds = new HashSet<>();
+            result.getList().forEach(order -> {
+                if ("保养工单".equals(order.getType())) {
+                    orderIds.add(order.getId());
+                }
+                if ("瑞都日报".equals(order.getType()) || "瑞鹰日报".equals(order.getType()) || "瑞恒日报".equals(order.getType())) {
+                    taskIds.add(order.getTaskId());
+                }
+            });
+            if (CollUtil.isNotEmpty(taskIds)) {
+                IotProjectTaskPageReqVO reqVO = new IotProjectTaskPageReqVO();
+                reqVO.setTaskIds(new ArrayList<>(taskIds));
+                List<IotProjectTaskDO> tasks = iotProjectTaskMapper.selectList(reqVO);
+                if (CollUtil.isNotEmpty(tasks)) {
+                    tasks.forEach(task -> {
+                        Set<Long> deviceIds = task.getDeviceIds();
+                        if (CollUtil.isNotEmpty(deviceIds)) {
+                            totalDeviceIds.addAll(deviceIds);
+                            taskDevicesPair.put(task.getId(), task.getDeviceIds());
+                        }
+                    });
+                }
+                // 查询所有设备信息
+                IotDevicePageReqVO deviceReqVO = new IotDevicePageReqVO();
+                deviceReqVO.setDeviceIds(new ArrayList<>(totalDeviceIds));
+                List<IotDeviceDO> devices = iotDeviceMapper.selectListAlone(deviceReqVO);
+                if (CollUtil.isNotEmpty(devices)) {
+                    devices.forEach(device -> {
+                        reportDevicePair.put(device.getId(), StrUtil.join("|", device.getDeviceCode(), device.getDeviceName()));
+                    });
+                }
+                // 建立日报关联的任务id 与 任务下所有设备 编码名称 的对应关系
+                if (CollUtil.isNotEmpty(taskDevicesPair) && CollUtil.isNotEmpty(reportDevicePair)) {
+                    for (Map.Entry<Long, Set<Long>> entry : taskDevicesPair.entrySet()) {
+                        Long taskId = entry.getKey();
+                        Set<Long> deviceIds = entry.getValue();
+
+                        // 使用流处理获取设备名称,并用分号连接
+                        String deviceStr = deviceIds.stream()
+                                .map(reportDevicePair::get)  // 从 reportDevicePair 获取设备字符串
+                                .filter(StrUtil::isNotBlank)  // 过滤掉空值
+                                .collect(Collectors.joining(";"));  // 用分号连接
+
+                        if (StrUtil.isNotBlank(deviceStr)) {
+                            taskDevicesStrPair.put(taskId, deviceStr);
+                        }
+                    }
+                }
+            }
+            if (CollUtil.isNotEmpty(orderIds)) {
+                Set<Long> deviceIds = new HashSet<>();
+                // 查询所有保养工单的设备名称
+                IotMainWorkOrderBomPageReqVO bomReqVO = new IotMainWorkOrderBomPageReqVO();
+                bomReqVO.setWorkOrderIds(new ArrayList<>(orderIds));
+                List<IotMainWorkOrderBomDO> orderBoms = iotMainWorkOrderBomMapper.selectList(bomReqVO);
+                if (CollUtil.isNotEmpty(orderBoms)) {
+                    orderBoms.forEach(bom -> {
+                        deviceIds.add(bom.getDeviceId());
+                        orderDeviceIdPair.put(bom.getWorkOrderId(), bom.getDeviceId());
+                    });
+                    // 查询所有设备的编码 名称
+                    IotDevicePageReqVO deviceReqVO = new IotDevicePageReqVO();
+                    deviceReqVO.setDeviceIds(new ArrayList<>(deviceIds));
+                    List<IotDeviceDO> devices = iotDeviceMapper.selectListAlone(deviceReqVO);
+                    if (CollUtil.isNotEmpty(devices)) {
+                        devices.forEach(device -> {
+                            devicePair.put(device.getId(), StrUtil.join("|", device.getDeviceCode(), device.getDeviceName()));
+                        });
+                    }
+                    orderDeviceIdPair.forEach((orderId, deviceId) -> {
+                        if (devicePair.containsKey(deviceId)) {
+                            orderPair.put(orderId, devicePair.get(deviceId));
+                        }
+                    });
+                }
+            }
+        }
         List<AllOrderResp> collect = result.getList().stream().map(e -> {
             if ("巡检工单".equals(e.getType())){
                 String deviceInfo = iotInspectOrderDeviceMapper.getDeviceInfo(e.getId());
@@ -87,6 +238,15 @@ public class IotReportOrderController {
                     joiner.add(fillDO.getDeviceCode() + "/" + fillDO.getDeviceName());
                 }
                 e.setDevice(joiner.toString());
+            }  else if ("保养工单".equals(e.getType())) {
+                if (orderPair.containsKey(e.getId())) {
+                    e.setDevice(orderPair.get(e.getId()));
+                }
+            } else if ("瑞都日报".equals(e.getType()) || "瑞鹰日报".equals(e.getType()) || "瑞恒日报".equals(e.getType())) {
+                // 设置日报的设备信息
+                if (taskDevicesStrPair.containsKey(e.getTaskId())) {
+                    e.setDevice(taskDevicesStrPair.get(e.getTaskId()));
+                }
             }
             return e;
         }).collect(Collectors.toList());

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

@@ -112,5 +112,5 @@ public interface IotMainWorkOrderMapper extends BaseMapperX<IotMainWorkOrderDO>
                                                        @Param("deptIds") Collection<Long> deptIds, @Param("eligibleWorkOrderIds") Collection<Long> eligibleWorkOrderIds);
 
 
-    List<AllOrderResp> selectStatusNumber(@Param("reqVO") IotMaintainPageReqVO pageReqVO);
+    List<AllOrderResp> selectStatusNumber(@Param("reqVO") IotMaintainPageReqVO reqVO);
 }

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

@@ -6,6 +6,8 @@ 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.controller.admin.maintain.vo.IotMaintainPageReqVO;
+import cn.iocoder.yudao.module.pms.controller.admin.stat.vo.AllOrderResp;
 import cn.iocoder.yudao.module.pms.dal.dataobject.iotrddailyreport.IotRdDailyReportDO;
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import org.apache.ibatis.annotations.Mapper;
@@ -229,4 +231,11 @@ public interface IotRdDailyReportMapper extends BaseMapperX<IotRdDailyReportDO>
                                                         @Param("taskIds") Collection<Long> taskIds,
                                                         @Param("projectIds") Collection<Long> projectIds, @Param("deptIds") Collection<Long> deptIds);
 
+    /**
+     * 瑞都日报状态统计
+     * @param reqVO
+     * @return
+     */
+    List<AllOrderResp> selectStatusNumber(@Param("reqVO") IotMaintainPageReqVO reqVO);
+
 }

+ 8 - 0
yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/dal/mysql/iotrhdailyreport/IotRhDailyReportMapper.java

@@ -8,6 +8,8 @@ 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.iotrhdailyreport.vo.IotRhDailyReportPageReqVO;
+import cn.iocoder.yudao.module.pms.controller.admin.maintain.vo.IotMaintainPageReqVO;
+import cn.iocoder.yudao.module.pms.controller.admin.stat.vo.AllOrderResp;
 import cn.iocoder.yudao.module.pms.controller.admin.stat.vo.YearTotalGas;
 import cn.iocoder.yudao.module.pms.dal.dataobject.iotrhdailyreport.IotRhDailyReportDO;
 import com.baomidou.mybatisplus.core.metadata.IPage;
@@ -220,4 +222,10 @@ public interface IotRhDailyReportMapper extends BaseMapperX<IotRhDailyReportDO>
                 .last("limit 1"));
     }
 
+    /**
+     * 瑞恒日报状态统计
+     * @param reqVO
+     * @return
+     */
+    List<AllOrderResp> selectStatusNumber(@Param("reqVO") IotMaintainPageReqVO reqVO);
 }

+ 9 - 0
yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/dal/mysql/iotrydailyreport/IotRyDailyReportMapper.java

@@ -9,6 +9,8 @@ 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.iotrydailyreport.vo.IotRyDailyReportPageReqVO;
 import cn.iocoder.yudao.module.pms.controller.admin.iotrydailyreport.vo.IotRyDailyReportTaskCountVO;
+import cn.iocoder.yudao.module.pms.controller.admin.maintain.vo.IotMaintainPageReqVO;
+import cn.iocoder.yudao.module.pms.controller.admin.stat.vo.AllOrderResp;
 import cn.iocoder.yudao.module.pms.dal.dataobject.iotrydailyreport.IotRyDailyReportDO;
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import org.apache.ibatis.annotations.Mapper;
@@ -463,4 +465,11 @@ public interface IotRyDailyReportMapper extends BaseMapperX<IotRyDailyReportDO>
     List<IotRyDailyReportDO> ryDeptDailyReportsGroupIds(IPage<IotRyDailyReportDO> page, @Param("reqVO") IotRyDailyReportPageReqVO reqVO,
                                                         @Param("taskIds") Collection<Long> taskIds,
                                                         @Param("projectIds") Collection<Long> projectIds, @Param("deptIds") Collection<Long> deptIds);
+
+    /**
+     * 瑞鹰日报状态统计
+     * @param reqVO
+     * @return
+     */
+    List<AllOrderResp> selectStatusNumber(@Param("reqVO") IotMaintainPageReqVO reqVO);
 }

+ 2 - 3
yudao-module-pms/yudao-module-pms-biz/src/main/resources/mapper/static/IotMainWorkOrderMapper.xml

@@ -77,7 +77,7 @@
 
     <select id="selectStatusNumber" parameterType="cn.iocoder.yudao.module.pms.controller.admin.maintain.vo.IotMaintainPageReqVO"
             resultType="cn.iocoder.yudao.module.pms.controller.admin.stat.vo.AllOrderResp">
-        SELECT status, COUNT(status) AS num FROM rq_iot_main_work_order a
+        SELECT result AS status, COUNT(result) AS num FROM rq_iot_main_work_order a
         <where>
             a.deleted = 0
             <if test="reqVO.createTime[0] != null">
@@ -93,8 +93,7 @@
                 </foreach>
             </if>
         </where>
-
-        GROUP BY status
+        GROUP BY result
     </select>
 
 </mapper>

+ 210 - 3
yudao-module-pms/yudao-module-pms-biz/src/main/resources/mapper/static/IotMaintainMapper.xml

@@ -122,7 +122,9 @@
     <select id="getAllOrder" parameterType="cn.iocoder.yudao.module.pms.controller.admin.maintain.vo.IotMaintainPageReqVO"
             resultType="cn.iocoder.yudao.module.pms.controller.admin.stat.vo.AllOrderResp">
 select * from (
-        select a.id,'维修工单' as type, a.create_time as createTime,
+        select a.id,'维修工单' as type,
+               '' as taskId,
+               a.create_time as createTime,
         CASE
         WHEN a.status = 'todo' THEN '未完成'
         WHEN a.status = 'finished' THEN '已完成'
@@ -168,7 +170,9 @@ select * from (
             </if>
         </where>
         UNION ALL
-        select b.id,'巡检工单' as type, b.create_time as createTime,
+        select b.id,'巡检工单' as type,
+                '' as taskId,
+               b.create_time as createTime,
         CASE
         WHEN b.status = 'todo' THEN '未完成'
         WHEN b.status = 'finished' THEN '已完成'
@@ -213,9 +217,212 @@ select * from (
                 </foreach>
             </if>
         </where>
-        union all
+
+        UNION ALL
+
+        select b.id,'保养工单' as type,
+                '' as taskId,
+               b.create_time as createTime,
+        CASE
+        WHEN b.result = 1 THEN '未完成'
+        WHEN b.result = 2 THEN '已完成'
+        ELSE '' -- 兼容其他未知状态值
+        END AS status, '' as device,b.dept_id as deptId,
+        CASE
+        WHEN d.type = 1 THEN COALESCE(d.`name`, '')
+        WHEN d.type = 2 THEN COALESCE(p1.`name`, '')
+        WHEN d.type = 3 THEN COALESCE(p2.`name`, '')
+        ELSE ''
+        END AS company,
+        -- 按type规则填充project字段
+        CASE
+        WHEN d.type = 2 THEN COALESCE(d.`name`, '')
+        WHEN d.type = 3 THEN COALESCE(p1.`name`, '')
+        ELSE ''
+        END AS project,
+        -- 按type规则填充deptName字段(仅type=3时有值)
+        CASE
+        WHEN d.type = 3 THEN COALESCE(d.`name`, '')
+        ELSE ''
+        END AS deptName
+        from rq_iot_main_work_order b
+        -- 左关联当前部门(避免主表数据丢失)
+        LEFT JOIN system_dept d ON b.dept_id = d.id
+        -- 左关联父级部门(type=2/3时用)
+        LEFT JOIN system_dept p1 ON d.parent_id = p1.id
+        -- 左关联祖父级部门(type=3时用)
+        LEFT JOIN system_dept p2 ON p1.parent_id = p2.id
+        <where>
+            b.deleted = 0
+            <if test="reqVO.createTime[0] != null">
+                AND b.create_time &gt;= #{reqVO.createTime[0]}
+            </if>
+            <if test="reqVO.createTime.length > 1 and reqVO.createTime[1] != null">
+                AND b.create_time &lt;= #{reqVO.createTime[1]}
+            </if>
+            <if test="reqVO.deptIds != null and reqVO.deptIds.size &gt; 0">
+                AND b.dept_id IN
+                <foreach collection="reqVO.deptIds" index="index" item="key" open="(" separator="," close=")">
+                    #{key}
+                </foreach>
+            </if>
+        </where>
+
+        UNION ALL
+
+        select b.id,'瑞恒日报' as type,
+            b.task_id as taskId,
+            b.create_time as createTime,
+        CASE
+        WHEN b.status = 0 THEN '未完成'
+        WHEN b.status = 1 THEN '已完成'
+        ELSE '' -- 兼容其他未知状态值
+        END AS status, '' as device,b.dept_id as deptId,
+        CASE
+        WHEN d.type = 1 THEN COALESCE(d.`name`, '')
+        WHEN d.type = 2 THEN COALESCE(p1.`name`, '')
+        WHEN d.type = 3 THEN COALESCE(p2.`name`, '')
+        ELSE ''
+        END AS company,
+        -- 按type规则填充project字段
+        CASE
+        WHEN d.type = 2 THEN COALESCE(d.`name`, '')
+        WHEN d.type = 3 THEN COALESCE(p1.`name`, '')
+        ELSE ''
+        END AS project,
+        -- 按type规则填充deptName字段(仅type=3时有值)
+        CASE
+        WHEN d.type = 3 THEN COALESCE(d.`name`, '')
+        ELSE ''
+        END AS deptName
+        from rq_iot_rh_daily_report b
+        -- 左关联当前部门(避免主表数据丢失)
+        LEFT JOIN system_dept d ON b.dept_id = d.id
+        -- 左关联父级部门(type=2/3时用)
+        LEFT JOIN system_dept p1 ON d.parent_id = p1.id
+        -- 左关联祖父级部门(type=3时用)
+        LEFT JOIN system_dept p2 ON p1.parent_id = p2.id
+        <where>
+            b.deleted = 0
+            <if test="reqVO.createTime[0] != null">
+                AND b.create_time &gt;= #{reqVO.createTime[0]}
+            </if>
+            <if test="reqVO.createTime.length > 1 and reqVO.createTime[1] != null">
+                AND b.create_time &lt;= #{reqVO.createTime[1]}
+            </if>
+            <if test="reqVO.deptIds != null and reqVO.deptIds.size &gt; 0">
+                AND b.dept_id IN
+                <foreach collection="reqVO.deptIds" index="index" item="key" open="(" separator="," close=")">
+                    #{key}
+                </foreach>
+            </if>
+        </where>
+
+        UNION ALL
+
+        select b.id,'瑞鹰日报' as type,
+            b.task_id taskId,
+            b.create_time as createTime,
+        CASE
+        WHEN b.status = 0 THEN '未完成'
+        WHEN b.status = 1 THEN '已完成'
+        ELSE '' -- 兼容其他未知状态值
+        END AS status, '' as device,b.dept_id as deptId,
+        CASE
+        WHEN d.type = 1 THEN COALESCE(d.`name`, '')
+        WHEN d.type = 2 THEN COALESCE(p1.`name`, '')
+        WHEN d.type = 3 THEN COALESCE(p2.`name`, '')
+        ELSE ''
+        END AS company,
+        -- 按type规则填充project字段
+        CASE
+        WHEN d.type = 2 THEN COALESCE(d.`name`, '')
+        WHEN d.type = 3 THEN COALESCE(p1.`name`, '')
+        ELSE ''
+        END AS project,
+        -- 按type规则填充deptName字段(仅type=3时有值)
+        CASE
+        WHEN d.type = 3 THEN COALESCE(d.`name`, '')
+        ELSE ''
+        END AS deptName
+        from rq_iot_ry_daily_report b
+        -- 左关联当前部门(避免主表数据丢失)
+        LEFT JOIN system_dept d ON b.dept_id = d.id
+        -- 左关联父级部门(type=2/3时用)
+        LEFT JOIN system_dept p1 ON d.parent_id = p1.id
+        -- 左关联祖父级部门(type=3时用)
+        LEFT JOIN system_dept p2 ON p1.parent_id = p2.id
+        <where>
+            b.deleted = 0
+            <if test="reqVO.createTime[0] != null">
+                AND b.create_time &gt;= #{reqVO.createTime[0]}
+            </if>
+            <if test="reqVO.createTime.length > 1 and reqVO.createTime[1] != null">
+                AND b.create_time &lt;= #{reqVO.createTime[1]}
+            </if>
+            <if test="reqVO.deptIds != null and reqVO.deptIds.size &gt; 0">
+                AND b.dept_id IN
+                <foreach collection="reqVO.deptIds" index="index" item="key" open="(" separator="," close=")">
+                    #{key}
+                </foreach>
+            </if>
+        </where>
+
+        UNION ALL
+
+        select b.id,'瑞都日报' as type,
+            b.task_id as taskId,
+            b.create_time as createTime,
+        CASE
+        WHEN b.status = 0 THEN '未完成'
+        WHEN b.status = 1 THEN '已完成'
+        ELSE '' -- 兼容其他未知状态值
+        END AS status, '' as device,b.dept_id as deptId,
+        CASE
+        WHEN d.type = 1 THEN COALESCE(d.`name`, '')
+        WHEN d.type = 2 THEN COALESCE(p1.`name`, '')
+        WHEN d.type = 3 THEN COALESCE(p2.`name`, '')
+        ELSE ''
+        END AS company,
+        -- 按type规则填充project字段
+        CASE
+        WHEN d.type = 2 THEN COALESCE(d.`name`, '')
+        WHEN d.type = 3 THEN COALESCE(p1.`name`, '')
+        ELSE ''
+        END AS project,
+        -- 按type规则填充deptName字段(仅type=3时有值)
+        CASE
+        WHEN d.type = 3 THEN COALESCE(d.`name`, '')
+        ELSE ''
+        END AS deptName
+        from rq_iot_rd_daily_report b
+        -- 左关联当前部门(避免主表数据丢失)
+        LEFT JOIN system_dept d ON b.dept_id = d.id
+        -- 左关联父级部门(type=2/3时用)
+        LEFT JOIN system_dept p1 ON d.parent_id = p1.id
+        -- 左关联祖父级部门(type=3时用)
+        LEFT JOIN system_dept p2 ON p1.parent_id = p2.id
+        <where>
+            b.deleted = 0
+            <if test="reqVO.createTime[0] != null">
+                AND b.create_time &gt;= #{reqVO.createTime[0]}
+            </if>
+            <if test="reqVO.createTime.length > 1 and reqVO.createTime[1] != null">
+                AND b.create_time &lt;= #{reqVO.createTime[1]}
+            </if>
+            <if test="reqVO.deptIds != null and reqVO.deptIds.size &gt; 0">
+                AND b.dept_id IN
+                <foreach collection="reqVO.deptIds" index="index" item="key" open="(" separator="," close=")">
+                    #{key}
+                </foreach>
+            </if>
+        </where>
+
+        UNION ALL
+
         SELECT
             c.id,
+            '' AS taskId,
         '运行记录' AS type,
         c.create_time AS createTime,
         -- 核心优化:status 数值转中文描述

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

@@ -300,4 +300,25 @@
         WHERE rn = 1
     </select>
 
+    <select id="selectStatusNumber" parameterType="cn.iocoder.yudao.module.pms.controller.admin.maintain.vo.IotMaintainPageReqVO"
+            resultType="cn.iocoder.yudao.module.pms.controller.admin.stat.vo.AllOrderResp">
+        SELECT status AS status, COUNT(status) AS num FROM rq_iot_rd_daily_report a
+        <where>
+            a.deleted = 0
+            <if test="reqVO.createTime[0] != null">
+                AND a.create_time &gt;= #{reqVO.createTime[0]}
+            </if>
+            <if test="reqVO.createTime.length > 1 and reqVO.createTime[1] != null">
+                AND a.create_time &lt;= #{reqVO.createTime[1]}
+            </if>
+            <if test="reqVO.deptIds != null and reqVO.deptIds.size &gt; 0">
+                AND a.dept_id IN
+                <foreach collection="reqVO.deptIds" index="index" item="key" open="(" separator="," close=")">
+                    #{key}
+                </foreach>
+            </if>
+        </where>
+        GROUP BY status
+    </select>
+
 </mapper>

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

@@ -446,4 +446,25 @@
         </if>
     </select>
 
+    <select id="selectStatusNumber" parameterType="cn.iocoder.yudao.module.pms.controller.admin.maintain.vo.IotMaintainPageReqVO"
+            resultType="cn.iocoder.yudao.module.pms.controller.admin.stat.vo.AllOrderResp">
+        SELECT status AS status, COUNT(status) AS num FROM rq_iot_rh_daily_report a
+        <where>
+            a.deleted = 0
+            <if test="reqVO.createTime[0] != null">
+                AND a.create_time &gt;= #{reqVO.createTime[0]}
+            </if>
+            <if test="reqVO.createTime.length > 1 and reqVO.createTime[1] != null">
+                AND a.create_time &lt;= #{reqVO.createTime[1]}
+            </if>
+            <if test="reqVO.deptIds != null and reqVO.deptIds.size &gt; 0">
+                AND a.dept_id IN
+                <foreach collection="reqVO.deptIds" index="index" item="key" open="(" separator="," close=")">
+                    #{key}
+                </foreach>
+            </if>
+        </where>
+        GROUP BY status
+    </select>
+
 </mapper>

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

@@ -330,4 +330,25 @@
         WHERE rn = 1
     </select>
 
+    <select id="selectStatusNumber" parameterType="cn.iocoder.yudao.module.pms.controller.admin.maintain.vo.IotMaintainPageReqVO"
+            resultType="cn.iocoder.yudao.module.pms.controller.admin.stat.vo.AllOrderResp">
+        SELECT status AS status, COUNT(status) AS num FROM rq_iot_ry_daily_report a
+        <where>
+            a.deleted = 0
+            <if test="reqVO.createTime[0] != null">
+                AND a.create_time &gt;= #{reqVO.createTime[0]}
+            </if>
+            <if test="reqVO.createTime.length > 1 and reqVO.createTime[1] != null">
+                AND a.create_time &lt;= #{reqVO.createTime[1]}
+            </if>
+            <if test="reqVO.deptIds != null and reqVO.deptIds.size &gt; 0">
+                AND a.dept_id IN
+                <foreach collection="reqVO.deptIds" index="index" item="key" open="(" separator="," close=")">
+                    #{key}
+                </foreach>
+            </if>
+        </where>
+        GROUP BY status
+    </select>
+
 </mapper>