vue-admin-template基础模板使用(六)

这是最后一篇,用户权限模块。

1、在页面permission.js中导航守卫配置代码如下

if (hasToken) {
    // 有token登录
    if (to.path === '/login') {
      // 如果去登录页就跳转登录页
      next({ path: '/' })
      NProgress.done() // 因为被next拦截了,所以需要手动关闭掉
    } else {
      const hasGetUserInfo = store.getters.userName // 看之前是否获取过userInfo信息
      if (hasGetUserInfo) {
        next()
      } else {
        try {
          // get user info
          const { roles } = await store.dispatch('user/getInfo')
          // 获取权限的路由名称
          // console.log(roles.menus) // ['approvals', 'attendances', 'departments', 'employees', 'permission', 'salarys', 'setting']

          // 获取当前所有路由配置信息
          // console.log(router.options.routes)

          // 动态添加路由 router.addRoutes (注意: 动态添加的路由不是响应式的)

          // 拿到的roles.menus, 就是后台返回的访问权限信息, 根据这个信息, 动态的添加路由
          // 动态的添加路由 => addRoutes (注意: 动态添加的路由不是响应式的)
          const otherRoutes = await store.dispatch('permission/filterRoutes', roles.menus)
          // console.log(otherRoutes)
          // addRoutes 方法仅仅是帮你注入新的路由,并没有帮你剔除其它路由
          router.addRoutes([...otherRoutes, { path: '*', redirect: '/404', hidden: true }])

          // 路由是动态添加的, 为了保证进入到页面时, 路由权限已经是配置好的
          // 这里需要重新进一次页面
          next({
            ...to,
            replace: true // 避免重新进入, 出现重复页的历史记录
          })
          return
        } catch (error) {
          // remove token and go to login page to re-login
          await store.dispatch('user/resetToken')
          Message.error(error || 'Has Error')
          next(`/login?redirect=${to.path}`)
          NProgress.done()
        }
      }
    }
  } 

2、在store/modules下新建permission.js用于处理异步路由

// 此模块, 用于管理路由数组(可以控制访问权限)
import { constantRoutes, asyncRoutes } from '@/router'
const state = {
  // routes的初始值, 推荐给静态路由表
  routes: constantRoutes
}
const mutations = {
  // 将来必然是要根据menus权限, 动态新增动态路由的
  setRoutes(state, otherRoutes) {
    // outerRoutes就是经过筛选后, 需要追加的动态路由表
    state.routes = [...constantRoutes, ...otherRoutes]
  }
}
const actions = {
  // 这里筛选出需要添加的权限路由的代码, 推荐封装到模块中
  filterRoutes(context, menus) {
    // 可以基于 menus, 从asyncRoutes中筛选出需要动态添加的路由内容
    // menus: ['settings', 'permissions', 'approvals']
    // asyncRoutes: [ 路由模块对象1, 路由模块对象2, .. ]
    const otherRoutes = asyncRoutes.filter(item => {
      if (menus.includes(item.children[0].name)) {
        // 用户有这个权限的
        return true
      } else {
        return false
      }
    })
    context.commit('setRoutes', otherRoutes)
    // 过滤完成后, 需要return, 将来交给 addRoutes 去添加
    return otherRoutes
  }
}
const getters = {}

export default {
  namespaced: true,
  state,
  mutations,
  actions,
  getters
}

3、在store/index.js中引入

import permission from './modules/permission'

const store = new Vuex.Store({
  modules: {
    permission
  }
})

4、在store/getters.js中引入方便使用

routes: state => state.permission.routes

5、这样操作之后导航是没有展示出来对应得路由的。需要在Sidebar/index.vue中写

