ソースを参照

Merge remote-tracking branch 'origin/master'

zhangcl 2 日 前
コミット
c820bbf4ec
17 ファイル変更471 行追加66 行削除
  1. 105 0
      yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/inspect/order/IotInspectOrderController.java
  2. 0 1
      yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/inspect/order/IotInspectOrderDetailController.java
  3. 1 0
      yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/inspect/order/vo/IotInspectOrderDetailPageReqVO.java
  4. 17 12
      yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/inspect/order/vo/IotInspectOrderDetailRespVO.java
  5. 2 0
      yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/inspect/order/vo/IotInspectOrderRespVO.java
  6. 42 0
      yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/inspect/order/vo/IotReportInspectOrderRespVO.java
  7. 33 0
      yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/stat/IotRepairController.java
  8. 7 50
      yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/stat/IotReportDeviceController.java
  9. 60 1
      yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/stat/IotReportFailureController.java
  10. 8 0
      yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/stat/vo/ReportCost.java
  11. 6 0
      yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/vo/IotDeviceSimple.java
  12. 66 0
      yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/vo/IotReportDeviceRespVO.java
  13. 1 0
      yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/dal/mysql/IotDeviceMapper.java
  14. 3 0
      yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/dal/mysql/inspect/IotInspectOrderMapper.java
  15. 55 0
      yudao-module-pms/yudao-module-pms-biz/src/main/resources/mapper/static/IotDeviceMapper.xml
  16. 63 0
      yudao-module-pms/yudao-module-pms-biz/src/main/resources/mapper/static/IotInspectOrderMapper.xml
  17. 2 2
      yudao-module-pms/yudao-module-pms-biz/src/main/resources/mapper/static/IotMaintainMapper.xml

+ 105 - 0
yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/inspect/order/IotInspectOrderController.java

@@ -16,7 +16,10 @@ import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils;
 import cn.iocoder.yudao.framework.tenant.core.aop.TenantIgnore;
 import cn.iocoder.yudao.module.pms.controller.admin.inspect.order.vo.*;
 import cn.iocoder.yudao.module.pms.controller.admin.stat.DeptUtil;
+import cn.iocoder.yudao.module.pms.controller.admin.vo.IotDevicePageReqVO;
+import cn.iocoder.yudao.module.pms.controller.admin.vo.IotDeviceRespVO;
 import cn.iocoder.yudao.module.pms.controller.admin.vo.IotDeviceSimple;
+import cn.iocoder.yudao.module.pms.controller.admin.vo.IotReportDeviceRespVO;
 import cn.iocoder.yudao.module.pms.dal.dataobject.IotDeviceDO;
 import cn.iocoder.yudao.module.pms.dal.dataobject.inspect.IotInspectOrderDO;
 import cn.iocoder.yudao.module.pms.dal.dataobject.inspect.IotInspectOrderDetailDO;
@@ -400,6 +403,61 @@ public class IotInspectOrderController {
         return success(new PageResult<>(collect, pageResult.getTotal()));
     }
 
