反序列化问题。
This commit is contained in:
parent
af8e3f6589
commit
6dbfb2c878
@ -0,0 +1,123 @@
|
|||||||
|
package com.qqchen.deploy.backend.workflow.config;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.experimental.Accessors;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 节点UI配置类
|
||||||
|
* 用于定义工作流节点的UI展示属性
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@Accessors(chain = true)
|
||||||
|
public class NodeUiConfig {
|
||||||
|
private String shape;
|
||||||
|
private Size size;
|
||||||
|
private Style style;
|
||||||
|
private Ports ports;
|
||||||
|
|
||||||
|
public NodeUiConfig setSize(int width, int height) {
|
||||||
|
this.size = new Size(width, height);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public NodeUiConfig setStyle(String fill, String stroke, String icon) {
|
||||||
|
this.style = new Style(fill, stroke, icon);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public NodeUiConfig setPorts(List<String> types) {
|
||||||
|
this.ports = new Ports();
|
||||||
|
Map<String, PortGroup> groups = new HashMap<>();
|
||||||
|
|
||||||
|
types.forEach(type -> {
|
||||||
|
PortGroup group = new PortGroup();
|
||||||
|
group.setPosition(type.equals("in") ? "left" : "right");
|
||||||
|
|
||||||
|
PortCircle circle = new PortCircle();
|
||||||
|
circle.setR(4);
|
||||||
|
circle.setFill("#ffffff");
|
||||||
|
circle.setStroke("#1890ff");
|
||||||
|
|
||||||
|
PortAttrs attrs = new PortAttrs();
|
||||||
|
attrs.setCircle(circle);
|
||||||
|
|
||||||
|
group.setAttrs(attrs);
|
||||||
|
groups.put(type, group);
|
||||||
|
});
|
||||||
|
|
||||||
|
this.ports.setGroups(groups);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 节点大小配置
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public static class Size {
|
||||||
|
private int width;
|
||||||
|
private int height;
|
||||||
|
|
||||||
|
public Size(int width, int height) {
|
||||||
|
this.width = width;
|
||||||
|
this.height = height;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 节点样式配置
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public static class Style {
|
||||||
|
private String fill; // 填充颜色
|
||||||
|
private String stroke; // 边框颜色
|
||||||
|
private String icon; // 图标名称
|
||||||
|
private String iconColor; // 图标颜色
|
||||||
|
private int strokeWidth = 2;// 边框宽度
|
||||||
|
|
||||||
|
public Style(String fill, String stroke, String icon) {
|
||||||
|
this.fill = fill;
|
||||||
|
this.stroke = stroke;
|
||||||
|
this.icon = icon;
|
||||||
|
this.iconColor = stroke;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 节点连接点配置
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public static class Ports {
|
||||||
|
private Map<String, PortGroup> groups;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 连接点分组配置
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public static class PortGroup {
|
||||||
|
private String position; // 位置:left, right, top, bottom
|
||||||
|
private PortAttrs attrs; // 连接点属性
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 连接点属性配置
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public static class PortAttrs {
|
||||||
|
private PortCircle circle; // 圆形连接点
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 圆形连接点配置
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public static class PortCircle {
|
||||||
|
private int r; // 半径
|
||||||
|
private String fill; // 填充颜色
|
||||||
|
private String stroke; // 边框颜色
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -13,73 +13,7 @@ import java.util.Map;
|
|||||||
@Data
|
@Data
|
||||||
@JsonInclude(JsonInclude.Include.NON_NULL) // 只序列化非空字段
|
@JsonInclude(JsonInclude.Include.NON_NULL) // 只序列化非空字段
|
||||||
public class NodeConfig {
|
public class NodeConfig {
|
||||||
/**
|
|
||||||
* 配置类型
|
|
||||||
*/
|
|
||||||
private String type;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 实现类
|
|
||||||
*/
|
|
||||||
private String implementation;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 字段配置
|
|
||||||
*/
|
|
||||||
private Map<String, Object> fields;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 任务处理人
|
|
||||||
*/
|
|
||||||
private String assignee;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 候选用户列表
|
|
||||||
*/
|
|
||||||
private List<String> candidateUsers;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 候选组列表
|
|
||||||
*/
|
|
||||||
private List<String> candidateGroups;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 到期时间
|
|
||||||
*/
|
|
||||||
private String dueDate;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 优先级
|
|
||||||
*/
|
|
||||||
private Integer priority;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 表单标识
|
|
||||||
*/
|
|
||||||
private String formKey;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 跳过表达式
|
|
||||||
*/
|
|
||||||
private String skipExpression;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 是否异步
|
|
||||||
*/
|
|
||||||
private Boolean isAsync;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 是否排他
|
|
||||||
*/
|
|
||||||
private Boolean exclusive;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 脚本格式
|
|
||||||
*/
|
|
||||||
private String scriptFormat;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 脚本内容
|
|
||||||
*/
|
|
||||||
private String script;
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -21,8 +21,4 @@ public class WorkflowGraph {
|
|||||||
*/
|
*/
|
||||||
private List<WorkflowEdge> edges;
|
private List<WorkflowEdge> edges;
|
||||||
|
|
||||||
/**
|
|
||||||
* 工作流属性
|
|
||||||
*/
|
|
||||||
private Map<String, Object> properties;
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,7 +1,6 @@
|
|||||||
package com.qqchen.deploy.backend.workflow.dto.nodeConfig;
|
package com.qqchen.deploy.backend.workflow.dto.nodeConfig;
|
||||||
|
|
||||||
import com.qqchen.deploy.backend.workflow.annotation.SchemaProperty;
|
import com.qqchen.deploy.backend.workflow.annotation.SchemaProperty;
|
||||||
import com.qqchen.deploy.backend.workflow.dto.nodeConfig.listener.ListenerNodeConfig;
|
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@ -84,14 +83,6 @@ public class BaseTaskNodeConfig extends BaseNodeConfig {
|
|||||||
)
|
)
|
||||||
private String retryStrategy;
|
private String retryStrategy;
|
||||||
|
|
||||||
/**
|
|
||||||
* 监听器配置列表
|
|
||||||
*/
|
|
||||||
@SchemaProperty(
|
|
||||||
title = "监听器配置",
|
|
||||||
description = "工作流节点的事件监听器配置列表"
|
|
||||||
)
|
|
||||||
private List<ListenerNodeConfig> listeners;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 是否异步
|
* 是否异步
|
||||||
|
|||||||
@ -1,37 +1,270 @@
|
|||||||
package com.qqchen.deploy.backend.workflow.enums;
|
package com.qqchen.deploy.backend.workflow.enums;
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonValue;
|
import com.fasterxml.jackson.annotation.JsonValue;
|
||||||
|
import com.qqchen.deploy.backend.workflow.config.NodeUiConfig;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 工作流节点类型枚举
|
||||||
|
* 定义了工作流中所有可用的节点类型及其UI配置
|
||||||
|
*
|
||||||
|
* 节点类型说明:
|
||||||
|
* 1. 事件类节点(Event):用于标记流程的开始和结束
|
||||||
|
* 2. 任务类节点(Task):执行具体的业务操作
|
||||||
|
* 3. 网关类节点(Gateway):控制流程的流转方向
|
||||||
|
* 4. 容器类节点:包含子流程或调用其他流程
|
||||||
|
*/
|
||||||
@Getter
|
@Getter
|
||||||
public enum NodeTypeEnums {
|
public enum NodeTypeEnums {
|
||||||
|
|
||||||
START_EVENT("START_EVENT", "开始节点"),
|
/**
|
||||||
END_EVENT("END_EVENT", "结束节点"),
|
* 开始节点 - 流程的起点
|
||||||
USER_TASK("USER_TASK", "用户任务"),
|
* 功能:
|
||||||
SERVICE_TASK("SERVICE_TASK", "服务任务"),
|
* - 标记流程的开始位置
|
||||||
SCRIPT_TASK("SCRIPT_TASK", "脚本任务"),
|
* - 可以定义流程启动条件
|
||||||
EXCLUSIVE_GATEWAY("EXCLUSIVE_GATEWAY", "排他网关"),
|
* - 可以初始化流程变量
|
||||||
PARALLEL_GATEWAY("PARALLEL_GATEWAY", "并行网关"),
|
*
|
||||||
SUBPROCESS("SUB_PROCESS", "子流程"),
|
* 使用场景:
|
||||||
CALL_ACTIVITY("CALL_ACTIVITY", "调用活动");
|
* - 用户手动启动流程
|
||||||
|
* - 定时触发流程
|
||||||
|
* - 外部系统调用启动
|
||||||
|
*
|
||||||
|
* 限制:
|
||||||
|
* - 每个流程必须有且仅有一个开始节点
|
||||||
|
* - 只能有出边,不能有入边
|
||||||
|
*/
|
||||||
|
START_EVENT("START_EVENT", "开始节点", new NodeUiConfig()
|
||||||
|
.setShape("circle")
|
||||||
|
.setSize(40, 40)
|
||||||
|
.setStyle("#e8f7ff", "#1890ff", "play-circle")
|
||||||
|
.setPorts(Arrays.asList("out"))),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 结束节点 - 流程的终点
|
||||||
|
* 功能:
|
||||||
|
* - 标记流程的结束位置
|
||||||
|
* - 可以定义流程结束时的清理操作
|
||||||
|
* - 可以设置流程结果和返回值
|
||||||
|
*
|
||||||
|
* 使用场景:
|
||||||
|
* - 流程正常结束
|
||||||
|
* - 流程异常终止
|
||||||
|
* - 需要返回处理结果
|
||||||
|
*
|
||||||
|
* 限制:
|
||||||
|
* - 每个流程必须有且仅有一个结束节点
|
||||||
|
* - 只能有入边,不能有出边
|
||||||
|
*/
|
||||||
|
END_EVENT("END_EVENT", "结束节点", new NodeUiConfig()
|
||||||
|
.setShape("circle")
|
||||||
|
.setSize(40, 40)
|
||||||
|
.setStyle("#fff1f0", "#ff4d4f", "stop")
|
||||||
|
.setPorts(Arrays.asList("in"))),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户任务节点 - 需要人工处理的任务
|
||||||
|
* 功能:
|
||||||
|
* - 分配任务给指定用户或角色
|
||||||
|
* - 支持任务表单的填写
|
||||||
|
* - 可以设置处理期限和提醒
|
||||||
|
* - 支持任务的转办、委托、退回
|
||||||
|
*
|
||||||
|
* 使用场景:
|
||||||
|
* - 审批流程
|
||||||
|
* - 表单填写
|
||||||
|
* - 人工审核
|
||||||
|
* - 数据确认
|
||||||
|
*
|
||||||
|
* 配置项:
|
||||||
|
* - 处理人/角色
|
||||||
|
* - 表单定义
|
||||||
|
* - 处理期限
|
||||||
|
* - 催办规则
|
||||||
|
*/
|
||||||
|
USER_TASK("USER_TASK", "用户任务", new NodeUiConfig()
|
||||||
|
.setShape("rectangle")
|
||||||
|
.setSize(120, 60)
|
||||||
|
.setStyle("#ffffff", "#1890ff", "user")
|
||||||
|
.setPorts(Arrays.asList("in", "out"))),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 服务任务节点 - 自动执行的系统服务
|
||||||
|
* 功能:
|
||||||
|
* - 调用系统服务或外部接口
|
||||||
|
* - 执行自动化操作
|
||||||
|
* - 支持异步执行和结果回调
|
||||||
|
* - 可以进行数据转换和处理
|
||||||
|
*
|
||||||
|
* 使用场景:
|
||||||
|
* - 调用外部系统API
|
||||||
|
* - 发送通知消息
|
||||||
|
* - 数据同步处理
|
||||||
|
* - 自动化操作
|
||||||
|
*
|
||||||
|
* 配置项:
|
||||||
|
* - 服务类型
|
||||||
|
* - 接口参数
|
||||||
|
* - 超时设置
|
||||||
|
* - 重试策略
|
||||||
|
*/
|
||||||
|
SERVICE_TASK("SERVICE_TASK", "服务任务", new NodeUiConfig()
|
||||||
|
.setShape("rectangle")
|
||||||
|
.setSize(120, 60)
|
||||||
|
.setStyle("#ffffff", "#1890ff", "api")
|
||||||
|
.setPorts(Arrays.asList("in", "out"))),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 脚本任务节点 - 执行自定义脚本
|
||||||
|
* 功能:
|
||||||
|
* - 执行自定义脚本代码
|
||||||
|
* - 支持多种脚本语言
|
||||||
|
* - 可以访问流程变量
|
||||||
|
* - 支持复杂的业务逻辑
|
||||||
|
*
|
||||||
|
* 使用场景:
|
||||||
|
* - 数据处理和转换
|
||||||
|
* - 条件判断
|
||||||
|
* - 自定义业务规则
|
||||||
|
* - 系统集成
|
||||||
|
*
|
||||||
|
* 配置项:
|
||||||
|
* - 脚本语言类型
|
||||||
|
* - 脚本内容
|
||||||
|
* - 资源限制
|
||||||
|
* - 超时设置
|
||||||
|
*/
|
||||||
|
SCRIPT_TASK("SCRIPT_TASK", "脚本任务", new NodeUiConfig()
|
||||||
|
.setShape("rectangle")
|
||||||
|
.setSize(120, 60)
|
||||||
|
.setStyle("#ffffff", "#1890ff", "code")
|
||||||
|
.setPorts(Arrays.asList("in", "out"))),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 排他网关 - 条件分支
|
||||||
|
* 功能:
|
||||||
|
* - 根据条件选择一个分支执行
|
||||||
|
* - 支持复杂的条件表达式
|
||||||
|
* - 可以设置默认分支
|
||||||
|
*
|
||||||
|
* 使用场景:
|
||||||
|
* - 条件判断
|
||||||
|
* - 分支选择
|
||||||
|
* - 业务规则路由
|
||||||
|
*
|
||||||
|
* 配置项:
|
||||||
|
* - 分支条件表达式
|
||||||
|
* - 默认分支设置
|
||||||
|
* - 条件优先级
|
||||||
|
*
|
||||||
|
* 限制:
|
||||||
|
* - 必须至少有两个出口
|
||||||
|
* - 条件必须互斥
|
||||||
|
*/
|
||||||
|
EXCLUSIVE_GATEWAY("EXCLUSIVE_GATEWAY", "排他网关", new NodeUiConfig()
|
||||||
|
.setShape("diamond")
|
||||||
|
.setSize(50, 50)
|
||||||
|
.setStyle("#fff7e6", "#faad14", "fork")
|
||||||
|
.setPorts(Arrays.asList("in", "out"))),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 并行网关 - 并行分支
|
||||||
|
* 功能:
|
||||||
|
* - 将流程分成多个并行分支
|
||||||
|
* - 等待所有分支完成后合并
|
||||||
|
* - 支持复杂的并行处理
|
||||||
|
*
|
||||||
|
* 使用场景:
|
||||||
|
* - 并行审批
|
||||||
|
* - 多任务同时处理
|
||||||
|
* - 并行数据处理
|
||||||
|
*
|
||||||
|
* 配置项:
|
||||||
|
* - 分支数量
|
||||||
|
* - 合并策略
|
||||||
|
* - 超时设置
|
||||||
|
*
|
||||||
|
* 限制:
|
||||||
|
* - 必须有对应的合并节点
|
||||||
|
* - 所有分支都必须完成才能继续
|
||||||
|
*/
|
||||||
|
PARALLEL_GATEWAY("PARALLEL_GATEWAY", "并行网关", new NodeUiConfig()
|
||||||
|
.setShape("diamond")
|
||||||
|
.setSize(50, 50)
|
||||||
|
.setStyle("#fff7e6", "#faad14", "branches")
|
||||||
|
.setPorts(Arrays.asList("in", "out"))),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 子流程节点 - 嵌入式子流程
|
||||||
|
* 功能:
|
||||||
|
* - 在当前流程中嵌入子流程
|
||||||
|
* - 可以重用流程片段
|
||||||
|
* - 支持事务处理
|
||||||
|
* - 可以有自己的变量范围
|
||||||
|
*
|
||||||
|
* 使用场景:
|
||||||
|
* - 流程复用
|
||||||
|
* - 模块化处理
|
||||||
|
* - 事务管理
|
||||||
|
* - 错误处理
|
||||||
|
*
|
||||||
|
* 配置项:
|
||||||
|
* - 子流程定义
|
||||||
|
* - 输入参数映射
|
||||||
|
* - 输出参数映射
|
||||||
|
* - 错误处理策略
|
||||||
|
*/
|
||||||
|
SUBPROCESS("SUB_PROCESS", "子流程", new NodeUiConfig()
|
||||||
|
.setShape("rectangle")
|
||||||
|
.setSize(120, 60)
|
||||||
|
.setStyle("#ffffff", "#1890ff", "apartment")
|
||||||
|
.setPorts(Arrays.asList("in", "out"))),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 调用活动节点 - 外部流程调用
|
||||||
|
* 功能:
|
||||||
|
* - 调用外部定义的流程
|
||||||
|
* - 支持跨系统流程调用
|
||||||
|
* - 可以传递和接收参数
|
||||||
|
* - 支持异步调用
|
||||||
|
*
|
||||||
|
* 使用场景:
|
||||||
|
* - 跨系统流程集成
|
||||||
|
* - 公共流程复用
|
||||||
|
* - 分布式流程处理
|
||||||
|
* - 大型流程解耦
|
||||||
|
*
|
||||||
|
* 配置项:
|
||||||
|
* - 目标流程定义
|
||||||
|
* - 版本控制
|
||||||
|
* - 参数映射
|
||||||
|
* - 调用方式(同步/异步)
|
||||||
|
*/
|
||||||
|
CALL_ACTIVITY("CALL_ACTIVITY", "调用活动", new NodeUiConfig()
|
||||||
|
.setShape("rectangle")
|
||||||
|
.setSize(120, 60)
|
||||||
|
.setStyle("#ffffff", "#1890ff", "api")
|
||||||
|
.setPorts(Arrays.asList("in", "out")));
|
||||||
|
|
||||||
@JsonValue
|
@JsonValue
|
||||||
private final String value;
|
private final String value;
|
||||||
|
|
||||||
private final String description;
|
private final String description;
|
||||||
|
private final NodeUiConfig uiConfig;
|
||||||
|
|
||||||
NodeTypeEnums(String value, String description) {
|
NodeTypeEnums(String value, String description, NodeUiConfig uiConfig) {
|
||||||
this.value = value;
|
this.value = value;
|
||||||
this.description = description;
|
this.description = description;
|
||||||
|
this.uiConfig = uiConfig;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getCode() {
|
/**
|
||||||
return value;
|
* 根据值查找对应的枚举
|
||||||
}
|
*
|
||||||
|
* @param value 枚举值
|
||||||
|
* @return 对应的枚举实例
|
||||||
|
* @throws IllegalArgumentException 当找不到对应的枚举值时抛出
|
||||||
|
*/
|
||||||
public static NodeTypeEnums fromValue(String value) {
|
public static NodeTypeEnums fromValue(String value) {
|
||||||
for (NodeTypeEnums type : values()) {
|
for (NodeTypeEnums type : values()) {
|
||||||
if (type.value.equals(value)) {
|
if (type.value.equals(value)) {
|
||||||
|
|||||||
@ -7,6 +7,7 @@ import org.flowable.bpmn.model.Process;
|
|||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -156,15 +157,15 @@ public class BpmnConverter {
|
|||||||
|
|
||||||
if (node.getConfig() != null) {
|
if (node.getConfig() != null) {
|
||||||
NodeConfig config = node.getConfig();
|
NodeConfig config = node.getConfig();
|
||||||
serviceTask.setImplementation(config.getImplementation());
|
// serviceTask.setImplementation(config.getImplementation());
|
||||||
if (config.getFields() != null) {
|
// if (config.getFields() != null) {
|
||||||
config.getFields().forEach((key, value) -> {
|
// config.getFields().forEach((key, value) -> {
|
||||||
FieldExtension field = new FieldExtension();
|
// FieldExtension field = new FieldExtension();
|
||||||
field.setFieldName(key);
|
// field.setFieldName(key);
|
||||||
field.setStringValue(value != null ? value.toString() : null);
|
// field.setStringValue(value != null ? value.toString() : null);
|
||||||
serviceTask.getFieldExtensions().add(field);
|
// serviceTask.getFieldExtensions().add(field);
|
||||||
});
|
// });
|
||||||
}
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
return serviceTask;
|
return serviceTask;
|
||||||
@ -181,14 +182,14 @@ public class BpmnConverter {
|
|||||||
userTask.setName(node.getName());
|
userTask.setName(node.getName());
|
||||||
|
|
||||||
if (node.getConfig() != null) {
|
if (node.getConfig() != null) {
|
||||||
NodeConfig config = node.getConfig();
|
// NodeConfig config = node.getConfig();
|
||||||
userTask.setAssignee(config.getAssignee());
|
// userTask.setAssignee(config.getAssignee());
|
||||||
userTask.setCandidateUsers(config.getCandidateUsers());
|
// userTask.setCandidateUsers(config.getCandidateUsers());
|
||||||
userTask.setCandidateGroups(config.getCandidateGroups());
|
// userTask.setCandidateGroups(config.getCandidateGroups());
|
||||||
userTask.setDueDate(config.getDueDate());
|
// userTask.setDueDate(config.getDueDate());
|
||||||
userTask.setPriority(config.getPriority() != null ? config.getPriority().toString() : null);
|
// userTask.setPriority(config.getPriority() != null ? config.getPriority().toString() : null);
|
||||||
userTask.setFormKey(config.getFormKey());
|
// userTask.setFormKey(config.getFormKey());
|
||||||
userTask.setSkipExpression(config.getSkipExpression());
|
// userTask.setSkipExpression(config.getSkipExpression());
|
||||||
}
|
}
|
||||||
|
|
||||||
return userTask;
|
return userTask;
|
||||||
@ -205,11 +206,11 @@ public class BpmnConverter {
|
|||||||
scriptTask.setName(node.getName());
|
scriptTask.setName(node.getName());
|
||||||
|
|
||||||
if (node.getConfig() != null) {
|
if (node.getConfig() != null) {
|
||||||
NodeConfig config = node.getConfig();
|
// NodeConfig config = node.getConfig();
|
||||||
scriptTask.setScriptFormat(config.getImplementation());
|
// scriptTask.setScriptFormat(config.getImplementation());
|
||||||
if (config.getFields() != null && config.getFields().containsKey("script")) {
|
// if (config.getFields() != null && config.getFields().containsKey("script")) {
|
||||||
scriptTask.setScript(config.getFields().get("script").toString());
|
// scriptTask.setScript(config.getFields().get("script").toString());
|
||||||
}
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
return scriptTask;
|
return scriptTask;
|
||||||
@ -263,15 +264,15 @@ public class BpmnConverter {
|
|||||||
|
|
||||||
if (node.getConfig() != null) {
|
if (node.getConfig() != null) {
|
||||||
NodeConfig config = node.getConfig();
|
NodeConfig config = node.getConfig();
|
||||||
callActivity.setCalledElement(config.getImplementation());
|
// callActivity.setCalledElement(config.getImplementation());
|
||||||
if (config.getFields() != null) {
|
// if (config.getFields() != null) {
|
||||||
config.getFields().forEach((key, value) -> {
|
// config.getFields().forEach((key, value) -> {
|
||||||
IOParameter parameter = new IOParameter();
|
// IOParameter parameter = new IOParameter();
|
||||||
parameter.setSource(key);
|
// parameter.setSource(key);
|
||||||
parameter.setTarget(value != null ? value.toString() : null);
|
// parameter.setTarget(value != null ? value.toString() : null);
|
||||||
callActivity.getInParameters().add(parameter);
|
// callActivity.getInParameters().add(parameter);
|
||||||
});
|
// });
|
||||||
}
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
return callActivity;
|
return callActivity;
|
||||||
|
|||||||
@ -1,39 +0,0 @@
|
|||||||
package com.qqchen.deploy.backend.workflow.util;
|
|
||||||
|
|
||||||
import com.fasterxml.jackson.databind.JsonNode;
|
|
||||||
import com.networknt.schema.JsonSchema;
|
|
||||||
import com.networknt.schema.JsonSchemaFactory;
|
|
||||||
import com.networknt.schema.SpecVersion;
|
|
||||||
import com.networknt.schema.ValidationMessage;
|
|
||||||
import com.qqchen.deploy.backend.framework.exception.BusinessException;
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
|
||||||
import org.springframework.stereotype.Component;
|
|
||||||
|
|
||||||
import java.util.Set;
|
|
||||||
import java.util.stream.Collectors;
|
|
||||||
|
|
||||||
@Slf4j
|
|
||||||
@Component
|
|
||||||
public class JsonSchemaValidator {
|
|
||||||
private final JsonSchemaFactory factory = JsonSchemaFactory.getInstance(SpecVersion.VersionFlag.V7);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 验证JSON数据是否符合Schema
|
|
||||||
*/
|
|
||||||
public void validate(JsonNode data, JsonNode schema) {
|
|
||||||
try {
|
|
||||||
JsonSchema jsonSchema = factory.getSchema(schema);
|
|
||||||
Set<ValidationMessage> errors = jsonSchema.validate(data);
|
|
||||||
|
|
||||||
if (!errors.isEmpty()) {
|
|
||||||
String errorMessages = errors.stream()
|
|
||||||
.map(ValidationMessage::getMessage)
|
|
||||||
.collect(Collectors.joining(", "));
|
|
||||||
throw new IllegalStateException("JSON Schema validation failed: " + errorMessages);
|
|
||||||
}
|
|
||||||
} catch (Exception e) {
|
|
||||||
log.error("JSON Schema validation error", e);
|
|
||||||
throw new IllegalStateException("JSON Schema validation error: " + e.getMessage());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -11,6 +11,8 @@ import com.qqchen.deploy.backend.workflow.enums.NodeTypeEnums;
|
|||||||
import java.lang.reflect.Field;
|
import java.lang.reflect.Field;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Schema生成器
|
* Schema生成器
|
||||||
@ -18,39 +20,46 @@ import java.util.List;
|
|||||||
public class SchemaGenerator {
|
public class SchemaGenerator {
|
||||||
private static final ObjectMapper mapper = new ObjectMapper();
|
private static final ObjectMapper mapper = new ObjectMapper();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取节点类型对应的配置类
|
||||||
|
*/
|
||||||
|
private static Class<?> getConfigClassForNodeType(NodeTypeEnums nodeType) {
|
||||||
|
switch (nodeType) {
|
||||||
|
case START_EVENT:
|
||||||
|
return StartNodeConfig.class;
|
||||||
|
case END_EVENT:
|
||||||
|
return EndNodeConfig.class;
|
||||||
|
case SCRIPT_TASK:
|
||||||
|
return ScriptNodeConfig.class;
|
||||||
|
// 其他节点类型的配置类
|
||||||
|
case USER_TASK:
|
||||||
|
case SERVICE_TASK:
|
||||||
|
case EXCLUSIVE_GATEWAY:
|
||||||
|
case PARALLEL_GATEWAY:
|
||||||
|
case SUBPROCESS:
|
||||||
|
case CALL_ACTIVITY:
|
||||||
|
// TODO: 为其他节点类型添加对应的配置类
|
||||||
|
return BaseNodeConfig.class;
|
||||||
|
default:
|
||||||
|
return BaseNodeConfig.class;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 生成所有节点类型的schema
|
* 生成所有节点类型的schema
|
||||||
*/
|
*/
|
||||||
public static JsonNode generateAllNodeTypeSchemas() {
|
public static JsonNode generateAllNodeTypeSchemas() {
|
||||||
ObjectNode schemas = mapper.createObjectNode();
|
ArrayNode schemas = mapper.createArrayNode();
|
||||||
|
|
||||||
// // 生成开始节点schema
|
// 遍历所有节点类型
|
||||||
// ObjectNode startNode = generateNodeSchema("START", "开始", "开始节点", StartNodeConfig.class);
|
for (NodeTypeEnums nodeType : NodeTypeEnums.values()) {
|
||||||
// schemas.set("START", startNode);
|
// 获取节点类型对应的配置类
|
||||||
//
|
Class<?> configClass = getConfigClassForNodeType(nodeType);
|
||||||
// // 生成脚本节点schema
|
// 生成该节点类型的schema
|
||||||
// ObjectNode scriptNode = generateNodeSchema("SCRIPT", "脚本执行", "执行脚本任务", ScriptNodeConfig.class);
|
ObjectNode nodeSchema = generateNodeSchema(nodeType, configClass);
|
||||||
// schemas.set("SCRIPT", scriptNode);
|
schemas.add(nodeSchema);
|
||||||
//
|
}
|
||||||
// // 生成Git克隆节点schema
|
|
||||||
// ObjectNode gitNode = generateNodeSchema("GIT_CLONE", "Git克隆", "克隆Git仓库", GitCloneConfig.class);
|
|
||||||
// schemas.set("GIT_CLONE", gitNode);
|
|
||||||
//
|
|
||||||
//
|
|
||||||
// // 生成事件节点schema
|
|
||||||
// ObjectNode eventNode = generateNodeSchema("EVENT", "事件", "事件节点", BaseEventNodeConfig.class);
|
|
||||||
// schemas.set("EVENT", eventNode);
|
|
||||||
//
|
|
||||||
// // 生成结束节点schema
|
|
||||||
// ObjectNode endNode = generateNodeSchema("END", "结束", "结束节点", EndNodeConfig.class);
|
|
||||||
// schemas.set("END", endNode);
|
|
||||||
|
|
||||||
ObjectNode startNode = generateNodeSchema(NodeTypeEnums.START_EVENT, StartNodeConfig.class);
|
|
||||||
schemas.set(NodeTypeEnums.START_EVENT.getCode(), startNode);
|
|
||||||
ObjectNode scriptNode = generateNodeSchema(NodeTypeEnums.SCRIPT_TASK, ScriptNodeConfig.class);
|
|
||||||
schemas.set(NodeTypeEnums.SCRIPT_TASK.getCode(), scriptNode);
|
|
||||||
ObjectNode endNode = generateNodeSchema(NodeTypeEnums.END_EVENT, EndNodeConfig.class);
|
|
||||||
schemas.set(NodeTypeEnums.END_EVENT.getCode(), endNode);
|
|
||||||
return schemas;
|
return schemas;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -58,11 +67,18 @@ public class SchemaGenerator {
|
|||||||
* 生成节点schema
|
* 生成节点schema
|
||||||
*/
|
*/
|
||||||
private static ObjectNode generateNodeSchema(NodeTypeEnums nodeType, Class<?> configClass) {
|
private static ObjectNode generateNodeSchema(NodeTypeEnums nodeType, Class<?> configClass) {
|
||||||
NodeTypeSchemaConfig node = new NodeTypeSchemaConfig();
|
ObjectNode node = mapper.createObjectNode();
|
||||||
node.setCode(nodeType);
|
|
||||||
node.setDescription(nodeType.getDescription());
|
// 设置基本信息
|
||||||
ObjectNode schema = generateConfigSchema(configClass);
|
node.put("code", nodeType.getCode());
|
||||||
return schema;
|
node.put("name", nodeType.getDescription());
|
||||||
|
node.put("description", nodeType.getDescription());
|
||||||
|
|
||||||
|
// 生成配置schema并设置到configSchema字段
|
||||||
|
ObjectNode configSchema = generateConfigSchema(configClass);
|
||||||
|
node.set("configSchema", configSchema);
|
||||||
|
|
||||||
|
return node;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -72,27 +88,15 @@ public class SchemaGenerator {
|
|||||||
ObjectNode schema = mapper.createObjectNode();
|
ObjectNode schema = mapper.createObjectNode();
|
||||||
schema.put("type", "object");
|
schema.put("type", "object");
|
||||||
|
|
||||||
|
// 创建一个有序的properties对象
|
||||||
ObjectNode properties = mapper.createObjectNode();
|
ObjectNode properties = mapper.createObjectNode();
|
||||||
List<String> required = new ArrayList<>();
|
List<String> required = new ArrayList<>();
|
||||||
|
|
||||||
// 处理所有字段
|
// 先处理基础字段(按指定顺序)
|
||||||
for (Field field : configClass.getDeclaredFields()) {
|
processBaseFields(properties, required, configClass);
|
||||||
SchemaProperty annotation = field.getAnnotation(SchemaProperty.class);
|
|
||||||
if (annotation != null) {
|
|
||||||
processField(properties, required, field, annotation);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 处理父类字段
|
// 处理其他字段
|
||||||
Class<?> superClass = configClass.getSuperclass();
|
processRemainingFields(properties, required, configClass);
|
||||||
if (superClass != null && !superClass.equals(Object.class)) {
|
|
||||||
for (Field field : superClass.getDeclaredFields()) {
|
|
||||||
SchemaProperty annotation = field.getAnnotation(SchemaProperty.class);
|
|
||||||
if (annotation != null) {
|
|
||||||
processField(properties, required, field, annotation);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
schema.set("properties", properties);
|
schema.set("properties", properties);
|
||||||
if (!required.isEmpty()) {
|
if (!required.isEmpty()) {
|
||||||
@ -103,109 +107,183 @@ public class SchemaGenerator {
|
|||||||
return schema;
|
return schema;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 处理基础字段(code、name、description)
|
||||||
|
*/
|
||||||
|
private static void processBaseFields(ObjectNode properties, List<String> required, Class<?> configClass) {
|
||||||
|
String[] baseFields = {"code", "name", "description"};
|
||||||
|
Class<?> currentClass = configClass;
|
||||||
|
|
||||||
|
while (currentClass != null && !currentClass.equals(Object.class)) {
|
||||||
|
for (String fieldName : baseFields) {
|
||||||
|
try {
|
||||||
|
Field field = currentClass.getDeclaredField(fieldName);
|
||||||
|
SchemaProperty annotation = field.getAnnotation(SchemaProperty.class);
|
||||||
|
if (annotation != null && !properties.has(fieldName)) {
|
||||||
|
processField(properties, required, field, annotation);
|
||||||
|
}
|
||||||
|
} catch (NoSuchFieldException ignored) {
|
||||||
|
// 字段不在当前类中,继续查找父类
|
||||||
|
}
|
||||||
|
}
|
||||||
|
currentClass = currentClass.getSuperclass();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 处理剩余字段
|
||||||
|
*/
|
||||||
|
private static void processRemainingFields(ObjectNode properties, List<String> required, Class<?> configClass) {
|
||||||
|
Set<String> baseFields = Set.of("code", "name", "description");
|
||||||
|
Class<?> currentClass = configClass;
|
||||||
|
|
||||||
|
while (currentClass != null && !currentClass.equals(Object.class)) {
|
||||||
|
for (Field field : currentClass.getDeclaredFields()) {
|
||||||
|
String fieldName = field.getName();
|
||||||
|
if (!baseFields.contains(fieldName)) {
|
||||||
|
SchemaProperty annotation = field.getAnnotation(SchemaProperty.class);
|
||||||
|
if (annotation != null && !properties.has(fieldName)) {
|
||||||
|
processField(properties, required, field, annotation);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
currentClass = currentClass.getSuperclass();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 处理字段
|
* 处理字段
|
||||||
*/
|
*/
|
||||||
private static void processField(ObjectNode properties, List<String> required, Field field, SchemaProperty annotation) {
|
private static void processField(ObjectNode properties, List<String> required, Field field, SchemaProperty annotation) {
|
||||||
ObjectNode property = properties.putObject(field.getName());
|
ObjectNode fieldSchema = mapper.createObjectNode();
|
||||||
|
Class<?> fieldType = field.getType();
|
||||||
// 设置类型
|
|
||||||
String type = getJsonSchemaType(field.getType());
|
// 设置字段类型
|
||||||
property.put("type", type);
|
String jsonType = getJsonSchemaType(fieldType);
|
||||||
|
fieldSchema.put("type", jsonType);
|
||||||
// 设置标题和描述
|
|
||||||
if (!annotation.title().isEmpty()) {
|
// 设置基本属性
|
||||||
property.put("title", annotation.title());
|
fieldSchema.put("title", annotation.title());
|
||||||
}
|
|
||||||
if (!annotation.description().isEmpty()) {
|
if (!annotation.description().isEmpty()) {
|
||||||
property.put("description", annotation.description());
|
fieldSchema.put("description", annotation.description());
|
||||||
}
|
}
|
||||||
|
|
||||||
// 设置必填
|
// 处理format
|
||||||
|
if (!annotation.format().isEmpty()) {
|
||||||
|
fieldSchema.put("format", annotation.format());
|
||||||
|
}
|
||||||
|
|
||||||
|
// 处理默认值
|
||||||
|
if (!annotation.defaultValue().isEmpty()) {
|
||||||
|
setDefaultValue(fieldSchema, fieldType, annotation.defaultValue());
|
||||||
|
}
|
||||||
|
|
||||||
|
// 处理数值范围
|
||||||
|
if (isNumberType(fieldType)) {
|
||||||
|
if (annotation.minimum() != Integer.MIN_VALUE) {
|
||||||
|
fieldSchema.put("minimum", annotation.minimum());
|
||||||
|
}
|
||||||
|
if (annotation.maximum() != Integer.MAX_VALUE) {
|
||||||
|
fieldSchema.put("maximum", annotation.maximum());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 处理枚举值
|
||||||
|
if (annotation.enumValues().length > 0) {
|
||||||
|
ArrayNode enumValues = fieldSchema.putArray("enum");
|
||||||
|
for (String value : annotation.enumValues()) {
|
||||||
|
enumValues.add(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 如果有枚举显示名称
|
||||||
|
if (annotation.enumNames().length > 0) {
|
||||||
|
ArrayNode enumNames = fieldSchema.putArray("enumNames");
|
||||||
|
for (String name : annotation.enumNames()) {
|
||||||
|
enumNames.add(name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 处理数组类型
|
||||||
|
if (jsonType.equals("array")) {
|
||||||
|
ObjectNode items = fieldSchema.putObject("items");
|
||||||
|
if (field.getType().isArray()) {
|
||||||
|
Class<?> componentType = field.getType().getComponentType();
|
||||||
|
items.put("type", getJsonSchemaType(componentType));
|
||||||
|
} else {
|
||||||
|
// 默认为字符串类型
|
||||||
|
items.put("type", "string");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 处理对象类型
|
||||||
|
if (jsonType.equals("object") && Map.class.isAssignableFrom(fieldType)) {
|
||||||
|
ObjectNode additionalProperties = fieldSchema.putObject("additionalProperties");
|
||||||
|
additionalProperties.put("type", "string");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 如果是必填字段,添加到required列表
|
||||||
if (annotation.required()) {
|
if (annotation.required()) {
|
||||||
required.add(field.getName());
|
required.add(field.getName());
|
||||||
}
|
}
|
||||||
|
|
||||||
// 设置格式
|
properties.set(field.getName(), fieldSchema);
|
||||||
if (!annotation.format().isEmpty()) {
|
}
|
||||||
property.put("format", annotation.format());
|
|
||||||
}
|
|
||||||
|
|
||||||
// 设置默认值
|
/**
|
||||||
if (!annotation.defaultValue().isEmpty()) {
|
* 设置默认值(根据字段类型进行类型转换)
|
||||||
setDefaultValue(property, type, annotation.defaultValue());
|
*/
|
||||||
}
|
private static void setDefaultValue(ObjectNode fieldSchema, Class<?> fieldType, String defaultValue) {
|
||||||
|
if (isNumberType(fieldType)) {
|
||||||
// 设置数值范围
|
try {
|
||||||
if ("integer".equals(type) || "number".equals(type)) {
|
if (fieldType == Integer.class || fieldType == int.class) {
|
||||||
if (annotation.minimum() != Integer.MIN_VALUE) {
|
fieldSchema.put("default", Integer.parseInt(defaultValue));
|
||||||
property.put("minimum", annotation.minimum());
|
} else if (fieldType == Long.class || fieldType == long.class) {
|
||||||
}
|
fieldSchema.put("default", Long.parseLong(defaultValue));
|
||||||
if (annotation.maximum() != Integer.MAX_VALUE) {
|
} else if (fieldType == Double.class || fieldType == double.class) {
|
||||||
property.put("maximum", annotation.maximum());
|
fieldSchema.put("default", Double.parseDouble(defaultValue));
|
||||||
}
|
} else if (fieldType == Float.class || fieldType == float.class) {
|
||||||
}
|
fieldSchema.put("default", Float.parseFloat(defaultValue));
|
||||||
|
|
||||||
// 设置枚举值
|
|
||||||
if (annotation.enumValues().length > 0) {
|
|
||||||
ArrayNode enumArray = property.putArray("enum");
|
|
||||||
for (String value : annotation.enumValues()) {
|
|
||||||
enumArray.add(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (annotation.enumNames().length > 0) {
|
|
||||||
ArrayNode enumNamesArray = property.putArray("enumNames");
|
|
||||||
for (String name : annotation.enumNames()) {
|
|
||||||
enumNamesArray.add(name);
|
|
||||||
}
|
}
|
||||||
|
} catch (NumberFormatException e) {
|
||||||
|
// 如果转换失败,使用字符串形式
|
||||||
|
fieldSchema.put("default", defaultValue);
|
||||||
}
|
}
|
||||||
|
} else if (fieldType == Boolean.class || fieldType == boolean.class) {
|
||||||
|
fieldSchema.put("default", Boolean.parseBoolean(defaultValue));
|
||||||
|
} else {
|
||||||
|
fieldSchema.put("default", defaultValue);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 判断是否为数值类型
|
||||||
|
*/
|
||||||
|
private static boolean isNumberType(Class<?> type) {
|
||||||
|
return type == Integer.class || type == int.class ||
|
||||||
|
type == Long.class || type == long.class ||
|
||||||
|
type == Double.class || type == double.class ||
|
||||||
|
type == Float.class || type == float.class;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取JSON Schema类型
|
* 获取JSON Schema类型
|
||||||
*/
|
*/
|
||||||
private static String getJsonSchemaType(Class<?> type) {
|
private static String getJsonSchemaType(Class<?> type) {
|
||||||
if (type == String.class) {
|
if (type == String.class) {
|
||||||
return "string";
|
return "string";
|
||||||
} else if (type == Integer.class || type == int.class) {
|
} else if (type == Integer.class || type == int.class || type == Long.class || type == long.class) {
|
||||||
return "integer";
|
return "integer";
|
||||||
} else if (type == Double.class || type == double.class || type == Float.class || type == float.class) {
|
|
||||||
return "number";
|
|
||||||
} else if (type == Boolean.class || type == boolean.class) {
|
} else if (type == Boolean.class || type == boolean.class) {
|
||||||
return "boolean";
|
return "boolean";
|
||||||
|
} else if (type == Double.class || type == double.class || type == Float.class || type == float.class) {
|
||||||
|
return "number";
|
||||||
} else if (type.isArray() || List.class.isAssignableFrom(type)) {
|
} else if (type.isArray() || List.class.isAssignableFrom(type)) {
|
||||||
return "array";
|
return "array";
|
||||||
|
} else if (type.isEnum()) {
|
||||||
|
return "string";
|
||||||
} else {
|
} else {
|
||||||
return "object";
|
return "object";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 设置默认值
|
|
||||||
*/
|
|
||||||
private static void setDefaultValue(ObjectNode property, String type, String defaultValue) {
|
|
||||||
switch (type) {
|
|
||||||
case "string":
|
|
||||||
property.put("default", defaultValue);
|
|
||||||
break;
|
|
||||||
case "integer":
|
|
||||||
try {
|
|
||||||
property.put("default", Integer.parseInt(defaultValue));
|
|
||||||
} catch (NumberFormatException e) {
|
|
||||||
// 忽略无效的默认值
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case "number":
|
|
||||||
try {
|
|
||||||
property.put("default", Double.parseDouble(defaultValue));
|
|
||||||
} catch (NumberFormatException e) {
|
|
||||||
// 忽略无效的默认值
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case "boolean":
|
|
||||||
property.put("default", Boolean.parseBoolean(defaultValue));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -492,7 +492,6 @@ CREATE TABLE workflow_node_definition (
|
|||||||
category VARCHAR(50) NOT NULL COMMENT '节点分类',
|
category VARCHAR(50) NOT NULL COMMENT '节点分类',
|
||||||
flowable_config TEXT COMMENT 'Flowable引擎配置JSON',
|
flowable_config TEXT COMMENT 'Flowable引擎配置JSON',
|
||||||
graph_config TEXT NOT NULL COMMENT 'X6图形配置JSON',
|
graph_config TEXT NOT NULL COMMENT 'X6图形配置JSON',
|
||||||
form_config TEXT COMMENT '表单配置JSON',
|
|
||||||
order_num INT NOT NULL DEFAULT 0 COMMENT '排序号',
|
order_num INT NOT NULL DEFAULT 0 COMMENT '排序号',
|
||||||
enabled BOOLEAN NOT NULL DEFAULT TRUE COMMENT '是否启用',
|
enabled BOOLEAN NOT NULL DEFAULT TRUE COMMENT '是否启用',
|
||||||
create_time DATETIME NOT NULL COMMENT '创建时间',
|
create_time DATETIME NOT NULL COMMENT '创建时间',
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user