VUE2后台管理系统--权限管理
在项目接手时候想的还是根据花裤衩大佬的方法进行,后端返回异步路由进行加载。后来和后端一起确认并且查阅了其他项目做法后,采用的是所有路由在前端的异步路由中进行对比查找赋值,再通过动态路由添加。
·
1、做法
在项目接手时候想的还是根据花裤衩大佬的方法进行,后端返回异步路由进行加载。后来和后端一起确认并且查阅了其他项目做法后,采用的是所有路由在前端的异步路由中进行对比查找赋值,再通过动态路由添加。
2、思路
在用户进行登录时候,在路由守卫中调用后端接口返回该用户的相关权限列表,权限按钮、权限名称。再根据相关权限进行查找赋与addrouters
3、判断逻辑:
所有的都在路由守卫中进行,不存储在本地缓存中
3.1首先判断有无token,
如果不存在token 判断是不是在白名单中 如果在白名单中就放行,不然就跳转到登录页
3.2如果存在token,判断有无权限名称。
存在权限名 放行(这一步是在用户登录成功后的所有逻辑)
不存在权限名称,进行查询,调用vuex中的获取用户权限登录数据
查询到数据后,将权限名称、菜单列表、按钮列表存入vuex中
因为有一个管理员,如果他的权限名称为管理员,赋予本地的全部asyncRouters,不进行判断。
如果是其他权限名称。就将拿到的菜单列表与异步路由进行对比赋值,再添加到动态路由中
4、代码
// 导航守卫
router.beforeEach(async (to, from, next) => {
// document.title = getTitle(to.meta.title)
//如果去登录页进行跳转
if (to.path === '/login') {
// 如果login 页面没有重定向 手动重定向
if (!Object.keys(to.query).length) {
next({
path: '/login',
query: {
redirect: '/'
}
})
} else {
next()
}
} else {
//查询有没有token
if (store.getters.token) {
const roleName = store.getters.roleName
//这里判断是否有一级菜单导航
//判断有无权限名 有就放行
if (roleName) {
next()
} else {
// 没有权限名进行api调用,获取当前用户所拥有权限
try {
//try执行一些可能会抛出的错误
// 这是一个错误处理机制,用于捕获 JavaScript 代码中的错误并执行相应的处理程序,catch() 方法接受一个函数作为参数,该函数在发生错误时被调用并传递错误消息作为参数
// 将接口查询到的东西都存入vuex中
const data = await store.dispatch('user/_getInfo')
const menuList = store.getters.menuList
// 将获取到的菜单列表与本地的路由进行对比赛选
const addRoutes = await store.dispatch(
'permission/getAsyncRoutes',
menuList
)
router.addRoutes(addRoutes)
next({ ...to, replace: true })
} catch (error) {
// 抛出错误
if (error) {
Message.error(error)
}
}
}
} else if (whiteList.indexOf(to.path) !== -1) {
next()
} else {
next({
path: '/login',
query: {
redirect: to.fullPath
}
})
}
}
})
user的vuex
//获取后端接口得到用户登录权限数据
_getInfo({ commit }) {
return new Promise((resolve, reject) => {
getInfo()
.then(res => {
if (res.data) {
// 如果查询成功了跳转到主页
router.push('/home')
//结构权限名与菜单列表、按钮列表
const { roleName, menuList, permissionList } = res.data
//2将用户数据储存到vuex里面用于使用时取值
commit('SET_ROLE_NAME', roleName)
commit('SET_MENU_LIST', menuList)
commit('SET_PERMISSION_LIST', permissionList)
} else {
Message.error(res.msg)
}
resolve(res.data)
})
.catch(error => {
if (error.msg) {
Message.error(error.msg)
}
reject(error)
})
})
}
SET_ROLE_NAME(state, payload) {
state.roleName = payload
},
SET_INTRODUCE(state, payload) {
state.introduce = payload
},
SET_MENU_LIST(state, payload) {
state.menuList = payload
},
SET_PERMISSION_LIST(state, payload) {
state.permissionList = payload
}
最重要的路由处理因为后端返回的都是权限名称,所以用不到树状结构数据
import { asyncRoutes, currencyRoutes } from '@/router'
const state = {
routes: [],
addRoutes: []
}
const mutations = {
SET_ROUTES(state, payload) {
// 存入整合后的所有路由方便后续使用
state.routes = [...currencyRoutes, ...payload]
// 需要动态路由添加的路由
state.addRoutes = payload
}
}
//遍历asyncRoutes动态路由
function forSearchArr(route, routerName) {
let arrNew = []
for (let item of route) {
// 将其复制到一个新的对象中,从而实现对象的浅拷贝(只拷贝对象中的属性,而不包括属性所引用的对象)
let itemNew = { ...item }
// includes() 是 JavaScript 中字符串、数组和类数组对象内置的方法之一,用于判断一个对象中是否包含指定的元素。
// 对于字符串和数组对象,该方法会遍历整个对象,判断其中是否包含指定的元素,返回一个布尔值用于表示结果。
// 对于类数组对象,该方法会将其转换为数组对象后再进行比较
if (routerName.includes(itemNew.name)) {
// 如果存在子元素,进行递归调用
if (itemNew.children) {
itemNew.children = forSearchArr(itemNew.children, routerName)
}
arrNew.push(itemNew)
}
}
return arrNew
}
const actions = {
getAsyncRoutes({ commit, rootGetters }, menuList) {
return new Promise(resolve => {
let routes = []
// 管理员拥有所有的路由,菜单权限
if (rootGetters.roleName === '管理员') {
routes = asyncRoutes || ''
} else {
// 不是管理员,进行异步路由和获取的菜单列表进行对比重组
routes = forSearchArr(asyncRoutes, menuList)
}
commit('SET_ROUTES', routes)
resolve(routes)
})
}
}
export default {
namespaced: true,
state,
mutations,
actions
}
更多推荐
已为社区贡献3条内容
所有评论(0)