element vue2 动态添加 select+tree

难点在 1 添加一组一组的渲染 是往数组里push对象 循环的;但是要注意对象的结构! 因为这涉及到编辑完成后,表单提交时候的 校验! 是校验每一个select tree里边 是否勾选

2 是在后期做编辑回显的时候 保证后端返回的值 是渲染到 select中的tree当中! 并且是勾选着的
3 任意在一个select当中 移除的时候。
4 任意一个select当中 取消勾选后 显示是否正确

只在提交的时候校验!
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

父组件
<template>
    <el-dialog
        class="mpks-common-dialog mpks-search-strategy-resultintervene-dialog"
        width="810px"
        :title="innerTitle"
        :visible.sync="innerDialogVisible"
        :close-on-click-modal="false"
        :close-on-press-escape="false"
        @opened="open('form')"
        @close="close"
    >
        <el-form
            ref="form"
            :model="currentItem"
            label-width="104px"
            :rules="formRule"
        >
            <el-form-item label="知识库名称:" prop="name" class="cd">
                <el-col :span="20">
                    <el-input
                        v-model="currentItem.name"
                        placeholder="请输入知识库名称"
                        maxlength="20"
                        show-word-limit
                        clearable
                    >
                    </el-input>
                </el-col>
            </el-form-item>

            <el-form-item
                label=""
                v-for="(item, index) in currentItem.selects"
                :key="index"
                class="mpks-common-dialog-form-item-qa create-css"
            >
                    <div class="flex mtop margin-bottom">
                        <el-col >
                            <el-form-item
                                :prop="'selects.' + index + '.NodeVal'"
                                :rules="formRule.NodeVal"
                            >
                                <el-select
                                    v-model="item.NodeVal"
                                    placeholder="请选择知识树节点"
                                    multiple
                                    collapse-tags
                                    @change="nodeValChange(item, index)"
                                    @remove-tag="removeTag(item)"
                                >
                                    <el-option
                                        :value="seletedNodeIdsOptions"
                                        style="height: auto;"
                                    >
                                        <channel-tree
                                            :idx="index"
                                            ref="nodeTree"
                                            class="mpks-add-task-tree"
                                            :checkable="true"
                                            :check-strictly="false"
                                            :default-checked-keys="
                                                item.innerselectTreeIds
                                            "
                                            :get-permission-node="true"
                                            @node-check="selectNodeId"
                                        />
                                    </el-option>
                                </el-select>
                            </el-form-item>
                        </el-col>
                        <el-col>
                            <el-form-item
                                :prop="'selects.' + index + '.picVal'"
                                :rules="formRule.picVal"
                            >
                                <el-select
                                    v-model="item.picVal"
                                    placeholder="请选择图谱类目"
                                    multiple
                                    collapse-tags
                                    @change="picValChange(item, index)"
                                    @remove-tag="removeTagPic(item)"
                                >
                                    <el-option
                                        :value="seletedPicIdsOptions"
                                        style="height: auto;"
                                    >
                                        <channel-tree-pic
                                            :idx="index"
                                            ref="nodeTreePic"
                                            class="mpks-add-task-tree"
                                            :checkable="true"
                                            :check-strictly="false"
                                            :default-checked-keys="
                                                item.innerselectTreePicIds
                                            "
                                            :get-permission-node="true"
                                            @node-check="selectPicId"
                                        />
                                    </el-option>
                                </el-select>
                            </el-form-item>
                        </el-col>
                        <el-col>
                            <el-form-item
                                :prop="'selects.' + index + '.categoryVal'"
                                :rules="formRule.categoryVal"
                            >
                                <el-select
                                    v-model="item.categoryVal"
                                    placeholder="请选择全文索引类目"
                                    multiple
                                    collapse-tags
                                    @change="classChange(item, index)"
                                    @remove-tag="removeTagCategoryVal(item)"
                                >
                                    <el-option
                                        style="height: auto;"
                                        :value="seletedIdxIdsOptions"
                                    >
                                        <channel-tree-idx
                                            :idx="index"
                                            ref="nodeTreeIdx"
                                            class="mpks-add-task-tree"
                                            :checkable="true"
                                            :check-strictly="false"
                                            :default-checked-keys="
                                                item.innerselectTreeIdxIds
                                            "
                                            :get-permission-node="true"
                                            @node-check="selectIdxId"
                                        />
                                    </el-option>
                                </el-select>
                            </el-form-item>
                        </el-col>
                        <span
                            v-if="currentItem.selects.length === 1"
                            class="between-delete"
                            >删除
                        </span>
                        <span
                            v-else
                            class="between-delete-true"
                            @click="deleteSelects(item, index)"
                            >删除
                        </span>
                    </div>
            </el-form-item>

            <div
                v-if="currentItem.selects.length < maxAdd"
                class="mpks-visual-query-filter-add-attribute"
                @click="addCategory"
            >
                <svg-icon name="add"></svg-icon>
                <span class="add-txt">新增一组</span>
                <span  class="add-plus">(最多支持5)</span>
            </div>
            <div v-else class="disabled margin-top">
                +   <span class="add-txt-to">新增一组</span>
                <span  class="add-plus-to">(最多支持5)</span>
            </div>
        </el-form>
        <div slot="footer">
            <el-button type="primary" @click="OK('form')">确认</el-button>
            <el-button type="default" @click="Cancel">取消</el-button>
        </div>
    </el-dialog>
