仿钉钉流程设计- 条件节点 review 修改

This commit is contained in:
jason 2024-09-21 10:54:12 +08:00
parent 6cc577eaaa
commit 5a1c3bdef5
5 changed files with 83 additions and 91 deletions

View File

@ -1,9 +1,12 @@
package cn.iocoder.yudao.module.bpm.enums.definition; package cn.iocoder.yudao.module.bpm.enums.definition;
import cn.hutool.core.util.ArrayUtil; import cn.hutool.core.util.ArrayUtil;
import cn.iocoder.yudao.framework.common.core.IntArrayValuable;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
import lombok.Getter; import lombok.Getter;
import java.util.Arrays;
/** /**
* 仿钉钉的流程器设计器条件节点的条件类型 * 仿钉钉的流程器设计器条件节点的条件类型
* *
@ -11,16 +14,23 @@ import lombok.Getter;
*/ */
@Getter @Getter
@AllArgsConstructor @AllArgsConstructor
public enum BpmSimpleModeConditionType { public enum BpmSimpleModeConditionType implements IntArrayValuable {
EXPRESSION(1, "条件表达式"), EXPRESSION(1, "条件表达式"),
RULE(2, "条件规则"); RULE(2, "条件规则");
public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(BpmSimpleModeConditionType::getType).toArray();
private final Integer type; private final Integer type;
private final String name; private final String name;
public static BpmSimpleModeConditionType valueOf(Integer type) { public static BpmSimpleModeConditionType valueOf(Integer type) {
return ArrayUtil.firstMatch(nodeType -> nodeType.getType().equals(type), values()); return ArrayUtil.firstMatch(nodeType -> nodeType.getType().equals(type), values());
} }
@Override
public int[] array() {
return ARRAYS;
}
} }

View File

@ -41,15 +41,19 @@ public class BpmSimpleModelNodeVO {
@Schema(description = "条件节点") @Schema(description = "条件节点")
private List<BpmSimpleModelNodeVO> conditionNodes; // 补充说明有且仅有条件并行包容等分支会使用 private List<BpmSimpleModelNodeVO> conditionNodes; // 补充说明有且仅有条件并行包容等分支会使用
@Schema(description = "节点的属性") @Schema(description = "条件类型", example = "1")
private Map<String, Object> attributes; // TODO @jason这个字段目前只有条件表达式使用是不是搞的更巨像TODO @芋艿 @InEnum(BpmSimpleModeConditionType.class)
private Integer conditionType; // 仅用于条件节点 BpmSimpleModelNodeType.CONDITION_NODE
// TODO @jason看看是不是可以简化@芋艿 暂时先放着不知道后面是否会用到 @Schema(description = "条件表达式", example = "${day>3}")
private String conditionExpression; // 仅用于条件节点 BpmSimpleModelNodeType.CONDITION_NODE
@Schema(description = "是否默认条件", example = "true")
private Boolean defaultFlow; // 仅用于条件节点 BpmSimpleModelNodeType.CONDITION_NODE
/** /**
* 附加节点 Id, 该节点不从前端传入 由程序生成. 由于当个节点无法完成功能 需要附加节点来完成 * 条件组
*/ */
@JsonIgnore private ConditionGroups conditionGroups; // 仅用于条件节点 BpmSimpleModelNodeType.CONDITION_NODE
private String attachNodeId;
@Schema(description = "候选人策略", example = "30") @Schema(description = "候选人策略", example = "30")
@InEnum(BpmTaskCandidateStrategyEnum.class) @InEnum(BpmTaskCandidateStrategyEnum.class)
@ -75,6 +79,12 @@ public class BpmSimpleModelNodeVO {
@Schema(description = "操作按钮设置", example = "[]") @Schema(description = "操作按钮设置", example = "[]")
private List<OperationButtonSetting> buttonsSetting; // 用于审批节点 private List<OperationButtonSetting> buttonsSetting; // 用于审批节点
// TODO @jason看看是不是可以简化@芋艿 暂时先放着不知道后面是否会用到
/**
* 附加节点 Id, 该节点不从前端传入 由程序生成. 由于当个节点无法完成功能 需要附加节点来完成
*/
@JsonIgnore
private String attachNodeId;
/** /**
* 审批节点拒绝处理 * 审批节点拒绝处理
*/ */
@ -160,6 +170,51 @@ public class BpmSimpleModelNodeVO {
private Boolean enable; private Boolean enable;
} }
// TODO @芋艿条件建议可以固化的一些选项然后有个表达式兜底要支持 @Schema(description = "条件组")
@Data
@Valid
public static class ConditionGroups {
@Schema(description = "条件组下的条件关系是否为与关系", example = "true")
@NotNull(message = "条件关系不能为空")
private Boolean and;
@Schema(description = "条件组下的条件", example = "[]")
@NotEmpty(message = "条件不能为空")
private List<Condition> conditions;
}
@Schema(description = "条件")
@Data
@Valid
public static class Condition {
@Schema(description = "条件下的规则关系是否为与关系", example = "true")
@NotNull(message = "规则关系不能为空")
private Boolean and;
@Schema(description = "条件下的规则", example = "[]")
@NotEmpty(message = "规则不能为空")
private List<ConditionRule> rules;
}
@Schema(description = "条件规则")
@Data
@Valid
public static class ConditionRule {
@Schema(description = "运行符号", example = "==")
@NotEmpty(message = "运行符号不能为空")
private String opCode;
@Schema(description = "运算符左边的值,例如某个流程变量", example = "startUserId")
@NotEmpty(message = "运算符左边的值不能为空")
private String leftSide;
@Schema(description = "运算符右边的值", example = "1")
@NotEmpty(message = "运算符右边的值不能为空")
private String rightSide;
}
// TODO @芋艿条件建议可以固化的一些选项然后有个表达式兜底要支持
} }

