3.0.1 • Published 3 months ago

vue3-form-designer v3.0.1

Weekly downloads
-
License
MIT
Repository
-
Last release
3 months ago

element-plus-form-designer

基于 vue3 和 element-plus 的表单设计器.

#原作者:(lucky7)https://gitee.com/loogn/element-plus-form-designer

#基于原来的基础上做的修改 ##源代码git:https://gitee.com/roffer-d/vue3-form-designer.git

包含三个组件 FormDesigner、FormRenderer 和 FormViewer. FormDesigner 组件用于设计表单,FormRenderer 组件用于呈现表单组件和获取表单提交数据,FormViewer 组件查看数据。

npm i vue3-form-designer

预览

FormDesigner 使用

setup代码:

import { reactive } from "vue";
import { FormDesigner } from "vue3-form-designer";
import "vue3-form-designer/dist/style.css";
let data = reactive({});
//上传配置
let uploadOptions = {
  action: 'http://localhost/UploadFile',
  getHeaders: function () {
    return { 'token': '123456' };
  },
  getFileHook: (res) => {
    if (res.success) {
      return {
        name: res.url.substr(res.url.lastIndexOf('/') + 1),
        url: res.url
      };
    } else {
      return res.msg;
    }
  }
}
// 默认控件配置
let controlGroups = [
  {
    name: '基础组件',
    controls: ['input', 'textarea', 'inputnumber', 'select', 'radio', 'checkbox',
      'rate', 'color', 'date', 'time', 'switch', 'slider', 'text', 'html', 'link', 'divider']
  },
  {
    name: '高级组件',
    controls: ['subForm','upload', 'uploadImage', 'region', 'cascader', 'editor','table','tab','geographicalPosition']
  }, 
    {
        name: '个性化组件',
        controls: [
                    'position', 
                    'licenseDistinguish', 
                    'businessLicenseDistinguish', 
                    'faceDistinguish',
                    'voiceToText', 
                    'licensePlateDistinguish', 
                    'idCardDistinguish', 
                    'currencyOcr','autograph',
                    'qrcode','code32','txcode',
        ]
    }
];

// 英文值下拉数据,如果有长度,则是下拉,没有该数据则是输入框
const enData = {
    label:'label',//指定显示的key
    value:'value',//指定v-model的key
    options:[
        {label: '选择1',value: '1'},
        {label: '选择2',value: '2'}
    ]//数据集合
}

//自定义表单项按钮点击事件
function itemCustomButtonClick(element) {
    console.log(element)
}

//删除表单元素
const deleteItem = (element)=>{
    console.log('删除表单元素:',element)
}
//复制表单元素
const copyItem = (element)=>{
    console.log('复制表单元素:',element)
}

###若没有能满足需求的组件,可以向表单设计器传入自定义组件:

import test1 from './components/custom/test1'
import test2 from './components/custom/test2'
//自定义组件
const customComponents = [
    {
        groupName: '自定义组件1',
        components: {test1,test2}
    },
    {
        groupName: '自定义组件2',
        components: {test1,test2}
    }
]

####将自定义组件挂在上去

<FormDesigner ... :customComponents="customComponents">
test1、test2分别为目录,该目录下包含:
    index.js 控制器,定义组件的所有属性内容
    PropsEditor.vue 定义组件的属性配置项
    Renderer.vue 拖拽该组件后呈现的内容
    Viewer.vue 预览内容

###index.js

import Renderer from "./Renderer.vue";
import PropEditor from "./PropsEditor.vue";
import Viewer from './Viewer.vue';

class Control {
    constructor(props) {
        this.type = 'test';
        this.name = '测试组件';
        this.key = Date.now();
        this.id = this.type + "_" + this.key;
        this.lock = false;
        this.dataType = 'string';

        this.props = {
            type: 'test',
            width: 12,
            showLabel: true,
            labelWidth: undefined,
            label: '测试组件',
            enName: '', // 英文名称
            inputType: 'text', //类型
            defaultValue: '',
            placeholder: '',
            required: false,
            ...props
        };
        this.rules = [
            {message: '必填字段', required: !!props?.required}
        ]
    }
}

Control.type = "test";
Control.label = "测试组件";
Control.icon = "https://t7.baidu.com/it/u=1819248061,230866778&fm=193&f=GIF";
export default {Control, Renderer, PropEditor, Viewer};

###PropsEditor.vue

<script setup>
    let props = defineProps({
    control: Object,
    formProps: Object,
    enData: Object
})

    function requiredChange(value) {
    props.control.rules[0].required = value;
}

    function requiredMessageChange(value) {
    props.control.rules[0].message = value;
}
</script>

<template>
    <el-form label-width="90px">
        <el-form-item label="中文名称">
            <el-input v-model="control.props.label" placeholder="请输入中文名称" :disabled="control.props.disabled"></el-input>
    </el-form-item>
    <el-form-item label="填写提示">
        <el-input v-model="control.props.placeholder" placeholder="请输入填写提示"></el-input>
    </el-form-item>
    <el-form-item label="描述信息">
        <el-input type="textarea" rows="5" v-model="control.props.remark" placeholder="请输入描述信息"></el-input>
    </el-form-item>
    <el-form-item label="是否必填">
        <el-switch @change="requiredChange" v-model="control.props.required"></el-switch>
</el-form-item>
<el-form-item label="必填提示" v-if="control.props.required">
    <el-input @change="requiredMessageChange" v-model="control.props.requiredMessage"></el-input>
</el-form-item>
</el-form>
</template>

###Renderer.vue