</template>

<script>
import cloneDeep from "lodash/cloneDeep";
import {
    
     validate } from "@/common/util.js";
import SvgIcon from "@/components/SvgIcon.vue";
import ChannelTree from "@/components/channelTree.vue";
import ChannelTreePic from "@/components/channelTreepic.vue";
import ChannelTreeIdx from "@/components/ChannelTreeIdx.vue";
// 判断一下, 编辑的时候,不push这个那个对象
export default {
    
    
    name: "SearchStrategyResultInterveneDialog",
    components: {
    
    
        SvgIcon,
        ChannelTree,
        ChannelTreePic,
        ChannelTreeIdx
    },
    props: {
    
    
        title: {
    
    
            type: String,
            default: "新建知识库"
        },
        dialogVisible: {
    
    
            type: Boolean,
            default: false
        },
        sendData: {
    
    
            type: Array,
            required: true
        },
        data: {
    
    
            type: Object,
            required: true
        },
        dataEdit: {
    
    
            type: Object
        }
    },
    beforeMount() {
    
    },
    created() {
    
    },
    mounted() {
    
    },
    data() {
    
    
        var NodeValPass = (rule, value, callback) => {
    
    
            if(this.currentItem.selects[rule.field.substring(8,9)].NodeVal.length===0){
    
    
                 callback(new Error('知识树节点不能为空'));
            }else{
    
    
                 callback();
            }
        };
        var picValPass = (rule, value, callback) => {
    
    
             if(this.currentItem.selects[rule.field.substring(8,9)].picVal.length===0){
    
    
                 callback(new Error('图谱类目不能为空'));
            }else{
    
    
                 callback();
            }
        };
        var categoryValPass = (rule, value, callback) => {
    
    
             if(this.currentItem.selects[rule.field.substring(8,9)].categoryVal.length===0){
    
    
                 callback(new Error('全文索引类目不能为空'));
            }else{
    
    
                 callback();
            }
        };
        return {
    
    
            editFirstNodeIds: [],
            seletedNodeIdsOptions: [],
            seletedPicIdsOptions: [],
            seletedIdxIdsOptions: [],
            innerselectTreeIds: [],
            innerselectTreePicIds: [],
            innerselectTreeIdxIds: [],
            maxAdd: 1, //允许添加的最大数量
            NodesOptionsIds: [], //知识树节点id
            listClassOptionsIn: [], //init
            getClassFilterOptionsIn: [], //init
            getNodesOptionsIn: [], //init

            listClassOptions: [], //响应 //全文索引类目
            getClassFilterOptions: [], //响应 图谱类目
            getNodesOptions: [], //响应 知识树节点
            editInfo: {
    
    
                edit: 0,
                id: ""
            }, //编辑的时候的数据
            innerTitle: this.title,
            innerDialogVisible: this.dialogVisible,
            currentItem: {
    
    
                name: "",
                selects: []
            },
            formRule: {
    
    
                NodeVal: [
                    {
    
    
                        validator: NodeValPass,
                        trigger: "change"
                    }
                ],
                picVal: [
                    {
    
    
                        validator: picValPass,
                        trigger: "change"
                    }
                ],
                categoryVal: [
                    {
    
    
                        validator: categoryValPass,
                        trigger: "change"
                    }
                ],
                name: [
                    {
    
    
                        required: true,
                        validator: validate.whitespace,
                        message: "知识库名称不能为空",
                        trigger: "blur"
                    },
                    {
    
    
                        validator: validate.length,
                        max: 20,
                        message: "最多20个字符",
                        trigger: "change"
                    }
                ]
            }
        };
    },
    watch: {
    
    
        dataEdit(newVal) {
    
    
            this.editInfo.edit = 1;
            this.editInfo.id = newVal.id;
            this.currentItem.name = newVal.name;
            this.currentItem.selects = [];
            newVal.options.forEach((item, index) => {
    
    
                let arr = item.nodeIds
                    .map(i => i)
                    .map(itemId => {
    
    
                        return this.sendData[2].filter(
                            item => item.id === itemId
                        );
                    });
                let echoArr = [];
                arr.forEach(item => {
    
    
                    echoArr.push(item[0].name);
                });
                this.currentItem.selects.push({
    
    
                NodeVal:  [],
                picVal:  [],
                categoryVal: [],
                innerselectTreeIds: [],
                innerselectTreePicIds: [],
                innerselectTreeIdxIds: []
            });
                this.currentItem.selects[index] = {
    
    
                    innerselectTreeIds: item.nodeIds.map(i => i),
                    innerselectTreePicIds: item.spoIds.map(i => i),
                    innerselectTreeIdxIds: item.presetIds.map(i => i),
                    NodeVal: echoArr,
                    picVal: item.spoIds.map(i => i),
                    categoryVal: item.presetIds.map(i => i)?item.presetIds.map(i => i):[]
                };
            });
        },
        dialogVisible: "sync",
        sendData: {
    
    
            handler(newVal) {
    
    
                this.listClassOptions = newVal[0];
                this.getClassFilterOptions = newVal[1];
                this.getNodesOptions = newVal[2];
                this.maxAdd = this.findMinArr(
                    this.listClassOptions,
                    this.getClassFilterOptions,
                    this.getNodesOptions
                );
            },
            deep: true
        },
        title(newVal) {
    
    
            this.innerTitle = newVal;
            if (newVal === "新建知识库") {
    
    
                this.currentItem.name = "";
                this.editInfo.edit = 0;
            }
        }
    },
    methods: {
    
    
        removeTag(currentItem) {
    
    
            //转成id 后 与v-modle中的 :default-checked-keys="item.innerselectTreeIds"匹配 回显tree勾选
            let arr = currentItem.NodeVal.map(itemZhcn => {
    
    
                return this.sendData[2].filter(item => item.name === itemZhcn);
            });
            let toIds = [];
            arr.forEach(item => {
    
    
                toIds.push(item[0].id);
            });
            currentItem.innerselectTreeIds = toIds;
        },
        removeTagPic(currentItem) {
    
    
            currentItem.innerselectTreePicIds = currentItem.picVal;
        },
        removeTagCategoryVal(currentItem) {
    
    
            currentItem.innerselectTreeIdxIds = currentItem.categoryVal;
        },
        selectNodeId(params, index) {
    
    
          console.log(params);
          
            let selectList = [];
            let selectLable = [];
            params.data.forEach(item => {
    
    
                if (+item.id !== 1) {
    
    
                    selectList.push(item.id);
                    selectLable.push(item.name);
                }
            });
            this.seletedNodeIdsOptions = selectList;
            this.currentItem.selects[params.idx].NodeVal = selectLable;
            this.currentItem.selects[params.idx].NodeValSend = selectList;
        },
        selectPicId(params, index) {
    
    
            let selectList = [];
            let selectLable = [];
            params.data.forEach(item => {
    
    
                if (+item.id !== 1) {
    
    
                    selectList.push(item.id);
                    selectLable.push(item.name);
                }
            });
            this.seletedPicIdsOptions = selectList;
            this.currentItem.selects[params.idx].picVal = selectLable;
            this.currentItem.selects[params.idx].picValSend = selectList;
        },
        selectIdxId(params, index) {
    
    
            let selectList = [];
            let selectLable = [];
            params.data.forEach(item => {
    
    
                if (+item.id !== 1) {
    
    
                    selectList.push(item.id);
                    selectLable.push(item.name);
                }
            });
            this.seletedIdxIdsOptions = selectList;
            this.currentItem.selects[params.idx].categoryVal = selectLable;
            this.currentItem.selects[params.idx].categoryValSend = selectList;
        },
        Cancel() {
    
    
            this.innerDialogVisible = false;
        },
        nodeValChange(item, index) {
    
    
            this.currentItem.selects[index].NodeVal = item.NodeVal;
            this.$forceUpdate();
        },
        picValChange(item, index) {
    
    
            // 图谱类目option改变
            this.currentItem.selects[index].picVal = item.picVal;
            this.$forceUpdate();
        },
        classChange(item, index) {
    
    
            // 全文索引类目option改变
            this.currentItem.selects[index].categoryVal = item.categoryVal;
            this.$forceUpdate();
        },
        findMinArr(arr1, arr2, arr3) {
    
    
            const shortestLength = Math.min(
                arr1.length,
                arr2.length,
                arr3.length
            );
            return shortestLength;
        },
        verifyInput() {
    
    
            this.currentItem.selects.forEach(item => {
    
    
                for (const i of Object.keys(item)) {
    
    
                    if (item[i].length === 0) {
    
    
                        break;
                    }
                }
            });
        },
        OK(formName) {
    
    
            // TODO:提交
            this.$refs[formName].validate(valid => {
    
    
                if (valid) {
    
    
                    let param = {
    
    
                        name: this.currentItem.name,
                        options: []
                    };
                    if (this.editInfo.edit === 1) {
    
    
                        //修改 添加参数
                        param.id = this.editInfo.id;
                        param.enabled = 1;
                    }
                    this.currentItem.selects.forEach((currentItem, index) => {
    
    
                        let arr = currentItem.NodeVal.map(itemZhcn => {
    
    
                            return this.sendData[2].filter(
                                item => item.name === itemZhcn
                            );
                        });
                        let toIds = [];
                        arr.forEach(item => {
    
    
                            toIds.push(item[0].id);
                        });
                        let obj = {
    
    };
                        obj.nodeIds = toIds; //nodeIds 传id 其他2个传中文过去!
                        obj.presetIds = currentItem.categoryVal;
                        obj.spoIds = currentItem.picVal;
                        param.options.push(obj);
                    });
                    this.$store
                        .dispatch("channel/channelAddOrUpdate", param)
                        .then(res => {
    
    
                            if (+res.errno === 0) {
    
    
                                if (this.editInfo.edit === 1) {
    
    
                                    //修改
                                    this.$message.success("修改成功");
                                    this.$parent.channelList();
                                    this.currentItem.name = "";
                                    this.innerDialogVisible = false;
                                    this.editInfo.edit = 0;
                                    return;
                                }
                                // 新增
                                this.$message.success("添加成功");
                                this.$parent.channelList();
                                this.currentItem.name = "";
                                this.innerDialogVisible = false;
                            } else {
    
    
                                this.$message.error(
                                    res.msg || "出错啦,请稍候再试。"
                                );
                            }
                        });
                } else {
    
    
                    console.log("error submit!!");
                    return false;
                }
            });
        },

        addCategory(formName) {
    
    
            this.currentItem.selects.push({
    
    
                NodeVal:  [],
                picVal:  [],
                categoryVal: [],
                innerselectTreeIds: [],
                innerselectTreePicIds: [],
                innerselectTreeIdxIds: []
            });
            setTimeout(() => {
    
    
                this.clearValidate("form");
            }, 10);
        },
        deleteSelects(item, index) {
    
    
            this.currentItem.selects.splice(index, 1);
        },
        modifyItem() {
    
    },
        open(formName) {
    
    
             this.$refs[formName].clearValidate()
                if (this.editInfo.edit !== 1) {
    
    //新增
                  this.currentItem.selects.push({
    
    
                                NodeVal:  [],
                                picVal:  [],
                                categoryVal: [],
                                innerselectTreeIds: [],
                                innerselectTreePicIds: [],
                                innerselectTreeIdxIds: []
                            });
                }
        },
        close() {
    
    
            this.clearValidate("form");
            this.$emit("close");
            this.currentItem.selects = [];
            this.currentItem.name = "";
        },
        clearValidate(formName) {
    
    
            this.$refs[formName] && this.$refs[formName].clearValidate();
        },
        sync(newVal) {
    
    
            this.innerDialogVisible = newVal;
        }
    }
};
</script>

