vForm

lishihuan大约 25 分钟

vForm

《VForm组件二次开发指南》 https://www.yuque.com/docs/shareopen in new window ... ac55-a6f1845d0785?#(密码:fvih)

《VForm 3组件二次开发指南》 https://www.yuque.com/docs/shareopen in new window ... a2f2-62e14cee43c4?#(密码:hz4m)

https://www.vform666.com/vform2/open in new window

https://www.yuque.com/visualdev/vform/open in new window

下拉选调用api接口

在表单的 onFormMounted 事件中通过axios调用后端接口

https://www.yuque.com/visualdev/vform/atgf0topen in new window

image.png
image.png
import request from '@/utils/request' // 封装的axios

// 自定义表单-需要依赖 elementiUI
import vform from '../public/lib/vform/VFormDesigner.umd.min'
import '../public/lib/vform/VFormDesigner.css'
Vue.use(vform)
window.axios = request  // request 指的是axios对象,一般项目上会对去进行处理,比如添加 baseURL 和 herad/tocken 等,
// window.axios = axios

其中 service 对于是定义的axios对象,如果使用的是axios变量

const service = axios.create({
  // axios中请求配置有baseURL选项,表示请求URL公共部分
  baseURL: process.env.VUE_APP_BASE_API,
  retry: 2, // 请求次数
  retryInterval: 50000 // 求期间隙
})

其中:会用到2个 API 方法

