package com.ruoyi.safe.service.impl;
|
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
import com.baomidou.mybatisplus.core.metadata.IPage;
|
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
import com.ruoyi.common.utils.StringUtils;
|
import com.ruoyi.project.system.domain.SysUser;
|
import com.ruoyi.project.system.mapper.SysUserMapper;
|
import com.ruoyi.safe.mapper.SafeFacilityInspectionTaskMapper;
|
import com.ruoyi.safe.pojo.SafeFacilityInspectionTask;
|
import com.ruoyi.safe.pojo.SafeFacilityLedger;
|
import com.ruoyi.safe.service.SafeFacilityInspectionTaskService;
|
import com.ruoyi.safe.service.SafeFacilityLedgerService;
|
import lombok.RequiredArgsConstructor;
|
import org.quartz.SchedulerException;
|
import org.springframework.stereotype.Service;
|
import org.springframework.transaction.annotation.Transactional;
|
|
import java.time.DayOfWeek;
|
import java.time.LocalDateTime;
|
import java.time.LocalTime;
|
import java.time.YearMonth;
|
import java.time.format.DateTimeFormatter;
|
import java.time.format.DateTimeParseException;
|
import java.util.Arrays;
|
import java.util.HashMap;
|
import java.util.List;
|
import java.util.Map;
|
import java.util.Objects;
|
import java.util.stream.Collectors;
|
|
/**
|
* <p>
|
* 安全生产--安全设施定时巡检任务 服务实现类
|
* </p>
|
*/
|
@Service
|
@RequiredArgsConstructor
|
public class SafeFacilityInspectionTaskServiceImpl extends ServiceImpl<SafeFacilityInspectionTaskMapper, SafeFacilityInspectionTask> implements SafeFacilityInspectionTaskService {
|
|
private static final int ENABLED = 1;
|
private static final DateTimeFormatter TIME_FORMATTER = DateTimeFormatter.ofPattern("HH:mm");
|
private static final Map<String, DayOfWeek> WEEK_DAY_MAP = new HashMap<>();
|
|
static {
|
WEEK_DAY_MAP.put("MON", DayOfWeek.MONDAY);
|
WEEK_DAY_MAP.put("TUE", DayOfWeek.TUESDAY);
|
WEEK_DAY_MAP.put("WED", DayOfWeek.WEDNESDAY);
|
WEEK_DAY_MAP.put("THU", DayOfWeek.THURSDAY);
|
WEEK_DAY_MAP.put("FRI", DayOfWeek.FRIDAY);
|
WEEK_DAY_MAP.put("SAT", DayOfWeek.SATURDAY);
|
WEEK_DAY_MAP.put("SUN", DayOfWeek.SUNDAY);
|
}
|
|
private final SafeFacilityInspectionTaskMapper safeFacilityInspectionTaskMapper;
|
private final SafeFacilityInspectionTaskScheduler safeFacilityInspectionTaskScheduler;
|
private final SafeFacilityLedgerService safeFacilityLedgerService;
|
private final SysUserMapper sysUserMapper;
|
|
@Override
|
public IPage<SafeFacilityInspectionTask> pageSafeFacilityInspectionTask(Page<SafeFacilityInspectionTask> page, SafeFacilityInspectionTask task) {
|
LambdaQueryWrapper<SafeFacilityInspectionTask> queryWrapper = new LambdaQueryWrapper<>();
|
queryWrapper.like(StringUtils.isNotBlank(task.getInspectionName()), SafeFacilityInspectionTask::getInspectionName, task.getInspectionName())
|
.like(StringUtils.isNotBlank(task.getFacilityName()), SafeFacilityInspectionTask::getFacilityName, task.getFacilityName())
|
.like(StringUtils.isNotBlank(task.getFacilityCode()), SafeFacilityInspectionTask::getFacilityCode, task.getFacilityCode())
|
.eq(task.getFacilityId() != null, SafeFacilityInspectionTask::getFacilityId, task.getFacilityId())
|
.eq(task.getIsEnabled() != null, SafeFacilityInspectionTask::getIsEnabled, task.getIsEnabled())
|
.orderByDesc(SafeFacilityInspectionTask::getId);
|
|
IPage<SafeFacilityInspectionTask> result = safeFacilityInspectionTaskMapper.selectPage(page, queryWrapper);
|
fillInspectorName(result.getRecords());
|
return result;
|
}
|
|
@Override
|
@Transactional
|
public boolean saveOrUpdateTask(SafeFacilityInspectionTask task) throws SchedulerException {
|
SafeFacilityInspectionTask oldTask = null;
|
if (task.getId() != null) {
|
oldTask = safeFacilityInspectionTaskMapper.selectById(task.getId());
|
if (oldTask == null) {
|
throw new IllegalArgumentException("定时巡检任务不存在");
|
}
|
}
|
|
normalizeTask(task, oldTask);
|
task.setNextExecutionTime(calculateFirstExecutionTime(task.getFrequencyType(), task.getFrequencyDetail()));
|
|
boolean result;
|
if (task.getId() == null) {
|
result = safeFacilityInspectionTaskMapper.insert(task) > 0;
|
if (result && isEnabled(task.getIsEnabled())) {
|
safeFacilityInspectionTaskScheduler.scheduleTask(task);
|
}
|
return result;
|
}
|
|
result = safeFacilityInspectionTaskMapper.updateById(task) > 0;
|
if (result) {
|
boolean oldEnabled = oldTask != null && isEnabled(oldTask.getIsEnabled());
|
boolean newEnabled = isEnabled(task.getIsEnabled());
|
if (!newEnabled) {
|
safeFacilityInspectionTaskScheduler.unscheduleTask(task.getId());
|
} else if (oldEnabled) {
|
safeFacilityInspectionTaskScheduler.rescheduleTask(task);
|
} else {
|
safeFacilityInspectionTaskScheduler.scheduleTask(task);
|
}
|
}
|
return result;
|
}
|
|
@Override
|
@Transactional
|
public boolean removeTaskByIds(List<Long> ids) {
|
boolean removed = removeBatchByIds(ids);
|
if (removed) {
|
for (Long id : ids) {
|
safeFacilityInspectionTaskScheduler.unscheduleTask(id);
|
}
|
}
|
return removed;
|
}
|
|
@Override
|
public LocalDateTime calculateFirstExecutionTime(String frequencyType, String frequencyDetail) {
|
LocalDateTime now = LocalDateTime.now();
|
return calculateNextExecutionTime(frequencyType, frequencyDetail, now);
|
}
|
|
@Override
|
public LocalDateTime calculateNextExecutionTime(String frequencyType, String frequencyDetail, LocalDateTime currentTime) {
|
validateFrequency(frequencyType, frequencyDetail);
|
return switch (frequencyType) {
|
case "DAILY" -> calculateDailyNextTime(frequencyDetail, currentTime);
|
case "WEEKLY" -> calculateWeeklyNextTime(frequencyDetail, currentTime);
|
case "MONTHLY" -> calculateMonthlyNextTime(frequencyDetail, currentTime);
|
default -> throw new IllegalArgumentException("不支持的频率类型: " + frequencyType);
|
};
|
}
|
|
private void normalizeTask(SafeFacilityInspectionTask task, SafeFacilityInspectionTask oldTask) {
|
if (StringUtils.isBlank(task.getInspectionName())) {
|
throw new IllegalArgumentException("巡检任务名称不能为空");
|
}
|
if (task.getFacilityId() == null) {
|
throw new IllegalArgumentException("请选择安全设施");
|
}
|
if (StringUtils.isBlank(task.getInspectionProject())) {
|
throw new IllegalArgumentException("巡检项目不能为空");
|
}
|
if (task.getInspectorId() == null) {
|
throw new IllegalArgumentException("巡检人不能为空");
|
}
|
|
SafeFacilityLedger ledger = safeFacilityLedgerService.getById(task.getFacilityId());
|
if (ledger == null) {
|
throw new IllegalArgumentException("选择的安全设施不存在");
|
}
|
if ("报废".equals(ledger.getStatus())) {
|
throw new IllegalArgumentException("报废设施不能创建巡检任务");
|
}
|
task.setFacilityCode(ledger.getFacilityCode());
|
task.setFacilityName(ledger.getFacilityName());
|
task.setIsEnabled(resolveEnabledValue(task.getIsEnabled(), oldTask));
|
task.setFrequencyType(task.getFrequencyType() == null ? null : task.getFrequencyType().trim().toUpperCase());
|
task.setFrequencyDetail(task.getFrequencyDetail() == null ? null : task.getFrequencyDetail().trim());
|
validateFrequency(task.getFrequencyType(), task.getFrequencyDetail());
|
}
|
|
private void validateFrequency(String frequencyType, String frequencyDetail) {
|
if (StringUtils.isBlank(frequencyType) || StringUtils.isBlank(frequencyDetail)) {
|
throw new IllegalArgumentException("任务频率不能为空");
|
}
|
switch (frequencyType) {
|
case "DAILY" -> parseTime(frequencyDetail);
|
case "WEEKLY" -> {
|
String[] parts = splitFrequencyDetail(frequencyDetail);
|
if (!WEEK_DAY_MAP.containsKey(parts[0])) {
|
throw new IllegalArgumentException("无效的星期: " + parts[0]);
|
}
|
parseTime(parts[1]);
|
}
|
case "MONTHLY" -> {
|
String[] parts = splitFrequencyDetail(frequencyDetail);
|
validateDayOfMonth(parts[0]);
|
parseTime(parts[1]);
|
}
|
default -> throw new IllegalArgumentException("不支持的频率类型: " + frequencyType);
|
}
|
}
|
|
private LocalDateTime calculateDailyNextTime(String timeStr, LocalDateTime currentTime) {
|
LocalTime executionTime = parseTime(timeStr);
|
LocalDateTime candidate = LocalDateTime.of(currentTime.toLocalDate(), executionTime);
|
return currentTime.isBefore(candidate) ? candidate : candidate.plusDays(1);
|
}
|
|
private LocalDateTime calculateWeeklyNextTime(String detail, LocalDateTime currentTime) {
|
String[] parts = splitFrequencyDetail(detail);
|
DayOfWeek targetDay = WEEK_DAY_MAP.get(parts[0]);
|
LocalTime targetTime = parseTime(parts[1]);
|
int daysUntil = targetDay.getValue() - currentTime.getDayOfWeek().getValue();
|
|
if (daysUntil < 0 || (daysUntil == 0 && !currentTime.toLocalTime().isBefore(targetTime))) {
|
daysUntil += 7;
|
}
|
return LocalDateTime.of(currentTime.toLocalDate().plusDays(daysUntil), targetTime);
|
}
|
|
private LocalDateTime calculateMonthlyNextTime(String detail, LocalDateTime currentTime) {
|
String[] parts = splitFrequencyDetail(detail);
|
int dayOfMonth = validateDayOfMonth(parts[0]);
|
LocalTime targetTime = parseTime(parts[1]);
|
YearMonth currentMonth = YearMonth.from(currentTime);
|
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,
|
targetTime.getHour(),
|
targetTime.getMinute()
|
);
|
if (currentTime.isBefore(candidate)) {
|
return candidate;
|
}
|
}
|
throw new IllegalArgumentException("无法计算下次执行时间");
|
}
|
|
private String[] splitFrequencyDetail(String detail) {
|
String[] parts = detail.split(",");
|
if (parts.length != 2) {
|
throw new IllegalArgumentException("频率详情格式错误");
|
}
|
return Arrays.stream(parts).map(String::trim).toArray(String[]::new);
|
}
|
|
private LocalTime parseTime(String timeStr) {
|
try {
|
return LocalTime.parse(timeStr, TIME_FORMATTER);
|
} catch (DateTimeParseException e) {
|
throw new IllegalArgumentException("时间格式必须为HH:mm", e);
|
}
|
}
|
|
private int validateDayOfMonth(String dayStr) {
|
try {
|
int day = Integer.parseInt(dayStr);
|
if (day < 1 || day > 31) {
|
throw new IllegalArgumentException("日期必须在1-31之间");
|
}
|
return day;
|
} catch (NumberFormatException e) {
|
throw new IllegalArgumentException("日期必须在1-31之间", e);
|
}
|
}
|
|
private Integer resolveEnabledValue(Integer requestEnabled, SafeFacilityInspectionTask oldTask) {
|
if (requestEnabled != null) {
|
return requestEnabled;
|
}
|
if (oldTask != null && oldTask.getIsEnabled() != null) {
|
return oldTask.getIsEnabled();
|
}
|
return ENABLED;
|
}
|
|
private boolean isEnabled(Integer enabledValue) {
|
return Objects.equals(enabledValue, ENABLED);
|
}
|
|
private void fillInspectorName(List<SafeFacilityInspectionTask> records) {
|
if (records == null || records.isEmpty()) {
|
return;
|
}
|
|
List<Long> userIds = records.stream()
|
.map(SafeFacilityInspectionTask::getInspectorId)
|
.filter(Objects::nonNull)
|
.map(Integer::longValue)
|
.distinct()
|
.collect(Collectors.toList());
|
if (userIds.isEmpty()) {
|
return;
|
}
|
|
Map<Long, String> userNameMap = sysUserMapper.selectUserByIds(userIds).stream()
|
.collect(Collectors.toMap(SysUser::getUserId, SysUser::getNickName, (v1, v2) -> v1));
|
for (SafeFacilityInspectionTask record : records) {
|
if (record.getInspectorId() != null) {
|
record.setInspectorName(userNameMap.getOrDefault(record.getInspectorId().longValue(), "未知用户"));
|
}
|
}
|
}
|
}
|