浏览代码

Merge remote-tracking branch 'origin/master'

# Conflicts:
#	yudao-module-pms/yudao-module-pms-api/src/main/java/cn/iocoder/yudao/module/pms/enums/ErrorCodeConstant.java
lipenghui 3 月之前
父节点
当前提交
21a3c9d2cc
共有 63 个文件被更改,包括 3456 次插入59 次删除
  1. 57 4
      yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/IotDeviceController.java
  2. 9 0
      yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/iotbom/IotBomController.java
  3. 9 1
      yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/iotbom/vo/IotBomPageReqVO.java
  4. 11 0
      yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/iotbom/vo/IotBomRespVO.java
  5. 8 0
      yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/iotmaintenancebom/IotMaintenanceBomController.java
  6. 21 0
      yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/iotmaintenancebom/vo/IotMaintenanceBomPageReqVO.java
  7. 22 0
      yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/iotmaintenancebom/vo/IotMaintenanceBomRespVO.java
  8. 29 0
      yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/iotmaintenancebom/vo/IotMaintenanceBomSaveReqVO.java
  9. 93 0
      yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/iotmainworkorder/IotMainWorkOrderController.java
  10. 84 0
      yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/iotmainworkorder/vo/IotMainWorkOrderPageReqVO.java
  11. 100 0
      yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/iotmainworkorder/vo/IotMainWorkOrderRespVO.java
  12. 73 0
      yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/iotmainworkorder/vo/IotMainWorkOrderSaveReqVO.java
  13. 93 0
      yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/iotmainworkorderbom/IotMainWorkOrderBomController.java
  14. 148 0
      yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/iotmainworkorderbom/vo/IotMainWorkOrderBomPageReqVO.java
  15. 180 0
      yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/iotmainworkorderbom/vo/IotMainWorkOrderBomRespVO.java
  16. 133 0
      yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/iotmainworkorderbom/vo/IotMainWorkOrderBomSaveReqVO.java
  17. 93 0
      yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/iotmainworkorderbommaterial/IotMainWorkOrderBomMaterialController.java
  18. 97 0
      yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/iotmainworkorderbommaterial/vo/IotMainWorkOrderBomMaterialPageReqVO.java
  19. 120 0
      yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/iotmainworkorderbommaterial/vo/IotMainWorkOrderBomMaterialRespVO.java
  20. 87 0
      yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/iotmainworkorderbommaterial/vo/IotMainWorkOrderBomMaterialSaveReqVO.java
  21. 93 0
      yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/iotmainworkorderdetails/IotMainWorkOrderDetailsController.java
  22. 66 0
      yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/iotmainworkorderdetails/vo/IotMainWorkOrderDetailsPageReqVO.java
  23. 76 0
      yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/iotmainworkorderdetails/vo/IotMainWorkOrderDetailsRespVO.java
  24. 54 0
      yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/iotmainworkorderdetails/vo/IotMainWorkOrderDetailsSaveReqVO.java
  25. 45 21
      yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/maintenance/IotMaintenancePlanController.java
  26. 1 3
      yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/maintenance/vo/IotMaintenancePlanSaveReqVO.java
  27. 17 0
      yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/maintenance/vo/IotMaintenanceSaveVO.java
  28. 16 1
      yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/vo/IotDevicePageReqVO.java
  29. 13 4
      yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/vo/IotDeviceRespVO.java
  30. 1 1
      yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/dal/dataobject/iotbom/IotBomDO.java
  31. 16 0
      yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/dal/dataobject/iotmaintenancebom/IotMaintenanceBomDO.java
  32. 109 0
      yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/dal/dataobject/iotmainworkorder/IotMainWorkOrderDO.java
  33. 189 0
      yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/dal/dataobject/iotmainworkorderbom/IotMainWorkOrderBomDO.java
  34. 128 0
      yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/dal/dataobject/iotmainworkorderbommaterial/IotMainWorkOrderBomMaterialDO.java
  35. 84 0
      yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/dal/dataobject/iotmainworkorderdetails/IotMainWorkOrderDetailsDO.java
  36. 19 2
      yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/dal/mysql/IotDeviceMapper.java
  37. 22 0
      yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/dal/mysql/iotbom/IotBomMapper.java
  38. 12 0
      yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/dal/mysql/iotmaintenancebom/IotMaintenanceBomMapper.java
  39. 43 0
      yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/dal/mysql/iotmainworkorder/IotMainWorkOrderMapper.java
  40. 63 0
      yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/dal/mysql/iotmainworkorderbom/IotMainWorkOrderBomMapper.java
  41. 48 0
      yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/dal/mysql/iotmainworkorderbommaterial/IotMainWorkOrderBomMaterialMapper.java
  42. 37 0
      yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/dal/mysql/iotmainworkorderdetails/IotMainWorkOrderDetailsMapper.java
  43. 4 3
      yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/dal/mysql/maintenance/IotMaintenancePlanMapper.java
  44. 51 0
      yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/dal/redis/BizNoRedisDAO.java
  45. 18 0
      yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/dal/redis/RedisKeyConstants.java
  46. 18 0
      yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/service/IotDeviceService.java
  47. 39 4
      yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/service/IotDeviceServiceImpl.java
  48. 30 0
      yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/service/iotbom/IotBomService.java
  49. 16 0
      yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/service/iotbom/IotBomServiceImpl.java
  50. 8 0
      yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/service/iotmaintenancebom/IotMaintenanceBomService.java
  51. 5 0
      yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/service/iotmaintenancebom/IotMaintenanceBomServiceImpl.java
  52. 55 0
      yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/service/iotmainworkorder/IotMainWorkOrderService.java
  53. 71 0
      yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/service/iotmainworkorder/IotMainWorkOrderServiceImpl.java
  54. 55 0
      yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/service/iotmainworkorderbom/IotMainWorkOrderBomService.java
  55. 71 0
      yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/service/iotmainworkorderbom/IotMainWorkOrderBomServiceImpl.java
  56. 55 0
      yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/service/iotmainworkorderbommaterial/IotMainWorkOrderBomMaterialService.java
  57. 72 0
      yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/service/iotmainworkorderbommaterial/IotMainWorkOrderBomMaterialServiceImpl.java
  58. 55 0
      yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/service/iotmainworkorderdetails/IotMainWorkOrderDetailsService.java
  59. 71 0
      yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/service/iotmainworkorderdetails/IotMainWorkOrderDetailsServiceImpl.java
  60. 4 4
      yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/service/maintenance/IotMaintenancePlanService.java
  61. 44 10
      yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/service/maintenance/IotMaintenancePlanServiceImpl.java
  62. 12 1
      yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/util/IotDeviceConvert.java
  63. 83 0
      yudao-module-pms/yudao-module-pms-biz/src/main/resources/mapper/static/IotDeviceMapper.xml

+ 57 - 4
yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/IotDeviceController.java

@@ -12,9 +12,10 @@ import cn.iocoder.yudao.module.pms.controller.admin.vo.IotDeviceRespVO;
 import cn.iocoder.yudao.module.pms.controller.admin.vo.IotDeviceSaveReqVO;
 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.iotmodel.IotModelDO;
+import cn.iocoder.yudao.module.pms.dal.dataobject.iotbom.IotBomDO;
 import cn.iocoder.yudao.module.pms.service.IotDeviceService;
 import cn.iocoder.yudao.module.pms.service.IotProductClassifyService;
+import cn.iocoder.yudao.module.pms.service.iotbom.IotBomService;
 import cn.iocoder.yudao.module.pms.service.iotmodel.IotModelService;
 import cn.iocoder.yudao.module.pms.util.IotDeviceConvert;
 import cn.iocoder.yudao.module.supplier.dal.dataobject.product.SupplierDO;
@@ -34,13 +35,12 @@ import javax.annotation.Resource;
 import javax.servlet.http.HttpServletResponse;
 import javax.validation.Valid;
 import java.io.IOException;
-import java.util.List;
-import java.util.Map;
-import java.util.Objects;
+import java.util.*;
 
 import static cn.iocoder.yudao.framework.apilog.core.enums.OperateTypeEnum.EXPORT;
 import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
 import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList;
+import static cn.iocoder.yudao.framework.common.util.collection.MapUtils.findAndThen;
 
 
 @Tag(name = "管理后台 - 设备台账")
@@ -61,6 +61,8 @@ public class IotDeviceController {
     private IotProductClassifyService iotProductClassifyService;
     @Resource
     private IotModelService iotModelService;
+    @Resource
+    private IotBomService iotBomService;
 
     @PostMapping("/create")
     @Operation(summary = "创建设备台账")
@@ -123,6 +125,57 @@ public class IotDeviceController {
                 pageResult.getTotal()));
     }
 
+    @GetMapping("/deviceAssociateBomPage")
+    @Operation(summary = "获得设备台账分页")
+    @PreAuthorize("@ss.hasPermission('rq:iot-device:query')")
+    public CommonResult<PageResult<IotDeviceRespVO>> deviceAssociateBomPage(@Valid IotDevicePageReqVO pageReqVO) {
+        PageResult<IotDeviceRespVO> pageResult = iotDeviceService.deviceAssociateBomPage(pageReqVO);
+        if (CollUtil.isEmpty(pageResult.getList())) {
+            return success(new PageResult<>(pageResult.getTotal()));
+        }
+        Map<Long, DeptDO> deptMap = deptService.getDeptMap(
+                convertList(pageResult.getList(), IotDeviceRespVO::getDeptId));
+        // 拼接BOM节点信息
+        // return success(new PageResult<>(buildDeviceAssociateBomList(pageResult.getList()), pageResult.getTotal()));
+        return success(new PageResult<>(IotDeviceConvert.INSTANCE.convertList1(pageResult.getList(), deptMap), pageResult.getTotal()));
+    }
+
+    @GetMapping("/deviceAssociateBomList")
+    @Operation(summary = "获得设备-bom关联关系列表")
+    @PreAuthorize("@ss.hasPermission('rq:iot-device:query')")
+    public CommonResult<List<IotDeviceRespVO>> deviceAssociateBomList(IotDevicePageReqVO pageReqVO) {
+        List<IotDeviceRespVO> devices = iotDeviceService.deviceAssociateBomList(pageReqVO.getDeviceIds());
+        if (CollUtil.isEmpty(devices)) {
+            return success(new ArrayList<>());
+        }
+        Map<Long, DeptDO> deptMap = deptService.getDeptMap(
+                convertList(devices, IotDeviceRespVO::getDeptId));
+        return success(IotDeviceConvert.INSTANCE.convertList1(devices, deptMap));
+    }
+
+    /**
+     * 组装 设备-bom 关联关系对象
+     * @param devices
+     * @return
+     */
+    private List<IotDeviceRespVO> buildDeviceAssociateBomList(List<IotDeviceDO> devices) {
+        if (CollUtil.isEmpty(devices)) {
+            return Collections.emptyList();
+        }
+        // 设备部门信息
+        Map<Long, DeptDO> deptMap = deptService.getDeptMap(
+                convertList(devices, IotDeviceDO::getDeptId));
+        // 拼接设备分类关联的BOM节点信息
+        Map<Long, IotBomDO> bomMap = iotBomService.getBomMap(convertList(devices, IotDeviceDO::getAssetClass));
+        // 2. 拼接数据
+        return BeanUtils.toBean(devices, IotDeviceRespVO.class, (deviceVO) -> {
+            // 2.1 拼接部门信息
+            findAndThen(deptMap, deviceVO.getDeptId(), dept -> deviceVO.setDeptName(dept.getName()));
+            // 2.2 设备关联的BOM节点信息
+            findAndThen(bomMap, deviceVO.getAssetClass(), bom -> {deviceVO.setName(bom.getName()); deviceVO.setCode(bom.getCode());});
+        });
+    }
+
     @GetMapping("/export-excel")
     @Operation(summary = "导出设备台账 Excel")
     @PreAuthorize("@ss.hasPermission('rq:iot-device:export')")

+ 9 - 0
yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/iotbom/IotBomController.java

@@ -78,6 +78,15 @@ public class IotBomController {
         return success(BeanUtils.toBean(pageResult, IotBomRespVO.class));
     }
 
+    @GetMapping("/deviceAssociateBomPage")
+    @Operation(summary = "获得PMS 设备关联-BOM 关系分页")
+    @PreAuthorize("@ss.hasPermission('rq:iot-bom:query')")
+    public CommonResult<PageResult<IotBomRespVO>> deviceAssociateBomPage(@Valid IotBomPageReqVO pageReqVO) {
+        PageResult<IotBomDO> pageResult = iotBomService.deviceAssociateBomPage(pageReqVO);
+
+        return success(BeanUtils.toBean(pageResult, IotBomRespVO.class));
+    }
+
     @GetMapping("/list")
     @Operation(summary = "获取 Bom树 列表")
     @PreAuthorize("@ss.hasPermission('rq:iot-bom:query')")

+ 9 - 1
yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/iotbom/vo/IotBomPageReqVO.java

