<template> <el-menu :default-active="activeMenu" mode="horizontal" @select="handleSelect" :ellipsis="false" > <template v-for="(item, index) in topMenus"> <el-menu-item :style="{'--theme': theme}" :index="item.path" :key="index" v-if="index < visibleNumber" ><svg-icon :icon-class="item.meta.icon" /> {{ item.meta.title }}</el-menu-item > </template> <!-- 顶部菜单超出数量折叠 --> <el-sub-menu :style="{'--theme': theme}" index="more" v-if="topMenus.length > visibleNumber"> <template #title>更多菜单</template> <template v-for="(item, index) in topMenus"> <el-menu-item :index="item.path" :key="index" v-if="index >= visibleNumber" ><svg-icon :icon-class="item.meta.icon" /> {{ item.meta.title }}</el-menu-item > </template> </el-sub-menu> </el-menu> </template> <script setup> import { constantRoutes } from "@/router" import { isHttp } from '@/utils/validate' import useAppStore from '@/store/modules/app' import useSettingsStore from '@/store/modules/settings' import usePermissionStore from '@/store/modules/permission' // 顶部栏初始数 const visibleNumber = ref(null); // 当前激活菜单的 index const currentIndex = ref(null); // 隐藏侧边栏路由 const hideList = ['/index', '/user/profile']; const appStore = useAppStore() const settingsStore = useSettingsStore() const permissionStore = usePermissionStore() const route = useRoute(); const router = useRouter(); // 主题颜色 const theme = computed(() => settingsStore.theme); // 所有的路由信息 const routers = computed(() => permissionStore.topbarRouters); // 顶部显示菜单 const topMenus = computed(() => { let topMenus = []; routers.value.map((menu) => { if (menu.hidden !== true) { // 兼容顶部栏一级菜单内部跳转 if (menu.path === "/") { topMenus.push(menu.children[0]); } else { topMenus.push(menu); } } }) return topMenus; }) // 设置子路由 const childrenMenus = computed(() => { let childrenMenus = []; routers.value.map((router) => { for (let item in router.children) { if (router.children[item].parentPath === undefined) { if(router.path === "/") { router.children[item].path = "/" + router.children[item].path; } else { if(!isHttp(router.children[item].path)) { router.children[item].path = router.path + "/" + router.children[item].path; } } router.children[item].parentPath = router.path; } childrenMenus.push(router.children[item]); } }) return constantRoutes.concat(childrenMenus); }) // 默认激活的菜单 const activeMenu = computed(() => { const path = route.path; let activePath = path; if (path !== undefined && path.lastIndexOf("/") > 0 && hideList.indexOf(path) === -1) { const tmpPath = path.substring(1, path.length); activePath = "/" + tmpPath.substring(0, tmpPath.indexOf("/")); if (!route.meta.link) { appStore.toggleSideBarHide(false); } } else if(!route.children) { activePath = path; appStore.toggleSideBarHide(true); } activeRoutes(activePath); return activePath; }) function setVisibleNumber() { const width = document.body.getBoundingClientRect().width / 3; visibleNumber.value = parseInt(width / 85); } function handleSelect(key, keyPath) { currentIndex.value = key; const route = routers.value.find(item => item.path === key); if (isHttp(key)) { // http(s):// 路径新窗口打开 window.open(key, "_blank"); } else if (!route || !route.children) { // 没有子路由路径内部打开 router.push({ path: key }); appStore.toggleSideBarHide(true); } else { // 显示左侧联动菜单 activeRoutes(key); appStore.toggleSideBarHide(false); } } function activeRoutes(key) { let routes = []; if (childrenMenus.value && childrenMenus.value.length > 0) { childrenMenus.value.map((item) => { if (key == item.parentPath || (key == "index" && "" == item.path)) { routes.push(item); } }); } if(routes.length > 0) { permissionStore.setSidebarRouters(routes); } else { appStore.toggleSideBarHide(true); } return routes; } onMounted(() => { window.addEventListener('resize', setVisibleNumber) }) onBeforeUnmount(() => { window.removeEventListener('resize', setVisibleNumber) }) onMounted(() => { setVisibleNumber() }) </script> <style lang="scss"> .topmenu-container.el-menu--horizontal > .el-menu-item { float: left; height: 50px !important; line-height: 50px !important; color: #999093 !important; padding: 0 5px !important; margin: 0 10px !important; } .topmenu-container.el-menu--horizontal > .el-menu-item.is-active, .el-menu--horizontal > .el-sub-menu.is-active .el-submenu__title { border-bottom: 2px solid #{'var(--theme)'} !important; color: #303133; } /* sub-menu item */ .topmenu-container.el-menu--horizontal > .el-sub-menu .el-sub-menu__title { float: left; height: 50px !important; line-height: 50px !important; color: #999093 !important; padding: 0 5px !important; margin: 0 10px !important; } </style>