package com.dl.workflow.service.impl; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.convert.Convert; import cn.hutool.core.date.BetweenFormatter; import cn.hutool.core.date.DateUtil; import cn.hutool.core.io.IORuntimeException; import cn.hutool.core.io.IoUtil; import cn.hutool.core.util.ObjectUtil; import cn.hutool.core.util.StrUtil; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.dl.common.core.domain.PageQuery; import com.dl.common.core.domain.entity.SysDept; import com.dl.common.core.domain.entity.SysRole; import com.dl.common.core.page.TableDataInfo; import com.dl.common.core.service.UserService; import com.dl.common.exception.ServiceException; import com.dl.common.utils.DateUtils; import com.dl.common.utils.JsonUtils; import com.dl.common.utils.StringUtils; import com.dl.flowable.common.constant.ProcessConstants; import com.dl.flowable.common.constant.TaskConstants; import com.dl.flowable.common.enums.ProcessStatus; import com.dl.flowable.core.FormConf; import com.dl.flowable.core.domain.ProcessQuery; import com.dl.flowable.factory.FlowServiceFactory; import com.dl.flowable.flow.FlowableUtils; import com.dl.flowable.utils.ModelUtils; import com.dl.flowable.utils.ProcessFormUtils; import com.dl.flowable.utils.ProcessUtils; import com.dl.flowable.utils.TaskUtils; import com.dl.system.service.ISysDeptService; import com.dl.system.service.ISysRoleService; import com.dl.workflow.domain.WfDeployForm; import com.dl.workflow.domain.vo.*; import com.dl.workflow.mapper.WfDeployFormMapper; import com.dl.workflow.service.IWfProcessService; import com.dl.workflow.service.IWfTaskService; import lombok.RequiredArgsConstructor; import org.flowable.bpmn.constants.BpmnXMLConstants; import org.flowable.bpmn.model.Process; import org.flowable.bpmn.model.*; import org.flowable.engine.history.HistoricActivityInstance; import org.flowable.engine.history.HistoricActivityInstanceQuery; import org.flowable.engine.history.HistoricProcessInstance; import org.flowable.engine.history.HistoricProcessInstanceQuery; import org.flowable.engine.repository.Deployment; import org.flowable.engine.repository.ProcessDefinition; import org.flowable.engine.repository.ProcessDefinitionQuery; import org.flowable.engine.runtime.ProcessInstance; import org.flowable.engine.task.Comment; import org.flowable.identitylink.api.history.HistoricIdentityLink; import org.flowable.task.api.Task; import org.flowable.task.api.TaskQuery; import org.flowable.task.api.history.HistoricTaskInstance; import org.flowable.task.api.history.HistoricTaskInstanceQuery; import org.flowable.variable.api.history.HistoricVariableInstance; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import java.io.InputStream; import java.util.*; import java.util.stream.Collectors; /** * @author KonBAI * @createTime 2022/3/24 18:57 */ @RequiredArgsConstructor @Service public class WfProcessServiceImpl extends FlowServiceFactory implements IWfProcessService { private final IWfTaskService wfTaskService; private final UserService userService; private final ISysRoleService roleService; private final ISysDeptService deptService; private final WfDeployFormMapper deployFormMapper; /** * 流程定义列表 * * @param pageQuery 分页参数 * @return 流程定义分页列表数据 */ @Override public TableDataInfo selectPageStartProcessList(ProcessQuery processQuery, PageQuery pageQuery) { Page page = new Page<>(); // 流程定义列表数据查询 ProcessDefinitionQuery processDefinitionQuery = repositoryService.createProcessDefinitionQuery() .latestVersion() .active() .orderByProcessDefinitionKey() .asc(); // 构建搜索条件 ProcessUtils.buildProcessSearch(processDefinitionQuery, processQuery); long pageTotal = processDefinitionQuery.count(); if (pageTotal <= 0) { return TableDataInfo.build(); } int offset = pageQuery.getPageSize() * (pageQuery.getPageNum() - 1); List definitionList = processDefinitionQuery.listPage(offset, pageQuery.getPageSize()); List definitionVoList = new ArrayList<>(); for (ProcessDefinition processDefinition : definitionList) { String deploymentId = processDefinition.getDeploymentId(); Deployment deployment = repositoryService.createDeploymentQuery().deploymentId(deploymentId).singleResult(); WfDefinitionVo vo = new WfDefinitionVo(); vo.setDefinitionId(processDefinition.getId()); vo.setProcessKey(processDefinition.getKey()); vo.setProcessName(processDefinition.getName()); vo.setVersion(processDefinition.getVersion()); vo.setDeploymentId(processDefinition.getDeploymentId()); vo.setSuspended(processDefinition.isSuspended()); // 流程定义时间 vo.setCategory(deployment.getCategory()); vo.setDeploymentTime(deployment.getDeploymentTime()); definitionVoList.add(vo); } page.setRecords(definitionVoList); page.setTotal(pageTotal); return TableDataInfo.build(page); } @Override public List selectStartProcessList(ProcessQuery processQuery) { // 流程定义列表数据查询 ProcessDefinitionQuery processDefinitionQuery = repositoryService.createProcessDefinitionQuery() .latestVersion() .active() .orderByProcessDefinitionKey() .asc(); // 构建搜索条件 ProcessUtils.buildProcessSearch(processDefinitionQuery, processQuery); List definitionList = processDefinitionQuery.list(); List definitionVoList = new ArrayList<>(); for (ProcessDefinition processDefinition : definitionList) { String deploymentId = processDefinition.getDeploymentId(); Deployment deployment = repositoryService.createDeploymentQuery().deploymentId(deploymentId).singleResult(); WfDefinitionVo vo = new WfDefinitionVo(); vo.setDefinitionId(processDefinition.getId()); vo.setProcessKey(processDefinition.getKey()); vo.setProcessName(processDefinition.getName()); vo.setVersion(processDefinition.getVersion()); vo.setDeploymentId(processDefinition.getDeploymentId()); vo.setSuspended(processDefinition.isSuspended()); // 流程定义时间 vo.setCategory(deployment.getCategory()); vo.setDeploymentTime(deployment.getDeploymentTime()); definitionVoList.add(vo); } return definitionVoList; } @Override public TableDataInfo selectPageOwnProcessList(ProcessQuery processQuery, PageQuery pageQuery) { Page page = new Page<>(); HistoricProcessInstanceQuery historicProcessInstanceQuery = historyService.createHistoricProcessInstanceQuery() .startedBy(TaskUtils.getUserId()) .orderByProcessInstanceStartTime() .desc(); // 构建搜索条件 ProcessUtils.buildProcessSearch(historicProcessInstanceQuery, processQuery); int offset = pageQuery.getPageSize() * (pageQuery.getPageNum() - 1); List historicProcessInstances = historicProcessInstanceQuery .listPage(offset, pageQuery.getPageSize()); page.setTotal(historicProcessInstanceQuery.count()); List taskVoList = new ArrayList<>(); for (HistoricProcessInstance hisIns : historicProcessInstances) { WfTaskVo taskVo = new WfTaskVo(); // 获取流程状态 HistoricVariableInstance processStatusVariable = historyService.createHistoricVariableInstanceQuery() .processInstanceId(hisIns.getId()) .variableName(ProcessConstants.PROCESS_STATUS_KEY) .singleResult(); String processStatus = null; if (ObjectUtil.isNotNull(processStatusVariable)) { processStatus = Convert.toStr(processStatusVariable.getValue()); } // 兼容旧流程 if (processStatus == null) { processStatus = ObjectUtil.isNull(hisIns.getEndTime()) ? ProcessStatus.RUNNING.getStatus() : ProcessStatus.COMPLETED.getStatus(); } taskVo.setProcessStatus(processStatus); taskVo.setCreateTime(hisIns.getStartTime()); taskVo.setFinishTime(hisIns.getEndTime()); taskVo.setProcInsId(hisIns.getId()); // 计算耗时 if (Objects.nonNull(hisIns.getEndTime())) { taskVo.setDuration(DateUtils.getDatePoor(hisIns.getEndTime(), hisIns.getStartTime())); } else { taskVo.setDuration(DateUtils.getDatePoor(DateUtils.getNowDate(), hisIns.getStartTime())); } // 流程部署实例信息 Deployment deployment = repositoryService.createDeploymentQuery() .deploymentId(hisIns.getDeploymentId()).singleResult(); taskVo.setDeployId(hisIns.getDeploymentId()); taskVo.setProcDefId(hisIns.getProcessDefinitionId()); taskVo.setProcDefName(hisIns.getProcessDefinitionName()); taskVo.setProcDefVersion(hisIns.getProcessDefinitionVersion()); taskVo.setCategory(deployment.getCategory()); // 当前所处流程 List taskList = taskService.createTaskQuery().processInstanceId(hisIns.getId()).includeIdentityLinks().list(); if (CollUtil.isNotEmpty(taskList)) { taskVo.setTaskName(taskList.stream().map(Task::getName).filter(StringUtils::isNotEmpty).collect(Collectors.joining(","))); } taskVoList.add(taskVo); } page.setRecords(taskVoList); return TableDataInfo.build(page); } @Override public List selectOwnProcessList(ProcessQuery processQuery) { HistoricProcessInstanceQuery historicProcessInstanceQuery = historyService.createHistoricProcessInstanceQuery() .startedBy(TaskUtils.getUserId()) .orderByProcessInstanceStartTime() .desc(); // 构建搜索条件 ProcessUtils.buildProcessSearch(historicProcessInstanceQuery, processQuery); List historicProcessInstances = historicProcessInstanceQuery.list(); List taskVoList = new ArrayList<>(); for (HistoricProcessInstance hisIns : historicProcessInstances) { WfTaskVo taskVo = new WfTaskVo(); taskVo.setCreateTime(hisIns.getStartTime()); taskVo.setFinishTime(hisIns.getEndTime()); taskVo.setProcInsId(hisIns.getId()); // 计算耗时 if (Objects.nonNull(hisIns.getEndTime())) { taskVo.setDuration(DateUtils.getDatePoor(hisIns.getEndTime(), hisIns.getStartTime())); } else { taskVo.setDuration(DateUtils.getDatePoor(DateUtils.getNowDate(), hisIns.getStartTime())); } // 流程部署实例信息 Deployment deployment = repositoryService.createDeploymentQuery() .deploymentId(hisIns.getDeploymentId()).singleResult(); taskVo.setDeployId(hisIns.getDeploymentId()); taskVo.setProcDefId(hisIns.getProcessDefinitionId()); taskVo.setProcDefName(hisIns.getProcessDefinitionName()); taskVo.setProcDefVersion(hisIns.getProcessDefinitionVersion()); taskVo.setCategory(deployment.getCategory()); // 当前所处流程 List taskList = taskService.createTaskQuery().processInstanceId(hisIns.getId()).includeIdentityLinks().list(); if (CollUtil.isNotEmpty(taskList)) { taskVo.setTaskName(taskList.stream().map(Task::getName).filter(StringUtils::isNotEmpty).collect(Collectors.joining(","))); } taskVoList.add(taskVo); } return taskVoList; } @Override public TableDataInfo selectPageTodoProcessList(ProcessQuery processQuery, PageQuery pageQuery) { Page page = new Page<>(); TaskQuery taskQuery = taskService.createTaskQuery() .active() .includeProcessVariables() .taskCandidateOrAssigned(TaskUtils.getUserId()) .taskCandidateGroupIn(TaskUtils.getCandidateGroup()) .orderByTaskCreateTime().desc(); // 构建搜索条件 ProcessUtils.buildProcessSearch(taskQuery, processQuery); page.setTotal(taskQuery.count()); int offset = pageQuery.getPageSize() * (pageQuery.getPageNum() - 1); List taskList = taskQuery.listPage(offset, pageQuery.getPageSize()); List flowList = new ArrayList<>(); for (Task task : taskList) { WfTaskVo flowTask = new WfTaskVo(); // 当前流程信息 flowTask.setTaskId(task.getId()); flowTask.setTaskDefKey(task.getTaskDefinitionKey()); flowTask.setCreateTime(task.getCreateTime()); flowTask.setProcDefId(task.getProcessDefinitionId()); flowTask.setTaskName(task.getName()); // 流程定义信息 ProcessDefinition pd = repositoryService.createProcessDefinitionQuery() .processDefinitionId(task.getProcessDefinitionId()) .singleResult(); flowTask.setDeployId(pd.getDeploymentId()); // flowTask.setProcDefName(pd.getName()); flowTask.setProcDefVersion(pd.getVersion()); flowTask.setProcInsId(task.getProcessInstanceId()); // 流程发起人信息 HistoricProcessInstance historicProcessInstance = historyService.createHistoricProcessInstanceQuery() .processInstanceId(task.getProcessInstanceId()) .singleResult(); flowTask.setProcDefName(historicProcessInstance.getName()); String userId = historicProcessInstance.getStartUserId(); String nickName = userService.selectNickNameById(userId); flowTask.setStartUserId(userId); flowTask.setStartUserName(nickName); // 流程变量 flowTask.setProcVars(task.getProcessVariables()); // 业务主键信息 String businessKey = historicProcessInstance.getBusinessKey(); flowTask.setBusinessKey(businessKey); flowList.add(flowTask); } page.setRecords(flowList); return TableDataInfo.build(page); } @Override public List selectTodoProcessList(ProcessQuery processQuery) { TaskQuery taskQuery = taskService.createTaskQuery() .active() .includeProcessVariables() .taskCandidateOrAssigned(TaskUtils.getUserId()) .taskCandidateGroupIn(TaskUtils.getCandidateGroup()) .orderByTaskCreateTime().desc(); // 构建搜索条件 ProcessUtils.buildProcessSearch(taskQuery, processQuery); List taskList = taskQuery.list(); List taskVoList = new ArrayList<>(); for (Task task : taskList) { WfTaskVo taskVo = new WfTaskVo(); // 当前流程信息 taskVo.setTaskId(task.getId()); taskVo.setTaskDefKey(task.getTaskDefinitionKey()); taskVo.setCreateTime(task.getCreateTime()); taskVo.setProcDefId(task.getProcessDefinitionId()); taskVo.setTaskName(task.getName()); // 流程定义信息 ProcessDefinition pd = repositoryService.createProcessDefinitionQuery() .processDefinitionId(task.getProcessDefinitionId()) .singleResult(); taskVo.setDeployId(pd.getDeploymentId()); taskVo.setProcDefName(pd.getName()); taskVo.setProcDefVersion(pd.getVersion()); taskVo.setProcInsId(task.getProcessInstanceId()); // 流程发起人信息 HistoricProcessInstance historicProcessInstance = historyService.createHistoricProcessInstanceQuery() .processInstanceId(task.getProcessInstanceId()) .singleResult(); String userId = historicProcessInstance.getStartUserId(); String nickName = userService.selectNickNameById(userId); taskVo.setStartUserId(userId); taskVo.setStartUserName(nickName); taskVoList.add(taskVo); } return taskVoList; } @Override public TableDataInfo selectPageClaimProcessList(ProcessQuery processQuery, PageQuery pageQuery) { Page page = new Page<>(); TaskQuery taskQuery = taskService.createTaskQuery() .active() .includeProcessVariables() .taskCandidateUser(TaskUtils.getUserId()) .taskCandidateGroupIn(TaskUtils.getCandidateGroup()) .orderByTaskCreateTime().desc(); // 构建搜索条件 ProcessUtils.buildProcessSearch(taskQuery, processQuery); page.setTotal(taskQuery.count()); int offset = pageQuery.getPageSize() * (pageQuery.getPageNum() - 1); List taskList = taskQuery.listPage(offset, pageQuery.getPageSize()); List flowList = new ArrayList<>(); for (Task task : taskList) { WfTaskVo flowTask = new WfTaskVo(); // 当前流程信息 flowTask.setTaskId(task.getId()); flowTask.setTaskDefKey(task.getTaskDefinitionKey()); flowTask.setCreateTime(task.getCreateTime()); flowTask.setProcDefId(task.getProcessDefinitionId()); flowTask.setTaskName(task.getName()); // 流程定义信息 ProcessDefinition pd = repositoryService.createProcessDefinitionQuery() .processDefinitionId(task.getProcessDefinitionId()) .singleResult(); flowTask.setDeployId(pd.getDeploymentId()); flowTask.setProcDefName(pd.getName()); flowTask.setProcDefVersion(pd.getVersion()); flowTask.setProcInsId(task.getProcessInstanceId()); // 流程发起人信息 HistoricProcessInstance historicProcessInstance = historyService.createHistoricProcessInstanceQuery() .processInstanceId(task.getProcessInstanceId()) .singleResult(); String userId = historicProcessInstance.getStartUserId(); String nickName = userService.selectNickNameById(userId); flowTask.setStartUserId(userId); flowTask.setStartUserName(nickName); flowList.add(flowTask); } page.setRecords(flowList); return TableDataInfo.build(page); } @Override public List selectClaimProcessList(ProcessQuery processQuery) { TaskQuery taskQuery = taskService.createTaskQuery() .active() .includeProcessVariables() .taskCandidateUser(TaskUtils.getUserId()) .taskCandidateGroupIn(TaskUtils.getCandidateGroup()) .orderByTaskCreateTime().desc(); // 构建搜索条件 ProcessUtils.buildProcessSearch(taskQuery, processQuery); List taskList = taskQuery.list(); List flowList = new ArrayList<>(); for (Task task : taskList) { WfTaskVo flowTask = new WfTaskVo(); // 当前流程信息 flowTask.setTaskId(task.getId()); flowTask.setTaskDefKey(task.getTaskDefinitionKey()); flowTask.setCreateTime(task.getCreateTime()); flowTask.setProcDefId(task.getProcessDefinitionId()); flowTask.setTaskName(task.getName()); // 流程定义信息 ProcessDefinition pd = repositoryService.createProcessDefinitionQuery() .processDefinitionId(task.getProcessDefinitionId()) .singleResult(); flowTask.setDeployId(pd.getDeploymentId()); flowTask.setProcDefName(pd.getName()); flowTask.setProcDefVersion(pd.getVersion()); flowTask.setProcInsId(task.getProcessInstanceId()); // 流程发起人信息 HistoricProcessInstance historicProcessInstance = historyService.createHistoricProcessInstanceQuery() .processInstanceId(task.getProcessInstanceId()) .singleResult(); String userId = historicProcessInstance.getStartUserId(); String nickName = userService.selectNickNameById(userId); flowTask.setStartUserId(userId); flowTask.setStartUserName(nickName); flowList.add(flowTask); } return flowList; } @Override public TableDataInfo selectPageFinishedProcessList(ProcessQuery processQuery, PageQuery pageQuery) { Page page = new Page<>(); HistoricTaskInstanceQuery taskInstanceQuery = historyService.createHistoricTaskInstanceQuery() .includeProcessVariables() .finished() .taskAssignee(TaskUtils.getUserId()) .orderByHistoricTaskInstanceEndTime() .desc(); // 构建搜索条件 ProcessUtils.buildProcessSearch(taskInstanceQuery, processQuery); int offset = pageQuery.getPageSize() * (pageQuery.getPageNum() - 1); List historicTaskInstanceList = taskInstanceQuery.listPage(offset, pageQuery.getPageSize()); List hisTaskList = new ArrayList<>(); for (HistoricTaskInstance histTask : historicTaskInstanceList) { WfTaskVo flowTask = new WfTaskVo(); // 当前流程信息 flowTask.setTaskId(histTask.getId()); // 审批人员信息 flowTask.setCreateTime(histTask.getCreateTime()); flowTask.setFinishTime(histTask.getEndTime()); flowTask.setDuration(DateUtil.formatBetween(histTask.getDurationInMillis(), BetweenFormatter.Level.SECOND)); flowTask.setProcDefId(histTask.getProcessDefinitionId()); flowTask.setTaskDefKey(histTask.getTaskDefinitionKey()); flowTask.setTaskName(histTask.getName()); // 流程定义信息 ProcessDefinition pd = repositoryService.createProcessDefinitionQuery() .processDefinitionId(histTask.getProcessDefinitionId()) .singleResult(); flowTask.setDeployId(pd.getDeploymentId()); flowTask.setProcDefName(pd.getName()); flowTask.setProcDefVersion(pd.getVersion()); flowTask.setProcInsId(histTask.getProcessInstanceId()); flowTask.setHisProcInsId(histTask.getProcessInstanceId()); // 流程发起人信息 HistoricProcessInstance historicProcessInstance = historyService.createHistoricProcessInstanceQuery() .processInstanceId(histTask.getProcessInstanceId()) .singleResult(); String userId = historicProcessInstance.getStartUserId(); String nickName = userService.selectNickNameById(userId); flowTask.setStartUserId(userId); flowTask.setStartUserName(nickName); // 流程变量 flowTask.setProcVars(histTask.getProcessVariables()); flowTask.setBusinessKey(historicProcessInstance.getBusinessKey()); hisTaskList.add(flowTask); } page.setTotal(taskInstanceQuery.count()); page.setRecords(hisTaskList); // Map result = new HashMap<>(); // result.put("result",page); // result.put("finished",true); return TableDataInfo.build(page); } @Override public List selectFinishedProcessList(ProcessQuery processQuery) { HistoricTaskInstanceQuery taskInstanceQuery = historyService.createHistoricTaskInstanceQuery() .includeProcessVariables() .finished() .taskAssignee(TaskUtils.getUserId()) .orderByHistoricTaskInstanceEndTime() .desc(); // 构建搜索条件 ProcessUtils.buildProcessSearch(taskInstanceQuery, processQuery); List historicTaskInstanceList = taskInstanceQuery.list(); List hisTaskList = new ArrayList<>(); for (HistoricTaskInstance histTask : historicTaskInstanceList) { WfTaskVo flowTask = new WfTaskVo(); // 当前流程信息 flowTask.setTaskId(histTask.getId()); // 审批人员信息 flowTask.setCreateTime(histTask.getCreateTime()); flowTask.setFinishTime(histTask.getEndTime()); flowTask.setDuration(DateUtil.formatBetween(histTask.getDurationInMillis(), BetweenFormatter.Level.SECOND)); flowTask.setProcDefId(histTask.getProcessDefinitionId()); flowTask.setTaskDefKey(histTask.getTaskDefinitionKey()); flowTask.setTaskName(histTask.getName()); // 流程定义信息 ProcessDefinition pd = repositoryService.createProcessDefinitionQuery() .processDefinitionId(histTask.getProcessDefinitionId()) .singleResult(); flowTask.setDeployId(pd.getDeploymentId()); flowTask.setProcDefName(pd.getName()); flowTask.setProcDefVersion(pd.getVersion()); flowTask.setProcInsId(histTask.getProcessInstanceId()); flowTask.setHisProcInsId(histTask.getProcessInstanceId()); // 流程发起人信息 HistoricProcessInstance historicProcessInstance = historyService.createHistoricProcessInstanceQuery() .processInstanceId(histTask.getProcessInstanceId()) .singleResult(); String userId = historicProcessInstance.getStartUserId(); String nickName = userService.selectNickNameById(userId); flowTask.setStartUserId(userId); flowTask.setStartUserName(nickName); // 流程变量 flowTask.setProcVars(histTask.getProcessVariables()); hisTaskList.add(flowTask); } return hisTaskList; } @Override public FormConf selectFormContent(String definitionId, String deployId, String procInsId) { BpmnModel bpmnModel = repositoryService.getBpmnModel(definitionId); if (ObjectUtil.isNull(bpmnModel)) { throw new RuntimeException("获取流程设计失败!"); } StartEvent startEvent = ModelUtils.getStartEvent(bpmnModel); WfDeployForm deployForm = deployFormMapper.selectOne(new LambdaQueryWrapper() .eq(WfDeployForm::getDeployId, deployId) .eq(WfDeployForm::getFormKey, startEvent.getFormKey()) .eq(WfDeployForm::getNodeKey, startEvent.getId())); FormConf formConf = JsonUtils.parseObject(deployForm.getContent(), FormConf.class); if (ObjectUtil.isNull(formConf)) { throw new RuntimeException("获取流程表单失败!"); } if (ObjectUtil.isNotEmpty(procInsId)) { // 获取流程实例 HistoricProcessInstance historicProcIns = historyService.createHistoricProcessInstanceQuery() .processInstanceId(procInsId) .includeProcessVariables() .singleResult(); // 填充表单信息 ProcessFormUtils.fillFormData(formConf, historicProcIns.getProcessVariables()); } return formConf; } /** * 根据流程定义ID启动流程实例 * * @param procDefId 流程定义Id * @param variables 流程变量 * @return */ @Override @Transactional(rollbackFor = Exception.class) public void startProcessByDefId(String procDefId, Map variables) { try { ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery() .processDefinitionId(procDefId).singleResult(); startProcess(processDefinition, variables); } catch (Exception e) { e.printStackTrace(); throw new ServiceException("流程启动错误"); } } /** * 通过DefinitionKey启动流程 * * @param procDefKey 流程定义Key * @param variables 扩展参数 */ @Override @Transactional(rollbackFor = Exception.class) public void startProcessByDefKey(String procDefKey, Map variables) { try { ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery() .processDefinitionKey(procDefKey).latestVersion().singleResult(); startProcess(processDefinition, variables); } catch (Exception e) { e.printStackTrace(); throw new ServiceException("流程启动错误"); } } @Override @Transactional(rollbackFor = Exception.class) public void deleteProcessByIds(String[] instanceIds) { List ids = Arrays.asList(instanceIds); // 校验流程是否结束 long activeInsCount = runtimeService.createProcessInstanceQuery() .processInstanceIds(new HashSet<>(ids)).active().count(); if (activeInsCount > 0) { throw new ServiceException("不允许删除进行中的流程实例"); } // 删除历史流程实例 historyService.bulkDeleteHistoricProcessInstances(ids); } /** * 读取xml文件 * * @param processDefId 流程定义ID */ @Override public String queryBpmnXmlById(String processDefId) { InputStream inputStream = repositoryService.getProcessModel(processDefId); try { return IoUtil.readUtf8(inputStream); } catch (IORuntimeException exception) { throw new RuntimeException("加载xml文件异常"); } } /** * 流程详情信息 * * @param procInsId 流程实例ID * @param taskId 任务ID * @return */ @Override public WfDetailVo queryProcessDetail(String procInsId, String taskId) { WfDetailVo detailVo = new WfDetailVo(); // 获取流程实例 HistoricProcessInstance historicProcIns = historyService.createHistoricProcessInstanceQuery() .processInstanceId(procInsId) .includeProcessVariables() .singleResult(); if (StringUtils.isNotBlank(taskId)) { HistoricTaskInstance taskIns = historyService.createHistoricTaskInstanceQuery() .taskId(taskId) .includeIdentityLinks() .includeProcessVariables() .includeTaskLocalVariables() .singleResult(); if (taskIns == null) { throw new ServiceException("没有可办理的任务!"); } detailVo.setBusinessKey(historicProcIns.getBusinessKey()); detailVo.setTaskFormData(currTaskFormData(historicProcIns.getDeploymentId(), taskIns)); } // 获取Bpmn模型信息 InputStream inputStream = repositoryService.getProcessModel(historicProcIns.getProcessDefinitionId()); String bpmnXmlStr = StrUtil.utf8Str(IoUtil.readBytes(inputStream, false)); BpmnModel bpmnModel = ModelUtils.getBpmnModel(bpmnXmlStr); detailVo.setBpmnXml(bpmnXmlStr); detailVo.setHistoryProcNodeList(historyProcNodeList(historicProcIns)); // detailVo.setProcessFormList(processFormList(bpmnModel, historicProcIns)); detailVo.setFlowViewer(getFlowViewer(bpmnModel, procInsId)); return detailVo; } @Override public WfDetailVo queryProcessDetail(String businessKey) { WfDetailVo detailVo = new WfDetailVo(); // 获取流程实例 HistoricProcessInstance historicProcIns = null; long count = historyService.createHistoricProcessInstanceQuery() .processInstanceBusinessKey(businessKey) .includeProcessVariables() .orderByProcessInstanceStartTime().desc() .count(); if(count > 0){ historicProcIns = historyService.createHistoricProcessInstanceQuery() .processInstanceBusinessKey(businessKey) .includeProcessVariables() .orderByProcessInstanceStartTime().desc() // 按开始时间倒序排序 .listPage(0, 1) // 获取第一页的结果,限制为1条 .get(0); // 获取第一条结果 } if (historicProcIns == null) { // throw new ServiceException("没有找到与业务主键对应的流程实例!"); return null; } detailVo.setBusinessKey(historicProcIns.getBusinessKey()); // 获取Bpmn模型信息 InputStream inputStream = repositoryService.getProcessModel(historicProcIns.getProcessDefinitionId()); String bpmnXmlStr = StrUtil.utf8Str(IoUtil.readBytes(inputStream, false)); BpmnModel bpmnModel = ModelUtils.getBpmnModel(bpmnXmlStr); detailVo.setBpmnXml(bpmnXmlStr); detailVo.setHistoryProcNodeList(historyProcNodeList(historicProcIns)); detailVo.setFlowViewer(getFlowViewer(bpmnModel, historicProcIns.getId())); return detailVo; } /** * 启动流程实例 */ private void startProcess(ProcessDefinition procDef, Map variables) { if (ObjectUtil.isNotNull(procDef) && procDef.isSuspended()) { throw new ServiceException("流程已被挂起,请先激活流程"); } // 设置流程发起人Id到流程中 String userIdStr = TaskUtils.getUserId(); identityService.setAuthenticatedUserId(userIdStr); variables.put(BpmnXMLConstants.ATTRIBUTE_EVENT_START_INITIATOR, userIdStr); // 设置流程状态为进行中 variables.put(ProcessConstants.PROCESS_STATUS_KEY, ProcessStatus.RUNNING.getStatus()); // 发起流程实例 ProcessInstance processInstance = runtimeService.startProcessInstanceById(procDef.getId(), variables); // 第一个用户任务为发起人,则自动完成任务 wfTaskService.startFirstTask(processInstance, variables); } /** * 获取流程变量 * * @param taskId 任务ID * @return 流程变量 */ private Map getProcessVariables(String taskId) { HistoricTaskInstance historicTaskInstance = historyService.createHistoricTaskInstanceQuery() .includeProcessVariables() .finished() .taskId(taskId) .singleResult(); if (Objects.nonNull(historicTaskInstance)) { return historicTaskInstance.getProcessVariables(); } return taskService.getVariables(taskId); } /** * 获取当前任务流程表单信息 */ private WfDeployFormVo currTaskFormData(String deployId, HistoricTaskInstance taskIns) { WfDeployFormVo deployFormVo = deployFormMapper.selectVoOne(new LambdaQueryWrapper() .eq(WfDeployForm::getDeployId, deployId) .eq(WfDeployForm::getFormKey, taskIns.getFormKey()) .eq(WfDeployForm::getNodeKey, taskIns.getTaskDefinitionKey())); // if (ObjectUtil.isNotEmpty(deployFormVo)) { // FormConf currTaskFormData = JsonUtils.parseObject(deployFormVo.getContent(), FormConf.class); // if (null != currTaskFormData) { // currTaskFormData.setFormBtns(false); // ProcessFormUtils.fillFormData(currTaskFormData, taskIns.getTaskLocalVariables()); // return currTaskFormData; // } // } return deployFormVo; } /** * 获取历史流程表单信息 */ private List processFormList(BpmnModel bpmnModel, HistoricProcessInstance historicProcIns) { List procFormList = new ArrayList<>(); List activityInstanceList = historyService.createHistoricActivityInstanceQuery() .processInstanceId(historicProcIns.getId()).finished() .activityTypes(CollUtil.newHashSet(BpmnXMLConstants.ELEMENT_EVENT_START, BpmnXMLConstants.ELEMENT_TASK_USER)) .orderByHistoricActivityInstanceStartTime().asc() .list(); List processFormKeys = new ArrayList<>(); for (HistoricActivityInstance activityInstance : activityInstanceList) { // 获取当前节点流程元素信息 FlowElement flowElement = ModelUtils.getFlowElementById(bpmnModel, activityInstance.getActivityId()); // 获取当前节点表单Key String formKey = ModelUtils.getFormKey(flowElement); if (formKey == null) { continue; } boolean localScope = Convert.toBool(ModelUtils.getElementAttributeValue(flowElement, ProcessConstants.PROCESS_FORM_LOCAL_SCOPE), false); Map variables; if (localScope) { // 查询任务节点参数,并转换成Map variables = historyService.createHistoricVariableInstanceQuery() .processInstanceId(historicProcIns.getId()) .taskId(activityInstance.getTaskId()) .list() .stream() .collect(Collectors.toMap(HistoricVariableInstance::getVariableName, HistoricVariableInstance::getValue)); } else { if (processFormKeys.contains(formKey)) { continue; } variables = historicProcIns.getProcessVariables(); processFormKeys.add(formKey); } // 非节点表单此处查询结果可能有多条,只获取第一条信息 List formInfoList = deployFormMapper.selectVoList(new LambdaQueryWrapper() .eq(WfDeployForm::getDeployId, historicProcIns.getDeploymentId()) .eq(WfDeployForm::getFormKey, formKey) .eq(localScope, WfDeployForm::getNodeKey, flowElement.getId())); //@update by Brath:避免空集合导致的NULL空指针 WfDeployFormVo formInfo = formInfoList.stream().findFirst().orElse(null); if (ObjectUtil.isNotNull(formInfo)) { // 旧数据 formInfo.getFormName() 为 null String formName = Optional.ofNullable(formInfo.getFormName()).orElse(StringUtils.EMPTY); String title = localScope ? formName.concat("(" + flowElement.getName() + ")") : formName; FormConf formConf = JsonUtils.parseObject(formInfo.getContent(), FormConf.class); if (null != formConf) { formConf.setTitle(title); formConf.setDisabled(true); formConf.setFormBtns(false); ProcessFormUtils.fillFormData(formConf, variables); procFormList.add(formConf); } } } return procFormList; } @Deprecated private void buildStartFormData(HistoricProcessInstance historicProcIns, Process process, String deployId, List procFormList) { procFormList = procFormList == null ? new ArrayList<>() : procFormList; HistoricActivityInstance startInstance = historyService.createHistoricActivityInstanceQuery() .processInstanceId(historicProcIns.getId()) .activityId(historicProcIns.getStartActivityId()) .singleResult(); StartEvent startEvent = (StartEvent) process.getFlowElement(startInstance.getActivityId()); WfDeployFormVo startFormInfo = deployFormMapper.selectVoOne(new LambdaQueryWrapper() .eq(WfDeployForm::getDeployId, deployId) .eq(WfDeployForm::getFormKey, startEvent.getFormKey()) .eq(WfDeployForm::getNodeKey, startEvent.getId())); if (ObjectUtil.isNotNull(startFormInfo)) { FormConf formConf = JsonUtils.parseObject(startFormInfo.getContent(), FormConf.class); if (null != formConf) { formConf.setTitle(startEvent.getName()); formConf.setDisabled(true); formConf.setFormBtns(false); ProcessFormUtils.fillFormData(formConf, historicProcIns.getProcessVariables()); procFormList.add(formConf); } } } @Deprecated private void buildUserTaskFormData(String procInsId, String deployId, Process process, List procFormList) { procFormList = procFormList == null ? new ArrayList<>() : procFormList; List activityInstanceList = historyService.createHistoricActivityInstanceQuery() .processInstanceId(procInsId).finished() .activityType(BpmnXMLConstants.ELEMENT_TASK_USER) .orderByHistoricActivityInstanceStartTime().asc() .list(); for (HistoricActivityInstance instanceItem : activityInstanceList) { UserTask userTask = (UserTask) process.getFlowElement(instanceItem.getActivityId(), true); String formKey = userTask.getFormKey(); if (formKey == null) { continue; } // 查询任务节点参数,并转换成Map Map variables = historyService.createHistoricVariableInstanceQuery() .processInstanceId(procInsId) .taskId(instanceItem.getTaskId()) .list() .stream() .collect(Collectors.toMap(HistoricVariableInstance::getVariableName, HistoricVariableInstance::getValue)); WfDeployFormVo deployFormVo = deployFormMapper.selectVoOne(new LambdaQueryWrapper() .eq(WfDeployForm::getDeployId, deployId) .eq(WfDeployForm::getFormKey, formKey) .eq(WfDeployForm::getNodeKey, userTask.getId())); if (ObjectUtil.isNotNull(deployFormVo)) { FormConf formConf = JsonUtils.parseObject(deployFormVo.getContent(), FormConf.class); if (null != formConf) { formConf.setTitle(userTask.getName()); formConf.setDisabled(true); formConf.setFormBtns(false); ProcessFormUtils.fillFormData(formConf, variables); procFormList.add(formConf); } } } } /** * 获取历史任务信息列表 */ private List historyProcNodeList(HistoricProcessInstance historicProcIns) { String procInsId = historicProcIns.getId(); List historicActivityInstanceList = historyService.createHistoricActivityInstanceQuery() .processInstanceId(procInsId) .activityTypes(CollUtil.newHashSet(BpmnXMLConstants.ELEMENT_EVENT_START, BpmnXMLConstants.ELEMENT_EVENT_END, BpmnXMLConstants.ELEMENT_TASK_USER)) .orderByHistoricActivityInstanceStartTime().desc() .orderByHistoricActivityInstanceEndTime().desc() .list(); List commentList = taskService.getProcessInstanceComments(procInsId); List elementVoList = new ArrayList<>(); for (HistoricActivityInstance activityInstance : historicActivityInstanceList) { WfProcNodeVo elementVo = new WfProcNodeVo(); elementVo.setProcDefId(activityInstance.getProcessDefinitionId()); elementVo.setActivityId(activityInstance.getActivityId()); elementVo.setActivityName(activityInstance.getActivityName()); elementVo.setActivityType(activityInstance.getActivityType()); elementVo.setCreateTime(activityInstance.getStartTime()); elementVo.setEndTime(activityInstance.getEndTime()); if (ObjectUtil.isNotNull(activityInstance.getDurationInMillis())) { elementVo.setDuration(DateUtil.formatBetween(activityInstance.getDurationInMillis(), BetweenFormatter.Level.SECOND)); } if (BpmnXMLConstants.ELEMENT_EVENT_START.equals(activityInstance.getActivityType())) { if (ObjectUtil.isNotNull(historicProcIns)) { String userId = historicProcIns.getStartUserId(); String nickName = userService.selectNickNameById(userId); if (nickName != null) { elementVo.setAssigneeId(userId); elementVo.setAssigneeName(nickName); } } } else if (BpmnXMLConstants.ELEMENT_TASK_USER.equals(activityInstance.getActivityType())) { if (StringUtils.isNotBlank(activityInstance.getAssignee())) { String userId = activityInstance.getAssignee(); String nickName = userService.selectNickNameById(userId); elementVo.setAssigneeId(userId); elementVo.setAssigneeName(nickName); } // 展示审批人员 List linksForTask = historyService.getHistoricIdentityLinksForTask(activityInstance.getTaskId()); StringBuilder stringBuilder = new StringBuilder(); for (HistoricIdentityLink identityLink : linksForTask) { if ("candidate".equals(identityLink.getType())) { if (StringUtils.isNotBlank(identityLink.getUserId())) { String userId = identityLink.getUserId(); String nickName = userService.selectNickNameById(userId); stringBuilder.append(nickName).append(","); } if (StringUtils.isNotBlank(identityLink.getGroupId())) { if (identityLink.getGroupId().startsWith(TaskConstants.ROLE_GROUP_PREFIX)) { String roleId = StringUtils.stripStart(identityLink.getGroupId(), TaskConstants.ROLE_GROUP_PREFIX); // Long roleId = Long.parseLong(); SysRole role = roleService.selectRoleById(roleId); stringBuilder.append(role.getRoleName()).append(","); } else if (identityLink.getGroupId().startsWith(TaskConstants.DEPT_GROUP_PREFIX)) { Long deptId = Long.parseLong(StringUtils.stripStart(identityLink.getGroupId(), TaskConstants.DEPT_GROUP_PREFIX)); SysDept dept = deptService.selectDeptById(deptId); stringBuilder.append(dept.getDeptName()).append(","); } } } } if (StringUtils.isNotBlank(stringBuilder)) { elementVo.setCandidate(stringBuilder.substring(0, stringBuilder.length() - 1)); } // 获取意见评论内容 if (CollUtil.isNotEmpty(commentList)) { List comments = new ArrayList<>(); for (Comment comment : commentList) { if (comment.getTaskId().equals(activityInstance.getTaskId())) { comments.add(comment); } } elementVo.setCommentList(comments); } } elementVoList.add(elementVo); } return elementVoList; } /** * 获取流程执行过程 * * @param procInsId * @return */ private WfViewerVo getFlowViewer(BpmnModel bpmnModel, String procInsId) { // 构建查询条件 HistoricActivityInstanceQuery query = historyService.createHistoricActivityInstanceQuery() .processInstanceId(procInsId); List allActivityInstanceList = query.list(); if (CollUtil.isEmpty(allActivityInstanceList)) { return new WfViewerVo(); } // 查询所有已完成的元素 List finishedElementList = allActivityInstanceList.stream() .filter(item -> ObjectUtil.isNotNull(item.getEndTime())).collect(Collectors.toList()); // 所有已完成的连线 Set finishedSequenceFlowSet = new HashSet<>(); // 所有已完成的任务节点 Set finishedTaskSet = new HashSet<>(); finishedElementList.forEach(item -> { if (BpmnXMLConstants.ELEMENT_SEQUENCE_FLOW.equals(item.getActivityType())) { finishedSequenceFlowSet.add(item.getActivityId()); } else { finishedTaskSet.add(item.getActivityId()); } }); // 查询所有未结束的节点 Set unfinishedTaskSet = allActivityInstanceList.stream() .filter(item -> ObjectUtil.isNull(item.getEndTime())) .map(HistoricActivityInstance::getActivityId) .collect(Collectors.toSet()); // DFS 查询未通过的元素集合 Set rejectedSet = FlowableUtils.dfsFindRejects(bpmnModel, unfinishedTaskSet, finishedSequenceFlowSet, finishedTaskSet); return new WfViewerVo(finishedTaskSet, finishedSequenceFlowSet, unfinishedTaskSet, rejectedSet); } }