美文网首页
Vue实现后台管理的权限控制

Vue实现后台管理的权限控制

作者: Avery_G | 来源:发表于2021-07-14 16:11 被阅读0次

    一、前言

    在后台管理系统中,权限管理是很重要的一部分。一般权限管理分为两大类:
    1.接口访问权限控制
    2.页面访问权限控制
    菜单中的页面能否被访问
    页面中的按钮的权限
    今天先来看页面访问权限的控制

    二、页面访问权限的控制

    首先页面访问权限,可以分为两种:
    1.菜单栏展示全部菜单,没有权限的菜单点击时提示没有权限
    2.菜单栏只展示用户能访问的菜单,通过URL强行进入页面时,进入的是404
    比较倾向于第二种,一眼就让用户知道自己有哪些权限
    大致流程如下:
    登录的时候,获取权限菜单--------->存储到session---------->渲染
    1.肯定是要搭建vue项目,封装axios,就不说了,可以参考之前写的文章,Vue项目搭建
    2.我们可以先获取权限信息,再继续其他操作

    import { login, getAside } from '@/api/user-api'
    import { StatusCode } from '@/utils/constant'
    import { saveRouterInfoFromStorage, transfer } from '@/utils/utils'
    
    function sLogin (data) {
      return new Promise((resolve, reject) => {
        login(data).then(res => {
          if (res.code === StatusCode.Success) {
            // 登录成功,请求接口获取权限信息
            let routerInfo
            getAside().then(res => {
              if (res.data.code === StatusCode.Success) {
                routerInfo = res.data.data
                // 因为没有一个公共的共有的权限页面,所以需要保存下权限信息里的第一个页面,并在登录成功之后跳转到该页面
                sessionStorage.setItem('redirectPath', routerInfo[0].children[0].path)
                // 权限信息存储到session中,此处是把存储封方法装了一下
                saveRouterInfoFromStorage(routerInfo)
                this.$router.push(sessionStorage.getItem('redirectPath'))
                if (routerInfo.length === 0) {
                  // 如果该用户没有任何菜单权限,进入指定的提示页面
                  this.$router.push('/noPerssion')
                }
              }
            })
            return transfer(res.data)
          } else {
            // eslint-disable-next-line prefer-promise-reject-errors
            reject()
          }
        })
      })
    }
    
    export {
      sLogin
    }
    
    

    我这里把接口请求封装之后,做了个api层和service层,api层管理接口请求,service层管理数据,这样view层拿到数据直接渲染就可以,不需要在view里过多的去处理数据。
    这里其实就是调用登录接口,成功之后,调用获取权限信息的接口,把拿到的数据存储到session中。
    3.接下来要创建路由表了,需要把权限页面和登录页、404等页面分开

    import Vue from 'vue'
    import Router from 'vue-router'
    
    
    // 登录页以及404等不需要权限的页面
    import Index from '../views/index/index.vue'
    import Login from '../views/login/login.vue'
    // 权限页面,这里写所有需要权限的页面
    const Commodity = () => import('../views/commodityManagement/commodity')
    const ProductGroup = () => import('../views/commodityManagement/productGroup')
    const Live = () => import('../views/courseManage/live')
    
    Vue.use(Router)
    
    const constRouterMap = [
      {
        path: '/',
        name: 'index',
        component: Index
    
      },
    
      {
        path: '/login',
        name: 'Login',
        // route level code-splitting
        // this generates a separate chunk (about.[hash].js) for this route
        // which is lazy-loaded when the route is visited.
        component: Login
      }]
    
    const router = new Router({
      routes: constRouterMap
    })
    
    const routerMap = {
      Commodity,
      ProductGroup,
      Live
    }
    
    export {
      router,
      routerMap,
      constRouterMap
    }
    
    

    接下来,我们利用返回数据匹配之前写的路由表,将匹配结果和静态路由表结合,开成最终的实际路由表。在这里我写了个权限文件,在main.js中引入就可以了。
    以下是权限文件的代码 permission.js文件

    import { router, routerMap } from '../routers/router'
    import Layout from '@/layout'
    import { clearStorage, getRouterInfoFromStorage, getToken, saveRouterInfoFromStorage } from './utils'
    import { getAside } from '../api/system-api'
    import { StatusCode } from './constant'
    
    let routerInfo
    const whiteList = ['/login']
    
    router.beforeEach((to, from, next) => {
      // 判断是否登录
      if (getToken()) {
        if (to.path === '/login') {
          next({ path: '/' })
        } else {
          if (!routerInfo) {
            // 判断localStorage中是否有路由信息
            if (!getRouterInfoFromStorage()) {
              clearStorage()
              // 重新获取路由
              getAside().then(result => {
                console.log(result)
                if (result.data.code === StatusCode.Success) {
                  routerInfo = result.data.data
                  sessionStorage.setItem('redirectPath', routerInfo[0].children[0].path)
                  saveRouterInfoFromStorage(routerInfo)
                  addRouterAndNext(to, next)
                }
              })
            } else {
              routerInfo = getRouterInfoFromStorage()
              addRouterAndNext(to, next)
            }
          } else {
            next()
          }
        }
      } else {
        if (whiteList.indexOf(to.path) !== -1) {
          next()
        } else {
          next({ path: '/login' })
        }
      }
    })
    
    function addRouterAndNext (to, next) {
      routerInfo = filterRouter(routerInfo)
      router.addRoutes(routerInfo) // 添加动态路由
      next({ ...to, replace: true })
    }
    
    function filterRouter (routerInfo) {
      return routerInfo.filter(router => {
        if (router.component) {
          if (router.component === 'Layout') {
            router.component = Layout
          } else {
            router.component = routerMap[router.component]
          }
        }
        if (router.children && router.children.length) {
          router.children = filterRouter(router.children)
        }
        return true
      })
    }
    
    
    

    到此,页面的权限控制已经完成了。

    三、按钮权限控制

    按钮权限控制,我是写了个方法放到了utils.js中,直接上代码

    // Get all the buttons in this page by specified privileges
    function getButtonsOfPage (pageName) {
      const routeInfo = getRouterInfoFromStorage()
      let routeName = this.$route.name
      if (routeInfo) {
        if (pageName != null) {
          routeName = pageName
        }
        const currentPermission = getPermission(routeInfo, routeName)
        this.allButtons = getButtons(currentPermission.children)
      }
    }
    
    function getPermission (routerInfo, name) {
      let result
      for (let i = 0; i < routerInfo.length; i++) {
        if (routerInfo[i].name !== name && routerInfo[i].children) {
          result = getPermission(routerInfo[i].children, name)
        } else if (routerInfo[i].name === name) {
          result = routerInfo[i]
        }
        if (result != null) {
          return result
        }
      }
      return result
    }
    

    使用的时候,直接在要使用的页面先引入

    import { getButtonsOfPage } from '../../utils/utils‘
    data(){
        return{
            getButtonsOfPage
        }
    }
    

    然后在页面创建的时候,调用一下

    created () {
        this.getButtonsOfPage()
    },
    

    这里区分了是页面按钮还是表单按钮,可以根据buttonType去做个区分,页面渲染是一样的

     <fragment v-for="(item, index) in allButtons" :key="index">
            <el-button  v-if="item.subType === StatusButton.PageButton" @click="clickBtn">{{ item.name }}</el-button>
     </fragment>
    

    到此为止,页面和按钮的权限控制就完成了,下面附上后台返回的权限的数据格式
    meta里边定义了一个用于配置子页面时,当前菜单栏的高亮显示
    type:定义了时页面还是按钮
    subType:定义了是页面按钮还是表单按钮
    注意⚠️:path不能为null,如果没有path,随便写个字符串就可以,不然会报错
    此处定义了菜单栏的icon的名称,在渲染的时候,名称和路径对应过来就可以了

     "data": [
        {
          "id": 1,
          "parentId": 0,
          "path": "none",
          "meta": {
            "activePath": null
          },
          "name": "首页",
          "img": null,
          "imgHover": null,
          "component": "Layout",
          "type": 1,
          "subType": null,
          "sort": 1,
          "children": [
            {
              "id": 6,
              "parentId": 1,
              "path": "/partnerRelated/partner",
              "meta": {
                "activePath": "/partnerRelated/partner"
              },
              "name": "管理1",
              "img": "Partner",
              "imgHover": "PartnerHover",
              "component": "Partner",
              "type": 1,
              "subType": null,
              "sort": 6,
              "children": [
                {
                  "id": 25,
                  "parentId": 6,
                  "path": "none",
                  "meta": {
                    "activePath": null
                  },
                  "name": "详情",
                  "img": null,
                  "imgHover": null,
                  "component": null,
                  "type": 2,
                  "subType": 2,
                  "sort": 25,
                  "children": []
                },
                {
                  "id": 52,
                  "parentId": 6,
                  "path": "none",
                  "meta": {
                    "activePath": null
                  },
                  "name": "分配",
                  "img": null,
                  "imgHover": null,
                  "component": null,
                  "type": 2,
                  "subType": 2,
                  "sort": 52,
                  "children": []
                },
                {
                  "id": 53,
                  "parentId": 6,
                  "path": "none",
                  "meta": {
                    "activePath": null
                  },
                  "name": "导出",
                  "img": null,
                  "imgHover": null,
                  "component": null,
                  "type": 2,
                  "subType": 1,
                  "sort": 53,
                  "children": []
                }
              ]
            }
          ]
        }
      ],
    

    相关文章

      网友评论

          本文标题:Vue实现后台管理的权限控制

          本文链接:https://www.haomeiwen.com/subject/dwtpeltx.html