update - 完善 BPMN 协议 JSON 转换功能

This commit is contained in:
wangli 2023-11-15 15:40:20 +08:00
parent e29b94cd0c
commit 26894bb889
11 changed files with 1345 additions and 64 deletions

View File

@ -0,0 +1,47 @@
package cn.axzo.workflow.common.model.dto;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;
import java.util.List;
/**
* 组织架构人员选择器
* 协同组织列表的限制条件
*
* @author tanjie@axzo.cn
* @date 2023/11/14 11:29
*/
@Data
@Accessors(chain = true)
@NoArgsConstructor
@AllArgsConstructor
public class CooperationOrgDTO {
/**
* 企业组织架构
*/
private List<OrgScope> entOrg;
/**
* 项目部工作台
*/
private Long projWorkspaceId;
/**
* 参与项目部工作台的指定单位
*/
private List<Long> projOuId;
@Data
@Accessors(chain = true)
@NoArgsConstructor
@AllArgsConstructor
public static class OrgScope {
private Long workspaceId;
private Long ouId;
}
}

View File

@ -51,40 +51,3 @@ public class BpmnFieldConf {
private List<BpmnFieldOptionConf> options;
}
/**
* 单选/多选的选项配置
*/
@Accessors(chain = true)
@Data
@NoArgsConstructor
class BpmnFieldOptionConf {
/**
* 选项的名称
*/
@ApiModelProperty(value = "选项的名称", example = "选项1")
@NotBlank(message = "选项的名称不能为空")
private String name;
/**
* 选项的值
*/
@ApiModelProperty(value = "选项的值", example = "1")
@NotBlank(message = "选项的值不能为空")
private String value;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
}

View File

@ -0,0 +1,47 @@
package cn.axzo.workflow.common.model.request.bpmn;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;
import javax.validation.constraints.NotBlank;
/**
* 单选/多选的选项配置
*/
@Accessors(chain = true)
@Data
@NoArgsConstructor
public class BpmnFieldOptionConf {
/**
* 选项的名称
*/
@ApiModelProperty(value = "选项的名称", example = "选项1")
@NotBlank(message = "选项的名称不能为空")
private String name;
/**
* 选项的值
*/
@ApiModelProperty(value = "选项的值", example = "1")
@NotBlank(message = "选项的值不能为空")
private String value;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
}

View File

