element vue2 动态添加 select+tree

news2024/11/24 14:50:56

难点在 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>

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Markdown系列之Flowchat流程图

一.欢迎来到我的酒馆 介绍Markdown的Flowchart流程图语法。 目录 一.欢迎来到我的酒馆二.什么是Flowchart三.更进一步 二.什么是Flowchart 2.1 Flowchart是一款基于javascript的工具&#xff0c;使用它可以用代码创建简单的流程图。具体信息可以查看flowchart官网&#xff1a;…

vscode 设置滑条颜色

1. 默认的滑条是灰黑色的&#xff0c;很难看的清 2. 左下角&#xff0c;打开VS Code 设置功能 3. 输入命令 workbench color&#xff0c;回车 4. 找到工作台&#xff1a;自定义颜色设置&#xff0c;打开设置文件 setting.json 5. 打开配置文件 6. 添加颜色配置 "workben…

【C++】开源:事件驱动网络库libevent配置使用

&#x1f60f;★,:.☆(&#xffe3;▽&#xffe3;)/$:.★ &#x1f60f; 这篇文章主要介绍事件驱动库libevent配置使用。 无专精则不能成&#xff0c;无涉猎则不能通。——梁启超 欢迎来到我的博客&#xff0c;一起学习&#xff0c;共同进步。 喜欢的朋友可以关注一下&#xf…

C++——STL容器【priority_queue】模拟实现

本章代码&#xff1a;优先级队列模拟实现、priority_queue文档 文章目录 &#x1f408;1. priority_queue介绍&#x1f984;2. priority_queue模拟实现&#x1f427;2.1 构造函数&#x1f427;2.2 建堆向下调整向上调整 &#x1f427;2.3 仿函数&#x1f427;2.4 push & po…

通向架构师的道路之漫谈使用ThreadLocal改进你的层次的划分

一、什么是ThreadLocal 早在JDK 1.2的版本中就提供java.lang.ThreadLocal&#xff0c;ThreadLocal为解决多线程程序的并发问题提供了一种新的思路。使用这个工具类可以很简洁地编写出优美的多线程程序。 ThreadLocal很容易让人望文生义&#xff0c;想当然地认为是一个“本地线…

MapTR论文笔记

MAPTR: STRUCTURED MODELING AND LEARNING FOR ONLINE VECTORIZED HD MAP CONSTRUCTION 目的 传统高精地图 通过一些离线的基于 SLAM 的方法生成&#xff0c;需要复杂的流程以及高昂的维护费用。基于 bev 分割的建图方法&#xff0c;缺少向量化 实例级的信息&#xff0c;比如…

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

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

如何使用 ChatGPT 规划家居装修

你正在计划家庭装修项目&#xff0c;但不确定从哪里开始&#xff1f;ChatGPT 随时为你提供帮助。从集思广益的设计理念到估算成本&#xff0c;ChatGPT 可以简化你的家居装修规划流程。在本文中&#xff0c;我们将讨论如何使用 ChatGPT 有效地规划家居装修&#xff0c;以便你的项…

vue diff 前后缀+最长递增子序列算法

文章目录 查找相同前后缀通过前后缀位置信息新增节点通过前后缀位置信息删除节点 中间部份 diff判断节点是否需要移动删除节点删除未查找到的节点删除多余节点 移动和新增节点最长递增子序列 求解最长递增子序列位置信息 查找相同前后缀 如上图所示&#xff0c;新旧 children 拥…

SCT82A30DHKR_5.5V-100V Vin同步降压控制器

SCT82A30是一款100V电压模式控制同步降压控制器&#xff0c;具有线路前馈。40ns受控高压侧MOSFET的最小导通时间支持高转换比&#xff0c;实现从48V输入到低压轨的直接降压转换&#xff0c;降低了系统复杂性和解决方案成本。如果需要&#xff0c;在低至6V的输入电压下降期间&am…

Photoshop 2023 25.0beta「Mac」

