element-Plus es-tree 树的分页加载

发布时间 2023-07-13 17:38:18作者: iwen1992
<template>
  <es-dialog
    :visible.sync="show"
    :title="$t('templateConfig.applyScope')"
    append-to-body
    :modal-append-to-body="false"
    :close-on-click-modal="false"
    :hide-required-asterisk="true"
    custom-class="chose-wrapper"
    @closed="closeModal"
  >
    <es-row>
      <es-col :span="24">
        <div class="action-wrapper">
          <es-menu
            :default-active="'org'"
            mode="horizontal"
            @select="
              val => {
                selectType(val)
              }
            "
            class="tab-wrapper"
          >
            <es-menu-item index="org">{{ $t('templateConfig.chooseOrg') }}</es-menu-item>
            <es-menu-item index="user">{{ $t('templateConfig.chooseUser') }}</es-menu-item>
          </es-menu>
          <div class="chosen-desciption">
            <p>
              <span>{{ $t('templateConfig.chosen') }}</span>
              <span>({{ orgsNum }}{{ $t('templateConfig.orgNum') }},{{ usersNum }}{{ $t('templateConfig.userNum') }})</span>
            </p>
            <a v-show="allSelections.length" @click="clearAll">{{ $t('common.clear') }}</a>
          </div>
        </div>
        <ChosenPanel>
          <template v-slot:left>
            <div v-show="isUser" v-loading="treeLoading">
              <div class="search-input-container">
                <es-input
                  v-model="userSearchValue"
                  clearable
                  :placeholder="$t('placeHolder.input')"
                  @keyup.enter.native="searchUser"
                  @click.enter="searchUser"
                  @input="searchUser"
                  ><i slot="prefix" class="el-icon-search"
                /></es-input>
              </div>
              <!-- 用户树 -->
              <div class="checked-tree-container" v-show="!userSearchShow">
                <es-scrollbar ref="userTreeBar" style="height:560px">
                  <es-tree
                    ref="usersTree"
                    id="usersTree"
                    :lazy="true"
                    :load="loadUser"
                    :data="userTreeDataList"
                    :props="defaultProps"
                    :show-checkbox="true"
                    node-key="id"
                    :check-strictly="true"
                    :check-on-click-node="true"
                    @check-change="checkUser"
                  >
                    <template slot-scope="{ node, data }">
                      <span class="es-tree-node__label">
                        <span
                          v-if="data.btnType == 'btn'"
                          class="es-tree-node_btn"
                          @click="
                            e => {
                              e.preventDefault()
                              e.stopPropagation()
                              cTreeMore(node, data)
                            }
                          "
                          >{{ node.label }}</span
                        >
                        <span v-else :title="node.label" class="name">
                          <span v-if="data.userMainType && data.userMainType === '2'" class="words">兼</span>{{ node.label }}
                        </span>
                      </span>
                    </template>
                  </es-tree>
                  <span v-if="loadTreeData" class="loadTreeData">{{ loadTreeText }}</span>
                </es-scrollbar>
              </div>
              <!-- 搜索结果 -->
              <div v-show="userSearchShow" class="checked-tree-container search-tree-container">
                <es-scrollbar>
                  <es-tree
                    ref="searchUserTree"
                    :data="searchUsers"
                    :props="defaultProps"
                    :show-checkbox="true"
                    node-key="id"
                    class="searchMorePerson"
                    :check-on-click-node="true"
                    @check-change="checkUser"
                  >
                    <template v-slot="{ node, data }">
                      <div class="tree-check">
                        <div>
                          <div :title="node.label">
                            <b v-if="data.userMainType && data.userMainType === '2'" class="words">兼</b>{{ node.label }}
                          </div>
                          <div :title="data.companyAndOrganizationName" class="companyStyle">
                            {{ data.companyAndOrganizationName }}
                          </div>
                        </div>
                      </div>
                    </template>
                  </es-tree>
                </es-scrollbar>
              </div>
            </div>
            <div v-show="!isUser" v-loading="treeLoading">
              <div class="search-input-container">
                <es-input
                  v-model="orgSearchValue"
                  clearable
                  :placeholder="$t('placeHolder.input')"
                  @keyup.enter.native="searchOrg"
                  @click.enter="searchOrg"
                  @input="searchOrg"
                  ><i slot="prefix" class="el-icon-search"
                /></es-input>
              </div>
              <!-- 组织树 -->
              <div class="checked-tree-container" v-show="!orgSearchShow">
                <es-scrollbar ref="orgsTreeBar" style="height:560px">
                  <es-tree
                    ref="orgsTree"
                    id="orgsTree"
                    :data="treeDataList"
                    :lazy="true"
                    :load="loadOrg"
                    :props="defaultProps"
                    :show-checkbox="true"
                    node-key="id"
                    :check-strictly="true"
                    :check-on-click-node="true"
                    @check-change="checkOrg"
                  >
                    <template slot-scope="{ node, data }">
                      <span class="es-tree-node__label">
                        <span
                          v-if="data.btnType == 'btn'"
                          class="es-tree-node_btn"
                          @click="
                            e => {
                              e.preventDefault()
                              e.stopPropagation()
                              cTreeMore(node, data)
                            }
                          "
                          >{{ node.label }}</span
                        >
                        <span v-else :title="node.label" class="name">
                          <span v-if="data.userMainType && data.userMainType === '2'" class="words">兼</span>{{ node.label }}
                        </span>
                      </span>
                    </template>
                  </es-tree>
                  <span v-if="loadTreeData" class="loadTreeData">{{ loadTreeText }}</span>
                </es-scrollbar>
              </div>
              <!-- 搜索结果 -->
              <div v-show="orgSearchShow" class="checked-tree-container search-tree-container">
                <es-scrollbar style="height:100%">
                  <es-tree
                    ref="searchOrgTree"
                    :data="searchOrgs"
                    :props="defaultProps"
                    :show-checkbox="true"
                    node-key="id"
                    class="searchMorePerson"
                    :check-on-click-node="true"
                    @check-change="checkOrg"
                  >
                    <template v-slot="{ node, data }">
                      <div class="tree-check">
                        <div>
                          <div :title="node.label">
                            <b v-if="data.userMainType && data.userMainType === '2'" class="words">兼</b>{{ node.label }}
                          </div>
                          <div :title="data.companyAndOrganizationName" class="companyStyle">
                            {{ data.companyAndOrganizationName }}
                          </div>
                        </div>
                      </div>
                    </template>
                  </es-tree>
                </es-scrollbar>
              </div>
            </div>
          </template>
          <template v-slot:right>
            <div class="select-component-content">
              <es-scrollbar style="height:100%">
                <div class="clearfix">
                  <div v-for="(item, index) in allSelections" :key="item.id" class="select-component-content-row">
                    <div class="select-component-content-row-item">
                      <span v-if="item.userMainType && item.userMainType === '2'" class="words">兼</span>
                      <span :title="showSearchTitle(item)">{{ showSearchName(item) }} </span>
                      <i class="es-icon-circle-close" @click="deleteChosen(index)" />
                    </div>
                  </div>
                </div>
              </es-scrollbar>
            </div>
          </template>
        </ChosenPanel>
      </es-col>
    </es-row>
    <template v-slot:footer>
      <span>
        <es-button plain class="width60" size="small" @click="closeModal" :loading="loading">{{ $t('common.cancel') }}</es-button>
        <es-button type="primary" class="width60" :loading="loading" size="small" :disabled="!allSelections.length" @click="selectOK">{{
          $t('common.confirm')
        }}</es-button>
      </span>
    </template>
  </es-dialog>
