使用el-tree封装一个权限管理的小功能

使用el-tree封装一个权限管理的小功能

在这里插入图片描述
在这里插入图片描述
使用el-tree封装权限管理, 选中人员并且在右侧回显, 此组件用到了递归, 我只是将需要显示的数据进行了动态传递, 其他数据小伙伴可以自己封装

父组件

<template>
  <div>
      <authorityManage ref="authorityManage" :deptData="data"></authorityManage>

      <el-button class="saveBtn" @click="saveBtnClick()">保存</el-button>
      <el-button class="saveBtn" @click="editBtnClick()">回显数据(编辑 [曹丕] )</el-button>
  </div>
</template>

<script>
import authorityManage from './common/authorityManage.vue'
export default {
    name: "index",
    components: {
        authorityManage
    },
    data(){
        return {
            data: [
                {
                    id: 1,
                    name: '部门A',
                    parentId: 0,
                },
                {
                    id: 2,
                    parentId: 1,
                    name: '曹操',
                },
                {
                    id: 230,
                    parentId: 2,
                    name: '曹丕'
                },
                {
                    id: 231,
                    parentId: 2,
                    name: '曹植'
                },
                {
                    id: 3,
                    parentId: 1,
                    name: '司马懿'
                },
                {
                    id: 20,
                    name: '部门B',
                    parentId: 0,
                },
                {
                    id: 21,
                    name: '刘备',
                    parentId: 20,
                },
            ]
        }
    },
    methods: {
        saveBtnClick(){
            let data = this.$refs.authorityManage.submitData();
            console.log(data,'data')
        },

        editBtnClick(){
            let list = [
                {
                    authority: "1",
                    copyContent: "0",
                    download: "1",
                    id: 230,
                    name: "曹丕",
                    parentId:2,
                    printing: "0",
                }
            ]
            this.$refs.authorityManage.editData(list)
        },
    }
}
</script>

<style scoped>
.saveBtn{
    margin-top: 10px;
}
</style>

子组件

<template>
  <div>
      <div class="manage">
          <div class="personnel">
              <div class="header">未选</div>
              <div class="content">
                  <el-tree :props="defaultProps" ref="tree" :data="deptTreeData" node-key="id" show-checkbox @check="handleCheckChange">
                  </el-tree>
              </div>
          </div>

          <div class="authority">
              <div class="header">
                  <div>已选</div>
                  <div>
                      <el-dropdown>
                          <span class="el-dropdown-link">
                            {{ form.authority ? authorityMatter(form.authority) : '权限' }} <i class="el-icon-arrow-down el-icon--right"></i>
                          </span>
                          <el-dropdown-menu slot="dropdown">
                              <div class="dropdownBox" style="">
                                  <div class="dropdownBox_left">
                                      <div class="title">文档权限</div>
                                      <div class="permissionList">
                                          <el-radio v-model="form.authority" :label="item.value" v-for="(item,key) in authorityOptions" :key="key">
                                              {{ item.label }}</el-radio>
                                      </div>
                                  </div>

                                  <div class="dropdownBox_right">
                                      <div class="title">文档保护</div>
                                      <div class="permissionList">
                                          <div class="switch">
                                              <div class="title">下载</div>
                                              <div>
                                                  <el-switch active-value="1" inactive-value="0" v-model="form.download"></el-switch>
                                              </div>
                                          </div>
                                          <div class="switch">
                                              <div class="title">打印</div>
                                              <div>
                                                  <el-switch active-value="1" inactive-value="0" v-model="form.printing"></el-switch>
                                              </div>
                                          </div>
                                          <div class="switch">
                                              <div class="title">复制内容</div>
                                              <div>
                                                  <el-switch active-value="1" inactive-value="0" v-model="form.copyContent"></el-switch>
                                              </div>
                                          </div>
                                      </div>
                                  </div>

                              </div>
                          </el-dropdown-menu>

                      </el-dropdown>
                  </div>
              </div>

              <div class="content">
                  <el-tree :props="defaultProps" :data="selectDeptTreeData">
                  </el-tree>
              </div>
          </div>
      </div>
  </div>
</template>

