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>

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/63786.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

C语言案例 按序输出多个整数-03

难度2复杂度3 题目&#xff1a;输入多个整数&#xff0c;按从小到大的顺序输出 步骤一&#xff1a;定义程序的目标 编写一个C程序&#xff0c;随机输入整数&#xff0c;按照从小到大的顺序输出 步骤二&#xff1a;程序设计 整个C程序由三大模块组成&#xff0c;第一个模块使…

实战项目——多功能电子时钟

一&#xff0c;项目要求 二&#xff0c;理论原理 通过按键来控制状态机的状态&#xff0c;在将状态值传送到各个模块进行驱动&#xff0c;在空闲状态下&#xff0c;数码管显示基础时钟&#xff0c;基础时钟是由7个计数器组合而成&#xff0c;当在ADJUST状态下可以调整时间&…

AlexNet卷积神经网络-笔记

AlexNet卷积神经网络-笔记 AlexNet卷积神经网络2012年提出 测试结果为&#xff1a; 通过运行结果可以发现&#xff0c; 在眼疾筛查数据集iChallenge-PM上使用AlexNet&#xff0c;loss能有效下降&#xff0c; 经过5个epoch的训练&#xff0c;在验证集上的准确率可以达到94%左右…

电源控制--品质因素Q值全解

什么是品质因素Q值&#xff1f; 在电源控制中&#xff0c;品质因素 Q 值通常用于描述电源滤波器的性能。电源滤波器用于减小电源中的噪声和干扰&#xff0c;以提供干净稳定的电源供应给电子设备。 品质因素 Q 值在电源滤波器中表示滤波器的带宽和中心频率之比&#xff0c;用于…

SpringBoot集成百度人脸识别实现登陆注册功能Demo(二)

前言 上一篇SpringBoot集成百度人脸demo中我使用的是调用本机摄像头完成人脸注册&#xff0c;本次demo根据业务需求的不同我采用文件上传的方式实现人脸注册。 效果演示 注册 后端响应数据&#xff1a; 登录 后端响应数据&#xff1a; 项目结构 后端代码实现 1、BaiduAiUtil…

【C++学习】STL容器——list

目录 一、list的介绍及使用 1.1 list的介绍 1.2 list的使用 1.2.1 list的构造 1.2.2 list iterator的使用 1.2.3 list capacity 1.2.4 list element access 1.2.5 list modifiers 1.2.6 list 迭代器失效 二、list的模拟实现 2.1 模拟实现list 三、list和vector的对比…

8月1日上课内容 第一章web基础与http协议

dns与域名 网络是基于tcp/ip协议进行通信和连接的 应用层--传输层---网络层----数据链路层-----物理层 ip地址&#xff0c;我们每一台主机都有一个唯一的地址标识(固定的ip地址)&#xff0c;区分用户和计算机通信。 ip地址:32位二进制数组成的&#xff0c;不方便记忆 192.168.…

SpringMVC -- REST风格开发,RESTful快速开发、RESTful注解开发

&#x1f40c;个人主页&#xff1a; &#x1f40c; 叶落闲庭 &#x1f4a8;我的专栏&#xff1a;&#x1f4a8; c语言 数据结构 javaweb 石可破也&#xff0c;而不可夺坚&#xff1b;丹可磨也&#xff0c;而不可夺赤。 REST 一、REST简介1.1REST风格简介 二、RESTful入门案例2.…

绘制曲线python

文章目录 import matplotlib.pyplot as plt# 提供的数据 x= [1,1.1,1.2,1.3,1.4,1.5,1.6,1.7,1.8,1.9,2,2.1,2.2,2.3,2.4,2.5,2.6,2.7,2.8,2.9,3,3.1,3.2,3.3,3.4,3.5,3.6,3.7,3.8,3.9,4,4.1,4.2,4.3,4.4,4.5,4.6,4.7,4.8,4.9,5,5.1,5.2,5.3,5.4,5.5,5.6,5.7,5.8,5.9,6,6.1,6.2…

