| | |
| | | import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; |
| | | import com.ruoyi.common.utils.StringUtils; |
| | | import com.ruoyi.common.utils.bean.BeanUtils; |
| | | import com.ruoyi.device.mapper.DeviceAreaMapper; |
| | | import com.ruoyi.device.pojo.DeviceArea; |
| | | import com.ruoyi.inspectiontask.dto.TimingTaskDto; |
| | | import com.ruoyi.inspectiontask.mapper.TimingTaskMapper; |
| | | import com.ruoyi.inspectiontask.pojo.TimingTask; |
| | |
| | | private final TimingTaskMapper timingTaskMapper; |
| | | private final TimingTaskScheduler timingTaskScheduler; |
| | | private final SysUserMapper sysUserMapper; |
| | | private final DeviceAreaMapper deviceAreaMapper; |
| | | private static final int ENABLED = 1; |
| | | private static final int DISABLED = 0; |
| | | |
| | | |
| | | @Override |
| | |
| | | if (StringUtils.isNotBlank(timingTask.getTaskName())) { |
| | | queryWrapper.like(TimingTask::getTaskName, timingTask.getTaskName()); |
| | | } |
| | | if (StringUtils.isNotBlank(timingTask.getInspectionProject())) { |
| | | queryWrapper.like(TimingTask::getInspectionProject, timingTask.getInspectionProject()); |
| | | } |
| | | if (timingTask.getIsEnabled() != null) { |
| | | queryWrapper.eq(TimingTask::getIsEnabled, timingTask.getIsEnabled()); |
| | | } |
| | | if (timingTask.getAreaId() != null) { |
| | | queryWrapper.eq(TimingTask::getAreaId, timingTask.getAreaId()); |
| | | } |
| | | if (StringUtils.isNotBlank(timingTask.getTaskIdsStr())) { |
| | | queryWrapper.like(TimingTask::getTaskIdsStr, timingTask.getTaskIdsStr()); |
| | | } |
| | | queryWrapper.orderByDesc(TimingTask::getCreateTime); |
| | | IPage<TimingTask> taskPage = timingTaskMapper.selectPage(page, queryWrapper); |
| | | |
| | | // 2. 如果没有数据,直接返回空分页 |
| | |
| | | users.forEach(user -> userNickNameMap.put(user.getUserId(), user.getNickName())); |
| | | } |
| | | |
| | | // 4.1 批量查询区域名称 |
| | | Set<Long> areaIds = taskPage.getRecords().stream() |
| | | .map(TimingTask::getAreaId) |
| | | .filter(Objects::nonNull) |
| | | .collect(Collectors.toSet()); |
| | | Map<Long, String> areaNameMap = new HashMap<>(); |
| | | if (!areaIds.isEmpty()) { |
| | | List<DeviceArea> areas = deviceAreaMapper.selectBatchIds(new ArrayList<>(areaIds)); |
| | | areas.forEach(area -> areaNameMap.put(area.getId(), area.getAreaName())); |
| | | } |
| | | |
| | | // 5. 转换为DTO |
| | | List<TimingTaskDto> dtoList = taskPage.getRecords().stream().map(task -> { |
| | | TimingTaskDto dto = new TimingTaskDto(); |
| | |
| | | dto.setInspector(inspectorNickNames); |
| | | } |
| | | |
| | | // 设置区域名称 |
| | | if (task.getAreaId() != null) { |
| | | dto.setAreaName(areaNameMap.getOrDefault(task.getAreaId(), "")); |
| | | } |
| | | |
| | | return dto; |
| | | }).collect(Collectors.toList()); |
| | | |
| | |
| | | } |
| | | |
| | | @Override |
| | | @Transactional |
| | | @Transactional(rollbackFor = Exception.class) |
| | | public int addOrEditTimingTask(TimingTaskDto timingTaskDto) throws SchedulerException { |
| | | TimingTask oldTimingTask = null; |
| | | if (Objects.nonNull(timingTaskDto.getId())) { |
| | | oldTimingTask = timingTaskMapper.selectById(timingTaskDto.getId()); |
| | | if (oldTimingTask == null) { |
| | | throw new IllegalArgumentException("定时任务不存在"); |
| | | } |
| | | } |
| | | TimingTask timingTask = new TimingTask(); |
| | | BeanUtils.copyProperties(timingTaskDto, timingTask); |
| | | timingTask.setIsEnabled(resolveEnabledValue(timingTask.getIsEnabled(), oldTimingTask)); |
| | | timingTask.setActive(ENABLED == timingTask.getIsEnabled()); |
| | | // 1. 解析字符串为 LocalDate(只包含年月日) |
| | | DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd"); |
| | | LocalDate localDate = LocalDate.now(); |
| | |
| | | // 设置创建人信息和默认值 |
| | | if (Objects.isNull(timingTaskDto.getId())) { |
| | | timingTask.setRegistrationDate(LocalDate.now()); |
| | | timingTask.setActive(true); |
| | | |
| | | // 计算首次执行时间 |
| | | LocalDateTime firstExecutionTime = calculateFirstExecutionTime(timingTask); |
| | | timingTask.setNextExecutionTime(firstExecutionTime); |
| | | int result = timingTaskMapper.insert(timingTask); |
| | | if (result > 0) { |
| | | if (result > 0 && isEnabled(timingTask.getIsEnabled(), timingTask.isActive())) { |
| | | // 新增成功后添加到调度器 |
| | | timingTaskScheduler.scheduleTimingTask(timingTask); |
| | | } |
| | |
| | | |
| | | int result = timingTaskMapper.updateById(timingTask); |
| | | if (result > 0) { |
| | | // 更新成功后重新调度任务 |
| | | timingTaskScheduler.rescheduleTimingTask(timingTask); |
| | | boolean oldEnabled = isEnabled(oldTimingTask == null ? null : oldTimingTask.getIsEnabled(), oldTimingTask != null && oldTimingTask.isActive()); |
| | | boolean newEnabled = isEnabled(timingTask.getIsEnabled(), timingTask.isActive()); |
| | | if (!newEnabled) { |
| | | timingTaskScheduler.unscheduleTimingTask(timingTask.getId()); |
| | | } else if (oldEnabled) { |
| | | // 更新成功后重新调度任务 |
| | | timingTaskScheduler.rescheduleTimingTask(timingTask); |
| | | } else { |
| | | // 从禁用改为启用时重新创建调度任务 |
| | | timingTaskScheduler.scheduleTimingTask(timingTask); |
| | | } |
| | | } |
| | | return result; |
| | | } |
| | | } |
| | | |
| | | @Override |
| | | @Transactional(rollbackFor = Exception.class) |
| | | public int changeEnable(Long id, Integer isEnabled) throws SchedulerException { |
| | | TimingTask oldTimingTask = timingTaskMapper.selectById(id); |
| | | if (oldTimingTask == null) { |
| | | throw new IllegalArgumentException("定时任务不存在"); |
| | | } |
| | | TimingTask update = new TimingTask(); |
| | | update.setId(id); |
| | | update.setIsEnabled(resolveEnabledValue(isEnabled, oldTimingTask)); |
| | | update.setActive(ENABLED == update.getIsEnabled()); |
| | | |
| | | int result = timingTaskMapper.updateById(update); |
| | | if (result <= 0) { |
| | | return result; |
| | | } |
| | | |
| | | boolean enabled = isEnabled(update.getIsEnabled(), update.isActive()); |
| | | if (!enabled) { |
| | | timingTaskScheduler.unscheduleTimingTask(id); |
| | | } else if (oldTimingTask.getIsEnabled() != null && oldTimingTask.getIsEnabled() == DISABLED) { |
| | | timingTaskScheduler.scheduleTimingTask(oldTimingTask); |
| | | } else { |
| | | timingTaskScheduler.resumeTimingTask(id); |
| | | } |
| | | return result; |
| | | } |
| | | |
| | | public LocalDateTime calculateFirstExecutionTime(TimingTask task) { |
| | |
| | | } |
| | | |
| | | private LocalDateTime calculateCustomFirstExecution(String frequencyDetail) { |
| | | return null; |
| | | return TimingTaskScheduleUtils.calculateFirstExecutionTime("QUARTERLY", frequencyDetail); |
| | | } |
| | | |
| | | @Override |
| | |
| | | /** |
| | | * 计算每季度任务的下次执行时间 |
| | | */ |
| | | private LocalDateTime calculateQuarterlyNextTime(String detail, LocalDateTime current) { |
| | | private LocalDateTime calculateQuarterlyNextTimeLegacy(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]); |
| | |
| | | /** |
| | | * 解析星期几字符串 |
| | | */ |
| | | private LocalDateTime calculateQuarterlyNextTime(String detail, LocalDateTime current) { |
| | | return TimingTaskScheduleUtils.calculateNextExecutionTime("QUARTERLY", detail, current); |
| | | } |
| | | private Set<DayOfWeek> parseDayOfWeeks(String dayOfWeekStr) { |
| | | Set<DayOfWeek> days = new HashSet<>(); |
| | | String[] dayStrs = dayOfWeekStr.split("\\|"); |
| | |
| | | return days; |
| | | } |
| | | |
| | | private Integer resolveEnabledValue(Integer requestEnabled, TimingTask oldTimingTask) { |
| | | if (requestEnabled != null) { |
| | | return requestEnabled; |
| | | } |
| | | if (oldTimingTask != null) { |
| | | if (oldTimingTask.getIsEnabled() != null) { |
| | | return oldTimingTask.getIsEnabled(); |
| | | } |
| | | return oldTimingTask.isActive() ? ENABLED : DISABLED; |
| | | } |
| | | return ENABLED; |
| | | } |
| | | |
| | | private boolean isEnabled(Integer enabledValue, boolean activeFallback) { |
| | | if (enabledValue != null) { |
| | | return ENABLED == enabledValue; |
| | | } |
| | | return activeFallback; |
| | | } |
| | | |
| | | |
| | | |
| | | @Override |