diff --git a/crates/erp-plugin/src/manifest.rs b/crates/erp-plugin/src/manifest.rs index df08b4c..0a0108a 100644 --- a/crates/erp-plugin/src/manifest.rs +++ b/crates/erp-plugin/src/manifest.rs @@ -45,6 +45,13 @@ pub struct PluginEntity { pub indexes: Vec, } +/// 字段校验规则 +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct FieldValidation { + pub pattern: Option, // 正则表达式 + pub message: Option, // 校验失败提示 +} + /// 插件字段定义 #[derive(Debug, Clone, Serialize, Deserialize)] pub struct PluginField { @@ -66,6 +73,10 @@ pub struct PluginField { pub sortable: Option, #[serde(default)] pub visible_when: Option, + pub ref_entity: Option, // 外键引用的实体名 + pub validation: Option, // 字段校验规则 + #[serde(default)] + pub no_cycle: Option, // 禁止循环引用 } /// 字段类型 @@ -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")); + } }