<style lang="less" scoped>
.mpks-search-strategy-resultintervene-dialog {
    
    
    /deep/.el-dialog__footer {
    
    
        padding-top: 0;
margin-top: 28px;
        .el-button {
    
    
            width: 72px;
            margin-left: 12px;
        }
    }

    .mpks-search-strategy-resultintervene-search-button {
    
    
        margin: 0 0 0 16px;
        height: 32px;
        color: #fff;
        border-color: #2468f2;
        line-height: 10px;
        border: 1px solid #2468f2;
        border-radius: 4px;
        font-size: 14px;
        color: #2468f2;

        &:hover {
    
    
            border-color: #528eff;
            color: #528eff;
        }

        &:focus {
    
    
            border-color: #2468f2;
            color: #2468f2;
        }
    }

    .mpks-search-strategy-resultintervene-query-item-wrapper {
    
    
        border: 1px solid #f1f1f1;
        padding: 10px 0;
        margin-bottom: 20px;
        max-width: 880px;
    }

    .mpks-search-strategy-resultintervene-block {
    
    
        background: #fafafa;
        padding: 10px 15px;

        .mpks-search-strategy-resultintervene-block-title {
    
    
            font-size: 14px;
            font-weight: 600;
        }

        .mpks-search-strategy-resultintervene-block-item {
    
    
            margin: 10px 0;

            &:first-child {
    
    
                margin-top: 0;
            }

            &:last-child {
    
    
                margin-bottom: 0;
            }

            .el-button {
    
    
                padding: 0;
            }
        }
    }
}