+
+    @GetMapping("/report/exception/item/export-excel")
+    @Operation(summary = "导出巡检工单巡检异常点 Excel")
+    @PreAuthorize("@ss.hasPermission('rq:iot-inspect-order-detail:export')")
+    @ApiAccessLog(operateType = EXPORT)
+    public void exportReportExceptionItem(@Valid IotInspectOrderDetailPageReqVO pageReqVO,
+                                          HttpServletResponse response) throws IOException {
+        Set<Long> ids = new HashSet<>();
+        String companyCode;
+        if (Objects.isNull(pageReqVO.getDeptId())){
+            Long loginUserDeptId = SecurityFrameworkUtils.getLoginUserDeptId();
+            companyCode = deptUtil.getCompanyCode(loginUserDeptId);
+            ids = deptUtil.getDeptIds(companyCode);
+        } else {
+            companyCode = deptUtil.getCompanyCode(pageReqVO.getDeptId());
+            ids = deptService.getChildDeptIdListFromCache(pageReqVO.getDeptId());
+            ids.add(pageReqVO.getDeptId());
+        }
+        Set<Long> deviceIds = new HashSet<>();
+        if (StringUtils.isNotBlank(pageReqVO.getDeviceCode())) {
+            IotDevicePageReqVO devicePageReqVO = new IotDevicePageReqVO();
+            devicePageReqVO.setDeviceCode(pageReqVO.getDeviceCode());
+            deviceIds = iotDeviceMapper.selectList(devicePageReqVO).stream().map(IotDeviceDO::getId).collect(Collectors.toSet());
+        }
+        Set<Long> orderIds = new HashSet<>();
+        if (StringUtils.isNotBlank(pageReqVO.getOrderName())) {
+            IotInspectOrderPageReqVO iotInspectOrderPageReqVO = new IotInspectOrderPageReqVO();
+            iotInspectOrderPageReqVO.setInspectOrderTitle(pageReqVO.getOrderName());
+            orderIds = iotInspectOrderMapper.selectList(iotInspectOrderPageReqVO).stream().map(IotInspectOrderDO::getId).collect(Collectors.toSet());
+        }
+        pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE);
+        pageReqVO.setIfNormal(false);
+        List<IotInspectOrderDetailDO> list = iotInspectOrderDetailMapper.selectItemPage(pageReqVO, ids, deviceIds, orderIds).getList();
+        List<IotInspectOrderDetailRespVO> bean = BeanUtils.toBean(list, IotInspectOrderDetailRespVO.class);
+        bean.forEach(e -> {
+            if (Objects.nonNull(e.getDeviceId())) {
+                IotDeviceDO iotDevice = iotDeviceService.getIotDevice(e.getDeviceId());
+                if (Objects.nonNull(iotDevice)) {
+                    e.setDeviceCode(iotDevice.getDeviceCode());
+                    e.setDeviceName(iotDevice.getDeviceName());
+                }
+            }
+            if (Objects.nonNull(e.getOrderId())) {
+                IotInspectOrderDO iotInspectOrder = iotInspectOrderService.getIotInspectOrder(e.getOrderId());
+                if (Objects.nonNull(iotInspectOrder)) {
+                    e.setOrderName(iotInspectOrder.getInspectOrderTitle());
+                    e.setCharge(iotInspectOrder.getChargeName());
+                }
+            }
+            e.setResult(e.getIfNormal()?"正常":"异常");
+        });
+        // 导出 Excel
+        ExcelUtils.write(response, "巡检工单异常点统计.xls", "数据", IotInspectOrderDetailRespVO.class,
+                BeanUtils.toBean(bean, IotInspectOrderDetailRespVO.class));
+    }
     @GetMapping("/exception/device")
     public CommonResult<PageResult<IotDeviceSimple>> getExceptionDevice(@Valid IotInspectOrderPageReqVO pageReqVO) {
         Set<Long> ids;
@@ -416,4 +474,51 @@ public class IotInspectOrderController {
         PageResult<IotDeviceSimple> result = new PageResult<>(exceptionDevicePage.getRecords(), exceptionDevicePage.getTotal());
         return success(result);
     }
+
+
+    @GetMapping("/report/export-excel")
+    @Operation(summary = "导出巡检工单巡检异常点 Excel")
+    @PreAuthorize("@ss.hasPermission('rq:iot-inspect-order-detail:export')")
+    @ApiAccessLog(operateType = EXPORT)
+    public void exportReport(@Valid IotInspectOrderPageReqVO pageReqVO,
+                                          HttpServletResponse response) throws IOException {
+        Set<Long> ids;
+        if (Objects.isNull(pageReqVO.getDeptId())){
+            Long loginUserDeptId = SecurityFrameworkUtils.getLoginUserDeptId();
+            String companyCode = deptUtil.getCompanyCode(loginUserDeptId);
+            ids = deptUtil.getDeptIds(companyCode);
+            ids.add(pageReqVO.getDeptId());
+        } else {
+            ids = deptService.getChildDeptIdListFromCache(pageReqVO.getDeptId());
+            ids.add(pageReqVO.getDeptId());
+        }
+        pageReqVO.setDeptIds(ids);
+        List<IotInspectOrderRespVO> bean = iotInspectOrderMapper.selectExport(pageReqVO);
+        List<IotReportInspectOrderRespVO> list = BeanUtils.toBean(bean, IotReportInspectOrderRespVO.class);
+        // 导出 Excel
+        ExcelUtils.write(response, "巡检报表统计.xls", "数据", IotReportInspectOrderRespVO.class, list);
+    }
+
+    @GetMapping("/report/exception/device/export-excel")
+    @Operation(summary = "导出巡检工单巡检异常点 Excel")
+    @PreAuthorize("@ss.hasPermission('rq:iot-inspect-order-detail:export')")
+    @ApiAccessLog(operateType = EXPORT)
+    public void exportReportExceptionDevice(@Valid IotInspectOrderPageReqVO pageReqVO,
+                             HttpServletResponse response) throws IOException {
+        Set<Long> ids;
+        if (Objects.isNull(pageReqVO.getDeptId())){
+            Long loginUserDeptId = SecurityFrameworkUtils.getLoginUserDeptId();
+            String companyCode = deptUtil.getCompanyCode(loginUserDeptId);
+            ids = deptUtil.getDeptIds(companyCode);
+        } else {
+            ids = deptService.getChildDeptIdListFromCache(pageReqVO.getDeptId());
+            ids.add(pageReqVO.getDeptId());
+        }
+        pageReqVO.setDeptIds(ids);
+        pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE);
+        List<IotDeviceSimple> records = iotInspectOrderDetailMapper.getExceptionDevicePage(new Page<>(pageReqVO.getPageNo(), pageReqVO.getPageSize()), pageReqVO).getRecords();
+        // 导出 Excel
+        ExcelUtils.write(response, "巡检异常设备统计.xls", "数据", IotDeviceSimple.class, records);
+    }
+
 }

