合并 vue与cloud vue3 前端项目
This commit is contained in:
		
							
								
								
									
										186
									
								
								src/components/TopNav/index.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										186
									
								
								src/components/TopNav/index.vue
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,186 @@ | ||||
| <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> | ||||
		Reference in New Issue
	
	Block a user
	 疯狂的狮子li
					疯狂的狮子li