/deep/.mpks-common-dialog-form-item-qa {
    
    
    .el-input-group__append {
    
    
        padding: 0;
        height: 32px;
        background-color: #fff;
        line-height: 32px;
        border: none;
    }

    .el-input__inner {
    
    
        padding-right: 0px !important;
    }
}



/deep/.el-form-item.is-error .el-input__inner,
.el-form-item.is-error .el-textarea__inner {
    
    
    border-color: #f56c6c !important;
}

.flex {
    
    
    display: flex;
    justify-content: space-between;
    // width: 620px;
}

.mtop {
    
    
    margin-top: 10px;
}

.mtop:first-of-type {
    
    
    margin-top: 0;
}

.margin-bottom{
    
    
  // margin-bottom: 20px!important;
}


.between-delete {
    
    
    color: #b7babf;
    cursor: pointer;
}

.between-delete-true {
    
    
    color: #2468F2;
    cursor: pointer;
}

/deep/.el-form-item__error {
    
    
    // padding-top: 8px;
}
.margin-top {
    
    
    margin-top: 10px;
}

.el-col-24 {
    
    
    width: auto;
}


.mpks-visual-query-filter-add-attribute {
    
    
  width: 170px;
    margin-top: -16px;
    margin-left: 102px;
}
.disabled {
    
    
    margin-top: -14px;
    margin-left: 102px;
    font-family: PingFangSC-Regular;
    font-size: 14px;
    color: #b8babf;
    line-height: 20px;
    display: -webkit-box;
    display: -ms-flexbox;
    display: flex;
    -webkit-box-align: center;
    -ms-flex-align: center;
    align-items: center;
    cursor: pointer;
}

