基于element-ui 和avue 表单组件。自定义左树右表组件

时间:2024-05-19 09:14:32

基于element-ui 和avue 表单组件。自定义左树右表组件1.menu-form.vue

<template>
    <div>
        <avue-form :option="modelOption" v-model="modelForm" @submit="handleSubmit"></avue-form>
    </div>

</template>

<script>

    export default {
        name: "menu-form",
        watch: {
            'form.parentId'(n, o) {
                this.modelForm=this.form
            },
            'form.id'(n, o) {
                this.modelForm=this.form
            }

        },
        model: {
            prop: 'form',//指向props的参数名
            event: 'returnBack'//事件名称
        },
        props: {
            form: {
                type: Object
            },
            option: {
                type: Object
            }
        },
        data() {
            return {
                modelForm: this.form,
                modelOption: this.option
            }
        },

        methods: {
            handleSubmit(form, done) {
                this.$emit("submit", form, done);

            }
        }
    }
</script>

<style scoped>

</style>

2.meun-tree.vue

<template>
    <div>
        <el-row >
            <el-col :span="17">
                <el-input
                        placeholder="输入关键字进行过滤"
                        v-model="filterText">
                </el-input>
            </el-col>
            <el-col :span="6" style="margin-left: 10px" >
                <slot name="handle">
                    <el-button slot="handle" type="primary">添加</el-button>
                </slot>
            </el-col>
        </el-row>
        <el-tree
                show-checkbox
                node-key="id"
                class="filter-tree"
                :data="modelData"
                :props="defaultProps"
                default-expand-all
                :expand-on-click-node="false"
                :filter-node-method="filterNode"
                @node-click="nodeClick"
                ref="tree">
            <span class="custom-tree-node" slot-scope="{ node, data }">
        <span class="treeLeft">{{ node.label }}</span>
        <span class="treeRight">
          <el-button
                  type="text"
                  size="mini"
                  @click="() => append(data)">
            添 加
          </el-button>
                <el-button
                        type="text"
                        size="mini"
                        @click="() => edit(data)">
            编 辑
          </el-button>
          <el-button
                  type="text"
                  size="mini"
                  @click="() => remove(node, data)">
            删 除
          </el-button>
        </span>
      </span>
        </el-tree>
    </div>
</template>

<script>
    export default {
        name: "menu-tree",
        model: {
            prop: 'data',//指向props的参数名
            event: 'returnBack'//事件名称
        },
        props: {
            data: {
                type:Array
            }
        },
        data() {
            return {

                filterText: '',
                modelData:this.data,
                defaultProps: {
                    children: 'children',
                    label: 'label'
                }
            };

        },
        watch: {
            data(){
                this.modelData=this.data
            },
            filterText(val) {
                this.$refs.tree.filter(val);
            },

        },
        methods: {
            filterNode(value, data) {
                if (!value) return true;
                return data.label.indexOf(value) !== -1;
            },
            nodeClick(data,n,x){

                this.$emit("node-click",data)
            },
            append(data) {
                // const newChild = {id: id++, label: 'testtest', children: []};
                // if (!data.children) {
                //     this.$set(data, 'children', []);
                // }
                // data.children.push(newChild);
                this.$emit("append",data)
            },

            remove(node, data) {
                // const parent = node.parent;
                // const children = parent.data.children || parent.data;
                // const index = children.findIndex(d => d.id === data.id);
                // children.splice(index, 1);
                this.$emit("remove",node, data)
            },
            edit(data){
                this.$emit("edit",data)
            }

        },


    };

</script>

<style scoped>
    .filter-tree{
    }
    .treeRight {

    }

    .treeLeft {

    }

    .custom-tree-node {
        flex: 1;
        display: flex;
        width: 100%;
        align-items: center;
        justify-content: space-between;
        font-size: 14px;
        padding-right: 8px;
    }
</style>

3.menu-tree-form.vue

<template>
    <el-row :gutter="50">
        <el-col :span="8" style="width: 400px;height: 75vh; ">
            <menu-tree v-model="menuDataModel" @node-click="nodeClick" @append="append" @remove="remove" @edit="edit">
                <el-button slot="handle" type="primary" @click="add">添加</el-button>
            </menu-tree>
        </el-col>
        <el-col :span="16" style=" box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);padding: 20px">
            <menu-form v-model="menuFormModel" :option="menuOptionModel" @submit="handleSubmit"></menu-form>
        </el-col>
    </el-row>
</template>

<script>

    import MenuTree from "@/page/admin/menu/menu-tree";
    import MenuForm from "@/page/admin/menu/menu-form";

    export default {
        name: "menu-tree-form",
        components: {MenuForm, MenuTree},

        model: {
            prop: 'menuData',//指向props的参数名
            event: 'returnBack'//事件名称
        },
        props: {
            menuData: {
                type: Object
            },
            menuForm: {
                type: Object
            },
            menuOption: {
                type: Object
            }
        },
        data() {
            return {
                menuDataModel: this.menuData.list,
                menuFormModel: this.menuData.form,
                menuOptionModel: this.menuData.option
            }
        },
        watch: {

            'menuData.list'(n, o) {
                this.menuDataModel = n;
            },
            'menuData.form.parentId'(n, o) {
                this.menuFormModel = this.menuData.form;
            },
            'menuData.form.id'(n, o) {
                this.menuFormModel = this.menuData.form;
            }

        },
        methods: {
            nodeClick(data) {
                this.$emit("node-click", data)
            },
            add() {
                this.$emit("add");
            },
            append(data) {
                this.$emit("append", data);
            },
            remove(node, data) {
                this.$emit("remove", node, data);
            },
            edit(data) {
                this.$emit("edit", data);
            },
            handleSubmit(form, done) {

                this.$emit("submit", form, done);
            }
        }
    }
