核心想法:

登陆后获得用户角色,通过角色获得用户的权限,注入权限对应的路由。刷新页面,从localStorage用角色(更好的方式是通过token)再次获得所属权限,再次注入路由。在管理界面左端循环权限对应的路由菜单
localStorage存用户的信息(token),权限路由不会存。
所有的路由分为2种:
  • 公共路由:所有用户可以查看。
  • 权限路由:当前用户权限所属的路由。
实现控制的方式分两种:
  • 通过 vue-router addRoutes 方法注入路由实现控制
  • 通过 vue-router beforeEach 钩子限制路由跳转
一般来讲,需要采用第一种方式,addRoutes注入的方式,第二种每次判断,开销比较大,而且一次性拿不到角色对应的所有路由列表。这个列表需要再登陆后立即渲染在左边。

vue 权限管理-LMLPHP


权限的控制分为好几种:
  • 一级菜单的权限控制,
  • 二级菜单的权限控制,
  • 按钮级别的权限控制。
控制方式有2种:
  • 后端返回路由控制列表
  • 前后端约定路由控制列表
代码:一级菜单的权限控制,前后端约定的方式确定角色能访问的路由。
routers/index.js

 

import Vue from 'vue'
import Router from 'vue-router'
import loginRoute from './modules/login.js';
import homeRoute from './modules/home.js'
import productionRoute from './modules/production.js';
import store from '../stores/index.js'; Vue.use(Router) //不需要权限的路由
export const constantRoutes = [loginRoute];
//需要权限的路由
//这里只是导出。实际上添加到router里在在store的permission里
export const asyncRoutes = [
homeRoute,
productionRoute,
];
console.log(asyncRoutes);
const router = new Router({
mode: 'history',
base: process.env.BASE_URL,
routes: [
...constantRoutes,
]
})
router.beforeEach((to,from,next)=>{
let user = store.state.user.user;
let permissionRoutes= store.state.permission.permissionRoutes;
console.log(store.state);
console.log(user);
if(!user && to.path!=='/'){
next({
path:'/'
});
}else{
//刷新页面的情况
if(!permissionRoutes && user){
store.dispatch('generateRoutes',{
role:user.role
}) console.log(router);
console.log(to);
//这里写next没用
next({...to})
}else{
next();
} // next({...to, replace: true })
}
});
export default router;

  其中,productionRoute:

import Layout from '../../layouts/Index.vue'
const productionAdd = () => import('../../pages/production/Add.vue')
const productionList = () => import('../../pages/production/List.vue')
const productionTemplateComplete = () => import('../../pages/production/TemplateComplete.vue')
let routes = {
path: '/production',
component: Layout,
meta: {
title: '产品管理',
roles: [0, 1]
},
children: [
{
path: 'add',
component: productionAdd,
beforeEnter (to, from, next) {
console.log('router beforeEnter');
next();
},
meta: {
title: '产品新增'
}
},
{
path: 'list',
component: productionList,
meta: {
title: '产品列表'
}
},
{
path: 'templateComplete',
component: productionTemplateComplete,
meta: {
title: '产品新增完善'
}
}
]
} export default routes

  

stores/index.js
import Vue from 'vue'
import Vuex from 'vuex' import user from './modules/user.js'
import permission from './modules/permission.js' Vue.use(Vuex) export default new Vuex.Store({
modules: {
user,
permission,
}
})

  


stores/modules/user.js
const SET_USER = 'SET_USER' //登录成功
const CLEAR_USER = 'CLEAR_USER' //退出登录
import $ajax from '../../axios/index.js';
import store from '../index.js';
export default {
state: {
user:JSON.parse(localStorage.getItem('user')) || null
},
mutations: {
[SET_USER](state, user) {
state.user = user;
localStorage.setItem('user', JSON.stringify(user))
}, [CLEAR_USER](state) {
state.user = null;
localStorage.removeItem('user');
}
},
actions: {
login({commit}, param) {
console.log('action');
console.log(param);
return new Promise((resolve, reject) => {
//一期不做后台登陆,前端判断
// $ajax({
// url:api.login,
// data:{
// ...param
// }
// }).then(res=>{
// let user = res.data.data;
// commit(SET_USER, user);
// resolve();
// }).catch(res=>{
// reject();
// })
//前端验证用户名,密码
window.setTimeout(()=>{
if(param.username === 'huainanju' && param.password === 'huainanju123'){
let user = {
username:'管理员',
role:0
}
commit(SET_USER, user);
store.dispatch('generateRoutes',{
role:user.role
})
resolve();
}else{
reject();
}
},1000)
});
},
logout({commit}) {
commit(CLEAR_USER)
}
}
}

  


stores/modules/permisson.js
import {asyncRoutes} from '../../routers/index';
import router from '../../routers/index';
/**
* 递归过滤异步路由表,返回符合用户角色权限的路由表
* @param role
*/
function filterAsyncRoutes(role) {
const res = asyncRoutes.filter(route => {
return route.meta.roles.includes(role)
});
return res
} const permisssion = {
state:{
permissionRoutes:null
},
getter:{ },
mutations:{
SET_ROUTERS: (state, routes) => {
//添加路由
console.log('添加路由');
router.addRoutes(routes);
state.permissionRoutes = routes // 权限路由
},
},
actions:{
generateRoutes({ commit }, data) {
let {role} = data;
let routes = filterAsyncRoutes(role);
console.log(routes);
commit('SET_ROUTERS', routes)
}
}
} export default permisssion;

  

layouts/Left.vue
<template>
<el-aside style="min-height:100%;min-width:250px;" width="250px">
<el-menu :default-active="defaultActive"
background-color="#324157"
text-color="#bfcbd9"
active-text-color="#409EFF"
style="position:fixed;top:0;left:0;min-height: 100%;width:250px;z-index:100"
router>
<template v-for="(item,index) in permissionRoutes">
<!--一级菜单-->
<el-menu-item :index="item.path" v-if="item.children.length === 1 ">
<i class="el-icon-menu"></i>
<!-- <div>我是</div>-->
<span>{{item.meta.title}}</span>
</el-menu-item>
<!--多级菜单-->
<el-submenu :index="index+''" v-else>
<template slot="title">
<i class="el-icon-menu"></i>
<span>{{item.meta.title}}</span>
</template>
<template v-for="child in item.children">
<el-menu-item :index="item.path+'/'+child.path">{{child.meta.title}}</el-menu-item>
</template>
</el-submenu>
</template>
</el-menu>
</el-aside>
</template>
<script>
import {mapState} from 'vuex' export default {
data() {
return {
}
},
computed: {
...mapState({
'permissionRoutes':state=>state.permission.permissionRoutes
}),
defaultActive: function () {
if (this.$route.path.indexOf('/classInfo') >= 0) {
return 'classList'
}
return this.$route.path.replace('/org/', '');
}
},
created() {
window.setTimeout(()=>{
console.log(this.permissionRoutes);
},1000)
}
}
</script>

  


05-28 19:22