computed: {
    ...mapGetters([
      'sidebar',
      'routes'
    ])

6、处理刷新后404问题

注释掉router/index.js中静态路由表(constantRoutes)中的

// 如果前面的路由都没有匹配到, 那么就会被 * 匹配, 重定向到了 /404
  // { path: '*', redirect: '/404', hidden: true }

最后附上路由表

import Vue from 'vue'
import Router from 'vue-router'

Vue.use(Router)

/* Layout */
import Layout from '@/layout'

/**
 * Note: sub-menu only appear when route children.length >= 1
 * Detail see: https://panjiachen.github.io/vue-element-admin-site/guide/essentials/router-and-nav.html
 *
 * hidden: true                   if set true, item will not show in the sidebar(default is false)
 * alwaysShow: true               if set true, will always show the root menu
 *                                if not set alwaysShow, when item has more than one children route,
 *                                it will becomes nested mode, otherwise not show the root menu
 * redirect: noRedirect           if set noRedirect will no redirect in the breadcrumb
 * name:'router-name'             the name is used by <keep-alive> (must set!!!)
 * meta : {
    roles: ['admin','editor']    control the page roles (you can set multiple roles)
    title: 'title'               the name show in sidebar and breadcrumb (recommend set)
    icon: 'svg-name'/'el-icon-x' the icon show in the sidebar
    breadcrumb: false            if set false, the item will hidden in breadcrumb(default is true)
    activeMenu: '/example/list'  if set path, the sidebar will highlight the path you set
  }
 */

/**
 * constantRoutes
 * a base page that does not have permission requirements
 * all roles can be accessed
 */
// 静态路由表(一直能看到的路由)
export const constantRoutes = [
  {
    path: '/login',
    component: () => import('@/views/login/index'),
    hidden: true
  },

  {
    path: '/404',
    component: () => import('@/views/404'),
    hidden: true
  },

  // 首页
  {
    path: '/',
    component: Layout,
    redirect: '/dashboard',
    children: [{
      path: 'dashboard',
      name: 'Dashboard',
      component: () => import('@/views/dashboard/index'),
      meta: { title: '首页', icon: 'dashboard' }
    }]
  }
  // 如果前面的路由都没有匹配到, 那么就会被 * 匹配, 重定向到了 /404
  // { path: '*', redirect: '/404', hidden: true }
]

// 动态路由
export const asyncRoutes = [
  {
    path: '/approvals',
    component: Layout,
    children: [
      {
        path: 'approvals',
        name: 'approvals',
        component: () => import('@/views/approvals/index'),
        meta: { title: '审批', icon: 'tree-table' }
      }
    ]
  },
  {
    path: '/attendances',
    component: Layout,
    children: [
      {
        path: '',
        name: 'attendances',
        component: () => import('@/views/attendances/index'),
        meta: { title: '考勤', icon: 'skill' }
      }
    ]
  },
  {
    path: '/departments',
    component: Layout,
    children: [
      {
        path: '',
        name: 'departments',
        component: () => import('@/views/departments/index'),
        meta: { title: '组织架构', icon: 'tree' }
      }
    ]
  },
  {
    path: '/employees',
    component: Layout,
    children: [
      {
        path: '',
        name: 'employees',
        component: () => import('@/views/employees/index'),
        meta: { title: '员工', icon: 'people' }
      }
    ]
  },
  {
    path: '/permission',
    component: Layout,
    children: [
      {
        path: '',
        name: 'permission',
        component: () => import('@/views/permission/index'),
        meta: { title: '权限管理', icon: 'lock' }
      }
    ]
  },
  {
    path: '/salarys',
    component: Layout,
    children: [
      {
        path: '',
        name: 'salarys',
        component: () => import('@/views/salarys/index'),
        meta: { title: '工资', icon: 'money' }
      }
    ]
  },
  {
    path: '/setting',
    component: Layout,
    children: [
      {
        path: '',
        name: 'setting',
        component: () => import('@/views/setting/index'),
        meta: { title: '公司设置', icon: 'tree' }
      }
    ]
  },
  {
    path: '/social',
    component: Layout,
    children: [
      {
        path: '',
        name: 'social',
        component: () => import('@/views/social/index'),
        meta: { title: '社保', icon: 'table' }
      }
    ]
  }
]

const createRouter = () => new Router({
  // mode: 'history', // require service support
  scrollBehavior: () => ({ y: 0 }),
  // 现这样写,最后权限的时候再改
  routes: [
    ...constantRoutes
  ]
})

const router = createRouter()

// Detail see: https://github.com/vuejs/vue-router/issues/1234#issuecomment-357941465
export function resetRouter() {
  const newRouter = createRouter()
  router.matcher = newRouter.matcher // reset router
}

export default router

简单的权限就可以了,欢迎大佬交流意见

附上权限截图

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

shuleijia

您的鼓励是我最大的创作动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值