@@ -38,7 +38,7 @@ public class IotBomPageReqVO extends PageParam {
     @Schema(description = "显示顺序")
     private Integer sort;
 
-    @Schema(description = "M维修 S保养 维修+保养", example = "1")
+    @Schema(description = "1维修 2保养 维修+保养", example = "1")
     private String type;
 
     @Schema(description = "状态 0启用  1停用", example = "1")
@@ -57,4 +57,12 @@ public class IotBomPageReqVO extends PageParam {
     @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
     private LocalDateTime[] createTime;
 
+    @Schema(description = "设备名称")
+    private String deviceName;
+    @Schema(description = "设备编码")
+    private String deviceCode;
+    @Schema(description = "设备状态")
+    private String deviceStatus;
+    @Schema(description = "资产性质")
+    private String assetProperty;
 }

+ 11 - 0
yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/iotbom/vo/IotBomRespVO.java

@@ -69,4 +69,15 @@ public class IotBomRespVO {
     @ExcelProperty("创建时间")
     private LocalDateTime createTime;
 
+    /**
+     * 设备关联字段
+     */
+    @Schema(description = "设备名称")
+    private String deviceName;
+    @Schema(description = "设备编码")
+    private String deviceCode;
+    @Schema(description = "设备状态")
+    private String deviceStatus;
+    @Schema(description = "资产性质")
+    private String assetProperty;
 }

+ 8 - 0
yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/iotmaintenancebom/IotMaintenanceBomController.java

@@ -77,6 +77,14 @@ public class IotMaintenanceBomController {
         return success(BeanUtils.toBean(pageResult, IotMaintenanceBomRespVO.class));
     }
 
+    @GetMapping("/deviceAssociateBomPage")
+    @Operation(summary = "获得PMS 保养计划明细 设备关联-BOM分页")
+    @PreAuthorize("@ss.hasPermission('pms:iot-maintenance-bom:query')")
+    public CommonResult<PageResult<IotMaintenanceBomRespVO>> deviceAssociateBomPage(@Valid IotMaintenanceBomPageReqVO pageReqVO) {
+        PageResult<IotMaintenanceBomDO> pageResult = iotMaintenanceBomService.deviceAssociateBomPage(pageReqVO);
+        return success(BeanUtils.toBean(pageResult, IotMaintenanceBomRespVO.class));
+    }
+
     @GetMapping("/export-excel")
     @Operation(summary = "导出PMS 保养计划明细BOM Excel")
     @PreAuthorize("@ss.hasPermission('pms:iot-maintenance-bom:export')")

+ 21 - 0
yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/iotmaintenancebom/vo/IotMaintenanceBomPageReqVO.java

@@ -33,6 +33,13 @@ public class IotMaintenanceBomPageReqVO extends PageParam {
     @Schema(description = "保养规则(量程 运行时间 自然日期) 可多选")
     private String rule;
 
+    @Schema(description = "保养规则-里程(0启用 1停用)", example = "2")
+    private Integer mileageRule;
+    @Schema(description = "保养规则-自然日期(0启用 1停用)", example = "2")
+    private Integer naturalDateRule;
+    @Schema(description = "保养规则-运行时间(0启用 1停用)", example = "2")
+    private Integer runningTimeRule;
+
     @Schema(description = "上次保养运行时长(小时)")
     @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
     private BigDecimal[] lastRunningTime;
@@ -55,6 +62,9 @@ public class IotMaintenanceBomPageReqVO extends PageParam {
     @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
     private BigDecimal[] nextNaturalDate;
 
+    @Schema(description = "BOM节点 id", example = "18063")
+    private Long bomNodeId;
+
     @Schema(description = "BOM名称", example = "张三")
     private String name;
 
@@ -92,4 +102,15 @@ public class IotMaintenanceBomPageReqVO extends PageParam {
     @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
     private LocalDateTime[] createTime;
 
+    /**
+     * 设备关联字段
+     */
+    @Schema(description = "设备名称")
+    private String deviceName;
+    @Schema(description = "设备编码")
+    private String deviceCode;
+    @Schema(description = "设备状态")
+    private String deviceStatus;
+    @Schema(description = "资产性质")
+    private String assetProperty;
 }

+ 22 - 0
yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/iotmaintenancebom/vo/IotMaintenanceBomRespVO.java

@@ -37,6 +37,13 @@ public class IotMaintenanceBomRespVO {
     @ExcelProperty("保养规则(量程 运行时间 自然日期) 可多选")
     private String rule;
 
+    @Schema(description = "保养规则-里程(0启用 1停用)", example = "2")
+    private Integer mileageRule;
+    @Schema(description = "保养规则-自然日期(0启用 1停用)", example = "2")
+    private Integer naturalDateRule;
+    @Schema(description = "保养规则-运行时间(0启用 1停用)", example = "2")
+    private Integer runningTimeRule;
+
     @Schema(description = "上次保养运行时长(小时)")
     @ExcelProperty("上次保养运行时长(小时)")
     private BigDecimal lastRunningTime;
@@ -61,6 +68,9 @@ public class IotMaintenanceBomRespVO {
     @ExcelProperty("下次保养自然日期(天)")
     private BigDecimal nextNaturalDate;
 
+    @Schema(description = "BOM节点 id", example = "18063")
+    private Long bomNodeId;
+
     @Schema(description = "BOM名称", example = "张三")
     @ExcelProperty("BOM名称")
     private String name;
@@ -109,4 +119,16 @@ public class IotMaintenanceBomRespVO {
     @ExcelProperty("创建时间")
     private LocalDateTime createTime;
 
+    /**
+     * 设备关联字段
+     */
+    @Schema(description = "设备名称")
+    private String deviceName;
+    @Schema(description = "设备编码")
+    private String deviceCode;
+    @Schema(description = "设备状态")
+    private String deviceStatus;
+    @Schema(description = "资产性质")
+    private String assetProperty;
+
 }

+ 29 - 0
yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/iotmaintenancebom/vo/IotMaintenanceBomSaveReqVO.java

@@ -27,6 +27,13 @@ public class IotMaintenanceBomSaveReqVO {
     @Schema(description = "保养规则(量程 运行时间 自然日期) 可多选")
     private String rule;
 
+    @Schema(description = "保养规则-里程(0启用 1停用)", example = "2")
+    private Integer mileageRule;
+    @Schema(description = "保养规则-自然日期(0启用 1停用)", example = "2")
+    private Integer naturalDateRule;
+    @Schema(description = "保养规则-运行时间(0启用 1停用)", example = "2")
+    private Integer runningTimeRule;
+
     @Schema(description = "上次保养运行时长(小时)")
     private BigDecimal lastRunningTime;
 
@@ -45,6 +52,9 @@ public class IotMaintenanceBomSaveReqVO {
     @Schema(description = "下次保养自然日期(天)")
     private BigDecimal nextNaturalDate;
 
+    @Schema(description = "BOM节点 id", example = "18063")
+    private Long bomNodeId;
+
     @Schema(description = "BOM名称", example = "张三")
     private String name;
 
@@ -78,4 +88,23 @@ public class IotMaintenanceBomSaveReqVO {
     @Schema(description = "版本")
     private Integer version;
 
+    /**
+     * 设备关联字段
+     */
+    @Schema(description = "设备名称")
+    private String deviceName;
+    @Schema(description = "设备编码")
+    private String deviceCode;
+    @Schema(description = "设备状态")
+    private String deviceStatus;
+    @Schema(description = "资产性质")
+    private String assetProperty;
+    @Schema(description = "部门名称")
+    private String deptName;
+    @Schema(description = "设备类别")
+    private Long assetClass;
+    @Schema(description = "设备运行时间")
+    private BigDecimal runningTime;
+    @Schema(description = "设备运行公里数")
+    private BigDecimal runningKilometers;
 }

+ 93 - 0
yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/iotmainworkorder/IotMainWorkOrderController.java

@@ -0,0 +1,93 @@
+package cn.iocoder.yudao.module.pms.controller.admin.iotmainworkorder;
+
+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.module.pms.controller.admin.iotmainworkorder.vo.IotMainWorkOrderPageReqVO;
+import cn.iocoder.yudao.module.pms.controller.admin.iotmainworkorder.vo.IotMainWorkOrderRespVO;
+import cn.iocoder.yudao.module.pms.controller.admin.iotmainworkorder.vo.IotMainWorkOrderSaveReqVO;
+import cn.iocoder.yudao.module.pms.dal.dataobject.iotmainworkorder.IotMainWorkOrderDO;
+import cn.iocoder.yudao.module.pms.service.iotmainworkorder.IotMainWorkOrderService;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.Parameter;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.*;
+
+import javax.annotation.Resource;
+import javax.servlet.http.HttpServletResponse;
+import javax.validation.Valid;
+import java.io.IOException;
+import java.util.List;
+
+import static cn.iocoder.yudao.framework.apilog.core.enums.OperateTypeEnum.EXPORT;
+import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
+
+@Tag(name = "管理后台 - 保养工单")
+@RestController
+@RequestMapping("/pms/iot-main-work-order")
+@Validated
+public class IotMainWorkOrderController {
+
+    @Resource
+    private IotMainWorkOrderService iotMainWorkOrderService;
+
+    @PostMapping("/create")
+    @Operation(summary = "创建保养工单")
+    @PreAuthorize("@ss.hasPermission('pms:iot-main-work-order:create')")
+    public CommonResult<Long> createIotMainWorkOrder(@Valid @RequestBody IotMainWorkOrderSaveReqVO createReqVO) {
+        return success(iotMainWorkOrderService.createIotMainWorkOrder(createReqVO));
+    }
+
+    @PutMapping("/update")
+    @Operation(summary = "更新保养工单")
+    @PreAuthorize("@ss.hasPermission('pms:iot-main-work-order:update')")
+    public CommonResult<Boolean> updateIotMainWorkOrder(@Valid @RequestBody IotMainWorkOrderSaveReqVO updateReqVO) {
+        iotMainWorkOrderService.updateIotMainWorkOrder(updateReqVO);
+        return success(true);
+    }
+
+    @DeleteMapping("/delete")
+    @Operation(summary = "删除保养工单")
+    @Parameter(name = "id", description = "编号", required = true)
+    @PreAuthorize("@ss.hasPermission('pms:iot-main-work-order:delete')")
+    public CommonResult<Boolean> deleteIotMainWorkOrder(@RequestParam("id") Long id) {
+        iotMainWorkOrderService.deleteIotMainWorkOrder(id);
+        return success(true);
+    }
+
+    @GetMapping("/get")
+    @Operation(summary = "获得保养工单")
+    @Parameter(name = "id", description = "编号", required = true, example = "1024")
+    @PreAuthorize("@ss.hasPermission('pms:iot-main-work-order:query')")
+    public CommonResult<IotMainWorkOrderRespVO> getIotMainWorkOrder(@RequestParam("id") Long id) {
+        IotMainWorkOrderDO iotMainWorkOrder = iotMainWorkOrderService.getIotMainWorkOrder(id);
+        return success(BeanUtils.toBean(iotMainWorkOrder, IotMainWorkOrderRespVO.class));
+    }
+
+    @GetMapping("/page")
+    @Operation(summary = "获得保养工单分页")
+    @PreAuthorize("@ss.hasPermission('pms:iot-main-work-order:query')")
+    public CommonResult<PageResult<IotMainWorkOrderRespVO>> getIotMainWorkOrderPage(@Valid IotMainWorkOrderPageReqVO pageReqVO) {
+        PageResult<IotMainWorkOrderDO> pageResult = iotMainWorkOrderService.getIotMainWorkOrderPage(pageReqVO);
+        return success(BeanUtils.toBean(pageResult, IotMainWorkOrderRespVO.class));
+    }
+
+    @GetMapping("/export-excel")
+    @Operation(summary = "导出保养工单 Excel")
+    @PreAuthorize("@ss.hasPermission('pms:iot-main-work-order:export')")
+    @ApiAccessLog(operateType = EXPORT)
+    public void exportIotMainWorkOrderExcel(@Valid IotMainWorkOrderPageReqVO pageReqVO,
+              HttpServletResponse response) throws IOException {
+        pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE);
+        List<IotMainWorkOrderDO> list = iotMainWorkOrderService.getIotMainWorkOrderPage(pageReqVO).getList();
+        // 导出 Excel
+        ExcelUtils.write(response, "保养工单.xls", "数据", IotMainWorkOrderRespVO.class,
+                        BeanUtils.toBean(list, IotMainWorkOrderRespVO.class));
+    }
+
+}

+ 84 - 0
yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/iotmainworkorder/vo/IotMainWorkOrderPageReqVO.java

@@ -0,0 +1,84 @@
+package cn.iocoder.yudao.module.pms.controller.admin.iotmainworkorder.vo;
+
+import cn.iocoder.yudao.framework.common.pojo.PageParam;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.ToString;
+import org.springframework.format.annotation.DateTimeFormat;
+
+import java.math.BigDecimal;
+import java.time.LocalDateTime;
+
+import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
+
+@Schema(description = "管理后台 - 保养工单分页 Request VO")
+@Data
+@EqualsAndHashCode(callSuper = true)
+@ToString(callSuper = true)
+public class IotMainWorkOrderPageReqVO extends PageParam {
+
+    @Schema(description = "保养计划id", example = "28145")
+    private Long planId;
+
+    @Schema(description = "保养计划编号")
+    private String planSerialNumber;
+
+    @Schema(description = "组织id", example = "8684")
+    private Long deptId;
+
+    @Schema(description = "工单号")
+    private String orderNumber;
+
+    @Schema(description = "工单名称 (吐哈-C14-保养计划)", example = "张三")
+    private String name;
+
+    @Schema(description = "工单类型(1计划生成  2临时新建)", example = "1")
+    private Integer type;
+
+    @Schema(description = "负责人id 多个以逗号分隔")
+    private String responsiblePerson;
+
+    @Schema(description = "负责人id 多个以逗号分隔", example = "王五")
+    private String responsiblePersonName;
+
+    @Schema(description = "保养费用")
+    private BigDecimal cost;
+
+    @Schema(description = "保养结果(1待执行 2已执行)")
+    private Integer result;
+
+    @Schema(description = "其他费用")
+    private BigDecimal otherCost;
+
+    @Schema(description = "人工费用")
+    private BigDecimal laborCost;
+
+    @Schema(description = "是否委外 0否  1是")
+    private Integer outsourcingFlag;
+
+    @Schema(description = "实际保养开始时间")
+    @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
+    private LocalDateTime[] actualStartTime;
+
+    @Schema(description = "实际保养结束时间")
+    @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
+    private LocalDateTime[] actualEndTime;
+
+    @Schema(description = "备注", example = "你说的对")
+    private String remark;
+
+    @Schema(description = "状态 0启用  1停用", example = "2")
+    private Integer status;
+
+    @Schema(description = "流程实例id", example = "12662")
+    private String processInstanceId;
+
+    @Schema(description = "审批状态 未提交、审批中、审批通过、审批不通过、已取消", example = "1")
+    private Integer auditStatus;
+
+    @Schema(description = "创建时间")
+    @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
+    private LocalDateTime[] createTime;
+
+}

+ 100 - 0
yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/iotmainworkorder/vo/IotMainWorkOrderRespVO.java

@@ -0,0 +1,100 @@
+package cn.iocoder.yudao.module.pms.controller.admin.iotmainworkorder.vo;
+
+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.math.BigDecimal;
+import java.time.LocalDateTime;
+
+@Schema(description = "管理后台 - 保养工单 Response VO")
+@Data
+@ExcelIgnoreUnannotated
+public class IotMainWorkOrderRespVO {
+
+    @Schema(description = "主键id", requiredMode = Schema.RequiredMode.REQUIRED, example = "18795")
+    @ExcelProperty("主键id")
+    private Long id;
+
+    @Schema(description = "保养计划id", example = "28145")
+    @ExcelProperty("保养计划id")
+    private Long planId;
+
+    @Schema(description = "保养计划编号")
+    @ExcelProperty("保养计划编号")
+    private String planSerialNumber;
+
+    @Schema(description = "组织id", example = "8684")
+    @ExcelProperty("组织id")
+    private Long deptId;
+
+    @Schema(description = "工单号")
+    @ExcelProperty("工单号")
+    private String orderNumber;
+
+    @Schema(description = "工单名称 (吐哈-C14-保养计划)", example = "张三")
+    @ExcelProperty("工单名称 (吐哈-C14-保养计划)")
+    private String name;
+
+    @Schema(description = "工单类型(1计划生成  2临时新建)", example = "1")
+    @ExcelProperty("工单类型(1计划生成  2临时新建)")
+    private Integer type;
+
+    @Schema(description = "负责人id 多个以逗号分隔")
+    @ExcelProperty("负责人id 多个以逗号分隔")
+    private String responsiblePerson;
+
+    @Schema(description = "负责人id 多个以逗号分隔", example = "王五")
+    @ExcelProperty("负责人id 多个以逗号分隔")
+    private String responsiblePersonName;
+
+    @Schema(description = "保养费用")
+    @ExcelProperty("保养费用")
+    private BigDecimal cost;
+
+    @Schema(description = "保养结果(1待执行 2已执行)")
+    @ExcelProperty("保养结果(1待执行 2已执行)")
+    private Integer result;
+
+    @Schema(description = "其他费用")
+    @ExcelProperty("其他费用")
+    private BigDecimal otherCost;
+
+    @Schema(description = "人工费用")
+    @ExcelProperty("人工费用")
+    private BigDecimal laborCost;
+
+    @Schema(description = "是否委外 0否  1是")
+    @ExcelProperty("是否委外 0否  1是")
+    private Integer outsourcingFlag;
+
+    @Schema(description = "实际保养开始时间")
+    @ExcelProperty("实际保养开始时间")
+    private LocalDateTime actualStartTime;
+
+    @Schema(description = "实际保养结束时间")
+    @ExcelProperty("实际保养结束时间")
+    private LocalDateTime actualEndTime;
+
+    @Schema(description = "备注", example = "你说的对")
+    @ExcelProperty("备注")
+    private String remark;
+
+    @Schema(description = "状态 0启用  1停用", example = "2")
+    @ExcelProperty("状态 0启用  1停用")
+    private Integer status;
+
+    @Schema(description = "流程实例id", example = "12662")
+    @ExcelProperty("流程实例id")
+    private String processInstanceId;
+
+    @Schema(description = "审批状态 未提交、审批中、审批通过、审批不通过、已取消", example = "1")
+    @ExcelProperty("审批状态 未提交、审批中、审批通过、审批不通过、已取消")
+    private Integer auditStatus;
+
+    @Schema(description = "创建时间")
+    @ExcelProperty("创建时间")
+    private LocalDateTime createTime;
+
+}

+ 73 - 0
yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/iotmainworkorder/vo/IotMainWorkOrderSaveReqVO.java

@@ -0,0 +1,73 @@
+package cn.iocoder.yudao.module.pms.controller.admin.iotmainworkorder.vo;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+import java.math.BigDecimal;
+import java.time.LocalDateTime;
+
+@Schema(description = "管理后台 - 保养工单新增/修改 Request VO")
+@Data
+public class IotMainWorkOrderSaveReqVO {
+
+    @Schema(description = "主键id", requiredMode = Schema.RequiredMode.REQUIRED, example = "18795")
+    private Long id;
+
+    @Schema(description = "保养计划id", example = "28145")
+    private Long planId;
+
+    @Schema(description = "保养计划编号")
+    private String planSerialNumber;
+
+    @Schema(description = "组织id", example = "8684")
+    private Long deptId;
+
+    @Schema(description = "工单号")
+    private String orderNumber;
+
+    @Schema(description = "工单名称 (吐哈-C14-保养计划)", example = "张三")
+    private String name;
+
+    @Schema(description = "工单类型(1计划生成  2临时新建)", example = "1")
+    private Integer type;
+
+    @Schema(description = "负责人id 多个以逗号分隔")
+    private String responsiblePerson;
+
+    @Schema(description = "负责人id 多个以逗号分隔", example = "王五")
+    private String responsiblePersonName;
+
+    @Schema(description = "保养费用")
+    private BigDecimal cost;
+
+    @Schema(description = "保养结果(1待执行 2已执行)")
+    private Integer result;
+
+    @Schema(description = "其他费用")
+    private BigDecimal otherCost;
+
+    @Schema(description = "人工费用")
+    private BigDecimal laborCost;
+
+    @Schema(description = "是否委外 0否  1是")
+    private Integer outsourcingFlag;
+
+    @Schema(description = "实际保养开始时间")
+    private LocalDateTime actualStartTime;
+
+    @Schema(description = "实际保养结束时间")
+    private LocalDateTime actualEndTime;
+
+    @Schema(description = "备注", example = "你说的对")
+    private String remark;
+
+    @Schema(description = "状态 0启用  1停用", example = "2")
+    private Integer status;
+
+    @Schema(description = "流程实例id", example = "12662")
+    private String processInstanceId;
+
+    @Schema(description = "审批状态 未提交、审批中、审批通过、审批不通过、已取消", example = "1")
+    private Integer auditStatus;
+
+}

+ 93 - 0
yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/iotmainworkorderbom/IotMainWorkOrderBomController.java

@@ -0,0 +1,93 @@
+package cn.iocoder.yudao.module.pms.controller.admin.iotmainworkorderbom;
+
+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.module.pms.controller.admin.iotmainworkorderbom.vo.IotMainWorkOrderBomPageReqVO;
+import cn.iocoder.yudao.module.pms.controller.admin.iotmainworkorderbom.vo.IotMainWorkOrderBomRespVO;
+import cn.iocoder.yudao.module.pms.controller.admin.iotmainworkorderbom.vo.IotMainWorkOrderBomSaveReqVO;
+import cn.iocoder.yudao.module.pms.dal.dataobject.iotmainworkorderbom.IotMainWorkOrderBomDO;
+import cn.iocoder.yudao.module.pms.service.iotmainworkorderbom.IotMainWorkOrderBomService;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.Parameter;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.*;
+
+import javax.annotation.Resource;
+import javax.servlet.http.HttpServletResponse;
+import javax.validation.Valid;
+import java.io.IOException;
+import java.util.List;
+
+import static cn.iocoder.yudao.framework.apilog.core.enums.OperateTypeEnum.EXPORT;
+import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
+
+@Tag(name = "管理后台 - PMS 保养计划明细BOM")
+@RestController
+@RequestMapping("/pms/iot-main-work-order-bom")
+@Validated
+public class IotMainWorkOrderBomController {
+
+    @Resource
+    private IotMainWorkOrderBomService iotMainWorkOrderBomService;
+
+    @PostMapping("/create")
+    @Operation(summary = "创建PMS 保养计划明细BOM")
+    @PreAuthorize("@ss.hasPermission('pms:iot-main-work-order-bom:create')")
+    public CommonResult<Long> createIotMainWorkOrderBom(@Valid @RequestBody IotMainWorkOrderBomSaveReqVO createReqVO) {
+        return success(iotMainWorkOrderBomService.createIotMainWorkOrderBom(createReqVO));
+    }
+
+    @PutMapping("/update")
+    @Operation(summary = "更新PMS 保养计划明细BOM")
+    @PreAuthorize("@ss.hasPermission('pms:iot-main-work-order-bom:update')")
+    public CommonResult<Boolean> updateIotMainWorkOrderBom(@Valid @RequestBody IotMainWorkOrderBomSaveReqVO updateReqVO) {
+        iotMainWorkOrderBomService.updateIotMainWorkOrderBom(updateReqVO);
+        return success(true);
+    }
+
+    @DeleteMapping("/delete")
+    @Operation(summary = "删除PMS 保养计划明细BOM")
+    @Parameter(name = "id", description = "编号", required = true)
+    @PreAuthorize("@ss.hasPermission('pms:iot-main-work-order-bom:delete')")
+    public CommonResult<Boolean> deleteIotMainWorkOrderBom(@RequestParam("id") Long id) {
+        iotMainWorkOrderBomService.deleteIotMainWorkOrderBom(id);
+        return success(true);
+    }
+
+    @GetMapping("/get")
+    @Operation(summary = "获得PMS 保养计划明细BOM")
+    @Parameter(name = "id", description = "编号", required = true, example = "1024")
+    @PreAuthorize("@ss.hasPermission('pms:iot-main-work-order-bom:query')")
+    public CommonResult<IotMainWorkOrderBomRespVO> getIotMainWorkOrderBom(@RequestParam("id") Long id) {
+        IotMainWorkOrderBomDO iotMainWorkOrderBom = iotMainWorkOrderBomService.getIotMainWorkOrderBom(id);
+        return success(BeanUtils.toBean(iotMainWorkOrderBom, IotMainWorkOrderBomRespVO.class));
+    }
+
+    @GetMapping("/page")
+    @Operation(summary = "获得PMS 保养计划明细BOM分页")
+    @PreAuthorize("@ss.hasPermission('pms:iot-main-work-order-bom:query')")
+    public CommonResult<PageResult<IotMainWorkOrderBomRespVO>> getIotMainWorkOrderBomPage(@Valid IotMainWorkOrderBomPageReqVO pageReqVO) {
+        PageResult<IotMainWorkOrderBomDO> pageResult = iotMainWorkOrderBomService.getIotMainWorkOrderBomPage(pageReqVO);
+        return success(BeanUtils.toBean(pageResult, IotMainWorkOrderBomRespVO.class));
+    }
+
+    @GetMapping("/export-excel")
+    @Operation(summary = "导出PMS 保养计划明细BOM Excel")
+    @PreAuthorize("@ss.hasPermission('pms:iot-main-work-order-bom:export')")
+    @ApiAccessLog(operateType = EXPORT)
+    public void exportIotMainWorkOrderBomExcel(@Valid IotMainWorkOrderBomPageReqVO pageReqVO,
+              HttpServletResponse response) throws IOException {
+        pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE);
+        List<IotMainWorkOrderBomDO> list = iotMainWorkOrderBomService.getIotMainWorkOrderBomPage(pageReqVO).getList();
+        // 导出 Excel
+        ExcelUtils.write(response, "PMS 保养计划明细BOM.xls", "数据", IotMainWorkOrderBomRespVO.class,
+                        BeanUtils.toBean(list, IotMainWorkOrderBomRespVO.class));
+    }
+
+}

+ 148 - 0
yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/iotmainworkorderbom/vo/IotMainWorkOrderBomPageReqVO.java

@@ -0,0 +1,148 @@
+package cn.iocoder.yudao.module.pms.controller.admin.iotmainworkorderbom.vo;
+
+import cn.iocoder.yudao.framework.common.pojo.PageParam;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.ToString;
+import org.springframework.format.annotation.DateTimeFormat;
+
+import java.math.BigDecimal;
+import java.time.LocalDateTime;
+
+import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
+
+@Schema(description = "管理后台 - PMS 保养计划明细BOM分页 Request VO")
+@Data
+@EqualsAndHashCode(callSuper = true)
+@ToString(callSuper = true)
+public class IotMainWorkOrderBomPageReqVO extends PageParam {
+
+    @Schema(description = "保养计划id", example = "17036")
+    private Long planId;
+
+    @Schema(description = "保养计划明细id", example = "2291")
+    private Long planDetailId;
+
+    @Schema(description = "保养工单id", example = "28354")
+    private Long workOrderId;
+
+    @Schema(description = "所属设备分类", example = "5173")
+    private Long deviceCategoryId;
+
+    @Schema(description = "设备id", example = "4335")
+    private Long deviceId;
+
+    @Schema(description = "保养规则(量程 运行时间 自然日期) 可多选")
+    private String rule;
+
+    @Schema(description = "保养规则-里程(0启用 1停用)")
+    private Integer mileageRule;
+
+    @Schema(description = "保养规则-自然日期(0启用 1停用)")
+    private Integer naturalDateRule;
+
+    @Schema(description = "保养规则-运行时间(0启用 1停用)")
+    private Integer runningTimeRule;
+
+    @Schema(description = "上次保养运行时长(小时)")
+    @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
+    private BigDecimal[] lastRunningTime;
+
+    @Schema(description = "下次保养运行时长(小时)")
+    @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
+    private BigDecimal[] nextRunningTime;
+
+    @Schema(description = "推迟运行时长(小时)")
+    private BigDecimal delayDuration;
+
+    @Schema(description = "上次保养运行公里数(千米)")
+    private BigDecimal lastRunningKilometers;
+
+    @Schema(description = "下次保养运行公里数(千米)")
+    private BigDecimal nextRunningKilometers;
+
+    @Schema(description = "推迟运行公里数(千米)")
+    private BigDecimal delayKilomaters;
+
+    @Schema(description = "上次保养自然日期(天)")
+    @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
+    private BigDecimal[] lastNaturalDate;
+
+    @Schema(description = "下次保养自然日期(天)")
+    @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
+    private BigDecimal[] nextNaturalDate;
+
+    @Schema(description = "推迟自然日期(天)")
+    @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
+    private BigDecimal[] delayNaturalDate;
+
+    @Schema(description = "推迟原因", example = "不对")
+    private String delayReason;
+
+    @Schema(description = "上次保养日期")
+    @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
+    private LocalDateTime[] lastMainDate;
+
+    @Schema(description = "时间周期(小时)")
+    private BigDecimal timePeriod;
+
+    @Schema(description = "时间周期-提前量(小时)")
+    private BigDecimal timePeriodLead;
+
+    @Schema(description = "公里数周期(千米)")
+    private BigDecimal kilometerCycle;
+
+    @Schema(description = "公里数周期-提前量(千米)")
+    private BigDecimal kiloCycleLead;
+
+    @Schema(description = "自然日周期(天)")
+    private BigDecimal naturalDatePeriod;
+
+    @Schema(description = "自然日周期-提前量(天)")
+    private BigDecimal naturalDatePeroidLead;
+
+    @Schema(description = "BOM节点id", example = "13933")
+    private Long bomNodeId;
+
+    @Schema(description = "BOM名称", example = "李四")
+    private String name;
+
+    @Schema(description = "BOM编码")
+    private String code;
+
+    @Schema(description = "父BOM id 顶级为0", example = "2631")
+    private Long parentId;
+
+    @Schema(description = "子节点id 逗号分隔")
+    private String childIds;
+
+    @Schema(description = "层级")
+    private Integer level;
+
+    @Schema(description = "是否叶子节点 0是 1否")
+    private Integer leafFlag;
+
+    @Schema(description = "显示顺序")
+    private Integer sort;
+
+    @Schema(description = "1维修 2保养 维修+保养 (1,2)", example = "2")
+    private String type;
+
+    @Schema(description = "保养类型(1临时保养  2计划保养)", example = "1")
+    private Integer mainType;
+
+    @Schema(description = "状态 0启用  1停用", example = "2")
+    private Integer status;
+
+    @Schema(description = "备注", example = "你说的对")
+    private String remark;
+
+    @Schema(description = "版本")
+    private Integer version;
+
+    @Schema(description = "创建时间")
+    @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
+    private LocalDateTime[] createTime;
+
+}

+ 180 - 0
yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/iotmainworkorderbom/vo/IotMainWorkOrderBomRespVO.java

@@ -0,0 +1,180 @@
+package cn.iocoder.yudao.module.pms.controller.admin.iotmainworkorderbom.vo;
+
+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.math.BigDecimal;
+import java.time.LocalDateTime;
+
+@Schema(description = "管理后台 - PMS 保养计划明细BOM Response VO")
+@Data
+@ExcelIgnoreUnannotated
+public class IotMainWorkOrderBomRespVO {
+
+    @Schema(description = "主键", requiredMode = Schema.RequiredMode.REQUIRED, example = "31182")
+    @ExcelProperty("主键")
+    private Long id;
+
+    @Schema(description = "保养计划id", example = "17036")
+    @ExcelProperty("保养计划id")
+    private Long planId;
+
+    @Schema(description = "保养计划明细id", example = "2291")
+    @ExcelProperty("保养计划明细id")
+    private Long planDetailId;
+
+    @Schema(description = "保养工单id", example = "28354")
+    @ExcelProperty("保养工单id")
+    private Long workOrderId;
+
+    @Schema(description = "所属设备分类", example = "5173")
+    @ExcelProperty("所属设备分类")
+    private Long deviceCategoryId;
+
+    @Schema(description = "设备id", example = "4335")
+    @ExcelProperty("设备id")
+    private Long deviceId;
+
+    @Schema(description = "保养规则(量程 运行时间 自然日期) 可多选")
+    @ExcelProperty("保养规则(量程 运行时间 自然日期) 可多选")
+    private String rule;
+
+    @Schema(description = "保养规则-里程(0启用 1停用)")
+    @ExcelProperty("保养规则-里程(0启用 1停用)")
+    private Integer mileageRule;
+
+    @Schema(description = "保养规则-自然日期(0启用 1停用)")
+    @ExcelProperty("保养规则-自然日期(0启用 1停用)")
+    private Integer naturalDateRule;
+
+    @Schema(description = "保养规则-运行时间(0启用 1停用)")
+    @ExcelProperty("保养规则-运行时间(0启用 1停用)")
+    private Integer runningTimeRule;
+
+    @Schema(description = "上次保养运行时长(小时)")
+    @ExcelProperty("上次保养运行时长(小时)")
+    private BigDecimal lastRunningTime;
+
+    @Schema(description = "下次保养运行时长(小时)")
+    @ExcelProperty("下次保养运行时长(小时)")
+    private BigDecimal nextRunningTime;
+
+    @Schema(description = "推迟运行时长(小时)")
+    @ExcelProperty("推迟运行时长(小时)")
+    private BigDecimal delayDuration;
+
+    @Schema(description = "上次保养运行公里数(千米)")
+    @ExcelProperty("上次保养运行公里数(千米)")
+    private BigDecimal lastRunningKilometers;
+
+    @Schema(description = "下次保养运行公里数(千米)")
+    @ExcelProperty("下次保养运行公里数(千米)")
+    private BigDecimal nextRunningKilometers;
+
+    @Schema(description = "推迟运行公里数(千米)")
+    @ExcelProperty("推迟运行公里数(千米)")
+    private BigDecimal delayKilomaters;
+
+    @Schema(description = "上次保养自然日期(天)")
+    @ExcelProperty("上次保养自然日期(天)")
+    private BigDecimal lastNaturalDate;
+
+    @Schema(description = "下次保养自然日期(天)")
+    @ExcelProperty("下次保养自然日期(天)")
+    private BigDecimal nextNaturalDate;
+
+    @Schema(description = "推迟自然日期(天)")
+    @ExcelProperty("推迟自然日期(天)")
+    private BigDecimal delayNaturalDate;
+
+    @Schema(description = "推迟原因", example = "不对")
+    @ExcelProperty("推迟原因")
+    private String delayReason;
+
+    @Schema(description = "上次保养日期")
+    @ExcelProperty("上次保养日期")
+    private LocalDateTime lastMainDate;
+
+    @Schema(description = "时间周期(小时)")
+    @ExcelProperty("时间周期(小时)")
+    private BigDecimal timePeriod;
+
+    @Schema(description = "时间周期-提前量(小时)")
+    @ExcelProperty("时间周期-提前量(小时)")
+    private BigDecimal timePeriodLead;
+
+    @Schema(description = "公里数周期(千米)")
+    @ExcelProperty("公里数周期(千米)")
+    private BigDecimal kilometerCycle;
+
+    @Schema(description = "公里数周期-提前量(千米)")
+    @ExcelProperty("公里数周期-提前量(千米)")
+    private BigDecimal kiloCycleLead;
+
+    @Schema(description = "自然日周期(天)")
+    @ExcelProperty("自然日周期(天)")
+    private BigDecimal naturalDatePeriod;
+
+    @Schema(description = "自然日周期-提前量(天)")
+    @ExcelProperty("自然日周期-提前量(天)")
+    private BigDecimal naturalDatePeroidLead;
+
+    @Schema(description = "BOM节点id", example = "13933")
+    @ExcelProperty("BOM节点id")
+    private Long bomNodeId;
+
+    @Schema(description = "BOM名称", example = "李四")
+    @ExcelProperty("BOM名称")
+    private String name;
+
+    @Schema(description = "BOM编码")
+    @ExcelProperty("BOM编码")
+    private String code;
+
+    @Schema(description = "父BOM id 顶级为0", example = "2631")
+    @ExcelProperty("父BOM id 顶级为0")
+    private Long parentId;
+
+    @Schema(description = "子节点id 逗号分隔")
+    @ExcelProperty("子节点id 逗号分隔")
+    private String childIds;
+
+    @Schema(description = "层级")
+    @ExcelProperty("层级")
+    private Integer level;
+
+    @Schema(description = "是否叶子节点 0是 1否")
+    @ExcelProperty("是否叶子节点 0是 1否")
+    private Integer leafFlag;
+
+    @Schema(description = "显示顺序")
+    @ExcelProperty("显示顺序")
+    private Integer sort;
+
+    @Schema(description = "1维修 2保养 维修+保养 (1,2)", example = "2")
+    @ExcelProperty("1维修 2保养 维修+保养 (1,2)")
+    private String type;
+
+    @Schema(description = "保养类型(1临时保养  2计划保养)", example = "1")
+    @ExcelProperty("保养类型(1临时保养  2计划保养)")
+    private Integer mainType;
+
+    @Schema(description = "状态 0启用  1停用", example = "2")
+    @ExcelProperty("状态 0启用  1停用")
+    private Integer status;
+
+    @Schema(description = "备注", example = "你说的对")
+    @ExcelProperty("备注")
+    private String remark;
+
+    @Schema(description = "版本")
+    @ExcelProperty("版本")
+    private Integer version;
+
+    @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
+    @ExcelProperty("创建时间")
+    private LocalDateTime createTime;
+
+}

+ 133 - 0
yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/iotmainworkorderbom/vo/IotMainWorkOrderBomSaveReqVO.java

@@ -0,0 +1,133 @@
+package cn.iocoder.yudao.module.pms.controller.admin.iotmainworkorderbom.vo;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+import java.math.BigDecimal;
+import java.time.LocalDateTime;
+
+@Schema(description = "管理后台 - PMS 保养计划明细BOM新增/修改 Request VO")
+@Data
+public class IotMainWorkOrderBomSaveReqVO {
+
+    @Schema(description = "主键", requiredMode = Schema.RequiredMode.REQUIRED, example = "31182")
+    private Long id;
+
+    @Schema(description = "保养计划id", example = "17036")
+    private Long planId;
+
+    @Schema(description = "保养计划明细id", example = "2291")
+    private Long planDetailId;
+
+    @Schema(description = "保养工单id", example = "28354")
+    private Long workOrderId;
+
+    @Schema(description = "所属设备分类", example = "5173")
+    private Long deviceCategoryId;
+
+    @Schema(description = "设备id", example = "4335")
+    private Long deviceId;
+
+    @Schema(description = "保养规则(量程 运行时间 自然日期) 可多选")
+    private String rule;
+
+    @Schema(description = "保养规则-里程(0启用 1停用)")
+    private Integer mileageRule;
+
+    @Schema(description = "保养规则-自然日期(0启用 1停用)")
+    private Integer naturalDateRule;
+
+    @Schema(description = "保养规则-运行时间(0启用 1停用)")
+    private Integer runningTimeRule;
+
+    @Schema(description = "上次保养运行时长(小时)")
+    private BigDecimal lastRunningTime;
+
+    @Schema(description = "下次保养运行时长(小时)")
+    private BigDecimal nextRunningTime;
+
+    @Schema(description = "推迟运行时长(小时)")
+    private BigDecimal delayDuration;
+
+    @Schema(description = "上次保养运行公里数(千米)")
+    private BigDecimal lastRunningKilometers;
+
+    @Schema(description = "下次保养运行公里数(千米)")
+    private BigDecimal nextRunningKilometers;
+
+    @Schema(description = "推迟运行公里数(千米)")
+    private BigDecimal delayKilomaters;
+
+    @Schema(description = "上次保养自然日期(天)")
+    private BigDecimal lastNaturalDate;
+
+    @Schema(description = "下次保养自然日期(天)")
+    private BigDecimal nextNaturalDate;
+
+    @Schema(description = "推迟自然日期(天)")
+    private BigDecimal delayNaturalDate;
+
+    @Schema(description = "推迟原因", example = "不对")
+    private String delayReason;
+
+    @Schema(description = "上次保养日期")
+    private LocalDateTime lastMainDate;
+
+    @Schema(description = "时间周期(小时)")
+    private BigDecimal timePeriod;
+
+    @Schema(description = "时间周期-提前量(小时)")
+    private BigDecimal timePeriodLead;
+
+    @Schema(description = "公里数周期(千米)")
+    private BigDecimal kilometerCycle;
+
+    @Schema(description = "公里数周期-提前量(千米)")
+    private BigDecimal kiloCycleLead;
+
+    @Schema(description = "自然日周期(天)")
+    private BigDecimal naturalDatePeriod;
+
+    @Schema(description = "自然日周期-提前量(天)")
+    private BigDecimal naturalDatePeroidLead;
+
+    @Schema(description = "BOM节点id", example = "13933")
+    private Long bomNodeId;
+
+    @Schema(description = "BOM名称", example = "李四")
+    private String name;
+
+    @Schema(description = "BOM编码")
+    private String code;
+
+    @Schema(description = "父BOM id 顶级为0", example = "2631")
+    private Long parentId;
+
+    @Schema(description = "子节点id 逗号分隔")
+    private String childIds;
+
+    @Schema(description = "层级")
+    private Integer level;
+
+    @Schema(description = "是否叶子节点 0是 1否")
+    private Integer leafFlag;
+
+    @Schema(description = "显示顺序")
+    private Integer sort;
+
+    @Schema(description = "1维修 2保养 维修+保养 (1,2)", example = "2")
+    private String type;
+
+    @Schema(description = "保养类型(1临时保养  2计划保养)", example = "1")
+    private Integer mainType;
+
+    @Schema(description = "状态 0启用  1停用", example = "2")
+    private Integer status;
+
+    @Schema(description = "备注", example = "你说的对")
+    private String remark;
+
+    @Schema(description = "版本")
+    private Integer version;
+
+}

+ 93 - 0
yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/iotmainworkorderbommaterial/IotMainWorkOrderBomMaterialController.java

@@ -0,0 +1,93 @@
+package cn.iocoder.yudao.module.pms.controller.admin.iotmainworkorderbommaterial;
+
+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.module.pms.controller.admin.iotmainworkorderbommaterial.vo.IotMainWorkOrderBomMaterialPageReqVO;
+import cn.iocoder.yudao.module.pms.controller.admin.iotmainworkorderbommaterial.vo.IotMainWorkOrderBomMaterialRespVO;
+import cn.iocoder.yudao.module.pms.controller.admin.iotmainworkorderbommaterial.vo.IotMainWorkOrderBomMaterialSaveReqVO;
+import cn.iocoder.yudao.module.pms.dal.dataobject.iotmainworkorderbommaterial.IotMainWorkOrderBomMaterialDO;
+import cn.iocoder.yudao.module.pms.service.iotmainworkorderbommaterial.IotMainWorkOrderBomMaterialService;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.Parameter;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.*;
+
+import javax.annotation.Resource;
+import javax.servlet.http.HttpServletResponse;
+import javax.validation.Valid;
+import java.io.IOException;
+import java.util.List;
+
+import static cn.iocoder.yudao.framework.apilog.core.enums.OperateTypeEnum.EXPORT;
+import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
+
+@Tag(name = "管理后台 - PMS 保养工单明细设备BOM挂载物料关联")
+@RestController
+@RequestMapping("/pms/iot-main-work-order-bom-material")
+@Validated
+public class IotMainWorkOrderBomMaterialController {
+
+    @Resource
+    private IotMainWorkOrderBomMaterialService iotMainWorkOrderBomMaterialService;
+
+    @PostMapping("/create")
+    @Operation(summary = "创建PMS 保养工单明细设备BOM挂载物料关联")
+    @PreAuthorize("@ss.hasPermission('pms:iot-main-work-order-bom-material:create')")
+    public CommonResult<Long> createIotMainWorkOrderBomMaterial(@Valid @RequestBody IotMainWorkOrderBomMaterialSaveReqVO createReqVO) {
+        return success(iotMainWorkOrderBomMaterialService.createIotMainWorkOrderBomMaterial(createReqVO));
+    }
+
+    @PutMapping("/update")
+    @Operation(summary = "更新PMS 保养工单明细设备BOM挂载物料关联")
+    @PreAuthorize("@ss.hasPermission('pms:iot-main-work-order-bom-material:update')")
+    public CommonResult<Boolean> updateIotMainWorkOrderBomMaterial(@Valid @RequestBody IotMainWorkOrderBomMaterialSaveReqVO updateReqVO) {
+        iotMainWorkOrderBomMaterialService.updateIotMainWorkOrderBomMaterial(updateReqVO);
+        return success(true);
+    }
+
+    @DeleteMapping("/delete")
+    @Operation(summary = "删除PMS 保养工单明细设备BOM挂载物料关联")
+    @Parameter(name = "id", description = "编号", required = true)
+    @PreAuthorize("@ss.hasPermission('pms:iot-main-work-order-bom-material:delete')")
+    public CommonResult<Boolean> deleteIotMainWorkOrderBomMaterial(@RequestParam("id") Long id) {
+        iotMainWorkOrderBomMaterialService.deleteIotMainWorkOrderBomMaterial(id);
+        return success(true);
+    }
+
+    @GetMapping("/get")
+    @Operation(summary = "获得PMS 保养工单明细设备BOM挂载物料关联")
+    @Parameter(name = "id", description = "编号", required = true, example = "1024")
+    @PreAuthorize("@ss.hasPermission('pms:iot-main-work-order-bom-material:query')")
+    public CommonResult<IotMainWorkOrderBomMaterialRespVO> getIotMainWorkOrderBomMaterial(@RequestParam("id") Long id) {
+        IotMainWorkOrderBomMaterialDO iotMainWorkOrderBomMaterial = iotMainWorkOrderBomMaterialService.getIotMainWorkOrderBomMaterial(id);
+        return success(BeanUtils.toBean(iotMainWorkOrderBomMaterial, IotMainWorkOrderBomMaterialRespVO.class));
+    }
+
+    @GetMapping("/page")
+    @Operation(summary = "获得PMS 保养工单明细设备BOM挂载物料关联分页")
+    @PreAuthorize("@ss.hasPermission('pms:iot-main-work-order-bom-material:query')")
+    public CommonResult<PageResult<IotMainWorkOrderBomMaterialRespVO>> getIotMainWorkOrderBomMaterialPage(@Valid IotMainWorkOrderBomMaterialPageReqVO pageReqVO) {
+        PageResult<IotMainWorkOrderBomMaterialDO> pageResult = iotMainWorkOrderBomMaterialService.getIotMainWorkOrderBomMaterialPage(pageReqVO);
+        return success(BeanUtils.toBean(pageResult, IotMainWorkOrderBomMaterialRespVO.class));
+    }
+
+    @GetMapping("/export-excel")
+    @Operation(summary = "导出PMS 保养工单明细设备BOM挂载物料关联 Excel")
+    @PreAuthorize("@ss.hasPermission('pms:iot-main-work-order-bom-material:export')")
+    @ApiAccessLog(operateType = EXPORT)
+    public void exportIotMainWorkOrderBomMaterialExcel(@Valid IotMainWorkOrderBomMaterialPageReqVO pageReqVO,
+              HttpServletResponse response) throws IOException {
+        pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE);
+        List<IotMainWorkOrderBomMaterialDO> list = iotMainWorkOrderBomMaterialService.getIotMainWorkOrderBomMaterialPage(pageReqVO).getList();
+        // 导出 Excel
+        ExcelUtils.write(response, "PMS 保养工单明细设备BOM挂载物料关联.xls", "数据", IotMainWorkOrderBomMaterialRespVO.class,
+                        BeanUtils.toBean(list, IotMainWorkOrderBomMaterialRespVO.class));
+    }
+
+}

+ 97 - 0
yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/iotmainworkorderbommaterial/vo/IotMainWorkOrderBomMaterialPageReqVO.java

@@ -0,0 +1,97 @@
+package cn.iocoder.yudao.module.pms.controller.admin.iotmainworkorderbommaterial.vo;
+
+import cn.iocoder.yudao.framework.common.pojo.PageParam;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.ToString;
+import org.springframework.format.annotation.DateTimeFormat;
+
+import java.math.BigDecimal;
+import java.time.LocalDateTime;
+
+import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
+
+@Schema(description = "管理后台 - PMS 保养工单明细设备BOM挂载物料关联分页 Request VO")
+@Data
+@EqualsAndHashCode(callSuper = true)
+@ToString(callSuper = true)
+public class IotMainWorkOrderBomMaterialPageReqVO extends PageParam {
+
+    @Schema(description = "保养计划id", example = "21957")
+    private Long mainPlanId;
+
+    @Schema(description = "保养工单id", example = "11659")
+    private Long workOrderId;
+
+    @Schema(description = "保养工单明细id", example = "28110")
+    private Long mainWorkOrderDetailId;
+
+    @Schema(description = "物料所属设备分类", example = "25032")
+    private Long deviceCategoryId;
+
+    @Schema(description = "保养工单明细设备BOM节点id", example = "17705")
+    private Long bomNodeId;
+
+    @Schema(description = "设备分类公共BOM节点名称", example = "芋艿")
+    private String name;
+
+    @Schema(description = "设备分类公共BOM节点编码")
+    private String code;
+
+    @Schema(description = "物料id", example = "2521")
+    private Long materialId;
+
+    @Schema(description = "物料编码")
+    private String materialCode;
+
+    @Schema(description = "物料名称", example = "芋艿")
+    private String materialName;
+
+    @Schema(description = "消耗数量")
+    private BigDecimal quantity;
+
+    @Schema(description = "单价(元)", example = "25019")
+    private BigDecimal unitPrice;
+
+    @Schema(description = "总金额(元)", example = "12420")
+    private BigDecimal totalPrice;
+
+    @Schema(description = "公里数周期(千米)")
+    private BigDecimal kilometerCycle;
+
+    @Schema(description = "公里数周期-提前量(千米)")
+    private BigDecimal kiloCycleLead;
+
+    @Schema(description = "时间周期(小时)")
+    private BigDecimal timePeriod;
+
+    @Schema(description = "时间周期-提前量(小时)")
+    private BigDecimal timePeriodLead;
+
+    @Schema(description = "自然日周期(天)")
+    private BigDecimal naturalDatePeriod;
+
+    @Schema(description = "自然日周期-提前量(天)")
+    private BigDecimal naturalDatePeroidLead;
+
+    @Schema(description = "物料来源 (SAP库存 本地库存...)")
+    private String materialSource;
+
+    @Schema(description = "库存地点")
+    private String inventoryAddress;
+
+    @Schema(description = "排序")
+    private Integer sort;
+
+    @Schema(description = "状态 0启用  1停用", example = "1")
+    private Integer status;
+
+    @Schema(description = "备注", example = "随便")
+    private String remark;
+
+    @Schema(description = "创建时间")
+    @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
+    private LocalDateTime[] createTime;
+
+}

+ 120 - 0
yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/iotmainworkorderbommaterial/vo/IotMainWorkOrderBomMaterialRespVO.java

@@ -0,0 +1,120 @@
+package cn.iocoder.yudao.module.pms.controller.admin.iotmainworkorderbommaterial.vo;
+
+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.math.BigDecimal;
+import java.time.LocalDateTime;
+
+@Schema(description = "管理后台 - PMS 保养工单明细设备BOM挂载物料关联 Response VO")
+@Data
+@ExcelIgnoreUnannotated
+public class IotMainWorkOrderBomMaterialRespVO {
+
+    @Schema(description = "主键", requiredMode = Schema.RequiredMode.REQUIRED, example = "30856")
+    @ExcelProperty("主键")
+    private Long id;
+
+    @Schema(description = "保养计划id", example = "21957")
+    @ExcelProperty("保养计划id")
+    private Long mainPlanId;
+
+    @Schema(description = "保养工单id", example = "11659")
+    @ExcelProperty("保养工单id")
+    private Long workOrderId;
+
+    @Schema(description = "保养工单明细id", example = "28110")
+    @ExcelProperty("保养工单明细id")
+    private Long mainWorkOrderDetailId;
+
+    @Schema(description = "物料所属设备分类", example = "25032")
+    @ExcelProperty("物料所属设备分类")
+    private Long deviceCategoryId;
+
+    @Schema(description = "保养工单明细设备BOM节点id", example = "17705")
+    @ExcelProperty("保养工单明细设备BOM节点id")
+    private Long bomNodeId;
+
+    @Schema(description = "设备分类公共BOM节点名称", example = "芋艿")
+    @ExcelProperty("设备分类公共BOM节点名称")
+    private String name;
+
+    @Schema(description = "设备分类公共BOM节点编码")
+    @ExcelProperty("设备分类公共BOM节点编码")
+    private String code;
+
+    @Schema(description = "物料id", example = "2521")
+    @ExcelProperty("物料id")
+    private Long materialId;
+
+    @Schema(description = "物料编码")
+    @ExcelProperty("物料编码")
+    private String materialCode;
+
+    @Schema(description = "物料名称", example = "芋艿")
+    @ExcelProperty("物料名称")
+    private String materialName;
+
+    @Schema(description = "消耗数量")
+    @ExcelProperty("消耗数量")
+    private BigDecimal quantity;
+
+    @Schema(description = "单价(元)", example = "25019")
+    @ExcelProperty("单价(元)")
+    private BigDecimal unitPrice;
+
+    @Schema(description = "总金额(元)", example = "12420")
+    @ExcelProperty("总金额(元)")
+    private BigDecimal totalPrice;
+
+    @Schema(description = "公里数周期(千米)")
+    @ExcelProperty("公里数周期(千米)")
+    private BigDecimal kilometerCycle;
+
+    @Schema(description = "公里数周期-提前量(千米)")
+    @ExcelProperty("公里数周期-提前量(千米)")
+    private BigDecimal kiloCycleLead;
+
+    @Schema(description = "时间周期(小时)")
+    @ExcelProperty("时间周期(小时)")
+    private BigDecimal timePeriod;
+
+    @Schema(description = "时间周期-提前量(小时)")
+    @ExcelProperty("时间周期-提前量(小时)")
+    private BigDecimal timePeriodLead;
+
+    @Schema(description = "自然日周期(天)")
+    @ExcelProperty("自然日周期(天)")
+    private BigDecimal naturalDatePeriod;
+
+    @Schema(description = "自然日周期-提前量(天)")
+    @ExcelProperty("自然日周期-提前量(天)")
+    private BigDecimal naturalDatePeroidLead;
+
+    @Schema(description = "物料来源 (SAP库存 本地库存...)")
+    @ExcelProperty("物料来源 (SAP库存 本地库存...)")
+    private String materialSource;
+
+    @Schema(description = "库存地点")
+    @ExcelProperty("库存地点")
+    private String inventoryAddress;
+
+    @Schema(description = "排序")
+    @ExcelProperty("排序")
+    private Integer sort;
+
+    @Schema(description = "状态 0启用  1停用", example = "1")
+    @ExcelProperty("状态 0启用  1停用")
+    private Integer status;
+
+    @Schema(description = "备注", example = "随便")
+    @ExcelProperty("备注")
+    private String remark;
+
+    @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
+    @ExcelProperty("创建时间")
+    private LocalDateTime createTime;
+
+}

+ 87 - 0
yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/iotmainworkorderbommaterial/vo/IotMainWorkOrderBomMaterialSaveReqVO.java

@@ -0,0 +1,87 @@
+package cn.iocoder.yudao.module.pms.controller.admin.iotmainworkorderbommaterial.vo;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+import java.math.BigDecimal;
+
+@Schema(description = "管理后台 - PMS 保养工单明细设备BOM挂载物料关联新增/修改 Request VO")
+@Data
+public class IotMainWorkOrderBomMaterialSaveReqVO {
+
+    @Schema(description = "主键", requiredMode = Schema.RequiredMode.REQUIRED, example = "30856")
+    private Long id;
+
+    @Schema(description = "保养计划id", example = "21957")
+    private Long mainPlanId;
+
+    @Schema(description = "保养工单id", example = "11659")
+    private Long workOrderId;
+
+    @Schema(description = "保养工单明细id", example = "28110")
+    private Long mainWorkOrderDetailId;
+
+    @Schema(description = "物料所属设备分类", example = "25032")
+    private Long deviceCategoryId;
+
+    @Schema(description = "保养工单明细设备BOM节点id", example = "17705")
+    private Long bomNodeId;
+
+    @Schema(description = "设备分类公共BOM节点名称", example = "芋艿")
+    private String name;
+
+    @Schema(description = "设备分类公共BOM节点编码")
+    private String code;
+
+    @Schema(description = "物料id", example = "2521")
+    private Long materialId;
+
+    @Schema(description = "物料编码")
+    private String materialCode;
+
+    @Schema(description = "物料名称", example = "芋艿")
+    private String materialName;
+
+    @Schema(description = "消耗数量")
+    private BigDecimal quantity;
+
+    @Schema(description = "单价(元)", example = "25019")
+    private BigDecimal unitPrice;
+
+    @Schema(description = "总金额(元)", example = "12420")
+    private BigDecimal totalPrice;
+
+    @Schema(description = "公里数周期(千米)")
+    private BigDecimal kilometerCycle;
+
+    @Schema(description = "公里数周期-提前量(千米)")
+    private BigDecimal kiloCycleLead;
+
+    @Schema(description = "时间周期(小时)")
+    private BigDecimal timePeriod;
+
+    @Schema(description = "时间周期-提前量(小时)")
+    private BigDecimal timePeriodLead;
+
+    @Schema(description = "自然日周期(天)")
+    private BigDecimal naturalDatePeriod;
+
+    @Schema(description = "自然日周期-提前量(天)")
+    private BigDecimal naturalDatePeroidLead;
+
+    @Schema(description = "物料来源 (SAP库存 本地库存...)")
+    private String materialSource;
+
+    @Schema(description = "库存地点")
+    private String inventoryAddress;
+
+    @Schema(description = "排序")
+    private Integer sort;
+
+    @Schema(description = "状态 0启用  1停用", example = "1")
+    private Integer status;
+
+    @Schema(description = "备注", example = "随便")
+    private String remark;
+
+}

+ 93 - 0
yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/iotmainworkorderdetails/IotMainWorkOrderDetailsController.java

@@ -0,0 +1,93 @@
+package cn.iocoder.yudao.module.pms.controller.admin.iotmainworkorderdetails;
+
+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.module.pms.controller.admin.iotmainworkorderdetails.vo.IotMainWorkOrderDetailsPageReqVO;
+import cn.iocoder.yudao.module.pms.controller.admin.iotmainworkorderdetails.vo.IotMainWorkOrderDetailsRespVO;
+import cn.iocoder.yudao.module.pms.controller.admin.iotmainworkorderdetails.vo.IotMainWorkOrderDetailsSaveReqVO;
+import cn.iocoder.yudao.module.pms.dal.dataobject.iotmainworkorderdetails.IotMainWorkOrderDetailsDO;
+import cn.iocoder.yudao.module.pms.service.iotmainworkorderdetails.IotMainWorkOrderDetailsService;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.Parameter;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.*;
+
+import javax.annotation.Resource;
+import javax.servlet.http.HttpServletResponse;
+import javax.validation.Valid;
+import java.io.IOException;
+import java.util.List;
+
+import static cn.iocoder.yudao.framework.apilog.core.enums.OperateTypeEnum.EXPORT;
+import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
+
+@Tag(name = "管理后台 - 保养工单明细")
+@RestController
+@RequestMapping("/pms/iot-main-work-order-details")
+@Validated
+public class IotMainWorkOrderDetailsController {
+
+    @Resource
+    private IotMainWorkOrderDetailsService iotMainWorkOrderDetailsService;
+
+    @PostMapping("/create")
+    @Operation(summary = "创建保养工单明细")
+    @PreAuthorize("@ss.hasPermission('pms:iot-main-work-order-details:create')")
+    public CommonResult<Long> createIotMainWorkOrderDetails(@Valid @RequestBody IotMainWorkOrderDetailsSaveReqVO createReqVO) {
+        return success(iotMainWorkOrderDetailsService.createIotMainWorkOrderDetails(createReqVO));
+    }
+
+    @PutMapping("/update")
+    @Operation(summary = "更新保养工单明细")
+    @PreAuthorize("@ss.hasPermission('pms:iot-main-work-order-details:update')")
+    public CommonResult<Boolean> updateIotMainWorkOrderDetails(@Valid @RequestBody IotMainWorkOrderDetailsSaveReqVO updateReqVO) {
+        iotMainWorkOrderDetailsService.updateIotMainWorkOrderDetails(updateReqVO);
+        return success(true);
+    }
+
+    @DeleteMapping("/delete")
+    @Operation(summary = "删除保养工单明细")
+    @Parameter(name = "id", description = "编号", required = true)
+    @PreAuthorize("@ss.hasPermission('pms:iot-main-work-order-details:delete')")
+    public CommonResult<Boolean> deleteIotMainWorkOrderDetails(@RequestParam("id") Long id) {
+        iotMainWorkOrderDetailsService.deleteIotMainWorkOrderDetails(id);
+        return success(true);
+    }
+
+    @GetMapping("/get")
+    @Operation(summary = "获得保养工单明细")
+    @Parameter(name = "id", description = "编号", required = true, example = "1024")
+    @PreAuthorize("@ss.hasPermission('pms:iot-main-work-order-details:query')")
+    public CommonResult<IotMainWorkOrderDetailsRespVO> getIotMainWorkOrderDetails(@RequestParam("id") Long id) {
+        IotMainWorkOrderDetailsDO iotMainWorkOrderDetails = iotMainWorkOrderDetailsService.getIotMainWorkOrderDetails(id);
+        return success(BeanUtils.toBean(iotMainWorkOrderDetails, IotMainWorkOrderDetailsRespVO.class));
+    }
+
+    @GetMapping("/page")
+    @Operation(summary = "获得保养工单明细分页")
+    @PreAuthorize("@ss.hasPermission('pms:iot-main-work-order-details:query')")
+    public CommonResult<PageResult<IotMainWorkOrderDetailsRespVO>> getIotMainWorkOrderDetailsPage(@Valid IotMainWorkOrderDetailsPageReqVO pageReqVO) {
+        PageResult<IotMainWorkOrderDetailsDO> pageResult = iotMainWorkOrderDetailsService.getIotMainWorkOrderDetailsPage(pageReqVO);
+        return success(BeanUtils.toBean(pageResult, IotMainWorkOrderDetailsRespVO.class));
+    }
+
+    @GetMapping("/export-excel")
+    @Operation(summary = "导出保养工单明细 Excel")
+    @PreAuthorize("@ss.hasPermission('pms:iot-main-work-order-details:export')")
+    @ApiAccessLog(operateType = EXPORT)
+    public void exportIotMainWorkOrderDetailsExcel(@Valid IotMainWorkOrderDetailsPageReqVO pageReqVO,
+              HttpServletResponse response) throws IOException {
+        pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE);
+        List<IotMainWorkOrderDetailsDO> list = iotMainWorkOrderDetailsService.getIotMainWorkOrderDetailsPage(pageReqVO).getList();
+        // 导出 Excel
+        ExcelUtils.write(response, "保养工单明细.xls", "数据", IotMainWorkOrderDetailsRespVO.class,
+                        BeanUtils.toBean(list, IotMainWorkOrderDetailsRespVO.class));
+    }
+
+}

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

@@ -0,0 +1,66 @@
+package cn.iocoder.yudao.module.pms.controller.admin.iotmainworkorderdetails.vo;
+
+import cn.iocoder.yudao.framework.common.pojo.PageParam;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.ToString;
+import org.springframework.format.annotation.DateTimeFormat;
+
+import java.math.BigDecimal;
+import java.time.LocalDateTime;
+
+import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
+
+@Schema(description = "管理后台 - 保养工单明细分页 Request VO")
+@Data
+@EqualsAndHashCode(callSuper = true)
+@ToString(callSuper = true)
+public class IotMainWorkOrderDetailsPageReqVO extends PageParam {
+
+    @Schema(description = "保养计划id", example = "32395")
+    private Long planId;
+
+    @Schema(description = "保养工单id", example = "26461")
+    private Long workOrderId;
+
+    @Schema(description = "设备id", example = "14822")
+    private Long deviceId;
+
+    @Schema(description = "设备资产编号")
+    private String deviceAssetNumber;
+
+    @Schema(description = "设备名称", example = "李四")
+    private String deviceName;
+
+    @Schema(description = "设备类别")
+    private String deviceCategory;
+
+    @Schema(description = "设备品牌")
+    private String deviceBrand;
+
+    @Schema(description = "当前运行公里数(km)")
+    private BigDecimal runningKilometers;
+
+    @Schema(description = "当前运行时间(小时)")
+    @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
+    private BigDecimal[] runningTime;
+
+    @Schema(description = "自然日期(天)")
+    @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
+    private BigDecimal[] naturalDate;
+
+    @Schema(description = "备注", example = "你说的对")
+    private String remark;
+
+    @Schema(description = "排序")
+    private Integer sort;
+
+    @Schema(description = "状态 0启用  1停用", example = "1")
+    private Integer status;
+
+    @Schema(description = "创建时间")
+    @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
+    private LocalDateTime[] createTime;
+
+}

+ 76 - 0
yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/iotmainworkorderdetails/vo/IotMainWorkOrderDetailsRespVO.java

@@ -0,0 +1,76 @@
+package cn.iocoder.yudao.module.pms.controller.admin.iotmainworkorderdetails.vo;
+
+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.math.BigDecimal;
+import java.time.LocalDateTime;
+
+@Schema(description = "管理后台 - 保养工单明细 Response VO")
+@Data
+@ExcelIgnoreUnannotated
+public class IotMainWorkOrderDetailsRespVO {
+
+    @Schema(description = "主键id", requiredMode = Schema.RequiredMode.REQUIRED, example = "26330")
+    @ExcelProperty("主键id")
+    private Long id;
+
+    @Schema(description = "保养计划id", example = "32395")
+    @ExcelProperty("保养计划id")
+    private Long planId;
+
+    @Schema(description = "保养工单id", example = "26461")
+    @ExcelProperty("保养工单id")
+    private Long workOrderId;
+
+    @Schema(description = "设备id", example = "14822")
+    @ExcelProperty("设备id")
+    private Long deviceId;
+
+    @Schema(description = "设备资产编号")
+    @ExcelProperty("设备资产编号")
+    private String deviceAssetNumber;
+
+    @Schema(description = "设备名称", example = "李四")
+    @ExcelProperty("设备名称")
+    private String deviceName;
+
+    @Schema(description = "设备类别")
+    @ExcelProperty("设备类别")
+    private String deviceCategory;
+
+    @Schema(description = "设备品牌")
+    @ExcelProperty("设备品牌")
+    private String deviceBrand;
+
+    @Schema(description = "当前运行公里数(km)")
+    @ExcelProperty("当前运行公里数(km)")
+    private BigDecimal runningKilometers;
+
+    @Schema(description = "当前运行时间(小时)")
+    @ExcelProperty("当前运行时间(小时)")
+    private BigDecimal runningTime;
+
+    @Schema(description = "自然日期(天)")
+    @ExcelProperty("自然日期(天)")
+    private BigDecimal naturalDate;
+
+    @Schema(description = "备注", example = "你说的对")
+    @ExcelProperty("备注")
+    private String remark;
+
+    @Schema(description = "排序")
+    @ExcelProperty("排序")
+    private Integer sort;
+
+    @Schema(description = "状态 0启用  1停用", example = "1")
+    @ExcelProperty("状态 0启用  1停用")
+    private Integer status;
+
+    @Schema(description = "创建时间")
+    @ExcelProperty("创建时间")
+    private LocalDateTime createTime;
+
+}

+ 54 - 0
yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/iotmainworkorderdetails/vo/IotMainWorkOrderDetailsSaveReqVO.java

@@ -0,0 +1,54 @@
+package cn.iocoder.yudao.module.pms.controller.admin.iotmainworkorderdetails.vo;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+import java.math.BigDecimal;
+
+@Schema(description = "管理后台 - 保养工单明细新增/修改 Request VO")
+@Data
+public class IotMainWorkOrderDetailsSaveReqVO {
+
+    @Schema(description = "主键id", requiredMode = Schema.RequiredMode.REQUIRED, example = "26330")
+    private Long id;
+
+    @Schema(description = "保养计划id", example = "32395")
+    private Long planId;
+
+    @Schema(description = "保养工单id", example = "26461")
+    private Long workOrderId;
+
+    @Schema(description = "设备id", example = "14822")
+    private Long deviceId;
+
+    @Schema(description = "设备资产编号")
+    private String deviceAssetNumber;
+
+    @Schema(description = "设备名称", example = "李四")
+    private String deviceName;
+
+    @Schema(description = "设备类别")
+    private String deviceCategory;
+
+    @Schema(description = "设备品牌")
+    private String deviceBrand;
+
+    @Schema(description = "当前运行公里数(km)")
+    private BigDecimal runningKilometers;
+
+    @Schema(description = "当前运行时间(小时)")
+    private BigDecimal runningTime;
+
+    @Schema(description = "自然日期(天)")
+    private BigDecimal naturalDate;
+
+    @Schema(description = "备注", example = "你说的对")
+    private String remark;
+
+    @Schema(description = "排序")
+    private Integer sort;
+
+    @Schema(description = "状态 0启用  1停用", example = "1")
+    private Integer status;
+
+}

+ 45 - 21
yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/maintenance/IotMaintenancePlanController.java

@@ -1,34 +1,41 @@
 package cn.iocoder.yudao.module.pms.controller.admin.maintenance;
 
+import cn.hutool.core.collection.CollUtil;
+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.collection.MapUtils;
+import cn.iocoder.yudao.framework.common.util.number.NumberUtils;
+import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
+import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;
 import cn.iocoder.yudao.module.pms.controller.admin.maintenance.vo.IotMaintenancePlanPageReqVO;
 import cn.iocoder.yudao.module.pms.controller.admin.maintenance.vo.IotMaintenancePlanRespVO;
 import cn.iocoder.yudao.module.pms.controller.admin.maintenance.vo.IotMaintenancePlanSaveReqVO;
+import cn.iocoder.yudao.module.pms.controller.admin.maintenance.vo.IotMaintenanceSaveVO;
 import cn.iocoder.yudao.module.pms.dal.dataobject.maintenance.IotMaintenancePlanDO;
 import cn.iocoder.yudao.module.pms.service.maintenance.IotMaintenancePlanService;
-import org.springframework.web.bind.annotation.*;
-import javax.annotation.Resource;
-import org.springframework.validation.annotation.Validated;
-import org.springframework.security.access.prepost.PreAuthorize;
-import io.swagger.v3.oas.annotations.tags.Tag;
-import io.swagger.v3.oas.annotations.Parameter;
+import cn.iocoder.yudao.module.system.api.user.AdminUserApi;
+import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO;
 import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.Parameter;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.*;
 
-import javax.validation.constraints.*;
-import javax.validation.*;
-import javax.servlet.http.*;
-import java.util.*;
+import javax.annotation.Resource;
+import javax.servlet.http.HttpServletResponse;
+import javax.validation.Valid;
 import java.io.IOException;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Stream;
 
-import cn.iocoder.yudao.framework.common.pojo.PageParam;
-import cn.iocoder.yudao.framework.common.pojo.PageResult;
-import cn.iocoder.yudao.framework.common.pojo.CommonResult;
-import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
+import static cn.iocoder.yudao.framework.apilog.core.enums.OperateTypeEnum.EXPORT;
 import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
-
-import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;
-
-import cn.iocoder.yudao.framework.apilog.core.annotation.ApiAccessLog;
-import static cn.iocoder.yudao.framework.apilog.core.enums.OperateTypeEnum.*;
+import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertListByFlatMap;
 
 
 @Tag(name = "管理后台 - 保养计划")
@@ -39,11 +46,13 @@ public class IotMaintenancePlanController {
 
     @Resource
     private IotMaintenancePlanService iotMaintenancePlanService;
+    @Resource
+    private AdminUserApi adminUserApi;
 
     @PostMapping("/create")
     @Operation(summary = "创建保养计划")
     @PreAuthorize("@ss.hasPermission('rq:iot-maintenance-plan:create')")
-    public CommonResult<Long> createIotMaintenancePlan(@Valid @RequestBody IotMaintenancePlanSaveReqVO createReqVO) {
+    public CommonResult<Long> createIotMaintenancePlan(@Valid @RequestBody IotMaintenanceSaveVO createReqVO) {
         return success(iotMaintenancePlanService.createIotMaintenancePlan(createReqVO));
     }
 
@@ -78,7 +87,7 @@ public class IotMaintenancePlanController {
     @PreAuthorize("@ss.hasPermission('rq:iot-maintenance-plan:query')")
     public CommonResult<PageResult<IotMaintenancePlanRespVO>> getIotMaintenancePlanPage(@Valid IotMaintenancePlanPageReqVO pageReqVO) {
         PageResult<IotMaintenancePlanDO> pageResult = iotMaintenancePlanService.getIotMaintenancePlanPage(pageReqVO);
-        return success(BeanUtils.toBean(pageResult, IotMaintenancePlanRespVO.class));
+        return success(new PageResult<>(buildMaintenancePlanList(pageResult.getList()), pageResult.getTotal()));
     }
 
     @GetMapping("/export-excel")
@@ -94,4 +103,19 @@ public class IotMaintenancePlanController {
                         BeanUtils.toBean(list, IotMaintenancePlanRespVO.class));
     }
 
+    private List<IotMaintenancePlanRespVO> buildMaintenancePlanList(List<IotMaintenancePlanDO> plans) {
+        if (CollUtil.isEmpty(plans)) {
+            return Collections.emptyList();
+        }
+        // 查询保养计划 负责人
+        Map<Long, AdminUserRespDTO> userMap = adminUserApi.getUserMap(convertListByFlatMap(plans,
+                plan -> Stream.of(NumberUtils.parseLong(plan.getResponsiblePerson()))));
+        // 2. 转换成 VO
+        return BeanUtils.toBean(plans, IotMaintenancePlanRespVO.class, planVO -> {
+            // 2.2 设置创建人、负责人名称
+            MapUtils.findAndThen(userMap, NumberUtils.parseLong(planVO.getResponsiblePerson()),
+                    user -> planVO.setResponsiblePersonName(user.getNickname()));
+        });
+    }
+
 }

+ 1 - 3
yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/maintenance/vo/IotMaintenancePlanSaveReqVO.java

@@ -1,9 +1,7 @@
 package cn.iocoder.yudao.module.pms.controller.admin.maintenance.vo;
 
 import io.swagger.v3.oas.annotations.media.Schema;
-import lombok.*;
-import java.util.*;
-import javax.validation.constraints.*;
+import lombok.Data;
 
 @Schema(description = "管理后台 - 保养计划新增/修改 Request VO")
 @Data

+ 17 - 0
yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/maintenance/vo/IotMaintenanceSaveVO.java

@@ -0,0 +1,17 @@
+package cn.iocoder.yudao.module.pms.controller.admin.maintenance.vo;
+
+import cn.iocoder.yudao.module.pms.controller.admin.iotmaintenancebom.vo.IotMaintenanceBomSaveReqVO;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+import java.util.List;
+
+@Schema(description = "管理后台 - 保养计划 保存/修改 Request VO")
+@Data
+public class IotMaintenanceSaveVO {
+    @Schema(description = "保养计划")
+    private IotMaintenancePlanSaveReqVO mainPlan;
+    @Schema(description = "保养计划明细")
+    private List<IotMaintenanceBomSaveReqVO> mainPlanBom;
+
+}

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

@@ -7,8 +7,8 @@ import lombok.EqualsAndHashCode;
 import lombok.ToString;
 import org.springframework.format.annotation.DateTimeFormat;
 
-import java.time.LocalDate;
 import java.time.LocalDateTime;
+import java.util.List;
 
 import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
 
@@ -106,4 +106,19 @@ public class IotDevicePageReqVO extends PageParam {
     private Long assetClass;
     @Schema(description = "创建时间")
     private LocalDateTime createTime;
+
+    /**
+     * bom相关信息
+     */
+    @Schema(description = "BOM名称", example = "李四")
+    private String name;
+
+    @Schema(description = "BOM编码")
+    private String code;
+
+    /**
+     * 自定义请求参数
+     */
+    @Schema(description = "设备id集合")
+    private List<Long> deviceIds;
 }

+ 13 - 4
yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/vo/IotDeviceRespVO.java

@@ -1,12 +1,11 @@
 package cn.iocoder.yudao.module.pms.controller.admin.vo;
 
+import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
+import com.alibaba.excel.annotation.ExcelProperty;
 import io.swagger.v3.oas.annotations.media.Schema;
-import lombok.*;
+import lombok.Data;
 
-import java.time.LocalDate;
 import java.time.LocalDateTime;
-import java.util.*;
-import com.alibaba.excel.annotation.*;
 
 @Schema(description = "管理后台 - 设备台账 Response VO")
 @Data
@@ -144,4 +143,14 @@ public class IotDeviceRespVO {
     private String supplierName;
     @Schema(description = "规格名称")
     private String modelName;
+
+    /**
+     * 设备关联bom相关信息
+     */
+    @Schema(description = "bom节点id")
+    private String bomNodeId;
+    @Schema(description = "bom节点名称")
+    private String name;
+    @Schema(description = "bom节点编码")
+    private String code;
 }

+ 1 - 1
yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/dal/dataobject/iotbom/IotBomDO.java

@@ -59,7 +59,7 @@ public class IotBomDO extends BaseDO {
      */
     private Integer sort;
     /**
-     * M维修 S保养 维修+保养
+     * 1维修 2保养 维修+保养
      */
     @TableField(typeHandler = IntegerListTypeHandler.class)
     private List<Integer> type;

+ 16 - 0
yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/dal/dataobject/iotmaintenancebom/IotMaintenanceBomDO.java

@@ -48,6 +48,18 @@ public class IotMaintenanceBomDO extends BaseDO {
      * 保养规则(量程 运行时间 自然日期) 可多选
      */
     private String rule;
+    /**
+     * 保养规则-里程(0启用 1停用)
+     */
+    private Integer mileageRule;
+    /**
+     * 保养规则-自然日期(0启用 1停用)
+     */
+    private Integer naturalDateRule;
+    /**
+     * 保养规则-运行时间(0启用 1停用)
+     */
+    private Integer runningTimeRule;
     /**
      * 上次保养运行时长(小时)
      */
@@ -72,6 +84,10 @@ public class IotMaintenanceBomDO extends BaseDO {
      * 下次保养自然日期(天)
      */
     private BigDecimal nextNaturalDate;
+    /**
+     * BOM节点id
+     */
+    private Long bomNodeId;
     /**
      * BOM名称
      */

+ 109 - 0
yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/dal/dataobject/iotmainworkorder/IotMainWorkOrderDO.java

@@ -0,0 +1,109 @@
+package cn.iocoder.yudao.module.pms.dal.dataobject.iotmainworkorder;
+
+import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
+import com.baomidou.mybatisplus.annotation.KeySequence;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.*;
+
+import java.math.BigDecimal;
+import java.time.LocalDateTime;
+
+/**
+ * 保养工单 DO
+ *
+ * @author ruiqi
+ */
+@TableName("rq_iot_main_work_order")
+@KeySequence("rq_iot_main_work_order_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
+@Data
+@EqualsAndHashCode(callSuper = true)
+@ToString(callSuper = true)
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+public class IotMainWorkOrderDO extends BaseDO {
+
+    /**
+     * 主键id
+     */
+    @TableId
+    private Long id;
+    /**
+     * 保养计划id
+     */
+    private Long planId;
+    /**
+     * 保养计划编号
+     */
+    private String planSerialNumber;
+    /**
+     * 组织id
+     */
+    private Long deptId;
+    /**
+     * 工单号
+     */
+    private String orderNumber;
+    /**
+     * 工单名称 (吐哈-C14-保养计划)
+     */
+    private String name;
+    /**
+     * 工单类型(1计划生成  2临时新建)
+     */
+    private Integer type;
+    /**
+     * 负责人id 多个以逗号分隔
+     */
+    private String responsiblePerson;
+    /**
+     * 负责人id 多个以逗号分隔
+     */
+    private String responsiblePersonName;
+    /**
+     * 保养费用
+     */
+    private BigDecimal cost;
+    /**
+     * 保养结果(1待执行 2已执行)
+     */
+    private Integer result;
+    /**
+     * 其他费用
+     */
+    private BigDecimal otherCost;
+    /**
+     * 人工费用
+     */
+    private BigDecimal laborCost;
+    /**
+     * 是否委外 0否  1是
+     */
+    private Integer outsourcingFlag;
+    /**
+     * 实际保养开始时间
+     */
+    private LocalDateTime actualStartTime;
+    /**
+     * 实际保养结束时间
+     */
+    private LocalDateTime actualEndTime;
+    /**
+     * 备注
+     */
+    private String remark;
+    /**
+     * 状态 0启用  1停用
+     */
+    private Integer status;
+    /**
+     * 流程实例id
+     */
+    private String processInstanceId;
+    /**
+     * 审批状态 未提交、审批中、审批通过、审批不通过、已取消
+     */
+    private Integer auditStatus;
+
+}

+ 189 - 0
yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/dal/dataobject/iotmainworkorderbom/IotMainWorkOrderBomDO.java

@@ -0,0 +1,189 @@
+package cn.iocoder.yudao.module.pms.dal.dataobject.iotmainworkorderbom;
+
+import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
+import com.baomidou.mybatisplus.annotation.KeySequence;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.*;
+
+import java.math.BigDecimal;
+import java.time.LocalDateTime;
+
+/**
+ * PMS 保养计划明细BOM DO
+ *
+ * @author ruiqi
+ */
+@TableName("rq_iot_main_work_order_bom")
+@KeySequence("rq_iot_main_work_order_bom_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
+@Data
+@EqualsAndHashCode(callSuper = true)
+@ToString(callSuper = true)
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+public class IotMainWorkOrderBomDO extends BaseDO {
+
+    /**
+     * 主键
+     */
+    @TableId
+    private Long id;
+    /**
+     * 保养计划id
+     */
+    private Long planId;
+    /**
+     * 保养计划明细id
+     */
+    private Long planDetailId;
+    /**
+     * 保养工单id
+     */
+    private Long workOrderId;
+    /**
+     * 所属设备分类
+     */
+    private Long deviceCategoryId;
+    /**
+     * 设备id
+     */
+    private Long deviceId;
+    /**
+     * 保养规则(量程 运行时间 自然日期) 可多选
+     */
+    private String rule;
+    /**
+     * 保养规则-里程(0启用 1停用)
+     */
+    private Integer mileageRule;
+    /**
+     * 保养规则-自然日期(0启用 1停用)
+     */
+    private Integer naturalDateRule;
+    /**
+     * 保养规则-运行时间(0启用 1停用)
+     */
+    private Integer runningTimeRule;
+    /**
+     * 上次保养运行时长(小时)
+     */
+    private BigDecimal lastRunningTime;
+    /**
+     * 下次保养运行时长(小时)
+     */
+    private BigDecimal nextRunningTime;
+    /**
+     * 推迟运行时长(小时)
+     */
+    private BigDecimal delayDuration;
+    /**
+     * 上次保养运行公里数(千米)
+     */
+    private BigDecimal lastRunningKilometers;
+    /**
+     * 下次保养运行公里数(千米)
+     */
+    private BigDecimal nextRunningKilometers;
+    /**
+     * 推迟运行公里数(千米)
+     */
+    private BigDecimal delayKilomaters;
+    /**
+     * 上次保养自然日期(天)
+     */
+    private BigDecimal lastNaturalDate;
+    /**
+     * 下次保养自然日期(天)
+     */
+    private BigDecimal nextNaturalDate;
+    /**
+     * 推迟自然日期(天)
+     */
+    private BigDecimal delayNaturalDate;
+    /**
+     * 推迟原因
+     */
+    private String delayReason;
+    /**
+     * 上次保养日期
+     */
+    private LocalDateTime lastMainDate;
+    /**
+     * 时间周期(小时)
+     */
+    private BigDecimal timePeriod;
+    /**
+     * 时间周期-提前量(小时)
+     */
+    private BigDecimal timePeriodLead;
+    /**
+     * 公里数周期(千米)
+     */
+    private BigDecimal kilometerCycle;
+    /**
+     * 公里数周期-提前量(千米)
+     */
+    private BigDecimal kiloCycleLead;
+    /**
+     * 自然日周期(天)
+     */
+    private BigDecimal naturalDatePeriod;
+    /**
+     * 自然日周期-提前量(天)
+     */
+    private BigDecimal naturalDatePeroidLead;
+    /**
+     * BOM节点id
+     */
+    private Long bomNodeId;
+    /**
+     * BOM名称
+     */
+    private String name;
+    /**
+     * BOM编码
+     */
+    private String code;
+    /**
+     * 父BOM id 顶级为0
+     */
+    private Long parentId;
+    /**
+     * 子节点id 逗号分隔
+     */
+    private String childIds;
+    /**
+     * 层级
+     */
+    private Integer level;
+    /**
+     * 是否叶子节点 0是 1否
+     */
+    private Integer leafFlag;
+    /**
+     * 显示顺序
+     */
+    private Integer sort;
+    /**
+     * 1维修 2保养 维修+保养 (1,2)
+     */
+    private String type;
+    /**
+     * 保养类型(1临时保养  2计划保养)
+     */
+    private Integer mainType;
+    /**
+     * 状态 0启用  1停用
+     */
+    private Integer status;
+    /**
+     * 备注
+     */
+    private String remark;
+    /**
+     * 版本
+     */
+    private Integer version;
+
+}

+ 128 - 0
yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/dal/dataobject/iotmainworkorderbommaterial/IotMainWorkOrderBomMaterialDO.java

@@ -0,0 +1,128 @@
+package cn.iocoder.yudao.module.pms.dal.dataobject.iotmainworkorderbommaterial;
+
+import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
+import com.baomidou.mybatisplus.annotation.KeySequence;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.*;
+
+import java.math.BigDecimal;
+
+/**
+ * PMS 保养工单明细设备BOM挂载物料关联 DO
+ *
+ * @author ruiqi
+ */
+@TableName("rq_iot_main_work_order_bom_material")
+@KeySequence("rq_iot_main_work_order_bom_material_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
+@Data
+@EqualsAndHashCode(callSuper = true)
+@ToString(callSuper = true)
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+public class IotMainWorkOrderBomMaterialDO extends BaseDO {
+
+    /**
+     * 主键
+     */
+    @TableId
+    private Long id;
+    /**
+     * 保养计划id
+     */
+    private Long mainPlanId;
+    /**
+     * 保养工单id
+     */
+    private Long workOrderId;
+    /**
+     * 保养工单明细id
+     */
+    private Long mainWorkOrderDetailId;
+    /**
+     * 物料所属设备分类
+     */
+    private Long deviceCategoryId;
+    /**
+     * 保养工单明细设备BOM节点id
+     */
+    private Long bomNodeId;
+    /**
+     * 设备分类公共BOM节点名称
+     */
+    private String name;
+    /**
+     * 设备分类公共BOM节点编码
+     */
+    private String code;
+    /**
+     * 物料id
+     */
+    private Long materialId;
+    /**
+     * 物料编码
+     */
+    private String materialCode;
+    /**
+     * 物料名称
+     */
+    private String materialName;
+    /**
+     * 消耗数量
+     */
+    private BigDecimal quantity;
+    /**
+     * 单价(元)
+     */
+    private BigDecimal unitPrice;
+    /**
+     * 总金额(元)
+     */
+    private BigDecimal totalPrice;
+    /**
+     * 公里数周期(千米)
+     */
+    private BigDecimal kilometerCycle;
+    /**
+     * 公里数周期-提前量(千米)
+     */
+    private BigDecimal kiloCycleLead;
+    /**
+     * 时间周期(小时)
+     */
+    private BigDecimal timePeriod;
+    /**
+     * 时间周期-提前量(小时)
+     */
+    private BigDecimal timePeriodLead;
+    /**
+     * 自然日周期(天)
+     */
+    private BigDecimal naturalDatePeriod;
+    /**
+     * 自然日周期-提前量(天)
+     */
+    private BigDecimal naturalDatePeroidLead;
+    /**
+     * 物料来源 (SAP库存 本地库存...)
+     */
+    private String materialSource;
+    /**
+     * 库存地点
+     */
+    private String inventoryAddress;
+    /**
+     * 排序
+     */
+    private Integer sort;
+    /**
+     * 状态 0启用  1停用
+     */
+    private Integer status;
+    /**
+     * 备注
+     */
+    private String remark;
+
+}

+ 84 - 0
yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/dal/dataobject/iotmainworkorderdetails/IotMainWorkOrderDetailsDO.java

@@ -0,0 +1,84 @@
+package cn.iocoder.yudao.module.pms.dal.dataobject.iotmainworkorderdetails;
+
+import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
+import com.baomidou.mybatisplus.annotation.KeySequence;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.*;
+
+import java.math.BigDecimal;
+
+/**
+ * 保养工单明细 DO
+ *
+ * @author ruiqi
+ */
+@TableName("rq_iot_main_work_order_details")
+@KeySequence("rq_iot_main_work_order_details_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
+@Data
+@EqualsAndHashCode(callSuper = true)
+@ToString(callSuper = true)
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+public class IotMainWorkOrderDetailsDO extends BaseDO {
+
+    /**
+     * 主键id
+     */
+    @TableId
+    private Long id;
+    /**
+     * 保养计划id
+     */
+    private Long planId;
+    /**
+     * 保养工单id
+     */
+    private Long workOrderId;
+    /**
+     * 设备id
+     */
+    private Long deviceId;
+    /**
+     * 设备资产编号
+     */
+    private String deviceAssetNumber;
+    /**
+     * 设备名称
+     */
+    private String deviceName;
+    /**
+     * 设备类别
+     */
+    private String deviceCategory;
+    /**
+     * 设备品牌
+     */
+    private String deviceBrand;
+    /**
+     * 当前运行公里数(km)
+     */
+    private BigDecimal runningKilometers;
+    /**
+     * 当前运行时间(小时)
+     */
+    private BigDecimal runningTime;
+    /**
+     * 自然日期(天)
+     */
+    private BigDecimal naturalDate;
+    /**
+     * 备注
+     */
+    private String remark;
+    /**
+     * 排序
+     */
+    private Integer sort;
+    /**
+     * 状态 0启用  1停用
+     */
+    private Integer status;
+
+}

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

@@ -4,12 +4,14 @@ 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.vo.IotDevicePageReqVO;
+import cn.iocoder.yudao.module.pms.controller.admin.vo.IotDeviceRespVO;
 import cn.iocoder.yudao.module.pms.dal.dataobject.IotDeviceDO;
-import cn.iocoder.yudao.module.system.controller.admin.user.vo.user.UserPageReqVO;
-import cn.iocoder.yudao.module.system.dal.dataobject.user.AdminUserDO;
+import com.baomidou.mybatisplus.core.metadata.IPage;
 import org.apache.ibatis.annotations.Mapper;
+import org.apache.ibatis.annotations.Param;
 
 import java.util.Collection;
+import java.util.List;
 
 /**
  * 设备台账 Mapper
@@ -52,4 +54,19 @@ public interface IotDeviceMapper extends BaseMapperX<IotDeviceDO> {
                 .orderByDesc(IotDeviceDO::getId));
     }
 
+    /* default PageResult<IotDeviceDO> deviceAssociateBomPage(IotDevicePageReqVO reqVO, Collection<Long> deptIds) {
+        MPJLambdaWrapperX<IotDeviceDO> query = new MPJLambdaWrapperX<IotDeviceDO>();
+        query.innerJoin(IotBomDO.class, IotBomDO::getDeviceCategoryId, IotDeviceDO::getAssetClass)
+                .eq(IotBomDO::getLeafFlag, 1)
+                .like(IotBomDO::getType, "2")
+                .in(CollUtil.isNotEmpty(deptIds), IotDeviceDO::getDeptId, deptIds)
+                .like(StrUtil.isNotBlank(reqVO.getDeviceName()), IotDeviceDO::getDeviceName, reqVO.getDeviceName())
+                .like(StrUtil.isNotBlank(reqVO.getName()), IotBomDO::getName, reqVO.getName());
+        return selectJoinPage(reqVO, IotDeviceDO.class, query);
+    } */
+
+    IPage<IotDeviceRespVO> deviceAssociateBomPage(IPage<IotDeviceRespVO> page,
+                                                  @Param("reqVO") IotDevicePageReqVO reqVO, @Param("deptIds") Collection<Long> deptIds);
+
+    List<IotDeviceRespVO> deviceAssociateBomList(@Param("deviceIds") Collection<Long> deviceIds);
 }

+ 22 - 0
yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/dal/mysql/iotbom/IotBomMapper.java

@@ -1,14 +1,18 @@
 package cn.iocoder.yudao.module.pms.dal.mysql.iotbom;
 
+import cn.hutool.core.util.StrUtil;
 import cn.iocoder.yudao.framework.common.pojo.PageResult;
 import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
 import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
+import cn.iocoder.yudao.framework.mybatis.core.query.MPJLambdaWrapperX;
 import cn.iocoder.yudao.module.pms.controller.admin.iotbom.vo.IotBomListReqVO;
 import cn.iocoder.yudao.module.pms.controller.admin.iotbom.vo.IotBomPageReqVO;
 import cn.iocoder.yudao.module.pms.controller.admin.iotbom.vo.IotBomSaveReqVO;
+import cn.iocoder.yudao.module.pms.dal.dataobject.IotDeviceDO;
 import cn.iocoder.yudao.module.pms.dal.dataobject.iotbom.IotBomDO;
 import org.apache.ibatis.annotations.Mapper;
 
+import java.util.Collection;
 import java.util.List;
 
 /**
@@ -47,4 +51,22 @@ public interface IotBomMapper extends BaseMapperX<IotBomDO> {
     default IotBomDO selectParentNode(IotBomSaveReqVO reqVO) {
         return selectOne(IotBomDO::getId, reqVO.getParentId());
     }
+
+    default PageResult<IotBomDO> deviceAssociateBomPage(IotBomPageReqVO reqVO) {
+        MPJLambdaWrapperX<IotBomDO> query = new MPJLambdaWrapperX<IotBomDO>();
+        query.innerJoin(IotDeviceDO.class, IotDeviceDO::getAssetClass, IotBomDO::getDeviceCategoryId)
+                .eq(IotBomDO::getLeafFlag, 1)
+                .like(IotBomDO::getType, "2")
+                .like(StrUtil.isNotBlank(reqVO.getDeviceName()), IotDeviceDO::getDeviceName, reqVO.getDeviceName())
+                .like(StrUtil.isNotBlank(reqVO.getName()), IotBomDO::getName, reqVO.getName());
+
+        return selectJoinPage(reqVO, IotBomDO.class, query);
+    }
+
+    default List<IotBomDO> getListByDeviceCategoryIds(Collection<Long> deviceCategoryIds) {
+        return selectList(new LambdaQueryWrapperX<IotBomDO>()
+                .inIfPresent(IotBomDO::getDeviceCategoryId, deviceCategoryIds)
+                .eq(IotBomDO::getLeafFlag, 1)
+                .like(IotBomDO::getType, "2"));
+    }
 }

+ 12 - 0
yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/dal/mysql/iotmaintenancebom/IotMaintenanceBomMapper.java

@@ -1,9 +1,12 @@
 package cn.iocoder.yudao.module.pms.dal.mysql.iotmaintenancebom;
 
+import cn.hutool.core.util.StrUtil;
 import cn.iocoder.yudao.framework.common.pojo.PageResult;
 import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
 import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
+import cn.iocoder.yudao.framework.mybatis.core.query.MPJLambdaWrapperX;
 import cn.iocoder.yudao.module.pms.controller.admin.iotmaintenancebom.vo.IotMaintenanceBomPageReqVO;
+import cn.iocoder.yudao.module.pms.dal.dataobject.IotDeviceDO;
 import cn.iocoder.yudao.module.pms.dal.dataobject.iotmaintenancebom.IotMaintenanceBomDO;
 import org.apache.ibatis.annotations.Mapper;
 
@@ -43,4 +46,13 @@ public interface IotMaintenanceBomMapper extends BaseMapperX<IotMaintenanceBomDO
                 .orderByDesc(IotMaintenanceBomDO::getId));
     }
 
+    default PageResult<IotMaintenanceBomDO> deviceAssociateBomPage(IotMaintenanceBomPageReqVO reqVO) {
+        MPJLambdaWrapperX<IotMaintenanceBomDO> query = new MPJLambdaWrapperX<IotMaintenanceBomDO>();
+        query.leftJoin(IotDeviceDO.class, IotDeviceDO::getAssetClass, IotMaintenanceBomDO::getDeviceCategoryId)
+                .like(StrUtil.isNotBlank(reqVO.getDeviceName()), IotDeviceDO::getDeviceName, reqVO.getDeviceName())
+                .like(StrUtil.isNotBlank(reqVO.getName()), IotMaintenanceBomDO::getName, reqVO.getName());
+
+        return selectJoinPage(reqVO, IotMaintenanceBomDO.class, query);
+    }
+
 }

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

@@ -0,0 +1,43 @@
+package cn.iocoder.yudao.module.pms.dal.mysql.iotmainworkorder;
+
+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.iotmainworkorder.vo.IotMainWorkOrderPageReqVO;
+import cn.iocoder.yudao.module.pms.dal.dataobject.iotmainworkorder.IotMainWorkOrderDO;
+import org.apache.ibatis.annotations.Mapper;
+
+/**
+ * 保养工单 Mapper
+ *
+ * @author ruiqi
+ */
+@Mapper
+public interface IotMainWorkOrderMapper extends BaseMapperX<IotMainWorkOrderDO> {
+
+    default PageResult<IotMainWorkOrderDO> selectPage(IotMainWorkOrderPageReqVO reqVO) {
+        return selectPage(reqVO, new LambdaQueryWrapperX<IotMainWorkOrderDO>()
+                .eqIfPresent(IotMainWorkOrderDO::getPlanId, reqVO.getPlanId())
+                .eqIfPresent(IotMainWorkOrderDO::getPlanSerialNumber, reqVO.getPlanSerialNumber())
+                .eqIfPresent(IotMainWorkOrderDO::getDeptId, reqVO.getDeptId())
+                .eqIfPresent(IotMainWorkOrderDO::getOrderNumber, reqVO.getOrderNumber())
+                .likeIfPresent(IotMainWorkOrderDO::getName, reqVO.getName())
+                .eqIfPresent(IotMainWorkOrderDO::getType, reqVO.getType())
+                .eqIfPresent(IotMainWorkOrderDO::getResponsiblePerson, reqVO.getResponsiblePerson())
+                .likeIfPresent(IotMainWorkOrderDO::getResponsiblePersonName, reqVO.getResponsiblePersonName())
+                .eqIfPresent(IotMainWorkOrderDO::getCost, reqVO.getCost())
+                .eqIfPresent(IotMainWorkOrderDO::getResult, reqVO.getResult())
+                .eqIfPresent(IotMainWorkOrderDO::getOtherCost, reqVO.getOtherCost())
+                .eqIfPresent(IotMainWorkOrderDO::getLaborCost, reqVO.getLaborCost())
+                .eqIfPresent(IotMainWorkOrderDO::getOutsourcingFlag, reqVO.getOutsourcingFlag())
+                .betweenIfPresent(IotMainWorkOrderDO::getActualStartTime, reqVO.getActualStartTime())
+                .betweenIfPresent(IotMainWorkOrderDO::getActualEndTime, reqVO.getActualEndTime())
+                .eqIfPresent(IotMainWorkOrderDO::getRemark, reqVO.getRemark())
+                .eqIfPresent(IotMainWorkOrderDO::getStatus, reqVO.getStatus())
+                .eqIfPresent(IotMainWorkOrderDO::getProcessInstanceId, reqVO.getProcessInstanceId())
+                .eqIfPresent(IotMainWorkOrderDO::getAuditStatus, reqVO.getAuditStatus())
+                .betweenIfPresent(IotMainWorkOrderDO::getCreateTime, reqVO.getCreateTime())
+                .orderByDesc(IotMainWorkOrderDO::getId));
+    }
+
+}

+ 63 - 0
yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/dal/mysql/iotmainworkorderbom/IotMainWorkOrderBomMapper.java

@@ -0,0 +1,63 @@
+package cn.iocoder.yudao.module.pms.dal.mysql.iotmainworkorderbom;
+
+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.iotmainworkorderbom.vo.IotMainWorkOrderBomPageReqVO;
+import cn.iocoder.yudao.module.pms.dal.dataobject.iotmainworkorderbom.IotMainWorkOrderBomDO;
+import org.apache.ibatis.annotations.Mapper;
+
+/**
+ * PMS 保养计划明细BOM Mapper
+ *
+ * @author ruiqi
+ */
+@Mapper
+public interface IotMainWorkOrderBomMapper extends BaseMapperX<IotMainWorkOrderBomDO> {
+
+    default PageResult<IotMainWorkOrderBomDO> selectPage(IotMainWorkOrderBomPageReqVO reqVO) {
+        return selectPage(reqVO, new LambdaQueryWrapperX<IotMainWorkOrderBomDO>()
+                .eqIfPresent(IotMainWorkOrderBomDO::getPlanId, reqVO.getPlanId())
+                .eqIfPresent(IotMainWorkOrderBomDO::getPlanDetailId, reqVO.getPlanDetailId())
+                .eqIfPresent(IotMainWorkOrderBomDO::getWorkOrderId, reqVO.getWorkOrderId())
+                .eqIfPresent(IotMainWorkOrderBomDO::getDeviceCategoryId, reqVO.getDeviceCategoryId())
+                .eqIfPresent(IotMainWorkOrderBomDO::getDeviceId, reqVO.getDeviceId())
+                .eqIfPresent(IotMainWorkOrderBomDO::getRule, reqVO.getRule())
+                .eqIfPresent(IotMainWorkOrderBomDO::getMileageRule, reqVO.getMileageRule())
+                .eqIfPresent(IotMainWorkOrderBomDO::getNaturalDateRule, reqVO.getNaturalDateRule())
+                .eqIfPresent(IotMainWorkOrderBomDO::getRunningTimeRule, reqVO.getRunningTimeRule())
+                .betweenIfPresent(IotMainWorkOrderBomDO::getLastRunningTime, reqVO.getLastRunningTime())
+                .betweenIfPresent(IotMainWorkOrderBomDO::getNextRunningTime, reqVO.getNextRunningTime())
+                .eqIfPresent(IotMainWorkOrderBomDO::getDelayDuration, reqVO.getDelayDuration())
+                .eqIfPresent(IotMainWorkOrderBomDO::getLastRunningKilometers, reqVO.getLastRunningKilometers())
+                .eqIfPresent(IotMainWorkOrderBomDO::getNextRunningKilometers, reqVO.getNextRunningKilometers())
+                .eqIfPresent(IotMainWorkOrderBomDO::getDelayKilomaters, reqVO.getDelayKilomaters())
+                .betweenIfPresent(IotMainWorkOrderBomDO::getLastNaturalDate, reqVO.getLastNaturalDate())
+                .betweenIfPresent(IotMainWorkOrderBomDO::getNextNaturalDate, reqVO.getNextNaturalDate())
+                .betweenIfPresent(IotMainWorkOrderBomDO::getDelayNaturalDate, reqVO.getDelayNaturalDate())
+                .eqIfPresent(IotMainWorkOrderBomDO::getDelayReason, reqVO.getDelayReason())
+                .betweenIfPresent(IotMainWorkOrderBomDO::getLastMainDate, reqVO.getLastMainDate())
+                .eqIfPresent(IotMainWorkOrderBomDO::getTimePeriod, reqVO.getTimePeriod())
+                .eqIfPresent(IotMainWorkOrderBomDO::getTimePeriodLead, reqVO.getTimePeriodLead())
+                .eqIfPresent(IotMainWorkOrderBomDO::getKilometerCycle, reqVO.getKilometerCycle())
+                .eqIfPresent(IotMainWorkOrderBomDO::getKiloCycleLead, reqVO.getKiloCycleLead())
+                .eqIfPresent(IotMainWorkOrderBomDO::getNaturalDatePeriod, reqVO.getNaturalDatePeriod())
+                .eqIfPresent(IotMainWorkOrderBomDO::getNaturalDatePeroidLead, reqVO.getNaturalDatePeroidLead())
+                .eqIfPresent(IotMainWorkOrderBomDO::getBomNodeId, reqVO.getBomNodeId())
+                .likeIfPresent(IotMainWorkOrderBomDO::getName, reqVO.getName())
+                .eqIfPresent(IotMainWorkOrderBomDO::getCode, reqVO.getCode())
+                .eqIfPresent(IotMainWorkOrderBomDO::getParentId, reqVO.getParentId())
+                .eqIfPresent(IotMainWorkOrderBomDO::getChildIds, reqVO.getChildIds())
+                .eqIfPresent(IotMainWorkOrderBomDO::getLevel, reqVO.getLevel())
+                .eqIfPresent(IotMainWorkOrderBomDO::getLeafFlag, reqVO.getLeafFlag())
+                .eqIfPresent(IotMainWorkOrderBomDO::getSort, reqVO.getSort())
+                .eqIfPresent(IotMainWorkOrderBomDO::getType, reqVO.getType())
+                .eqIfPresent(IotMainWorkOrderBomDO::getMainType, reqVO.getMainType())
+                .eqIfPresent(IotMainWorkOrderBomDO::getStatus, reqVO.getStatus())
+                .eqIfPresent(IotMainWorkOrderBomDO::getRemark, reqVO.getRemark())
+                .eqIfPresent(IotMainWorkOrderBomDO::getVersion, reqVO.getVersion())
+                .betweenIfPresent(IotMainWorkOrderBomDO::getCreateTime, reqVO.getCreateTime())
+                .orderByDesc(IotMainWorkOrderBomDO::getId));
+    }
+
+}

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

@@ -0,0 +1,48 @@
+package cn.iocoder.yudao.module.pms.dal.mysql.iotmainworkorderbommaterial;
+
+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.iotmainworkorderbommaterial.vo.IotMainWorkOrderBomMaterialPageReqVO;
+import cn.iocoder.yudao.module.pms.dal.dataobject.iotmainworkorderbommaterial.IotMainWorkOrderBomMaterialDO;
+import org.apache.ibatis.annotations.Mapper;
+
+/**
+ * PMS 保养工单明细设备BOM挂载物料关联 Mapper
+ *
+ * @author ruiqi
+ */
+@Mapper
+public interface IotMainWorkOrderBomMaterialMapper extends BaseMapperX<IotMainWorkOrderBomMaterialDO> {
+
+    default PageResult<IotMainWorkOrderBomMaterialDO> selectPage(IotMainWorkOrderBomMaterialPageReqVO reqVO) {
+        return selectPage(reqVO, new LambdaQueryWrapperX<IotMainWorkOrderBomMaterialDO>()
+                .eqIfPresent(IotMainWorkOrderBomMaterialDO::getMainPlanId, reqVO.getMainPlanId())
+                .eqIfPresent(IotMainWorkOrderBomMaterialDO::getWorkOrderId, reqVO.getWorkOrderId())
+                .eqIfPresent(IotMainWorkOrderBomMaterialDO::getMainWorkOrderDetailId, reqVO.getMainWorkOrderDetailId())
+                .eqIfPresent(IotMainWorkOrderBomMaterialDO::getDeviceCategoryId, reqVO.getDeviceCategoryId())
+                .eqIfPresent(IotMainWorkOrderBomMaterialDO::getBomNodeId, reqVO.getBomNodeId())
+                .likeIfPresent(IotMainWorkOrderBomMaterialDO::getName, reqVO.getName())
+                .eqIfPresent(IotMainWorkOrderBomMaterialDO::getCode, reqVO.getCode())
+                .eqIfPresent(IotMainWorkOrderBomMaterialDO::getMaterialId, reqVO.getMaterialId())
+                .eqIfPresent(IotMainWorkOrderBomMaterialDO::getMaterialCode, reqVO.getMaterialCode())
+                .likeIfPresent(IotMainWorkOrderBomMaterialDO::getMaterialName, reqVO.getMaterialName())
+                .eqIfPresent(IotMainWorkOrderBomMaterialDO::getQuantity, reqVO.getQuantity())
+                .eqIfPresent(IotMainWorkOrderBomMaterialDO::getUnitPrice, reqVO.getUnitPrice())
+                .eqIfPresent(IotMainWorkOrderBomMaterialDO::getTotalPrice, reqVO.getTotalPrice())
+                .eqIfPresent(IotMainWorkOrderBomMaterialDO::getKilometerCycle, reqVO.getKilometerCycle())
+                .eqIfPresent(IotMainWorkOrderBomMaterialDO::getKiloCycleLead, reqVO.getKiloCycleLead())
+                .eqIfPresent(IotMainWorkOrderBomMaterialDO::getTimePeriod, reqVO.getTimePeriod())
+                .eqIfPresent(IotMainWorkOrderBomMaterialDO::getTimePeriodLead, reqVO.getTimePeriodLead())
+                .eqIfPresent(IotMainWorkOrderBomMaterialDO::getNaturalDatePeriod, reqVO.getNaturalDatePeriod())
+                .eqIfPresent(IotMainWorkOrderBomMaterialDO::getNaturalDatePeroidLead, reqVO.getNaturalDatePeroidLead())
+                .eqIfPresent(IotMainWorkOrderBomMaterialDO::getMaterialSource, reqVO.getMaterialSource())
+                .eqIfPresent(IotMainWorkOrderBomMaterialDO::getInventoryAddress, reqVO.getInventoryAddress())
+                .eqIfPresent(IotMainWorkOrderBomMaterialDO::getSort, reqVO.getSort())
+                .eqIfPresent(IotMainWorkOrderBomMaterialDO::getStatus, reqVO.getStatus())
+                .eqIfPresent(IotMainWorkOrderBomMaterialDO::getRemark, reqVO.getRemark())
+                .betweenIfPresent(IotMainWorkOrderBomMaterialDO::getCreateTime, reqVO.getCreateTime())
+                .orderByDesc(IotMainWorkOrderBomMaterialDO::getId));
+    }
+
+}

+ 37 - 0
yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/dal/mysql/iotmainworkorderdetails/IotMainWorkOrderDetailsMapper.java

@@ -0,0 +1,37 @@
+package cn.iocoder.yudao.module.pms.dal.mysql.iotmainworkorderdetails;
+
+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.iotmainworkorderdetails.vo.IotMainWorkOrderDetailsPageReqVO;
+import cn.iocoder.yudao.module.pms.dal.dataobject.iotmainworkorderdetails.IotMainWorkOrderDetailsDO;
+import org.apache.ibatis.annotations.Mapper;
+
+/**
+ * 保养工单明细 Mapper
+ *
+ * @author ruiqi
+ */
+@Mapper
+public interface IotMainWorkOrderDetailsMapper extends BaseMapperX<IotMainWorkOrderDetailsDO> {
+
+    default PageResult<IotMainWorkOrderDetailsDO> selectPage(IotMainWorkOrderDetailsPageReqVO reqVO) {
+        return selectPage(reqVO, new LambdaQueryWrapperX<IotMainWorkOrderDetailsDO>()
+                .eqIfPresent(IotMainWorkOrderDetailsDO::getPlanId, reqVO.getPlanId())
+                .eqIfPresent(IotMainWorkOrderDetailsDO::getWorkOrderId, reqVO.getWorkOrderId())
+                .eqIfPresent(IotMainWorkOrderDetailsDO::getDeviceId, reqVO.getDeviceId())
+                .eqIfPresent(IotMainWorkOrderDetailsDO::getDeviceAssetNumber, reqVO.getDeviceAssetNumber())
+                .likeIfPresent(IotMainWorkOrderDetailsDO::getDeviceName, reqVO.getDeviceName())
+                .eqIfPresent(IotMainWorkOrderDetailsDO::getDeviceCategory, reqVO.getDeviceCategory())
+                .eqIfPresent(IotMainWorkOrderDetailsDO::getDeviceBrand, reqVO.getDeviceBrand())
+                .eqIfPresent(IotMainWorkOrderDetailsDO::getRunningKilometers, reqVO.getRunningKilometers())
+                .betweenIfPresent(IotMainWorkOrderDetailsDO::getRunningTime, reqVO.getRunningTime())
+                .betweenIfPresent(IotMainWorkOrderDetailsDO::getNaturalDate, reqVO.getNaturalDate())
+                .eqIfPresent(IotMainWorkOrderDetailsDO::getRemark, reqVO.getRemark())
+                .eqIfPresent(IotMainWorkOrderDetailsDO::getSort, reqVO.getSort())
+                .eqIfPresent(IotMainWorkOrderDetailsDO::getStatus, reqVO.getStatus())
+                .betweenIfPresent(IotMainWorkOrderDetailsDO::getCreateTime, reqVO.getCreateTime())
+                .orderByDesc(IotMainWorkOrderDetailsDO::getId));
+    }
+
+}

+ 4 - 3
yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/dal/mysql/maintenance/IotMaintenancePlanMapper.java

@@ -1,10 +1,8 @@
 package cn.iocoder.yudao.module.pms.dal.mysql.maintenance;
 
-import java.util.*;
-
 import cn.iocoder.yudao.framework.common.pojo.PageResult;
-import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
 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.maintenance.vo.IotMaintenancePlanPageReqVO;
 import cn.iocoder.yudao.module.pms.dal.dataobject.maintenance.IotMaintenancePlanDO;
 import org.apache.ibatis.annotations.Mapper;
@@ -30,4 +28,7 @@ public interface IotMaintenancePlanMapper extends BaseMapperX<IotMaintenancePlan
                 .orderByDesc(IotMaintenancePlanDO::getId));
     }
 
+    default IotMaintenancePlanDO selectByNo(String no) {
+        return selectOne(IotMaintenancePlanDO::getSerialNumber, no);
+    }
 }

+ 51 - 0
yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/dal/redis/BizNoRedisDAO.java

@@ -0,0 +1,51 @@
+package cn.iocoder.yudao.module.pms.dal.redis;
+
+import cn.hutool.core.date.DatePattern;
+import cn.hutool.core.date.DateUtil;
+import org.springframework.data.redis.core.StringRedisTemplate;
+import org.springframework.stereotype.Repository;
+
+import javax.annotation.Resource;
+import java.time.Duration;
+import java.time.LocalDateTime;
+
+
+/**
+ * pms 业务单据的 Redis DAO
+ *
+ * @author ruiqi
+ */
+@Repository
+public class BizNoRedisDAO {
+
+    /**
+     * 保养计划
+     */
+    public static final String MAIN_PLAN_NO_PREFIX = "BYJH";
+
+    /**
+     * 保养工单
+     */
+    public static final String MAIN_WORK_ORDER_NO_PREFIX = "BYGD";
+
+    @Resource
+    private StringRedisTemplate stringRedisTemplate;
+
+    /**
+     * 生成序号,使用当前日期,格式为 {PREFIX} + yyyyMMdd + 6 位自增
+     * 例如说:BYJH 202109 000001 (没有中间空格)
+     *
+     * @param prefix 前缀
+     * @return 序号
+     */
+    public String generate(String prefix) {
+        // 递增序号
+        String noPrefix = prefix + DateUtil.format(LocalDateTime.now(), DatePattern.PURE_DATE_PATTERN);
+        String key = RedisKeyConstants.NO + noPrefix;
+        Long no = stringRedisTemplate.opsForValue().increment(key);
+        // 设置过期时间
+        stringRedisTemplate.expire(key, Duration.ofDays(1L));
+        return noPrefix + String.format("%06d", no);
+    }
+
+}

+ 18 - 0
yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/dal/redis/RedisKeyConstants.java

@@ -0,0 +1,18 @@
+package cn.iocoder.yudao.module.pms.dal.redis;
+
+/**
+ * CRM Redis Key 枚举类
+ *
+ * @author ruiqi
+ */
+public interface RedisKeyConstants {
+
+    /**
+     * 序号的缓存
+     *
+     * KEY 格式:trade_no:{prefix}
+     * VALUE 数据格式:编号自增
+     */
+    String NO = "pms:seq_no:";
+
+}

+ 18 - 0
yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/service/IotDeviceService.java

@@ -2,10 +2,12 @@ package cn.iocoder.yudao.module.pms.service;
 
 import cn.iocoder.yudao.framework.common.pojo.PageResult;
 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.IotDeviceSaveReqVO;
 import cn.iocoder.yudao.module.pms.dal.dataobject.IotDeviceDO;
 
 import javax.validation.Valid;
+import java.util.List;
 
 /**
  * 设备台账 Service 接口
@@ -52,4 +54,20 @@ public interface IotDeviceService {
      */
     PageResult<IotDeviceDO> getIotDevicePage(IotDevicePageReqVO pageReqVO);
 
+    /**
+     * 获得 设备bom 关联 关系 分页
+     *
+     * @param pageReqVO 分页查询
+     * @return 设备bom 关联分页
+     */
+    PageResult<IotDeviceRespVO> deviceAssociateBomPage(IotDevicePageReqVO pageReqVO);
+
+    /**
+     * 获得 设备bom 关联 关系 列表
+     *
+     * @param deviceIds
+     * @return 设备bom 关联 列表
+     */
+    List<IotDeviceRespVO> deviceAssociateBomList(List<Long> deviceIds);
+
 }

+ 39 - 4
yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/service/IotDeviceServiceImpl.java

@@ -6,28 +6,28 @@ import cn.iocoder.yudao.framework.common.exception.ServiceException;
 import cn.iocoder.yudao.framework.common.pojo.PageResult;
 import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
 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.IotDeviceSaveReqVO;
 import cn.iocoder.yudao.module.pms.dal.dataobject.IotDeviceDO;
 import cn.iocoder.yudao.module.pms.dal.dataobject.IotInfoClassifyDO;
+import cn.iocoder.yudao.module.pms.dal.dataobject.IotTreeDO;
 import cn.iocoder.yudao.module.pms.dal.dataobject.iotmodel.IotModelDO;
 import cn.iocoder.yudao.module.pms.dal.mysql.IotDeviceMapper;
 import cn.iocoder.yudao.module.pms.dal.mysql.IotInfoClassifyMapper;
-import cn.iocoder.yudao.module.pms.dal.dataobject.IotTreeDO;
 import cn.iocoder.yudao.module.pms.dal.mysql.IotTreeMapper;
 import cn.iocoder.yudao.module.pms.dal.mysql.iotmodel.IotModelMapper;
-import cn.iocoder.yudao.module.pms.service.iotmodel.IotModelService;
 import cn.iocoder.yudao.module.system.dal.dataobject.dict.DictDataDO;
 import cn.iocoder.yudao.module.system.enums.ErrorCodeConstants;
 import cn.iocoder.yudao.module.system.service.dept.DeptService;
 import cn.iocoder.yudao.module.system.service.dict.DictDataService;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.google.common.collect.ImmutableMap;
-import org.apache.commons.lang3.StringUtils;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 import org.springframework.validation.annotation.Validated;
 
 import javax.annotation.Resource;
-
 import java.util.HashSet;
 import java.util.List;
 import java.util.Objects;
@@ -151,4 +151,39 @@ public class IotDeviceServiceImpl implements IotDeviceService {
         return iotDeviceMapper.selectPage(pageReqVO,ids);
     }
 
+    /* @Override
+    public PageResult<IotDeviceDO> deviceAssociateBomPage(IotDevicePageReqVO pageReqVO) {
+        Set<Long> ids = new HashSet<>();
+        if (Objects.nonNull(pageReqVO.getDeptId())) {
+            ids = deptService.getChildDeptIdListFromCache(pageReqVO.getDeptId());
+            ids.add(pageReqVO.getDeptId());
+        }
+
+        return iotDeviceMapper.deviceAssociateBomPage(pageReqVO,ids);
+    } */
+
+    @Override
+    public PageResult<IotDeviceRespVO> deviceAssociateBomPage(IotDevicePageReqVO pageReqVO) {
+        Set<Long> ids = new HashSet<>();
+        if (Objects.nonNull(pageReqVO.getDeptId())) {
+            ids = deptService.getChildDeptIdListFromCache(pageReqVO.getDeptId());
+            ids.add(pageReqVO.getDeptId());
+        }
+        try {
+            IPage<IotDeviceRespVO> page = iotDeviceMapper.deviceAssociateBomPage(
+                    new Page<>(pageReqVO.getPageNo(), pageReqVO.getPageSize()), pageReqVO, ids);
+            return new PageResult<>(page.getRecords(), page.getTotal());
+        } catch (Exception exception) {
+            if (exception.getMessage().contains("Table does not exist")) {
+                return PageResult.empty();
+            }
+            throw exception;
+        }
+    }
+
+    @Override
+    public List<IotDeviceRespVO> deviceAssociateBomList(List<Long> deviceIds) {
+        List<IotDeviceRespVO> devices = iotDeviceMapper.deviceAssociateBomList(deviceIds);
+        return devices;
+    }
 }

+ 30 - 0
yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/service/iotbom/IotBomService.java

@@ -1,13 +1,16 @@
 package cn.iocoder.yudao.module.pms.service.iotbom;
 
 import cn.iocoder.yudao.framework.common.pojo.PageResult;
+import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
 import cn.iocoder.yudao.module.pms.controller.admin.iotbom.vo.IotBomListReqVO;
 import cn.iocoder.yudao.module.pms.controller.admin.iotbom.vo.IotBomPageReqVO;
 import cn.iocoder.yudao.module.pms.controller.admin.iotbom.vo.IotBomSaveReqVO;
 import cn.iocoder.yudao.module.pms.dal.dataobject.iotbom.IotBomDO;
 
 import javax.validation.Valid;
+import java.util.Collection;
 import java.util.List;
+import java.util.Map;
 
 /**
  * PMS BOM 关系 Service 接口
@@ -61,4 +64,31 @@ public interface IotBomService {
      * @return BOM列表
      */
     List<IotBomDO> getBomList(IotBomListReqVO reqVO);
+
+    /**
+     * 获得PMS 设备关联-BOM 关系分页
+     *
+     * @param pageReqVO 分页查询
+     * @return PMS 设备关联-BOM 关系分页
+     */
+    PageResult<IotBomDO> deviceAssociateBomPage(IotBomPageReqVO pageReqVO);
+
+    /**
+     * 获得 BOM节点 信息数组
+     *
+     * @param deviceCategoryIds bom 编号数组
+     * @return bom 信息数组
+     */
+    List<IotBomDO> getBomList(Collection<Long> deviceCategoryIds);
+
+    /**
+     * 获得指定编号的 BOM节点 Map
+     *
+     * @param deviceCategoryIds 设备分类 编号数组
+     * @return BOM节点 Map
+     */
+    default Map<Long, IotBomDO> getBomMap(Collection<Long> deviceCategoryIds) {
+        List<IotBomDO> list = getBomList(deviceCategoryIds);
+        return CollectionUtils.convertMap(list, IotBomDO::getDeviceCategoryId);
+    }
 }

+ 16 - 0
yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/service/iotbom/IotBomServiceImpl.java

@@ -1,5 +1,6 @@
 package cn.iocoder.yudao.module.pms.service.iotbom;
 
+import cn.hutool.core.collection.CollUtil;
 import cn.iocoder.yudao.framework.common.pojo.PageResult;
 import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
 import cn.iocoder.yudao.module.pms.controller.admin.iotbom.vo.IotBomListReqVO;
@@ -12,6 +13,8 @@ import org.springframework.transaction.annotation.Transactional;
 import org.springframework.validation.annotation.Validated;
 
 import javax.annotation.Resource;
+import java.util.Collection;
+import java.util.Collections;
 import java.util.Comparator;
 import java.util.List;
 
@@ -88,4 +91,17 @@ public class IotBomServiceImpl implements IotBomService {
         return list;
     }
 
+    @Override
+    public PageResult<IotBomDO> deviceAssociateBomPage(IotBomPageReqVO pageReqVO) {
+        return iotBomMapper.deviceAssociateBomPage(pageReqVO);
+    }
+
+    @Override
+    public List<IotBomDO> getBomList(Collection<Long> deviceCategoryIds) {
+        if (CollUtil.isEmpty(deviceCategoryIds)) {
+            return Collections.emptyList();
+        }
+        return iotBomMapper.getListByDeviceCategoryIds(deviceCategoryIds);
+    }
+
 }

+ 8 - 0
yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/service/iotmaintenancebom/IotMaintenanceBomService.java

@@ -52,4 +52,12 @@ public interface IotMaintenanceBomService {
      */
     PageResult<IotMaintenanceBomDO> getIotMaintenanceBomPage(IotMaintenanceBomPageReqVO pageReqVO);
 
+    /**
+     * 获得PMS 保养计划明细 设备关联-BOM节点 分页
+     *
+     * @param pageReqVO 分页查询
+     * @return PMS 保养计划 明细 设备关联-BOM分页
+     */
+    PageResult<IotMaintenanceBomDO> deviceAssociateBomPage(IotMaintenanceBomPageReqVO pageReqVO);
+
 }

+ 5 - 0
yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/service/iotmaintenancebom/IotMaintenanceBomServiceImpl.java

@@ -68,4 +68,9 @@ public class IotMaintenanceBomServiceImpl implements IotMaintenanceBomService {
         return iotMaintenanceBomMapper.selectPage(pageReqVO);
     }
 
+    @Override
+    public PageResult<IotMaintenanceBomDO> deviceAssociateBomPage(IotMaintenanceBomPageReqVO pageReqVO) {
+        return iotMaintenanceBomMapper.deviceAssociateBomPage(pageReqVO);
+    }
+
 }

+ 55 - 0
yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/service/iotmainworkorder/IotMainWorkOrderService.java

@@ -0,0 +1,55 @@
+package cn.iocoder.yudao.module.pms.service.iotmainworkorder;
+
+import cn.iocoder.yudao.framework.common.pojo.PageResult;
+import cn.iocoder.yudao.module.pms.controller.admin.iotmainworkorder.vo.IotMainWorkOrderPageReqVO;
+import cn.iocoder.yudao.module.pms.controller.admin.iotmainworkorder.vo.IotMainWorkOrderSaveReqVO;
+import cn.iocoder.yudao.module.pms.dal.dataobject.iotmainworkorder.IotMainWorkOrderDO;
+
+import javax.validation.Valid;
+
+/**
+ * 保养工单 Service 接口
+ *
+ * @author ruiqi
+ */
+public interface IotMainWorkOrderService {
+
+    /**
+     * 创建保养工单
+     *
+     * @param createReqVO 创建信息
+     * @return 编号
+     */
+    Long createIotMainWorkOrder(@Valid IotMainWorkOrderSaveReqVO createReqVO);
+
+    /**
+     * 更新保养工单
+     *
+     * @param updateReqVO 更新信息
+     */
+    void updateIotMainWorkOrder(@Valid IotMainWorkOrderSaveReqVO updateReqVO);
+
+    /**
+     * 删除保养工单
+     *
+     * @param id 编号
+     */
+    void deleteIotMainWorkOrder(Long id);
+
+    /**
+     * 获得保养工单
+     *
+     * @param id 编号
+     * @return 保养工单
+     */
+    IotMainWorkOrderDO getIotMainWorkOrder(Long id);
+
+    /**
+     * 获得保养工单分页
+     *
+     * @param pageReqVO 分页查询
+     * @return 保养工单分页
+     */
+    PageResult<IotMainWorkOrderDO> getIotMainWorkOrderPage(IotMainWorkOrderPageReqVO pageReqVO);
+
+}

+ 71 - 0
yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/service/iotmainworkorder/IotMainWorkOrderServiceImpl.java

@@ -0,0 +1,71 @@
+package cn.iocoder.yudao.module.pms.service.iotmainworkorder;
+
+import cn.iocoder.yudao.framework.common.pojo.PageResult;
+import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
+import cn.iocoder.yudao.module.pms.controller.admin.iotmainworkorder.vo.IotMainWorkOrderPageReqVO;
+import cn.iocoder.yudao.module.pms.controller.admin.iotmainworkorder.vo.IotMainWorkOrderSaveReqVO;
+import cn.iocoder.yudao.module.pms.dal.dataobject.iotmainworkorder.IotMainWorkOrderDO;
+import cn.iocoder.yudao.module.pms.dal.mysql.iotmainworkorder.IotMainWorkOrderMapper;
+import org.springframework.stereotype.Service;
+import org.springframework.validation.annotation.Validated;
+
+import javax.annotation.Resource;
+
+import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
+import static cn.iocoder.yudao.module.pms.enums.ErrorCodeConstant.IOT_MAIN_WORK_ORDER_NOT_EXISTS;
+
+/**
+ * 保养工单 Service 实现类
+ *
+ * @author ruiqi
+ */
+@Service
+@Validated
+public class IotMainWorkOrderServiceImpl implements IotMainWorkOrderService {
+
+    @Resource
+    private IotMainWorkOrderMapper iotMainWorkOrderMapper;
+
+    @Override
+    public Long createIotMainWorkOrder(IotMainWorkOrderSaveReqVO createReqVO) {
+        // 插入
+        IotMainWorkOrderDO iotMainWorkOrder = BeanUtils.toBean(createReqVO, IotMainWorkOrderDO.class);
+        iotMainWorkOrderMapper.insert(iotMainWorkOrder);
+        // 返回
+        return iotMainWorkOrder.getId();
+    }
+
+    @Override
+    public void updateIotMainWorkOrder(IotMainWorkOrderSaveReqVO updateReqVO) {
+        // 校验存在
+        validateIotMainWorkOrderExists(updateReqVO.getId());
+        // 更新
+        IotMainWorkOrderDO updateObj = BeanUtils.toBean(updateReqVO, IotMainWorkOrderDO.class);
+        iotMainWorkOrderMapper.updateById(updateObj);
+    }
+
+    @Override
+    public void deleteIotMainWorkOrder(Long id) {
+        // 校验存在
+        validateIotMainWorkOrderExists(id);
+        // 删除
+        iotMainWorkOrderMapper.deleteById(id);
+    }
+
+    private void validateIotMainWorkOrderExists(Long id) {
+        if (iotMainWorkOrderMapper.selectById(id) == null) {
+            throw exception(IOT_MAIN_WORK_ORDER_NOT_EXISTS);
+        }
+    }
+
+    @Override
+    public IotMainWorkOrderDO getIotMainWorkOrder(Long id) {
+        return iotMainWorkOrderMapper.selectById(id);
+    }
+
+    @Override
+    public PageResult<IotMainWorkOrderDO> getIotMainWorkOrderPage(IotMainWorkOrderPageReqVO pageReqVO) {
+        return iotMainWorkOrderMapper.selectPage(pageReqVO);
+    }
+
+}

+ 55 - 0
yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/service/iotmainworkorderbom/IotMainWorkOrderBomService.java

@@ -0,0 +1,55 @@
+package cn.iocoder.yudao.module.pms.service.iotmainworkorderbom;
+
+import cn.iocoder.yudao.framework.common.pojo.PageResult;
+import cn.iocoder.yudao.module.pms.controller.admin.iotmainworkorderbom.vo.IotMainWorkOrderBomPageReqVO;
+import cn.iocoder.yudao.module.pms.controller.admin.iotmainworkorderbom.vo.IotMainWorkOrderBomSaveReqVO;
+import cn.iocoder.yudao.module.pms.dal.dataobject.iotmainworkorderbom.IotMainWorkOrderBomDO;
+
+import javax.validation.Valid;
+
+/**
+ * PMS 保养计划明细BOM Service 接口
+ *
+ * @author ruiqi
+ */
+public interface IotMainWorkOrderBomService {
+
+    /**
+     * 创建PMS 保养计划明细BOM
+     *
+     * @param createReqVO 创建信息
+     * @return 编号
+     */
+    Long createIotMainWorkOrderBom(@Valid IotMainWorkOrderBomSaveReqVO createReqVO);
+
+    /**
+     * 更新PMS 保养计划明细BOM
+     *
+     * @param updateReqVO 更新信息
+     */
+    void updateIotMainWorkOrderBom(@Valid IotMainWorkOrderBomSaveReqVO updateReqVO);
+
+    /**
+     * 删除PMS 保养计划明细BOM
+     *
+     * @param id 编号
+     */
+    void deleteIotMainWorkOrderBom(Long id);
+
+    /**
+     * 获得PMS 保养计划明细BOM
+     *
+     * @param id 编号
+     * @return PMS 保养计划明细BOM
+     */
+    IotMainWorkOrderBomDO getIotMainWorkOrderBom(Long id);
+
+    /**
+     * 获得PMS 保养计划明细BOM分页
+     *
+     * @param pageReqVO 分页查询
+     * @return PMS 保养计划明细BOM分页
+     */
+    PageResult<IotMainWorkOrderBomDO> getIotMainWorkOrderBomPage(IotMainWorkOrderBomPageReqVO pageReqVO);
+
+}

+ 71 - 0
yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/service/iotmainworkorderbom/IotMainWorkOrderBomServiceImpl.java

@@ -0,0 +1,71 @@
+package cn.iocoder.yudao.module.pms.service.iotmainworkorderbom;
+
+import cn.iocoder.yudao.framework.common.pojo.PageResult;
+import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
+import cn.iocoder.yudao.module.pms.controller.admin.iotmainworkorderbom.vo.IotMainWorkOrderBomPageReqVO;
+import cn.iocoder.yudao.module.pms.controller.admin.iotmainworkorderbom.vo.IotMainWorkOrderBomSaveReqVO;
+import cn.iocoder.yudao.module.pms.dal.dataobject.iotmainworkorderbom.IotMainWorkOrderBomDO;
+import cn.iocoder.yudao.module.pms.dal.mysql.iotmainworkorderbom.IotMainWorkOrderBomMapper;
+import org.springframework.stereotype.Service;
+import org.springframework.validation.annotation.Validated;
+
+import javax.annotation.Resource;
+
+import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
+import static cn.iocoder.yudao.module.pms.enums.ErrorCodeConstant.IOT_MAIN_WORK_ORDER_BOM_NOT_EXISTS;
+
+/**
+ * PMS 保养计划明细BOM Service 实现类
+ *
+ * @author ruiqi
+ */
+@Service
+@Validated
+public class IotMainWorkOrderBomServiceImpl implements IotMainWorkOrderBomService {
+
+    @Resource
+    private IotMainWorkOrderBomMapper iotMainWorkOrderBomMapper;
+
+    @Override
+    public Long createIotMainWorkOrderBom(IotMainWorkOrderBomSaveReqVO createReqVO) {
+        // 插入
+        IotMainWorkOrderBomDO iotMainWorkOrderBom = BeanUtils.toBean(createReqVO, IotMainWorkOrderBomDO.class);
+        iotMainWorkOrderBomMapper.insert(iotMainWorkOrderBom);
+        // 返回
+        return iotMainWorkOrderBom.getId();
+    }
+
+    @Override
+    public void updateIotMainWorkOrderBom(IotMainWorkOrderBomSaveReqVO updateReqVO) {
+        // 校验存在
+        validateIotMainWorkOrderBomExists(updateReqVO.getId());
+        // 更新
+        IotMainWorkOrderBomDO updateObj = BeanUtils.toBean(updateReqVO, IotMainWorkOrderBomDO.class);
+        iotMainWorkOrderBomMapper.updateById(updateObj);
+    }
+
+    @Override
+    public void deleteIotMainWorkOrderBom(Long id) {
+        // 校验存在
+        validateIotMainWorkOrderBomExists(id);
+        // 删除
+        iotMainWorkOrderBomMapper.deleteById(id);
+    }
+
+    private void validateIotMainWorkOrderBomExists(Long id) {
+        if (iotMainWorkOrderBomMapper.selectById(id) == null) {
+            throw exception(IOT_MAIN_WORK_ORDER_BOM_NOT_EXISTS);
+        }
+    }
+
+    @Override
+    public IotMainWorkOrderBomDO getIotMainWorkOrderBom(Long id) {
+        return iotMainWorkOrderBomMapper.selectById(id);
+    }
+
+    @Override
+    public PageResult<IotMainWorkOrderBomDO> getIotMainWorkOrderBomPage(IotMainWorkOrderBomPageReqVO pageReqVO) {
+        return iotMainWorkOrderBomMapper.selectPage(pageReqVO);
+    }
+
+}

+ 55 - 0
yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/service/iotmainworkorderbommaterial/IotMainWorkOrderBomMaterialService.java

@@ -0,0 +1,55 @@
+package cn.iocoder.yudao.module.pms.service.iotmainworkorderbommaterial;
+
+import cn.iocoder.yudao.framework.common.pojo.PageResult;
+import cn.iocoder.yudao.module.pms.controller.admin.iotmainworkorderbommaterial.vo.IotMainWorkOrderBomMaterialPageReqVO;
+import cn.iocoder.yudao.module.pms.controller.admin.iotmainworkorderbommaterial.vo.IotMainWorkOrderBomMaterialSaveReqVO;
+import cn.iocoder.yudao.module.pms.dal.dataobject.iotmainworkorderbommaterial.IotMainWorkOrderBomMaterialDO;
+
+import javax.validation.Valid;
+
+/**
+ * PMS 保养工单明细设备BOM挂载物料关联 Service 接口
+ *
+ * @author ruiqi
+ */
+public interface IotMainWorkOrderBomMaterialService {
+
+    /**
+     * 创建PMS 保养工单明细设备BOM挂载物料关联
+     *
+     * @param createReqVO 创建信息
+     * @return 编号
+     */
+    Long createIotMainWorkOrderBomMaterial(@Valid IotMainWorkOrderBomMaterialSaveReqVO createReqVO);
+
+    /**
+     * 更新PMS 保养工单明细设备BOM挂载物料关联
+     *
+     * @param updateReqVO 更新信息
+     */
+    void updateIotMainWorkOrderBomMaterial(@Valid IotMainWorkOrderBomMaterialSaveReqVO updateReqVO);
+
+    /**
+     * 删除PMS 保养工单明细设备BOM挂载物料关联
+     *
+     * @param id 编号
+     */
+    void deleteIotMainWorkOrderBomMaterial(Long id);
+
+    /**
+     * 获得PMS 保养工单明细设备BOM挂载物料关联
+     *
+     * @param id 编号
+     * @return PMS 保养工单明细设备BOM挂载物料关联
+     */
+    IotMainWorkOrderBomMaterialDO getIotMainWorkOrderBomMaterial(Long id);
+
+    /**
+     * 获得PMS 保养工单明细设备BOM挂载物料关联分页
+     *
+     * @param pageReqVO 分页查询
+     * @return PMS 保养工单明细设备BOM挂载物料关联分页
+     */
+    PageResult<IotMainWorkOrderBomMaterialDO> getIotMainWorkOrderBomMaterialPage(IotMainWorkOrderBomMaterialPageReqVO pageReqVO);
+
+}

+ 72 - 0
yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/service/iotmainworkorderbommaterial/IotMainWorkOrderBomMaterialServiceImpl.java

@@ -0,0 +1,72 @@
+package cn.iocoder.yudao.module.pms.service.iotmainworkorderbommaterial;
+
+import cn.iocoder.yudao.framework.common.pojo.PageResult;
+import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
+import cn.iocoder.yudao.module.pms.controller.admin.iotmainworkorderbommaterial.vo.IotMainWorkOrderBomMaterialPageReqVO;
+import cn.iocoder.yudao.module.pms.controller.admin.iotmainworkorderbommaterial.vo.IotMainWorkOrderBomMaterialSaveReqVO;
+import cn.iocoder.yudao.module.pms.dal.dataobject.iotmainworkorderbommaterial.IotMainWorkOrderBomMaterialDO;
+import cn.iocoder.yudao.module.pms.dal.mysql.iotmainworkorderbommaterial.IotMainWorkOrderBomMaterialMapper;
+import org.springframework.stereotype.Service;
+import org.springframework.validation.annotation.Validated;
+
+import javax.annotation.Resource;
+
+import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
+import static cn.iocoder.yudao.module.pms.enums.ErrorCodeConstant.IOT_MAIN_WORK_ORDER_BOM_MATERIAL_NOT_EXISTS;
+
+
+/**
+ * PMS 保养工单明细设备BOM挂载物料关联 Service 实现类
+ *
+ * @author ruiqi
+ */
+@Service
+@Validated
+public class IotMainWorkOrderBomMaterialServiceImpl implements IotMainWorkOrderBomMaterialService {
+
+    @Resource
+    private IotMainWorkOrderBomMaterialMapper iotMainWorkOrderBomMaterialMapper;
+
+    @Override
+    public Long createIotMainWorkOrderBomMaterial(IotMainWorkOrderBomMaterialSaveReqVO createReqVO) {
+        // 插入
+        IotMainWorkOrderBomMaterialDO iotMainWorkOrderBomMaterial = BeanUtils.toBean(createReqVO, IotMainWorkOrderBomMaterialDO.class);
+        iotMainWorkOrderBomMaterialMapper.insert(iotMainWorkOrderBomMaterial);
+        // 返回
+        return iotMainWorkOrderBomMaterial.getId();
+    }
+
+    @Override
+    public void updateIotMainWorkOrderBomMaterial(IotMainWorkOrderBomMaterialSaveReqVO updateReqVO) {
+        // 校验存在
+        validateIotMainWorkOrderBomMaterialExists(updateReqVO.getId());
+        // 更新
+        IotMainWorkOrderBomMaterialDO updateObj = BeanUtils.toBean(updateReqVO, IotMainWorkOrderBomMaterialDO.class);
+        iotMainWorkOrderBomMaterialMapper.updateById(updateObj);
+    }
+
+    @Override
+    public void deleteIotMainWorkOrderBomMaterial(Long id) {
+        // 校验存在
+        validateIotMainWorkOrderBomMaterialExists(id);
+        // 删除
+        iotMainWorkOrderBomMaterialMapper.deleteById(id);
+    }
+
+    private void validateIotMainWorkOrderBomMaterialExists(Long id) {
+        if (iotMainWorkOrderBomMaterialMapper.selectById(id) == null) {
+            throw exception(IOT_MAIN_WORK_ORDER_BOM_MATERIAL_NOT_EXISTS);
+        }
+    }
+
+    @Override
+    public IotMainWorkOrderBomMaterialDO getIotMainWorkOrderBomMaterial(Long id) {
+        return iotMainWorkOrderBomMaterialMapper.selectById(id);
+    }
+
+    @Override
+    public PageResult<IotMainWorkOrderBomMaterialDO> getIotMainWorkOrderBomMaterialPage(IotMainWorkOrderBomMaterialPageReqVO pageReqVO) {
+        return iotMainWorkOrderBomMaterialMapper.selectPage(pageReqVO);
+    }
+
+}

+ 55 - 0
yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/service/iotmainworkorderdetails/IotMainWorkOrderDetailsService.java

@@ -0,0 +1,55 @@
+package cn.iocoder.yudao.module.pms.service.iotmainworkorderdetails;
+
+import cn.iocoder.yudao.framework.common.pojo.PageResult;
+import cn.iocoder.yudao.module.pms.controller.admin.iotmainworkorderdetails.vo.IotMainWorkOrderDetailsPageReqVO;
+import cn.iocoder.yudao.module.pms.controller.admin.iotmainworkorderdetails.vo.IotMainWorkOrderDetailsSaveReqVO;
+import cn.iocoder.yudao.module.pms.dal.dataobject.iotmainworkorderdetails.IotMainWorkOrderDetailsDO;
+
+import javax.validation.Valid;
+
+/**
+ * 保养工单明细 Service 接口
+ *
+ * @author ruiqi
+ */
+public interface IotMainWorkOrderDetailsService {
+
+    /**
+     * 创建保养工单明细
+     *
+     * @param createReqVO 创建信息
+     * @return 编号
+     */
+    Long createIotMainWorkOrderDetails(@Valid IotMainWorkOrderDetailsSaveReqVO createReqVO);
+
+    /**
+     * 更新保养工单明细
+     *
+     * @param updateReqVO 更新信息
+     */
+    void updateIotMainWorkOrderDetails(@Valid IotMainWorkOrderDetailsSaveReqVO updateReqVO);
+
+    /**
+     * 删除保养工单明细
+     *
+     * @param id 编号
+     */
+    void deleteIotMainWorkOrderDetails(Long id);
+
+    /**
+     * 获得保养工单明细
+     *
+     * @param id 编号
+     * @return 保养工单明细
+     */
+    IotMainWorkOrderDetailsDO getIotMainWorkOrderDetails(Long id);
+
+    /**
+     * 获得保养工单明细分页
+     *
+     * @param pageReqVO 分页查询
+     * @return 保养工单明细分页
+     */
+    PageResult<IotMainWorkOrderDetailsDO> getIotMainWorkOrderDetailsPage(IotMainWorkOrderDetailsPageReqVO pageReqVO);
+
+}

+ 71 - 0
yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/service/iotmainworkorderdetails/IotMainWorkOrderDetailsServiceImpl.java

@@ -0,0 +1,71 @@
+package cn.iocoder.yudao.module.pms.service.iotmainworkorderdetails;
+
+import cn.iocoder.yudao.framework.common.pojo.PageResult;
+import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
+import cn.iocoder.yudao.module.pms.controller.admin.iotmainworkorderdetails.vo.IotMainWorkOrderDetailsPageReqVO;
+import cn.iocoder.yudao.module.pms.controller.admin.iotmainworkorderdetails.vo.IotMainWorkOrderDetailsSaveReqVO;
+import cn.iocoder.yudao.module.pms.dal.dataobject.iotmainworkorderdetails.IotMainWorkOrderDetailsDO;
+import cn.iocoder.yudao.module.pms.dal.mysql.iotmainworkorderdetails.IotMainWorkOrderDetailsMapper;
+import org.springframework.stereotype.Service;
+import org.springframework.validation.annotation.Validated;
+
+import javax.annotation.Resource;
+
+import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
+import static cn.iocoder.yudao.module.pms.enums.ErrorCodeConstant.IOT_MAIN_WORK_ORDER_DETAILS_NOT_EXISTS;
+
+/**
+ * 保养工单明细 Service 实现类
+ *
+ * @author ruiqi
+ */
+@Service
+@Validated
+public class IotMainWorkOrderDetailsServiceImpl implements IotMainWorkOrderDetailsService {
+
+    @Resource
+    private IotMainWorkOrderDetailsMapper iotMainWorkOrderDetailsMapper;
+
+    @Override
+    public Long createIotMainWorkOrderDetails(IotMainWorkOrderDetailsSaveReqVO createReqVO) {
+        // 插入
+        IotMainWorkOrderDetailsDO iotMainWorkOrderDetails = BeanUtils.toBean(createReqVO, IotMainWorkOrderDetailsDO.class);
+        iotMainWorkOrderDetailsMapper.insert(iotMainWorkOrderDetails);
+        // 返回
+        return iotMainWorkOrderDetails.getId();
+    }
+
+    @Override
+    public void updateIotMainWorkOrderDetails(IotMainWorkOrderDetailsSaveReqVO updateReqVO) {
+        // 校验存在
+        validateIotMainWorkOrderDetailsExists(updateReqVO.getId());
+        // 更新
+        IotMainWorkOrderDetailsDO updateObj = BeanUtils.toBean(updateReqVO, IotMainWorkOrderDetailsDO.class);
+        iotMainWorkOrderDetailsMapper.updateById(updateObj);
+    }
+
+    @Override
+    public void deleteIotMainWorkOrderDetails(Long id) {
+        // 校验存在
+        validateIotMainWorkOrderDetailsExists(id);
+        // 删除
+        iotMainWorkOrderDetailsMapper.deleteById(id);
+    }
+
+    private void validateIotMainWorkOrderDetailsExists(Long id) {
+        if (iotMainWorkOrderDetailsMapper.selectById(id) == null) {
+            throw exception(IOT_MAIN_WORK_ORDER_DETAILS_NOT_EXISTS);
+        }
+    }
+
+    @Override
+    public IotMainWorkOrderDetailsDO getIotMainWorkOrderDetails(Long id) {
+        return iotMainWorkOrderDetailsMapper.selectById(id);
+    }
+
+    @Override
+    public PageResult<IotMainWorkOrderDetailsDO> getIotMainWorkOrderDetailsPage(IotMainWorkOrderDetailsPageReqVO pageReqVO) {
+        return iotMainWorkOrderDetailsMapper.selectPage(pageReqVO);
+    }
+
+}

+ 4 - 4
yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/service/maintenance/IotMaintenancePlanService.java

@@ -1,13 +1,13 @@
 package cn.iocoder.yudao.module.pms.service.maintenance;
 
-import java.util.*;
-import javax.validation.*;
 import cn.iocoder.yudao.framework.common.pojo.PageResult;
-import cn.iocoder.yudao.framework.common.pojo.PageParam;
 import cn.iocoder.yudao.module.pms.controller.admin.maintenance.vo.IotMaintenancePlanPageReqVO;
 import cn.iocoder.yudao.module.pms.controller.admin.maintenance.vo.IotMaintenancePlanSaveReqVO;
+import cn.iocoder.yudao.module.pms.controller.admin.maintenance.vo.IotMaintenanceSaveVO;
 import cn.iocoder.yudao.module.pms.dal.dataobject.maintenance.IotMaintenancePlanDO;
 
+import javax.validation.Valid;
+
 /**
  * 保养计划 Service 接口
  *
@@ -21,7 +21,7 @@ public interface IotMaintenancePlanService {
      * @param createReqVO 创建信息
      * @return 编号
      */
-    Long createIotMaintenancePlan(@Valid IotMaintenancePlanSaveReqVO createReqVO);
+    Long createIotMaintenancePlan(@Valid IotMaintenanceSaveVO createReqVO);
 
     /**
      * 更新保养计划

+ 44 - 10
yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/service/maintenance/IotMaintenancePlanServiceImpl.java

@@ -1,22 +1,28 @@
 package cn.iocoder.yudao.module.pms.service.maintenance;
 
+import cn.hutool.core.util.ObjectUtil;
+import cn.iocoder.yudao.framework.common.pojo.PageResult;
+import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
+import cn.iocoder.yudao.module.pms.controller.admin.iotmaintenancebom.vo.IotMaintenanceBomSaveReqVO;
 import cn.iocoder.yudao.module.pms.controller.admin.maintenance.vo.IotMaintenancePlanPageReqVO;
 import cn.iocoder.yudao.module.pms.controller.admin.maintenance.vo.IotMaintenancePlanSaveReqVO;
+import cn.iocoder.yudao.module.pms.controller.admin.maintenance.vo.IotMaintenanceSaveVO;
+import cn.iocoder.yudao.module.pms.dal.dataobject.iotmaintenancebom.IotMaintenanceBomDO;
 import cn.iocoder.yudao.module.pms.dal.dataobject.maintenance.IotMaintenancePlanDO;
+import cn.iocoder.yudao.module.pms.dal.mysql.iotmaintenancebom.IotMaintenanceBomMapper;
 import cn.iocoder.yudao.module.pms.dal.mysql.maintenance.IotMaintenancePlanMapper;
+import cn.iocoder.yudao.module.pms.dal.redis.BizNoRedisDAO;
 import org.springframework.stereotype.Service;
-import javax.annotation.Resource;
 import org.springframework.validation.annotation.Validated;
-import org.springframework.transaction.annotation.Transactional;
-
-import java.util.*;
-import cn.iocoder.yudao.framework.common.pojo.PageResult;
-import cn.iocoder.yudao.framework.common.pojo.PageParam;
-import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
 
+import javax.annotation.Resource;
+import java.util.ArrayList;
+import java.util.List;
 
 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
+import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList;
 import static cn.iocoder.yudao.module.pms.enums.ErrorCodeConstant.IOT_MAINTENANCE_PLAN_NOT_EXISTS;
+import static cn.iocoder.yudao.module.pms.enums.ErrorCodeConstant.IOT_MAINTENANCE_PLAN_NO_EXISTS;
 
 /**
  * 保养计划 Service 实现类
@@ -29,12 +35,40 @@ public class IotMaintenancePlanServiceImpl implements IotMaintenancePlanService
 
     @Resource
     private IotMaintenancePlanMapper iotMaintenancePlanMapper;
+    @Resource
+    private IotMaintenanceBomMapper iotMaintenanceBomMapper;
+    @Resource
+    private BizNoRedisDAO bizNoRedisDAO;
 
     @Override
-    public Long createIotMaintenancePlan(IotMaintenancePlanSaveReqVO createReqVO) {
-        // 插入
-        IotMaintenancePlanDO iotMaintenancePlan = BeanUtils.toBean(createReqVO, IotMaintenancePlanDO.class);
+    public Long createIotMaintenancePlan(IotMaintenanceSaveVO createReqVO) {
+        if (ObjectUtil.isEmpty(createReqVO)) {
+            throw exception(IOT_MAINTENANCE_PLAN_NOT_EXISTS);
+        }
+        if (ObjectUtil.isEmpty(createReqVO.getMainPlan())) {
+            throw exception(IOT_MAINTENANCE_PLAN_NOT_EXISTS);
+        }
+        List<IotMaintenanceBomSaveReqVO> deviceBOMs = createReqVO.getMainPlanBom();
+        if (ObjectUtil.isEmpty(deviceBOMs)) {
+            throw exception(IOT_MAINTENANCE_PLAN_NOT_EXISTS);
+        }
+        // 先保存保养计划主表 再根据主表id更新明细
+        IotMaintenancePlanSaveReqVO mainPlanSaveVO = createReqVO.getMainPlan();
+        // 自动生成保养计划编号 BYJH202504300001
+        // 插入 保养计划
+        IotMaintenancePlanDO iotMaintenancePlan = BeanUtils.toBean(mainPlanSaveVO, IotMaintenancePlanDO.class);
+        String no = bizNoRedisDAO.generate(BizNoRedisDAO.MAIN_PLAN_NO_PREFIX);
+        if (ObjectUtil.isNotEmpty(iotMaintenancePlanMapper.selectByNo(no))) {
+            throw exception(IOT_MAINTENANCE_PLAN_NO_EXISTS);
+        }
+        iotMaintenancePlan.setSerialNumber(no);
         iotMaintenancePlanMapper.insert(iotMaintenancePlan);
+        // 插入保养计划明细
+        List<IotMaintenanceBomDO> maintenanceBOMs = new ArrayList<>();
+        maintenanceBOMs = convertList(deviceBOMs, bom -> BeanUtils.toBean(bom, IotMaintenanceBomDO.class, item -> item
+                .setPlanId(iotMaintenancePlan.getId())
+                .setDeviceCategoryId(bom.getAssetClass())));
+        iotMaintenanceBomMapper.insertBatch(maintenanceBOMs);
         // 返回
         return iotMaintenancePlan.getId();
     }

+ 12 - 1
yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/util/IotDeviceConvert.java

@@ -9,7 +9,6 @@ import cn.iocoder.yudao.module.system.controller.admin.dept.vo.dept.DeptSimpleRe
 import cn.iocoder.yudao.module.system.controller.admin.dept.vo.post.PostSimpleRespVO;
 import cn.iocoder.yudao.module.system.controller.admin.permission.vo.role.RoleSimpleRespVO;
 import cn.iocoder.yudao.module.system.controller.admin.user.vo.profile.UserProfileRespVO;
-import cn.iocoder.yudao.module.system.controller.admin.user.vo.user.UserRespVO;
 import cn.iocoder.yudao.module.system.controller.admin.user.vo.user.UserSimpleRespVO;
 import cn.iocoder.yudao.module.system.dal.dataobject.dept.DeptDO;
 import cn.iocoder.yudao.module.system.dal.dataobject.dept.PostDO;
@@ -31,6 +30,10 @@ public interface IotDeviceConvert {
         return CollectionUtils.convertList(list, de -> convert(de, deptMap.get(de.getDeptId())));
     }
 
+    default List<IotDeviceRespVO> convertList1(List<IotDeviceRespVO> list, Map<Long, DeptDO> deptMap) {
+        return CollectionUtils.convertList(list, de -> convert1(de, deptMap.get(de.getDeptId())));
+    }
+
     default IotDeviceRespVO convert(IotDeviceDO user, DeptDO dept) {
         IotDeviceRespVO userVO = BeanUtils.toBean(user, IotDeviceRespVO.class);
         if (dept != null) {
@@ -39,6 +42,14 @@ public interface IotDeviceConvert {
         return userVO;
     }
 
+    default IotDeviceRespVO convert1(IotDeviceRespVO user, DeptDO dept) {
+        IotDeviceRespVO userVO = BeanUtils.toBean(user, IotDeviceRespVO.class);
+        if (dept != null) {
+            userVO.setDeptName(dept.getName());
+        }
+        return userVO;
+    }
+
     default List<UserSimpleRespVO> convertSimpleList(List<AdminUserDO> list, Map<Long, DeptDO> deptMap) {
         return CollectionUtils.convertList(list, user -> {
             UserSimpleRespVO userVO = BeanUtils.toBean(user, UserSimpleRespVO.class);

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

@@ -0,0 +1,83 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="cn.iocoder.yudao.module.pms.dal.mysql.IotDeviceMapper">
+
+    <!--
+        一般情况下,尽可能使用 Mapper 进行 CRUD 增删改查即可。
+        无法满足的场景,例如说多表关联查询,才使用 XML 编写 SQL。
+        代码生成器暂时只生成 Mapper XML 文件本身,更多推荐 MybatisX 快速开发插件来生成查询。
+        文档可见:https://www.iocoder.cn/MyBatis/x-plugins/
+     -->
+    <select id="deviceAssociateBomPage"
+            resultType="cn.iocoder.yudao.module.pms.controller.admin.vo.IotDeviceRespVO">
+        SELECT
+            t.id ,
+            t.device_code,
+            t.device_name,
+            t.brand,
+            t.model,
+            t.dept_id,
+            t.device_status,
+            t.asset_property,
+            t.pic_url,
+            t.remark,
+            t.create_time,
+            t1.id bomNodeId,
+            t1.`name`,
+            t1.`code`
+        FROM
+            rq_iot_device t
+        INNER JOIN rq_iot_bom t1 ON ( t1.device_category_id = t.asset_class AND t1.deleted = 0 )
+        WHERE
+            t.deleted = 0
+          AND t1.deleted = 0
+          AND t1.leaf_flag = 1
+          AND t1.type LIKE '%2%'
+        <if test="deptIds != null and deptIds.size &gt; 0">
+            AND t.dept_id IN
+            <foreach collection="deptIds" index="index" item="key" open="(" separator="," close=")">
+                #{key}
+            </foreach>
+        </if>
+        <if test="reqVO.deviceName!=null and reqVO.deviceName!=''">
+            AND t.device_name LIKE concat(concat("%",#{reqVO.deviceName}),"%")
+        </if>
+        <if test="reqVO.name!=null and reqVO.name!=''">
+            AND t1.name LIKE concat(concat("%",#{reqVO.name}),"%")
+        </if>
+    </select>
+
+    <select id="deviceAssociateBomList"
+            resultType="cn.iocoder.yudao.module.pms.controller.admin.vo.IotDeviceRespVO">
+        SELECT
+        t.id ,
+        t.device_code,
+        t.device_name,
+        t.asset_class,
+        t.brand,
+        t.model,
+        t.dept_id,
+        t.device_status,
+        t.asset_property,
+        t.pic_url,
+        t.remark,
+        t.create_time,
+        t1.id bomNodeId,
+        t1.`name`,
+        t1.`code`
+        FROM
+        rq_iot_device t
+        INNER JOIN rq_iot_bom t1 ON ( t1.device_category_id = t.asset_class AND t1.deleted = 0 )
+        WHERE
+        t.deleted = 0
+        AND t1.deleted = 0
+        AND t1.leaf_flag = 1
+        AND t1.type LIKE '%2%'
+        <if test="deviceIds != null and deviceIds.size &gt; 0">
+            AND t.id IN
+            <foreach collection="deviceIds" index="index" item="key" open="(" separator="," close=")">
+                #{key}
+            </foreach>
+        </if>
+    </select>
+</mapper>