| ¶Ô±ÈÐÂÎļþ |
| | |
| | | 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; |
| | | } |
| | | } |