协议转换优化
This commit is contained in:
parent
88cb143512
commit
ad6bba3ddc
@ -0,0 +1,36 @@
|
||||
package cn.axzo.workflow.core.common.enums;
|
||||
|
||||
import org.flowable.bpmn.model.UserTask;
|
||||
|
||||
public enum BpmFlowMultiMode {
|
||||
|
||||
//0 发起人 1审批 2抄送 3条件 4路由
|
||||
OR("OR", "或签"),
|
||||
AND("AND", "会签");
|
||||
|
||||
private String type;
|
||||
private String desc;
|
||||
BpmFlowMultiMode(String type, String desc) {
|
||||
this.type = type;
|
||||
this.desc = desc;
|
||||
}
|
||||
public boolean isEqual(String type) {
|
||||
return this.type.equals(type);
|
||||
}
|
||||
|
||||
public String getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public void setType(String type) {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public String getDesc() {
|
||||
return desc;
|
||||
}
|
||||
|
||||
public void setDesc(String desc) {
|
||||
this.desc = desc;
|
||||
}
|
||||
}
|
||||
@ -1,5 +1,6 @@
|
||||
package cn.axzo.workflow.core.common.enums;
|
||||
|
||||
import lombok.Data;
|
||||
import org.flowable.bpmn.model.UserTask;
|
||||
|
||||
public enum BpmFlowNodeType {
|
||||
@ -22,4 +23,28 @@ public enum BpmFlowNodeType {
|
||||
public boolean isEqual(String type) {
|
||||
return this.type.equals(type);
|
||||
}
|
||||
|
||||
public String getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public void setType(String type) {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public String getDesc() {
|
||||
return desc;
|
||||
}
|
||||
|
||||
public void setDesc(String desc) {
|
||||
this.desc = desc;
|
||||
}
|
||||
|
||||
public Class<?> getTypeClass() {
|
||||
return typeClass;
|
||||
}
|
||||
|
||||
public void setTypeClass(Class<?> typeClass) {
|
||||
this.typeClass = typeClass;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,23 +1,27 @@
|
||||
package cn.axzo.workflow.core.common.utils;
|
||||
|
||||
import cn.axzo.workflow.core.common.BpmConstants;
|
||||
import cn.axzo.workflow.core.common.enums.BpmFlowMultiMode;
|
||||
import cn.axzo.workflow.core.common.enums.BpmFlowNodeType;
|
||||
import cn.axzo.workflow.core.common.exception.WorkflowEngineException;
|
||||
import cn.axzo.workflow.core.service.dto.BpmJsonNode;
|
||||
import cn.axzo.workflow.core.service.dto.request.BpmJsonNodeProperty;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.google.common.collect.Lists;
|
||||
import lombok.SneakyThrows;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.time.DateUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.flowable.bpmn.BpmnAutoLayout;
|
||||
import org.flowable.bpmn.converter.BpmnXMLConverter;
|
||||
import org.flowable.bpmn.model.*;
|
||||
import org.flowable.bpmn.model.Process;
|
||||
import org.flowable.engine.delegate.ExecutionListener;
|
||||
import org.flowable.engine.delegate.TaskListener;
|
||||
import org.flowable.engine.repository.Model;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
import java.util.*;
|
||||
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static cn.axzo.workflow.core.common.BpmConstants.*;
|
||||
import static cn.axzo.workflow.core.common.enums.BpmErrorCode.BPM_META_DATA_FORMAT_ERROR;
|
||||
import static org.flowable.bpmn.model.ImplementationType.IMPLEMENTATION_TYPE_DELEGATEEXPRESSION;
|
||||
|
||||
@ -31,28 +35,31 @@ public class BpmTransformUtil {
|
||||
BpmnModel bpmnModel =new BpmnModel();
|
||||
Process process=new Process();
|
||||
bpmnModel.addProcess(process);
|
||||
List<SequenceFlow> sequenceFlows = Lists.newArrayList();
|
||||
|
||||
process.setId(model.getKey());
|
||||
StartEvent startEvent = createStartEvent();
|
||||
process.addFlowElement(startEvent);
|
||||
process.setName(model.getName());
|
||||
JSONObject jsonObject = (JSONObject) JSONObject.toJSON(bpmnJson);
|
||||
List<SequenceFlow> sequenceFlows = Lists.newArrayList();
|
||||
Map<String,BpmJsonNode> childNodeMap=new HashMap<>();
|
||||
// JSONObject jsonObject = (JSONObject) JSONObject.toJSON(bpmnJson);
|
||||
// ExtensionAttribute extensionAttribute=new ExtensionAttribute();
|
||||
// extensionAttribute.setName("TestName");
|
||||
// extensionAttribute.setNamespace("http://flowable.org/bpmn");
|
||||
// extensionAttribute.setValue(bpmnJson.toJSONString());
|
||||
//// process.addAttribute(extensionAttribute);
|
||||
// JSONObject processNodes = bpmnJson.getJSONObject("nodeConfig");
|
||||
|
||||
String lastNode = null;
|
||||
try {
|
||||
lastNode = create(startEvent.getId(), jsonObject, bpmnModel,process,sequenceFlows);
|
||||
lastNode = create(startEvent.getId(), bpmnJson,process, bpmnModel, sequenceFlows, childNodeMap);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
throw new WorkflowEngineException(BPM_META_DATA_FORMAT_ERROR);
|
||||
}
|
||||
EndEvent endEvent = createEndEvent();
|
||||
process.addFlowElement(endEvent);
|
||||
process.addFlowElement(connect(lastNode, endEvent.getId(),sequenceFlows));
|
||||
process.addFlowElement(connect(lastNode, endEvent.getId(),sequenceFlows, childNodeMap, process));
|
||||
|
||||
|
||||
new BpmnAutoLayout(bpmnModel).execute();
|
||||
@ -62,187 +69,8 @@ public class BpmTransformUtil {
|
||||
return xmlMeta;
|
||||
}
|
||||
|
||||
private static String create(String fromId, JSONObject flowNode, BpmnModel model, Process process, List<SequenceFlow> sequenceFlows) throws IllegalAccessException {
|
||||
String nodeType = flowNode.getString("type");
|
||||
if (BpmFlowNodeType.NODE_STARTER.name().equals(nodeType)) {
|
||||
// flowNode.put("incoming", Collections.singletonList(fromId));
|
||||
String id = fromId;
|
||||
|
||||
// 如果当前任务还有后续任务,则遍历创建后续任务
|
||||
com.alibaba.fastjson.JSONObject nextNode = flowNode.getJSONObject("childNode");
|
||||
if (Objects.nonNull(nextNode)) {
|
||||
FlowElement flowElement = model.getFlowElement(id);
|
||||
return create(id, nextNode,model,process,sequenceFlows);
|
||||
} else {
|
||||
return id;
|
||||
}
|
||||
}
|
||||
else if (BpmFlowNodeType.NODE_TASK.name().equals(nodeType)) {
|
||||
flowNode.put("incoming", Collections.singletonList(fromId));
|
||||
String id = createTask(flowNode,process,sequenceFlows);
|
||||
|
||||
// 如果当前任务还有后续任务,则遍历创建后续任务
|
||||
com.alibaba.fastjson.JSONObject nextNode = flowNode.getJSONObject("childNode");
|
||||
if (Objects.nonNull(nextNode)&& Objects.nonNull(nextNode.get("nodeId"))) {
|
||||
FlowElement flowElement = model.getFlowElement(id);
|
||||
return create(id, nextNode,model,process,sequenceFlows);
|
||||
} else {
|
||||
return id;
|
||||
}
|
||||
}
|
||||
else {
|
||||
throw new RuntimeException("未知节点类型: nodeType=" + nodeType);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static String createParallelGatewayBuilder(String formId, com.alibaba.fastjson.JSONObject flowNode, BpmnModel model, Process process, List<SequenceFlow> sequenceFlows) throws IllegalAccessException {
|
||||
String name = flowNode.getString("nodeName");
|
||||
ParallelGateway parallelGateway = new ParallelGateway();
|
||||
String parallelGatewayId = id("parallelGateway");
|
||||
parallelGateway.setId(parallelGatewayId);
|
||||
parallelGateway.setName(name);
|
||||
process.addFlowElement(parallelGateway);
|
||||
process.addFlowElement(connect(formId, parallelGatewayId,sequenceFlows));
|
||||
|
||||
if (Objects.isNull(flowNode.getJSONArray("conditionNodes"))
|
||||
&& Objects.isNull(flowNode.getJSONObject("childNode"))) {
|
||||
return parallelGatewayId;
|
||||
}
|
||||
|
||||
List<com.alibaba.fastjson.JSONObject> flowNodes = Optional.ofNullable(flowNode.getJSONArray("conditionNodes")).map(e -> e.toJavaList(com.alibaba.fastjson.JSONObject.class)).orElse(Collections.emptyList());
|
||||
List<String> incoming = Lists.newArrayListWithCapacity(flowNodes.size());
|
||||
for (com.alibaba.fastjson.JSONObject element : flowNodes) {
|
||||
com.alibaba.fastjson.JSONObject childNode = element.getJSONObject("childNode");
|
||||
if (Objects.isNull(childNode)) {
|
||||
incoming.add(parallelGatewayId);
|
||||
continue;
|
||||
}
|
||||
String identifier = create(parallelGatewayId, childNode,model,process,sequenceFlows);
|
||||
if (Objects.nonNull(identifier)) {
|
||||
incoming.add(identifier);
|
||||
}
|
||||
}
|
||||
|
||||
com.alibaba.fastjson.JSONObject childNode = flowNode.getJSONObject("childNode");
|
||||
if (Objects.nonNull(childNode)) {
|
||||
// 普通结束网关
|
||||
if (CollectionUtils.isEmpty(incoming)) {
|
||||
return create(parallelGatewayId, childNode,model,process,sequenceFlows);
|
||||
} else {
|
||||
// 所有 service task 连接 end parallel gateway
|
||||
childNode.put("incoming", incoming);
|
||||
FlowElement flowElement = model.getFlowElement(incoming.get(0));
|
||||
// 1.0 先进行边连接, 暂存 nextNode
|
||||
com.alibaba.fastjson.JSONObject nextNode = childNode.getJSONObject("childNode");
|
||||
childNode.put("childNode", null);
|
||||
String identifier = create(incoming.get(0), childNode,model,process,sequenceFlows);
|
||||
for (int i = 1; i < incoming.size(); i++) {
|
||||
FlowElement flowElement1 = model.getFlowElement(incoming.get(i));
|
||||
process.addFlowElement(connect(flowElement1.getId(), identifier,sequenceFlows));
|
||||
}
|
||||
// 1.1 边连接完成后,在进行 nextNode 创建
|
||||
if (Objects.nonNull(nextNode)) {
|
||||
return create(identifier, nextNode,model,process,sequenceFlows);
|
||||
} else {
|
||||
return identifier;
|
||||
}
|
||||
}
|
||||
}
|
||||
return parallelGatewayId;
|
||||
}
|
||||
|
||||
private static String createServiceTask(com.alibaba.fastjson.JSONObject flowNode, Process process, List<SequenceFlow> sequenceFlows) {
|
||||
List<String> incoming = flowNode.getJSONArray("incoming").toJavaList(String.class);
|
||||
// 自动生成id
|
||||
String id = id("serviceTask");
|
||||
if (incoming != null && !incoming.isEmpty()) {
|
||||
ServiceTask serviceTask = new ServiceTask();
|
||||
serviceTask.setName(flowNode.getString("nodeName"));
|
||||
serviceTask.setId(id);
|
||||
|
||||
// todo lvshaohua
|
||||
serviceTask.setImplementationType("class");
|
||||
serviceTask.setImplementation("com.dingding.mid.listener.Vue3Listener");
|
||||
|
||||
process.addFlowElement(serviceTask);
|
||||
process.addFlowElement(connect(incoming.get(0), id,sequenceFlows));
|
||||
}
|
||||
return id;
|
||||
}
|
||||
|
||||
private static String createTask(com.alibaba.fastjson.JSONObject flowNode, Process process, List<SequenceFlow> sequenceFlows) {
|
||||
List<String> incoming = flowNode.getJSONArray("incoming").toJavaList(String.class);
|
||||
|
||||
// 自动生成id
|
||||
String id = flowNode.getString("nodeId");
|
||||
if (incoming != null && !incoming.isEmpty()) {
|
||||
UserTask userTask = new UserTask();
|
||||
userTask.setName(flowNode.getString("nodeName"));
|
||||
userTask.setId(id);
|
||||
process.addFlowElement(userTask);
|
||||
if(BpmFlowNodeType.NODE_STARTER.name().equals(flowNode.getString("type"))){
|
||||
id = BpmConstants.START_EVENT_ID;
|
||||
}
|
||||
else{
|
||||
|
||||
// if ((!ObjectUtils.isEmpty(flowNode.getJSONArray("nodeUserList")) && flowNode.getJSONArray("nodeUserList").size() > 1)
|
||||
// || flowNode.getBoolean(""))
|
||||
|
||||
MultiInstanceLoopCharacteristics multiInstanceLoopCharacteristics=new MultiInstanceLoopCharacteristics();
|
||||
String examineMode = flowNode.getString("examineMode");
|
||||
// 审批人集合参数
|
||||
multiInstanceLoopCharacteristics.setInputDataItem(userTask.getId()+"_assigneeList");
|
||||
// 迭代集合
|
||||
multiInstanceLoopCharacteristics.setElementVariable("assignee");
|
||||
// 并行
|
||||
multiInstanceLoopCharacteristics.setSequential(false);
|
||||
// userTask.setAssignee("${assigneeName}");
|
||||
// 设置多实例属性
|
||||
if("NEXT".equals(examineMode)){
|
||||
multiInstanceLoopCharacteristics.setSequential(true);
|
||||
} else if("OR".equals(examineMode)){
|
||||
multiInstanceLoopCharacteristics.setCompletionCondition("${nrOfCompletedInstances==1}");
|
||||
} else if ("AND".equals(examineMode)) {
|
||||
multiInstanceLoopCharacteristics.setCompletionCondition("${nrOfCompletedInstances==nrOfInstances}");
|
||||
}
|
||||
|
||||
|
||||
ArrayList<FlowableListener> taskListeners = new ArrayList<>();
|
||||
FlowableListener taskListener = new FlowableListener();
|
||||
// 事件类型,
|
||||
taskListener.setEvent(TaskListener.EVENTNAME_CREATE);
|
||||
// 监听器类型
|
||||
taskListener.setImplementationType(IMPLEMENTATION_TYPE_DELEGATEEXPRESSION);
|
||||
// 设置实现了,这里设置监听器的类型是delegateExpression,这样可以在实现类注入Spring bean.
|
||||
taskListener.setImplementation("${DDTaskCreateListener}");
|
||||
taskListeners.add(taskListener);
|
||||
userTask.setLoopCharacteristics(multiInstanceLoopCharacteristics);
|
||||
|
||||
userTask.setTaskListeners(taskListeners);
|
||||
}
|
||||
SequenceFlow sequenceFlow = connect(incoming.get(0), id,sequenceFlows);
|
||||
if (sequenceFlow != null) {
|
||||
process.addFlowElement(sequenceFlow);
|
||||
}
|
||||
}
|
||||
return id;
|
||||
}
|
||||
|
||||
@SneakyThrows
|
||||
private static String id(String prefix) {
|
||||
|
||||
long qutient = (System.currentTimeMillis() - DateUtils.parseDate("2020-08-01", "yyyy-MM-dd").getTime());
|
||||
qutient += Math.ceil(Math.random() * 1000); // 防止重複
|
||||
String chars = "0123456789ABCDEFGHIGKLMNOPQRSTUVWXYZabcdefghigklmnopqrstuvwxyz";
|
||||
int radix = chars.length();
|
||||
StringBuilder stringBuffer = new StringBuilder(prefix + "_");
|
||||
do {
|
||||
int mod = (int) (qutient % radix);
|
||||
qutient = ( qutient - mod ) / radix;
|
||||
stringBuffer.append(chars.charAt(mod));
|
||||
} while ( qutient > 0 );
|
||||
return stringBuffer.toString();
|
||||
return prefix + "_" + UUID.randomUUID().toString().replace("-", "").toLowerCase();
|
||||
}
|
||||
|
||||
private static ServiceTask serviceTask(String name) {
|
||||
@ -251,35 +79,283 @@ public class BpmTransformUtil {
|
||||
return serviceTask;
|
||||
}
|
||||
|
||||
protected static SequenceFlow connect(String from, String to,List<SequenceFlow> sequenceFlows) {
|
||||
public static SequenceFlow connect(String from, String to,List<SequenceFlow> sequenceFlows,Map<String,BpmJsonNode> childNodeMap,Process process) {
|
||||
SequenceFlow flow = new SequenceFlow();
|
||||
flow.setId(id("sequenceFlow"));
|
||||
String sequenceFlowId = id("sequenceFlow");
|
||||
if(process.getFlowElement(from) !=null && process.getFlowElement(from) instanceof ExclusiveGateway){
|
||||
BpmJsonNode childNode = childNodeMap.get(to);
|
||||
if(childNode!=null){
|
||||
String parentId = childNode.getParentId();
|
||||
if(StringUtils.isNotBlank(parentId)){
|
||||
BpmJsonNode parentNode = childNodeMap.get(parentId);
|
||||
if(parentNode!=null){
|
||||
if(BpmFlowNodeType.NODE_CONDITION.getType().equals(parentNode.getType()) ){
|
||||
sequenceFlowId=parentNode.getId();
|
||||
flow.setName(parentNode.getName());
|
||||
if(!Boolean.TRUE.equals(parentNode.getProperty().getDefaultCondition())){
|
||||
//解析条件表达式
|
||||
StringBuffer conditionExpression=new StringBuffer();
|
||||
conditionExpression.append("${ ( ");
|
||||
conditionExpression.append(EXPRESSION_CLASS+"numberEquals("+parentNode.getProperty().getConditionKey()+","+parentNode.getProperty().getConditionBranchValue()+") ");
|
||||
conditionExpression.append(" ) }");
|
||||
|
||||
flow.setConditionExpression(conditionExpression.toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
flow.setId(sequenceFlowId);
|
||||
flow.setSourceRef(from);
|
||||
flow.setTargetRef(to);
|
||||
// 连接线必须同时有 source 和 target
|
||||
if (from == null || to == null) {
|
||||
return null;
|
||||
}
|
||||
sequenceFlows.add(flow);
|
||||
return flow;
|
||||
}
|
||||
|
||||
protected static StartEvent createStartEvent() {
|
||||
public static StartEvent createStartEvent() {
|
||||
StartEvent startEvent = new StartEvent();
|
||||
startEvent.setId(id("start"));
|
||||
startEvent.setId(START_EVENT_ID);
|
||||
startEvent.setInitiator("applyUserId");
|
||||
return startEvent;
|
||||
}
|
||||
|
||||
protected static EndEvent createEndEvent() {
|
||||
public static EndEvent createEndEvent() {
|
||||
EndEvent endEvent = new EndEvent();
|
||||
endEvent.setId(id("end"));
|
||||
endEvent.setId(END_EVENT_ID);
|
||||
return endEvent;
|
||||
}
|
||||
|
||||
// public static StartEvent createStartEvent() {
|
||||
// StartEvent startEvent = new StartEvent();
|
||||
// startEvent.setId(WorkflowConstants.START_EVENT_ID);
|
||||
// startEvent.setInitiator("applyUserId");
|
||||
// return startEvent;
|
||||
// }
|
||||
|
||||
public static String create(String fromId, BpmJsonNode flowNode, Process process,BpmnModel bpmnModel,List<SequenceFlow> sequenceFlows,Map<String,BpmJsonNode> childNodeMap) throws InvocationTargetException, IllegalAccessException {
|
||||
String nodeType = flowNode.getType();
|
||||
if (BpmFlowNodeType.NODE_CONDITION.isEqual(nodeType)) {
|
||||
return createExclusiveGatewayBuilder(fromId, flowNode,process,bpmnModel,sequenceFlows,childNodeMap);
|
||||
} else if (BpmFlowNodeType.NODE_TASK.isEqual(nodeType)) {
|
||||
childNodeMap.put(flowNode.getId(),flowNode);
|
||||
Map incoming = flowNode.getIncoming();
|
||||
incoming.put("incoming", Collections.singletonList(fromId));
|
||||
String id = createTask(process,flowNode,sequenceFlows,childNodeMap);
|
||||
// 如果当前任务还有后续任务,则遍历创建后续任务
|
||||
BpmJsonNode children = flowNode.getChildren();
|
||||
if (Objects.nonNull(children) &&StringUtils.isNotBlank(children.getId())) {
|
||||
return create(id, children,process,bpmnModel,sequenceFlows,childNodeMap);
|
||||
} else {
|
||||
return id;
|
||||
}
|
||||
}
|
||||
else if(BpmFlowNodeType.NODE_STARTER.isEqual(nodeType)){
|
||||
childNodeMap.put(flowNode.getId(),flowNode);
|
||||
Map incoming = flowNode.getIncoming();
|
||||
incoming.put("incoming", Collections.singletonList(fromId));
|
||||
String id = createTask(process,flowNode,sequenceFlows,childNodeMap);
|
||||
// 如果当前任务还有后续任务,则遍历创建后续任务
|
||||
BpmJsonNode children = flowNode.getChildren();
|
||||
if (Objects.nonNull(children) &&StringUtils.isNotBlank(children.getId())) {
|
||||
return create(id, children,process,bpmnModel,sequenceFlows,childNodeMap);
|
||||
} else {
|
||||
return id;
|
||||
}
|
||||
}
|
||||
else {
|
||||
throw new RuntimeException("未知节点类型: nodeType=" + nodeType);
|
||||
}
|
||||
}
|
||||
public static ExclusiveGateway createExclusiveGateWayEnd(String id){
|
||||
ExclusiveGateway exclusiveGateway=new ExclusiveGateway();
|
||||
exclusiveGateway.setId(id);
|
||||
return exclusiveGateway;
|
||||
}
|
||||
|
||||
|
||||
private static String createExclusiveGatewayBuilder(String formId, BpmJsonNode flowNode,Process process,BpmnModel bpmnModel,List<SequenceFlow> sequenceFlows,Map<String,BpmJsonNode> childNodeMap) throws InvocationTargetException, IllegalAccessException {
|
||||
childNodeMap.put(flowNode.getId(),flowNode);
|
||||
String name =flowNode.getName();
|
||||
String exclusiveGatewayId = flowNode.getId();
|
||||
ExclusiveGateway exclusiveGateway = new ExclusiveGateway();
|
||||
exclusiveGateway.setId(exclusiveGatewayId);
|
||||
exclusiveGateway.setName(name);
|
||||
process.addFlowElement(exclusiveGateway);
|
||||
process.addFlowElement(connect(formId, exclusiveGatewayId,sequenceFlows,childNodeMap,process));
|
||||
|
||||
if (Objects.isNull(flowNode.getBranches()) && Objects.isNull(flowNode.getChildren())) {
|
||||
return exclusiveGatewayId;
|
||||
}
|
||||
List<BpmJsonNode> flowNodes = flowNode.getBranches();
|
||||
List<String> incoming = Lists.newArrayListWithCapacity(flowNodes.size());
|
||||
List<Map> conditions = Lists.newCopyOnWriteArrayList();
|
||||
for (BpmJsonNode element : flowNodes) {
|
||||
Boolean typeElse = element.getProperty().getDefaultCondition();
|
||||
if(Boolean.TRUE.equals(typeElse)){
|
||||
exclusiveGateway.setDefaultFlow(element.getId());
|
||||
}
|
||||
childNodeMap.put(element.getId(),element);
|
||||
BpmJsonNode childNode = element.getChildren();
|
||||
String nodeName = element.getName();
|
||||
|
||||
if (Objects.isNull(childNode) || StringUtils.isBlank(childNode.getId())) {
|
||||
|
||||
incoming.add(exclusiveGatewayId);
|
||||
Map condition = new HashMap();
|
||||
|
||||
//解析条件表达式
|
||||
StringBuffer conditionExpression=new StringBuffer();
|
||||
conditionExpression.append("${ ( ");
|
||||
conditionExpression.append(EXPRESSION_CLASS+"numberEquals("+element.getProperty().getConditionKey()+","+element.getProperty().getConditionBranchValue()+") ");
|
||||
conditionExpression.append(" ) }");
|
||||
condition.put("nodeName", nodeName);
|
||||
condition.put("expression", conditionExpression.toString());
|
||||
|
||||
conditions.add(condition);
|
||||
continue;
|
||||
}
|
||||
// 只生成一个任务,同时设置当前任务的条件
|
||||
Map incomingObj = childNode.getIncoming();
|
||||
incomingObj.put("incoming", Collections.singletonList(exclusiveGatewayId));
|
||||
String identifier = create(exclusiveGatewayId, childNode,process,bpmnModel,sequenceFlows,childNodeMap);
|
||||
List<SequenceFlow> flows = sequenceFlows.stream().filter(flow -> StringUtils.equals(exclusiveGatewayId, flow.getSourceRef()))
|
||||
.collect(Collectors.toList());
|
||||
flows.stream().forEach(
|
||||
e -> {
|
||||
if (StringUtils.isBlank(e.getName()) && StringUtils.isNotBlank(nodeName)) {
|
||||
e.setName(nodeName);
|
||||
}
|
||||
// 设置条件表达式
|
||||
// TODO 不知道什么意思
|
||||
// if (Objects.isNull(e.getConditionExpression()) && StringUtils.isNotBlank(expression)) {
|
||||
// e.setConditionExpression(expression);
|
||||
// }
|
||||
}
|
||||
);
|
||||
if (Objects.nonNull(identifier)) {
|
||||
incoming.add(identifier);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
BpmJsonNode childNode = flowNode.getChildren();
|
||||
|
||||
if (Objects.nonNull(childNode) &&StringUtils.isNotBlank(childNode.getId()) ) {
|
||||
String parentId = childNode.getParentId();
|
||||
BpmJsonNode parentChildNode = childNodeMap.get(parentId);
|
||||
if(BpmFlowNodeType.NODE_CONDITION.getType().equals(parentChildNode.getType())){
|
||||
String endExId= parentChildNode.getId()+"end";
|
||||
process.addFlowElement(createExclusiveGateWayEnd(endExId));
|
||||
if (incoming == null || incoming.isEmpty()) {
|
||||
return create(exclusiveGatewayId, childNode, process, bpmnModel, sequenceFlows,
|
||||
childNodeMap);
|
||||
}
|
||||
else {
|
||||
Map incomingObj = childNode.getIncoming();
|
||||
// 所有 service task 连接 end exclusive gateway
|
||||
incomingObj.put("incoming", incoming);
|
||||
FlowElement flowElement = bpmnModel.getFlowElement(incoming.get(0));
|
||||
// 1.0 先进行边连接, 暂存 nextNode
|
||||
BpmJsonNode nextNode = childNode.getChildren();
|
||||
childNode.setChildren(null);
|
||||
String identifier = endExId;
|
||||
for (int i = 0; i < incoming.size(); i++) {
|
||||
process.addFlowElement(connect(incoming.get(i), identifier, sequenceFlows,childNodeMap,process));
|
||||
}
|
||||
|
||||
// 针对 gateway 空任务分支 添加条件表达式
|
||||
if (!conditions.isEmpty()) {
|
||||
FlowElement flowElement1 = bpmnModel.getFlowElement(identifier);
|
||||
// 获取从 gateway 到目标节点 未设置条件表达式的节点
|
||||
List<SequenceFlow> flows = sequenceFlows.stream().filter(
|
||||
flow -> StringUtils.equals(flowElement1.getId(), flow.getTargetRef()))
|
||||
.filter(
|
||||
flow -> StringUtils.equals(flow.getSourceRef(), exclusiveGatewayId))
|
||||
.collect(Collectors.toList());
|
||||
flows.stream().forEach(sequenceFlow -> {
|
||||
if (!conditions.isEmpty()) {
|
||||
Map condition = conditions.get(0);
|
||||
String nodeName = (String) condition.get("nodeName");
|
||||
String expression = (String) condition.get("expression");
|
||||
|
||||
if (StringUtils.isBlank(sequenceFlow.getName()) && StringUtils
|
||||
.isNotBlank(nodeName)) {
|
||||
sequenceFlow.setName(nodeName);
|
||||
}
|
||||
// 设置条件表达式
|
||||
if (Objects.isNull(sequenceFlow.getConditionExpression())
|
||||
&& StringUtils.isNotBlank(expression)) {
|
||||
sequenceFlow.setConditionExpression(expression);
|
||||
}
|
||||
conditions.remove(0);
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
// 1.1 边连接完成后,在进行 nextNode 创建
|
||||
if (Objects.nonNull(nextNode) &&StringUtils.isNotBlank(nextNode.getId())) {
|
||||
return create(identifier, nextNode, process, bpmnModel, sequenceFlows,
|
||||
childNodeMap);
|
||||
} else {
|
||||
return identifier;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return exclusiveGatewayId;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
private static String createTask(Process process,BpmJsonNode flowNode,List<SequenceFlow> sequenceFlows,Map<String,BpmJsonNode> childNodeMap) {
|
||||
Map incomingJson = flowNode.getIncoming();
|
||||
List<String> incoming = (List<String>) incomingJson.get("incoming");
|
||||
// 自动生成id
|
||||
// String id = id("serviceTask");
|
||||
String id=flowNode.getId();
|
||||
if (incoming != null && !incoming.isEmpty()) {
|
||||
UserTask userTask = new UserTask();
|
||||
userTask.setName(flowNode.getName());
|
||||
userTask.setId(id);
|
||||
process.addFlowElement(userTask);
|
||||
process.addFlowElement(connect(incoming.get(0), id,sequenceFlows,childNodeMap,process));
|
||||
|
||||
FlowableListener createTaskListener = new FlowableListener();
|
||||
createTaskListener.setEvent(TaskListener.EVENTNAME_ALL_EVENTS);
|
||||
createTaskListener.setImplementationType(IMPLEMENTATION_TYPE_DELEGATEEXPRESSION);
|
||||
createTaskListener.setImplementation("${engineTaskEventListener}");
|
||||
userTask.setTaskListeners(Arrays.asList(createTaskListener));
|
||||
if("root".equalsIgnoreCase(id)){
|
||||
}
|
||||
else{
|
||||
ArrayList<FlowableListener> listeners = new ArrayList<>();
|
||||
FlowableListener activitiListener = new FlowableListener();
|
||||
activitiListener.setEvent(ExecutionListener.EVENTNAME_START);
|
||||
activitiListener.setImplementationType(IMPLEMENTATION_TYPE_DELEGATEEXPRESSION);
|
||||
activitiListener.setImplementation("${counterSignListener}");
|
||||
|
||||
listeners.add(activitiListener);
|
||||
userTask.setExecutionListeners(listeners);
|
||||
|
||||
if (Boolean.TRUE.equals(flowNode.getProperty().getIsMultiTask())) {
|
||||
BpmJsonNodeProperty property = flowNode.getProperty();
|
||||
BpmFlowMultiMode mode = property.getMultiMode();
|
||||
|
||||
MultiInstanceLoopCharacteristics multiInstanceLoopCharacteristics = new MultiInstanceLoopCharacteristics();
|
||||
// 审批人集合参数
|
||||
multiInstanceLoopCharacteristics.setInputDataItem(userTask.getId()+"assigneeList");
|
||||
// 迭代集合
|
||||
multiInstanceLoopCharacteristics.setElementVariable("assigneeName");
|
||||
// 并行
|
||||
multiInstanceLoopCharacteristics.setSequential(false);
|
||||
userTask.setAssignee("${assigneeName}");
|
||||
// 设置多实例属性
|
||||
userTask.setLoopCharacteristics(multiInstanceLoopCharacteristics);
|
||||
if(BpmFlowMultiMode.OR.getType().equals(mode.getType())){
|
||||
multiInstanceLoopCharacteristics.setCompletionCondition("${nrOfCompletedInstances/nrOfInstances > 0}");
|
||||
} else if (BpmFlowMultiMode.AND.getType().equals(mode.getType())){
|
||||
multiInstanceLoopCharacteristics.setCompletionCondition("${nrOfInstances == nrOfCompletedInstances}");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return id;
|
||||
}
|
||||
}
|
||||
|
||||
@ -0,0 +1,23 @@
|
||||
package cn.axzo.workflow.core.deletege;
|
||||
|
||||
import lombok.Data;
|
||||
import org.flowable.common.engine.api.FlowableObjectNotFoundException;
|
||||
import org.flowable.identitylink.api.IdentityLink;
|
||||
import org.flowable.identitylink.api.IdentityLinkType;
|
||||
import org.flowable.task.api.DelegationState;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Date;
|
||||
import java.util.Set;
|
||||
|
||||
@Data
|
||||
public class BpmTaskCalculateDTO {
|
||||
|
||||
private String taskId;
|
||||
private String taskName;
|
||||
private String processDefinitionId;
|
||||
private String processInstanceId;
|
||||
private String taskDefinitionKey;
|
||||
private String category;
|
||||
private String tenantId;
|
||||
}
|
||||
@ -5,5 +5,5 @@ import org.flowable.task.service.delegate.DelegateTask;
|
||||
import java.util.List;
|
||||
|
||||
public interface BpmTaskDelegate {
|
||||
List<BpmTaskDelegateAssigner> calculateAssignerAtExecution(DelegateTask delegateTask);
|
||||
List<BpmTaskDelegateAssigner> calculateAssignerAtExecution(BpmTaskCalculateDTO delegateTask);
|
||||
}
|
||||
|
||||
@ -2,9 +2,8 @@ package cn.axzo.workflow.core.service;
|
||||
|
||||
import cn.axzo.workflow.core.service.dto.response.process.BpmProcessInstanceVO;
|
||||
import cn.axzo.workflow.core.service.dto.request.process.BpmProcessInstanceCreateDTO;
|
||||
import cn.axzo.workflow.core.service.dto.response.process.BpmProcessInstanceWithdrawDTO;
|
||||
import cn.axzo.workflow.core.service.dto.request.process.BpmProcessInstanceWithdrawDTO;
|
||||
import org.flowable.engine.history.HistoricProcessInstance;
|
||||
import org.flowable.engine.repository.ProcessDefinition;
|
||||
import org.flowable.engine.runtime.ProcessInstance;
|
||||
|
||||
public interface BpmProcessInstanceService {
|
||||
|
||||
@ -1,10 +1,14 @@
|
||||
package cn.axzo.workflow.core.service.dto;
|
||||
|
||||
import cn.axzo.workflow.core.common.enums.BpmFlowNodeType;
|
||||
import cn.axzo.workflow.core.service.dto.request.BpmJsonNodeProperty;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@Data
|
||||
public class BpmJsonNode {
|
||||
|
||||
@ApiModelProperty(value = "节点ID", required = true)
|
||||
@ -25,6 +29,11 @@ public class BpmJsonNode {
|
||||
private BpmJsonNode children;
|
||||
@ApiModelProperty(value = "分支节点信息", required = true)
|
||||
private List<BpmJsonNode> branches;
|
||||
private BpmJsonNodeProperty property;
|
||||
|
||||
/*自己使用,不需要外界传*/
|
||||
private Map incoming;
|
||||
|
||||
|
||||
public BpmJsonNode() {
|
||||
}
|
||||
@ -84,4 +93,8 @@ public class BpmJsonNode {
|
||||
public void setBranches(List<BpmJsonNode> branches) {
|
||||
this.branches = branches;
|
||||
}
|
||||
|
||||
class properties {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@ -0,0 +1,35 @@
|
||||
package cn.axzo.workflow.core.service.dto.request;
|
||||
|
||||
import cn.axzo.workflow.core.common.enums.BpmFlowMultiMode;
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class BpmJsonNodeProperty {
|
||||
|
||||
/**
|
||||
* 是否是多实例节点;
|
||||
* */
|
||||
private Boolean isMultiTask;
|
||||
|
||||
/**
|
||||
* 多实例模式;OR:"或签",AND:"会签"
|
||||
* */
|
||||
private BpmFlowMultiMode multiMode;
|
||||
|
||||
/**
|
||||
* 条件节点中是否是默认分支
|
||||
* */
|
||||
private Boolean defaultCondition;
|
||||
|
||||
/**
|
||||
* 条件分支的Key
|
||||
* */
|
||||
private String conditionKey;
|
||||
|
||||
/**
|
||||
* 当ConditionKey的值是多少,走该分支
|
||||
* */
|
||||
private Integer conditionBranchValue;
|
||||
|
||||
|
||||
}
|
||||
@ -1,4 +1,4 @@
|
||||
package cn.axzo.workflow.core.service.dto.response.process;
|
||||
package cn.axzo.workflow.core.service.dto.request.process;
|
||||
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
@ -0,0 +1,54 @@
|
||||
package cn.axzo.workflow.core.service.engine;
|
||||
|
||||
import cn.axzo.workflow.core.deletege.BpmTaskCalculateDTO;
|
||||
import cn.axzo.workflow.core.deletege.BpmTaskDelegate;
|
||||
import cn.axzo.workflow.core.deletege.BpmTaskDelegateAssigner;
|
||||
import org.flowable.bpmn.model.Process;
|
||||
import org.flowable.bpmn.model.UserTask;
|
||||
import org.flowable.engine.RepositoryService;
|
||||
import org.flowable.engine.delegate.DelegateExecution;
|
||||
import org.flowable.engine.delegate.ExecutionListener;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 在这里设置审批人
|
||||
* */
|
||||
@Component
|
||||
public class EngineExecutionStartListener implements ExecutionListener {
|
||||
@Resource
|
||||
private RepositoryService repositoryService;
|
||||
@Resource
|
||||
private BpmTaskDelegate bpmTaskDelegate;
|
||||
@Override
|
||||
public void notify(DelegateExecution execution) {
|
||||
String currentActivityId = execution.getCurrentActivityId();
|
||||
Process mainProcess = repositoryService.getBpmnModel(execution.getProcessDefinitionId()).getMainProcess();
|
||||
UserTask userTask = (UserTask) mainProcess.getFlowElement(currentActivityId);
|
||||
|
||||
String variable=currentActivityId+"assigneeList";
|
||||
List usersValue = (List) execution.getVariable(variable);
|
||||
if(usersValue==null){
|
||||
|
||||
BpmTaskCalculateDTO calculateDTO = new BpmTaskCalculateDTO();
|
||||
calculateDTO.setTaskId(userTask.getId());
|
||||
calculateDTO.setCategory(userTask.getCategory());
|
||||
calculateDTO.setProcessDefinitionId(execution.getProcessDefinitionId());
|
||||
calculateDTO.setProcessInstanceId(execution.getProcessInstanceId());
|
||||
calculateDTO.setTaskName(userTask.getName());
|
||||
calculateDTO.setTenantId(execution.getTenantId());
|
||||
calculateDTO.setTaskDefinitionKey(currentActivityId);
|
||||
|
||||
List<BpmTaskDelegateAssigner> assigners = bpmTaskDelegate.calculateAssignerAtExecution(calculateDTO);
|
||||
|
||||
List<String> assigneeIdList= new ArrayList<>();
|
||||
for (BpmTaskDelegateAssigner user : assigners) {
|
||||
assigneeIdList.add(user.getAssignerId());
|
||||
}
|
||||
execution.setVariable(variable,assigneeIdList);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -5,7 +5,6 @@ import cn.axzo.workflow.core.common.enums.BpmProcessInstanceResultEnum;
|
||||
import cn.axzo.workflow.core.common.enums.BpmProcessInstanceStatusEnum;
|
||||
import cn.axzo.workflow.core.common.exception.WorkflowEngineException;
|
||||
import cn.axzo.workflow.core.common.utils.BpmCollectionUtils;
|
||||
import cn.axzo.workflow.core.repository.entity.BpmProcessDefinitionExtDO;
|
||||
import cn.axzo.workflow.core.repository.entity.BpmProcessInstanceExtDO;
|
||||
import cn.axzo.workflow.core.repository.mapper.BpmProcessInstanceExtMapper;
|
||||
import cn.axzo.workflow.core.service.dto.response.process.BpmProcessInstanceVO;
|
||||
@ -13,14 +12,11 @@ import cn.axzo.workflow.core.service.BpmProcessDefinitionService;
|
||||
import cn.axzo.workflow.core.service.BpmProcessInstanceService;
|
||||
import cn.axzo.workflow.core.service.BpmTaskService;
|
||||
import cn.axzo.workflow.core.service.dto.request.process.BpmProcessInstanceCreateDTO;
|
||||
import cn.axzo.framework.domain.web.BizException;
|
||||
import cn.axzo.workflow.core.service.dto.response.process.BpmProcessInstanceWithdrawDTO;
|
||||
import cn.axzo.workflow.core.service.dto.request.process.BpmProcessInstanceWithdrawDTO;
|
||||
import cn.azxo.framework.common.utils.StringUtils;
|
||||
import cn.hutool.core.lang.Assert;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.collections4.CollectionUtils;
|
||||
import org.flowable.common.engine.impl.identity.Authentication;
|
||||
import org.flowable.engine.*;
|
||||
import org.flowable.engine.history.HistoricProcessInstance;
|
||||
|
||||
@ -4,7 +4,7 @@ import cn.axzo.framework.jackson.utility.JSON;
|
||||
import cn.axzo.workflow.core.service.BpmProcessInstanceService;
|
||||
import cn.axzo.workflow.core.service.dto.request.process.BpmProcessInstanceCreateDTO;
|
||||
import cn.axzo.workflow.core.service.dto.response.process.BpmProcessInstanceVO;
|
||||
import cn.axzo.workflow.core.service.dto.response.process.BpmProcessInstanceWithdrawDTO;
|
||||
import cn.axzo.workflow.core.service.dto.request.process.BpmProcessInstanceWithdrawDTO;
|
||||
import cn.azxo.framework.common.model.CommonResponse;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.flowable.engine.history.HistoricProcessInstance;
|
||||
|
||||
575
workflow-engine-server/src/main/resources/bpmjson
Normal file
575
workflow-engine-server/src/main/resources/bpmjson
Normal file
@ -0,0 +1,575 @@
|
||||
{
|
||||
"id":"root",
|
||||
"desc":"任何人",
|
||||
"name":"发起人",
|
||||
"type":"ROOT",
|
||||
"props":{
|
||||
"formPerms":[
|
||||
{
|
||||
"id":"field6315293116649",
|
||||
"perm":"E",
|
||||
"title":"单行文本输入",
|
||||
"required":false
|
||||
},
|
||||
{
|
||||
"id":"field2424440922220",
|
||||
"perm":"E",
|
||||
"title":"单行文本输入1",
|
||||
"required":false
|
||||
},
|
||||
{
|
||||
"id":"field3654540926170",
|
||||
"perm":"E",
|
||||
"title":"日期时间点",
|
||||
"required":false
|
||||
},
|
||||
{
|
||||
"id":"field6931940950104",
|
||||
"perm":"E",
|
||||
"title":"多选框",
|
||||
"required":false
|
||||
},
|
||||
{
|
||||
"id":"field8821740927538",
|
||||
"perm":"E",
|
||||
"title":"日期时间区间",
|
||||
"required":false
|
||||
},
|
||||
{
|
||||
"id":"field5416940932938",
|
||||
"perm":"E",
|
||||
"title":"说明文字",
|
||||
"required":false
|
||||
},
|
||||
{
|
||||
"id":"field1905040930820",
|
||||
"perm":"E",
|
||||
"title":"部门选择",
|
||||
"required":false
|
||||
},
|
||||
{
|
||||
"id":"field6136640929087",
|
||||
"perm":"E",
|
||||
"title":"上传图片",
|
||||
"required":false
|
||||
}
|
||||
],
|
||||
"assignedUser":[
|
||||
{
|
||||
"id":231535,
|
||||
"name":"生产管理部",
|
||||
"type":"dept",
|
||||
"selected":false
|
||||
},
|
||||
{
|
||||
"id":4319868,
|
||||
"name":"销售服务部",
|
||||
"type":"dept",
|
||||
"selected":false
|
||||
}
|
||||
]
|
||||
},
|
||||
"children":{
|
||||
"id":"node_598263651142",
|
||||
"name":"审批人",
|
||||
"type":"APPROVAL",
|
||||
"props":{
|
||||
"mode":"AND",
|
||||
"role":[
|
||||
|
||||
],
|
||||
"sign":false,
|
||||
"leader":{
|
||||
"level":1
|
||||
},
|
||||
"nobody":{
|
||||
"handler":"TO_PASS",
|
||||
"assignedUser":[
|
||||
|
||||
]
|
||||
},
|
||||
"refuse":{
|
||||
"type":"TO_END",
|
||||
"target":""
|
||||
},
|
||||
"formUser":"",
|
||||
"formPerms":[
|
||||
{
|
||||
"id":"field6315293116649",
|
||||
"perm":"R",
|
||||
"title":"单行文本输入",
|
||||
"required":false
|
||||
},
|
||||
{
|
||||
"id":"field2424440922220",
|
||||
"perm":"R",
|
||||
"title":"单行文本输入1",
|
||||
"required":false
|
||||
},
|
||||
{
|
||||
"id":"field3654540926170",
|
||||
"perm":"R",
|
||||
"title":"日期时间点",
|
||||
"required":false
|
||||
},
|
||||
{
|
||||
"id":"field6931940950104",
|
||||
"perm":"R",
|
||||
"title":"多选框",
|
||||
"required":false
|
||||
},
|
||||
{
|
||||
"id":"field8821740927538",
|
||||
"perm":"R",
|
||||
"title":"日期时间区间",
|
||||
"required":false
|
||||
},
|
||||
{
|
||||
"id":"field5416940932938",
|
||||
"perm":"R",
|
||||
"title":"说明文字",
|
||||
"required":false
|
||||
},
|
||||
{
|
||||
"id":"field1905040930820",
|
||||
"perm":"R",
|
||||
"title":"部门选择",
|
||||
"required":false
|
||||
},
|
||||
{
|
||||
"id":"field6136640929087",
|
||||
"perm":"R",
|
||||
"title":"上传图片",
|
||||
"required":false
|
||||
}
|
||||
],
|
||||
"leaderTop":{
|
||||
"endLevel":1,
|
||||
"endCondition":"TOP"
|
||||
},
|
||||
"timeLimit":{
|
||||
"handler":{
|
||||
"type":"REFUSE",
|
||||
"notify":{
|
||||
"hour":1,
|
||||
"once":true
|
||||
}
|
||||
},
|
||||
"timeout":{
|
||||
"unit":"H",
|
||||
"value":0
|
||||
}
|
||||
},
|
||||
"selfSelect":{
|
||||
"multiple":false
|
||||
},
|
||||
"assignedType":"LEADER",
|
||||
"assignedUser":[
|
||||
{
|
||||
"id":61769798,
|
||||
"name":"李四",
|
||||
"type":"user",
|
||||
"selected":true
|
||||
}
|
||||
]
|
||||
},
|
||||
"children":{
|
||||
"id":"node_698816342966",
|
||||
"name":"审批人",
|
||||
"type":"APPROVAL",
|
||||
"props":{
|
||||
"mode":"OR",
|
||||
"role":[
|
||||
|
||||
],
|
||||
"sign":false,
|
||||
"leader":{
|
||||
"level":1
|
||||
},
|
||||
"nobody":{
|
||||
"handler":"TO_PASS",
|
||||
"assignedUser":[
|
||||
|
||||
]
|
||||
},
|
||||
"refuse":{
|
||||
"type":"TO_END",
|
||||
"target":""
|
||||
},
|
||||
"formUser":"",
|
||||
"formPerms":[
|
||||
{
|
||||
"id":"field6315293116649",
|
||||
"perm":"R",
|
||||
"title":"单行文本输入",
|
||||
"required":false
|
||||
},
|
||||
{
|
||||
"id":"field2424440922220",
|
||||
"perm":"R",
|
||||
"title":"单行文本输入1",
|
||||
"required":false
|
||||
},
|
||||
{
|
||||
"id":"field3654540926170",
|
||||
"perm":"R",
|
||||
"title":"日期时间点",
|
||||
"required":false
|
||||
},
|
||||
{
|
||||
"id":"field6931940950104",
|
||||
"perm":"R",
|
||||
"title":"多选框",
|
||||
"required":false
|
||||
},
|
||||
{
|
||||
"id":"field8821740927538",
|
||||
"perm":"R",
|
||||
"title":"日期时间区间",
|
||||
"required":false
|
||||
},
|
||||
{
|
||||
"id":"field5416940932938",
|
||||
"perm":"R",
|
||||
"title":"说明文字",
|
||||
"required":false
|
||||
},
|
||||
{
|
||||
"id":"field1905040930820",
|
||||
"perm":"R",
|
||||
"title":"部门选择",
|
||||
"required":false
|
||||
},
|
||||
{
|
||||
"id":"field6136640929087",
|
||||
"perm":"R",
|
||||
"title":"上传图片",
|
||||
"required":false
|
||||
}
|
||||
],
|
||||
"leaderTop":{
|
||||
"endLevel":1,
|
||||
"endCondition":"TOP"
|
||||
},
|
||||
"timeLimit":{
|
||||
"handler":{
|
||||
"type":"REFUSE",
|
||||
"notify":{
|
||||
"hour":1,
|
||||
"once":true
|
||||
}
|
||||
},
|
||||
"timeout":{
|
||||
"unit":"H",
|
||||
"value":0
|
||||
}
|
||||
},
|
||||
"selfSelect":{
|
||||
"multiple":true
|
||||
},
|
||||
"assignedType":"SELF_SELECT",
|
||||
"assignedUser":[
|
||||
|
||||
]
|
||||
},
|
||||
"children":{
|
||||
"id":"node_905097096913",
|
||||
"name":"条件分支",
|
||||
"type":"CONDITIONS",
|
||||
"props":{
|
||||
|
||||
},
|
||||
"branchs":[
|
||||
{
|
||||
"id":"node_905097097011",
|
||||
"name":"条件1",
|
||||
"type":"CONDITION",
|
||||
"props":{
|
||||
"groups":[
|
||||
{
|
||||
"cids":[
|
||||
"root"
|
||||
],
|
||||
"groupType":"AND",
|
||||
"conditions":[
|
||||
{
|
||||
"id":"root",
|
||||
"title":"发起人",
|
||||
"value":[
|
||||
{
|
||||
"id":381496,
|
||||
"name":"旅人",
|
||||
"type":"user",
|
||||
"selected":false
|
||||
}
|
||||
],
|
||||
"compare":"",
|
||||
"valueType":"User"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"expression":"",
|
||||
"groupsType":"AND"
|
||||
},
|
||||
"children":{
|
||||
"id":"node_275574083794",
|
||||
"name":"审批人",
|
||||
"type":"APPROVAL",
|
||||
"props":{
|
||||
"mode":"AND",
|
||||
"role":[
|
||||
|
||||
],
|
||||
"sign":false,
|
||||
"leader":{
|
||||
"level":1
|
||||
},
|
||||
"nobody":{
|
||||
"handler":"TO_PASS",
|
||||
"assignedUser":[
|
||||
|
||||
]
|
||||
},
|
||||
"refuse":{
|
||||
"type":"TO_END",
|
||||
"target":""
|
||||
},
|
||||
"formUser":"",
|
||||
"formPerms":[
|
||||
{
|
||||
"id":"field6315293116649",
|
||||
"perm":"R",
|
||||
"title":"单行文本输入",
|
||||
"required":false
|
||||
},
|
||||
{
|
||||
"id":"field2424440922220",
|
||||
"perm":"R",
|
||||
"title":"单行文本输入1",
|
||||
"required":false
|
||||
},
|
||||
{
|
||||
"id":"field3654540926170",
|
||||
"perm":"R",
|
||||
"title":"日期时间点",
|
||||
"required":false
|
||||
},
|
||||
{
|
||||
"id":"field6931940950104",
|
||||
"perm":"R",
|
||||
"title":"多选框",
|
||||
"required":false
|
||||
},
|
||||
{
|
||||
"id":"field8821740927538",
|
||||
"perm":"R",
|
||||
"title":"日期时间区间",
|
||||
"required":false
|
||||
},
|
||||
{
|
||||
"id":"field5416940932938",
|
||||
"perm":"R",
|
||||
"title":"说明文字",
|
||||
"required":false
|
||||
},
|
||||
{
|
||||
"id":"field1905040930820",
|
||||
"perm":"R",
|
||||
"title":"部门选择",
|
||||
"required":false
|
||||
},
|
||||
{
|
||||
"id":"field6136640929087",
|
||||
"perm":"R",
|
||||
"title":"上传图片",
|
||||
"required":false
|
||||
}
|
||||
],
|
||||
"leaderTop":{
|
||||
"endLevel":1,
|
||||
"endCondition":"TOP"
|
||||
},
|
||||
"timeLimit":{
|
||||
"handler":{
|
||||
"type":"REFUSE",
|
||||
"notify":{
|
||||
"hour":1,
|
||||
"once":true
|
||||
}
|
||||
},
|
||||
"timeout":{
|
||||
"unit":"H",
|
||||
"value":0
|
||||
}
|
||||
},
|
||||
"selfSelect":{
|
||||
"multiple":false
|
||||
},
|
||||
"assignedType":"LEADER",
|
||||
"assignedUser":[
|
||||
|
||||
]
|
||||
},
|
||||
"children":{
|
||||
|
||||
},
|
||||
"parentId":"node_905097097011"
|
||||
},
|
||||
"parentId":"node_905097096913"
|
||||
},
|
||||
{
|
||||
"id":"node_905097094019",
|
||||
"name":"条件2",
|
||||
"type":"CONDITION",
|
||||
"props":{
|
||||
"groups":[
|
||||
{
|
||||
"cids":[
|
||||
"root"
|
||||
],
|
||||
"groupType":"AND",
|
||||
"conditions":[
|
||||
{
|
||||
"id":"root",
|
||||
"title":"发起人",
|
||||
"value":[
|
||||
{
|
||||
"id":381496,
|
||||
"name":"旅人",
|
||||
"type":"user",
|
||||
"selected":false
|
||||
}
|
||||
],
|
||||
"compare":"",
|
||||
"valueType":"User"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"expression":"",
|
||||
"groupsType":"OR"
|
||||
},
|
||||
"children":{
|
||||
"id":"node_275658471060",
|
||||
"name":"审批人",
|
||||
"type":"APPROVAL",
|
||||
"props":{
|
||||
"mode":"AND",
|
||||
"role":[
|
||||
|
||||
],
|
||||
"sign":false,
|
||||
"leader":{
|
||||
"level":1
|
||||
},
|
||||
"nobody":{
|
||||
"handler":"TO_PASS",
|
||||
"assignedUser":[
|
||||
|
||||
]
|
||||
},
|
||||
"refuse":{
|
||||
"type":"TO_END",
|
||||
"target":""
|
||||
},
|
||||
"formUser":"",
|
||||
"formPerms":[
|
||||
{
|
||||
"id":"field6315293116649",
|
||||
"perm":"R",
|
||||
"title":"单行文本输入",
|
||||
"required":false
|
||||
},
|
||||
{
|
||||
"id":"field2424440922220",
|
||||
"perm":"R",
|
||||
"title":"单行文本输入1",
|
||||
"required":false
|
||||
},
|
||||
{
|
||||
"id":"field3654540926170",
|
||||
"perm":"R",
|
||||
"title":"日期时间点",
|
||||
"required":false
|
||||
},
|
||||
{
|
||||
"id":"field6931940950104",
|
||||
"perm":"R",
|
||||
"title":"多选框",
|
||||
"required":false
|
||||
},
|
||||
{
|
||||
"id":"field8821740927538",
|
||||
"perm":"R",
|
||||
"title":"日期时间区间",
|
||||
"required":false
|
||||
},
|
||||
{
|
||||
"id":"field5416940932938",
|
||||
"perm":"R",
|
||||
"title":"说明文字",
|
||||
"required":false
|
||||
},
|
||||
{
|
||||
"id":"field1905040930820",
|
||||
"perm":"R",
|
||||
"title":"部门选择",
|
||||
"required":false
|
||||
},
|
||||
{
|
||||
"id":"field6136640929087",
|
||||
"perm":"R",
|
||||
"title":"上传图片",
|
||||
"required":false
|
||||
}
|
||||
],
|
||||
"leaderTop":{
|
||||
"endLevel":1,
|
||||
"endCondition":"TOP"
|
||||
},
|
||||
"timeLimit":{
|
||||
"handler":{
|
||||
"type":"REFUSE",
|
||||
"notify":{
|
||||
"hour":1,
|
||||
"once":true
|
||||
}
|
||||
},
|
||||
"timeout":{
|
||||
"unit":"H",
|
||||
"value":0
|
||||
}
|
||||
},
|
||||
"selfSelect":{
|
||||
"multiple":false
|
||||
},
|
||||
"assignedType":"SELF_SELECT",
|
||||
"assignedUser":[
|
||||
|
||||
]
|
||||
},
|
||||
"children":{
|
||||
|
||||
},
|
||||
"parentId":"node_905097094019"
|
||||
},
|
||||
"parentId":"node_905097096913"
|
||||
}
|
||||
],
|
||||
"children":{
|
||||
"id":"node_905097099172",
|
||||
"type":"EMPTY",
|
||||
"children":{
|
||||
|
||||
},
|
||||
"parentId":"node_905097096913"
|
||||
},
|
||||
"parentId":"node_698816342966"
|
||||
},
|
||||
"parentId":"node_598263651142"
|
||||
},
|
||||
"parentId":"root"
|
||||
},
|
||||
"parentId":null
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user