在一些后台管理系统中,每个身份登录的权限不一样,以至于配置的菜单不一样。就我做过的小区物业管理系统而言,举个例子:业主登录网站只能看到社区服务中的投诉、维修以及查看公告。而管理员可以看到一些对本小区的基本操作,例如查看楼栋,查看业主,账单催缴等等…而超级管理员,可以看到所有界面,以及处理一些审核等等一系列。那么这个时候,我们没必要每个身份做一个系统,而是通过权限管理,对每种身份做配置;
————————————————
上述引用自:CSDN博主「一坨仙女」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq_51462774/article/details/117194323
权限管理的实现,其实是需要后台配合的,也可能会根据不同的需求有不同的实现方法。这章的内容主要说要一下我们公司之前后台管理系统的实现思路。
先给同学们描述一下具体的实现步骤:
1、用户登录
2、返回权限数据
3、根据权限数据写拦截器
一、约定权限数据
也就是首先要向后台所有的权限数据放到配置文件中,我这里做的是一个json数组,将每个路由名称映射到每个对应的权限上面,入下图所示:

由于具体代码就不贴了,可以根据截图在config文件夹下创建config.permission.js文件,然后把每个权限做成键值对,键名可以通过权限对应的内容来命名,这个键名后面在路由配置文件中是用到的。
二、用户登录缓存权限数据
当用户登录成功之后,拿到了对应的权限数据,这些权限数据有很多地方要用到,所以我们需要做成缓存,一般的话是通过Vuex来缓存,不过这个有个弊端,就是页面F5刷新之后会丢失。也可以缓存到浏览器的storeage,建议存本地缓存的应使用加密方式进行存储。
先实现个登录页面,在view/login/ 文件夹下新建 index.vue 文件,代码如下:
<template>
<div>
<h5>我是登录</h5>
<input type="text" v-model="username" placeholder="请输入用户名" />
<input type="password" v-model="password" placeholder="请输入密码" />
<button @click="login">登录</button>
</div>
</template>
<script>
export default {
data() {
return {
username: '',
password: '',
}
},
methods: {
login() {
this.$ajax('login/authApi/loginApi', {
usernmae: this.username,
passwrod: this.password
})
.then((res) => {
console.log('success', JSON.stringify(res))
})
.catch((rej) => {
console.log('fail', rej)
})
},
},
}
</script>
在App.vue中添加router-view组件:
<template>
<div id="app">
<router-view></router-view>
</div>
</template>
<script>
export default {
name: 'App',
components: {
},
methods: {
},
}
</script>
<style>
#app {
font-family: Avenir, Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
margin-top: 60px;
}
</style>
记得之前的代码是把路由跳转给关闭掉了,现在把它开放出来。更改router/index.js 文件
/** * 全局前置守卫 * @func beforeEach * @param {object} to 即将要进入的目标 路由对象 * @param {object} form 当前导航正要离开的路由 * @func next 进行管道中的下一个钩子 */ router.beforeEach(async (to, from, next) => { next() })
在router/routers.js 导入页面模块:
/** * 逐个导出模块 */ export const constantRoutes = [ { path: '/', redirect: '/home' }, { path: '/login', name: 'login', meta: { title: '登录', }, component: () => import('../views/login/index.vue') } ] export default [ ...constantRoutes, ]
在使用import导入页面模块,由于之前加的代码规范,是会报错的,我们在.eslintrc.js文件加入以下代码就可以了。
//import模块导入 parserOptions: { parser: 'babel-eslint', ecmaVersion: 10, sourceType: 'module', }, //import模块导入
最后在浏览器地址栏中后面加上/login,就能看到正常跳转了。