Photoshop 2023是一款专业图像处理软件&#xff0c;它主要用于图像编辑、合成和设计等方面。 Photoshop beta创新式填充的功能特色包括&#xff1a; 自动识别和删除对象&#xff1a;该功能可以自动识别图像中的对象&#xff0c;并用周围的图像填充空白部分&#xff0c;使图像看…

window系统下 tinymce富文本编辑器在搜狗输入法下placeholder不消失现象

window 搜狗输入法下编辑器占位符和内容重叠问题 这种情况是&#xff0c;tinymce插件库存在一些兼容BUG&#xff0c;需要我们自行手写样式或者js替换掉placeholder&#xff0c;代码如下&#xff1a; // 获取富文本框的内容const handleChange (editorContent) > {// cons…

C++11 新特性 ---- final 和 override

一、final C中增加了final关键字&#xff0c;作用如下&#xff1a; ① 限制某个类不能被继承② 或者某个虚函数不能被重写 ① 限制某个类不能被继承 // ① 限制某个类不能被继承,也就是说这个类不能有派生类 class Base{ public:virtual void print() {cout<<"Ba…

电商数据获取:网络爬虫还是付费数据接口?

随着电商行业的迅速发展&#xff0c;对电商数据的需求也越来越大。在获取电商数据时&#xff0c;常常面临一个选择&#xff1a;是自己编写网络爬虫进行数据爬取&#xff0c;还是使用现有的付费数据接口呢&#xff1f;本文将从成本、可靠性、数据质量等多个角度进行分析&#xf…

【css】组合器

组合器是解释选择器之间关系的某种机制。在简单选择器器之间&#xff0c;可以包含一个组合器&#xff0c;从而实现简单选择器难以达到的效果。 CSS 中有四种组合器&#xff1a; 后代选择器 (空格)&#xff1a;匹配属于指定元素后代的所有元素&#xff0c;示例&#xff1a;div …

element-ui表格数据为空,图片占位提示

当表格的绑定数据为空时常需要显示暂无数据等字样&#xff0c;这时候就用到了empty-text <el-table:data"tableData"stripeborderempty-text"暂无数据"> 但&#xff0c;当数据为空&#xff0c;想用图片展示呢&#xff0c;如下图 方法一&#xff1a…

java.lang.UnsupportedClassVersionError TestCase

JavaFramework-JDK6.jar 放到JDK17运行没有问题 JavaFramework源码放到JDK17环境下编译出来的JavaFramework-JDK17.jar JavaFramework-JDK17.jar 放到JDK17运行没有问题 JavaFramework-JDK17.jar 放到JDK8运行没有问题&#xff0c;这个好像不对啊&#xff0c;可能之前编译设置…

day39反转字符串总结

反转字符串原理其实就是交换位置&#xff0c;以中间为分隔点&#xff1b; 基本套路&#xff1a;遍历前一般字符&#xff0c;互换位置&#xff1b; for循环模板 void reverseString(char* s, int sSize){char temp;for (int i 0, j sSize - 1; i < sSize/2; i, j--) {temp…

【无公网IP】本地电脑搭建个人博客网站(并发布公网访问 )和web服务器

【无公网IP】本地电脑搭建个人博客网站&#xff08;并发布公网访问 &#xff09;和web服务器 文章目录 【无公网IP】本地电脑搭建个人博客网站&#xff08;并发布公网访问 &#xff09;和web服务器前言1. 安装套件软件2. 创建网页运行环境 指定网页输出的端口号3. 让WordPress在…

【Rust】Rust学习第三章常见编程概念

包含第一、二章 文档&#xff1a;Rust 程序设计语言 - Rust 程序设计语言 简体中文版 (bootcss.com) 墙裂推荐这个文档 第一章入门 入门指南 - Rust 程序设计语言 简体中文版 第二章猜猜看游戏 猜猜看游戏教程 - Rust 程序设计语言 简体中文版 (bootcss.com) // 导入库 us…