门面模式(C++)

定义 为子系统中的一组接口提供一个一致(稳定) 的界面&#xff0c;Facade模式定义了一个高层接口&#xff0c;这个接口使得这一子系统更加容易使用(复用)。 应用场景 上述A方案的问题在于组件的客户和组件中各种复杂的子系统有了过多的耦合&#xff0c;随着外部客户程序和各子…

代码随想录算法训练营day55

文章目录 Day55 判断子序列题目思路代码 不同的子序列题目思路代码 Day55 判断子序列 392. 判断子序列 - 力扣&#xff08;LeetCode&#xff09; 题目 给定字符串 s 和 t &#xff0c;判断 s 是否为 t 的子序列。 字符串的一个子序列是原始字符串删除一些&#xff08;也可以…

java文件

一.File类 二.扫描指定目录&#xff0c;并找到名称中包含指定字符的所有普通文件&#xff08;不包含目录&#xff09;&#xff0c;并且后续询问用户是否要删除该文件 我的代码: import java.io.File; import java.io.IOException; import java.util.Scanner;public class Tes…

Excel功能总结

1&#xff09;每一张表格上都打印表头 “页面布局”-->“打印标题”-->页面设置“工作表”页-->打印标题“顶端标题行” 如&#xff1a;固定第1~2行&#xff0c;设置成“$1:$2” 2&#xff09;将页面内容打印在一页【缩印】 1.选好需要打印的区域&#xff0c;“页面布…

数据结构 | 利用二叉堆实现优先级队列

目录 一、二叉堆的操作 二、二叉堆的实现 2.1 结构属性 2.2 堆的有序性 2.3 堆操作 队列有一个重要的变体&#xff0c;叫作优先级队列。和队列一样&#xff0c;优先级队列从头部移除元素&#xff0c;不过元素的逻辑顺序是由优先级决定的。优先级最高的元素在最前&#xff…

全志D1-H (MQ-Pro)驱动 OV5640 摄像头

内核配置 运行 m kernel_menuconfig 勾选下列驱动 Device Drivers ---><*> Multimedia support --->[*] V4L platform devices ---><*> Video Multiplexer[*] SUNXI platform devices ---><*> sunxi video input (camera csi/mipi…

C++11 新特性 ---- 模板的优化

C11 模板机制:① 函数模板② 类模板模板的使用&#xff1a;① 范围&#xff1a;模板的声明或定义只能在全局或类范围进行&#xff0c;不可以在局部范围&#xff08;如函数&#xff09;② 目的&#xff1a;为了能够编写与类型无关的代码函数模板&#xff1a;- 格式&#xff1a;t…

软件工程:帕金森定律

在软件开发中&#xff0c;你是否遇到过这种情况&#xff1a; 团队要开发一个简单的购物车应用&#xff0c;项目预期时间是2周工期。负责开发的工程师默认利用完整的2周时间来完成任务。在第一周&#xff0c;工程师会认为任务很轻松&#xff0c;有充足的时间来完成任务&#xff…

SPM(Swift Package Manager)开发及常见事项

SPM怎么使用的不再赘述&#xff0c;其优点是Cocoapods这样的远古产物难以望其项背的&#xff0c;而且最重要的是可二进制化、对xcproj项目无侵入&#xff0c;除了网络之外简直就是为团队开发的项目库依赖最好的管理工具&#xff0c;是时候抛弃繁杂低下的cocoapods了。 一&…

Camunda 7.x 系列【2】开源工作流引擎框架

有道无术&#xff0c;术尚可求&#xff0c;有术无道&#xff0c;止于术。 本系列Spring Boot 版本 2.7.9 本系列Camunda 版本 7.19.0 源码地址&#xff1a;https://gitee.com/pearl-organization/camunda-study-demo 文章目录 1. 前言2. 开源工作流引擎框架2.1 jBPM2.2 Activ…