</template>
<script>
import ChosenPanel from '@/components/ChosenPanel'
export default {
  name: 'SelectPersonOrOrganize',
  components: { ChosenPanel },
  props: {
    chosenData: {
      type: Array,
      default: () => [],
    },
    loading: {
      type: Boolean,
      default: false,
    },
  },
  data() {
    return {
      userTreeDataTotal: null,
      loadTreeData: false,
      loadTreeText: '加载中...',
      treeDataList: null,
      treeDataTotal: null,
      loadChildTree: false,
      userTreeDataList: null,
      currPage: 1,
      pageSize: 50,
      btn: [],
      isScroll: true,
      layzeMap: [],
      show: false, // dialog展示或隐藏
      activeMenu: 'org',
      userSearchValue: '',
      orgSearchValue: '',
      searchUsers: [],
      userSearchShow: false,
      searchOrgs: [],
      orgSearchShow: false,
      defaultProps: {
        id: 'id',
        label: 'label',
        code: 'code',
        isLeaf: 'leaf',
        disabled: 'disabled',
      },
      selectUsers: [],
      selectOrgs: [],
      allSelections: [],
      treeLoading: false,
    }
  },
  computed: {
    isUser() {
      return this.activeMenu === 'user'
    },
    usersNum() {
      return this.allSelections?.filter(sel => sel.isUser)?.length || 0
    },
    orgsNum() {
      return this.allSelections?.length - this.usersNum || 0
    },
  },
  mounted() {
    this.show = true
    this.$nextTick(function() {
      this.allSelections = this.chosenData
      this.selectUsers = this.chosenData.filter(data => data.isUser)
      this.selectOrgs = this.chosenData.filter(data => !data.isUser)
      this.initCheck()
    })
  },
  methods: {
    initTreeData() {
      this.loadTreeData = false
      this.loadTreeText = '加载中...'
      this.treeDataList = null
      this.treeDataTotal = null
      this.userTreeDataTotal = null
      this.loadChildTree = false
      this.userTreeDataList = null
      this.currPage = 1
      this.pageSize = 50
      this.btn = []
      this.isScroll = true
    },
    selectType(val) {
      this.activeMenu = val
      if (val === 'user') {
        this.layzeMap.forEach((v, k) => {
          if (v.id === 'loadUser') {
            this.treeDataList = null
            this.initTreeData()
            this.loadUser(v.node_zero, v.resolve_zero)
          }
        })
      } else if (val === 'org') {
        this.layzeMap.forEach((v, k) => {
          if (v.id === 'loadOrg') {
            this.userTreeDataList = null
            this.initTreeData()
            this.loadOrg(v.node_zero, v.resolve_zero)
          }
        })
      }
    },
    deWeightArray(arr) {
      const map = new Map()
      for (const item of arr) {
        if (item && !map.has(item.id)) {
          map.set(item.id, item)
        }
      }

      return [...map.values()]
    },
    debounce(fn, wait) {
      let timer = null

      return function() {
        if (timer !== null) {
          clearTimeout(timer)
        }
        timer = setTimeout(fn, wait)
      }
    },
    getBtnData(keyId, theTotal, total, page, size) {
      if (theTotal < total) {
        return [
          {
            id: keyId,
            code: 'btnMore',
            page,
            size,
            leaf: true,
            disabled: true,
            btnType: 'btn',
            class: 'treeBtn',
            label: '点击加载更多',
          },
        ]
      }

      return [
        {
          id: keyId,
          page,
          size,
          code: 'btnNot',
          leaf: true,
          disabled: true,
          btnType: 'btn',
          class: 'treeBtn',
          label: '没有更多了',
        },
      ]
    },
    async cTreeMore(node, data) {
      this.layzeMap.length > 0 &&
        this.layzeMap.forEach((item, index) => {
          if (item.id === data.id) {
            item.node_zero.childNodes = []
            if (item.func === 'loadOrg') {
              this.loadOrg(item.node_zero, item.resolve_zero, data.page + 1, data)
            } else if (item.func === 'loadUser') {
              this.loadUser(item.node_zero, item.resolve_zero, data.page + 1, data)
            }
          }
        })
    },
    // 监听滚动事件
    async getMoreTreeData() {
      this.currPage = this.currPage + 1
      const data = await this.$API.getPageOrganizationListByPId({
        parentOrganizationId: 0,
        organizationTerritory: 1,
        currPage: this.currPage,
        pageSize: this.pageSize,
      })
      this.loadTreeData = false
      const company = data.list.map(item => {
        if (this.isUser) {
          return {
            id: item.id,
            label: item.organizationName ? item.organizationName : item.companyName,
            code: item.organizationCode,
            disabled: true,
          }
        }

        return {
          id: item.id,
          label: item.organizationName,
          code: item.organizationCode,
          organizationTerritory: item.organizationTerritory,
          type: item.organizationType,
          parentOrganizationId: item.parentOrganizationId,
          organizationTerritory: item.organizationTerritory,
          isUser: false,
        }
      })
      const dataArr = this.isUser ? this.userTreeDataList.concat(company) : this.treeDataList.concat(company)
      this.isUser ? (this.userTreeDataList = this.deWeightArray(dataArr)) : (this.treeDataList = this.deWeightArray(dataArr))
      this.initCheck()
    },
    handleScroll() {
      let treeHeight
      let scrollBarEl
      if (!this.isUser) {
        treeHeight = document.getElementById('orgsTree').clientHeight
        scrollBarEl = this.$refs.orgsTreeBar.wrap
      } else {
        treeHeight = document.getElementById('usersTree').clientHeight
        scrollBarEl = this.$refs.userTreeBar.wrap
      }
      const that = this
      let maxScrollHeight = parseInt(treeHeight - scrollBarEl.clientHeight)
      scrollBarEl.onscroll = that.debounce(() => {
        if (!that.isScroll) {
          return
        }
        if (
          treeHeight !== that.isUser ? document.getElementById('usersTree').clientHeight : document.getElementById('orgsTree').clientHeight
        ) {
          if (!that.isUser) {
            treeHeight = document.getElementById('orgsTree').clientHeight
            scrollBarEl = that.$refs.orgsTreeBar.wrap
          } else {
            treeHeight = document.getElementById('usersTree').clientHeight
            scrollBarEl = that.$refs.userTreeBar.wrap
          }
          maxScrollHeight = parseInt(treeHeight - scrollBarEl.clientHeight)
        }
        if (
          scrollBarEl.scrollTop === maxScrollHeight ||
          Math.ceil(scrollBarEl.scrollTop) === maxScrollHeight ||
          Math.floor(scrollBarEl.scrollTop) === maxScrollHeight
        ) {
          that.loadTreeData = true
          const length = that.isUser ? that.userTreeDataList.length : that.treeDataList.length
          const total = that.isUser ? that.userTreeDataTotal : that.treeDataTotal
          if (length === total) {
            that.loadTreeText = '没有更多了'
          } else {
            that.debounce(that.getMoreTreeData(), 1000)
          }
        }
      }, 50)
    },
    concatTreeData(list, newData, keyId, isLayze) {
      let isFlag = false
      list.map((item, index) => {
        if (item.id === keyId) {
          if (item.children) {
            item.children = [...item.children, ...newData]
          } else {
            item.children = newData
          }
          isFlag = true
        } else {
          if (!isFlag) {
            if (item.children) {
              this.concatTreeData(item.children, newData, keyId)
            }
          }
        }

        return item
      })
      this.treeDataList = list
    },
    initCheck() {
      const userIds = this.selectUsers.map(item => {
        return item.id
      })
      this.$refs.usersTree.setCheckedKeys(userIds)
      this.$refs.searchUserTree?.setCheckedKeys(userIds)
      const orgIds = this.selectOrgs.map(item => {
        return item.id
      })
      this.$refs.orgsTree.setCheckedKeys(orgIds)
      this.$refs.searchOrgTree?.setCheckedKeys(orgIds)
    },
    showSearchTitle(item) {
      return item.isUser ? `${item.label}-${item.organizationName}` : item.label
    },
    showSearchName(item) {
      if (!item.isUser) {
        return `${item.label}`
      }
      const orgName = item.companyAndOrganizationName ? item.companyAndOrganizationName : item.organizationName

      return `${item.label}-${orgName}`
    },
    async searchUser() {
      if (this.userSearchValue) {
        const params = {
          userName: this.userSearchValue,
          organizationTerritory: 1,
          userMainType: '',
        }
        const res = await this.$API.getUserListByUserCodeName(params, { loading: ['treeLoading'], vm: this })
        const data = res.userList
        let searchUsers = []
        if (data.length > 0) {
          searchUsers = data.map(item => {
            item.companyAndOrganizationName = item.organizationName ? `${item.companyName}-${item.organizationName}` : item.companyName

            return {
              id: item.id,
              code: item.realUserCode,
              label: item.userName,
              organizationId: item.organizationId,
              organizationName: item.organizationName ? item.organizationName : item.companyName,
              organizationCode: item.organizationCode,
              companyName: item.companyName,
              organizationTerritory: item.organizationTerritory,
              companyAndOrganizationName: item.companyAndOrganizationName,
              userMainType: item.userMainType,
              userCode: item.realUserCode || item.userCode,
              isUser: true,
            }
          })
        }
        this.searchUsers = searchUsers
        this.userSearchShow = true
        this.initCheck()
      } else {
        this.searchUsers = []
        this.userSearchShow = false
        this.initCheck()
      }
    },
    async loadUser(node, resolve, pg, data) {
      const that = this
      if (node.level === 0) {
        this.layzeMap.push({
          node_zero: node,
          resolve_zero: resolve,
          id: 0,
          func: 'loadUser',
        })
        const params = { parentOrganizationId: 0, organizationTerritory: '1', currPage: this.currPage, pageSize: this.pageSize }
        const data = await this.$API.getPageOrganizationListByPId(params, { loading: ['treeLoading'], vm: this })
        this.userTreeDataTotal = data.totalCount
        let company = data?.list?.map(item => {
          return {
            id: item.id,
            label: item.organizationName ? item.organizationName : item.companyName,
            code: item.organizationCode,
            disabled: true,
          }
        })
        company = that.deWeightArray(company)
        let isOrgLaz = false
        that.layzeMap.map((v, k) => {
          if (v.id === 'loadUser') {
            isOrgLaz = true
            v.node_zero = node
            v.resolve_zero = resolve
          }

          return v
        })
        if (!isOrgLaz) {
          that.layzeMap.push({
            node_zero: node,
            resolve_zero: resolve,
            id: 'loadUser',
            func: 'loadUser',
          })
        }
        if (that.isUser) {
          that.userTreeDataList = company
          resolve(company)
        } else {
          resolve = []
        }
        setTimeout(() => {
          that.handleScroll('loadNode')
        }, 300)
      } else {
        this.currPage = 1
        this.loadChildTree = true
        let total = 0
        const keyId = node.key
        if (pg) {
          this.isScroll = false
        }
        const dataList = await Promise.all([
          this.$API.getPageOrganizationListByPId({
            parentOrganizationId: node.key,
            currPage: pg || this.currPage,
            pageSize: this.pageSize,
          }),
          this.$API.getUserListByOrganizationID({ organizationId: node.key, userMainType: '' }),
        ])
        let companys = dataList[0].list
        let userList = dataList[1].userList
        total = dataList[0].totalCount
        if (companys.length > 0) {
          companys = companys.map(item => {
            return {
              id: item.id,
              label: item.organizationName ? item.organizationName : item.companyName,
              code: item.organizationCode,
              disabled: true,
            }
          })
        }

        if (userList.length > 0) {
          userList = userList.map(item => {
            return {
              id: item.id,
              label: item.userName,
              code: item.userMainType === '1' ? item.userCode : item.userParentCode,
              leaf: true,
              disabled: false,
              _is_checked: true,
              organizationId: item.organizationId,
              organizationName: item.organizationName ? item.organizationName : item.companyName,
              companyName: item.companyName,
              organizationCode: item.organizationCode,
              organizationTerritory: item.organizationTerritory,
              userMainType: item.userMainType, // 主兼类型(1主 2兼)
              userCode: item.userParentCode || item.userCode,
            }
          })
        }
        const theTotal = pg ? (pg + 1) * 50 : 50
        const btn = this.getBtnData(keyId, theTotal, total, pg ? pg + 1 : 1, this.pageSize)
        let newData = pg ? [...companys, ...userList] : [...companys, ...userList, ...btn]
        let isId = false
        this.layzeMap.map((v, k) => {
          if (v.id === keyId) {
            isId = true
            if (v.data[v.data.length - 1].btnType === 'btn') {
              v.data.pop()
            }

            v.node_zero = node
            v.resolve_zero = resolve
            newData = [...v.data, ...newData, ...btn]
          }

          return v
        })
        if (!isId) {
          this.layzeMap.push({
            node_zero: node,
            resolve_zero: resolve,
            id: keyId,
            data: that.deWeightArray(newData),
            func: 'loadUser',
          })
        }
        newData = that.deWeightArray(newData)
        if (that.isUser) {
          resolve(newData)
          this.$nextTick(this.initCheck)
        } else {
          resolve([])
        }
        setTimeout(() => {
          that.isScroll = true
        }, 1000)
      }
    },
    checkUser(data, checked) {
      const userIndex = this.selectUsers.findIndex(item => {
        return item.id === data.id
      })
      const index = this.allSelections.findIndex(item => {
        return item.id === data.id
      })
      if (checked && userIndex === -1) {
        if (this.multipleLimit && this.selectUsers.length === this.multipleLimit.maxNumber) {
          this.$message.info(this.multipleLimit.message)
          this.selectUsers = [...this.selectUsers] // watch selectUsers 重新设置树选中的值
        } else {
          this.selectUsers.push({ ...data, isUser: true })
          this.allSelections.push({ ...data, isUser: true })
        }
      }
      if (!checked && userIndex !== -1) {
        this.selectUsers.splice(userIndex, 1)
        this.allSelections.splice(index, 1)
      }
    },
    async searchOrg() {
      if (this.orgSearchValue) {
        const data = await this.$API.getOrganizationListByOrgCodeName(
          {
            organizationName: this.orgSearchValue,
            organizationTerritory: 1,
          },
          { loading: ['treeLoading'], vm: this }
        )
        let searchOrgs = []
        if (data?.length > 0) {
          searchOrgs = data.map(item => {
            item.companyAndOrganizationName = item.parentOrganizationName
              ? `${item.companyName}-${item.parentOrganizationName}`
              : item.companyName

            return {
              id: item.id,
              code: item.organizationCode,
              label: item.organizationName,
              organizationId: item.parentOrganizationId,
              organizationName: item.parentOrganizationName,
              organizationCode: item.organizationCode,
              companyName: item.companyName,
              companyAndOrganizationName: item.companyAndOrganizationName,
              isUser: false,
            }
          })
        }
        this.searchOrgs = searchOrgs
        this.orgSearchShow = true
        this.initCheck()
      } else {
        this.searchOrgs = []
        this.orgSearchShow = false
        this.initCheck()
      }
    },
    async loadOrg(node, resolve, pg, data) {
      const that = this
      if (node.level === 0) {
        this.layzeMap.push({
          node_zero: node,
          resolve_zero: resolve,
          id: 0,
          func: 'loadOrg',
        })
        const data = await this.$API.getPageOrganizationListByPId(
          { parentOrganizationId: 0, organizationTerritory: 1, currPage: this.currPage, pageSize: this.pageSize },
          { loading: ['treeLoading'], vm: this }
        )
        this.treeDataTotal = data.totalCount
        const company = data?.list?.map(item => {
          return {
            id: item.id,
            label: item.organizationName,
            code: item.organizationCode,
            type: item.organizationType,
            parentOrganizationId: item.parentOrganizationId,
            organizationTerritory: item.organizationTerritory,
            isUser: false,
          }
        })
        let isOrgLaz = false
        that.layzeMap.map((v, k) => {
          if (v.id === 'loadOrg') {
            isOrgLaz = true
            v.node_zero = node
            v.resolve_zero = resolve
          }

          return v
        })
        if (!isOrgLaz) {
          that.layzeMap.push({
            node_zero: node,
            resolve_zero: resolve,
            id: 'loadOrg',
            func: 'loadOrg',
          })
        }

        if (!that.isUser) {
          this.treeDataList = that.deWeightArray(company)
          resolve(company)
          this.$nextTick(this.initCheck)
        } else {
          resolve = []
        }

        setTimeout(() => {
          that.handleScroll('loadNode')
        }, 300)
      } else {
        this.currPage = 1
        this.loadChildTree = true
        let total = 0
        const keyId = node.key
        if (pg) {
          this.isScroll = false
        }
        const data = await this.$API.getPageOrganizationListByPId(
          { parentOrganizationId: node.key, currPage: pg || this.currPage, pageSize: this.pageSize },
          { loading: ['treeLoading'], vm: this }
        )
        total = data.totalCount
        let companys = []
        if (data?.list?.length > 0) {
          companys = data?.list?.map(item => {
            return {
              id: item.id,
              label: item.organizationName,
              code: item.organizationCode,
              type: item.organizationType,
              parentOrganizationId: item.parentOrganizationId,
              organizationTerritory: item.organizationTerritory,
              isUser: false,
            }
          })
        }
        const theTotal = pg ? (pg + 1) * 50 : 50
        const btn = this.getBtnData(keyId, theTotal, total, pg ? pg + 1 : 1, this.pageSize)
        let newData = pg ? [...companys] : [...companys, ...btn]
        // let newData = [...companys, ...persons]
        let isId = false
        this.layzeMap.map((v, k) => {
          if (v.id === keyId) {
            isId = true
            if (v.data[v.data.length - 1].btnType === 'btn') {
              v.data.pop()
            }

            v.node_zero = node
            v.resolve_zero = resolve
            newData = [...v.data, ...newData, ...btn]
          }

          return v
        })
        if (!isId) {
          this.layzeMap.push({
            node_zero: node,
            resolve_zero: resolve,
            id: keyId,
            data: that.deWeightArray(newData),
            func: 'loadOrg',
          })
        }
        newData = that.deWeightArray(newData)
        resolve(newData)
        setTimeout(() => {
          that.isScroll = true
        }, 1000)
        this.$nextTick(this.initCheck)
      }
    },

    checkOrg(data, checked) {
      const orgIndex = this.selectOrgs.findIndex(item => {
        return item.id === data.id
      })
      const selectIndex = this.allSelections.findIndex(item => {
        return item.id === data.id
      })
      if (checked && orgIndex === -1) {
        const user = { ...data, isUser: false }
        this.selectOrgs.push(user)
        this.allSelections.push(user)
      }
      if (!checked && orgIndex !== -1) {
        this.selectOrgs.splice(orgIndex, 1)
        this.allSelections.splice(selectIndex, 1)
      }
    },

    selectOK() {
      this.$emit('on-save', this.allSelections)
    },

    clearAll() {
      this.allSelections = []
      this.selectUsers = []
      this.selectOrgs = []
      this.initCheck()
    },

    deleteChosen(index) {
      const isUser = this.allSelections[index].isUser
      const arr = isUser ? 'selectUsers' : 'selectOrgs'
      const I = this[arr].findIndex(item => {
        return item.id === this.allSelections[index].id
      })
      this[arr].splice(I, 1)
      this.allSelections.splice(index, 1)
      this.initCheck()
    },

    closeModal() {
      this.$emit('on-close')
    },
  },
}
</script>
<style lang="scss">
@import '@/styles/searchInput.scss';
$background-cg: #f0f2f5;
.chose-wrapper {
  .es-dialog__body {
    padding: 0;
    .action-wrapper {
      display: flex;
      align-items: center;
      .tab-wrapper {
        width: 300px;
        border: none;
        border-right: 1px solid #ebeef5;
      }
      .is-active {
        background-color: #fff;
      }
      .chosen-desciption {
        padding: 0 16px;
        display: flex;
        justify-content: space-between;
        align-items: center;
        flex: 1;

        a {
          color: #1063f2;
          cursor: pointer;
        }

        span:last-of-type {
          color: rgba(153, 153, 153, 0.85);
        }
      }
    }

    .chosen-panel-body-left {
      width: 300px;
    }
  }

  .chosen-panel-body-right {
    flex: 1;
  }

  .search-input-container {
    padding-left: 6px;
  }

  .checked-tree-container {
    //height: 376px;
    overflow-x: hidden;
    .es-scrollbar__wrap {
      margin-bottom: -17px !important;
      margin-right: -17px !important;
      overflow-x: hidden;
    }
  }
  .es-tree-node__label {
    overflow: hidden;
    white-space: nowrap;
    text-overflow: ellipsis;
    .name {
      overflow: hidden;
      white-space: nowrap;
      text-overflow: ellipsis;
    }
  }
  .checked-tree-container .es-tree-node__content {
    cursor: pointer !important;
    overflow: hidden;
    white-space: nowrap;
    text-overflow: ellipsis;
  }

  .search-tree-container {
    .es-tree-node {
      margin-bottom: 15px;
    }
    .es-tree-node__content {
      height: auto;
    }
    .single-tree-check {
      overflow: hidden;
      white-space: nowrap;
      text-overflow: ellipsis;
      .companyStyle {
        overflow: hidden;
        white-space: nowrap;
        text-overflow: ellipsis;
      }
    }
  }

  .es-checkbox.is-disabled + .es-tree-node__label {
    cursor: pointer;
    overflow: hidden;
    white-space: nowrap;
    text-overflow: ellipsis;
    .name {
      overflow: hidden;
      white-space: nowrap;
      text-overflow: ellipsis;
    }
  }
  .checked-tree-container .es-tree-node__content {
    cursor: pointer !important;
    overflow: hidden;
    white-space: nowrap;
    text-overflow: ellipsis;
  }
  .select-compoent-tree-radio {
    .es-radio__label {
      display: none;
    }
  }
  .select-compoent-tree-checkbox {
    .es-radio__label {
      display: none;
    }
  }
  .select-component-content .select-component-content-row .select-component-content-row-item .es-icon-circle-close {
    top: 35%;
  }
  .es-tree-node__content {
    padding-top: 7px !important;
    padding-bottom: 7px !important;
    height: auto !important;
  }
  .select-component-content {
    display: inline-block;
    height: 428px;
    .es-scrollbar__wrap {
      overflow-x: hidden !important;
      margin-bottom: -17px !important;
      margin-right: -17px !important;
      .select-component-content-row-item {
        text-overflow: -o-ellipsis-lastline;
        overflow: hidden;
        text-overflow: ellipsis;
        display: -webkit-box;
        -webkit-line-clamp: 2;
        line-clamp: 2;
        -webkit-box-orient: vertical;
        line-height: 22px;
      }
    }
  }
  .single-tree-check {
    flex: 1;
    display: flex;
    align-items: center;
    justify-content: space-between;
    font-size: 14px;
    padding-right: 15px;
    line-height: 26px;
    cursor: pointer !important;
    overflow: hidden;
    white-space: nowrap;
    text-overflow: ellipsis;
  }
  .single-tree-check > div {
    text-align: left;
    &:nth-child(1) {
      flex: 0 0 8% !important;
      margin-right: 0px !important;
    }
    &:nth-child(2) {
      flex: 0 0 90%;
      overflow: hidden;
      width: 100%;
      white-space: nowrap;
      text-overflow: ellipsis;
      div {
        width: 100%;
        overflow: hidden;
        white-space: nowrap;
        text-overflow: ellipsis;
      }
    }
  }

  .singleSelect {
    text-align: left;
    .select-compoent-tree-radio {
      flex: 0 0 10% !important;
      margin-right: 0px !important;
    }
    .name {
      flex: 0 0 90%;
      overflow: hidden;
      width: 100%;
      overflow: hidden;
      white-space: nowrap;
      text-overflow: ellipsis;
    }
  }
  .select-compoent-tree-radio {
    .es-radio__label {
      display: none;
    }
  }

  .companyStyle {
    color: #909399;
    font-size: 12px;
  }

  .searchMorePerson {
    .es-checkbox {
      flex: 0 0 5% !important;
    }
    .tree-check {
      flex: 0 0 80%;
      overflow: hidden;
      width: 100%;
      overflow: hidden;
      white-space: nowrap;
      text-overflow: ellipsis;
      font-size: 14px;
      padding-right: 15px;
      line-height: 26px;
      cursor: pointer !important;
      div {
        width: 100%;
        overflow: hidden;
        white-space: nowrap;
        text-overflow: ellipsis;
      }
    }
  }
  .words {
    display: inline-block;
    border: 1px solid #0975e0;
    font-size: 12px !important;
    line-height: 12px;
    padding: 2px;
    color: #0975e0;
    border-radius: 4px;
    position: relative;
    margin-right: 3px;
  }

  .es-checkbox.is-disabled {
    display: none;
  }

  .select-component-content {
    .select-component-content-row {
      position: relative;
      margin-top: 0px;
      margin-bottom: 0px;
      float: left;
      background-color: $background-cg;
      margin-right: 10px;
      margin-bottom: 8px;
      -webkit-border-radius: 3px;
      -moz-border-radius: 3px;
      -ms-border-radius: 3px;
      -o-border-radius: 3px;
      border-radius: 3px;
      padding: 6px 25px 6px 8px;
      .select-component-content-row-item {
        font-size: '14px';
        .es-icon-circle-close {
          right: 8px;
          top: 11px;
          cursor: pointer;
          position: absolute;
        }
      }
    }
  }

  /*
*只有一级节点 图标时候设置的样式
*/
  .tree-remove-icon {
    width: 0px;
  }
}
.loadTreeData {
  display: block;
  width: 100%;
  height: 30px;
  line-height: 30px;
  text-align: center;
  background: #f0f0f0;
  color: #666666;
}
</style>

