From a2d3c6f8d43fbf9daa372fea53acf50642094de4 Mon Sep 17 00:00:00 2001
From: 云 <2163098428@qq.com>
Date: 星期六, 16 五月 2026 10:49:06 +0800
Subject: [PATCH] feat(task): 添加定时任务启用禁用功能

---
 src/main/java/com/ruoyi/inspectiontask/service/impl/TimingTaskServiceImpl.java |   66 +++++++
 src/main/java/com/ruoyi/inspectiontask/pojo/TimingTask.java                    |    4 
 src/main/java/com/ruoyi/inspectiontask/service/impl/TimingTaskJob.java         |    3 
 src/main/java/com/ruoyi/device/controller/MaintenanceTaskController.java       |   44 +++--
 sql/timing_and_maintenance_task_add_is_enabled.sql                             |    5 
 src/main/java/com/ruoyi/inspectiontask/service/impl/TimingTaskScheduler.java   |   10 +
 src/main/java/com/ruoyi/device/pojo/MaintenanceTask.java                       |    4 
 src/main/java/com/ruoyi/device/service/impl/MaintenanceTaskScheduler.java      |   10 +
 src/main/java/com/ruoyi/device/service/impl/MaintenanceTaskServiceImpl.java    |  117 +++++++++++++-
 src/main/java/com/ruoyi/device/service/MaintenanceTaskService.java             |    2 
 src/main/java/com/ruoyi/device/service/impl/MaintenanceTaskJob.java            |    3 
 src/main/java/com/ruoyi/inspectiontask/controller/TimingTaskController.java    |   33 ++-
 src/main/java/com/ruoyi/inspectiontask/service/TimingTaskService.java          |    2 
 doc/20260516_timing_task_enable_frontend_api.md                                |  140 +++++++++++++++++
 14 files changed, 390 insertions(+), 53 deletions(-)