+ 0 - 1
yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/inspect/order/IotInspectOrderDetailController.java

@@ -191,5 +191,4 @@ public class IotInspectOrderDetailController {
         }).collect(Collectors.toList());
         return success(new PageResult<>(collect, deviceStatus.getTotal()));
     }
-
 }

+ 1 - 0
yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/inspect/order/vo/IotInspectOrderDetailPageReqVO.java

@@ -42,6 +42,7 @@ public class IotInspectOrderDetailPageReqVO extends PageParam {
 
     @Schema(description = "部门id", example = "26288")
     private Long deptId;
+    private Set<Long> deptIds;
 
     private String status;
 

+ 17 - 12
yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/inspect/order/vo/IotInspectOrderDetailRespVO.java

@@ -13,26 +13,36 @@ import com.alibaba.excel.annotation.*;
 public class IotInspectOrderDetailRespVO {
 
     @Schema(description = "主键id", requiredMode = Schema.RequiredMode.REQUIRED, example = "4075")
-    @ExcelProperty("主键id")
+//    @ExcelProperty("主键id")
     private Long id;
-
+    @ExcelProperty("工单名称")
+    private String orderName;
+    @ExcelProperty("历史编码")
+    private String deviceCode;
+    @ExcelProperty("设备名称")
+    private String deviceName;
+    @ExcelProperty("责任人")
+    private String charge;
     @Schema(description = "工单id", requiredMode = Schema.RequiredMode.REQUIRED, example = "9096")
-    @ExcelProperty("工单id")
+//    @ExcelProperty("工单id")
     private Long orderId;
 
     @Schema(description = "设备id", requiredMode = Schema.RequiredMode.REQUIRED, example = "28723")
-    @ExcelProperty("设备id")
+//    @ExcelProperty("设备id")
     private Long deviceId;
 
     @Schema(description = "巡检项id", requiredMode = Schema.RequiredMode.REQUIRED, example = "14105")
-    @ExcelProperty("巡检项id")
+//    @ExcelProperty("巡检项id")
     private Long itemId;
+    @ExcelProperty("巡检项")
     private String item;
 
     @Schema(description = "是否正常", requiredMode = Schema.RequiredMode.REQUIRED)
-    @ExcelProperty("是否正常")
+//    @ExcelProperty("巡检结果")
     private Boolean ifNormal;
 
+    @ExcelProperty("巡检结果")
+    private String result;
     @Schema(description = "异常描述", example = "你猜")
     @ExcelProperty("异常描述")
     private String description;
@@ -50,12 +60,7 @@ public class IotInspectOrderDetailRespVO {
     private LocalDateTime createTime;
 
     @Schema(description = "部门id", example = "26288")
-    @ExcelProperty("部门id")
+//    @ExcelProperty("部门id")
     private Long deptId;
 
-    private String deviceName;
-    private String deviceCode;
-    private String orderName;
-    private String charge;
-
 }

+ 2 - 0
yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/inspect/order/vo/IotInspectOrderRespVO.java

@@ -30,6 +30,8 @@ public class IotInspectOrderRespVO {
     @ExcelProperty("巡检工单状态")
     private String status;
 
+    private String orderStatus;
+
     @Schema(description = "备注", example = "你猜")
     @ExcelProperty("备注")
     private String remark;

+ 42 - 0
yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/inspect/order/vo/IotReportInspectOrderRespVO.java

@@ -0,0 +1,42 @@
+package cn.iocoder.yudao.module.pms.controller.admin.inspect.order.vo;
+
+import cn.iocoder.yudao.module.pms.controller.admin.inspect.order.IotInspectOrderController;
+import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
+import com.alibaba.excel.annotation.ExcelProperty;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+import java.time.LocalDateTime;
+import java.util.List;
+
+@Schema(description = "管理后台 - 巡检工单 Response VO")
+@Data
+@ExcelIgnoreUnannotated
+public class IotReportInspectOrderRespVO {
+
+
+    @Schema(description = "巡检工单名", requiredMode = Schema.RequiredMode.REQUIRED)
+    @ExcelProperty("巡检工单名")
+    private String inspectOrderTitle;
+
+    @Schema(description = "巡检工单编码", requiredMode = Schema.RequiredMode.REQUIRED)
+    @ExcelProperty("巡检工单编码")
+    private String inspectOrderCode;
+    @ExcelProperty("公司")
+    private String company;
+    @ExcelProperty("项目部")
+    private String project;
+    @ExcelProperty("所在部门")
+    private String deptName;
+    @ExcelProperty("工单类型")
+    private String type;
+    @Schema(description = "巡检工单状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
+    @ExcelProperty("巡检工单状态")
+    private String orderStatus;
+
+    private String reason;
+    @ExcelProperty("设备明细")
+    private String deviceInfo;
+    @ExcelProperty("负责人")
+    private String chargeName;
+}

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

@@ -1,9 +1,15 @@
 package cn.iocoder.yudao.module.pms.controller.admin.stat;
 
+import cn.iocoder.yudao.framework.apilog.core.annotation.ApiAccessLog;
 import cn.iocoder.yudao.framework.common.pojo.CommonResult;
 import cn.iocoder.yudao.framework.common.pojo.PageParam;
 import cn.iocoder.yudao.framework.common.pojo.PageResult;
+import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
+import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;
 import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils;
+import cn.iocoder.yudao.module.pms.controller.admin.inspect.order.vo.IotInspectOrderPageReqVO;
+import cn.iocoder.yudao.module.pms.controller.admin.inspect.order.vo.IotInspectOrderRespVO;
+import cn.iocoder.yudao.module.pms.controller.admin.inspect.order.vo.IotReportInspectOrderRespVO;
 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;
@@ -13,20 +19,25 @@ import cn.iocoder.yudao.module.pms.service.iotmainworkorder.IotMainWorkOrderServ
 import cn.iocoder.yudao.module.pms.service.maintain.IotMaintainService;
 import cn.iocoder.yudao.module.system.service.dept.DeptService;
 import com.google.common.collect.ImmutableMap;
+import io.swagger.v3.oas.annotations.Operation;
 import io.swagger.v3.oas.annotations.tags.Tag;
 import lombok.AllArgsConstructor;
+import org.springframework.security.access.prepost.PreAuthorize;
 import org.springframework.validation.annotation.Validated;
 import org.springframework.web.bind.annotation.GetMapping;
 import org.springframework.web.bind.annotation.RequestMapping;
 import org.springframework.web.bind.annotation.RestController;
 
 import javax.annotation.security.PermitAll;
+import javax.servlet.http.HttpServletResponse;
 import javax.validation.Valid;
+import java.io.IOException;
 import java.math.BigDecimal;
 import java.math.RoundingMode;
 import java.time.LocalDateTime;
 import java.util.*;
 
+import static cn.iocoder.yudao.framework.apilog.core.enums.OperateTypeEnum.EXPORT;
 import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
 
 @Tag(name = "报表维修接口")
@@ -197,4 +208,26 @@ public class IotRepairController {
         PageResult<ReportCost> page = iotMaintainService.getReportCost(pageReqVO);
         return success(page);
     }
+
+
+    @GetMapping("/report/export-excel")
+    @Operation(summary = "运维成本导出 Excel")
+    @ApiAccessLog(operateType = EXPORT)
+    public void exportReport(@Valid IotMaintainPageReqVO pageReqVO,
+                             HttpServletResponse response) throws IOException {
+        Set<Long> ids;
+        if (Objects.isNull(pageReqVO.getDeptId())){
+            Long loginUserDeptId = SecurityFrameworkUtils.getLoginUserDeptId();
+            String companyCode = deptUtil.getCompanyCode(loginUserDeptId);
+            ids = deptUtil.getDeptIds(companyCode);
+        } else {
+            ids = deptService.getChildDeptIdListFromCache(pageReqVO.getDeptId());
+            ids.add(pageReqVO.getDeptId());
+        }
+        pageReqVO.setDeptIds(ids);
+        pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE);
+        PageResult<ReportCost> page = iotMaintainService.getReportCost(pageReqVO);
+        // 导出 Excel
+        ExcelUtils.write(response, "运维成本统计.xls", "数据", ReportCost.class, page.getList());
+    }
 }

+ 7 - 50
yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/stat/IotReportDeviceController.java

@@ -5,10 +5,13 @@ import cn.iocoder.yudao.framework.common.exception.ErrorCode;
 import cn.iocoder.yudao.framework.common.exception.ServiceException;
 import cn.iocoder.yudao.framework.common.pojo.CommonResult;
 import cn.iocoder.yudao.framework.common.pojo.PageResult;
+import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
+import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;
 import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils;
 import cn.iocoder.yudao.module.pms.controller.admin.vo.IotDevicePageReqVO;
 import cn.iocoder.yudao.module.pms.controller.admin.vo.IotDeviceRespVO;
 import cn.iocoder.yudao.module.pms.controller.admin.vo.IotDeviceSimple;
+import cn.iocoder.yudao.module.pms.controller.admin.vo.IotReportDeviceRespVO;
 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.mysql.IotDeviceMapper;
@@ -325,56 +328,10 @@ public class IotReportDeviceController {
             ids = deptService.getChildDeptIdListFromCache(pageReqVO.getDeptId());
             ids.add(pageReqVO.getDeptId());
         }
-        PageResult<IotDeviceDO> pageResult = iotDeviceMapper.selectPageReport(pageReqVO, ids);
-        if (CollUtil.isEmpty(pageResult.getList())) {
-            throw new ServiceException(new ErrorCode(2,"导出异常"));
-        }
-        Map<Long, DeptDO> deptMap = deptService.getDeptMap(
-                convertList(pageResult.getList(), IotDeviceDO::getDeptId));
-        List<IotDeviceRespVO> iotDeviceRespVOS = IotDeviceConvert.INSTANCE.convertList(pageResult.getList(), deptMap);
-        iotDeviceRespVOS.forEach(e ->{
-            if (Objects.nonNull(e.getAssetClass())) {
-                IotProductClassifyDO iotProductClassify = iotProductClassifyService.getIotProductClassify(e.getAssetClass());
-                e.setAssetClassName(Objects.nonNull(iotProductClassify)?iotProductClassify.getName():"");
-            }
-            SupplierDO supplierDO = supplierService.get(e.getManufacturerId());
-            if (Objects.nonNull(supplierDO)) {
-                e.setManufacturer(supplierDO.getName());
-            }
-            DeptRespDTO dept = deptApi.getDept(e.getDeptId());
-            if (Objects.nonNull(dept)) {
-                if ("1".equals(dept.getType())) {
-                    e.setCompany(dept.getName());
-                } else if ("2".equals(dept.getType())) {
-                    e.setProject(dept.getName());
-                    DeptRespDTO dept1 = deptApi.getDept(dept.getParentId());
-                    if (Objects.nonNull(dept1)) {
-                        e.setCompany(dept1.getName());
-                    }
-                } else if ("3".equals(dept.getType())) {
-                    e.setDeptName(dept.getName());
-                    DeptRespDTO dept1 = deptApi.getDept(dept.getParentId());
-                    if (Objects.nonNull(dept1)) {
-                        e.setProject(dept1.getName());
-                        DeptRespDTO dept2 = deptApi.getDept(dept1.getParentId());
-                        if (Objects.nonNull(dept2)) {
-                            e.setCompany(dept2.getName());
-                        }
-                    }
-                }
-            }
-        });
-
-        // 2. 下载配置(复用工具方法)
-        setExcelDownloadResponse(response, "设备报表");
-
-
-        String[] includeFieldArr = includeFields.split(",");
-        EasyExcel.write(response.getOutputStream(), IotDeviceRespVO.class)
-                .sheet("设备报表数据")
-                .includeColumnFiledNames(Arrays.asList(includeFieldArr))
-                // 核心方法:正向筛选
-                .doWrite(iotDeviceRespVOS);
+        pageReqVO.setDeptIds(new ArrayList<>(ids));
+        List<IotDeviceRespVO> iotDeviceRespVOS = iotDeviceMapper.selectExport(pageReqVO);
+        List<IotReportDeviceRespVO> bean = BeanUtils.toBean(iotDeviceRespVOS, IotReportDeviceRespVO.class);
+        ExcelUtils.write(response, "设备报表.xls", "数据", IotReportDeviceRespVO.class, bean);
     }
 
     // Excel下载响应配置(解决中文乱码、指定文件类型)

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

@@ -1,15 +1,23 @@
 package cn.iocoder.yudao.module.pms.controller.admin.stat;
 
+import cn.iocoder.yudao.framework.apilog.core.annotation.ApiAccessLog;
 import cn.iocoder.yudao.framework.common.pojo.CommonResult;
+import cn.iocoder.yudao.framework.common.pojo.PageParam;
 import cn.iocoder.yudao.framework.common.pojo.PageResult;
 import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
+import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;
 import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils;
 import cn.iocoder.yudao.module.pms.controller.admin.failure.vo.IotFailureReportPageReqVO;
 import cn.iocoder.yudao.module.pms.controller.admin.failure.vo.IotFailureReportRespVO;
+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.failure.IotFailureReportDO;
 import cn.iocoder.yudao.module.pms.dal.mysql.failure.IotFailureReportMapper;
+import cn.iocoder.yudao.module.system.dal.dataobject.dict.DictDataDO;
 import cn.iocoder.yudao.module.system.service.dept.DeptService;
+import cn.iocoder.yudao.module.system.service.dict.DictDataService;
 import com.google.common.collect.ImmutableMap;
+import io.swagger.v3.oas.annotations.Operation;
 import io.swagger.v3.oas.annotations.tags.Tag;
 import org.springframework.validation.annotation.Validated;
 import org.springframework.web.bind.annotation.GetMapping;
@@ -17,12 +25,15 @@ import org.springframework.web.bind.annotation.RequestMapping;
 import org.springframework.web.bind.annotation.RestController;
 
 import javax.annotation.security.PermitAll;
+import javax.servlet.http.HttpServletResponse;
 import javax.validation.Valid;
+import java.io.IOException;
 import java.util.List;
 import java.util.Objects;
 import java.util.Set;
 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;
 
 @Tag(name = "报表故障上报接口")
@@ -34,11 +45,13 @@ public class IotReportFailureController {
     private final DeptUtil deptUtil;
     private final DeptService deptService;
     private final IotFailureReportMapper iotFailureReportMapper;
+    private final DictDataService dictDataService;
 
-    public IotReportFailureController(DeptUtil deptUtil, DeptService deptService, IotFailureReportMapper iotFailureReportMapper) {
+    public IotReportFailureController(DeptUtil deptUtil, DeptService deptService, IotFailureReportMapper iotFailureReportMapper, DictDataService dictDataService) {
         this.deptUtil = deptUtil;
         this.deptService = deptService;
         this.iotFailureReportMapper = iotFailureReportMapper;
+        this.dictDataService = dictDataService;
     }
 
     @GetMapping("/status")
@@ -87,4 +100,50 @@ public class IotReportFailureController {
         }).collect(Collectors.toList());
         return CommonResult.success(new PageResult<>(collect, iotFailureReportDOPageResult.getTotal()));
     }
+
+    @GetMapping("/report/export-excel")
+    @Operation(summary = "故障上报 Excel")
+    @ApiAccessLog(operateType = EXPORT)
+    public void exportReport(@Valid IotFailureReportPageReqVO iotFailureReportPageReqVO,
+                             HttpServletResponse response) throws IOException {
+        Set<Long> ids;
+        String companyCode;
+        if (Objects.isNull(iotFailureReportPageReqVO.getDeptId())){
+            Long loginUserDeptId = SecurityFrameworkUtils.getLoginUserDeptId();
+            companyCode = deptUtil.getCompanyCode(loginUserDeptId);
+            ids = deptUtil.getDeptIds(companyCode);
+        } else {
+            ids = deptService.getChildDeptIdListFromCache(iotFailureReportPageReqVO.getDeptId());
+            ids.add(iotFailureReportPageReqVO.getDeptId());
+        }
+        iotFailureReportPageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE);
+        PageResult<IotFailureReportDO> iotFailureReportDOPageResult = iotFailureReportMapper.selectPage(iotFailureReportPageReqVO, ids);
+
+        List<IotFailureReportDO> list = iotFailureReportDOPageResult.getList();
+        List<DictDataDO> failureStatus = dictDataService.getDictDataListByDictType("pms_failure_status");
+        List<DictDataDO> failureType = dictDataService.getDictDataListByDictType("failure_type");
+        List<IotFailureReportRespVO> collect = iotFailureReportDOPageResult.getList().stream().map(e -> {
+            IotFailureReportRespVO bean = BeanUtils.toBean(e, IotFailureReportRespVO.class);
+            long count = list.stream().filter(f -> f.getDeviceId().equals(e.getDeviceId())).count();
+            bean.setFailureNum(count);
+            if (Objects.nonNull(e.getIfStop())) {
+                bean.setStop(e.getIfStop()?"是":"否");
+            }
+            if (Objects.nonNull(e.getNeedHelp())) {
+                bean.setIfNeedHelp(e.getNeedHelp()?"是":"否");
+            }
+            if (Objects.nonNull(e.getIfDeal())) {
+                bean.setDeal(e.getIfDeal()?"是":"否");
+            }
+            failureType.stream().filter(f -> f.getValue().equals(e.getFailureType())).findFirst().ifPresent(f -> {
+                bean.setFailureType(f.getLabel());
+            });
+            failureStatus.stream().filter(f -> f.getValue().equals(e.getStatus())).findFirst().ifPresent(f -> {
+                bean.setStatus(f.getLabel());
+            });
+            return bean;
+        }).collect(Collectors.toList());
+        // 导出 Excel
+        ExcelUtils.write(response, "故障上报报表统计.xls", "数据", IotFailureReportRespVO.class, collect);
+    }
 }

