refactor: ♻️ 菜单路由优化
This commit is contained in:
@@ -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": {
|
||||
|
||||
@@ -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 左侧菜单列表
|
||||
|
||||
@@ -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 }
|
||||
);
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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,
|
||||
};
|
||||
});
|
||||
|
||||
@@ -1,15 +0,0 @@
|
||||
/**
|
||||
* WebSocket相关类型定义
|
||||
*/
|
||||
|
||||
/**
|
||||
* 字典WebSocket事件类型
|
||||
*/
|
||||
export interface DictWebSocketEvent {
|
||||
/** 事件类型:更新或删除 */
|
||||
type: "DICT_UPDATED" | "DICT_DELETED";
|
||||
/** 字典编码 */
|
||||
dictCode: string;
|
||||
/** 时间戳 */
|
||||
timestamp: number;
|
||||
}
|
||||
Reference in New Issue
Block a user