---代码如上

核心:

子菜单:layzeMap 建立 map 表,以便与操作回调,更新数据
1级节点:通过滚动到最后一层出发,加载分页数据,合并数据实现一级分页数据请求

子节点树:由于滚轮不好判断我还是采用了点击事件,点击在map表通过id寻找到数据触发load更新子节点数据

代码挖坑点:报错多个根节点....只允许一个根节点....

<es-tree
                    ref="usersTree"
                    id="usersTree"
                    :lazy="true"
                    :load="loadUser"
                    :data="userTreeDataList"
                    :props="defaultProps"
                    :show-checkbox="true"
                    node-key="id"
                    :check-strictly="true"
                    :check-on-click-node="true"
                    @check-change="checkUser"
                  >
                    <template slot-scope="{ node, data }">
                     正确写法:<span class="es-tree-node__label">
                        <span
                          v-if="data.btnType == 'btn'"
                          class="es-tree-node_btn"
                          @click="
                            e => {
                              e.preventDefault()
                              e.stopPropagation()
                              cTreeMore(node, data)
                            }
                          "
                          >{{ node.label }}</span
                        >
                        <span v-else :title="node.label" class="name">
                          <span v-if="data.userMainType && data.userMainType === '2'" class="words">兼</span>{{ node.label }}
                        </span>
                      </span>
            错误写法:
                        <span
                          v-if="data.btnType == 'btn'"
                          class="es-tree-node_btn"
                          @click="
                            e => {
                              e.preventDefault()
                              e.stopPropagation()
                              cTreeMore(node, data)
                            }
                          "
                          >{{ node.label }}</span
                        >
              <span class="es-tree-node__label">