@ -90,7 +90,7 @@ public class BpmnJsonNodeProperty {
* 按钮权限
*/
@ApiModelProperty(value = "发起人节点/任务节点: 按钮权限集合")
private List<BpmnButtonConf> buttonPermission;
private BpmnButtonConf buttonPermission;
//************* 条件节点Start **************//

View File

@ -1,11 +1,13 @@
package cn.axzo.workflow.common.model.request.bpmn.process;
import cn.axzo.workflow.common.model.dto.CooperationOrgDTO;
import cn.axzo.workflow.common.model.request.bpmn.task.BpmnTaskDelegateAssigner;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;
import java.util.HashMap;
import java.util.Map;
@ -31,6 +33,13 @@ public class BpmnProcessInstanceCreateDTO {
*/
private Map<String, Object> variables = new HashMap<>();
/**
* 组织关系
*/
@ApiModelProperty(value = "组织关系")
@NotNull(message = "组织关系不能为空")
private CooperationOrgDTO cooperationOrg;
/**
* 业务的唯一标识
* <p>

View File

@ -1,27 +1,66 @@
package cn.axzo.workflow.core.common.utils;
import cn.axzo.workflow.common.model.request.bpmn.*;
import cn.axzo.workflow.common.model.request.bpmn.BpmnButtonConf;
import cn.axzo.workflow.common.model.request.bpmn.BpmnButtonMetaInfo;
import cn.axzo.workflow.common.model.request.bpmn.BpmnFieldConf;
import cn.axzo.workflow.common.model.request.bpmn.BpmnJsonNode;
import cn.axzo.workflow.common.model.request.bpmn.BpmnNoticeConf;
import cn.axzo.workflow.common.model.request.bpmn.model.BpmnModelCreateDTO;
import cn.axzo.workflow.core.common.exception.WorkflowEngineException;
import cn.axzo.workflow.core.converter.json.*;
import cn.axzo.workflow.core.converter.json.AbstractBpmnJsonConverter;
import cn.axzo.workflow.core.converter.json.EndEventJsonConverter;
import cn.axzo.workflow.core.converter.json.ExclusiveGatewayJsonConverter;
import cn.axzo.workflow.core.converter.json.NotSupportConverter;
import cn.axzo.workflow.core.converter.json.ParallelGatewayJsonConverter;
import cn.axzo.workflow.core.converter.json.ReceiveTaskJsonConverter;
import cn.axzo.workflow.core.converter.json.SequenceFlowJsonConverter;
import cn.axzo.workflow.core.converter.json.ServiceTaskJsonConverter;
import cn.axzo.workflow.core.converter.json.StartEventJsonConverter;
import cn.axzo.workflow.core.converter.json.UserTaskJsonConverter;
import com.alibaba.fastjson.JSON;
import com.google.common.collect.Lists;
import org.flowable.bpmn.BpmnAutoLayout;
import org.flowable.bpmn.converter.BpmnXMLConverter;
import org.flowable.bpmn.model.BaseElement;
import org.flowable.bpmn.model.BpmnModel;
import org.flowable.bpmn.model.EndEvent;
import org.flowable.bpmn.model.ExclusiveGateway;
import org.flowable.bpmn.model.ExtensionAttribute;
import org.flowable.bpmn.model.ExtensionElement;
import org.flowable.bpmn.model.FlowElement;
import org.flowable.bpmn.model.Gateway;
import org.flowable.bpmn.model.ParallelGateway;
import org.flowable.bpmn.model.Process;
import org.flowable.bpmn.model.*;
import org.flowable.bpmn.model.ReceiveTask;
import org.flowable.bpmn.model.SequenceFlow;
import org.flowable.bpmn.model.ServiceTask;
import org.flowable.bpmn.model.StartEvent;
import org.flowable.bpmn.model.UserTask;
import org.flowable.image.ProcessDiagramGenerator;
import org.flowable.image.impl.DefaultProcessDiagramGenerator;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.*;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.UUID;
import static cn.axzo.workflow.common.constant.BpmnConstants.*;
import static cn.axzo.workflow.common.constant.BpmnConstants.END_EVENT_ID;
import static cn.axzo.workflow.common.constant.BpmnConstants.FLOW_NODE_JSON;
import static cn.axzo.workflow.common.constant.BpmnConstants.SEQUENCE_FLOW_ID;
import static cn.axzo.workflow.common.constant.BpmnConstants.START_EVENT_ID;
import static cn.axzo.workflow.common.enums.BpmnFlowNodeType.NODE_EMPTY;
import static cn.axzo.workflow.core.common.enums.BpmnErrorCode.CONVERTOR_COMMON_ERROR;
@ -45,6 +84,7 @@ public class BpmnJsonConverterUtil {
converters.put(ParallelGateway.class, new ParallelGatewayJsonConverter());
converters.put(UserTask.class, new UserTaskJsonConverter());
converters.put(ServiceTask.class, new ServiceTaskJsonConverter());
converters.put(ReceiveTask.class, new ReceiveTaskJsonConverter());
}
/**
@ -86,9 +126,11 @@ public class BpmnJsonConverterUtil {
mainProcess.setDocumentation(documentation);
mainProcess.addAttribute(extensionAttribute);
// 设置流程的通知管理配置
setProcessNoticeConfig(noticeConf, mainProcess);
// 设置流程的默认的按钮配置
setProcessButtonConfig(buttonConf, mainProcess);
// 设置流程的字段元数据配置
setProcessFieldConfig(fieldConf, mainProcess);
bpmnModel.addProcess(mainProcess);
@ -112,12 +154,56 @@ public class BpmnJsonConverterUtil {
}
private static void setProcessFieldConfig(List<BpmnFieldConf> fieldConf, Process mainProcess) {
// TODO
ExtensionElement fieldConfigElement = new ExtensionElement();
fieldConfigElement.setName("fieldConfig");
if (!CollectionUtils.isEmpty(fieldConf)) {
fieldConf.forEach(i -> {
ExtensionElement field = new ExtensionElement();
field.setName("filed");
ExtensionAttribute fieldDataType = new ExtensionAttribute();
fieldDataType.setName("type");
fieldDataType.setValue(i.getType());
field.addAttribute(fieldDataType);
ExtensionAttribute fieldName = new ExtensionAttribute();
fieldName.setName("name");
fieldName.setValue(i.getName());
field.addAttribute(fieldName);
ExtensionAttribute fieldCode = new ExtensionAttribute();
fieldCode.setName("code");
fieldCode.setValue(i.getCode());
field.addAttribute(fieldCode);
if (!CollectionUtils.isEmpty(i.getOptions())) {
i.getOptions().forEach(j -> {
ExtensionElement option = new ExtensionElement();
option.setName("option");
ExtensionAttribute optionName = new ExtensionAttribute();
optionName.setName("name");
optionName.setValue(j.getName());
option.addAttribute(optionName);
ExtensionAttribute optionValue = new ExtensionAttribute();
optionValue.setName("value");
optionValue.setValue(j.getValue());
option.addAttribute(optionValue);
field.addChildElement(option);
});
}
fieldConfigElement.addChildElement(field);
});
}
mainProcess.addExtensionElement(fieldConfigElement);
}
private static void setProcessButtonConfig(BpmnButtonConf buttonConf, Process mainProcess) {
ExtensionElement buttonConfigElement = new ExtensionElement();
buttonConfigElement.setName("buttonConfigElement");
buttonConfigElement.setName("buttonConfig");
buildMetaButton(buttonConf.getInitiator(), "initiator", buttonConfigElement);
buildMetaButton(buttonConf.getCurrent(), "current", buttonConfigElement);
@ -127,7 +213,7 @@ public class BpmnJsonConverterUtil {
mainProcess.addExtensionElement(buttonConfigElement);
}
private static void buildMetaButton(List<BpmnButtonMetaInfo> buttonMetaInfos, String buttonType,
public static void buildMetaButton(List<BpmnButtonMetaInfo> buttonMetaInfos, String buttonType,
ExtensionElement buttonConfigElement) {
if (!CollectionUtils.isEmpty(buttonMetaInfos)) {
ExtensionElement initiator = new ExtensionElement();
@ -135,11 +221,15 @@ public class BpmnJsonConverterUtil {
buttonMetaInfos.forEach(i -> {
ExtensionElement button = new ExtensionElement();
button.setName(i.getBtnKey());
ExtensionAttribute attribute = new ExtensionAttribute();
attribute.setName("name");
attribute.setValue(i.getBtnName());
button.addAttribute(attribute);
button.setElementText(String.valueOf(i.getEnabled()));
ExtensionAttribute nameAttribute = new ExtensionAttribute();
nameAttribute.setName("name");
nameAttribute.setValue(i.getBtnName());
button.addAttribute(nameAttribute);
ExtensionAttribute valueAttribute = new ExtensionAttribute();
valueAttribute.setName("value");
valueAttribute.setValue(String.valueOf(i.getEnabled()));
button.addAttribute(valueAttribute);
initiator.addChildElement(button);
});
buttonConfigElement.addChildElement(initiator);
@ -148,7 +238,7 @@ public class BpmnJsonConverterUtil {
private static void setProcessNoticeConfig(BpmnNoticeConf noticeConf, Process mainProcess) {
ExtensionElement noticeConfigElement = new ExtensionElement();
noticeConfigElement.setName("noticeConfigElement");
noticeConfigElement.setName("noticeConfig");
// 通知消息模板配置
ExtensionElement noticeMessage = new ExtensionElement();
@ -223,7 +313,17 @@ public class BpmnJsonConverterUtil {
case NODE_CONDITION:
clz = SequenceFlow.class;
break;
case NODE_BUSINESS:
// "业务节点"是很特殊包装节点,因为它在前端有两种配法:
// 一种是: 可以不配置人, 当运行到该节点时, 需要由外部发送信号来触发(这个信号的发送方通常是程序应用), 流程继续运行.
// 另外一种是: 可以配置人, 当运行到该节点时, 有需要人为来处理. 这种情况下, 该节点就是一个普通的任务节点.
clz = ReceiveTask.class;
if (!Objects.equals("nobody", bpmnJsonNode.getProperty().getApprovalMethod())) {
clz = UserTask.class;
}
break;
case NODE_TRIGGER:
// 这个类型目前暂不支持
case NODE_CARBON_COPY:
// 这里可以细化, 带后续有实际场景了,再处理, 现目前只有 "抄送" 功能可能会用到
clz = ServiceTask.class;
@ -238,12 +338,15 @@ public class BpmnJsonConverterUtil {
// 通用链接当前节点和前一个节点的 SequenceFlow
if (preNodeIdList.size() > 1) {
// 如果涉及到网关,那么 incoming 就是大于 1
preNodeIdList.forEach(income -> {
Map<String, List<String>> tmpIncomeMap = new HashMap<>();
tmpIncomeMap.put("incoming", Lists.newArrayList(income));
bpmnJsonNode.setIncoming(tmpIncomeMap);
mainProcess.addFlowElement(convertJsonToElement(SequenceFlow.class, bpmnJsonNode, mainProcess));
});
preNodeIdList.stream()
// 过滤掉自己
.filter(income -> !Objects.equals(bpmnJsonNode.getId(), income))
.forEach(income -> {
Map<String, List<String>> tmpIncomeMap = new HashMap<>();
tmpIncomeMap.put("incoming", Lists.newArrayList(income));
bpmnJsonNode.setIncoming(tmpIncomeMap);
mainProcess.addFlowElement(convertJsonToElement(SequenceFlow.class, bpmnJsonNode, mainProcess));
});
} else {
FlowElement sequenceFlow = convertJsonToElement(SequenceFlow.class, bpmnJsonNode, mainProcess);
mainProcess.addFlowElement(sequenceFlow);
@ -264,9 +367,12 @@ public class BpmnJsonConverterUtil {
List<String> gatewayPreIds = new ArrayList<>();
if (!CollectionUtils.isEmpty(bpmnJsonNode.getBranches())) {
for (BpmnJsonNode branch : bpmnJsonNode.getBranches()) {
BpmnJsonNode children = branch.getChildren();
children.setPreJsonNode(branch);
gatewayPreIds.add(create(children, mainProcess, bpmnModel, flowElement.getId()));
BpmnJsonNode children = Objects.isNull(branch.getChildren()) ? bpmnJsonNode.getChildren() :
branch.getChildren();
if (Objects.nonNull(children)) {
children.setPreJsonNode(branch);
gatewayPreIds.add(create(children, mainProcess, bpmnModel, flowElement.getId()));
}
}
}
@ -329,6 +435,48 @@ public class BpmnJsonConverterUtil {
model.getButtonConf(), model.getFieldConf());
System.out.println("bpmnModel = " + bpmnModel);
transformBytes(bpmnModel);
generateImage(bpmnModel);
}
public static void generateImage(BpmnModel bpmnModel) {
String pngName = "/Users/wangli/work/company/yizhi/workflow-engine/workflow-engine-server/src/main" +
"/resources/test.png";
ProcessDiagramGenerator diagramGenerator = new DefaultProcessDiagramGenerator();
// 设置字体渲染选项
System.setProperty("java.awt.headless", "false");
System.setProperty("awt.useSystemAAFontSettings", "on");
System.setProperty("swing.aatext", "true");
System.setProperty("sun.java2d.xrender", "true");
try {
// 创建输出流
OutputStream outputStream = Files.newOutputStream(new File(pngName).toPath());
// 生成图像并写入输出流
InputStream imageStream = diagramGenerator.generateDiagram(bpmnModel, "png", new ArrayList<>(), 1.0d, true);
// 将图像流写入输出流
try {
byte[] buffer = new byte[1024];
int bytesRead;
while ((bytesRead = imageStream.read(buffer)) != -1) {
outputStream.write(buffer, 0, bytesRead);
}
} catch (Exception e) {
// 处理异常
} finally {
try {
imageStream.close();
outputStream.close();
} catch (Exception e) {
// 处理异常
}
}
// 关闭输出流
outputStream.close();
} catch (Exception e) {
// 处理异常
}
}
}

View File

@ -0,0 +1,25 @@
package cn.axzo.workflow.core.converter.json;
import cn.axzo.workflow.common.model.request.bpmn.BpmnJsonNode;
import org.flowable.bpmn.model.Process;
import org.flowable.bpmn.model.ReceiveTask;
/**
* 接收任务节点
*
* @author wangli
* @since 2023/10/13 17:01
*/
public class ReceiveTaskJsonConverter extends AbstractBpmnJsonConverter<ReceiveTask> {
@Override
public ReceiveTask convertJsonToElement(BpmnJsonNode node, Process process) {
ReceiveTask receiveTask = new ReceiveTask();
receiveTask.setId(node.getId());
receiveTask.setName(node.getName());
return receiveTask;
}
}

View File

@ -1,17 +1,23 @@
package cn.axzo.workflow.core.converter.json;
import cn.axzo.workflow.common.model.request.bpmn.BpmnButtonConf;
import cn.axzo.workflow.common.model.request.bpmn.BpmnJsonNode;
import cn.axzo.workflow.common.model.request.bpmn.BpmnJsonNodeProperty;
import org.flowable.bpmn.model.ExtensionAttribute;
import org.flowable.bpmn.model.ExtensionElement;
import org.flowable.bpmn.model.FlowableListener;
import org.flowable.bpmn.model.Process;
import org.flowable.bpmn.model.UserTask;
import org.flowable.engine.delegate.BaseExecutionListener;
import org.flowable.engine.delegate.TaskListener;
import org.springframework.util.StringUtils;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import static cn.axzo.workflow.common.enums.BpmnFlowNodeType.NODE_STARTER;
import static cn.axzo.workflow.core.common.utils.BpmnJsonConverterUtil.buildMetaButton;
import static org.flowable.bpmn.model.ImplementationType.IMPLEMENTATION_TYPE_DELEGATEEXPRESSION;
/**
@ -28,6 +34,14 @@ public class UserTaskJsonConverter extends AbstractBpmnJsonConverter<UserTask> {
userTask.setId(node.getId());
userTask.setName(node.getName());
// "设置审批人"
setApprovalExtensionElement(node, userTask);
// "权限设置"
setFieldExtensionElement(node, userTask);
// "高级设置"
setButtonExtensionElement(node, userTask);
setTaskListeners(userTask);
if (!Objects.equals(NODE_STARTER, node.getType())) {
@ -37,6 +51,118 @@ public class UserTaskJsonConverter extends AbstractBpmnJsonConverter<UserTask> {
return userTask;
}
private static void setButtonExtensionElement(BpmnJsonNode node, UserTask userTask) {
if (Objects.isNull(node.getProperty())) {
return;
}
BpmnButtonConf buttonConf = node.getProperty().getButtonPermission();
ExtensionElement buttonConfigElement = new ExtensionElement();
buttonConfigElement.setName("buttonConfig");
if (Objects.nonNull(buttonConf)) {
buildMetaButton(buttonConf.getInitiator(), "initiator", buttonConfigElement);
buildMetaButton(buttonConf.getCurrent(), "current", buttonConfigElement);
buildMetaButton(buttonConf.getHistory(), "history", buttonConfigElement);
buildMetaButton(buttonConf.getCarbonCopy(), "carbonCopy", buttonConfigElement);
}
userTask.addExtensionElement(buttonConfigElement);
}
private static void setFieldExtensionElement(BpmnJsonNode node, UserTask userTask) {
if (Objects.isNull(node.getProperty())) {
return;
}
ExtensionElement fieldElement = new ExtensionElement();
fieldElement.setName("fieldPermission");
fieldElement.setElementText(node.getProperty().getFieldPermission());
userTask.addExtensionElement(fieldElement);
}
private static void setApprovalExtensionElement(BpmnJsonNode node, UserTask userTask) {
BpmnJsonNodeProperty property = node.getProperty();
if (Objects.isNull(property)) {
return;
}
// 审批方式
ExtensionElement approvalMethodElement = new ExtensionElement();
approvalMethodElement.setName("approvalMethod");
ExtensionAttribute approvalMethodValueAttribute = new ExtensionAttribute();
approvalMethodValueAttribute.setName("value");
approvalMethodValueAttribute.setValue(property.getApprovalMethod());
approvalMethodElement.addAttribute(approvalMethodValueAttribute);
ExtensionAttribute approvalMethodDescAttribute = new ExtensionAttribute();
approvalMethodDescAttribute.setName("desc");
approvalMethodDescAttribute.setValue("审批方式");
approvalMethodElement.addAttribute(approvalMethodDescAttribute);
userTask.addExtensionElement(approvalMethodElement);
// 审批人所在范围
ExtensionElement approverScopeElement = new ExtensionElement();
approverScopeElement.setName("approverScope");
ExtensionAttribute approverScopeValueAttribute = new ExtensionAttribute();
approverScopeValueAttribute.setName("value");
approverScopeValueAttribute.setValue(property.getApproverScope());
approverScopeElement.addAttribute(approverScopeValueAttribute);
ExtensionAttribute approverScopeDescAttribute = new ExtensionAttribute();
approverScopeDescAttribute.setName("desc");
approverScopeDescAttribute.setValue("审批人所在范围");
approverScopeElement.addAttribute(approverScopeDescAttribute);
userTask.addExtensionElement(approverScopeElement);
// 审批人指定
ExtensionElement approverSpecifyElement = new ExtensionElement();
approverSpecifyElement.setName("approverSpecify");
ExtensionAttribute approverSpecifyValueAttribute = new ExtensionAttribute();
approverSpecifyValueAttribute.setName("value");
approverSpecifyValueAttribute.setValue(property.getApproverSpecify());
approverSpecifyElement.addAttribute(approverSpecifyValueAttribute);
ExtensionAttribute approverSpecifyDescAttribute = new ExtensionAttribute();
approverSpecifyDescAttribute.setName("desc");
approverSpecifyDescAttribute.setValue("审批人指定");
approverSpecifyElement.addAttribute(approverSpecifyDescAttribute);
// 审批人指定的具体值
approverSpecifyElement.setElementText(StringUtils.collectionToCommaDelimitedString(property.getSpecifyValue()));
userTask.addExtensionElement(approverSpecifyElement);
// 多人审批时审批模式
ExtensionElement approverModeTypeElement = new ExtensionElement();
approverModeTypeElement.setName("approverModeType");
ExtensionAttribute approverModeTypeValueAttribute = new ExtensionAttribute();
approverModeTypeValueAttribute.setName("value");
approverModeTypeValueAttribute.setValue(property.getMultiMode().getType());
approverModeTypeElement.addAttribute(approverModeTypeValueAttribute);
ExtensionAttribute approverModeTypeDescAttribute = new ExtensionAttribute();
approverModeTypeDescAttribute.setName("desc");
approverModeTypeDescAttribute.setValue("多人审批时审批模式");
approverModeTypeElement.addAttribute(approverModeTypeDescAttribute);
userTask.addExtensionElement(approverModeTypeElement);
// 审批人为空时
ExtensionElement approverEmptyHandleTypeElement = new ExtensionElement();
approverEmptyHandleTypeElement.setName("approverEmptyHandleType");
ExtensionAttribute approverEmptyHandleTypeValueAttribute = new ExtensionAttribute();
approverEmptyHandleTypeValueAttribute.setName("value");
approverEmptyHandleTypeValueAttribute.setValue(property.getApproverEmptyHandleType());
approverEmptyHandleTypeElement.addAttribute(approverEmptyHandleTypeValueAttribute);
ExtensionAttribute approverEmptyHandleTypeDescAttribute = new ExtensionAttribute();
approverEmptyHandleTypeDescAttribute.setName("desc");
approverEmptyHandleTypeDescAttribute.setValue("审批人为空时");
approverEmptyHandleTypeElement.addAttribute(approverEmptyHandleTypeDescAttribute);
userTask.addExtensionElement(approverEmptyHandleTypeElement);
}
/**
* 设置执行监听
*

View File

@ -107,6 +107,7 @@ public class BpmnProcessModelServiceImpl implements BpmnProcessModelService {
}
@Override
@Transactional(rollbackFor = Exception.class)
public String createBpmModel(@Valid BpmnModelCreateDTO dto) {
Model existModel = repositoryService.createModelQuery()
.modelKey(dto.getKey())

File diff suppressed because one or more lines are too long

View File

@ -229,7 +229,557 @@
"parentId": "0",
"type": "NODE_STARTER",
"name": "发起人",
"children": null,
"children": {
"id": "2",
"parentId": "1",
"type": "NODE_TASK",
"name": "一级审批",
"children": {
"id": "3",
"parentId": "2",
"type": "NODE_EXCLUSIVE_GATEWAY",
"name": "排它网关",
"children": {
"id": "11",
"parentId": "3",
"type": "NODE_CARBON_COPY",
"name": "主流程抄送节点",
"children": {
"id": "12",
"parentId": "3",
"type": "NODE_EMPTY",
"name": "结束",
"children": null,
"branches": null,
"property": null
},
"branches": null,
"property": null
},
"branches": [
{
"id": "4",
"parentId": "3",
"type": "NODE_CONDITION",
"name": "条件1",
"property": {
"groups": [
{
"conditionsType": "and",
"conditions": [
{
"fieldDataType": "string",
"fieldCode": "title",
"operator": "contains",
"defaultValue": "测试"
},
{
"fieldDataType": "number",
"fieldCode": "price",
"operator": "eq",
"defaultValue": "2"
}
]
}
],
"defaultBranch": false,
"groupsType": "and"
},
"children": {
"id": "7",
"parentId": "4",
"type": "NODE_TASK",
"name": "条件1审核节点",
"children": {
"id": "8",
"parentId": "7",
"type": "NODE_CARBON_COPY",
"name": "条件1抄送节点",
"children": null,
"property": null,
"branches": null
},
"property": {
"approvalMethod": "autoPassed",
"approverScope": "entWorkspace",
"approverSpecify": "position",
"specifyValue": [
"job1",
"job2"
],
"isMultiTask": "true",
"multiMode": "AND",
"approverEmptyHandleType": "autoPassed",
"fieldPermission": null,
"buttonPermission": {
"initiator": [
{
"btnKey": "BPMN_APPROVE",
"enabled": true,
"btnName": "同意"
},
{
"btnKey": "BPMN_REJECT",
"btnName": "拒绝",
"enabled": true
},
{
"btnKey": "BPMN_REVOCATION",
"btnName": "撤回",
"enabled": true
},
{
"btnKey": "BPMN_FORWARD",
"btnName": "转交",
"enabled": true
},
{
"btnKey": "BPMN_COUNTERSIGN",
"btnName": "加签",
"enabled": true
},
{
"btnKey": "BPMN_COMMENT",
"btnName": "评论",
"enabled": true
},
{
"btnKey": "BPMN_ROLLBACK",
"btnName": "回退",
"enabled": true
},
{
"btnKey": "BPMN_COPY",
"btnName": "抄送",
"enabled": true
}
],
"carbonCopy": [
{
"btnKey": "BPMN_APPROVE",
"enabled": true,
"btnName": "同意"
},
{
"btnKey": "BPMN_REJECT",
"btnName": "拒绝",
"enabled": true
},
{
"btnKey": "BPMN_REVOCATION",
"btnName": "撤回",
"enabled": true
},
{
"btnKey": "BPMN_FORWARD",
"btnName": "转交",
"enabled": true
},
{
"btnKey": "BPMN_COUNTERSIGN",
"btnName": "加签",
"enabled": true
},
{
"btnKey": "BPMN_COMMENT",
"btnName": "评论",
"enabled": true
},
{
"btnKey": "BPMN_ROLLBACK",
"btnName": "回退",
"enabled": true
},
{
"btnKey": "BPMN_COPY",
"btnName": "抄送",
"enabled": true
}
],
"history": [
{
"btnKey": "BPMN_APPROVE",
"enabled": true,
"btnName": "同意"
},
{
"btnKey": "BPMN_REJECT",
"btnName": "拒绝",
"enabled": true
},
{
"btnKey": "BPMN_REVOCATION",
"btnName": "撤回",
"enabled": true
},
{
"btnKey": "BPMN_FORWARD",
"btnName": "转交",
"enabled": true
},
{
"btnKey": "BPMN_COUNTERSIGN",
"btnName": "加签",
"enabled": true
},
{
"btnKey": "BPMN_COMMENT",
"btnName": "评论",
"enabled": true
},
{
"btnKey": "BPMN_ROLLBACK",
"btnName": "回退",
"enabled": true
},
{
"btnKey": "BPMN_COPY",
"btnName": "抄送",
"enabled": true
}
],
"current": [
{
"btnKey": "BPMN_APPROVE",
"enabled": true,
"btnName": "同意"
},
{
"btnKey": "BPMN_REJECT",
"btnName": "拒绝",
"enabled": true
},
{
"btnKey": "BPMN_REVOCATION",
"btnName": "撤回",
"enabled": true
},
{
"btnKey": "BPMN_FORWARD",
"btnName": "转交",
"enabled": true
},
{
"btnKey": "BPMN_COUNTERSIGN",
"btnName": "加签",
"enabled": true
},
{
"btnKey": "BPMN_COMMENT",
"btnName": "评论",
"enabled": true
},
{
"btnKey": "BPMN_ROLLBACK",
"btnName": "回退",
"enabled": true
},
{
"btnKey": "BPMN_COPY",
"btnName": "抄送",
"enabled": true
}
]
}
},
"branches": null
},
"branches": null
},
{
"id": "5",
"parentId": "3",
"type": "NODE_CONDITION",
"name": "条件2",
"property": {
"groups": [
{
"conditionsType": "and",
"conditions": [
{
"fieldDataType": "number",
"fieldCode": "size",
"operator": "between",
"leftValue": "31",
"leftOperator": "le",
"rightValue": "34",
"rightOperator": "gt"
},
{
"fieldDataType": "radio",
"fieldCode": "sex",
"operator": "eq",
"defaultValue": "2"
},
{
"fieldDataType": "checkbox",
"fieldCode": "color",
"operator": "in",
"defaultValues": [
"red",
"blue"
]
}
]
}
],
"defaultBranch": false,
"groupsType": "and"
},
"children": {
"id": "9",
"parentId": "5",
"type": "NODE_BUSINESS",
"name": "条件2业务节点",
"children": {
"id": "10",
"parentId": "9",
"type": "NODE_TASK",
"name": "条件2审批节点",
"children": {
"id": "13",
"parentId": "10",
"type": "NODE_BUSINESS",
"name": "业务节点有审批人",
"property": {
"approvalMethod": "human",
"approverScope": "projectWorkspace",
"approverSpecify": "identity",
"specifyValue": [
"worker",
"team_worker"
],
"isMultiTask": "true",
"multiMode": "AND",
"approverEmptyHandleType": "transferToAdmin",
"fieldPermission": null,
"buttonPermission": null
},
"children": null,
"branches": null
},
"property": {
"approvalMethod": "human",
"approverScope": "projectWorkspace",
"approverSpecify": "position",
"specifyValue": [
"job1",
"job2"
],
"isMultiTask": "true",
"multiMode": "AND",
"approverEmptyHandleType": "autoPassed",
"fieldPermission": null,
"buttonPermission": null
},
"branches": null
},
"property": {
"approvalMethod": "nobody"
},
"branches": null
},
"branches": null
},
{
"id": "6",
"parentId": "3",
"type": "NODE_CONDITION",
"name": "默认条件",
"property": {
"defaultBranch": true
},
"children": null,
"branches": null
}
],
"property": null
},
"branches": null,
"property": {
"approvalMethod": "human",
"approverScope": "projectWorkspace",
"approverSpecify": "position",
"specifyValue": [
"job1",
"job2"
],
"isMultiTask": "true",
"multiMode": "AND",
"approverEmptyHandleType": "autoPassed",
"fieldPermission": null,
"buttonPermission": {
"initiator": [
{
"btnKey": "BPMN_APPROVE",
"enabled": true,
"btnName": "同意"
},
{
"btnKey": "BPMN_REJECT",
"btnName": "拒绝",
"enabled": true
},
{
"btnKey": "BPMN_REVOCATION",
"btnName": "撤回",
"enabled": true
},
{
"btnKey": "BPMN_FORWARD",
"btnName": "转交",
"enabled": true
},
{
"btnKey": "BPMN_COUNTERSIGN",
"btnName": "加签",
"enabled": true
},
{
"btnKey": "BPMN_COMMENT",
"btnName": "评论",
"enabled": true
},
{
"btnKey": "BPMN_ROLLBACK",
"btnName": "回退",
"enabled": true
},
{
"btnKey": "BPMN_COPY",
"btnName": "抄送",
"enabled": true
}
],
"carbonCopy": [
{
"btnKey": "BPMN_APPROVE",
"enabled": true,
"btnName": "同意"
},
{
"btnKey": "BPMN_REJECT",
"btnName": "拒绝",
"enabled": true
},
{
"btnKey": "BPMN_REVOCATION",
"btnName": "撤回",
"enabled": true
},
{
"btnKey": "BPMN_FORWARD",
"btnName": "转交",
"enabled": true
},
{
"btnKey": "BPMN_COUNTERSIGN",
"btnName": "加签",
"enabled": true
},
{
"btnKey": "BPMN_COMMENT",
"btnName": "评论",
"enabled": true
},
{
"btnKey": "BPMN_ROLLBACK",
"btnName": "回退",
"enabled": true
},
{
"btnKey": "BPMN_COPY",
"btnName": "抄送",
"enabled": true
}
],
"history": [
{
"btnKey": "BPMN_APPROVE",
"enabled": true,
"btnName": "同意"
},
{
"btnKey": "BPMN_REJECT",
"btnName": "拒绝",
"enabled": true
},
{
"btnKey": "BPMN_REVOCATION",
"btnName": "撤回",
"enabled": true
},
{
"btnKey": "BPMN_FORWARD",
"btnName": "转交",
"enabled": true
},
{
"btnKey": "BPMN_COUNTERSIGN",
"btnName": "加签",
"enabled": true
},
{
"btnKey": "BPMN_COMMENT",
"btnName": "评论",
"enabled": true
},
{
"btnKey": "BPMN_ROLLBACK",
"btnName": "回退",
"enabled": true
},
{
"btnKey": "BPMN_COPY",
"btnName": "抄送",
"enabled": true
}
],
"current": [
{
"btnKey": "BPMN_APPROVE",
"enabled": true,
"btnName": "同意"
},
{
"btnKey": "BPMN_REJECT",
"btnName": "拒绝",
"enabled": true
},
{
"btnKey": "BPMN_REVOCATION",
"btnName": "撤回",
"enabled": true
},
{
"btnKey": "BPMN_FORWARD",
"btnName": "转交",
"enabled": true
},
{
"btnKey": "BPMN_COUNTERSIGN",
"btnName": "加签",
"enabled": true
},
{
"btnKey": "BPMN_COMMENT",
"btnName": "评论",
"enabled": true
},
{
"btnKey": "BPMN_ROLLBACK",
"btnName": "回退",
"enabled": true
},
{
"btnKey": "BPMN_COPY",
"btnName": "抄送",
"enabled": true
}
]
}
}
},
"branches": null,
"property": null
},