View File

@ -1,63 +0,0 @@
package cn.iocoder.yudao.module.bpm.framework.flowable.core.simplemodel;
import lombok.Data;
import java.util.List;
/**
* 仿钉钉流程设计器条件节点的条件组 Model
*
* @author jason
*/
@Data
public class SimpleModelConditionGroups {
/**
* 条件组的逻辑关系是否为与的关系
*/
private Boolean and;
/**
* 条件组下的条件
*/
private List<SimpleModelCondition> conditions;
@Data
public static class SimpleModelCondition {
/**
* 条件下面多个规则的逻辑关系是否为与的关系
*/
private Boolean and;
/**
* 条件下的规则
*/
private List<ConditionRule> rules;
}
@Data
public static class ConditionRule {
/**
* 类型. TODO 暂时未定义, 未想好
*/
private Integer type;
/**
* 运行符号. 例如 == <
*/
private String opCode;
/**
* 运算符左边的值
*/
private String leftSide;
/**
* 运算符右边的值
*/
private String rightSide;
}
}

View File

@ -1,13 +1,12 @@
package cn.iocoder.yudao.module.bpm.framework.flowable.core.util; package cn.iocoder.yudao.module.bpm.framework.flowable.core.util;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil; import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.lang.Assert; import cn.hutool.core.lang.Assert;
import cn.hutool.core.lang.TypeReference;
import cn.hutool.core.map.MapUtil; import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.*; import cn.hutool.core.util.*;
import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.model.simple.BpmSimpleModelNodeVO; import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.model.simple.BpmSimpleModelNodeVO;
import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.model.simple.BpmSimpleModelNodeVO.ConditionGroups;
import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.model.simple.BpmSimpleModelNodeVO.RejectHandler; import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.model.simple.BpmSimpleModelNodeVO.RejectHandler;
import cn.iocoder.yudao.module.bpm.enums.definition.BpmBoundaryEventType; import cn.iocoder.yudao.module.bpm.enums.definition.BpmBoundaryEventType;
import cn.iocoder.yudao.module.bpm.enums.definition.BpmSimpleModeConditionType; import cn.iocoder.yudao.module.bpm.enums.definition.BpmSimpleModeConditionType;
@ -15,7 +14,6 @@ import cn.iocoder.yudao.module.bpm.enums.definition.BpmSimpleModelNodeType;
import cn.iocoder.yudao.module.bpm.enums.definition.BpmUserTaskApproveMethodEnum; import cn.iocoder.yudao.module.bpm.enums.definition.BpmUserTaskApproveMethodEnum;
import cn.iocoder.yudao.module.bpm.framework.flowable.core.enums.BpmnModelConstants; import cn.iocoder.yudao.module.bpm.framework.flowable.core.enums.BpmnModelConstants;
import cn.iocoder.yudao.module.bpm.framework.flowable.core.listener.BpmCopyTaskDelegate; import cn.iocoder.yudao.module.bpm.framework.flowable.core.listener.BpmCopyTaskDelegate;
import cn.iocoder.yudao.module.bpm.framework.flowable.core.simplemodel.SimpleModelConditionGroups;
import org.flowable.bpmn.BpmnAutoLayout; import org.flowable.bpmn.BpmnAutoLayout;
import org.flowable.bpmn.model.Process; import org.flowable.bpmn.model.Process;
import org.flowable.bpmn.model.*; import org.flowable.bpmn.model.*;
@ -35,7 +33,6 @@ import static cn.iocoder.yudao.module.bpm.enums.definition.BpmUserTaskAssignStar
import static cn.iocoder.yudao.module.bpm.enums.definition.BpmUserTaskTimeoutHandlerTypeEnum.REMINDER; import static cn.iocoder.yudao.module.bpm.enums.definition.BpmUserTaskTimeoutHandlerTypeEnum.REMINDER;
import static cn.iocoder.yudao.module.bpm.framework.flowable.core.enums.BpmTaskCandidateStrategyEnum.START_USER; import static cn.iocoder.yudao.module.bpm.framework.flowable.core.enums.BpmTaskCandidateStrategyEnum.START_USER;
import static cn.iocoder.yudao.module.bpm.framework.flowable.core.enums.BpmnModelConstants.*; import static cn.iocoder.yudao.module.bpm.framework.flowable.core.enums.BpmnModelConstants.*;
import static cn.iocoder.yudao.module.bpm.framework.flowable.core.enums.SimpleModelConstants.*;
import static org.flowable.bpmn.constants.BpmnXMLConstants.*; import static org.flowable.bpmn.constants.BpmnXMLConstants.*;
/** /**
@ -219,17 +216,12 @@ public class SimpleModelUtils {
* @param conditionNode 条件节点 * @param conditionNode 条件节点
*/ */
public static String buildConditionExpression(BpmSimpleModelNodeVO conditionNode) { public static String buildConditionExpression(BpmSimpleModelNodeVO conditionNode) {
Integer conditionType = MapUtil.getInt(conditionNode.getAttributes(), CONDITION_TYPE_ATTRIBUTE); BpmSimpleModeConditionType conditionTypeEnum = BpmSimpleModeConditionType.valueOf(conditionNode.getConditionType());
BpmSimpleModeConditionType conditionTypeEnum = BpmSimpleModeConditionType.valueOf(conditionType);
String conditionExpression = null; String conditionExpression = null;
if (conditionTypeEnum == BpmSimpleModeConditionType.EXPRESSION) { if (conditionTypeEnum == BpmSimpleModeConditionType.EXPRESSION) {
conditionExpression = MapUtil.getStr(conditionNode.getAttributes(), CONDITION_EXPRESSION_ATTRIBUTE); conditionExpression = conditionNode.getConditionExpression();
} } else if (conditionTypeEnum == BpmSimpleModeConditionType.RULE) {
if (conditionTypeEnum == BpmSimpleModeConditionType.RULE) { ConditionGroups conditionGroups = conditionNode.getConditionGroups();
SimpleModelConditionGroups conditionGroups = BeanUtil.toBean(MapUtil.get(conditionNode.getAttributes(),
CONDITION_GROUPS_ATTRIBUTE, new TypeReference<Map<String, Object>>() {
}),
SimpleModelConditionGroups.class);
if (conditionGroups != null && CollUtil.isNotEmpty(conditionGroups.getConditions())) { if (conditionGroups != null && CollUtil.isNotEmpty(conditionGroups.getConditions())) {
List<String> strConditionGroups = conditionGroups.getConditions().stream().map(item -> { List<String> strConditionGroups = conditionGroups.getConditions().stream().map(item -> {
if (CollUtil.isNotEmpty(item.getRules())) { if (CollUtil.isNotEmpty(item.getRules())) {
@ -246,7 +238,6 @@ public class SimpleModelUtils {
}).toList(); }).toList();
conditionExpression = String.format("${%s}", CollUtil.join(strConditionGroups, conditionGroups.getAnd() ? " && " : " || ")); conditionExpression = String.format("${%s}", CollUtil.join(strConditionGroups, conditionGroups.getAnd() ? " && " : " || "));
} }
} }
// TODO 待增加其它类型 // TODO 待增加其它类型
return conditionExpression; return conditionExpression;
@ -400,8 +391,7 @@ public class SimpleModelUtils {
// TODO @jasonsetName // TODO @jasonsetName
// TODO @芋艿 + jason合并网关是不是要有条件啥的微信讨论 // TODO @芋艿 + jason合并网关是不是要有条件啥的微信讨论
// @芋艿 感觉聚合网关(合并网关)还是从前端传过来好理解一点 // 并行聚合网关有程序创建前端不需要传入
// 并行聚合网关
ParallelGateway joinParallelGateway = new ParallelGateway(); ParallelGateway joinParallelGateway = new ParallelGateway();
joinParallelGateway.setId(node.getId() + JOIN_GATE_WAY_NODE_ID_SUFFIX); joinParallelGateway.setId(node.getId() + JOIN_GATE_WAY_NODE_ID_SUFFIX);
return CollUtil.newArrayList(parallelGateway, joinParallelGateway); return CollUtil.newArrayList(parallelGateway, joinParallelGateway);
@ -436,7 +426,7 @@ public class SimpleModelUtils {
exclusiveGateway.setId(node.getId()); exclusiveGateway.setId(node.getId());
// 寻找默认的序列流 // 寻找默认的序列流
BpmSimpleModelNodeVO defaultSeqFlow = CollUtil.findOne(node.getConditionNodes(), BpmSimpleModelNodeVO defaultSeqFlow = CollUtil.findOne(node.getConditionNodes(),
item -> BooleanUtil.isTrue(MapUtil.getBool(item.getAttributes(), DEFAULT_FLOW_ATTRIBUTE))); item -> BooleanUtil.isTrue(item.getDefaultFlow()));
if (defaultSeqFlow != null) { if (defaultSeqFlow != null) {
exclusiveGateway.setDefaultFlow(defaultSeqFlow.getId()); exclusiveGateway.setDefaultFlow(defaultSeqFlow.getId());
} }
@ -453,8 +443,8 @@ public class SimpleModelUtils {
if (isFork) { if (isFork) {
Assert.notEmpty(node.getConditionNodes(), "条件节点不能为空"); Assert.notEmpty(node.getConditionNodes(), "条件节点不能为空");
// 寻找默认的序列流 // 寻找默认的序列流
BpmSimpleModelNodeVO defaultSeqFlow = CollUtil.findOne(node.getConditionNodes(), BpmSimpleModelNodeVO defaultSeqFlow = CollUtil.findOne(
item -> BooleanUtil.isTrue(MapUtil.getBool(item.getAttributes(), DEFAULT_FLOW_ATTRIBUTE))); node.getConditionNodes(), item -> BooleanUtil.isTrue(item.getDefaultFlow()));
if (defaultSeqFlow != null) { if (defaultSeqFlow != null) {
inclusiveGateway.setDefaultFlow(defaultSeqFlow.getId()); inclusiveGateway.setDefaultFlow(defaultSeqFlow.getId());
} }