<script>
export default {
    name: "authority",
    data(){
        return {
            form: {
                authority: '', // 权限
                download: '0', // 下载
                printing:'0', // 打印
                copyContent: '0', // 复制内容
            },
            // 权限options
            authorityOptions: [
                {
                    label: '仅查看',
                    value: '1'
                },
                {
                    label: '可编辑',
                    value: '2'
                },
                {
                    label: '可批注',
                    value: '3'
                },
                {
                    label: '可审核',
                    value: '4'
                },
                {
                    label: '禁止访问',
                    value: '5'
                },
            ],
            // 部门数据
            deptTreeData: [],
            defaultProps: {
                children: 'children',
                label: 'name',
            },
            // 已选择部门人员
            selectDeptData: [],
            // 已选择的部门人员树状数据
            selectDeptTreeData: [],
        }
    },
    props: {
        // 父组件传递的数据
        deptData: {
            default: null,
            type: Array,
        }
    },
    mounted() {
        this.initData()
    },
    methods: {

        /**接受父组件传递的数据, 并格式化为树状数据图形左侧使用 */
        initData(){
            this.deptTreeData = this.treeLikeData(this.deptData, 0,);
        },

        /**权限label格式化 */
        authorityMatter(){
            let filterList = this.authorityOptions.filter(item=>item.value == this.form.authority);
            if (filterList.length){
                return filterList[0].label;
            }
        },

        /**树状数据change事件 */
        handleCheckChange(data){
            // 1(if),判断是否有children, 如果有children, 需要将children里的数据取出,
            // 2(else),如果没有children, 需要通过pid查询出上一级, 直到pid为0

            if (data.children.length){
                let resoltData = this.recursionGetChildrenData(data,[]);
                this.mergeData(resoltData,);

                if (data.parentId !== 0){
                    let resoltData = this.adoptPidGetPreviousLevelData(data);
                    this.mergeData(resoltData);
                }
            } else {
                let resoltData = this.adoptPidGetPreviousLevelData(data);
                this.mergeData(resoltData);
            }

            this.selectDeptTreeData = this.treeLikeData(this.selectDeptData, 0,);
        },

        /**通过递归, 将children里的数据全部取出 */
        recursionGetChildrenData(data, recoverList){
            let dataObj = {
                id: data.id,
                name: data.name,
                parentId: data.parentId,
            }
            let list = recoverList;
            list.push(dataObj)
            let childData = function(data){
                data.forEach(item=>{
                    let obj = {
                        id: item.id,
                        name: item.name,
                        parentId: item.parentId,
                    }
                    list.push(obj);
                    if (item.children.length){
                        childData(item.children);
                    }
                })
                return list;
            }
            return childData(data.children, list)

        },

        /**通过pid获取上一级数据, 直到pid为0 */
        adoptPidGetPreviousLevelData(data){

            let deptData = this.deptData;
            let list = [];
            let dataObj = {
                id: data.id,
                name: data.name,
                parentId: data.parentId
            }
            list.push(dataObj);

            let getPreviouseData = function(data){
                let index = deptData.map(item=>item.id).indexOf(data.parentId);
                if (index !== -1){
                    let obj = {
                        id: deptData[index].id,
                        name: deptData[index].name,
                        parentId: deptData[index].parentId,
                    }
                    list.push(obj);
                    if (obj.pid !== 0){
                        getPreviouseData(obj);
                    }
                }
                return list;
            }
            return getPreviouseData(data);
        },

        /**将过滤出来的数据合并到selectDeptData里, 如果过滤出来的数据存在在selectDeptData,需要删除,如果不存在,则添加 */
        mergeData(data){
            if (data.length){
                data.forEach(item=>{
                    let index = this.selectDeptData.map(mapItem=>mapItem.id).indexOf(item.id);
                    let pidIndex = this.selectDeptData.map(mapItem=>mapItem.parentId).indexOf(item.id);
                    // 查询当前数据是否存在selectDeptData里, 如果存在,需要删除
                    if (index !== -1 && pidIndex == -1){
                        let treeNode = this.$refs.tree.getNode(item.id);
                        if (treeNode && !treeNode.checked){
                            this.selectDeptData.splice(index, 1);
                        }

                    } else {
                        // 查看当前数据是否在selectDeptData里, 如果不存在就添加, 防止重复添加
                        let index = this.selectDeptData.map(mapItem=>mapItem.id).indexOf(item.id);
                        if (index == -1){
                            this.selectDeptData.push(item);
                        }

                    }
                })
            }
        },

        /**提交数据 */
        submitData(){
            let data = this.getBottomData();
            return data;
        },

        /**查询已选择数据的最底层, 为其赋权限 */
        getBottomData(){
            let list = [];
            let _this = this;
            let child = function(data){
                data.forEach(item=>{
                    if (item.children.length){
                        child(item.children)
                    } else {
                        let obj = {
                            id: item.id,
                            name: item.name,
                            parentId: item.parentId,
                            authority: _this.form.authority, // 权限
                            download: _this.form.download, // 下载
                            printing: _this.form.printing, // 打印
                            copyContent: _this.form.copyContent, // 复制内容
                        }
                        list.push(obj);
                    }
                })
                return list;
            }
            return child(this.selectDeptTreeData)
        },

        /**编辑回显数据 */
        editData(data){
            let idList = [];
            if (data.length){
                data.forEach(item=>{
                    idList.push(item.id);
                    this.form.authority = item.authority;
                    this.form.download = item.download;
                    this.form.printing = item.printing;
                    this.form.copyContent = item.copyContent;
                    let resoltData = this.adoptPidGetPreviousLevelData(item);
                    this.mergeData(resoltData);
                })
                this.selectDeptTreeData = this.treeLikeData(this.selectDeptData, 0,);
            }
            this.setCheckedKeys(idList)
        },

        /**通过key设置选中数据 */
        setCheckedKeys(idList){
            this.$refs.tree.setCheckedKeys(idList);
        },

        /**格式化数据, 将数据格式化为树状数据 */
        treeLikeData (list, parentID, parentIdName) {
            let parentName = parentIdName ? parentIdName : 'parentId';
            //定义一个用于递归查找子元素的函数
            var child = function (pareID) {
                //先定义一个数组,用于存储所查到的子元素
                var childs = [];
                //循环数组
                for (let i = 0; i < list.length; i++) {
                    //如果数组其中一项的parentId等于传入的,说明这一项是传入的子元素,把他push进数组,然后重复递归自己找该项的子元素
                    if (list[i][parentName] == pareID) {
                        list[i].children = child(list[i].id);
                        childs.push(list[i])
                    }
                }
                //最后将查到的所有子元素返回
                return childs;
            };
            return child(parentID)
        },

    }
}
</script>

