package com.ruoyi.device.service.impl;
|
|
import com.ruoyi.device.mapper.DeviceLedgerMapper;
|
import com.ruoyi.device.pojo.DeviceLedger;
|
import com.ruoyi.device.pojo.DeviceMaintenance;
|
import com.ruoyi.device.pojo.MaintenanceTask;
|
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.jdbc.core.BeanPropertyRowMapper;
|
import org.springframework.jdbc.core.JdbcTemplate;
|
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.util.Arrays;
|
import java.util.ArrayList;
|
import java.util.HashSet;
|
import java.util.List;
|
import java.util.Set;
|
|
@Component
|
@DisallowConcurrentExecution
|
public class MaintenanceTaskJob implements Job, Serializable {
|
private static final long serialVersionUID = 1L;
|
|
@Autowired
|
private DeviceMaintenanceServiceImpl deviceMaintenanceService;
|
|
@Autowired
|
private JdbcTemplate jdbcTemplate;
|
|
@Autowired
|
private DeviceLedgerMapper deviceLedgerMapper;
|
|
@Override
|
public void execute(JobExecutionContext context) throws JobExecutionException {
|
JobDataMap jobDataMap = context.getJobDetail().getJobDataMap();
|
Long taskId = jobDataMap.getLong("maintenanceTaskId");
|
|
try {
|
String yourSql = "SELECT * FROM maintenance_task where id = ?";
|
List<MaintenanceTask> tasks = jdbcTemplate.query(
|
yourSql,
|
new BeanPropertyRowMapper<>(MaintenanceTask.class),
|
taskId
|
);
|
MaintenanceTask timingTask = tasks.isEmpty() ? null : tasks.get(0);
|
if (timingTask == null) {
|
throw new JobExecutionException("MaintenanceTaskJob找不到定时任务 " + taskId);
|
}
|
|
List<Long> deviceIds = resolveDeviceIds(timingTask);
|
List<DeviceMaintenance> maintenanceList = new ArrayList<>();
|
for (Long deviceId : deviceIds) {
|
int quantity = resolveQuantity(deviceId);
|
for (int i = 0; i < quantity; i++) {
|
maintenanceList.add(createInspectionTask(timingTask, deviceId));
|
}
|
}
|
deviceMaintenanceService.saveBatch(maintenanceList);
|
|
if (!tasks.isEmpty()) {
|
MaintenanceTask task = tasks.get(0);
|
LocalDateTime lastExecutionTime = LocalDateTime.now();
|
LocalDateTime nextExecutionTime = calculateNextExecutionTime(
|
task.getFrequencyType(),
|
task.getFrequencyDetail(),
|
lastExecutionTime
|
);
|
|
String updateSql = "UPDATE maintenance_task SET last_execution_time = ?, next_execution_time = ? WHERE id = ?";
|
jdbcTemplate.update(updateSql, lastExecutionTime, nextExecutionTime, taskId);
|
}
|
} catch (Exception e) {
|
throw new JobExecutionException(e);
|
}
|
}
|
|
private DeviceMaintenance createInspectionTask(MaintenanceTask timingTask, Long deviceLedgerId) {
|
DeviceMaintenance inspectionTask = new DeviceMaintenance();
|
DeviceLedger deviceLedger = deviceLedgerMapper.selectById(deviceLedgerId);
|
inspectionTask.setDeviceName(deviceLedger != null ? deviceLedger.getDeviceName() : timingTask.getTaskName());
|
inspectionTask.setMaintenanceTaskId(timingTask.getId());
|
inspectionTask.setDeviceLedgerId(deviceLedgerId);
|
inspectionTask.setAreaId(timingTask.getAreaId() != null ? timingTask.getAreaId() : (deviceLedger != null ? deviceLedger.getAreaId() : null));
|
inspectionTask.setMaintenancePlanTime(LocalDateTime.now());
|
inspectionTask.setFrequencyType(timingTask.getFrequencyType());
|
inspectionTask.setFrequencyDetail(timingTask.getFrequencyDetail());
|
inspectionTask.setTenantId(timingTask.getTenantId());
|
inspectionTask.setStatus(0);
|
inspectionTask.setDeviceModel(deviceLedger != null ? deviceLedger.getDeviceModel() : timingTask.getDeviceModel());
|
inspectionTask.setCreateUser(Integer.parseInt(timingTask.getRegistrantId().toString()));
|
inspectionTask.setUpdateTime(LocalDateTime.now());
|
inspectionTask.setCreateTime(LocalDateTime.now());
|
inspectionTask.setUpdateUser(Integer.parseInt(timingTask.getRegistrantId().toString()));
|
return inspectionTask;
|
}
|
|
private List<Long> resolveDeviceIds(MaintenanceTask timingTask) {
|
if (timingTask.getDeviceLedgerIdsStr() != null && !timingTask.getDeviceLedgerIdsStr().trim().isEmpty()) {
|
return Arrays.stream(timingTask.getDeviceLedgerIdsStr().split(","))
|
.map(String::trim)
|
.filter(item -> !item.isEmpty())
|
.map(Long::valueOf)
|
.distinct()
|
.collect(java.util.stream.Collectors.toList());
|
}
|
List<Long> ids = new ArrayList<>();
|
if (timingTask.getTaskId() != null) {
|
ids.add(timingTask.getTaskId());
|
}
|
return ids;
|
}
|
|
private int resolveQuantity(Long deviceLedgerId) {
|
try {
|
String sql = "SELECT number FROM device_ledger WHERE id = ?";
|
Number quantity = jdbcTemplate.queryForObject(sql, Number.class, deviceLedgerId);
|
return quantity == null || quantity.intValue() < 1 ? 1 : quantity.intValue();
|
} catch (Exception ignored) {
|
return 1;
|
}
|
}
|
|
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);
|
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];
|
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]);
|
return current.plusMonths(1)
|
.withDayOfMonth(Math.min(dayOfMonth, current.plusMonths(1).toLocalDate().lengthOfMonth()))
|
.with(time);
|
}
|
|
private LocalDateTime calculateQuarterlyNextTime(String detail, LocalDateTime current) {
|
String[] parts = detail.split(",");
|
int quarterMonth = Integer.parseInt(parts[0]);
|
int dayOfMonth = Integer.parseInt(parts[1]);
|
LocalTime time = LocalTime.parse(parts[2]);
|
|
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;
|
}
|
}
|