| | |
| | | import com.alibaba.fastjson2.TypeReference; |
| | | 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.baomidou.mybatisplus.extension.plugins.pagination.Page; |
| | | import com.ycl.common.base.Result; |
| | | import com.ycl.common.constant.ProcessConstants; |
| | | import com.ycl.common.core.domain.AjaxResult; |
| | | import com.ycl.common.core.domain.entity.SysDept; |
| | |
| | | import com.ycl.domain.dto.FlowTaskDto; |
| | | import com.ycl.domain.dto.FlowViewerDto; |
| | | import com.ycl.domain.entity.ProcessCoding; |
| | | import com.ycl.domain.entity.ProcessLog; |
| | | import com.ycl.domain.entity.ProjectProcess; |
| | | import com.ycl.domain.entity.SysForm; |
| | | import com.ycl.domain.form.EditFinishedTaskForm; |
| | | import com.ycl.domain.json.RejectData; |
| | | import com.ycl.domain.vo.FlowQueryVo; |
| | | import com.ycl.domain.vo.FlowTaskVo; |
| | | import com.ycl.domain.vo.FormDetailVO; |
| | | import com.ycl.domain.query.ProcessLogQuery; |
| | | import com.ycl.domain.vo.*; |
| | | import com.ycl.event.event.TaskLogEvent; |
| | | import com.ycl.factory.FlowServiceFactory; |
| | | import com.ycl.flow.CustomProcessDiagramGenerator; |
| | |
| | | import org.flowable.bpmn.model.*; |
| | | import org.flowable.common.engine.api.FlowableException; |
| | | import org.flowable.common.engine.api.FlowableObjectNotFoundException; |
| | | import org.flowable.common.engine.impl.persistence.StrongUuidGenerator; |
| | | import org.flowable.engine.ProcessEngineConfiguration; |
| | | import org.flowable.engine.history.HistoricActivityInstance; |
| | | import org.flowable.engine.history.HistoricProcessInstance; |
| | |
| | | import org.flowable.task.api.TaskQuery; |
| | | import org.flowable.task.api.history.HistoricTaskInstance; |
| | | import org.flowable.task.api.history.HistoricTaskInstanceQuery; |
| | | import org.springframework.beans.BeanUtils; |
| | | import org.springframework.context.ApplicationEventPublisher; |
| | | import org.springframework.stereotype.Service; |
| | | import org.springframework.transaction.annotation.Transactional; |
| | | |
| | | import java.io.InputStream; |
| | | import java.io.*; |
| | | import java.lang.reflect.Field; |
| | | import java.nio.charset.StandardCharsets; |
| | | import java.util.*; |
| | |
| | | * |
| | | * @param taskId 任务id |
| | | * @param variables 表单数据 |
| | | * @param addLog |
| | | * @return |
| | | */ |
| | | @Override |
| | | @Transactional(rollbackFor = Exception.class) |
| | | public AjaxResult completeSubmitForm(String taskId, Map<String, Object> variables) { |
| | | public AjaxResult completeSubmitForm(String taskId, Map<String, Object> variables, Boolean addLog) { |
| | | Task task = taskService.createTaskQuery().taskId(taskId).singleResult(); |
| | | if (Objects.isNull(task)) { |
| | | return AjaxResult.error("任务不存在"); |
| | |
| | | return AjaxResult.error("项目流程未绑定"); |
| | | } |
| | | |
| | | Map<String, Object> processVariables = new HashMap<>(); |
| | | //查出字典中需要注入的字段信息 |
| | | // 查出字典中需要注入的字段信息 |
| | | List<String> dictList = sysDictDService.selectDictDataByType("flow_variables").stream().map(SysDictData::getDictValue).collect(Collectors.toList()); |
| | | Map<String, Object> newV = new HashMap<>(2); |
| | | if (!org.springframework.util.CollectionUtils.isEmpty(variables)) { |
| | | for (String key : variables.keySet()) { |
| | | newV.put(task.getTaskDefinitionKey() + "&" + key, variables.get(key)); |
| | | //字典里有就放入流程变量中 |
| | | // 字典里有就不做处理 |
| | | if (!CollectionUtils.isEmpty(dictList) && dictList.contains(key)) { |
| | | processVariables.put(key,variables.get(key)); |
| | | newV.put(key,variables.get(key)); |
| | | } |
| | | } |
| | | } |
| | | //添加流程变量 |
| | | if(!processVariables.isEmpty()) taskService.setVariables(taskId,processVariables); |
| | | taskService.addComment(taskId, task.getProcessInstanceId(), FlowComment.SUBMIT.getType(), "完成提交"); |
| | | if (DelegationState.PENDING.equals(task.getDelegationState())) { |
| | | taskService.resolveTask(taskId, newV); |
| | |
| | | taskService.complete(taskId, newV); |
| | | } |
| | | // 保存日志 |
| | | if (addLog) { |
| | | publisher.publishEvent(new TaskLogEvent(this, null, |
| | | SecurityUtils.getUserId(), |
| | | projectProcess.getProjectId(), |
| | | projectProcess.getProcessInsId(), |
| | | taskId, |
| | | task.getTaskDefinitionKey(), |
| | | task.getName(), |
| | | ProcessLogEventTypeEnum.FINISHED, |
| | | null)); |
| | | } |
| | | return AjaxResult.success("提交成功"); |
| | | } |
| | | |
| | | |
| | | /** |
| | | * 容缺补交 |
| | | * |
| | | * @param taskId 任务id |
| | | * @param variables 表单数据 |
| | | * @param addLog |
| | | * @return |
| | | */ |
| | | @Override |
| | | @Transactional(rollbackFor = Exception.class) |
| | | public AjaxResult waitCompleteSubmitForm(String taskId, Map<String, Object> variables, Boolean addLog) throws IOException { |
| | | List<HistoricTaskInstance> hisTasks = historyService.createHistoricTaskInstanceQuery().taskId(taskId).orderByHistoricTaskInstanceStartTime().desc().list(); |
| | | if (CollectionUtils.isEmpty(hisTasks) || Objects.isNull(hisTasks.get(0))) { |
| | | return AjaxResult.error("任务不存在"); |
| | | } |
| | | HistoricTaskInstance task = hisTasks.get(0); |
| | | ProjectProcess projectProcess = new LambdaQueryChainWrapper<>(projectProcessMapper) |
| | | .eq(ProjectProcess::getProcessInsId, task.getProcessInstanceId()) |
| | | .eq(ProjectProcess::getProcessDefId, task.getProcessDefinitionId()) |
| | | .one(); |
| | | if (Objects.isNull(projectProcess)) { |
| | | return AjaxResult.error("项目流程未绑定"); |
| | | } |
| | | // 查出字典中需要注入的字段信息 |
| | | List<String> dictList = sysDictDService.selectDictDataByType("flow_variables").stream().map(SysDictData::getDictValue).collect(Collectors.toList()); |
| | | Map<String, Object> newV = new HashMap<>(2); |
| | | if (!org.springframework.util.CollectionUtils.isEmpty(variables)) { |
| | | for (String key : variables.keySet()) { |
| | | newV.put(task.getTaskDefinitionKey() + "&" + key, variables.get(key)); |
| | | // 字典里有就不做处理 |
| | | if (!CollectionUtils.isEmpty(dictList) && dictList.contains(key)) { |
| | | newV.put(key,variables.get(key)); |
| | | } |
| | | } |
| | | } |
| | | ProcessInstance processInstance = runtimeService.createProcessInstanceQuery().processInstanceId(task.getProcessInstanceId()).singleResult(); |
| | | Date now = new Date(); |
| | | for (String key : newV.keySet()) { |
| | | FlowableVarVO var = null; |
| | | if (Objects.isNull(processInstance)) { |
| | | // 查询历史流程变量 |
| | | var = projectProcessMapper.getHisByteId(projectProcess.getProcessInsId(), key); |
| | | } else { |
| | | // 查询运行时流程变量 |
| | | var = projectProcessMapper.getRuByteId(projectProcess.getProcessInsId(), key); |
| | | } |
| | | |
| | | if (Objects.isNull(var)) { |
| | | // 没有这个变量新增即可 |
| | | FlowableVarVO run = new FlowableVarVO(); |
| | | FlowableVarVO v = new FlowableVarVO(); |
| | | v.setNAME_(key); |
| | | v.setPROC_INST_ID_(task.getProcessInstanceId()); |
| | | v.setEXECUTION_ID_(task.getProcessInstanceId()); |
| | | v.setCREATE_TIME_(now); |
| | | v.setLAST_UPDATED_TIME_(now); |
| | | v.setID_(new StrongUuidGenerator().getNextId()); |
| | | |
| | | BeanUtils.copyProperties(v, run); |
| | | run.setID_(new StrongUuidGenerator().getNextId()); |
| | | if (newV.get(key) instanceof String) { |
| | | v.setVAR_TYPE_("string"); |
| | | v.setTEXT_((String) newV.get(key)); |
| | | run.setVAR_TYPE_("string"); |
| | | run.setTEXT_((String) newV.get(key)); |
| | | } else if (newV.get(key) instanceof Integer) { |
| | | v.setVAR_TYPE_("integer"); |
| | | v.setLONG_((Long) newV.get(key)); |
| | | v.setTEXT_((String) newV.get(key)); |
| | | run.setVAR_TYPE_("integer"); |
| | | run.setLONG_((Long) newV.get(key)); |
| | | run.setTEXT_((String) newV.get(key)); |
| | | } else if (newV.get(key) instanceof Long) { |
| | | v.setVAR_TYPE_("long"); |
| | | v.setLONG_((Long) newV.get(key)); |
| | | v.setTEXT_((String) newV.get(key)); |
| | | run.setVAR_TYPE_("long"); |
| | | run.setLONG_((Long) newV.get(key)); |
| | | run.setTEXT_((String) newV.get(key)); |
| | | } else if (newV.get(key) instanceof Boolean) { |
| | | v.setVAR_TYPE_("boolean"); |
| | | v.setLONG_((Long) newV.get(key)); |
| | | v.setTEXT_((String) newV.get(key)); |
| | | run.setVAR_TYPE_("boolean"); |
| | | run.setLONG_((Long) newV.get(key)); |
| | | run.setTEXT_((String) newV.get(key)); |
| | | } else { |
| | | // 其它类型的表单数据:如图片、文件单独存表的。历史、运行中的流程需各存一份 |
| | | v.setVAR_TYPE_("serializable"); |
| | | v.setBYTEARRAY_ID_(new StrongUuidGenerator().getNextId()); |
| | | projectProcessMapper.insertByteArray(v.getBYTEARRAY_ID_(), 1, "hist.var-" + key, newV.get(key)); |
| | | |
| | | run.setVAR_TYPE_("serializable"); |
| | | run.setBYTEARRAY_ID_(new StrongUuidGenerator().getNextId()); |
| | | projectProcessMapper.insertByteArray(run.getBYTEARRAY_ID_(), 1, "var-" + key, newV.get(key)); |
| | | } |
| | | |
| | | projectProcessMapper.insertHisFlowableVar(v); |
| | | projectProcessMapper.insertRunFlowableVar(run); |
| | | } |
| | | } |
| | | // 保存日志 |
| | | publisher.publishEvent(new TaskLogEvent(this, null, |
| | | SecurityUtils.getUserId(), |
| | | projectProcess.getProjectId(), |
| | | projectProcess.getProcessInsId(), |
| | | taskId, |
| | | task.getTaskDefinitionKey(), |
| | | task.getName(), |
| | | ProcessLogEventTypeEnum.FINISHED, |
| | | null)); |
| | | |
| | | return AjaxResult.success("提交成功"); |
| | | } |
| | | |
| | | // 将对象转换为 byte[] |
| | | public static byte[] objectToBytes(Object obj) throws IOException { |
| | | if (Objects.isNull(obj)) { |
| | | return null; |
| | | } |
| | | try (ByteArrayOutputStream bos = new ByteArrayOutputStream(); |
| | | ObjectOutputStream oos = new ObjectOutputStream(bos)) { |
| | | oos.writeObject(obj); // 序列化对象 |
| | | oos.flush(); |
| | | return bos.toByteArray(); // 返回字节数组 |
| | | } |
| | | } |
| | | |
| | | /** |
| | |
| | | if (taskService.createTaskQuery().taskId(flowTaskVo.getTaskId()).singleResult().isSuspended()) { |
| | | throw new CustomException("任务处于挂起状态!"); |
| | | } |
| | | |
| | | // 当前任务 task |
| | | Task task = taskService.createTaskQuery().taskId(flowTaskVo.getTaskId()).singleResult(); |
| | | |
| | | ProjectProcess projectProcess = new LambdaQueryChainWrapper<>(projectProcessMapper) |
| | | .eq(ProjectProcess::getProcessInsId, task.getProcessInstanceId()) |
| | | .eq(ProjectProcess::getProcessDefId, task.getProcessDefinitionId()) |
| | | .one(); |
| | | if (Objects.isNull(projectProcess)) { |
| | | throw new CustomException("项目流程未绑定"); |
| | | } |
| | | |
| | | // 获取流程定义信息 |
| | | ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().processDefinitionId(task.getProcessDefinitionId()).singleResult(); |
| | | // 获取所有节点信息 |
| | |
| | | try { |
| | | // 如果父级任务多于 1 个,说明当前节点不是并行节点,原因为不考虑多对多情况 |
| | | if (targetIds.size() > 1) { |
| | | // 删除被驳回任务的所有日志 |
| | | for (String targetId : targetIds) { |
| | | List<HistoricTaskInstance> rejectHisTaskList = historyService.createHistoricTaskInstanceQuery() |
| | | .taskDefinitionKey(targetId) |
| | | .processInstanceId(projectProcess.getProcessInsId()) |
| | | .orderByHistoricTaskInstanceStartTime() |
| | | .desc() |
| | | .list(); |
| | | if (CollectionUtils.isNotEmpty(rejectHisTaskList)) { |
| | | new LambdaUpdateChainWrapper<>(processLogService.getBaseMapper()) |
| | | .eq(ProcessLog::getTaskId, rejectHisTaskList.get(0).getId()) |
| | | .eq(ProcessLog::getProcessInsId, projectProcess.getProcessInsId()) |
| | | .remove(); |
| | | } |
| | | } |
| | | // 1 对 多任务跳转,currentIds 当前节点(1),targetIds 跳转到的节点(多) |
| | | runtimeService.createChangeActivityStateBuilder() |
| | | .processInstanceId(task.getProcessInstanceId()). |
| | |
| | | } |
| | | // 如果父级任务只有一个,因此当前任务可能为网关中的任务 |
| | | if (targetIds.size() == 1) { |
| | | // 删除被驳回任务的所有日志 |
| | | List<HistoricTaskInstance> rejectHisTaskList = historyService.createHistoricTaskInstanceQuery() |
| | | .taskDefinitionKey(targetIds.get(0)) |
| | | .processInstanceId(projectProcess.getProcessInsId()) |
| | | .orderByHistoricTaskInstanceStartTime() |
| | | .desc() |
| | | .list(); |
| | | if (CollectionUtils.isNotEmpty(rejectHisTaskList)) { |
| | | new LambdaUpdateChainWrapper<>(processLogService.getBaseMapper()) |
| | | .eq(ProcessLog::getTaskId, rejectHisTaskList.get(0).getId()) |
| | | .eq(ProcessLog::getProcessInsId, projectProcess.getProcessInsId()) |
| | | .remove(); |
| | | } |
| | | |
| | | // 1 对 1 或 多 对 1 情况,currentIds 当前要跳转的节点列表(1或多),targetIds.get(0) 跳转到的节点(1) |
| | | runtimeService.createChangeActivityStateBuilder() |
| | | .processInstanceId(task.getProcessInstanceId()) |
| | | .moveActivityIdsToSingleActivityId(currentIds, targetIds.get(0)).changeState(); |
| | | } |
| | | historyService.deleteHistoricTaskInstance(flowTaskVo.getTaskId()); |
| | | } catch (FlowableObjectNotFoundException e) { |
| | | throw new CustomException("未找到流程实例,流程可能已发生变化"); |
| | | } catch (FlowableException e) { |
| | | throw new CustomException("无法取消或开始活动"); |
| | | } |
| | | ProjectProcess projectProcess = new LambdaQueryChainWrapper<>(projectProcessMapper) |
| | | .eq(ProjectProcess::getProcessInsId, task.getProcessInstanceId()) |
| | | .eq(ProjectProcess::getProcessDefId, task.getProcessDefinitionId()) |
| | | .one(); |
| | | if (Objects.isNull(projectProcess)) { |
| | | throw new CustomException("项目流程未绑定"); |
| | | } |
| | | // 保存日志 |
| | | publisher.publishEvent(new TaskLogEvent(this, null, |
| | |
| | | projectProcess.getProjectId(), |
| | | projectProcess.getProcessInsId(), |
| | | flowTaskVo.getTaskId(), |
| | | task.getTaskDefinitionKey(), |
| | | task.getName(), |
| | | ProcessLogEventTypeEnum.REJECT, |
| | | new RejectData(flowTaskVo.getComment()))); |
| | |
| | | public AjaxResult flowRecord(String procInsId) { |
| | | Map<String, Object> map = new HashMap<String, Object>(); |
| | | if (StringUtils.isNotBlank(procInsId)) { |
| | | List<HistoricActivityInstance> list = historyService |
| | | .createHistoricActivityInstanceQuery() |
| | | List<HistoricTaskInstance> list = historyService |
| | | .createHistoricTaskInstanceQuery() |
| | | .processInstanceId(procInsId) |
| | | .orderByHistoricActivityInstanceStartTime() |
| | | .orderByHistoricTaskInstanceStartTime() |
| | | .desc().list(); |
| | | //扩展 获取这个流程实例的监控信息 key:TaskId value:实体类 |
| | | Map<String, ProcessCoding> processCodingMap = processCodingMapper.selectList(new QueryWrapper<ProcessCoding>().eq("process_ins_id", procInsId)) |
| | | .stream() |
| | | .collect(Collectors.toMap(ProcessCoding::getTaskId, Function.identity())); |
| | | List<FlowTaskDto> hisFlowList = new ArrayList<>(); |
| | | for (HistoricActivityInstance histIns : list) { |
| | | for (HistoricTaskInstance histIns : list) { |
| | | // 展示开始节点 |
| | | // if ("startEvent".equals(histIns.getActivityType())) { |
| | | // FlowTaskDto flowTask = new FlowTaskDto(); |
| | |
| | | // flowTask.setFinishTime(histIns.getEndTime()); |
| | | // hisFlowList.add(flowTask); |
| | | // } else |
| | | if (StringUtils.isNotBlank(histIns.getTaskId())) { |
| | | if (StringUtils.isNotBlank(histIns.getId())) { |
| | | FlowTaskDto flowTask = new FlowTaskDto(); |
| | | flowTask.setTaskId(histIns.getTaskId()); |
| | | flowTask.setTaskName(histIns.getActivityName()); |
| | | flowTask.setTaskId(histIns.getId()); |
| | | flowTask.setTaskName(histIns.getName()); |
| | | flowTask.setCreateTime(histIns.getStartTime()); |
| | | flowTask.setFinishTime(histIns.getEndTime()); |
| | | if (StringUtils.isNotBlank(histIns.getAssignee())) { |
| | |
| | | flowTask.setDeptName(Objects.nonNull(sysUser.getDept()) ? sysUser.getDept().getDeptName() : ""); |
| | | } |
| | | // 展示审批人员 |
| | | List<HistoricIdentityLink> linksForTask = historyService.getHistoricIdentityLinksForTask(histIns.getTaskId()); |
| | | List<HistoricIdentityLink> linksForTask = historyService.getHistoricIdentityLinksForTask(histIns.getId()); |
| | | StringBuilder stringBuilder = new StringBuilder(); |
| | | for (HistoricIdentityLink identityLink : linksForTask) { |
| | | // 获选人,候选组/角色(多个) |
| | |
| | | |
| | | flowTask.setDuration(histIns.getDurationInMillis() == null || histIns.getDurationInMillis() == 0 ? null : getDate(histIns.getDurationInMillis())); |
| | | //扩展 判断是否超时 |
| | | ProcessCoding processCoding = processCodingMap.get(histIns.getTaskId()); |
| | | ProcessCoding processCoding = processCodingMap.get(histIns.getId()); |
| | | if (processCoding != null) { |
| | | //通过耗时判断是否是代办节点 |
| | | //如果任务是代办节点 |
| | |
| | | // 获取意见评论内容 |
| | | List<Comment> commentList = taskService.getProcessInstanceComments(histIns.getProcessInstanceId()); |
| | | commentList.forEach(comment -> { |
| | | if (histIns.getTaskId().equals(comment.getTaskId())) { |
| | | if (histIns.getId().equals(comment.getTaskId())) { |
| | | flowTask.setComment(FlowCommentDto.builder().type(comment.getType()).comment(comment.getFullMessage()).build()); |
| | | } |
| | | }); |
| | |
| | | .processInstanceId(procInsId) |
| | | .finished() |
| | | .list(); |
| | | listFinished = this.distinctHisActivity(listFinished); |
| | | |
| | | //扩展 获取这个流程实例的监控信息 key:TaskId value:实体类 |
| | | Map<String, ProcessCoding> processCodingMap = processCodingMapper |
| | | .selectList(new QueryWrapper<ProcessCoding>().eq("process_ins_id", procInsId)) |
| | | Map<String, ProcessCoding> processCodingMap = new LambdaQueryChainWrapper<>(processCodingMapper) |
| | | .eq(ProcessCoding::getProcessInsId, procInsId) |
| | | .list() |
| | | .stream() |
| | | .collect(Collectors.toMap(ProcessCoding::getTaskId, Function.identity())); |
| | | // 保存已经完成的流程节点编号 |
| | |
| | | if (StringUtils.isBlank(s.getDeleteReason())) { |
| | | flowViewerList.add(flowViewerDto); |
| | | } |
| | | flowViewerDto.setHasJump(processLogService.taskIsJump(s.getTaskId(), procInsId)); |
| | | flowViewerDto.setHasWait(processLogService.taskIsWait(s.getTaskId(), procInsId)); |
| | | }); |
| | | |
| | | // 获取代办节点 |
| | |
| | | // 扩展内容 代办的通过当前时间作为endTime |
| | | ProcessCoding processCoding = processCodingMap.get(s.getTaskId()); |
| | | //如果有监控数据 不反的话前端默认是进行中(蓝色) |
| | | if (processCoding != null && (RED.equals(processCoding.getStatus()) || YELLOW.equals(processCoding.getStatus()))) { |
| | | flowViewerDto.setOvertime(processCoding.getStatus()); |
| | | if (Objects.nonNull(processCoding)) { |
| | | if (RED.equals(processCoding.getStatus()) || YELLOW.equals(processCoding.getStatus())) { |
| | | flowViewerDto.setOvertime(processCoding.getStatus()); |
| | | } |
| | | } |
| | | flowViewerList.add(flowViewerDto); |
| | | }); |
| | |
| | | } |
| | | |
| | | /** |
| | | * 根据任务key去重历史任务,相同情况下取最新的一条 |
| | | * |
| | | * @param hisTaskList |
| | | * @return |
| | | */ |
| | | private List<HistoricActivityInstance> distinctHisActivity(List<HistoricActivityInstance> hisTaskList) { |
| | | Map<String, HistoricActivityInstance> uniqueTasks = new HashMap<>(); |
| | | for (HistoricActivityInstance task : hisTaskList) { |
| | | String taskDefinitionKey = task.getActivityId(); |
| | | HistoricActivityInstance existingTask = uniqueTasks.get(taskDefinitionKey); |
| | | |
| | | // 如果任务key重复(可能被驳回过,重新提交导致key重复),取最近的一条 |
| | | if (existingTask == null || task.getStartTime().after(existingTask.getStartTime())) { |
| | | uniqueTasks.put(taskDefinitionKey, task); |
| | | } |
| | | } |
| | | // 最终去重后的任务列表 |
| | | return new ArrayList<>(uniqueTasks.values()); |
| | | } |
| | | |
| | | /** |
| | | * 查询当前任务的表单数据 |
| | | * |
| | | * @param taskId |
| | | * @return |
| | | * @throws Exception |
| | | */ |
| | | @Override |
| | | public AjaxResult currentFlowTaskForm(String taskId) { |
| | | // 流程变量 |
| | | List<HistoricTaskInstance> hisTaskList = historyService.createHistoricTaskInstanceQuery() |
| | | .finished() |
| | | .taskId(taskId) |
| | | .orderByHistoricTaskInstanceStartTime() |
| | | .desc() |
| | | .list(); |
| | | if (CollectionUtils.isEmpty(hisTaskList) || Objects.isNull(hisTaskList.get(0))) { |
| | | return AjaxResult.error("未找到该任务信息"); |
| | | } |
| | | HistoricTaskInstance historicTaskInstance = hisTaskList.get(0); |
| | | ProcessInstance processInstance = runtimeService.createProcessInstanceQuery().includeProcessVariables().processInstanceId(historicTaskInstance.getProcessInstanceId()).singleResult(); |
| | | Map<String, Object> parameters = new HashMap<>(); |
| | | if (Objects.nonNull(processInstance)) { |
| | | parameters = processInstance.getProcessVariables(); |
| | | } else { |
| | | // 如果为空,表明流程已经结束 |
| | | HistoricProcessInstance historicProcessInstance = historyService.createHistoricProcessInstanceQuery().includeProcessVariables().processInstanceId(historicTaskInstance.getProcessInstanceId()).singleResult(); |
| | | if (Objects.isNull(historicProcessInstance)) { |
| | | throw new RuntimeException("流程不存在"); |
| | | } |
| | | parameters = historicProcessInstance.getProcessVariables(); |
| | | } |
| | | |
| | | String processInsId = historicTaskInstance.getProcessInstanceId(); |
| | | List<FormDetailVO> beforeNodes = this.getBeforeNodeForm(parameters, |
| | | historicTaskInstance.getFormKey(), |
| | | historicTaskInstance.getName(), |
| | | historicTaskInstance.getProcessDefinitionId(), |
| | | historicTaskInstance.getTaskDefinitionKey(), |
| | | Boolean.TRUE, Boolean.FALSE); |
| | | |
| | | |
| | | String finalProcessInsId = processInsId; |
| | | List<DoFormDetailVO> vos = beforeNodes.stream() |
| | | .filter(FormDetailVO::getCurrent) |
| | | .map(node -> { |
| | | // 判断任务是否存在特殊操作(如跳过、转办等),需要在前端展示出来 |
| | | ProcessLogQuery query = new ProcessLogQuery(); |
| | | query.setTaskId(taskId); |
| | | query.setProcessInsId(finalProcessInsId); |
| | | Result result = processLogService.projectProcessLogList(query); |
| | | List<ProcessLogVO> logList = (List<ProcessLogVO>) result.get("data"); |
| | | DoFormDetailVO vo = new DoFormDetailVO(); |
| | | BeanUtils.copyProperties(node, vo); |
| | | if (CollectionUtils.isNotEmpty(logList)) { |
| | | vo.setEvents(logList); |
| | | } |
| | | // 根据日志判断当前任务的状态 |
| | | if (logList.stream().anyMatch(log -> ProcessLogEventTypeEnum.FINISHED.equals(log.getEventType()))) { |
| | | vo.setTaskStatus(TaskStatusEnum.FINISHED); |
| | | } else if (logList.stream().anyMatch(log -> ProcessLogEventTypeEnum.JUMP.equals(log.getEventType()))) { |
| | | vo.setTaskStatus(TaskStatusEnum.JUMP); |
| | | } else if (processLogService.taskIsWait(taskId, processInsId)) { |
| | | vo.setTaskStatus(TaskStatusEnum.WAIT); |
| | | } else if (processLogService.taskIsHangup(taskId, processInsId)) { |
| | | vo.setTaskStatus(TaskStatusEnum.HANGUP); |
| | | } |
| | | return vo; |
| | | }).collect(Collectors.toList()); |
| | | return AjaxResult.success(vos.get(0)); |
| | | } |
| | | |
| | | /** |
| | | * 流程节点表单 |
| | | * |
| | | * @param taskId 流程任务编号 |
| | |
| | | @Override |
| | | public AjaxResult flowTaskForm(String taskId) throws Exception { |
| | | Task task = taskService.createTaskQuery().taskId(taskId).singleResult(); |
| | | // 流程变量 |
| | | Map<String, Object> parameters = new HashMap<>(); |
| | | List<FormDetailVO> beforeNodes = new ArrayList<>(); |
| | | // 1. 获取到变量信息,因为任务可能是运行中的也可能是历史任务 |
| | | String processInsId = ""; |
| | | HistoricTaskInstance historicTaskInstance = historyService.createHistoricTaskInstanceQuery().includeProcessVariables().finished().taskId(taskId).singleResult(); |
| | | if (Objects.nonNull(historicTaskInstance)) { |
| | | parameters = historicTaskInstance.getProcessVariables(); |
| | | processInsId = historicTaskInstance.getProcessInstanceId(); |
| | | beforeNodes = this.getBeforeNodeForm(parameters, historicTaskInstance.getFormKey(), historicTaskInstance.getName(), historicTaskInstance.getProcessDefinitionId(), historicTaskInstance.getTaskDefinitionKey(), Boolean.FALSE); |
| | | String processDefId = ""; |
| | | String formKey = ""; |
| | | String taskName = ""; |
| | | String taskDefKey = ""; |
| | | if (Objects.isNull(task)) { |
| | | List<HistoricTaskInstance> hisTaskList = historyService.createHistoricTaskInstanceQuery() |
| | | .finished() |
| | | .taskId(taskId) |
| | | .orderByHistoricTaskInstanceStartTime() |
| | | .desc() |
| | | .list(); |
| | | if (CollectionUtils.isEmpty(hisTaskList) || Objects.isNull(hisTaskList.get(0))) { |
| | | return AjaxResult.error("任务不存在"); |
| | | } |
| | | HistoricTaskInstance hisTask = hisTaskList.get(0); |
| | | processInsId = hisTask.getProcessInstanceId(); |
| | | processDefId = hisTask.getProcessDefinitionId(); |
| | | formKey = hisTask.getFormKey(); |
| | | taskName = hisTask.getName(); |
| | | taskDefKey = hisTask.getTaskDefinitionKey(); |
| | | } else { |
| | | parameters = taskService.getVariables(taskId); |
| | | processInsId = task.getProcessInstanceId(); |
| | | beforeNodes = this.getBeforeNodeForm(parameters, task.getFormKey(), task.getName(), task.getProcessDefinitionId(), task.getTaskDefinitionKey(), Boolean.FALSE); |
| | | processDefId = task.getProcessDefinitionId(); |
| | | formKey = task.getFormKey(); |
| | | taskName = task.getName(); |
| | | taskDefKey = task.getTaskDefinitionKey(); |
| | | } |
| | | // 2. 获取流程变量 |
| | | ProcessInstance processInstance = runtimeService.createProcessInstanceQuery().includeProcessVariables().processInstanceId(processInsId).singleResult(); |
| | | Map<String, Object> parameters = new HashMap<>(); |
| | | if (Objects.nonNull(processInstance)) { |
| | | parameters = processInstance.getProcessVariables(); |
| | | } else { |
| | | // 如果为空,表明流程已经结束 |
| | | HistoricProcessInstance historicProcessInstance = historyService.createHistoricProcessInstanceQuery().includeProcessVariables().processInstanceId(processInsId).singleResult(); |
| | | if (Objects.isNull(historicProcessInstance)) { |
| | | throw new RuntimeException("流程不存在"); |
| | | } |
| | | parameters = historicProcessInstance.getProcessVariables(); |
| | | } |
| | | List<FormDetailVO> beforeNodes = new ArrayList<>(); |
| | | beforeNodes = this.getBeforeNodeForm(parameters, |
| | | formKey, |
| | | taskName, |
| | | processDefId, |
| | | taskDefKey, |
| | | Boolean.TRUE, Boolean.TRUE); |
| | | // 判断前置任务是不是和当前任务为同一个executeId |
| | | // 判断当前任务是否被挂起中 |
| | | String finalProcessInsId = processInsId; |
| | | beforeNodes = beforeNodes.stream().filter(node -> { |
| | | List<FormDetailVO> dataList = new ArrayList<>(2); |
| | | Map<String, List<FormDetailVO>> map = new HashMap<>(2); |
| | | beforeNodes.stream().forEach(node -> { |
| | | if (node.getCurrent()) { |
| | | return Boolean.TRUE; |
| | | node.setTaskId(taskId); |
| | | dataList.add(node); |
| | | } else { |
| | | List<HistoricTaskInstance> beforeTasks = historyService.createHistoricTaskInstanceQuery() |
| | | .processInstanceId(finalProcessInsId) |
| | | .finished() |
| | | .taskDefinitionKey(node.getBeforeNodeDefId()) |
| | | .orderByTaskCreateTime() |
| | | .desc() |
| | | .list(); |
| | | if (CollectionUtils.isNotEmpty(beforeTasks) && Objects.nonNull(beforeTasks.get(0))) { |
| | | node.setTaskId(beforeTasks.get(0).getId()); |
| | | List<FormDetailVO> l = map.get(beforeTasks.get(0)); |
| | | if (CollectionUtils.isEmpty(l)) { |
| | | map.put(beforeTasks.get(0).getExecutionId(), Arrays.asList(node)); |
| | | } else { |
| | | l.add(node); |
| | | } |
| | | } |
| | | } |
| | | HistoricTaskInstance beforeTask = historyService.createHistoricTaskInstanceQuery().processInstanceId(finalProcessInsId).finished().taskDefinitionKey(node.getBeforeNodeDefId()).singleResult(); |
| | | return Objects.nonNull(beforeTask); |
| | | }).collect(Collectors.toList()); |
| | | beforeNodes.forEach(node -> { |
| | | }); |
| | | for (String key : map.keySet()) { |
| | | if (StringUtils.isNotBlank(key)) { |
| | | // 同一执行器上只取最近的一个 |
| | | dataList.add(map.get(key).get(0)); |
| | | } |
| | | } |
| | | List<DoFormDetailVO> vos = dataList.stream().map(node -> { |
| | | if (node.getCurrent()) { |
| | | if (processLogService.taskIsHangup(taskId, finalProcessInsId)) { |
| | | node.setTaskStatus(TaskStatusEnum.HANGUP); |
| | | } |
| | | } |
| | | }); |
| | | return AjaxResult.success(beforeNodes); |
| | | // 判断任务是否存在特殊操作(如跳过、转办等),需要在前端展示出来 |
| | | ProcessLogQuery query = new ProcessLogQuery(); |
| | | query.setTaskId(node.getTaskId()); |
| | | query.setProcessInsId(finalProcessInsId); |
| | | Result result = processLogService.projectProcessLogList(query); |
| | | List<ProcessLogVO> logList = (List<ProcessLogVO>) result.get("data"); |
| | | DoFormDetailVO vo = new DoFormDetailVO(); |
| | | BeanUtils.copyProperties(node, vo); |
| | | if (CollectionUtils.isNotEmpty(logList)) { |
| | | vo.setEvents(logList); |
| | | } |
| | | return vo; |
| | | }).collect(Collectors.toList()); |
| | | return AjaxResult.success(vos); |
| | | } |
| | | |
| | | @Override |
| | | public AjaxResult detail(String taskId) { |
| | | Task task = taskService.createTaskQuery().taskId(taskId).singleResult(); |
| | | public AjaxResult detail(String processInsId, String taskId) { |
| | | ProcessInstance processInstance = runtimeService.createProcessInstanceQuery().includeProcessVariables().processInstanceId(processInsId).singleResult(); |
| | | // 流程变量 |
| | | Map<String, Object> parameters = new HashMap<>(); |
| | | if (Objects.isNull(task)) { |
| | | // 如果为空,可能是任务已经结束 |
| | | HistoricTaskInstance hisTask = historyService.createHistoricTaskInstanceQuery().taskId(taskId).includeProcessVariables().singleResult(); |
| | | if (Objects.isNull(hisTask)) { |
| | | if (Objects.isNull(processInstance)) { |
| | | |
| | | // 如果为空,表明流程已经结束 |
| | | HistoricProcessInstance historicProcessInstance = historyService.createHistoricProcessInstanceQuery().includeProcessVariables().processInstanceId(processInsId).singleResult(); |
| | | if (Objects.isNull(historicProcessInstance)) { |
| | | throw new RuntimeException("流程不存在"); |
| | | } |
| | | |
| | | List<HistoricTaskInstance> hisTasks = historyService.createHistoricTaskInstanceQuery() |
| | | .taskId(taskId) |
| | | .finished() |
| | | .includeProcessVariables() |
| | | .orderByHistoricTaskInstanceStartTime() |
| | | .desc() |
| | | .list(); |
| | | if (CollectionUtils.isNotEmpty(hisTasks) && Objects.isNull(hisTasks.get(0))) { |
| | | throw new RuntimeException("该任务不存在"); |
| | | } |
| | | parameters = hisTask.getProcessVariables(); |
| | | List<FormDetailVO> beforeNodes = this.getBeforeNodeForm(parameters, hisTask.getFormKey(), hisTask.getName(), hisTask.getProcessDefinitionId(), hisTask.getTaskDefinitionKey(), Boolean.TRUE); |
| | | List<FormDetailVO> dataList = beforeNodes.stream().filter(node -> { |
| | | HistoricTaskInstance hisTask = hisTasks.get(0); |
| | | parameters = historicProcessInstance.getProcessVariables(); |
| | | List<FormDetailVO> beforeNodes = this.getBeforeNodeForm(parameters, |
| | | hisTask.getFormKey(), |
| | | hisTask.getName(), |
| | | hisTask.getProcessDefinitionId(), |
| | | hisTask.getTaskDefinitionKey(), |
| | | Boolean.TRUE, Boolean.TRUE); |
| | | List<FormDetailVO> dataList = new ArrayList<>(2); |
| | | Map<String, List<FormDetailVO>> map = new HashMap<>(2); |
| | | beforeNodes.stream().forEach(node -> { |
| | | if (node.getCurrent()) { |
| | | return Boolean.TRUE; |
| | | node.setTaskId(taskId); |
| | | dataList.add(node); |
| | | } else { |
| | | List<HistoricTaskInstance> beforeTasks = historyService.createHistoricTaskInstanceQuery() |
| | | .processInstanceId(hisTask.getProcessInstanceId()) |
| | | .finished() |
| | | .taskDefinitionKey(node.getBeforeNodeDefId()) |
| | | .orderByTaskCreateTime() |
| | | .desc() |
| | | .list(); |
| | | if (CollectionUtils.isNotEmpty(beforeTasks) && Objects.nonNull(beforeTasks.get(0))) { |
| | | node.setTaskId(beforeTasks.get(0).getId()); |
| | | List<FormDetailVO> l = map.get(beforeTasks.get(0)); |
| | | if (CollectionUtils.isEmpty(l)) { |
| | | map.put(beforeTasks.get(0).getExecutionId(), Arrays.asList(node)); |
| | | } else { |
| | | l.add(node); |
| | | } |
| | | } |
| | | } |
| | | HistoricTaskInstance beforeTask = historyService.createHistoricTaskInstanceQuery().processInstanceId(hisTask.getProcessInstanceId()).finished().taskDefinitionKey(node.getBeforeNodeDefId()).singleResult(); |
| | | return Objects.nonNull(beforeTask); |
| | | }); |
| | | for (String key : map.keySet()) { |
| | | if (StringUtils.isNotBlank(key)) { |
| | | // 同一执行器上只取最近的一个 |
| | | dataList.add(map.get(key).get(0)); |
| | | } |
| | | } |
| | | List<DoFormDetailVO> vos = dataList.stream().map(node -> { |
| | | if (node.getCurrent()) { |
| | | if (processLogService.taskIsHangup(taskId, hisTask.getProcessInstanceId())) { |
| | | node.setTaskStatus(TaskStatusEnum.HANGUP); |
| | | } |
| | | } |
| | | // 判断任务是否存在特殊操作(如跳过、转办等),需要在前端展示出来 |
| | | ProcessLogQuery query = new ProcessLogQuery(); |
| | | query.setTaskId(node.getTaskId()); |
| | | query.setProcessInsId(hisTask.getProcessInstanceId()); |
| | | Result result = processLogService.projectProcessLogList(query); |
| | | List<ProcessLogVO> logList = (List<ProcessLogVO>) result.get("data"); |
| | | DoFormDetailVO vo = new DoFormDetailVO(); |
| | | BeanUtils.copyProperties(node, vo); |
| | | if (CollectionUtils.isNotEmpty(logList)) { |
| | | vo.setEvents(logList); |
| | | } |
| | | return vo; |
| | | }).collect(Collectors.toList()); |
| | | return AjaxResult.success(dataList); |
| | | return AjaxResult.success(vos); |
| | | } else { |
| | | parameters = taskService.getVariables(taskId); |
| | | List<FormDetailVO> beforeNodes = this.getBeforeNodeForm(parameters, task.getFormKey(), task.getName(), task.getProcessDefinitionId(), task.getTaskDefinitionKey(), Boolean.TRUE); |
| | | List<FormDetailVO> dataList = beforeNodes.stream().filter(node -> { |
| | | if (node.getCurrent()) { |
| | | return Boolean.TRUE; |
| | | parameters = processInstance.getProcessVariables(); |
| | | Task task = taskService.createTaskQuery().taskId(taskId).processInstanceId(processInsId).singleResult(); |
| | | List<FormDetailVO> beforeNodes = new ArrayList<>(); |
| | | if (Objects.nonNull(task)) { |
| | | beforeNodes = this.getBeforeNodeForm(parameters, |
| | | task.getFormKey(), |
| | | task.getName(), |
| | | task.getProcessDefinitionId(), |
| | | task.getTaskDefinitionKey(), |
| | | Boolean.TRUE, Boolean.TRUE); |
| | | } else { |
| | | List<HistoricTaskInstance> hisTasks = historyService.createHistoricTaskInstanceQuery() |
| | | .taskId(taskId) |
| | | .finished() |
| | | .includeProcessVariables() |
| | | .orderByHistoricTaskInstanceStartTime() |
| | | .desc() |
| | | .list(); |
| | | if (CollectionUtils.isNotEmpty(hisTasks) && Objects.isNull(hisTasks.get(0))) { |
| | | throw new RuntimeException("该任务不存在"); |
| | | } |
| | | HistoricTaskInstance beforeTask = historyService.createHistoricTaskInstanceQuery().processInstanceId(task.getProcessInstanceId()).finished().taskDefinitionKey(node.getBeforeNodeDefId()).singleResult(); |
| | | return Objects.nonNull(beforeTask); |
| | | HistoricTaskInstance hisTask = hisTasks.get(0); |
| | | beforeNodes = this.getBeforeNodeForm(parameters, |
| | | hisTask.getFormKey(), |
| | | hisTask.getName(), |
| | | hisTask.getProcessDefinitionId(), |
| | | hisTask.getTaskDefinitionKey(), |
| | | Boolean.TRUE, Boolean.TRUE); |
| | | } |
| | | List<FormDetailVO> dataList = new ArrayList<>(2); |
| | | Map<String, List<FormDetailVO>> map = new HashMap<>(2); |
| | | beforeNodes.stream().forEach(node -> { |
| | | if (node.getCurrent()) { |
| | | node.setTaskId(taskId); |
| | | dataList.add(node); |
| | | } else { |
| | | List<HistoricTaskInstance> beforeTasks = historyService.createHistoricTaskInstanceQuery() |
| | | .processInstanceId(processInsId) |
| | | .finished() |
| | | .taskDefinitionKey(node.getBeforeNodeDefId()) |
| | | .orderByTaskCreateTime() |
| | | .desc() |
| | | .list(); |
| | | if (CollectionUtils.isNotEmpty(beforeTasks) && Objects.nonNull(beforeTasks.get(0))) { |
| | | node.setTaskId(beforeTasks.get(0).getId()); |
| | | List<FormDetailVO> l = map.get(beforeTasks.get(0)); |
| | | if (CollectionUtils.isEmpty(l)) { |
| | | map.put(beforeTasks.get(0).getExecutionId(), Arrays.asList(node)); |
| | | } else { |
| | | l.add(node); |
| | | } |
| | | } |
| | | } |
| | | }); |
| | | for (String key : map.keySet()) { |
| | | if (StringUtils.isNotBlank(key)) { |
| | | // 同一执行器上只取最近的一个 |
| | | dataList.add(map.get(key).get(0)); |
| | | } |
| | | } |
| | | List<DoFormDetailVO> vos = dataList.stream().map(node -> { |
| | | if (node.getCurrent()) { |
| | | if (processLogService.taskIsHangup(taskId, processInsId)) { |
| | | node.setTaskStatus(TaskStatusEnum.HANGUP); |
| | | } |
| | | } |
| | | // 判断任务是否存在特殊操作(如跳过、转办等),需要在前端展示出来 |
| | | ProcessLogQuery query = new ProcessLogQuery(); |
| | | query.setTaskId(node.getTaskId()); |
| | | query.setProcessInsId(processInsId); |
| | | Result result = processLogService.projectProcessLogList(query); |
| | | List<ProcessLogVO> logList = (List<ProcessLogVO>) result.get("data"); |
| | | DoFormDetailVO vo = new DoFormDetailVO(); |
| | | BeanUtils.copyProperties(node, vo); |
| | | if (CollectionUtils.isNotEmpty(logList)) { |
| | | vo.setEvents(logList); |
| | | } |
| | | return vo; |
| | | }).collect(Collectors.toList()); |
| | | return AjaxResult.success(dataList); |
| | | return AjaxResult.success(vos); |
| | | } |
| | | } |
| | | |
| | |
| | | * @param taskName 任务 |
| | | * @param processDefId 流程定义id |
| | | * @param processDefKey 流程实例id |
| | | * @param disableInput 是否禁用已经有值的输入项 |
| | | * @return |
| | | */ |
| | | private List<FormDetailVO> getBeforeNodeForm(Map<String, Object> parameters, String formKey, String taskName, String processDefId, String processDefKey, Boolean currentNeedData) { |
| | | private List<FormDetailVO> getBeforeNodeForm(Map<String, Object> parameters, |
| | | String formKey, |
| | | String taskName, |
| | | String processDefId, |
| | | String processDefKey, |
| | | Boolean currentNeedData, |
| | | Boolean disableInput) { |
| | | |
| | | // 这里只需要查自身以及上一个节点(如果并行的有多个)的表单数据 |
| | | List<FormDetailVO> beforeNodes = taskCommonService.getBeforeNodeDefInfo(processDefId, processDefKey, sysFormService, Boolean.TRUE); |
| | |
| | | |
| | | if(CollectionUtils.isNotEmpty(oldFields)) { |
| | | // 设置已填写的表单为禁用状态 |
| | | for (JSONObject oldField : oldFields) { |
| | | JSONObject options = oldField.getJSONObject("options"); |
| | | options.put("disabled", true); |
| | | if (disableInput) { |
| | | for (JSONObject oldField : oldFields) { |
| | | JSONObject options = oldField.getJSONObject("options"); |
| | | options.put("disabled", true); |
| | | } |
| | | } |
| | | formJson.put(ProcessConstants.WIDGET_LIST, oldFields); |
| | | newP.put(ProcessConstants.TASK_FORM_KEY, formJson); |
| | |
| | | return beforeNodes; |
| | | } |
| | | |
| | | |
| | | /** |
| | | * 流程节点信息 |
| | | * |