vue-admin-template角色的权限判断
后端
实现获取用户角色的方法挺多的,比如:
- 可以单独写一个通过用户标识获取用户的roles接口
- 可以在用户登录成功后,返回用户的信息中加入用户的roles信息,我的项目目前用的是这个,所以会以这个写一下记录
实现:
// 设置角色
Set<String> rolesSet = roleService.getUserRolesSet(user.getUsername());
return Result.success(MapUtil.builder()
.put("id", user.getId())
.put("username", user.getUsername())
.put("avatar", user.getAvatar())
.put("email", user.getEmail())
.put("roles", rolesSet)
.map());
rolesSet打印:
System.out.println("角色集合======" + rolesSet);
角色集合======[admin]
或者
角色集合======[admin,editor]
前端
通过登录成功后,将用户的roles信息储存到store中,引入permission调取store中的roles信息,在组件中通过v-permission进行权限判断
实现:
在store的user.js中
定义user对象:
state: {
token: '',
name: '',
avatar: '',
userInfo: JSON.parse(sessionStorage.getItem('userInfo')),
// 该roles定义为数组
roles: [],
},
mutations: {
// set
SET_TOKEN: (state, token) => {
state.token = token
localStorage.setItem('token', token)
},
SET_USERINFO: (state, userInfo) => {
state.userInfo = userInfo
sessionStorage.setItem('userInfo', JSON.stringify(userInfo))
},
REMOVE_INFO: (state) => {
state.token = ''
state.userInfo = {}
state.avatar = ''
// 记得此处也要还原为数组,否则会产生文末的报错信息
state.roles = []
localStorage.setItem('token', '')
sessionStorage.setItem('userInfo', JSON.stringify(''))
},
SET_NAME: (state, name) => {
state.name = name
},
SET_AVATAR: (state, avatar) => {
state.avatar = avatar
},
SET_ROLES: (state, roles) => {
state.roles = roles
},
}
登录请求:
Login({ commit }, userInfo) {
const username = userInfo.username.trim()
return new Promise((resolve, reject) => {
login(username, userInfo.password).then(response => {
const jwt = response.headers['authorization']
const userInfo = response.data.data
commit('SET_TOKEN', jwt)
commit('SET_USERINFO', userInfo)
commit('SET_AVATAR', userInfo.avatar)
commit('SET_NAME', userInfo.username)
// 将获取到的角色数据赋值
commit('SET_ROLES', userInfo.roles)
resolve()
}).catch(error => {
reject(error)
})
})
},
引入下面链接的permission:
https://github.com/PanJiaChen/vue-element-admin/tree/master/src/directive/permission
使用:
v-permission="['admin','editor']"判断该按钮、模块是否可见
<el-button v-permission="['admin','editor']" size="mini" type="primary" @click="handleDownloadFile(scope.row.fileUrl,offStyle)">
下载
</el-button>
效果
检验前:
检验后:
这样,就做到了按钮的权限控制,模块类似。
但是,这时,我并不想把按钮隐藏起来,想把按钮变成“禁用”状态
如下:
这样,“下载”按钮就变成了禁用状态了,鼠标移上去会有禁用图标出现,无法点击。
实现:
(1)将https://github.com/PanJiaChen/vue-element-admin/tree/master/src/utils中的permission.js的工具类引入项目,要不就自己写一个检查store中的roles数据的方法
引入的permission.js:
import store from '@/store'
/**
* @param {Array} value
* @returns {Boolean}
* @example see @/views/permission/directive.vue
*/
export default function checkPermission(value) {
if (value && value instanceof Array && value.length > 0) {
const roles = store.getters && store.getters.roles
const permissionRoles = value
const hasPermission = roles.some(role => {
return permissionRoles.includes(role)
})
return hasPermission
} else {
console.error(`need roles! Like v-permission="['admin','editor']"`)
return false
}
}
可以看出来,调用需要传入一个value值,和v-permission="['admin']"中['admin']所需要的一样,上面引入的permission模块中的主要方法和utils中的permission.js类似
(2)引入完成后,在view界面中,引入utils下的permission.js用于检验权限
import checkPermission from '@/utils/permission' // 权限判断函数
methods: {
// 定义方法
checkPermission,
handleRolesChange() {
this.key++
}
}
vue中,使用disabled控制“禁用状态” ,disabled="true"为禁用,为false为不禁用
<el-button :disabled="!checkPermission(['admin'])" size="mini" type="primary" @click="handleDownloadFile(scope.row.fileUrl,offStyle)">
下载
</el-button>
到这,暂时实现了想要实现的基本功能
另外:在上文中,我将store中的roles直接赋值了,这样vue路由重载后会丢失,所以建议用sessionStore或localStore存储起来
报错(补充记录产生的问题,可不看)
下面的报错是在进入到使用v-permission判断的vue界面后,退出系统时闪过的异常,截图发现
报错内容为引入的permission中的roles.some is not a function,查看permission.js中,有代码:
const hasPermission = roles.some(role => {
return permissionRoles.includes(role)
})
可以定位到此处的报错。
(1)发现在上面“定义user对象”时,roles已经被定义为了数组
(2)刚开始时,在REMOVE_INFO中,我的roles还原直接是state.roles=' '
(3)在登录成功后,并且进入使用了v-permission的页面时,还未抛出该错误,但是当退出系统时就抛出了,于是猜想可能就是退出系统时,未将state.roles还原为空数组,所以报错。
解决:将REMOVE_INFO中的state.roles=' '修改为state.roles=[]
这样测试之后,系统正常。
总结
这里总结一下在项目中view页面用到的几种判断方法:
第一种:设置为不可见
// 使用v-permission="['admin','editor']"
<el-button v-permission="['admin','editor']" size="mini" type="primary" @click="handleDownloadFile">
下载
</el-button>
第二种:设置为不可见
// 使用v-if="checkPermission['admin']"
<el-tab-pane v-if="checkPermission(['admin'])" label="Admin">
Admin can see this
<el-tag class="permission-sourceCode" type="info">
v-if="checkPermission(['admin'])"
</el-tag>
</el-tab-pane>
第三种:设置为禁用状态
<el-button :disabled="!checkPermission(['admin','editor'])" size="mini" type="primary" @click="handleDownloadFile()">
按钮禁用方式
</el-button>
第四种:设置为禁用状态
该方法设置标签的style css
<template slot-scope="scope">
<span :style="!checkPermission(['admin','editor'])===true?spanForbid:spanNormal"
class="link-type" @click="handleUpdate(scope.row)">
span禁用方式
</span>
</template>
data() {
return {
spanForbid: {
// color: 'grey', 设置颜色为灰色
cursor: 'not-allowed'
// pointerEvents: 'none'为鼠标无法点击,cursor为出现禁用icon,两者无法同时显示
},
spanNormal: {}
}
}
—————————————————————
作为初学者,很多前端的知识都没有掌握,见谅,如有错误请指出,以期进步,感谢!。后续有新的学习,继续补充上来。