仿钉钉流程设计-抄送节点实现
This commit is contained in:
parent
d88718071d
commit
d9758636b1
@ -20,8 +20,10 @@ public enum BpmSimpleModelNodeType implements IntArrayValuable {
|
||||
// TODO @jaosn:-1、0、1、4、-2 是前端已经定义好的么?感觉未来可以考虑搞成和 BPMN 尽量一致的单词哈;类似 usertask 用户审批;
|
||||
START_EVENT_NODE(0, "开始节点"),
|
||||
APPROVE_USER_NODE (1, "审批人节点"),
|
||||
// 抄送人节点、对应 BPMN 的 ScriptTask. 使用ScriptTask 原因。好像 ServiceTask 自定义属性不能写入 XML
|
||||
SCRIPT_TASK_NODE(2, "抄送人节点"),
|
||||
EXCLUSIVE_GATEWAY_NODE(4, "排他网关"),
|
||||
END_NODE(-2, "结束节点");
|
||||
END_EVENT_NODE(-2, "结束节点");
|
||||
|
||||
public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(BpmSimpleModelNodeType::getType).toArray();
|
||||
|
||||
|
@ -13,6 +13,7 @@ import org.flowable.bpmn.BpmnAutoLayout;
|
||||
import org.flowable.bpmn.converter.BpmnXMLConverter;
|
||||
import org.flowable.bpmn.model.Process;
|
||||
import org.flowable.bpmn.model.*;
|
||||
import org.flowable.common.engine.impl.scripting.ScriptingEngines;
|
||||
import org.flowable.common.engine.impl.util.io.BytesStreamSource;
|
||||
|
||||
import java.util.ArrayList;
|
||||
@ -20,11 +21,15 @@ import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import static org.flowable.bpmn.constants.BpmnXMLConstants.*;
|
||||
|
||||
/**
|
||||
* 流程模型转操作工具类
|
||||
*/
|
||||
public class BpmnModelUtils {
|
||||
|
||||
public static final String BPMN_SIMPLE_COPY_EXECUTION_SCRIPT = "#{bpmSimpleNodeService.copy(execution)}";
|
||||
|
||||
public static Integer parseCandidateStrategy(FlowElement userTask) {
|
||||
return NumberUtils.parseInt(userTask.getAttributeValue(
|
||||
BpmnModelConstants.NAMESPACE, BpmnModelConstants.USER_TASK_CANDIDATE_STRATEGY));
|
||||
@ -379,26 +384,27 @@ public class BpmnModelUtils {
|
||||
Assert.notNull(nodeType, "模型节点类型不支持");
|
||||
switch (nodeType) {
|
||||
case START_EVENT_NODE:
|
||||
case APPROVE_USER_NODE: {
|
||||
case APPROVE_USER_NODE:
|
||||
case SCRIPT_TASK_NODE: {
|
||||
addBpmnSequenceFlowElement(mainProcess, node.getId(), childNode.getId(), null, null);
|
||||
// 递归调用后续节点
|
||||
addBpmnSequenceFlow(mainProcess, childNode,endId);
|
||||
addBpmnSequenceFlow(mainProcess, childNode, endId);
|
||||
break;
|
||||
}
|
||||
case EXCLUSIVE_GATEWAY_NODE: {
|
||||
String gateWayEndId = ( childNode == null || childNode.getId() == null ) ? BpmnModelConstants.END_EVENT_ID : childNode.getId();
|
||||
String gateWayEndId = (childNode == null || childNode.getId() == null) ? BpmnModelConstants.END_EVENT_ID : childNode.getId();
|
||||
List<BpmSimpleModelNodeVO> conditionNodes = node.getConditionNodes();
|
||||
Assert.notEmpty(conditionNodes, "网关节点的条件节点不能为空");
|
||||
for (int i = 0; i < conditionNodes.size(); i++) {
|
||||
BpmSimpleModelNodeVO item = conditionNodes.get(i);
|
||||
BpmSimpleModelNodeVO nextNodeOnCondition = getNextNodeOnCondition(item);
|
||||
BpmSimpleModelNodeVO nextNodeOnCondition = item.getChildNode();
|
||||
if (nextNodeOnCondition != null && nextNodeOnCondition.getId() != null) {
|
||||
addBpmnSequenceFlowElement(mainProcess, node.getId(), nextNodeOnCondition.getId(),
|
||||
String.format("%s_SequenceFlow_%d", node.getId(), i+1), null);
|
||||
String.format("%s_SequenceFlow_%d", node.getId(), i + 1), null);
|
||||
addBpmnSequenceFlow(mainProcess, nextNodeOnCondition, gateWayEndId);
|
||||
} else {
|
||||
addBpmnSequenceFlowElement(mainProcess, node.getId(), gateWayEndId,
|
||||
String.format("%s_SequenceFlow_%d", node.getId(), i+1), null);
|
||||
String.format("%s_SequenceFlow_%d", node.getId(), i + 1), null);
|
||||
}
|
||||
}
|
||||
// 递归调用后续节点
|
||||
@ -412,10 +418,6 @@ public class BpmnModelUtils {
|
||||
|
||||
}
|
||||
|
||||
private static BpmSimpleModelNodeVO getNextNodeOnCondition(BpmSimpleModelNodeVO conditionNode) {
|
||||
return conditionNode.getChildNode();
|
||||
}
|
||||
|
||||
private static void addBpmnSequenceFlowElement(Process mainProcess, String sourceId, String targetId, String seqFlowId, String conditionExpression) {
|
||||
SequenceFlow sequenceFlow = new SequenceFlow(sourceId, targetId);
|
||||
if (StrUtil.isNotEmpty(conditionExpression)) {
|
||||
@ -439,7 +441,10 @@ public class BpmnModelUtils {
|
||||
addBpmnStartEventNode(mainProcess, simpleModelNode);
|
||||
break;
|
||||
case APPROVE_USER_NODE:
|
||||
addBpmnUserTaskEventNode(mainProcess, simpleModelNode);
|
||||
addBpmnUserTaskNode(mainProcess, simpleModelNode);
|
||||
break;
|
||||
case SCRIPT_TASK_NODE:
|
||||
addBpmnScriptTaSskNode(mainProcess, simpleModelNode);
|
||||
break;
|
||||
case EXCLUSIVE_GATEWAY_NODE:
|
||||
addBpmnExclusiveGatewayNode(mainProcess, simpleModelNode);
|
||||
@ -467,6 +472,25 @@ public class BpmnModelUtils {
|
||||
}
|
||||
}
|
||||
|
||||
private static void addBpmnScriptTaSskNode(Process mainProcess, BpmSimpleModelNodeVO node) {
|
||||
ScriptTask scriptTask = new ScriptTask();
|
||||
scriptTask.setId(node.getId());
|
||||
scriptTask.setName(node.getName());
|
||||
scriptTask.setScriptFormat(ScriptingEngines.DEFAULT_SCRIPTING_LANGUAGE);
|
||||
scriptTask.setScript(BPMN_SIMPLE_COPY_EXECUTION_SCRIPT);
|
||||
// 添加自定义属性
|
||||
addExtensionAttributes(node, scriptTask);
|
||||
mainProcess.addFlowElement(scriptTask);
|
||||
}
|
||||
|
||||
private static void addExtensionAttributes(BpmSimpleModelNodeVO node, FlowElement flowElement) {
|
||||
Integer candidateStrategy = MapUtil.getInt(node.getAttributes(), BpmnModelConstants.USER_TASK_CANDIDATE_STRATEGY);
|
||||
addExtensionAttributes(flowElement, BpmnModelConstants.NAMESPACE, BpmnModelConstants.USER_TASK_CANDIDATE_STRATEGY,
|
||||
candidateStrategy == null ? null : String.valueOf(candidateStrategy));
|
||||
addExtensionAttributes(flowElement, BpmnModelConstants.NAMESPACE, BpmnModelConstants.USER_TASK_CANDIDATE_PARAM,
|
||||
MapUtil.getStr(node.getAttributes(), BpmnModelConstants.USER_TASK_CANDIDATE_PARAM));
|
||||
}
|
||||
|
||||
private static void addBpmnExclusiveGatewayNode(Process mainProcess, BpmSimpleModelNodeVO node) {
|
||||
Assert.notEmpty(node.getConditionNodes(), "网关节点的条件节点不能为空");
|
||||
ExclusiveGateway exclusiveGateway = new ExclusiveGateway();
|
||||
@ -483,25 +507,21 @@ public class BpmnModelUtils {
|
||||
mainProcess.addFlowElement(endEvent);
|
||||
}
|
||||
|
||||
private static void addBpmnUserTaskEventNode(Process mainProcess, BpmSimpleModelNodeVO node) {
|
||||
private static void addBpmnUserTaskNode(Process mainProcess, BpmSimpleModelNodeVO node) {
|
||||
UserTask userTask = new UserTask();
|
||||
userTask.setId(node.getId());
|
||||
userTask.setName(node.getName());
|
||||
Integer candidateStrategy = MapUtil.getInt(node.getAttributes(), BpmnModelConstants.USER_TASK_CANDIDATE_STRATEGY);
|
||||
// 添加自定义属性
|
||||
addExtensionAttribute(userTask, BpmnModelConstants.NAMESPACE, BpmnModelConstants.USER_TASK_CANDIDATE_STRATEGY,
|
||||
candidateStrategy == null ? null : String.valueOf(candidateStrategy));
|
||||
addExtensionAttribute(userTask, BpmnModelConstants.NAMESPACE, BpmnModelConstants.USER_TASK_CANDIDATE_PARAM,
|
||||
MapUtil.getStr(node.getAttributes(), BpmnModelConstants.USER_TASK_CANDIDATE_PARAM));
|
||||
addExtensionAttributes(node, userTask);
|
||||
mainProcess.addFlowElement(userTask);
|
||||
}
|
||||
|
||||
private static void addExtensionAttribute(FlowElement element, String namespace, String name, String value) {
|
||||
private static void addExtensionAttributes(FlowElement element, String namespace, String name, String value) {
|
||||
if (value == null) {
|
||||
return;
|
||||
}
|
||||
ExtensionAttribute extensionAttribute = new ExtensionAttribute(name, value);
|
||||
extensionAttribute.setNamespace(namespace);
|
||||
extensionAttribute.setNamespacePrefix(FLOWABLE_EXTENSIONS_PREFIX);
|
||||
element.addAttribute(extensionAttribute);
|
||||
}
|
||||
|
||||
|
@ -17,9 +17,11 @@ public interface BpmProcessInstanceCopyService {
|
||||
* 流程实例的抄送
|
||||
*
|
||||
* @param userIds 抄送的用户编号
|
||||
* @param taskId 流程任务编号
|
||||
* @param processInstanceId 流程编号
|
||||
* @param taskId 任务编号
|
||||
* @param taskName 任务名称
|
||||
*/
|
||||
void createProcessInstanceCopy(Collection<Long> userIds, String taskId);
|
||||
void createProcessInstanceCopy(Collection<Long> userIds, String processInstanceId, String taskId, String taskName);
|
||||
|
||||
/**
|
||||
* 获得抄送的流程的分页
|
||||
|
@ -1,6 +1,5 @@
|
||||
package cn.iocoder.yudao.module.bpm.service.task;
|
||||
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.instance.BpmProcessInstanceCopyPageReqVO;
|
||||
import cn.iocoder.yudao.module.bpm.dal.dataobject.task.BpmProcessInstanceCopyDO;
|
||||
@ -11,7 +10,6 @@ import jakarta.annotation.Resource;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.flowable.engine.repository.ProcessDefinition;
|
||||
import org.flowable.engine.runtime.ProcessInstance;
|
||||
import org.flowable.task.api.Task;
|
||||
import org.springframework.context.annotation.Lazy;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
@ -47,14 +45,14 @@ public class BpmProcessInstanceCopyServiceImpl implements BpmProcessInstanceCopy
|
||||
private BpmProcessDefinitionService processDefinitionService;
|
||||
|
||||
@Override
|
||||
public void createProcessInstanceCopy(Collection<Long> userIds, String taskId) {
|
||||
// 1.1 校验任务存在
|
||||
Task task = taskService.getTask(taskId);
|
||||
if (ObjectUtil.isNull(task)) {
|
||||
throw exception(ErrorCodeConstants.TASK_NOT_EXISTS);
|
||||
}
|
||||
public void createProcessInstanceCopy(Collection<Long> userIds, String processInstanceId, String taskId, String taskName) {
|
||||
// 1.1 校验任务存在 暂时去掉这个校验. 因为任务可能仿钉钉快搭的抄送节点(ScriptTask)
|
||||
// Task task = taskService.getTask(taskId);
|
||||
// if (ObjectUtil.isNull(task)) {
|
||||
// throw exception(ErrorCodeConstants.TASK_NOT_EXISTS);
|
||||
// }
|
||||
// 1.2 校验流程实例存在
|
||||
String processInstanceId = task.getProcessInstanceId();
|
||||
// String processInstanceId = task.getProcessInstanceId();
|
||||
ProcessInstance processInstance = processInstanceService.getProcessInstance(processInstanceId);
|
||||
if (processInstance == null) {
|
||||
throw exception(ErrorCodeConstants.PROCESS_INSTANCE_NOT_EXISTS);
|
||||
@ -70,7 +68,7 @@ public class BpmProcessInstanceCopyServiceImpl implements BpmProcessInstanceCopy
|
||||
List<BpmProcessInstanceCopyDO> copyList = convertList(userIds, userId -> new BpmProcessInstanceCopyDO()
|
||||
.setUserId(userId).setStartUserId(Long.valueOf(processInstance.getStartUserId()))
|
||||
.setProcessInstanceId(processInstanceId).setProcessInstanceName(processInstance.getName())
|
||||
.setCategory(processDefinition.getCategory()).setTaskId(taskId).setTaskName(task.getName()));
|
||||
.setCategory(processDefinition.getCategory()).setTaskId(taskId).setTaskName(taskName));
|
||||
processInstanceCopyMapper.insertBatch(copyList);
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,34 @@
|
||||
package cn.iocoder.yudao.module.bpm.service.task;
|
||||
|
||||
import cn.iocoder.yudao.module.bpm.framework.flowable.core.candidate.BpmTaskCandidateInvoker;
|
||||
import jakarta.annotation.Resource;
|
||||
import org.flowable.bpmn.model.FlowElement;
|
||||
import org.flowable.engine.delegate.DelegateExecution;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* 仿钉钉快搭各个节点 Service
|
||||
* @author jason
|
||||
*/
|
||||
@Service
|
||||
public class BpmSimpleNodeService {
|
||||
|
||||
@Resource
|
||||
private BpmTaskCandidateInvoker taskCandidateInvoker;
|
||||
@Resource
|
||||
private BpmProcessInstanceCopyService processInstanceCopyService;
|
||||
|
||||
/**
|
||||
* 仿钉钉快搭抄送
|
||||
* @param execution 执行的任务(ScriptTask)
|
||||
*/
|
||||
public Boolean copy(DelegateExecution execution) {
|
||||
Set<Long> userIds = taskCandidateInvoker.calculateUsers(execution);
|
||||
FlowElement currentFlowElement = execution.getCurrentFlowElement();
|
||||
processInstanceCopyService.createProcessInstanceCopy(userIds, execution.getProcessInstanceId(),
|
||||
currentFlowElement.getId(), currentFlowElement.getName());
|
||||
return Boolean.TRUE;
|
||||
}
|
||||
}
|
@ -185,7 +185,8 @@ public class BpmTaskServiceImpl implements BpmTaskService {
|
||||
|
||||
// 2. 抄送用户
|
||||
if (CollUtil.isNotEmpty(reqVO.getCopyUserIds())) {
|
||||
processInstanceCopyService.createProcessInstanceCopy(reqVO.getCopyUserIds(), reqVO.getId());
|
||||
processInstanceCopyService.createProcessInstanceCopy(reqVO.getCopyUserIds(), instance.getProcessInstanceId(),
|
||||
reqVO.getId(), task.getName());
|
||||
}
|
||||
|
||||
// 情况一:被委派的任务,不调用 complete 去完成任务
|
||||
|
Loading…
Reference in New Issue
Block a user