221 lines
5.4 KiB
Vue
221 lines
5.4 KiB
Vue
<template>
|
|
<el-container>
|
|
<el-aside width="300px" v-loading="menuloading">
|
|
<el-container>
|
|
<el-header>
|
|
<el-input placeholder="输入关键字进行过滤" v-model="menuFilterText" clearable></el-input>
|
|
</el-header>
|
|
<el-main class="nopadding">
|
|
<el-tree ref="menuRef" class="menu" node-key="menu_id" :data="menuList" :props="menuProps"
|
|
highlight-current :expand-on-click-node="false" check-strictly show-checkbox
|
|
:filter-node-method="menuFilterNode" @node-click="menuClick" :check-on-click-leaf="false">
|
|
<template #default="{node, data}">
|
|
<span class="custom-tree-node el-tree-node__label">
|
|
<span class="label">
|
|
{{ node.label }}
|
|
<el-button v-if="data.type == 0" link size="small" type="warning"
|
|
style="margin-left: 5px;">菜单</el-button>
|
|
<el-button v-if="data.type == 1" link size="small" type="primary"
|
|
style="margin-left: 5px;">按钮</el-button>
|
|
<el-button v-if="data.type == 2" link size="small" type="success"
|
|
style="margin-left: 5px;">接口</el-button>
|
|
<el-button v-if="data.type == 3" link size="small" type="danger"
|
|
style="margin-left: 5px;">外链</el-button>
|
|
</span>
|
|
<span class="do">
|
|
<el-icon @click.stop="add(node, data)"><el-icon-plus/></el-icon>
|
|
<el-icon @click.stop="quick(node, data)"><pi-icon-quick/></el-icon>
|
|
</span>
|
|
</span>
|
|
</template>
|
|
</el-tree>
|
|
</el-main>
|
|
<el-footer style="height:51px;">
|
|
<el-button type="primary" size="small" icon="el-icon-plus" @click="add"></el-button>
|
|
<el-button type="danger" size="small" plain icon="el-icon-delete" @click="delMenu"></el-button>
|
|
</el-footer>
|
|
</el-container>
|
|
</el-aside>
|
|
<el-container>
|
|
<el-main class="nopadding" style="padding:20px;" ref="mainRef">
|
|
<save ref="saveRef" :menu="menuList"></save>
|
|
</el-main>
|
|
</el-container>
|
|
<quick-dialog v-if="quickShow" ref="quickRef" @success="success" @closed="quickShow = false"></quick-dialog>
|
|
</el-container>
|
|
</template>
|
|
|
|
<script setup>
|
|
import quickDialog from "./quick"
|
|
import {ref, watch, getCurrentInstance, nextTick} from "vue";
|
|
import save from './save'
|
|
import api from "@/api/index";
|
|
|
|
defineOptions({
|
|
name: "systemMenu"
|
|
})
|
|
|
|
const menuRef = ref(null)
|
|
const saveRef = ref(null)
|
|
const mainRef = ref(null)
|
|
const quickRef = ref(null)
|
|
|
|
const {proxy} = getCurrentInstance()
|
|
let menuloading = ref(false)
|
|
let menuList = ref([])
|
|
let menuProps = ref({
|
|
label: (data) => {
|
|
return data.title
|
|
}
|
|
})
|
|
let menuFilterText = ref("")
|
|
let newMenuIndex = ref(1);
|
|
let quickShow = ref(false)
|
|
|
|
watch(menuFilterText, (val) => {
|
|
menuRef.value.filter(val);
|
|
})
|
|
|
|
getMenu()
|
|
|
|
async function getMenu() {
|
|
menuloading.value = true
|
|
var res = await api.system.menu.list();
|
|
menuloading.value = false
|
|
menuList.value = treeData(res.data, 0);
|
|
}
|
|
|
|
function treeData(menus, menu_id) {
|
|
if (menus == undefined || menus.length <= 0) return [];
|
|
const arr = [];
|
|
for (let item of menus) {
|
|
// 数据格式处理
|
|
const tmp = item;
|
|
if (item.parent_id == menu_id) {
|
|
var children = treeData(menus, item.menu_id);
|
|
if (children.length > 0) {
|
|
tmp['children'] = children
|
|
}
|
|
arr.push(tmp)
|
|
}
|
|
}
|
|
return arr
|
|
}
|
|
|
|
function menuClick(data) {
|
|
saveRef.value.setData(data)
|
|
mainRef.value.$el.scrollTop = 0
|
|
}
|
|
|
|
function menuFilterNode(value, data) {
|
|
if (!value) return true;
|
|
var targetText = data.title;
|
|
return targetText.indexOf(value) !== -1;
|
|
}
|
|
|
|
async function add(node, data) {
|
|
var newMenuName = "未命名" + newMenuIndex.value++;
|
|
var newMenuData = {
|
|
menu_id: "",
|
|
parent_id: data ? data.menu_id : 0,
|
|
name: newMenuName,
|
|
path: "",
|
|
title: newMenuName,
|
|
type: 0,
|
|
rank: 1
|
|
}
|
|
menuloading.value = false
|
|
menuRef.value.append(newMenuData, node)
|
|
menuRef.value.setCurrentKey(newMenuData.menu_id)
|
|
saveRef.value.setData(newMenuData)
|
|
}
|
|
|
|
function quick(node, data) {
|
|
quickShow.value = true
|
|
nextTick(() => {
|
|
quickRef.value.open(data.menu_id)
|
|
})
|
|
}
|
|
|
|
function success() {
|
|
quickShow.value = false
|
|
reload()
|
|
}
|
|
|
|
async function delMenu() {
|
|
var CheckedNodes = menuRef.value.getCheckedNodes()
|
|
if (CheckedNodes.length == 0) {
|
|
proxy.$message.warning("请选择需要删除的项")
|
|
return false;
|
|
}
|
|
var confirm = await proxy.$confirm('确认删除已选择的菜单吗?', '提示', {
|
|
type: 'warning',
|
|
confirmButtonText: '删除',
|
|
cancelButtonText: '取消',
|
|
confirmButtonClass: 'el-button--danger'
|
|
}).catch(() => {
|
|
})
|
|
if (confirm != 'confirm') {
|
|
return false
|
|
}
|
|
menuloading.value = true
|
|
var res = await api.system.menu.del({ids: CheckedNodes.map(item => item.menu_id)})
|
|
menuloading.value = false
|
|
proxy.$message.success(res.msg)
|
|
CheckedNodes.forEach(item => {
|
|
var node = menuRef.value.getNode(item)
|
|
if (node == null) {
|
|
reload()
|
|
} else if (node.isCurrent) {
|
|
saveRef.value.setData({})
|
|
}
|
|
menuRef.value.remove(item)
|
|
})
|
|
}
|
|
|
|
function reload() {
|
|
getMenu()
|
|
saveRef.value.setData(menuList.value[0])
|
|
mainRef.value.$el.scrollTop = 0
|
|
}
|
|
</script>
|
|
|
|
<style scoped>
|
|
.custom-tree-node {
|
|
display: flex;
|
|
flex: 1;
|
|
align-items: center;
|
|
justify-content: space-between;
|
|
font-size: 14px;
|
|
padding-right: 24px;
|
|
height: 100%;
|
|
}
|
|
|
|
.custom-tree-node .label {
|
|
display: flex;
|
|
align-items: center;;
|
|
height: 100%;
|
|
}
|
|
|
|
.custom-tree-node .label .el-tag {
|
|
margin-left: 5px;
|
|
}
|
|
|
|
.custom-tree-node .do {
|
|
display: none;
|
|
}
|
|
|
|
.custom-tree-node .do i {
|
|
margin-left: 5px;
|
|
color: #999;
|
|
}
|
|
|
|
.custom-tree-node .do i:hover {
|
|
color: #333;
|
|
}
|
|
|
|
.custom-tree-node:hover .do {
|
|
display: inline-block;
|
|
}
|
|
</style>
|