<template>
|
<div class="vol-el-menu">
|
<div class="menu-search" v-if="showSearch">
|
<el-select placement="bottom" v-model="searchValue" clearable filterable remote reserve-keyword
|
:placeholder="'请输入关键字搜索...'" :remote-method="remoteMethod" @change="selectChange" :loading="loading">
|
<template #prefix><i class="el-icon-search"></i></template>
|
<el-option v-for="item in options" :key="item.value" :label="item.label" :value="item.value" />
|
</el-select>
|
</div>
|
<el-menu close="vol-el-menu--vertical" :default-openeds="openedIds" :default-active="defaultActive"
|
:unique-opened="true" @select="select" :collapse="isCollapse" @open="handleOpen" @close="handleClose"
|
@contextmenu.prevent="bindRightClickMenu">
|
<template v-for="item in convertTree(list)">
|
<el-sub-menu :key="item.id" :index="'' + item.id" v-if="item.children.length && (!enable || item.enable == 1)">
|
<template #title>
|
<i class="menu-icon" :class="item.icon"></i>
|
<span> {{ item.name}}</span>
|
</template>
|
<vol-element-menu-child :enable="enable" :list="item.children"></vol-element-menu-child>
|
</el-sub-menu>
|
<template v-else>
|
<el-menu-item class="menu-item-lv1" v-if="!enable || item.enable == 1" :key="item.id" :index="'' + item.id">
|
<i :class="item.icon"></i>
|
<span> {{ item.name }}</span>
|
</el-menu-item>
|
</template>
|
</template>
|
</el-menu>
|
</div>
|
</template>
|
|
<script>
|
import VolElementMenuChild from "./VolElementMenuChild";
|
import { useRouter } from "vue-router";
|
|
import {
|
defineComponent,
|
reactive,
|
watch,
|
ref,
|
toRef,
|
toRefs,
|
getCurrentInstance,
|
// onMounted,
|
} from "vue";
|
export default defineComponent({
|
components: {
|
"vol-element-menu-child": VolElementMenuChild,
|
},
|
props: {
|
enable: {
|
type: Boolean,
|
default: false, //是否判断enable=1
|
},
|
isCollapse: {
|
type: Boolean,
|
default: false,
|
},
|
onSelect: {
|
type: Function,
|
default: (x) => { },
|
},
|
openSelect: {
|
//打开的时候是否触发选中事件
|
type: Boolean,
|
default: true,
|
},
|
list: {
|
type: Array,
|
default: [],
|
},
|
rootId: {
|
type: String,
|
default: "0",
|
},
|
currentMenuId: {
|
type: Number,
|
default: 0,
|
},
|
},
|
setup(props) {
|
// const { list } = toRefs(props);
|
// const treeList = ref([]);
|
const getTree = (id, node, data) => {
|
if (!node.children) {
|
node.children = [];
|
}
|
data.forEach((x) => {
|
if (x.parentId == id && !node.children.some((c) => c.id === x.id)) {
|
node.children.push(x);
|
getTree(x.id, x, data);
|
}
|
});
|
};
|
let rootTreeId = !isNaN(props.rootId) ? ~~props.rootId : props.rootId;
|
props.list.forEach((x) => {
|
if (!x.icon || x.icon.substring(0, 3) != "el-") {
|
x.icon = "el-icon-menu";
|
}
|
x.children = [];
|
x.isRoot = x.parentId === rootTreeId;
|
});
|
const convertTree = (data) => {
|
var root_data = [];
|
data.forEach((x) => {
|
if (x.parentId === rootTreeId) {
|
if (!x.hasOwnProperty("enable")) x.enable = 1;
|
root_data.push(x);
|
getTree(x.id, x, data);
|
}
|
});
|
return root_data;
|
};
|
const openedIds = reactive([props.currentMenuId]);
|
const defaultActive = ref(props.currentMenuId + "");
|
let _base = getCurrentInstance().appContext.config.globalProperties.base;
|
watch(
|
() => props.currentMenuId,
|
(newVal, oldVal) => {
|
defaultActive.value = newVal + "";
|
openedIds.splice(0);
|
openedIds.push(
|
..._base.getTreeAllParent(newVal, props.list).map((c) => {
|
return c.id;
|
})
|
);
|
}
|
);
|
const router = useRouter();
|
let eventSelect = false;
|
const select = (index, _item) => {
|
|
_item = props.list.find((x) => {
|
return x.id == index;
|
});
|
|
if (_item.linkType == 1) {
|
window.open(_item.url || _item.path, '_blank')
|
return;
|
}
|
if (eventSelect) {
|
return;
|
}
|
eventSelect = true;
|
setTimeout(() => {
|
eventSelect = false;
|
}, 20);
|
|
|
|
props.onSelect(index, _item);
|
router.push({ path: _item.path || "", query: _item.query });
|
};
|
|
const handleOpen = (index, path) => {
|
if (props.openSelect) {
|
select(index, path);
|
}
|
};
|
const handleClose = () => { };
|
|
/**
|
* 菜单导航右键事件
|
* @param {*} enable 是否启用右键事件[true:启用;false:禁用;]
|
*/
|
const bindRightClickMenu = (enable) => {
|
if (!enable) return;
|
};
|
const { proxy } = getCurrentInstance();
|
const loading = ref(false)
|
const searchValue = ref('');
|
const options = ref([]);
|
const remoteMethod = (query) => {
|
if (!query) {
|
options.value.length = 0;
|
return;
|
}
|
options.value = props.list
|
.filter(c => { return (c.enable == 1 || c.enable === undefined) && c.name.indexOf(query) != -1 && (!c.children || !c.children.length) })
|
.map(x => { return { value: x.id, label: x.name } }).slice(0, 7)
|
}
|
const selectChange = (id) => {
|
if (!id) {
|
return;
|
}
|
let index = props.list.findIndex(c => { return c.id === id });
|
if (index === -1) {
|
return;
|
}
|
searchValue.value = "";
|
if(proxy.list.some(c=>{return c.parentId===id})){
|
return;
|
}
|
select(id, props.list[index]);
|
}
|
|
const showSearch=ref(proxy.$global.menuSearch===undefined||proxy.$global.menuSearch)
|
return {
|
// treeList,
|
// list,
|
select,
|
convertTree,
|
handleOpen,
|
handleClose,
|
bindRightClickMenu,
|
openedIds,
|
defaultActive,
|
searchValue,
|
options,
|
remoteMethod,
|
loading,
|
selectChange,
|
showSearch
|
};
|
},
|
});
|
</script>
|
<style lang="less" scoped>
|
.vol-el-menu {
|
// box-sizing: content-box;
|
width: 100%;
|
|
.menu-icon {
|
font-size: 18px;
|
margin-right: 6px;
|
}
|
}
|
|
.menu-search {
|
padding: 6px 10px;
|
|
::v-deep(.el-input__wrapper) {
|
border-radius: 15px !important;
|
}
|
}
|
</style>
|