/deep/.el-dialog__body {
    
    
    padding: 24px 34px 0!important;
}
/deep/.el-select-dropdown__item {
    
    
    height: 100% !important;
}

/deep/.cd {
    
    
    margin-bottom: 40px !important;
}


.create-css{
    
    
  margin-bottom: 8px!important;
}


/deep/.create-css::before{
    
    
  color: #5C5F66;
  position: absolute;
        left: 36px;
        top: 152px;
        content: "知识库配置:";
        width: 120px;
        height: 26px;
        display: inline-block;
}

/deep/.create-css::after{
    
    
  color: #F56C6C;
  position: absolute;
        left: 26px;
        top:152px;
        content: "*";
        width: 120px;
        height: 26px;
        display: inline-block;
}

/deep/.el-select .el-tag{
    
    
// width: 20px;
// display: -webkit-box;
//     -webkit-box-orient: vertical;
//     -webkit-line-clamp: 1;//第几行末尾出现省略号
//     overflow: hidden; 
}


                .add-txt{
    
    
                  display: inline-block;
                }

                .add-plus{
    
    
                  display: inline-block;
                  color:  #CCCCCC;
                  margin-left: 8px;
                }
                .add-txt-to{
    
    
                  display: inline-block;
                  color:  #CCCCCC;
                }

                .add-plus-to{
    
    
                  display: inline-block;
                  color:  #CCCCCC;
                  margin-left: 8px;
                }