diff --git a/doc/20260516_timing_task_enable_frontend_api.md b/doc/20260516_timing_task_enable_frontend_api.md
new file mode 100644
index 0000000..267c455
--- /dev/null
+++ b/doc/20260516_timing_task_enable_frontend_api.md
@@ -0,0 +1,140 @@
+# 瀹氭椂浠诲姟銆屾槸鍚﹀惎鐢ㄣ�嶅墠绔仈璋冩枃妗�
+
+## 1. 鍙樻洿鑼冨洿
+
+鏈鏀瑰姩瑕嗙洊涓や釜妯″潡鐨勫畾鏃朵换鍔$鐞嗭細
+
+1. 璁惧宸℃瀹氭椂浠诲姟锛坄inspectiontask`锛�
+2. 璁惧淇濆吇瀹氭椂浠诲姟锛坄device`锛�
+
+涓や釜妯″潡鍧囨柊澧炲苟鍚敤瀛楁锛歚isEnabled`銆�
+
+## 2. 瀛楁瀹氫箟
+
+| 瀛楁鍚� | 绫诲瀷 | 璇存槑 | 鍙栧�� |
+|---|---|---|---|
+| isEnabled | number | 鏄惁鍚敤 | `1`=鍚敤锛宍0`=绂佺敤 |
+
+璇存槑锛�
+
+1. 鏂板浠诲姟鏃讹紝濡傛灉鍓嶇涓嶄紶 `isEnabled`锛屽悗绔粯璁ゆ寜 `1`锛堝惎鐢級澶勭悊銆�
+2. 浠诲姟绂佺敤鍚庯紝涓嶅啀鐢熸垚鏂扮殑宸℃/淇濆吇璁板綍銆�
+3. 鍒囨崲鍚敤鐘舵�佷細鍚屾鏇存柊 Quartz 璋冨害锛堝惎鐢�=鎭㈠锛岀鐢�=鏆傚仠锛夈��
+
+## 3. 鏁版嵁搴撹剼鏈�
+
+鎵ц鑴氭湰锛�
+
+`sql/timing_and_maintenance_task_add_is_enabled.sql`
+
+鏂板鍒楋細
+
+1. `timing_task.is_enabled`
+2. `maintenance_task.is_enabled`
+
+## 4. 宸℃瀹氭椂浠诲姟鎺ュ彛锛坕nspectiontask锛�
+
+鍩虹璺緞锛歚/timingTask`
+
+### 4.1 鍒楄〃鏌ヨ
+
+- `GET /timingTask/list`
+- 鏀寔绛涢�夊弬鏁帮細`isEnabled`
+
+绀轰緥鍙傛暟锛�
+
+```http
+GET /timingTask/list?current=1&size=10&isEnabled=1
+```
+
+### 4.2 鏂板/缂栬緫浠诲姟
+
+- `POST /timingTask/addOrEditTimingTask`
+- 璇锋眰浣撳彲甯� `isEnabled`
+
+绀轰緥锛�
+
+```json
+{
+  "id": null,
+  "taskName": "绌哄帇鏈哄贰妫�",
+  "frequencyType": "DAILY",
+  "frequencyDetail": "09:00",
+  "taskIds": [101, 102],
+  "isEnabled": 1
+}
+```
+
+### 4.3 鍒囨崲鍚敤鐘舵�侊紙鎺ㄨ崘鍓嶇寮�鍏崇洿鎺ヨ皟鐢級
+
+- `POST /timingTask/changeEnable`
+
+绀轰緥锛�
+
+```json
+{
+  "id": 12,
+  "isEnabled": 0
+}
+```
+
+杩斿洖锛歚R`锛宍data` 涓哄彈褰卞搷琛屾暟锛堟垚鍔熼�氬父涓� `1`锛夈��
+
+## 5. 淇濆吇瀹氭椂浠诲姟鎺ュ彛锛坉evice锛�
+
+鍩虹璺緞锛歚/deviceMaintenanceTask`
+
+### 5.1 鍒楄〃鏌ヨ
+
+- `GET /deviceMaintenanceTask/listPage`
+- 鏀寔绛涢�夊弬鏁帮細`isEnabled`
+
+绀轰緥鍙傛暟锛�
+
+```http
+GET /deviceMaintenanceTask/listPage?current=1&size=10&isEnabled=1
+```
+
+### 5.2 鏂板浠诲姟
+
+- `POST /deviceMaintenanceTask/add`
+- 璇锋眰浣撳彲甯� `isEnabled`
+
+绀轰緥锛�
+
+```json
+{
+  "taskName": "鍙嶅簲閲滀繚鍏�",
+  "frequencyType": "WEEKLY",
+  "frequencyDetail": "MON,10:00",
+  "deviceLedgerIds": [301, 302],
+  "isEnabled": 1
+}
+```
+
+### 5.3 缂栬緫浠诲姟
+
+- `POST /deviceMaintenanceTask/update`
+- 璇锋眰浣撳彲甯� `isEnabled`
+
+### 5.4 鍒囨崲鍚敤鐘舵�侊紙鎺ㄨ崘鍓嶇寮�鍏崇洿鎺ヨ皟鐢級
+
+- `POST /deviceMaintenanceTask/changeEnable`
+
+绀轰緥锛�
+
+```json
+{
+  "id": 26,
+  "isEnabled": 0
+}
+```
+
+杩斿洖锛歚AjaxResult`銆�
+
+## 6. 鍓嶇鑱旇皟寤鸿
+
+1. 鍒楄〃椤垫柊澧炪�屾槸鍚﹀惎鐢ㄣ�嶅垪锛屼娇鐢ㄥ紑鍏崇粍浠舵槧灏勶細寮�=`1`锛屽叧=`0`銆�
+2. 寮�鍏冲彉鏇存椂鐩存帴璋冪敤瀵瑰簲 `changeEnable` 鎺ュ彛锛屾垚鍔熷悗鍒锋柊褰撳墠琛屾垨鍒楄〃銆�
+3. 鏂板/缂栬緫寮圭獥涓鍔犮�屾槸鍚﹀惎鐢ㄣ�嶅瓧娈碉紝榛樿鍕鹃�夛紙`1`锛夈��
+4. 濡傛灉鍚庣杩斿洖 `id鍜宨sEnabled涓嶈兘涓虹┖`锛屾鏌ュ紑鍏虫彁浜ゅ弬鏁版槸鍚﹀畬鏁淬��
diff --git a/sql/timing_and_maintenance_task_add_is_enabled.sql b/sql/timing_and_maintenance_task_add_is_enabled.sql
new file mode 100644
index 0000000..5374037
--- /dev/null
+++ b/sql/timing_and_maintenance_task_add_is_enabled.sql
@@ -0,0 +1,5 @@
+ALTER TABLE `timing_task`
+    ADD COLUMN `is_enabled` tinyint(1) NOT NULL DEFAULT 1 COMMENT '鏄惁鍚敤(1=鍚敤,0=绂佺敤)' AFTER `last_execution_time`;
+
+ALTER TABLE `maintenance_task`
+    ADD COLUMN `is_enabled` tinyint(1) NOT NULL DEFAULT 1 COMMENT '鏄惁鍚敤(1=鍚敤,0=绂佺敤)' AFTER `last_execution_time`;
diff --git a/src/main/java/com/ruoyi/device/controller/MaintenanceTaskController.java b/src/main/java/com/ruoyi/device/controller/MaintenanceTaskController.java
index fd8398c..7482f57 100644
--- a/src/main/java/com/ruoyi/device/controller/MaintenanceTaskController.java
+++ b/src/main/java/com/ruoyi/device/controller/MaintenanceTaskController.java
@@ -10,51 +10,57 @@
 import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiOperation;
 import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.web.bind.annotation.*;
+import org.springframework.web.bind.annotation.DeleteMapping;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
 
 import java.util.List;
 
-/**
- * @author :yys
- * @date : 2025/12/22 14:58
- */
-@Api(tags = "璁惧淇濆吇瀹氭椂浠诲姟绠$悊")
+@Api(tags = "Maintenance Timing Task")
 @RestController
 @RequestMapping("/deviceMaintenanceTask")
 public class MaintenanceTaskController extends BaseController {
 
-
     @Autowired
     private MaintenanceTaskService maintenanceTaskService;
 
-
     @GetMapping("/listPage")
-    @ApiOperation(value = "璁惧淇濆吇瀹氭椂浠诲姟鍒楄〃")
+    @ApiOperation(value = "Maintenance timing task list")
     public AjaxResult listPage(Page page, MaintenanceTask maintenanceTask) {
-        return maintenanceTaskService.listPage(page,maintenanceTask);
+        return maintenanceTaskService.listPage(page, maintenanceTask);
     }
 
-
     @PostMapping("/add")
-    @ApiOperation(value = "娣诲姞璁惧淇濆吇瀹氭椂浠诲姟")
-    @Log(title = "璁惧淇濆吇瀹氭椂浠诲姟", businessType = BusinessType.INSERT)
+    @ApiOperation(value = "Create maintenance timing task")
+    @Log(title = "Maintenance Timing Task", businessType = BusinessType.INSERT)
     public AjaxResult add(@RequestBody MaintenanceTask maintenanceTask) {
         return maintenanceTaskService.add(maintenanceTask);
     }
 
     @PostMapping("/update")
-    @ApiOperation(value = "淇敼璁惧淇濆吇瀹氭椂浠诲姟")
-    @Log(title = "璁惧淇濆吇瀹氭椂浠诲姟", businessType = BusinessType.UPDATE)
+    @ApiOperation(value = "Update maintenance timing task")
+    @Log(title = "Maintenance Timing Task", businessType = BusinessType.UPDATE)
     public AjaxResult update(@RequestBody MaintenanceTask maintenanceTask) {
         return maintenanceTaskService.updateByMaintenanceTaskId(maintenanceTask);
     }
 
+    @PostMapping("/changeEnable")
+    @ApiOperation(value = "Change enable status")
+    @Log(title = "Maintenance Timing Task", businessType = BusinessType.UPDATE)
+    public AjaxResult changeEnable(@RequestBody MaintenanceTask maintenanceTask) {
+        if (maintenanceTask.getId() == null || maintenanceTask.getIsEnabled() == null) {
+            return AjaxResult.error("id and isEnabled are required");
+        }
+        return maintenanceTaskService.changeEnable(maintenanceTask.getId(), maintenanceTask.getIsEnabled());
+    }
+
     @DeleteMapping("/delete")
-    @ApiOperation(value = "鍒犻櫎璁惧淇濆吇瀹氭椂浠诲姟")
-    @Log(title = "璁惧淇濆吇瀹氭椂浠诲姟", businessType = BusinessType.DELETE)
+    @ApiOperation(value = "Delete maintenance timing tasks")
+    @Log(title = "Maintenance Timing Task", businessType = BusinessType.DELETE)
     public AjaxResult delete(@RequestBody List<Long> ids) {
         return maintenanceTaskService.delete(ids);
     }
-
-
 }
diff --git a/src/main/java/com/ruoyi/device/pojo/MaintenanceTask.java b/src/main/java/com/ruoyi/device/pojo/MaintenanceTask.java
index 73d0933..a73387b 100644
--- a/src/main/java/com/ruoyi/device/pojo/MaintenanceTask.java
+++ b/src/main/java/com/ruoyi/device/pojo/MaintenanceTask.java
@@ -63,8 +63,8 @@
     @ApiModelProperty(value = "鏈�鍚庢墽琛屾椂闂�")
     private LocalDateTime lastExecutionTime;
 
-    @ApiModelProperty(value = "鏄惁婵�娲�")
-    private boolean isActive;
+    @ApiModelProperty(value = "鏄惁鍚敤(1=鍚敤,0=绂佺敤)")
+    private Integer isEnabled;
 
     @ApiModelProperty(value = "澶囨敞")
     @Excel(name = "澶囨敞")
diff --git a/src/main/java/com/ruoyi/device/service/MaintenanceTaskService.java b/src/main/java/com/ruoyi/device/service/MaintenanceTaskService.java
index 19cb6ed..e4c912d 100644
--- a/src/main/java/com/ruoyi/device/service/MaintenanceTaskService.java
+++ b/src/main/java/com/ruoyi/device/service/MaintenanceTaskService.java
@@ -19,4 +19,6 @@
     AjaxResult updateByMaintenanceTaskId(MaintenanceTask maintenanceTask);
 
     AjaxResult delete(List<Long> ids);
+
+    AjaxResult changeEnable(Long taskId, Integer isEnabled);
 }
diff --git a/src/main/java/com/ruoyi/device/service/impl/MaintenanceTaskJob.java b/src/main/java/com/ruoyi/device/service/impl/MaintenanceTaskJob.java
index 69ba222..e1fa443 100644
--- a/src/main/java/com/ruoyi/device/service/impl/MaintenanceTaskJob.java
+++ b/src/main/java/com/ruoyi/device/service/impl/MaintenanceTaskJob.java
@@ -55,6 +55,9 @@
             if (timingTask == null) {
                 throw new JobExecutionException("MaintenanceTaskJob鎵句笉鍒板畾鏃朵换鍔� " + taskId);
             }
+            if (Integer.valueOf(0).equals(timingTask.getIsEnabled())) {
+                return;
+            }
 
             List<Long> deviceIds = resolveDeviceIds(timingTask);
             List<DeviceMaintenance> maintenanceList = new ArrayList<>();
diff --git a/src/main/java/com/ruoyi/device/service/impl/MaintenanceTaskScheduler.java b/src/main/java/com/ruoyi/device/service/impl/MaintenanceTaskScheduler.java
index da24a2e..da50fa1 100644
--- a/src/main/java/com/ruoyi/device/service/impl/MaintenanceTaskScheduler.java
+++ b/src/main/java/com/ruoyi/device/service/impl/MaintenanceTaskScheduler.java
@@ -45,8 +45,14 @@
         try {
             TriggerKey triggerKey = new TriggerKey("triggerMaintenanceTask_" + task.getId());
             Trigger oldTrigger = scheduler.getTrigger(triggerKey);
+            if (oldTrigger == null) {
+                scheduleMaintenanceTask(task);
+                return;
+            }
             if (!(oldTrigger instanceof CronTrigger)) {
-                throw new SchedulerException("Existing trigger is not a CronTrigger");
+                scheduler.unscheduleJob(triggerKey);
+                scheduleMaintenanceTask(task);
+                return;
             }
 
             CronTrigger newTrigger = TriggerBuilder.newTrigger()
@@ -234,4 +240,4 @@
                 throw new IllegalArgumentException("鏃犳晥鐨勬槦鏈�: " + dayName);
         }
     }
-}
\ No newline at end of file
+}
diff --git a/src/main/java/com/ruoyi/device/service/impl/MaintenanceTaskServiceImpl.java b/src/main/java/com/ruoyi/device/service/impl/MaintenanceTaskServiceImpl.java
index 5c84b2e..30122c3 100644
--- a/src/main/java/com/ruoyi/device/service/impl/MaintenanceTaskServiceImpl.java
+++ b/src/main/java/com/ruoyi/device/service/impl/MaintenanceTaskServiceImpl.java
@@ -17,8 +17,10 @@
 import com.ruoyi.project.system.domain.SysUser;
 import com.ruoyi.project.system.mapper.SysUserMapper;
 import lombok.extern.slf4j.Slf4j;
+import org.quartz.SchedulerException;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
 
 import java.time.LocalDateTime;
 import java.util.ArrayList;
@@ -36,14 +38,19 @@
 
     @Autowired
     private MaintenanceTaskMapper maintenanceTaskMapper;
+
     @Autowired
     private SysUserMapper sysUserMapper;
+
     @Autowired
     private TimingTaskServiceImpl timingTaskService;
+
     @Autowired
     private MaintenanceTaskScheduler maintenanceTaskScheduler;
+
     @Autowired
     private IDeviceLedgerService deviceLedgerService;
+
     @Autowired
     private DeviceAreaMapper deviceAreaMapper;
 
@@ -57,6 +64,10 @@
         if (maintenanceTask.getAreaId() != null) {
             queryWrapper.eq(MaintenanceTask::getAreaId, maintenanceTask.getAreaId());
         }
+        if (maintenanceTask.getIsEnabled() != null) {
+            queryWrapper.eq(MaintenanceTask::getIsEnabled, maintenanceTask.getIsEnabled());
+        }
+
         Page<MaintenanceTask> taskPage = maintenanceTaskMapper.selectPage(page, queryWrapper);
         if (taskPage.getRecords().isEmpty()) {
             return AjaxResult.success(taskPage);
@@ -74,6 +85,7 @@
             List<SysUser> users = sysUserMapper.selectUserByIds(new ArrayList<>(userIds));
             users.forEach(user -> userNickNameMap.put(user.getUserId(), user.getNickName()));
         }
+
         Map<Long, String> areaNameMap = deviceAreaMapper.selectBatchIds(taskPage.getRecords().stream()
                         .map(MaintenanceTask::getAreaId)
                         .filter(java.util.Objects::nonNull)
@@ -81,6 +93,7 @@
                         .collect(Collectors.toList()))
                 .stream()
                 .collect(Collectors.toMap(DeviceArea::getId, DeviceArea::getAreaName, (left, right) -> left, HashMap::new));
+
         taskPage.getRecords().forEach(task -> {
             if (task.getRegistrantId() != null) {
                 task.setRegistrant(userNickNameMap.getOrDefault(task.getRegistrantId(), "鏈煡鐢ㄦ埛"));
@@ -91,37 +104,70 @@
     }
 
     @Override
+    @Transactional
     public AjaxResult add(MaintenanceTask maintenanceTask) {
         if (!prepareMaintenanceTask(maintenanceTask)) {
             return AjaxResult.error("璇烽�夋嫨璁惧");
         }
-        maintenanceTask.setActive(true);
+        if (maintenanceTask.getIsEnabled() == null) {
+            maintenanceTask.setIsEnabled(1);
+        }
+
         TimingTask task = new TimingTask();
         task.setFrequencyType(maintenanceTask.getFrequencyType());
         task.setFrequencyDetail(maintenanceTask.getFrequencyDetail());
         LocalDateTime firstExecutionTime = timingTaskService.calculateFirstExecutionTime(task);
         maintenanceTask.setNextExecutionTime(firstExecutionTime);
+
         int insert = maintenanceTaskMapper.insert(maintenanceTask);
         if (insert > 0) {
-            maintenanceTaskScheduler.scheduleMaintenanceTask(maintenanceTask);
+            AjaxResult schedulerResult = resetSchedulerStatus(maintenanceTask);
+            if (schedulerResult.isError()) {
+                return schedulerResult;
+            }
         }
         return AjaxResult.success("娣诲姞鎴愬姛");
     }
 
     @Override
+    @Transactional
     public AjaxResult updateByMaintenanceTaskId(MaintenanceTask maintenanceTask) {
-        MaintenanceTask maintenanceTask1 = maintenanceTaskMapper.selectById(maintenanceTask.getId());
-        if (maintenanceTask1 == null) {
+        if (maintenanceTask.getId() == null) {
+            return AjaxResult.error("id涓嶈兘涓虹┖");
+        }
+
+        MaintenanceTask currentTask = maintenanceTaskMapper.selectById(maintenanceTask.getId());
+        if (currentTask == null) {
             return AjaxResult.warn("娌℃湁姝ゆ暟鎹�");
         }
-        BeanUtils.copyProperties(maintenanceTask, maintenanceTask1);
-        if (!prepareMaintenanceTask(maintenanceTask1)) {
+
+        Integer oldEnabled = currentTask.getIsEnabled();
+        LocalDateTime oldNextExecutionTime = currentTask.getNextExecutionTime();
+        BeanUtils.copyProperties(maintenanceTask, currentTask);
+        if (maintenanceTask.getIsEnabled() == null) {
+            currentTask.setIsEnabled(oldEnabled);
+        }
+        if (maintenanceTask.getNextExecutionTime() == null) {
+            currentTask.setNextExecutionTime(oldNextExecutionTime);
+        }
+        if (!prepareMaintenanceTask(currentTask)) {
             return AjaxResult.error("璇烽�夋嫨璁惧");
         }
-        maintenanceTask1.setDeviceLedgerIds(null);
-        int update = maintenanceTaskMapper.updateById(maintenanceTask1);
+
+        currentTask.setDeviceLedgerIds(null);
+        if (currentTask.getNextExecutionTime() == null) {
+            TimingTask task = new TimingTask();
+            task.setFrequencyType(currentTask.getFrequencyType());
+            task.setFrequencyDetail(currentTask.getFrequencyDetail());
+            currentTask.setNextExecutionTime(timingTaskService.calculateFirstExecutionTime(task));
+        }
+
+        int update = maintenanceTaskMapper.updateById(currentTask);
         if (update > 0) {
-            maintenanceTaskScheduler.rescheduleMaintenanceTask(maintenanceTask1);
+            AjaxResult schedulerResult = resetSchedulerStatus(currentTask);
+            if (schedulerResult.isError()) {
+                return schedulerResult;
+            }
         }
         return AjaxResult.success("鏇存柊鎴愬姛");
     }
@@ -133,6 +179,57 @@
             ids.forEach(id -> maintenanceTaskScheduler.unscheduleMaintenanceTask(id));
         }
         return AjaxResult.success("鍒犻櫎鎴愬姛");
+    }
+
+    @Override
+    @Transactional
+    public AjaxResult changeEnable(Long taskId, Integer isEnabled) {
+        if (taskId == null || isEnabled == null) {
+            return AjaxResult.error("id鍜宨sEnabled涓嶈兘涓虹┖");
+        }
+
+        MaintenanceTask task = maintenanceTaskMapper.selectById(taskId);
+        if (task == null) {
+            return AjaxResult.warn("娌℃湁姝ゆ暟鎹�");
+        }
+        task.setIsEnabled(isEnabled);
+        if (task.getNextExecutionTime() == null) {
+            TimingTask timingTask = new TimingTask();
+            timingTask.setFrequencyType(task.getFrequencyType());
+            timingTask.setFrequencyDetail(task.getFrequencyDetail());
+            task.setNextExecutionTime(timingTaskService.calculateFirstExecutionTime(timingTask));
+        }
+
+        int update = maintenanceTaskMapper.updateById(task);
+        if (update > 0) {
+            AjaxResult schedulerResult = resetSchedulerStatus(task);
+            if (schedulerResult.isError()) {
+                return schedulerResult;
+            }
+        }
+        return AjaxResult.success("鏇存柊鎴愬姛");
+    }
+
+    private AjaxResult resetSchedulerStatus(MaintenanceTask task) {
+        try {
+            maintenanceTaskScheduler.rescheduleMaintenanceTask(task);
+            if (isTaskEnabled(task.getIsEnabled())) {
+                maintenanceTaskScheduler.resumeMaintenanceTask(task.getId());
+            } else {
+                maintenanceTaskScheduler.pauseMaintenanceTask(task.getId());
+            }
+            return AjaxResult.success();
+        } catch (SchedulerException e) {
+            log.error("resetSchedulerStatus error, taskId={}", task.getId(), e);
+            return AjaxResult.error("鏇存柊璋冨害鐘舵�佸け璐�");
+        } catch (RuntimeException e) {
+            log.error("resetSchedulerStatus runtime error, taskId={}", task.getId(), e);
+            return AjaxResult.error("鏇存柊璋冨害鐘舵�佸け璐�");
+        }
+    }
+
+    private boolean isTaskEnabled(Integer isEnabled) {
+        return isEnabled == null || isEnabled == 1;
     }
 
     private boolean prepareMaintenanceTask(MaintenanceTask task) {
@@ -150,6 +247,7 @@
         if (validIds.isEmpty()) {
             return false;
         }
+
         List<DeviceLedger> devices = validIds.stream()
                 .map(deviceLedgerService::getById)
                 .filter(device -> device != null)
@@ -157,6 +255,7 @@
         if (devices.isEmpty()) {
             return false;
         }
+
         task.setTaskId(devices.get(0).getId());
         if (task.getAreaId() == null) {
             task.setAreaId(devices.get(0).getAreaId());
diff --git a/src/main/java/com/ruoyi/inspectiontask/controller/TimingTaskController.java b/src/main/java/com/ruoyi/inspectiontask/controller/TimingTaskController.java
index 3f371be..2fce72f 100644
--- a/src/main/java/com/ruoyi/inspectiontask/controller/TimingTaskController.java
+++ b/src/main/java/com/ruoyi/inspectiontask/controller/TimingTaskController.java
@@ -9,7 +9,6 @@
 import com.ruoyi.framework.web.domain.R;
 import com.ruoyi.inspectiontask.dto.InspectionTaskDto;
 import com.ruoyi.inspectiontask.dto.TimingTaskDto;
-import com.ruoyi.inspectiontask.pojo.InspectionTask;
 import com.ruoyi.inspectiontask.pojo.TimingTask;
 import com.ruoyi.inspectiontask.service.InspectionTaskService;
 import com.ruoyi.inspectiontask.service.TimingTaskService;
@@ -28,12 +27,8 @@
 import javax.servlet.http.HttpServletResponse;
 import java.util.List;
 
-/**
- * @author :yys
- * @date : 2025/9/19 10:53
- */
 @RestController
-@Api(tags = "宸℃绠$悊")
+@Api(tags = "Inspection Timing Task")
 @RequestMapping("/timingTask")
 public class TimingTaskController extends BaseController {
 
@@ -44,38 +39,48 @@
     private InspectionTaskService inspectionTaskService;
 
     @GetMapping("/list")
-    @ApiOperation(value = "瀹氭椂浠诲姟鍒楄〃")
+    @ApiOperation(value = "Timing task list")
     public R<IPage<TimingTaskDto>> list(Page<TimingTask> page, TimingTask timingTask) {
         IPage<TimingTaskDto> list = timingTaskService.selectTimingTaskList(page, timingTask);
         return R.ok(list);
     }
 
     @GetMapping("/recordList/{timingId}")
-    @ApiOperation(value = "鏍规嵁瀹氭椂浠诲姟ID鏌ヨ宸℃璁板綍鍒楄〃")
+    @ApiOperation(value = "Inspection records by timing task id")
     public R<List<InspectionTaskDto>> recordList(@PathVariable Long timingId) {
         return R.ok(inspectionTaskService.selectInspectionTaskRecordListByTimingId(timingId));
     }
 
     @PostMapping("/export")
-    @ApiOperation(value = "瀵煎嚭瀹氭椂浠诲姟")
+    @ApiOperation(value = "Export timing tasks")
     public void export(HttpServletResponse response) {
         Page page = new Page<>(-1, -1);
         TimingTaskDto timingTask = new TimingTaskDto();
         IPage<TimingTaskDto> list = timingTaskService.selectTimingTaskList(page, timingTask);
         ExcelUtil<TimingTaskDto> util = new ExcelUtil<>(TimingTaskDto.class);
-        util.exportExcel(response, list.getRecords(), "瀵煎嚭瀹氭椂浠诲姟");
+        util.exportExcel(response, list.getRecords(), "timing_task_export");
     }
 
     @PostMapping("/addOrEditTimingTask")
-    @ApiOperation(value = "鏂板淇敼瀹氭椂浠诲姟")
-    @Log(title = "瀹氭椂浠诲姟", businessType = BusinessType.INSERT)
+    @ApiOperation(value = "Create or update timing task")
+    @Log(title = "Timing Task", businessType = BusinessType.INSERT)
     public R addOrEditTimingTask(@RequestBody TimingTaskDto timingTaskDto) throws SchedulerException {
         return R.ok(timingTaskService.addOrEditTimingTask(timingTaskDto));
     }
 
+    @PostMapping("/changeEnable")
+    @ApiOperation(value = "Change enable status")
+    @Log(title = "Timing Task", businessType = BusinessType.UPDATE)
+    public R changeEnable(@RequestBody TimingTask timingTask) throws SchedulerException {
+        if (timingTask.getId() == null || timingTask.getIsEnabled() == null) {
+            return R.fail("id and isEnabled are required");
+        }
+        return R.ok(timingTaskService.changeEnable(timingTask.getId(), timingTask.getIsEnabled()));
+    }
+
     @DeleteMapping("/delTimingTask")
-    @ApiOperation(value = "鍒犻櫎瀹氭椂浠诲姟")
-    @Log(title = "瀹氭椂浠诲姟", businessType = BusinessType.DELETE)
+    @ApiOperation(value = "Delete timing tasks")
+    @Log(title = "Timing Task", businessType = BusinessType.DELETE)
     public R remove(@RequestBody Long[] ids) {
         return R.ok(timingTaskService.delByIds(ids));
     }
diff --git a/src/main/java/com/ruoyi/inspectiontask/pojo/TimingTask.java b/src/main/java/com/ruoyi/inspectiontask/pojo/TimingTask.java
index 474d53e..5af275c 100644
--- a/src/main/java/com/ruoyi/inspectiontask/pojo/TimingTask.java
+++ b/src/main/java/com/ruoyi/inspectiontask/pojo/TimingTask.java
@@ -65,8 +65,8 @@
     @ApiModelProperty(value = "鏈�鍚庢墽琛屾椂闂�")
     private LocalDateTime lastExecutionTime;
 
-    @ApiModelProperty(value = "鏄惁婵�娲�")
-    private boolean isActive;
+    @ApiModelProperty(value = "鏄惁鍚敤(1=鍚敤,0=绂佺敤)")
+    private Integer isEnabled;
 
     @ApiModelProperty(value = "澶囨敞")
     @Excel(name = "澶囨敞")
diff --git a/src/main/java/com/ruoyi/inspectiontask/service/TimingTaskService.java b/src/main/java/com/ruoyi/inspectiontask/service/TimingTaskService.java
index 8d00032..46f7380 100644
--- a/src/main/java/com/ruoyi/inspectiontask/service/TimingTaskService.java
+++ b/src/main/java/com/ruoyi/inspectiontask/service/TimingTaskService.java
@@ -20,4 +20,6 @@
     int delByIds(Long[] ids);
 
     void updateTaskExecutionTime(Long taskId);
+
+    int changeEnable(Long taskId, Integer isEnabled) throws SchedulerException;
 }
diff --git a/src/main/java/com/ruoyi/inspectiontask/service/impl/TimingTaskJob.java b/src/main/java/com/ruoyi/inspectiontask/service/impl/TimingTaskJob.java
index f4cd4f2..51f5e80 100644
--- a/src/main/java/com/ruoyi/inspectiontask/service/impl/TimingTaskJob.java
+++ b/src/main/java/com/ruoyi/inspectiontask/service/impl/TimingTaskJob.java
@@ -68,6 +68,9 @@
             if (timingTask == null) {
                 throw new RuntimeException("瀹氭椂浠诲姟涓嶅瓨鍦細 " + taskId);
             }
+            if (Integer.valueOf(0).equals(timingTask.getIsEnabled())) {
+                return;
+            }
 
             List<Long> deviceIds = resolveTaskIds(timingTask);
             if (deviceIds.isEmpty()) {
diff --git a/src/main/java/com/ruoyi/inspectiontask/service/impl/TimingTaskScheduler.java b/src/main/java/com/ruoyi/inspectiontask/service/impl/TimingTaskScheduler.java
index 5671156..95720f6 100644
--- a/src/main/java/com/ruoyi/inspectiontask/service/impl/TimingTaskScheduler.java
+++ b/src/main/java/com/ruoyi/inspectiontask/service/impl/TimingTaskScheduler.java
@@ -37,8 +37,14 @@
     public void rescheduleTimingTask(TimingTask task) throws SchedulerException {
         TriggerKey triggerKey = new TriggerKey("trigger_" + task.getId());
         Trigger oldTrigger = scheduler.getTrigger(triggerKey);
+        if (oldTrigger == null) {
+            scheduleTimingTask(task);
+            return;
+        }
         if (!(oldTrigger instanceof CronTrigger)) {
-            throw new SchedulerException("Existing trigger is not a CronTrigger");
+            scheduler.unscheduleJob(triggerKey);
+            scheduleTimingTask(task);
+            return;
         }
 
         CronTrigger newTrigger = TriggerBuilder.newTrigger()
@@ -223,4 +229,4 @@
                 throw new IllegalArgumentException("鏃犳晥鐨勬槦鏈�: " + dayName);
         }
     }
-}
\ No newline at end of file
+}
diff --git a/src/main/java/com/ruoyi/inspectiontask/service/impl/TimingTaskServiceImpl.java b/src/main/java/com/ruoyi/inspectiontask/service/impl/TimingTaskServiceImpl.java
index d551399..688f3a3 100644
--- a/src/main/java/com/ruoyi/inspectiontask/service/impl/TimingTaskServiceImpl.java
+++ b/src/main/java/com/ruoyi/inspectiontask/service/impl/TimingTaskServiceImpl.java
@@ -77,6 +77,9 @@
         if (timingTask.getAreaId() != null) {
             queryWrapper.eq(TimingTask::getAreaId, timingTask.getAreaId());
         }
+        if (timingTask.getIsEnabled() != null) {
+            queryWrapper.eq(TimingTask::getIsEnabled, timingTask.getIsEnabled());
+        }
         IPage<TimingTask> taskPage = timingTaskMapper.selectPage(page, queryWrapper);
         if (taskPage.getRecords().isEmpty()) {
             return new Page<>(taskPage.getCurrent(), taskPage.getSize(), taskPage.getTotal());
@@ -154,18 +157,40 @@
 
         if (Objects.isNull(timingTaskDto.getId())) {
             timingTask.setRegistrationDate(LocalDate.now());
-            timingTask.setActive(true);
+            if (timingTask.getIsEnabled() == null) {
+                timingTask.setIsEnabled(1);
+            }
             timingTask.setNextExecutionTime(calculateFirstExecutionTime(timingTask));
             int result = timingTaskMapper.insert(timingTask);
             if (result > 0) {
-                timingTaskScheduler.scheduleTimingTask(timingTask);
+                resetSchedulerStatus(timingTask);
             }
             return result;
         }
 
+        TimingTask existingTask = timingTaskMapper.selectById(timingTaskDto.getId());
+        if (existingTask == null) {
+            throw new IllegalArgumentException("瀹氭椂浠诲姟涓嶅瓨鍦�: " + timingTaskDto.getId());
+        }
+        if (timingTask.getIsEnabled() == null) {
+            timingTask.setIsEnabled(existingTask.getIsEnabled());
+        }
+        if (timingTask.getNextExecutionTime() == null) {
+            timingTask.setNextExecutionTime(existingTask.getNextExecutionTime());
+        }
+        if (timingTask.getRegistrationDate() == null) {
+            timingTask.setRegistrationDate(existingTask.getRegistrationDate());
+        }
         int result = timingTaskMapper.updateById(timingTask);
         if (result > 0) {
-            timingTaskScheduler.rescheduleTimingTask(timingTask);
+            TimingTask latestTask = timingTaskMapper.selectById(timingTask.getId());
+            if (latestTask != null) {
+                if (latestTask.getNextExecutionTime() == null) {
+                    latestTask.setNextExecutionTime(calculateFirstExecutionTime(latestTask));
+                    timingTaskMapper.updateById(latestTask);
+                }
+                resetSchedulerStatus(latestTask);
+            }
         }
         return result;
     }
@@ -492,6 +517,41 @@
     }
 
     @Override
+    @Transactional
+    public int changeEnable(Long taskId, Integer isEnabled) throws SchedulerException {
+        if (taskId == null || isEnabled == null) {
+            throw new IllegalArgumentException("id鍜宨sEnabled涓嶈兘涓虹┖");
+        }
+        TimingTask task = timingTaskMapper.selectById(taskId);
+        if (task == null) {
+            throw new IllegalArgumentException("瀹氭椂浠诲姟涓嶅瓨鍦�: " + taskId);
+        }
+        task.setIsEnabled(isEnabled);
+        int updated = timingTaskMapper.updateById(task);
+        if (updated > 0) {
+            if (task.getNextExecutionTime() == null) {
+                task.setNextExecutionTime(calculateFirstExecutionTime(task));
+                timingTaskMapper.updateById(task);
+            }
+            resetSchedulerStatus(task);
+        }
+        return updated;
+    }
+
+    private void resetSchedulerStatus(TimingTask task) throws SchedulerException {
+        timingTaskScheduler.rescheduleTimingTask(task);
+        if (isTaskEnabled(task.getIsEnabled())) {
+            timingTaskScheduler.resumeTimingTask(task.getId());
+        } else {
+            timingTaskScheduler.pauseTimingTask(task.getId());
+        }
+    }
+
+    private boolean isTaskEnabled(Integer isEnabled) {
+        return isEnabled == null || isEnabled == 1;
+    }
+
+    @Override
     public int delByIds(Long[] ids) {
         int i = timingTaskMapper.deleteBatchIds(Arrays.asList(ids));
         if (i > 0) {

--
Gitblit v1.9.3