|
|
|
@ -26,9 +26,8 @@ |
|
|
|
v-for="menu in menuList" |
|
|
|
:key="menu.menuId" |
|
|
|
class="main-menu-item" |
|
|
|
@mouseenter="showSubMenu(menu, $event)" |
|
|
|
@mouseleave="hideSubMenu" |
|
|
|
@click="handleMainMenuClick(menu)"> |
|
|
|
:class="{ 'active': hoveredMenu && hoveredMenu.menuId === menu.menuId }" |
|
|
|
@click="handleMainMenuClick(menu, $event)"> |
|
|
|
<icon-svg :name="menu.icon || ''" class="sidebar-menu-icon"></icon-svg> |
|
|
|
<span class="menu-title">{{ menu.name }}</span> |
|
|
|
<i v-if="menu.list && menu.list.length > 0" class="el-icon-arrow-right menu-arrow"></i> |
|
|
|
@ -39,9 +38,8 @@ |
|
|
|
v-for="menu in favoriteList" |
|
|
|
:key="'fav-' + menu.menuId" |
|
|
|
class="main-menu-item favorite-menu" |
|
|
|
@mouseenter="showSubMenu(menu, $event)" |
|
|
|
@mouseleave="hideSubMenu" |
|
|
|
@click="handleMainMenuClick(menu)"> |
|
|
|
:class="{ 'active': hoveredMenu && hoveredMenu.menuId === menu.menuId }" |
|
|
|
@click="handleMainMenuClick(menu, $event)"> |
|
|
|
<icon-svg :name="menu.icon || 'star-on'" class="sidebar-menu-icon"></icon-svg> |
|
|
|
<span class="menu-title">{{ menu.name }}</span> |
|
|
|
<i v-if="menu.list && menu.list.length > 0" class="el-icon-arrow-right menu-arrow"></i> |
|
|
|
@ -62,9 +60,8 @@ |
|
|
|
v-for="menu in menuList" |
|
|
|
:key="menu.menuId" |
|
|
|
class="main-menu-item folded-item" |
|
|
|
@mouseenter="showSubMenu(menu, $event)" |
|
|
|
@mouseleave="hideSubMenu" |
|
|
|
@click="handleMainMenuClick(menu)" |
|
|
|
:class="{ 'active': hoveredMenu && hoveredMenu.menuId === menu.menuId }" |
|
|
|
@click="handleMainMenuClick(menu, $event)" |
|
|
|
:title="menu.name"> |
|
|
|
<icon-svg :name="menu.icon || ''" class="sidebar-menu-icon"></icon-svg> |
|
|
|
</div> |
|
|
|
@ -74,9 +71,8 @@ |
|
|
|
v-for="menu in favoriteList" |
|
|
|
:key="'fav-' + menu.menuId" |
|
|
|
class="main-menu-item folded-item favorite-menu" |
|
|
|
@mouseenter="showSubMenu(menu, $event)" |
|
|
|
@mouseleave="hideSubMenu" |
|
|
|
@click="handleMainMenuClick(menu)" |
|
|
|
:class="{ 'active': hoveredMenu && hoveredMenu.menuId === menu.menuId }" |
|
|
|
@click="handleMainMenuClick(menu, $event)" |
|
|
|
:title="menu.name"> |
|
|
|
<icon-svg :name="menu.icon || 'star-on'" class="sidebar-menu-icon"></icon-svg> |
|
|
|
</div> |
|
|
|
@ -89,8 +85,7 @@ |
|
|
|
v-if="hoveredMenu && hoveredMenu.list && hoveredMenu.list.length > 0" |
|
|
|
class="hover-submenu" |
|
|
|
:style="submenuStyle" |
|
|
|
@mouseenter="keepSubMenuVisible" |
|
|
|
@mouseleave="hideSubMenu"> |
|
|
|
@click.stop> |
|
|
|
<div class="submenu-content"> |
|
|
|
<div class="submenu-title">{{ hoveredMenu.name }}</div> |
|
|
|
<div class="submenu-items"> |
|
|
|
@ -112,7 +107,7 @@ |
|
|
|
v-for="greatGrandChild in getAllLeafMenus(grandChild)" |
|
|
|
:key="greatGrandChild.menuId" |
|
|
|
class="submenu-link sub-link" |
|
|
|
@click="gotoRouteHandle(greatGrandChild)"> |
|
|
|
@click="gotoRouteHandle(greatGrandChild); hideSubMenu()"> |
|
|
|
{{ greatGrandChild.name }} |
|
|
|
</span> |
|
|
|
</div> |
|
|
|
@ -121,7 +116,7 @@ |
|
|
|
<span |
|
|
|
v-else |
|
|
|
class="submenu-link" |
|
|
|
@click="gotoRouteHandle(grandChild)"> |
|
|
|
@click="gotoRouteHandle(grandChild); hideSubMenu()"> |
|
|
|
{{ grandChild.name }} |
|
|
|
</span> |
|
|
|
</div> |
|
|
|
@ -130,7 +125,7 @@ |
|
|
|
<template v-else> |
|
|
|
<span |
|
|
|
class="submenu-link" |
|
|
|
@click="gotoRouteHandle(subItem)"> |
|
|
|
@click="gotoRouteHandle(subItem); hideSubMenu()"> |
|
|
|
{{ subItem.name }} |
|
|
|
</span> |
|
|
|
</template> |
|
|
|
@ -218,6 +213,14 @@ export default { |
|
|
|
this.routeHandle(this.$route) |
|
|
|
this.getFunctionButtonList() |
|
|
|
}, |
|
|
|
mounted() { |
|
|
|
// 添加全局点击监听,点击其他地方时收起菜单 |
|
|
|
document.addEventListener('click', this.handleDocumentClick) |
|
|
|
}, |
|
|
|
beforeDestroy() { |
|
|
|
// 移除全局点击监听 |
|
|
|
document.removeEventListener('click', this.handleDocumentClick) |
|
|
|
}, |
|
|
|
methods: { |
|
|
|
// 获取页面多语言数据 |
|
|
|
getFunctionButtonList() { |
|
|
|
@ -249,11 +252,6 @@ export default { |
|
|
|
|
|
|
|
// 显示子菜单 |
|
|
|
showSubMenu(menu, event) { |
|
|
|
if (this.hideTimer) { |
|
|
|
clearTimeout(this.hideTimer) |
|
|
|
this.hideTimer = null |
|
|
|
} |
|
|
|
|
|
|
|
if (menu.list && menu.list.length > 0) { |
|
|
|
this.hoveredMenu = menu |
|
|
|
const rect = event.currentTarget.getBoundingClientRect() |
|
|
|
@ -267,24 +265,42 @@ export default { |
|
|
|
|
|
|
|
// 隐藏子菜单 |
|
|
|
hideSubMenu() { |
|
|
|
this.hideTimer = setTimeout(() => { |
|
|
|
this.hoveredMenu = null |
|
|
|
this.submenuStyle = { display: 'none' } |
|
|
|
}, 100) |
|
|
|
}, |
|
|
|
|
|
|
|
// 保持子菜单可见 |
|
|
|
keepSubMenuVisible() { |
|
|
|
if (this.hideTimer) { |
|
|
|
clearTimeout(this.hideTimer) |
|
|
|
this.hideTimer = null |
|
|
|
// 处理主菜单点击 |
|
|
|
handleMainMenuClick(menu, event) { |
|
|
|
// 阻止事件冒泡,避免触发全局点击事件 |
|
|
|
if (event) { |
|
|
|
event.stopPropagation() |
|
|
|
} |
|
|
|
}, |
|
|
|
|
|
|
|
// 处理主菜单点击 |
|
|
|
handleMainMenuClick(menu) { |
|
|
|
if (!menu.list || menu.list.length === 0) { |
|
|
|
// 如果菜单有子菜单 |
|
|
|
if (menu.list && menu.list.length > 0) { |
|
|
|
// 如果当前菜单已经展开,则收起 |
|
|
|
if (this.hoveredMenu && this.hoveredMenu.menuId === menu.menuId) { |
|
|
|
this.hideSubMenu() |
|
|
|
} else { |
|
|
|
// 否则展开当前菜单 |
|
|
|
this.showSubMenu(menu, event || window.event) |
|
|
|
} |
|
|
|
} else { |
|
|
|
// 如果没有子菜单,直接跳转 |
|
|
|
this.gotoRouteHandle(menu) |
|
|
|
this.hideSubMenu() // 跳转后收起任何已展开的菜单 |
|
|
|
} |
|
|
|
}, |
|
|
|
|
|
|
|
// 处理全局点击事件 |
|
|
|
handleDocumentClick(event) { |
|
|
|
// 检查点击是否在侧边栏或子菜单内 |
|
|
|
const sidebar = this.$el |
|
|
|
const submenu = document.querySelector('.hover-submenu') |
|
|
|
|
|
|
|
if (sidebar && !sidebar.contains(event.target) && |
|
|
|
(!submenu || !submenu.contains(event.target))) { |
|
|
|
this.hideSubMenu() |
|
|
|
} |
|
|
|
}, |
|
|
|
|
|
|
|
@ -620,6 +636,28 @@ export default { |
|
|
|
&:hover .sidebar-menu-icon { |
|
|
|
transform: scale(1.1); |
|
|
|
} |
|
|
|
|
|
|
|
// 活跃状态样式 |
|
|
|
&.active { |
|
|
|
background: linear-gradient(135deg, rgba(23, 179, 163, 0.2), rgba(11, 178, 212, 0.2)); |
|
|
|
color: #fff; |
|
|
|
transform: translateX(5px); |
|
|
|
|
|
|
|
&::before { |
|
|
|
width: 4px; |
|
|
|
} |
|
|
|
|
|
|
|
.menu-arrow { |
|
|
|
transform: translateX(5px) rotate(90deg); |
|
|
|
opacity: 1; |
|
|
|
color: #fff; |
|
|
|
} |
|
|
|
|
|
|
|
.sidebar-menu-icon { |
|
|
|
transform: scale(1.1); |
|
|
|
color: #17B3A3; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|