gaoluyang
5 天以前 cf330c6a6c2ae7ec86d20de465d5af27a4684cf6
巡检任务频次增加“每年”支持

- TimingTaskScheduler:新增 YEARLY 的 cron 转换(默认 07:00)
- TimingTaskServiceImpl / TimingTaskJob:补充每年频次的首次/下次执行时间计算,frequencyDetail 格式为“月,日”,兼容旧的“月,日,HH:mm”

Co-Authored-By: Claude Code <noreply@anthropic.com>
已修改3个文件
71 ■■■■■ 文件已修改
src/main/java/com/ruoyi/inspectiontask/service/impl/TimingTaskJob.java 26 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/inspectiontask/service/impl/TimingTaskScheduler.java 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/inspectiontask/service/impl/TimingTaskServiceImpl.java 35 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/inspectiontask/service/impl/TimingTaskJob.java
@@ -146,6 +146,8 @@
                                                     LocalDateTime currentTime) {
        try {
            switch (frequencyType) {
                case "YEARLY":
                    return calculateYearlyNextTime(frequencyDetail, currentTime);
                case "DAILY":
                    return calculateDailyNextTime(frequencyDetail, currentTime);
                case "WEEKLY":
@@ -162,6 +164,30 @@
        }
    }
    /** 每年巡检默认执行时间:07:00(页面上不精确到时分) */
    private static final LocalTime DEFAULT_EXECUTION_TIME = LocalTime.of(7, 0);
    /**
     * 计算每年任务的下次执行时间
     * 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;
    }
    /**
     * 计算每日任务的下次执行时间
     */
src/main/java/com/ruoyi/inspectiontask/service/impl/TimingTaskScheduler.java
@@ -145,6 +145,8 @@
        // 使用switch确保条件互斥
        String frequencyType = task.getFrequencyType().toUpperCase(); // 统一转为大写比较
        switch (frequencyType) {
            case "YEARLY":
                return convertYearlyToCron(task.getFrequencyDetail());
            case "DAILY":
                return convertDailyToCron(task.getFrequencyDetail());
            case "WEEKLY":
@@ -158,6 +160,14 @@
        }
    }
    // 每年任务转换(frequencyDetail 格式为 "月,日",默认 07:00 执行)
    private String convertYearlyToCron(String frequencyDetail) {
        String[] parts = validateAndSplit(frequencyDetail, ",", 2);
        int month = validateMonth(parts[0]);
        int day = validateDayOfMonth(parts[1]);
        return String.format("0 0 7 %d %d ? *", day, month);
    }
    // 每日任务转换
    private String convertDailyToCron(String frequencyDetail) {
        LocalTime time = parseTime(frequencyDetail);
src/main/java/com/ruoyi/inspectiontask/service/impl/TimingTaskServiceImpl.java
@@ -223,6 +223,9 @@
        }
    }
    /** 每年巡检默认执行时间:07:00(页面上不精确到时分) */
    private static final LocalTime DEFAULT_EXECUTION_TIME = LocalTime.of(7, 0);
    private LocalDateTime calculateDailyFirstExecution(String frequencyDetail) {
        // frequencyDetail可能是具体时间,如 "14:30"
        LocalTime executionTime = LocalTime.parse(frequencyDetail);
@@ -338,8 +341,9 @@
    private LocalDateTime calculateAnnualFirstExecution(String frequencyDetail) {
        String[] parts = frequencyDetail.split(",");
        if (parts.length != 3) {
            throw new IllegalArgumentException("参数格式错误,应为'12,31,09:00'格式");
        // 每年频率不需要精确到时分:默认格式为 "月,日",兼容旧的 "月,日,HH:mm"
        if (parts.length != 2 && parts.length != 3) {
            throw new IllegalArgumentException("参数格式错误,应为'12,31'格式");
        }
        int month;
@@ -354,7 +358,9 @@
            throw new IllegalArgumentException("月份必须在1-12之间,日期必须在1-31之间");
        }
        LocalTime time = LocalTime.parse(parts[2].trim(), DateTimeFormatter.ofPattern("HH:mm"));
        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);
@@ -397,6 +403,8 @@
                                                     LocalDateTime currentTime) {
        try {
            switch (frequencyType) {
                case "YEARLY":
                    return calculateYearlyNextTime(frequencyDetail, currentTime);
                case "DAILY":
                    return calculateDailyNextTime(frequencyDetail, currentTime);
                case "WEEKLY":
@@ -414,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) {