gaoluyang
6 天以前 cf330c6a6c2ae7ec86d20de465d5af27a4684cf6
src/main/java/com/ruoyi/inspectiontask/service/impl/TimingTaskServiceImpl.java
@@ -6,6 +6,7 @@
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.bean.BeanUtils;
import com.ruoyi.device.pojo.DeviceLedger;
import com.ruoyi.inspectiontask.dto.TimingTaskDto;
import com.ruoyi.inspectiontask.mapper.TimingTaskMapper;
import com.ruoyi.inspectiontask.pojo.TimingTask;
@@ -35,6 +36,7 @@
    private final TimingTaskMapper timingTaskMapper;
    private final TimingTaskScheduler timingTaskScheduler;
    private final SysUserMapper sysUserMapper;
    private final com.ruoyi.device.mapper.DeviceLedgerMapper deviceLedgerMapper;
    private static final int ENABLED = 1;
    private static final int DISABLED = 0;
@@ -131,6 +133,7 @@
                throw new IllegalArgumentException("定时任务不存在");
            }
        }
        validateDeviceExists(timingTaskDto, oldTimingTask);
        TimingTask timingTask = new TimingTask();
        BeanUtils.copyProperties(timingTaskDto, timingTask);
        timingTask.setIsEnabled(resolveEnabledValue(timingTask.getIsEnabled(), oldTimingTask));
@@ -181,6 +184,24 @@
        }
    }
    private void validateDeviceExists(TimingTaskDto timingTaskDto, TimingTask oldTimingTask) {
        Integer taskId = timingTaskDto.getTaskId();
        if (taskId == null && oldTimingTask != null) {
            taskId = oldTimingTask.getTaskId();
        }
        if (taskId == null || taskId <= 0) {
            return;
        }
        DeviceLedger deviceLedger = deviceLedgerMapper.selectById(taskId.longValue());
        if (deviceLedger == null) {
            throw new IllegalArgumentException("所选设备不存在,请重新选择");
        }
        boolean deviceChanged = oldTimingTask == null || !Objects.equals(oldTimingTask.getTaskId(), taskId);
        if (deviceChanged && Integer.valueOf(0).equals(deviceLedger.getIsEnabled())) {
            throw new IllegalArgumentException("所选设备已停用,不能安排巡检");
        }
    }
    public LocalDateTime calculateFirstExecutionTime(TimingTask task) {
        // 根据频率类型和详情计算首次执行时间
        String frequencyType = task.getFrequencyType();
@@ -194,12 +215,16 @@
            // 如果是每月执行,计算下个月的具体日期
            return calculateMonthlyFirstExecution(task.getFrequencyDetail());
        } else if ("QUARTERLY".equals(frequencyType)) {
            // 自定义频率,如每小时、每30分钟等
            return calculateCustomFirstExecution(task.getFrequencyDetail());
        } else if ("YEARLY".equals(frequencyType)) {
            return calculateAnnualFirstExecution(task.getFrequencyDetail());
        } else {
            throw new IllegalArgumentException("不支持的频率类型: " + task.getFrequencyType());
        }
    }
    /** 每年巡检默认执行时间:07:00(页面上不精确到时分) */
    private static final LocalTime DEFAULT_EXECUTION_TIME = LocalTime.of(7, 0);
    private LocalDateTime calculateDailyFirstExecution(String frequencyDetail) {
        // frequencyDetail可能是具体时间,如 "14:30"
@@ -314,6 +339,35 @@
        return targetDateTime;
    }
    private LocalDateTime calculateAnnualFirstExecution(String frequencyDetail) {
        String[] parts = frequencyDetail.split(",");
        // 每年频率不需要精确到时分:默认格式为 "月,日",兼容旧的 "月,日,HH:mm"
        if (parts.length != 2 && parts.length != 3) {
            throw new IllegalArgumentException("参数格式错误,应为'12,31'格式");
        }
        int month;
        int day;
        try {
            month = Integer.parseInt(parts[0].trim());
            day = Integer.parseInt(parts[1].trim());
        } catch (NumberFormatException e) {
            throw new IllegalArgumentException("月份或日期格式错误", e);
        }
        if (month < 1 || month > 12 || day < 1 || day > 31) {
            throw new IllegalArgumentException("月份必须在1-12之间,日期必须在1-31之间");
        }
        LocalTime time = parts.length == 3
                ? LocalTime.parse(parts[2].trim(), DateTimeFormatter.ofPattern("HH:mm"))
                : DEFAULT_EXECUTION_TIME;
        LocalDateTime now = LocalDateTime.now();
        int year = now.getYear();
        LocalDateTime target = LocalDateTime.of(LocalDate.of(year, month, Math.min(day, YearMonth.of(year, month).lengthOfMonth())), time);
        return target.isAfter(now) ? target : LocalDateTime.of(LocalDate.of(year + 1, month,
                Math.min(day, YearMonth.of(year + 1, month).lengthOfMonth())), time);
    }
    private LocalDateTime calculateCustomFirstExecution(String frequencyDetail) {
        return null;
    }
@@ -349,6 +403,8 @@
                                                     LocalDateTime currentTime) {
        try {
            switch (frequencyType) {
                case "YEARLY":
                    return calculateYearlyNextTime(frequencyDetail, currentTime);
                case "DAILY":
                    return calculateDailyNextTime(frequencyDetail, currentTime);
                case "WEEKLY":
@@ -366,6 +422,27 @@
    }
    /**
     * 计算每年任务的下次执行时间
     * frequencyDetail 格式为 "月,日",兼容 "月,日,HH:mm"(默认 07:00)
     */
    private LocalDateTime calculateYearlyNextTime(String detail, LocalDateTime current) {
        String[] parts = detail.split(",");
        int month = Integer.parseInt(parts[0].trim());
        int day = Integer.parseInt(parts[1].trim());
        LocalTime time = parts.length >= 3 ? LocalTime.parse(parts[2].trim()) : DEFAULT_EXECUTION_TIME;
        int year = current.getYear();
        LocalDateTime target = LocalDateTime.of(
                year, month, Math.min(day, YearMonth.of(year, month).lengthOfMonth()), time.getHour(), time.getMinute());
        if (!current.isBefore(target)) {
            year++;
            target = LocalDateTime.of(
                    year, month, Math.min(day, YearMonth.of(year, month).lengthOfMonth()), time.getHour(), time.getMinute());
        }
        return target;
    }
    /**
     * 计算每日任务的下次执行时间
     */
    private LocalDateTime calculateDailyNextTime(String timeStr, LocalDateTime current) {