Explorar o código

系统wbsTree复制

cr hai 3 días
pai
achega
dcfc1d0a71

+ 2 - 2
blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/vo/copyNodeVo.java

@@ -5,6 +5,6 @@ import lombok.Data;
 import java.util.List;
 @Data
 public class copyNodeVo {
-  private   List<String> leftIds;
-  private  List<String>rightIds;
+  private   List<Long> leftIds;
+  private  List<Long>rightIds;
 }

+ 1 - 1
blade-service/blade-manager/src/main/java/org/springblade/manager/mapper/WbsTreeMapper.java

@@ -103,5 +103,5 @@ public interface WbsTreeMapper extends EasyBaseMapper<WbsTree> {
     List<WbsTreePrivate> getTitleRange(@Param("projectId")Long projectId,
                                        @Param("wbsType")Integer wbsType);
 
-    List<WbsTree> selectAllChildNode(@Param("leftIds") List<String> leftIds);
+    List<WbsTree> selectAllChildNode(@Param("leftIds") List<Long> leftIds);
 }

+ 1 - 1
blade-service/blade-manager/src/main/java/org/springblade/manager/mapper/WbsTreeMapper.xml

@@ -579,7 +579,7 @@
         <if test="leftIds != null and leftIds.size() > 0">
             AND (
             <foreach collection="leftIds" item="item" separator=" OR ">
-                FIND_IN_SET(#{item}, ancestors)
+                FIND_IN_SET(#{item}, ancestors) OR id = #{item}
             </foreach>
             )
         </if>

+ 1 - 1
blade-service/blade-manager/src/main/java/org/springblade/manager/service/IWbsTreeService.java

@@ -82,5 +82,5 @@ public interface IWbsTreeService extends BaseService<WbsTree> {
 
     Object getQueryValueByNodeType(WbsTreePrivateQueryVO vo);
 
-    boolean copyNode(List<String> leftIds, List<String> rightIds);
+    boolean copyNode(List<Long> leftIds, List<Long> rightIds);
 }

+ 108 - 56
blade-service/blade-manager/src/main/java/org/springblade/manager/service/impl/WbsTreeServiceImpl.java

@@ -600,80 +600,132 @@ public class WbsTreeServiceImpl extends BaseServiceImpl<WbsTreeMapper, WbsTree>
     }
 
     @Override
-    public boolean copyNode(List<String> leftIds, List<String> rightIds) {
-        List<WbsTree> leftLists = baseMapper.selectAllChildNode(leftIds);
-        for (String rightId : rightIds) {
-            // 每次循环都创建一个新的集合作为副本
-            List<WbsTree> workingList = leftLists.stream()
+    public boolean copyNode(List<Long> leftIds, List<Long> rightIds) {
+        // 获取所有需要复制的节点
+        List<WbsTree> originalNodes = baseMapper.selectAllChildNode(leftIds);
+
+        for (Long rightId : rightIds) {
+            // 第一要求:每次循环重新创建新的leftLists
+            List<WbsTree> leftLists = originalNodes.stream()
                     .map(node -> {
-                        // 创建每个节点的副本
                         WbsTree copy = new WbsTree();
-                        BeanUtils.copyProperties(copy, node);
+                        BeanUtils.copyProperties(node, copy);
                         return copy;
                     })
                     .collect(Collectors.toList());
-            WbsTree rightWbsTree = baseMapper.selectById(Long.parseLong(rightId));
-
-            // 找到leftLists中所有的根节点(没有在leftLists中作为子节点出现的节点)
-            Set<Long> allPIds = workingList.stream()
-                    .map(WbsTree::getParentId)
-                    .filter(Objects::nonNull)
-                    .collect(Collectors.toSet());
 
-            List<WbsTree> rootNodes = workingList.stream()
-                    .filter(node -> !allPIds.contains(node.getId()))
+            // 第二要求:找出新的leftLists里面id在leftIds里面的作为根节点
+            List<WbsTree> rootNodes = leftLists.stream()
+                    .filter(node -> leftIds.contains(node.getId()))
                     .collect(Collectors.toList());
 
-            // 为每个根节点重新设置属性,并将其放到rightWbsTreePrivate节点下
-            for (WbsTree rootNode : rootNodes) {
-                // 重新分配节点值
-                reassignNodeValues(workingList, rootNode, rightWbsTree);
+            // 获取目标父节点信息
+            WbsTree wbsTree = baseMapper.selectById(rightId);
+
+            // 第三要求:重新构建整个树的id、parentId和ancestors
+            rebuildTreeStructure(leftLists, rootNodes, rightId, wbsTree);
+
+            // 保存到数据库
+            if (!leftLists.isEmpty()) {
+                this.insertBatchPublic(leftLists, 500);
             }
         }
         return true;
     }
-    // 添加一个辅助方法来重新分配节点值
-    private void reassignNodeValues(List<WbsTree> leftLists, WbsTree rootNode, WbsTree rightWbsTree) {
-        // 创建节点映射以便快速查找
-        Map<Long, WbsTree> nodeMap = leftLists.stream()
-                .collect(Collectors.toMap(WbsTree::getId, node -> node));
-
-        // 为根节点生成新的随机ID
-        Long newRootId = SnowFlakeUtil.getId();
-        // 设置根节点属性,使其成为rightWbsTreePrivate的子节点
-        rootNode.setId(newRootId);
-        rootNode.setParentId(rightWbsTree.getId());
-        // ancestors设置为rightWbsTreePrivate的ancestors加上rightWbsTreePrivate的id
-        if (rightWbsTree.getAncestors() != null && !rightWbsTree.getAncestors().isEmpty()) {
-            rootNode.setAncestors(rightWbsTree.getAncestors() + "," + rightWbsTree.getId());
-        } else {
-            rootNode.setAncestors(String.valueOf(rightWbsTree.getId()));
+
+    /**
+     * 重新构建整个树的id、parentId和ancestors
+     */
+    private void rebuildTreeStructure(List<WbsTree> allNodes,
+                                      List<WbsTree> rootNodes,
+                                      Long targetParentId,
+                                      WbsTree targetParentNode) {
+        // 存储原ID到新ID的映射
+        Map<Long, Long> idMapping = new HashMap<>();
+
+        // 第一步:为所有节点生成新的ID并建立映射
+        for (WbsTree node : allNodes) {
+            Long newId = SnowFlakeUtil.getId();
+            idMapping.put(node.getId(), newId);
+            node.setId(newId);
         }
-        // 更新所有子节点
-        updateChildNodes(nodeMap, rootNode, rootNode.getAncestors());
+
+        // 第二步:处理根节点
+        for (WbsTree rootNode : rootNodes) {
+            // 根节点的parentId设置为targetParentId
+            rootNode.setParentId(targetParentId);
+
+            // 根节点的ancestors = 目标父节点的ancestors + "," + targetParentId
+            String targetAncestors = targetParentNode.getAncestors();
+            if (targetAncestors == null || targetAncestors.isEmpty()) {
+                rootNode.setAncestors(targetParentId.toString());
+            } else {
+                rootNode.setAncestors(targetAncestors + "," + targetParentId);
+            }
+        }
+
+        // 第三步:使用队列进行广度优先遍历,处理所有子节点
+        Queue<WbsTree> queue = new LinkedList<>(rootNodes);
+
+        while (!queue.isEmpty()) {
+            WbsTree currentNode = queue.poll();
+            Long currentNewId = currentNode.getId();
+
+            // 查找当前节点的所有直接子节点(根据原始父子关系)
+            List<WbsTree> children = allNodes.stream()
+                    .filter(node -> {
+                        // 获取节点的原始parentId
+                        Long originalParentId = getOriginalParentId(node, idMapping);
+                        // 获取当前节点的原始ID
+                        Long currentOriginalId = getKeyByValue(idMapping, currentNewId);
+                        // 判断是否是当前节点的子节点
+                        return originalParentId != null && originalParentId.equals(currentOriginalId);
+                    })
+                    .collect(Collectors.toList());
+
+            for (WbsTree child : children) {
+                // 设置子节点的parentId为当前节点的新ID
+                child.setParentId(currentNewId);
+
+                // 设置子节点的ancestors为当前节点的ancestors + "," + 当前节点的新ID
+                child.setAncestors(currentNode.getAncestors() + "," + currentNewId);
+
+                queue.offer(child);
+            }
+        }
+    }
+
+    /**
+     * 获取节点的原始parentId
+     */
+    private Long getOriginalParentId(WbsTree node, Map<Long, Long> idMapping) {
+        // 节点的parentId在复制后可能已经被修改,我们需要找到它原始的parentId
+        // 通过反向查找idMapping来找到原始的parentId
+        Long currentParentId = node.getParentId();
+
+        // 如果当前parentId不在idMapping的value中,说明这是原始parentId
+        if (!idMapping.containsValue(currentParentId)) {
+            return currentParentId;
+        }
+
+        // 如果当前parentId在idMapping的value中,找到对应的原始ID
+        return getKeyByValue(idMapping, currentParentId);
     }
 
-    // 递归更新子节点属性
-    private void updateChildNodes(Map<Long, WbsTree> nodeMap, WbsTree parentNode, String parentAncestors) {
-        // 查找当前节点的所有直接子节点(通过pId匹配父节点的pKeyId)
-        List<WbsTree> childNodes = nodeMap.values().stream()
-                .filter(node -> node.getParentId() != null && node.getParentId().equals(parentNode.getId()))
-                .collect(Collectors.toList());
-        // 更新每个子节点的属性
-        for (WbsTree childNode : childNodes) {
-            // 为子节点生成新的随机ID
-            Long newChildId = SnowFlakeUtil.getId();
-            // id设置为新的随机ID
-            childNode.setId(newChildId);
-            // parentId设置为父节点的id
-            childNode.setParentId(parentNode.getId());
-            // ancestors设置为父节点的ancestors加上父节点的id
-            childNode.setAncestors(parentAncestors + "," + parentNode.getId());
-            // 递归更新孙子节点
-            updateChildNodes(nodeMap, childNode, childNode.getAncestors());
+    /**
+     * 根据value从Map中获取key
+     */
+    private Long getKeyByValue(Map<Long, Long> map, Long value) {
+        for (Map.Entry<Long, Long> entry : map.entrySet()) {
+            if (entry.getValue().equals(value)) {
+                return entry.getKey();
+            }
         }
+        return null;
     }
 
+
+
     /**
      * 公有排序
      */