增加formily json schema生成
This commit is contained in:
parent
4c79000f30
commit
a76685bbd6
@ -3,6 +3,8 @@ package com.qqchen.deploy.backend.deploy.dto.variables.build;
|
|||||||
import com.qqchen.deploy.backend.framework.annotation.formily.*;
|
import com.qqchen.deploy.backend.framework.annotation.formily.*;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Jenkins构建变量
|
* Jenkins构建变量
|
||||||
*/
|
*/
|
||||||
@ -10,105 +12,136 @@ import lombok.Data;
|
|||||||
@FormilyForm(name = "Jenkins构建配置")
|
@FormilyForm(name = "Jenkins构建配置")
|
||||||
public class JenkinsBaseBuildVariables {
|
public class JenkinsBaseBuildVariables {
|
||||||
|
|
||||||
@FormilyField(
|
// @FormilyField(
|
||||||
title = "绑定三方Jenkins系统",
|
// title = "绑定三方Jenkins系统",
|
||||||
type = "string",
|
// component = "Select",
|
||||||
component = "Select",
|
// order = 1,
|
||||||
props = @FormilyComponentProps(
|
// props = @FormilyComponentProps(
|
||||||
api = "/api/v1/external-system/list?type=JENKINS",
|
// labelField = "name",
|
||||||
labelField = "name",
|
// valueField = "id",
|
||||||
valueField = "id",
|
// allowClear = true,
|
||||||
showSearch = true,
|
// showSearch = true,
|
||||||
allowClear = true,
|
// placeholder = "请选择Jenkins系统"
|
||||||
placeholder = "请选择Jenkins系统"
|
// ),
|
||||||
),
|
// validators = {
|
||||||
validators = {
|
// @FormilyValidator(
|
||||||
@FormilyValidator(
|
// required = true,
|
||||||
required = true,
|
// message = "请选择Jenkins系统"
|
||||||
message = "请选择Jenkins系统"
|
// )
|
||||||
)
|
// },
|
||||||
}
|
// reactions = {
|
||||||
)
|
// @FormilyReaction(
|
||||||
private String externalSystemId;
|
// state = "dataSource",
|
||||||
|
// value = "{{$fetch('/api/v1/external-system/list?type=JENKINS').then(data => data.data)}}",
|
||||||
@FormilyField(
|
// when = "{{$form.mounted && $form.values.__modalVisible}}"
|
||||||
title = "绑定Jenkins视图",
|
// )
|
||||||
type = "string",
|
// }
|
||||||
component = "Select",
|
// )
|
||||||
props = @FormilyComponentProps(
|
// private String externalSystemId;
|
||||||
labelField = "viewName",
|
//
|
||||||
valueField = "id",
|
// @FormilyField(
|
||||||
showSearch = true,
|
// title = "绑定Jenkins视图",
|
||||||
allowClear = true,
|
// component = "Select",
|
||||||
placeholder = "请选择Jenkins视图"
|
// order = 2,
|
||||||
),
|
// props = @FormilyComponentProps(
|
||||||
validators = {
|
// labelField = "viewName",
|
||||||
@FormilyValidator(
|
// valueField = "id",
|
||||||
required = true,
|
// allowClear = true,
|
||||||
message = "请选择Jenkins视图"
|
// showSearch = true,
|
||||||
)
|
// placeholder = "请选择Jenkins视图"
|
||||||
},
|
// ),
|
||||||
reactions = {
|
// validators = {
|
||||||
@FormilyReaction(
|
// @FormilyValidator(
|
||||||
dependencies = {"externalSystemId"},
|
// required = true,
|
||||||
state = "dataSource",
|
// message = "请选择Jenkins视图"
|
||||||
value = "{{$fetch('/api/v1/jenkins-view/list?externalSystemId=' + $deps.externalSystemId).then(data => data.data)}}"
|
// )
|
||||||
)
|
// },
|
||||||
}
|
// reactions = {
|
||||||
)
|
// @FormilyReaction(
|
||||||
private String viewId;
|
// dependencies = {"externalSystemId"},
|
||||||
|
// state = "dataSource",
|
||||||
@FormilyField(
|
// value = "{{$fetch('/api/v1/jenkins-view/list?externalSystemId=' + $deps.externalSystemId).then(data => data.data)}}"
|
||||||
title = "绑定Jenkins任务",
|
// )
|
||||||
type = "string",
|
// }
|
||||||
component = "Select",
|
// )
|
||||||
props = @FormilyComponentProps(
|
// private String viewId;
|
||||||
labelField = "jobName",
|
//
|
||||||
valueField = "id",
|
// @FormilyField(
|
||||||
showSearch = true,
|
// title = "绑定Jenkins任务",
|
||||||
allowClear = true,
|
// component = "Select",
|
||||||
placeholder = "请选择Jenkins任务"
|
// order = 3,
|
||||||
),
|
// props = @FormilyComponentProps(
|
||||||
validators = {
|
// labelField = "jobName",
|
||||||
@FormilyValidator(
|
// valueField = "id",
|
||||||
required = true,
|
// allowClear = true,
|
||||||
message = "请选择Jenkins任务"
|
// showSearch = true,
|
||||||
)
|
// placeholder = "请选择Jenkins任务"
|
||||||
},
|
// ),
|
||||||
reactions = {
|
// validators = {
|
||||||
@FormilyReaction(
|
// @FormilyValidator(
|
||||||
dependencies = {"externalSystemId", "viewId"},
|
// required = true,
|
||||||
state = "dataSource",
|
// message = "请选择Jenkins任务"
|
||||||
value = "{{$fetch('/api/v1/jenkins-job/list?externalSystemId=' + $deps.externalSystemId + '&viewId=' + $deps.viewId).then(data => data.data)}}"
|
// )
|
||||||
)
|
// },
|
||||||
}
|
// reactions = {
|
||||||
)
|
// @FormilyReaction(
|
||||||
private String jobId;
|
// dependencies = {"externalSystemId", "viewId"},
|
||||||
|
// state = "dataSource",
|
||||||
@FormilyField(
|
// value = "{{$fetch('/api/v1/jenkins-job/list?externalSystemId=' + $deps.externalSystemId + '&viewId=' + $deps.viewId).then(data => data.data)}}"
|
||||||
title = "Pipeline script",
|
// )
|
||||||
type = "string",
|
// }
|
||||||
component = "MonacoEditor",
|
// )
|
||||||
props = @FormilyComponentProps(
|
// private String jobId;
|
||||||
editor = @FormilyEditorProps(
|
//
|
||||||
language = "groovy",
|
// @FormilyField(
|
||||||
theme = "vs-dark",
|
// title = "环境变量",
|
||||||
minimap = false,
|
// type = "map",
|
||||||
lineNumbers = true,
|
// order = 4,
|
||||||
wordWrap = true,
|
// mapConfig = @FormilyMapConfig(
|
||||||
fontSize = 14,
|
// keyTitle = "变量名",
|
||||||
tabSize = 4,
|
// valueTitle = "变量值",
|
||||||
automaticLayout = true,
|
// keyComponent = "Select",
|
||||||
folding = true,
|
// valueComponent = "Input",
|
||||||
placeholder = "请输入Pipeline脚本"
|
// keyProps = @FormilyComponentProps(
|
||||||
)
|
//// api = "/api/v1/env-vars/keys",
|
||||||
),
|
// showSearch = true,
|
||||||
validators = {
|
// allowClear = true,
|
||||||
@FormilyValidator(
|
// placeholder = "请选择或输入变量名"
|
||||||
required = true,
|
// ),
|
||||||
message = "请输入Pipeline脚本"
|
// valueProps = @FormilyComponentProps(
|
||||||
)
|
// placeholder = "请输入变量值"
|
||||||
}
|
// ),
|
||||||
)
|
// addText = "添加环境变量",
|
||||||
private String script;
|
// allowCustomKey = true
|
||||||
|
// )
|
||||||
|
// )
|
||||||
|
// private Map<String, String> envVars;
|
||||||
|
//
|
||||||
|
// @FormilyField(
|
||||||
|
// title = "Pipeline script",
|
||||||
|
// type = "string",
|
||||||
|
// component = "MonacoEditor",
|
||||||
|
// order = 5,
|
||||||
|
// props = @FormilyComponentProps(
|
||||||
|
// editor = @FormilyEditorProps(
|
||||||
|
// language = "groovy",
|
||||||
|
// theme = "vs-dark",
|
||||||
|
// minimap = false,
|
||||||
|
// lineNumbers = true,
|
||||||
|
// wordWrap = true,
|
||||||
|
// fontSize = 14,
|
||||||
|
// tabSize = 4,
|
||||||
|
// automaticLayout = true,
|
||||||
|
// folding = true,
|
||||||
|
// placeholder = "请输入Pipeline脚本"
|
||||||
|
// )
|
||||||
|
// ),
|
||||||
|
// validators = {
|
||||||
|
// @FormilyValidator(
|
||||||
|
// required = true,
|
||||||
|
// message = "请输入Pipeline脚本"
|
||||||
|
// )
|
||||||
|
// }
|
||||||
|
// )
|
||||||
|
// private String script;
|
||||||
}
|
}
|
||||||
@ -2,22 +2,86 @@ package com.qqchen.deploy.backend.framework.annotation.formily;
|
|||||||
|
|
||||||
import java.lang.annotation.Retention;
|
import java.lang.annotation.Retention;
|
||||||
import java.lang.annotation.RetentionPolicy;
|
import java.lang.annotation.RetentionPolicy;
|
||||||
import java.lang.annotation.Target;
|
|
||||||
import java.lang.annotation.ElementType;
|
|
||||||
|
|
||||||
@Target({ElementType.FIELD})
|
|
||||||
@Retention(RetentionPolicy.RUNTIME)
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
public @interface FormilyComponentProps {
|
public @interface FormilyComponentProps {
|
||||||
String api() default ""; // 数据源API
|
/**
|
||||||
String labelField() default "label"; // 标签字段
|
* 占位符
|
||||||
String valueField() default "value"; // 值字段
|
*/
|
||||||
boolean allowClear() default false; // 允许清除
|
String placeholder() default "";
|
||||||
boolean showSearch() default false; // 显示搜索
|
|
||||||
String placeholder() default ""; // 占位符
|
|
||||||
String mode() default ""; // 模式(single/multiple等)
|
|
||||||
String[] enum_() default {}; // 枚举值
|
|
||||||
String[] enumNames() default {}; // 枚举显示值
|
|
||||||
|
|
||||||
// 编辑器属性
|
/**
|
||||||
FormilyEditorProps editor() default @FormilyEditorProps; // 编辑器配置
|
* 是否允许清除
|
||||||
|
*/
|
||||||
|
boolean allowClear() default false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 是否允许搜索
|
||||||
|
*/
|
||||||
|
boolean showSearch() default false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 选择模式 (single/multiple)
|
||||||
|
*/
|
||||||
|
String mode() default "single";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 是否启用过滤
|
||||||
|
*/
|
||||||
|
boolean filterOption() default true;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 标签字段名
|
||||||
|
*/
|
||||||
|
String labelField() default "label";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 值字段名
|
||||||
|
*/
|
||||||
|
String valueField() default "value";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 防抖时间(ms)
|
||||||
|
*/
|
||||||
|
int debounceTime() default 300;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 枚举值
|
||||||
|
*/
|
||||||
|
String[] enum_() default {};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 枚举标签
|
||||||
|
*/
|
||||||
|
String[] enumNames() default {};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 编辑器配置
|
||||||
|
*/
|
||||||
|
FormilyEditorProps editor() default @FormilyEditorProps;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 是否加载中
|
||||||
|
*/
|
||||||
|
boolean loading() default false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 是否禁用
|
||||||
|
*/
|
||||||
|
boolean disabled() default false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 最大长度
|
||||||
|
*/
|
||||||
|
int maxLength() default -1;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 最小长度
|
||||||
|
*/
|
||||||
|
int minLength() default -1;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 正则表达式
|
||||||
|
*/
|
||||||
|
String pattern() default "";
|
||||||
}
|
}
|
||||||
@ -1,25 +1,22 @@
|
|||||||
package com.qqchen.deploy.backend.framework.annotation.formily;
|
package com.qqchen.deploy.backend.framework.annotation.formily;
|
||||||
|
|
||||||
import java.lang.annotation.ElementType;
|
|
||||||
import java.lang.annotation.Retention;
|
import java.lang.annotation.Retention;
|
||||||
import java.lang.annotation.RetentionPolicy;
|
import java.lang.annotation.RetentionPolicy;
|
||||||
import java.lang.annotation.Target;
|
|
||||||
|
|
||||||
@Target({ElementType.FIELD})
|
|
||||||
@Retention(RetentionPolicy.RUNTIME)
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
public @interface FormilyEditorProps {
|
public @interface FormilyEditorProps {
|
||||||
/**
|
/**
|
||||||
* 编辑器语言
|
* 编程语言
|
||||||
*/
|
*/
|
||||||
String language() default "plaintext";
|
String language() default "javascript";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 编辑器主题
|
* 主题
|
||||||
*/
|
*/
|
||||||
String theme() default "vs";
|
String theme() default "vs";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 是否启用小地图
|
* 是否显示小地图
|
||||||
*/
|
*/
|
||||||
boolean minimap() default true;
|
boolean minimap() default true;
|
||||||
|
|
||||||
@ -31,7 +28,7 @@ public @interface FormilyEditorProps {
|
|||||||
/**
|
/**
|
||||||
* 是否自动换行
|
* 是否自动换行
|
||||||
*/
|
*/
|
||||||
boolean wordWrap() default false;
|
String wordWrap() default "off";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 字体大小
|
* 字体大小
|
||||||
@ -54,7 +51,37 @@ public @interface FormilyEditorProps {
|
|||||||
boolean folding() default true;
|
boolean folding() default true;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 占位符文本
|
* 是否允许滚动到最后一行之后
|
||||||
*/
|
*/
|
||||||
String placeholder() default "";
|
boolean scrollBeyondLastLine() default false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 是否启用建议
|
||||||
|
*/
|
||||||
|
boolean suggestOnTriggerCharacters() default true;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 是否启用代码片段建议
|
||||||
|
*/
|
||||||
|
boolean snippetsPreventQuickSuggestions() default false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 垂直滚动条
|
||||||
|
*/
|
||||||
|
String scrollbarVertical() default "auto";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 水平滚动条
|
||||||
|
*/
|
||||||
|
String scrollbarHorizontal() default "auto";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 防抖时间(ms)
|
||||||
|
*/
|
||||||
|
int debounceTime() default 300;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 是否只读
|
||||||
|
*/
|
||||||
|
boolean readOnly() default false;
|
||||||
}
|
}
|
||||||
@ -8,29 +8,93 @@ import java.lang.annotation.Target;
|
|||||||
@Target(ElementType.FIELD)
|
@Target(ElementType.FIELD)
|
||||||
@Retention(RetentionPolicy.RUNTIME)
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
public @interface FormilyField {
|
public @interface FormilyField {
|
||||||
// 基础属性
|
/**
|
||||||
String title(); // 字段标题
|
* 字段标题
|
||||||
String description() default ""; // 字段描述
|
*/
|
||||||
String type() default "string"; // 字段类型(string/number/boolean/array/object/map)
|
String title();
|
||||||
int order() default Integer.MAX_VALUE; // 字段顺序,值越小越靠前
|
|
||||||
|
|
||||||
// 组件属性
|
/**
|
||||||
String component() default "Input"; // 组件类型
|
* 字段描述
|
||||||
String decorator() default "FormItem"; // 装饰器类型
|
*/
|
||||||
FormilyComponentProps props() default @FormilyComponentProps; // 组件属性
|
String description() default "";
|
||||||
FormilyDecoratorProps decoratorProps() default @FormilyDecoratorProps; // 装饰器属性
|
|
||||||
|
|
||||||
// 校验规则
|
/**
|
||||||
FormilyValidator[] validators() default {}; // 校验规则
|
* 字段类型
|
||||||
|
*/
|
||||||
|
String type() default "string";
|
||||||
|
|
||||||
// 联动配置
|
/**
|
||||||
FormilyReaction[] reactions() default {}; // 联动规则
|
* 默认值
|
||||||
|
*/
|
||||||
|
String defaultValue() default "";
|
||||||
|
|
||||||
// 展示控制
|
/**
|
||||||
String pattern() default "editable"; // 展示模式(editable/disabled/readOnly)
|
* 组件类型
|
||||||
String display() default "visible"; // 显示模式(visible/hidden/none)
|
*/
|
||||||
boolean hidden() default false; // 是否隐藏
|
String component() default "Input";
|
||||||
|
|
||||||
// Map类型配置
|
/**
|
||||||
FormilyMapConfig mapConfig() default @FormilyMapConfig; // Map配置
|
* 装饰器类型
|
||||||
|
*/
|
||||||
|
String decorator() default "FormItem";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 字段顺序
|
||||||
|
*/
|
||||||
|
int order() default 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 组件属性配置
|
||||||
|
*/
|
||||||
|
FormilyComponentProps props() default @FormilyComponentProps;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 装饰器属性配置
|
||||||
|
*/
|
||||||
|
FormilyDecoratorProps decoratorProps() default @FormilyDecoratorProps;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 验证规则
|
||||||
|
*/
|
||||||
|
FormilyValidator[] validators() default {};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 联动配置
|
||||||
|
*/
|
||||||
|
FormilyReaction[] reactions() default {};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Map类型配置
|
||||||
|
*/
|
||||||
|
FormilyMapConfig mapConfig() default @FormilyMapConfig;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 编辑模式
|
||||||
|
*/
|
||||||
|
String pattern() default "editable";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 展示模式
|
||||||
|
*/
|
||||||
|
String display() default "visible";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 是否隐藏
|
||||||
|
*/
|
||||||
|
boolean hidden() default false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 提示信息
|
||||||
|
*/
|
||||||
|
String tooltip() default "";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 是否必填
|
||||||
|
*/
|
||||||
|
boolean required() default false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 栅格跨度
|
||||||
|
*/
|
||||||
|
int gridSpan() default 1;
|
||||||
}
|
}
|
||||||
@ -1,13 +1,38 @@
|
|||||||
package com.qqchen.deploy.backend.framework.annotation.formily;
|
package com.qqchen.deploy.backend.framework.annotation.formily;
|
||||||
|
|
||||||
import java.lang.annotation.ElementType;
|
import java.lang.annotation.*;
|
||||||
import java.lang.annotation.Retention;
|
|
||||||
import java.lang.annotation.RetentionPolicy;
|
|
||||||
import java.lang.annotation.Target;
|
|
||||||
|
|
||||||
@Target(ElementType.TYPE)
|
@Target(ElementType.TYPE)
|
||||||
@Retention(RetentionPolicy.RUNTIME)
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
@Documented
|
||||||
public @interface FormilyForm {
|
public @interface FormilyForm {
|
||||||
String name(); // 表单名称
|
/**
|
||||||
String description() default ""; // 表单描述
|
* 表单名称
|
||||||
|
*/
|
||||||
|
String name();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 表单描述
|
||||||
|
*/
|
||||||
|
String description() default "";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Schema版本号
|
||||||
|
*/
|
||||||
|
String version() default "2.0";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 是否在遇到第一个错误时立即停止验证
|
||||||
|
*/
|
||||||
|
boolean validateFirst() default true;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 标签列宽度
|
||||||
|
*/
|
||||||
|
int labelCol() default 6;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 内容列宽度
|
||||||
|
*/
|
||||||
|
int wrapperCol() default 18;
|
||||||
}
|
}
|
||||||
@ -2,12 +2,66 @@ package com.qqchen.deploy.backend.framework.annotation.formily;
|
|||||||
|
|
||||||
import java.lang.annotation.Retention;
|
import java.lang.annotation.Retention;
|
||||||
import java.lang.annotation.RetentionPolicy;
|
import java.lang.annotation.RetentionPolicy;
|
||||||
import java.lang.annotation.Target;
|
|
||||||
|
|
||||||
@Target({})
|
|
||||||
@Retention(RetentionPolicy.RUNTIME)
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
public @interface FormilyReaction {
|
public @interface FormilyReaction {
|
||||||
String[] dependencies() default {}; // 依赖字段
|
/**
|
||||||
String state() default ""; // 状态表达式,如 dataSource
|
* 依赖字段
|
||||||
String value() default ""; // 状态值,如 {{$fetch('/api/options/B?a=' + $deps.a).then(data => data.data)}}
|
*/
|
||||||
|
String[] dependencies() default {};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 触发条件
|
||||||
|
*/
|
||||||
|
String when() default "";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 目标状态
|
||||||
|
*/
|
||||||
|
String state() default "";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 目标值
|
||||||
|
*/
|
||||||
|
String value() default "";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 执行表达式
|
||||||
|
*/
|
||||||
|
String run() default "";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 是否立即执行
|
||||||
|
*/
|
||||||
|
boolean immediate() default false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 是否在表单挂载时执行
|
||||||
|
*/
|
||||||
|
boolean runOnMounted() default false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 防抖时间(ms)
|
||||||
|
*/
|
||||||
|
int debounceTime() default 100;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 是否显示加载状态
|
||||||
|
*/
|
||||||
|
boolean showLoading() default true;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 加载状态文本
|
||||||
|
*/
|
||||||
|
String loadingText() default "加载中...";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 错误处理
|
||||||
|
*/
|
||||||
|
String onError() default "";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 成功处理
|
||||||
|
*/
|
||||||
|
String onSuccess() default "";
|
||||||
}
|
}
|
||||||
@ -38,12 +38,22 @@ public class FormilySchemaFactory {
|
|||||||
|
|
||||||
FormilyForm formDef = formClass.getAnnotation(FormilyForm.class);
|
FormilyForm formDef = formClass.getAnnotation(FormilyForm.class);
|
||||||
ObjectNode schema = objectMapper.createObjectNode();
|
ObjectNode schema = objectMapper.createObjectNode();
|
||||||
|
|
||||||
|
// 基础属性
|
||||||
schema.put("type", "object");
|
schema.put("type", "object");
|
||||||
|
schema.put("version", formDef.version());
|
||||||
schema.put("name", formDef.name());
|
schema.put("name", formDef.name());
|
||||||
|
schema.put("validateFirst", formDef.validateFirst());
|
||||||
|
|
||||||
if (!formDef.description().isEmpty()) {
|
if (!formDef.description().isEmpty()) {
|
||||||
schema.put("description", formDef.description());
|
schema.put("description", formDef.description());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 表单布局配置
|
||||||
|
ObjectNode formProps = schema.putObject("x-props");
|
||||||
|
formProps.put("labelCol", formDef.labelCol());
|
||||||
|
formProps.put("wrapperCol", formDef.wrapperCol());
|
||||||
|
|
||||||
ObjectNode properties = schema.putObject("properties");
|
ObjectNode properties = schema.putObject("properties");
|
||||||
boolean hasFields = false;
|
boolean hasFields = false;
|
||||||
|
|
||||||
@ -70,41 +80,6 @@ public class FormilySchemaFactory {
|
|||||||
return schema;
|
return schema;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取类的所有字段,包括父类的字段
|
|
||||||
* @param clazz 要获取字段的类
|
|
||||||
* @return 所有字段的列表
|
|
||||||
*/
|
|
||||||
private static List<Field> getAllFields(Class<?> clazz) {
|
|
||||||
List<Field> fields = new ArrayList<>();
|
|
||||||
Class<?> currentClass = clazz;
|
|
||||||
|
|
||||||
while (currentClass != null && currentClass != Object.class) {
|
|
||||||
fields.addAll(Arrays.asList(currentClass.getDeclaredFields()));
|
|
||||||
currentClass = currentClass.getSuperclass();
|
|
||||||
}
|
|
||||||
|
|
||||||
return fields;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 查找最近的带有FormilyForm注解的类
|
|
||||||
* @param clazz 要查找的类
|
|
||||||
* @return 带有FormilyForm注解的最近的类,如果没有找到则返回null
|
|
||||||
*/
|
|
||||||
private static Class<?> findNearestFormClass(Class<?> clazz) {
|
|
||||||
Class<?> currentClass = clazz;
|
|
||||||
|
|
||||||
while (currentClass != null && currentClass != Object.class) {
|
|
||||||
if (currentClass.isAnnotationPresent(FormilyForm.class)) {
|
|
||||||
return currentClass;
|
|
||||||
}
|
|
||||||
currentClass = currentClass.getSuperclass();
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static JsonNode generateFieldSchema(FormilyField field) {
|
private static JsonNode generateFieldSchema(FormilyField field) {
|
||||||
ObjectNode fieldSchema = objectMapper.createObjectNode();
|
ObjectNode fieldSchema = objectMapper.createObjectNode();
|
||||||
|
|
||||||
@ -114,78 +89,42 @@ public class FormilySchemaFactory {
|
|||||||
if (!field.description().isEmpty()) {
|
if (!field.description().isEmpty()) {
|
||||||
fieldSchema.put("description", field.description());
|
fieldSchema.put("description", field.description());
|
||||||
}
|
}
|
||||||
|
if (!field.defaultValue().isEmpty()) {
|
||||||
|
fieldSchema.put("default", field.defaultValue());
|
||||||
|
}
|
||||||
|
if (!field.tooltip().isEmpty()) {
|
||||||
|
fieldSchema.put("tooltip", field.tooltip());
|
||||||
|
}
|
||||||
|
|
||||||
// 组件属性
|
// 组件属性
|
||||||
fieldSchema.put("x-decorator", field.decorator());
|
fieldSchema.put("x-decorator", field.decorator());
|
||||||
if ("map".equals(field.type())) {
|
|
||||||
// 对于Map类型,使用ArrayItems组件
|
|
||||||
fieldSchema.put("x-component", "ArrayItems");
|
|
||||||
|
|
||||||
// 生成Map配置
|
|
||||||
ObjectNode componentProps = generateMapComponentProps(field.mapConfig());
|
|
||||||
if (componentProps.size() > 0) {
|
|
||||||
fieldSchema.set("x-component-props", componentProps);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 生成Map项的Schema
|
|
||||||
ObjectNode items = fieldSchema.putObject("items");
|
|
||||||
items.put("type", "object");
|
|
||||||
items.put("x-component", "ArrayItems.Item");
|
|
||||||
|
|
||||||
// 生成Map项的属性Schema
|
|
||||||
ObjectNode properties = items.putObject("properties");
|
|
||||||
|
|
||||||
// 键的Schema
|
|
||||||
ObjectNode keySchema = properties.putObject("key");
|
|
||||||
keySchema.put("type", "string");
|
|
||||||
keySchema.put("title", field.mapConfig().keyTitle());
|
|
||||||
keySchema.put("x-decorator", "FormItem");
|
|
||||||
keySchema.put("x-component", field.mapConfig().keyComponent());
|
|
||||||
ObjectNode keyProps = generateComponentProps(field.mapConfig().keyProps(), field.mapConfig().keyComponent());
|
|
||||||
if (keyProps.size() > 0) {
|
|
||||||
keySchema.set("x-component-props", keyProps);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 值的Schema
|
|
||||||
ObjectNode valueSchema = properties.putObject("value");
|
|
||||||
valueSchema.put("type", "string");
|
|
||||||
valueSchema.put("title", field.mapConfig().valueTitle());
|
|
||||||
valueSchema.put("x-decorator", "FormItem");
|
|
||||||
valueSchema.put("x-component", field.mapConfig().valueComponent());
|
|
||||||
ObjectNode valueProps = generateComponentProps(field.mapConfig().valueProps(), field.mapConfig().valueComponent());
|
|
||||||
if (valueProps.size() > 0) {
|
|
||||||
valueSchema.set("x-component-props", valueProps);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 操作按钮
|
|
||||||
ObjectNode operationSchema = properties.putObject("operations");
|
|
||||||
operationSchema.put("type", "void");
|
|
||||||
operationSchema.put("x-component", "ArrayItems.Remove");
|
|
||||||
operationSchema.put("x-component-props", field.mapConfig().removeText());
|
|
||||||
|
|
||||||
// 添加按钮
|
|
||||||
ObjectNode addition = fieldSchema.putObject("properties").putObject("addition");
|
|
||||||
addition.put("type", "void");
|
|
||||||
addition.put("title", field.mapConfig().addText());
|
|
||||||
addition.put("x-component", "ArrayItems.Addition");
|
|
||||||
} else {
|
|
||||||
fieldSchema.put("x-component", field.component());
|
fieldSchema.put("x-component", field.component());
|
||||||
// 组件属性配置
|
|
||||||
|
// 装饰器属性
|
||||||
|
ObjectNode decoratorProps = generateDecoratorProps(field);
|
||||||
|
if (decoratorProps.size() > 0) {
|
||||||
|
fieldSchema.set("x-decorator-props", decoratorProps);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 组件属性
|
||||||
|
if ("map".equals(field.type())) {
|
||||||
|
generateMapSchema(fieldSchema, field.mapConfig());
|
||||||
|
} else {
|
||||||
ObjectNode componentProps = generateComponentProps(field.props(), field.component());
|
ObjectNode componentProps = generateComponentProps(field.props(), field.component());
|
||||||
if (componentProps.size() > 0) {
|
if (componentProps.size() > 0) {
|
||||||
fieldSchema.set("x-component-props", componentProps);
|
fieldSchema.set("x-component-props", componentProps);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 装饰器属性配置
|
// 验证规则
|
||||||
ObjectNode decoratorProps = generateDecoratorProps(field.decoratorProps());
|
if (field.validators().length > 0 || field.required()) {
|
||||||
if (decoratorProps.size() > 0) {
|
|
||||||
fieldSchema.set("x-decorator-props", decoratorProps);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 校验规则
|
|
||||||
if (field.validators().length > 0) {
|
|
||||||
ArrayNode validators = fieldSchema.putArray("x-validator");
|
ArrayNode validators = fieldSchema.putArray("x-validator");
|
||||||
|
if (field.required()) {
|
||||||
|
ObjectNode requiredValidator = objectMapper.createObjectNode();
|
||||||
|
requiredValidator.put("required", true);
|
||||||
|
requiredValidator.put("message", "此项为必填项");
|
||||||
|
validators.add(requiredValidator);
|
||||||
|
}
|
||||||
for (FormilyValidator validator : field.validators()) {
|
for (FormilyValidator validator : field.validators()) {
|
||||||
validators.add(generateValidator(validator));
|
validators.add(generateValidator(validator));
|
||||||
}
|
}
|
||||||
@ -199,7 +138,7 @@ public class FormilySchemaFactory {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 展示控制 - 这些属性始终输出,因为它们有默认值
|
// 展示控制
|
||||||
fieldSchema.put("x-pattern", field.pattern());
|
fieldSchema.put("x-pattern", field.pattern());
|
||||||
fieldSchema.put("x-display", field.display());
|
fieldSchema.put("x-display", field.display());
|
||||||
fieldSchema.put("x-hidden", field.hidden());
|
fieldSchema.put("x-hidden", field.hidden());
|
||||||
@ -207,12 +146,18 @@ public class FormilySchemaFactory {
|
|||||||
return fieldSchema;
|
return fieldSchema;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static ObjectNode generateMapComponentProps(FormilyMapConfig config) {
|
private static ObjectNode generateDecoratorProps(FormilyField field) {
|
||||||
ObjectNode props = objectMapper.createObjectNode();
|
ObjectNode props = objectMapper.createObjectNode();
|
||||||
|
|
||||||
props.put("allowAdd", config.allowAdd());
|
if (field.gridSpan() > 1) {
|
||||||
props.put("allowRemove", config.allowRemove());
|
props.put("gridSpan", field.gridSpan());
|
||||||
props.put("allowCustomKey", config.allowCustomKey());
|
}
|
||||||
|
if (!field.tooltip().isEmpty()) {
|
||||||
|
props.put("tooltip", field.tooltip());
|
||||||
|
}
|
||||||
|
if (field.required()) {
|
||||||
|
props.put("asterisk", true);
|
||||||
|
}
|
||||||
|
|
||||||
return props;
|
return props;
|
||||||
}
|
}
|
||||||
@ -220,11 +165,19 @@ public class FormilySchemaFactory {
|
|||||||
private static ObjectNode generateComponentProps(FormilyComponentProps props, String componentType) {
|
private static ObjectNode generateComponentProps(FormilyComponentProps props, String componentType) {
|
||||||
ObjectNode node = objectMapper.createObjectNode();
|
ObjectNode node = objectMapper.createObjectNode();
|
||||||
|
|
||||||
|
// 通用属性
|
||||||
|
if (!props.placeholder().isEmpty()) {
|
||||||
|
node.put("placeholder", props.placeholder());
|
||||||
|
}
|
||||||
|
if (props.disabled()) {
|
||||||
|
node.put("disabled", true);
|
||||||
|
}
|
||||||
|
if (props.loading()) {
|
||||||
|
node.put("loading", true);
|
||||||
|
}
|
||||||
|
|
||||||
// Select组件属性
|
// Select组件属性
|
||||||
if ("Select".equals(componentType)) {
|
if ("Select".equals(componentType)) {
|
||||||
if (!props.api().isEmpty()) {
|
|
||||||
node.put("api", props.api());
|
|
||||||
}
|
|
||||||
if (!props.labelField().equals("label")) {
|
if (!props.labelField().equals("label")) {
|
||||||
node.put("labelField", props.labelField());
|
node.put("labelField", props.labelField());
|
||||||
}
|
}
|
||||||
@ -237,12 +190,11 @@ public class FormilySchemaFactory {
|
|||||||
if (props.showSearch()) {
|
if (props.showSearch()) {
|
||||||
node.put("showSearch", true);
|
node.put("showSearch", true);
|
||||||
}
|
}
|
||||||
if (!props.placeholder().isEmpty()) {
|
|
||||||
node.put("placeholder", props.placeholder());
|
|
||||||
}
|
|
||||||
if (!props.mode().isEmpty()) {
|
if (!props.mode().isEmpty()) {
|
||||||
node.put("mode", props.mode());
|
node.put("mode", props.mode());
|
||||||
}
|
}
|
||||||
|
node.put("filterOption", props.filterOption());
|
||||||
|
|
||||||
if (props.enum_().length > 0) {
|
if (props.enum_().length > 0) {
|
||||||
ArrayNode enumValues = node.putArray("enum");
|
ArrayNode enumValues = node.putArray("enum");
|
||||||
Arrays.stream(props.enum_()).forEach(enumValues::add);
|
Arrays.stream(props.enum_()).forEach(enumValues::add);
|
||||||
@ -256,62 +208,86 @@ public class FormilySchemaFactory {
|
|||||||
// MonacoEditor组件属性
|
// MonacoEditor组件属性
|
||||||
if ("MonacoEditor".equals(componentType)) {
|
if ("MonacoEditor".equals(componentType)) {
|
||||||
FormilyEditorProps editorProps = props.editor();
|
FormilyEditorProps editorProps = props.editor();
|
||||||
if (editorProps != null) {
|
|
||||||
if (!editorProps.placeholder().isEmpty()) {
|
|
||||||
node.put("placeholder", editorProps.placeholder());
|
|
||||||
}
|
|
||||||
|
|
||||||
ObjectNode options = node.putObject("options");
|
ObjectNode options = node.putObject("options");
|
||||||
|
|
||||||
options.put("language", editorProps.language());
|
options.put("language", editorProps.language());
|
||||||
options.put("theme", editorProps.theme());
|
options.put("theme", editorProps.theme());
|
||||||
|
options.put("minimap", editorProps.minimap());
|
||||||
ObjectNode minimap = options.putObject("minimap");
|
options.put("lineNumbers", editorProps.lineNumbers());
|
||||||
minimap.put("enabled", editorProps.minimap());
|
options.put("wordWrap", editorProps.wordWrap());
|
||||||
|
|
||||||
options.put("lineNumbers", editorProps.lineNumbers() ? "on" : "off");
|
|
||||||
options.put("wordWrap", editorProps.wordWrap() ? "on" : "off");
|
|
||||||
options.put("fontSize", editorProps.fontSize());
|
options.put("fontSize", editorProps.fontSize());
|
||||||
options.put("tabSize", editorProps.tabSize());
|
options.put("tabSize", editorProps.tabSize());
|
||||||
options.put("automaticLayout", editorProps.automaticLayout());
|
options.put("automaticLayout", editorProps.automaticLayout());
|
||||||
options.put("folding", editorProps.folding());
|
options.put("folding", editorProps.folding());
|
||||||
}
|
options.put("scrollBeyondLastLine", editorProps.scrollBeyondLastLine());
|
||||||
|
options.put("suggestOnTriggerCharacters", editorProps.suggestOnTriggerCharacters());
|
||||||
|
options.put("snippetsPreventQuickSuggestions", editorProps.snippetsPreventQuickSuggestions());
|
||||||
|
|
||||||
|
ObjectNode scrollbar = options.putObject("scrollbar");
|
||||||
|
scrollbar.put("vertical", editorProps.scrollbarVertical());
|
||||||
|
scrollbar.put("horizontal", editorProps.scrollbarHorizontal());
|
||||||
|
|
||||||
|
node.put("debounceTime", editorProps.debounceTime());
|
||||||
|
node.put("readOnly", editorProps.readOnly());
|
||||||
}
|
}
|
||||||
|
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static ObjectNode generateDecoratorProps(FormilyDecoratorProps props) {
|
private static void generateMapSchema(ObjectNode fieldSchema, FormilyMapConfig config) {
|
||||||
ObjectNode node = objectMapper.createObjectNode();
|
fieldSchema.put("x-component", "ArrayItems");
|
||||||
|
|
||||||
if (!props.tooltip().isEmpty()) {
|
// Map组件属性
|
||||||
node.put("tooltip", props.tooltip());
|
ObjectNode componentProps = fieldSchema.putObject("x-component-props");
|
||||||
}
|
componentProps.put("allowAdd", config.allowAdd());
|
||||||
if (props.labelCol() != 6) {
|
componentProps.put("allowRemove", config.allowRemove());
|
||||||
node.put("labelCol", props.labelCol());
|
componentProps.put("allowCustomKey", config.allowCustomKey());
|
||||||
}
|
|
||||||
if (props.wrapperCol() != 12) {
|
// 生成Map项的Schema
|
||||||
node.put("wrapperCol", props.wrapperCol());
|
ObjectNode items = fieldSchema.putObject("items");
|
||||||
}
|
items.put("type", "object");
|
||||||
if (!props.labelAlign().equals("right")) {
|
items.put("x-component", "ArrayItems.Item");
|
||||||
node.put("labelAlign", props.labelAlign());
|
|
||||||
}
|
// 生成Map项的属性Schema
|
||||||
if (!props.size().equals("default")) {
|
ObjectNode properties = items.putObject("properties");
|
||||||
node.put("size", props.size());
|
|
||||||
}
|
// 键的Schema
|
||||||
if (props.asterisk()) {
|
ObjectNode keySchema = properties.putObject("key");
|
||||||
node.put("asterisk", true);
|
keySchema.put("type", "string");
|
||||||
}
|
keySchema.put("title", config.keyTitle());
|
||||||
if (!props.bordered()) {
|
keySchema.put("x-decorator", "FormItem");
|
||||||
node.put("bordered", false);
|
keySchema.put("x-component", config.keyComponent());
|
||||||
}
|
|
||||||
if (!props.colon()) {
|
ObjectNode keyProps = generateComponentProps(config.keyProps(), config.keyComponent());
|
||||||
node.put("colon", false);
|
if (keyProps.size() > 0) {
|
||||||
|
keySchema.set("x-component-props", keyProps);
|
||||||
}
|
}
|
||||||
|
|
||||||
return node;
|
// 值的Schema
|
||||||
|
ObjectNode valueSchema = properties.putObject("value");
|
||||||
|
valueSchema.put("type", "string");
|
||||||
|
valueSchema.put("title", config.valueTitle());
|
||||||
|
valueSchema.put("x-decorator", "FormItem");
|
||||||
|
valueSchema.put("x-component", config.valueComponent());
|
||||||
|
|
||||||
|
ObjectNode valueProps = generateComponentProps(config.valueProps(), config.valueComponent());
|
||||||
|
if (valueProps.size() > 0) {
|
||||||
|
valueSchema.set("x-component-props", valueProps);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static ObjectNode generateValidator(FormilyValidator validator) {
|
// 操作按钮
|
||||||
|
ObjectNode operationSchema = properties.putObject("operations");
|
||||||
|
operationSchema.put("type", "void");
|
||||||
|
operationSchema.put("x-component", "ArrayItems.Remove");
|
||||||
|
|
||||||
|
// 添加按钮
|
||||||
|
ObjectNode addition = fieldSchema.putObject("properties").putObject("addition");
|
||||||
|
addition.put("type", "void");
|
||||||
|
addition.put("title", config.addText());
|
||||||
|
addition.put("x-component", "ArrayItems.Addition");
|
||||||
|
}
|
||||||
|
|
||||||
|
private static JsonNode generateValidator(FormilyValidator validator) {
|
||||||
ObjectNode node = objectMapper.createObjectNode();
|
ObjectNode node = objectMapper.createObjectNode();
|
||||||
|
|
||||||
if (validator.required()) {
|
if (validator.required()) {
|
||||||
@ -326,33 +302,110 @@ public class FormilySchemaFactory {
|
|||||||
if (!validator.pattern().isEmpty()) {
|
if (!validator.pattern().isEmpty()) {
|
||||||
node.put("pattern", validator.pattern());
|
node.put("pattern", validator.pattern());
|
||||||
}
|
}
|
||||||
if (validator.min() != -1) {
|
if (validator.whitespace()) {
|
||||||
|
node.put("whitespace", true);
|
||||||
|
}
|
||||||
|
if (validator.min() != Double.MIN_VALUE) {
|
||||||
node.put("min", validator.min());
|
node.put("min", validator.min());
|
||||||
}
|
}
|
||||||
if (validator.max() != -1) {
|
if (validator.max() != Double.MAX_VALUE) {
|
||||||
node.put("max", validator.max());
|
node.put("max", validator.max());
|
||||||
}
|
}
|
||||||
|
if (validator.minLength() != -1) {
|
||||||
|
node.put("minLength", validator.minLength());
|
||||||
|
}
|
||||||
|
if (validator.maxLength() != -1) {
|
||||||
|
node.put("maxLength", validator.maxLength());
|
||||||
|
}
|
||||||
|
if (!validator.triggerType().isEmpty()) {
|
||||||
|
node.put("triggerType", validator.triggerType());
|
||||||
|
}
|
||||||
|
if (!validator.validator().isEmpty()) {
|
||||||
|
node.put("validator", validator.validator());
|
||||||
|
}
|
||||||
|
if (!validator.asyncValidator().isEmpty()) {
|
||||||
|
node.put("asyncValidator", validator.asyncValidator());
|
||||||
|
}
|
||||||
|
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static ObjectNode generateReaction(FormilyReaction reaction) {
|
private static JsonNode generateReaction(FormilyReaction reaction) {
|
||||||
ObjectNode node = objectMapper.createObjectNode();
|
ObjectNode node = objectMapper.createObjectNode();
|
||||||
|
|
||||||
// 添加依赖字段
|
|
||||||
if (reaction.dependencies().length > 0) {
|
if (reaction.dependencies().length > 0) {
|
||||||
ArrayNode deps = node.putArray("dependencies");
|
ArrayNode dependencies = node.putArray("dependencies");
|
||||||
Arrays.stream(reaction.dependencies()).forEach(deps::add);
|
Arrays.stream(reaction.dependencies()).forEach(dependencies::add);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!reaction.when().isEmpty()) {
|
||||||
|
node.put("when", reaction.when());
|
||||||
}
|
}
|
||||||
|
|
||||||
// 创建fulfill结构
|
|
||||||
ObjectNode fulfill = node.putObject("fulfill");
|
ObjectNode fulfill = node.putObject("fulfill");
|
||||||
|
|
||||||
|
// 处理run配置
|
||||||
|
if (!reaction.run().isEmpty()) {
|
||||||
|
fulfill.put("run", reaction.run());
|
||||||
|
}
|
||||||
|
|
||||||
ObjectNode state = fulfill.putObject("state");
|
ObjectNode state = fulfill.putObject("state");
|
||||||
|
|
||||||
if (!reaction.state().isEmpty() && !reaction.value().isEmpty()) {
|
// 处理loading状态
|
||||||
|
if (reaction.showLoading()) {
|
||||||
|
state.put("loading", false);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 处理数据源
|
||||||
|
if (!reaction.state().isEmpty()) {
|
||||||
state.put(reaction.state(), reaction.value());
|
state.put(reaction.state(), reaction.value());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!reaction.onSuccess().isEmpty()) {
|
||||||
|
fulfill.put("onSuccess", reaction.onSuccess());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!reaction.onError().isEmpty()) {
|
||||||
|
fulfill.put("onError", reaction.onError());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (reaction.immediate()) {
|
||||||
|
node.put("immediate", true);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (reaction.runOnMounted()) {
|
||||||
|
node.put("runOnMounted", true);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (reaction.debounceTime() != 100) {
|
||||||
|
node.put("debounceTime", reaction.debounceTime());
|
||||||
|
}
|
||||||
|
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static List<Field> getAllFields(Class<?> clazz) {
|
||||||
|
List<Field> fields = new ArrayList<>();
|
||||||
|
Class<?> currentClass = clazz;
|
||||||
|
|
||||||
|
while (currentClass != null && currentClass != Object.class) {
|
||||||
|
fields.addAll(Arrays.asList(currentClass.getDeclaredFields()));
|
||||||
|
currentClass = currentClass.getSuperclass();
|
||||||
|
}
|
||||||
|
|
||||||
|
return fields;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Class<?> findNearestFormClass(Class<?> clazz) {
|
||||||
|
Class<?> currentClass = clazz;
|
||||||
|
|
||||||
|
while (currentClass != null && currentClass != Object.class) {
|
||||||
|
if (currentClass.isAnnotationPresent(FormilyForm.class)) {
|
||||||
|
return currentClass;
|
||||||
|
}
|
||||||
|
currentClass = currentClass.getSuperclass();
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@ -2,15 +2,66 @@ package com.qqchen.deploy.backend.framework.annotation.formily;
|
|||||||
|
|
||||||
import java.lang.annotation.Retention;
|
import java.lang.annotation.Retention;
|
||||||
import java.lang.annotation.RetentionPolicy;
|
import java.lang.annotation.RetentionPolicy;
|
||||||
import java.lang.annotation.Target;
|
|
||||||
|
|
||||||
@Target({})
|
|
||||||
@Retention(RetentionPolicy.RUNTIME)
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
public @interface FormilyValidator {
|
public @interface FormilyValidator {
|
||||||
boolean required() default false; // 是否必填
|
/**
|
||||||
String message() default ""; // 错误信息
|
* 是否必填
|
||||||
String format() default ""; // 格式(email/url/phone等)
|
*/
|
||||||
String pattern() default ""; // 正则表达式
|
boolean required() default false;
|
||||||
int min() default -1; // 最小值/长度
|
|
||||||
int max() default -1; // 最大值/长度
|
/**
|
||||||
|
* 错误提示消息
|
||||||
|
*/
|
||||||
|
String message() default "";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 触发类型
|
||||||
|
*/
|
||||||
|
String triggerType() default "onChange";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 格式验证
|
||||||
|
*/
|
||||||
|
String format() default "";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 是否验证空白字符
|
||||||
|
*/
|
||||||
|
boolean whitespace() default false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 最小值
|
||||||
|
*/
|
||||||
|
double min() default Double.MIN_VALUE;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 最大值
|
||||||
|
*/
|
||||||
|
double max() default Double.MAX_VALUE;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 最小长度
|
||||||
|
*/
|
||||||
|
int minLength() default -1;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 最大长度
|
||||||
|
*/
|
||||||
|
int maxLength() default -1;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 正则表达式
|
||||||
|
*/
|
||||||
|
String pattern() default "";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 自定义验证器
|
||||||
|
*/
|
||||||
|
String validator() default "";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 异步验证器
|
||||||
|
*/
|
||||||
|
String asyncValidator() default "";
|
||||||
}
|
}
|
||||||
@ -1,262 +1,186 @@
|
|||||||
package com.qqchen.deploy.backend.framework.annotation.formily;
|
package com.qqchen.deploy.backend.framework.annotation.formily;
|
||||||
|
|
||||||
import com.fasterxml.jackson.databind.JsonNode;
|
import com.fasterxml.jackson.databind.JsonNode;
|
||||||
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Iterator;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
|
|
||||||
import static org.junit.jupiter.api.Assertions.*;
|
import static org.junit.jupiter.api.Assertions.*;
|
||||||
|
|
||||||
public class FormilySchemaFactoryTest {
|
public class FormilySchemaFactoryTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testGenerateSchema() {
|
public void testGenerateSchema() throws Exception {
|
||||||
JsonNode schema = FormilySchemaFactory.generateSchema(TestForm.class);
|
JsonNode schema = FormilySchemaFactory.generateSchema(CascadeForm.class);
|
||||||
|
|
||||||
|
// 打印生成的Schema
|
||||||
|
ObjectMapper mapper = new ObjectMapper();
|
||||||
|
System.out.println("Generated Schema:");
|
||||||
|
System.out.println(mapper.writerWithDefaultPrettyPrinter().writeValueAsString(schema));
|
||||||
|
|
||||||
// 验证基本结构
|
// 验证基本结构
|
||||||
assertEquals("object", schema.get("type").asText());
|
assertEquals("object", schema.get("type").asText());
|
||||||
assertEquals("测试表单", schema.get("name").asText());
|
assertEquals("2.0", schema.get("version").asText());
|
||||||
assertTrue(schema.has("properties"));
|
assertEquals("级联选择表单", schema.get("name").asText());
|
||||||
|
assertTrue(schema.get("validateFirst").asBoolean());
|
||||||
|
|
||||||
// 验证字段顺序
|
// 验证表单布局
|
||||||
Iterator<String> fieldNames = schema.get("properties").fieldNames();
|
JsonNode xProps = schema.get("x-props");
|
||||||
List<String> actualOrder = new ArrayList<>();
|
assertEquals(6, xProps.get("labelCol").asInt());
|
||||||
fieldNames.forEachRemaining(actualOrder::add);
|
assertEquals(18, xProps.get("wrapperCol").asInt());
|
||||||
|
|
||||||
List<String> expectedOrder = Arrays.asList("a", "b", "c", "envVars", "script");
|
// 验证字段A(系统选择)
|
||||||
assertEquals(expectedOrder, actualOrder, "字段顺序应该按照order排序");
|
JsonNode fieldA = schema.get("properties").get("systemId");
|
||||||
|
|
||||||
// 验证字段A
|
|
||||||
JsonNode fieldA = schema.get("properties").get("a");
|
|
||||||
assertEquals("string", fieldA.get("type").asText());
|
assertEquals("string", fieldA.get("type").asText());
|
||||||
assertEquals("选择A", fieldA.get("title").asText());
|
assertEquals("选择系统", fieldA.get("title").asText());
|
||||||
assertEquals("Select", fieldA.get("x-component").asText());
|
assertEquals("Select", fieldA.get("x-component").asText());
|
||||||
assertEquals("FormItem", fieldA.get("x-decorator").asText());
|
assertEquals("FormItem", fieldA.get("x-decorator").asText());
|
||||||
|
|
||||||
|
// 验证装饰器属性
|
||||||
|
JsonNode decoratorPropsA = fieldA.get("x-decorator-props");
|
||||||
|
assertTrue(decoratorPropsA.get("asterisk").asBoolean());
|
||||||
|
|
||||||
|
// 验证组件属性
|
||||||
|
JsonNode propsA = fieldA.get("x-component-props");
|
||||||
|
assertEquals("请选择系统", propsA.get("placeholder").asText());
|
||||||
|
assertEquals("name", propsA.get("labelField").asText());
|
||||||
|
assertEquals("id", propsA.get("valueField").asText());
|
||||||
|
assertTrue(propsA.get("showSearch").asBoolean());
|
||||||
|
assertEquals("single", propsA.get("mode").asText());
|
||||||
|
assertTrue(propsA.get("filterOption").asBoolean());
|
||||||
|
|
||||||
|
// 验证验证规则
|
||||||
|
JsonNode validatorA = fieldA.get("x-validator").get(0);
|
||||||
|
assertTrue(validatorA.get("required").asBoolean());
|
||||||
|
assertEquals("此项为必填项", validatorA.get("message").asText());
|
||||||
|
|
||||||
|
// 验证展示控制
|
||||||
assertEquals("editable", fieldA.get("x-pattern").asText());
|
assertEquals("editable", fieldA.get("x-pattern").asText());
|
||||||
assertEquals("visible", fieldA.get("x-display").asText());
|
assertEquals("visible", fieldA.get("x-display").asText());
|
||||||
assertFalse(fieldA.get("x-hidden").asBoolean());
|
assertFalse(fieldA.get("x-hidden").asBoolean());
|
||||||
|
|
||||||
// 验证组件属性
|
// 验证字段B(视图选择)
|
||||||
JsonNode propsA = fieldA.get("x-component-props");
|
JsonNode fieldB = schema.get("properties").get("viewId");
|
||||||
assertEquals("/api/options/A", propsA.get("api").asText());
|
|
||||||
assertEquals("name", propsA.get("labelField").asText());
|
|
||||||
assertEquals("id", propsA.get("valueField").asText());
|
|
||||||
assertTrue(propsA.get("allowClear").asBoolean());
|
|
||||||
|
|
||||||
// 验证字段B的联动
|
|
||||||
JsonNode fieldB = schema.get("properties").get("b");
|
|
||||||
JsonNode reactionsB = fieldB.get("x-reactions");
|
JsonNode reactionsB = fieldB.get("x-reactions");
|
||||||
assertTrue(reactionsB.isArray());
|
|
||||||
JsonNode reactionB = reactionsB.get(0);
|
JsonNode reactionB = reactionsB.get(0);
|
||||||
assertTrue(reactionB.get("dependencies").isArray());
|
|
||||||
assertEquals("a", reactionB.get("dependencies").get(0).asText());
|
|
||||||
|
|
||||||
|
// 验证B依赖于A
|
||||||
|
assertTrue(reactionB.has("dependencies"));
|
||||||
|
JsonNode depsB = reactionB.get("dependencies");
|
||||||
|
assertTrue(depsB.isArray());
|
||||||
|
assertEquals("systemId", depsB.get(0).asText());
|
||||||
|
|
||||||
|
// 验证B的条件
|
||||||
|
assertEquals("{{$deps.systemId}}", reactionB.get("when").asText());
|
||||||
|
|
||||||
|
// 验证B的数据源
|
||||||
JsonNode fulfillB = reactionB.get("fulfill");
|
JsonNode fulfillB = reactionB.get("fulfill");
|
||||||
JsonNode stateB = fulfillB.get("state");
|
JsonNode stateB = fulfillB.get("state");
|
||||||
assertEquals("{{$fetch('/api/v1/jenkins-view/list?externalSystemId=' + $deps.a).then(data => data.data)}}",
|
assertFalse(stateB.get("loading").asBoolean());
|
||||||
|
assertEquals("{{$fetch('/api/v1/views?systemId=' + $deps.systemId).then(data => data.data)}}",
|
||||||
stateB.get("dataSource").asText());
|
stateB.get("dataSource").asText());
|
||||||
|
|
||||||
// 验证字段C的联动
|
// 验证字段C(任务选择)
|
||||||
JsonNode fieldC = schema.get("properties").get("c");
|
JsonNode fieldC = schema.get("properties").get("jobId");
|
||||||
JsonNode reactionsC = fieldC.get("x-reactions");
|
JsonNode reactionsC = fieldC.get("x-reactions");
|
||||||
assertTrue(reactionsC.isArray());
|
|
||||||
JsonNode reactionC = reactionsC.get(0);
|
JsonNode reactionC = reactionsC.get(0);
|
||||||
assertTrue(reactionC.get("dependencies").isArray());
|
|
||||||
assertEquals(2, reactionC.get("dependencies").size());
|
|
||||||
assertEquals("a", reactionC.get("dependencies").get(0).asText());
|
|
||||||
assertEquals("b", reactionC.get("dependencies").get(1).asText());
|
|
||||||
|
|
||||||
|
// 验证C依赖于A和B
|
||||||
|
JsonNode depsC = reactionC.get("dependencies");
|
||||||
|
assertEquals(2, depsC.size());
|
||||||
|
assertEquals("systemId", depsC.get(0).asText());
|
||||||
|
assertEquals("viewId", depsC.get(1).asText());
|
||||||
|
|
||||||
|
// 验证C的条件
|
||||||
|
assertEquals("{{$deps.systemId && $deps.viewId}}", reactionC.get("when").asText());
|
||||||
|
|
||||||
|
// 验证C的数据源
|
||||||
JsonNode fulfillC = reactionC.get("fulfill");
|
JsonNode fulfillC = reactionC.get("fulfill");
|
||||||
JsonNode stateC = fulfillC.get("state");
|
JsonNode stateC = fulfillC.get("state");
|
||||||
assertEquals("{{$fetch('/api/v1/jenkins-job/list?externalSystemId=' + $deps.a + '&viewId=' + $deps.b).then(data => data.data)}}",
|
assertFalse(stateC.get("loading").asBoolean());
|
||||||
|
assertEquals(
|
||||||
|
"{{$fetch('/api/v1/jobs?systemId=' + $deps.systemId + '&viewId=' + $deps.viewId).then(data => data.data)}}",
|
||||||
stateC.get("dataSource").asText());
|
stateC.get("dataSource").asText());
|
||||||
|
|
||||||
// 验证编辑器字段
|
|
||||||
JsonNode fieldScript = schema.get("properties").get("script");
|
|
||||||
assertEquals("string", fieldScript.get("type").asText());
|
|
||||||
assertEquals("Pipeline script", fieldScript.get("title").asText());
|
|
||||||
assertEquals("MonacoEditor", fieldScript.get("x-component").asText());
|
|
||||||
|
|
||||||
// 验证编辑器属性
|
|
||||||
JsonNode scriptProps = fieldScript.get("x-component-props");
|
|
||||||
JsonNode options = scriptProps.get("options");
|
|
||||||
assertEquals("groovy", options.get("language").asText());
|
|
||||||
assertEquals("vs-dark", options.get("theme").asText());
|
|
||||||
assertFalse(options.get("minimap").get("enabled").asBoolean());
|
|
||||||
assertEquals("on", options.get("lineNumbers").asText());
|
|
||||||
assertEquals("on", options.get("wordWrap").asText());
|
|
||||||
assertEquals(14, options.get("fontSize").asInt());
|
|
||||||
assertEquals(4, options.get("tabSize").asInt());
|
|
||||||
assertTrue(options.get("automaticLayout").asBoolean());
|
|
||||||
assertTrue(options.get("folding").asBoolean());
|
|
||||||
assertEquals("请输入Pipeline脚本", scriptProps.get("placeholder").asText());
|
|
||||||
|
|
||||||
// 验证Map字段
|
|
||||||
JsonNode mapField = schema.get("properties").get("envVars");
|
|
||||||
assertEquals("map", mapField.get("type").asText());
|
|
||||||
assertEquals("环境变量", mapField.get("title").asText());
|
|
||||||
assertEquals("ArrayItems", mapField.get("x-component").asText());
|
|
||||||
|
|
||||||
// 验证Map项配置
|
|
||||||
JsonNode items = mapField.get("items");
|
|
||||||
assertEquals("object", items.get("type").asText());
|
|
||||||
assertEquals("ArrayItems.Item", items.get("x-component").asText());
|
|
||||||
|
|
||||||
// 验证键值配置
|
|
||||||
JsonNode properties = items.get("properties");
|
|
||||||
|
|
||||||
// 验证键配置
|
|
||||||
JsonNode keySchema = properties.get("key");
|
|
||||||
assertEquals("string", keySchema.get("type").asText());
|
|
||||||
assertEquals("变量名", keySchema.get("title").asText());
|
|
||||||
assertEquals("Select", keySchema.get("x-component").asText());
|
|
||||||
|
|
||||||
// 验证键的组件属性
|
|
||||||
JsonNode keyProps = keySchema.get("x-component-props");
|
|
||||||
assertEquals("/api/v1/env-vars/keys", keyProps.get("api").asText());
|
|
||||||
assertTrue(keyProps.get("showSearch").asBoolean());
|
|
||||||
assertTrue(keyProps.get("allowClear").asBoolean());
|
|
||||||
|
|
||||||
// 验证值配置
|
|
||||||
JsonNode valueSchema = properties.get("value");
|
|
||||||
assertEquals("string", valueSchema.get("type").asText());
|
|
||||||
assertEquals("变量值", valueSchema.get("title").asText());
|
|
||||||
assertEquals("Input", valueSchema.get("x-component").asText());
|
|
||||||
|
|
||||||
// 验证操作按钮
|
|
||||||
JsonNode operations = properties.get("operations");
|
|
||||||
assertEquals("void", operations.get("type").asText());
|
|
||||||
assertEquals("ArrayItems.Remove", operations.get("x-component").asText());
|
|
||||||
|
|
||||||
// 验证添加按钮
|
|
||||||
JsonNode addition = mapField.get("properties").get("addition");
|
|
||||||
assertEquals("void", addition.get("type").asText());
|
|
||||||
assertEquals("添加环境变量", addition.get("title").asText());
|
|
||||||
assertEquals("ArrayItems.Addition", addition.get("x-component").asText());
|
|
||||||
|
|
||||||
// 打印生成的Schema以便查看
|
|
||||||
System.out.println(schema.toPrettyString());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@FormilyForm(name = "测试表单")
|
@FormilyForm(
|
||||||
class TestForm {
|
name = "级联选择表单",
|
||||||
|
version = "2.0",
|
||||||
|
validateFirst = true,
|
||||||
|
labelCol = 6,
|
||||||
|
wrapperCol = 18
|
||||||
|
)
|
||||||
|
class CascadeForm {
|
||||||
@FormilyField(
|
@FormilyField(
|
||||||
title = "选择A",
|
title = "选择系统",
|
||||||
component = "Select",
|
component = "Select",
|
||||||
order = 1,
|
order = 1,
|
||||||
|
required = true,
|
||||||
props = @FormilyComponentProps(
|
props = @FormilyComponentProps(
|
||||||
api = "/api/options/A",
|
|
||||||
labelField = "name",
|
labelField = "name",
|
||||||
valueField = "id",
|
valueField = "id",
|
||||||
allowClear = true
|
showSearch = true,
|
||||||
|
mode = "single",
|
||||||
|
filterOption = true,
|
||||||
|
placeholder = "请选择系统"
|
||||||
),
|
),
|
||||||
validators = {
|
reactions = {
|
||||||
@FormilyValidator(
|
@FormilyReaction(
|
||||||
required = true,
|
state = "dataSource",
|
||||||
message = "请选择A"
|
value = "{{$fetch('/api/v1/systems').then(data => data.data)}}",
|
||||||
|
showLoading = true
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
private String a;
|
private String systemId;
|
||||||
|
|
||||||
@FormilyField(
|
@FormilyField(
|
||||||
title = "选择B",
|
title = "选择视图",
|
||||||
component = "Select",
|
component = "Select",
|
||||||
order = 2,
|
order = 2,
|
||||||
props = @FormilyComponentProps(
|
|
||||||
labelField = "viewName",
|
|
||||||
valueField = "id"
|
|
||||||
),
|
|
||||||
validators = {
|
|
||||||
@FormilyValidator(
|
|
||||||
required = true,
|
required = true,
|
||||||
message = "请选择B"
|
props = @FormilyComponentProps(
|
||||||
)
|
labelField = "name",
|
||||||
},
|
valueField = "id",
|
||||||
|
showSearch = true,
|
||||||
|
mode = "single",
|
||||||
|
filterOption = true,
|
||||||
|
placeholder = "请选择视图"
|
||||||
|
),
|
||||||
reactions = {
|
reactions = {
|
||||||
@FormilyReaction(
|
@FormilyReaction(
|
||||||
dependencies = {"a"},
|
dependencies = {"systemId"},
|
||||||
|
when = "{{$deps.systemId}}",
|
||||||
state = "dataSource",
|
state = "dataSource",
|
||||||
value = "{{$fetch('/api/v1/jenkins-view/list?externalSystemId=' + $deps.a).then(data => data.data)}}"
|
value = "{{$fetch('/api/v1/views?systemId=' + $deps.systemId).then(data => data.data)}}",
|
||||||
|
showLoading = true
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
private String b;
|
private String viewId;
|
||||||
|
|
||||||
@FormilyField(
|
@FormilyField(
|
||||||
title = "选择C",
|
title = "选择任务",
|
||||||
component = "Select",
|
component = "Select",
|
||||||
order = 3,
|
order = 3,
|
||||||
props = @FormilyComponentProps(
|
|
||||||
labelField = "jobName",
|
|
||||||
valueField = "id"
|
|
||||||
),
|
|
||||||
validators = {
|
|
||||||
@FormilyValidator(
|
|
||||||
required = true,
|
required = true,
|
||||||
message = "请选择C"
|
props = @FormilyComponentProps(
|
||||||
)
|
labelField = "name",
|
||||||
},
|
valueField = "id",
|
||||||
|
showSearch = true,
|
||||||
|
mode = "single",
|
||||||
|
filterOption = true,
|
||||||
|
placeholder = "请选择任务"
|
||||||
|
),
|
||||||
reactions = {
|
reactions = {
|
||||||
@FormilyReaction(
|
@FormilyReaction(
|
||||||
dependencies = {"a", "b"},
|
dependencies = {"systemId", "viewId"},
|
||||||
|
when = "{{$deps.systemId && $deps.viewId}}",
|
||||||
state = "dataSource",
|
state = "dataSource",
|
||||||
value = "{{$fetch('/api/v1/jenkins-job/list?externalSystemId=' + $deps.a + '&viewId=' + $deps.b).then(data => data.data)}}"
|
value = "{{$fetch('/api/v1/jobs?systemId=' + $deps.systemId + '&viewId=' + $deps.viewId).then(data => data.data)}}",
|
||||||
|
showLoading = true
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
private String c;
|
private String jobId;
|
||||||
|
|
||||||
@FormilyField(
|
|
||||||
title = "环境变量",
|
|
||||||
type = "map",
|
|
||||||
order = 4,
|
|
||||||
mapConfig = @FormilyMapConfig(
|
|
||||||
keyTitle = "变量名",
|
|
||||||
valueTitle = "变量值",
|
|
||||||
keyComponent = "Select",
|
|
||||||
valueComponent = "Input",
|
|
||||||
keyProps = @FormilyComponentProps(
|
|
||||||
api = "/api/v1/env-vars/keys",
|
|
||||||
showSearch = true,
|
|
||||||
allowClear = true
|
|
||||||
),
|
|
||||||
addText = "添加环境变量",
|
|
||||||
allowCustomKey = true
|
|
||||||
)
|
|
||||||
)
|
|
||||||
private Map<String, String> envVars;
|
|
||||||
|
|
||||||
@FormilyField(
|
|
||||||
title = "Pipeline script",
|
|
||||||
type = "string",
|
|
||||||
component = "MonacoEditor",
|
|
||||||
order = 5,
|
|
||||||
props = @FormilyComponentProps(
|
|
||||||
editor = @FormilyEditorProps(
|
|
||||||
language = "groovy",
|
|
||||||
theme = "vs-dark",
|
|
||||||
minimap = false,
|
|
||||||
lineNumbers = true,
|
|
||||||
wordWrap = true,
|
|
||||||
fontSize = 14,
|
|
||||||
tabSize = 4,
|
|
||||||
automaticLayout = true,
|
|
||||||
folding = true,
|
|
||||||
placeholder = "请输入Pipeline脚本"
|
|
||||||
)
|
|
||||||
),
|
|
||||||
validators = {
|
|
||||||
@FormilyValidator(
|
|
||||||
required = true,
|
|
||||||
message = "请输入Pipeline脚本"
|
|
||||||
)
|
|
||||||
}
|
|
||||||
)
|
|
||||||
private String script;
|
|
||||||
}
|
}
|
||||||
Loading…
Reference in New Issue
Block a user