diff --git a/src/main/java/com/metis/controller/TestController.java b/src/main/java/com/metis/controller/TestController.java index 657f89f..16781ed 100644 --- a/src/main/java/com/metis/controller/TestController.java +++ b/src/main/java/com/metis/controller/TestController.java @@ -1,6 +1,8 @@ package com.metis.controller; import com.metis.flow.domain.bo.BuildApp; +import com.metis.flow.engine.AppFlowEngineRunnerService; +import com.metis.flow.runner.FlowRunningContext; import com.metis.flow.validator.ValidatorService; import com.metis.result.Result; import lombok.RequiredArgsConstructor; @@ -16,6 +18,7 @@ public class TestController { private final ValidatorService validatorService; + private final AppFlowEngineRunnerService engineRunnerService; @PostMapping public Result test(@RequestBody BuildApp app) { @@ -23,4 +26,12 @@ public class TestController { return Result.ok("测试成功"); } + + @PostMapping("/run") + public Result run(@RequestBody FlowRunningContext context) { + engineRunnerService.running(context); + return Result.ok("测试成功"); + } + + } diff --git a/src/main/java/com/metis/flow/domain/context/RunningContext.java b/src/main/java/com/metis/flow/domain/context/RunningContext.java index 8dbff6f..87d99d4 100644 --- a/src/main/java/com/metis/flow/domain/context/RunningContext.java +++ b/src/main/java/com/metis/flow/domain/context/RunningContext.java @@ -3,13 +3,13 @@ package com.metis.flow.domain.context; import com.alibaba.fastjson2.JSONObject; import com.metis.flow.runner.FlowRunningContext; import lombok.Builder; -import lombok.Data; +import lombok.Getter; import java.util.HashMap; import java.util.Map; import java.util.Set; -@Data +@Getter @Builder public class RunningContext { @@ -29,11 +29,21 @@ public class RunningContext { private Map nodeRunningContext; /** - * 下一个运行节点id集合, 可能是多个 + * 下一个运行节点id集合, 可能是多个, 执行器每一次清空该节点 */ private Set nextRunNodeId; + /** + * 添加节点运行环境 + * + * @param nodeId 节点id + * @param nodeRunningContext 节点运行背景信息 + */ + public void addNodeRunningContext(Long nodeId, JSONObject nodeRunningContext) { + this.nodeRunningContext.put(nodeId, nodeRunningContext); + } + /** * 构建上下文 * diff --git a/src/main/java/com/metis/flow/domain/context/RunningResult.java b/src/main/java/com/metis/flow/domain/context/RunningResult.java new file mode 100644 index 0000000..bb5b598 --- /dev/null +++ b/src/main/java/com/metis/flow/domain/context/RunningResult.java @@ -0,0 +1,56 @@ +package com.metis.flow.domain.context; + +import com.alibaba.fastjson2.JSONObject; +import lombok.Builder; +import lombok.Data; + +import java.util.Set; + +@Data +@Builder +public class RunningResult { + + /** + * 节点上下文 + */ + private JSONObject nodeContext; + + /** + * 下一个运行节点id, 一些特殊节点需要, 必须条件节点满足后, 才会运行下一个节点 + */ + private Set nextRunNodeId; + + + /** + * 构建结果 + * + * @param nodeContext 节点上下文 + * @param nextRunNodeId 下一个运行节点id + * @return {@link RunningResult } + */ + public static RunningResult buildResult(JSONObject nodeContext, Set nextRunNodeId) { + return RunningResult.builder() + .nodeContext(nodeContext) + .nextRunNodeId(nextRunNodeId) + .build(); + } + + /** + * 构建结果 + * + * @param nodeContext 节点上下文 + * @return {@link RunningResult } + */ + public static RunningResult buildResult(JSONObject nodeContext) { + return RunningResult.builder() + .nodeContext(nodeContext) + .build(); + } + + public static RunningResult buildResult() { + return RunningResult.builder() + .build(); + } + + +} diff --git a/src/main/java/com/metis/flow/domain/entity/base/Node.java b/src/main/java/com/metis/flow/domain/entity/base/Node.java index 057f0b7..20dff37 100644 --- a/src/main/java/com/metis/flow/domain/entity/base/Node.java +++ b/src/main/java/com/metis/flow/domain/entity/base/Node.java @@ -40,6 +40,23 @@ public class Node { @NotNull(message = "节点业务数据不能为空") private NodeData data; + /** + * 宽度 + */ +// @NotNull(message = "节点宽度不能为空") + private Integer width; + + /** + * 高度 + */ +// @NotNull(message = "节点高度不能为空") + private Integer height; + + /** + * 节点是否选中 + */ + private Boolean selected; + @JsonIgnore public Map getHandleMap() { diff --git a/src/main/java/com/metis/flow/domain/entity/base/NodeData.java b/src/main/java/com/metis/flow/domain/entity/base/NodeData.java index c6add39..ed632d2 100644 --- a/src/main/java/com/metis/flow/domain/entity/base/NodeData.java +++ b/src/main/java/com/metis/flow/domain/entity/base/NodeData.java @@ -29,6 +29,9 @@ public class NodeData { */ private PositionType toolbarPosition; + + + /** * 配置 */ diff --git a/src/main/java/com/metis/flow/domain/entity/base/NodeVariable.java b/src/main/java/com/metis/flow/domain/entity/base/NodeVariable.java new file mode 100644 index 0000000..0a93469 --- /dev/null +++ b/src/main/java/com/metis/flow/domain/entity/base/NodeVariable.java @@ -0,0 +1,98 @@ +package com.metis.flow.domain.entity.base; + +import cn.hutool.core.lang.Assert; +import cn.hutool.core.util.ObjectUtil; +import com.alibaba.fastjson2.JSONObject; +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.metis.flow.enums.FileUploadType; +import com.metis.flow.enums.NodeVariableType; +import jakarta.validation.Valid; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +import java.util.List; + +@Data +public class NodeVariable { + + /** + * 参数字段 + */ + @NotBlank(message = "参数字段不能为空") + private String variable; + + /** + * 标签 + */ + private String label; + + /** + * 最大长度 + */ + private Integer maxLength; + + /** + * 类型 + */ + @NotNull(message = "类型不能为空") + private String type; + + /** + * 是否必填 + */ + @NotNull(message = "是否必填不能为空") + private Boolean required; + + /** + * 选项 + */ + @Valid + private List options; + + /** + * 允许上传方式 + */ + private List allowedFileUploadMethods; + + /** + * 允许文件类型 + */ + private List allowedFileTypes; + + /** + * 允许文件扩展名 + */ + private List allowedFileExtensions; + + + @JsonIgnore + public Object getValue(JSONObject custom) { + Object serializable = getSerializable(custom); + Assert.isTrue(!(ObjectUtil.isNull(serializable) && ObjectUtil.isNotNull(required) && required), "参数字段 {} 的值不能为空", variable); + return serializable; + } + + private Object getSerializable(JSONObject custom) { + switch (getVariableType()) { + case TEXT_INPUT, PARAGRAPH, SELECT, FILE -> { + return custom.getString(variable); + } + case NUMBER -> { + return custom.getInteger(variable); + } + case FILE_LIST -> { + return custom.getList(variable, String.class); + } + default -> throw new RuntimeException("不支持的类型"); + } + } + + + @JsonIgnore + public NodeVariableType getVariableType() { + return NodeVariableType.get(type); + } + + +} diff --git a/src/main/java/com/metis/flow/domain/entity/base/VariableOption.java b/src/main/java/com/metis/flow/domain/entity/base/VariableOption.java new file mode 100644 index 0000000..cc3a4ef --- /dev/null +++ b/src/main/java/com/metis/flow/domain/entity/base/VariableOption.java @@ -0,0 +1,22 @@ +package com.metis.flow.domain.entity.base; + + +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +@Data +public class VariableOption { + + /** + * 标签 + */ + private String label; + + /** + * 值 + */ + @NotNull(message = "值不能为空") + private String value; + + +} diff --git a/src/main/java/com/metis/flow/domain/entity/config/node/StartNodeConfig.java b/src/main/java/com/metis/flow/domain/entity/config/node/StartNodeConfig.java new file mode 100644 index 0000000..685c1c4 --- /dev/null +++ b/src/main/java/com/metis/flow/domain/entity/config/node/StartNodeConfig.java @@ -0,0 +1,17 @@ +package com.metis.flow.domain.entity.config.node; + +import com.metis.flow.domain.entity.base.NodeVariable; +import jakarta.validation.Valid; +import lombok.Data; + +import java.util.List; + +@Data +public class StartNodeConfig { + + + @Valid + private List variables; + + +} diff --git a/src/main/java/com/metis/flow/engine/impl/AppFlowEngineRunnerServiceImpl.java b/src/main/java/com/metis/flow/engine/impl/AppFlowEngineRunnerServiceImpl.java index 10dd2c0..ff00289 100644 --- a/src/main/java/com/metis/flow/engine/impl/AppFlowEngineRunnerServiceImpl.java +++ b/src/main/java/com/metis/flow/engine/impl/AppFlowEngineRunnerServiceImpl.java @@ -1,18 +1,31 @@ package com.metis.flow.engine.impl; +import cn.hutool.core.lang.Assert; import cn.hutool.core.util.IdUtil; import cn.hutool.core.util.ObjectUtil; +import com.metis.flow.domain.bo.Graph; import com.metis.flow.domain.context.RunningContext; +import com.metis.flow.domain.context.RunningResult; import com.metis.flow.domain.context.SysContext; import com.metis.flow.domain.entity.App; +import com.metis.flow.domain.entity.base.Edge; +import com.metis.flow.domain.entity.base.Node; import com.metis.flow.engine.AppEngineService; import com.metis.flow.engine.AppFlowEngineRunnerService; +import com.metis.flow.enums.NodeType; import com.metis.flow.runner.FlowRunningContext; +import com.metis.flow.runner.NodeRunner; import com.metis.flow.runner.RunnerResult; +import com.metis.flow.runner.factory.RunnerFactory; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; +import java.util.List; +import java.util.Map; +import java.util.function.Function; +import java.util.stream.Collectors; + @Slf4j @Service @RequiredArgsConstructor @@ -36,9 +49,33 @@ public class AppFlowEngineRunnerServiceImpl implements AppFlowEngineRunnerServic .build(); // 构建运行中上下文 RunningContext runningContext = RunningContext.buildContext(sysContext, context); + // 构建节点映射对象 + Graph graph = app.getGraph(); + Map nodeMap = graph.getNodes().stream() + .collect(Collectors.toMap(Node::getId, Function.identity())); + Map> edgeMap = graph.getEdges().stream() + .collect(Collectors.groupingBy(Edge::getSource)); + // 获取到开始节点 + Node runningNode = graph.getNodes().stream().filter(node -> node.getType() == NodeType.START) + .findFirst().orElse(null); + // 开始节点为空,则表示数据存在异常 + Assert.isTrue(ObjectUtil.isNotNull(runningNode), "流程图不存在开始节点"); + while (ObjectUtil.isNotNull(runningNode)) { + NodeRunner nodeRunner = RunnerFactory.get(runningNode.getType()); + // 获取到返回结果 + RunningResult result = nodeRunner.run(runningContext, runningNode, edgeMap.get(runningNode.getId())); + if (ObjectUtil.isNotNull(result.getNodeContext())) { + runningContext.addNodeRunningContext(runningNode.getId(), result.getNodeContext()); + } + runningNode = null; + } - return null; + return RunnerResult.builder() + .content("你他妈的!") + .context(sysContext) + .build(); + } @@ -49,7 +86,7 @@ public class AppFlowEngineRunnerServiceImpl implements AppFlowEngineRunnerServic * @return {@link App } */ private App getApp(FlowRunningContext context) { - if (ObjectUtil.isNull(context.getWorkflowId())) { + if (ObjectUtil.isNotNull(context.getWorkflowId())) { return appEngineService.getByWorkflowId(context.getWorkflowId()); } return appEngineService.getByAppId(context.getAppId()); diff --git a/src/main/java/com/metis/flow/enums/FileUploadType.java b/src/main/java/com/metis/flow/enums/FileUploadType.java new file mode 100644 index 0000000..15181df --- /dev/null +++ b/src/main/java/com/metis/flow/enums/FileUploadType.java @@ -0,0 +1,45 @@ +package com.metis.flow.enums; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonValue; +import lombok.AllArgsConstructor; +import lombok.Getter; + +import java.util.Arrays; + +/** + * 文件上传类型 + * + * @author clay + * @date 2025/04/08 + */ +@Getter +@AllArgsConstructor +public enum FileUploadType { + LOCAL_FILE(1, "localFile", "本地文件"), + REMOTE_URL(2, "remoteUrl", "远程URL"); + + + private final Integer code; + + @JsonValue + private final String value; + + private final String name; + + + /** + * 枚举序列化器(前端传code时自动转换为对应枚举) + * + * @param value 值 + * @return 枚举 + */ + @JsonCreator(mode = JsonCreator.Mode.DELEGATING) + public static FileUploadType get(String value) { + return Arrays.stream(FileUploadType.class.getEnumConstants()) + .filter(e -> e.getValue().equals(value)) + .findFirst() + .orElse(null); + } + + } diff --git a/src/main/java/com/metis/flow/enums/NodeType.java b/src/main/java/com/metis/flow/enums/NodeType.java index dea39f3..a56c7fb 100644 --- a/src/main/java/com/metis/flow/enums/NodeType.java +++ b/src/main/java/com/metis/flow/enums/NodeType.java @@ -3,6 +3,7 @@ package com.metis.flow.enums; import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonValue; import com.metis.flow.domain.entity.config.node.DocumentExtractorNodeConfig; +import com.metis.flow.domain.entity.config.node.StartNodeConfig; import lombok.AllArgsConstructor; import lombok.Getter; @@ -12,11 +13,9 @@ import java.util.Arrays; @AllArgsConstructor public enum NodeType { - START(1, "start", "开始", Object.class), + START(1, "start", "开始", StartNodeConfig.class), END(2, "end", "结束", Object.class), - DOCUMENT_EXTRACTOR(3, "document-extractor", "文档提取器", DocumentExtractorNodeConfig.class) - - ; + DOCUMENT_EXTRACTOR(3, "document-extractor", "文档提取器", DocumentExtractorNodeConfig.class); private final Integer code; diff --git a/src/main/java/com/metis/flow/enums/NodeVariableType.java b/src/main/java/com/metis/flow/enums/NodeVariableType.java new file mode 100644 index 0000000..e9617ca --- /dev/null +++ b/src/main/java/com/metis/flow/enums/NodeVariableType.java @@ -0,0 +1,50 @@ +package com.metis.flow.enums; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonValue; +import lombok.AllArgsConstructor; +import lombok.Getter; + +import java.util.Arrays; + +/** + * 节点变量类型 + * + * @author clay + * @date 2025/04/08 + */ +@Getter +@AllArgsConstructor +public enum NodeVariableType { + TEXT_INPUT(1, "text-input", "文本"), + PARAGRAPH(2, "paragraph", "段落"), + SELECT(3, "select", "下拉框"), + NUMBER(4, "number", "数字"), + FILE(5, "file", "文件"), + FILE_LIST(6, "file-list", "文件列表") + ; + + + private final Integer code; + + @JsonValue + private final String value; + + private final String name; + + + /** + * 枚举序列化器(前端传code时自动转换为对应枚举) + * + * @param value 值 + * @return 枚举 + */ + @JsonCreator(mode = JsonCreator.Mode.DELEGATING) + public static NodeVariableType get(String value) { + return Arrays.stream(NodeVariableType.class.getEnumConstants()) + .filter(e -> e.getValue().equals(value)) + .findFirst() + .orElse(null); + } + +} diff --git a/src/main/java/com/metis/flow/runner/FlowRunningContext.java b/src/main/java/com/metis/flow/runner/FlowRunningContext.java index c477353..5159a44 100644 --- a/src/main/java/com/metis/flow/runner/FlowRunningContext.java +++ b/src/main/java/com/metis/flow/runner/FlowRunningContext.java @@ -1,8 +1,10 @@ package com.metis.flow.runner; import com.alibaba.fastjson2.JSONObject; +import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Data; +import lombok.NoArgsConstructor; import java.util.List; @@ -14,6 +16,8 @@ import java.util.List; */ @Data @Builder +@AllArgsConstructor +@NoArgsConstructor public class FlowRunningContext { /** diff --git a/src/main/java/com/metis/flow/runner/NodeRunner.java b/src/main/java/com/metis/flow/runner/NodeRunner.java index c7e5679..855a7f7 100644 --- a/src/main/java/com/metis/flow/runner/NodeRunner.java +++ b/src/main/java/com/metis/flow/runner/NodeRunner.java @@ -1,6 +1,7 @@ package com.metis.flow.runner; import com.metis.flow.domain.context.RunningContext; +import com.metis.flow.domain.context.RunningResult; import com.metis.flow.domain.entity.base.Edge; import com.metis.flow.domain.entity.base.Node; import com.metis.flow.enums.NodeType; @@ -18,7 +19,7 @@ public interface NodeRunner { * @param edges * @return {@link RunningContext } */ - RunningContext run(RunningContext context, Node node, List edges); + RunningResult run(RunningContext context, Node node, List edges); /** diff --git a/src/main/java/com/metis/flow/runner/RunnerResult.java b/src/main/java/com/metis/flow/runner/RunnerResult.java index 17358df..0b573f4 100644 --- a/src/main/java/com/metis/flow/runner/RunnerResult.java +++ b/src/main/java/com/metis/flow/runner/RunnerResult.java @@ -2,6 +2,7 @@ package com.metis.flow.runner; import com.metis.flow.domain.context.SysContext; +import lombok.Builder; import lombok.Data; /** @@ -11,6 +12,7 @@ import lombok.Data; * @date 2025/04/07 */ @Data +@Builder public class RunnerResult { /** diff --git a/src/main/java/com/metis/flow/runner/impl/EndNodeRunner.java b/src/main/java/com/metis/flow/runner/impl/EndNodeRunner.java index 430b2db..8b252c3 100644 --- a/src/main/java/com/metis/flow/runner/impl/EndNodeRunner.java +++ b/src/main/java/com/metis/flow/runner/impl/EndNodeRunner.java @@ -2,6 +2,7 @@ package com.metis.flow.runner.impl; import com.metis.flow.domain.context.RunningContext; +import com.metis.flow.domain.context.RunningResult; import com.metis.flow.domain.entity.base.Edge; import com.metis.flow.domain.entity.base.Node; import com.metis.flow.enums.NodeType; @@ -16,8 +17,8 @@ import java.util.List; public class EndNodeRunner implements NodeRunner { @Override - public RunningContext run(RunningContext context, Node node, List edges) { - return context; + public RunningResult run(RunningContext context, Node node, List edges) { + return RunningResult.buildResult(); } @Override diff --git a/src/main/java/com/metis/flow/runner/impl/StartNodeRunner.java b/src/main/java/com/metis/flow/runner/impl/StartNodeRunner.java index 3d7332b..2975174 100644 --- a/src/main/java/com/metis/flow/runner/impl/StartNodeRunner.java +++ b/src/main/java/com/metis/flow/runner/impl/StartNodeRunner.java @@ -1,8 +1,13 @@ package com.metis.flow.runner.impl; +import cn.hutool.core.collection.CollUtil; +import com.alibaba.fastjson2.JSONObject; import com.metis.flow.domain.context.RunningContext; +import com.metis.flow.domain.context.RunningResult; import com.metis.flow.domain.entity.base.Edge; import com.metis.flow.domain.entity.base.Node; +import com.metis.flow.domain.entity.base.NodeVariable; +import com.metis.flow.domain.entity.config.node.StartNodeConfig; import com.metis.flow.enums.NodeType; import com.metis.flow.runner.NodeRunner; import lombok.extern.slf4j.Slf4j; @@ -10,15 +15,37 @@ import org.springframework.stereotype.Service; import java.util.List; +/** + * 启动节点运行器, 开始节点功能主要为将用户传入的参数进行校验, 并放入到上下文中 + * + * @author clay + * @date 2025/04/08 + */ @Slf4j @Service public class StartNodeRunner implements NodeRunner { @Override - public RunningContext run(RunningContext context, Node node, List edges) { - return context; + public RunningResult run(RunningContext context, Node node, List edges) { + log.info("开始节点{}, 节点id: {} 运行", node.getData().getLabel(), node.getId()); + StartNodeConfig config = node.getConfig(); + // 获取到节点的自定义参数 + List variables = config.getVariables(); + // 如果没有自定义参数, 则直接返回 + if (CollUtil.isEmpty(variables)) { + return RunningResult.buildResult(); + } + // 获取用户自定义参数 + JSONObject custom = context.getCustom(); + JSONObject contextNodeValue = new JSONObject(); + for (NodeVariable variable : variables) { + Object value = variable.getValue(custom); + contextNodeValue.put(variable.getVariable(), value); + } + return RunningResult.buildResult(contextNodeValue); } + @Override public NodeType getType() { return NodeType.START; diff --git a/src/main/java/com/metis/flow/validator/impl/node/StartNodeValidator.java b/src/main/java/com/metis/flow/validator/impl/node/StartNodeValidator.java index 02be8ac..97dfc11 100644 --- a/src/main/java/com/metis/flow/validator/impl/node/StartNodeValidator.java +++ b/src/main/java/com/metis/flow/validator/impl/node/StartNodeValidator.java @@ -1,11 +1,17 @@ package com.metis.flow.validator.impl.node; +import cn.hutool.core.collection.CollUtil; import cn.hutool.core.lang.Assert; +import cn.hutool.core.util.ObjectUtil; import com.metis.flow.domain.entity.base.Edge; import com.metis.flow.domain.entity.base.Node; +import com.metis.flow.domain.entity.base.NodeVariable; +import com.metis.flow.domain.entity.config.node.StartNodeConfig; import com.metis.flow.enums.NodeType; import com.metis.flow.validator.NodeValidator; +import com.metis.flow.validator.ValidatorCodeService; import com.metis.flow.validator.ValidatorResult; +import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; @@ -13,13 +19,65 @@ import java.util.List; @Slf4j @Service +@RequiredArgsConstructor public class StartNodeValidator implements NodeValidator { + private final ValidatorCodeService validatorCodeService; + + @Override public ValidatorResult validateValue(Node node) { + StartNodeConfig config = node.getConfig(); + validatorCodeService.validateThrow(config); + + List variables = config.getVariables(); + if (CollUtil.isEmpty(variables)) { + return ValidatorResult.valid(); + } + + for (NodeVariable variable : variables) { + switch (variable.getVariableType()) { + // 文本类型校验 + case TEXT_INPUT, PARAGRAPH -> textVariableValidator(variable); + // 下拉框变量校验 + case SELECT -> selectVariableValidator(variable); + // 文件变量校验 + case FILE, FILE_LIST -> fileVariableValidator(variable); + } + } return ValidatorResult.valid(); } + /** + * 文本变量验证器 + * + * @param variable 变量 + */ + private void textVariableValidator(NodeVariable variable) { + Assert.isTrue(ObjectUtil.isNotNull(variable.getMaxLength()), "文本变量 {} {} 的最大长度不能为空", variable.getLabel(), variable.getLabel(), variable.getVariable()); + } + + /** + * 选择变量验证器 + * + * @param variable 变量 + */ + private void selectVariableValidator(NodeVariable variable) { + Assert.isTrue(CollUtil.isNotEmpty(variable.getOptions()), "选择变量 {} {} 的选项不能为空", variable.getLabel(), variable.getLabel(), variable.getVariable()); + } + + /** + * 文件变量验证器 + * + * @param variable 变量 + */ + private void fileVariableValidator(NodeVariable variable) { + Assert.isTrue(ObjectUtil.isNotNull(variable.getMaxLength()), "文本变量 {} {} 的最大长度不能为空", variable.getLabel(), variable.getVariable()); + Assert.isTrue(CollUtil.isNotEmpty(variable.getAllowedFileUploadMethods()), "文本变量 {} {} 的允许上传方式不能为空", variable.getLabel(), variable.getVariable()); + Assert.isTrue(CollUtil.isNotEmpty(variable.getAllowedFileTypes()) || CollUtil.isNotEmpty(variable.getAllowedFileExtensions()), "文本变量 {} 的允许上传文件类型不能为空", variable.getLabel(), variable.getVariable()); + } + + @Override public ValidatorResult validateRelation(Node node, List sources, List targets) { // 1. 开始节点不允许有源连接 diff --git a/src/main/resources/json/run.json b/src/main/resources/json/run.json new file mode 100644 index 0000000..c7e457d --- /dev/null +++ b/src/main/resources/json/run.json @@ -0,0 +1,7 @@ +{ + "appId": "1909636986931470336", + "userId": 1, + "custom": { + "context": "测试内容!" + } +} \ No newline at end of file diff --git a/src/main/resources/json/test.json b/src/main/resources/json/test.json new file mode 100644 index 0000000..00df0ea --- /dev/null +++ b/src/main/resources/json/test.json @@ -0,0 +1,152 @@ + +{ + "id": 0, + "name": "测试流程", + "description": "测试流程", + "graph": { + "nodes": [ + { + "id": "5", + "type": "start", + "dimensions": { + "width": 300, + "height": 300 + }, + "draggable": true, + "resizing": false, + "selected": true, + "data": { + "label": "开始", + "toolbarPosition": "right", + "config": { + "variables": [ + { + "variable": "context", + "label": "段落", + "type": "paragraph", + "maxLength": 48, + "required": true + }, + { + "variable": "text", + "label": "文本", + "type": "text-input", + "maxLength": 48, + "required": true, + "options": [] + }, + { + "variable": "select", + "label": "下拉", + "type": "select", + "maxLength": 48, + "required": true, + "options": [ + { + "label": "选型1", + "value": "1" + }, + { + "label": "选型2", + "value": "2" + } + ] + }, + { + "variable": "number", + "label": "数字", + "type": "number", + "maxLength": 48, + "required": true, + "options": [] + }, + { + "variable": "singlefile", + "label": "singlefile单文件", + "type": "file", + "maxLength": 48, + "required": true, + "options": [], + "allowedFileUploadMethods": [ + "local_file", + "remote_url" + ], + "allowedFileTypes": [ + "image", + "document", + "audio", + "video" + ], + "allowedFileExtensions": [] + }, + { + "variable": "mufile", + "label": "多文件", + "type": "file-list", + "maxLength": 5, + "required": true, + "options": [], + "allowedFileUploadMethods": [ + "local_file" + ], + "allowedFileTypes": [ + "custom" + ], + "allowedFileExtensions": [ + "docx", + "aaa" + ] + } + ], + "parent": "234" + }, + "handles": [ + { + "id": "7", + "position": "right", + "type": "source", + "connectable": true + } + ] + }, + "position": { "x": 0, "y": 300 } + }, + { + "id": "6", + "type": "end", + "selected": false, + "data": { + "label": "结束", + "toolbarPosition": "right", + "handles": [ + { + "id": "8", + "position": "left", + "type": "target", + "connectable": true + } + ] + }, + "position": { "x": 500, "y": 300 } + } + ], + "edges": [ + { + "id": "6", + "type": "default", + "source": "5", + "target": "6", + "sourceHandle": "7", + "animated": true, + "targetHandle": "8", + "label": "线标签", + "markerEnd": "none", + "markerStart": "none", + "updatable": true, + "selectable": true, + "deletable": true + } + ] + } + +} \ No newline at end of file