/** * ======================================== * 动态表单核心类型定义 * ======================================== * 本文件定义了基于 JSON Schema 的动态表单渲染引擎的核心类型。 * 通过这些类型配置,可以实现无代码/低代码的表单构建和渲染。 * * 适用场景: * - 可视化表单设计器:用户通过拖拽组件构建表单,生成 JSON 配置 * - 动态表单渲染:根据 JSON 配置自动渲染表单,支持复杂的表单交互 * - 多语言支持:字段标签支持多语言切换 * - 复杂表单控制:基于其他字段值动态显示/隐藏字段 */ /** * 表单项动态显示/隐藏控制配置 * * 用于定义表单项的显示逻辑,可以根据其他表单字段的值或自定义函数来控制当前字段是否显示。 * * @example * // 示例1: 简单控制 - 始终显示 * { * "matchPattern": "&&", * "type": "select", * "value": false, // false=显示, true=隐藏 * "dataJs": "function hidden(config,data){\n return false;\n}" * } * * @example * // 示例2: 基于其他字段控制 - 当 userType='admin' 时隐藏该字段 * { * "matchPattern": "&&", * "type": "function", * "value": false, * "dataJs": "function hidden(config,data){\n // data 是当前表单的所有字段值\n return data.userType === 'admin';\n}" * } * * @example * // 示例3: 多条件组合 - 当 age > 18 且 city='beijing' 时显示 * { * "matchPattern": "&&", // && 表示所有条件都满足, || 表示任一条件满足 * "type": "function", * "value": true, * "dataJs": "function hidden(config,data){\n return data.age > 18 && data.city === 'beijing';\n}" * } */ export interface BooleanDragFormData { /** * 逻辑匹配模式 * - "&&": AND 逻辑,所有条件都满足时生效 * - "||": OR 逻辑,任一条件满足时生效 * 用于多个条件组合时使用 */ matchPattern: string; /** * 编辑器类型 * - "select": 使用下拉选择器配置(简单模式) * - "function": 使用代码编辑器编写自定义函数(高级模式) */ type: string; /** * 是否隐藏字段 * - false: 显示该字段(默认值) * - true: 隐藏该字段 * 实际显示/隐藏状态由 dataJs 函数的返回值决定 */ value: Boolean; /** * 编辑器数据(可选) * 当 type="select" 时使用,提供可选择的条件列表 * 通常用于可视化配置时预设一些常用条件 * * @example * [{ * label: "用户类型为管理员", * value: "data.userType === 'admin'" * }] */ dataSelect?: any[]; /** * 显示/隐藏控制函数 * 可以是字符串形式的函数代码,也可以是直接传入函数对象 * * @param config - 当前字段的 FormItemJSON 配置对象 * @param data - 表单的所有字段数据对象 { [prop: string]: any } * @returns boolean - true 表示隐藏, false 表示显示 * * @example 函数签名 * function hidden(config: FormItemJSON, data: Record): boolean { * // config.prop: 当前字段名 * // data: 整个表单的数据对象 * // 返回 true 隐藏, false 显示 * return data.someField === 'someValue'; * } */ dataJs: string | Function; } /** * 表单项配置接口 * * 这是动态表单的核心数据结构,每个表单字段对应一个 FormItemJSON 对象。 * 通过配置这个对象,可以完全定义一个表单字段的行为、样式、验证规则和交互逻辑。 * * 使用场景: * 1. 作为拖拽表单设计器的组件配置(schema 数组中的元素) * 2. 直接用于 ElementEasyForm 组件的 formJson.schema 属性 * 3. 支持嵌套结构(如 ElSelect 包含 ElOption 子组件) * * @example 基础文本输入框 * { * "label": "用户名", * "prop": "username", * "componentName": "ElInput", * "attrs": { * "type": "text", * "placeholder": "请输入用户名" * }, * "rules": [{ * "required": true, * "message": "用户名不能为空" * }] * } * * @example 下拉选择框(带子组件) * { * "label": "城市", * "prop": "city", * "componentName": "ElSelect", * "attrs": { * "placeholder": "请选择城市", * "clearable": true * }, * "children": [ * { "componentName": "ElOption", "value": "bj", "label": "北京" }, * { "componentName": "ElOption", "value": "sh", "label": "上海" } * ] * } * * @example 带动态显示控制的字段 * { * "label": "管理员密码", * "prop": "adminPassword", * "componentName": "ElInput", * "attrs": { "type": "password", "show-password": true }, * "hidden": { * "matchPattern": "&&", * "type": "function", * "value": true, * "dataJs": "function hidden(config,data){\n return data.userType !== 'admin';\n}" * } * } */ export interface FormItemJSON { /** * 表单标签文本 * 显示在输入框上方的提示文字 * - 可选字段,如果不提供则不显示标签 * - 支持多语言(通过 locale 配置) * * @example "用户名" * @example 支持多语言: 从 locale.dataList 中查找对应语言的翻译 */ label?: string; /** * 字段唯一标识符 * - 必填字段,用于标识表单字段 * - 对应 model 对象中的 key * - 必须在整个 schema 中唯一 * * 使用场景: * 1. 表单提交时的字段名 * 2. 表单验证时引用字段 * 3. hidden 函数中访问其他字段的值 * 4. 动态表单渲染的数据绑定路径 * * @example "username" * @example "user.age" (支持嵌套路径) */ prop: string; /** * 自定义渲染函数(高级功能) * 用于完全自定义字段渲染逻辑,替代 componentName 的默认渲染 * - 接收 JSX 格式的渲染函数 * - 适用于需要高度定制化场景 * * @param config - 当前字段的配置对象 * @param model - 表单数据模型 * @returns JSX 元素或 VNode * * 使用示例: * render: (config, model) => ( *
* 自定义内容: {model[config.prop]} *
* ) */ render?: any; /** * 组件名称 * 指定使用哪个 Vue 组件来渲染该表单项 * - 组件需要全局注册或在父组件中局部注册 * - 支持 Element Plus 的所有组件和自定义组件 * - 如果提供了 render,则忽略此属性 * * 常用组件: * - ElInput: 输入框 * - ElInputNumber: 数字输入框 * - ElSelect: 下拉选择 * - ElRadioGroup: 单选组 * - ElCheckboxGroup: 多选组 * - ElDatePicker: 日期选择器 * - ElSwitch: 开关 * - 等等... * * @example "ElInput" * @example "CustomField" (自定义组件名) */ componentName?: string; /** * FormItem 容器属性 * 传递给 Element Plus 组件的属性 * 用于控制表单项容器本身的行为和样式 * * 常用属性: * - labelWidth: 标签宽度,如 "80px" * - required: 是否必填,与 rules 配合使用 * - error: 错误提示信息 * - showMessage: 是否显示校验错误信息 * - inline: 是否为行内表单模式 * * @example { "labelWidth": "100px" } * @example { "required": true } */ formItemAttrs?: any; /** * 组件属性配置 * 传递给实际渲染组件(如 ElInput)的属性 * 用于控制组件的行为、样式和交互 * * 不同组件支持的属性不同,需参考对应组件的文档 * * ElInput 常用属性: * - type: 输入框类型(text/password/textarea/number) * - placeholder: 占位符文本 * - disabled: 是否禁用 * - readonly: 是否只读 * - maxlength: 最大输入长度 * - show-password: 是否显示密码切换图标 * * ElSelect 常用属性: * - placeholder: 占位符 * - clearable: 是否可清空 * - multiple: 是否多选 * - filterable: 是否可搜索 * * @example ElInput: { "type": "text", "placeholder": "请输入" } * @example ElSwitch: { "active-color": "#13ce66" } */ attrs?: any; /** * 自定义标签渲染函数 * 用于完全自定义标签部分的内容 * - 接收 JSX 格式的渲染函数 * - 与 label 属性二选一使用 * * @param config - 当前字段的配置对象 * @returns JSX 元素或 VNode * * 使用场景: * - 标签中需要包含图标、链接等复杂内容 * - 标签需要根据条件动态变化 * * @example * renderLabel: (config) => ( *
* * {config.label} *
* ) */ renderLabel?: any; /** * 栅格布局属性 * 传递给 Element Plus 组件的属性 * 用于控制表单项在栅格系统中的占位和布局 * * 常用属性: * - span: 栅格占位格数(总共24格),如 12 表示占一半宽度 * - offset: 栅格左侧间隔格数 * - push: 栅格向右移动格数 * - pull: 栅格向左移动格数 * - xs/sm/md/lg/xl: 响应式断点配置 * * @example { "span": 12 } // 占50%宽度 * @example { "span": 8, "offset": 4 } // 占1/3宽度,右侧间隔1/6 */ colAttrs?: any; /** * 组件事件配置 * 定义组件支持的事件及其处理函数 * - 数组格式,每个元素代表一个事件配置 * - 事件函数以字符串形式存储,运行时通过 eval 或 Function 构造器执行 * * 事件配置对象结构: * - prop: 事件名称(如 change、blur、focus) * - label: 事件描述 * - defaultValue: 事件处理函数代码字符串 * - componentName: 固定为 "ElFunctionEvent" * * @example 输入框事件 * events: [ * { * "prop": "blur", * "label": "当失去焦点时触发", * "defaultValue": "function blur(config,data,event){\n console.log('blur');\n}", * "componentName": "ElFunctionEvent" * }, * { * "prop": "change", * "label": "值改变时触发", * "defaultValue": "function change(config, data, value){\n console.log(value);\n}", * "componentName": "ElFunctionEvent" * } * ] * * 事件函数参数说明: * - config: 当前字段的 FormItemJSON 配置 * - data: 整个表单的数据模型 * - event/value: 事件对象或新值(根据事件类型不同) */ events?: any; /** * 字段默认值 * 表单初始化时该字段的默认值 * - 可选字段 * - 值的类型需与组件类型匹配 * * @example 字符串: "" * @example 数字: 0 * @example 数组: [] (用于多选组件) * @example 布尔: false (用于开关组件) */ defaultValue?: any; /** * 动态显示/隐藏控制 * 配置该字段的显示逻辑 * - 可选字段 * - 不配置则始终显示 * - 参见 BooleanDragFormData 接口说明 * * @example 简单隐藏 * hidden: { * "matchPattern": "&&", * "type": "function", * "value": true, * "dataJs": "function hidden(config,data){ return false; }" * } * * @example 条件显示:当 age > 18 时显示 * hidden: { * "matchPattern": "&&", * "type": "function", * "value": false, * "dataJs": "function hidden(config,data){ return data.age > 18; }" * } */ hidden?: BooleanDragFormData; /** * 子组件配置 * 某些组件需要嵌套子组件来定义其选项或内容 * - 可选字段 * - 子组件也遵循 FormItemJSON 结构 * * 常用场景: * 1. ElSelect: 子项为 ElOption,定义可选项 * 2. ElRadioGroup: 子项为 ElRadio,定义单选项 * 3. ElCheckboxGroup: 子项为 ElCheckbox,定义多选项 * 4. ElCascader: 子项为级联选项 * 5. ElRow: 子项为 ElCol,定义栅格布局 * 6. ElDragTable: 子项为表格列配置 * * @example ElSelect 的 children * children: [ * { "componentName": "ElOption", "value": "bj", "label": "北京" }, * { "componentName": "ElOption", "value": "sh", "label": "上海" } * ] * * @example ElRadioGroup 的 children * children: [ * { "componentName": "ElRadio", "value": "male", "label": "男" }, * { "componentName": "ElRadio", "value": "female", "label": "女" } * ] */ children?: any[]; /** * 表单验证规则 * 定义字段的校验规则 * - 数组格式,可配置多个规则 * - 符合 Element Plus 验证规则格式 * * 常用规则属性: * - required: 是否必填 * - message: 错误提示信息 * - trigger: 触发时机('blur'/'change') * - min/max: 最小/最大长度 * - pattern: 正则表达式 * - validator: 自定义验证函数 * * @example 基础验证 * rules: [{ * "required": true, * "message": "用户名不能为空", * "trigger": "blur" * }] * * @example 多个验证规则 * rules: [{ * "required": true, * "message": "手机号不能为空" * }, { * "pattern": /^1[3-9]\d{9}$/, * "message": "请输入正确的手机号" * }] * * @example 自定义验证 * rules: [{ * "validator": (rule, value, callback) => { * if (value !== '123456') { * callback(new Error('密码错误')); * } else { * callback(); * } * } * }] */ rules?: any; } /** * 完整表单配置接口 * * 这是动态表单的顶级配置对象,包含了渲染整个表单所需的所有信息。 * 通常作为 ElementEasyForm 或 dragForm 组件的 v-model 绑定值。 * * @example 完整的表单配置 * { * "language": "zh", * "formType": "drag-form", * "schema": [...], * "model": { "username": "", "age": "" }, * "formAttrs": { "disabled": false }, * "rowAttrs": { "gutter": 20 }, * "locale": {...} * } */ export interface FormJSON { /** * 表单结构配置数组 * 定义了表单包含的所有字段及其配置 * - 数组中的每个元素对应一个表单项 * - 数组顺序决定了字段在表单中的显示顺序 * * 使用场景: * 1. 拖拽表单设计器:用户从左侧拖拽组件,schema 实时更新 * 2. 直接渲染:通过 JSON 配置定义表单结构 * 3. 动态生成:根据后端返回的数据生成 schema * * @example 简单表单 * schema: [ * { "label": "用户名", "prop": "username", "componentName": "ElInput" }, * { "label": "年龄", "prop": "age", "componentName": "ElInputNumber" } * ] * * @example 带布局的表单 * schema: [ * { * "componentName": "ElRow", * "attrs": { "gutter": 20 }, * "children": [ * { "componentName": "ElCol", "colAttrs": { "span": 12 }, "children": [...] }, * { "componentName": "ElCol", "colAttrs": { "span": 12 }, "children": [...] } * ] * } * ] */ schema: Array; /** * 表单数据模型 * 存储表单所有字段的当前值 * - 对象的 key 对应 schema 中各字段的 prop * - 组件的 v-model 绑定到此对象 * - 表单提交时使用此对象 * * 数据同步: * - 用户输入时自动更新 model 中对应的值 * - 可以通过外部修改 model 值来改变表单显示 * - watch 监听 model 变化可实现联动效果 * * @example 初始空数据 * model: { * "username": "", * "password": "", * "age": null * } * * @example 带默认值 * model: { * "username": "admin", * "remember": true, * "city": "bj" * } */ model: any; /** * 表单容器属性 * 传递给 Element Plus 组件的属性 * 用于控制整个表单的行为 * * 常用属性: * - disabled: 是否禁用整个表单 * - labelPosition: 标签位置('left'/'right'/'top') * - labelWidth: 标签宽度 * - labelSuffix: 标签后缀 * - hideRequiredAsterisk: 是否隐藏必填星号 * - showMessage: 是否显示校验错误信息 * - inlineMessage: 是否以行内形式展示校验信息 * - statusIcon: 是否在输入框中显示校验结果反馈图标 * - validateOnRuleChange: 是否在 rules 属性改变后立即触发一次验证 * - size: 表单尺寸('large'/'default'/'small') * * @example * formAttrs: { * "labelPosition": "top", * "labelWidth": "100px", * "disabled": false, * "statusIcon": true * } */ formAttrs: any; /** * 行布局属性 * 用于栅格布局系统中的行级配置 * - 传递给 Element Plus 组件 * - 主要在复杂布局中使用 * * 常用属性: * - gutter: 栅格间隔,如 20 * - type: 布局模式('flex') * - justify: flex 布局下的水平排列方式('start'/'center'/'end'/'space-between' 等) * - align: flex 布局下的垂直排列方式('top'/'middle'/'bottom') * * @example * rowAttrs: { * "gutter": 20, * "type": "flex", * "justify": "center" * } */ rowAttrs: any; }