2 天以前 4f55d3cb4bc644e4534106336f2047af1a4db5df
src/main/java/com/ruoyi/inspectiontask/service/impl/TimingTaskServiceImpl.java
@@ -6,6 +6,8 @@
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;
@@ -35,6 +37,9 @@
    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
@@ -45,6 +50,19 @@
        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. 如果没有数据,直接返回空分页
@@ -80,6 +98,17 @@
            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();
@@ -103,6 +132,11 @@
                dto.setInspector(inspectorNickNames);
            }
            // 设置区域名称
            if (task.getAreaId() != null) {
                dto.setAreaName(areaNameMap.getOrDefault(task.getAreaId(), ""));
            }
            return dto;
        }).collect(Collectors.toList());
@@ -113,10 +147,19 @@
    }
    @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();
@@ -132,13 +175,12 @@
        // 设置创建人信息和默认值
        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);
            }
@@ -148,11 +190,48 @@
            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) {
@@ -289,7 +368,7 @@
    }
    private LocalDateTime calculateCustomFirstExecution(String frequencyDetail) {
        return null;
        return TimingTaskScheduleUtils.calculateFirstExecutionTime("QUARTERLY", frequencyDetail);
    }
    @Override
@@ -395,7 +474,7 @@
    /**
     * 计算每季度任务的下次执行时间
     */
    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]);
@@ -431,6 +510,9 @@
    /**
     * 解析星期几字符串
     */
    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("\\|");
@@ -451,6 +533,26 @@
        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