Diseño de permisos de botones (configurar la disposición del árbol en el elemento)

Usado en la pagina

 <el-button
              type="text"
              @click="edit(slotProps.date)"
              v-btn-key="['client:clue:update']"
              >编辑</el-button
            >
            <el-button
              type="text"
              @click="del(slotProps.date)"
              v-btn-key="['client:clue:delete']"
              >删除</el-button
            >
            <el-button
              type="text"
              @click="details(slotProps.date)"
              v-btn-key="['client:clue:detail']"
              >详情</el-button
            >
import Vue from 'vue';
// 检测是否有权限
// 使用Vue.directive声明自定义指令btn-key
export const buttonPermissions = Vue.directive('btn-key', {
  inserted(el, binding, vnode) {
    const { value } = binding
    const all_permission = "*:*:*";
    const permissions = JSON.parse(localStorage.getItem("btnlist"))


    if (value && value instanceof Array && value.length > 0) {
      const permissionFlag = value
      const hasPermissions = permissions.some(permission => {
        return all_permission === permission || permissionFlag.includes(permission)
      })

      console.log(hasPermissions, 123)


      if (!hasPermissions) {
        el.parentNode && el.parentNode.removeChild(el)
      }
    } else {
      throw new Error(`请设置操作权限标签值`)
    }
  }
})


El documento js anterior debe distribuirse en main.js
import {} desde './assets/js/hasPermi'

Establecer permisos relevantes

Para establecer permisos es necesario configurar un árbol. El siguiente es el diseño del árbol en elementos.

<template>
  <div class="box">
    <div class="card" style="padding: 10px; margin-bottom: 10px">
      <el-button type="primary" class="btn_color_1" size="small" @click="change"
        >绑定</el-button
      >
    </div>
    <el-card>
      <el-tree
        default-expand-all
        ref="tree"
        :check-strictly="true"
        @check="handleCheck"
        :data="routeList"
        show-checkbox
        node-key="id"
        :props="defaultProps"
        :render-content="renderContent"
        @node-expand="handleExpand"
        :default-checked-keys="selected"
      >
      </el-tree>
    </el-card>
  </div>
</template>
<script>
import {
      
       RolePermissions, RolesUserdetach } from "@/api/limits/index";

