美文网首页
vue之按钮权限及优雅请求API

vue之按钮权限及优雅请求API

作者: Coder慌 | 来源:发表于2019-12-23 15:46 被阅读0次

    系统开发中按钮级权限控制也是非常重要的功能之一,可以严格控制不同角色用户所拥有的功能权限。

    自定义v-permission指令

    首先可以通过vue的自定义指令来控制按钮(div,link也阔以)等的显示与否以及是否禁用状态。具体可查看官方文档vue自定义指令

    /**
     * 定义vue permission指令
     *
     * el:指令所绑定的元素,可以用来直接操作 DOM 
     * binding:一个对象,包含以下属性:
     *     name:指令名,不包括 v- 前缀。
     *     value:指令的绑定值,例如:v-my-directive="1 + 1" 中,绑定值为 2。
     *     oldValue:指令绑定的前一个值,仅在 update 和 componentUpdated 钩子 
     *           中可用。无论值是否改变都可用。
     *    expression:字符串形式的指令表达式。例如 v-my-directive="1 + 1" 中,表达式为 "1 + 1"。
     */
    Vue.directive('permission', function (el, binding) {
      // 检查是否有该code代表的权限or该code是否为禁用状态,并将对应的dom进行相应的控制(没有则隐藏,禁用则置灰不可点击)
      // 前端可在登录后将拥有的菜单以及权限的树结构存于sessionStorage,也可每次进入页面后单独请求api判断是否存在等。
      Permission.checkCodeAndSetDom(binding.value, el);
    })
    
    1. 在功能模块定义各自的permission.js文件用于设置需要控制的权限的code,uri,请求方法等。
    const code = {
      // 菜单列表页面相关
      menu: {  
          // 保存资源权限
          save: Permission.code("resource:save").uri("/sys/resources").method(method.POST),
      }
    }
    
    export default code;
    
    1. 在vue页面中对需要控制的按钮等使用v-permission指令,并可对权限相关联的uri进行请求,并返回结果
    // 对要限制的按钮进行控制
    <el-button v-permission="permission.save.code" 
    type="primary" icon="el-icon-plus"  @click="addResource(false)">添加</el-button>
    
    // 以下是script区
    // 导入permission.js文件
    import permissions from '../permissions.js'
    
    export default {
      data() {
        // 设置save权限
        savePermission: permissions.menu.save
      },
      methods: {
        // 在method中定义的按钮click事件方法
        async addResource() {
           // 该方法会用在permission.js文件中指定该权限的请求uri和请发方法发送请求,并获取响应结果
          let res = await this.savePermission.requset(this.form);
          ....
        }
      }
    }
    
    Permission.js文件之Permission类

    以下为上述功能所需要依赖的Permission类

    import request from './request'
    import Config from './config'
    
    /**
     * show: 菜单按钮是否显示
     * disabled: 菜单功能是否被禁用
     */
    class PermissionInfo {
      constructor(show, disabled) {
        this.show = show;
        this.disabled = disabled;
      }
    }
    
    /**
     * 可用于各模块定义各自权限对象
     */
    class Permission {
      constructor(code) {
        this.code = code;
      }
    
      /**
       * 权限对应的uri
       * @param {String} uri 请求uri
       */
      uri(uri) {
        this.uri = uri;
        return this;
      }
    
      /**
       * uri的请求方法(方法枚举)
       * @param {Number} method 请求方法
       */
      method(method) {
        this.method = method;
        return this;
      }
      
      /**
       * 获取权限的完整url
       */
      getUrl() {
        return request.getApiUrl(this.uri);
      }
    
      /**
       * 操作该权限,即请求对应的uri
       * @param {Object} param 请求该权限的参数
       */
      request(param) {
        return request.send(this, param);
      }
    
    
      /**    静态方法     **/
    
      /**
       * 静态工厂,设置code,并返回Permission对象
       * @param {String} code 权限code(权限标识符)Permission对象必有的属性
       */
      static code(code) {
        return new Permission(code);
      }
    
      /**
       * 登录成功保存对应的token以及菜单按钮列表
       */
      static savePermission(tokenMenuAndPermission) {
        //保存token
        Permission.saveToken(tokenMenuAndPermission.token);
        //保存menus
        sessionStorage.setItem(Config.name.resourcesKey, JSON.stringify(tokenMenuAndPermission.resources));
      }
    
      /**
       * 获取token
       */
      static getToken() {
        return sessionStorage.getItem(Config.name.tokenKey);
      }
    
      /**
       * 保存token
       * @param {Object} token token
       */
      static saveToken(token) {
        sessionStorage.setItem(Config.name.tokenKey, token);
      }
    
      /**
       * 从sessionStorage所有permissions获取指定permission对象的PermissionInfo
       */
      static getPermission(code) {
        // 超级管理员通行
        // if (JSON.parse(sessionStorage.getItem(Config.name.adminKey)).username == 'admin') {
        //   return new PermissionInfo(true, false);
        // }
        let menus = JSON.parse(sessionStorage.getItem(Config.name.resourcesKey));
        for (let menu of menus) {
          let leafs = Permission.getLeafs(menu);
          // 获取菜单的所有叶子节点
          for (let p of leafs) {
            // 如果是菜单类型,则跳过
            if (p.type === 1) {
              continue;
            }
    
            if (p.code === code) {
              // 如果是禁用状态,则禁止按钮点击
              if (p.status === 0) {
                return new PermissionInfo(true, true);
              }
              return new PermissionInfo(true, false);
            }
          }
        }
    
        return new PermissionInfo(false, true);
      }
    
      /**
       * 获取菜单的所有叶子节点
       * @param {Object} menu 根菜单
       */
      static getLeafs(menu) {
        let leafs = [];
        Permission.fillLeafs(menu, leafs);
        return leafs;
      }
    
      /**
       * 将所有叶子节点填充
       * @param {Object} meun  根菜单
       * @param {Object} leafs 需要填充的叶子节点
       */
      static fillLeafs(menu, leafs) {
        let children = menu.children;
        if (!children) {
          leafs.push(menu);
          return;
        }
        children.forEach(m => {
          Permission.fillLeafs(m, leafs);
        })
      }
    
      /**
       * 检查权限code并设定对应dom的属性
       * @param code 权限码
       * @param elDom  dom元素
       */
      static checkCodeAndSetDom(code, elDom) {
        // 根据权限code获取对应权限信息
        let permission = Permission.getPermission(code);
        // 如果没有显示权限,则隐藏该元素
        if (!permission.show) {
          elDom.style.display = 'none';
        }
        // 如果该权限被暂用,则禁止该btn
        if (permission.disabled) {
          // 将按钮置为禁用
          elDom.setAttribute('disabled', 'disabled');
          // element-ui需要添加该类样式
          elDom.className = elDom.className + ' ' + 'is-disabled';
        }
      }
    }
    
    export default Permission
    
    

    到此为止前端的按钮,link, div等的权限控制就差不多了。再提一点的就是权限code就是与指定资源操作相关联的一个标识符。简单操作页面及详情页面如下:

    权限code关联页面

    当然前端权限是控制了,但是后端也需要对其进行相对应的控制才可以真正实现控制,具体的后端权限控制方案or完整的前端控制案例,可查看 https://gitee.com/objs/mayfly 项目中有完整的使用案例。

    相关文章

      网友评论

          本文标题:vue之按钮权限及优雅请求API

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