11<template >
2- <el-dialog
3- v-model =" centerDialogVisible"
4- :title =" $t(dialogTitle)"
5- modal-class =" sync-user_ding"
6- width =" 840"
7- >
2+ <el-dialog v-model =" centerDialogVisible" modal-class =" sync-user_ding" width =" 840" >
3+ <template #header >
4+ <div class =" dialog-header" >
5+ <span style =" margin-right : 12px " >{{ $t(dialogTitle) }}</span >
6+ <el-checkbox v-model =" isLazy" class =" lazy-checkbox" >
7+ {{ $t('sync.lazy_load') }}
8+ </el-checkbox >
9+ </div >
10+ </template >
811 <div v-loading =" loading" class =" flex border" style =" height : 428px ; border-radius : 6px " >
912 <div class =" p-16 border-r" >
1013 <el-input
14+ v-if =" !isLazy"
1115 v-model =" search"
1216 :validate-event =" false"
1317 :placeholder =" $t('datasource.search')"
2024 </el-icon >
2125 </template >
2226 </el-input >
23- <div class =" mt-8 max-height_workspace" >
27+ <div
28+ class =" max-height_workspace"
29+ :class =" { 'mt-8': !isLazy }"
30+ :style =" isLazy ? { maxHeight: '100%' } : {}"
31+ >
2432 <el-tree
33+ :key =" `${treeKey}-${isLazy}`"
2534 ref =" organizationUserRef"
2635 style =" max-width : 426px "
2736 class =" checkbox-group-block"
28- :data =" organizationUserList"
37+ :data =" isLazy ? EMPTY_DATA : organizationUserList"
2938 :filter-node-method =" filterNode"
3039 show-checkbox
3140 :default-checked-keys =" defaultCheckedKeys"
3241 :props =" defaultProps"
3342 node-key =" id"
34- default-expand-all
43+ : default-expand-all= " !isLazy "
3544 :expand-on-click-node =" false"
45+ :lazy =" isLazy"
46+ :load =" isLazy ? loadNode : undefined"
3647 @check =" handleCheck"
3748 >
3849 <template #default =" { node , data } " >
112123</template >
113124
114125<script lang="ts" setup>
115- import { ref , computed , watch , nextTick } from ' vue'
116126import { modelApi } from ' @/api/system'
117- import { ElLoading } from ' element-plus-secondary'
118- import avatar_personal from ' @/assets/svg/avatar_personal.svg'
119127import avatar_organize from ' @/assets/svg/avatar_organize.svg'
128+ import avatar_personal from ' @/assets/svg/avatar_personal.svg'
120129import Close from ' @/assets/svg/icon_close_outlined_w.svg'
121130import Search from ' @/assets/svg/icon_search-outline_outlined.svg'
122- import type { CheckboxValueType } from ' element-plus-secondary'
123- import type { FilterNodeMethodFunction } from ' element-plus-secondary'
131+ import type { CheckboxValueType , FilterNodeMethodFunction } from ' element-plus-secondary'
132+ import { ElLoading } from ' element-plus-secondary'
124133import { cloneDeep } from ' lodash-es'
134+ import { computed , nextTick , ref , watch } from ' vue'
125135const checkAll = ref (false )
126136const existingUser = ref (false )
127137const isIndeterminate = ref (false )
@@ -134,12 +144,17 @@ const defaultCheckedKeys = ref<any[]>([])
134144const defaultProps = {
135145 children: ' children' ,
136146 label: ' name' ,
147+ isLeaf : (data : any ) => data .options ?.is_user ,
137148}
138149let rawTree: any = []
139150const organizationUserList = ref <any []>([])
140151const loading = ref (false )
141152const centerDialogVisible = ref (false )
142153const checkTableList = ref ([] as any [])
154+ const EMPTY_DATA: any [] = []
155+ const isLazy = ref (true )
156+ const treeKey = ref (0 )
157+ const wecomDeptCache = ref (new Map <string , any []>())
143158
144159const workspaceWithKeywords = computed (() => {
145160 return workspace .value .filter ((ele : any ) =>
@@ -185,6 +200,21 @@ watch(search, () => {
185200 })
186201})
187202
203+ watch (isLazy , async () => {
204+ search .value = ' '
205+ checkTableList .value = []
206+ checkedWorkspace .value = []
207+ defaultCheckedKeys .value = []
208+ wecomDeptCache .value .clear ()
209+ loading .value = true
210+ const systemWorkspaceList = await modelApi .platform (oid , isLazy .value ? 1 : 0 )
211+ organizationUserList .value = isLazy .value
212+ ? stripDeptChildren (systemWorkspaceList .tree || [])
213+ : systemWorkspaceList .tree || []
214+ rawTree = cloneDeep (systemWorkspaceList .tree )
215+ loading .value = false
216+ })
217+
188218const filterNode: FilterNodeMethodFunction = (value : string , data : any ) => {
189219 if (! value ) return true
190220 return data .name .includes (value )
@@ -230,7 +260,61 @@ const handleCheckedWorkspaceChange = (value: CheckboxValueType[]) => {
230260}
231261let oid: any = null
232262
263+ const buildWecomDeptCache = (tree : any []) => {
264+ const cache = new Map <string , any []>()
265+ const stack = [... tree ]
266+ while (stack .length ) {
267+ const node = stack .pop ()!
268+ if (! node .options ?.is_user && node .children ?.length ) {
269+ cache .set (
270+ node .id ,
271+ node .children .map ((c : any ) => ({ ... c , children: [] }))
272+ )
273+ stack .push (... node .children )
274+ }
275+ }
276+ wecomDeptCache .value = cache
277+ }
278+
279+ const stripDeptChildren = (nodes : any []) => {
280+ return nodes .map ((node : any ) => {
281+ if (! node .options ?.is_user ) {
282+ const { children, ... rest } = node
283+ void children
284+ return rest
285+ }
286+ return { ... node }
287+ })
288+ }
289+
290+ const loadNode = (node : any , resolve : any ) => {
291+ if (node .level === 0 ) {
292+ modelApi .platform (oid , 1 ).then ((res : any ) => {
293+ resolve (stripDeptChildren (res .tree || []))
294+ })
295+ return
296+ }
297+ if (oid === 6 ) {
298+ const deptChildren = wecomDeptCache .value .get (node .data .id ) || []
299+ modelApi .platform (oid , 1 , node .data .id ).then ((res : any ) => {
300+ resolve (stripDeptChildren ([... (res .tree || []), ... deptChildren ]))
301+ nextTick (() => {
302+ organizationUserRef .value ?.setChecked (node .data .id , false , true )
303+ })
304+ })
305+ return
306+ }
307+ modelApi .platform (oid , 1 , node .data .id ).then ((res : any ) => {
308+ resolve (stripDeptChildren (res .tree || []))
309+ nextTick (() => {
310+ organizationUserRef .value ?.setChecked (node .data .id , false , true )
311+ })
312+ })
313+ }
314+
233315const open = async (id : any , title : any ) => {
316+ isLazy .value = true
317+ treeKey .value ++
234318 dialogTitle .value = title
235319 loading .value = true
236320 search .value = ' '
@@ -240,8 +324,15 @@ const open = async (id: any, title: any) => {
240324 checkAll .value = false
241325 isIndeterminate .value = false
242326 const loadingInstance = ElLoading .service ({ fullscreen: true })
243- const systemWorkspaceList = await modelApi .platform (id )
244- organizationUserList .value = systemWorkspaceList .tree || []
327+ const systemWorkspaceList = await modelApi .platform (id , isLazy .value ? 1 : 0 )
328+ if (isLazy .value && id === 6 ) {
329+ buildWecomDeptCache (systemWorkspaceList .tree )
330+ organizationUserList .value = stripDeptChildren (systemWorkspaceList .tree || [])
331+ } else {
332+ organizationUserList .value = isLazy .value
333+ ? stripDeptChildren (systemWorkspaceList .tree || [])
334+ : systemWorkspaceList .tree || []
335+ }
245336 rawTree = cloneDeep (systemWorkspaceList .tree )
246337 loadingInstance ?.close ()
247338 loading .value = false
@@ -283,6 +374,16 @@ defineExpose({
283374 </script >
284375<style lang="less">
285376.sync-user_ding {
377+ .dialog-header {
378+ display : flex ;
379+ align-items : center ;
380+
381+ .lazy-checkbox {
382+ font-size : 12px ;
383+ color : #8f959e ;
384+ }
385+ }
386+
286387 .mb-8 {
287388 margin-bottom : 8px ;
288389 }
0 commit comments