From 49e1bc66ebaf696ebd3fc3ed33d65c8795fd3cde Mon Sep 17 00:00:00 2001
From: liding <756868258@qq.com>
Date: 星期二, 01 七月 2025 18:05:12 +0800
Subject: [PATCH] 1.巡检定时任务 2.设备管理 3.文档查询

---
 main-business/src/main/java/com/ruoyi/business/service/impl/EquipmentManagementServiceImpl.java                 |   57 ++
 main-business/src/main/java/com/ruoyi/business/entity/InspectionTask.java                                       |   11 
 main-business/src/main/java/com/ruoyi/business/mapper/EquipmentManagementMapper.java                            |   18 
 main-business/src/main/java/com/ruoyi/business/service/impl/ArchiveServiceImpl.java                             |   28 
 main-business/src/main/java/com/ruoyi/business/controller/InputInventoryRecordController.java                   |   20 
 ruoyi-system/src/main/resources/mapper/system/SysUserMapper.xml                                                 |   32 +
 main-business/pom.xml                                                                                           |    4 
 main-business/src/main/resources/mapper/EquipmentManagementMapper.xml                                           |   35 +
 main-business/src/main/java/com/ruoyi/business/service/InspectionTaskService.java                               |    2 
 main-business/src/main/java/com/ruoyi/business/service/impl/InspectionTaskServiceImpl.java                      |   72 ++
 main-business/src/main/java/com/ruoyi/business/dto/TimingTaskDto.java                                           |   10 
 main-business/src/main/java/com/ruoyi/business/dto/ArchiveDto.java                                              |    2 
 main-business/src/main/java/com/ruoyi/business/mapper/TimingTaskMapper.java                                     |   24 
 main-business/src/main/resources/mapper/TimingTaskMapper.xml                                                    |   33 +
 main-business/src/main/resources/mapper/TreeMapper.xml                                                          |    9 
 main-business/src/main/java/com/ruoyi/business/controller/TimingTaskController.java                             |   56 ++
 main-business/src/main/java/com/ruoyi/business/service/impl/TimingTaskScheduler.java                            |  238 ++++++++
 main-business/src/main/java/com/ruoyi/business/service/TimingTaskService.java                                   |   27 
 main-business/src/main/resources/db/migration/postgresql/V20250630153900__create_table_timing_task.sql          |   63 ++
 ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysUserMapper.java                                           |   13 
 main-business/src/main/java/com/ruoyi/business/service/impl/PurchaseRegistrationServiceImpl.java                |    2 
 main-business/src/main/resources/db/migration/postgresql/V20250614134700__create_table_inspection_task.sql      |   37 
 main-business/src/main/java/com/ruoyi/business/service/EquipmentManagementService.java                          |   24 
 main-business/src/main/java/com/ruoyi/business/controller/InspectionTaskController.java                         |    3 
 main-business/src/main/java/com/ruoyi/business/entity/TimingTask.java                                           |   96 +++
 main-business/src/main/java/com/ruoyi/business/service/impl/ProductionMasterServiceImpl.java                    |   29 
 main-business/src/main/java/com/ruoyi/business/mapper/TreeMapper.java                                           |    3 
 main-business/src/main/java/com/ruoyi/business/service/impl/TimingTaskServiceImpl.java                          |  405 ++++++++++++++
 main-business/src/main/java/com/ruoyi/business/service/ArchiveService.java                                      |    2 
 main-business/src/main/java/com/ruoyi/business/controller/ArchiveController.java                                |    3 
 main-business/src/main/java/com/ruoyi/business/controller/EquipmentManagementController.java                    |   56 ++
 main-business/src/main/resources/db/migration/postgresql/V20250701142700__create_table_equipment_management.sql |   59 ++
 main-business/src/main/java/com/ruoyi/business/entity/EquipmentManagement.java                                  |   79 ++
 main-business/src/main/java/com/ruoyi/business/task/TimingTaskJob.java                                          |   66 ++
 main-business/src/main/java/com/ruoyi/business/dto/EquipmentManagementDto.java                                  |    8 
 35 files changed, 1,585 insertions(+), 41 deletions(-)

diff --git a/main-business/pom.xml b/main-business/pom.xml
index c1f56f7..18ff099 100644
--- a/main-business/pom.xml
+++ b/main-business/pom.xml
@@ -44,6 +44,10 @@
             <groupId>com.ruoyi</groupId>
             <artifactId>basic-server</artifactId>
         </dependency>
+        <dependency>
+            <groupId>org.quartz-scheduler</groupId>
+            <artifactId>quartz</artifactId>
+        </dependency>
     </dependencies>
 
     <properties>
diff --git a/main-business/src/main/java/com/ruoyi/business/controller/ArchiveController.java b/main-business/src/main/java/com/ruoyi/business/controller/ArchiveController.java
index 4e4ca1a..3f934be 100644
--- a/main-business/src/main/java/com/ruoyi/business/controller/ArchiveController.java
+++ b/main-business/src/main/java/com/ruoyi/business/controller/ArchiveController.java
@@ -3,6 +3,7 @@
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.ruoyi.business.dto.ArchiveDto;
+import com.ruoyi.business.entity.Archive;
 import com.ruoyi.business.service.ArchiveService;
 import com.ruoyi.common.core.domain.R;
 import lombok.AllArgsConstructor;
@@ -28,7 +29,7 @@
      * 鏌ヨ妗f淇℃伅琛�
      */
     @GetMapping("/list")
-    public R<IPage<ArchiveDto>> treeList(Page page, ArchiveDto archiveDto) {
+    public R<IPage<ArchiveDto>> treeList(Page<Archive> page, ArchiveDto archiveDto) {
         IPage<ArchiveDto> list = archiveService.selectArchiveList(page, archiveDto);
         return R.ok(list);
     }
diff --git a/main-business/src/main/java/com/ruoyi/business/controller/EquipmentManagementController.java b/main-business/src/main/java/com/ruoyi/business/controller/EquipmentManagementController.java
new file mode 100644
index 0000000..1a30f74
--- /dev/null
+++ b/main-business/src/main/java/com/ruoyi/business/controller/EquipmentManagementController.java
@@ -0,0 +1,56 @@
+package com.ruoyi.business.controller;
+
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.ruoyi.business.dto.EquipmentManagementDto;
+import com.ruoyi.business.dto.ProductionDto;
+import com.ruoyi.business.entity.EquipmentManagement;
+import com.ruoyi.business.entity.Production;
+import com.ruoyi.business.service.EquipmentManagementService;
+import com.ruoyi.common.core.domain.R;
+import org.springframework.web.bind.annotation.*;
+import lombok.AllArgsConstructor;
+
+/**
+ * <p>
+ * 璁惧绠$悊琛�  鍓嶇鎺у埗鍣�
+ * </p>
+ *
+ * @author ld
+ * @since 2025-07-01
+ */
+
+@RestController
+@AllArgsConstructor
+@RequestMapping("/equipmentManagement")
+public class EquipmentManagementController {
+    
+    private EquipmentManagementService equipmentManagementService;
+
+    /**
+     * 璁惧绠$悊琛ㄦ煡璇�
+     */
+    @GetMapping("/list")
+    public R<IPage<EquipmentManagementDto>> list(Page<EquipmentManagement> page, EquipmentManagementDto equipmentManagementDto) {
+        IPage<EquipmentManagementDto> list = equipmentManagementService.selectProductionList(page, equipmentManagementDto);
+        return R.ok(list);
+    }
+
+    /**
+     * 璁惧绠$悊琛ㄦ柊澧炰慨鏀�
+     */
+    @PostMapping("/addOrEditEquipment")
+    public R addOrEditEquipment(@RequestBody EquipmentManagementDto equipmentManagementDto) {
+        return R.ok(equipmentManagementService.addOrEditEquipment(equipmentManagementDto));
+    }
+
+    /**
+     * 璁惧绠$悊琛ㄥ垹闄�
+     */
+    @DeleteMapping("/delEquipment")
+    public R remove(@RequestBody Long[] ids) {
+        return R.ok(equipmentManagementService.delByIds(ids));
+    }
+
+
+}
diff --git a/main-business/src/main/java/com/ruoyi/business/controller/InputInventoryRecordController.java b/main-business/src/main/java/com/ruoyi/business/controller/InputInventoryRecordController.java
index ec8e4f1..14b391e 100644
--- a/main-business/src/main/java/com/ruoyi/business/controller/InputInventoryRecordController.java
+++ b/main-business/src/main/java/com/ruoyi/business/controller/InputInventoryRecordController.java
@@ -2,20 +2,20 @@
 
 import org.springframework.web.bind.annotation.RequestMapping;
 import lombok.AllArgsConstructor;
-    import org.springframework.web.bind.annotation.RestController;
+import org.springframework.web.bind.annotation.RestController;
 
 /**
-* <p>
-    * 鍏ュ簱璁板綍琛� 鍓嶇鎺у埗鍣�
-    * </p>
-*
-* @author chenhj
-* @since 2025-06-14
-*/
+ * <p>
+ * 鍏ュ簱璁板綍琛� 鍓嶇鎺у埗鍣�
+ * </p>
+ *
+ * @author chenhj
+ * @since 2025-06-14
+ */
 
 @RestController
 @AllArgsConstructor
 @RequestMapping("/business/inputInventoryRecord")
-        public class InputInventoryRecordController {
+public class InputInventoryRecordController {
 
-    }
+}
diff --git a/main-business/src/main/java/com/ruoyi/business/controller/InspectionTaskController.java b/main-business/src/main/java/com/ruoyi/business/controller/InspectionTaskController.java
index d085f74..9d092fc 100644
--- a/main-business/src/main/java/com/ruoyi/business/controller/InspectionTaskController.java
+++ b/main-business/src/main/java/com/ruoyi/business/controller/InspectionTaskController.java
@@ -3,6 +3,7 @@
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.ruoyi.business.dto.InspectionTaskDto;
+import com.ruoyi.business.entity.InspectionTask;
 import com.ruoyi.business.service.InspectionTaskService;
 import com.ruoyi.common.core.domain.R;
 import lombok.AllArgsConstructor;
@@ -27,7 +28,7 @@
      * 宸℃浠诲姟琛ㄨ〃鏌ヨ
      */
     @GetMapping("/list")
-    public R<IPage<InspectionTaskDto>> list(Page page, InspectionTaskDto inspectionTaskDto) {
+    public R<IPage<InspectionTaskDto>> list(Page<InspectionTask> page, InspectionTaskDto inspectionTaskDto) {
         IPage<InspectionTaskDto> list = inspectionTaskService.selectInspectionTaskList(page,inspectionTaskDto);
         return R.ok(list);
     }
diff --git a/main-business/src/main/java/com/ruoyi/business/controller/TimingTaskController.java b/main-business/src/main/java/com/ruoyi/business/controller/TimingTaskController.java
new file mode 100644
index 0000000..ee3e64c
--- /dev/null
+++ b/main-business/src/main/java/com/ruoyi/business/controller/TimingTaskController.java
@@ -0,0 +1,56 @@
+package com.ruoyi.business.controller;
+
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.ruoyi.business.dto.SalesRecordDto;
+import com.ruoyi.business.dto.TimingTaskDto;
+import com.ruoyi.business.entity.SalesRecord;
+import com.ruoyi.business.entity.TimingTask;
+import com.ruoyi.business.service.TimingTaskService;
+import com.ruoyi.common.core.domain.R;
+import org.quartz.SchedulerException;
+import org.springframework.web.bind.annotation.*;
+import lombok.AllArgsConstructor;
+
+/**
+ * <p>
+ * 瀹氭椂宸℃浠诲姟琛� 鍓嶇鎺у埗鍣�
+ * </p>
+ *
+ * @author ld
+ * @since 2025-06-30
+ */
+
+@RestController
+@AllArgsConstructor
+@RequestMapping("/timingTask")
+public class TimingTaskController {
+    
+    private TimingTaskService timingTaskService;
+
+    /**
+     * 瀹氭椂宸℃浠诲姟琛ㄦ煡璇�
+     */
+    @GetMapping("/list")
+    public R<IPage<TimingTaskDto>> list(Page<TimingTask> page, TimingTask timingTask) {
+        IPage<TimingTaskDto> list = timingTaskService.selectTimingTaskList(page,timingTask);
+        return R.ok(list);
+    }
+
+    /**
+     * 瀹氭椂宸℃浠诲姟琛ㄦ柊澧炰慨鏀�
+     */
+    @PostMapping("/addOrEditTimingTask")
+    public R addOrEditTimingTask(@RequestBody TimingTaskDto timingTaskDto) throws SchedulerException {
+        return R.ok(timingTaskService.addOrEditTimingTask(timingTaskDto));
+    }
+
+    /**
+     * 瀹氭椂宸℃浠诲姟琛ㄥ垹闄�
+     */
+    @DeleteMapping("/delTimingTask")
+    public R remove(@RequestBody Long[] ids) {
+        return R.ok(timingTaskService.delByIds(ids));
+    }
+
+}
diff --git a/main-business/src/main/java/com/ruoyi/business/dto/ArchiveDto.java b/main-business/src/main/java/com/ruoyi/business/dto/ArchiveDto.java
index dc92a44..52a889a 100644
--- a/main-business/src/main/java/com/ruoyi/business/dto/ArchiveDto.java
+++ b/main-business/src/main/java/com/ruoyi/business/dto/ArchiveDto.java
@@ -15,4 +15,6 @@
     private List<StorageBlobDTO> storageBlobDTO;
 
     private List<StorageBlob> attachments;
+
+    private String searchAll;
 }
diff --git a/main-business/src/main/java/com/ruoyi/business/dto/EquipmentManagementDto.java b/main-business/src/main/java/com/ruoyi/business/dto/EquipmentManagementDto.java
new file mode 100644
index 0000000..858a31a
--- /dev/null
+++ b/main-business/src/main/java/com/ruoyi/business/dto/EquipmentManagementDto.java
@@ -0,0 +1,8 @@
+package com.ruoyi.business.dto;
+
+import com.ruoyi.business.entity.EquipmentManagement;
+import lombok.Data;
+
+@Data
+public class EquipmentManagementDto extends EquipmentManagement {
+}
diff --git a/main-business/src/main/java/com/ruoyi/business/dto/TimingTaskDto.java b/main-business/src/main/java/com/ruoyi/business/dto/TimingTaskDto.java
new file mode 100644
index 0000000..84b0b81
--- /dev/null
+++ b/main-business/src/main/java/com/ruoyi/business/dto/TimingTaskDto.java
@@ -0,0 +1,10 @@
+package com.ruoyi.business.dto;
+
+import com.ruoyi.business.entity.TimingTask;
+import lombok.Data;
+
+@Data
+public class TimingTaskDto extends TimingTask {
+
+    private String inspector;
+}
diff --git a/main-business/src/main/java/com/ruoyi/business/entity/EquipmentManagement.java b/main-business/src/main/java/com/ruoyi/business/entity/EquipmentManagement.java
new file mode 100644
index 0000000..4cb21c4
--- /dev/null
+++ b/main-business/src/main/java/com/ruoyi/business/entity/EquipmentManagement.java
@@ -0,0 +1,79 @@
+package com.ruoyi.business.entity;
+
+import com.baomidou.mybatisplus.annotation.*;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import lombok.Data;
+import com.ruoyi.common.core.domain.MyBaseEntity;
+
+import java.math.BigDecimal;
+import java.time.LocalDate;
+
+/**
+ * 璁惧绠$悊琛�  瀹炰綋绫�
+ *
+ * @author ld
+ * @date 2025-07-01
+ */
+@Data
+@TableName("equipment_management")
+public class EquipmentManagement extends MyBaseEntity {
+
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 涓婚敭 ID
+     */
+    @TableId(value = "id", type = IdType.AUTO)
+    private Long id;
+    /**
+     * 璁惧缂栧彿
+     */
+    @TableField(value = "equipment_id")
+    private String equipmentId;
+    /**
+     * 璁惧鍚嶇О
+     */
+    @TableField(value = "equipment_name")
+    private String equipmentName;
+    /**
+     * 鏁伴噺
+     */
+    @TableField(value = "quantity")
+    private Integer quantity;
+    /**
+     * 瑙勬牸鍨嬪彿
+     */
+    @TableField(value = "specification")
+    private String specification;
+    /**
+     * 浣跨敤鐘舵��
+     */
+    @TableField(value = "usage_status")
+    private String usageStatus;
+    /**
+     * 浣跨敤閮ㄩ棬
+     */
+    @TableField(value = "using_department")
+    private String usingDepartment;
+    /**
+     * 浣跨敤浜篒D
+     */
+    @TableField(value = "user_id")
+    private Long userId;
+    /**
+     * 瀛樻斁浣嶇疆
+     */
+    @TableField(value = "storage_location")
+    private String storageLocation;
+    /**
+     * 閲囪喘鏃ユ湡
+     */
+    @TableField(value = "purchase_date")
+    @JsonFormat(pattern = "yyyy-MM-dd")
+    private LocalDate purchaseDate;
+    /**
+     * 閲囪喘浠锋牸
+     */
+    @TableField(value = "purchase_price")
+    private BigDecimal purchasePrice;
+}
\ No newline at end of file
diff --git a/main-business/src/main/java/com/ruoyi/business/entity/InspectionTask.java b/main-business/src/main/java/com/ruoyi/business/entity/InspectionTask.java
index 8c96c92..7354a13 100644
--- a/main-business/src/main/java/com/ruoyi/business/entity/InspectionTask.java
+++ b/main-business/src/main/java/com/ruoyi/business/entity/InspectionTask.java
@@ -30,7 +30,7 @@
      *
      */
     @TableField(value = "inspector_id")
-    private Long inspectorId;
+    private String inspectorId;
     /**
      * 鎵ц宸℃鐨勪汉鍛樺鍚�
      */
@@ -39,8 +39,8 @@
     /**
      * 宸℃鍦扮偣璇︾粏鎻忚堪
      */
-    @TableField(value = "port")
-    private String port;
+    @TableField(value = "inspection_location")
+    private String inspectionLocation;
     /**
      * 浠诲姟闄勫姞璇存槑鎴栫壒娈婃儏鍐佃褰�
      */
@@ -56,4 +56,9 @@
      */
     @TableField(value = "registrant")
     private String registrant;
+    /**
+     * 棰戞
+     */
+    @TableField(value = "frequency_type")
+    private String frequencyType;
 }
