fix: 🐛 修复登录成功路由无法跳转问题和相关代码优化

This commit is contained in:
Ray.Hao
2025-08-04 15:04:11 +08:00
parent 4a224bbd0e
commit 0179b5c470
7 changed files with 96 additions and 221 deletions

View File

@@ -1,169 +1,87 @@
import type { NavigationGuardNext, RouteLocationNormalized, RouteRecordRaw } from "vue-router";
import type { RouteRecordRaw } from "vue-router";
import NProgress from "@/utils/nprogress";
import { Auth } from "@/utils/auth";
import router from "@/router";
import { usePermissionStore, useUserStore } from "@/store";
import { ROLE_ROOT } from "@/constants";
// 路由生成锁,防止重复生成
let isGeneratingRoutes = false;
export function setupPermission() {
// 白名单路由
const whiteList = ["/login"];
const whiteList = ["/login"]; // 无需登录的页面
router.beforeEach(async (to, from, next) => {
NProgress.start();
const isLoggedIn = Auth.isLoggedIn();
try {
const isLoggedIn = Auth.isLoggedIn();
if (isLoggedIn) {
// 如果已登录但访问登录页,重定向到首页
// 未登录处理
if (!isLoggedIn) {
if (whiteList.includes(to.path)) {
next();
} else {
next(`/login?redirect=${encodeURIComponent(to.fullPath)}`);
NProgress.done();
}
return;
}
// 已登录且访问登录页,重定向到首页
if (to.path === "/login") {
next({ path: "/" });
return;
}
// 处理已登录用户的路由访问
await handleAuthenticatedUser(to, from, next);
} else {
console.log("❌ User not logged in");
// 已登录用户的正常访问
const permissionStore = usePermissionStore();
const userStore = useUserStore();
// 未登录用户的处理
if (whiteList.includes(to.path)) {
next();
} else {
redirectToLogin(to, next);
NProgress.done();
// 确保用户信息已加载
if (!userStore.userInfo.username) {
await userStore.getUserInfo();
}
// 确保动态路由已生成
if (!permissionStore.isDynamicRoutesGenerated) {
const dynamicRoutes = await permissionStore.generateRoutes();
dynamicRoutes.forEach((route: RouteRecordRaw) => {
router.addRoute(route);
});
// 路由刚生成,重新导航
next({ ...to, replace: true });
return;
}
// 检查路由是否存在
if (to.matched.length === 0) {
next("/404");
return;
}
// 设置页面标题
const title = (to.params.title as string) || (to.query.title as string);
if (title) {
to.meta.title = title;
}
next();
} catch (error) {
console.error("❌ Route guard error:", error);
// 出错时清理状态并重定向到登录页
try {
await useUserStore().resetAllState();
} catch (resetError) {
console.error("❌ Failed to reset user state:", resetError);
}
next("/login");
NProgress.done();
}
});
// 后置守卫,确保进度条关闭
router.afterEach(() => {
NProgress.done();
});
}
/**
* 处理已登录用户的路由访问
*/
async function handleAuthenticatedUser(
to: RouteLocationNormalized,
from: RouteLocationNormalized,
next: NavigationGuardNext
) {
const permissionStore = usePermissionStore();
const userStore = useUserStore();
try {
// 检查用户信息是否存在
if (!userStore.userInfo.username) {
await userStore.getUserInfo();
}
// 检查路由是否已生成
if (!permissionStore.routesLoaded) {
// 防止重复生成路由
if (isGeneratingRoutes) {
console.log("⏳ Routes already generating, waiting...");
// 等待当前路由生成完成
await waitForRoutesGeneration(permissionStore);
} else {
await generateAndAddRoutes(permissionStore);
}
// 路由生成完成后,重新导航到目标路由
next({ ...to, replace: true });
return;
}
// 路由已加载,检查路由是否存在
if (to.matched.length === 0) {
next("/404");
return;
}
// 动态设置页面标题
const title = (to.params.title as string) || (to.query.title as string);
if (title) {
to.meta.title = title;
}
next();
} catch (error) {
console.error("❌ Route guard error:", error);
// 出错时重置状态并重定向到登录页
await resetUserStateAndRedirect(to, next);
}
}
/**
* 生成并添加动态路由
*/
async function generateAndAddRoutes(permissionStore: any) {
isGeneratingRoutes = true;
try {
const dynamicRoutes = await permissionStore.generateRoutes();
// 添加路由到路由器
dynamicRoutes.forEach((route: RouteRecordRaw) => {
router.addRoute(route);
});
} finally {
isGeneratingRoutes = false;
}
}
/**
* 等待路由生成完成
*/
async function waitForRoutesGeneration(permissionStore: any): Promise<void> {
return new Promise((resolve) => {
const checkInterval = setInterval(() => {
if (!isGeneratingRoutes && permissionStore.routesLoaded) {
clearInterval(checkInterval);
resolve();
}
}, 50);
// 超时保护最多等待5秒
setTimeout(() => {
clearInterval(checkInterval);
resolve();
}, 5000);
});
}
/**
* 重置用户状态并重定向到登录页
*/
async function resetUserStateAndRedirect(to: RouteLocationNormalized, next: NavigationGuardNext) {
try {
await useUserStore().resetAllState();
redirectToLogin(to, next);
} catch (resetError) {
console.error("❌ Failed to reset user state:", resetError);
// 强制跳转到登录页
next("/login");
} finally {
NProgress.done();
}
}
/**
* 重定向到登录页
*/
function redirectToLogin(to: RouteLocationNormalized, next: NavigationGuardNext) {
const params = new URLSearchParams(to.query as Record<string, string>);
const queryString = params.toString();
const redirect = queryString ? `${to.path}?${queryString}` : to.path;
next(`/login?redirect=${encodeURIComponent(redirect)}`);
}
/** 判断是否有权限 */
export function hasAuth(value: string | string[], type: "button" | "role" = "button") {
const { roles, perms } = useUserStore().userInfo;