getWidgetRef获取容器或字段组件/**通过元素的id拿到 对于的表单控件对象 **(widgetName, showError):widgetName,组件名称showError=true/false,如组件不存在是否显示错误
loadOptions加载选择项,仅支持radio/checkbox/select/cascader组件options,选项数组,格式为:[{label: '选项1', value: '1'},{label: '选项2', value: '2'},{label: '选项3', value: '3'}]

参考:https://www.yuque.com/visualdev/vform/xgugczopen in new window

var select = this.getWidgetRef('selectId')
axios.get('/system/dict/data/type/IS_AQXY').then((res)=> {
  const options = res.data.map(({ dictValue, dictLabel }) => ({ value: dictValue, label: dictLabel }));
  select.loadOptions(options)
}).catch(function(error) {
  console.error(error)
})



    let productTypeR = this.getWidgetRef('productType')
   console.log(11111)
  axios.get("https://www.fastmock.site/mock/2de212e0dc4b8e0885fea44ab9f2e1d0/vform/getOptions").then(function(res) {
    console.log(res.data)
    productTypeR.loadOptions(res.data)
  }).catch(function(error) {
    console.log(error)
  })

组件说明

src/components/form-designer/form-widget/index.vue

编辑界面主界面,对应预览界面

静态文本对应的构造组件 static-text-widget.vue

二次开发说明

当组件从左侧的组件面板拖拽到设计画布上时,会触发draggable组件的move钩子,因此在这里控制即可。 具体查看源码widget-panel\index.vue中的checkContainerMove、checkFieldMove方法。

VForm源码目录结构说明

image.png
image.png

二次开发文档目录结构

1. 容器组件开发
  1.1 定义容器JSON Schema
  1.2 开发设计状态的容器组件
    1.2.1 容器组件SFC文件编写
    1.2.2 插入Draggable组件
    1.2.3 接收组件拖放事件
    1.2.4 创建并注册组件属性设计器
  1.3 开发运行状态的容器组件
    1.3.1 容器组件SFC文件编写
    1.3.2 增加交互事件和API方法
  
2. 字段组件开发
  2.1 定义字段JSON Schema
  2.2 字段组件SFC文件编写
  2.3 创建并注册组件属性设计器
  2.4 增加交互事件和API方法
  
3. 代码自动生成

二次开发

核心的几个文件说明

  • widgetsConfig: 左侧菜单用到的组件定义
  • form-render/index: 渲染组件

1. 添加表单控件属性

列如:添加自定义 class,字体颜色、大小、粗细 设置

自定义属性用到:

  • zh-CN.js 定义属性名称 列如: fontFamilyName: '选择字体', // 字体类型

  • propertyRegister.js 定义属性和属性编辑器的组件名称对应关系 列如: 'fontFamily':'font-family-editor',// fontFamily fontStyle

  • widgetsConfig.js 设置组件的属性和默认值,结合propertyRegister.js 定义的,才能正常加载属性组件

1.1 自定义属性

考虑到目前组件给的属性无法满足需求,需要添加自己的属性,比如给组件添加自定义的class 属性

  • src/lang/zh-CN.js 中声明 class 属性名
setting: {
      className: '自定义class', // 类型 目前初始计划 定义几个公共的样式,工单:work-order
}
  • 声明组件src/components/form-designer/setting-panel/propertyRegister.js
const COMMON_PROPERTIES = {
  //字段
  'name'              :            'name-editor',
  'class'             :            'class-editor'  // 表示添加一个 class-editor.vue 组件
}
  • 添加一个 src/components/form-designer/setting-panel/property-editor/class-editor.vue 组件 ,可以仿size-editor.vue
  • src/components/form-designer/widget-panel/widgetsConfig.js 中给每个需要自定义属性的 options 对象添加 class 属性

目前class 用是下拉选,当前class 属性值决定下拉选默认值

    options: {
      name: '',
      class: '', // 自定义属性,给元素添加class属性  
    }
## 开发调试
npm run serve
## 生产打包
npm run build
## 表单设计器 + 表单渲染器打包
npm run lib
## 表单渲染器打包
npm run lib-render

1.2 表格

编辑的表格组件 table-widget.vuetable-cell-widget.vue

预览的表格: table-item.vuetable-cell-item.vue

2. 添加表单属性

以自定义主题背景色为例: 添加属性 themeColor 目前定义

属性在 src/utils/util.js getDefaultFormConfig中

export function getDefaultFormConfig() {
  return {
    modelName: 'formData',
    refName: 'vForm',
    rulesName: 'rules',
    labelWidth: 80,
    labelPosition: 'left',
    size: '',
    labelAlign: 'label-left-align',
    cssCode: '',
    customClass: [],
    functions: '',
    layoutType: 'PC',
    themeColor:'basic-theme', // 主题背景色 (basic-theme深色的切合巡检保的主题色,white-theme 白色主题色)
    onFormCreated: '',
    onFormMounted: '',
    onFormDataChange: '',
  }
}

上面中 自定义了属性 themeColor

src/components/form-designer/setting-panel/form-setting.vue 中定义 操作按钮

          <!-- 设置主题色,目前罗列了2套样式颜色,主题背景色和纯白色-->
          <el-form-item  :label="i18nt('designer.setting.themeColorName')" class="theme-select-wrap ">
            <!--<el-color-picker ref="colorPicker" v-model="formConfig.themeColor" :predefine="predefineColors" show-alpha class="el-item-ele"></el-color-picker>-->
            <el-tooltip class="item" effect="dark" content="默认主题色" placement="top-start">
              <div class="theme-select" @click="formConfig.themeColor='basic-theme'"> <span class="basic-theme"></span></div>
            </el-tooltip>
            <el-tooltip class="item" effect="dark" content="白色主题色" placement="top-start">
              <div class="theme-select" @click="formConfig.themeColor='white-theme'"> <span class="white-theme"></span></div>
            </el-tooltip>
          </el-form-item>

3. 字段组件开发

添加左侧菜单栏的组件 下面以 编号 为例

功能描述: 自定义工单,需要编号 格式为 编号:{yyyy}年{num}号

源码

3.1 extension-schema.js 添加 JSON Schema

/*
    编号,目前 表单填写的编号  稍微复杂
    编号:{yyyy}年{num}号
    所以 想通过  预设 初始化好的html 作为组件,给用户添加,以减少用户自定操作
*  */
export const codeNumSchema = {
    type: 'code-num',
    icon: 'code-num',
    formItemFlag: true,
    options: {
        name: '',
        label: '编号', // 用于显示用的--主要是表单校验是提示的字段信息
        class: '', // 自定义属性,给元素添加class属性
        fontFamily:'',
        fontStyles:{
            bold: false,
            italic: false,
            underline: false,
            color: 'rgb(12,12,12)'
        }, // 其他字体样式,加粗,倾斜,下划线,颜色
        columnWidth: '200px',
        hidden: false,
        labelHidden2: true, // 考虑到编号也需要校验格式,顾需要
        // labelWidth:'0',
        disabled: false,
        required: true, // 必填
        requiredHint: '',
        validation: 'codenum', // 目前编号 只做格式校验
        validationHint: '',
        // textContent: '编号:{yyyy}年{num}号',
        defaultValue: '编号:{yyyy}年{num}号',
        inputTextAlign: 'right',// 设置 输入框等组件 文本对其方式
       // textAlign: 'right',
        fontSize: '13px',
        lineHeight: '1.15em', // 行高,默认是1.15em
        preWrap: true,  //是否自动换行
        //-------------------
        customClass: '',  //自定义css类名
        //-------------------
        onCreated: '',
        onMounted: '',
    },
}

3.2 extension-loader.js 中

引入 并且添加到项目中

import {codeNumSchema} from "@/extension/samples/extension-schema";// JSON schema对象
import CodeNumWidget from '@/extension/samples/codeNum/code-num-widget' // 创建的 编号组件
addCustomWidgetSchema(codeNumSchema)  //加载组件Json Schema
/* -------------------------------------------------- */
Vue.component(CodeNumWidget.name, CodeNumWidget)  //注册组件