</style>

一组 共3个select tree 组件;这是其中一个select tree组件。 其他2个 结构一样的!
channelTree.Vue
<template>
    <div class="mpks-common-tree">
        <el-tree
            ref="tree"
            class="mpks-common-tree-container"
            v-loading="loading"
            node-key="id"
            :indent="8"
            :data="tree"
            :auto-expand-parent="true"
            :highlight-current="true"
            :check-strictly="checkStrictly"
            :expand-on-click-node="expandOnClickNode"
            :default-expanded-keys="defaultExpandedKeys"
            :default-checked-keys="innerDefaultCheckedKeys"
            :default-expand-all="defaultExpandAllNodes"
            :show-checkbox="checkable"
            :filter-node-method="filterNode"
            @node-click="nodeClick"
            @node-expand="nodeExpand"
            @node-collapse="nodeCollapse"
            @check="nodeCheck"
            @check-change="checkChange"
        >
            <span class="mpks-common-tree-node" slot-scope="{ node, data }">
                <span class="mpks-common-tree-node-title" :title="data.name">{
    
    {
    
    
                    data.name
                }}</span>
                <div class="mpks-common-tree-node-control-wrapper">
                    <el-popover
                        v-if="data.isEncryption && from !== 'role'"
                        placement="top"
                        trigger="hover"
                        content="此节点为非公开"
                    >
                        <i
                            slot="reference"
                            class="el-icon-view mpks-common-tree-node-permission"
                        ></i>
                    </el-popover>
                </div>
            </span>
        </el-tree>
    </div>
</template>

