• vue【路由导航守卫控制访问主页前先登录】--实现用户登录及token验证----以及使用NProgress


    参考:

    实现用户登录及token验证:

    https://blog.csdn.net/qzcrystal/article/details/106884810

    https://www.cnblogs.com/tt-ff/p/11736463.html

    NProgress使用参考:

    https://blog.csdn.net/wn1245343496/article/details/82151273

    官网:http://ricostacruz.com/nprogress/
    github:https://github.com/rstacruz/nprogress

     主要用到导航守卫:

    官网:https://router.vuejs.org/zh/guide/advanced/navigation-guards.html#%E5%85%A8%E5%B1%80%E5%89%8D%E7%BD%AE%E5%AE%88%E5%8D%AB

    与main.js同级的 permission.js:

    import router from './router';
    import store from './store';
    import NProgress from 'nprogress';
    import 'nprogress/nprogress.css';
    import { Message } from 'element-ui';
    import { getToken } from '@/utils/auth'; // 验权从cookie中获取
    import { getUserInfo } from '@/api/user';
    import { setTitle } from '@/utils/mUtils'; // 设置浏览器头部标题
    
    function hasPermission(roles, permissionRoles) {
      if (roles.indexOf('admin') >= 0) {
        return true;
      }
      if (!permissionRoles) {
        return true;
      }
      return roles.some(role => permissionRoles.indexOf(role) >= 0);
    }
    
    const whiteList = ['/login']; // 不重定向白名单
    
    router.beforeEach((to, from, next) => {
      NProgress.start();
      // 设置头部浏览器标题
      const browserHeaderTitle = to.meta.title;
      store.commit('SET_BROWSERHEADERTITLE', {
        browserHeaderTitle: browserHeaderTitle
      });
      // 点击登录时拿到了token,并存入了了cookie,保证页面刷新时,始终可以拿到token
      if (getToken('Token')) {
        if (to.path === '/login') {
          next();
          NProgress.done();
        } else {
          // 用户登录成功之后,每次点击路由都进行角色的判断
          if (store.getters.roles.length === 0) {
            const token = getToken('Token');
            getUserInfo({ token: token })
              .then(res => {
                console.log(res);
                const userList = res.data.userList;
                store.commit('SET_ROLES', userList.roles);
                store.commit('SET_NAME', userList.name);
                store.commit('SET_AVATAR', userList.avatar);
                store
                  .dispatch('GenerateRoutes', { roles: userList.roles })
                  .then(() => {
                    // 根据roles权限生成可访问的路由表
                    router.addRoutes(store.getters.addRouters); // 动态添加可访问权限路由表
                    next({ ...to, replace: true }); // hack方法,确保addRoutes已经完成
                  });
              })
              .catch(err => {
                store.dispatch('LogOut').then(() => {
                  Message.error(err || 'V;erification failed, please login again');
                  next({ path: '/login' });
                });
              });
          } else {
            // 没有动态改编权限的需求可直接next() 删除下方权限判断
            if (hasPermission(store.getters.roles, to.meta.roles)) {
              next();
            } else {
              next({ path: '/401', replace: true, query: { noGoBack: true } });
            }
          }
        }
      } else {
        if (whiteList.indexOf(to.path) !== -1) {
          // 点击退出时,会定位到这里
          next();
        } else {
          next('/login');
          NProgress.done();
        }
      }
    });
    
    router.afterEach(() => {
      NProgress.done();
      setTimeout(() => {
        const browserHeaderTitle = store.getters.browserHeaderTitle;
        setTitle(browserHeaderTitle);
      }, 0);
    });

    main.js:

    import '@/permission.js';

    路由:router:index.js

    import Vue from "vue";
    import Router from "vue-router";
    import { Layout, Content } from "../layout"; // 页面整体布局
    import { topRouterMap } from "./topRouter";
    
    process.env.NODE_ENV === "development" ? Vue.use(Router) : null;
    
    function filterTopRouterMap(name) {
      let router = topRouterMap.find((item) => {
        return item.parentName === name;
      });
      return router.data; // arr
    }
    
    /**
     * 1、roles:后台返回的权限结构;
     *
     */
    //手动跳转的页面白名单
    const whiteList = ["/"];
    /**
     * path:''与path:'*'的区别:
     * 1、path:'*', 会匹配所有路径
     * 2、path:'',也是会匹配到路由
     *
     */
    //默认不需要权限的页面
    export const constantRouterMap = [
      {
        path: "",
        component: Layout,
        redirect: "/index/index",
        hidden: true,
      },
      {
        path: "/login",
        name: "login",
        component: () => import("@/page/login"),
        hidden: true,
      },
      {
        path: "/404",
        component: () => import("@/page/errorPage/404"),
        hidden: true,
      },
      {
        path: "/401",
        component: () => import("@/page/errorPage/401"),
        hidden: true,
      },
      {
        path: "/index",
        name: "index",
        component: Layout,
        meta: {
          title: "首页",
          icon: "icondashboard",
        },
        noDropdown: true,
        children: [
          {
            path: "index",
            meta: {
              title: "首页",
              icon: "icondashboard",
              routerType: "leftmenu",
            },
            component: () => import("@/page/index/index"),
          },
        ],
      },
    ];
    
    //注册路由
    export default new Router({
      mode: "history", // 默认为'hash'模式
      base: "/permission/", // 添加跟目录,对应服务器部署子目录
      routes: constantRouterMap,
    });
    
    //异步路由(需要权限的页面)
    export const asyncRouterMap = [
      {
        path: "/userManager",
        name: "userManage",
        component: Layout,
        meta: {
          title: "用户管理",
          icon: "iconuser",
        },
        noDropdown: true,
        children: [
          {
            path: "userList",
            meta: {
              title: "用户管理",
              icon: "iconuser",
              routerType: "leftMenu",
            },
            component: () => import("@/page/userList/userList"),
          },
        ],
      },
      {
        path: "/share",
        name: "share",
        component: Layout,
        meta: {
          title: "分享功能",
          icon: "iconshare",
        },
        noDropdown: true,
        children: [
          {
            path: "share",
            meta: {
              title: "分享功能",
              icon: "iconshare",
              routerType: "leftMenu",
            },
            component: () => import("@/page/share"),
          },
        ],
      },
      {
        path: "/infoManage",
        name: "infoManage",
        meta: {
          title: "信息管理",
          icon: "iconinfo",
        },
        component: Layout,
        children: [
          {
            path: "infoShow",
            name: "infoShow",
            meta: {
              title: "个人信息",
              icon: "iconinfo",
              routerType: "leftMenu",
              titleList: [
                { path: "infoShow1", title: "个人信息子菜单1" },
                { path: "infoShow2", title: "个人信息子菜单2" },
                { path: "infoShow3", title: "个人信息子菜单3" },
                { path: "infoShow4", title: "个人信息子菜单4" },
                { path: "infoShow5", title: "个人信息子菜单5" },
              ],
            },
            component: Content,
            children: filterTopRouterMap("infoShow"),
          },
          {
            path: "infoModify",
            name: "infoModify",
            meta: {
              title: "修改信息",
              icon: "iconinfo",
              routerType: "leftmenu",
              titleList: [
                { path: "infoModify1", title: "修改信息子菜单1" },
                { path: "infoModify2", title: "修改信息子菜单2" },
                { path: "infoModify3", title: "修改信息子菜单3" },
              ],
            },
            component: Content,
            children: filterTopRouterMap("infoModify"),
          },
        ],
      },
      {
        path: "/fundManage",
        name: "fundManage",
        meta: {
          title: "资金管理",
          icon: "iconpay3",
        },
        component: Layout,
        children: [
          {
            path: "fundList",
            name: "fundList",
            meta: {
              title: "资金流水",
              routerType: "leftmenu",
            },
            component: () => import("@/page/fundList/fundList"),
          },
          {
            path: "chinaTabsList",
            name: "chinaTabsList",
            meta: {
              title: "区域投资",
              routerType: "leftmenu",
            },
            component: () => import("@/page/fundList/chinaTabsList"),
          },
        ],
      },
      {
        path: "/fundData",
        name: "fundData",
        meta: {
          title: "资金数据",
          icon: "iconecharts",
        },
        component: Layout,
        redirect: "/fundData/fundPosition",
        children: [
          {
            path: "fundPosition",
            name: "fundPosition",
            meta: {
              title: "投资分布",
            },
            component: () => import("@/page/fundData/fundPosition"),
          },
          {
            path: "typePosition",
            name: "typePosition",
            meta: {
              title: "项目分布",
            },
            component: () => import("@/page/fundData/typePosition"),
          },
          {
            path: "incomePayPosition",
            name: "incomePayPosition",
            meta: {
              title: "收支统计",
            },
            component: () => import("@/page/fundData/incomePayPosition"),
          },
        ],
      },
      {
        path: "/permission",
        name: "permission",
        meta: {
          title: "权限设置",
          icon: "iconpermission",
          roles: ["admin", "editor"], // you can set roles in root nav
        },
        component: Layout,
        redirect: "/permission/page",
        children: [
          {
            path: "page",
            name: "pagePer",
            meta: {
              title: "页面权限",
              roles: ["admin"], // or you can only set roles in sub nav
            },
            component: () => import("@/page/permission/page"),
          },
          {
            path: "directive",
            name: "directivePer",
            meta: {
              title: "按钮权限",
              roles: ["editor"],
            },
            component: () => import("@/page/permission/directive"),
          },
        ],
      },
      {
        path: "/error",
        component: Layout,
        name: "errorPage",
        meta: {
          title: "错误页面",
          icon: "iconError",
        },
        children: [
          {
            path: "401",
            name: "page401",
            component: () => import("@/page/errorPage/401"),
            meta: {
              title: "401",
              noCache: true,
            },
          },
          {
            path: "404",
            name: "page404",
            component: () => import("@/page/errorPage/404"),
            meta: {
              title: "404",
              noCache: true,
            },
          },
        ],
      },
      { path: "*", redirect: "/404", hidden: true },
    ];
    
    /**
     *  路由设置要求:
     * 1、该路由有子菜单,可以设置多层嵌套路由children;如果没有子菜单,不需要设置children;通过item.children.length来判断路由的级数;
     * 2、登录成功后,定位到系统首页时,需要加载页面整体布局组件Layout并进行子路由定向加载;
     *
     * 按需加载路由组件的2种方法:
     * 1、component: () => import('@/page/login')
     * 2、component:resolve => require(['@/page/fundPosition'], resolve)
     *
     *
     *
     * 什么情况下,路由会定位到404页面?
     * 路由中redirect:'',不起作用?
     * 三级子菜单要在顶部展示?
     *
     *
     *
     */

  • 相关阅读:
    HDU3336 Count the string —— KMP next数组
    CodeForces
    51Nod 1627 瞬间移动 —— 组合数学
    51Nod 1158 全是1的最大子矩阵 —— 预处理 + 暴力枚举 or 单调栈
    51Nod 1225 余数之和 —— 分区枚举
    51Nod 1084 矩阵取数问题 V2 —— 最小费用最大流 or 多线程DP
    51Nod 机器人走方格 V3 —— 卡特兰数、Lucas定理
    51Nod XOR key —— 区间最大异或值 可持久化字典树
    HDU4825 Xor Sum —— Trie树
    51Nod 1515 明辨是非 —— 并查集 + 启发式合并
  • 原文地址:https://www.cnblogs.com/hahahakc/p/13253485.html
Copyright © 2020-2023  润新知