export default {
      
      
  data() {
      
      
    return {
      
      
      defaultProps: {
      
      
        children: "children",
        label: "name",
      },
      routeList: [],
      selected: [],
    };
  },
  mounted() {
      
      
    this.getRolePermissions(this.$route.params.user_id);
  },
  computed: {
      
      },
  methods: {
      
      
    // 渲染权限组
    getRolePermissions(id) {
      
      
      RolePermissions({
      
      
        user_id: id,
      })
        .then((res) => {
      
      
          if (res.status == 1) {
      
      
            this.routeList = res.data.menu_list;
            this.selected = res.data.selected;
            this.$nextTick(() => {
      
      
              this.changeCss();
            });
          } else {
      
      
            this.$message.warning(res.msg || "请求数据失败");
          }
        })
        .catch((err) => {
      
      
          console.log(err);
        });
    },

    change() {
      
      
      RolesUserdetach({
      
      
        user_id: this.$route.params.user_id,
        ids: this.selected,
      })
        .then((res) => {
      
      
          if (res.status == 1) {
      
      
            this.$router.go(-1);
          } else {
      
      
            this.$message.warning(res.msg || "请求数据失败");
          }
        })
        .catch((err) => {
      
      
          console.log(err);
        });
    },
    // 内容区渲染后执行 判断底层 赋 class
    handleExpand() {
      
      
      // 节点被展开时触发的事件
      // 因为该函数执行在renderContent函数之前,所以得加this.$nextTick()
      this.$nextTick(() => {
      
      
        this.changeCss();
      });
    },
    renderContent(h, {
       
        node, data, store }) {
      
      
      // 树节点的内容区的渲染 Function
      let classname = "";
      // 由于项目中有三级菜单也有四级级菜单,就要在此做出判断
      if (node.level === 4) {
      
      
        classname = "foo";
      }
      if (node.level === 3 && node.childNodes.length === 0) {
      
      
        classname = "foo";
      }
      return h(
        "p",
        {
      
      
          class: classname,
        },
        node.label
      );
    },
    changeCss() {
      
      
      //将子节点横向排列方法
      var levelName = document.getElementsByClassName("foo"); // levelname是上面的最底层节点的名字
      for (var i = 0; i < levelName.length; i++) {
      
      
        // cssFloat 兼容 ie6-8  styleFloat 兼容ie9及标准浏览器
        levelName[i].parentNode.style.cssFloat = "left"; // 最底层的节点,包括多选框和名字都让他左浮动
        levelName[i].parentNode.style.styleFloat = "left";
        levelName[i].parentNode.onmouseover = function () {
      
      
          this.style.backgroundColor = "#fff";
        };
      }
    },

    //  =======================
    handleCheck(data, {
       
        checkedKeys }) {
      
      
      if (checkedKeys.includes(data.id)) {
      
      
        // 选中
        let node = this.$refs.tree.getNode(data.id); // getNode(node-key)
        this.selectChildren(data, true); // 选中子节点
        this.parentNodesChange(node); // 选中父节点
      } else {
      
      
        this.selectChildren(data, false); // 取消子节点
      }
      this.selected = this.$refs.tree.getCheckedKeys();
    },
    selectChildren(data, checked) {
      
      
      data &&
        data.children &&
        data.children.map((item) => {
      
      
          this.$refs.tree.setChecked(item.id, checked);
          if (data.children) {
      
      
            this.selectChildren(item, checked);
          }
        });
    },
    // 父级递归
    parentNodesChange(node) {
      
      
      // console.log(node);
      if (node.parent) {
      
      
        for (let key in node) {
      
      
          if (key == "id") {
      
      
            // console.log(node[key]);
            this.$refs.tree.setChecked(node, true);
          }
        }
        if (node.parent && node.id !== 0) {
      
      
          this.parentNodesChange(node.parent);
        }
      }
    },
  },
};
</script>
<style scoped lang="less">
.box {
      
      
  padding: 15px;
}
// 树样式
/deep/ .el-tree-node.is-expanded > .el-tree-node__children {
      
      
  padding-left: 18px;
}
.el-tree {
      
      
  ::v-deep .el-tree-node {
      
      
    position: relative;
    padding-left: 16px; // 缩进量
  }
  ::v-deep .el-tree-node__children {
      
      
    padding-left: 16px; // 缩进量
  }
  // 竖线
  ::v-deep .el-tree-node::before {
      
      
    content: "";
    height: 100%;
    width: 1px;
    position: absolute;
    left: -3px;
    top: -26px;
    border-width: 1px;
    border-left: 1px dashed #ccc;
  }
  // 当前层最后⼀个节点的竖线⾼度固定
  ::v-deep .el-tree-node:last-child::before {
      
      
    height: 38px; // 可以⾃⼰调节到合适数值
  }
  // 去掉最顶层的虚线,放最下⾯样式才不会被上⾯的覆盖了
  & > ::v-deep .el-tree-node::after {
      
      
    border-top: none;
  }
  & > ::v-deep .el-tree-node::before {
      
      
    border-left: none;
  }
  // 展开关闭的icon
  ::v-deep .el-tree-node__expand-icon {
      
      
    font-size: 16px;
    // 叶⼦节点(⽆⼦节点)
    ::v-deep &.is-leaf {
      
      
      color: transparent;
      // display: none; // 也可以去掉
    }
  }
}
</style>

Mostrar resultados:

Insertar descripción de la imagen aquí

Supongo que te gusta

Origin blog.csdn.net/weixin_44694682/article/details/131313630
Recomendado
Clasificación