这是最后一篇,用户权限模块。
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
简单的权限就可以了,欢迎大佬交流意见
附上权限截图