| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146 |
- <!-- 带有二级菜单的layout -->
- <template>
- <div class="component-container home-container">
- <aside class="aside">
- <header class="aside__header" />
- <main class="aside__main">
- <el-menu :default-active="selectedKeys" :default-openeds="openKeys" router class="el-menu-vertical">
- <template v-for="item in subMenus" :key="item.name">
- <el-sub-menu v-if="item.children" :index="item.path">
- <template #title>
- <component v-if="item.meta?.icon" :is="item.meta.icon" />
- <span class="menu-title">{{ item.meta?.title }}</span>
- </template>
- <el-menu-item v-for="child in item.children" :key="child.name" :index="child.path">
- <div style="margin-left: 12px">
- {{ child.meta?.title }}
- </div>
- </el-menu-item>
- </el-sub-menu>
- <el-menu-item v-else :index="item.path">
- <component v-if="item.meta?.icon" :is="item.meta?.icon" />
- <span class="menu-title">
- {{ item.meta?.title }}
- </span>
- </el-menu-item>
- </template>
- </el-menu>
- </main>
- </aside>
- <div class="main">
- <router-view></router-view>
- </div>
- </div>
- </template>
- <script setup lang="ts">
- import { ref, watch, computed } from 'vue';
- import { useRoute } from 'vue-router';
- // 当前路由
- const currentRoute = useRoute();
- const activeMenu = currentRoute.meta?.activeMenu || null; // activeMenu undefined,null 或 空字符串,统一变为 null。
- const selectedKeys = ref<string>((activeMenu ?? currentRoute.path) as string);
- const openKeys = ref<string[]>([]);
- // 将菜单数组过滤掉隐藏的菜单
- const filterHiddenMenus = (menus: any[]) => {
- return menus.filter((menu) => !menu.meta?.hidden);
- };
- function filterHiddenItems(arr: any[]): any[] {
- return arr.filter((item) => {
- if (item.meta && item.meta.hidden) {
- return false;
- }
- if (item.children && Array.isArray(item.children)) {
- item.children = filterHiddenItems(item.children);
- }
- return true;
- });
- }
- const subMenus = computed(() => {
- return filterHiddenItems(currentRoute.matched[0].children);
- });
- // 跟随页面路由变化,切换菜单选中状态
- watch(
- () => currentRoute.fullPath,
- () => {
- const matched = currentRoute.matched;
- openKeys.value = matched.map((item) => item.name) as string[];
- const activeMenu: string = (currentRoute.meta?.activeMenu as string) || '';
- selectedKeys.value = activeMenu ? activeMenu : (currentRoute.path as string);
- },
- );
- </script>
- <style scoped lang="scss">
- .home-container {
- display: flex;
- gap: 10px;
- padding: 10px;
- height: 100%;
- }
- .aside {
- display: flex;
- flex-direction: column;
- width: 270px;
- height: 100%;
- flex-shrink: 0;
- border-radius: 4px;
- background-color: $white-color;
- &__header {
- width: inherit;
- height: 10px;
- flex-shrink: 0;
- }
- &__main {
- width: inherit;
- flex: 1;
- }
- }
- .main {
- flex: 1;
- overflow: auto;
- border-radius: 4px;
- }
- .el-menu-vertical {
- width: 100%;
- height: 100%;
- border: none;
- border-radius: 4px;
- .el-menu-item,
- :deep(.el-sub-menu__title) {
- font-size: 18px;
- color: #333;
- }
- .el-menu-item.is-active {
- color: $white-color;
- background-color: $primary-color;
- }
- }
- .el-menu-item,
- .el-sub-menu {
- svg {
- color: $primary-color;
- }
- }
- .el-menu-item {
- &.is-active {
- svg {
- color: #fff;
- }
- }
- }
- :deep(.el-sub-menu__title),
- :deep(.el-menu-item) {
- display: flex;
- align-items: center;
- gap: 12px;
- }
- </style>
|