import { NavigationGuardNext, RouteLocationNormalized, RouteRecordRaw, } from "vue-router"; import NProgress from "@/utils/nprogress"; import { TOKEN_KEY } from "@/enums/CacheEnum"; import router from "@/router"; import { usePermissionStore, useUserStore } from "@/store"; export function setupPermission() { // 白名单路由 const whiteList = ["/login"]; router.beforeEach(async (to, from, next) => { NProgress.start(); const hasToken = localStorage.getItem(TOKEN_KEY); if (hasToken) { if (to.path === "/login") { // 如果已登录,跳转到首页 next({ path: "/" }); NProgress.done(); } else { const userStore = useUserStore(); const hasRoles = userStore.user.roles && userStore.user.roles.length > 0; if (hasRoles) { // 如果未匹配到任何路由,跳转到404页面 if (to.matched.length === 0) { next(from.name ? { name: from.name } : "/404"); } else { // 如果路由参数中有 title,覆盖路由元信息中的 title const title = (to.params.title as string) || (to.query.title as string); if (title) { to.meta.title = title; } next(); } } else { const permissionStore = usePermissionStore(); try { await userStore.getUserInfo(); const dynamicRoutes = await permissionStore.generateRoutes(); dynamicRoutes.forEach((route: RouteRecordRaw) => router.addRoute(route) ); next({ ...to, replace: true }); } catch (error) { // 移除 token 并重定向到登录页,携带当前页面路由作为跳转参数 await userStore.resetToken(); redirectToLogin(to, next); NProgress.done(); } } } } else { // 未登录 if (whiteList.includes(to.path)) { next(); // 在白名单,直接进入 } else { // 不在白名单,重定向到登录页 redirectToLogin(to, next); NProgress.done(); } } }); router.afterEach(() => { NProgress.done(); }); } /** 重定向到登录页 */ function redirectToLogin( to: RouteLocationNormalized, next: NavigationGuardNext ) { const params = new URLSearchParams(to.query as Record); 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().user; // 超级管理员 拥有所有权限 if (type === "button" && roles.includes("ROOT")) { return true; } const auths = type === "button" ? perms : roles; return typeof value === "string" ? auths.includes(value) : value.some((perm) => auths.includes(perm)); }