简单的camunda流程处理开发记录

时间:2025-02-15 07:33:51
package cn.git.camunda.service.impl; import cn.git.camunda.consts.CamundaConst; import cn.git.camunda.dto.*; import cn.git.camunda.entity.*; import cn.git.camunda.mapper.ActReProcdefMapper; import cn.git.camunda.mapper.CamundaJumpPointMapper; import cn.git.camunda.mapper.CamundaUnfinishedFlowMapper; import cn.git.camunda.page.CamundaFlowPage; import cn.git.camunda.page.PageUtil; import cn.git.camunda.service.CamundaCommonService; import cn.git.camunda.util.CamundaFlowTypeEnum; import cn.git.camunda.util.CamundaSysEnum; import cn.git.camunda.util.CamundaTenantEnum; import cn.git.camunda.util.CamundaUtil; import cn.git.common.exception.ServiceException; import cn.git.common.page.PaginationContext; import cn.git.common.util.LogUtil; import cn.git.common.util.WebUtil; import cn.hutool.core.date.DatePattern; import cn.hutool.core.date.DateUtil; import cn.hutool.core.util.IdUtil; import cn.hutool.core.util.ObjectUtil; import cn.hutool.core.util.StrUtil; import com.alibaba.fastjson.JSONObject; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import lombok.extern.slf4j.Slf4j; import org.apache.commons.io.IOUtils; import org.camunda.bpm.engine.*; import org.camunda.bpm.engine.history.*; import org.camunda.bpm.engine.impl.persistence.entity.ProcessDefinitionEntity; import org.camunda.bpm.engine.impl.pvm.PvmActivity; import org.camunda.bpm.engine.impl.pvm.PvmTransition; import org.camunda.bpm.engine.impl.pvm.process.ActivityImpl; import org.camunda.bpm.engine.repository.Deployment; import org.camunda.bpm.engine.repository.ProcessDefinition; import org.camunda.bpm.engine.repository.ProcessDefinitionQuery; import org.camunda.bpm.engine.runtime.ProcessInstance; import org.camunda.bpm.engine.runtime.ProcessInstanceModificationInstantiationBuilder; import org.camunda.bpm.engine.runtime.ProcessInstantiationBuilder; import org.camunda.bpm.engine.task.Comment; import org.camunda.bpm.engine.task.Task; import org.camunda.bpm.engine.task.TaskQuery; import org.camunda.bpm.engine.variable.VariableMap; import org.camunda.bpm.engine.variable.Variables; import org.camunda.bpm.model.bpmn.BpmnModelInstance; import org.camunda.bpm.model.bpmn.impl.instance.ProcessImpl; import org.camunda.bpm.model.bpmn.impl.instance.UserTaskImpl; import org.camunda.bpm.model.bpmn.instance.FlowNode; import org.camunda.bpm.model.bpmn.instance.Process; import org.camunda.bpm.model.bpmn.instance.SequenceFlow; import org.camunda.bpm.model.bpmn.instance.UserTask; import org.camunda.bpm.model.xml.instance.ModelElementInstance; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.web.multipart.MultipartFile; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.nio.charset.StandardCharsets; import java.util.*; import java.util.function.Function; import java.util.stream.Collectors; /** * @description: camunda通用方法service * @program: bank-credit-sy * @author: lixuchun * @create: 2023-09-12 09:12:05 */ @Slf4j @Service public class CamundaCommonServiceImpl implements CamundaCommonService { @Autowired private TaskService taskService; @Autowired private RuntimeService runtimeService; @Autowired private IdentityService identityService; @Autowired private RepositoryService repositoryService; @Autowired private HistoryService historyService; @Autowired private ProcessEngine processEngine; @Autowired private CamundaUnfinishedFlowMapper camundaUnfinishedFlowMapper; @Autowired private ActReProcdefMapper actReProcdefMapper; @Autowired private CamundaJumpPointMapper camundaJumpPointMapper; @Autowired private FormService formService; @Autowired private PageUtil pageUtil; @Autowired private CamundaUtil camundaUtil; @Autowired private HttpServletResponse response; @Autowired private WebUtil webUtil; /** * 发起流程 * * @param startProcessDTO 参数dto * @return rspDTO */ @Override @Transactional(rollbackFor = Exception.class) public CamundaStartRspDTO startProcess(CamundaStartProcessDTO startProcessDTO) { // 发起流程key String businessKey = startProcessDTO.getBusinessKey(); log.info("businessKey[{}]准备发起流程,入参startProcessDTO为[{}]", businessKey, JSONObject.toJSONString(startProcessDTO)); // 设置发起流程操作员标识,以及认证信息(group组信息,tenantId租户信息) String creator = startProcessDTO.getUserCd().concat(StrUtil.COLON).concat(startProcessDTO.getOrgCd()); identityService.setAuthentication(creator, Arrays.asList(startProcessDTO.getCamundaTenantEnum().getGroup()), Arrays.asList(startProcessDTO.getCamundaTenantEnum().getTenantId())); log.info("businessKey[{}]发起流程设置操作员信息成功", businessKey); // 设置传递参数信息 VariableMap variableMap = Variables.createVariables(); // 流程发起用户id variableMap.put(CamundaConst.USER_ID_FLAG, creator); // 流程模板id variableMap.put(CamundaConst.PROCESS_TEMPLATE_KEY, startProcessDTO.getCamundaFlowTypeEnum().getProcessTemplateKey()); // 流程业务id variableMap.put(CamundaConst.BUSINESS_KEY_FLAG, startProcessDTO.getBusinessKey()); // 流程业务类型 variableMap.put(CamundaConst.PROCESS_BIZ_TYPE, startProcessDTO.getCamundaFlowTypeEnum().getBizType()); // 流程业务名称 variableMap.put(CamundaConst.PROCESS_BIZ_NAME, startProcessDTO.getCamundaFlowTypeEnum().getBizName()); // 流程发起人 variableMap.put(CamundaConst.PROCESS_CREATOR, creator); // 设置机构信息 variableMap.put(CamundaConst.ORG_NAME_FLAG, webUtil.getCurrentOrgName()); // 客户名称 variableMap.put(CamundaConst.CUSTOMER_NAME_FLAG, startProcessDTO.getCustomerName()); // 客户编号 variableMap.put(CamundaConst.CUSTOMER_NUM_FLAG, startProcessDTO.getCustomerNum()); // 发起系统来源 variableMap.put(CamundaConst.SYSTEM, startProcessDTO.getCamundaSysEnum().getSystemFlag()); // 设置自定义参数信息 if (ObjectUtil.isNotEmpty(startProcessDTO.getVariableMap())) { variableMap.putAll(startProcessDTO.getVariableMap()); log.info("businessKey[{}]发起流程设置操作参数信息成功,参数为[{}]", businessKey, JSONObject.toJSONString(variableMap)); } // 发起流程 log.info("businessKey[{}]装备发起流程!", businessKey); String templateKey = startProcessDTO.getCamundaFlowTypeEnum().getProcessTemplateKey(); ProcessInstantiationBuilder builder = runtimeService.createProcessInstanceByKey(templateKey) .processDefinitionTenantId(startProcessDTO.getCamundaTenantEnum().getTenantId()) .businessKey(startProcessDTO.getBusinessKey()) .setVariables(variableMap); ProcessInstance processInstance = builder.execute(); // 设置响应信息 CamundaStartRspDTO camundaStartRspDTO = null; if (ObjectUtil.isNotNull(processInstance)) { camundaStartRspDTO = new CamundaStartRspDTO(); // 流程processId String processInstanceId = processInstance.getProcessInstanceId(); // 通过 processId,获取task信息进行返回 Task task = taskService.createTaskQuery() .tenantIdIn(startProcessDTO.getCamundaTenantEnum().getTenantId()) .processInstanceId(processInstanceId).singleResult(); if (ObjectUtil.isNotNull(task)) { camundaStartRspDTO.setProcessId(processInstanceId); camundaStartRspDTO.setTaskId(task.getId()); camundaStartRspDTO.setTaskName(task.getName()); // 当前流程任务定义key camundaStartRspDTO.setTaskDefinitionKey(task.getTaskDefinitionKey()); log.info("businessKey[{}],发起流程后,获取任务信息为[{}]", businessKey, JSONObject.toJSONString(camundaStartRspDTO)); // 新增业务插入到在途业务表中,自定义代办任务记录表,业务系统方便查询。 CamundaUnfinishedFlow camundaUnfinishedFlow = new CamundaUnfinishedFlow(); camundaUnfinishedFlow.setId(IdUtil.simpleUUID()); camundaUnfinishedFlow.setOptionOrgCd(startProcessDTO.getUserCd()); camundaUnfinishedFlow.setOptionOrgCd(startProcessDTO.getOrgCd()); camundaUnfinishedFlow.setCustomerNum(startProcessDTO.getCustomerNum()); camundaUnfinishedFlow.setCustomerName(startProcessDTO.getCustomerName()); camundaUnfinishedFlow.setBusinessKey(startProcessDTO.getBusinessKey()); camundaUnfinishedFlow.setProcessId(processInstanceId); camundaUnfinishedFlow.setBizName(startProcessDTO.getCamundaFlowTypeEnum().getBizName()); camundaUnfinishedFlow.setProcessTemplateKey(startProcessDTO.getCamundaFlowTypeEnum().getProcessTemplateKey()); if (ObjectUtil.isNotNull(startProcessDTO.getCamundaSysEnum())) { camundaUnfinishedFlow.setSystemFlag(startProcessDTO.getCamundaSysEnum().getSystemFlag()); } else { camundaUnfinishedFlow.setSystemFlag(CamundaSysEnum.DICS.getSystemFlag()); } camundaUnfinishedFlowMapper.insert(camundaUnfinishedFlow); } } return camundaStartRspDTO; } /** * 通过柜员编号和机构编号获取代办未分类列表信息 * * @param camundaUndoCountDTO 参数dto * @return */ @Override public CamundaFlowPage<List<CamundaUndoCount>> getUndoCountList(CamundaUndoCountDTO camundaUndoCountDTO) { // 创建一个查询接口,进行传入操作标识人员代办任务查询 String userId = camundaUndoCountDTO.getUserCd().concat(StrUtil.COLON).concat(camundaUndoCountDTO.getOrgCd()); TaskQuery taskQuery = taskService.createTaskQuery() // 具体操作人员标识 .taskAssignee(userId) // 未被挂起任务 .active() // 租户信息 .tenantIdIn(camundaUndoCountDTO.getCamundaTenantEnum().getTenantId()) // 获取参数信息 .matchVariableNamesIgnoreCase(); // 设定查询模板类型 if (StrUtil.isNotBlank(camundaUndoCountDTO.getProcessTemplateKey())) { taskQuery.processDefinitionKey(camundaUndoCountDTO.getProcessTemplateKey()); } // 查询带如下参数的流程信息 Map<String, Object> paramMap = camundaUndoCountDTO.getParamMap(); if (ObjectUtil.isNotEmpty(paramMap)) { for (String key : camundaUndoCountDTO.getParamMap().keySet()) { taskQuery.processVariableValueEquals(key, paramMap.get(key)); } } // 计算从哪条开始取,如何取出数据 List<Task> taskList = taskQuery.list(); // 对代办数据进行分类求count处理 List<CamundaUndoCount> camundaUndoCountList = new ArrayList<>(); if (ObjectUtil.isNotEmpty(taskList)) { // 获取所有任务代办任务类型数据 List<String> processIdList = taskList.stream().map(Task::getProcessInstanceId).collect(Collectors.toList()); QueryWrapper<CamundaUnfinishedFlow> unfinishedFlowQueryWrapper = new QueryWrapper<>(); unfinishedFlowQueryWrapper.lambda().in(CamundaUnfinishedFlow::getProcessId, processIdList); List<CamundaUnfinishedFlow> unfinishedFlowList = camundaUnfinishedFlowMapper .selectList(unfinishedFlowQueryWrapper); // 将查询数据转换为map信息 Map<String, CamundaUnfinishedFlow> unfinishedFlowMap = unfinishedFlowList.stream().collect( Collectors.toMap( CamundaUnfinishedFlow::getProcessId, Function.identity(), (k1, k2) -> k1 ) ); Map<String, CamundaUndoCount> undoCountMap = new HashMap<>(CamundaConst.INT_16); taskList.forEach(task -> { // 对任务进行分类计算count信息 CamundaUnfinishedFlow unfinishedFlow = unfinishedFlowMap.get(task.getProcessInstanceId()); if (ObjectUtil.isNotNull(unfinishedFlow)) { // 获取流程模板id以及流程模板枚举类型 String processTemplateKey = unfinishedFlow.getProcessTemplateKey(); CamundaFlowTypeEnum flowTypeEnum = camundaUtil.getCamundaEnumByTemplateKey(processTemplateKey); if (ObjectUtil.isNotNull(flowTypeEnum)) { // 如果此类型有值,则count数进行加一 if (ObjectUtil.isNotNull(undoCountMap.get(processTemplateKey))) { CamundaUndoCount currentUndoCount = undoCountMap.get(processTemplateKey); currentUndoCount.setBizCount(currentUndoCount.getBizCount() + 1); undoCountMap.put(processTemplateKey, currentUndoCount); } else { // 首次添加 CamundaUndoCount camundaUndoCount = new CamundaUndoCount(); camundaUndoCount.setBizCount(CamundaConst.INT_1); camundaUndoCount.setBizTypeName(flowTypeEnum.getBizName()); camundaUndoCount.setBizType(flowTypeEnum.getBizType()); undoCountMap.put(processTemplateKey, camundaUndoCount); } } } }); // 封装返回信息list if (ObjectUtil.isNotEmpty(undoCountMap)) { undoCountMap.forEach((key, value) -> { camundaUndoCountList.add(value); }); } } return pageUtil.setFlowListPage(camundaUndoCountList, PaginationContext.getPageNum(), PaginationContext.getPageSize()); } /** * 查询代办分类后单一业务列表信息 * * @param camundaUndoTaskDTO 参数dto * @return */ @Override @Transactional(rollbackFor = Exception.class) public CamundaFlowPage<CamundaUndoTask> getUndoTaskList(CamundaUndoTaskDTO camundaUndoTaskDTO) { // 创建一个查询接口,进行传入操作标识人员代办任务查询 String userId = camundaUndoTaskDTO.getUserCd().concat(StrUtil.COLON).concat(camundaUndoTaskDTO.getOrgCd()); TaskQuery taskQuery = taskService.createTaskQuery() // 具体操作人员标识 .taskAssignee(userId) // 未被挂起任务 .active() // 租户信息 .tenantIdIn(camundaUndoTaskDTO.getCamundaTenantEnum().getTenantId()) // 获取参数信息 .matchVariableNamesIgnoreCase() .orderByTaskCreateTime() .desc(); // 设定查询模板类型 String processTemplateKey = camundaUndoTaskDTO.getProcessTemplateKey(); if (StrUtil.isNotBlank(processTemplateKey)) { taskQuery.processDefinitionKey(processTemplateKey); } else { throw new ServiceException("单一业务模板查询必填!"); } // 查询总条数信息 int totalCount = (int) taskQuery.count(); // 分页查询 int firstResultNum = pageUtil.getStartSizeNum(PaginationContext.getPageNum(), PaginationContext.getPageSize()); List<Task> taskList = taskQuery.listPage(firstResultNum, PaginationContext.getPageSize()); // 查询获取列表信息,封装最终返回信息 List<CamundaUndoTask> camundaUndoTaskList = new ArrayList<>(); if (ObjectUtil.isNotEmpty(taskList)) { taskList.forEach(task -> { // 获取参数信息以及业务枚举类型 Map<String, Object> variableMap = runtimeService.getVariables(task.getExecutionId()); CamundaFlowTypeEnum camundaFlowTypeEnum = camundaUtil.getCamundaEnumByTemplateKey(processTemplateKey); // 封装返回类型信息 CamundaUndoTask camundaUndoTask = new CamundaUndoTask(); camundaUndoTask.setTaskId(task.getId()); camundaUndoTask.setOrgCd(StrUtil.toString(variableMap.get(CamundaConst.PROCESS_CREATOR))); camundaUndoTask.setOrgName(StrUtil.toString(variableMap.get(CamundaConst.ORG_NAME_FLAG))); camundaUndoTask.setProcessId(task.getProcessInstanceId()); camundaUndoTask.setBizType(camundaFlowTypeEnum.getBizType()); camundaUndoTask.setBizName(camundaFlowTypeEnum.getBizName()); camundaUndoTask.setProcessTemplateKey(camundaFlowTypeEnum.getProcessTemplateKey()); camundaUndoTask.setBusinessKey(StrUtil.toString(variableMap.get(CamundaConst.BUSINESS_KEY_FLAG))); camundaUndoTask.setActivityId(task.getTaskDefinitionKey()); camundaUndoTask.setCreator(StrUtil.toString(variableMap.get(CamundaConst.PROCESS_CREATOR))); camundaUndoTask.setProcessCreateDate(task.getCreateTime()); camundaUndoTask.setCustomerName(StrUtil.toString(variableMap.get(CamundaConst.CUSTOMER_NAME_FLAG))); camundaUndoTask.setCustomerNum(StrUtil.toString(variableMap.get(CamundaConst.CUSTOMER_NAME_FLAG))); camundaUndoTaskList.add(camundaUndoTask); }); } CamundaFlowPage<CamundaUndoTask> camundaFlowPage = new CamundaFlowPage<>(); camundaFlowPage.setPageSize(PaginationContext.getPageSize()); camundaFlowPage.setPageNum(PaginationContext.getPageNum()); // 返回分页信息 return pageUtil.setCountFlowListPage(camundaUndoTaskList, PaginationContext.getPageNum(), PaginationContext.getPageSize(), totalCount); } /** * 结束任务 * * @param endTaskDTO 参数dto */ @Override @Transactional(rollbackFor = Exception.class) public void endProcess(CamundaEndTaskDTO endTaskDTO) { // 获取任务信息以及流程实例信息 Task task = taskService.createTaskQuery() // 租户id .tenantIdIn(endTaskDTO.getCamundaTenantEnum().getTenantId()) // 任务id .taskId(endTaskDTO.getTaskId()) .singleResult(); if (ObjectUtil.isNull(task)) { throw new ServiceException(StrUtil.format("通过taskId[{}]以及租户id[{}]获取任务信息为空!")); } // 获取流程实例信息 ProcessInstance processInstance = runtimeService.createProcessInstanceQuery() // 流程实例id .processInstanceId(task.getProcessInstanceId()) // 租户信息 .tenantIdIn(endTaskDTO.getCamundaTenantEnum().getTenantId()) .singleResult(); // 空值校验 if (ObjectUtil.isNull(processInstance)) { throw new ServiceException(StrUtil.format("通过taskId[{}]以及租户id[{}]获取流程实例信息为空,请确认!", task.getProcessInstanceId(), endTaskDTO.getCamundaTenantEnum().getTenantId())); } // 流程定义id String processId = processInstance.getProcessInstanceId(); // 获取流程定义信息,获取结束任务对应节点,如果强制结束则直接获取流程中end结束节点进行结束任务 ProcessDefinitionEntity processDefinition = (ProcessDefinitionEntity) repositoryService .getProcessDefinition(processInstance.getProcessDefinitionId()); List<ActivityImpl> activityList = processDefinition.getActivities(); // 强制结束分支,如果一个节点没有 OutgoingTransitions 则为结束节点 ActivityImpl activityEndPoint = activityList.stream().filter(filterAct -> ObjectUtil.isEmpty(filterAct.getOutgoingTransitions()) ).findFirst().orElse(null); // 设置评论信息 if (StrUtil.isNotBlank(endTaskDTO.getOpinion())) { taskService.createComment(task.getId(), task.getProcessInstanceId(), endTaskDTO.getOpinion()); } // 获取当前节点 ActivityImpl currentActivity = processDefinition.findActivity(task.getTaskDefinitionKey()); // 进行任务结束处理,判定当前节点是否为end节点 if (currentActivity.getActivityId().equals(activityEndPoint.getActivityId())) { // 非强制结束,当前节点为end节点,调用complete方法即可 if (ObjectUtil.isNotEmpty(endTaskDTO.getParamsMap())) { taskService.complete(task.getId(), endTaskDTO.getParamsMap()); } else { taskService.complete(task.getId()); } } else { // 非end节点,进行强制结束,不是在结束任务,需要任务流转(跳节点),判断流转节点是否为空 if (ObjectUtil.isNotEmpty(endTaskDTO.getParamsMap())) { // 带参数结束任务 runtimeService.createProcessInstanceModification(processInstance.getProcessInstanceId()) // 取消当前节点所有活动中的Task任务 .cancelAllForActivity(currentActivity.getActivityId()) // 目标节点Id,在流程图中看 .startBeforeActivity(activityEndPoint.getActivityId()) // 参数信息 .setVariables(endTaskDTO.getParamsMap()) // 意见信息 .setAnnotation(endTaskDTO.getOpinion()) .execute(); } else { // 不带参数结束任务 runtimeService.createProcessInstanceModification(processInstance.getProcessInstanceId()) // 取消当前节点所有活动中的Task任务 .cancelAllForActivity(currentActivity.getActivityId()) // 目标节点Id,在流程图中看 .startBeforeActivity(activityEndPoint.getActivityId()) // 意见信息 .setAnnotation(endTaskDTO.getOpinion()) .execute(); } // 未完成任务列表信息设置为删除状态 QueryWrapper<CamundaUnfinishedFlow> unfinishedFlowQueryWrapper = new QueryWrapper<>(); unfinishedFlowQueryWrapper.lambda().eq(CamundaUnfinishedFlow::getProcessId, processId); camundaUnfinishedFlowMapper.delete(unfinishedFlowQueryWrapper); } } /** * 撤销任务 * * @param camundaCancelDTO */ @Override @Transactional(rollbackFor = Exception.class) public void cancelProcess(CamundaCancelDTO camundaCancelDTO) { // 获取流程实例 ProcessInstance processInstance = runtimeService.createProcessInstanceQuery() .tenantIdIn(camundaCancelDTO.getCamundaTenantEnum().getTenantId()) .processInstanceId(camundaCancelDTO.getProcessId()) .singleResult(); if (ObjectUtil.isNull(processInstance)) { throw new ServiceException(StrUtil.format("通过流程实例id[{}]以及租户id[{}]获取流程实例为空,撤销失败!", camundaCancelDTO.getProcessId(), camundaCancelDTO.getCamundaTenantEnum().getTenantId())); } // 进行撤销操作 runtimeService.deleteProcessInstance(camundaCancelDTO.getProcessId(), camundaCancelDTO.getCancelReason()); // 未完成任务列表信息设置为删除状态 QueryWrapper<CamundaUnfinishedFlow> unfinishedFlowQueryWrapper = new QueryWrapper<>(); unfinishedFlowQueryWrapper.lambda().eq(CamundaUnfinishedFlow::getProcessId, camundaCancelDTO.getProcessId()); camundaUnfinishedFlowMapper.delete(unfinishedFlowQueryWrapper); } /** * 提交普通任务 * * @param camundaSubmitTaskDTO 参数dto * @return */ @Override @Transactional(rollbackFor = Exception.class) public CamundaSubmitTaskRspDTO submitNormalTask(CamundaSubmitTaskDTO camundaSubmitTaskDTO) { // 获取task任务信息 Task task = taskService.createTaskQuery() // 租户id .tenantIdIn(camundaSubmitTaskDTO.getCamundaTenantEnum().getTenantId()) // 任务id .taskId(camundaSubmitTaskDTO.getTaskId()).singleResult(); if (ObjectUtil.isNull(task)) { throw new ServiceException("提交普通任务,获取task信息为空!"); } // 获取流程实例信息 ProcessInstance processInstance = runtimeService.createProcessInstanceQuery() // 租户id .tenantIdIn(camundaSubmitTaskDTO.getCamundaTenantEnum().getTenantId()) // 流程实例id .processInstanceId(task.getProcessInstanceId()) .singleResult(); if (ObjectUtil.isNull(processInstance)) { throw new ServiceException("提交普通任务,获取流程实例为空!"); } // 设置评论信息 String approver = camundaSubmitTaskDTO.getNextUserCd().concat(StrUtil.COLON).concat(camundaSubmitTaskDTO.getNextOrgCd()); // 设置认证身份信息 identityService.setAuthentication(approver, Arrays.asList(camundaSubmitTaskDTO.getCamundaTenantEnum().getGroup()), Arrays.asList(camundaSubmitTaskDTO.getCamundaTenantEnum().getTenantId())); // 将处理人填入 runtimeService.setVariable(task.getExecutionId(), "approver", approver); // 设置评论信息 taskService.createComment(camundaSubmitTaskDTO.getTaskId(), processInstance.getProcessInstanceId(), camundaSubmitTaskDTO.getOpinion()); // 正常提交任务信息 if (ObjectUtil.isNotEmpty(camundaSubmitTaskDTO.getVariableMap())) { taskService.complete(camundaSubmitTaskDTO.getTaskId(), camundaSubmitTaskDTO.getVariableMap()); } else { taskService.complete(camundaSubmitTaskDTO.getTaskId()); } // 获取提交之后的task信息 List<Task> taskList = taskService.createTaskQuery() // 租戶信息 .tenantIdIn(camundaSubmitTaskDTO.getCamundaTenantEnum().getTenantId()) // 流程实例id .processInstanceId(processInstance.getProcessInstanceId()) .orderByFollowUpDate() .desc() .list(); CamundaSubmitTaskRspDTO camundaSubmitTaskRspDTO = null; if (ObjectUtil.isNotEmpty(taskList)) { // 设定任务执行人信息 Task currentTask = taskList.get(CamundaConst.INT_0); if (ObjectUtil.isNotNull(currentTask) && StrUtil.isBlank(task.getAssignee())) { // 类似于setAssignee,设定执行人信息 taskService.claim(currentTask.getId(), approver); } // 设置下一处理task任务信息 camundaSubmitTaskRspDTO = new CamundaSubmitTaskRspDTO(); camundaSubmitTaskRspDTO.setNextTaskId(currentTask.getId()); camundaSubmitTaskRspDTO.setNextTaskName(currentTask.getName()); camundaSubmitTaskRspDTO.setTaskDefKey(currentTask.getTaskDefinitionKey()); } return camundaSubmitTaskRspDTO; } /** * 获取下一处理岗位信息 * * @param camundaNextPositionDTO * @return */ @Override public CamundaNextPositionRspDTO getNextPositionList(CamundaNextPositionDTO camundaNextPositionDTO) { // 最终响应参数信息 CamundaNextPositionRspDTO positionRspDTO = new CamundaNextPositionRspDTO(); // 通过taskId获取task实例信息 Task task = taskService.createTaskQuery() // 租户id .tenantIdIn(camundaNextPositionDTO.getCamundaTenantEnum().getTenantId()) // 任务id .taskId(camundaNextPositionDTO.getTaskId()) .singleResult(); // 空值校验 if (ObjectUtil.isNull(task)) { throw new ServiceException(StrUtil.format("通过taskId[{}]以及租户id[{}]获取下一处理岗位获取task实例信息为空!", camundaNextPositionDTO.getTaskId(), camundaNextPositionDTO.getCamundaTenantEnum().getTenantId())); } positionRspDTO.setCurrentPositionDefinitionKey(task.getTaskDefinitionKey()); // 获取流程实信息 ProcessInstance processInstance = runtimeService.createProcessInstanceQuery() // 租户id .tenantIdIn(camundaNextPositionDTO.getCamundaTenantEnum().getTenantId()) // 流程实例id .processInstanceId(task.getProcessInstanceId()) .singleResult(); // 空值校验 if (ObjectUtil.isNull(processInstance)) { throw new ServiceException(StrUtil.format("通过流程实例id[{}]以及租户id[{}]获取流程定义信息获取为空!", task.getProcessInstanceId(), camundaNextPositionDTO.getCamundaTenantEnum().getTenantId())); } // 获取整体流程定义信息 ProcessDefinitionEntity processDefinition = (ProcessDefinitionEntity) repositoryService .getProcessDefinition(processInstance.getProcessDefinitionId()); // 获取当前节点定义信息 ActivityImpl currentActivity = processDefinition.findActivity(task.getTaskDefinitionKey()); // 获取当前节点传入参数信息 Map<String, Object> variablesMap = runtimeService.getVariables(task.getExecutionId()); // 最终获取全部下一处理岗位定义节点 List<PvmActivity> finalActivityList = new ArrayList<>(); // 获取当前节点对外指向,并且对指向进行分析 List<PvmTransition> transitionList = currentActivity.getOutgoingTransitions(); if (ObjectUtil.isNotEmpty(transitionList)) { for (PvmTransition transition : transitionList) { // 获取目标节点 PvmActivity destinationActivity = transition.getDestination(); String activityNodeType = StrUtil.toString(destinationActivity.getProperty(CamundaConst.CAMUNDA_NODE_TYPE)); // 目标节点不同类型进行不同处理, if (CamundaConst.EXCLUSIVE_GATEWAY.equals(activityNodeType) || CamundaConst.INCLUSIVE_GATEWAY.equals(activityNodeType)) { // 注意此处为 节点->排他网关/包含网关->节点 形式,更复杂形式需要针对业务进行调整 List<PvmActivity> exclusiveGateActivityList = getNextPositionByExclusiveGateway(destinationActivity, variablesMap); finalActivityList.addAll(exclusiveGateActivityList); } else if (CamundaConst.PARALLEL_GATEWAY.equals(activityNodeType)) { // 并行网关 节点->并行网关->节点 List<PvmActivity> parallelGateActivityList = getNextPositionByParallelGateway(destinationActivity); finalActivityList.addAll(parallelGateActivityList); } else if (CamundaConst.USER_TASK.equals(activityNodeType)) { // 普通用户任务 节点->节点 finalActivityList.add(destinationActivity); } else { throw new ServiceException(StrUtil.format("当前获取下一岗位信息暂时activityNodeType[{}]暂时不支持!", activityNodeType)); } } // 返回信息进行封装 List<CamundaNextPositionRspDTO.NextPosition> nextPositionList = new ArrayList<>(); if (ObjectUtil.isNotEmpty(finalActivityList)) { nextPositionList = finalActivityList.stream().map(pvmActivity -> { ActivityImpl activity = (ActivityImpl)pvmActivity; CamundaNextPositionRspDTO.NextPosition nextPosition = new CamundaNextPositionRspDTO.NextPosition(); nextPosition.setNextPositionName(activity.getName()); nextPosition.setNextPositionDefinitionKey(activity.getActivityId()); return nextPosition; }).collect(Collectors.toList()); } // 查看是否有跳岗信息 String processDefinitionId = task.getProcessDefinitionId(); ActReProcdef actReProcdef = actReProcdefMapper.selectById(processDefinitionId); if (ObjectUtil.isNull(actReProcdef)) { throw new ServiceException(StrUtil.format("通过流程定义id[{}]获取流程实例定义信息为空!", processDefinitionId)); } // 获取版本,机构,模板key,机构以及task定义id查询跳岗信息 QueryWrapper<CamundaJumpPoint> jumpPointQueryWrapper = new QueryWrapper<>(); jumpPointQueryWrapper.lambda().eq(CamundaJumpPoint::getProcessTemplateKey, actReProcdef.getKey()) .eq(CamundaJumpPoint::getTemplateVersion, actReProcdef.getVersion()) .eq(CamundaJumpPoint::getActivityId, task.getTaskDefinitionKey()) .eq(CamundaJumpPoint::getOwnOrg, camundaNextPositionDTO.getOrgCd()); CamundaJumpPoint camundaJumpPoint = camundaJumpPointMapper.selectOne(jumpPointQueryWrapper); // 如果当前没有获取到配置的机构,则向上获取上级机构配置,直到最*配置机构0001,如果没有配置,则认为当前你岗位不能跳岗,整体跳岗原则为就近原则 if (ObjectUtil.isNotNull(camundaJumpPoint) && StrUtil.isNotBlank(camundaJumpPoint.getJumpActivityIds())) { // 获取跳岗信息字符串,多个岗位使用逗号分隔 List<String> activityIdList = Arrays.asList(camundaJumpPoint.getJumpActivityIds().split(StrUtil.COMMA).clone()); jumpPointQueryWrapper = new QueryWrapper<>(); jumpPointQueryWrapper.lambda().in(CamundaJumpPoint::getProcessTemplateKey, actReProcdef.getKey()) .eq(CamundaJumpPoint::getTemplateVersion, actReProcdef.getVersion()) .in(CamundaJumpPoint::getActivityId, activityIdList) .eq(CamundaJumpPoint::getOwnOrg, camundaNextPositionDTO.getOrgCd()); List<CamundaJumpPoint> camundaJumpPointList = camundaJumpPointMapper.selectList(jumpPointQueryWrapper); if (ObjectUtil.isNotEmpty(camundaJumpPointList)) { // 封装跳岗信息 List<CamundaNextPositionRspDTO.NextPosition> jumpPositionList = camundaJumpPointList.stream().map(jumpPoint -> { CamundaNextPositionRspDTO.NextPosition nextPosition = new CamundaNextPositionRspDTO.NextPosition(); nextPosition.setNextPositionName(jumpPoint.getActivityName()); nextPosition.setNextPositionDefinitionKey(jumpPoint.getActivityId()); return nextPosition; }).collect(Collectors.toList()); // 添加跳岗信息 nextPositionList.addAll(jumpPositionList); } } positionRspDTO.setNextPositionList(nextPositionList); } return positionRspDTO; } /** * 获取任务变量信息 * * @param camundaVariablesDTO 参数DTO * @return */ @Override public Map<String, Object> getTaskVariables(CamundaVariablesDTO camundaVariablesDTO) { // 通过taskId获取task实例信息 Task task = taskService.createTaskQuery() // 租户信息 .tenantIdIn(camundaVariablesDTO.getCamundaTenantEnum().getTenantId()) // 任务id .taskId(camundaVariablesDTO.getTaskId()) .singleResult(); if (ObjectUtil.isNull(task)) { throw new ServiceException(StrUtil.format("通过taskId[{}]以及租户id[{}]获取任务实例失败,请确认taskId传入正确!", camundaVariablesDTO.getTaskId(), camundaVariablesDTO.getCamundaTenantEnum().getTenantId())); } // 获取参数信息 Map<String, Object> variablesMap = taskService.getVariables(camundaVariablesDTO.getTaskId()); if (ObjectUtil.isNotEmpty(variablesMap) && ObjectUtil.isNotEmpty(camundaVariablesDTO.getVariableKeyList())) { // 进行值过滤,过滤非筛选值 Map<String, Object> innerMap = variablesMap.entrySet().stream().filter(entry -> camundaVariablesDTO.getVariableKeyList().contains(entry.getKey()) ).collect(Collectors.toMap( Map.Entry::getKey, Map.Entry::getValue) ); return innerMap; } return variablesMap; } /** * 删除参数key值 * * @param taskId 任务id * @param removeKey 参数key * @return */ @Override @Transactional(rollbackFor = Exception.class) public void removeVariable(String taskId, String removeKey, CamundaTenantEnum tenantEnum) { // 获取task实例信息 Task task = taskService.createTaskQuery() // 租户信息 .tenantIdIn(tenantEnum.getTenantId()) // 任务id .taskId(taskId).singleResult(); if (ObjectUtil.isNull(task)) { throw new ServiceException(StrUtil.format("删除参数通过taskId[{}]以及租户id[{}]查询task实例信息为空!", taskId, tenantEnum.getTenantId())); } taskService.removeVariable(taskId, removeKey); } /** * 新增或者修改参数 * * @param addOrUpdateVariableDTO 参数dto * @return */ @Override @Transactional(rollbackFor = Exception.class) public void addOrUpdateVariable(CamundaAddOrUpdateVariableDTO addOrUpdateVariableDTO) { // 获取taskId以及租户信息 String taskId = addOrUpdateVariableDTO.getTaskId(); String tenantId = addOrUpdateVariableDTO.getCamundaTenantEnum().getTenantId(); // 获取任务实例信息,空值判定 Task task = taskService.createTaskQuery() .tenantIdIn(tenantId) .taskId(taskId) .singleResult(); if (ObjectUtil.isNull(task)) { throw new ServiceException(StrUtil.format("修改参数通过taskId[{}]以及租户id[{}]查询task实例信息为空!", taskId, tenantId)); } // 修改参数 taskService.setVariable(taskId, addOrUpdateVariableDTO.getParamKey(), addOrUpdateVariableDTO.getParamValue()); } /** * 部署流程定义信息到本地库表中 * * @param processDefinitionId 流程实例key * @param orgCd 配置属于哪个机构 */ @Override @Transactional(rollbackFor = Exception.class) public void loadProcessDefinition(String processDefinitionId, String orgCd) { // 流程定义信息 BpmnModelInstance bpmnModelInstance = repositoryService.getBpmnModelInstance(processDefinitionId); if(ObjectUtil.isNull(bpmnModelInstance)){ throw new ServiceException(StrUtil.format("通过processDefinitionId[{}]查询流程定义实例信息为空", processDefinitionId)); } // 获取process定义信息,服务名称 String processDefinitionName = null; String processDefinitionKey = null; Collection<Process> processCollection = bpmnModelInstance.getModelElementsByType(Process.class); if (ObjectUtil.isNotNull(processCollection)) { Optional<Process> optionalProcess = processCollection.stream().findFirst(); ProcessImpl processImpl = (ProcessImpl) optionalProcess.get(); // 获取流程定义名称 eg: camunda流程测试请假 processDefinitionName = processImpl.getName(); // 获取流程定义key eg: getRestDays processDefinitionKey = processImpl.getId(); } // 获取流程定义信息 ActReProcdef actReProcdef = actReProcdefMapper.selectById(processDefinitionId); if (ObjectUtil.isNull(actReProcdef)) { throw new ServiceException(StrUtil.format("通过processDefinitionId[{}]查询流程定义实例信息为空", processDefinitionId)); } // 删除原有信息 QueryWrapper<CamundaJumpPoint> jumpPointQueryWrapper = new QueryWrapper<>(); jumpPointQueryWrapper.lambda().eq(CamundaJumpPoint::getProcessTemplateKey, processDefinitionKey) .eq(CamundaJumpPoint::getOwnOrg, orgCd) .eq(CamundaJumpPoint::getTemplateVersion, actReProcdef.getVersion()); camundaJumpPointMapper.delete(jumpPointQueryWrapper); // 获取所有userTask任务节点信息 Collection<UserTask> userTaskCollection = bpmnModelInstance.getModelElementsByType(UserTask.class); // 整合任务节点信息 List<UserTaskImpl> userTaskImplList = null; if (ObjectUtil.isNotEmpty(userTaskCollection)) { userTaskImplList = userTaskCollection.stream().map(userTask -> { UserTaskImpl userTaskImpl = (UserTaskImpl) userTask; return userTaskImpl; }).collect(Collectors.toList()); } // 开始进行落数 String finalProcessDefinitionKey = processDefinitionKey; String finalProcessDefinitionName = processDefinitionName; userTaskImplList.forEach(userTask -> { // 获取流程task任务定义id以及定义name String activityId = userTask.getId(); String activityName = userTask.getName(); // 封装跳转参数信息 CamundaJumpPoint camundaJumpPoint = new CamundaJumpPoint(); camundaJumpPoint.setId(IdUtil.simpleUUID()); // 所属机构 camundaJumpPoint.setOwnOrg(orgCd); // 流程任务节点定义id camundaJumpPoint.setActivityId(activityId); // 任务节点定义名称 camundaJumpPoint.setActivityName(activityName); // 模板key camundaJumpPoint.setProcessTemplateKey(finalProcessDefinitionKey); // 模板名称 camundaJumpPoint.setProcessTemplateName(finalProcessDefinitionName); // 是否禁止跳岗标识 camundaJumpPoint.setNoJumpFlag(CamundaConst.STR_0); // 版本信息 camundaJumpPoint.setTemplateVersion(actReProcdef.getVersion().toString()); // 插入信息 camundaJumpPointMapper.insert(camundaJumpPoint); }); } /** * 操作跳跃节点信息 * * @param camundaJumpPointSetDTO 参数dto */ @Override @Transactional(rollbackFor = Exception.class) public void optionJumpPoint(CamundaJumpPointSetDTO camundaJumpPointSetDTO) { // 跳跃节点不能包含当前节点信息 if (ObjectUtil.isNotEmpty(camundaJumpPointSetDTO.getJumpPoints()) && camundaJumpPointSetDTO.getJumpPoints().contains(camundaJumpPointSetDTO.getCurrentActivityId())) { throw new ServiceException("跳跃节点不能包含当前节点信息"); } // 通过流程定义id获取流程定义信息 String processDefinitionId = camundaJumpPointSetDTO.getProcessDefinitionId(); ActReProcdef actReProcdef = actReProcdefMapper.selectById(processDefinitionId); if (ObjectUtil.isNull(actReProcdef)) { throw new ServiceException(StrUtil.format("通过processDefinitionId[{}]查询流程定义实例信息为空", processDefinitionId)); } // 获取流程名称以及定义key以及version信息 String processTemplateName = actReProcdef.getName(); String processTemplateKey = actReProcdef.getKey(); String version = actReProcdef.getVersion().toString(); // 查询预设置跳岗信息 QueryWrapper<CamundaJumpPoint> camundaJumpPointQueryWrapper = new QueryWrapper<>(); camundaJumpPointQueryWrapper.lambda().eq(CamundaJumpPoint::getActivityId, camundaJumpPointSetDTO.getCurrentActivityId()) .eq(CamundaJumpPoint::getProcessTemplateKey, processTemplateKey) .eq(CamundaJumpPoint::getProcessTemplateName, processTemplateName) .eq(CamundaJumpPoint::getTemplateVersion, version) .eq(CamundaJumpPoint::getOwnOrg, camundaJumpPointSetDTO.getOrgCd()); CamundaJumpPoint camundaJumpPoint = camundaJumpPointMapper.selectOne(camundaJumpPointQueryWrapper); if (ObjectUtil.isNull(camundaJumpPoint)) { throw new ServiceException(StrUtil.format("获取设置跳岗节点信息为空!")); } // 开始设置节点信息 if (StrUtil.isNotBlank(camundaJumpPointSetDTO.getJumpPoints())) { camundaJumpPoint.setJumpActivityIds(camundaJumpPointSetDTO.getJumpPoints()); camundaJumpPointMapper.updateById(camundaJumpPoint); } else { // 跳转节点为空,则设置不能跳转 camundaJumpPointMapper.deleteJumpPointsById(camundaJumpPoint.getId()); } } /** * 获取全部流程定义列表信息 * * @param camundaDeployDTO 参数dto * @return */ @Override public CamundaFlowPage<ActReProcdef> getReProcessDeployPage(CamundaDeployDTO camundaDeployDTO) { // 进行信息查询 QueryWrapper<ActReProcdef> queryWrapper = new QueryWrapper<>(); queryWrapper.eq(StrUtil.isNotBlank(camundaDeployDTO.getProcessTemplateKey()), "KEY_", camundaDeployDTO.getProcessTemplateKey()) .like(StrUtil.isNotBlank(camundaDeployDTO.getProcessTemplateName()), "NAME_", camundaDeployDTO.getProcessTemplateName()) .eq(StrUtil.isNotBlank(camundaDeployDTO.getVersion()), "VERSION_", camundaDeployDTO.getVersion()); List<ActReProcdef> actReProcdefList = actReProcdefMapper.selectList(queryWrapper); return pageUtil.setFlowListPage(actReProcdefList, PaginationContext.getPageNum(), PaginationContext.getPageSize()); } /** * 获取任务节点信息 * * @param camundaJumpPointPageDTO 参数dto * @return */ @Override public CamundaFlowPage<CamundaJumpPoint> getJumpPointPage(CamundaJumpPointPageDTO camundaJumpPointPageDTO) { // 获取流程定义信息 ActReProcdef actReProcdef = actReProcdefMapper.selectById(camundaJumpPointPageDTO.getProcessDefinitionId()); if (ObjectUtil.isNull(actReProcdef)) { throw new ServiceException(StrUtil.format("通过processDefinitionId[{}]查询流程定义实例信息为空", camundaJumpPointPageDTO.getProcessDefinitionId())); } // 获取流程名称以及定义key以及version信息 String processTemplateName = actReProcdef.getName(); String processTemplateKey = actReProcdef.getKey(); String version = actReProcdef.getVersion().toString(); // 查询预设置跳岗信息 List<String> unExpectActivityIdList = camundaJumpPointPageDTO.getUnExpectActivityIdList(); QueryWrapper<CamundaJumpPoint> camundaJumpPointQueryWrapper = new QueryWrapper<>(); camundaJumpPointQueryWrapper.lambda() .eq(CamundaJumpPoint::getProcessTemplateKey, processTemplateKey) .eq(CamundaJumpPoint::getProcessTemplateName, processTemplateName) .eq(CamundaJumpPoint::getTemplateVersion, version) // 跳跃节点设置权限失效标识 0 生效, 1 失效 .eq(CamundaJumpPoint::getIsDel, CamundaConst.STR_0) .eq(CamundaJumpPoint::getOwnOrg, camundaJumpPointPageDTO.getOrgCd()) // 排除自定义无用节点 .notIn(ObjectUtil.isNotEmpty(unExpectActivityIdList), CamundaJumpPoint::getActivityId, unExpectActivityIdList); List<CamundaJumpPoint> camundaJumpPointList = camundaJumpPointMapper.selectList(camundaJumpPointQueryWrapper); return pageUtil.setFlowListPage(camundaJumpPointList, PaginationContext.getPageNum(), PaginationContext.getPageSize()); } /** * 获取跟踪列表信息 * 以任务角度出发,可能会出现一个businessKey对应多个task任务,因为此人在流程中多次审批,以不同岗位 * * @param camundaTraceHistoryDTO 参数dto * @return */ @Override public CamundaFlowPage<List<CamundaTraceHistory>> getCamundaTracePage(CamundaTraceHistoryDTO camundaTraceHistoryDTO) { // 封装列表参数信息 List<CamundaTraceHistory> camundaTraceHistoryList = new ArrayList<>(); // 封装查询参数信息 userCd:orgCd String handleUser = camundaTraceHistoryDTO.getUserCd() .concat(StrUtil.COLON) .concat(camundaTraceHistoryDTO.getOrgCd()); // 封装查询参数信息 HistoricTaskInstanceQuery historicTaskInstanceQuery = historyService.createHistoricTaskInstanceQuery() .tenantIdIn(camundaTraceHistoryDTO.getCamundaTenantEnum().getTenantId()) .taskInvolvedUser(handleUser) .orderByProcessInstanceId() .desc() .matchVariableNamesIgnoreCase(); // 条件参数确认,任务模板查询 if (StrUtil.isNotBlank(camundaTraceHistoryDTO.getProcessTemplateKey())) { historicTaskInstanceQuery.processVariableValueEquals(CamundaConst.PROCESS_TEMPLATE_KEY, camundaTraceHistoryDTO.getProcessTemplateKey()); } // 客户名称查询 if (StrUtil.isNotBlank(camundaTraceHistoryDTO.getCustomerName())) { historicTaskInstanceQuery.processVariableValueEquals(CamundaConst.CUSTOMER_NAME_FLAG, camundaTraceHistoryDTO.getCustomerName()); } // 发起业务系统 if (StrUtil.isNotBlank(camundaTraceHistoryDTO.getSystem())) { historicTaskInstanceQuery.processVariableValueEquals(CamundaConst.SYSTEM, camundaTraceHistoryDTO.getSystem()); } // 流程在途结束判定 if (CamundaConst.RUNNING.equals(camundaTraceHistoryDTO.getStatus())) { // 在途任务查询 historicTaskInstanceQuery.processUnfinished(); } else if (CamundaConst.FINISHED.equals(camundaTraceHistoryDTO.getStatus())) { // 已经结束任务查询参数封装 historicTaskInstanceQuery.processFinished(); } else { throw new ServiceException("查询跟踪列信息,是否在途参数获取为空!"); } // 获取所有任务列表信息 List<HistoricTaskInstance> historicTaskInstanceList = historicTaskInstanceQuery.list(); // 进行数据封装 int totalCount = 0; if (ObjectUtil.isNotEmpty(historicTaskInstanceList)) { // 查询历史记录参数信息为map信息 Map<String, Map<String, Object>> historyVariablesMap = new HashMap<>(CamundaConst.INT_16); Set<String> processIdList = historicTaskInstanceList.stream(). map(HistoricTaskInstance::getProcessInstanceId) .collect(Collectors.toSet()); // 获取processInstance实例列表信息 int firstResultNum = pageUtil.getStartSizeNum(PaginationContext.getPageNum(), PaginationContext.getPageSize()); HistoricProcessInstanceQuery processInstanceQuery = historyService.createHistoricProcessInstanceQuery() .processInstanceIds(processIdList) .orderByProcessInstanceStartTime() .desc() .matchVariableValuesIgnoreCase(); // 流程实例历史信息进行分页查询 totalCount = (int)processInstanceQuery.count(); List<HistoricProcessInstance> historicProcessInstanceList = processInstanceQuery .listPage(firstResultNum, PaginationContext.getPageSize()); // 组装查询variables 参数信息idArray String[] processIdArray = processIdList.toArray(new String[processIdList.size()]); List<HistoricVariableInstance> variableInstanceList = historyService.createHistoricVariableInstanceQuery() // 租户信息 .tenantIdIn(camundaTraceHistoryDTO.getCamundaTenantEnum().getTenantId()) // 流程实例id列表 .processInstanceIdIn(processIdArray) .list(); // 开始封装参数map key 为processInstanceId,value为当前processInstanceId下个属性map信息 if (ObjectUtil.isNotEmpty(variableInstanceList)) { variableInstanceList.forEach(variableInstance-> { String processInstanceId = variableInstance.getProcessInstanceId(); // 当前那processInstanceId加入过map Map<String, Object> currentMap; if (ObjectUtil.isNotEmpty(historyVariablesMap.get(processInstanceId))) { currentMap = historyVariablesMap.get(processInstanceId); } else { // 首次加入map信息 currentMap = new HashMap<>(CamundaConst.INT_16); } currentMap.put(variableInstance.getName(), variableInstance.getValue()); historyVariablesMap.put(processInstanceId, currentMap); }); } historicProcessInstanceList.forEach(processInstance -> { // 获取参数信息 Map<String, Object> variablesMap = historyVariablesMap.get(processInstance.getId()); CamundaTraceHistory camundaTraceHistory = new CamundaTraceHistory(); camundaTraceHistory.setBizType(StrUtil.toString(variablesMap.get(CamundaConst.PROCESS_BIZ_TYPE))); camundaTraceHistory.setBusinessKey(StrUtil.toString(variablesMap.get(CamundaConst.BUSINESS_KEY_FLAG))); camundaTraceHistory.setCreator(StrUtil.toString(variablesMap.get(CamundaConst.PROCESS_CREATOR))); camundaTraceHistory.setOrgCd(StrUtil.toString(variablesMap.get(CamundaConst.PROCESS_CREATOR))); camundaTraceHistory.setCustomerName(StrUtil.toString(variablesMap.get(CamundaConst.CUSTOMER_NAME_FLAG))); camundaTraceHistory.setCustomerNum(StrUtil.toString(variablesMap.get(CamundaConst.CUSTOMER_NAME_FLAG))); camundaTraceHistory.setProcessId(processInstance.getId()); camundaTraceHistory.setCreateDate(processInstance.getStartTime()); if (CamundaConst.FINISHED.equals(camundaTraceHistoryDTO.getStatus())) { camundaTraceHistory.setStatus(CamundaConst.FINISHED); } else { camundaTraceHistory.setStatus(CamundaConst.RUNNING); } camundaTraceHistoryList.add(camundaTraceHistory); }); } // 返回分页信息 return pageUtil.setCountFlowListPage(camundaTraceHistoryList, PaginationContext.getPageNum(), PaginationContext.getPageSize(), totalCount); } /** * 跟踪列表处理人列表信息 * * @param camundaTraceApproveHistoryDTO 参数dto * @return */ @Override public CamundaFlowPage<CamundaTraceApproveHistory> getCamundaTraceApprovePage(CamundaTraceApproveHistoryDTO camundaTraceApproveHistoryDTO) { // 获取流程实例id String processInstanceId = camundaTraceApproveHistoryDTO.getProcessId(); // 获取历史任务查询类 HistoricTaskInstanceQuery historicTaskInstanceQuery = historyService.createHistoricTaskInstanceQuery() // 租户信息 .tenantIdIn(camundaTraceApproveHistoryDTO.getCamundaTenantEnum().getTenantId()) // 流程实例id .processInstanceId(processInstanceId) .orderByHistoricActivityInstanceStartTime() .desc() .matchVariableNamesIgnoreCase(); // 分页查询 int totalCount = (int) historicTaskInstanceQuery.count(); int firstResultNum = pageUtil.getStartSizeNum(PaginationContext.getPageNum(), PaginationContext.getPageSize()); List<HistoricTaskInstance> historicTaskInstanceList = historicTaskInstanceQuery.listPage(firstResultNum, PaginationContext.getPageSize()); // 最终返回分页信息 List<CamundaTraceApproveHistory> camundaTraceApproveHistoryList = new ArrayList<>(); // 进行数据封装 if (ObjectUtil.isNotEmpty(historicTaskInstanceList)) { // 查询历史记录参数信息为map信息 Map<String, Object> historyVariablesMap = new HashMap<>(CamundaConst.INT_16); // 组装查询variables List<HistoricVariableInstance> variableInstanceList = historyService.createHistoricVariableInstanceQuery() // 租户信息 .tenantIdIn(camundaTraceApproveHistoryDTO.getCamundaTenantEnum().getTenantId()) // 流程实例id .processInstanceIdIn(processInstanceId) .list(); // 开始封装参数map key 为processInstanceId,value为当前 processInstanceId 下个属性map信息 if (ObjectUtil.isNotEmpty(variableInstanceList)) { variableInstanceList.forEach(variableInstance -> { historyVariablesMap.put(variableInstance.getName(), variableInstance.getValue()); }); } historicTaskInstanceList.forEach(historicTaskInstance -> { // 获取参数信息 CamundaTraceApproveHistory camundaTraceApproveHistory = new CamundaTraceApproveHistory(); // 业务编号 camundaTraceApproveHistory.setBusinessKey(StrUtil.toString(historyVariablesMap.get(CamundaConst.BUSINESS_KEY_FLAG))); // 流程实例id camundaTraceApproveHistory.setProcessId(historicTaskInstance.getProcessInstanceId()); // 创建时间 camundaTraceApproveHistory.setCreateDate(historicTaskInstance.getStartTime()); // 结束时间 camundaTraceApproveHistory.setEndDate(historicTaskInstance.getEndTime()); // 操作岗位名称 camundaTraceApproveHistory.setPositionName(historicTaskInstance.getName()); // 机构信息 assign 截取 camundaTraceApproveHistory.setOrgCd(historicTaskInstance.getAssignee()); // 柜员信息 assign 截取 camundaTraceApproveHistory.setUserCd(historicTaskInstance.getAssignee()); // 获取评论信息 String commentMessage = null; String taskId = historicTaskInstance.getId(); List<Comment> commentList = taskService.getTaskComments(taskId); if (ObjectUtil.isNotEmpty(commentList)) { commentMessage = commentList.get(CamundaConst.INT_0).getFullMessage(); } camundaTraceApproveHistory.setOpinion(commentMessage); camundaTraceApproveHistoryList.add(camundaTraceApproveHistory); }); } return pageUtil.setCountFlowListPage(camundaTraceApproveHistoryList, PaginationContext.getPageNum(), PaginationContext.getPageSize(), totalCount); } /** * 获取已经部署流程模板列表信息 * * @param camundaLoadTemplateDTO 参数dto * @return */ @Override public CamundaFlowPage<CamundaLoadTemplate> getLoadTemplatePage(CamundaLoadTemplateDTO camundaLoadTemplateDTO) { // 定义查询类 ProcessDefinitionQuery processDefinitionQuery = repositoryService.createProcessDefinitionQuery(); // 设置爱租户信息 processDefinitionQuery.tenantIdIn(camundaLoadTemplateDTO.getCamundaTenantEnum().getTenantId()); // 流程定义条件查询,分别是定义key,以及流程定义名称还有版本号 if (StrUtil.isNotBlank(camundaLoadTemplateDTO.getTemplateKey())) { processDefinitionQuery.processDefinitionKeyLike(camundaLoadTemplateDTO.getTemplateKey()); } // 版本编号如果为空,则默认设置为最终版本 if (ObjectUtil.isNotNull(camundaLoadTemplateDTO.getVersion())) { processDefinitionQuery.processDefinitionVersion(camundaLoadTemplateDTO.getVersion()); } else { processDefinitionQuery.latestVersion(); } // 开始查询列表信息 List<ProcessDefinition> definitionList = processDefinitionQuery .orderByProcessDefinitionKey() .asc() .list(); // 封装返回分页信息 List<CamundaLoadTemplate> camundaLoadTemplateList = new ArrayList<>(); if (ObjectUtil.isNotEmpty(definitionList)) { camundaLoadTemplateList = definitionList.stream().filter(definition -> { if (StrUtil.isBlank(camundaLoadTemplateDTO.getTemplateName())) { return true; } else if (ObjectUtil.isNull(definition) || StrUtil.isBlank(definition.getName())) { return false; } else { return definition.getName().contains(camundaLoadTemplateDTO.getTemplateName()); } }).map(definition -> { CamundaLoadTemplate camundaLoadTemplate = new CamundaLoadTemplate(); camundaLoadTemplate.setId(definition.getDeploymentId()); camundaLoadTemplate.setTemplateKey(definition.getKey()); camundaLoadTemplate.setTemplateName(definition.getName()); camundaLoadTemplate.setVersion(definition.getVersion()); // 通过deploymentId获取deployment部署时间信息 String deploymentId = definition.getDeploymentId(); Deployment deployment = repositoryService.createDeploymentQuery().deploymentId(deploymentId) .singleResult(); if (ObjectUtil.isNotNull(deployment)) { camundaLoadTemplate.setCreateTime(DateUtil.format(deployment.getDeploymentTime(), DatePattern.NORM_DATETIME_PATTERN)); } return camundaLoadTemplate; }).collect(Collectors.toList()); } return pageUtil.setCountFlowListPage(camundaLoadTemplateList, PaginationContext.getPageNum(), PaginationContext.getPageSize(), definitionList.size()); } /** * 任务驳回到发起岗或者上一岗位 * * @param camundaRejectTaskDTO 驳回参数DTO * @return */ @Override @Transactional(rollbackFor = Exception.class) public Boolean rejectTaskToStartNode(CamundaRejectTaskDTO camundaRejectTaskDTO) { // 获取当前任务信息 Task currentTask = taskService.createTaskQuery() // 租户信息 .tenantIdIn(camundaRejectTaskDTO.getCamundaTenantEnum().getTenantId()) .taskId(camundaRejectTaskDTO.getTaskId()) .singleResult(); if (ObjectUtil.isNull(currentTask)) { throw new ServiceException(StrUtil.format("通过taskId[{}]获取当前任务信息为空!", camundaRejectTaskDTO.getTaskId())); } // 通过task任务信息获取流程实例信息 ProcessInstance processInstance = runtimeService.createProcessInstanceQuery() // 租户信息 .tenantIdIn(camundaRejectTaskDTO.getCamundaTenantEnum().getTenantId()) // 流程实例id .processInstanceId(currentTask.getProcessInstanceId()) .singleResult(); if (ObjectUtil.isNull(processInstance)) { throw new ServiceException(StrUtil.format("通过processId[{}]获取流程实例信息为空!", processInstance.getProcessInstanceId())); } // 获取已经结束的历史节点信息 List<HistoricActivityInstance> activityInstanceList = historyService.createHistoricActivityInstanceQuery() // 租户信息 .tenantIdIn(camundaRejectTaskDTO.getCamundaTenantEnum().getTenantId()) // 流程实例id .processInstanceId(processInstance.getProcessInstanceId()) // 节点类型 .activityType(CamundaConst.USER_TASK) // 已经结束的 .finished() // 按照结束时间进行升序排序 .orderByHistoricActivityInstanceEndTime() .asc() .list(); // 空值校验 if (ObjectUtil.isEmpty(activityInstanceList)) { throw new ServiceException("获取历史userTask任务信息为空!"); } // 首个任务节点 HistoricActivityInstance startInstance = activityInstanceList.get(CamundaConst.INT_0); // 设置退回操作员信息以及退回节点activityId信息 String activityId = null; String assignee = null; // 强制退回到发起节点判定 if (camundaRejectTaskDTO.getIfRejectToStartNode()) { // 如果历史userTask节点没有或者只有一个,则不能进行驳回操作 if (activityInstanceList.size() < CamundaConst.INT_1) { throw new ServiceException("首个用户操作节点无法驳回!"); } // 获取跳转节点信息,目标节点id以及节点操作员信息 activityId = startInstance.getActivityId(); assignee = startInstance.getAssignee(); } else { // 退回到上一节点判定,当前节点为首个节点,无法退回 if (currentTask.getTaskDefinitionKey().equals(startInstance.getActivityId())) { throw new ServiceException("首个用户操作节点无法驳回!"); } // 判断当前任务是否已经退回过 List<HistoricActivityInstance> equalCurrentActivityList = activityInstanceList.stream().filter(instance -> { if (instance.getActivityId().equals(currentTask.getTaskDefinitionKey())) { return true; } return false; }).collect(Collectors.toList()); // 首次退回 if (ObjectUtil.isEmpty(equalCurrentActivityList)) { // 倒数第一个为上一岗位信息 HistoricActivityInstance historicActivityInstance = activityInstanceList.get(activityInstanceList.size() - 1); activityId = historicActivityInstance.getActivityId(); assignee = historicActivityInstance.getAssignee(); } else { // 经过退回操作,eg: 1 2 3 4,4个节点当前节点信息如果在3,则表示该节点是从4退回来的,如果再退回则需要退回到2,再到1 for (int index = 0; index < activityInstanceList.size(); index ++) { // 获取循环对象 HistoricActivityInstance loopActivityInstance = activityInstanceList.get(index); // 如果当前循环activity信息不是第一节点,并且循环节点等于当前任务节点,则上一节点就为应退回节点 if (index > CamundaConst.INT_0 && loopActivityInstance.getActivityId().equals(currentTask.getTaskDefinitionKey())) { HistoricActivityInstance backActivityInstance = activityInstanceList.get(index - CamundaConst.INT_1); activityId = backActivityInstance.getActivityId(); assignee = backActivityInstance.getAssignee(); } } } } // 设置参数以及拒绝任务的原因参数信息 Map<String, Object> variablesMap = new HashMap<>(); variablesMap.put(CamundaConst.APPROVE, assignee); taskService.createComment(currentTask.getId(), processInstance.getProcessInstanceId(), camundaRejectTaskDTO.getRejectReason()); // 获取流程定义信息,获取结束任务对应节点,如果强制结束则直接获取流程中end结束节点进行结束任务 ProcessDefinitionEntity processDefinition = (ProcessDefinitionEntity) repositoryService .getProcessDefinition(processInstance.getProcessDefinitionId()); // 获取当前节点 ActivityImpl currentActivity = processDefinition.findActivity(currentTask.getTaskDefinitionKey()); runtimeService.createProcessInstanceModification(processInstance.getProcessInstanceId()) // 驳回原因 .setAnnotation(camundaRejectTaskDTO.getRejectReason()) // 取消当前活动的所有任务 .cancelAllForActivity(currentActivity.getActivityId()) // 目标节点Id,在流程图中看 .startBeforeActivity(activityId) // 参数信息 .setVariables(variablesMap) .execute(); return true; } /** * 跳转到目标节点 * * @param camundaGotoDTO * @return */ @Override @Transactional(rollbackFor = Exception.class) public Boolean gotoDestinationTask(CamundaGotoDTO camundaGotoDTO) { // 获取当前节点task任务信息 Task currentTask = taskService.createTaskQuery() // 租户信息 .tenantIdIn(camundaGotoDTO.getCamundaTenantEnum().getTenantId()) // 任务节点信息 .taskId(camundaGotoDTO.getCurrentTaskId()).singleResult(); if (ObjectUtil.isNull(currentTask)) { throw new ServiceException(StrUtil.format("通过taskId[{}]获取task信息为空!", camundaGotoDTO.getCurrentTaskId())); } // 校验节点是否可以跳跃,获取流程定义id,当前节点activityId以及机构信息 String processDefinitionId = currentTask.getProcessDefinitionId(); String currentActivityId = currentTask.getTaskDefinitionKey(); String ownOrgCd = camundaGotoDTO.getOrgCd(); // 查询当前节点是否配置可跳跃节点信息 ActReProcdef actReProcdef = actReProcdefMapper.selectById(processDefinitionId); if (ObjectUtil.isNull(actReProcdef)) { throw new ServiceException(StrUtil.format("通过流程定义id[{}],获取流程定义信息为空!", processDefinitionId)); } // 获取当前节点配置信息 QueryWrapper<CamundaJumpPoint> jumpPointQueryWrapper = new QueryWrapper<>(); jumpPointQueryWrapper.lambda().eq(CamundaJumpPoint::getActivityId, currentActivityId) .eq(CamundaJumpPoint::getTemplateVersion, actReProcdef.getVersion()) .eq(CamundaJumpPoint::getOwnOrg, ownOrgCd) .eq(CamundaJumpPoint::getProcessTemplateKey, actReProcdef.getKey()); CamundaJumpPoint camundaJumpPoint = camundaJumpPointMapper.selectOne(jumpPointQueryWrapper); if (ObjectUtil.isNull(camundaJumpPoint)) { throw new ServiceException(StrUtil.format("当前模板[{}]对应机构[{}]对应岗位未配置跳岗信息,请确认!", actReProcdef.getKey(), ownOrgCd)); } // 岗位配置正确性校验,可跳跃节点不好含当前跳跃节点,则直接返回异常信息 if (StrUtil.isNotBlank(camundaJumpPoint.getJumpActivityIds()) && !camundaJumpPoint.getJumpActivityIds().contains(camundaGotoDTO.getDestActivityId())) { throw new ServiceException("当前岗位不能跳转到选定岗位,请配置后再试!"); } // 设置意见信息 taskService.createComment(currentTask.getId(), currentTask.getProcessInstanceId(), camundaGotoDTO.getOpinion()); // 进行跳岗信息 ProcessInstanceModificationInstantiationBuilder instantiationBuilder = runtimeService .createProcessInstanceModification(currentTask.getProcessInstanceId()) // 取消当前活动的所有任务 .cancelAllForActivity(currentActivityId) // 跳转原因 .setAnnotation(camundaGotoDTO.getOpinion()) // 目标节点Id,在流程图中看 .startBeforeActivity(camundaGotoDTO.getDestActivityId()); // 参数信息 if (ObjectUtil.isNotEmpty(camundaGotoDTO.getVariablesMap())) { instantiationBuilder.setVariables(camundaGotoDTO.getVariablesMap()); } // 执行节点跳跃 instantiationBuilder.execute(); return true; } /** * 获取当前任务完成节点,连线,未完成节点信息 * todo: 后续可以加入自定义的完成节点,退回操作记录表,更准确展示当前节点任务高亮信息 * * @param camundaTaskImageDTO 参数dto * @return */ @Override public CamundaTaskImageNodeRspDTO getCamundaTaskImage(CamundaTaskImageDTO camundaTaskImageDTO) { // 最终返回参数信息 CamundaTaskImageNodeRspDTO camundaTaskImageNodeRspDTO = new CamundaTaskImageNodeRspDTO(); // 根据taskId获取任务信息 String taskId = camundaTaskImageDTO.getTaskId(); Task currentTask = taskService.createTaskQuery() .tenantIdIn(camundaTaskImageDTO.getCamundaTenantEnum().getTenantId()) .taskId(taskId) .singleResult(); if (ObjectUtil.isNull(currentTask)) { throw new ServiceException(StrUtil.format("通过taskId[{}]以及租户id[{}]获取task信息为空!", taskId, camundaTaskImageDTO.getCamundaTenantEnum().getTenantId())); } // 获取processInstance信息 ProcessInstance processInstance = runtimeService.createProcessInstanceQuery() // 租户id .tenantIdIn(camundaTaskImageDTO.getCamundaTenantEnum().getTenantId()) // 流程实例id .processInstanceId(currentTask.getProcessInstanceId()) .singleResult(); if (ObjectUtil.isNull(processInstance)) { throw new ServiceException(StrUtil.format("通过processId[{}]获取流程实例信息为空!", currentTask.getProcessInstanceId())); } // 流程实例id String processInstanceId = processInstance.getProcessInstanceId(); // 获取已经完成的任务节点 List<HistoricActivityInstance> finishedActivityInstanceList = historyService.createHistoricActivityInstanceQuery() .tenantIdIn(camundaTaskImageDTO.getCamundaTenantEnum().getTenantId()) .processInstanceId(processInstanceId) .finished() .orderByHistoricActivityInstanceStartTime() .asc() .list(); if (ObjectUtil.isNotEmpty(finishedActivityInstanceList)) { List<String> finishedActivityIdList = finishedActivityInstanceList .stream() .map(HistoricActivityInstance::getActivityId) .collect(Collectors.toList()); camundaTaskImageNodeRspDTO.setFinishedActivityIdList(finishedActivityIdList); } // 未完成节点信息 List<HistoricActivityInstance> unfinishedActivityInstanceList = historyService.createHistoricActivityInstanceQuery() .tenantIdIn(camundaTaskImageDTO.getCamundaTenantEnum().getTenantId()) .processInstanceId(processInstanceId) .unfinished() .list(); if (ObjectUtil.isNotEmpty(unfinishedActivityInstanceList)) { List<String> unfinishedActivityIdList = unfinishedActivityInstanceList .stream() .map(HistoricActivityInstance::getActivityId) .collect(Collectors.toList()); camundaTaskImageNodeRspDTO.setUnfinishedActivityIdList(unfinishedActivityIdList); } // 自己办理任务获取 String optionUser = camundaTaskImageDTO.getUserCd().concat(StrUtil.COLON).concat(camundaTaskImageDTO.getOrgCd()); List<HistoricTaskInstance> selfOptionTaskInstanceList = historyService.createHistoricTaskInstanceQuery() .tenantIdIn(camundaTaskImageDTO.getCamundaTenantEnum().getTenantId()) .taskAssignee(optionUser) .finished() .processInstanceId(processInstanceId) .list(); if (ObjectUtil.isNotEmpty(selfOptionTaskInstanceList)) { List<String> selfOptionIdList = selfOptionTaskInstanceList .stream() .map(HistoricTaskInstance::getTaskDefinitionKey) .collect(Collectors.toList()); camundaTaskImageNodeRspDTO.setSelfOptionActivityIdList(selfOptionIdList); } // 获取流程中的高亮线,获取流程定义的bpmn模型 List<String> highLineList = new ArrayList<>(); BpmnModelInstance bpmnModelInstance = repositoryService.getBpmnModelInstance(processInstance.getProcessDefinitionId()); for (HistoricActivityInstance finishedActivity : finishedActivityInstanceList) { // 获取 bpmn 元素 ModelElementInstance modelElementInstance = bpmnModelInstance.getModelElementById(finishedActivity.getActivityId()); // 将节点转换为 flowNode 流程节点,获取输入输出线 FlowNode flowNode = (FlowNode)modelElementInstance; // 获取outgoing线信息 Collection<SequenceFlow> outgoingCollection = flowNode.getOutgoing(); if (ObjectUtil.isEmpty(outgoingCollection)) { continue; } // 循环outgoing信息 outgoingCollection.forEach(outgoing -> { // 线段目标节点信息 String targetId = outgoing.getTarget().getId(); // 完成任务,多次循环,所有完成任务对应outgoing线全部高亮 for (HistoricActivityInstance innerFinished : finishedActivityInstanceList) { String optionActivityId = innerFinished.getActivityId(); // 循环任务为target目标节点,并且 则高亮 if(targetId.equals(optionActivityId)){ if(finishedActivity.getEndTime().equals(innerFinished.getStartTime())){ highLineList.add(outgoing.getId()); } } } // 待完成任务高亮节点 for (HistoricActivityInstance unfinishedActivityInstance : unfinishedActivityInstanceList) { String optionActivityId = unfinishedActivityInstance.getActivityId(); if(targetId.equals(optionActivityId)){ if(finishedActivity.getEndTime().equals(unfinishedActivityInstance.getStartTime())){ highLineList.add(outgoing.getId()); } } } }); camundaTaskImageNodeRspDTO.setHighLineList(highLineList); } return camundaTaskImageNodeRspDTO; } /** * 通过版本号,流程定义processDefinitionKey获取流程定义xml信息 * * @param processDefinitionKey * @param version 版本编号 * @param tenantEnum 租户枚举信息 */ @Override public String getDefinitionXMLByKeyAndVersion(String processDefinitionKey, Integer version, CamundaTenantEnum tenantEnum) throws IOException { // 获取流程定义信息 List<ProcessDefinition> processDefinitionList = repositoryService.createProcessDefinitionQuery() // 租户id .tenantIdIn(tenantEnum.getTenantId()) .processDefinitionKey(processDefinitionKey) .list(); // 空值判定 if (ObjectUtil.isEmpty(processDefinitionList)) { throw new ServiceException(StrUtil.format("通过processDefinitionKey[{}]获取流程定义信息为空!", processDefinitionKey)); } // 获取对应版本的信息 ProcessDefinition processDefinition = processDefinitionList.stream().filter(definition -> version.equals(definition.getVersion()) ).findFirst().orElse(null); // 空值判定 if (ObjectUtil.isNull(processDefinition)) { throw new ServiceException(StrUtil.format("通过processDefinitionKey[{}]获取版本号[{}]的流程定义信息为空,未找到对应版本定义信息!", processDefinitionKey, version)); } // 获取文件输入流信息 InputStream xmlStream = repositoryService.getProcessModel(processDefinition.getId()); // 通过 inputStream 获取xml字符串信息 String xmlStr = IOUtils.toString(xmlStream, StandardCharsets.UTF_8); return xmlStr; } /** * 获取流程图 * * @param processId 流程实例id */ @Override public void getDefinitionXMLByProcessId(String processId, CamundaTenantEnum camundaTenantEnum) throws IOException { // 通过runtimeService获取processDefinitionId String processDefinitionId = runtimeService.createProcessInstanceQuery() // 租户信息 .tenantIdIn(camundaTenantEnum.getTenantId()) .processInstanceId(processId) .singleResult() .getProcessDefinitionId(); ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery() // 租户信息 .tenantIdIn(camundaTenantEnum.getTenantId()) .processDefinitionId(processDefinitionId) .singleResult(); InputStream xmlStream = repositoryService.getProcessModel(processDefinition.getId()); // 设置响应头信息,比如Content-Type和Content-Disposition response.setContentType("application/xml"); // 根据实际文件类型设置MIME类型,这里是XML文件 response.setHeader("Content-Disposition", "attachment;filename=\"" + processDefinition.getKey() + "\""); try (OutputStream out = response.getOutputStream()) { byte[] buffer = new byte[1024]; // 缓冲区大小,可以根据实际情况调整 int bytesRead; // 从xmlStream读取数据并写入到responseOutputStream while ((bytesRead = xmlStream.read(buffer)) != -1) { out.write(buffer, 0, bytesRead); } } catch (IOException e) { // 处理IO异常 String errorMessage = LogUtil.getStackTraceInfo(e); throw new ServiceException(StrUtil.format("下载文件异常,异常信息为[{}]", errorMessage)); } finally { response.flushBuffer(); } } /** * 获取流程图XML字符串 * * @param processId 流程实例id * @param camundaTenantEnum 租户枚举信息 */ @Override public String getDefinitionXMLStrByProcessId(String processId, CamundaTenantEnum camundaTenantEnum) throws IOException { // 通过runtimeService获取processDefinitionId String processDefinitionId = runtimeService.createProcessInstanceQuery() // 租户信息 .tenantIdIn(camundaTenantEnum.getTenantId()) .processInstanceId(processId) .singleResult() .getProcessDefinitionId(); // 空值判定 if (StrUtil.isBlank(processDefinitionId)) { throw new ServiceException("通过processId获取流程定义processDefinitionId为空!"); } ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery() .tenantIdIn(camundaTenantEnum.getTenantId()) .processDefinitionId(processDefinitionId) .singleResult(); // 空值判定 if (ObjectUtil.isNull(processDefinition)) { throw new ServiceException(StrUtil.format("通过processDefinitionId[{}]获取流程定义信息为空!", processDefinitionId)); } InputStream xmlStream = repositoryService.getProcessModel(processDefinition.getId()); // 通过 inputStream 获取xml字符串信息 String xmlStr = IOUtils.toString(xmlStream, StandardCharsets.UTF_8); return xmlStr; } /** * 部署流程 * * @param file 文件 * @param tenantEnum 租户枚举 */ @Override @Transactional(rollbackFor = Exception.class) public String deployProcess(MultipartFile file, CamundaTenantEnum tenantEnum) throws IOException { // 文件校验 if (file.isEmpty()) { throw new ServiceException("部署新流程,流程文件为空!"); } // 开始部署流程 Deployment deployment = repositoryService.createDeployment() .addInputStream(file.getOriginalFilename(), file.getInputStream()) .tenantId(tenantEnum.getTenantId()) .name(file.getOriginalFilename()) .deploy(); // 通过deploymentId获取流程定义集合信息(首次部署,只有一个流程定义信息) String deploymentId = deployment.getId(); List<ProcessDefinition> definitionList = repositoryService.createProcessDefinitionQuery() // 租户id .tenantIdIn(tenantEnum.getTenantId()) .deploymentId(deploymentId) .list(); // 通过流程定义信息获取流程定义key if (ObjectUtil.isNotEmpty(definitionList)) { // 首次部署,取第一个定义信息即可 ProcessDefinition processDefinition = definitionList.get(0); return processDefinition.getKey(); } else { throw new ServiceException(StrUtil.format("流程已经部署,通过部署deploymentId[{}]获取流程定义信息为空!", deploymentId)); } } /** * 获取排他网关正确的下一节点信息 * @param currentActivity 当前节点信息 * @param currentVariablesMap 当前节点处参数信息 * @return */ public List<PvmActivity> getNextPositionByExclusiveGateway(PvmActivity currentActivity, Map<String, Object> currentVariablesMap) { // 返回结果信息 List<PvmActivity> activityList = new ArrayList<>(); // 获取当前节点对外连接信息,并且计算最终选择哪条路线 List<PvmTransition> transitionList = currentActivity.getOutgoingTransitions(); for (PvmTransition transition : transitionList) { // 获取当前任务判定条件,注意此处不是节点,为对外条件flowSequence Object condition = transition.getProperty(CamundaConst.CONDITION_TEXT); // 节点条件判定是否满足 if (ObjectUtil.isNotNull(condition) && camundaUtil.camundaEvalExpress(condition, currentVariablesMap)) { // 此处为对外指向flowSequence指向满足条件的节点 activityList.add(transition.getDestination()); } } return activityList; } /** * 获取并行网关正确的下一节点信息 * @param currentActivity 当前节点信息 * @return */ public List<PvmActivity> getNextPositionByParallelGateway(PvmActivity currentActivity) { // 返回结果信息 List<PvmActivity> activityList = new ArrayList<>(); // 获取当前并行网关节点对外连接信息 transitionList 为并行网关对外的 -> 连线 List<PvmTransition> transitionList = currentActivity.getOutgoingTransitions(); for (PvmTransition transition : transitionList) { // 获取当前任务判定条件,注意此处不是节点,为对外条件 flowSequence,获取destination则为 -> 对应后面的节点 PvmActivity destinationActivity = transition.getDestination(); String activityNodeType = StrUtil.toString(destinationActivity.getProperty(CamundaConst.CAMUNDA_NODE_TYPE)); // 如果目标节点为userTask节点,则直接加入执行节点 if (CamundaConst.USER_TASK.equals(activityNodeType)) { activityList.add(transition.getDestination()); } } return activityList; } }