| | |
| | | package com.ycl.task; |
| | | |
| | | import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; |
| | | import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper; |
| | | import com.baomidou.mybatisplus.extension.conditions.update.LambdaUpdateChainWrapper; |
| | | import com.ycl.common.enums.business.ProcessLogEventTypeEnum; |
| | | import com.ycl.common.enums.business.ProjectProcessTypeEnum; |
| | | import com.ycl.common.utils.DateUtils; |
| | | import com.ycl.domain.entity.ProcessCoding; |
| | | import com.ycl.domain.entity.ProcessLog; |
| | | import com.ycl.domain.entity.ProjectInfo; |
| | | import com.ycl.domain.entity.ProjectProcess; |
| | | import com.ycl.factory.FlowServiceFactory; |
| | | import com.ycl.mapper.ProcessCodingMapper; |
| | | import com.ycl.mapper.ProcessLogMapper; |
| | | import com.ycl.mapper.ProjectInfoMapper; |
| | | import com.ycl.mapper.ProjectProcessMapper; |
| | | import com.ycl.service.ProjectProcessService; |
| | | import com.ycl.service.ProcessCodingService; |
| | | import com.ycl.service.ProcessLogService; |
| | | import lombok.extern.slf4j.Slf4j; |
| | | import org.apache.commons.lang3.StringUtils; |
| | | import org.flowable.task.api.Task; |
| | | import org.flowable.task.api.TaskInfo; |
| | | import org.flowable.task.api.history.HistoricTaskInstance; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.springframework.stereotype.Component; |
| | | import org.springframework.util.CollectionUtils; |
| | | |
| | | import java.util.Date; |
| | | import java.util.List; |
| | | import java.util.Map; |
| | | import java.util.*; |
| | | import java.util.function.Function; |
| | | import java.util.stream.Collectors; |
| | | |
| | | import static com.ycl.common.constant.ProcessOverTimeConstants.*; |
| | | import static com.ycl.common.enums.business.ProcessLogEventTypeEnum.CANCEL_HANGUP; |
| | | import static com.ycl.common.enums.business.ProcessLogEventTypeEnum.HANGUP; |
| | | |
| | | @Slf4j |
| | | @Component("flowableTask") |
| | |
| | | private ProjectProcessMapper projectProcessMapper; |
| | | @Autowired |
| | | private ProjectInfoMapper projectInfoMapper; |
| | | @Autowired |
| | | private ProcessCodingMapper processCodingMapper; |
| | | @Autowired |
| | | private ProcessLogService processLogService; |
| | | @Autowired |
| | | private ProcessLogMapper processLogMapper; |
| | | |
| | | /** |
| | | * 赋码任务 |
| | | * 两个逻辑 改项目码、改节点颜色 |
| | | */ |
| | | public void expireTask() { |
| | | log.info("开始赋码"); |
| | | List<Task> taskList = taskService.createTaskQuery().list(); |
| | | if (!CollectionUtils.isEmpty(taskList)) { |
| | | Date now = new Date(); |
| | | // 按超时状态分组任务 |
| | | Map<Boolean, List<String>> processInstanceMap = taskList.stream() |
| | | .collect(Collectors.groupingBy( |
| | | task -> task.getDueDate() != null && now.after(task.getDueDate()), |
| | | Collectors.mapping(TaskInfo::getProcessInstanceId, Collectors.toList()) |
| | | )); |
| | | // 处理超时和未超时的项目 |
| | | updateProjectCoding(processInstanceMap.get(true), "red"); // 超时项目 |
| | | updateProjectCoding(processInstanceMap.get(false), "green"); // 未超时项目 |
| | | //当前正在运行的所有任务节点 |
| | | List<Task> taskList = taskService.createTaskQuery().active().list(); |
| | | if (CollectionUtils.isEmpty(taskList)) return; |
| | | //排除掉节点挂起的任务 |
| | | List<String> allHangupTask = processLogMapper.getAllHangup(); |
| | | taskList = taskList.stream() |
| | | .filter(task -> !allHangupTask.contains(task.getId())) |
| | | .collect(Collectors.toList()); |
| | | //TODO:筛选出流程实例id,用作项目挂起 |
| | | Set<String> proInsIds = taskList.stream() |
| | | .map(TaskInfo::getProcessInstanceId) |
| | | .collect(Collectors.toSet()); |
| | | //TODO:查询项目挂起日志 |
| | | |
| | | List<String> taskIds = taskList.stream().map(TaskInfo::getId).collect(Collectors.toList()); |
| | | //查询节点挂起日志 |
| | | Map<String, List<ProcessLog>> hangupLogMap = new LambdaQueryChainWrapper<>(processLogMapper) |
| | | .in(ProcessLog::getEventType, HANGUP, CANCEL_HANGUP) |
| | | .in(ProcessLog::getProcessInsId, taskIds) |
| | | .list() |
| | | .stream() |
| | | .collect(Collectors.groupingBy(ProcessLog::getTaskId)); |
| | | |
| | | //需要监控的赋码任务 |
| | | List<ProcessCoding> processCodingList = new LambdaQueryChainWrapper<>(processCodingMapper) |
| | | .in(ProcessCoding::getTaskId, taskIds) |
| | | .list(); |
| | | Map<String, ProcessCoding> taskMap = new HashMap<>(); |
| | | Map<String, Date> startTaskMap = new HashMap<>(); |
| | | if (!CollectionUtils.isEmpty(processCodingList)) { |
| | | //key为taskId value为本体对象 |
| | | taskMap = processCodingList.stream().collect(Collectors.toMap(ProcessCoding::getTaskId, Function.identity())); |
| | | //拿到开始计时的节点集合 key:taskId value:开始时间 |
| | | startTaskMap = getStartTaskList(processCodingList); |
| | | } |
| | | //提前准备接收数据的map key:流程实例id value:需要改变的颜色 |
| | | Map<String, List<String>> map = new HashMap<>(); |
| | | List<ProcessCoding> list = new ArrayList<>(); |
| | | map.put(GREEN, new ArrayList<>()); |
| | | map.put(RED, new ArrayList<>()); |
| | | map.put(YELLOW, new ArrayList<>()); |
| | | Date now = new Date(); |
| | | //遍历所有代办的节点 |
| | | for (Task task : taskList) { |
| | | String taskId = task.getId(); |
| | | ProcessCoding processCoding = taskMap.get(taskId); |
| | | if (processCoding == null) { |
| | | //不需要监控的任务节点项目码直接改为绿色 |
| | | map.get(GREEN).add(task.getProcessInstanceId()); |
| | | continue; |
| | | } |
| | | //判断赋码统一用秒作为单位,且只需用红码时间判断超时,通过超时去改变项目的赋码状态,节点本身无赋码状态 |
| | | Date startTime = startTaskMap.get(processCoding.getStartTaskId()); |
| | | try { |
| | | Long redTime = getTime(processCoding.getRedTime()); |
| | | // Long yellowTime = getTime(processCoding.getYellowTime()); |
| | | // Long overtime = getTime(processCoding.getOvertime()); |
| | | if (startTime == null) continue; |
| | | |
| | | //节点处理时间,需排除节假日 |
| | | long durationTime = DateUtils.getWorkingSed(startTime, now); |
| | | |
| | | //TODO:减去流程挂起时长 |
| | | |
| | | //减去节点挂起时长 |
| | | durationTime = subNodeHangupTime(hangupLogMap, task, durationTime); |
| | | |
| | | String status = GREEN; // 默认状态为绿色 |
| | | String overtimeStatus = NORMAL; |
| | | if (redTime != null && redTime != 0 && durationTime >= redTime) { |
| | | status = RED; // 如果超过红色时间阈值,则表明该任务超时 |
| | | overtimeStatus = OVERTIME; |
| | | } |
| | | // else if (yellowTime != null && yellowTime != 0 && durationTime >= yellowTime) { |
| | | // status = YELLOW; // 否则,如果超过黄色时间阈值,则状态为黄色 |
| | | // } |
| | | // //处理办理期限 |
| | | // String overtimeStatus = NORMAL; |
| | | // if (overtime != null && overtime != 0 && durationTime >= overtime) { |
| | | // overtimeStatus = OVERTIME; // 如果超过办理期限 |
| | | // } else if (overtime != null && overtime != 0 && durationTime >= (overtime - 12 * 60 * 60)) { |
| | | // overtimeStatus = WILLOVERTIME; // 如果临期(固定超时前12小时为临期) |
| | | // } |
| | | // else if (overtime != null && overtime != 0 && durationDay >= (overtime - 60)) { |
| | | // overtimeStatus = WILLOVERTIME; // 如果临期(固定超时前12小时为临期) |
| | | // } |
| | | map.get(status).add(task.getProcessInstanceId()); |
| | | processCoding.setStatus(status); |
| | | processCoding.setOvertimeStatus(overtimeStatus); |
| | | processCoding.setStartTaskTime(task.getCreateTime()); |
| | | list.add(processCoding); |
| | | } catch (Exception e) { |
| | | log.error(e.getMessage(), "赋码时间格式有误"); |
| | | } |
| | | } |
| | | //更新项目码 |
| | | map.forEach((key, value) -> updateProjectCoding(value, key)); |
| | | //更新节点状态 自定义的mybatis方法 |
| | | if (!CollectionUtils.isEmpty(list)) processCodingMapper.updateBatch(list); |
| | | |
| | | log.info("结束赋码"); |
| | | } |
| | | |
| | | //减去节点挂起时长 |
| | | private long subNodeHangupTime(Map<String, List<ProcessLog>> hangupLogMap, Task task, long durationTime) { |
| | | List<ProcessLog> processLogs = hangupLogMap.get(task.getId()); |
| | | if (!CollectionUtils.isEmpty(processLogs)) { |
| | | long hangupTime = 0; |
| | | //分组分为挂起和取消挂起 |
| | | Map<ProcessLogEventTypeEnum, List<ProcessLog>> logEventTypeMap = processLogs.stream() |
| | | .sorted(Comparator.comparing(ProcessLog::getGmtCreate)) |
| | | .collect(Collectors.groupingBy(ProcessLog::getEventType)); |
| | | List<ProcessLog> cancelHangup = logEventTypeMap.get(CANCEL_HANGUP); |
| | | for (int i = 0; i < cancelHangup.size(); i++) { |
| | | ProcessLog processLog = cancelHangup.get(i); |
| | | hangupTime += processLog.getGmtCreate().getTime() - logEventTypeMap.get(HANGUP).get(i).getGmtCreate().getTime(); |
| | | } |
| | | durationTime = durationTime - hangupTime; |
| | | } |
| | | return durationTime; |
| | | } |
| | | |
| | | private Long getTime(String timeStr) { |
| | | Long time = null; |
| | | if (StringUtils.isNotBlank(timeStr)) { |
| | | String[] timeArr = timeStr.split("-"); |
| | | // 解析天数和小时数 |
| | | int days = Integer.parseInt(timeArr[0]); |
| | | int hours = 0; |
| | | if (timeArr.length > 1) { |
| | | hours = Integer.parseInt(timeArr[1]); |
| | | } |
| | | time = (days * 24L + hours) * 3600L; |
| | | // //分-秒 |
| | | // time= (days * 60L) + hours; |
| | | } |
| | | return time; |
| | | } |
| | | |
| | | private Map<String, Date> getStartTaskList(List<ProcessCoding> processCodingList) { |
| | | //查出任务计时起始节点集合 |
| | | List<String> startTaskIds = processCodingList.stream().map(ProcessCoding::getStartTaskId).collect(Collectors.toList()); |
| | | //查出起始计时节点数据 |
| | | Map<String, Date> startDateMap = new HashMap<>(); |
| | | List<HistoricTaskInstance> hisStartTasks = historyService.createHistoricTaskInstanceQuery().taskIds(startTaskIds).list(); |
| | | if (!CollectionUtils.isEmpty(hisStartTasks)) { |
| | | hisStartTasks.forEach(hisTask -> { |
| | | startDateMap.put(hisTask.getId(), hisTask.getStartTime()); |
| | | }); |
| | | } |
| | | return startDateMap; |
| | | } |
| | | |
| | | /** |
| | |
| | | return; |
| | | } |
| | | |
| | | List<Long> projectIds = projectProcessMapper.selectList( |
| | | new QueryWrapper<ProjectProcess>() |
| | | .in("process_ins_id", processInstanceIds) |
| | | ).stream() |
| | | List<String> projectIds = new LambdaQueryChainWrapper<>(projectProcessMapper) |
| | | .in(ProjectProcess::getProcessInsId, processInstanceIds) |
| | | .eq(ProjectProcess::getProjectType, ProjectProcessTypeEnum.PROJECT) |
| | | .list() |
| | | .stream() |
| | | .map(ProjectProcess::getProjectId) |
| | | .collect(Collectors.toList()); |
| | | |