要实现的效果是: 点击保存回校验当前页面的所有输入框
首先 分成两个上下两个子组件,
上面的子组件是一个表单包括规则名称和区域
         下面的子组件是一个表格,表格可以是多行的,需要校验每一行的输入框
父组件调用两个子组件的校验方法, 第一个子组件可以直接校验,第二个子组件在分别调用下面的子组件
最外层-父组件
<template>
    <div>
            <!-- 基础信息 -->
            <baseForm
                ref="baseFormRef"
                :mode="mode"
                @cityUpdate="cityUpdate"
            />
            <h3>规则配置</h3>
            <ruleConfigurationTable
                ref="ruleConfigRef"
                v-model="detailsData.ruleConfigModels"
                :mode="mode"
                :details-data="detailsData"
            />
            <div>
                <el-button @click="saveRule" > 保存 </el-button>
            </div>
    </div>
</template>
<script>
import {
    defineComponent, reactive, toRefs, getCurrentInstance,
} from 'vue';
import baseForm from '../components/BaseForm';
import ruleConfigurationTable from '../components/RuleConfigurationTable';
import { ruleDefaultData } from '../constants';
export default defineComponent({
    name: 'PriceComparisonRulesManagement',
    components: {
        baseForm,
        ruleConfigurationTable,
    },
    setup() {
        const { proxy } = getCurrentInstance();
        const mode = proxy.$query.get('mode') || '';
        const id = +proxy.$query.get('id') || '';
        // 如果是创建,默认输入框都是空
        const detailsData = mode === 'create' ? ruleDefaultData : {};
        const initData = reactive({
            mode,
            detailsData,
        });
        // 详情接口
        const initialization = async () => {
            try {
                const ruleDetail = await proxy.$hPost('/detail', {id});
                // 基础信息,这里调用子组件的setFormData对每个输入框进行赋值
                const { ruleName, managementCityId } = ruleDetail;
                proxy.$refs.baseFormRef?.setFormData({ ruleName, managementCityId });
                // 规则配置,这里赋值给一个变量,然后传递给子组件
                initData.detailsData = ruleDetail;
            } catch (e) {
                console.log(e);
            }
        };
        initialization();
        // 返回
        const cancel = () => {//自定义返回地址};
        // 保存规则接口
        const saveCompetition = async () => {
            try {
                const params = {
                    ...initData.detailsData,
                };
                // 拿基础信息输入框的信息
                const { managementCityId, managementCityName, ruleName } = await proxy.$refs.baseFormRef?.getUpdatedFormData();
                Object.assign(params, { managementCityId, managementCityName, ruleName });
                
                await proxy.$hPost('/price/parity/rule/insertOrUpdate', params);
                
                cancel();
            } catch (e) {
                console.log(e);
            }
        };
        // 保存规则校验
        const saveRule = async () => {
            // 校验基础信息   
            const res1 = await proxy.$refs.baseFormRef?.validate().catch(() => false);    
            // 规则配置  
            const res2 = await proxy.$refs.ruleConfigRef?.validate().catch(() => false);
            if (!res1 || !res2) return false;
            // 如果这两个子组件通过校验的话, 那么就可以调保存接口了
            saveCompetition();
        }
        return {
            ...toRefs(initData),
            cancel,
            saveRule,
            cityUpdate,
        };
    },
});
</script>
constants.js
// 竞价规则初始化数据
export const ruleDefaultData = {
    id: '',
    ruleName: '', // 规则名称,比价区域城市名/ID
    managementCityId: '',
    managementCityName: '',
    ruleConfigModels: [
        {
            procurementOrgIds: [], // 第一列 组织
            strategyConfigByCategories: [ // 第二列 商品分层
                {
                    priceType: 2, // 对标价格类型
                    productType: [], // 第三列
                    cptType: [], // 竞对设置
                },
            ],
        },
    ],
};
// 规则配置表头
export function ruleConfigurationTableHeader() {
    return [
        {
            label: '商品所属组织',
            width: '20%',
        },
        {
            label: '商品分层',
            width: '20%',
        },
        {
            label: '对标价格类型',
            width: '20%',
        },
        {
            label: '竞对设置',
            width: '40%',
        },
    ];
}
baseForm - 子组件
<template>
    <el-form
        ref="baseFormRef"
        :model="formData"
        :rules="rules"
        label-width="100px"
    >
        <el-form-item
            label="规则名称"
            prop="ruleName"
        >
            <el-input
                v-model="formData.ruleName"
            />
        </el-form-item>
        <el-form-item
            label="比价区域"
            prop="managementCityId"
        >
            <!-- 这里其实就是el-selsct -->
            <manageCitySelect
                ref="manageCitySelectRef"
                v-model="formData.managementCityId"
            />
        </el-form-item>
    </el-form>
</template>
<script>
const getBaseFormRules = () => ({
    ruleName: [
        { required: true, message: '请输入规则名称', trigger: 'blur' },
    ],
    managementCityId: [
        { required: true, message: '请选择比价区域', trigger: 'blur' },
    ],
});
import manageCitySelect from 'components/ManageCitySelect';
import {
    defineComponent, computed, getCurrentInstance, reactive, toRefs,
} from 'vue';
// 获取初始化的数据
import {
    ruleDefaultData,
} from '../constants';
export default defineComponent({
    name: 'BaseForm',
    components: {
        manageCitySelect,
    },
    setup() {
        const { proxy } = getCurrentInstance();
        const initData = reactive({
            formData: ruleDefaultData,
        });
        // 自动校验
        const rules = computed(() => getBaseFormRules());
        // 手动校验, 父组件点击保存的时候调用validate方法
        const validate = () => proxy.$refs.baseFormRef?.validate();
        // 回显. 父组件调用setFormData把数据带过来
        const setFormData = (newFormData) => {
            Object.assign(initData.formData, newFormData);
        };
        // 父组件点击保存的时候调用getUpdatedFormData获取最新数据
        const getUpdatedFormData = async () => {
            const { formData } = initData;
            return { ...formData };
        };
        return {
            ...toRefs(initData),
            rules,
            validate,
            setFormData,
            getUpdatedFormData,
        };
    },
});
</script>
RuleConfigurationTable 子组件
<template>
    <div class="content">
        <dl class="multi-level-table">
            <dt>
                <div
                    v-for="(column, c1) in columns"
                    :key="c1"
                    class="th"
                    :style="`width: ${column.width}`"
                >
                    <span v-text="column.label"></span>
                </div>
            </dt>
            <dd
                v-for="(item, i) in detailsData.ruleConfigModels"
                :key="`${i}_1`"
            >
                <!-- 第一行的第一个表格---所属组织-->
                <div
                    class="td p10"
                    :style="`width: ${columns[0].width}`"
                >
                    <BelongOrganization
                        ref="purchasingOrganizationRef"
                        v-model="item.procurementOrgIds"
                        :index="i"
                        :details-data="detailsData"
                    />
                    <AddDelButtonGroup
                        :index-list="[i]"
                        :disabled="detailsData.ruleConfigModels.length === 1"
                        @operator="operatorRow"
                    />
                </div>
                <!-- 第一行的第二个表格  商品分层-->
                <div
                    v-for="(strategy, s) in item.strategyConfigByCategories"
                    :key="`${s}_2`"
                    class="td-line"
                >
                    <div
                        class="td p10"
                        :style="`width: ${columns[1].width}`"
                    >
                        <GoodsStratification
                            ref="commodityStratification"
                            v-model="strategy.productType"
                            :strategy-config-by-categories="item.strategyConfigByCategories"
                        />
                        <AddDelButtonGroup
                            :index-list="[i, s]"
                            :disabled="item.strategyConfigByCategories.length === 1"
                            @operator="operatorRow"
                        />
                    </div>
                    <!-- 第一行的第三个表格     对标价格类型 -->
                    <div
                        class="td p10"
                        :style="`width: ${columns[2].width};`"
                    >
                        <div
                            class="td p10"
                            :style="`width: ${columns[2].width};`"
                        >
                            <!-- 忽略 -->
                        </div>
                    </div>
                    <!-- 第一行的第四个表格 -->
                    <div
                        class="p10 td"
                        :style="`width: ${columns[3].width}`"
                    >
                        <!-- 忽略 -->
                    </div>
                </div>
            </dd>
        </dl>
    </div>
</template>
<script>
import {
    defineComponent, getCurrentInstance, reactive, toRefs,
} from 'vue';
import {
    ruleConfigurationTableHeader, ruleDefaultData,
} from '../constants';
import AddDelButtonGroup from './AddDelButtonGroup';
import GoodsStratification from './GoodsStratification';
import BelongOrganization from './BelongOrganization';
export default defineComponent({
    name: 'ConventionalPricingTableRef',
    components: {
        AddDelButtonGroup,
        GoodsStratification,
        BelongOrganization,
    },
    props: {
        detailsData: {
            type: Object,
            default: () => ({}),
        },
    },
    setup(props, { emit }) {
        const { proxy } = getCurrentInstance();
        // 从库里引入的深拷贝函数
        const { cloneDeep } = proxy.$tools;
        // 初始化
        const initData = reactive({
            // 表头
            columns: ruleConfigurationTableHeader(),
            // 添加的空数据列
            defaultDataSimulation: ruleDefaultData,
        });
        // 父组件调用校验
        const validate = () => {
            // 商品分层的校验
            const proArr1 = proxy.$refs.commodityStratification.map((item, index) => (
                proxy.$refs.commodityStratification[index].validate()
            ));
            // 所属组织的校验
            const proArr2 = proxy.$refs.purchasingOrganizationRef.map((item, index) => (
                proxy.$refs.purchasingOrganizationRef[index].validate()
            ));
            return Promise.all([...proArr1, ...proArr2]);
        };
        // 添加/复制/删除每行数据
        const operatorRow = (obj) => {
            const { isAdd, indexList } = obj || {};
            const indexLen = indexList.length;
            // 拷贝一下原数据(ruleConfigModels是规则配置的数据),等下操作这个数据的增删
            const sourceData = cloneDeep(props.detailsData.ruleConfigModels);
            switch (indexLen) {
                case 1: // 添加第一列
                    if (isAdd === 'copy') {
                        // 实现逻辑是如果复制的是组织,那么需要将组织项清空,如果不深拷贝的话,会影响原数据
                        const copyValue = sourceData[indexList[0]];
                        const deepCloneCopy = cloneDeep(copyValue);
                        deepCloneCopy.procurementOrgIds = [];
                        sourceData.splice(+indexList[0] + 1, 0, cloneDeep(deepCloneCopy));
                    } else if (isAdd === 'add') {
                        sourceData.splice(+indexList[0] + 1, 0, cloneDeep(initData.defaultDataSimulation.ruleConfigModels[0]));
                    } else {
                        sourceData.splice(+indexList[0], 1);
                    }
                    break;
                case 2:// 添加第二列
                    if (isAdd === 'copy') {
                        // 要复制的数据
                        const copyValue = sourceData[indexList[0]].strategyConfigByCategories[indexList[1]];
                        const deepCloneCopy = cloneDeep(copyValue);
                        deepCloneCopy.productType = [];
                        sourceData[+indexList[0]].strategyConfigByCategories.splice(+indexList[1] + 1, 0, cloneDeep(deepCloneCopy));
                    } else if (isAdd === 'add') {
                        sourceData[+indexList[0]].strategyConfigByCategories.splice(+indexList[1] + 1, 0, cloneDeep(initData.defaultDataSimulation.ruleConfigModels[0].strategyConfigByCategories[0]));
                    } else {
                        sourceData[+indexList[0]].strategyConfigByCategories.splice(+indexList[1], 1);
                    }
                    break;
                default:
                    break;
            }
            emit('input', sourceData);
        };
        return {
            ...toRefs(initData),
            operatorRow,
            validate,
        };
    },
});
</script>
<style scoped lang="scss">
$tBorderColor: #edf0f5;
.multi-table-wrapper {
    width: 100%;
    overflow-x: auto;
}
.multi-level-table {
    min-width: 100%;
    display: table;
    border: $tBorderColor 1px solid;
    border-bottom: none;
    dt,
    dd {
        width: 100%;
        margin: 0;
        padding: 0;
        border-bottom: $tBorderColor 1px solid;
        display: table;
        table-layout: fixed;
        line-height: 20px;
        .th,
        .td {
            display: table-cell;
            vertical-align: middle!important;
            font-size: 12px;
            border-right: $tBorderColor 1px solid;
            &:last-child {
                border-right: none;
            }
            line-height: 22px;
            box-sizing: border-box;
            &.p10 {
                padding: 0 10px;
            }
            &.inner {
                padding: 0 10px;
                height: 120px;
            }
            &.inner-mini {
                padding: 0 10px;
                height: 80px;
            }
        }
        .th {
            padding: 10px;
        }
        .td-line {
            width: 100%;
            display: table;
            table-layout: fixed;
            border-bottom: $tBorderColor 1px solid;
            &:last-child {
                border-bottom: none;
            }
        }
        .error-tips {
            margin: 0;
            padding: 5px 0;
            color: #ff0000;
        }
    }
    dt {
        background: #f5f6f7;
        font-weight: bold;
    }
    .border-box {
        box-sizing: border-box
    }
    .table {
        display: table;
    }
}
</style>
AddDelButtonGroup 孙组件
<template>
    <div class="btn-wrapper">
        <el-button
            type="text"
            @click="operatorRow('copy')"
        >
            复制
        </el-button>
        <el-button
            type="text"
            @click="operatorRow('add')"
        >
            添加
        </el-button>
        <el-button
            type="text"
            v-bind="$attrs"
            @click="operatorRow('delete')"
        >
            删除
        </el-button>
    </div>
</template>
<script>
export default {
    name: 'AddDelButtonGroup',
    props: {
        indexList: {
            type: Array,
            required: true,
        },
    },
    setup(props, { emit }) {
        // 复制/添加\删除行
        const operatorRow = (isAdd) => {
            emit('operator', { isAdd, indexList: props.indexList.map((index) => `${index}`) });
        };
        return {
            operatorRow,
        };
    },
};
</script>
<style lang="scss" scoped>
.btn-wrapper {
    margin-top: 10px;
}
.del-btn {
    color: #ff0000;
    &:disabled {
        color: #B0B3B8;
    }
}
</style>
BelongOrganization 组织组件(孙组件)
<template>
    <el-form
        ref="BelongOrganizationRef"
        :model="ruleForm"
        :rules="rules"
        style="padding-top: 10px;"
    >
        <el-form-item prop="procurementOrgIds">
            <!-- 这里其实是一个el-tree -->
            <PurchasingOrganizationDeletable
                ref="purchasingOrganizationRef"
                v-model="ruleForm.procurementOrgIds"
                :multiple="true"
                node-key="id"
                :tag-tender="true"
                :merge-value="true"
                :organization-data="organizationData"
                :clone-deep-organization-data="cloneDeepOrganizationData"
                :remote="false"
                :disabled-ids="getPurchasingOrgDisList(index)"
                @change="change"
            />
        </el-form-item>
    </el-form>
</template>
<script>
import PurchasingOrganizationDeletable from 'components/PurchasingOrganizationDeletable';
import {
    reactive, getCurrentInstance, toRefs, watch,
} from 'vue';
export default {
    name: 'BelongOrganization',
    components: {
        PurchasingOrganizationDeletable,
    },
    props: {
        value: {
            type: Array,
            default: () => ([]),
        },
        index: {
            type: Number,
            required: true,
        },
        detailsData: {
            type: Object,
            default: () => ({}),
        },
    },
    setup(props, { emit }) {
        const { proxy } = getCurrentInstance();
        const { cloneDeep } = proxy.$tools;
        const init = reactive({
            ruleForm: {
                procurementOrgIds: props.value,
            },
            // 所有的组织树
            organizationData: [],
            // 深拷贝的所有的组织树
            cloneDeepOrganizationData: [],
            rules: {
                procurementOrgIds: [
                    {
                        required: true, type: 'array', message: '请选择商品所属组织', trigger: 'change',
                    },
                ],
            },
        });
        watch(() => props.value, (v) => {
            init.ruleForm.procurementOrgIds = v;
        });
        // 获取组织列表
        const getOrganizationList = async () => {
            try {
                const list = await proxy.$hPost('/getAll');
                // 默认全部可选
                init.organizationData = list.map((item) => ({ ...item, disabled: false }));
                init.cloneDeepOrganizationData = cloneDeep(init.organizationData);
            } catch (error) {
                console.log(error);
            }
        };
        getOrganizationList();
        
        // 子组件调用validate进行校验
        const validate = () => proxy.$refs.BelongOrganizationRef?.validate();
        // 组织发生变化
        const change = (v) => {
            emit('input', v);
        };
        // 组织不能重复选择
        const getPurchasingOrgDisList = (i) => {
            const { detailsData: { ruleConfigModels } } = props;
            const arr = cloneDeep(ruleConfigModels);
            arr.splice(i, 1);
            return arr.reduce((tol, cur) => [...tol, ...cur.procurementOrgIds], []);
        };
        return {
            ...toRefs(init),
            getPurchasingOrgDisList,
            validate,
            change,
        };
    },
};
</script>
GoodsStratification 商品分层组件(孙组件)
<template>
    <el-form
        ref="GoodsStratificationRef"
        :model="ruleForm"
        :rules="rules"
        style="padding-top: 10px;"
    >
        <el-form-item prop="productType">
            <el-select
                v-model="ruleForm.productType"
                multiple
                @change="changeStratification"
            >
                <el-option
                    v-for="mbl in getDisabledMblOptions(strategyConfigByCategories.reduce((pre,cur) => pre.concat(cur.productType),[]))"
                    :key="mbl.code"
                    :label="mbl.value"
                    :value="mbl.code"
                    :disabled="mbl.disabled"
                >
                    <span>{{ mbl.value }}</span>
                </el-option>
            </el-select>
        </el-form-item>
    </el-form>
</template>
<script>
import {
    reactive, getCurrentInstance, watch,
} from 'vue';
export default {
    name: 'GoodsStratification',
    props: {
        value: {
            type: Array,
            default: () => ([]),
        },
        // 当前的商品分层信息
        strategyConfigByCategories: {
            type: Array,
            required: true,
        },
    },
    setup(props, { emit }) {
        const { proxy } = getCurrentInstance();
        const init = reactive({
            ruleForm: {
                productType: props.value,
            },
            // 全部的商品分层
            commodityStratificationList: [],
            rules: {
                productType: [
                    {
                        required: true, type: 'array', message: '请选择商品分层', trigger: 'change',
                    },
                ],
            },
        });
        watch(() => props.value, (v) => {
            init.ruleForm.productType = v;
        });
        const validate = () => proxy.$refs.GoodsStratificationRef?.validate();
        // 获取商品分层列表
        const getStratificationList = async () => {
            init.commodityStratificationList = await proxy.$hGet('/basic');
        };
        getStratificationList();
        // 商品分层发生变化
        const changeStratification = (v) => {
            emit('input', v);
        };
        // 商品分层同一个组织不能重复选择商品分层
        const getDisabledMblOptions = (disArr = []) => init.commodityStratificationList.map((oriItem) => {
            const disabled = disArr.includes(oriItem.code);
            return {
                ...oriItem,
                disabled,
            };
        });
        return {
            ...init,
            getDisabledMblOptions,
            changeStratification,
            validate,
        };
    },
};
</script>
 <style lang="scss" scoped>
</style>
组织组件 PurchasingOrganizationDeletable (业务组件和上面功能关系不大)
<template>
    <div>
        <treeselect
            v-model="innerValue"
            :data="showData"
            :multiple="multiple"
            :only-leaf="onlyLeaf"
            :disabled="disabled"
            :render-node="renderNode"
            :render-tag="renderTag"
            :merge-value="mergeValue"
            :editable-method="isSelectLevel"
            :placeholder="placeholder"
            v-bind="$attrs"
            @change="onChange"
            @focus="filterDisabledList"
        />
    </div>
</template>
<script lang="jsx">
import { cloneDeep } from '@lsfe/tools';
export default {
    name: 'PurchasingOrganizationSelect',
    props: {
        multiple: {
            type: Boolean,
            default: false,
        },
        // 是否只选择子节点
        onlyLeaf: {
            type: Boolean,
            default: false,
        },
        // 数据会自动收敛,即如果父节点被选中,则返回的值中不会存在子节点的值。
        mergeValue: {
            type: Boolean,
            default: false,
        },
        disabled: {
            type: Boolean,
            default: false,
        },
        value: {
            type: [String, Number, Array],
            default: '',
        },
        maxLevel: {
            type: Number,
            default: Infinity,
        },
        selectLevel: {
            type: [Number, String, Array],
            default: '',
        },
        placeholder: {
            type: String,
            default: '请选择所属组织',
        },
        // 从外部传的data
        organizationData: {
            type: Array,
            default: () => ([]),
        },
        usePermission: {
            type: Boolean,
            default: false,
        },
        tagTender: {
            type: Boolean,
            default: false,
        },
        canTagDel: {
            type: Boolean,
            default: true,
        },
        remote: {
            type: Boolean,
            default: true,
        },
        disabledIds: {
            type: Array,
            default: () => ([]),
        },
        cloneDeepOrganizationData: {
            type: Array,
            default: () => ([]),
        },
    },
    data() {
        return {
            innerValue: this.value,
            organizationList: [],
            cloneDeepOrganization: [],
        };
    },
    computed: {
        showData() {
            return this.organizationList
                .filter((item) => !this.maxLevel || item.level <= this.maxLevel);
        },
    },
    watch: {
        value: {
            // 详情和编辑的数据回显
            handler(newValue) {
                this.innerValue = newValue;
            },
        },
        organizationData: {
            deep: true,
            handler(newValue) {
                this.organizationList = newValue;
                this.filterDisabledList(newValue);
            },
        },
    },
    mounted() {
        if (this.remote) {
            this.getOrganizationList();
        } else if (this.organizationData.length) {
            this.filterDisabledList(this.organizationData);
        }
    },
    methods: {
        async getOrganizationList() {
            try {
                const url = this.usePermission ? '/shepherd/product/bizcenter/purchaserOrgTService/getDeptListByMisId' : '/shepherd/product/bizcenter/purchaserOrgTService/getAllDept';
                const list = await this.$hPost(url);
                this.cloneDeepOrganization = cloneDeep(list);
                this.$emit('getChildOrganizationList', cloneDeep(list));
                this.filterDisabledList(list);
            } catch (error) {
                this.$message.error(error.msg || error.message || '获取所属组织列表失败');
            } finally {
                this.$emit('loaded', this.organizationList);
            }
        },
        onChange(val, item) {
            this.$emit('input', val);
            this.$emit('change', val, item);
        },
        deleteNode(treeSelect, item) {
            const tree = treeSelect.$refs.treeWrapper.$refs.tree;
            const targetNode = tree.getNode(item);
            // 被从组织中删除的某个组织
            if (!targetNode) {
                const i = this.innerValue.indexOf(item.id);
                this.innerValue.splice(i, 1);
                this.$emit('input', this.innerValue);
            }
            targetNode?.setChecked(false, true);
            this.$nextTick(() => {
                const store = tree.store;
                tree.$emit('check', targetNode?.data, {
                    checkedNodes: store.getCheckedNodes(),
                    checkedKeys: store.getCheckedKeys(),
                    halfCheckedNodes: store.getHalfCheckedNodes(),
                    halfCheckedKeys: store.getHalfCheckedKeys(),
                });
            });
        },
        renderTag(h, data, treeSelect) {
            const { canTagDel, tagTender } = this;
            const arr = data.filter((item) => !item.children);
            if (!tagTender) {
                arr.slice(0, 1);
            }
            const tagList = arr.map((item) => (
                <el-tag
                    size="small"
                    key={item.id}
                    disable-transitions={true}
                    closable={canTagDel}
                    onClose={() => { this.deleteNode(treeSelect, item); }}
                >
                    {item.label}
                </el-tag>
            ));
            if (!tagTender) {
                if (data.length > 1) {
                    tagList.push((
                        <el-tag size="small">+{data.length - 1}</el-tag>
                    ));
                }
            }
            return [tagList];
        },
        filterDisabledList(data = this.organizationList) {
            const { disabledIds } = this;
            if (disabledIds.length === 0) {
                /*
                    这里用的是从父组件请求的组织列表, 传过来的有组织列表和深拷贝的组织列表,
                    如果disabledIds为空,使用深拷贝的组织列表,ss
                    如果不是使用的父组件传过来的数据,就用在本组织中深拷贝的数据,对初始化组织赋值
                */
                if (!this.remote) {
                    this.organizationList = this.cloneDeepOrganizationData;
                } else {
                    this.organizationList = this.cloneDeepOrganization;
                }
            } else {
                this.organizationList = data.map((item) => ({ ...item, disabled: disabledIds.includes(item.id) }));
            }
        },
        // eslint-disable-next-line no-unused-vars
        renderNode(h, { node, data }) {
            return (
                <div>
                    <span>{data.id} -- {data.label}</span>
                </div>
            );
        },
        // eslint-disable-next-line consistent-return
        isSelectLevel(node) {
            const level = Number(node.level);
            if (!this.selectLevel) {
                // 没有selectLevel 直接通过
                return true;
            }
            if (Array.isArray(this.selectLevel)) {
                // selectLevel是数组
                // eslint-disable-next-line no-bitwise
                return ~this.selectLevel.indexOf(level);
            }
            if (typeof this.selectLevel === 'number' || typeof this.selectLevel === 'string') {
                // selectLevel是数字 或 字符串
                return Number(this.selectLevel) === level;
            }
        },
    },
};
</script>
<style lang="scss" scoped>
::v-deep .el-select__input{
    width: 0px;
}
::v-deep .tag-wrapper .el-input__inner {
    overflow-y: auto;
    max-height: 100px;
}
 ::v-deep .tag-wrapper .el-input__inner .tag-wrapper__inner {
    overflow-y: auto;
    max-height: 100px;
}
</style>



