<span v-else :title="node.label" class="name"> <span v-if="data.userMainType && data.userMainType === '2'" class="words">兼</span>{{ node.label }} </span> </span>
</template> </es-tree>

  

<template>
  <es-dialog
    :visible.sync="show"
    :title="$t('templateConfig.applyScope')"
    append-to-body
    :modal-append-to-body="false"
    :close-on-click-modal="false"
    :hide-required-asterisk="true"
    custom-class="chose-wrapper"
    @closed="closeModal"
  >
    <es-row>
      <es-col :span="24">
        <divclass="action-wrapper">
          <es-menu
            :default-active="'org'"
            mode="horizontal"
            @select="
              val=> {
                selectType(val)
              }
            "
            class="tab-wrapper"
          >
            <es-menu-itemindex="org">{{$t('templateConfig.chooseOrg') }}</es-menu-item>
            <es-menu-itemindex="user">{{$t('templateConfig.chooseUser') }}</es-menu-item>
          </es-menu>
          <divclass="chosen-desciption">
            <p>
              <span>{{$t('templateConfig.chosen') }}</span>
              <span>{{orgsNum}}{{$t('templateConfig.orgNum') }}{{usersNum}}{{$t('templateConfig.userNum') }}</span>
            </p>
            <a v-show="allSelections.length" @click="clearAll">{{$t('common.clear') }}</a>
          </div>
        </div>
        <ChosenPanel>
          <templatev-slot:left>
            <div v-show="isUser"v-loading="treeLoading">
              <divclass="search-input-container">
                <es-input
                  v-model="userSearchValue"
                  clearable
                  :placeholder="$t('placeHolder.input')"
                  @keyup.enter.native="searchUser"
                  @click.enter="searchUser"
                  @input="searchUser"
                  ><islot="prefix"class="el-icon-search"
                /></es-input>
              </div>
              <!-- 用户树 -->
              <divclass="checked-tree-container" v-show="!userSearchShow">
                <es-scrollbarref="userTreeBar"style="height:560px">
                  <es-tree
                    ref="usersTree"
                    id="usersTree"
                    :lazy="true"
                    :load="loadUser"
                    :data="userTreeDataList"
                    :props="defaultProps"
                    :show-checkbox="true"
                    node-key="id"
                    :check-strictly="true"
                    :check-on-click-node="true"
                    @check-change="checkUser"
                  >
                    <templateslot-scope="{ node, data }">
                      <spanclass="es-tree-node__label">
                        <span
                          v-if="data.btnType == 'btn'"
                          class="es-tree-node_btn"
                          @click="
                            e=> {
                              e.preventDefault()
                              e.stopPropagation()
                              cTreeMore(node, data)
                            }
                          "
                          >{{node.label}}</span
                        >
                        <spanv-else :title="node.label"class="name">
                          <spanv-if="data.userMainType && data.userMainType === '2'"class="words"></span>{{node.label}}
                        </span>
                      </span>
                    </template>
                  </es-tree>
                  <spanv-if="loadTreeData"class="loadTreeData">{{loadTreeText}}</span>
                </es-scrollbar>
              </div>
              <!-- 搜索结果 -->
              <div v-show="userSearchShow"class="checked-tree-container search-tree-container">
                <es-scrollbar>
                  <es-tree
                    ref="searchUserTree"
                    :data="searchUsers"
                    :props="defaultProps"
                    :show-checkbox="true"
                    node-key="id"
                    class="searchMorePerson"
                    :check-on-click-node="true"
                    @check-change="checkUser"
                  >
                    <templatev-slot="{ node, data }">
                      <divclass="tree-check">
                        <div>
                          <div :title="node.label">
                            <bv-if="data.userMainType && data.userMainType === '2'"class="words"></b>{{node.label}}
                          </div>
                          <div :title="data.companyAndOrganizationName"class="companyStyle">
                            {{data.companyAndOrganizationName}}
                          </div>
                        </div>
                      </div>
                    </template>
                  </es-tree>
                </es-scrollbar>
              </div>
            </div>
            <div v-show="!isUser"v-loading="treeLoading">
              <divclass="search-input-container">
                <es-input
                  v-model="orgSearchValue"
                  clearable
                  :placeholder="$t('placeHolder.input')"
                  @keyup.enter.native="searchOrg"
                  @click.enter="searchOrg"
                  @input="searchOrg"
                  ><islot="prefix"class="el-icon-search"
                /></es-input>
              </div>
              <!-- 组织树 -->
              <divclass="checked-tree-container" v-show="!orgSearchShow">
                <es-scrollbarref="orgsTreeBar"style="height:560px">
                  <es-tree
                    ref="orgsTree"
                    id="orgsTree"
                    :data="treeDataList"
                    :lazy="true"
                    :load="loadOrg"
                    :props="defaultProps"
                    :show-checkbox="true"
                    node-key="id"
                    :check-strictly="true"
                    :check-on-click-node="true"
                    @check-change="checkOrg"
                  >
                    <templateslot-scope="{ node, data }">
                      <spanclass="es-tree-node__label">
                        <span
                          v-if="data.btnType == 'btn'"
                          class="es-tree-node_btn"
                          @click="
                            e=> {
                              e.preventDefault()
                              e.stopPropagation()
                              cTreeMore(node, data)
                            }
                          "
                          >{{node.label}}</span
                        >
                        <spanv-else :title="node.label"class="name">
                          <spanv-if="data.userMainType && data.userMainType === '2'"class="words"></span>{{node.label}}
                        </span>
                      </span>
                    </template>
                  </es-tree>
                  <spanv-if="loadTreeData"class="loadTreeData">{{loadTreeText}}</span>
                </es-scrollbar>
              </div>
              <!-- 搜索结果 -->
              <div v-show="orgSearchShow"class="checked-tree-container search-tree-container">
                <es-scrollbarstyle="height:100%">
                  <es-tree
                    ref="searchOrgTree"
                    :data="searchOrgs"
                    :props="defaultProps"
                    :show-checkbox="true"
                    node-key="id"
                    class="searchMorePerson"
                    :check-on-click-node="true"
                    @check-change="checkOrg"
                  >
                    <templatev-slot="{ node, data }">
                      <divclass="tree-check">
                        <div>
                          <div :title="node.label">
                            <bv-if="data.userMainType && data.userMainType === '2'"class="words"></b>{{node.label}}
                          </div>
                          <div :title="data.companyAndOrganizationName"class="companyStyle">
                            {{data.companyAndOrganizationName}}
                          </div>
                        </div>
                      </div>
                    </template>
                  </es-tree>
                </es-scrollbar>
              </div>
            </div>
          </template>
          <templatev-slot:right>
            <divclass="select-component-content">
              <es-scrollbarstyle="height:100%">
                <divclass="clearfix">
                  <divv-for="(item, index) inallSelections" :key="item.id"class="select-component-content-row">
                    <divclass="select-component-content-row-item">
                      <spanv-if="item.userMainType && item.userMainType === '2'"class="words"></span>
                      <span :title="showSearchTitle(item)">{{showSearchName(item) }}</span>
                      <iclass="es-icon-circle-close" @click="deleteChosen(index)"/>
                    </div>
                  </div>
                </div>
              </es-scrollbar>
            </div>
          </template>
        </ChosenPanel>
      </es-col>
    </es-row>
    <templatev-slot:footer>
      <span>
        <es-buttonplainclass="width60"size="small" @click="closeModal" :loading="loading">{{$t('common.cancel') }}</es-button>
        <es-buttontype="primary"class="width60" :loading="loading"size="small" :disabled="!allSelections.length" @click="selectOK">{{
          $t('common.confirm')
        }}</es-button>
      </span>
    </template>
  </es-dialog>
