vue+elementui实现动态生成form 配置相关json即可生成form

组件目录

form.vue

<template>
    <el-form
        @submit.native.prevent
        class="dynamic-form"
        :ref="formConfig.ref"
        :inline="formConfig.inline"
        :model="value"
        :label-position="formConfig.labelPosition"
        :label-width="formConfig.labelWidth"
        :size="formConfig.size"
        :status-icon="formConfig.statusIcon"
    >
        <div
            class="formWrap"
            v-for="parentItem in formConfig.tabs"
            :key="parentItem.name"
            :label="parentItem.label"
            :name="parentItem.name"
            v-show="showOne==parentItem.name"
        >
            <dynamic-form-item
                v-for="item in parentItem.formItemList"
                :key="item.key"
                :item="item"
                :value="value[item.key]"
                v-if="value[item.key]!==undefined&&item.show!=false"
                @input="handleInput($event, item.key)"
                :style="{'min-width':columnMinWidth}"
            ></dynamic-form-item>
        </div>
        <slot/>
    </el-form>
</template>

<script>
export default {
    data() {
        // 密码验证
        return {
            activeName: "1"
        };
    },
    props: {
        formConfig: {
            type: Object,
            required: true
        },
        value: {
            type: Object,
            required: true
        },
        showOne: {
            type: String
        },
        columnMinWidth: {
            type: String
        }
    },
    created() {},
    mounted() {
        // this.setDefaultValue();
    },
    methods: {
        handleInput(val, key) {
            // 这里element-ui没有上报event,直接就是value了
            if(typeof(val) == 'string'){
                val = val.replace(/\s+/g, "");//去除空格
            }
            this.$emit("input", { ...this.value, [key]: val });
        },
        setDefaultValue() {
            const formData = { ...this.value };
            var that = this;
            // 设置默认值
            that.formConfig.tabs.forEach(item => {
                let formItemList = item.formItemList;
                formItemList.forEach(item1 => {
                    const { key, value } = item1;
                    if (formData[key] === undefined || formData[key] === null) {
                        formData[key] = value;
                    }
                });
            });
            that.$emit("input", { ...formData });
        }
    }
};
</script>

<style lang="scss">
.formWrap {
    overflow: hidden;
}
</style>

item.vue

<style>
.block {
    display: block !important;
    display: flex !important;
}
.inputo,
.selecto {
    width: 200px!important;
}
.form-itemo {
    width: 48%;
    float: left;
}
</style>

