文章目录
前言
通过自定义指令控制按钮权限,菜单权限需要综合权限数据和本地路由信息进行过滤提示:以下是本篇文章正文内容,下面案例可供参考
一、菜单权限
获取权限数据,与本地路由对比筛选,将数据保存在vuex
1. 在store目录下建立permission.js
- 后台返回数据格式:
path
代表菜单路由path,与前端路由文件对应,作为唯一标识parentId
代表父级ID,0 代表一级菜单type
代表菜单级别,0 代表一级菜单,1 代表二级菜单,2 代表按钮
[{
"id": 1000,
"name": "生产订单",
"path": "/order-model",
"description": null,
"status": "enable",
"method": "GET",
"parentId": 0,
"type": 0,
}, {
"id": 1010,
"name": "销售订单",
"path": "/order-model/salesOrder",
"description": null,
"status": "enable",
"method": "GET",
"parentId": 1000,
"type": 1
}, {
"id": 1011,
"name": "新增",
"path": "sales.order:add",
"description": null,
"status": "enable",
"method": "POST",
"parentId": 1010,
"type": 2
}, {
"id": 1012,
"name": "编辑",
"path": "sales.order:update",
"description": null,
"status": "enable",
"method": "PUT",
"parentId": 1010,
"type": 2
}, {
"id": 1013,
"name": "详情",
"path": "sales.order:select",
"description": null,
"status": "enable",
"method": "GET",
"parentId": 1010,
"type": 2
}, {
"id": 1014,
"name": "删除",
"path": "sales.order:delete",
"description": null,
"status": "enable",
"method": "DELETE",
"parentId": 1010,
"type": 2
}, {
"id": 1018,
"name": "审核",
"path": "sales.order:review",
"description": null,
"status": "enable",
"method": "GET",
"parentId": 1010,
"type": 2
}, {
"id": 1019,
"name": "批准",
"path": "sales.order:approval",
"description": null,
"status": "enable",
"method": "GET",
"parentId": 1010,
"type": 2
}, {
"id": 1050,
"name": "辅助计划",
"path": "/order-model/auxiliary_plan",
"description": null,
"status": "enable",
"method": "GET",
"parentId": 1000,
"type": 1
}, {
"id": 1051,
"name": "导入",
"path": "auxiliary.plan:import",
"description": null,
"status": "enable",
"method": "POST",
"parentId": 1050,
"type": 2
}, {
"id": 1052,
"name": "导出",
"path": "auxiliary.plan:export",
"description": null,
"status": "enable",
"method": "GET",
"parentId": 1050,
"type": 2
},{
"id": 1056,
"name": "编辑",
"path": "auxiliary.plan:update",
"description": null,
"status": "enable",
"method": "GET",
"parentId": 1050,
"type": 2
}]
permission.js
import { asyncRoutes, constantRoutes } from '@/router'
import { getUserAuth } from '@/api/user'
/**
* @param {Array} list 后端权限数据
* @param {*} route 本地路由
*/
function hasPermission2(list, route) {
if (route.path) {
return list.some(el => route.path === el.path || route.hidden)
} else {
return true
}
}
/**
* 设置路由重定向
* @param {*} routes
* @returns
*/
export function loadRedirect(routes) {
const res = []
routes.forEach(el => {
if (!el.redirect) {
if (el.children) {
el.children = loadRedirect(el.children)
if (el.children.length !== 0) {
el.redirect = el.children[0].path
}
}
}
res.push(el)
})
return res
}
/**
* 根据权限列表匹配路由列表
* @param {*} routes
* @param {*} list
* @returns
*/
export function filterAsyncRoutes2(routes, list) {
const res = []
routes.forEach(route => {
const tmp = { ...route }
if (hasPermission2(list, tmp)) {
if (tmp.children) {
if (tmp.children.filter(el => !el.hidden).length !== 1) {
tmp.children = filterAsyncRoutes2(tmp.children, list)
}
}
res.push(tmp)
}
})
return res
}
const state = {
// 前台路由信息
routes: [],
// 按钮信息
authList: [],
// 前台路由
frontRoutes: []
}
const mutations = {
SET_AUTHLIST: (state, authList) => {
state.authList = authList
},
FRONT_ROUTES: (state, routes) => {
state.frontRoutes = routes
state.routes = routes
}
}
const actions = {
generateRoutes({ commit }, homeScreen = []) {
return new Promise((resolve, reject) => {
getUserAuth()
.then(result => {
const list = result.data.data
const authList = list.filter(el => el.path.indexOf('/') === -1)
// 后端返回数据 myRouter代表前台信息,myBackRouter代表后台信息
const myRouter = list.filter(
el => el.path.indexOf('/') !== -1
)
const accessedRoutes = loadRedirect(
filterAsyncRoutes2(asyncRoutes, myRouter)
)
commit('FRONT_ROUTES', accessedRoutes)
commit('SET_AUTHLIST', authList)
resolve(accessedRoutes)
})
.catch(err => {
reject(err)
})
})
}
}
export default {
namespaced: true,
state,
mutations,
actions
}
getters.js
const getters = {
token: state => state.user.token,
userInfo: state => state.user.userInfo,
roles: state => state.user.roles,
permission_routes: state => state.permission.routes,
front_routes: state => state.permission.frontRoutes,
authList: state => state.permission.authList
}
export default getters
index.js
import Vue from 'vue'
import Vuex from 'vuex'
import getters from './getters'
Vue.use(Vuex)
const modulesFiles = require.context('./modules', true, /\.js$/)
const modules = modulesFiles.keys().reduce((modules, modulePath) => {
const moduleName = modulePath.replace(/^\.\/(.*)\.\w+$/, '$1')
const value = modulesFiles(modulePath)
modules[moduleName] = value.default
return modules
}, {})
const store = new Vuex.Store({
modules,
getters
})
export default store
2.在main.js
文件同级新建permission.js
权限控制文件
- 在
router
的导航守卫beforeEach
中判断是否有token
,是否有权限列表
import router from './router'
import store from './store'
import { Message } from 'element-ui'
import NProgress from 'nprogress' // progress bar
import 'nprogress/nprogress.css' // progress bar style
import { getToken } from '@/utils/auth'
import getPageTitle from '@/utils/get-page-title'
NProgress.configure({ showSpinner: false }) // NProgress Configuration
const whiteList = ['/login', '/auth-redirect'] // no redirect whitelist
router.beforeEach(async (to, from, next) => {
NProgress.start()
document.title = getPageTitle(to.meta.title)
const hasToken = getToken()
if (hasToken) {
if (to.path === '/login') {
next({ path: '/' })
NProgress.done()
} else {
const hasRoles = store.getters.roles && store.getters.roles.length > 0
if (hasRoles) {
if (to.path === '/') {
const frontRoutes = store.getters.front_routes
const toPath =
frontRoutes.find(route => {
return (
route.path !== '/process/production/line' &&
route.path !== '/device/module/screen' &&
route.path !== '/current/process/oad/line/index' &&
route.path !== '/setting/screen/line'
)
})?.path || '/profile'
next(toPath)
} else {
next()
}
} else {
try {
//获取用户信息
await store.dispatch('user/getInfo')
//获取权限列表
const accessRoutes = await store.dispatch('permission/generateRoutes')
router.addRoutes(accessRoutes)
next({ ...to, replace: true })
} catch (error) {
//清除token
await store.dispatch('user/resetToken')
Message.error(error || 'Has Error')
next(`/login?redirect=${to.path}`)
NProgress.done()
}
}
}
} else {
if (whiteList.indexOf(to.path) !== -1) {
next()
} else {
next(`/login?redirect=${to.path}`)
NProgress.done()
}
}
})
router.afterEach(() => {
NProgress.done()
})
3.在main.js
文件中引用permission.js
import './permission'
二、按钮权限
参考:https://blog.csdn.net/Julia_0502/article/details/121822566
总结
- 菜单和按钮的权限配置页面及数据结构参考:https://blog.csdn.net/Julia_0502/article/details/117293713?spm=1001.2014.3001.5501
提示:
本文章只是记录权限控制菜单的方法,避免忘记,若有不足,欢迎指教