Vue+element搭建后台管理系统-六、实现权限管理

发布时间 2023-05-31 12:03:30作者: padding2020

在一些后台管理系统中,每个身份登录的权限不一样,以至于配置的菜单不一样。就我做过的小区物业管理系统而言,举个例子:业主登录网站只能看到社区服务中的投诉、维修以及查看公告。而管理员可以看到一些对本小区的基本操作,例如查看楼栋,查看业主,账单催缴等等…而超级管理员,可以看到所有界面,以及处理一些审核等等一系列。那么这个时候,我们没必要每个身份做一个系统,而是通过权限管理,对每种身份做配置;
————————————————
上述引用自: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)