<template>
    <el-form-item
        class="form-itemo"
        :rules="Rules"
        :label="item.label"
        :prop="item.key"
        v-if="!item.isHide"
        :class="{'block':item.block}"
    >

        <el-input
            v-if="item.type==='input'"
            v-bind="$attrs"
            v-on="$listeners"
            :type="item.subtype"
            :min="item.min"
            :max="item.max"
            :minlength="item.minlength"
            :maxlength="item.maxlength"
            autocomplete="off"
            :placeholder="item.placeholder"
            :disabled="item.disabled"
            :readonly="item.readonly"
            :autosize="item.autosize"
            :clearable="item.clearable"
            class="inputo"
        >
            <template v-if="item.append" slot="append">{{item.append}}</template>
        </el-input>

        <el-select
            v-else-if="item.type==='select'"
            v-bind="$attrs"
            v-on="$listeners"
            :multiple="item.multiple"
            :collapse-tags="item.collapseTags"
            :disabled="item.disabled"
            :props="item.props"
            :clearable="item.clearable"
            :multiple-limit="item.multipleLimit"
            class="selecto"
        >
            <el-option
                v-for="o in item.options||ajaxOptions"
                :key="o[item.props.value]"
                :label="o[item.props.label]"
                :value="o[item.props.value]"
                :disabled="o.disabled"
            ></el-option>
        </el-select>


        <el-cascader
            v-else-if="item.type==='cascader'"
            v-bind="$attrs"
            v-on="$listeners"
            :options="item.options||ajaxOptions"
            :filterable="item.filterable"
            :change-on-select="item.changeOnSelect"
            :props="item.props"
            :placeholder="item.placeholder"
            :disabled="item.disabled"
            :clearable="true"
            class="selecto"
        ></el-cascader>
       
        <el-checkbox
            v-else-if="item.type==='switch' && item.appearance==='checkbox'"
            v-bind="$attrs"
            v-on="$listeners"
            :disabled="item.disabled"
        ></el-checkbox>

        <el-switch
            v-else-if="item.type==='switch'"
            v-bind="$attrs"
            v-on="$listeners"
            :disabled="item.disabled"
        ></el-switch>

        <el-rate
            v-else-if="item.type==='rate'"
            v-bind="$attrs"
            v-on="$listeners"
            :colors="['#99A9BF', '#F7BA2A', '#FF9900']"
            text-color="#ff9900"
        ></el-rate>

        <el-color-picker
            v-else-if="item.type==='color'"
            v-bind="$attrs"
            v-on="$listeners"
            :show-alpha="item.showAlpha"
            :color-format="item.format"
        ></el-color-picker>

        <el-slider
            v-else-if="item.type==='slider'"
            v-bind="$attrs"
            v-on="$listeners"
            :range="item.isRange"
            :show-stops="item.showStops"
            :step="item.step"
            :min="item.min"
            :max="item.max"
        ></el-slider>

        <el-radio-group v-else-if="item.type==='radio'" :disabled="item.disabled" v-bind="$attrs" v-on="$listeners">
            <component
                :is="item.button?'el-radio-button':'el-radio'"
                v-for="o in item.options||ajaxOptions"
                :key="o.code"
                :label="o.code"
                :disabled="o.disabled"
                :border="item.border"
            >{{o.name}}</component>
        </el-radio-group>

        <el-checkbox-group
            v-else-if="item.type==='checkbox'"
            :min="item.min"
            :max="item.max"
            v-bind="$attrs"
            v-on="$listeners"
            :props="item.props"
        >
            <component
                :is="item.button?'el-checkbox-button':'el-checkbox'"
                v-for="o in item.options||ajaxOptions"
                :key="o.value"
                :disabled="o.disabled"
                :label="o.code"
                :border="item.border"
            >{{o.name}}</component>
        </el-checkbox-group>

        <el-time-picker
            v-else-if="item.type==='time'"
            :is-range="item.isRange"
            range-separator="-"
            start-placeholder="开始时间"
            end-placeholder="结束时间"
            :value-format="item.valueFormat"
            :format="item.valueFormat"
            default-time="12:00:00"
            :placeholder="item.placeholder"
            :picker-options="item.pickerOptions"
            v-bind="$attrs"
            v-on="$listeners"
        ></el-time-picker>

        <el-date-picker
            v-else-if="item.type==='date'"
            :type="item.subtype"
            range-separator="-"
            start-placeholder="开始时间"
            end-placeholder="结束时间"
            :value-format="item.valueFormat"
            :format="item.format"
            :placeholder="item.placeholder"
            :picker-options="item.pickerOptions"
            v-bind="$attrs"
            v-on="$listeners"
            :disabled="item.disabled"
        ></el-date-picker>
        <span v-else-if="item.type==='txt'">{{item.txt}}</span>
        <!-- <richtext v-else-if="item.type==='richtext'" v-bind="$attrs" v-on="$listeners"></richtext> -->
        <span v-else>未知控件类型</span>
    </el-form-item>
</template>

