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:'',不起作用?
 * 三级子菜单要在顶部展示?
 *
 *
 *
 */

 

posted @ 2020-07-06 10:25  haha-uu  阅读(569)  评论(0编辑  收藏  举报