/** src/access/index.ts */ import type { RouteLocationNormalizedGeneric } from "vue-router"; import router from "../router/router"; import type { LoginUesr } from "../store/types"; import { useUserStore } from "../store/user"; import ACCESS_ENUM from "./accessEnum"; import checkAccess from "./checkAccess"; import { getAccessToken } from "@/utils/token"; /** * 检查是否需要权限访问 * @param to 要访问的路由 * @param loginUser 当前登录用户 * @returns 如果需要权限访问且权限不足,返回重定向路径;否则返回空字符串 */ const redirectWithAccess = ( to: RouteLocationNormalizedGeneric, loginUser: LoginUesr ): string => { // 获取要访问的路由的权限 const needAccess: string = to.meta?.access ?? ACCESS_ENUM.NOT_LOGIN; //?? 运算符, 如果 to.meta?.access 为 undefined 或 null, // 则使用 ACCESS_ENUM.NOT_LOGIN 作为默认值 // 必须要登录才能访问的页面 if (needAccess !== ACCESS_ENUM.NOT_LOGIN) { // 如果说当前是未登录状态 那直接给他跳登录页面去 if ( !loginUser || !loginUser.userRole || loginUser.userRole === ACCESS_ENUM.NOT_LOGIN ) { return `/user/login?redirect=${to.fullPath}`; } // 权限不足,跳到无权限页面 if (!checkAccess(loginUser, needAccess)) { return "/noAuth"; } } return ""; }; // 这里接收异步函数,是因为下面要调用 userStore.getLoginUser() router.beforeEach(async (to, from, next) => { const userStore = useUserStore(); // 必须在守卫内部获取 store,确保 pinia 已安装 console.log("登陆用户信息", userStore.loginUser); let loginUser = userStore.loginUser; // 如果之前没登陆过,且有 token,尝试自动登录 // 没有 token 时不调用 API,避免未登录状态重复弹出错误提示 if (!loginUser || !loginUser.userRole || loginUser.userRole === ACCESS_ENUM.NOT_LOGIN) { const token = getAccessToken(); if (token) { await userStore.getLoginUser(); loginUser = userStore.loginUser; } } // 检查是否需要权限访问 const redirectUrl = redirectWithAccess(to, loginUser); if (redirectUrl) { next(redirectUrl); return; } // 未重定向时,继续导航 next(); });