<template>
<div
class="ky-menus-box"
ref="kyMenus"
@mouseenter="handleMouseEnter"
@mouseleave="handleMouseLeave"
>
<div
class="ky-menus-bg"
:class="{ active: showAllSubMenus }"
:style="{ height: backgroundHeight + 'px' }"
></div>
<ul class="ky-menus" :class="{ active: showAllSubMenus }">
<template v-for="item in menus">
<li
class="ky-menus-item"
v-if="item.isShow && !(item.children && item.children.length)"
:icon="item.iconClass"
@click="handleOpenFunc(item)"
:key="item.resId"
>
{{ item.name }}
</li>
<li
class="ky-menus-item"
v-if="item.isShow && item.children && item.children.length"
:key="item.resId"
>
<div class="title">
<span class="txt">{{ item.name }}</span>
</div>
<div
class="sub-menu"
v-if="item.isShow && item.children && item.children.length"
>
<ul v-show="showAllSubMenus">
<template v-for="child in item.children">
<li
v-if="
child.isShow && !(child.children && child.children.length)
"
@click="handleOpenFunc(child)"
:key="child.resId"
>
<div class="title">
<span class="txt">{{ child.name }}</span>
</div>
</li>
<nav-sub-menus
:level="0"
:menuitem="child"
:parent="kyMenus"
v-if="child.isShow && child.children && child.children.length"
:key="child.resId"
>
</nav-sub-menus>
</template>
</ul>
</div>
</li>
</template>
</ul>
</div>
</template>
<script>
import NavSubMenus from "./menus.vue";
export default {
inject: ["addTab"],
provide() {
let me = this;
return {
hideMenus() {
me.hideMenus();
},
};
},
props: {},
components: { NavSubMenus },
data() {
return {
showAllSubMenus: false,
backgroundHeight: 0,
isMenuDisabled: false, // 添加禁用标志
};
},
computed: {
menus() {
const menus = this.$store.getters.menus;
return menus;
},
},
watch: {},
mounted() {
console.log(this.menus);
},
methods: {
async handleOpenFunc(item) {
if (item.type == "link") {
window.open(item.resUrl, item.name);
return;
} else if (item.type == "sso") {
item.ssoUrl = await this.$store.dispatch("user/openSSOFuncPage", {
serviceUrl: item.resUrl,
});
}
// this.addTab(item.resUrl,item.name,item.resId)//,item.resId
this.addTab(item); //inject 提供的方法只能 传一个参数
this.hideMenus();
},
handleMouseEnter(e) {
// 如果菜单被禁用,则不处理鼠标事件
if (this.isMenuDisabled) {
return;
}
if (e) {
const target = e.target || e.srcElement;
if (target.closest && target.closest(".pl-menus-item")) {
return;
}
}
this.showAllSubMenus = true;
this.$nextTick(() => {
this.calculateMaxHeight();
});
},
handleMouseLeave(e) {
// 如果菜单被禁用,则不处理鼠标事件
if (this.isMenuDisabled) {
return;
}
if (e) {
// 检查鼠标是否移向.pl-menus-item类元素
const relatedTarget = e.relatedTarget || e.toElement;
if (
relatedTarget &&
relatedTarget.closest &&
relatedTarget.closest(".pl-menus-item")
) {
return;
}
}
this.hideMenus();
},
hideMenus() {
// return;
this.showAllSubMenus = false;
this.backgroundHeight = 0;
this.isMenuDisabled = true;
// 延迟重置禁用标志,避免立即触发鼠标事件
setTimeout(() => {
this.isMenuDisabled = false;
}, 100);
},
calculateMaxHeight() {
// 获取所有显示的子菜单
const subMenus = document.querySelectorAll(".ky-menus-item .sub-menu");
let maxHeight = 0;
subMenus.forEach((menu) => {
maxHeight = Math.max(maxHeight, menu.offsetHeight);
});
this.backgroundHeight = maxHeight + 20;
},
},
};
</script>
<style lang="less" scoped>
.ky-menus-box {
ul,
li {
margin: 0;
padding: 0;
list-style: none;
}
.ky-menus-bg {
position: absolute;
top: 48px;
left: 50%;
transform: translateX(-50%) scaleY(0);
width: 100%;
z-index: -999;
background: #0066cc;
transition: all 0.5s;
transform-origin: center top;
max-height: calc(100vh - 148px);
&.active {
transform: translateX(-50%) scaleY(1);
}
}
.ky-menus {
display: flex;
padding-left: 10px;
// &.active .ky-menus-item {
// opacity: 0.5;
// &:hover {
// opacity: 1;
// }
// }
.ky-menus-item {
position: relative;
line-height: 48px;
padding-right: 30px;
cursor: pointer;
}
.sub-menu {
position: absolute;
top: 48px;
left: 0;
line-height: 20px;
// white-space: nowrap;
font-size: 13px;
max-height: calc(100vh - 148px);
overflow: auto;
::v-deep .pl-menus-item {
.title {
position: relative;
.txt {
box-sizing: border-box;
padding: 5px;
padding-right: 20px;
padding-left: 0;
display: inline-block;
width: 100%;
i {
position: absolute;
right: 8px;
top: 50%;
transform: translateY(-50%);
font-size: 12px;
}
}
}
}
li {
.title {
padding: 5px;
padding-left: 0;
}
}
}
}
}
</style>