+ 8 - 0
yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/stat/vo/ReportCost.java

@@ -1,14 +1,22 @@
 package cn.iocoder.yudao.module.pms.controller.admin.stat.vo;
 
+import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
+import com.alibaba.excel.annotation.ExcelProperty;
 import lombok.Data;
 
 import java.math.BigDecimal;
 
 @Data
+@ExcelIgnoreUnannotated
 public class ReportCost {
+    @ExcelProperty("日期")
     private String date;
+    @ExcelProperty("类型")
     private String type;
+    @ExcelProperty("设备编号")
     private String deviceCode;
+    @ExcelProperty("设备名称")
     private String deviceName;
+    @ExcelProperty("成本")
     private BigDecimal cost;
 }

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

@@ -1,12 +1,18 @@
 package cn.iocoder.yudao.module.pms.controller.admin.vo;
 
+import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
+import com.alibaba.excel.annotation.ExcelProperty;
 import lombok.Data;
 
 @Data
+@ExcelIgnoreUnannotated
 public class IotDeviceSimple {
     private Long id;
+    @ExcelProperty("设备编码")
     private String deviceCode;
+    @ExcelProperty("设备名称")
     private String deviceName;
+    @ExcelProperty("工单数量")
     private Long orderCount;
     private Long deptId;
     private String category;

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

@@ -0,0 +1,66 @@
+package cn.iocoder.yudao.module.pms.controller.admin.vo;
+
+import cn.iocoder.yudao.module.pms.controller.admin.iotdevicematerial.vo.IotDeviceMaterialRespVO;
+import cn.iocoder.yudao.module.pms.controller.admin.iotdevicerunlog.vo.IotDeviceRunLogRespVO;
+import cn.iocoder.yudao.module.pms.controller.admin.iotmaintenancebom.vo.IotMaintenanceBomRespVO;
+import com.alibaba.excel.annotation.ExcelProperty;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+import java.math.BigDecimal;
+import java.time.LocalDateTime;
+import java.util.List;
+
+@Data
+public class IotReportDeviceRespVO {
+
+    @Schema(description = "资产编码", requiredMode = Schema.RequiredMode.REQUIRED)
+    @ExcelProperty("设备编码")
+    private String deviceCode;
+
+    @Schema(description = "设备名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋艿")
+    @ExcelProperty("设备名称")
+    private String deviceName;
+
+    @ExcelProperty("公司")
+    private String company;
+    @ExcelProperty("项目部")
+    private String project;
+
+    @Schema(description = "部门名称")
+    @ExcelProperty("部门名称")
+    private String deptName;
+
+    @Schema(description = "设备状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "2")
+    @ExcelProperty("设备状态")
+    private String deviceStatus;
+
+    @Schema(description = "资产性质", requiredMode = Schema.RequiredMode.REQUIRED)
+    @ExcelProperty("资产性质")
+    private String assetProperty;
+
+    @Schema(description = "生产厂家")
+    @ExcelProperty("生产厂家/制造商")
+    private String manufacturer;
+
+    @Schema(description = "生产日期", requiredMode = Schema.RequiredMode.REQUIRED)
+    @ExcelProperty("生产日期")
+    private LocalDateTime manDate;
+
+    @Schema(description = "启用日期")
+    @ExcelProperty("投运日期")
+    private String enableDate;
+
+    @Schema(description = "品牌型号")
+    @ExcelProperty("品牌")
+    private String brandName;
+
+    @Schema(description = "规格型号")
+    @ExcelProperty("规格型号")
+    private String model;
+
+    @Schema(description = "责任人")
+    @ExcelProperty("责任人")
+    private String chargeName;
+
+}

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

@@ -350,4 +350,5 @@ public interface IotDeviceMapper extends BaseMapperX<IotDeviceDO> {
                                            @Param("mainBomDeviceIds") Collection<Long> mainBomDeviceIds);
     List<IotDeviceSimple> selectCodeAndNameList();
     List<IotDeviceSimple> selectTypeNumber(@Param("reqVO") IotDevicePageReqVO reqVO,@Param("products") List<Integer> products);
+    List<IotDeviceRespVO> selectExport(@Param("reqVO") IotDevicePageReqVO reqVO);
 }

+ 3 - 0
yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/dal/mysql/inspect/IotInspectOrderMapper.java

@@ -4,10 +4,12 @@ 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.module.pms.controller.admin.inspect.order.vo.IotInspectOrderPageReqVO;
+import cn.iocoder.yudao.module.pms.controller.admin.inspect.order.vo.IotInspectOrderRespVO;
 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.OrderVo;
 import cn.iocoder.yudao.module.pms.controller.admin.vo.IotDevicePageReqVO;
+import cn.iocoder.yudao.module.pms.controller.admin.vo.IotDeviceRespVO;
 import cn.iocoder.yudao.module.pms.dal.dataobject.inspect.IotInspectOrderDO;
 import cn.iocoder.yudao.module.pms.dal.dataobject.iotcountdata.IotCountDataDO;
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
@@ -84,4 +86,5 @@ public interface IotInspectOrderMapper extends BaseMapperX<IotInspectOrderDO> {
     }
 
     List<AllOrderResp> selectStatusNumber(@Param("reqVO") IotMaintainPageReqVO reqVO);
+    List<IotInspectOrderRespVO> selectExport(@Param("reqVO") IotInspectOrderPageReqVO reqVO);
 }

