mirror of
https://gitee.com/xiaonuobase/snowy.git
synced 2026-03-22 02:37:16 +08:00
【机构】左侧树加入虚拟滚动,优化业务授权机构逻辑
This commit is contained in:
@@ -1,15 +1,18 @@
|
||||
<template>
|
||||
<XnResizablePanel direction="row" :initial-size="300" :min-size="200" :max-size="500" :md="0">
|
||||
<template #left>
|
||||
<a-tree
|
||||
v-if="treeData.length > 0"
|
||||
v-model:expandedKeys="defaultExpandedKeys"
|
||||
:tree-data="treeData"
|
||||
:field-names="treeFieldNames"
|
||||
:load-data="onLoadData"
|
||||
@select="treeSelect"
|
||||
/>
|
||||
<a-empty v-else :image="Empty.PRESENTED_IMAGE_SIMPLE" />
|
||||
<div ref="treeContainerRef" style="height: 100%">
|
||||
<a-tree
|
||||
v-if="treeData.length > 0"
|
||||
v-model:expandedKeys="defaultExpandedKeys"
|
||||
:tree-data="treeData"
|
||||
:field-names="treeFieldNames"
|
||||
:load-data="onLoadData"
|
||||
:height="treeHeight"
|
||||
@select="treeSelect"
|
||||
/>
|
||||
<a-empty v-else :image="Empty.PRESENTED_IMAGE_SIMPLE" />
|
||||
</div>
|
||||
</template>
|
||||
<template #right>
|
||||
<a-form ref="searchFormRef" :model="searchFormState">
|
||||
@@ -116,6 +119,7 @@
|
||||
<script setup name="bizOrg">
|
||||
import { Empty } from 'ant-design-vue'
|
||||
import { isEmpty } from 'lodash-es'
|
||||
import { triggerRef, onMounted, onActivated, onUnmounted } from 'vue'
|
||||
import bizOrgApi from '@/api/biz/bizOrgApi'
|
||||
import Form from './form.vue'
|
||||
import CopyForm from './copyForm.vue'
|
||||
@@ -168,10 +172,31 @@
|
||||
const treeData = ref([])
|
||||
// 替换treeNode 中 title,key,children
|
||||
const treeFieldNames = { children: 'children', title: 'name', key: 'id' }
|
||||
// 树容器高度自适应
|
||||
const treeContainerRef = ref(null)
|
||||
const treeHeight = ref(0)
|
||||
let resizeObserver = null
|
||||
const calcTreeHeight = () => {
|
||||
if (treeContainerRef.value) {
|
||||
treeHeight.value = treeContainerRef.value.clientHeight
|
||||
}
|
||||
}
|
||||
onMounted(() => {
|
||||
calcTreeHeight()
|
||||
if (treeContainerRef.value) {
|
||||
resizeObserver = new ResizeObserver(calcTreeHeight)
|
||||
resizeObserver.observe(treeContainerRef.value)
|
||||
}
|
||||
})
|
||||
onActivated(calcTreeHeight)
|
||||
onUnmounted(() => {
|
||||
if (resizeObserver) {
|
||||
resizeObserver.disconnect()
|
||||
}
|
||||
})
|
||||
|
||||
// 表格查询 返回 Promise 对象
|
||||
const loadData = (parameter) => {
|
||||
loadTreeData()
|
||||
return bizOrgApi.orgPage(Object.assign(parameter, searchFormState.value)).then((res) => {
|
||||
return res
|
||||
})
|
||||
@@ -200,10 +225,11 @@
|
||||
}
|
||||
})
|
||||
}
|
||||
loadTreeData()
|
||||
// 懒加载子节点
|
||||
const onLoadData = (treeNode) => {
|
||||
return new Promise((resolve) => {
|
||||
if (treeNode.dataRef.children) {
|
||||
if (treeNode.dataRef.children || treeNode.dataRef.isLeaf) {
|
||||
resolve()
|
||||
return
|
||||
}
|
||||
@@ -218,7 +244,7 @@
|
||||
isLeaf: item.isLeaf === undefined ? false : item.isLeaf
|
||||
}
|
||||
})
|
||||
treeData.value = [...treeData.value]
|
||||
triggerRef(treeData)
|
||||
resolve()
|
||||
})
|
||||
})
|
||||
|
||||
@@ -1,15 +1,18 @@
|
||||
<template>
|
||||
<XnResizablePanel direction="row" :initial-size="300" :min-size="200" :max-size="500" :md="0">
|
||||
<template #left>
|
||||
<a-tree
|
||||
v-if="treeData.length > 0"
|
||||
v-model:expandedKeys="defaultExpandedKeys"
|
||||
:tree-data="treeData"
|
||||
:field-names="treeFieldNames"
|
||||
:load-data="onLoadData"
|
||||
@select="treeSelect"
|
||||
/>
|
||||
<a-empty v-else :image="Empty.PRESENTED_IMAGE_SIMPLE" />
|
||||
<div ref="treeContainerRef" style="height: 100%">
|
||||
<a-tree
|
||||
v-if="treeData.length > 0"
|
||||
v-model:expandedKeys="defaultExpandedKeys"
|
||||
:tree-data="treeData"
|
||||
:field-names="treeFieldNames"
|
||||
:load-data="onLoadData"
|
||||
:height="treeHeight"
|
||||
@select="treeSelect"
|
||||
/>
|
||||
<a-empty v-else :image="Empty.PRESENTED_IMAGE_SIMPLE" />
|
||||
</div>
|
||||
</template>
|
||||
<template #right>
|
||||
<a-form ref="searchFormRef" :model="searchFormState">
|
||||
@@ -107,6 +110,7 @@
|
||||
<script setup name="bizPosition">
|
||||
import { Empty } from 'ant-design-vue'
|
||||
import { isEmpty } from 'lodash-es'
|
||||
import { triggerRef, onMounted, onActivated, onUnmounted } from 'vue'
|
||||
import bizPositionApi from '@/api/biz/bizPositionApi'
|
||||
import bizOrgApi from '@/api/biz/bizOrgApi'
|
||||
import Form from './form.vue'
|
||||
@@ -159,6 +163,28 @@
|
||||
const treeData = ref([])
|
||||
// 替换treeNode 中 title,key,children
|
||||
const treeFieldNames = { children: 'children', title: 'name', key: 'id' }
|
||||
// 树容器高度自适应
|
||||
const treeContainerRef = ref(null)
|
||||
const treeHeight = ref(0)
|
||||
let resizeObserver = null
|
||||
const calcTreeHeight = () => {
|
||||
if (treeContainerRef.value) {
|
||||
treeHeight.value = treeContainerRef.value.clientHeight
|
||||
}
|
||||
}
|
||||
onMounted(() => {
|
||||
calcTreeHeight()
|
||||
if (treeContainerRef.value) {
|
||||
resizeObserver = new ResizeObserver(calcTreeHeight)
|
||||
resizeObserver.observe(treeContainerRef.value)
|
||||
}
|
||||
})
|
||||
onActivated(calcTreeHeight)
|
||||
onUnmounted(() => {
|
||||
if (resizeObserver) {
|
||||
resizeObserver.disconnect()
|
||||
}
|
||||
})
|
||||
|
||||
// 表格查询 返回 Promise 对象
|
||||
const loadData = (parameter) => {
|
||||
@@ -210,7 +236,7 @@
|
||||
isLeaf: item.isLeaf === undefined ? false : item.isLeaf
|
||||
}
|
||||
})
|
||||
treeData.value = [...treeData.value]
|
||||
triggerRef(treeData)
|
||||
resolve()
|
||||
})
|
||||
.catch(() => {
|
||||
|
||||
@@ -1,15 +1,18 @@
|
||||
<template>
|
||||
<XnResizablePanel direction="row" :initial-size="300" :min-size="200" :max-size="500" :md="0">
|
||||
<template #left>
|
||||
<a-tree
|
||||
v-if="treeData.length > 0"
|
||||
v-model:expandedKeys="defaultExpandedKeys"
|
||||
:tree-data="treeData"
|
||||
:field-names="treeFieldNames"
|
||||
:load-data="onLoadData"
|
||||
@select="treeSelect"
|
||||
/>
|
||||
<a-empty v-else :image="Empty.PRESENTED_IMAGE_SIMPLE" />
|
||||
<div ref="treeContainerRef" style="height: 100%">
|
||||
<a-tree
|
||||
v-if="treeData.length > 0"
|
||||
v-model:expandedKeys="defaultExpandedKeys"
|
||||
:tree-data="treeData"
|
||||
:field-names="treeFieldNames"
|
||||
:load-data="onLoadData"
|
||||
:height="treeHeight"
|
||||
@select="treeSelect"
|
||||
/>
|
||||
<a-empty v-else :image="Empty.PRESENTED_IMAGE_SIMPLE" />
|
||||
</div>
|
||||
</template>
|
||||
<template #right>
|
||||
<a-form ref="searchFormRef" :model="searchFormState">
|
||||
@@ -169,6 +172,7 @@
|
||||
<script setup name="bizUser">
|
||||
import { message, Empty } from 'ant-design-vue'
|
||||
import { isEmpty } from 'lodash-es'
|
||||
import { triggerRef, onMounted, onActivated, onUnmounted } from 'vue'
|
||||
import tool from '@/utils/tool'
|
||||
import downloadUtil from '@/utils/downloadUtil'
|
||||
import bizUserApi from '@/api/biz/bizUserApi'
|
||||
@@ -235,6 +239,28 @@
|
||||
const RoleSelectorPlusRef = ref()
|
||||
const selectedRecord = ref({})
|
||||
const loading = ref(false)
|
||||
// 树容器高度自适应
|
||||
const treeContainerRef = ref(null)
|
||||
const treeHeight = ref(0)
|
||||
let resizeObserver = null
|
||||
const calcTreeHeight = () => {
|
||||
if (treeContainerRef.value) {
|
||||
treeHeight.value = treeContainerRef.value.clientHeight
|
||||
}
|
||||
}
|
||||
onMounted(() => {
|
||||
calcTreeHeight()
|
||||
if (treeContainerRef.value) {
|
||||
resizeObserver = new ResizeObserver(calcTreeHeight)
|
||||
resizeObserver.observe(treeContainerRef.value)
|
||||
}
|
||||
})
|
||||
onActivated(calcTreeHeight)
|
||||
onUnmounted(() => {
|
||||
if (resizeObserver) {
|
||||
resizeObserver.disconnect()
|
||||
}
|
||||
})
|
||||
// 表格查询 返回 Promise 对象
|
||||
const loadData = (parameter) => {
|
||||
return bizUserApi.userPage(Object.assign(parameter, searchFormState.value)).then((res) => {
|
||||
@@ -285,7 +311,7 @@
|
||||
isLeaf: item.isLeaf === undefined ? false : item.isLeaf
|
||||
}
|
||||
})
|
||||
treeData.value = [...treeData.value]
|
||||
triggerRef(treeData)
|
||||
resolve()
|
||||
})
|
||||
.catch(() => {
|
||||
|
||||
@@ -1,15 +1,18 @@
|
||||
<template>
|
||||
<XnResizablePanel direction="row" :initial-size="300" :min-size="200" :max-size="500" :md="0">
|
||||
<template #left>
|
||||
<a-tree
|
||||
v-if="treeData.length > 0"
|
||||
v-model:expandedKeys="defaultExpandedKeys"
|
||||
:tree-data="treeData"
|
||||
:field-names="treeFieldNames"
|
||||
:load-data="onLoadData"
|
||||
@select="treeSelect"
|
||||
/>
|
||||
<a-empty v-else :image="Empty.PRESENTED_IMAGE_SIMPLE" />
|
||||
<div ref="treeContainerRef" style="height: 100%">
|
||||
<a-tree
|
||||
v-if="treeData.length > 0"
|
||||
v-model:expandedKeys="defaultExpandedKeys"
|
||||
:tree-data="treeData"
|
||||
:field-names="treeFieldNames"
|
||||
:load-data="onLoadData"
|
||||
:height="treeHeight"
|
||||
@select="treeSelect"
|
||||
/>
|
||||
<a-empty v-else :image="Empty.PRESENTED_IMAGE_SIMPLE" />
|
||||
</div>
|
||||
</template>
|
||||
<template #right>
|
||||
<a-form ref="searchFormRef" :model="searchFormState">
|
||||
@@ -115,6 +118,7 @@
|
||||
<script setup name="sysOrg">
|
||||
import { Empty } from 'ant-design-vue'
|
||||
import { isEmpty } from 'lodash-es'
|
||||
import { triggerRef, onMounted, onActivated, onUnmounted } from 'vue'
|
||||
import orgApi from '@/api/sys/orgApi'
|
||||
import Form from './form.vue'
|
||||
import CopyForm from './copyForm.vue'
|
||||
@@ -165,10 +169,31 @@
|
||||
const treeData = ref([])
|
||||
// 替换treeNode 中 title,key,children
|
||||
const treeFieldNames = { children: 'children', title: 'name', key: 'id' }
|
||||
// 树容器高度自适应
|
||||
const treeContainerRef = ref(null)
|
||||
const treeHeight = ref(0)
|
||||
let resizeObserver = null
|
||||
const calcTreeHeight = () => {
|
||||
if (treeContainerRef.value) {
|
||||
treeHeight.value = treeContainerRef.value.clientHeight
|
||||
}
|
||||
}
|
||||
onMounted(() => {
|
||||
calcTreeHeight()
|
||||
if (treeContainerRef.value) {
|
||||
resizeObserver = new ResizeObserver(calcTreeHeight)
|
||||
resizeObserver.observe(treeContainerRef.value)
|
||||
}
|
||||
})
|
||||
onActivated(calcTreeHeight)
|
||||
onUnmounted(() => {
|
||||
if (resizeObserver) {
|
||||
resizeObserver.disconnect()
|
||||
}
|
||||
})
|
||||
|
||||
// 表格查询 返回 Promise 对象
|
||||
const loadData = (parameter) => {
|
||||
loadTreeData()
|
||||
return orgApi.orgPage(Object.assign(parameter, searchFormState.value)).then((res) => {
|
||||
return res
|
||||
})
|
||||
@@ -197,10 +222,11 @@
|
||||
}
|
||||
})
|
||||
}
|
||||
loadTreeData()
|
||||
// 懒加载子节点
|
||||
const onLoadData = (treeNode) => {
|
||||
return new Promise((resolve) => {
|
||||
if (treeNode.dataRef.children) {
|
||||
if (treeNode.dataRef.children || treeNode.dataRef.isLeaf) {
|
||||
resolve()
|
||||
return
|
||||
}
|
||||
@@ -215,7 +241,7 @@
|
||||
isLeaf: item.isLeaf === undefined ? false : item.isLeaf
|
||||
}
|
||||
})
|
||||
treeData.value = [...treeData.value]
|
||||
triggerRef(treeData)
|
||||
resolve()
|
||||
})
|
||||
})
|
||||
|
||||
@@ -1,15 +1,18 @@
|
||||
<template>
|
||||
<XnResizablePanel direction="row" :initial-size="300" :min-size="200" :max-size="500" :md="0">
|
||||
<template #left>
|
||||
<a-tree
|
||||
v-if="treeData.length > 0"
|
||||
v-model:expandedKeys="defaultExpandedKeys"
|
||||
:tree-data="treeData"
|
||||
:field-names="treeFieldNames"
|
||||
:load-data="onLoadData"
|
||||
@select="treeSelect"
|
||||
/>
|
||||
<a-empty v-else :image="Empty.PRESENTED_IMAGE_SIMPLE" />
|
||||
<div ref="treeContainerRef" style="height: 100%">
|
||||
<a-tree
|
||||
v-if="treeData.length > 0"
|
||||
v-model:expandedKeys="defaultExpandedKeys"
|
||||
:tree-data="treeData"
|
||||
:field-names="treeFieldNames"
|
||||
:load-data="onLoadData"
|
||||
:height="treeHeight"
|
||||
@select="treeSelect"
|
||||
/>
|
||||
<a-empty v-else :image="Empty.PRESENTED_IMAGE_SIMPLE" />
|
||||
</div>
|
||||
</template>
|
||||
<template #right>
|
||||
<a-form ref="searchFormRef" :model="searchFormState">
|
||||
@@ -107,6 +110,7 @@
|
||||
<script setup name="sysPosition">
|
||||
import { Empty } from 'ant-design-vue'
|
||||
import { isEmpty } from 'lodash-es'
|
||||
import { triggerRef, onMounted, onActivated, onUnmounted } from 'vue'
|
||||
import positionApi from '@/api/sys/positionApi'
|
||||
import orgApi from '@/api/sys/orgApi'
|
||||
import Form from './form.vue'
|
||||
@@ -156,6 +160,28 @@
|
||||
const treeData = ref([])
|
||||
// 替换treeNode 中 title,key,children
|
||||
const treeFieldNames = { children: 'children', title: 'name', key: 'id' }
|
||||
// 树容器高度自适应
|
||||
const treeContainerRef = ref(null)
|
||||
const treeHeight = ref(0)
|
||||
let resizeObserver = null
|
||||
const calcTreeHeight = () => {
|
||||
if (treeContainerRef.value) {
|
||||
treeHeight.value = treeContainerRef.value.clientHeight
|
||||
}
|
||||
}
|
||||
onMounted(() => {
|
||||
calcTreeHeight()
|
||||
if (treeContainerRef.value) {
|
||||
resizeObserver = new ResizeObserver(calcTreeHeight)
|
||||
resizeObserver.observe(treeContainerRef.value)
|
||||
}
|
||||
})
|
||||
onActivated(calcTreeHeight)
|
||||
onUnmounted(() => {
|
||||
if (resizeObserver) {
|
||||
resizeObserver.disconnect()
|
||||
}
|
||||
})
|
||||
|
||||
// 表格查询 返回 Promise 对象
|
||||
const loadData = (parameter) => {
|
||||
@@ -188,7 +214,7 @@
|
||||
// 懒加载子节点
|
||||
const onLoadData = (treeNode) => {
|
||||
return new Promise((resolve) => {
|
||||
if (treeNode.dataRef.children) {
|
||||
if (treeNode.dataRef.children || treeNode.dataRef.isLeaf) {
|
||||
resolve()
|
||||
return
|
||||
}
|
||||
@@ -203,7 +229,7 @@
|
||||
isLeaf: item.isLeaf === undefined ? false : item.isLeaf
|
||||
}
|
||||
})
|
||||
treeData.value = [...treeData.value]
|
||||
triggerRef(treeData)
|
||||
resolve()
|
||||
})
|
||||
})
|
||||
|
||||
@@ -1,15 +1,18 @@
|
||||
<template>
|
||||
<XnResizablePanel direction="row" :initial-size="300" :min-size="200" :max-size="500" :md="0">
|
||||
<template #left>
|
||||
<a-tree
|
||||
v-if="treeData.length > 0"
|
||||
v-model:expandedKeys="defaultExpandedKeys"
|
||||
:tree-data="treeData"
|
||||
:field-names="treeFieldNames"
|
||||
:load-data="onLoadData"
|
||||
@select="treeSelect"
|
||||
/>
|
||||
<a-empty v-else :image="Empty.PRESENTED_IMAGE_SIMPLE" />
|
||||
<div ref="treeContainerRef" style="height: 100%">
|
||||
<a-tree
|
||||
v-if="treeData.length > 0"
|
||||
v-model:expandedKeys="defaultExpandedKeys"
|
||||
:tree-data="treeData"
|
||||
:field-names="treeFieldNames"
|
||||
:load-data="onLoadData"
|
||||
:height="treeHeight"
|
||||
@select="treeSelect"
|
||||
/>
|
||||
<a-empty v-else :image="Empty.PRESENTED_IMAGE_SIMPLE" />
|
||||
</div>
|
||||
</template>
|
||||
<template #right>
|
||||
<a-form ref="searchFormRef" :model="searchFormState">
|
||||
@@ -144,6 +147,7 @@
|
||||
<script setup name="sysRole">
|
||||
import { Empty } from 'ant-design-vue'
|
||||
import { isEmpty } from 'lodash-es'
|
||||
import { triggerRef, onMounted, onActivated, onUnmounted } from 'vue'
|
||||
import roleApi from '@/api/sys/roleApi'
|
||||
import orgApi from '@/api/sys/orgApi'
|
||||
import GrantResourceForm from './grantResourceForm.vue'
|
||||
@@ -202,6 +206,28 @@
|
||||
const treeFieldNames = { children: 'children', title: 'name', key: 'id' }
|
||||
// 记录数据
|
||||
const recordCacheData = ref({})
|
||||
// 树容器高度自适应
|
||||
const treeContainerRef = ref(null)
|
||||
const treeHeight = ref(0)
|
||||
let resizeObserver = null
|
||||
const calcTreeHeight = () => {
|
||||
if (treeContainerRef.value) {
|
||||
treeHeight.value = treeContainerRef.value.clientHeight
|
||||
}
|
||||
}
|
||||
onMounted(() => {
|
||||
calcTreeHeight()
|
||||
if (treeContainerRef.value) {
|
||||
resizeObserver = new ResizeObserver(calcTreeHeight)
|
||||
resizeObserver.observe(treeContainerRef.value)
|
||||
}
|
||||
})
|
||||
onActivated(calcTreeHeight)
|
||||
onUnmounted(() => {
|
||||
if (resizeObserver) {
|
||||
resizeObserver.disconnect()
|
||||
}
|
||||
})
|
||||
|
||||
// 表格查询 返回 Promise 对象
|
||||
const loadData = (parameter) => {
|
||||
@@ -268,7 +294,7 @@
|
||||
isLeaf: item.isLeaf === undefined ? false : item.isLeaf
|
||||
}
|
||||
})
|
||||
treeData.value = [...treeData.value]
|
||||
triggerRef(treeData)
|
||||
resolve()
|
||||
})
|
||||
.catch(() => {
|
||||
|
||||
@@ -1,15 +1,18 @@
|
||||
<template>
|
||||
<XnResizablePanel direction="row" :initial-size="300" :min-size="200" :max-size="500" :md="0">
|
||||
<template #left>
|
||||
<a-tree
|
||||
v-if="treeData.length > 0"
|
||||
v-model:expandedKeys="defaultExpandedKeys"
|
||||
:tree-data="treeData"
|
||||
:field-names="treeFieldNames"
|
||||
:load-data="onLoadData"
|
||||
@select="treeSelect"
|
||||
/>
|
||||
<a-empty v-else :image="Empty.PRESENTED_IMAGE_SIMPLE" />
|
||||
<div ref="treeContainerRef" style="height: 100%">
|
||||
<a-tree
|
||||
v-if="treeData.length > 0"
|
||||
v-model:expandedKeys="defaultExpandedKeys"
|
||||
:tree-data="treeData"
|
||||
:field-names="treeFieldNames"
|
||||
:load-data="onLoadData"
|
||||
:height="treeHeight"
|
||||
@select="treeSelect"
|
||||
/>
|
||||
<a-empty v-else :image="Empty.PRESENTED_IMAGE_SIMPLE" />
|
||||
</div>
|
||||
</template>
|
||||
<template #right>
|
||||
<a-form ref="searchFormRef" :model="searchFormState">
|
||||
@@ -187,6 +190,7 @@
|
||||
<script setup name="sysUser">
|
||||
import { message, Empty } from 'ant-design-vue'
|
||||
import { isEmpty } from 'lodash-es'
|
||||
import { triggerRef, onMounted, onActivated, onUnmounted } from 'vue'
|
||||
import tool from '@/utils/tool'
|
||||
import downloadUtil from '@/utils/downloadUtil'
|
||||
import userApi from '@/api/sys/userApi'
|
||||
@@ -256,6 +260,28 @@
|
||||
const ImpExpRef = ref()
|
||||
const grantResourceFormRef = ref()
|
||||
const grantPermissionFormRef = ref()
|
||||
// 树容器高度自适应
|
||||
const treeContainerRef = ref(null)
|
||||
const treeHeight = ref(0)
|
||||
let resizeObserver = null
|
||||
const calcTreeHeight = () => {
|
||||
if (treeContainerRef.value) {
|
||||
treeHeight.value = treeContainerRef.value.clientHeight
|
||||
}
|
||||
}
|
||||
onMounted(() => {
|
||||
calcTreeHeight()
|
||||
if (treeContainerRef.value) {
|
||||
resizeObserver = new ResizeObserver(calcTreeHeight)
|
||||
resizeObserver.observe(treeContainerRef.value)
|
||||
}
|
||||
})
|
||||
onActivated(calcTreeHeight)
|
||||
onUnmounted(() => {
|
||||
if (resizeObserver) {
|
||||
resizeObserver.disconnect()
|
||||
}
|
||||
})
|
||||
// 表格查询 返回 Promise 对象
|
||||
const loadData = (parameter) => {
|
||||
return userApi.userPage(Object.assign(parameter, searchFormState.value)).then((res) => {
|
||||
@@ -282,7 +308,7 @@
|
||||
// 懒加载子节点
|
||||
const onLoadData = (treeNode) => {
|
||||
return new Promise((resolve) => {
|
||||
if (treeNode.dataRef.children) {
|
||||
if (treeNode.dataRef.children || treeNode.dataRef.isLeaf) {
|
||||
resolve()
|
||||
return
|
||||
}
|
||||
@@ -297,7 +323,7 @@
|
||||
isLeaf: item.isLeaf === undefined ? false : item.isLeaf
|
||||
}
|
||||
})
|
||||
treeData.value = [...treeData.value]
|
||||
triggerRef(treeData)
|
||||
resolve()
|
||||
})
|
||||
})
|
||||
|
||||
@@ -139,38 +139,52 @@ public class BizOrgServiceImpl extends ServiceImpl<BizOrgMapper, BizOrg> impleme
|
||||
@Override
|
||||
public List<JSONObject> treeLazy(BizOrgTreeLazyParam bizOrgTreeLazyParam) {
|
||||
String parentId = ObjectUtil.isNotEmpty(bizOrgTreeLazyParam.getParentId()) ? bizOrgTreeLazyParam.getParentId() : "0";
|
||||
// 校验数据范围
|
||||
List<String> loginUserDataScope = StpLoginUserUtil.getLoginUserDataScope();
|
||||
|
||||
// 获取所有机构
|
||||
List<BizOrg> allOrgList = this.getAllOrgList();
|
||||
Set<String> visibleOrgIds = null;
|
||||
|
||||
// 如果数据范围不为空,则计算可见机构ID集合(包含自身及其所有父级)
|
||||
if (ObjectUtil.isNotEmpty(loginUserDataScope)) {
|
||||
Set<BizOrg> bizOrgSet = CollectionUtil.newHashSet();
|
||||
loginUserDataScope.forEach(orgId -> bizOrgSet.addAll(this.getParentListById(allOrgList, orgId, true)));
|
||||
visibleOrgIds = bizOrgSet.stream().map(BizOrg::getId).collect(Collectors.toSet());
|
||||
}
|
||||
|
||||
// 过滤出当前父级下的可见子级
|
||||
final Set<String> finalVisibleOrgIds = visibleOrgIds;
|
||||
List<BizOrg> sysOrgList = allOrgList.stream()
|
||||
.filter(bizOrg -> bizOrg.getParentId().equals(parentId))
|
||||
.filter(bizOrg -> finalVisibleOrgIds == null || finalVisibleOrgIds.contains(bizOrg.getId()))
|
||||
.sorted(Comparator.comparingInt(BizOrg::getSortCode).thenComparing(BizOrg::getId))
|
||||
.collect(Collectors.toList());
|
||||
|
||||
if (ObjectUtil.isEmpty(sysOrgList)) {
|
||||
if (ObjectUtil.isEmpty(loginUserDataScope)) {
|
||||
return CollectionUtil.newArrayList();
|
||||
}
|
||||
|
||||
// 判断这些机构是否还有可见子机构
|
||||
return sysOrgList.stream().map(bizOrg -> {
|
||||
JSONObject jsonObject = JSONUtil.parseObj(bizOrg);
|
||||
// 计算是否有可见的子节点
|
||||
boolean hasChildren = allOrgList.stream()
|
||||
.anyMatch(item -> item.getParentId().equals(bizOrg.getId()) && (finalVisibleOrgIds == null || finalVisibleOrgIds.contains(item.getId())));
|
||||
// 获取所有机构
|
||||
List<BizOrg> allOrgList = this.getAllOrgList();
|
||||
|
||||
// 构建索引,避免重复线性遍历(O(N) 一次性构建)
|
||||
Map<String, BizOrg> orgById = allOrgList.stream()
|
||||
.collect(Collectors.toMap(BizOrg::getId, org -> org, (a, b) -> a));
|
||||
Map<String, List<BizOrg>> childrenByParentId = allOrgList.stream()
|
||||
.collect(Collectors.groupingBy(BizOrg::getParentId));
|
||||
|
||||
// 计算可见机构ID集合(包含自身及其所有父级),使用索引将复杂度从 O(M*N*D) 降至 O(M*D)
|
||||
Set<String> visibleOrgIds = new HashSet<>();
|
||||
for (String orgId : loginUserDataScope) {
|
||||
if (orgById.containsKey(orgId)) {
|
||||
visibleOrgIds.add(orgId);
|
||||
// 向上遍历添加所有父级
|
||||
String currentId = orgById.get(orgId).getParentId();
|
||||
while (ObjectUtil.isNotEmpty(currentId) && !"0".equals(currentId) && orgById.containsKey(currentId)) {
|
||||
if (!visibleOrgIds.add(currentId)) {
|
||||
break; // 已经添加过,停止遍历
|
||||
}
|
||||
currentId = orgById.get(currentId).getParentId();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 过滤出当前父级下的可见子级(使用 parentId 索引,O(K) 而非 O(N))
|
||||
List<BizOrg> childList = childrenByParentId.getOrDefault(parentId, Collections.emptyList()).stream()
|
||||
.filter(bizOrg -> visibleOrgIds.contains(bizOrg.getId()))
|
||||
.sorted(Comparator.comparingInt(BizOrg::getSortCode).thenComparing(BizOrg::getId))
|
||||
.collect(Collectors.toList());
|
||||
|
||||
if (ObjectUtil.isEmpty(childList)) {
|
||||
return CollectionUtil.newArrayList();
|
||||
}
|
||||
|
||||
// 判断这些机构是否还有可见子机构(使用 parentId 索引,O(1) 查找子节点列表)
|
||||
return childList.stream().map(bizOrg -> {
|
||||
JSONObject jsonObject = JSONUtil.parseObj(bizOrg);
|
||||
List<BizOrg> subChildren = childrenByParentId.getOrDefault(bizOrg.getId(), Collections.emptyList());
|
||||
boolean hasChildren = subChildren.stream().anyMatch(item -> visibleOrgIds.contains(item.getId()));
|
||||
jsonObject.set("isLeaf", !hasChildren);
|
||||
return jsonObject;
|
||||
}).collect(Collectors.toList());
|
||||
|
||||
Reference in New Issue
Block a user