增加formily json schema生成
This commit is contained in:
parent
5cd9f4c4d3
commit
9d1f77c069
@ -11,7 +11,7 @@ public @interface FormilyField {
|
|||||||
// 基础属性
|
// 基础属性
|
||||||
String title(); // 字段标题
|
String title(); // 字段标题
|
||||||
String description() default ""; // 字段描述
|
String description() default ""; // 字段描述
|
||||||
String type() default "string"; // 字段类型(string/number/boolean/array/object)
|
String type() default "string"; // 字段类型(string/number/boolean/array/object/map)
|
||||||
|
|
||||||
// 组件属性
|
// 组件属性
|
||||||
String component() default "Input"; // 组件类型
|
String component() default "Input"; // 组件类型
|
||||||
@ -29,4 +29,7 @@ public @interface FormilyField {
|
|||||||
String pattern() default "editable"; // 展示模式(editable/disabled/readOnly)
|
String pattern() default "editable"; // 展示模式(editable/disabled/readOnly)
|
||||||
String display() default "visible"; // 显示模式(visible/hidden/none)
|
String display() default "visible"; // 显示模式(visible/hidden/none)
|
||||||
boolean hidden() default false; // 是否隐藏
|
boolean hidden() default false; // 是否隐藏
|
||||||
|
|
||||||
|
// Map类型配置
|
||||||
|
FormilyMapConfig mapConfig() default @FormilyMapConfig; // Map配置
|
||||||
}
|
}
|
||||||
@ -0,0 +1,65 @@
|
|||||||
|
package com.qqchen.deploy.backend.framework.annotation.formily;
|
||||||
|
|
||||||
|
import java.lang.annotation.ElementType;
|
||||||
|
import java.lang.annotation.Retention;
|
||||||
|
import java.lang.annotation.RetentionPolicy;
|
||||||
|
import java.lang.annotation.Target;
|
||||||
|
|
||||||
|
@Target({})
|
||||||
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
public @interface FormilyMapConfig {
|
||||||
|
/**
|
||||||
|
* 键的标题
|
||||||
|
*/
|
||||||
|
String keyTitle() default "键";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 值的标题
|
||||||
|
*/
|
||||||
|
String valueTitle() default "值";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 键的组件类型
|
||||||
|
*/
|
||||||
|
String keyComponent() default "Input";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 值的组件类型
|
||||||
|
*/
|
||||||
|
String valueComponent() default "Input";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 键的组件属性
|
||||||
|
*/
|
||||||
|
FormilyComponentProps keyProps() default @FormilyComponentProps;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 值的组件属性
|
||||||
|
*/
|
||||||
|
FormilyComponentProps valueProps() default @FormilyComponentProps;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 是否允许添加
|
||||||
|
*/
|
||||||
|
boolean allowAdd() default true;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 是否允许删除
|
||||||
|
*/
|
||||||
|
boolean allowRemove() default true;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 是否允许自定义键
|
||||||
|
*/
|
||||||
|
boolean allowCustomKey() default true;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 添加按钮文本
|
||||||
|
*/
|
||||||
|
String addText() default "添加";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除按钮文本
|
||||||
|
*/
|
||||||
|
String removeText() default "删除";
|
||||||
|
}
|
||||||
@ -108,12 +108,64 @@ public class FormilySchemaFactory {
|
|||||||
|
|
||||||
// 组件属性
|
// 组件属性
|
||||||
fieldSchema.put("x-decorator", field.decorator());
|
fieldSchema.put("x-decorator", field.decorator());
|
||||||
fieldSchema.put("x-component", field.component());
|
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 componentProps = generateComponentProps(field.props(), field.component());
|
ObjectNode items = fieldSchema.putObject("items");
|
||||||
if (componentProps.size() > 0) {
|
items.put("type", "object");
|
||||||
fieldSchema.set("x-component-props", componentProps);
|
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());
|
||||||
|
// 组件属性配置
|
||||||
|
ObjectNode componentProps = generateComponentProps(field.props(), field.component());
|
||||||
|
if (componentProps.size() > 0) {
|
||||||
|
fieldSchema.set("x-component-props", componentProps);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 装饰器属性配置
|
// 装饰器属性配置
|
||||||
@ -146,6 +198,16 @@ public class FormilySchemaFactory {
|
|||||||
return fieldSchema;
|
return fieldSchema;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static ObjectNode generateMapComponentProps(FormilyMapConfig config) {
|
||||||
|
ObjectNode props = objectMapper.createObjectNode();
|
||||||
|
|
||||||
|
props.put("allowAdd", config.allowAdd());
|
||||||
|
props.put("allowRemove", config.allowRemove());
|
||||||
|
props.put("allowCustomKey", config.allowCustomKey());
|
||||||
|
|
||||||
|
return props;
|
||||||
|
}
|
||||||
|
|
||||||
private static ObjectNode generateComponentProps(FormilyComponentProps props, String componentType) {
|
private static ObjectNode generateComponentProps(FormilyComponentProps props, String componentType) {
|
||||||
ObjectNode node = objectMapper.createObjectNode();
|
ObjectNode node = objectMapper.createObjectNode();
|
||||||
|
|
||||||
|
|||||||
@ -2,6 +2,9 @@ package com.qqchen.deploy.backend.framework.annotation.formily;
|
|||||||
|
|
||||||
import com.fasterxml.jackson.databind.JsonNode;
|
import com.fasterxml.jackson.databind.JsonNode;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
import static org.junit.jupiter.api.Assertions.*;
|
import static org.junit.jupiter.api.Assertions.*;
|
||||||
|
|
||||||
public class FormilySchemaFactoryTest {
|
public class FormilySchemaFactoryTest {
|
||||||
@ -9,12 +12,12 @@ public class FormilySchemaFactoryTest {
|
|||||||
@Test
|
@Test
|
||||||
public void testGenerateSchema() {
|
public void testGenerateSchema() {
|
||||||
JsonNode schema = FormilySchemaFactory.generateSchema(TestForm.class);
|
JsonNode schema = FormilySchemaFactory.generateSchema(TestForm.class);
|
||||||
|
|
||||||
// 验证基本结构
|
// 验证基本结构
|
||||||
assertEquals("object", schema.get("type").asText());
|
assertEquals("object", schema.get("type").asText());
|
||||||
assertEquals("测试表单", schema.get("name").asText());
|
assertEquals("测试表单", schema.get("name").asText());
|
||||||
assertTrue(schema.has("properties"));
|
assertTrue(schema.has("properties"));
|
||||||
|
|
||||||
// 验证字段A
|
// 验证字段A
|
||||||
JsonNode fieldA = schema.get("properties").get("a");
|
JsonNode fieldA = schema.get("properties").get("a");
|
||||||
assertEquals("string", fieldA.get("type").asText());
|
assertEquals("string", fieldA.get("type").asText());
|
||||||
@ -24,14 +27,14 @@ public class FormilySchemaFactoryTest {
|
|||||||
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());
|
||||||
|
|
||||||
// 验证组件属性
|
// 验证组件属性
|
||||||
JsonNode propsA = fieldA.get("x-component-props");
|
JsonNode propsA = fieldA.get("x-component-props");
|
||||||
assertEquals("/api/options/A", propsA.get("api").asText());
|
assertEquals("/api/options/A", propsA.get("api").asText());
|
||||||
assertEquals("name", propsA.get("labelField").asText());
|
assertEquals("name", propsA.get("labelField").asText());
|
||||||
assertEquals("id", propsA.get("valueField").asText());
|
assertEquals("id", propsA.get("valueField").asText());
|
||||||
assertTrue(propsA.get("allowClear").asBoolean());
|
assertTrue(propsA.get("allowClear").asBoolean());
|
||||||
|
|
||||||
// 验证字段B的联动
|
// 验证字段B的联动
|
||||||
JsonNode fieldB = schema.get("properties").get("b");
|
JsonNode fieldB = schema.get("properties").get("b");
|
||||||
JsonNode reactionsB = fieldB.get("x-reactions");
|
JsonNode reactionsB = fieldB.get("x-reactions");
|
||||||
@ -39,12 +42,12 @@ public class FormilySchemaFactoryTest {
|
|||||||
JsonNode reactionB = reactionsB.get(0);
|
JsonNode reactionB = reactionsB.get(0);
|
||||||
assertTrue(reactionB.get("dependencies").isArray());
|
assertTrue(reactionB.get("dependencies").isArray());
|
||||||
assertEquals("a", reactionB.get("dependencies").get(0).asText());
|
assertEquals("a", reactionB.get("dependencies").get(0).asText());
|
||||||
|
|
||||||
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)}}",
|
assertEquals("{{$fetch('/api/v1/jenkins-view/list?externalSystemId=' + $deps.a).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("c");
|
||||||
JsonNode reactionsC = fieldC.get("x-reactions");
|
JsonNode reactionsC = fieldC.get("x-reactions");
|
||||||
@ -54,10 +57,10 @@ public class FormilySchemaFactoryTest {
|
|||||||
assertEquals(2, reactionC.get("dependencies").size());
|
assertEquals(2, reactionC.get("dependencies").size());
|
||||||
assertEquals("a", reactionC.get("dependencies").get(0).asText());
|
assertEquals("a", reactionC.get("dependencies").get(0).asText());
|
||||||
assertEquals("b", reactionC.get("dependencies").get(1).asText());
|
assertEquals("b", reactionC.get("dependencies").get(1).asText());
|
||||||
|
|
||||||
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)}}",
|
assertEquals("{{$fetch('/api/v1/jenkins-job/list?externalSystemId=' + $deps.a + '&viewId=' + $deps.b).then(data => data.data)}}",
|
||||||
stateC.get("dataSource").asText());
|
stateC.get("dataSource").asText());
|
||||||
|
|
||||||
// 验证编辑器字段
|
// 验证编辑器字段
|
||||||
@ -65,7 +68,7 @@ public class FormilySchemaFactoryTest {
|
|||||||
assertEquals("string", fieldScript.get("type").asText());
|
assertEquals("string", fieldScript.get("type").asText());
|
||||||
assertEquals("Pipeline script", fieldScript.get("title").asText());
|
assertEquals("Pipeline script", fieldScript.get("title").asText());
|
||||||
assertEquals("MonacoEditor", fieldScript.get("x-component").asText());
|
assertEquals("MonacoEditor", fieldScript.get("x-component").asText());
|
||||||
|
|
||||||
// 验证编辑器属性
|
// 验证编辑器属性
|
||||||
JsonNode scriptProps = fieldScript.get("x-component-props");
|
JsonNode scriptProps = fieldScript.get("x-component-props");
|
||||||
JsonNode options = scriptProps.get("options");
|
JsonNode options = scriptProps.get("options");
|
||||||
@ -79,7 +82,50 @@ public class FormilySchemaFactoryTest {
|
|||||||
assertTrue(options.get("automaticLayout").asBoolean());
|
assertTrue(options.get("automaticLayout").asBoolean());
|
||||||
assertTrue(options.get("folding").asBoolean());
|
assertTrue(options.get("folding").asBoolean());
|
||||||
assertEquals("请输入Pipeline脚本", scriptProps.get("placeholder").asText());
|
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以便查看
|
// 打印生成的Schema以便查看
|
||||||
System.out.println(schema.toPrettyString());
|
System.out.println(schema.toPrettyString());
|
||||||
}
|
}
|
||||||
@ -177,4 +223,23 @@ class TestForm {
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
private String script;
|
private String script;
|
||||||
|
|
||||||
|
@FormilyField(
|
||||||
|
title = "环境变量",
|
||||||
|
type = "map",
|
||||||
|
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;
|
||||||
}
|
}
|
||||||
Loading…
Reference in New Issue
Block a user