UNPKG

element-easy-form

Version:

vue3.0 的自定义表单,基于element-Plus

476 lines (474 loc) 15.5 kB
import { FormItemJSON } from '../element-easy-form'; import { AttrType, ComponentType } from './enum'; import { WatchOptions } from 'vue'; /** * ======================================== * 拖拽表单设计器类型定义 * ======================================== * 本文件定义了用于可视化表单设计器的类型和工厂函数。 * DragFormType 是设计器中每个组件的数据结构,扩展了基础的 FormItemJSON。 * * 与 FormItemJSON 的区别: * - FormItemJSON: 运行时表单渲染用的轻量级配置 * - DragFormType: 设计器用的增强配置,包含额外的设计时信息(id、active、attrsJson等) */ /** * Watch 监听器配置接口 * * 用于在设计器中为组件添加响应式监听 * 监听某个属性的变化并执行相应操作 * * @example 监听 prop 变化 * { * "prop": "attrs.disabled", * "immediate": true, * "handler": (value, children) => { * console.log('disabled 变为:', value); * } * } * * @example 监听并联动子组件 * { * "prop": "attrs.value", * "handler": (value, children) => { * children.forEach(child => { * child.attrs.placeholder = value; * }); * } * } */ interface WatchHandler { /** * 监听的属性路径 * 支持点号访问嵌套属性 * * @example "attrs.disabled" - 监听组件的 disabled 属性 * @example "attrs.value" - 监听组件的 value 属性 * @example "attrsJson[0].defaultValue" - 监听属性配置数组中某项的默认值 */ prop: string; /** * 是否立即执行一次监听器 * - true: 组件初始化时立即调用 handler * - false: 只在属性变化时调用 * * 默认: false */ immediate?: boolean; /** * Vue watch 配置选项 * 用于精细控制监听行为 * * 可选配置: * - deep: 是否深度监听对象/数组 * - flush: 回调的触发时机('pre'/'post'/'sync') * * @example { "deep": true } - 深度监听对象变化 * @example { "deep": false, "flush": "post" } - 不深度监听,回调在 DOM 更新后触发 */ options?: WatchOptions; /** * 属性变化时的回调函数 * 在监听的属性值改变时执行 * * @param value - 属性的新值 * @param children - 组件的子组件数组(可选) * * 使用场景: * 1. 联动更新子组件属性 * 2. 根据某个属性值的变化执行自定义逻辑 * 3. 属性间的复杂联动关系 * * @example 简单日志输出 * handler: (value) => { * console.log('值变为:', value); * } * * @example 联动更新子组件 * handler: (value, children) => { * if (children) { * children.forEach(child => { * if (child.componentName === 'ElOption') { * child.attrs.disabled = value; * } * }); * } * } */ handler: (value: any, children?: any[]) => void; } /** * 拖拽表单组件类型 * * 扩展自 FormItemJSON,在运行时表单配置的基础上增加了设计器所需的属性 * 用于拖拽表单设计器中每个组件的内部表示 * * 继承自 FormItemJSON 的属性: * - label, prop, componentName, attrs, events, defaultValue, hidden, children, rules 等 * * 新增的设计器专属属性: * - id: 组件唯一标识(设计器中生成) * - type: 组件分类(布局/组件/表单项) * - attrsJson: 属性配置元数据(用于生成右侧属性面板) * - title: 设计器中的显示标题 * - active: 当前选中状态 * - formType: 支持的表单类型 * - parentId: 父组件 ID * - watch: 属性监听配置 * * 使用场景: * 1. 左侧组件列表:定义可拖拽的组件模板 * 2. 中间画布:定义已拖入的组件实例 * 3. 右侧属性面板:通过 attrsJson 生成属性编辑表单 * 4. 拖拽交互:通过 id、parentId 管理组件树结构 * * @example 设计器中的输入框组件 * { * // 继承自 FormItemJSON 的运行时属性 * "label": "用户名", * "prop": "username", * "componentName": "ElInput", * "attrs": { "type": "text", "placeholder": "请输入" }, * * // 设计器专属属性 * "id": "a1b2c3d4-e5f6-7890-1234-567890abcdef", * "title": "输入框", * "type": "COMPONENT", * "active": false, * "formType": "all", * "parentId": "parent-row-id", * * // 属性配置元数据(用于生成右侧属性编辑面板) * "attrsJson": [ * { * "label": "类型", * "prop": "attrs.type", * "componentName": "ElSelect", * "type": "COMPONENT", * "defaultValue": "text", * "children": [ * { "componentName": "ElOption", "value": "text", "label": "文本" }, * { "componentName": "ElOption", "value": "password", "label": "密码" } * ] * }, * { * "label": "占位符", * "prop": "attrs.placeholder", * "componentName": "ElInput", * "type": "COMPONENT", * "defaultValue": "请输入" * } * ], * * // 属性监听器 * "watch": [ * { * "prop": "attrs.type", * "handler": (value) => { * console.log('输入框类型变为:', value); * } * } * ] * } * * @example 设计器中的栅格列组件 * { * "id": "col-1", * "title": "列", * "componentName": "ElCol", * "type": "LAYOUT", * "attrs": { "span": 12 }, * "parentId": "row-1", * "children": [...], * "attrsJson": [...] * } */ export interface DragFormType extends FormItemJSON { /** * 组件唯一标识符 * 设计器中每个组件实例的唯一 ID * - 使用 UUID 生成 * - 用于在拖拽操作中识别组件 * - 用于建立父子关系(parentId) * - 用于选中组件时的状态管理 * * 使用场景: * 1. 拖拽时克隆组件生成新 ID * 2. 右侧属性面板选中组件时通过 id 查找 * 3. 删除组件时通过 id 从数组中移除 * 4. 导出 JSON 时保留组件层级关系 * * 注意: * - 生成最终表单 JSON 时,运行时不需要这些 ID * - 只在设计器中使用 * * @example "550e8400-e29b-41d4-a716-446655440000" */ id?: string; /** * 组件分类类型 * 标识组件在设计器中的分类和用途 * * 可选值(参考 AttrType 枚举): * - "COMPONENT": 表单组件(输入框、选择器等) * - "LAYOUT": 布局组件(ElRow、ElCol) * - "FORMITEM": 表单项容器属性 * * 使用场景: * 1. 过滤左侧组件列表(按 formType 显示不同类型) * 2. 控制拖拽规则(某些组件只能拖入特定容器) * 3. 右侧属性面板渲染不同的表单项 * * @example "COMPONENT" - 表单字段组件 * @example "LAYOUT" - 栅格布局组件 * @example "FORMITEM" - FormItem 属性配置 */ type?: string; /** * 属性配置元数据数组 * 定义了该组件在右侧属性面板中可配置的所有属性 * - 数组中每个元素是一个 FormItemJSON * - 用于动态生成属性编辑表单 * - 与 attrs 是不同的概念:attrs 是组件本身的属性,attrsJson 是如何配置这些属性的元数据 * * 属性配置项结构: * - prop: 要配置的组件属性路径(如 "attrs.type") * - label: 属性显示名称 * - componentName: 用于编辑该属性的组件(ElInput、ElSelect 等) * - defaultValue: 默认值 * - children: 对于需要子组件的属性(如 ElSelect 需要 ElOption) * - type: 属性分类(COMPONENT/FORMITEM/LAYOUT) * * 使用场景: * 1. 设计器右侧属性面板自动生成 * 2. 可视化配置组件的所有可配置属性 * 3. 属性面板的表单验证 * * @example ElInput 的 attrsJson * attrsJson: [ * { * "label": "类型", * "prop": "attrs.type", * "type": "COMPONENT", * "componentName": "ElSelect", * "defaultValue": "text", * "children": [ * { "componentName": "ElOption", "value": "text", "label": "文本" }, * { "componentName": "ElOption", "value": "password", "label": "密码" } * ] * }, * { * "label": "占位符", * "prop": "attrs.placeholder", * "type": "COMPONENT", * "componentName": "ElInput", * "defaultValue": "请输入" * }, * { * "label": "是否禁用", * "prop": "attrs.disabled", * "type": "COMPONENT", * "componentName": "ElSwitch", * "defaultValue": false * } * ] * * @example ElRow 的 attrsJson(配置列的 span) * attrsJson: [ * { * "label": "栅格列配置", * "prop": "attrsJson", * "type": "FORMITEM", * "componentName": "ElRowAttrs", * "defaultValue": [ * { "attrs": { "span": 12 } }, * { "attrs": { "span": 12 } } * ] * } * ] */ attrsJson?: FormItemJSON[]; /** * 组件显示标题 * 在设计器中展示给用户的组件名称 * - 固定值,用户不可更改 * - 用于左侧组件列表按钮的文字 * - 用于中间画布组件的标题显示 * - 不同于 label(label 是表单字段的标签,title 是设计器中的组件名) * * @example "输入框" * @example "下拉选择" * @example "日期选择器" * @example "栅格行" */ title?: string; /** * 当前激活状态 * 标识组件是否被用户选中 * - true: 组件被选中(在画布上高亮,右侧显示属性面板) * - false: 组件未被选中 * * 使用场景: * 1. 点击画布中的组件,设置 active = true * 2. 点击画布空白处,清除所有组件的 active 状态 * 3. 根据 active 状态渲染高亮样式(边框、阴影等) * 4. 右侧属性面板根据 active 组件显示对应属性 * * 注意: * - 同一时间只能有一个组件处于 active 状态 * - 切换组件选中时需要更新其他组件的 active 为 false * - 最终导出的 JSON 中不包含此字段 * * @example 被选中的组件: { "active": true, ... } * @example 未选中的组件: { "active": false, ... } */ active?: boolean; /** * 支持的表单类型 * 标识该组件在哪种表单模式下可用 * * 可选值(参考 JSONType 枚举): * - "drag-form": 仅在拖拽表单模式下可用 * - "element-easy-form": 仅在二开表单模式下可用 * - "all": 在两种模式下都可用 * * 使用场景: * 1. 切换表单类型时过滤左侧组件列表 * 2. 控制不同模式下显示不同的可用组件 * * @example "all" - 两种表单类型都支持 * @example "drag-form" - 仅拖拽表单模式支持 * @example "element-easy-form" - 仅二开表单模式支持 */ formType?: string; /** * 父组件唯一标识符 * 标识当前组件的父组件,用于构建组件树结构 * - 对于根级组件,parentId 可能为空 * - 对于子组件,parentId 指向其父组件的 id * * 使用场景: * 1. 建立组件层级关系(树形结构) * 2. 拖拽时判断组件是否可以放置到某个容器内 * 3. 删除父组件时同时删除所有子组件 * 4. 查找组件的父级或兄弟组件 * 5. 导出 JSON 时重建嵌套结构 * * @example 顶层组件: parentId = undefined 或 "" * @example ElOption: parentId = "el-select-id" * @example ElCol: parentId = "el-row-id" */ parentId?: string; /** * 属性监听器配置 * 用于监听组件自身属性的变化并执行回调 * - 可以配置单个监听器或监听器数组 * - 监听器在属性值变化时自动触发 * * 使用场景: * 1. 联动更新子组件的属性(如改变 Select 的值,影响 Option 的状态) * 2. 属性之间的依赖关系(如改变某个属性,自动调整其他属性) * 3. 属性变化时的自定义业务逻辑 * 4. 组件初始化时的默认设置(使用 immediate: true) * * @example 监听单个属性 * watch: { * "prop": "attrs.disabled", * "immediate": true, * "handler": (value) => { * console.log('disabled 变为:', value); * } * } * * @example 监听多个属性(数组形式) * watch: [ * { * "prop": "attrs.type", * "handler": (value) => { * // 输入框类型改变时的处理 * } * }, * { * "prop": "attrs.placeholder", * "handler": (value) => { * // 占位符改变时的处理 * } * } * ] * * @example 联动更新子组件 * watch: { * "prop": "attrs.value", * "handler": (value, children) => { * if (children) { * children.forEach(child => { * child.attrs.label = `选项 ${value}`; * }); * } * } * } */ watch?: WatchHandler | WatchHandler[]; } /** * 创建 ElCol 栅格列数据工厂函数 * * 生成 ElCol 组件在设计器中的标准配置 * 常用于 ElRow 的子组件创建 * * @param span - 栅格占位格数,默认使用 SPANDEFAULT * @param parentId - 父组件 ID,默认为空字符串 * * @returns DragFormType - ElCol 组件配置对象 * * @example 创建一个占12格的列 * const col1 = ElColDragFormData(12, "row-1"); * // 结果: { title: "列", type: "LAYOUT", componentName: "ElCol", attrs: { span: 12 }, ... } * * @example 创建一个占8格的列 * const col2 = ElColDragFormData(8, "row-1"); * // 结果: { title: "列", type: "LAYOUT", componentName: "ElCol", attrs: { span: 8 }, ... } * * @example 使用默认 span * const col3 = ElColDragFormData(undefined, "row-1"); * // 结果: { title: "列", type: "LAYOUT", componentName: "ElCol", attrs: { span: SPANDEFAULT }, ... } */ export declare const ElColDragFormData: (span?: number, parentId?: string) => { title: string; type: AttrType; componentName: ComponentType; attrs: { span: number; }; parentId: string; children: never[]; attrsJson: DragFormType[]; }; /** * 创建表格列数据工厂函数 * * 生成 ElDragTable 组件的列配置 * 用于动态表格的列定义 * * @param span - (未使用)保留参数,未来可能扩展 * * @returns DragFormType - 表格列配置对象 * * @example 创建一个表格列 * const column = ElTableColumnsData(); * // 结果: { title: "列", type: "COMPONENT", componentName: "ElDragTableColumns", ... } * * 注意: * - 此函数返回的列配置是一个模板 * - 实际使用时需要设置 prop、label 等属性 * - 表格组件的 children 数组包含多个列配置 */ export declare const ElTableColumnsData: (span?: number) => { title: string; type: AttrType; componentName: ComponentType; attrs: {}; children: never[]; attrsJson: never[]; }; export {};