菜单权限
store\modules\permisstion.ts -> generateRoutes()
按钮权限
directive\permission\index.ts
路由权限
plugins\permission.ts
permission.ts 修改如下
import type { NavigationGuardNext, RouteLocationNormalized, RouteRecordRaw } from "vue-router";
import NProgress from "@/utils/nprogress";
import { getAccessToken } from "@/utils/auth";
import router from "@/router";
import { usePermissionStore, useUserStore } from "@/store";export function setupPermission() {// 白名单路由const whiteList = ["/login", "/datav"];router.beforeEach(async (to, from, next) => {// 开始进度条NProgress.start();const isLogin = !!getAccessToken(); // 判断是否登录if (isLogin) {if (to.path === "/login") {// 已登录,访问登录页,跳转到首页next({ path: "/" });} else {const permissionStore = usePermissionStore();console.log("permissionStore", permissionStore);// 判断路由是否加载完成if (permissionStore.isRoutesLoaded) {if (to.matched.length === 0) {// 路由未匹配,跳转到404next("/404");} else {// console.log("to", to);// 动态设置页面标题const title = (to.params.title as string) || (to.query.title as string);if (title) {to.meta.title = title;}next();}} else {try {// 生成动态路由 -- 直接游览器里输入地址会走到这边const dynamicRoutes = await permissionStore.generateRoutes();// console.log("to", to.path);// console.log("permissionStore.routes Array", permissionStore.routes);// permissionStore.routes.forEach((route: RouteRecordRaw) => {// console.log("permissionStore.route", route.path);//// });// 在此处进行判断,要等 permissionStore.generateRoutes(); 执行完 permissionStore.routes 才有值const routeExists = permissionStore.routes.some((route: RouteRecordRaw) => {//console.log("permissionStore.route", route.path);//看用户可访问的所有 path 里面,是否有浏览器直接输入的 path ,如果包含,说明用户无权访问该菜单return route.path.includes(to.path);});if (!routeExists) {next("/401");}// console.log("dynamicRoutes", dynamicRoutes);// console.log("router", router);dynamicRoutes.forEach((route: RouteRecordRaw) => {//console.log("route", route);router.addRoute(route);});// console.log("router", router);// console.log("to", to);next({ ...to, replace: true });} catch (error) {console.error(error);// 路由加载失败,重置 token 并重定向到登录页await useUserStore().clearUserData();redirectToLogin(to, next);NProgress.done();}}}} else {// 未登录,判断是否在白名单中if (whiteList.includes(to.path)) {console.log("router", 5);next();} else {console.log("router", 6);// 不在白名单,重定向到登录页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().userInfo;// 超级管理员 拥有所有权限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));
}
console.log("to", to.path);
let found = false;
permissionStore.routes.forEach((route: RouteRecordRaw) => {console.log("permissionStore.route", route.path);if (route.path.includes(to.path)) {found = true;}
});if (!found) {next("/404");
}
用 some 优化后
console.log("to", to.path);
const routeExists = permissionStore.routes.some((route: RouteRecordRaw) => {console.log("permissionStore.route", route.path);return route.path.includes(to.path);
});if (!routeExists) {next("/404");
}