<script>
// import Richtext from "@/components/tinymce";
export default {
    components: {
        // Richtext
    },
    props: {
        item: {
            type: Object,
            required: true
        }
    },
    data() {
        return {
            ajaxOptions: [],
            provinceData: [],
            city: [],
            area: []
        };
    },
    methods: {},
    computed: {
        Rules() {
            var that = this;
            const rules = that.item.rules;
            if (rules === undefined) return undefined;
            const R = [];
            rules.forEach(rule => {
                // 请求验证
                if (rule.sql) {
                    /* 请求验证 */
                    const validator = (rule2, value, callback) => {
                        that.$http
                            .post(rule.sql, {
                                // key: rule2.field,
                                value
                                // sql: rule.sql.replace(/{key}/gi, rule2.field)
                            })
                            .then(res => {
                                // eslint-disable-next-line
                                callback(!res.data.returnMsg || undefined);
                            })
                            .catch(err => {
                                console.log(err);
                                that.$message.error(err.message);
                                // eslint-disable-next-line
                                callback(false);
                            });
                    };

                    R.push({
                        validator,
                        message: rule.message,
                        trigger: "blur"
                    });
                    // 正则验证
                } else if (rule.pattern) {
                    var reg = rule.pattern;
                    const validator = (rule2, value, callback) => {
                        if (value === "") {
                            callback(new Error("必填哦"));
                        } else if (!reg.test(value)) {
                            callback(new Error(rule.message));
                        } else {
                            callback();
                        }
                    };
                    R.push({
                        validator,
                        message: rule.message,
                        trigger: "blur"
                    });
                } else {
                    R.push(rule);
                }
            });
            return R;
        }
    },
    created() {
        const { optionsUrl, optionsParam, key, type } = this.item;
        if (optionsUrl) {
            var that = this;
            that.$http
                .post(optionsUrl, optionsParam)
                .then(res => {
                    // console.log(res);
                    // console.log(that.item);
                    if (res.data.succeed == YESTAE_OMS.SUCCESS) {
                        that.item.options = res.data.datas;
                        if(res.data.datas.rows){
                            that.item.options = res.data.datas.rows
                        }
                    }
                    // that.$set(this.item, 'options', res)
                    // that.ajaxOptions = res.data.datas;
                    // console.log(that.item)
                })
                .catch(err => {
                    that.$message.error(err.message);
                });
        }
    }
};
</script>

index.js输出一下

import Vue from 'vue'
import Form from './form'
import Item from './item'

Vue.component('dynamic-form', Form)
Vue.component('dynamic-form-item', Item)

最终使用

main.js中引入一下

import "@/components/dynamicForm";//添加编辑

list.vue

<template>
    <div class="order-list">
        
                    <dynamic-search-form
                        ref="dynamicForm"
                        :formConfig="formConfig"
                        v-model="formInfo"
                    ></dynamic-search-form>
                

    </div>
</template>

<script>

