|
@@ -600,80 +600,132 @@ public class WbsTreeServiceImpl extends BaseServiceImpl<WbsTreeMapper, WbsTree>
|
|
}
|
|
}
|
|
|
|
|
|
@Override
|
|
@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 -> {
|
|
.map(node -> {
|
|
- // 创建每个节点的副本
|
|
|
|
WbsTree copy = new WbsTree();
|
|
WbsTree copy = new WbsTree();
|
|
- BeanUtils.copyProperties(copy, node);
|
|
|
|
|
|
+ BeanUtils.copyProperties(node, copy);
|
|
return copy;
|
|
return copy;
|
|
})
|
|
})
|
|
.collect(Collectors.toList());
|
|
.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());
|
|
.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;
|
|
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;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+
|
|
|
|
+
|
|
/**
|
|
/**
|
|
* 公有排序
|
|
* 公有排序
|
|
*/
|
|
*/
|