<style scoped lang="scss">
.el-dropdown-menu{
    width: 300px;
    .dropdownBox{
        display: flex;
        padding: 10px;
        box-sizing: border-box;
        font-size: 14px;

        .dropdownBox_left{
            width: 100px;
            border-right: 1px solid #ccc;

            .permissionList{
                .el-radio{
                    margin-top: 10px;
                }
            }
        }
        .dropdownBox_right{
            flex: 1;
            padding: 0 10px;
            box-sizing: border-box;

            .permissionList{
                .switch{
                    display: flex;
                    align-items: center;
                    margin-top: 10px;
                    .title{
                        width: 80px;
                    }
                }
            }
        }
    }
}

.manage{
    width: 600px;
    height: 500px;
    border: 2px solid #ccc;
    display: flex;
    justify-content: space-between;

    .personnel{
        width: 50%;
        height: 100%;
        border-right: 1px solid #ccc;

        .header{
            height: 40px;
            display: flex;
            align-items: center;
            padding: 0 10px;
            box-sizing: border-box;
            background: #ddd;
        }

        .content{
            height: calc(100% - 40px);
            padding: 0 10px;
            box-sizing: border-box;
        }
    }
    .authority{
        width: 50%;
        height: 100%;

        .header{
            height: 40px;
            display: flex;
            align-items: center;
            justify-content: space-between;
            padding: 0 10px;
            box-sizing: border-box;
            background: #ddd;
        }
        .content{
            height: calc(100% - 40px);
        }
    }
}
</style>

以上是我处理的方式, 如果有更好的方式, 请兄弟们指教

  • 10
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
可以将el-select和el-tree封装一个自定义组件,例如:SelectableTree。 首先,在组件的template,可以使用el-select和el-tree的模板,并将它们放在一起。同时,在el-select添加一个v-model来绑定选的值。 ```html <template> <div class="selectable-tree"> <el-select v-model="selectedNode" placeholder="请选择" @change="handleSelectionChange"> <el-option v-for="node in nodes" :key="node.id" :label="node.label" :value="node"></el-option> </el-select> <el-tree :data="treeData" :props="treeProps" @node-click="handleNodeClick"></el-tree> </div> </template> ``` 在script,需要定义props和data,同时还需要定义computed属性来将el-tree的data转换为适合el-select使用的数据。 ```javascript <script> export default { name: 'SelectableTree', props: { nodes: { type: Array, required: true }, treeProps: { type: Object, required: true } }, data() { return { selectedNode: null, treeData: [] } }, computed: { selectData() { return this.nodes.map(node => { return { label: node.label, value: node } }) } }, methods: { handleSelectionChange(value) { this.$refs.tree.setCurrentKey(value.id) }, handleNodeClick(data, node) { this.selectedNode = data } }, created() { this.treeData = this.nodes.map(node => { return { label: node.label, id: node.id, children: node.children || [] } }) } } </script> ``` 最后,在使用组件时,只需传入el-select和el-tree的props和数据即可。 ```html <template> <div> <selectable-tree :nodes="nodes" :tree-props="treeProps"></selectable-tree> </div> </template> <script> import SelectableTree from "./SelectableTree.vue"; export default { name: "App", components: { SelectableTree, }, data() { return { nodes: [ { id: 1, label: "一级 1", children: [ { id: 4, label: "二级 1-1", children: [ { id: 9, label: "三级 1-1-1", }, { id: 10, label: "三级 1-1-2", }, ], }, ], }, { id: 2, label: "一级 2", children: [ { id: 5, label: "二级 2-1", }, { id: 6, label: "二级 2-2", }, ], }, ], treeProps: { children: "children", label: "label", }, }; }, }; </script> ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值