|
|
@@ -1,96 +1,56 @@
|
|
|
<template>
|
|
|
- <div class="menus">
|
|
|
- <el-select v-model="category" placeholder="分类" clearable>
|
|
|
- <el-option v-for="item in categories" :label="item" :key="item" :value="item"></el-option>
|
|
|
- </el-select>
|
|
|
- <el-row :gutter="20">
|
|
|
- <el-col :span="12">
|
|
|
- <div class="menu-tree">
|
|
|
- <el-tree
|
|
|
- :data="menus"
|
|
|
- :render-content="renderContent"
|
|
|
- :highlight-current="true"
|
|
|
- :expand-on-click-node="true"
|
|
|
- node-key="id"
|
|
|
- v-loading="loading"
|
|
|
- accordion
|
|
|
- @node-click="nodeClick"
|
|
|
- :default-expanded-keys="expandKeys"
|
|
|
- :default-checked-keys="expandKeys"
|
|
|
+ <div class="edit-view" style="padding:20px;">
|
|
|
+ <el-tree
|
|
|
+ :data="menus"
|
|
|
+ :render-content="renderContent"
|
|
|
+ :highlight-current="true"
|
|
|
+ :expand-on-click-node="true"
|
|
|
+ node-key="id"
|
|
|
+ default-expand-all
|
|
|
+ v-loading="loading"
|
|
|
+ >
|
|
|
+ </el-tree>
|
|
|
+ <el-button type="text" @click="addRootMenu" style="margin-left: 24px;">添加 </el-button>
|
|
|
+ <el-dialog :visible.sync="dialogVisible" title="添加菜单">
|
|
|
+ <el-form :model="menu" ref="form" label-position="top">
|
|
|
+ <el-form-item
|
|
|
+ label="菜单名"
|
|
|
+ prop="name"
|
|
|
+ :rules="[{ required: true, message: '请填写菜单名', trigger: 'blur' }]"
|
|
|
+ >
|
|
|
+ <el-input v-model="menu.name"></el-input>
|
|
|
+ </el-form-item>
|
|
|
+ <el-form-item label="菜单地址" prop="path">
|
|
|
+ <el-input v-model="menu.path"></el-input>
|
|
|
+ </el-form-item>
|
|
|
+ <el-form-item prop="icon">
|
|
|
+ <template slot="label"
|
|
|
+ >图标
|
|
|
+ <a
|
|
|
+ href="https://fontawesome.com/icons?d=gallery&s=brands,solid&m=free"
|
|
|
+ target="_blank"
|
|
|
+ class="available-icons"
|
|
|
+ >查看所有可用图标</a
|
|
|
+ ></template
|
|
|
>
|
|
|
- </el-tree>
|
|
|
- <el-button type="text" @click="addRootMenu" style="margin-left: 24px;">添加 </el-button>
|
|
|
- </div>
|
|
|
- </el-col>
|
|
|
- <transition name="el-fade-in">
|
|
|
- <el-col :span="12" v-if="dialogVisible">
|
|
|
- <div class="menu-tree">
|
|
|
- <div style="font-weight:bold;padding:10px 0">{{ menu.id ? '编辑菜单' : '新增菜单' }}</div>
|
|
|
- <el-form :model="menu" ref="form" label-position="top">
|
|
|
- <el-form-item
|
|
|
- label="菜单名"
|
|
|
- prop="name"
|
|
|
- :rules="[{ required: true, message: '请填写菜单名', trigger: 'blur' }]"
|
|
|
- >
|
|
|
- <el-input v-model="menu.name"></el-input>
|
|
|
- </el-form-item>
|
|
|
- <el-form-item label="菜单地址" prop="path">
|
|
|
- <el-input v-model="menu.path"></el-input>
|
|
|
- </el-form-item>
|
|
|
- <el-form-item prop="icon">
|
|
|
- <template slot="label"
|
|
|
- >图标
|
|
|
- <a
|
|
|
- href="https://fontawesome.com/icons?d=gallery&s=brands,solid&m=free"
|
|
|
- target="_blank"
|
|
|
- class="available-icons"
|
|
|
- >查看所有可用图标</a
|
|
|
- ></template
|
|
|
- >
|
|
|
- <el-input v-model="icon">
|
|
|
- <template slot="append"
|
|
|
- ><span ref="iconContainer" style="font-size: 18px;"
|
|
|
- ><i class="fas fa-"></i></span
|
|
|
- ></template>
|
|
|
- </el-input>
|
|
|
- </el-form-item>
|
|
|
- <el-form-item prop="category" label="分类" v-if="menu.root">
|
|
|
- <el-input v-model="menu.category"></el-input>
|
|
|
- </el-form-item>
|
|
|
- <el-form-item prop="authorities" label="权限">
|
|
|
- <el-select
|
|
|
- v-model="menu.authorities"
|
|
|
- clearable
|
|
|
- multiple
|
|
|
- value-key="name"
|
|
|
- style="width:100%"
|
|
|
- >
|
|
|
- <el-option
|
|
|
- v-for="item in authorities"
|
|
|
- :label="item.description"
|
|
|
- :value="item"
|
|
|
- :key="item.name"
|
|
|
- ></el-option>
|
|
|
- </el-select>
|
|
|
- </el-form-item>
|
|
|
- </el-form>
|
|
|
- <div slot="footer">
|
|
|
- <el-button @click="dialogVisible = false">取消 </el-button>
|
|
|
- <el-button type="primary" @click="addMenu" :loading="loading">保存 </el-button>
|
|
|
- </div>
|
|
|
- </div>
|
|
|
- </el-col>
|
|
|
- </transition>
|
|
|
- </el-row>
|
|
|
+ <el-input v-model="icon">
|
|
|
+ <template slot="append"
|
|
|
+ ><span ref="iconContainer" style="font-size: 18px;"><i class="fas fa-"></i></span
|
|
|
+ ></template>
|
|
|
+ </el-input>
|
|
|
+ </el-form-item>
|
|
|
+ </el-form>
|
|
|
+ <div slot="footer">
|
|
|
+ <el-button @click="dialogVisible = false">取消 </el-button>
|
|
|
+ <el-button type="primary" @click="addMenu" :loading="loading">保存 </el-button>
|
|
|
+ </div>
|
|
|
+ </el-dialog>
|
|
|
</div>
|
|
|
</template>
|
|
|
<script>
|
|
|
export default {
|
|
|
created() {
|
|
|
this.getData();
|
|
|
- this.$http.get('/authority/all').then(res => {
|
|
|
- this.authorities = res;
|
|
|
- });
|
|
|
},
|
|
|
data() {
|
|
|
return {
|
|
|
@@ -108,11 +68,7 @@ export default {
|
|
|
parent: null,
|
|
|
currentRef: null,
|
|
|
edit: false,
|
|
|
- icon: '',
|
|
|
- categories: [],
|
|
|
- category: null,
|
|
|
- expandKeys: [],
|
|
|
- authorities: []
|
|
|
+ icon: ''
|
|
|
};
|
|
|
},
|
|
|
methods: {
|
|
|
@@ -122,9 +78,7 @@ export default {
|
|
|
path: '',
|
|
|
active: true,
|
|
|
root: true,
|
|
|
- icon: 'bars',
|
|
|
- category: this.category || null,
|
|
|
- authorities: [{ name: 'ROLE_ADMIN' }]
|
|
|
+ icon: 'bars'
|
|
|
};
|
|
|
this.parent = null;
|
|
|
this.icon = 'bars';
|
|
|
@@ -142,8 +96,7 @@ export default {
|
|
|
path: '',
|
|
|
active: true,
|
|
|
root: false,
|
|
|
- icon: null,
|
|
|
- authorities: [{ name: 'ROLE_ADMIN' }]
|
|
|
+ icon: null
|
|
|
};
|
|
|
this.icon = '';
|
|
|
this.dialogVisible = true;
|
|
|
@@ -181,12 +134,22 @@ export default {
|
|
|
let menu = { ...this.menu };
|
|
|
delete menu.children;
|
|
|
this.$http
|
|
|
- .post('/menu/save', menu, { body: 'json' })
|
|
|
+ .post('/dataCenterMenu/save', menu)
|
|
|
.then(res => {
|
|
|
this.loading = false;
|
|
|
this.$message.success('添加成功');
|
|
|
this.dialogVisible = false;
|
|
|
- this.getData();
|
|
|
+ if (this.edit) {
|
|
|
+ for (let [key, value] of Object.entries(res)) {
|
|
|
+ console.log(`${key}: ${value}`);
|
|
|
+ this.$set(this.currentRef, key, value);
|
|
|
+ }
|
|
|
+ } else if (this.parent) {
|
|
|
+ this.parent.children = this.parent.children || [];
|
|
|
+ this.parent.children.push(res);
|
|
|
+ } else {
|
|
|
+ this.menus.push(res);
|
|
|
+ }
|
|
|
})
|
|
|
.catch(e => {
|
|
|
console.log(e);
|
|
|
@@ -204,27 +167,29 @@ export default {
|
|
|
type: 'error'
|
|
|
})
|
|
|
.then(() => {
|
|
|
- return this.$http.post(
|
|
|
- '/menu/save',
|
|
|
- {
|
|
|
+ this.$http
|
|
|
+ .post('/dataCenterMenu/save', {
|
|
|
...data,
|
|
|
active: false,
|
|
|
+ enabled: false,
|
|
|
children: null
|
|
|
- },
|
|
|
- { body: 'json' }
|
|
|
- );
|
|
|
- })
|
|
|
- .then(res => {
|
|
|
- this.$message.success('删除成功');
|
|
|
- this.getData();
|
|
|
+ })
|
|
|
+ .then(res => {
|
|
|
+ this.$message.success('删除成功');
|
|
|
+ let index = node.parent.data.children.findIndex(i => {
|
|
|
+ return i.id === data.id;
|
|
|
+ });
|
|
|
+ if (index > -1) {
|
|
|
+ node.parent.data.children.splice(index, 1);
|
|
|
+ }
|
|
|
+ })
|
|
|
+ .catch(e => {
|
|
|
+ console.log(e);
|
|
|
+ this.loading = false;
|
|
|
+ this.$message.error(e.error);
|
|
|
+ });
|
|
|
})
|
|
|
- .catch(e => {
|
|
|
- this.loading = false;
|
|
|
- if (e !== 'cancel') {
|
|
|
- console.log(e);
|
|
|
- this.$message.error(e.error);
|
|
|
- }
|
|
|
- });
|
|
|
+ .catch(() => {});
|
|
|
},
|
|
|
moveUp(node, data) {
|
|
|
if (node.previousSibling) {
|
|
|
@@ -232,28 +197,25 @@ export default {
|
|
|
let sort0 = node.previousSibling.data.sort,
|
|
|
sort1 = node.data.sort;
|
|
|
Promise.all([
|
|
|
- this.$http.post(
|
|
|
- '/menu/save',
|
|
|
- {
|
|
|
- ...node.data,
|
|
|
- children: null,
|
|
|
- sort: sort0
|
|
|
- },
|
|
|
- { body: 'json' }
|
|
|
- ),
|
|
|
- this.$http.post(
|
|
|
- '/menu/save',
|
|
|
- {
|
|
|
- ...node.previousSibling.data,
|
|
|
- children: null,
|
|
|
- sort: sort1
|
|
|
- },
|
|
|
- { body: 'json' }
|
|
|
- )
|
|
|
+ this.$http.post('/dataCenterMenu/save', {
|
|
|
+ ...node.data,
|
|
|
+ children: null,
|
|
|
+ sort: sort0
|
|
|
+ }),
|
|
|
+ this.$http.post('/dataCenterMenu/save', {
|
|
|
+ ...node.previousSibling.data,
|
|
|
+ children: null,
|
|
|
+ sort: sort1
|
|
|
+ })
|
|
|
])
|
|
|
.then(_ => {
|
|
|
this.loading = false;
|
|
|
- this.getData();
|
|
|
+ let tmp = { ...node.previousSibling.data, sort: sort1 };
|
|
|
+ node.previousSibling.data = {
|
|
|
+ ...node.data,
|
|
|
+ sort: sort0
|
|
|
+ };
|
|
|
+ node.data = tmp;
|
|
|
})
|
|
|
.catch(e => {
|
|
|
console.log(e);
|
|
|
@@ -268,28 +230,22 @@ export default {
|
|
|
let sort0 = node.data.sort,
|
|
|
sort1 = node.nextSibling.data.sort;
|
|
|
Promise.all([
|
|
|
- this.$http.post(
|
|
|
- '/menu/save',
|
|
|
- {
|
|
|
- ...node.data,
|
|
|
- children: null,
|
|
|
- sort: sort1
|
|
|
- },
|
|
|
- { body: 'json' }
|
|
|
- ),
|
|
|
- this.$http.post(
|
|
|
- '/menu/save',
|
|
|
- {
|
|
|
- ...node.nextSibling.data,
|
|
|
- children: null,
|
|
|
- sort: sort0
|
|
|
- },
|
|
|
- { body: 'json' }
|
|
|
- )
|
|
|
+ this.$http.post('/dataCenterMenu/save', {
|
|
|
+ ...node.data,
|
|
|
+ children: null,
|
|
|
+ sort: sort1
|
|
|
+ }),
|
|
|
+ this.$http.post('/dataCenterMenu/save', {
|
|
|
+ ...node.nextSibling.data,
|
|
|
+ children: null,
|
|
|
+ sort: sort0
|
|
|
+ })
|
|
|
])
|
|
|
.then(_ => {
|
|
|
this.loading = false;
|
|
|
- this.getData();
|
|
|
+ let tmp = { ...node.nextSibling.data, sort: sort0 };
|
|
|
+ node.nextSibling.data = { ...node.data, sort: sort1 };
|
|
|
+ node.data = tmp;
|
|
|
})
|
|
|
.catch(e => {
|
|
|
console.log(e);
|
|
|
@@ -300,7 +256,7 @@ export default {
|
|
|
},
|
|
|
getData() {
|
|
|
this.$http
|
|
|
- .get('/menu/all', { category: this.category })
|
|
|
+ .get('/dataCenterMenu/all')
|
|
|
.then(res => {
|
|
|
this.menus = res;
|
|
|
})
|
|
|
@@ -308,19 +264,10 @@ export default {
|
|
|
console.log(e);
|
|
|
this.$message.error(e.error);
|
|
|
});
|
|
|
- this.$http.get('/menu/categories').then(res => {
|
|
|
- this.categories = res;
|
|
|
- });
|
|
|
},
|
|
|
renderContent(h, { node, data, store }) {
|
|
|
return (
|
|
|
- <span
|
|
|
- class={
|
|
|
- this.menu.id == data.id || (this.menu.parent == data.id && !this.menu.id)
|
|
|
- ? 'custom-tree-node selected'
|
|
|
- : 'custom-tree-node'
|
|
|
- }
|
|
|
- >
|
|
|
+ <span class="custom-tree-node">
|
|
|
<span>{data.name}</span>
|
|
|
<span class="url">{data.path}</span>
|
|
|
<span class="opt">
|
|
|
@@ -398,42 +345,23 @@ export default {
|
|
|
FontAwesome.dom.i2svg();
|
|
|
this.menu.icon = '';
|
|
|
}
|
|
|
- },
|
|
|
- nodeClick(data, node, el) {
|
|
|
- if (this.expandKeys[0] != data.id) {
|
|
|
- this.expandKeys = [data.id];
|
|
|
- }
|
|
|
}
|
|
|
},
|
|
|
watch: {
|
|
|
icon(val) {
|
|
|
this.showIcon(val);
|
|
|
- },
|
|
|
- category() {
|
|
|
- this.getData();
|
|
|
}
|
|
|
}
|
|
|
};
|
|
|
</script>
|
|
|
-<style lang="less" scoped>
|
|
|
-.menus {
|
|
|
- padding: 20px;
|
|
|
-}
|
|
|
-.menu-tree {
|
|
|
- border-radius: 4px;
|
|
|
- background: white;
|
|
|
- margin-top: 20px;
|
|
|
- padding: 10px;
|
|
|
-}
|
|
|
-/deep/ .custom-tree-node {
|
|
|
+<style lang="less">
|
|
|
+.custom-tree-node {
|
|
|
flex: 1;
|
|
|
display: flex;
|
|
|
align-items: center;
|
|
|
justify-content: space-between;
|
|
|
font-size: 14px;
|
|
|
padding-right: 8px;
|
|
|
- line-height: 40px;
|
|
|
- height: 40px;
|
|
|
.url {
|
|
|
flex-grow: 1;
|
|
|
text-align: right;
|
|
|
@@ -443,33 +371,19 @@ export default {
|
|
|
.opt {
|
|
|
opacity: 0;
|
|
|
}
|
|
|
- &.selected {
|
|
|
- border: 2px solid @prim;
|
|
|
- border-radius: 4px;
|
|
|
- padding: 0 10px;
|
|
|
- box-sizing: border-box;
|
|
|
- .opt {
|
|
|
- opacity: 1;
|
|
|
- }
|
|
|
- }
|
|
|
- &:hover {
|
|
|
- .opt {
|
|
|
- opacity: 1;
|
|
|
- }
|
|
|
- }
|
|
|
}
|
|
|
-/deep/ .menu-tree {
|
|
|
- .el-tree-node__content {
|
|
|
- height: 40px;
|
|
|
- line-height: 40px;
|
|
|
+
|
|
|
+.custom-tree-node:hover {
|
|
|
+ .opt {
|
|
|
+ opacity: 1;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-/deep/ .available-icons {
|
|
|
- color: @prim;
|
|
|
+.available-icons {
|
|
|
+ color: #409eff;
|
|
|
text-decoration: none;
|
|
|
&:hover {
|
|
|
- color: @prim;
|
|
|
+ color: #409eff;
|
|
|
text-decoration: none;
|
|
|
}
|
|
|
}
|