package com.ruoyi.inspectiontask.service.impl; 
 | 
  
 | 
import com.ruoyi.inspectiontask.mapper.InspectionTaskMapper; 
 | 
import com.ruoyi.inspectiontask.mapper.TimingTaskMapper; 
 | 
import com.ruoyi.inspectiontask.pojo.InspectionTask; 
 | 
import com.ruoyi.inspectiontask.pojo.TimingTask; 
 | 
import com.ruoyi.inspectiontask.service.TimingTaskService; 
 | 
import org.quartz.*; 
 | 
import org.springframework.beans.factory.annotation.Autowired; 
 | 
import org.springframework.jdbc.core.BeanPropertyRowMapper; 
 | 
import org.springframework.jdbc.core.JdbcTemplate; 
 | 
import org.springframework.stereotype.Component; 
 | 
  
 | 
import javax.annotation.Resource; 
 | 
import javax.sql.DataSource; 
 | 
import java.time.DayOfWeek; 
 | 
import java.time.LocalDateTime; 
 | 
import java.time.LocalTime; 
 | 
import java.time.YearMonth; 
 | 
import java.util.HashSet; 
 | 
import java.util.List; 
 | 
import java.util.Set; 
 | 
  
 | 
@Component 
 | 
@DisallowConcurrentExecution // 禁止并发执行同一个Job 
 | 
public class TimingTaskJob implements Job { 
 | 
  
 | 
    @Autowired 
 | 
    private TimingTaskMapper timingTaskMapper; 
 | 
  
 | 
    @Autowired 
 | 
    private TimingTaskService timingTaskService; 
 | 
  
 | 
    @Autowired 
 | 
    private InspectionTaskMapper inspectionTaskMapper; 
 | 
  
 | 
    @Autowired 
 | 
    private JdbcTemplate jdbcTemplate; 
 | 
  
 | 
    @Override 
 | 
    public void execute(JobExecutionContext context) throws JobExecutionException { 
 | 
        JobDataMap jobDataMap = context.getJobDetail().getJobDataMap(); 
 | 
        // 修复类型转换错误,正确获取taskId 
 | 
        Long taskId = jobDataMap.getLong("taskId"); 
 | 
  
 | 
        try { 
 | 
            // 3. 尝试查询你的业务数据 
 | 
            // 通过JDBC模板查询定时任务信息,使用参数化查询防止SQL注入 
 | 
            String yourSql = "SELECT * FROM timing_task where id = ?"; 
 | 
            List<TimingTask> tasks = jdbcTemplate.query( 
 | 
                    yourSql, 
 | 
                    new BeanPropertyRowMapper<>(TimingTask.class), 
 | 
                    taskId 
 | 
            ); 
 | 
            TimingTask timingTask = tasks.isEmpty() ? null : tasks.get(0); 
 | 
            if (timingTask == null) { 
 | 
                throw new JobExecutionException("找不到定时任务: " + taskId); 
 | 
            } 
 | 
             
 | 
//            if (!timingTask.isActive()) { 
 | 
//                throw new JobExecutionException("定时任务已禁用: " + taskId); 
 | 
//            } 
 | 
  
 | 
            // 2. 创建并保存巡检任务记录 - 这就是您提供的代码应该放的位置 
 | 
            InspectionTask inspectionTask = createInspectionTask(timingTask); 
 | 
            inspectionTaskMapper.insert(inspectionTask); 
 | 
  
 | 
            // 3. 更新定时任务的执行时间 
 | 
            if (!tasks.isEmpty()) { 
 | 
                TimingTask task = tasks.get(0); 
 | 
  
 | 
                // 更新最后执行时间为当前时间 
 | 
                LocalDateTime lastExecutionTime = LocalDateTime.now(); 
 | 
  
 | 
                // 计算下次执行时间 
 | 
                LocalDateTime nextExecutionTime = calculateNextExecutionTime( 
 | 
                        task.getFrequencyType(), 
 | 
                        task.getFrequencyDetail(), 
 | 
                        lastExecutionTime 
 | 
                ); 
 | 
  
 | 
                // 执行更新操作 
 | 
                String updateSql = "UPDATE timing_task " + 
 | 
                        "SET last_execution_time = ?, next_execution_time = ? " + 
 | 
                        "WHERE id = ?"; 
 | 
  
 | 
                jdbcTemplate.update( 
 | 
                        updateSql, 
 | 
                        lastExecutionTime, 
 | 
                        nextExecutionTime, 
 | 
                        taskId 
 | 
                ); 
 | 
            } 
 | 
//            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.setTaskId(timingTask.getTaskId()); 
 | 
        inspectionTask.setInspectorId(timingTask.getInspectorIds()); 
 | 
        inspectionTask.setInspectionLocation(timingTask.getInspectionLocation()); 
 | 
        inspectionTask.setRemarks("自动生成自定时任务ID: " + timingTask.getId()); 
 | 
        inspectionTask.setRegistrantId(timingTask.getRegistrantId()); 
 | 
        inspectionTask.setFrequencyType(timingTask.getFrequencyType()); 
 | 
        inspectionTask.setFrequencyDetail(timingTask.getFrequencyDetail()); 
 | 
        inspectionTask.setTenantId(timingTask.getTenantId()); 
 | 
  
 | 
        return inspectionTask; 
 | 
    } 
 | 
  
 | 
  
 | 
    /** 
 | 
     * 计算下次执行时间 
 | 
     */ 
 | 
    private LocalDateTime calculateNextExecutionTime(String frequencyType, 
 | 
                                                     String frequencyDetail, 
 | 
                                                     LocalDateTime currentTime) { 
 | 
        try { 
 | 
            switch (frequencyType) { 
 | 
                case "DAILY": 
 | 
                    return calculateDailyNextTime(frequencyDetail, currentTime); 
 | 
                case "WEEKLY": 
 | 
                    return calculateWeeklyNextTime(frequencyDetail, currentTime); 
 | 
                case "MONTHLY": 
 | 
                    return calculateMonthlyNextTime(frequencyDetail, currentTime); 
 | 
                case "QUARTERLY": 
 | 
                    return 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); // 解析格式 "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]); // 时间部分 
 | 
  
 | 
        // 解析星期几(支持多个星期) 
 | 
        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]); 
 | 
  
 | 
        // 计算当前季度 
 | 
        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 { 
 | 
            // 需要到下个季度 
 | 
            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() 
 | 
        ); 
 | 
    } 
 | 
  
 | 
    /** 
 | 
     * 解析星期几字符串 
 | 
     */ 
 | 
    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; 
 | 
    } 
 | 
} 
 |