【更新】机构大数据优化(待完善)

This commit is contained in:
xuyuxiang
2026-02-25 23:55:18 +08:00
parent 783fe18619
commit f00d86aae3
9 changed files with 101 additions and 161 deletions

View File

@@ -243,7 +243,7 @@
treeLoading.value = true
searchMode.value = true
bizOrgApi
.orgTree({ searchKey: value.trim() })
.orgTreeLazy({ searchKey: value.trim() })
.then((res) => {
if (res !== null) {
treeData.value = res
@@ -270,8 +270,8 @@
}
})
if (isEmpty(defaultExpandedKeys.value)) {
// 默认展开第一级
if (treeData.value.length > 0) {
// 只有一个根节点时才自动展开
if (treeData.value.length === 1) {
defaultExpandedKeys.value.push(treeData.value[0].id)
}
}
@@ -287,7 +287,7 @@
treeLoading.value = true
treeData.value = []
bizOrgApi
.orgTree()
.orgTreeLazy({ searchKey: '' })
.then((res) => {
if (res !== null) {
treeData.value = res

View File

@@ -242,7 +242,7 @@
treeLoading.value = true
searchMode.value = true
orgApi
.orgTree({ searchKey: value.trim() })
.orgTreeLazy({ searchKey: value.trim() })
.then((res) => {
if (res !== null) {
treeData.value = res
@@ -269,8 +269,8 @@
}
})
if (isEmpty(defaultExpandedKeys.value)) {
// 默认展开第一级
if (treeData.value.length > 0) {
// 只有一个根节点时才自动展开
if (treeData.value.length === 1) {
defaultExpandedKeys.value.push(treeData.value[0].id)
}
}
@@ -286,7 +286,7 @@
treeLoading.value = true
treeData.value = []
orgApi
.orgTree()
.orgTreeLazy({ searchKey: '' })
.then((res) => {
if (res !== null) {
treeData.value = res

View File

@@ -26,7 +26,6 @@ import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import vip.xiaonuo.biz.modular.org.entity.BizOrg;
import vip.xiaonuo.biz.modular.org.enums.BizOrgSourceFromTypeEnum;
@@ -68,20 +67,6 @@ public class BizOrgController {
return CommonResult.data(bizOrgService.page(bizOrgPageParam));
}
/**
* 获取机构树
*
* @author xuyuxiang
* @date 2022/4/24 20:00
*/
@ApiOperationSupport(order = 2)
@Operation(summary = "获取机构树")
@SaCheckPermission("/biz/org/tree")
@GetMapping("/biz/org/tree")
public CommonResult<List<Tree<String>>> tree(@RequestParam(required = false) String searchKey) {
return CommonResult.data(bizOrgService.tree(searchKey));
}
/**
* 获取机构树(懒加载)
*

View File

@@ -29,4 +29,8 @@ public class BizOrgTreeLazyParam {
/** 父id */
@Schema(description = "父id")
private String parentId;
/** 搜索关键字 */
@Schema(description = "搜索关键字")
private String searchKey;
}

View File

@@ -125,56 +125,12 @@ public class BizOrgServiceImpl extends ServiceImpl<BizOrgMapper, BizOrg> impleme
return this.page(CommonPageRequest.defaultPage(), queryWrapper);
}
@Override
public List<Tree<String>> tree() {
return this.tree(null);
}
@Override
public List<Tree<String>> tree(String searchKey) {
// 获取所有机构
List<BizOrg> allOrgList = this.getAllOrgList();
// 定义机构集合
Set<BizOrg> bizOrgSet = CollectionUtil.newHashSet();
// 校验数据范围
List<String> loginUserDataScope = StpLoginUserUtil.getLoginUserDataScope();
if(loginUserDataScope != null && loginUserDataScope.isEmpty()) {
return CollectionUtil.newArrayList();
}
if(loginUserDataScope == null) {
bizOrgSet.addAll(allOrgList);
} else {
loginUserDataScope.forEach(orgId -> bizOrgSet.addAll(this.getParentListById(allOrgList, orgId, true)));
}
List<BizOrg> bizOrgArrayList = new ArrayList<>(bizOrgSet);
// 如果有搜索关键字,过滤匹配的机构及其所有父级
if (ObjectUtil.isNotEmpty(searchKey)) {
Set<BizOrg> filteredSet = CollectionUtil.newLinkedHashSet();
bizOrgArrayList.stream()
.filter(org -> StrUtil.containsIgnoreCase(org.getName(), searchKey))
.forEach(org -> filteredSet.addAll(this.getParentListById(allOrgList, org.getId(), true)));
// 取交集:既在数据范围内,又匹配搜索条件
bizOrgArrayList = new ArrayList<>(filteredSet);
bizOrgArrayList.retainAll(bizOrgSet);
}
// 修复使用稳定的排序方式首先按排序码排序然后按机构ID排序作为次级条件
bizOrgArrayList.sort(Comparator.comparingInt(BizOrg::getSortCode)
.thenComparing(BizOrg::getId)); // 添加ID作为次级排序条件
// 转换为TreeNode并构建树
List<TreeNode<String>> treeNodeList = bizOrgArrayList.stream().map(bizOrg ->
new TreeNode<>(bizOrg.getId(), bizOrg.getParentId(),
bizOrg.getName(), bizOrg.getSortCode()).setExtra(JSONUtil.parseObj(bizOrg)))
.collect(Collectors.toList());
return TreeUtil.build(treeNodeList, "0");
}
@Override
public List<JSONObject> treeLazy(BizOrgTreeLazyParam bizOrgTreeLazyParam) {
// searchKey不为null时走全量搜索模式返回嵌套树结构
if (bizOrgTreeLazyParam.getSearchKey() != null) {
return this.treeSearch(bizOrgTreeLazyParam.getSearchKey());
}
String parentId = ObjectUtil.isNotEmpty(bizOrgTreeLazyParam.getParentId()) ? bizOrgTreeLazyParam.getParentId() : "0";
// 校验数据范围
List<String> loginUserDataScope = StpLoginUserUtil.getLoginUserDataScope();
@@ -248,6 +204,42 @@ public class BizOrgServiceImpl extends ServiceImpl<BizOrgMapper, BizOrg> impleme
return this.treeLazy(bizOrgTreeLazyParam);
}
/**
* 全量搜索模式返回嵌套树结构的JSONObject列表
* searchKey为空字符串时返回全量树非空时按关键字过滤
* 保留数据范围过滤逻辑
*/
private List<JSONObject> treeSearch(String searchKey) {
List<BizOrg> allOrgList = this.getAllOrgList();
Set<BizOrg> bizOrgSet = CollectionUtil.newHashSet();
List<String> loginUserDataScope = StpLoginUserUtil.getLoginUserDataScope();
if (loginUserDataScope != null && loginUserDataScope.isEmpty()) {
return CollectionUtil.newArrayList();
}
if (loginUserDataScope == null) {
bizOrgSet.addAll(allOrgList);
} else {
loginUserDataScope.forEach(orgId -> bizOrgSet.addAll(this.getParentListById(allOrgList, orgId, true)));
}
List<BizOrg> bizOrgArrayList = new ArrayList<>(bizOrgSet);
if (ObjectUtil.isNotEmpty(searchKey)) {
Set<BizOrg> filteredSet = CollectionUtil.newLinkedHashSet();
bizOrgArrayList.stream()
.filter(org -> StrUtil.containsIgnoreCase(org.getName(), searchKey))
.forEach(org -> filteredSet.addAll(this.getParentListById(allOrgList, org.getId(), true)));
bizOrgArrayList = new ArrayList<>(filteredSet);
bizOrgArrayList.retainAll(bizOrgSet);
}
bizOrgArrayList.sort(Comparator.comparingInt(BizOrg::getSortCode)
.thenComparing(BizOrg::getId));
List<TreeNode<String>> treeNodeList = bizOrgArrayList.stream().map(bizOrg ->
new TreeNode<>(bizOrg.getId(), bizOrg.getParentId(),
bizOrg.getName(), bizOrg.getSortCode()).setExtra(JSONUtil.parseObj(bizOrg)))
.collect(Collectors.toList());
List<Tree<String>> treeList = TreeUtil.build(treeNodeList, "0");
return JSONUtil.toList(JSONUtil.parseArray(treeList), JSONObject.class);
}
@Transactional(rollbackFor = Exception.class)
@Override
public void add(BizOrgAddParam bizOrgAddParam, String sourceFromType) {

View File

@@ -25,7 +25,6 @@ import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import vip.xiaonuo.common.annotation.CommonLog;
import vip.xiaonuo.common.pojo.CommonResult;
@@ -66,19 +65,6 @@ public class SysOrgController {
return CommonResult.data(sysOrgService.page(sysOrgPageParam));
}
/**
* 获取组织树
*
* @author xuyuxiang
* @date 2022/4/24 20:00
*/
@ApiOperationSupport(order = 2)
@Operation(summary = "获取组织树")
@GetMapping("/sys/org/tree")
public CommonResult<List<Tree<String>>> tree(@RequestParam(required = false) String searchKey) {
return CommonResult.data(sysOrgService.tree(searchKey));
}
/**
* 获取组织树(懒加载)
*

View File

@@ -29,4 +29,8 @@ public class SysOrgTreeLazyParam {
/** 父id */
@Schema(description = "父id")
private String parentId;
/** 搜索关键字 */
@Schema(description = "搜索关键字")
private String searchKey;
}

View File

@@ -39,23 +39,7 @@ public interface SysOrgService extends IService<SysOrg> {
Page<SysOrg> page(SysOrgPageParam sysOrgPageParam);
/**
* 获取组织树
*
* @author xuyuxiang
* @date 2022/4/24 20:08
*/
List<Tree<String>> tree();
/**
* 获取组织树(带搜索关键字)
*
* @author xuyuxiang
* @date 2022/4/24 20:08
*/
List<Tree<String>> tree(String searchKey);
/**
* 获取机构树(懒加载)
* 获取机构树(懒加载),支持搜索
*
* @author xuyuxiang
* @date 2022/4/21 16:13

View File

@@ -112,71 +112,30 @@ public class SysOrgServiceImpl extends ServiceImpl<SysOrgMapper, SysOrg> impleme
return this.page(CommonPageRequest.defaultPage(), queryWrapper);
}
@Override
public List<Tree<String>> tree() {
return this.tree(null);
}
@Override
public List<Tree<String>> tree(String searchKey) {
List<SysOrg> allOrgList = this.getAllOrgList();
List<SysOrg> sysOrgList;
// 如果有搜索关键字,过滤匹配的组织及其所有父级
if (ObjectUtil.isNotEmpty(searchKey)) {
Set<SysOrg> filteredSet = CollectionUtil.newLinkedHashSet();
allOrgList.stream()
.filter(org -> StrUtil.containsIgnoreCase(org.getName(), searchKey))
.forEach(org -> filteredSet.addAll(this.getParentListById(allOrgList, org.getId(), true)));
sysOrgList = new ArrayList<>(filteredSet);
} else {
sysOrgList = allOrgList;
}
// 使用稳定的排序方式首先按排序码排序然后按机构ID排序作为次级条件
sysOrgList.sort(Comparator.comparingInt(SysOrg::getSortCode)
.thenComparing(SysOrg::getId)); // 添加ID作为次级排序条件
List<TreeNode<String>> treeNodeList = sysOrgList.stream().map(sysOrg ->
new TreeNode<>(sysOrg.getId(), sysOrg.getParentId(),
sysOrg.getName(), sysOrg.getSortCode()).setExtra(JSONUtil.parseObj(sysOrg)))
.collect(Collectors.toList());
return TreeUtil.build(treeNodeList, "0");
}
@Override
public List<JSONObject> treeLazy(SysOrgTreeLazyParam sysOrgTreeLazyParam) {
String parentId = ObjectUtil.isNotEmpty(sysOrgTreeLazyParam.getParentId()) ? sysOrgTreeLazyParam.getParentId() : "0";
List<String> loginUserDataScope = StpLoginUserUtil.getLoginUserDataScope();
// 获取所有机构
List<SysOrg> allOrgList = this.getAllOrgList();
Set<String> visibleOrgIds = null;
// 如果数据范围不为空则计算可见机构ID集合包含自身及其所有父级
if (ObjectUtil.isNotEmpty(loginUserDataScope)) {
Set<SysOrg> sysOrgSet = CollectionUtil.newHashSet();
loginUserDataScope.forEach(orgId -> sysOrgSet.addAll(this.getParentListById(allOrgList, orgId, true)));
visibleOrgIds = sysOrgSet.stream().map(SysOrg::getId).collect(Collectors.toSet());
// searchKey不为null时走全量搜索模式返回嵌套树结构
if (sysOrgTreeLazyParam.getSearchKey() != null) {
return this.treeSearch(sysOrgTreeLazyParam.getSearchKey());
}
// 过滤出当前父级下的可见子级
final Set<String> finalVisibleOrgIds = visibleOrgIds;
List<SysOrg> sysOrgList = allOrgList.stream()
.filter(sysOrg -> sysOrg.getParentId().equals(parentId))
.filter(sysOrg -> finalVisibleOrgIds == null || finalVisibleOrgIds.contains(sysOrg.getId()))
.sorted(Comparator.comparingInt(SysOrg::getSortCode).thenComparing(SysOrg::getId))
.collect(Collectors.toList());
if (CollectionUtil.isEmpty(sysOrgList)) {
String parentId = ObjectUtil.isNotEmpty(sysOrgTreeLazyParam.getParentId()) ? sysOrgTreeLazyParam.getParentId() : "0";
// 超管接口无需数据范围过滤直接SQL查询当前父级下的子机构
List<SysOrg> childList = this.list(new LambdaQueryWrapper<SysOrg>()
.eq(SysOrg::getParentId, parentId)
.orderByAsc(SysOrg::getSortCode)
.orderByAsc(SysOrg::getId));
if (ObjectUtil.isEmpty(childList)) {
return CollectionUtil.newArrayList();
}
// 判断这些机构是否还有可见子机构
return sysOrgList.stream().map(sysOrg -> {
// 批量判断哪些子机构还有下级
List<String> childIds = childList.stream().map(SysOrg::getId).collect(Collectors.toList());
Set<String> hasChildrenParentIds = this.list(new LambdaQueryWrapper<SysOrg>()
.select(SysOrg::getParentId)
.in(SysOrg::getParentId, childIds))
.stream().map(SysOrg::getParentId).collect(Collectors.toSet());
return childList.stream().map(sysOrg -> {
JSONObject jsonObject = JSONUtil.parseObj(sysOrg);
// 计算是否有可见的子节点
boolean hasChildren = allOrgList.stream()
.anyMatch(item -> item.getParentId().equals(sysOrg.getId()) && (finalVisibleOrgIds == null || finalVisibleOrgIds.contains(item.getId())));
jsonObject.set("isLeaf", !hasChildren);
jsonObject.set("isLeaf", !hasChildrenParentIds.contains(sysOrg.getId()));
return jsonObject;
}).collect(Collectors.toList());
}
@@ -193,6 +152,32 @@ public class SysOrgServiceImpl extends ServiceImpl<SysOrgMapper, SysOrg> impleme
return this.treeLazy(sysOrgTreeLazyParam);
}
/**
* 全量搜索模式返回嵌套树结构的JSONObject列表
* searchKey为空字符串时返回全量树非空时按关键字过滤
*/
private List<JSONObject> treeSearch(String searchKey) {
List<SysOrg> allOrgList = this.getAllOrgList();
List<SysOrg> sysOrgList;
if (ObjectUtil.isNotEmpty(searchKey)) {
Set<SysOrg> filteredSet = CollectionUtil.newLinkedHashSet();
allOrgList.stream()
.filter(org -> StrUtil.containsIgnoreCase(org.getName(), searchKey))
.forEach(org -> filteredSet.addAll(this.getParentListById(allOrgList, org.getId(), true)));
sysOrgList = new ArrayList<>(filteredSet);
} else {
sysOrgList = allOrgList;
}
sysOrgList.sort(Comparator.comparingInt(SysOrg::getSortCode)
.thenComparing(SysOrg::getId));
List<TreeNode<String>> treeNodeList = sysOrgList.stream().map(sysOrg ->
new TreeNode<>(sysOrg.getId(), sysOrg.getParentId(),
sysOrg.getName(), sysOrg.getSortCode()).setExtra(JSONUtil.parseObj(sysOrg)))
.collect(Collectors.toList());
List<Tree<String>> treeList = TreeUtil.build(treeNodeList, "0");
return JSONUtil.toList(JSONUtil.parseArray(treeList), JSONObject.class);
}
@Transactional(rollbackFor = Exception.class)
@Override
public void add(SysOrgAddParam sysOrgAddParam, String sourceFromType) {