+ 55 - 0
yudao-module-pms/yudao-module-pms-biz/src/main/resources/mapper/static/IotDeviceMapper.xml

@@ -555,4 +555,59 @@
             group by asset_class)a
         left join rq_iot_product_classify b on a.asset_class=b.id
     </select>
+
+
+    <select id="selectExport"
+            resultType="cn.iocoder.yudao.module.pms.controller.admin.vo.IotDeviceRespVO">
+        select a.*,
+        g.label as deviceStatus,m.name as manufacturer,
+        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_device a
+        -- 左关联当前部门(避免主表数据丢失)
+        LEFT JOIN system_dept d ON a.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
+        left join rq_iot_supplier m on a.manufacturer_id=m.id
+        left join (select r.value,r.label from system_dict_data r where r.dict_type='pms_device_status') g on a.device_status = g.value COLLATE utf8mb4_general_ci
+        <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>
+            <if test="reqVO.deviceCode != null">
+                AND a.deviceCode LIKE concat("%",#{reqVO.deviceCode},"%")
+            </if>
+            <if test="reqVO.deviceName != null">
+                AND a.deviceName LIKE concat("%",#{reqVO.deviceName},"%")
+            </if>
+        </where>
+    </select>
+
 </mapper>

+ 63 - 0
yudao-module-pms/yudao-module-pms-biz/src/main/resources/mapper/static/IotInspectOrderMapper.xml

@@ -29,4 +29,67 @@
 
         group by status
     </select>
+
+
+    <select id="selectExport"
+            resultType="cn.iocoder.yudao.module.pms.controller.admin.inspect.order.vo.IotInspectOrderRespVO">
+        SELECT
+        a.*,
+        g.label AS orderStatus,
+        -- 原有company字段逻辑
+        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,
+        -- 原有project字段逻辑
+        CASE
+        WHEN d.type = 2 THEN COALESCE(d.`name`, '')
+        WHEN d.type = 3 THEN COALESCE(p1.`name`, '')
+        ELSE ''
+        END AS project,
+        -- 原有deptName字段逻辑
+        CASE
+        WHEN d.type = 3 THEN COALESCE(d.`name`, '')
+        ELSE ''
+        END AS deptName,
+        -- 新增deviceInfo字段:拼接device表的code|name,无数据则为空字符串
+        IFNULL(GROUP_CONCAT(DISTINCT CONCAT(dev.device_code, '|', dev.device_name) SEPARATOR ','), '') AS deviceInfo
+        FROM
+        rq_iot_inspect_order a
+        -- 原有左关联:部门表(当前、父级、祖父级)
+        LEFT JOIN system_dept d ON a.dept_id = d.id
+        LEFT JOIN system_dept p1 ON d.parent_id = p1.id
+        LEFT JOIN system_dept p2 ON p1.parent_id = p2.id
+        -- 原有左关联:字典表(订单状态)
+        LEFT JOIN (SELECT r.value, r.label FROM system_dict_data r WHERE r.dict_type = 'pms_inspect_order_status') g
+        ON a.status = g.value COLLATE utf8mb4_general_ci
+        -- 新增左关联:设备表(关联条件:a表id = device表的order_id,需确认字段名是否正确)
+        LEFT JOIN rq_iot_inspect_order_device dev ON a.id = dev.order_id
+        -- 核心:按a表主键分组,保证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>
+            <if test="reqVO.status != null">
+                AND a.status LIKE concat("%",#{reqVO.status},"%")
+            </if>
+<!--            <if test="reqVO.deviceName != null">-->
+<!--                AND a.deviceName LIKE concat("%",#{reqVO.deviceName},"%")-->
+<!--            </if>-->
+        </where>
+        GROUP BY
+        a.id
+    </select>
 </mapper>

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

@@ -147,8 +147,8 @@
             resultType="cn.iocoder.yudao.module.pms.controller.admin.stat.vo.AllOrderResp">
 select * from (
         select a.id,'维修工单' as type,
-               '' as taskId,
-               a.create_time as createTime,
+        '' as taskId,
+        a.create_time as createTime,
         CASE
         WHEN a.status = 'todo' THEN '未完成'
         WHEN a.status = 'finished' THEN '已完成'