package com.ruoyi.safe.service.impl; import com.ruoyi.common.utils.StringUtils; import com.ruoyi.safe.mapper.SafeLineInspectionMapper; import com.ruoyi.safe.mapper.SafeLineInspectionTaskMapper; import com.ruoyi.safe.pojo.SafeLineInspection; import com.ruoyi.safe.pojo.SafeLineInspectionTask; import org.quartz.DisallowConcurrentExecution; import org.quartz.Job; import org.quartz.JobDataMap; import org.quartz.JobExecutionContext; import org.quartz.JobExecutionException; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import java.io.Serializable; import java.time.DayOfWeek; import java.time.LocalDateTime; import java.time.LocalTime; import java.time.YearMonth; import java.time.format.DateTimeFormatter; import java.util.HashSet; import java.util.Set; @Component @DisallowConcurrentExecution public class SafeLineInspectionTaskJob implements Job, Serializable { private static final long serialVersionUID = 1L; private static final DateTimeFormatter CODE_FORMATTER = DateTimeFormatter.ofPattern("yyyyMMddHHmmss"); @Autowired private SafeLineInspectionTaskMapper safeLineInspectionTaskMapper; @Autowired private SafeLineInspectionMapper safeLineInspectionMapper; @Override public void execute(JobExecutionContext context) throws JobExecutionException { JobDataMap jobDataMap = context.getJobDetail().getJobDataMap(); Long taskId = jobDataMap.getLong("taskId"); try { SafeLineInspectionTask task = safeLineInspectionTaskMapper.selectById(taskId); if (task == null || Integer.valueOf(0).equals(task.getIsEnabled())) { return; } LocalDateTime executionTime = LocalDateTime.now(); SafeLineInspection inspection = createLineInspection(task, executionTime); safeLineInspectionMapper.insert(inspection); task.setLastExecutionTime(executionTime); task.setNextExecutionTime(calculateNextExecutionTime( task.getFrequencyType(), task.getFrequencyDetail(), executionTime )); safeLineInspectionTaskMapper.updateById(task); } catch (Exception e) { throw new JobExecutionException(e); } } private SafeLineInspection createLineInspection(SafeLineInspectionTask task, LocalDateTime executionTime) { SafeLineInspection inspection = new SafeLineInspection(); inspection.setScheduleTaskId(task.getId()); inspection.setInspectionCode("XLXJ-" + executionTime.format(CODE_FORMATTER) + "-" + task.getId()); inspection.setInspectionName(task.getInspectionName()); inspection.setLineName(task.getLineName()); inspection.setInspectionType("定期巡检"); inspection.setInspectionProject(task.getInspectionProject()); inspection.setPlanTime(task.getNextExecutionTime() != null ? task.getNextExecutionTime() : executionTime); inspection.setAssignUserId(task.getCreateUser()); inspection.setInspectorId(task.getInspectorId()); inspection.setStatus("待巡检"); inspection.setRemark(buildRemark(task)); inspection.setCreateUser(task.getCreateUser()); inspection.setUpdateUser(task.getCreateUser()); inspection.setCreateTime(executionTime); inspection.setUpdateTime(executionTime); inspection.setTenantId(task.getTenantId() == null ? null : task.getTenantId().intValue()); inspection.setDeptId(task.getDeptId()); return inspection; } private String buildRemark(SafeLineInspectionTask task) { String remark = "自动生成自定时任务ID: " + task.getId(); if (StringUtils.isNotBlank(task.getRemark())) { remark = remark + ";" + task.getRemark(); } return remark; } private LocalDateTime calculateNextExecutionTime(String frequencyType, String frequencyDetail, LocalDateTime currentTime) { return switch (frequencyType) { case "DAILY" -> calculateDailyNextTime(frequencyDetail, currentTime); case "WEEKLY" -> calculateWeeklyNextTime(frequencyDetail, currentTime); case "MONTHLY" -> calculateMonthlyNextTime(frequencyDetail, currentTime); default -> throw new IllegalArgumentException("不支持的频率类型: " + frequencyType); }; } private LocalDateTime calculateDailyNextTime(String timeStr, LocalDateTime current) { LocalTime executionTime = LocalTime.parse(timeStr); 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(","); LocalTime time = LocalTime.parse(parts[1].trim()); Set targetDays = parseDayOfWeeks(parts[0]); 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].trim()); LocalTime time = LocalTime.parse(parts[1].trim()); YearMonth currentMonth = YearMonth.from(current); for (int i = 0; i < 24; i++) { YearMonth targetMonth = currentMonth.plusMonths(i); if (dayOfMonth > targetMonth.lengthOfMonth()) { continue; } LocalDateTime candidate = LocalDateTime.of( targetMonth.getYear(), targetMonth.getMonthValue(), dayOfMonth, time.getHour(), time.getMinute() ); if (current.isBefore(candidate)) { return candidate; } } throw new IllegalArgumentException("无法计算下次执行时间"); } private Set parseDayOfWeeks(String dayOfWeekStr) { Set days = new HashSet<>(); String[] dayStrs = dayOfWeekStr.split("\\|"); for (String dayStr : dayStrs) { switch (dayStr.trim()) { case "MON" -> days.add(DayOfWeek.MONDAY); case "TUE" -> days.add(DayOfWeek.TUESDAY); case "WED" -> days.add(DayOfWeek.WEDNESDAY); case "THU" -> days.add(DayOfWeek.THURSDAY); case "FRI" -> days.add(DayOfWeek.FRIDAY); case "SAT" -> days.add(DayOfWeek.SATURDAY); case "SUN" -> days.add(DayOfWeek.SUNDAY); default -> throw new IllegalArgumentException("无效的星期几: " + dayStr); } } return days; } }