export default {
    name: "order-list",
    data() {
        return {
          
            formInfo: {
                platOrderNo: "",

                orderType: "",
                wareId: "",
                area: [],
                receiverAddress: "",
                receiverPhone: "",
                customRemark: "",
                actualPaymax: "",
                actualPaymin: "",
                goodsSkuRangeType: "2",
                goodsSkuRangeNum: "",
                tradeTime: [],

                nick: "",
                shopId: "",
                goodsSku: ""
            },
            // 注册表单项们
            formConfig: {
                ref: "formInfo",
                inline: true, // 是否使用inline排版
                labelPosition: "right", // 标签对齐方式
                labelWidth: "100px", // 标签宽度
                size: "small", // 尺寸
                statusIcon: true, // 显示验证图标
                formItemList: [
                    {
                        label: "原始订单号",
                        prop: "platOrderNo",
                        type: "input",
                        value: "",
                        key: "platOrderNo",
                        clearable: true,
                        placeholder: "请输入"
                    },
                    {
                        type: "select",
                        label: "订单类型",
                        key: "orderType",
                        prop: "orderType",
                        value: "",
                        placeholder: "全部",
                        clearable: true,
                        isHide: true,
                        props: {
                            value: "code",
                            label: "name"
                        },
                        optionsUrl: "PO0132",
                        optionsParam: { pcode: "orderType" },
                        options: []
                    },
                    {
                        type: "select",
                        label: "店铺名称",
                        key: "shopId",
                        prop: "shopId",
                        value: "",
                        clearable: true,
                        props: {
                            value: "id",
                            label: "shopName"
                        },
                        optionsUrl: "PO1005",
                        options: []
                    },
                    {
                        type: "select",
                        label: "仓库名称",
                        key: "wareId",
                        prop: "wareId",
                        placeholder: "全部",
                        value: "",
                        clearable: true,
                        props: {
                            value: "id",
                            label: "wareName"
                        },
                        optionsUrl: "PO0705",
                        options: []
                    },
                    {
                        label: "用户昵称",
                        prop: "nick",
                        type: "input",
                        value: "",
                        key: "nick",
                        clearable: true,
                        placeholder: "请输入"
                    },
                    {
                        label: "商品SKU",
                        prop: "goodsSku",
                        type: "input",
                        value: "",
                        key: "goodsSku",
                        clearable: true,
                        placeholder: "请输入"
                    },
                    {
                        label: "实付金额",
                        key: "actualPaymin",
                        prop: "actualPaymin",
                        type: "input",
                        isHide: false,
                        subtype: "number",
                        value: "",
                        min: 0,
                        clearable: true,
                        placeholder: "",
                        formItemStyle: {
                            width: "205px!important"
                        },
                        style: {
                            width: "80px!important"
                        }
                    },
                    {
                        label: "~",
                        key: "actualPaymax",
                        prop: "actualPaymax",
                        type: "input",
                        isHide: false,
                        subtype: "number",
                        value: "",
                        clearable: true,
                        min: 0,
                        placeholder: "",
                        labelWidth: "20px",
                        formItemStyle: {
                            width: "120px!important"
                        },
                        style: {
                            width: "80px!important"
                        }
                    },
                    {
                        label: "交易时间",
                        prop: "tradeTime",
                        type: "date",
                        subtype: "datetimerange",
                        valueFormat: "yyyy-MM-dd HH:mm:ss",
                        value: "",
                        key: "tradeTime",
                        clearable: true,
                        style: { width: "340px" },
                        placeholder: "请选择"
                    },
                    {
                        type: "select",
                        label: "SKU数量",
                        key: "goodsSkuRangeType",
                        prop: "goodsSkuRangeType",
                        value: "",
                        isHide: false,
                        clearable: true,
                        props: {
                            value: "code",
                            label: "name"
                        },
                        optionsUrl: "PO0132",
                        optionsParam: { pcode: "mathNum" },
                        options: [],
                        formItemStyle: {
                            width: "200px!important"
                        },
                        style: {
                            width: "80px!important"
                        }
                    },
                    {
                        label: "",
                        key: "goodsSkuRangeNum",
                        prop: "goodsSkuRangeNum",
                        type: "input",
                        subtype: "number",
                        value: "",
                        isHide: false,
                        clearable: true,
                        min: 1,
                        placeholder: "SKU数量",
                        formItemStyle: {
                            width: "100px!important"
                        },
                        style: {
                            width: "105px!important"
                        }
                    },
                    {
                        label: "客服备注",
                        key: "customRemark",
                        prop: "customRemark",
                        type: "input",
                        maxlength: 50,
                        value: "",
                        clearable: true,
                        placeholder: "请输入"
                    },
                    {
                        type: "area",
                        label: "省市区",
                        key: "area",
                        prop: "area",
                        value: "",
                        clearable: true,
                        changeOnSelect: true,
                        props: {
                            value: "cityCodeId",
                            label: "name",
                            children: "children"
                        },
                        options: [],
                        style: {
                            width: "202px!important"
                        }
                    },
                    {
                        label: "收货地址",
                        key: "receiverAddress",
                        prop: "receiverAddress",
                        type: "input",
                        maxlength: 30,
                        value: "",
                        clearable: true,
                        placeholder: "请输入"
                    },
                    {
                        label: "收件人电话",
                        key: "receiverPhone",
                        prop: "receiverPhone",
                        type: "input",
                        maxlength: 30,
                        isHide: false,
                        value: "",
                        clearable: true,
                        placeholder: "请输入"
                    }
                ]
            },
            
        };
    },
    computed: {
        
    },
    watch: {
    },
    methods: {
        }
};
</script>

<style lang="scss">

</style>
发布了61 篇原创文章 · 获赞 33 · 访问量 13万+

猜你喜欢

转载自blog.csdn.net/qq_37588752/article/details/97129772
今日推荐