2026-05-16 a2d3c6f8d43fbf9daa372fea53acf50642094de4
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;
    }
@@ -225,6 +250,8 @@
            return calculateWeeklyFirstExecution(task.getFrequencyDetail());
        } else if ("MONTHLY".equals(frequencyType)) {
            return calculateMonthlyFirstExecution(task.getFrequencyDetail());
        } else if ("YEARLY".equals(frequencyType)) {
            return calculateYearlyFirstExecution(task.getFrequencyDetail());
        } else if ("QUARTERLY".equals(frequencyType)) {
            return calculateCustomFirstExecution(task.getFrequencyDetail());
        } else {
@@ -315,6 +342,28 @@
        return targetDateTime;
    }
    private LocalDateTime calculateYearlyFirstExecution(String frequencyDetail) {
        String[] parts = frequencyDetail.split(",");
        if (parts.length != 3) {
            throw new IllegalArgumentException("参数格式错误,应为 03,15,17:00");
        }
        int month = Integer.parseInt(parts[0].trim());
        int dayOfMonth = Integer.parseInt(parts[1].trim());
        LocalTime targetTime = LocalTime.parse(parts[2].trim(), DateTimeFormatter.ofPattern("HH:mm"));
        LocalDateTime now = LocalDateTime.now();
        YearMonth currentYearMonth = YearMonth.of(now.getYear(), month);
        int adjustedDay = Math.min(dayOfMonth, currentYearMonth.lengthOfMonth());
        LocalDateTime targetDateTime = LocalDateTime.of(now.getYear(), month, adjustedDay, targetTime.getHour(), targetTime.getMinute());
        if (!targetDateTime.isAfter(now)) {
            YearMonth nextYearMonth = YearMonth.of(now.getYear() + 1, month);
            adjustedDay = Math.min(dayOfMonth, nextYearMonth.lengthOfMonth());
            targetDateTime = LocalDateTime.of(now.getYear() + 1, month, adjustedDay, targetTime.getHour(), targetTime.getMinute());
        }
        return targetDateTime;
    }
    private LocalDateTime calculateCustomFirstExecution(String frequencyDetail) {
        return null;
    }
@@ -350,6 +399,8 @@
                    return calculateMonthlyNextTime(frequencyDetail, currentTime);
                case "QUARTERLY":
                    return calculateQuarterlyNextTime(frequencyDetail, currentTime);
                case "YEARLY":
                    return calculateYearlyNextTime(frequencyDetail, currentTime);
                default:
                    throw new IllegalArgumentException("不支持的频率类型: " + frequencyType);
            }
@@ -415,6 +466,23 @@
        );
    }
    private LocalDateTime calculateYearlyNextTime(String detail, LocalDateTime current) {
        String[] parts = detail.split(",");
        int month = Integer.parseInt(parts[0]);
        int dayOfMonth = Integer.parseInt(parts[1]);
        LocalTime time = LocalTime.parse(parts[2]);
        YearMonth targetYearMonth = YearMonth.of(current.getYear(), month);
        int adjustedDay = Math.min(dayOfMonth, targetYearMonth.lengthOfMonth());
        LocalDateTime target = LocalDateTime.of(current.getYear(), month, adjustedDay, time.getHour(), time.getMinute());
        if (!target.isAfter(current)) {
            targetYearMonth = YearMonth.of(current.getYear() + 1, month);
            adjustedDay = Math.min(dayOfMonth, targetYearMonth.lengthOfMonth());
            target = LocalDateTime.of(current.getYear() + 1, month, adjustedDay, time.getHour(), time.getMinute());
        }
        return target;
    }
    private Set<DayOfWeek> parseDayOfWeeks(String dayOfWeekStr) {
        Set<DayOfWeek> days = new HashSet<>();
        String[] dayStrs = dayOfWeekStr.split("\\|");
@@ -449,6 +517,41 @@
    }
    @Override
    @Transactional
    public int changeEnable(Long taskId, Integer isEnabled) throws SchedulerException {
        if (taskId == null || isEnabled == null) {
            throw new IllegalArgumentException("id和isEnabled不能为空");
        }
        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) {