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>