3.3 组件名称定义

zh-CN_extension.js

    widgetLabel: {
      card: '卡片',
      alert: '提示',
      'code-num': '编号', // 新增....
    },

3.4 表单校验

表单校验

其他

静态文本拖拽到容器后,字体默认颜色设置 是通过

designer.js 文件夹下 getStaticTextStyle()方法

// 针对静态文本,给出默认字体
getStaticTextStyle (newWidget) {
    // 针对 目前的2个主题色,修改 静态文字的默认字体颜色
    if ( (newWidget.type == "static-text" || newWidget.type == "code-num") && this.formConfig.themeColor == "basic-theme") { // 声色默认主题
    	newWidget.options.fontStyles.color = '#fff';
    }else if ( (newWidget.type == "static-text"|| newWidget.type == "code-num") && this.formConfig.themeColor == "white-theme") { // 白色主题
    	newWidget.options.fontStyles.color = 'rgb(12,12,12)';
    }
},

使用

1. 使用VFormDesigner组件

import vform from '../public/lib/vform/VFormDesigner.umd.min'
import '../public/lib/vform/VFormDesigner.css'
Vue.use(VForm)  //全局注册VForm(同时注册了v-form-designe、v-form-render等组件)
/* 注意:如果你的项目中有使用axios,请用下面一行代码将全局axios复位为你的axios!! */
window.axios = axios
<template>
<v-form-designer ref="vfDesignerRef" :designer-config="designerConfig">
    <template #customToolButtons>
        <el-button type="text" @click="saveFormData">保存</el-button>
</template>
</v-form-designer>
</template>

<script>
    export default {
        data() {
            return {
                designerConfig: {
                    logoHeader: false,
                    toolbarMaxWidth: 510
                }
            }
        }
    }
</script>

<style lang="scss">
    body {
        margin: 0;  /* 如果页面出现垂直滚动条,则加入此行CSS以消除之 */
    }

</style>

清除设计器的内容

 // 清空历史缓存
this.$refs.vfDesignerRef.clearDesigner();

2. 使用VFormRender组件

说明:

  • formJson是指表单设计器导出的json,包含了表单控件的样式等,用来渲染表单样式的

​ :form-json="formJson" 可以不指定 通过 setFormJson 赋值 this.$refs.vFormRef.setFormJson(formJson);

  • form-data="formData" :是用来数据初始化的,对表单控件进行默认赋值的
    • ​ form-data="formData" 可以不指定 通过 setFormData赋值 this.$refs.vFormRef.setFormData(formData);
<template>
<v-form-render :form-json="formJson" :form-data="formData" :option-data="optionData" ref="vFormRef"> </v-form-render>
</template>

<script>
    export default {
        data() {
            return {
                formData:{} // 表单字段和属性值,用于数据回显的(给表单赋值的)
                optionData: {},
                /* 注意:formJson是指表单设计器导出的json,此处演示的formJson只是一个空白表单json!! */
                formJson: {"widgetList":[],"formConfig":{"labelWidth":80,"labelPosition":"left","size":"","labelAlign":"label-left-align","cssCode":"","customClass":"","functions":"","layoutType":"PC","onFormCreated":"","onFormMounted":"","onFormDataChange":""}},

			}
		},
        methods: {
            submitForm() {
                this.$refs.vFormRef.getFormData().then(formData => {
                    // Form Validation OK
                    alert( JSON.stringify(formData) )
                }).catch(error => {
                    // Form Validation failed
                    this.$message.error(error)
                })
            }
        }
    }
</script>

额外说明,这里就会导致如果二次开发,需要修改属性,需要注意就存在2处需要同步修改

VForm组件接口文档

VForm分为两种状态:

设计状态,对应VFormDesigner组件;

渲染状态,对应于VFormRender组件。

简单地说,VFormDesigner用于生成表单JSON对象,VFormRender则将表单JSON渲染为Vue组件。

VForm表单对象由容器组件、字段组件构成,容器组件和字段组件统称为Widget

  • 容器组件,负责表单元素的排版、定位;

  • 字段组件,承载数据录入、展示及交互功能。

1. 表单组件

1.1 表单设计器——VFormDesigner

