|
@@ -0,0 +1,148 @@
|
|
|
+<template>
|
|
|
+ <div id="index">
|
|
|
+ <detail-frame :title="pageTitle">
|
|
|
+ <el-row :gutter="10" type="flex">
|
|
|
+ <el-col :span="12">
|
|
|
+ <el-row>
|
|
|
+ <el-col :span="6"><el-button type="text" @click="toDialog()">添加主菜单</el-button></el-col>
|
|
|
+ </el-row>
|
|
|
+ <el-tree :data="list" ref="tree" node-key="id" :props="defaultProps" :highlight-current="true">
|
|
|
+ <span class="custom-tree-node" slot-scope="{ node, data }">
|
|
|
+ <span>
|
|
|
+ <el-button type="text" @click="toUpdate(node, data)" style="font-size:16px">
|
|
|
+ {{ node.label }}
|
|
|
+ </el-button>
|
|
|
+ </span>
|
|
|
+ <span>
|
|
|
+ <el-button type="text" @click="toAppend(node, data)">
|
|
|
+ 添加子菜单
|
|
|
+ </el-button>
|
|
|
+ <el-button type="text" @click="toRemove(node, data)">
|
|
|
+ 删除菜单
|
|
|
+ </el-button>
|
|
|
+ </span>
|
|
|
+ </span>
|
|
|
+ </el-tree>
|
|
|
+ </el-col>
|
|
|
+ </el-row>
|
|
|
+ </detail-frame>
|
|
|
+ <el-dialog title="添加菜单" width="30%" center :visible.sync="dialog" @close="toClose" :destroy-on-close="true">
|
|
|
+ <el-form :model="form" label-width="100px">
|
|
|
+ <el-form-item label="上级菜单">
|
|
|
+ {{ getNodeTitle(form) }}
|
|
|
+ </el-form-item>
|
|
|
+ <el-form-item label="菜单名称" prop="title" required>
|
|
|
+ <el-input v-model="form.title" placeholder="请输入菜单名称"></el-input>
|
|
|
+ </el-form-item>
|
|
|
+ <el-form-item label="菜单路由">
|
|
|
+ <el-input v-model="form.route" placeholder="请输入菜单路由(有子菜单可以为空)"></el-input>
|
|
|
+ </el-form-item>
|
|
|
+ <el-form-item>
|
|
|
+ <el-button type="primary" @click="append">保存</el-button>
|
|
|
+ </el-form-item>
|
|
|
+ </el-form>
|
|
|
+ </el-dialog>
|
|
|
+ </div>
|
|
|
+</template>
|
|
|
+
|
|
|
+<script>
|
|
|
+const _ = require('lodash');
|
|
|
+import detailFrame from '@frame/layout/admin/detail-frame';
|
|
|
+import dataForm from '@frame/components/form';
|
|
|
+import { mapState, createNamespacedHelpers } from 'vuex';
|
|
|
+export default {
|
|
|
+ name: 'index',
|
|
|
+ props: {},
|
|
|
+ components: { detailFrame },
|
|
|
+ data: function() {
|
|
|
+ return {
|
|
|
+ dialog: false,
|
|
|
+ list: [{ id: '1', title: '菜单1', children: [{ id: '1-1', title: '菜单1-1' }] }],
|
|
|
+ defaultProps: {
|
|
|
+ children: 'children',
|
|
|
+ label: 'title',
|
|
|
+ },
|
|
|
+ form: {},
|
|
|
+ fields: [
|
|
|
+ // 数据格式:以垂直为主,每个主菜单的所有子菜单及其关系都垂直下来
|
|
|
+ { label: '上级菜单', required: false, model: 'node', custom: true }, // 虚拟字段
|
|
|
+ { label: '菜单名称', required: true, model: 'title' },
|
|
|
+ { label: '菜单路由', required: false, model: 'route' },
|
|
|
+ ],
|
|
|
+ rules: {
|
|
|
+ title: [{ required: true, message: '请输入菜单名称' }],
|
|
|
+ },
|
|
|
+ };
|
|
|
+ },
|
|
|
+ created() {},
|
|
|
+ methods: {
|
|
|
+ toCheck(data) {
|
|
|
+ console.log(data);
|
|
|
+ },
|
|
|
+ toUpdate(node, data) {
|
|
|
+ console.log(node, data);
|
|
|
+ },
|
|
|
+ toAppend(node, data) {
|
|
|
+ this.toDialog({ node });
|
|
|
+ },
|
|
|
+ append() {
|
|
|
+ const { node, ...info } = this.form;
|
|
|
+ if (node) {
|
|
|
+ this.$refs.tree.append(info, node);
|
|
|
+ } else {
|
|
|
+ this.list.push(info);
|
|
|
+ }
|
|
|
+ this.toClose();
|
|
|
+ },
|
|
|
+ toRemove(node, data) {
|
|
|
+ const oval = _.cloneDeep(this.list);
|
|
|
+ this.$confirm(`确定删除${data.title}?`, '提示', {
|
|
|
+ confirmButtonText: '确定',
|
|
|
+ cancelButtonText: '取消',
|
|
|
+ type: 'warning',
|
|
|
+ }).then(() => {
|
|
|
+ this.$refs.tree.remove(node);
|
|
|
+ const nval = _.cloneDeep(this.list);
|
|
|
+ const toUpdate = _.differenceWith(nval, oval, _.isEqual);
|
|
|
+ console.log(toUpdate);
|
|
|
+ });
|
|
|
+ },
|
|
|
+ getNodeTitle(form) {
|
|
|
+ const node = _.get(form, 'node');
|
|
|
+ if (!node) return '主菜单';
|
|
|
+ const { data } = node;
|
|
|
+ return _.get(data, 'title');
|
|
|
+ },
|
|
|
+ toDialog(data) {
|
|
|
+ this.dialog = true;
|
|
|
+ if (_.isObject(data)) {
|
|
|
+ this.$set(this, `form`, data);
|
|
|
+ }
|
|
|
+ },
|
|
|
+ toClose() {
|
|
|
+ this.dialog = false;
|
|
|
+ this.form = {};
|
|
|
+ },
|
|
|
+ },
|
|
|
+ computed: {
|
|
|
+ ...mapState(['user']),
|
|
|
+ pageTitle() {
|
|
|
+ return `${this.$route.meta.title}`;
|
|
|
+ },
|
|
|
+ },
|
|
|
+ metaInfo() {
|
|
|
+ return { title: this.$route.meta.title };
|
|
|
+ },
|
|
|
+};
|
|
|
+</script>
|
|
|
+
|
|
|
+<style lang="less" scoped>
|
|
|
+.custom-tree-node {
|
|
|
+ flex: 1;
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ justify-content: space-between;
|
|
|
+ font-size: 14px;
|
|
|
+ padding-right: 8px;
|
|
|
+}
|
|
|
+</style>
|