131 lines
3.6 KiB
Vue
131 lines
3.6 KiB
Vue
<!-- 混合布局顶部菜单 -->
|
|
<template>
|
|
<el-menu
|
|
mode="horizontal"
|
|
:default-active="activeTopMenuPath"
|
|
:background-color="
|
|
theme === 'dark' || sidebarColorScheme === SidebarColor.CLASSIC_BLUE
|
|
? variables['menu-background']
|
|
: undefined
|
|
"
|
|
:text-color="
|
|
theme === 'dark' || sidebarColorScheme === SidebarColor.CLASSIC_BLUE
|
|
? variables['menu-text']
|
|
: undefined
|
|
"
|
|
:active-text-color="
|
|
theme === 'dark' || sidebarColorScheme === SidebarColor.CLASSIC_BLUE
|
|
? variables['menu-active-text']
|
|
: undefined
|
|
"
|
|
@select="handleMenuSelect"
|
|
>
|
|
<el-menu-item v-for="route in topMenus" :key="route.path" :index="route.path">
|
|
<MenuItemTitle v-if="route.meta" :icon="route.meta.icon" :title="route.meta.title" />
|
|
</el-menu-item>
|
|
</el-menu>
|
|
</template>
|
|
|
|
<script lang="ts" setup>
|
|
import MenuItemTitle from "./components/MenuItemTitle.vue";
|
|
|
|
defineOptions({
|
|
name: "MixTopMenu",
|
|
});
|
|
|
|
import { LocationQueryRaw, RouteRecordRaw } from "vue-router";
|
|
import { usePermissionStore, useAppStore, useSettingsStore } from "@/store";
|
|
import variables from "@/styles/variables.module.scss";
|
|
import { SidebarColor } from "@/enums/settings/theme.enum";
|
|
|
|
const router = useRouter();
|
|
const appStore = useAppStore();
|
|
const permissionStore = usePermissionStore();
|
|
const settingsStore = useSettingsStore();
|
|
|
|
// 获取主题
|
|
const theme = computed(() => settingsStore.theme);
|
|
|
|
// 获取浅色主题下的侧边栏配色方案
|
|
const sidebarColorScheme = computed(() => settingsStore.sidebarColorScheme);
|
|
|
|
// 顶部菜单列表
|
|
const topMenus = ref<RouteRecordRaw[]>([]);
|
|
|
|
// 获取当前路由路径的顶部菜单路径
|
|
const activeTopMenuPath =
|
|
useRoute().path.split("/").filter(Boolean).length > 1
|
|
? useRoute().path.match(/^\/[^/]+/)?.[0] || "/"
|
|
: "/";
|
|
|
|
// 设置当前激活的顶部菜单路径
|
|
appStore.activeTopMenu(activeTopMenuPath);
|
|
|
|
/**
|
|
* 处理菜单点击事件,切换顶部菜单并加载对应的左侧菜单
|
|
* @param routePath 点击的菜单路径
|
|
*/
|
|
const handleMenuSelect = (routePath: string) => {
|
|
appStore.activeTopMenu(routePath); // 设置激活的顶部菜单
|
|
activateFirstLevelMenu(routePath); // 激活一级菜单并设置左侧二级菜单
|
|
};
|
|
|
|
/**
|
|
* 激活一级菜单并设置左侧二级菜单
|
|
* @param routePath 点击的菜单路径
|
|
*/
|
|
function activateFirstLevelMenu(routePath: string) {
|
|
permissionStore.updateSideMenu(routePath); // 更新左侧菜单
|
|
navigateToFirstLeftMenu(permissionStore.sideMenuRoutes); // 跳转到左侧第一个菜单
|
|
}
|
|
|
|
/**
|
|
* 跳转到左侧第一个可访问的菜单
|
|
* @param menus 左侧菜单列表
|
|
*/
|
|
const navigateToFirstLeftMenu = (menus: RouteRecordRaw[]) => {
|
|
if (menus.length === 0) return;
|
|
|
|
const [firstMenu] = menus;
|
|
|
|
// 如果第一个菜单有子菜单,递归跳转到第一个子菜单
|
|
if (firstMenu.children && firstMenu.children.length > 0) {
|
|
navigateToFirstLeftMenu(firstMenu.children as RouteRecordRaw[]);
|
|
} else if (firstMenu.name) {
|
|
router.push({
|
|
name: firstMenu.name,
|
|
query:
|
|
typeof firstMenu.meta?.params === "object"
|
|
? (firstMenu.meta.params as LocationQueryRaw)
|
|
: undefined,
|
|
});
|
|
}
|
|
};
|
|
|
|
onMounted(() => {
|
|
topMenus.value = permissionStore.routes.filter((item) => !item.meta || !item.meta.hidden);
|
|
});
|
|
</script>
|
|
|
|
<style lang="scss" scoped>
|
|
.el-menu {
|
|
width: 100%;
|
|
height: 100%;
|
|
|
|
&--horizontal {
|
|
height: $navbar-height !important;
|
|
|
|
// 确保菜单项垂直居中
|
|
:deep(.el-menu-item) {
|
|
height: 100%;
|
|
line-height: $navbar-height;
|
|
}
|
|
|
|
// 移除默认的底部边框
|
|
&:after {
|
|
display: none;
|
|
}
|
|
}
|
|
}
|
|
</style>
|