Vue3 前置路由鉴权案例

Vue\vue3_admin\src\permission.ts

// 路由鉴权,项目当中路由能不能被访问的设置
import router from "./router";
import setting from './setting'

// 任意路由切换实现进度条业务---> npm install --save nprogress   npm i --save-dev @types/nprogress
// 引入进度条
import nprogress from 'nprogress';

nprogress.configure({ showSpinner: false });

// 引入进度条样式
// import 'nprogress/nprogress.css'    // 灵活配置放入 全局样式配置:/src/styles/main.scss

// 获取用户相关的小仓库内部token数据,去判断用户是否登录成功
// 组件外部引入仓库需要引入pinia大仓库
import pinia from "./stores";
import useUserStore from '@/stores/modules/user'
import { GET_TOKEN, REMOVE_TOKEN } from '@/utils/token';
import type { tokenType } from "./api/user/type";
// import { storeToRefs } from "pinia";

// console.log(userStore.userInfo());
// // 重置路由
// const resetRouter = () => {
//     const userStore = useUserStore();
//     userStore.userAsyncRoute.forEach((route: any) => {
//         const { name } = route;
//         if (name && router.hasRoute(name)) router.removeRoute(name);
//     });
// };
// // 白名单
// const whiteList = ["login", '404'];
// console.log("路由守卫");
// 全局守卫:项目当中任意路由切换都会触发的钩子
//全局前置守卫
router.beforeEach(async (to: any, from: any, next: any) => {
    // 获取用户仓库
    const userStore = useUserStore(pinia)
    // 动态标题
    document.title = `${setting.title} - ${to.meta.title}`
    //to:你将要访问那个路由
    //from:你从来个路由而来
    //next:路由的放行函数
    nprogress.start()
    //获取token,去判断用户登录、还是未登录

    //获取用户名字
    // const username = userStore.username
    // console.log('路由前',userStore.userButtons, userStore.userAsyncRoute);
    // const { userAsyncRoute, userButtons } = storeToRefs(userStore);
    // console.log('token', GET_TOKEN(), 'username', GET_USERNAME());
    // console.log('token', userStore.token, 'username', userStore.username, 'userAsyncRoute', userStore.userAsyncRoute);
    const token: tokenType = {
        'token': GET_TOKEN() as string
    }
    //用户登录判断
    // if (localStorage.getItem("TOKEN")) {
    // console.log(token, token.token);
    if (typeof token.token != "object" && GET_TOKEN()) {
        // if (GET_TOKEN()) {
        // 已经登录成功,访问login,不能访问,指向首页
        // console.log("路由前验证token是否存在-存在");
        // console.log(GET_TOKEN());

        if (to.path == '/login') {
            next({ path: '/' })
        } else {
            //登录成功访问其余六个路由(登录排除)

            // 判断动态路由列表
            if (!userStore.userAsyncRoute.length || !userStore.userButtons.length) {
                // console.log('路由前验证路由表', router.getRoutes())
                // console.log('路由前验证路由表不存在!', router.getRoutes())
                try {
                    //获取用户信息
                    await userStore.userInfo()
                    // console.log("用户信息获取成功");
                    //放行
                    //万一:刷新的时候是异步路由,有可能获取到用户信息、异步路由还没有加载完毕,出现空白的效果
                    next({ ...to, replace: true })
                } catch (error) {
                    //token过期:获取不到用户信息了,或获取用户信息失败
                    //用户手动修改本地存储token
                    if (token) {
                        // 强制退出登录->用户相关的数据清空
                        // console.log('token过期');
                        await userStore.userLogout(token)
                        next({ path: '/login', query: { redirect: to.path } })
                    } else {
                        REMOVE_TOKEN()
                        next({ path: '/login', query: { redirect: to.path } })
                    }
                }
            } else {
                // 如果动态路由表存在则放行
                // console.log('路由前验证路由表存在!', router.getRoutes())
                next()
            }
        }
    } else {
        // console.log('token不存在!', to.path);
        //用户未登录判断
        if (to.path == '/login') {
            // console.log('跳转登录', to.path);
            next()
        } else {
            next({ path: '/login', query: { redirect: to.path } })
        }
    }
})

// // 2.判断是访问登陆页,有 Token 就在当前页面,没有 Token 重置路由到登陆页
// if (to.path.toLocaleLowerCase() === '/login') {
//     if (userStore.token) return next(from.fullPath);
//     resetRouter(); // 没有token 就重置路由
//     return next(); // 放行去登录页
// }

// // 3.判断访问页面是否在路由白名单地址(静态路由)中,如果存在直接放行
// if (whiteList.includes(to.path)) return next();

// // 4.判断是否有 Token,没有重定向到 login 页面
// if (userStore.token) return next({ path: '/login', replace: true });

// // 5.我们判断 vuex里面的设置的菜单列表是否为空,为空就重新获取列表添加路由
// if (!userStore.userAsyncRoute.length) {
//     await userStore.userInfo();
//     return next({ ...to, replace: true }); // 在已有的路由里自己匹配,replace: true 允许用户手贱点回退
// }

// // 8.正常访问页面
// next();

// });
//全局后置守卫
// router.afterEach((to: any, from: any) => {
router.afterEach(() => {
    // console.log(to,from);
    nprogress.done()
})

// 路由鉴权:路由组件访问权限的设置
// 全部路由组件:登录|404|任意路由|首页|数据大屏|权限管理(三个子路由)|商品管理(四个子路由)

// 用户未登录:可以访问login,其他六个路由不能访问并指定login
// 用户登录成功:不可以访问login并指定首页,可以访问其余路由