element-Plus 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">
<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>

浙公网安备 33010602011771号