</template>
<script>
importChosenPanelfrom'@/components/ChosenPanel'
exportdefault {
  name:'SelectPersonOrOrganize',
  components: { ChosenPanel },
  props: {
    chosenData: {
      type:Array,
      default: () => [],
    },
    loading: {
      type:Boolean,
      default:false,
    },
  },
  data() {
    return {
      userTreeDataTotal:null,
      loadTreeData:false,
      loadTreeText:'加载中...',
      treeDataList:null,
      treeDataTotal:null,
      loadChildTree:false,
      userTreeDataList:null,
      currPage:1,
      pageSize:50,
      btn: [],
      isScroll:true,
      layzeMap: [],
      show:false, // dialog展示或隐藏
      activeMenu:'org',
      userSearchValue:'',
      orgSearchValue:'',
      searchUsers: [],
      userSearchShow:false,
      searchOrgs: [],
      orgSearchShow:false,
      defaultProps: {
        id:'id',
        label:'label',
        code:'code',
        isLeaf:'leaf',
        disabled:'disabled',
      },
      selectUsers: [],
      selectOrgs: [],
      allSelections: [],
      treeLoading:false,
    }
  },
  computed: {
    isUser() {
      returnthis.activeMenu === 'user'
    },
    usersNum() {
      returnthis.allSelections?.filter(sel=>sel.isUser)?.length || 0
    },
    orgsNum() {
      returnthis.allSelections?.length - this.usersNum || 0
    },
  },
  mounted() {
    this.show = true
    this.$nextTick(function() {
      this.allSelections = this.chosenData
      this.selectUsers = this.chosenData.filter(data=>data.isUser)
      this.selectOrgs = this.chosenData.filter(data=> !data.isUser)
      this.initCheck()
    })
  },
  methods: {
    initTreeData() {
      this.loadTreeData = false
      this.loadTreeText = '加载中...'
      this.treeDataList = null
      this.treeDataTotal = null
      this.userTreeDataTotal = null
      this.loadChildTree = false
      this.userTreeDataList = null
      this.currPage = 1
      this.pageSize = 50
      this.btn = []
      this.isScroll = true
    },
    selectType(val) {
      this.activeMenu = val
      if (val === 'user') {
        this.layzeMap.forEach((v, k) => {
          if (v.id === 'loadUser') {
            this.treeDataList = null
            this.initTreeData()
            this.loadUser(v.node_zero, v.resolve_zero)
          }
        })
      } elseif (val === 'org') {
        this.layzeMap.forEach((v, k) => {
          if (v.id === 'loadOrg') {
            this.userTreeDataList = null
            this.initTreeData()
            this.loadOrg(v.node_zero, v.resolve_zero)
          }
        })
      }
    },
    deWeightArray(arr) {
      constmap = newMap()
      for (constitemofarr) {
        if (item && !map.has(item.id)) {
          map.set(item.id, item)
        }
      }

      return [...map.values()]
    },
    debounce(fn, wait) {
      lettimer = null

      returnfunction() {
        if (timer !== null) {
          clearTimeout(timer)
        }
        timer = setTimeout(fn, wait)
      }
    },
    getBtnData(keyId, theTotal, total, page, size) {
      if (theTotal < total) {
        return [
          {
            id:keyId,
            code:'btnMore',
            page,
            size,
            leaf:true,
            disabled:true,
            btnType:'btn',
            class:'treeBtn',
            label:'点击加载更多',
          },
        ]
      }

      return [
        {
          id:keyId,
          page,
          size,
          code:'btnNot',
          leaf:true,
          disabled:true,
          btnType:'btn',
          class:'treeBtn',
          label:'没有更多了',
        },
      ]
    },
    asynccTreeMore(node, data) {
      this.layzeMap.length > 0 &&
        this.layzeMap.forEach((item, index) => {
          if (item.id === data.id) {
            item.node_zero.childNodes = []
            if (item.func === 'loadOrg') {
              this.loadOrg(item.node_zero, item.resolve_zero, data.page + 1, data)
            } elseif (item.func === 'loadUser') {
              this.loadUser(item.node_zero, item.resolve_zero, data.page + 1, data)
            }
          }
        })
    },
    // 监听滚动事件
    asyncgetMoreTreeData() {
      this.currPage = this.currPage + 1
      constdata = awaitthis.$API.getPageOrganizationListByPId({
        parentOrganizationId:0,
        organizationTerritory:1,
        currPage:this.currPage,
        pageSize:this.pageSize,
      })
      this.loadTreeData = false
      constcompany = data.list.map(item=> {
        if (this.isUser) {
          return {
            id:item.id,
            label:item.organizationName ? item.organizationName : item.companyName,
            code:item.organizationCode,
            disabled:true,
          }
        }

        return {
          id:item.id,
          label:item.organizationName,
          code:item.organizationCode,
          organizationTerritory:item.organizationTerritory,
          type:item.organizationType,
          parentOrganizationId:item.parentOrganizationId,
          organizationTerritory:item.organizationTerritory,
          isUser:false,
        }
      })
      constdataArr = this.isUser ? this.userTreeDataList.concat(company) : this.treeDataList.concat(company)
      this.isUser ? (this.userTreeDataList = this.deWeightArray(dataArr)) : (this.treeDataList = this.deWeightArray(dataArr))
      this.initCheck()
    },
    handleScroll() {
      lettreeHeight
      letscrollBarEl
      if (!this.isUser) {
        treeHeight = document.getElementById('orgsTree').clientHeight
        scrollBarEl = this.$refs.orgsTreeBar.wrap
      } else {
        treeHeight = document.getElementById('usersTree').clientHeight
        scrollBarEl = this.$refs.userTreeBar.wrap
      }
      constthat = this
      letmaxScrollHeight = parseInt(treeHeight - scrollBarEl.clientHeight)
      scrollBarEl.onscroll = that.debounce(() => {
        if (!that.isScroll) {
          return
        }
        if (
          treeHeight !== that.isUser ? document.getElementById('usersTree').clientHeight : document.getElementById('orgsTree').clientHeight
        ) {
          if (!that.isUser) {
            treeHeight = document.getElementById('orgsTree').clientHeight
            scrollBarEl = that.$refs.orgsTreeBar.wrap
          } else {
            treeHeight = document.getElementById('usersTree').clientHeight
            scrollBarEl = that.$refs.userTreeBar.wrap
          }
          maxScrollHeight = parseInt(treeHeight - scrollBarEl.clientHeight)
        }
        if (
          scrollBarEl.scrollTop === maxScrollHeight ||
          Math.ceil(scrollBarEl.scrollTop) === maxScrollHeight ||
          Math.floor(scrollBarEl.scrollTop) === maxScrollHeight
        ) {
          that.loadTreeData = true
          constlength = that.isUser ? that.userTreeDataList.length : that.treeDataList.length
          consttotal = that.isUser ? that.userTreeDataTotal : that.treeDataTotal
          if (length === total) {
            that.loadTreeText = '没有更多了'
          } else {
            that.debounce(that.getMoreTreeData(), 1000)
          }
        }
      }, 50)
    },
    concatTreeData(list, newData, keyId, isLayze) {
      letisFlag = false
      list.map((item, index) => {
        if (item.id === keyId) {
          if (item.children) {
            item.children = [...item.children, ...newData]
          } else {
            item.children = newData
          }
          isFlag = true
        } else {
          if (!isFlag) {
            if (item.children) {
              this.concatTreeData(item.children, newData, keyId)
            }
          }
        }

        returnitem
      })
      this.treeDataList = list
    },
    initCheck() {
      constuserIds = this.selectUsers.map(item=> {
        returnitem.id
      })
      this.$refs.usersTree.setCheckedKeys(userIds)
      this.$refs.searchUserTree?.setCheckedKeys(userIds)
      constorgIds = this.selectOrgs.map(item=> {
        returnitem.id
      })
      this.$refs.orgsTree.setCheckedKeys(orgIds)
      this.$refs.searchOrgTree?.setCheckedKeys(orgIds)
    },
    showSearchTitle(item) {
      returnitem.isUser ? `${item.label}-${item.organizationName}` : item.label
    },
    showSearchName(item) {
      if (!item.isUser) {
        return`${item.label}`
      }
      constorgName = item.companyAndOrganizationName ? item.companyAndOrganizationName : item.organizationName

      return`${item.label}-${orgName}`
    },
    asyncsearchUser() {
      if (this.userSearchValue) {
        constparams = {
          userName:this.userSearchValue,
          organizationTerritory:1,
          userMainType:'',
        }
        constres = awaitthis.$API.getUserListByUserCodeName(params, { loading: ['treeLoading'], vm:this })
        constdata = res.userList
        letsearchUsers = []
        if (data.length > 0) {
          searchUsers = data.map(item=> {
            item.companyAndOrganizationName = item.organizationName ? `${item.companyName}-${item.organizationName}` : item.companyName

            return {
              id:item.id,
              code:item.realUserCode,
              label:item.userName,
              organizationId:item.organizationId,
              organizationName:item.organizationName ? item.organizationName : item.companyName,
              organizationCode:item.organizationCode,
              companyName:item.companyName,
              organizationTerritory:item.organizationTerritory,
              companyAndOrganizationName:item.companyAndOrganizationName,
              userMainType:item.userMainType,
              userCode:item.realUserCode || item.userCode,
              isUser:true,
            }
          })
        }
        this.searchUsers = searchUsers
        this.userSearchShow = true
        this.initCheck()
      } else {
        this.searchUsers = []
        this.userSearchShow = false
        this.initCheck()
      }
    },
    asyncloadUser(node, resolve, pg, data) {
      constthat = this
      if (node.level === 0) {
        this.layzeMap.push({
          node_zero:node,
          resolve_zero:resolve,
          id:0,
          func:'loadUser',
        })
        constparams = { parentOrganizationId:0, organizationTerritory:'1', currPage:this.currPage, pageSize:this.pageSize }
        constdata = awaitthis.$API.getPageOrganizationListByPId(params, { loading: ['treeLoading'], vm:this })
        this.userTreeDataTotal = data.totalCount
        letcompany = data?.list?.map(item=> {
          return {
            id:item.id,
            label:item.organizationName ? item.organizationName : item.companyName,
            code:item.organizationCode,
            disabled:true,
          }
        })
        company = that.deWeightArray(company)
        letisOrgLaz = false
        that.layzeMap.map((v, k) => {
          if (v.id === 'loadUser') {
            isOrgLaz = true
            v.node_zero = node
            v.resolve_zero = resolve
          }

          returnv
        })
        if (!isOrgLaz) {
          that.layzeMap.push({
            node_zero:node,
            resolve_zero:resolve,
            id:'loadUser',
            func:'loadUser',
          })
        }
        if (that.isUser) {
          that.userTreeDataList = company
          resolve(company)
        } else {
          resolve = []
        }
        setTimeout(() => {
          that.handleScroll('loadNode')
        }, 300)
      } else {
        this.currPage = 1
        this.loadChildTree = true
        lettotal = 0
        constkeyId = node.key
        if (pg) {
          this.isScroll = false
        }
        constdataList = awaitPromise.all([
          this.$API.getPageOrganizationListByPId({
            parentOrganizationId:node.key,
            currPage:pg || this.currPage,
            pageSize:this.pageSize,
          }),
          this.$API.getUserListByOrganizationID({ organizationId:node.key, userMainType:'' }),
        ])
        letcompanys = dataList[0].list
        letuserList = dataList[1].userList
        total = dataList[0].totalCount
        if (companys.length > 0) {
          companys = companys.map(item=> {
            return {
              id:item.id,
              label:item.organizationName ? item.organizationName : item.companyName,
              code:item.organizationCode,
              disabled:true,
            }
          })
        }

        if (userList.length > 0) {
          userList = userList.map(item=> {
            return {
              id:item.id,
              label:item.userName,
              code:item.userMainType === '1' ? item.userCode : item.userParentCode,
              leaf:true,
              disabled:false,
              _is_checked:true,
              organizationId:item.organizationId,
              organizationName:item.organizationName ? item.organizationName : item.companyName,
              companyName:item.companyName,
              organizationCode:item.organizationCode,
              organizationTerritory:item.organizationTerritory,
              userMainType:item.userMainType, // 主兼类型(1主 2兼)
              userCode:item.userParentCode || item.userCode,
            }
          })
        }
        consttheTotal = pg ? (pg + 1) * 50 : 50
        constbtn = this.getBtnData(keyId, theTotal, total, pg ? pg + 1 : 1, this.pageSize)
        letnewData = pg ? [...companys, ...userList] : [...companys, ...userList, ...btn]
        letisId = false
        this.layzeMap.map((v, k) => {
          if (v.id === keyId) {
            isId = true
            if (v.data[v.data.length - 1].btnType === 'btn') {
              v.data.pop()
            }

            v.node_zero = node
            v.resolve_zero = resolve
            newData = [...v.data, ...newData, ...btn]
          }

          returnv
        })
        if (!isId) {
          this.layzeMap.push({
            node_zero:node,
            resolve_zero:resolve,
            id:keyId,
            data:that.deWeightArray(newData),
            func:'loadUser',
          })
        }
        newData = that.deWeightArray(newData)
        if (that.isUser) {
          resolve(newData)
          this.$nextTick(this.initCheck)
        } else {
          resolve([])
        }
        setTimeout(() => {
          that.isScroll = true
        }, 1000)
      }
    },
    checkUser(data, checked) {
      constuserIndex = this.selectUsers.findIndex(item=> {
        returnitem.id === data.id
      })
      constindex = this.allSelections.findIndex(item=> {
        returnitem.id === data.id
      })
      if (checked && userIndex === -1) {
        if (this.multipleLimit && this.selectUsers.length === this.multipleLimit.maxNumber) {
          this.$message.info(this.multipleLimit.message)
          this.selectUsers = [...this.selectUsers] // watch selectUsers 重新设置树选中的值
        } else {
          this.selectUsers.push({ ...data, isUser:true })
          this.allSelections.push({ ...data, isUser:true })
        }
      }
      if (!checked && userIndex !== -1) {
        this.selectUsers.splice(userIndex, 1)
        this.allSelections.splice(index, 1)
      }
    },
    asyncsearchOrg() {
      if (this.orgSearchValue) {
        constdata = awaitthis.$API.getOrganizationListByOrgCodeName(
          {
            organizationName:this.orgSearchValue,
            organizationTerritory:1,
          },
          { loading: ['treeLoading'], vm:this }
        )
        letsearchOrgs = []
        if (data?.length > 0) {
          searchOrgs = data.map(item=> {
            item.companyAndOrganizationName = item.parentOrganizationName
              ? `${item.companyName}-${item.parentOrganizationName}`
              : item.companyName

            return {
              id:item.id,
              code:item.organizationCode,
              label:item.organizationName,
              organizationId:item.parentOrganizationId,
              organizationName:item.parentOrganizationName,
              organizationCode:item.organizationCode,
              companyName:item.companyName,
              companyAndOrganizationName:item.companyAndOrganizationName,
              isUser:false,
            }
          })
        }
        this.searchOrgs = searchOrgs
        this.orgSearchShow = true
        this.initCheck()
      } else {
        this.searchOrgs = []
        this.orgSearchShow = false
        this.initCheck()
      }
    },
    asyncloadOrg(node, resolve, pg, data) {
      constthat = this
      if (node.level === 0) {
        this.layzeMap.push({
          node_zero:node,
          resolve_zero:resolve,
          id:0,
          func:'loadOrg',
        })
        constdata = awaitthis.$API.getPageOrganizationListByPId(
          { parentOrganizationId:0, organizationTerritory:1, currPage:this.currPage, pageSize:this.pageSize },
          { loading: ['treeLoading'], vm:this }
        )
        this.treeDataTotal = data.totalCount
        constcompany = data?.list?.map(item=> {
          return {
            id:item.id,
            label:item.organizationName,
            code:item.organizationCode,
            type:item.organizationType,
            parentOrganizationId:item.parentOrganizationId,
            organizationTerritory:item.organizationTerritory,
            isUser:false,
          }
        })
        letisOrgLaz = false
        that.layzeMap.map((v, k) => {
          if (v.id === 'loadOrg') {
            isOrgLaz = true
            v.node_zero = node
            v.resolve_zero = resolve
          }

          returnv
        })
        if (!isOrgLaz) {
          that.layzeMap.push({
            node_zero:node,
            resolve_zero:resolve,
            id:'loadOrg',
            func:'loadOrg',
          })
        }

        if (!that.isUser) {
          this.treeDataList = that.deWeightArray(company)
          resolve(company)
          this.$nextTick(this.initCheck)
        } else {
          resolve = []
        }

        setTimeout(() => {
          that.handleScroll('loadNode')
        }, 300)
      } else {
        this.currPage = 1
        this.loadChildTree = true
        lettotal = 0
        constkeyId = node.key
        if (pg) {
          this.isScroll = false
        }
        constdata = awaitthis.$API.getPageOrganizationListByPId(
          { parentOrganizationId:node.key, currPage:pg || this.currPage, pageSize:this.pageSize },
          { loading: ['treeLoading'], vm:this }
        )
        total = data.totalCount
        letcompanys = []
        if (data?.list?.length > 0) {
          companys = data?.list?.map(item=> {
            return {
              id:item.id,
              label:item.organizationName,
              code:item.organizationCode,
              type:item.organizationType,
              parentOrganizationId:item.parentOrganizationId,
              organizationTerritory:item.organizationTerritory,
              isUser:false,
            }
          })
        }
        consttheTotal = pg ? (pg + 1) * 50 : 50
        constbtn = this.getBtnData(keyId, theTotal, total, pg ? pg + 1 : 1, this.pageSize)
        letnewData = pg ? [...companys] : [...companys, ...btn]
        // let newData = [...companys, ...persons]
        letisId = false
        this.layzeMap.map((v, k) => {
          if (v.id === keyId) {
            isId = true
            if (v.data[v.data.length - 1].btnType === 'btn') {
              v.data.pop()
            }

            v.node_zero = node
            v.resolve_zero = resolve
            newData = [...v.data, ...newData, ...btn]
          }

          returnv
        })
        if (!isId) {
          this.layzeMap.push({
            node_zero:node,
            resolve_zero:resolve,
            id:keyId,
            data:that.deWeightArray(newData),
            func:'loadOrg',
          })
        }
        newData = that.deWeightArray(newData)
        resolve(newData)
        setTimeout(() => {
          that.isScroll = true
        }, 1000)
        this.$nextTick(this.initCheck)
      }
    },

    checkOrg(data, checked) {
      constorgIndex = this.selectOrgs.findIndex(item=> {
        returnitem.id === data.id
      })
      constselectIndex = this.allSelections.findIndex(item=> {
        returnitem.id === data.id
      })
      if (checked && orgIndex === -1) {
        constuser = { ...data, isUser:false }
        this.selectOrgs.push(user)
        this.allSelections.push(user)
      }
      if (!checked && orgIndex !== -1) {
        this.selectOrgs.splice(orgIndex, 1)
        this.allSelections.splice(selectIndex, 1)
      }
    },

    selectOK() {
      this.$emit('on-save', this.allSelections)
    },

    clearAll() {
      this.allSelections = []
      this.selectUsers = []
      this.selectOrgs = []
      this.initCheck()
    },

    deleteChosen(index) {
      constisUser = this.allSelections[index].isUser
      constarr = isUser ? 'selectUsers' : 'selectOrgs'
      constI = this[arr].findIndex(item=> {
        returnitem.id === this.allSelections[index].id
      })
      this[arr].splice(I, 1)
      this.allSelections.splice(index, 1)
      this.initCheck()
    },

    closeModal() {
      this.$emit('on-close')
    },
  },
}
</script>
<style lang="scss">
@import'@/styles/searchInput.scss';
$background-cg: #f0f2f5;
.chose-wrapper {
  .es-dialog__body {
    padding: 0;
    .action-wrapper {
      display: flex;
      align-items: center;
      .tab-wrapper {
        width: 300px;
        border: none;
        border-right: 1pxsolid#ebeef5;
      }
      .is-active {
        background-color: #fff;
      }
      .chosen-desciption {
        padding: 016px;
        display: flex;
        justify-content: space-between;
        align-items: center;
        flex: 1;

        a {
          color: #1063f2;
          cursor: pointer;
        }

        span:last-of-type {
          color: rgba(153, 153, 153, 0.85);
        }
      }
    }

    .chosen-panel-body-left {
      width: 300px;
    }
  }

  .chosen-panel-body-right {
    flex: 1;
  }

  .search-input-container {
    padding-left: 6px;
  }

  .checked-tree-container {
    //height: 376px;
    overflow-x: hidden;
    .es-scrollbar__wrap {
      margin-bottom: -17px!important;
      margin-right: -17px!important;
      overflow-x: hidden;
    }
  }
  .es-tree-node__label {
    overflow: hidden;
    white-space: nowrap;
    text-overflow: ellipsis;
    .name {
      overflow: hidden;
      white-space: nowrap;
      text-overflow: ellipsis;
    }
  }
  .checked-tree-container.es-tree-node__content {
    cursor: pointer!important;
    overflow: hidden;
    white-space: nowrap;
    text-overflow: ellipsis;
  }

  .search-tree-container {
    .es-tree-node {
      margin-bottom: 15px;
    }
    .es-tree-node__content {
      height: auto;
    }
    .single-tree-check {
      overflow: hidden;
      white-space: nowrap;
      text-overflow: ellipsis;
      .companyStyle {
        overflow: hidden;
        white-space: nowrap;
        text-overflow: ellipsis;
      }
    }
  }

  .es-checkbox.is-disabled + .es-tree-node__label {
    cursor: pointer;
    overflow: hidden;
    white-space: nowrap;
    text-overflow: ellipsis;
    .name {
      overflow: hidden;
      white-space: nowrap;
      text-overflow: ellipsis;
    }
  }
  .checked-tree-container.es-tree-node__content {
    cursor: pointer!important;
    overflow: hidden;
    white-space: nowrap;
    text-overflow: ellipsis;
  }
  .select-compoent-tree-radio {
    .es-radio__label {
      display: none;
    }
  }
  .select-compoent-tree-checkbox {
    .es-radio__label {
      display: none;
    }
  }
  .select-component-content.select-component-content-row.select-component-content-row-item.es-icon-circle-close {
    top: 35%;
  }
  .es-tree-node__content {
    padding-top: 7px!important;
    padding-bottom: 7px!important;
    height: auto!important;
  }
  .select-component-content {
    display: inline-block;
    height: 428px;
    .es-scrollbar__wrap {
      overflow-x: hidden!important;
      margin-bottom: -17px!important;
      margin-right: -17px!important;
      .select-component-content-row-item {
        text-overflow: -o-ellipsis-lastline;
        overflow: hidden;
        text-overflow: ellipsis;
        display: -webkit-box;
        -webkit-line-clamp: 2;
        line-clamp: 2;
        -webkit-box-orient: vertical;
        line-height: 22px;
      }
    }
  }
  .single-tree-check {
    flex: 1;
    display: flex;
    align-items: center;
    justify-content: space-between;
    font-size: 14px;
    padding-right: 15px;
    line-height: 26px;
    cursor: pointer!important;
    overflow: hidden;
    white-space: nowrap;
    text-overflow: ellipsis;
  }
  .single-tree-check > div {
    text-align: left;
    &:nth-child(1) {
      flex: 008%!important;
      margin-right: 0px!important;
    }
    &:nth-child(2) {
      flex: 0090%;
      overflow: hidden;
      width: 100%;
      white-space: nowrap;
      text-overflow: ellipsis;
      div {
        width: 100%;
        overflow: hidden;
        white-space: nowrap;
        text-overflow: ellipsis;
      }
    }
  }

  .singleSelect {
    text-align: left;
    .select-compoent-tree-radio {
      flex: 0010%!important;
      margin-right: 0px!important;
    }
    .name {
      flex: 0090%;
      overflow: hidden;
      width: 100%;
      overflow: hidden;
      white-space: nowrap;
      text-overflow: ellipsis;
    }
  }
  .select-compoent-tree-radio {
    .es-radio__label {
      display: none;
    }
  }

  .companyStyle {
    color: #909399;
    font-size: 12px;
  }

  .searchMorePerson {
    .es-checkbox {
      flex: 005%!important;
    }
    .tree-check {
      flex: 0080%;
      overflow: hidden;
      width: 100%;
      overflow: hidden;
      white-space: nowrap;
      text-overflow: ellipsis;
      font-size: 14px;
      padding-right: 15px;
      line-height: 26px;
      cursor: pointer!important;
      div {
        width: 100%;
        overflow: hidden;
        white-space: nowrap;
        text-overflow: ellipsis;
      }
    }
  }
  .words {
    display: inline-block;
    border: 1pxsolid#0975e0;
    font-size: 12px!important;
    line-height: 12px;
    padding: 2px;
    color: #0975e0;
    border-radius: 4px;
    position: relative;
    margin-right: 3px;
  }

  .es-checkbox.is-disabled {
    display: none;
  }

  .select-component-content {
    .select-component-content-row {
      position: relative;
      margin-top: 0px;
      margin-bottom: 0px;
      float: left;
      background-color: $background-cg;
      margin-right: 10px;
      margin-bottom: 8px;
      -webkit-border-radius: 3px;
      -moz-border-radius: 3px;
      -ms-border-radius: 3px;
      -o-border-radius: 3px;
      border-radius: 3px;
      padding: 6px25px6px8px;
      .select-component-content-row-item {
        font-size: '14px';
        .es-icon-circle-close {
          right: 8px;
          top: 11px;
          cursor: pointer;
          position: absolute;
        }
      }
    }
  }

  /*
*只有一级节点 图标时候设置的样式
*/
  .tree-remove-icon {
    width: 0px;
  }
}
.loadTreeData {
  display: block;
  width: 100%;
  height: 30px;
  line-height: 30px;
  text-align: center;
  background: #f0f0f0;
  color: #666666;
}
</style>