1.1.1 属性(prop)
属性名称属性值说明默认值
field-list-api配置获取后端字段列表接口对象默认为null 接口对象格式为: { URL: '字段列表接口请求地址', nameKey: 'fieldName', labelKey: 'fieldLabel' } 详情参见:字段接口文档open in new window
banned-widgets配置禁止设计器显示的组件默认为[],数据格式为组件type名称的数组,比如: ['table', 'rate', 'switch']
designer-config配置设计器初始化界面显示设置默认值为: {
languageMenu: true, //是否显示语言切换菜单
externalLink: true,//是否显示GitHub、文档等外部链接
formTemplates: true, //是否显示表单模板
widgetNameReadonly: false, //是否禁止修改唯一名称
eventCollapse: true, //是否显示组件事件属性折叠面板
clearDesignerButton: true, //是否显示清空设计器按钮
previewFormButton: true, //是否显示预览表单按钮
importJsonButton: true, //是否显示导入JSON按钮
exportJsonButton: true, //是否显示导出JSON器按钮
exportCodeButton: true, //是否显示导出代码按钮
generateSFCButton: true, //是否显示生成SFC按钮
//工具按钮栏最大宽度(单位px)
//如新增按钮后不可见,请调大
//如右侧空白区域过大,请调小
toolbarMaxWidth: 420,
//工具栏按钮最小宽度(单位px)
//值必须小于toolbarMaxWidth
toolbarMinWidth: 300,
presetCssCode: '', //表单设计器预设CSS代码
//表单设计器初始化自动清空内容 /* 如设置为true,则刷新页面时也会清空设计器画布区域,慎用!*/
resetFormJson: false,
productName: '', //设置自定义产品名称(仅Pro)
productTitle: '', //设置自定义产品标题(仅Pro)
logoHeader: true, //是否显示顶部LOGO条(仅Pro)
}
global-dsv全局数据源变量(Pro版支持) dsv即Datasource Variables(数据源变量)缩写。默认值为{},数据格式为: { "myTestURL": "xxx", "token": "aabbcc", "countLimit": 600 //可以自由添加键值对 } 在数据源中可使用 DSV["myTestURL"]、 DSV["token"]、 DSV["countLimit"] 获取上述变量值。
form-templates表单模板配置(Pro版支持)默认值为null,使用内置模板。 配置值为数组,格式为:
1.1.2 插槽
名称说明
customToolButtons用于定制表单设计器的自定义工具按钮,位于默认工具按钮的右侧。
1.1.3 原生事件

原生事件可以在Vue模板中用@事件名称或JS代码中调用Vue实例的$on添加事件处理方法。

事件名称说明回调参数
暂无
1.1.4 交互事件

交互事件可在表单设计器中编写事件处理代码。

事件名称说明回调参数
暂无
1.1.5 API方法
方法名说明参数
changeLanguage修改界面显示语言string:'zh-CN'、'en-US'
setFormJson设置表单JSON对象string/object
getFormJson获取表单JSON对象
clearDesigner清空设计器画布
refreshDesigner刷新设计器画布(几乎用不到)
previewForm打开--预览表单--弹窗
importJson打开--导入表单JSON--弹窗
exportJson打开--导出表单JSON--弹窗
exportCode打开--导出Vue/HTML代码--弹窗
generateSFC打开--生成SFC组件代码--弹窗
getFieldWidgets获取表单JSON中的所有字段,返回对象数组,格式如下: [ { type: String, name: String, field: Object }, ..., ]— 无参数 注意:该方法获取的是formJson中的字段JSON定义,并非渲染后的字段组件。
getContainerWidgets获取表单JSON中的所有容器,返回对象数组,格式如下: [ { type: String, name: String, container: Object }, ..., ]— 无参数 注意:该方法获取的是formJson中的容器JSON定义,并非渲染后的容器组件。
getWidgetRef获取设计器组件实例(widgetName, showError): widgetName,组件名称 showError=true/false,如组件不存在是否显示错误
getSelectedWidgetRef获取设计器选中的组件实例
buildFormDataSchema构建并返回表单数据结构对象,仅Pro版本支持
addDataSource增加数据源对象dsObj,数据源对象
getFormTemplates获取全部表单模板返回表单模板数组
clearFormTemplates清空全部表单模板
addFormTemplate追加新的表单模板formTemplate,表单模板对象

1.2 表单渲染器——VFormRender

1.2.1 属性(prop)
属性名称属性值说明默认值
form-json表单对象JSON 注意:如表单Json是从后端接口异步获取到的,请使用下述的API方法——setFormJson()赋值,使用form-json属性传值则会导致表单校验异常或表单渲染不成功。无默认值
option-data表单radio、checkbox、select、cascader组件的选择项集合默认值为空对象:{}, 属性值格式如下: { 'gender': [ {label: '男', value: '1'}, {label: '女', value: '2'} ], 'paymentType': [ {label: '支付宝', value: 'alipay'}, {label: '微信', value: 'wechat'} ] }
form-data表单数据对象 注意:form-data属性通常用于表单初始化时给表单传递回显数据,如需多次修改表单数据或发现表单部分数据失去响应式更新,请调用下述的setFormData(formData)方法。默认值为空对象:{}, 属性值格式如下: { 'gender': '2', 'paymentType': 'wechat' 'subForm01': [ {'price': '88.00', 'count': '12'}, {'price': '199.00', 'count': '16'} ] }
global-dsv全局数据源变量(Pro版支持) dsv即Datasource Variables(数据源变量)缩写。默认值为{},数据格式为: { "myTestURL": "xxx", "token": "aabbcc", "countLimit": 600 } 在数据源中可使用 DSV["myTestURL"]、 DSV["token"]、 DSV["countLimit"] 获取上述变量值。
1.2.2 原生事件

原生事件可以在Vue模板中用@事件名称或JS代码中调用Vue实例的$on添加事件处理方法。

事件名称说明回调参数
buttonClickbutton组件被点击时触发 注意:如果button组件的交互事件onClick属性不为空,则不会触发buttonClick原生事件,两者不会同时生效。buttonWidget:被点击的按钮组件
appendButtonClickinput组件的附加按钮被点击时触发widget:input组件
formChange表单数据改变后触发(fieldName, newValue, oldValue, formModel, subFormName, subFormRowIndex): fieldName,触发本事件的字段名 newValue,字段新值 oldValue,字段旧值 formModel,表单数据对象 如果是子表单数据改变,则还会返回下述两个回调参数: subFormName, 子表单名称 subFormRowIndex, 子表单行索引
1.2.3 交互事件

交互事件可在表单设计器中编写事件处理代码。

事件名称说明回调参数
onFormCreated表单创建后触发
onFormMounted表单挂载后触发
onFormDataChange表单数据改变后触发(fieldName, newValue, oldValue, formModel, subFormName, subFormRowIndex): fieldName,触发本事件的字段名 newValue,字段新值 oldValue,字段旧值 formModel,表单数据对象 如果是子表单数据改变,则还会返回下述两个回调参数: subFormName, 子表单名称 subFormRowIndex, 子表单行索引
1.2.4 API方法
方法名说明参数
changeLanguage修改界面显示语言string:'zh-CN'、'en-US'
setFormJson动态加载表单JSON对象string/object
getWidgetRef获取容器或字段组件(widgetName, showError): widgetName,组件名称 showError=true/false,如组件不存在是否显示错误
getNativeForm获取内嵌的el-form组件
validateForm表单数据是否验证通过callback(valid),回调函数,接受valid参数(true/false)
getFormData获取表单数据对象(needValidation = true),获取表单数据时是否开启表单校验,默认开启。 注意:开启表单校验,返回的是一个Promise对象,否则返回数据对象。
setFormData设置表单数据对象formData,表单数据JSON对象
getFieldValue获取表单单个字段值fieldName,字段名称
setFieldValue设置表单单个字段值(fieldName, fieldValue):字段键值对
reloadOptionData刷新选项类型字段的选项数据(选项数据是从option-data属性传入的)widgetNames,组件名称,格式为字符串或字符串数组,不传该参数则刷新所有选项类型字段
getSubFormValues获取子表单数据对象subFormName,子表单名称
disableForm禁用表单编辑
enableForm启用表单编辑
resetForm重置表单数据,并清除校验状态
setReadMode设置表单为只读查看状态,仅Pro版本支持(readMode = true):只读查看标志,true/false,默认值为true
disableWidgets一个或多个组件禁用编辑widgetNames,组件名称,格式为字符串或字符串数组
enableWidgets一个或多个组件启用编辑widgetNames,组件名称,格式为字符串或字符串数组
hideWidgets隐藏一个或多个组件widgetNames,组件名称,格式为字符串或字符串数组
showWidgets显示一个或多个组件widgetNames,组件名称,格式为字符串或字符串数组
getFieldWidgets获取表单JSON中的所有字段,返回对象数组,格式如下: [ { type: String, name: String, field: Object }, ..., ]— 无参数 注意:该方法获取的是formJson中的字段JSON定义,并非渲染后的字段组件,如需获取字段组件,需要进一步调用getWidgetRef()方法。
getContainerWidgets获取表单JSON中的所有容器,返回对象数组,格式如下: [ { type: String, name: String, container: Object }, ..., ]— 无参数 注意:该方法获取的是formJson中的容器JSON定义,并非渲染后的容器组件,如需获取容器组件,需要进一步调用getWidgetRef()方法。
addEC增加外部组件实例引用,以便在VForm组件内部调用外部组件方法。 EC即external component(外部组件)缩写。(componentName, externalComponent): componentName, 外部组件名称 externalComponent, 外部组件实例
hasEC判断是否存在外部组件实例componentName, 外部组件名称
getEC获取外部组件实例componentName, 外部组件名称
getGlobalDsv获取全局数据源变量(Pro版支持)— 无参数
showDialog显示弹出窗口(Pro版支持)(dialogName, formData, extraData): dialogName,弹窗唯一名称 formData,弹窗表单回填数据 extraData,外部数据,用于其他逻辑处理
showDrawer显示侧滑抽屉(Pro版支持)(drawerName, formData, extraData): drawerName,抽屉唯一名称 formData,抽屉表单回填数据 extraData,外部数据,用于其他逻辑处理
executeDataSource执行数据源请求(dsName, localDsv): dsName,数据源名称 localDsv,本地DSV变量, localDsv对象会自动跟全局数据源对象globalDsv合并,合并之后传递给数据源,数据源设置处可通过DSV对象获取
getDialogOrDrawerRef弹窗、抽屉组件在渲染阶段,会动态创建一个v-form-render组件,弹窗和抽屉内的组件由此动态创建的v-form-render负责渲染。本方法可以获取表单所在的弹窗、抽屉组件实例,以便调用弹窗、抽屉组件的API方法。— 无参数

容器组件的交互事件与API方法

交互事件

交互事件可在表单设计器中编写事件处理代码。

事件名称说明回调参数
onSubFormRowAdd子表单新增行时触发(subFormData, newRowId):新增后的子表单数据,新增行Id(非行索引)
onSubFormRowInsert子表单插入行时触发(subFormData, newRowId):插入后的子表单数据,插入行Id(非行索引)
onSubFormRowDelete子表单删除行时触发(subFormData, deletedDataRow):删除后的子表单数据,删除行数据
onSubFormRowChange子表单新增行、插入行、删除行时触发(subFormData):变化后的子表单数据

API方法

方法名说明参数
getFormRef获取VFormRender组件
getWidgetRef获取容器或字段组件(widgetName, showError): 组件名称,如组件不存在是否显示错误
setHidden设置是否隐藏容器true/false
setDisabled设置是否禁用容器(包含容器内部组件)true/false
getActiveTabIndex获取当前激活Tab页签索引
activeTab激活Tab页签指定页tabIndex:tab页索引
disableTab禁用Tab页签指定页tabIndex:tab页索引
enableTab恢复Tab页签指定页tabIndex:tab页索引
hideTab隐藏Tab页签指定页tabIndex:tab页索引
showTab显示Tab页签指定页tabIndex:tab页索引
disableSubFormRow禁用子表单指定行rowIndex:行索引
enableSubFormRow恢复子表单指定行rowIndex:行索引
disableSubForm禁用子表单
enableSubForm恢复子表单
resetSubForm重置子表单数据为空
getSubFormValues获取子表单数据
setSubFormValues设置子表单数据参数为键值对数组,格式如下: [ {name: 'Jack', age: 19}, {name: 'Rose', age: 18} ]
getGlobalDsv获取全局数据源变量(Pro版支持)— 无参数

字段组件的交互事件与API方法

交互事件

交互事件可在表单设计器中编写事件处理代码。

事件名称说明回调参数
onCreated组件创建后触发
onMounted组件挂载后触发
onClick按钮被点击触发
onInput输入框值改变时触发value:当前输入值
onChange组件数据(v-model)改变时触发(value, oldValue, subFormData, rowId): value,当前数据值 oldValue,变化之前的数据值 如果字段位于子表单内,还会返回下述两个回调参数: subFormData,组件所在子表单数据 rowId,组件所在子表单的行Id(非行索引)
onFocus获得焦点时触发event:事件
onBlur失效焦点时触发event:事件
onValidate组件数据校验时触发(rule, value, callback): rule,组件校验规则 value,组件数据值 callback,校验回调函数
onBeforeUpload图片或文件组件开始上传时触发file:上传文件
onUploadSuccess图片或文件组件上传成功后触发(result, file, fileList): result,上传处理结果 file,当前上传文件 fileList,上传文件列表
onUploadError图片或文件组件上传失败后触发(error, file, fileList): error,错误信息 file,当前上传文件 fileList,上传文件列表
onFileRemove删除图片或文件时触发(file, fileList): file,被删除文件 fileList,文件列表
onRemoteQuery下拉选项组件(Select)远程搜索时触发keyword:搜索词

API方法

方法名说明参数
getFormRef获取VFormRender组件
getWidgetRef获取容器或字段组件(widgetName, showError): widgetName,组件名称 showError=true/false,如组件不存在是否显示错误
setValue设置组件数据值newValue,组件数据值
getValue获取组件数据值
resetField重置组件为默认值,并清除组件校验状态
setReadonly设置组件是否只读,仅input、textarea、time、time-range、date、date-range等部分组件支持true/false
setReadMode设置组件为只读查看状态,仅Pro版本支持(readMode = true):只读查看标志,true/false,默认值为true
setDisabled设置组件是否禁用true/false
setAppendButtonVisible设置组件附加按钮是否可见,仅支持inputtrue/false
setAppendButtonDisabled设置组件附加按钮是否禁用,仅支持inputtrue/false
setHidden设置组件是否隐藏true/false
setRequired设置组件是否必填true/false
setLabel设置组件标签文字(label)newLabel,新标签文字
focus让组件获得输入焦点
loadOptions加载选择项,仅支持radio/checkbox/select/cascader组件options,选项数组,格式为: [ {label: '选项1', value: '1'}, {label: '选项2', value: '2'}, {label: '选项3', value: '3'} ]
getOptions返回radio/checkbox/select/cascader组件的选择项数组
disableOption禁用指定选择项,仅支持radio/checkbox/select/cascader组件optionValue,被禁用的选项值
enableOption启用指定选择项,仅支持radio/checkbox/select/cascader组件optionValue,被启用的选项值
setUploadHeader设置文件或图片组件请求头(Header)(name, value):请求头键值对
setUploadData设置文件或图片组件上传参数(name, value):参数键值对
setToolbar设置富文本组件默认工具栏按钮customToolbar,工具按钮数组,详细参见Vue2Editor文档
setWidgetOption设置组件属性(optionName, optionValue): optionName,组件属性名 optionValue,属性值
getFieldEditor获取组件内嵌的Element UI表单组件
getGlobalDsv获取全局数据源变量(Pro版支持)— 无参数

开发记录

1. fieldModel 定义

在表单控件列如: input-widget 中 属性值fieldModel 是由 混入fieldMixin.js 中initFieldModel方法 初始化的

fieldModel

2. 字段值修改

例如给日期添加默认值,需要调用下面的2个方法,否则不生效

this.handleChangeEvent(this.fieldModel);
this.handleInputCustomEvent(this.fieldModel);

3. setFormData 数据回显的实现

组件通过混入fieldMixin.js 调用initEventHandler() 方法,实现对setFormData 方法的监听,这个方法就是用来数据回显写入的

组件中的几个方法说明

表单组件能正常使用需要下面的几个方法

created() {
    this.initFieldModel();// ==================================================完成对 fieldModel 的初始化
    this.registerToRefList()
    this.initEventHandler()

    this.handleOnCreated();
    this.buildFieldRules();// ==================================================添加 规则校验
},

设计期

this.designState

表单校验

validators.js 封装了了格式的校验

如果只是简单的自定义,例如目前 添加的编号字段组件,需要用户输入的格式为 编号:{yyyy}年{num}号

image-20231106104704053
image-20231106104704053

源码

    <form-item-wrapper :designer="designer" :field="field" :rules="rules" :design-state="designState"
                       :parent-widget="parentWidget" :parent-list="parentList" :index-of-parent-list="indexOfParentList"
                       :sub-form-row-index="subFormRowIndex" :sub-form-col-index="subFormColIndex" :sub-form-row-id="subFormRowId">
        <div ref="fieldEditor" :style="!!field.options.fontSize ? `font-size: ${field.options.fontSize};`: ''" >
            <!--:title="displayTitle"-->
            <pre class="" :style="textStyle"  @click="updateField" v-if="!isEdit">{{fieldModel}}</pre>
            <!-- 点击后-->
           <el-input ref="fieldEditor" v-model="fieldModel" v-if="isEdit" @focus="handleFocusCustomEvent"
                      @blur="handleBlurCustomEvent2" @input="handleInputCustomEvent" @change="handleChangeEvent"/>
        </div>
    </form-item-wrapper>
created() {
// 添加 规则校验
    this.buildFieldRules();
},

需要关联到下面的几个方法,主要涉及数据修改,和触发字段的校验

@focus="handleFocusCustomEvent" @blur="handleBlurCustomEvent" @input="handleInputCustomEvent"
@change="handleChangeEvent"

extension-schema.js

添加关于表单校验的几个字段

  • readonly: false,
  • disabled: false,
  • required: true, // 必填
  • requiredHint: '',
  • validation: 'codenum', // 目前编号 只做格式校验
  • validationHint: '',
/*
    编号,目前 表单填写的编号  稍微复杂
    编号:{yyyy}年{num}号
    所以 想通过  预设 初始化好的html 作为组件,给用户添加,以减少用户自定操作
*  */
export const codeNumSchema = {
    type: 'code-num',
    icon: 'code-num',
    formItemFlag: true,
    options: {
        name: '',
        label: '编号', // 用于显示用的--主要是表单校验是提示的字段信息
        class: '', // 自定义属性,给元素添加class属性
        fontFamily:'',
        fontStyles:{
            bold: false,
            italic: false,
            underline: false,
            color: 'rgb(12,12,12)'
        }, // 其他字体样式,加粗,倾斜,下划线,颜色
        columnWidth: '200px',
        hidden: false,
        labelHidden2: true, // 考虑到编号也需要校验格式,顾需要
        // labelWidth:'0',
        disabled: false,
        required: true, // 必填
        requiredHint: '',
        validation: 'codenum', // 目前编号 只做格式校验
        validationHint: '',
        // textContent: '编号:{yyyy}年{num}号',
        defaultValue: '编号:{yyyy}年{num}号',
        inputTextAlign: 'right',// 设置 输入框等组件 文本对其方式
       // textAlign: 'right',
        fontSize: '13px',
        lineHeight: '1.15em', // 行高,默认是1.15em
        preWrap: true,  //是否自动换行
        //-------------------
        customClass: '',  //自定义css类名
        //-------------------
        onCreated: '',
        onMounted: '',
    },
}

extension-schema.js

  // FormValidators对象中添加
  /* 编号 格式  */
  codenum(rule, value, callback) {
    var date = new Date();
    var year = date.getFullYear();
    // 编号:{yyyy}年{num}号
    const errorMes = `格式异常,要求格式为:年份+三位数的序号,列如 '编号:${year}年001号'`;
    validateFn('codenum', rule, value, callback, '[' + rule.label + ']'+errorMes)
  },
// commonRegExp 对象中添加 校验正则规则
 codenum: '/^编号:\\d{4}年\\d{3}号$/' // 自定义的 校验,针对的是 编号组件

下拉选拓展

对于其他组件二次开发,需要公用一个文件处理

下拉选接口处理

axios

Vue.use(VForm)  //全局注册VForm(同时注册了v-form-designe、v-form-render等组件)
/* 注意:如果你的项目中有使用axios,请用下面一行代码将全局axios复位为你的axios!! */
window.axios = axios

如果表单设计器中想使用项目的axios可以通过 window.axios

            getCodeName(url){
                window.axios.get(url).then(({data:res}) => {
                    this.fieldModel = res.data;
                    this.handleChangeEvent(this.fieldModel);
                }).catch(error => {
                    console.error(error);
                });
            },

如果是写在表单设计器中的函数中,入onCreated 则不用 window.

 saveCommonInterface(){
              if (!this.selectedWidget.options.selectApiId) {
                  this.$message.error('请选择常用接口...');
                  return;
              }
              this.showCommonInterface = false;
              this.selectedWidget.options.optionItems = [] ;// 重置,
              this.selectedWidget.options.onCreated = this.initCommonInterfaceFun();

          },
          // 构造 radio,checkbox,,select 下拉选数据获取函数
          initCommonInterfaceFun(){
              const selectItem = this.commonInterfaceOptions.find(item=>item.value === this.selectedWidget.options.selectApiId);
              const valueField = selectItem.valueField || 'dictValue';
              const labelField = selectItem.labelField || 'labelField';
              return `
                let dom  = this.getWidgetRef('${this.selectedWidget.id}');
                axios.get('${selectItem.url}').then((res)=> {
                    const options = res.data.map(item => ({ value: item['${valueField}'], label: item['${labelField}']}));
                    dom.loadOptions(options)
                }).catch(function(error) {
                    console.error(error)
                })
              `;
          },

行内布局

没有实现,设计思路:

行类布局 display: inline-block;

<div class="widget-inline widget-view active">
    <div class="widget-inline-content">
    	<div class="widget-inline-list"> 
        </div>
    </div>
    <div class="widget-view-action widget-inline-action">
        <i title="复制" class="fm-iconfont icon-icon_clone"></i>
        <i title="删除" class="fm-iconfont icon-trash"></i>
    </div>
    <div class="widget-view-drag widget-inline-drag">
        <i class="fm-iconfont icon-drag drag-widget"></i>
    </div>
    <div class="widget-view-model" style="color: rgb(102, 102, 102);">
        <span>inline_2ot9ifka</span>
    </div>
    <div class="widget-view-type"><span>行内布局</span></div>
</div>

dispatch 方法说明

调用名为'VFormRender'的组件的'fieldDefaultChanged'方法,并传递两个参数:value和this.field.idopen in new window

 this.dispatch('VFormRender', 'fieldDefaultChanged', [value,this.field.id]);
export default {
    name: "VForm-render",
    componentName: 'VFormRender', // 对应dispatch 中的第一个参数 
    created() {
      this.fieldDefaultChangedHandler(); // 注册  fieldDefaultChanged 方法,后面通过dispatch 进行
    },
    methods:{
        fieldDefaultChangedHandler(){
            this.$on('fieldDefaultChanged', (value,fieldId) => { // 对fieldDefaultChanged 方法进行监听 
                console.log(value,fieldId)})
        },
    }  
}