105 lines
3.0 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import {
NavigationGuardNext,
RouteLocationNormalized,
RouteRecordRaw,
} from "vue-router";
import NProgress from "@themeDefault/utils/nprogress";
import { TOKEN_KEY } from "@themeDefault/enums/CacheEnum";
import router from "@themeDefault/router";
import { usePermissionStore, useUserStore } from "@themeDefault/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<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().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));
}