<script setup>
defineProps({
    control: Object,
    model: Object,
})
</script>

<template>
  <el-radio-group v-if="model" v-model="model[control.id]" size="large">
    <el-radio-button label="New York" />
    <el-radio-button label="Washington" />
    <el-radio-button label="Los Angeles" />
    <el-radio-button label="Chicago" />
  </el-radio-group>
  <el-radio-group v-else v-model="control.props.defaultValue" size="large">
    <el-radio-button label="New York" />
    <el-radio-button label="Washington" />
    <el-radio-button label="Los Angeles" />
    <el-radio-button label="Chicago" />
  </el-radio-group>
</template>

###Viewer.vue

<script setup>
defineProps({
    control: Object,
    model: Object,
})
</script>

<template>
    <div>{{ model[control.id] }} </div>
</template>

模板代码:

<div class="h-full w-full">
    <FormDesigner 
            :controlGroups="controlGroups"  
            :uploadOptions="uploadOptions" 
            :enData="enData" 
            :formData="data" 
            :customComponents="customComponents"
            @deleteItem="deleteItem" @copyItem="copyItem">
        <template #button>
            <el-button text type="primary" @click="releaseForm">
                <el-icon><NameIcon name="upload"/></el-icon>
                <span>发布</span>
            </el-button>
        </template>
        <template #action="{data}">
            <el-icon @click.stop="itemCustomButtonClick(data)">
                <NameIcon name="editor" style="color:#fff"></NameIcon>
            </el-icon>
        </template>
    </FormDesigner>
</div>

FormDesigner 组件会是百分之百宽高,大小控制父容器即可。

说明:

formData默认值为:

{
  "controls": [],
  "props": {
    "labelPosition": "right",
    "labelWidth": 100,
    "size": "default",
    "customClass": "",
    "cols": 12
  }
}

controls里每个元素大概是这样的格式,以 select 为例子:

{
      "type": "select",
      "name": "下拉选择",
      "key": "qFahSi153",
      "id": "select_qFahSi153",
      "lock": false,
      "dataType": "string",
      "props": {
        "width": 12,
        "showLabel": true,
        "labelWidth": null,
        "label": "下拉选择",
        "defaultValue": "",
        "placeholder": "请选择",
        "required": false,
        "requiredMessage": "必填字段",
        "disabled": false,
        "clearable": true,
        "filterable": true,
        "customClass": "",
        "showOptionLabel": false,
        "options": [
          {
            "value": "值1",
            "label": "选项1"
          },
          {
            "value": "值2",
            "label": "选项2"
          }
        ]
      },
      "rules": [
        {
          "message": "必填字段",
          "required": false
        }
      ]
    }

其中的 lock属性,用于再次编辑的时候,如果要阻止组件删除,可以设置为true

uploadOptions说明:

  • action 表单内上传组件的上传地址。
  • getHeaders 一个方法,返回自定义上传头内容。
  • getFileHook 一个方法,自定义从action返回结果中获取文件信息,成功返回 {name:'文件名称',url:'文件地址'},失败返回错误信息字符串。

FormRenderer 使用

setup js代码

import { reactive ,ref } from 'vue';
import { FormRenderer } from 'vue3-form-designer';
import "vue3-form-designer/dist/style.css";

let data = reactive({
    formData: {},
    formModel: {}
})
let formRenderer=ref(null);
//formData 来自 FormDesigner 组件,意义相同,用于构建表单结构
//formModel 为表单数据,应该来自后台数据,大概是这样:
/*
{
  "select_qFahSi153": "值1",
  "input_t6ciGfNlv": "12",
  "checkbox_la0CN3uuA": [
    "值1","值2"
  ]
}
*/

模板代码:

<FormRenderer
        ref="formRenderer"
        :formData="data.formData"
        :formModel="data.formModel"
    />

FormRenderer 公开的 el-form 的几个方法:

  • validate 对整个表单作验证。
  • resetFields 对整个表单进行重置,将所有字段值重置为初始值并移除校验结果
  • scrollToField 滚动到指定表单字段
  • clearValidate 清理指定字段的表单验证信息

具体参考 element-plus 官方文档: https://element-plus.gitee.io/zh-CN/component/form.html#form-%E6%96%B9%E6%B3%95

FormViewer 使用

属性和 FormRenderer 相同。

3.0.1

3 months ago

3.0.0

4 months ago

1.4.0

4 months ago

2.0.1

4 months ago

2.0.0

4 months ago

1.3.9

4 months ago

1.3.8

7 months ago

1.3.7

9 months ago

1.3.6

10 months ago

1.3.5

10 months ago

1.3.4

1 year ago

1.3.3

1 year ago

1.3.2

1 year ago

1.3.1

1 year ago

1.3.0

1 year ago

1.2.9

1 year ago

1.2.8

1 year ago

1.2.7

1 year ago

1.2.6

1 year ago

1.2.5

1 year ago

1.2.4

1 year ago

1.2.3

1 year ago

1.2.2

1 year ago

1.2.1

1 year ago

1.2.0

1 year ago

1.1.9

1 year ago

1.1.8

1 year ago

1.1.7

1 year ago

1.1.6

1 year ago

1.1.5

1 year ago

1.1.4

1 year ago

1.1.2

1 year ago

1.1.1

1 year ago

1.1.0

1 year ago

1.0.9

1 year ago

1.0.8

1 year ago

1.0.7

1 year ago

1.0.6

1 year ago

1.0.5

1 year ago

1.0.4

1 year ago

1.0.3

1 year ago

1.0.1

1 year ago

1.0.0

2 years ago

0.0.0

2 years ago