refactor: ♻️ 菜单路由优化

This commit is contained in:
Ray.Hao
2025-05-20 23:14:31 +08:00
parent 1914657ce1
commit 1e584e9bc5
6 changed files with 29 additions and 35 deletions

View File

@@ -1,7 +1,7 @@
{
"name": "vue3-element-admin",
"description": "Vue3 + Vite + TypeScript + Element-Plus 的后台管理模板vue-element-admin 的 Vue3 版本",
"version": "2.28.4",
"version": "2.29.0",
"private": true,
"type": "module",
"scripts": {

View File

@@ -78,10 +78,18 @@ appStore.activeTopMenu(activeTopMenuPath);
*/
const handleMenuSelect = (routePath: string) => {
appStore.activeTopMenu(routePath); // 设置激活的顶部菜单
permissionStore.setMixedLayoutLeftRoutes(routePath); // 更新左侧菜单
navigateToFirstLeftMenu(permissionStore.mixedLayoutLeftRoutes); // 跳转到左侧第一个菜单
activateFirstLevelMenu(routePath); // 激活一级菜单并设置左侧二级菜单
};
/**
* 激活一级菜单并设置左侧二级菜单
* @param routePath 点击的菜单路径
*/
function activateFirstLevelMenu(routePath: string) {
permissionStore.updateSideMenu(routePath); // 更新左侧菜单
navigateToFirstLeftMenu(permissionStore.sideMenuRoutes); // 跳转到左侧第一个菜单
}
/**
* 跳转到左侧第一个可访问的菜单
* @param menus 左侧菜单列表

View File

@@ -11,7 +11,7 @@
<!-- 左侧菜单栏 -->
<div class="layout__sidebar--left">
<el-scrollbar>
<SidebarMenu :data="mixedLayoutLeftRoutes" :base-path="activeTopMenuPath" />
<SidebarMenu :data="sideMenuRoutes" :base-path="activeTopMenuPath" />
</el-scrollbar>
<!-- 侧边栏切换按钮 -->
<div class="layout__sidebar-toggle">
@@ -72,13 +72,13 @@ const isSidebarOpen = computed(() => appStore.sidebar.opened); // 侧边栏是
const isShowTagsView = computed(() => settingsStore.tagsView); // 是否显示标签视图
const layout = computed(() => settingsStore.layout); // 当前布局模式left、top、mix
const activeTopMenuPath = computed(() => appStore.activeTopMenuPath); // 顶部菜单激活路径
const mixedLayoutLeftRoutes = computed(() => permissionStore.mixedLayoutLeftRoutes); // 混合布局左侧菜单路由
const sideMenuRoutes = computed(() => permissionStore.sideMenuRoutes); // 混合布局左侧菜单路由
// 监听顶部菜单激活路径变化,更新混合布局左侧菜单路由
watch(
() => activeTopMenuPath.value,
(newVal: string) => {
permissionStore.setMixedLayoutLeftRoutes(newVal);
permissionStore.updateSideMenu(newVal);
},
{ deep: true, immediate: true }
);

View File

@@ -16,12 +16,13 @@ export function setupPermission() {
const isLogin = !!Storage.get(ACCESS_TOKEN_KEY, ""); // 判断是否登录
if (isLogin) {
if (to.path === "/login") {
// 已登录,访问登录页,跳转到首页
// 已登录,跳转到首页
next({ path: "/" });
} else {
// 未登录
const permissionStore = usePermissionStore();
// 判断路由是否加载完成
if (permissionStore.isRoutesLoaded) {
if (permissionStore.routesLoaded) {
if (to.matched.length === 0) {
// 路由未匹配跳转到404
next("/404");

View File

@@ -8,12 +8,12 @@ const modules = import.meta.glob("../../views/**/**.vue");
const Layout = () => import("@/layout/index.vue");
export const usePermissionStore = defineStore("permission", () => {
// 储所有路由,包括静态路由和动态路由
// 储所有路由,包括静态路由和动态路由
const routes = ref<RouteRecordRaw[]>([]);
// 混合模式左侧菜单路由
const mixedLayoutLeftRoutes = ref<RouteRecordRaw[]>([]);
const sideMenuRoutes = ref<RouteRecordRaw[]>([]);
// 路由是否加载完成
const isRoutesLoaded = ref(false);
const routesLoaded = ref(false);
/**
* 获取后台动态路由数据,解析并注册到全局路由
@@ -26,7 +26,7 @@ export const usePermissionStore = defineStore("permission", () => {
.then((data) => {
const dynamicRoutes = parseDynamicRoutes(data);
routes.value = [...constantRoutes, ...dynamicRoutes];
isRoutesLoaded.value = true;
routesLoaded.value = true;
resolve(dynamicRoutes);
})
.catch((error) => {
@@ -36,14 +36,14 @@ export const usePermissionStore = defineStore("permission", () => {
}
/**
* 根据父菜单路径设置混合模式左侧菜单
* 根据父菜单路径设置侧菜单
*
* @param parentPath 父菜单的路径,用于查找对应的菜单项
*/
const setMixedLayoutLeftRoutes = (parentPath: string) => {
const updateSideMenu = (parentPath: string) => {
const matchedItem = routes.value.find((item) => item.path === parentPath);
if (matchedItem && matchedItem.children) {
mixedLayoutLeftRoutes.value = matchedItem.children;
sideMenuRoutes.value = matchedItem.children;
}
};
@@ -60,16 +60,16 @@ export const usePermissionStore = defineStore("permission", () => {
// 清空本地存储的路由和菜单数据
routes.value = [];
mixedLayoutLeftRoutes.value = [];
isRoutesLoaded.value = false;
sideMenuRoutes.value = [];
routesLoaded.value = false;
};
return {
routes,
mixedLayoutLeftRoutes,
isRoutesLoaded,
sideMenuRoutes,
routesLoaded,
generateRoutes,
setMixedLayoutLeftRoutes,
updateSideMenu,
resetRouter,
};
});

View File

@@ -1,15 +0,0 @@
/**
* WebSocket相关类型定义
*/
/**
* 字典WebSocket事件类型
*/
export interface DictWebSocketEvent {
/** 事件类型:更新或删除 */
type: "DICT_UPDATED" | "DICT_DELETED";
/** 字典编码 */
dictCode: string;
/** 时间戳 */
timestamp: number;
}