</script>


<style scoped>

</style>

4.index.vue  使用

<template>
    <basic-container>

        <menu-tree-form v-model="menuData"  @add="add" @append="append" @edit="edit"
                        @remove="remove"
                        @submit="handleSubmit"></menu-tree-form>
    </basic-container>
</template>

<script>
    import {mapGetters} from 'vuex';
    import MenuTreeForm from "@/page/admin/menu/menu-tree-form";

    import {treeListLoad, del, save} from '@/api/admin/menu';

    export default {
        name: "index",
        components: {MenuTreeForm},
        watch: {},
        data() {
            return {
                menuData: {
                    list: [],
                    form: {parentId: 0},
                    option: {
                        column: [{
                            label: "父级编码",
                            prop: "parentId",
                            value:0,
                            disabled: true,
                            span: 24
                        }, {
                            label: "权限名称",
                            prop: "name",
                            span: 24,
                            rules: [{
                                required: true,
                                message: "请输入权限名称",
                                trigger: "blur"
                            }]
                        }, {
                            label: "权限标识",
                            prop: "code",
                            span: 24,
                            rules: [{
                                required: true,
                                message: "请输入权限标识",
                                trigger: "blur"
                            }]
                        }, {
                            label: "类型",
                            prop: "state",
                            span: 24,
                            type: "radio",
                            dicData: [{
                                label: '系统',
                                value: 0
                            }, {
                                label: '菜单',
                                value: 1
                            }, {
                                label: '按钮',
                                value: 2
                            }],
                            rules: [{
                                required: true,
                                message: "请输入类型",
                                trigger: "blur"
                            }]
                        }, {
                            label: "组件地址",
                            prop: "component",
                            span: 24
                        }, {
                            label: "图标",
                            prop: "icon",
                            span: 24
                        }, {
                            label: "请求地址",
                            prop: "path",
                            span: 24
                        }, {
                            label: "权限描述",
                            prop: "des",
                            span: 24
                        }, {
                            label: "排序",
                            prop: "order",
                            span: 24
                        }]
                    }
                },
                menuOption: {
                    column: [{
                        label: "父级编码",
                        prop: "parentId",
                        disabled: true,
                        span: 24
                    }, {
                        label: "权限名称",
                        prop: "name",
                        span: 24,
                        rules: [{
                            required: true,
                            message: "请输入权限名称",
                            trigger: "blur"
                        }]
                    }, {
                        label: "权限标识",
                        prop: "code",
                        span: 24,
                        rules: [{
                            required: true,
                            message: "请输入权限标识",
                            trigger: "blur"
                        }]
                    }, {
                        label: "类型",
                        prop: "state",
                        span: 24,
                        type: "radio",
                        dicData: [{
                            label: '系统',
                            value: 0
                        }, {
                            label: '菜单',
                            value: 1
                        }, {
                            label: '按钮',
                            value: 2
                        }],
                        rules: [{
                            required: true,
                            message: "请输入类型",
                            trigger: "blur"
                        }]
                    }, {
                        label: "组件地址",
                        prop: "component",
                        span: 24
                    }, {
                        label: "图标",
                        prop: "icon",
                        span: 24


                    }, {
                        label: "请求地址",
                        prop: "path",
                        span: 24
                    }, {
                        label: "权限描述",
                        prop: "des",
                        span: 24
                    }, {
                        label: "排序",
                        prop: "order",
                        span: 24
                    }]
                }
            }
        }, methods: {
            treeLoad() {
                let dto = {};
                treeListLoad(dto).then(res => {
                    this.menuData.list = res.data.data;
                }).catch(err => {
                    this.$message.error("网络异常:" + err)
                })
            },
            add() {
                const model = {
                    parentId: 0,
                    name: null,
                    code: null,
                    component: null,
                    icon: null,
                    id: null,
                    label: null,
                    meta: null,
                    path: null,
                    state: null,
                    des: null
                };
                this.menuData.form = model;
            },
            append(data) {
                const model = {
                    parentId: data.id,
                    name: null,
                    code: null,
                    component: null,
                    icon: null,
                    id: null,
                    label: null,
                    meta: null,
                    path: null,
                    state: null,
                    des: null
                };
                this.menuData.form = model;

            },
            remove(node, data) {
                console.log(node, data);
                this.$confirm('此操作将永久删除该权限, 是否继续?', '提示', {
                    confirmButtonText: '确定',
                    cancelButtonText: '取消',
                    type: 'warning'
                }).then(() => {
                    del(data.id).then(res => {
                        this.$message.success("操作完成")
                    }).catch(err => {
                        this.$message.error("网络异常:" + err)
                    });
                }).catch(() => {
                    this.$message({
                        type: 'info',
                        message: '已取消删除'
                    });
                });
                setTimeout(() => {
                    this.treeLoad();
                }, 3000)
            },
            edit(data) {
                this.menuData.form = data.menu;
            },
            handleSubmit(form, done) {
                this.$message.success('3s后关闭');
                let dto = form;
                save(dto).then(res => {
                    this.$message.success("操作完成")
                }).catch(err => {
                    this.$message.error("网络异常:" + err)
                });
                setTimeout(() => {
                    this.treeLoad();
                    done()
                }, 3000)
            }
        },
        created() {
            this.treeLoad();
        }
    }
</script>

<style scoped>

</style>