mirror of
https://gh-proxy.org/https://github.com/klinsmaya/SQLBot.git
synced 2026-11-08 01:06:59 +08:00
perf: Lazy loading for third-party platform organization structure
This commit is contained in:
committed by
fit2cloud-chenyw
parent
0b4a765115
commit
faa5c9f2e0
@@ -27,6 +27,7 @@ export const modelApi = {
|
||||
query: (id: number) => request.get(`/system/aimodel/${id}`),
|
||||
setDefault: (id: number) => request.put(`/system/aimodel/default/${id}`),
|
||||
check: (data: any) => request.fetchStream('/system/aimodel/status', data),
|
||||
platform: (id: number) => request.get(`/system/platform/org/${id}`),
|
||||
platform: (id: number, lazy?: number, pid?: string) =>
|
||||
request.get(`/system/platform/org/${id}`, { params: { lazy, pid } }),
|
||||
userSync: (data: any) => request.post(`/system/platform/user/sync`, data),
|
||||
}
|
||||
|
||||
@@ -38,6 +38,7 @@
|
||||
"field_details": "Field Details",
|
||||
"integration": "Platform integration needs to be enabled.",
|
||||
"the_existing_user": "If the user already exists, overwrite the existing user.",
|
||||
"lazy_load": "Lazy Load",
|
||||
"sync_users": "Sync Users",
|
||||
"sync_wechat_users": "Sync WeChat Users",
|
||||
"sync_dingtalk_users": "Sync DingTalk Users",
|
||||
|
||||
@@ -38,6 +38,7 @@
|
||||
"field_details": "필드 세부 정보",
|
||||
"integration": "플랫폼 통합을 활성화해야 합니다.",
|
||||
"the_existing_user": "해당 사용자가 이미 존재하는 경우 기존 사용자를 덮어씁니다.",
|
||||
"lazy_load": "지연 로딩",
|
||||
"sync_users": "사용자 동기화",
|
||||
"sync_wechat_users": "위챗 사용자 동기화",
|
||||
"sync_dingtalk_users": "딩톡 사용자 동기화",
|
||||
|
||||
@@ -38,6 +38,7 @@
|
||||
"field_details": "字段详情",
|
||||
"integration": "需开启平台对接",
|
||||
"the_existing_user": "若用户已存在,覆盖旧用户",
|
||||
"lazy_load": "懒加载",
|
||||
"sync_users": "同步用户",
|
||||
"sync_wechat_users": "同步企业微信用户",
|
||||
"sync_dingtalk_users": "同步钉钉用户",
|
||||
|
||||
@@ -38,6 +38,7 @@
|
||||
"field_details": "欄位詳情",
|
||||
"integration": "需開啟平台對接",
|
||||
"the_existing_user": "若使用者已存在,覆蓋舊使用者",
|
||||
"lazy_load": "懶加載",
|
||||
"sync_users": "同步使用者",
|
||||
"sync_wechat_users": "同步企業微信使用者",
|
||||
"sync_dingtalk_users": "同步釘釘使用者",
|
||||
|
||||
@@ -1,13 +1,17 @@
|
||||
<template>
|
||||
<el-dialog
|
||||
v-model="centerDialogVisible"
|
||||
:title="$t(dialogTitle)"
|
||||
modal-class="sync-user_ding"
|
||||
width="840"
|
||||
>
|
||||
<el-dialog v-model="centerDialogVisible" modal-class="sync-user_ding" width="840">
|
||||
<template #header>
|
||||
<div class="dialog-header">
|
||||
<span style="margin-right: 12px">{{ $t(dialogTitle) }}</span>
|
||||
<el-checkbox v-model="isLazy" class="lazy-checkbox">
|
||||
{{ $t('sync.lazy_load') }}
|
||||
</el-checkbox>
|
||||
</div>
|
||||
</template>
|
||||
<div v-loading="loading" class="flex border" style="height: 428px; border-radius: 6px">
|
||||
<div class="p-16 border-r">
|
||||
<el-input
|
||||
v-if="!isLazy"
|
||||
v-model="search"
|
||||
:validate-event="false"
|
||||
:placeholder="$t('datasource.search')"
|
||||
@@ -20,19 +24,26 @@
|
||||
</el-icon>
|
||||
</template>
|
||||
</el-input>
|
||||
<div class="mt-8 max-height_workspace">
|
||||
<div
|
||||
class="max-height_workspace"
|
||||
:class="{ 'mt-8': !isLazy }"
|
||||
:style="isLazy ? { maxHeight: '100%' } : {}"
|
||||
>
|
||||
<el-tree
|
||||
:key="`${treeKey}-${isLazy}`"
|
||||
ref="organizationUserRef"
|
||||
style="max-width: 426px"
|
||||
class="checkbox-group-block"
|
||||
:data="organizationUserList"
|
||||
:data="isLazy ? EMPTY_DATA : organizationUserList"
|
||||
:filter-node-method="filterNode"
|
||||
show-checkbox
|
||||
:default-checked-keys="defaultCheckedKeys"
|
||||
:props="defaultProps"
|
||||
node-key="id"
|
||||
default-expand-all
|
||||
:default-expand-all="!isLazy"
|
||||
:expand-on-click-node="false"
|
||||
:lazy="isLazy"
|
||||
:load="isLazy ? loadNode : undefined"
|
||||
@check="handleCheck"
|
||||
>
|
||||
<template #default="{ node, data }">
|
||||
@@ -112,16 +123,15 @@
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { ref, computed, watch, nextTick } from 'vue'
|
||||
import { modelApi } from '@/api/system'
|
||||
import { ElLoading } from 'element-plus-secondary'
|
||||
import avatar_personal from '@/assets/svg/avatar_personal.svg'
|
||||
import avatar_organize from '@/assets/svg/avatar_organize.svg'
|
||||
import avatar_personal from '@/assets/svg/avatar_personal.svg'
|
||||
import Close from '@/assets/svg/icon_close_outlined_w.svg'
|
||||
import Search from '@/assets/svg/icon_search-outline_outlined.svg'
|
||||
import type { CheckboxValueType } from 'element-plus-secondary'
|
||||
import type { FilterNodeMethodFunction } from 'element-plus-secondary'
|
||||
import type { CheckboxValueType, FilterNodeMethodFunction } from 'element-plus-secondary'
|
||||
import { ElLoading } from 'element-plus-secondary'
|
||||
import { cloneDeep } from 'lodash-es'
|
||||
import { computed, nextTick, ref, watch } from 'vue'
|
||||
const checkAll = ref(false)
|
||||
const existingUser = ref(false)
|
||||
const isIndeterminate = ref(false)
|
||||
@@ -134,12 +144,17 @@ const defaultCheckedKeys = ref<any[]>([])
|
||||
const defaultProps = {
|
||||
children: 'children',
|
||||
label: 'name',
|
||||
isLeaf: (data: any) => data.options?.is_user,
|
||||
}
|
||||
let rawTree: any = []
|
||||
const organizationUserList = ref<any[]>([])
|
||||
const loading = ref(false)
|
||||
const centerDialogVisible = ref(false)
|
||||
const checkTableList = ref([] as any[])
|
||||
const EMPTY_DATA: any[] = []
|
||||
const isLazy = ref(true)
|
||||
const treeKey = ref(0)
|
||||
const wecomDeptCache = ref(new Map<string, any[]>())
|
||||
|
||||
const workspaceWithKeywords = computed(() => {
|
||||
return workspace.value.filter((ele: any) =>
|
||||
@@ -185,6 +200,21 @@ watch(search, () => {
|
||||
})
|
||||
})
|
||||
|
||||
watch(isLazy, async () => {
|
||||
search.value = ''
|
||||
checkTableList.value = []
|
||||
checkedWorkspace.value = []
|
||||
defaultCheckedKeys.value = []
|
||||
wecomDeptCache.value.clear()
|
||||
loading.value = true
|
||||
const systemWorkspaceList = await modelApi.platform(oid, isLazy.value ? 1 : 0)
|
||||
organizationUserList.value = isLazy.value
|
||||
? stripDeptChildren(systemWorkspaceList.tree || [])
|
||||
: systemWorkspaceList.tree || []
|
||||
rawTree = cloneDeep(systemWorkspaceList.tree)
|
||||
loading.value = false
|
||||
})
|
||||
|
||||
const filterNode: FilterNodeMethodFunction = (value: string, data: any) => {
|
||||
if (!value) return true
|
||||
return data.name.includes(value)
|
||||
@@ -230,7 +260,61 @@ const handleCheckedWorkspaceChange = (value: CheckboxValueType[]) => {
|
||||
}
|
||||
let oid: any = null
|
||||
|
||||
const buildWecomDeptCache = (tree: any[]) => {
|
||||
const cache = new Map<string, any[]>()
|
||||
const stack = [...tree]
|
||||
while (stack.length) {
|
||||
const node = stack.pop()!
|
||||
if (!node.options?.is_user && node.children?.length) {
|
||||
cache.set(
|
||||
node.id,
|
||||
node.children.map((c: any) => ({ ...c, children: [] }))
|
||||
)
|
||||
stack.push(...node.children)
|
||||
}
|
||||
}
|
||||
wecomDeptCache.value = cache
|
||||
}
|
||||
|
||||
const stripDeptChildren = (nodes: any[]) => {
|
||||
return nodes.map((node: any) => {
|
||||
if (!node.options?.is_user) {
|
||||
const { children, ...rest } = node
|
||||
void children
|
||||
return rest
|
||||
}
|
||||
return { ...node }
|
||||
})
|
||||
}
|
||||
|
||||
const loadNode = (node: any, resolve: any) => {
|
||||
if (node.level === 0) {
|
||||
modelApi.platform(oid, 1).then((res: any) => {
|
||||
resolve(stripDeptChildren(res.tree || []))
|
||||
})
|
||||
return
|
||||
}
|
||||
if (oid === 6) {
|
||||
const deptChildren = wecomDeptCache.value.get(node.data.id) || []
|
||||
modelApi.platform(oid, 1, node.data.id).then((res: any) => {
|
||||
resolve(stripDeptChildren([...(res.tree || []), ...deptChildren]))
|
||||
nextTick(() => {
|
||||
organizationUserRef.value?.setChecked(node.data.id, false, true)
|
||||
})
|
||||
})
|
||||
return
|
||||
}
|
||||
modelApi.platform(oid, 1, node.data.id).then((res: any) => {
|
||||
resolve(stripDeptChildren(res.tree || []))
|
||||
nextTick(() => {
|
||||
organizationUserRef.value?.setChecked(node.data.id, false, true)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
const open = async (id: any, title: any) => {
|
||||
isLazy.value = true
|
||||
treeKey.value++
|
||||
dialogTitle.value = title
|
||||
loading.value = true
|
||||
search.value = ''
|
||||
@@ -240,8 +324,15 @@ const open = async (id: any, title: any) => {
|
||||
checkAll.value = false
|
||||
isIndeterminate.value = false
|
||||
const loadingInstance = ElLoading.service({ fullscreen: true })
|
||||
const systemWorkspaceList = await modelApi.platform(id)
|
||||
organizationUserList.value = systemWorkspaceList.tree || []
|
||||
const systemWorkspaceList = await modelApi.platform(id, isLazy.value ? 1 : 0)
|
||||
if (isLazy.value && id === 6) {
|
||||
buildWecomDeptCache(systemWorkspaceList.tree)
|
||||
organizationUserList.value = stripDeptChildren(systemWorkspaceList.tree || [])
|
||||
} else {
|
||||
organizationUserList.value = isLazy.value
|
||||
? stripDeptChildren(systemWorkspaceList.tree || [])
|
||||
: systemWorkspaceList.tree || []
|
||||
}
|
||||
rawTree = cloneDeep(systemWorkspaceList.tree)
|
||||
loadingInstance?.close()
|
||||
loading.value = false
|
||||
@@ -283,6 +374,16 @@ defineExpose({
|
||||
</script>
|
||||
<style lang="less">
|
||||
.sync-user_ding {
|
||||
.dialog-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
.lazy-checkbox {
|
||||
font-size: 12px;
|
||||
color: #8f959e;
|
||||
}
|
||||
}
|
||||
|
||||
.mb-8 {
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user