diff --git a/yudao-module-farm/src/main/java/cn/iocoder/yudao/module/farm/controller/admin/specieslibrary/SpeciesLibraryController.java b/yudao-module-farm/src/main/java/cn/iocoder/yudao/module/farm/controller/admin/specieslibrary/SpeciesLibraryController.java index 6b869208..1ca80890 100644 --- a/yudao-module-farm/src/main/java/cn/iocoder/yudao/module/farm/controller/admin/specieslibrary/SpeciesLibraryController.java +++ b/yudao-module-farm/src/main/java/cn/iocoder/yudao/module/farm/controller/admin/specieslibrary/SpeciesLibraryController.java @@ -86,8 +86,8 @@ public class SpeciesLibraryController { @GetMapping("/tree") @Operation(summary = "物种库三级树(speciesName1->speciesName2->cultivarName)") - public CommonResult> getSpeciesThreeLevelTree() { - return success(speciesLibraryService.getSpeciesThreeLevelTree()); + public CommonResult> getSpeciesThreeLevelTree() { + return success(speciesLibraryService.getSpeciesTwoTree(new SpeciesTwoLevelTreeReqVO())); } @GetMapping("/two/tree") diff --git a/yudao-module-farm/src/main/java/cn/iocoder/yudao/module/farm/controller/admin/specieslibrary/vo/SpeciesLibraryRespVO.java b/yudao-module-farm/src/main/java/cn/iocoder/yudao/module/farm/controller/admin/specieslibrary/vo/SpeciesLibraryRespVO.java index e61571b0..5380ab3f 100644 --- a/yudao-module-farm/src/main/java/cn/iocoder/yudao/module/farm/controller/admin/specieslibrary/vo/SpeciesLibraryRespVO.java +++ b/yudao-module-farm/src/main/java/cn/iocoder/yudao/module/farm/controller/admin/specieslibrary/vo/SpeciesLibraryRespVO.java @@ -23,12 +23,6 @@ public class SpeciesLibraryRespVO { @ExcelProperty("物种类别名称") private String speciesName; - @Schema(description = "物种类别名称-前半段") - private String speciesName1; - - @Schema(description = "物种类别名称-后半段") - private String speciesName2; - @Schema(description = "物种名称", example = "芋艿") @ExcelProperty("物种名称") private String cultivarName; diff --git a/yudao-module-farm/src/main/java/cn/iocoder/yudao/module/farm/dal/dataobject/specieslibrary/SpeciesLibraryDO.java b/yudao-module-farm/src/main/java/cn/iocoder/yudao/module/farm/dal/dataobject/specieslibrary/SpeciesLibraryDO.java index 1616c089..6bfe6aec 100644 --- a/yudao-module-farm/src/main/java/cn/iocoder/yudao/module/farm/dal/dataobject/specieslibrary/SpeciesLibraryDO.java +++ b/yudao-module-farm/src/main/java/cn/iocoder/yudao/module/farm/dal/dataobject/specieslibrary/SpeciesLibraryDO.java @@ -106,9 +106,4 @@ public class SpeciesLibraryDO extends BaseDO { private String tenantId; - @TableField(exist = false) - private String speciesName1; - @TableField(exist = false) - private String speciesName2; - } \ No newline at end of file diff --git a/yudao-module-farm/src/main/java/cn/iocoder/yudao/module/farm/dal/mysql/specieslibrary/SpeciesLibraryMapper.java b/yudao-module-farm/src/main/java/cn/iocoder/yudao/module/farm/dal/mysql/specieslibrary/SpeciesLibraryMapper.java index 80cec899..f7fa29c7 100644 --- a/yudao-module-farm/src/main/java/cn/iocoder/yudao/module/farm/dal/mysql/specieslibrary/SpeciesLibraryMapper.java +++ b/yudao-module-farm/src/main/java/cn/iocoder/yudao/module/farm/dal/mysql/specieslibrary/SpeciesLibraryMapper.java @@ -35,4 +35,6 @@ public interface SpeciesLibraryMapper extends BaseMapperX { } int getSpeciesCount(@Param("tenantId") long tenantId,@Param("baseId") String baseId); + + void deleteBySpeciesLibraryId(String id); } \ No newline at end of file diff --git a/yudao-module-farm/src/main/java/cn/iocoder/yudao/module/farm/dal/mysql/twodict/TwoDictMapper.java b/yudao-module-farm/src/main/java/cn/iocoder/yudao/module/farm/dal/mysql/twodict/TwoDictMapper.java index 915a9fc9..7e43cf1f 100644 --- a/yudao-module-farm/src/main/java/cn/iocoder/yudao/module/farm/dal/mysql/twodict/TwoDictMapper.java +++ b/yudao-module-farm/src/main/java/cn/iocoder/yudao/module/farm/dal/mysql/twodict/TwoDictMapper.java @@ -40,4 +40,5 @@ public interface TwoDictMapper extends BaseMapperX { .orderByAsc(TwoDictDO::getId)); } + void deleteByTreeId(String id); } \ No newline at end of file diff --git a/yudao-module-farm/src/main/java/cn/iocoder/yudao/module/farm/service/specieslibrary/SpeciesLibraryServiceImpl.java b/yudao-module-farm/src/main/java/cn/iocoder/yudao/module/farm/service/specieslibrary/SpeciesLibraryServiceImpl.java index b1cdceeb..b81cbb89 100644 --- a/yudao-module-farm/src/main/java/cn/iocoder/yudao/module/farm/service/specieslibrary/SpeciesLibraryServiceImpl.java +++ b/yudao-module-farm/src/main/java/cn/iocoder/yudao/module/farm/service/specieslibrary/SpeciesLibraryServiceImpl.java @@ -21,10 +21,8 @@ import cn.iocoder.yudao.module.farm.service.sysDict.SysDictService; import cn.iocoder.yudao.module.farm.service.twodict.TwoDictService; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; -import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; import jakarta.annotation.Resource; import org.apache.commons.lang3.ObjectUtils; -import org.apache.commons.lang3.StringUtils; import org.springframework.stereotype.Service; import org.springframework.validation.annotation.Validated; @@ -72,9 +70,12 @@ public class SpeciesLibraryServiceImpl implements SpeciesLibraryService { speciesLibrary.setId(id); speciesLibrary.setTenantId(String.valueOf(user.getTenantId())); speciesLibrary.setCreateTime(LocalDateTime.now()); - TwoDictDO dictDO = twoDictService.getTwoDict(Long.valueOf(speciesLibrary.getCategory())); - TwoDictDO twoDict = twoDictService.getTwoDict(dictDO.getParentId()); - speciesLibrary.setSpeciesName(twoDict.getName() + "/" + dictDO.getName()); + TwoDictDO dictDO3 = twoDictService.getTwoDict(Long.valueOf(speciesLibrary.getCategory())); + TwoDictDO dictDO2 = twoDictService.getTwoDict(dictDO3.getParentId()); + if (dictDO2.getParentId() != null) { + TwoDictDO dictDO1 = twoDictService.getTwoDict(dictDO2.getParentId()); + speciesLibrary.setSpeciesName(dictDO1.getName() + "/" + dictDO2.getName() + "/" + dictDO3.getName()); + } speciesLibraryMapper.insert(speciesLibrary); // 返回 return speciesLibrary.getId(); @@ -123,9 +124,12 @@ public class SpeciesLibraryServiceImpl implements SpeciesLibraryService { // 更新 SpeciesLibraryDO updateObj = BeanUtils.toBean(updateReqVO, SpeciesLibraryDO.class); - TwoDictDO dictDO = twoDictService.getTwoDict(Long.valueOf(updateReqVO.getCategory())); - TwoDictDO twoDict = twoDictService.getTwoDict(dictDO.getParentId()); - updateObj.setSpeciesName(twoDict.getName() + "/" + dictDO.getName()); + TwoDictDO dictDO3 = twoDictService.getTwoDict(Long.valueOf(updateObj.getCategory())); + TwoDictDO dictDO2 = twoDictService.getTwoDict(dictDO3.getParentId()); + if (dictDO2.getParentId() != null) { + TwoDictDO dictDO1 = twoDictService.getTwoDict(dictDO2.getParentId()); + updateObj.setSpeciesName(dictDO1.getName() + "/" + dictDO2.getName() + "/" + dictDO3.getName()); + } speciesLibraryMapper.updateById(updateObj); // 同步 // this.syncUpdateDict(updateObj.getId()); @@ -156,10 +160,8 @@ public class SpeciesLibraryServiceImpl implements SpeciesLibraryService { public void deleteSpeciesLibrary(String id) { // 校验存在 validateSpeciesLibraryExists(id); - // 同步 - this.syncDeleteDict(id); // 删除 - speciesLibraryMapper.deleteById(id); + speciesLibraryMapper.deleteBySpeciesLibraryId(id); } @@ -199,15 +201,6 @@ public class SpeciesLibraryServiceImpl implements SpeciesLibraryService { // 触发图片集合转换,确保返回的DO对象包含转换后的图片集合 speciesLibrary.getImageList(); } - if (speciesLibrary != null && speciesLibrary.getSpeciesName() != null) { - String[] parts = speciesLibrary.getSpeciesName().split("/"); - if (parts.length > 0) { - speciesLibrary.setSpeciesName1(parts[0]); - } - if (parts.length > 1) { - speciesLibrary.setSpeciesName2(parts[1]); - } - } return speciesLibrary; } @@ -220,15 +213,6 @@ public class SpeciesLibraryServiceImpl implements SpeciesLibraryService { if (speciesLibrary != null) { speciesLibrary.getImageList(); } - if (speciesLibrary != null && speciesLibrary.getSpeciesName() != null) { - String[] parts = speciesLibrary.getSpeciesName().split("/"); - if (parts.length > 0) { - speciesLibrary.setSpeciesName1(parts[0]); - } - if (parts.length > 1) { - speciesLibrary.setSpeciesName2(parts[1]); - } - } }); } return pageResult; @@ -378,57 +362,18 @@ public class SpeciesLibraryServiceImpl implements SpeciesLibraryService { @Override public List getSpeciesTwoTree(SpeciesTwoLevelTreeReqVO req) { + // 获取当前用户租户ID + Long tenantId = getLoginUser().getTenantId(); + // 构建查询条件 LambdaQueryWrapperX wrapperX = new LambdaQueryWrapperX<>(); - wrapperX.eq(TwoDictDO::getTenantId, String.valueOf(getLoginUser().getTenantId())); - wrapperX.eqIfPresent(TwoDictDO::getStatus,req.getUseStatus()); - wrapperX.orderByDesc(TwoDictDO::getId); + wrapperX.eq(TwoDictDO::getTenantId, String.valueOf(tenantId)); + wrapperX.eqIfPresent(TwoDictDO::getStatus, req.getUseStatus()); + wrapperX.orderByAsc(TwoDictDO::getParentId).orderByAsc(TwoDictDO::getId); List allDicts = twoDictMapper.selectList(wrapperX); - List matchedDicts = null; - if (!StringUtils.isEmpty(req.getName() )) { - // 查找匹配的节点 - matchedDicts = allDicts.stream().filter(dict -> dict.getName().equals(req.getName())).collect(Collectors.toList()); - if (matchedDicts.isEmpty()) { - return Collections.emptyList(); - } - } else { - matchedDicts = allDicts; - } - - // 构建完整的树结构用于查询 - List fullTree = buildTree(matchedDicts); - - Set resultIds = new HashSet<>(); - List result = new ArrayList<>(); - - for (TwoDictDO matchedDict : matchedDicts) { - if (matchedDict.getParentId() == null) { - // 查询的是父级:找到该父级节点及其所有子节点 - SpeciesTwoLevelTreeRespVO parentNode = findNodeById(fullTree, matchedDict.getId()); - if (parentNode != null) { - result.add(parentNode); - } - } else { - // 查询的是子类:找到该子类的父级节点 - SpeciesTwoLevelTreeRespVO parentNode = findParentNode(fullTree, matchedDict.getParentId()); - if (parentNode != null && !resultIds.contains(parentNode.getId())) { - resultIds.add(parentNode.getId()); - result.add(parentNode); - } - } - } - - return result.stream() - .collect(Collectors.collectingAndThen( - Collectors.toMap( - SpeciesTwoLevelTreeRespVO::getName, - item -> item, - (existing, replacement) -> existing, // 保留第一个出现的 - LinkedHashMap::new - ), - map -> new ArrayList<>(map.values()) - )); + // 构建无限极树形结构 + return buildInfiniteTree(allDicts, null, 0); } /** @@ -450,23 +395,240 @@ public class SpeciesLibraryServiceImpl implements SpeciesLibraryService { } /** - * 根据父级ID在树中查找父节点 + * 构建无限极树形结构 + * + * @param allDicts 所有字典数据 + * @param parentId 父级ID + * @param level 当前层级 + * @return 树形结构 */ - private SpeciesTwoLevelTreeRespVO findParentNode(List tree, Long parentId) { + private List buildInfiniteTree(List allDicts, Long parentId, int level) { + List treeList = new ArrayList<>(); + + for (TwoDictDO dict : allDicts) { + // 匹配父级ID,构建当前层级的节点 + if (Objects.equals(dict.getParentId(), parentId)) { + SpeciesTwoLevelTreeRespVO treeNode = convertToSpeciesTreeVO(dict); + treeNode.setSort(level); + + // 递归构建子节点 + List children = buildInfiniteTree(allDicts, dict.getId(), level + 1); + treeNode.setChildren(children); + + treeList.add(treeNode); + } + } + + return treeList; + } + + /** + * 将TwoDictDO转换为SpeciesTwoLevelTreeRespVO + */ + private SpeciesTwoLevelTreeRespVO convertToSpeciesTreeVO(TwoDictDO dict) { + SpeciesTwoLevelTreeRespVO vo = new SpeciesTwoLevelTreeRespVO(); + vo.setId(dict.getId()); + vo.setParentId(dict.getParentId() != null ? dict.getParentId() : 0L); + vo.setName(dict.getName()); + vo.setUseStatus(Boolean.TRUE.equals(dict.getStatus()) ? 1 : 0); + return vo; + } + + /** + * 构建从指定节点到根节点的完整路径,并过滤掉不相关的分支 + */ + private List buildPathToRoot(List tree, Long targetNodeId) { + // 首先找到目标节点 + SpeciesTwoLevelTreeRespVO targetNode = findNodeById(tree, targetNodeId); + if (targetNode == null) { + return new ArrayList<>(); + } + + // 构建从目标节点到根节点的路径 + List path = new ArrayList<>(); + buildPathRecursively(tree, targetNodeId, path); + + // 反转路径,使其从根节点开始 + Collections.reverse(path); + + // 构建过滤后的树结构 + if (!path.isEmpty()) { + return buildFilteredTreeFromPath(path); + } + + return new ArrayList<>(); + } + + /** + * 递归构建从目标节点到根节点的路径 + */ + private boolean buildPathRecursively(List tree, Long targetNodeId, List path) { for (SpeciesTwoLevelTreeRespVO node : tree) { - if (node.getId().equals(parentId)) { - return node; + if (node.getId().equals(targetNodeId)) { + path.add(node); + return true; } if (node.getChildren() != null && !node.getChildren().isEmpty()) { - SpeciesTwoLevelTreeRespVO found = findParentNode(node.getChildren(), parentId); - if (found != null) { - return found; + if (buildPathRecursively(node.getChildren(), targetNodeId, path)) { + path.add(node); + return true; + } + } + } + return false; + } + + /** + * 根据路径构建过滤后的树结构 + */ + private List buildFilteredTreeFromPath(List path) { + if (path.isEmpty()) { + return new ArrayList<>(); + } + + // 从根节点开始构建过滤后的树 + SpeciesTwoLevelTreeRespVO rootNode = createFilteredNodeFromPath(path, 0); + return Collections.singletonList(rootNode); + } + + /** + * 递归创建过滤后的节点,只包含路径上的节点 + */ + private SpeciesTwoLevelTreeRespVO createFilteredNodeFromPath(List path, int currentIndex) { + if (currentIndex >= path.size()) { + return null; + } + + SpeciesTwoLevelTreeRespVO originalNode = path.get(currentIndex); + SpeciesTwoLevelTreeRespVO filteredNode = new SpeciesTwoLevelTreeRespVO(); + filteredNode.setId(originalNode.getId()); + filteredNode.setParentId(originalNode.getParentId()); + filteredNode.setName(originalNode.getName()); + filteredNode.setUseStatus(originalNode.getUseStatus()); + filteredNode.setSort(originalNode.getSort()); + + // 如果有下一个节点,说明当前节点有子节点 + if (currentIndex + 1 < path.size()) { + SpeciesTwoLevelTreeRespVO childNode = createFilteredNodeFromPath(path, currentIndex + 1); + if (childNode != null) { + filteredNode.setChildren(Collections.singletonList(childNode)); + } else { + filteredNode.setChildren(new ArrayList<>()); + } + } else { + // 这是路径的最后一个节点,没有子节点 + filteredNode.setChildren(new ArrayList<>()); + } + + return filteredNode; + } + + /** + * 找到指定节点的根节点ID + */ + private Long findRootNodeId(List tree, Long targetNodeId) { + // 首先找到目标节点 + SpeciesTwoLevelTreeRespVO targetNode = findNodeById(tree, targetNodeId); + if (targetNode == null) { + return null; + } + + // 如果目标节点就是根节点 + if (targetNode.getParentId() == null || targetNode.getParentId() == 0L) { + return targetNode.getId(); + } + + // 递归向上查找根节点 + return findRootNodeIdRecursively(tree, targetNode.getParentId()); + } + + /** + * 递归查找根节点ID + */ + private Long findRootNodeIdRecursively(List tree, Long nodeId) { + for (SpeciesTwoLevelTreeRespVO node : tree) { + if (node.getId().equals(nodeId)) { + if (node.getParentId() == null || node.getParentId() == 0L) { + return node.getId(); + } else { + return findRootNodeIdRecursively(tree, node.getParentId()); + } + } + if (node.getChildren() != null && !node.getChildren().isEmpty()) { + Long result = findRootNodeIdRecursively(node.getChildren(), nodeId); + if (result != null) { + return result; } } } return null; } + /** + * 创建过滤后的根节点,只包含匹配的子节点路径 + */ + private SpeciesTwoLevelTreeRespVO createFilteredRootNode(SpeciesTwoLevelTreeRespVO rootNode, List matchedChildIds) { + SpeciesTwoLevelTreeRespVO filteredRootNode = new SpeciesTwoLevelTreeRespVO(); + filteredRootNode.setId(rootNode.getId()); + filteredRootNode.setParentId(rootNode.getParentId()); + filteredRootNode.setName(rootNode.getName()); + filteredRootNode.setUseStatus(rootNode.getUseStatus()); + filteredRootNode.setSort(rootNode.getSort()); + + // 递归过滤子节点 + List filteredChildren = filterChildrenRecursively(rootNode.getChildren(), matchedChildIds); + filteredRootNode.setChildren(filteredChildren); + + return filteredRootNode; + } + + /** + * 递归过滤子节点,只保留包含匹配节点的路径 + */ + private List filterChildrenRecursively(List children, List matchedChildIds) { + if (children == null || children.isEmpty()) { + return new ArrayList<>(); + } + + List filteredChildren = new ArrayList<>(); + + for (SpeciesTwoLevelTreeRespVO child : children) { + // 检查当前节点是否在匹配列表中 + boolean isMatched = matchedChildIds.contains(child.getId()); + + // 递归检查子节点 + List filteredGrandChildren = filterChildrenRecursively(child.getChildren(), matchedChildIds); + + // 如果当前节点匹配或有匹配的子节点,则包含此节点 + if (isMatched || !filteredGrandChildren.isEmpty()) { + SpeciesTwoLevelTreeRespVO filteredChild = new SpeciesTwoLevelTreeRespVO(); + filteredChild.setId(child.getId()); + filteredChild.setParentId(child.getParentId()); + filteredChild.setName(child.getName()); + filteredChild.setUseStatus(child.getUseStatus()); + filteredChild.setSort(child.getSort()); + filteredChild.setChildren(filteredGrandChildren); + filteredChildren.add(filteredChild); + } + } + + return filteredChildren; + } + + /** + * 收集指定节点的所有后代节点ID + */ + private void collectAllDescendants(List tree, Long nodeId, Set allDescendants) { + SpeciesTwoLevelTreeRespVO node = findNodeById(tree, nodeId); + if (node != null && node.getChildren() != null) { + for (SpeciesTwoLevelTreeRespVO child : node.getChildren()) { + allDescendants.add(child.getId()); + // 递归收集子节点的后代 + collectAllDescendants(tree, child.getId(), allDescendants); + } + } + } + /** * 构建完整的树形结构(之前的实现) */ @@ -509,7 +671,7 @@ public class SpeciesLibraryServiceImpl implements SpeciesLibraryService { vo.setId(dict.getId()); vo.setParentId(dict.getParentId() != null ? dict.getParentId() : 0L); vo.setName(dict.getName()); - vo.setUseStatus(dict.getStatus() ? 1 :0); + vo.setUseStatus(dict.getStatus() ? 1 : 0); return vo; } @@ -598,7 +760,7 @@ public class SpeciesLibraryServiceImpl implements SpeciesLibraryService { updateSelfAndChildren(id, req.getUseStatus() == 1); } else { // 4. 如果是子节点,只更新自身 - this.updateSelf(id,req.getName(),req.getUseStatus() ==1); + this.updateSelf(id, req.getName(), req.getUseStatus() == 1); } return true; } catch (Exception e) { @@ -627,9 +789,9 @@ public class SpeciesLibraryServiceImpl implements SpeciesLibraryService { /** * 更新自身及其所有子节点(递归更新) */ - private void updateSelfAndChildren(Long id,boolean status) { + private void updateSelfAndChildren(Long id, boolean status) { // 先更新自身 - updateSelf(id,null,status); + updateSelf(id, null, status); // 递归更新所有子节点 updateChildrenRecursively(id, status); } @@ -646,7 +808,7 @@ public class SpeciesLibraryServiceImpl implements SpeciesLibraryService { for (TwoDictDO child : children) { // 更新当前子节点 - updateSelf(child.getId(),null, useStatus); + updateSelf(child.getId(), null, useStatus); // 递归更新当前子节点的子节点(如果有) if (hasChildren(child.getId())) { @@ -658,11 +820,7 @@ public class SpeciesLibraryServiceImpl implements SpeciesLibraryService { @Override public boolean deleteSpeciesTwoLevelTree(String id) { try { - LambdaUpdateWrapper updateWrapper = new LambdaUpdateWrapper<>(); - updateWrapper.eq(TwoDictDO::getId, id) - .eq(TwoDictDO::getDeleted, false) // 只更新未删除的记录 - .set(TwoDictDO::getDeleted, true); // 设置删除状态 - twoDictMapper.update(updateWrapper); + twoDictMapper.deleteByTreeId(id); return true; } catch (Exception e) { return false; diff --git a/yudao-module-farm/src/main/resources/mapper/specieslibrary/SpeciesLibraryMapper.xml b/yudao-module-farm/src/main/resources/mapper/specieslibrary/SpeciesLibraryMapper.xml index a65752f4..b15c5826 100644 --- a/yudao-module-farm/src/main/resources/mapper/specieslibrary/SpeciesLibraryMapper.xml +++ b/yudao-module-farm/src/main/resources/mapper/specieslibrary/SpeciesLibraryMapper.xml @@ -2,6 +2,7 @@ + + + delete + from farm_two_dict + where id = #{id} + \ No newline at end of file