三、路由拦截器
权限控制就是判断你有哪些权限就可以访问哪些内容,这里我们来处理一下路由跳转的拦截。
先写一个简单的拦截器,就在utils文件夹下创建intercept文件夹和has-permission.js文件,实际就是一个工具类,根据传入的权限标识用来判断是否有权限。
import store from '@/store' import permissionsJson from '@/config/config.permission.js' /** * 判断用户是否拥有操作权限 * 根据传入的权限标识,查看是否存在用户权限标识集合 * @param perms */ export function hasPermission(perms) { let hasPermission = false let permissions = store.state.user.perms if (permissions.length == 0) { return false } for (let i = 0, len = permissions.length; i < len; i++) { if (permissions[i] === permissionsJson[perms]) { hasPermission = true break } } return hasPermission }
导入的store模块:
主要是取登录之后的权限数据,在store/modules/user.js加一下perms属性,
export default { namespaced: true, state: { userInfo: { id: null, account: '', realName: '', companies: '', sites: null, }, perms: [], //权限集合 }, mutations: { setUserInfo(state, param) { state.userInfo = param }, logout(state, param) { state.userInfo = param }, setPerms(state, perms){ // 用户权限标识集合 state.perms = perms } }, }
然后在登录页面中,在点击登录请求后,通this.$store.commit 缓存权限状态。这里插一句,this.$store.commit 是传值给vuex中的mutation改变state,这个是同步的方法,异步的是this.$store.dispatch。

登录页的代码如下:
<template>
<div>
<h5>我是登录</h5>
<input type="text" v-model="username" placeholder="请输入用户名" />
<input type="password" v-model="password" placeholder="请输入密码" />
<button @click="login">登录</button>
</div>
</template>
<script>
export default {
data() {
return {
username: '',
password: '',
}
},
methods: {
login() {
this.$ajax('login/authApi/loginApi', {
usernmae: this.username,
passwrod: this.password
})
.then(() => {
// console.log('success', JSON.stringify(res))
//模拟登录成功-状态缓存权限数据
this.$store.commit('user/setPerms', ['ruleList', 'scenicList'])
this.$router.push('home')
})
.catch((rej) => {
console.log('fail', rej)
})
},
},
}
</script>
上面api的接口的实现,是通过mockJS实现的,在前端开发过程中,对于mock数据的应用也是很重要的,太久没写博客了,忘记前面有没有细讲mockJS导入和使用的问题。如果没有的话,后面我会用一章节单独说这个内容。
在view文件夹中创建home页面

然后在路由中引入:router/routers.js

在权限管理的实现中,一般会分为两种实现,功能模块的控制显示和路由页面的控制跳转。
功能模块的控制显示。
在home页面中,查看获取到的权限列表;

上面是没有加权限控制显示的按钮,通过循环显示加上控制显示。

view/home/home.vue代码如下:
<template>
<div>
<h5>我是主页</h5>
<template v-for="item in menuList">
<el-button v-if="showBtn(item.persName)" :key="item.persName" :type="item.type">{{ item.name }}</el-button>
</template>
</div>
</template>
<script>
// import { mapState } from 'vuex'
import { hasPermission } from '../../utils/intercept/has-permission'
export default {
data() {
return {
menuList: [
{
type: 'primary',
name: '预约管理',
persName: 'preorder',
},
{
type: 'success',
name: '预约管理-预约记录',
persName: 'orderRecord',
},
{
type: 'info',
name: '预约管理-预约数据统计',
persName: 'orderStatistics',
},
{
type: 'warning',
name: '预约管理-规则设置',
persName: 'ruleSet',
},
{
type: 'danger',
name: '预约管理-规则查询',
persName: 'ruleList',
},
],
}
},
computed: {
// ...mapState({
// permissionList: (state) => state.user.perms,
// }),
permissionList() {
return this.$store.state.user.perms
},
},
created() {
// console.log('权限数据', this.$store.state.user.perms)
},
methods: {
showBtn(persName) {
console.log('打印权限', persName, hasPermission(persName))
return hasPermission(persName)
},
},
}
</script>
路由页面的控制跳转。
在路由跳转前置中做好控制,根据权限拦截,有权限通过,没权限就提示无权限。
在router/index.js中引入权限判断函数
import { hasPermission } from '../utils/intercept/has-permission'
修改路由跳转的前置函数:

在需要权限访问的页面中,注册路由的时候,在meta属性中加入persName属性,并添加具体的权限名;如订单页面:


当点击home页面的进行测试,可以看到,对没有权限的页面跳转进行了拦截;

即使知道路由名称,在地址栏中输入访问,也是不起效果的。

-----------------------======================================================================-----------------------
那么后台管理系统实现权限管理这个章节也算讲完了,内容有点多,希望大家好好消化一下,多动动手。
一直忘记把代码仓库发出来了,抱歉~
附上代码仓库:baskstate-sys: 前端修仙之路-后台管理系统框架-源码 配套学习:博客园-https://www.cnblogs.com/liao123/p/16168755.html 公众号:padding2020 (gitee.com)