\ No newline at end of file
diff --git a/main-business/src/main/java/com/ruoyi/business/entity/TimingTask.java b/main-business/src/main/java/com/ruoyi/business/entity/TimingTask.java
new file mode 100644
index 0000000..3a91e90
--- /dev/null
+++ b/main-business/src/main/java/com/ruoyi/business/entity/TimingTask.java
@@ -0,0 +1,96 @@
+package com.ruoyi.business.entity;
+
+import com.baomidou.mybatisplus.annotation.*;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import lombok.Data;
+import com.ruoyi.common.core.domain.MyBaseEntity;
+
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+
+/**
+ * 瀹氭椂宸℃浠诲姟琛� 瀹炰綋绫�
+ *
+ * @author ld
+ * @date 2025-06-30
+ */
+@Data
+@TableName("timing_task")
+public class TimingTask extends MyBaseEntity {
+
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 涓婚敭ID
+     */
+    @TableId(value = "id", type = IdType.AUTO)
+    private Long id;
+    /**
+     * 浠诲姟鍚嶇О
+     */
+    @TableField(value = "task_name")
+    private String taskName;
+    /**
+     * 宸℃浜�
+     */
+    @TableField(value = "inspector_ids")
+    private String inspectorIds;
+    /**
+     * 宸℃鍦扮偣
+     */
+    @TableField(value = "inspection_location")
+    private String inspectionLocation;
+    /**
+     * 棰戞
+     */
+    @TableField(value = "frequency_type")
+    private String frequencyType;
+    /**
+     * 鍏蜂綋鏃堕棿
+     */
+    @TableField(value = "frequency_detail")
+    private String frequencyDetail;
+    /**
+     * 涓嬫鎵ц鏃堕棿
+     */
+    @TableField(value = "next_execution_time")
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    private LocalDateTime nexExecutionTime;
+    /**
+     * 鏈�鍚庢墽琛屾椂闂�
+     */
+    @TableField(value = "last_execution_time")
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    private LocalDateTime lastExecuteTime;
+    /**
+     * 鏄惁婵�娲�
+     */
+    @TableField(value = "is_active")
+    private boolean isActive;
+    /**
+     * 澶囨敞
+     */
+    @TableField(value = "remarks")
+    private String remarks;
+    /**
+     * 鐧昏浜篿d
+     */
+    @TableField(value = "registrant_id")
+    private Long registrantId;
+    /**
+     * 鐧昏浜�
+     */
+    @TableField(value = "registrant")
+    private String registrant;
+    /**
+     * 鐧昏鏃ユ湡
+     */
+    @TableField(value = "registration_date")
+    @JsonFormat(pattern = "yyyy-MM-dd")
+    private LocalDate registrationDate;
+    /**
+     * 浠诲姟鐘舵��
+     */
+    @TableField(value = "status")
+    private String status; // ACTIVE, PAUSED, COMPLETED绛�
+}
\ No newline at end of file
diff --git a/main-business/src/main/java/com/ruoyi/business/mapper/EquipmentManagementMapper.java b/main-business/src/main/java/com/ruoyi/business/mapper/EquipmentManagementMapper.java
new file mode 100644
index 0000000..9f1d438
--- /dev/null
+++ b/main-business/src/main/java/com/ruoyi/business/mapper/EquipmentManagementMapper.java
@@ -0,0 +1,18 @@
+package com.ruoyi.business.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.ruoyi.business.entity.EquipmentManagement;
+import org.apache.ibatis.annotations.Mapper;
+
+/**
+ * <p>
+ *  璁惧绠$悊琛�  Mapper 鎺ュ彛
+ * </p>
+ *
+ * @author ld
+ * @since 2025-07-01
+ */
+@Mapper
+public interface EquipmentManagementMapper extends BaseMapper<EquipmentManagement> {
+
+}
diff --git a/main-business/src/main/java/com/ruoyi/business/mapper/TimingTaskMapper.java b/main-business/src/main/java/com/ruoyi/business/mapper/TimingTaskMapper.java
new file mode 100644
index 0000000..d459f1b
--- /dev/null
+++ b/main-business/src/main/java/com/ruoyi/business/mapper/TimingTaskMapper.java
@@ -0,0 +1,24 @@
+package com.ruoyi.business.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.ruoyi.business.entity.TimingTask;
+import org.apache.ibatis.annotations.Mapper;
+import org.apache.ibatis.annotations.Param;
+import org.apache.ibatis.annotations.Select;
+
+import java.time.LocalDateTime;
+import java.util.List;
+
+/**
+ * <p>
+ * 瀹氭椂宸℃浠诲姟琛� Mapper 鎺ュ彛
+ * </p>
+ *
+ * @author ld
+ * @since 2025-06-30
+ */
+@Mapper
+public interface TimingTaskMapper extends BaseMapper<TimingTask> {
+
+    @Select("SELECT * FROM timing_task WHERE next_execution_time <= #{currentTime}")
+    List<TimingTask> selectActiveTasks(@Param("currentTime") LocalDateTime currentTime);}
diff --git a/main-business/src/main/java/com/ruoyi/business/mapper/TreeMapper.java b/main-business/src/main/java/com/ruoyi/business/mapper/TreeMapper.java
index ec9bc03..89ce74e 100644
--- a/main-business/src/main/java/com/ruoyi/business/mapper/TreeMapper.java
+++ b/main-business/src/main/java/com/ruoyi/business/mapper/TreeMapper.java
@@ -4,6 +4,8 @@
 import com.ruoyi.business.entity.Tree;
 import org.apache.ibatis.annotations.Mapper;
 
