package com.ycl.service.common; import com.alibaba.fastjson2.JSONObject; import com.ycl.common.constant.ProcessConstants; import com.ycl.domain.entity.SysForm; import com.ycl.domain.vo.FormDetailVO; import com.ycl.flow.FindNextNodeUtil; import com.ycl.service.ISysFormService; import lombok.RequiredArgsConstructor; import org.flowable.bpmn.model.*; import org.flowable.bpmn.model.Process; import org.flowable.engine.RepositoryService; import org.flowable.engine.RuntimeService; import org.flowable.engine.repository.ProcessDefinition; import org.springframework.stereotype.Service; import org.springframework.util.CollectionUtils; import org.springframework.util.StringUtils; import java.util.*; import java.util.stream.Collectors; /** * @author:xp * @date:2024/12/4 23:22 */ @Service @RequiredArgsConstructor public class TaskCommonService { private final RuntimeService runtimeService; private final RepositoryService repositoryService; /** * 通过当前节点定义key,获取其上一个节点以及当前节点的信息,如果前面是并行的会返回多个 * * @param processDefId 流程定义id * @param currentNodeDefId 当前节点定义id * @param sysFormService 表单服务层 * @param needInitCurrentForm 是否需要初始化当前节点的表单数据,一般查询已完成的任务详情需要 * @return */ public List getBeforeNodeDefInfo(String processDefId, String currentNodeDefId, ISysFormService sysFormService, Boolean needInitCurrentForm) { // 获取流程定义 ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery() .processDefinitionId(processDefId) .singleResult(); // 获取流程模型 BpmnModel bpmnModel = repositoryService.getBpmnModel(processDefId); if (bpmnModel == null) { throw new RuntimeException("BpmnModel not found for processDefinitionId: " + processDefId); } // 获取流程对象 Process process = bpmnModel.getProcessById(processDefinition.getKey()); if (process == null) { throw new RuntimeException("Process not found for processDefinitionId: " + processDefId); } // 遍历流程元素,找到对应的任务节点 Collection flowElements = process.getFlowElements(); UserTask currentElement = null; for (FlowElement flowElement : flowElements) { if (flowElement instanceof UserTask && flowElement.getId().equals(currentNodeDefId)) { currentElement = (UserTask) flowElement; break; } } if (Objects.isNull(currentElement)) { throw new RuntimeException("未找到该任务的流程定义节点"); } // 获取当前节点的输入 List defKeys = new ArrayList<>(2); if (StringUtils.hasText(currentElement.getFormKey())) { FormDetailVO formDetailVO = new FormDetailVO(); formDetailVO.setBeforeNodeDefId(currentElement.getId()); formDetailVO.setBeforeNodeName(currentElement.getName()); formDetailVO.setCurrent(Boolean.TRUE); if (needInitCurrentForm) { SysForm sysForm = sysFormService.selectSysFormById(Long.parseLong(currentElement.getFormKey())); if (Objects.isNull(sysForm)) { throw new RuntimeException("该流程绑定的表单不存在或已被删除"); } Map data = new HashMap<>(1); data.put(ProcessConstants.TASK_FORM_KEY, JSONObject.parseObject(sysForm.getFormContent())); formDetailVO.setFormJsonObj(data); } defKeys.add(formDetailVO); } this.beforeNodeInfo(currentElement, defKeys); return defKeys; } /** * 递归获取当前节点的前一个任务节点信息 * * @param currentElement * @param defKeys */ private void beforeNodeInfo(FlowElement currentElement, List defKeys) { if (currentElement instanceof UserTask) { UserTask userTask = (UserTask) currentElement; if (! CollectionUtils.isEmpty(userTask.getIncomingFlows())) { for (SequenceFlow incomingFlow : userTask.getIncomingFlows()) { if (incomingFlow.getSourceFlowElement() instanceof UserTask) { FormDetailVO formDetailVO = new FormDetailVO(); formDetailVO.setBeforeNodeDefId(incomingFlow.getSourceFlowElement().getId()); formDetailVO.setBeforeNodeName(incomingFlow.getSourceFlowElement().getName()); formDetailVO.setBeforeNodeName(((UserTask) incomingFlow.getSourceFlowElement()).getOwner()); defKeys.add(formDetailVO); } else { beforeNodeInfo(incomingFlow.getSourceFlowElement(), defKeys); } } } } else if (currentElement instanceof Gateway ){ Gateway gateway = (Gateway) currentElement; if (! CollectionUtils.isEmpty(gateway.getIncomingFlows())) { for (SequenceFlow incomingFlow : gateway.getIncomingFlows()) { if (incomingFlow.getSourceFlowElement() instanceof UserTask) { FormDetailVO formDetailVO = new FormDetailVO(); formDetailVO.setBeforeNodeDefId(incomingFlow.getSourceFlowElement().getId()); formDetailVO.setBeforeNodeName(incomingFlow.getSourceFlowElement().getName()); defKeys.add(formDetailVO); } else { beforeNodeInfo(incomingFlow.getSourceFlowElement(), defKeys); } } } } } /** * 获取当前节点的上一节点id,不反悔当前节点信息,如果前面是并行,那么会返回多个 * * @param processDefId 流程定义id * @param currentNodeDefId 当前节点定义id * @return */ public List getBeforeNodeInfo(String processDefId, String currentNodeDefId) { // 获取流程定义 ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery() .processDefinitionId(processDefId) .singleResult(); // 获取流程模型 BpmnModel bpmnModel = repositoryService.getBpmnModel(processDefId); if (bpmnModel == null) { throw new RuntimeException("BpmnModel not found for processDefinitionId: " + processDefId); } // 获取流程对象 Process process = bpmnModel.getProcessById(processDefinition.getKey()); if (process == null) { throw new RuntimeException("Process not found for processDefinitionId: " + processDefId); } // 遍历流程元素,找到对应的任务节点 Collection flowElements = process.getFlowElements(); UserTask currentElement = null; for (FlowElement flowElement : flowElements) { if (flowElement instanceof UserTask && flowElement.getId().equals(currentNodeDefId)) { currentElement = (UserTask) flowElement; break; } } if (Objects.isNull(currentElement)) { throw new RuntimeException("未找到该任务的流程定义节点"); } // 获取当前节点的输入 List defKeys = new ArrayList<>(2); this.beforeNodeInfo(currentElement, defKeys); return defKeys.stream().map(FormDetailVO::getBeforeNodeDefId).collect(Collectors.toList()); } /** * 检查任务节点是否配置了:需要审核 的扩展属性 * * @param extensionElements 扩展列表 * @return */ public Boolean checkTaskNeedAuditing(List extensionElements) { if (CollectionUtils.isEmpty(extensionElements)) { return Boolean.FALSE; } for (ExtensionElement extensionElement : extensionElements) { if (CollectionUtils.isEmpty(extensionElement.getAttributes())) { // 如果本身没有属性,则递归child return checkTaskNeedAuditing(extensionElement.getChildElements().get("property")); } else { // 否则先查本身的属性有不有:需要审核 的属性,没有也是递归child if (extensionElement.getAttributes().get("name").stream().anyMatch(attribute -> ProcessConstants.EXTENSION_PROPERTY_NEED_AUDITING_TEXT.equals(attribute.getValue())) && extensionElement.getAttributes().get("value").stream().anyMatch(attribute -> ProcessConstants.EXTENSION_PROPERTY_NEED_AUDITING_VALUE.equals(attribute.getValue())) ) { return Boolean.TRUE; } else { return checkTaskNeedAuditing(extensionElement.getChildElements().get("property")); } } } return Boolean.FALSE; } }