feat(plugin): PluginField 扩展 — ref_entity / validation / no_cycle

新增 FieldValidation 类型支持正则校验规则,PluginField 增加
ref_entity(外键引用实体名)、validation(字段校验规则)、
no_cycle(禁止循环引用)三个可选字段。
This commit is contained in:
iven
2026-04-17 10:31:37 +08:00
parent abc3086571
commit f697b5fd6d

View File

@@ -45,6 +45,13 @@ pub struct PluginEntity {
pub indexes: Vec<PluginIndex>,
}
/// 字段校验规则
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct FieldValidation {
pub pattern: Option<String>, // 正则表达式
pub message: Option<String>, // 校验失败提示
}
/// 插件字段定义
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct PluginField {
@@ -66,6 +73,10 @@ pub struct PluginField {
pub sortable: Option<bool>,
#[serde(default)]
pub visible_when: Option<String>,
pub ref_entity: Option<String>, // 外键引用的实体名
pub validation: Option<FieldValidation>, // 字段校验规则
#[serde(default)]
pub no_cycle: Option<bool>, // 禁止循环引用
}
/// 字段类型
@@ -129,6 +140,9 @@ impl PluginField {
filterable: None,
sortable: None,
visible_when: None,
ref_entity: None,
validation: None,
no_cycle: None,
}
}
}
@@ -599,4 +613,81 @@ label = "空标签页"
assert_eq!(PluginFieldType::Integer.generated_expr("age"), "(data->>'age')::INTEGER");
assert_eq!(PluginFieldType::Uuid.generated_expr("ref_id"), "(data->>'ref_id')::UUID");
}
#[test]
fn parse_field_with_ref_entity() {
let toml = r#"
[metadata]
id = "test"
name = "Test"
version = "0.1.0"
[schema]
[[schema.entities]]
name = "contact"
display_name = "联系人"
[[schema.entities.fields]]
name = "customer_id"
field_type = "uuid"
required = true
display_name = "所属客户"
ref_entity = "customer"
"#;
let manifest = parse_manifest(toml).unwrap();
let field = &manifest.schema.unwrap().entities[0].fields[0];
assert_eq!(field.ref_entity.as_deref(), Some("customer"));
}
#[test]
fn parse_field_with_validation() {
let toml = r#"
[metadata]
id = "test"
name = "Test"
version = "0.1.0"
[schema]
[[schema.entities]]
name = "contact"
display_name = "联系人"
[[schema.entities.fields]]
name = "phone"
field_type = "string"
display_name = "手机号"
validation = { pattern = "^1[3-9]\\d{9}$", message = "手机号格式不正确" }
"#;
let manifest = parse_manifest(toml).unwrap();
let field = &manifest.schema.unwrap().entities[0].fields[0];
let v = field.validation.as_ref().unwrap();
assert_eq!(v.pattern.as_deref(), Some("^1[3-9]\\d{9}$"));
assert_eq!(v.message.as_deref(), Some("手机号格式不正确"));
}
#[test]
fn parse_field_with_no_cycle() {
let toml = r#"
[metadata]
id = "test"
name = "Test"
version = "0.1.0"
[schema]
[[schema.entities]]
name = "customer"
display_name = "客户"
[[schema.entities.fields]]
name = "parent_id"
field_type = "uuid"
display_name = "上级客户"
ref_entity = "customer"
no_cycle = true
"#;
let manifest = parse_manifest(toml).unwrap();
let field = &manifest.schema.unwrap().entities[0].fields[0];
assert_eq!(field.no_cycle, Some(true));
assert_eq!(field.ref_entity.as_deref(), Some("customer"));
}
}