+import java.util.List;
+
 /**
  * <p>
  * 妗f淇℃伅琛紝璁板綍绯荤粺涓悇绫绘。妗堢殑鍩烘湰淇℃伅 Mapper 鎺ュ彛
@@ -15,4 +17,5 @@
 @Mapper
 public interface TreeMapper extends BaseMapper<Tree> {
 
+    List<Long> listRecursiveSubNodeIds(Long treeId);
 }
diff --git a/main-business/src/main/java/com/ruoyi/business/service/ArchiveService.java b/main-business/src/main/java/com/ruoyi/business/service/ArchiveService.java
index 8eb6b86..3ba315f 100644
--- a/main-business/src/main/java/com/ruoyi/business/service/ArchiveService.java
+++ b/main-business/src/main/java/com/ruoyi/business/service/ArchiveService.java
@@ -19,7 +19,7 @@
  */
 public interface ArchiveService extends IService<Archive> {
 
-    IPage<ArchiveDto> selectArchiveList(Page page, ArchiveDto archiveDto);
+    IPage<ArchiveDto> selectArchiveList(Page<Archive> page, ArchiveDto archiveDto);
 
     int addOrEditArchive(ArchiveDto archiveDto);
 
diff --git a/main-business/src/main/java/com/ruoyi/business/service/EquipmentManagementService.java b/main-business/src/main/java/com/ruoyi/business/service/EquipmentManagementService.java
new file mode 100644
index 0000000..2cbca4b
--- /dev/null
+++ b/main-business/src/main/java/com/ruoyi/business/service/EquipmentManagementService.java
@@ -0,0 +1,24 @@
+package com.ruoyi.business.service;
+
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.ruoyi.business.dto.EquipmentManagementDto;
+import com.ruoyi.business.entity.EquipmentManagement;
+import com.baomidou.mybatisplus.extension.service.IService;
+
+/**
+ * <p>
+ *  璁惧绠$悊琛�  鏈嶅姟绫�
+ * </p>
+ *
+ * @author ld
+ * @since 2025-07-01
+ */
+public interface EquipmentManagementService extends IService<EquipmentManagement> {
+
+    IPage<EquipmentManagementDto> selectProductionList(Page<EquipmentManagement> page, EquipmentManagementDto equipmentManagementDto);
+
+    int addOrEditEquipment(EquipmentManagementDto equipmentManagementDto);
+
+    int delByIds(Long[] ids);
+}
diff --git a/main-business/src/main/java/com/ruoyi/business/service/InspectionTaskService.java b/main-business/src/main/java/com/ruoyi/business/service/InspectionTaskService.java
index f28573b..1fa20e2 100644
--- a/main-business/src/main/java/com/ruoyi/business/service/InspectionTaskService.java
+++ b/main-business/src/main/java/com/ruoyi/business/service/InspectionTaskService.java
@@ -16,7 +16,7 @@
  */
 public interface InspectionTaskService extends IService<InspectionTask> {
 
-    IPage<InspectionTaskDto> selectInspectionTaskList(Page page, InspectionTaskDto inspectionTaskDto);
+    IPage<InspectionTaskDto> selectInspectionTaskList(Page<InspectionTask> page, InspectionTaskDto inspectionTaskDto);
 
     int addOrEditInspectionTask(InspectionTaskDto inspectionTaskDto);
 
diff --git a/main-business/src/main/java/com/ruoyi/business/service/TimingTaskService.java b/main-business/src/main/java/com/ruoyi/business/service/TimingTaskService.java
new file mode 100644
index 0000000..4455d96
--- /dev/null
+++ b/main-business/src/main/java/com/ruoyi/business/service/TimingTaskService.java
@@ -0,0 +1,27 @@
+package com.ruoyi.business.service;
+
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.ruoyi.business.dto.TimingTaskDto;
+import com.ruoyi.business.entity.TimingTask;
+import com.baomidou.mybatisplus.extension.service.IService;
+import org.quartz.SchedulerException;
+
+/**
+ * <p>
+ * 瀹氭椂宸℃浠诲姟琛� 鏈嶅姟绫�
+ * </p>
+ *
+ * @author ld
+ * @since 2025-06-30
+ */
+public interface TimingTaskService extends IService<TimingTask> {
+
+    IPage<TimingTaskDto> selectTimingTaskList(Page<TimingTask> page, TimingTask timingTask);
+
+    int addOrEditTimingTask(TimingTaskDto timingTaskDto) throws SchedulerException;
+
+    int delByIds(Long[] ids);
+
+    void updateTaskExecutionTime(Long taskId);
+}
diff --git a/main-business/src/main/java/com/ruoyi/business/service/impl/ArchiveServiceImpl.java b/main-business/src/main/java/com/ruoyi/business/service/impl/ArchiveServiceImpl.java
index 09c460c..4866ff5 100644
--- a/main-business/src/main/java/com/ruoyi/business/service/impl/ArchiveServiceImpl.java
+++ b/main-business/src/main/java/com/ruoyi/business/service/impl/ArchiveServiceImpl.java
@@ -14,7 +14,9 @@
 import com.ruoyi.basic.service.StorageAttachmentService;
 import com.ruoyi.business.dto.ArchiveDto;
 import com.ruoyi.business.entity.Archive;
+import com.ruoyi.business.entity.Tree;
 import com.ruoyi.business.mapper.ArchiveMapper;
+import com.ruoyi.business.mapper.TreeMapper;
 import com.ruoyi.business.service.ArchiveService;
 import com.ruoyi.common.utils.bean.BeanUtils;
 import com.ruoyi.common.utils.file.MinioUtils;
@@ -43,6 +45,8 @@
 
     private final ArchiveMapper archiveMapper;
 
+    private final TreeMapper treeMapper;
+
     private final StorageAttachmentService storageAttachmentService;
 
     private final StorageBlobMapper storageBlobMapper;
@@ -53,12 +57,30 @@
 
 
     @Override
-    public IPage<ArchiveDto> selectArchiveList(Page page, ArchiveDto archiveDto) {
+    public IPage<ArchiveDto> selectArchiveList(Page<Archive> page, ArchiveDto archiveDto) {
         // 1. 鍒嗛〉鏌ヨ涓绘暟鎹�
         LambdaQueryWrapper<Archive> queryWrapper = new LambdaQueryWrapper<>();
         queryWrapper.orderByDesc(Archive::getCreateTime);
         if (archiveDto.getTreeId() != null) {
-            queryWrapper.eq(Archive::getTreeId, archiveDto.getTreeId());
+            Long treeId = archiveDto.getTreeId();
+            // 鍒ゆ柇鏄惁涓轰富ID
+            Tree tree = treeMapper.selectById(archiveDto.getTreeId());
+            boolean isMainId = tree != null && tree.getParentId() == null;
+
+            if (isMainId) {
+                // 鑾峰彇涓籌D鐨勬墍鏈夐�掑綊瀛愯妭鐐笽D
+                List<Long> recursiveSubIds = treeMapper.listRecursiveSubNodeIds(treeId);
+
+                // 灏嗕富ID鏈韩鍜屾墍鏈夊瓙鑺傜偣ID鍔犲叆鏌ヨ鏉′欢
+                recursiveSubIds.add(treeId);
+                queryWrapper.in(Archive::getTreeId, recursiveSubIds);
+            } else {
+                // 闈炰富ID锛岀洿鎺ユ寜鍘熸潯浠舵煡璇�
+                queryWrapper.eq(Archive::getTreeId, treeId);
+            }
+        }
+        if (archiveDto.getSearchAll() != null) {
+            queryWrapper.like(Archive::getName, archiveDto.getSearchAll());
         }
         IPage<Archive> archivePage = archiveMapper.selectPage(page, queryWrapper);
 
@@ -114,7 +136,7 @@
                     .map(blob -> {
                         StorageBlobDTO blobDTO = new StorageBlobDTO();
                         BeanUtils.copyProperties(blob, blobDTO);
-                   
+
                         // 鍔ㄦ�佺敓鎴愰瑙堝湴鍧�鍜屼笅杞藉湴鍧�
                         // 璁剧疆棰勮URL
                         blobDTO.setUrl(minioUtils.getPreviewUrls(
diff --git a/main-business/src/main/java/com/ruoyi/business/service/impl/EquipmentManagementServiceImpl.java b/main-business/src/main/java/com/ruoyi/business/service/impl/EquipmentManagementServiceImpl.java
new file mode 100644
index 0000000..1ac61c9
--- /dev/null
+++ b/main-business/src/main/java/com/ruoyi/business/service/impl/EquipmentManagementServiceImpl.java
@@ -0,0 +1,57 @@
+package com.ruoyi.business.service.impl;
+
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.ruoyi.business.dto.EquipmentManagementDto;
+import com.ruoyi.business.dto.ProductionMasterDto;
+import com.ruoyi.business.entity.EquipmentManagement;
+import com.ruoyi.business.entity.Production;
+import com.ruoyi.business.mapper.EquipmentManagementMapper;
+import com.ruoyi.business.service.EquipmentManagementService;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.ruoyi.common.utils.bean.BeanUtils;
+import org.springframework.stereotype.Service;
+import lombok.RequiredArgsConstructor;
+
+import java.util.Arrays;
+import java.util.Objects;
+
+/**
+ * <p>
+ * 璁惧绠$悊琛�  鏈嶅姟瀹炵幇绫�
+ * </p>
+ *
+ * @author ld
+ * @since 2025-07-01
+ */
+@Service
+@RequiredArgsConstructor
+public class EquipmentManagementServiceImpl extends ServiceImpl<EquipmentManagementMapper, EquipmentManagement> implements EquipmentManagementService {
+
+    private final EquipmentManagementMapper equipmentManagementMapper;
+
+    public IPage<EquipmentManagementDto> selectProductionList(Page<EquipmentManagement> page, EquipmentManagementDto equipmentManagementDto) {
+        Page<EquipmentManagement> entityPage = equipmentManagementMapper.selectPage(page, null);
+        IPage<EquipmentManagementDto> dtoPage = new Page<>();
+        BeanUtils.copyProperties(entityPage, dtoPage);
+
+        return dtoPage;
+    }
+
+    @Override
+    public int addOrEditEquipment(EquipmentManagementDto equipmentManagementDto) {
+        EquipmentManagement equipmentManagement = new EquipmentManagement();
+        BeanUtils.copyProperties(equipmentManagementDto, equipmentManagement);
+        if (Objects.isNull(equipmentManagementDto.getId())) {
+            return equipmentManagementMapper.insert(equipmentManagement);
+        } else {
+            return equipmentManagementMapper.updateById(equipmentManagement);
+        }
+    }
+
+    @Override
+    public int delByIds(Long[] ids) {
+        return equipmentManagementMapper.deleteByIds(Arrays.asList(ids));
+    }
+}
diff --git a/main-business/src/main/java/com/ruoyi/business/service/impl/InspectionTaskServiceImpl.java b/main-business/src/main/java/com/ruoyi/business/service/impl/InspectionTaskServiceImpl.java
index 414e3f7..2c2400a 100644
--- a/main-business/src/main/java/com/ruoyi/business/service/impl/InspectionTaskServiceImpl.java
+++ b/main-business/src/main/java/com/ruoyi/business/service/impl/InspectionTaskServiceImpl.java
@@ -7,6 +7,7 @@
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import com.ruoyi.basic.entity.StorageAttachment;
 import com.ruoyi.basic.entity.StorageBlob;
+import com.ruoyi.basic.entity.Supply;
 import com.ruoyi.basic.entity.dto.StorageBlobDTO;
 import com.ruoyi.basic.mapper.StorageAttachmentMapper;
 import com.ruoyi.basic.mapper.StorageBlobMapper;
@@ -15,9 +16,12 @@
 import com.ruoyi.business.entity.InspectionTask;
 import com.ruoyi.business.mapper.InspectionTaskMapper;
 import com.ruoyi.business.service.InspectionTaskService;
+import com.ruoyi.common.core.domain.entity.SysUser;
 import com.ruoyi.common.utils.SecurityUtils;
+import com.ruoyi.common.utils.StringUtils;
 import com.ruoyi.common.utils.bean.BeanUtils;
 import com.ruoyi.common.utils.file.MinioUtils;
+import com.ruoyi.system.mapper.SysUserMapper;
 import lombok.RequiredArgsConstructor;
 import org.springframework.stereotype.Service;
 
@@ -50,8 +54,10 @@
 
     private final MinioUtils minioUtils;
 
+    private final SysUserMapper sysUserMapper;
+
     @Override
-    public IPage<InspectionTaskDto> selectInspectionTaskList(Page page, InspectionTaskDto inspectionTaskDto) {
+    public IPage<InspectionTaskDto> selectInspectionTaskList(Page<InspectionTask> page, InspectionTaskDto inspectionTaskDto) {
         LambdaQueryWrapper<InspectionTask> queryWrapper = new LambdaQueryWrapper<>();
         queryWrapper.orderByDesc(InspectionTask::getCreateTime);
         IPage<InspectionTask> entityPage = inspectionTaskMapper.selectPage(page, queryWrapper);
@@ -61,8 +67,46 @@
             return new Page<>(entityPage.getCurrent(), entityPage.getSize(), entityPage.getTotal());
         }
         // 鑾峰彇id闆嗗悎
-        List<Long> ids = entityPage.getRecords().stream().map(InspectionTask::getId).collect(Collectors.toList());
+        List<Long> ids = entityPage.getRecords().stream().map(InspectionTask::getId).toList();
+        //鐧昏浜篿ds
+        List<Long> registrantIds = entityPage.getRecords().stream().map(InspectionTask::getRegistrantId).toList();
+        // 鎵归噺鏌ヨ鐧昏浜�
+        Map<Long, SysUser> sysUserMap;
+        if (!registrantIds.isEmpty()) {
+            List<SysUser> sysUsers = sysUserMapper.selectList(registrantIds);
+            sysUserMap = sysUsers.stream().collect(Collectors.toMap(SysUser::getUserId, Function.identity()));
+        } else {
+            sysUserMap = new HashMap<>();
+        }
+        //宸℃浜篿ds
+        List<String> inspectorIds = entityPage.getRecords().stream().map(InspectionTask::getInspectorId).toList();
 
+        //鑾峰彇鎵�鏈変笉閲嶅鐨勭敤鎴稩D
+        Set<Long> allUserIds = entityPage.getRecords().stream()
+                .map(InspectionTask::getInspectorId) // 鑾峰彇"2,3"杩欐牱鐨勫瓧绗︿覆
+                .filter(StringUtils::isNotBlank)
+                .flatMap(idsStr -> Arrays.stream(idsStr.split(",")))
+                .map(idStr -> {
+                    try {
+                        return Long.parseLong(idStr.trim());
+                    } catch (NumberFormatException e) {
+                        return null;
+                    }
+                })
+                .filter(Objects::nonNull)
+                .collect(Collectors.toSet());
+
+        // 浣跨敤SQL鎵归噺鏌ヨ鐢ㄦ埛淇℃伅
+        Map<Long, String> userIdToNameMap = allUserIds.isEmpty()
+                ? Collections.emptyMap()
+                : sysUserMapper.selectUsersByIds(new ArrayList<>(allUserIds))
+                .stream()
+                .collect(Collectors.toMap(
+                        SysUser::getUserId,
+                        SysUser::getNickName,
+                        (existing, replacement) -> existing));
+
+        //澶勭悊闄勪欢
         Map<Long, List<StorageAttachment>> attachmentsMap = storageAttachmentMapper.selectList(new LambdaQueryWrapper<StorageAttachment>().in(StorageAttachment::getRecordId, ids)
                         .eq(StorageAttachment::getRecordType, InspectionTasks.ordinal()))
                 .stream()
@@ -82,6 +126,27 @@
         List<InspectionTaskDto> dtoList = entityPage.getRecords().stream().map(inspectionTask -> {
             InspectionTaskDto dto = new InspectionTaskDto();
             BeanUtils.copyProperties(inspectionTask, dto);  // 澶嶅埗涓诲璞″睘鎬�
+
+            // 璁剧疆鐧昏浜�
+            SysUser sysUser = sysUserMap.get(inspectionTask.getRegistrantId());
+            if (sysUser != null) {
+                dto.setRegistrant(sysUser.getNickName());
+            }
+            // 澶勭悊宸℃浜哄悕绉�
+            if (StringUtils.isNotBlank(inspectionTask.getInspectorId())) {
+                String inspectorNames = Arrays.stream(inspectionTask.getInspectorId().split(","))
+                        .map(String::trim)
+                        .map(idStr -> {
+                            try {
+                                Long userId = Long.parseLong(idStr);
+                                return userIdToNameMap.getOrDefault(userId, "鏈煡鐢ㄦ埛(" + idStr + ")");
+                            } catch (NumberFormatException e) {
+                                return "鏃犳晥ID(" + idStr + ")";
+                            }
+                        })
+                        .collect(Collectors.joining(","));
+                dto.setInspector(inspectorNames);
+            }
 
             // 鍒濆鍖栦笁涓檮浠跺垪琛�
             dto.setBeforeProduction(new ArrayList<>());
@@ -149,7 +214,6 @@
 
     @Override
     public int addOrEditInspectionTask(InspectionTaskDto inspectionTaskDto) {
-        SecurityUtils.getLoginUser().getUserId();
         InspectionTask inspectionTask = new InspectionTask();
         BeanUtils.copyProperties(inspectionTaskDto, inspectionTask);
         inspectionTask.setRegistrantId(SecurityUtils.getLoginUser().getUserId());
@@ -184,6 +248,6 @@
         if (ids == null || ids.length == 0) {
             return 0;
         }
-      return inspectionTaskMapper.deleteByIds(Arrays.asList(ids));
+        return inspectionTaskMapper.deleteByIds(Arrays.asList(ids));
     }
 }
diff --git a/main-business/src/main/java/com/ruoyi/business/service/impl/ProductionMasterServiceImpl.java b/main-business/src/main/java/com/ruoyi/business/service/impl/ProductionMasterServiceImpl.java
index c92da97..4157611 100644
--- a/main-business/src/main/java/com/ruoyi/business/service/impl/ProductionMasterServiceImpl.java
+++ b/main-business/src/main/java/com/ruoyi/business/service/impl/ProductionMasterServiceImpl.java
@@ -5,12 +5,14 @@
 import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.ruoyi.basic.entity.CoalInfo;
 import com.ruoyi.basic.mapper.CoalInfoMapper;
 import com.ruoyi.business.dto.ProductionMasterDto;
 import com.ruoyi.business.entity.*;
 import com.ruoyi.business.mapper.*;
 import com.ruoyi.business.service.ProductionMasterService;
 import com.ruoyi.common.exception.base.BaseException;
+import com.ruoyi.common.utils.StringUtils;
 import com.ruoyi.common.utils.bean.BeanUtils;
 import lombok.RequiredArgsConstructor;
 import org.springframework.stereotype.Service;
@@ -49,11 +51,32 @@
     public IPage<ProductionMasterDto> selectPMList(Page page, ProductionMasterDto productionMasterDto) {
         // 1. 鏋勫缓涓昏〃鏌ヨ鏉′欢
         LambdaQueryWrapper<ProductionMaster> masterQueryWrapper = new LambdaQueryWrapper<>();
+        String keyword = productionMasterDto.getSearchAll();
+        if (StringUtils.isNotBlank(keyword)) {
+            // 鏌ヨ鐓ょ鍚嶇О涓ā绯婂尮閰嶇殑coalId鍒楄〃
+            List<Long> matchedCoalIds = coalInfoMapper.selectList(
+                            new LambdaQueryWrapper<CoalInfo>().like(CoalInfo::getCoal, keyword)
+                    ).stream()
+                    .map(CoalInfo::getId)
+                    .toList();
 
+            // 缁勮鏌ヨ鏉′欢锛氱叅绉岻D鍦ㄥ尮閰嶇殑鍒楄〃涓�
+            // 濡傛灉 matchedCoalIds 涓虹┖锛岀洿鎺ヨ繑鍥� 0 鏉℃暟鎹紙鏋勯�犱竴涓笉鍙兘鎴愮珛鐨勬潯浠讹級
+            if (matchedCoalIds.isEmpty()) {
+                masterQueryWrapper.apply("1 = 0"); // 寮哄埗杩斿洖绌虹粨鏋�
+            }
+            // 濡傛灉鏈夊尮閰嶇殑 coalId锛屽垯鎸� coalId 鏌ヨ
+            else {
+                String ids = matchedCoalIds.stream()
+                        .map(String::valueOf)
+                        .collect(Collectors.joining(","));
 
-
-
-
+                masterQueryWrapper.apply(
+                        "{0} = ANY(string_to_array(coal_id, ','))",
+                        ids
+                );
+            }
+        }
 
         // 2. 鎵ц涓昏〃鍒嗛〉鏌ヨ
         IPage<ProductionMaster> entityPage = productionMasterMapper.selectPage(page, masterQueryWrapper);
diff --git a/main-business/src/main/java/com/ruoyi/business/service/impl/PurchaseRegistrationServiceImpl.java b/main-business/src/main/java/com/ruoyi/business/service/impl/PurchaseRegistrationServiceImpl.java
index ad63a6c..bbae14c 100644
--- a/main-business/src/main/java/com/ruoyi/business/service/impl/PurchaseRegistrationServiceImpl.java
+++ b/main-business/src/main/java/com/ruoyi/business/service/impl/PurchaseRegistrationServiceImpl.java
@@ -62,7 +62,7 @@
                     .map(CoalInfo::getId)
                     .collect(Collectors.toList());
 
-            // 缁勮鏌ヨ鏉′欢锛氱叅绉岻D鍦ㄥ尮閰嶇殑鍒楄〃涓� 鎴� 渚涘簲鍟嗗悕绉板尮閰�
+            // 缁勮鏌ヨ鏉′欢锛氱叅绉岻D鍦ㄥ尮閰嶇殑鍒楄〃涓�
             queryWrapper.and(w -> {
                 if (!matchedCoalIds.isEmpty()) {
                     w.in(PurchaseRegistration::getCoalId, matchedCoalIds).or();
diff --git a/main-business/src/main/java/com/ruoyi/business/service/impl/TimingTaskScheduler.java b/main-business/src/main/java/com/ruoyi/business/service/impl/TimingTaskScheduler.java
new file mode 100644
index 0000000..9927845
--- /dev/null
+++ b/main-business/src/main/java/com/ruoyi/business/service/impl/TimingTaskScheduler.java
@@ -0,0 +1,238 @@
+package com.ruoyi.business.service.impl;
+
+import com.ruoyi.business.entity.TimingTask;
+import com.ruoyi.business.task.TimingTaskJob;
+import org.quartz.*;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.time.DayOfWeek;
+import java.time.LocalTime;
+import java.time.ZoneId;
+import java.time.format.DateTimeParseException;
+import java.util.Arrays;
+import java.util.Date;
+import java.util.HashSet;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+@Service
+public class TimingTaskScheduler {
+
+    @Autowired
+    private Scheduler scheduler;
+
+    /**
+     * 娣诲姞鏂颁换鍔″埌璋冨害鍣�
+     */
+    public void scheduleTimingTask(TimingTask task) throws SchedulerException {
+        JobDetail jobDetail = buildJobDetail(task);
+        Trigger trigger = buildJobTrigger(task, jobDetail);
+        scheduler.scheduleJob(jobDetail, trigger);
+    }
+
+    /**
+     * 鏇存柊宸叉湁浠诲姟
+     */
+    public void rescheduleTimingTask(TimingTask task) throws SchedulerException {
+        TriggerKey triggerKey = new TriggerKey("trigger_" + task.getId());
+
+        // 鑾峰彇鐜版湁瑙﹀彂鍣ㄥ苟杞崲涓� CronTrigger
+        Trigger oldTrigger = scheduler.getTrigger(triggerKey);
+        if (!(oldTrigger instanceof CronTrigger)) {
+            throw new SchedulerException("Existing trigger is not a CronTrigger");
+        }
+
+        // 鏋勫缓鏂拌Е鍙戝櫒
+        Trigger newTrigger = TriggerBuilder.newTrigger()
+                .withIdentity(triggerKey)
+                .withDescription(task.getTaskName())
+                .withSchedule(CronScheduleBuilder.cronSchedule(convertToCronExpression(task)))
+                .startAt(Date.from(task.getNexExecutionTime().atZone(ZoneId.systemDefault()).toInstant()))
+                .forJob(oldTrigger.getJobKey())
+                .build();
+
+        scheduler.rescheduleJob(triggerKey, newTrigger);
+    }
+
+    /**
+     * 鏆傚仠浠诲姟
+     */
+    public void pauseTimingTask(Long taskId) throws SchedulerException {
+        JobKey jobKey = new JobKey("timingTask_" + taskId);
+        scheduler.pauseJob(jobKey);
+    }
+
+    /**
+     * 鎭㈠浠诲姟
+     */
+    public void resumeTimingTask(Long taskId) throws SchedulerException {
+        JobKey jobKey = new JobKey("timingTask_" + taskId);
+        scheduler.resumeJob(jobKey);
+    }
+
+    /**
+     * 鍒犻櫎浠诲姟
+     */
+    public void unscheduleTimingTask(Long taskId) throws SchedulerException {
+        JobKey jobKey = new JobKey("timingTask_" + taskId);
+        scheduler.deleteJob(jobKey);
+    }
+
+    private JobDetail buildJobDetail(TimingTask task) {
+        JobDataMap jobDataMap = new JobDataMap();
+        jobDataMap.put("taskId", task.getId());
+
+        return JobBuilder.newJob(TimingTaskJob.class)
+                .withIdentity("timingTask_" + task.getId())
+                .withDescription(task.getTaskName())
+                .usingJobData(jobDataMap)
+                .storeDurably()
+                .build();
+    }
+
+    private Trigger buildJobTrigger(TimingTask task, JobDetail jobDetail) {
+        String cronExpression = convertToCronExpression(task);
+
+            TriggerBuilder<CronTrigger> triggerBuilder = TriggerBuilder.newTrigger()
+                .withIdentity("trigger_" + task.getId())
+                .withDescription(task.getTaskName())
+                .withSchedule(CronScheduleBuilder.cronSchedule(cronExpression));
+
+        if (jobDetail != null) {
+            triggerBuilder.forJob(jobDetail);
+        }
+
+        if (task.getNexExecutionTime() != null) {
+            triggerBuilder.startAt(Date.from(task.getNexExecutionTime().atZone(ZoneId.systemDefault()).toInstant()));
+        }
+
+        return triggerBuilder.build();
+    }
+
+    private String convertToCronExpression(TimingTask task) {
+        // 鍙傛暟鏍¢獙
+        if (task == null || task.getFrequencyType() == null || task.getFrequencyDetail() == null) {
+            throw new IllegalArgumentException("浠诲姟鍙傛暟涓嶈兘涓虹┖");
+        }
+
+        // 浣跨敤switch纭繚鏉′欢浜掓枼
+        return switch (task.getFrequencyType().toUpperCase()) { // 缁熶竴杞负澶у啓姣旇緝
+            case "DAILY" -> convertDailyToCron(task.getFrequencyDetail());
+            case "WEEKLY" -> convertWeeklyToCron(task.getFrequencyDetail());
+            case "MONTHLY" -> convertMonthlyToCron(task.getFrequencyDetail());
+            case "QUARTERLY" -> convertQuarterlyToCron(task.getFrequencyDetail());
+            default -> throw new IllegalArgumentException("涓嶆敮鎸佺殑棰戠巼绫诲瀷: " + task.getFrequencyType());
+        };
+    }
+
+    // 姣忔棩浠诲姟杞崲
+    private String convertDailyToCron(String frequencyDetail) {
+        LocalTime time = parseTime(frequencyDetail);
+        return String.format("0 %d %d * * ?", time.getMinute(), time.getHour());
+    }
+
+    // 姣忓懆浠诲姟杞崲
+    private String convertWeeklyToCron(String frequencyDetail) {
+        String[] parts = validateAndSplit(frequencyDetail, ",", 2);
+        String daysOfWeek = convertDayNamesToCron(parts[0]);
+        LocalTime time = parseTime(parts[1]);
+        return String.format("0 %d %d ? * %s", time.getMinute(), time.getHour(), daysOfWeek);
+    }
+
+    // 姣忔湀浠诲姟杞崲
+    private String convertMonthlyToCron(String frequencyDetail) {
+        String[] parts = validateAndSplit(frequencyDetail, ",", 2);
+        int day = validateDayOfMonth(parts[0]);
+        LocalTime time = parseTime(parts[1]);
+        return String.format("0 %d %d %d * ?", time.getMinute(), time.getHour(), day);
+    }
+
+    // 姣忓搴︿换鍔¤浆鎹�
+    private String convertQuarterlyToCron(String frequencyDetail) {
+        String[] parts = validateAndSplit(frequencyDetail, ",", 3);
+        int month = validateMonth(parts[0]);  // 楠岃瘉鏈堜唤(1-12)
+        int day = validateDayOfMonth(parts[1]);  // 楠岃瘉鏃ユ湡
+        LocalTime time = parseTime(parts[2]);  // 瑙f瀽鏃堕棿
+
+        // 璁$畻瀛e害璧峰鏈堜唤(1鏈�=1, 4鏈�=4, 7鏈�=7, 10鏈�=10)
+        int quarterStartMonth = ((month - 1) / 3) * 3 + 1;
+
+        return String.format("0 %d %d %d %d/3 ?",
+                time.getMinute(),
+                time.getHour(),
+                day,
+                quarterStartMonth);
+    }
+
+    // 鏂板楠岃瘉鏈堜唤鐨勬柟娉�(1-12)
+    private int validateMonth(String monthStr) {
+        try {
+            int month = Integer.parseInt(monthStr);
+            if (month < 1 || month > 12) {
+                throw new IllegalArgumentException("鏈堜唤蹇呴』鍦�1-12涔嬮棿");
+            }
+            return month;
+        } catch (NumberFormatException e) {
+            throw new IllegalArgumentException("鏃犳晥鐨勬湀浠芥牸寮�");
+        }
+    }
+
+    // 杈呭姪鏂规硶锛氳В鏋愭椂闂�
+    private LocalTime parseTime(String timeStr) {
+        try {
+            return LocalTime.parse(timeStr);
+        } catch (DateTimeParseException e) {
+            throw new IllegalArgumentException("鏃堕棿鏍煎紡蹇呴』涓篐H:mm", e);
+        }
+    }
+
+    // 杈呭姪鏂规硶锛氶獙璇佸苟鍒嗗壊瀛楃涓�
+    private String[] validateAndSplit(String input, String delimiter, int expectedParts) {
+        String[] parts = input.split(delimiter);
+        if (parts.length != expectedParts) {
+            throw new IllegalArgumentException(
+                    String.format("鏍煎紡閿欒锛屽簲涓�%d閮ㄥ垎鐢�'%s'鍒嗛殧", expectedParts, delimiter));
+        }
+        return parts;
+    }
+
+    // 杈呭姪鏂规硶锛氶獙璇佹湀浠戒腑鐨勬棩
+    private int validateDayOfMonth(String dayStr) {
+        int day = Integer.parseInt(dayStr);
+        if (day < 1 || day > 31) {
+            throw new IllegalArgumentException("鏃ユ湡蹇呴』鍦�1-31涔嬮棿");
+        }
+        return day;
+    }
+
+    // 杈呭姪鏂规硶锛氶獙璇佸搴︿腑鐨勬湀
+    private int validateMonthInQuarter(String monthStr) {
+        int month = Integer.parseInt(monthStr);
+        if (month < 1 || month > 3) {
+            throw new IllegalArgumentException("瀛e害鏈堜唤蹇呴』鏄�1銆�2鎴�3");
+        }
+        return month;
+    }
+
+    // 杞崲鏄熸湡鍑犲悕绉�
+    private String convertDayNamesToCron(String dayNames) {
+        return Arrays.stream(dayNames.split("\\|"))
+                .map(this::convertSingleDayName)
+                .collect(Collectors.joining(","));
+    }
+
+    // 杞崲鍗曚釜鏄熸湡鍑犲悕绉�
+    private String convertSingleDayName(String dayName) {
+        switch (dayName.toUpperCase()) {
+            case "MON": return "MON";
+            case "TUE": return "TUE";
+            case "WED": return "WED";
+            case "THU": return "THU";
+            case "FRI": return "FRI";
+            case "SAT": return "SAT";
+            case "SUN": return "SUN";
+            default: throw new IllegalArgumentException("鏃犳晥鐨勬槦鏈熷嚑: " + dayName);
+        }
+    }
+}
diff --git a/main-business/src/main/java/com/ruoyi/business/service/impl/TimingTaskServiceImpl.java b/main-business/src/main/java/com/ruoyi/business/service/impl/TimingTaskServiceImpl.java
new file mode 100644
index 0000000..fe1d77e
--- /dev/null
+++ b/main-business/src/main/java/com/ruoyi/business/service/impl/TimingTaskServiceImpl.java
@@ -0,0 +1,405 @@
+package com.ruoyi.business.service.impl;
+
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.ruoyi.business.dto.TimingTaskDto;
+import com.ruoyi.business.entity.TimingTask;
+import com.ruoyi.business.mapper.InspectionTaskMapper;
+import com.ruoyi.business.mapper.TimingTaskMapper;
+import com.ruoyi.business.service.TimingTaskService;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.ruoyi.common.core.domain.entity.SysUser;
+import com.ruoyi.common.utils.StringUtils;
+import com.ruoyi.common.utils.bean.BeanUtils;
+import com.ruoyi.system.mapper.SysUserMapper;
+import lombok.extern.slf4j.Slf4j;
+import org.quartz.SchedulerException;
+import org.springframework.stereotype.Service;
+import lombok.RequiredArgsConstructor;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.time.*;
+import java.util.*;
+import java.util.stream.Collectors;
+
+/**
+ * <p>
+ * 瀹氭椂宸℃浠诲姟琛� 鏈嶅姟瀹炵幇绫�
+ * </p>
+ *
+ * @author ld
+ * @since 2025-06-30
+ */
+@Service
+@Slf4j
+@RequiredArgsConstructor
+public class TimingTaskServiceImpl extends ServiceImpl<TimingTaskMapper, TimingTask> implements TimingTaskService {
+
+    private final TimingTaskMapper timingTaskMapper;
+
+    private final InspectionTaskMapper inspectionTaskMapper;
+
+    private  final TimingTaskScheduler timingTaskScheduler;
+
+    private  final SysUserMapper sysUserMapper;
+
+
+    @Override
+    public IPage<TimingTaskDto> selectTimingTaskList(Page<TimingTask> page, TimingTask timingTask) {
+        // 1. 鍏堝垎椤垫煡璇㈠畾鏃朵换鍔℃暟鎹�
+        IPage<TimingTask> taskPage = timingTaskMapper.selectPage(page, null);
+
+        // 2. 濡傛灉娌℃湁鏁版嵁锛岀洿鎺ヨ繑鍥炵┖鍒嗛〉
+        if (taskPage.getRecords().isEmpty()) {
+            return new Page<>(taskPage.getCurrent(), taskPage.getSize(), taskPage.getTotal());
+        }
+
+        // 3. 鏀堕泦鎵�鏈夐渶瑕佹煡璇㈢殑鐢ㄦ埛ID
+        Set<Long> userIds = new HashSet<>();
+
+        // 鏀堕泦鐧昏浜篒D
+        taskPage.getRecords().forEach(task -> {
+            if (task.getRegistrantId() != null) {
+                userIds.add(task.getRegistrantId());
+            }
+        });
+
+        // 鏀堕泦宸℃浜篒D锛堝涓狪D浠ラ�楀彿鍒嗛殧锛�
+        taskPage.getRecords().forEach(task -> {
+            if (StringUtils.isNotBlank(task.getInspectorIds())) {
+                Arrays.stream(task.getInspectorIds().split(","))
+                        .filter(StringUtils::isNotBlank)
+                        .map(Long::valueOf)
+                        .forEach(userIds::add);
+            }
+        });
+
+        // 4. 鎵归噺鏌ヨ鐢ㄦ埛淇℃伅
+        Map<Long, String> userNickNameMap = new HashMap<>();
+        if (!userIds.isEmpty()) {
+            List<SysUser> users = sysUserMapper.selectBatchIds(userIds);
+            users.forEach(user -> userNickNameMap.put(user.getUserId(), user.getNickName()));
+        }
+
+        // 5. 杞崲涓篋TO
+        List<TimingTaskDto> dtoList = taskPage.getRecords().stream().map(task -> {
+            TimingTaskDto dto = new TimingTaskDto();
+            // 澶嶅埗鍩烘湰灞炴��
+            BeanUtils.copyProperties(task, dto);
+
+            // 璁剧疆鐧昏浜烘樀绉�
+            if (task.getRegistrantId() != null) {
+                dto.setRegistrant(userNickNameMap.getOrDefault(task.getRegistrantId(), "鏈煡鐢ㄦ埛"));
+            }
+
+            // 璁剧疆宸℃浜烘樀绉板垪琛�
+            if (StringUtils.isNotBlank(task.getInspectorIds())) {
+                List<String> inspectorNickNames = Arrays.stream(task.getInspectorIds().split(","))
+                        .filter(StringUtils::isNotBlank)
+                        .map(idStr -> {
+                            Long id = Long.valueOf(idStr);
+                            return userNickNameMap.getOrDefault(id, "鏈煡鐢ㄦ埛");
+                        })
+                        .toList();
+                dto.setInspector(inspectorNickNames.toString());
+            }
+
+            return dto;
+        }).collect(Collectors.toList());
+
+        // 6. 鏋勫缓杩斿洖鐨勫垎椤靛璞�
+        Page<TimingTaskDto> resultPage = new Page<>(taskPage.getCurrent(), taskPage.getSize(), taskPage.getTotal());
+        resultPage.setRecords(dtoList);
+        return resultPage;
+    }
+
+    @Override
+    @Transactional
+    public int addOrEditTimingTask(TimingTaskDto timingTaskDto) throws SchedulerException {
+        TimingTask timingTask = new TimingTask();
+        BeanUtils.copyProperties(timingTaskDto, timingTask);
+
+        // 璁剧疆鍒涘缓浜轰俊鎭拰榛樿鍊�
+        if (Objects.isNull(timingTaskDto.getId())) {
+            timingTask.setRegistrationDate(LocalDate.now());
+            timingTask.setActive(true);
+
+            // 璁$畻棣栨鎵ц鏃堕棿
+            LocalDateTime firstExecutionTime = calculateFirstExecutionTime(timingTask);
+            timingTask.setNexExecutionTime(firstExecutionTime);
+
+            int result = timingTaskMapper.insert(timingTask);
+            if (result > 0) {
+                // 鏂板鎴愬姛鍚庢坊鍔犲埌璋冨害鍣�
+                timingTaskScheduler.scheduleTimingTask(timingTask);
+            }
+            return result;
+        } else {
+            int result = timingTaskMapper.updateById(timingTask);
+            if (result > 0) {
+                // 鏇存柊鎴愬姛鍚庨噸鏂拌皟搴︿换鍔�
+                timingTaskScheduler.rescheduleTimingTask(timingTask);
+            }
+            return result;
+        }
+    }
+
+    private LocalDateTime calculateFirstExecutionTime(TimingTask task) {
+        // 鏍规嵁棰戠巼绫诲瀷鍜岃鎯呰绠楅娆℃墽琛屾椂闂�
+        return switch (task.getFrequencyType()) {
+            case "DAILY" ->
+                // 濡傛灉鏄瘡澶╂墽琛岋紝璁$畻浠婂ぉ鎴栨槑澶╃殑鍏蜂綋鏃堕棿
+                    calculateDailyFirstExecution(task.getFrequencyDetail());
+            case "WEEKLY" ->
+                // 濡傛灉鏄瘡鍛ㄦ墽琛岋紝璁$畻涓嬪懆鐨勫叿浣撴槦鏈熷嚑
+                    calculateWeeklyFirstExecution(task.getFrequencyDetail());
+            case "MONTHLY" ->
+                // 濡傛灉鏄瘡鏈堟墽琛岋紝璁$畻涓嬩釜鏈堢殑鍏蜂綋鏃ユ湡
+                    calculateMonthlyFirstExecution(task.getFrequencyDetail());
+            case "QUARTERLY" ->
+                // 鑷畾涔夐鐜囷紝濡傛瘡灏忔椂銆佹瘡30鍒嗛挓绛�
+                    calculateCustomFirstExecution(task.getFrequencyDetail());
+            default -> throw new IllegalArgumentException("涓嶆敮鎸佺殑棰戠巼绫诲瀷: " + task.getFrequencyType());
+        };
+    }
+
+    private LocalDateTime calculateDailyFirstExecution(String frequencyDetail) {
+        // frequencyDetail鍙兘鏄叿浣撴椂闂达紝濡� "14:30"
+        LocalTime executionTime = LocalTime.parse(frequencyDetail);
+        LocalDateTime now = LocalDateTime.now();
+        LocalDateTime todayExecution = LocalDateTime.of(now.toLocalDate(), executionTime);
+
+        // 濡傛灉浠婂ぉ鐨勬椂闂村凡杩囷紝鍒欏畨鎺掓槑澶╂墽琛�
+        return now.isBefore(todayExecution) ? todayExecution : todayExecution.plusDays(1);
+    }
+
+    private LocalDateTime calculateWeeklyFirstExecution(String frequencyDetail) {
+        return null;
+    }
+
+    private LocalDateTime calculateMonthlyFirstExecution(String frequencyDetail) {
+        return null;
+    }
+
+    private LocalDateTime calculateCustomFirstExecution(String frequencyDetail) {
+        return null;
+    }
+
+    @Override
+    @Transactional
+    public void updateTaskExecutionTime(Long taskId) {
+        TimingTask task = timingTaskMapper.selectById(taskId);
+        if (task == null) {
+            throw new RuntimeException("瀹氭椂浠诲姟涓嶅瓨鍦紝ID: " + taskId);
+        }
+
+        // 鏇存柊鏈�鍚庢墽琛屾椂闂翠负褰撳墠鏃堕棿
+        task.setLastExecuteTime(LocalDateTime.now());
+
+        // 璁$畻涓嬫鎵ц鏃堕棿
+        LocalDateTime nextExecutionTime = calculateNextExecutionTime(
+                task.getFrequencyType(),
+                task.getFrequencyDetail(),
+                LocalDateTime.now()
+        );
+        task.setNexExecutionTime(nextExecutionTime);
+
+        // 鏇存柊鏁版嵁搴�
+        timingTaskMapper.updateById(task);
+    }
+
+    /**
+     * 璁$畻涓嬫鎵ц鏃堕棿
+     */
+    private LocalDateTime calculateNextExecutionTime(String frequencyType,
+                                                     String frequencyDetail,
+                                                     LocalDateTime currentTime) {
+        try {
+            return switch (frequencyType) {
+                case "DAILY" -> calculateDailyNextTime(frequencyDetail, currentTime);
+                case "WEEKLY" -> calculateWeeklyNextTime(frequencyDetail, currentTime);
+                case "MONTHLY" -> calculateMonthlyNextTime(frequencyDetail, currentTime);
+                case "QUARTERLY" -> calculateQuarterlyNextTime(frequencyDetail, currentTime);
+                default -> throw new IllegalArgumentException("涓嶆敮鎸佺殑棰戠巼绫诲瀷: " + frequencyType);
+            };
+        } catch (Exception e) {
+            throw new RuntimeException("璁$畻涓嬫鎵ц鏃堕棿澶辫触: " + e.getMessage(), e);
+        }
+    }
+
+    /**
+     * 璁$畻姣忔棩浠诲姟鐨勪笅娆℃墽琛屾椂闂�
+     */
+    private LocalDateTime calculateDailyNextTime(String timeStr, LocalDateTime current) {
+        LocalTime executionTime = LocalTime.parse(timeStr); // 瑙f瀽鏍煎紡 "HH:mm"
+        LocalDateTime nextTime = LocalDateTime.of(current.toLocalDate(), executionTime);
+
+        // 濡傛灉浠婂ぉ鐨勬椂闂村凡杩囷紝鍒欏畨鎺掓槑澶�
+        return current.isBefore(nextTime) ? nextTime : nextTime.plusDays(1);
+    }
+
+    /**
+     * 璁$畻姣忓懆浠诲姟鐨勪笅娆℃墽琛屾椂闂�
+     */
+    private LocalDateTime calculateWeeklyNextTime(String detail, LocalDateTime current) {
+        String[] parts = detail.split(",");
+        String dayOfWeekStr = parts[0];  // 濡� "MON" 鎴� "MON|WED|FRI"
+        LocalTime time = LocalTime.parse(parts[1]); // 鏃堕棿閮ㄥ垎
+
+        // 瑙f瀽鏄熸湡鍑�(鏀寔澶氫釜鏄熸湡)
+        Set<DayOfWeek> targetDays = parseDayOfWeeks(dayOfWeekStr);
+
+        // 浠庡綋鍓嶆椂闂村紑濮嬫壘涓嬩竴涓鍚堟潯浠剁殑鏄熸湡鍑�
+        LocalDateTime nextTime = current;
+        while (true) {
+            nextTime = nextTime.plusDays(1);
+            if (targetDays.contains(nextTime.getDayOfWeek())) {
+                return LocalDateTime.of(nextTime.toLocalDate(), time);
+            }
+
+            // 闃叉鏃犻檺寰幆(鐞嗚涓婁笉浼氬彂鐢�)
+            if (nextTime.isAfter(current.plusYears(1))) {
+                throw new RuntimeException("鏃犳硶鎵惧埌涓嬫鎵ц鏃堕棿");
+            }
+        }
+    }
+
+    /**
+     * 璁$畻姣忔湀浠诲姟鐨勪笅娆℃墽琛屾椂闂�
+     */
+    private LocalDateTime calculateMonthlyNextTime(String detail, LocalDateTime current) {
+        String[] parts = detail.split(",");
+        int dayOfMonth = Integer.parseInt(parts[0]);
+        LocalTime time = LocalTime.parse(parts[1]);
+
+        // 浠庝笅涓湀寮�濮嬭绠�
+        LocalDateTime nextTime = current.plusMonths(1)
+                .withDayOfMonth(Math.min(dayOfMonth, current.plusMonths(1).toLocalDate().lengthOfMonth()))
+                .with(time);
+
+        return nextTime;
+    }
+
+    /**
+     * 璁$畻姣忓搴︿换鍔$殑涓嬫鎵ц鏃堕棿
+     */
+    private LocalDateTime calculateQuarterlyNextTime(String detail, LocalDateTime current) {
+        String[] parts = detail.split(",");
+        int quarterMonth = Integer.parseInt(parts[0]); // 1=绗�1涓湀锛�2=绗�2涓湀锛�3=绗�3涓湀
+        int dayOfMonth = Integer.parseInt(parts[1]);
+        LocalTime time = LocalTime.parse(parts[2]);
+
+        // 璁$畻褰撳墠瀛e害
+        int currentQuarter = (current.getMonthValue() - 1) / 3 + 1;
+        int currentMonthInQuarter = (current.getMonthValue() - 1) % 3 + 1;
+
+        YearMonth targetYearMonth;
+        if (currentMonthInQuarter < quarterMonth) {
+            // 鏈搴﹀唴杩樻湁鎵ц鏈轰細
+            targetYearMonth = YearMonth.from(current)
+                    .plusMonths(quarterMonth - currentMonthInQuarter);
+        } else {
+            // 闇�瑕佸埌涓嬩釜瀛e害
+            targetYearMonth = YearMonth.from(current)
+                    .plusMonths(3 - currentMonthInQuarter + quarterMonth);
+        }
+
+        // 澶勭悊鏈堟湯鏃ユ湡
+        int adjustedDay = Math.min(dayOfMonth, targetYearMonth.lengthOfMonth());
+
+        return LocalDateTime.of(
+                targetYearMonth.getYear(),
+                targetYearMonth.getMonthValue(),
+                adjustedDay,
+                time.getHour(),
+                time.getMinute()
+        );
+    }
+
+    /**
+     * 瑙f瀽鏄熸湡鍑犲瓧绗︿覆
+     */
+    private Set<DayOfWeek> parseDayOfWeeks(String dayOfWeekStr) {
+        Set<DayOfWeek> days = new HashSet<>();
+        String[] dayStrs = dayOfWeekStr.split("\\|");
+
+        for (String dayStr : dayStrs) {
+            switch (dayStr) {
+                case "MON": days.add(DayOfWeek.MONDAY); break;
+                case "TUE": days.add(DayOfWeek.TUESDAY); break;
+                case "WED": days.add(DayOfWeek.WEDNESDAY); break;
+                case "THU": days.add(DayOfWeek.THURSDAY); break;
+                case "FRI": days.add(DayOfWeek.FRIDAY); break;
+                case "SAT": days.add(DayOfWeek.SATURDAY); break;
+                case "SUN": days.add(DayOfWeek.SUNDAY); break;
+                default: throw new IllegalArgumentException("鏃犳晥鐨勬槦鏈熷嚑: " + dayStr);
+            }
+        }
+
+        return days;
+    }
+
+//    /**
+//     * 姣忓ぉ17:40鍑嗘椂瑙﹀彂锛屾墽琛屽埌鏈熶换鍔�
+//     */
+//    @Scheduled(cron = "0 55 17 * * ?", zone = "Asia/Shanghai")
+//    @Transactional
+//    public void executeDueTasks() {
+//        LocalDateTime now = LocalDateTime.now();
+//        log.info("瀹氭椂浠诲姟瑙﹀彂锛屽綋鍓嶆椂闂�: {}", now);
+//
+//        // 1. 鏌ヨ鎵�鏈夐渶瑕佺珛鍗虫墽琛岀殑浠诲姟
+//        List<TimingTask> dueTasks = timingTaskMapper.selectActiveTasks(now);
+//
+//        // 2. 澶勭悊姣忎釜浠诲姟
+//        dueTasks.forEach(task -> {
+//            // 2.1 杞崲涓哄贰妫�浠诲姟骞朵繚瀛�
+//            InspectionTask inspectionTask = convertToInspectionTask(task);
+//            inspectionTaskMapper.insert(inspectionTask);
+//
+//            // 2.2 璁$畻骞舵洿鏂颁笅娆℃墽琛屾椂闂�
+//            updateNextExecutionTime(task, now);
+//
+//            log.info("浠诲姟[{}]宸叉墽琛岋紝涓嬫鎵ц鏃堕棿: {}",
+//                    task.getTaskName(),
+//                    task.getNexExecutionTime());
+//        });
+//    }
+//
+//    private InspectionTask  convertToInspectionTask(TimingTask timingTask) {
+//        InspectionTask inspectionTask = new InspectionTask();
+//
+//        // 澶嶅埗鍩烘湰灞炴��
+//        inspectionTask.setTaskName(timingTask.getTaskName());
+//        inspectionTask.setInspectorId(timingTask.getInspectorIds());
+//        inspectionTask.setPort(timingTask.getInspectionLocation());
+//        inspectionTask.setRemarks("鑷姩鐢熸垚鑷畾鏃朵换鍔D: " + timingTask.getId());
+//        inspectionTask.setRegistrantId(timingTask.getRegistrantId());
+//        inspectionTask.setFrequency(timingTask.getFrequencyType());
+//        return inspectionTask;
+//    }
+//
+//    private void updateNextExecutionTime(TimingTask task, LocalDateTime currentExecutionTime) {
+//        switch (task.getFrequencyType()) {
+//            case "DAILY":
+//                task.setNexExecutionTime(currentExecutionTime.plusDays(1));
+//                break;
+//            case "WEEKLY":
+//                task.setNexExecutionTime(currentExecutionTime.plusWeeks(1));
+//                break;
+//            case "MONTHLY":
+//                task.setNexExecutionTime(currentExecutionTime.plusMonths(1));
+//                break;
+//            default:
+//                task.setNexExecutionTime(null); // 鍗曟浠诲姟
+//        }
+//        timingTaskMapper.updateById(task);
+//    }
+
+
+
+    @Override
+    public int delByIds(Long[] ids) {
+        return timingTaskMapper.deleteByIds(Arrays.asList(ids));
+    }
+}
diff --git a/main-business/src/main/java/com/ruoyi/business/task/TimingTaskJob.java b/main-business/src/main/java/com/ruoyi/business/task/TimingTaskJob.java
new file mode 100644
index 0000000..bf4d1dc
--- /dev/null
+++ b/main-business/src/main/java/com/ruoyi/business/task/TimingTaskJob.java
@@ -0,0 +1,66 @@
+package com.ruoyi.business.task;
+
+import com.ruoyi.business.entity.InspectionTask;
+import com.ruoyi.business.entity.TimingTask;
+import com.ruoyi.business.mapper.InspectionTaskMapper;
+import com.ruoyi.business.service.TimingTaskService;
+import org.quartz.*;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+import java.time.LocalDateTime;
+
+@Component
+@DisallowConcurrentExecution // 绂佹骞跺彂鎵ц鍚屼竴涓狫ob
+public class TimingTaskJob implements Job {
+
+    @Autowired
+    private
+    TimingTaskService timingTaskService;
+
+    @Autowired
+    private InspectionTaskMapper inspectionTaskMapper;
+
+    @Override
+    public void execute(JobExecutionContext context) throws JobExecutionException {
+        JobDataMap jobDataMap = context.getJobDetail().getJobDataMap();
+        Long taskId = jobDataMap.getLong("taskId");
+
+        try {
+            // 1. 鑾峰彇瀹氭椂浠诲姟璇︽儏
+            TimingTask timingTask = timingTaskService.getById(taskId);
+            if (timingTask == null || !timingTask.isActive()) {
+                return;
+            }
+
+            // 2. 鍒涘缓骞朵繚瀛樺贰妫�浠诲姟璁板綍 - 杩欏氨鏄偍鎻愪緵鐨勪唬鐮佸簲璇ユ斁鐨勪綅缃�
+            InspectionTask inspectionTask = createInspectionTask(timingTask);
+            inspectionTaskMapper.insert(inspectionTask);
+
+            // 3. 鏇存柊瀹氭椂浠诲姟鐨勬墽琛屾椂闂�
+            timingTaskService.updateTaskExecutionTime(taskId);
+
+            // 4. 璁板綍鎵ц鏃ュ織
+//            timingTaskService.recordExecutionLog(taskId, true, "浠诲姟鎵ц鎴愬姛锛岀敓鎴愬贰妫�浠诲姟ID: " + inspectionTask.getId());
+
+        } catch (Exception e) {
+//            timingTaskService.recordExecutionLog(taskId, false, "浠诲姟鎵ц澶辫触: " + e.getMessage());
+            throw new JobExecutionException(e);
+        }
+    }
+
+    // 杩欏氨鏄偍鎻愪緵鐨勪唬鐮佸皝瑁呮垚鐨勬柟娉�
+    private InspectionTask createInspectionTask(TimingTask timingTask) {
+        InspectionTask inspectionTask = new InspectionTask();
+
+        // 澶嶅埗鍩烘湰灞炴��
+        inspectionTask.setTaskName(timingTask.getTaskName());
+        inspectionTask.setInspectorId(timingTask.getInspectorIds());
+        inspectionTask.setInspectionLocation(timingTask.getInspectionLocation());
+        inspectionTask.setRemarks("鑷姩鐢熸垚鑷畾鏃朵换鍔D: " + timingTask.getId());
+        inspectionTask.setRegistrantId(timingTask.getRegistrantId());
+        inspectionTask.setFrequencyType(timingTask.getFrequencyType());
+
+        return inspectionTask;
+    }
+}
diff --git a/main-business/src/main/resources/db/migration/postgresql/V20250614134700__create_table_inspection_task.sql b/main-business/src/main/resources/db/migration/postgresql/V20250614134700__create_table_inspection_task.sql
index d469e66..68aab45 100644
--- a/main-business/src/main/resources/db/migration/postgresql/V20250614134700__create_table_inspection_task.sql
+++ b/main-business/src/main/resources/db/migration/postgresql/V20250614134700__create_table_inspection_task.sql
@@ -9,6 +9,7 @@
     remarks       TEXT,                        -- 澶囨敞璇存槑
     registrant_id BIGINT,                      -- 鐧昏浜哄憳id
     registrant    VARCHAR(100),                -- 鐧昏浜哄憳
+    frequency     VARCHAR(100),                -- 棰戞
 
     deleted       INT NOT NULL DEFAULT 0,      -- 杞垹闄ゆ爣蹇楋細0=鏈垹闄わ紝1=宸插垹闄�
     create_by     VARCHAR(255),                -- 鍒涘缓浜虹敤鎴峰悕
@@ -17,18 +18,30 @@
     update_time   TIMESTAMP WITHOUT TIME ZONE  -- 鏈�鍚庢洿鏂版椂闂达紝榛樿褰撳墠鏃堕棿
 );
 -- 娣诲姞琛ㄦ敞閲�
-COMMENT ON TABLE inspection_task IS '宸℃浠诲姟琛�';
+COMMENT
+ON TABLE inspection_task IS '宸℃浠诲姟琛�';
 
 -- 娣诲姞瀛楁娉ㄩ噴
-COMMENT ON COLUMN inspection_task.id IS '宸℃浠诲姟鍞竴鏍囪瘑';
-COMMENT ON COLUMN inspection_task.task_name IS '宸℃浠诲姟鍚嶇О';
-COMMENT ON COLUMN inspection_task.inspector IS '鎵ц宸℃鐨勪汉鍛樺鍚�';
-COMMENT ON COLUMN inspection_task.port IS '宸℃鍦扮偣璇︾粏鎻忚堪';
-COMMENT ON COLUMN inspection_task.remarks IS '浠诲姟闄勫姞璇存槑鎴栫壒娈婃儏鍐佃褰�';
-COMMENT ON COLUMN inspection_task.registrant IS '浠诲姟鐧昏浜哄鍚�';
+COMMENT
+ON COLUMN inspection_task.id IS '宸℃浠诲姟鍞竴鏍囪瘑';
+COMMENT
+ON COLUMN inspection_task.task_name IS '宸℃浠诲姟鍚嶇О';
+COMMENT
+ON COLUMN inspection_task.inspector IS '鎵ц宸℃鐨勪汉鍛樺鍚�';
+COMMENT
+ON COLUMN inspection_task.port IS '宸℃鍦扮偣璇︾粏鎻忚堪';
+COMMENT
+ON COLUMN inspection_task.remarks IS '浠诲姟闄勫姞璇存槑鎴栫壒娈婃儏鍐佃褰�';
+COMMENT
+ON COLUMN inspection_task.registrant IS '浠诲姟鐧昏浜哄鍚�';
 
-COMMENT ON COLUMN inspection_task.deleted IS '杞垹闄ゆ爣蹇楋紝0=鏈垹闄わ紝1=宸插垹闄�';
-COMMENT ON COLUMN inspection_task.create_by IS '鍒涘缓璇ヨ褰曠殑鐢ㄦ埛';
-COMMENT ON COLUMN inspection_task.create_time IS '璁板綍鍒涘缓鏃堕棿';
-COMMENT ON COLUMN inspection_task.update_by IS '鏈�鍚庝慨鏀硅璁板綍鐨勭敤鎴�';
-COMMENT ON COLUMN inspection_task.update_time IS '璁板綍鏈�鍚庢洿鏂版椂闂�';
\ No newline at end of file
+COMMENT
+ON COLUMN inspection_task.deleted IS '杞垹闄ゆ爣蹇楋紝0=鏈垹闄わ紝1=宸插垹闄�';
+COMMENT
+ON COLUMN inspection_task.create_by IS '鍒涘缓璇ヨ褰曠殑鐢ㄦ埛';
+COMMENT
+ON COLUMN inspection_task.create_time IS '璁板綍鍒涘缓鏃堕棿';
+COMMENT
+ON COLUMN inspection_task.update_by IS '鏈�鍚庝慨鏀硅璁板綍鐨勭敤鎴�';
+COMMENT
+ON COLUMN inspection_task.update_time IS '璁板綍鏈�鍚庢洿鏂版椂闂�';
\ No newline at end of file
diff --git a/main-business/src/main/resources/db/migration/postgresql/V20250630153900__create_table_timing_task.sql b/main-business/src/main/resources/db/migration/postgresql/V20250630153900__create_table_timing_task.sql
new file mode 100644
index 0000000..d5c2107
--- /dev/null
+++ b/main-business/src/main/resources/db/migration/postgresql/V20250630153900__create_table_timing_task.sql
@@ -0,0 +1,63 @@
+CREATE TABLE timing_task
+(
+    id                  BIGSERIAL PRIMARY KEY,              -- 涓婚敭ID锛岃嚜鍔ㄩ�掑
+    task_name           VARCHAR(255) NOT NULL,              -- 浠诲姟鍚嶇О锛屼笉鍏佽涓虹┖
+    inspector_ids       VARCHAR(255) NOT NULL,              -- 宸℃浜篿ds锛屼笉鍏佽涓虹┖
+    inspection_location VARCHAR(255) NOT NULL,              -- 宸℃鍦扮偣锛屼笉鍏佽涓虹┖
+    -- 瀹氭椂閰嶇疆
+    frequency_type      VARCHAR(20)  NOT NULL CHECK (frequency_type IN ('DAILY', 'WEEKLY', 'MONTHLY', 'QUARTERLY')),
+    frequency_detail    VARCHAR(100),                       -- 鍏蜂綋鏃堕棿閰嶇疆
+
+    -- 姣忔棩浠诲姟閰嶇疆绀轰緥锛歠requency_type='DAILY', frequency_detail='14:30'
+    -- 姣忓懆浠诲姟閰嶇疆绀轰緥锛歠requency_type='WEEKLY', frequency_detail='MON;14:30'
+    -- 姣忔湀浠诲姟閰嶇疆绀轰緥锛歠requency_type='MONTHLY', frequency_detail='15;14:30' (姣忔湀15鏃�14:30)
+    -- 姣忓搴︿换鍔¢厤缃ず渚嬶細frequency_type='QUARTERLY', frequency_detail='15;14:30' (姣忓搴︾涓�涓湀15鏃�14:30)
+
+    next_execution_time TIMESTAMP,                          -- 涓嬫鎵ц鏃堕棿
+    last_execution_time TIMESTAMP,                          -- 鏈�鍚庢墽琛屾椂闂�
+    is_active           BOOLEAN               DEFAULT TRUE, -- 鏄惁婵�娲�
+    remarks             TEXT,                               -- 澶囨敞
+    registrant_id       BIGINT,                             -- 鐧昏浜篿d锛屼笉鍏佽涓虹┖
+    registrant          VARCHAR(255) NOT NULL,              -- 鐧昏浜猴紝涓嶅厑璁镐负绌�
+    registration_date   DATE         NOT NULL,              -- 鐧昏鏃ユ湡锛屼笉鍏佽涓虹┖
+
+    deleted             INT          NOT NULL DEFAULT 0,    -- 杞垹闄ゆ爣蹇楋細0=鏈垹闄わ紝1=宸插垹闄�
+    create_by           VARCHAR(255),                       -- 鍒涘缓浜虹敤鎴峰悕
+    create_time         TIMESTAMP WITHOUT TIME ZONE,        -- 鍒涘缓鏃堕棿锛岄粯璁ゅ綋鍓嶆椂闂�
+    update_by           VARCHAR(255),                       -- 鏈�鍚庢洿鏂颁汉鐢ㄦ埛鍚�
+    update_time         TIMESTAMP WITHOUT TIME ZONE         -- 鏈�鍚庢洿鏂版椂闂达紝榛樿褰撳墠鏃堕棿
+);
+
+-- 涓鸿〃娣诲姞娉ㄩ噴
+COMMENT
+ON TABLE timing_task IS '瀹氭椂宸℃浠诲姟琛�';
+
+-- 涓哄瓧娈垫坊鍔犳敞閲�
+COMMENT
+ON COLUMN timing_task.id IS '涓婚敭ID';
+COMMENT
+ON COLUMN timing_task.task_name IS '浠诲姟鍚嶇О';
+COMMENT
+ON COLUMN timing_task.inspector_ids IS '宸℃浜�';
+COMMENT
+ON COLUMN timing_task.inspection_location IS '宸℃鍦扮偣';
+COMMENT
+ON COLUMN timing_task.frequency IS '棰戞';
+COMMENT
+ON COLUMN timing_task.remarks IS '澶囨敞';
+COMMENT
+ON COLUMN timing_task.registrant_id IS '鐧昏浜篿d';
+COMMENT
+ON COLUMN timing_task.registrant IS '鐧昏浜�';
+COMMENT
+ON COLUMN timing_task.registration_date IS '鐧昏鏃ユ湡';
+COMMENT
+ON COLUMN timing_task.deleted IS '杞垹闄ゆ爣蹇楋紝0=鏈垹闄わ紝1=宸插垹闄�';
+COMMENT
+ON COLUMN timing_task.create_by IS '鍒涘缓璇ヨ褰曠殑鐢ㄦ埛';
+COMMENT
+ON COLUMN timing_task.create_time IS '璁板綍鍒涘缓鏃堕棿';
+COMMENT
+ON COLUMN timing_task.update_by IS '鏈�鍚庝慨鏀硅璁板綍鐨勭敤鎴�';
+COMMENT
+ON COLUMN timing_task.update_time IS '璁板綍鏈�鍚庢洿鏂版椂闂�';
\ No newline at end of file
diff --git a/main-business/src/main/resources/db/migration/postgresql/V20250701142700__create_table_equipment_management.sql b/main-business/src/main/resources/db/migration/postgresql/V20250701142700__create_table_equipment_management.sql
new file mode 100644
index 0000000..0abb2b1
--- /dev/null
+++ b/main-business/src/main/resources/db/migration/postgresql/V20250701142700__create_table_equipment_management.sql
@@ -0,0 +1,59 @@
+DROP TABLE IF EXISTS equipment_management;
+-- 鍒涘缓璁惧绠$悊琛�
+CREATE TABLE equipment_management
+(
+    id               BIGSERIAL PRIMARY KEY,           -- 涓婚敭 ID
+    equipment_id     VARCHAR(50)  NOT NULL,           -- 璁惧缂栧彿
+    equipment_name   VARCHAR(100) NOT NULL,           -- 璁惧鍚嶇О
+    quantity         INT          NOT NULL DEFAULT 0, -- 鏁伴噺
+    specification    VARCHAR(50)  NOT NULL,           -- 瑙勬牸鍨嬪彿
+    usage_status     VARCHAR(20)  NOT NULL,           -- 浣跨敤鐘舵��
+    using_department VARCHAR(50)  NOT NULL,           -- 浣跨敤閮ㄩ棬
+    user_id          BIGINT,                          -- 浣跨敤浜�
+    storage_location VARCHAR(100) NOT NULL,           -- 瀛樻斁浣嶇疆
+    purchase_date    DATE,                            -- 閲囪喘鏃ユ湡
+    purchase_price   DECIMAL(10, 2),                  -- 閲囪喘浠锋牸
+
+    deleted          INT          NOT NULL DEFAULT 0, -- 杞垹闄ゆ爣蹇楋細0=鏈垹闄わ紝1=宸插垹闄�
+    create_by        VARCHAR(255),                    -- 鍒涘缓浜虹敤鎴峰悕
+    create_time      TIMESTAMP WITHOUT TIME ZONE,     -- 鍒涘缓鏃堕棿锛岄粯璁ゅ綋鍓嶆椂闂�
+    update_by        VARCHAR(255),                    -- 鏈�鍚庢洿鏂颁汉鐢ㄦ埛鍚�
+    update_time      TIMESTAMP WITHOUT TIME ZONE      -- 鏈�鍚庢洿鏂版椂闂达紝榛樿褰撳墠鏃堕棿
+);
+-- 娣诲姞琛ㄦ敞閲�
+COMMENT
+ON TABLE equipment_management IS ' 璁惧绠$悊琛� ';
+-- 娣诲姞瀛楁娉ㄩ噴
+COMMENT
+ON COLUMN equipment_management.id IS ' 涓婚敭 ID';
+COMMENT
+ON COLUMN equipment_management.equipment_id IS ' 璁惧缂栧彿 ';
+COMMENT
+ON COLUMN equipment_management.equipment_name IS ' 璁惧鍚嶇О ';
+COMMENT
+ON COLUMN equipment_management.quantity IS ' 鏁伴噺 ';
+COMMENT
+ON COLUMN equipment_management.specification IS ' 瑙勬牸鍨嬪彿 ';
+COMMENT
+ON COLUMN equipment_management.usage_status IS ' 浣跨敤鐘舵�� ';
+COMMENT
+ON COLUMN equipment_management.using_department IS ' 浣跨敤閮ㄩ棬 ';
+COMMENT
+ON COLUMN equipment_management.user_id IS ' 浣跨敤浜篒D ';
+COMMENT
+ON COLUMN equipment_management.storage_location IS ' 瀛樻斁浣嶇疆 ';
+COMMENT
+ON COLUMN equipment_management.purchase_date IS ' 閲囪喘鏃ユ湡 ';
+COMMENT
+ON COLUMN equipment_management.purchase_price IS ' 閲囪喘浠锋牸 ';
+
+COMMENT
+ON COLUMN inspection_task.deleted IS '杞垹闄ゆ爣蹇楋紝0=鏈垹闄わ紝1=宸插垹闄�';
+COMMENT
+ON COLUMN inspection_task.create_by IS '鍒涘缓璇ヨ褰曠殑鐢ㄦ埛';
+COMMENT
+ON COLUMN inspection_task.create_time IS '璁板綍鍒涘缓鏃堕棿';
+COMMENT
+ON COLUMN inspection_task.update_by IS '鏈�鍚庝慨鏀硅璁板綍鐨勭敤鎴�';
+COMMENT
+ON COLUMN inspection_task.update_time IS '璁板綍鏈�鍚庢洿鏂版椂闂�';
diff --git a/main-business/src/main/resources/mapper/EquipmentManagementMapper.xml b/main-business/src/main/resources/mapper/EquipmentManagementMapper.xml
new file mode 100644
index 0000000..2726016
--- /dev/null
+++ b/main-business/src/main/resources/mapper/EquipmentManagementMapper.xml
@@ -0,0 +1,35 @@
+<?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="com.ruoyi.business.mapper.EquipmentManagementMapper">
+
+        <!-- 閫氱敤鏌ヨ鏄犲皠缁撴灉 -->
+        <resultMap id="BaseResultMap" type="com.ruoyi.business.entity.EquipmentManagement">
+                    <id column="id" property="id" />
+                <result column="deleted" property="deleted" />
+                <result column="create_by" property="createBy" />
+                <result column="create_time" property="createTime" />
+                <result column="update_by" property="updateBy" />
+                <result column="update_time" property="updateTime" />
+                    <result column="equipment_id" property="equipmentId" />
+                    <result column="equipment_name" property="equipmentName" />
+                    <result column="quantity" property="quantity" />
+                    <result column="specification" property="specification" />
+                    <result column="usage_status" property="usageStatus" />
+                    <result column="using_department" property="usingDepartment" />
+                    <result column="user_id" property="userId" />
+                    <result column="storage_location" property="storageLocation" />
+                    <result column="purchase_date" property="purchaseDate" />
+                    <result column="purchase_price" property="purchasePrice" />
+        </resultMap>
+
+        <!-- 閫氱敤鏌ヨ缁撴灉鍒� -->
+        <sql id="Base_Column_List">
+                deleted,
+                create_by,
+                create_time,
+                update_by,
+                update_time,
+            id, equipment_id, equipment_name, quantity, specification, usage_status, using_department, user_id, storage_location, purchase_date, purchase_price
+        </sql>
+
+</mapper>
\ No newline at end of file
diff --git a/main-business/src/main/resources/mapper/TimingTaskMapper.xml b/main-business/src/main/resources/mapper/TimingTaskMapper.xml
new file mode 100644
index 0000000..70fd0ab
--- /dev/null
+++ b/main-business/src/main/resources/mapper/TimingTaskMapper.xml
@@ -0,0 +1,33 @@
+<?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="com.ruoyi.business.mapper.TimingTaskMapper">
+
+        <!-- 閫氱敤鏌ヨ鏄犲皠缁撴灉 -->
+        <resultMap id="BaseResultMap" type="com.ruoyi.business.entity.TimingTask">
+                    <id column="id" property="id" />
+                <result column="deleted" property="deleted" />
+                <result column="create_by" property="createBy" />
+                <result column="create_time" property="createTime" />
+                <result column="update_by" property="updateBy" />
+                <result column="update_time" property="updateTime" />
+                    <result column="task_name" property="taskName" />
+                    <result column="inspector_ids" property="inspectorIds" />
+                    <result column="inspection_location" property="inspectionLocation" />
+                    <result column="frequency" property="frequency" />
+                    <result column="remarks" property="remarks" />
+                    <result column="registrant_id" property="registrantId" />
+                    <result column="registrant" property="registrant" />
+                    <result column="registration_date" property="registrationDate" />
+        </resultMap>
+
+        <!-- 閫氱敤鏌ヨ缁撴灉鍒� -->
+        <sql id="Base_Column_List">
+                deleted,
+                create_by,
+                create_time,
+                update_by,
+                update_time,
+            id, task_name, inspector_ids, inspection_location, frequency, remarks, registrant_id, registrant, registration_date
+        </sql>
+
+</mapper>
\ No newline at end of file
diff --git a/main-business/src/main/resources/mapper/TreeMapper.xml b/main-business/src/main/resources/mapper/TreeMapper.xml
index d9c0ef1..fcedc3f 100644
--- a/main-business/src/main/resources/mapper/TreeMapper.xml
+++ b/main-business/src/main/resources/mapper/TreeMapper.xml
@@ -23,5 +23,14 @@
                 update_time,
             id, name, parent_id
         </sql>
+    <select id="listRecursiveSubNodeIds" resultType="java.lang.Long">
+        WITH RECURSIVE sub_nodes AS (
+            SELECT id FROM tree WHERE parent_id = #{treeId}
+            UNION ALL
+            SELECT t.id FROM tree t
+                                 JOIN sub_nodes s ON t.parent_id = s.id
+        )
+        SELECT id FROM sub_nodes
+    </select>
 
 </mapper>
\ No newline at end of file
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysUserMapper.java b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysUserMapper.java
index a5063ac..0928434 100644
--- a/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysUserMapper.java
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysUserMapper.java
@@ -1,9 +1,13 @@
 package com.ruoyi.system.mapper;
 
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
 import com.ruoyi.common.core.domain.entity.SysUser;
 import org.apache.ibatis.annotations.Param;
 
+import java.util.ArrayList;
+import java.util.Collection;
 import java.util.List;
+import java.util.Set;
 
 /**
  * 鐢ㄦ埛琛� 鏁版嵁灞�
@@ -131,4 +135,13 @@
     List<SysUser> selectUserListAll();
 
     List<SysUser> selectList(List<Long> registrantIds);
+
+    List<SysUser> selectUsersByIds(@Param("userIds") List<Long> userIds);
+
+    /**
+     * 鎵归噺鏌ヨ鐢ㄦ埛淇℃伅
+     * @param userIds 鐢ㄦ埛ID闆嗗悎
+     * @return 鐢ㄦ埛鍒楄〃
+     */
+    List<SysUser> selectBatchIds(@Param("userIds") Set<Long> userIds);
 }
diff --git a/ruoyi-system/src/main/resources/mapper/system/SysUserMapper.xml b/ruoyi-system/src/main/resources/mapper/system/SysUserMapper.xml
index 8cbe2d3..b91baa4 100644
--- a/ruoyi-system/src/main/resources/mapper/system/SysUserMapper.xml
+++ b/ruoyi-system/src/main/resources/mapper/system/SysUserMapper.xml
@@ -158,8 +158,38 @@
 			</if>
 		</where>
 	</select>
+    <select id="selectUsersByIds" resultType="com.ruoyi.common.core.domain.entity.SysUser">
+		SELECT user_id, nick_name
+		FROM sys_user
+		WHERE user_id IN
+		<foreach collection="userIds" item="id" open="(" separator="," close=")">
+			#{id}
+		</foreach>
+	</select>
+	<select id="selectBatchIds" resultType="com.ruoyi.common.core.domain.entity.SysUser">
+		SELECT * FROM sys_user
+		<!-- 澶勭悊绌洪泦鍚堬細鑻� userIds 涓虹┖锛屼笉鎵ц WHERE 鏉′欢锛堥伩鍏� SQL 璇硶閿欒锛� -->
+		<where>
+			<if test="userIds != null and userIds.size() > 0">
+				user_id = ANY(
+				<foreach collection="userIds" item="id" open="ARRAY[" separator="," close="]">
+					#{id}
+				</foreach>
+				)
+			</if>
+		</where>
+		<!-- 鎺掑簭锛氭寜浼犲叆鐨� userIds 椤哄簭杩斿洖缁撴灉锛圥ostgreSQL 涓撶敤锛� -->
+		<if test="userIds != null and userIds.size() > 0">
+			ORDER BY array_position(
+			<foreach collection="userIds" item="id" open="ARRAY[" separator="," close="]" index="index">
+				#{id}
+			</foreach>,
+			user_id  -- 琛ㄤ腑鐨� id 瀛楁锛屼笌鏁扮粍涓殑鍏冪礌鍖归厤
+			)
+		</if>
+	</select>
 
-    <insert id="insertUser" parameterType="SysUser" useGeneratedKeys="true" keyProperty="userId">
+	<insert id="insertUser" parameterType="SysUser" useGeneratedKeys="true" keyProperty="userId">
  		insert into sys_user(
  			<if test="userId != null and userId != 0">user_id,</if>
  			<if test="deptId != null and deptId != 0">dept_id,</if>

--
Gitblit v1.9.3