<script>
export default {
    
    
    name: "Tree",
    props: {
    
    
        idx: {
    
    
            type: Number,
            default: undefined
        },
        // 当前选中节点的id, 只读属性
        currentId: {
    
    
            type: Number,
            default: undefined
        },
        // 点击目录回调函数
        expandOnClickNode: {
    
    
            type: Boolean,
            default: true
        },
        // 是否自动选中根节点, 会触发nodeClick
        autoSelectRoot: {
    
    
            type: Boolean,
            default: true
        },
        checkable: {
    
    
            type: Boolean,
            default: false
        },
        checkStrictly: {
    
    
            type: Boolean,
            default: true
        },
        defaultExpandAll: {
    
    
            type: Boolean,
            default: false
        },
        defaultCheckedKeys: {
    
    
            type: Array,
            default() {
    
    
                return [];
            }
        },
        disabledList: {
    
    
            type: Array,
            default() {
    
    
                return [];
            }
        },
        checkableItemList: {
    
    
            type: Array,
            default() {
    
    
                return [];
            }
        },
        displayList: {
    
    
            type: Array,
            default() {
    
    
                return [];
            }
        },
        from: {
    
    
            type: String,
            default: ""
        },
        roleId: {
    
    
            type: Number,
            default: 0
        },
        onlyEnabledEncryption: {
    
    
            type: Boolean,
            default: false
        },
        readonly: {
    
    
            type: Boolean,
            default: false
        },
        theOnly: {
    
    
            // 知识树权限复选框只能选择一个
            type: Boolean,
            default: false
        },
        getPermissionNode: {
    
    
            type: Boolean,
            default: false
        },

        
    },
    data() {
    
    
        return {
    
    
            list: [],
            tree: [],
            currentItem: {
    
    
                name: ""
            },
            defaultExpandedKeys: [],
            loading: false,
            innerDefaultCheckedKeys: this.defaultCheckedKeys,
            selectNodes: []
        };
    },
    watch: {
    
    
        defaultCheckedKeys: {
    
    
            handler(val) {
    
    
                this.innerDefaultCheckedKeys= []
                this.innerDefaultCheckedKeys = val;
                this.load(val);
            },
            deep: true,
            immediate: true
        }
    },
    computed: {
    
    
        defaultExpandAllNodes() {
    
    
            return !!this.defaultExpandAll;
        }
    },
    methods: {
    
    
        load(val) {
    
    
            this.loading = true;
            let param = {
    
    
                permissioncode: "knowledge_catelog_view"
            };

            this.$store.dispatch("channel/getNodes", param).then(
                res => {
    
    
                    this.loading = false;
                    if (+res.errno === 0) {
    
    
                        this.list = this.setDisabledStatus(res.data.list);
                        // this.list = this.filterDisplayNode(this.list);
                        this.tree = this.convertListToTree(this.list);
                        if (this.tree.length === 0) {
    
    
                            return false;
                        }

                        // 默认选中是知识树第一个节点
                        let defaultNodeKey = +this.tree[0].id;
                        // this.defaultExpandedKeys = val
                        this.defaultExpandedKeys.push(defaultNodeKey);
                    } else {
    
    
                        this.$message.error(res.msg || "出错啦,请稍候再试。");
                    }
                },
                () => {
    
    
                    this.loading = false;
                }
            );
        },
        clearTree() {
    
    
            this.$refs.tree.setCheckedKeys([]);
        },
        setDisabledStatus(list) {
    
    
            return list.map(item => {
    
    
                let newItem = item;
                if (this.readonly) {
    
    
                    newItem = {
    
    
                        ...item,
                        disabled: true
                    };
                } else if (this.onlyEnabledEncryption || this.roleId) {
    
    
                    if (!item.isEncryption) {
    
    
                        newItem = {
    
    
                            ...item,
                            disabled: true
                        };
                    }
                }

                if (this.disabledList.length) {
    
    
                    if (this.disabledList.indexOf(item.id) >= 0) {
    
    
                        newItem = {
    
    
                            ...item,
                            disabled: true
                        };
                    } else {
    
    
                        newItem = {
    
    
                            ...item,
                            disabled: false
                        };
                    }
                }

                if (this.checkableItemList.length) {
    
    
                    if (
                        this.checkableItemList.indexOf(item.id.toString()) < 0
                    ) {
    
    
                        newItem = {
    
    
                            ...item,
                            disabled: true
                        };
                    }
                }

                return newItem;
            });
        },
        filterDisplayNode(list) {
    
    
            if (this.displayList.length === 0) {
    
    
                return list;
            }

            return list.filter(item => {
    
    
                return this.displayList.indexOf(item.id.toString()) >= 0;
            });
        },
        nodeClick(data) {
    
    
            this.$emit("node-click", {
    
    
                data: data
            });
        },
        nodeExpand(data) {
    
    
            this.$emit("node-expand", {
    
    
                data: data
            });
            this.defaultExpandedKeys.push(data.id);
        },
        nodeCollapse(data) {
    
    
            this.$emit("node-collapse", {
    
    
                data: data
            });
            let collapseIndex = this.defaultExpandedKeys.findIndex(item => {
    
    
                return item === data.id;
            });
            this.defaultExpandedKeys.splice(collapseIndex, 1);
        },
        nodeCheck(data) {
    
    
            if (this.theOnly) {
    
    
                this.$refs.tree.setCheckedKeys([data.id]);
            }
            this.selectNodes = this.$refs.tree.getCheckedKeys(true);
            this.$emit("node-check", {
    
    
                data: this.$refs.tree.getCheckedNodes(),
                dataInfo: data,
                idx: this.idx
            });
        },
        checkChange(...args) {
    
    
            this.$emit("check-change", ...args);
        },
        convertListToTree(list) {
    
    
            let root = []; // 根节点列表
            if (!list || list.length <= 0) {
    
    
                return root;
            }
            let indexes = {
    
    };
            // 重置数据状态
            list.forEach(v => {
    
    
                indexes[v.id] = v;
                if (+v.parentId === 0) {
    
    
                    root.push(v);
                }
                v.children = []; // 带有可编辑的节点列表
                v.parent = null;
                v.list = []; // 节点所在列表
            });

            // 更新children
            list.forEach(node => {
    
    
                if (+node.parentId !== 0 && indexes[node.parentId]) {
    
    
                    let parent = indexes[node.parentId];
                    node.parent = parent;
                    node.list = parent.children;
                    parent.children.push(node);
                }
            });

            return root;
        },
        filterNode(value, data) {
    
    
            if (!value) {
    
    
                return true;
            }
            return data.name.indexOf(value) !== -1;
        },
        selectFilter(val) {
    
    
            this.$refs.tree.filter(val);
        },
        setCheckedKey(ids) {
    
    
            this.$refs.tree.setCheckedKeys(ids);
        }
    }
};
</script>

