diff --git a/snowy-admin-web/src/views/biz/org/index.vue b/snowy-admin-web/src/views/biz/org/index.vue index 511ca035..dd1ac278 100644 --- a/snowy-admin-web/src/views/biz/org/index.vue +++ b/snowy-admin-web/src/views/biz/org/index.vue @@ -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 diff --git a/snowy-admin-web/src/views/sys/org/index.vue b/snowy-admin-web/src/views/sys/org/index.vue index 9213efd3..9b01f983 100644 --- a/snowy-admin-web/src/views/sys/org/index.vue +++ b/snowy-admin-web/src/views/sys/org/index.vue @@ -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 diff --git a/snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/org/controller/BizOrgController.java b/snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/org/controller/BizOrgController.java index 686f20ff..aced3f9d 100644 --- a/snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/org/controller/BizOrgController.java +++ b/snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/org/controller/BizOrgController.java @@ -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>> tree(@RequestParam(required = false) String searchKey) { - return CommonResult.data(bizOrgService.tree(searchKey)); - } - /** * 获取机构树(懒加载) * diff --git a/snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/org/param/BizOrgTreeLazyParam.java b/snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/org/param/BizOrgTreeLazyParam.java index 42f520fc..157ab60a 100644 --- a/snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/org/param/BizOrgTreeLazyParam.java +++ b/snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/org/param/BizOrgTreeLazyParam.java @@ -29,4 +29,8 @@ public class BizOrgTreeLazyParam { /** 父id */ @Schema(description = "父id") private String parentId; + + /** 搜索关键字 */ + @Schema(description = "搜索关键字") + private String searchKey; } diff --git a/snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/org/service/impl/BizOrgServiceImpl.java b/snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/org/service/impl/BizOrgServiceImpl.java index 63ecd77c..eda2a351 100644 --- a/snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/org/service/impl/BizOrgServiceImpl.java +++ b/snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/org/service/impl/BizOrgServiceImpl.java @@ -125,56 +125,12 @@ public class BizOrgServiceImpl extends ServiceImpl impleme return this.page(CommonPageRequest.defaultPage(), queryWrapper); } - @Override - public List> tree() { - return this.tree(null); - } - - @Override - public List> tree(String searchKey) { - // 获取所有机构 - List allOrgList = this.getAllOrgList(); - // 定义机构集合 - Set bizOrgSet = CollectionUtil.newHashSet(); - // 校验数据范围 - List 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 bizOrgArrayList = new ArrayList<>(bizOrgSet); - - // 如果有搜索关键字,过滤匹配的机构及其所有父级 - if (ObjectUtil.isNotEmpty(searchKey)) { - Set 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> 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 treeLazy(BizOrgTreeLazyParam bizOrgTreeLazyParam) { + // searchKey不为null时,走全量搜索模式,返回嵌套树结构 + if (bizOrgTreeLazyParam.getSearchKey() != null) { + return this.treeSearch(bizOrgTreeLazyParam.getSearchKey()); + } String parentId = ObjectUtil.isNotEmpty(bizOrgTreeLazyParam.getParentId()) ? bizOrgTreeLazyParam.getParentId() : "0"; // 校验数据范围 List loginUserDataScope = StpLoginUserUtil.getLoginUserDataScope(); @@ -248,6 +204,42 @@ public class BizOrgServiceImpl extends ServiceImpl impleme return this.treeLazy(bizOrgTreeLazyParam); } + /** + * 全量搜索模式,返回嵌套树结构的JSONObject列表 + * searchKey为空字符串时返回全量树,非空时按关键字过滤 + * 保留数据范围过滤逻辑 + */ + private List treeSearch(String searchKey) { + List allOrgList = this.getAllOrgList(); + Set bizOrgSet = CollectionUtil.newHashSet(); + List 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 bizOrgArrayList = new ArrayList<>(bizOrgSet); + if (ObjectUtil.isNotEmpty(searchKey)) { + Set 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> treeNodeList = bizOrgArrayList.stream().map(bizOrg -> + new TreeNode<>(bizOrg.getId(), bizOrg.getParentId(), + bizOrg.getName(), bizOrg.getSortCode()).setExtra(JSONUtil.parseObj(bizOrg))) + .collect(Collectors.toList()); + List> 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) { diff --git a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/org/controller/SysOrgController.java b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/org/controller/SysOrgController.java index f105266d..ae2d74ef 100644 --- a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/org/controller/SysOrgController.java +++ b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/org/controller/SysOrgController.java @@ -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>> tree(@RequestParam(required = false) String searchKey) { - return CommonResult.data(sysOrgService.tree(searchKey)); - } - /** * 获取组织树(懒加载) * diff --git a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/org/param/SysOrgTreeLazyParam.java b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/org/param/SysOrgTreeLazyParam.java index 6055637e..434140ce 100644 --- a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/org/param/SysOrgTreeLazyParam.java +++ b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/org/param/SysOrgTreeLazyParam.java @@ -29,4 +29,8 @@ public class SysOrgTreeLazyParam { /** 父id */ @Schema(description = "父id") private String parentId; + + /** 搜索关键字 */ + @Schema(description = "搜索关键字") + private String searchKey; } diff --git a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/org/service/SysOrgService.java b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/org/service/SysOrgService.java index 28becdda..592cc631 100644 --- a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/org/service/SysOrgService.java +++ b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/org/service/SysOrgService.java @@ -39,23 +39,7 @@ public interface SysOrgService extends IService { Page page(SysOrgPageParam sysOrgPageParam); /** - * 获取组织树 - * - * @author xuyuxiang - * @date 2022/4/24 20:08 - */ - List> tree(); - - /** - * 获取组织树(带搜索关键字) - * - * @author xuyuxiang - * @date 2022/4/24 20:08 - */ - List> tree(String searchKey); - - /** - * 获取机构树(懒加载) + * 获取机构树(懒加载),支持搜索 * * @author xuyuxiang * @date 2022/4/21 16:13 diff --git a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/org/service/impl/SysOrgServiceImpl.java b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/org/service/impl/SysOrgServiceImpl.java index b3ea6c2d..9a88f0d6 100644 --- a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/org/service/impl/SysOrgServiceImpl.java +++ b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/org/service/impl/SysOrgServiceImpl.java @@ -112,71 +112,30 @@ public class SysOrgServiceImpl extends ServiceImpl impleme return this.page(CommonPageRequest.defaultPage(), queryWrapper); } - @Override - public List> tree() { - return this.tree(null); - } - - @Override - public List> tree(String searchKey) { - List allOrgList = this.getAllOrgList(); - List sysOrgList; - // 如果有搜索关键字,过滤匹配的组织及其所有父级 - if (ObjectUtil.isNotEmpty(searchKey)) { - Set 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> 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 treeLazy(SysOrgTreeLazyParam sysOrgTreeLazyParam) { - String parentId = ObjectUtil.isNotEmpty(sysOrgTreeLazyParam.getParentId()) ? sysOrgTreeLazyParam.getParentId() : "0"; - List loginUserDataScope = StpLoginUserUtil.getLoginUserDataScope(); - - // 获取所有机构 - List allOrgList = this.getAllOrgList(); - Set visibleOrgIds = null; - - // 如果数据范围不为空,则计算可见机构ID集合(包含自身及其所有父级) - if (ObjectUtil.isNotEmpty(loginUserDataScope)) { - Set 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 finalVisibleOrgIds = visibleOrgIds; - List 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 childList = this.list(new LambdaQueryWrapper() + .eq(SysOrg::getParentId, parentId) + .orderByAsc(SysOrg::getSortCode) + .orderByAsc(SysOrg::getId)); + if (ObjectUtil.isEmpty(childList)) { return CollectionUtil.newArrayList(); } - - // 判断这些机构是否还有可见子机构 - return sysOrgList.stream().map(sysOrg -> { + // 批量判断哪些子机构还有下级 + List childIds = childList.stream().map(SysOrg::getId).collect(Collectors.toList()); + Set hasChildrenParentIds = this.list(new LambdaQueryWrapper() + .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 impleme return this.treeLazy(sysOrgTreeLazyParam); } + /** + * 全量搜索模式,返回嵌套树结构的JSONObject列表 + * searchKey为空字符串时返回全量树,非空时按关键字过滤 + */ + private List treeSearch(String searchKey) { + List allOrgList = this.getAllOrgList(); + List sysOrgList; + if (ObjectUtil.isNotEmpty(searchKey)) { + Set 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> treeNodeList = sysOrgList.stream().map(sysOrg -> + new TreeNode<>(sysOrg.getId(), sysOrg.getParentId(), + sysOrg.getName(), sysOrg.getSortCode()).setExtra(JSONUtil.parseObj(sysOrg))) + .collect(Collectors.toList()); + List> 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) {