<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>
- element-Plus element es-tree Plus treeelement-plus element es-tree plus element-plus权限element el-tree element-plus quot element-plus elmessage element element-plus element plus resizeobserver notifications element-plus undelivered element-plus element类型 文件 resizeobserver element-plus exceeded element element-plus组件element功能 element-plus一行element数据