<style lang="less">
@import (reference) "~@/common/util.less";

.mpks-common-tree {
    
    
    height: 100%;
    border: 1px solid #eee;

    .mpks-common-tree-header {
    
    
        padding: 0 0 0 24px;
        height: 40px;
        background: #f9f9f9;
        line-height: 40px;
        color: #666;
    }

    .mpks-common-tree-header-button {
    
    
        padding: 13px 10px 13px 0;
    }

    .mpks-common-tree-node-title {
    
    
        .line-clamp(1);
        // margin-top: 4px;
        margin-right: 40px;
        color: #151b26;
    }

    .mpks-common-tree-node-permission {
    
    
        position: relative;
        width: 30px;
        text-align: center;
        color: #999;

        &:after {
    
    
            position: absolute;
            top: 6px;
            left: 6px;
            width: 17px;
            height: 0;
            border-top: 1px solid #999;
            transform: rotate(45deg);
            content: " ";
        }
    }

    .mpks-common-tree-node-control-wrapper {
    
    
        position: absolute;
        top: 0;
        right: 0;
    }

    .mpks-common-tree-node-control {
    
    
        width: 30px;
        text-align: center;
        background: #fff;
        visibility: hidden;
    }

    .el-tree-node:focus > .el-tree-node__content .mpks-common-tree-node-control,
    .el-tree-node__content:hover .mpks-common-tree-node-control,
    .mpks-common-tree-node-control:hover {
    
    
        background: #f5f7fa;
    }

    .el-tree--highlight-current
        .el-tree-node.is-current
        > .el-tree-node__content
        .mpks-common-tree-node-control,
    .el-tree--highlight-current
        .el-tree-node.is-current
        > .el-tree-node__content
        .mpks-common-tree-node-control:hover {
    
    
        background-color: #ebf4fd;
    }

    .mpks-common-tree-node-control:hover {
    
    
        color: #0073eb;
    }

    .el-tree-node {
    
    
        position: relative;
    }

    .el-tree-node__content {
    
    
        font-size: 14px;
        height: 24px;
        line-height: 24px;
        overflow-x: scroll;
        margin-top: 4px;

        &:hover {
    
    
            .mpks-common-tree-node-control {
    
    
                visibility: visible;
            }
        }
    }
    // .el-tree .el-icon-caret-right:before {
    
    
    //     background: url('~@/assets/icon/arrowDown.svg') no-repeat 0 3px;
    //     content: '\9B';
    //     display: block;
    //     height: 16px;
    //     font-size: 16px;
    //     background-size: 16px;
    // }

    .mpks-common-tree-dialog-tips {
    
    
        color: #666;
    }

    .mpks-common-tree-dialog-select {
    
    
        width: 100%;
    }

    .mpks-common-tree-filter {
    
    
        // background: #f9f9f9;
        padding: 0 4px 4px;

        .el-input__inner {
    
    
            // border: none;
            font-size: 12px;
            border-radius: 6px;
            height: 30px;
        }
        .el-input__suffix {
    
    
            display: flex;
            align-items: center;
            height: 30px;
            cursor: pointer;
        }
    }
}

.mpks-common-tree-node-control-disabled {
    
    
    visibility: hidden;
}
</style>

猜你喜欢

转载自blog.csdn.net/zhangyubababa/article/details/132147694