huangtf 2 ani în urmă
părinte
comite
772a9ea89d
15 a modificat fișierele cu 493 adăugiri și 49 ștergeri
  1. 22 0
      blade-common/src/main/java/org/springblade/common/utils/INodeEx.java
  2. 2 1
      blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/entity/ArchiveTree.java
  3. 27 0
      blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/entity/ArchiveTreeContract.java
  4. 11 1
      blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/vo/ArchiveTreeContractVO2.java
  5. 4 0
      blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/vo/ArchiveTreeVO2.java
  6. 2 0
      blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/vo/WbsTreeVO2.java
  7. 22 0
      blade-service/blade-manager/src/main/java/org/springblade/manager/controller/ArchiveTreeContractController.java
  8. 23 0
      blade-service/blade-manager/src/main/java/org/springblade/manager/controller/ArchiveTreeController.java
  9. 8 1
      blade-service/blade-manager/src/main/java/org/springblade/manager/mapper/ArchiveTreeContractMapper.xml
  10. 2 1
      blade-service/blade-manager/src/main/java/org/springblade/manager/mapper/WbsTreePrivateMapper.xml
  11. 2 0
      blade-service/blade-manager/src/main/java/org/springblade/manager/service/IArchiveTreeContractService.java
  12. 2 0
      blade-service/blade-manager/src/main/java/org/springblade/manager/service/IArchiveTreeService.java
  13. 160 1
      blade-service/blade-manager/src/main/java/org/springblade/manager/service/impl/ArchiveTreeContractServiceImpl.java
  14. 58 44
      blade-service/blade-manager/src/main/java/org/springblade/manager/service/impl/ArchiveTreeServiceImpl.java
  15. 148 0
      blade-service/blade-manager/src/main/java/org/springblade/manager/utils/ForestNodeMergerEx.java

+ 22 - 0
blade-common/src/main/java/org/springblade/common/utils/INodeEx.java

@@ -12,6 +12,28 @@ public interface INodeEx<T> extends Serializable {
 
     List<T> getChildren();
 
+    Long getFromId();
+
+    String getAncestors();
+
+    Integer getSort();
+
+    String getTreeSort();
+
+    Long getValue();
+
+    void setId(Long id);
+
+    void setParentId(Long parentId);
+
+    void setFromId(Long fromId);
+
+    void setAncestors(String ancestors);
+
+    void setSort(Integer sort);
+
+    void setTreeSort(String sortTree);
+
     default Boolean getHasChildren() {
         return false;
     }

+ 2 - 1
blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/entity/ArchiveTree.java

@@ -181,8 +181,9 @@ public class ArchiveTree extends BaseEntity {
         try {
             BeanUtils.copyProperties(archiveTree,this);
             this.nodeName = archiveTree.getTitle();
+            this.fullName = archiveTree.getTitle();
             this.isUploadFileDisplayConfigurationTree = archiveTree.getIsDisplayTree();
-            this.fromId = archiveTree.getId();
+
         } catch (BeansException e) {
             e.printStackTrace();
         }

+ 27 - 0
blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/entity/ArchiveTreeContract.java

@@ -20,9 +20,11 @@ import com.baomidou.mybatisplus.annotation.TableName;
 import java.io.Serializable;
 
 import io.swagger.annotations.ApiModelProperty;
+import org.apache.commons.lang.StringUtils;
 import org.springblade.core.mp.base.BaseEntity;
 import lombok.Data;
 import lombok.EqualsAndHashCode;
+import org.springblade.manager.vo.ArchiveTreeContractVO2;
 import org.springblade.manager.vo.ArchiveTreeVO;
 import org.springblade.manager.vo.ArchiveTreeVO2;
 import org.springframework.beans.BeanUtils;
@@ -207,9 +209,34 @@ public class ArchiveTreeContract extends BaseEntity {
 			BeanUtils.copyProperties(archiveTree,this);
 			this.fromId = archiveTree.getId();
 			this.nodeName = archiveTree.getTitle();
+			this.fullName = archiveTree.getTitle();
 			this.isUploadFileDisplayConfigurationTree = archiveTree.getIsDisplayTree();
 		} catch (BeansException e) {
 			e.printStackTrace();
 		}
 	}
+
+	public ArchiveTreeContract(ArchiveTreeContractVO2 archiveTree) {
+		if (archiveTree == null) {
+			return;
+		}
+
+		try {
+			BeanUtils.copyProperties(archiveTree,this);
+
+			this.nodeName = archiveTree.getTitle();
+			this.fullName = archiveTree.getTitle();
+			this.isUploadFileDisplayConfigurationTree = archiveTree.getIsDisplayTree();
+		} catch (BeansException e) {
+			e.printStackTrace();
+		}
+	}
+
+	public boolean isContractRoot(){
+		if (this.getExtType() != null && this.getExtType() == 2
+				&& StringUtils.isNotEmpty(this.getTreeCode())){
+			return true;
+		}
+		return false;
+	}
 }

+ 11 - 1
blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/vo/ArchiveTreeContractVO2.java

@@ -22,6 +22,7 @@ import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
 import io.swagger.annotations.ApiModelProperty;
 import lombok.Data;
 import lombok.EqualsAndHashCode;
+import org.apache.commons.lang.StringUtils;
 import org.springblade.common.utils.INodeEx;
 import org.springblade.core.tool.node.INode;
 import org.springblade.manager.entity.ArchiveTreeContract;
@@ -187,6 +188,9 @@ public class ArchiveTreeContractVO2 implements INodeEx<ArchiveTreeContractVO2> {
 
 	//树形排序
 	private String treeSort;
+	private String treeCode;
+
+	private Long fromId;
 
 	public String toString() {
 		return "TreeNode(parentId=" + this.getParentId()
@@ -226,6 +230,12 @@ public class ArchiveTreeContractVO2 implements INodeEx<ArchiveTreeContractVO2> {
 		return 100;
 	}
 
-
+	public boolean isContractRoot(){
+		if (this.getExtType() != null && this.getExtType() == 2
+				&& StringUtils.isNotEmpty(this.getTreeCode())){
+			return true;
+		}
+		return false;
+	}
 
 }

+ 4 - 0
blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/vo/ArchiveTreeVO2.java

@@ -181,4 +181,8 @@ public class ArchiveTreeVO2 implements INodeEx<ArchiveTreeVO2> {
      */
     private Long fromId;
 
+    private String treeSort;
+
+    private String ancestors;
+
 }

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

@@ -47,6 +47,8 @@ public class WbsTreeVO2 implements INode<WbsTreeVO2> {
 
     private String ancestors;
 
+    private Long  primaryKeyId;
+
 
     @JsonInclude(JsonInclude.Include.NON_EMPTY)
     private Boolean hasChildren;

+ 22 - 0
blade-service/blade-manager/src/main/java/org/springblade/manager/controller/ArchiveTreeContractController.java

@@ -290,4 +290,26 @@ public class ArchiveTreeContractController extends BladeController {
 		return R.status(archiveTreeContractService.submitArchiveTreeSort(listSort));
 	}
 
+	/**
+	 * 初始化归档树根节点
+	 */
+	@PostMapping("/syncProjectTree")
+	@ApiOperationSupport(order = 14)
+	@ApiOperation(value = "初始化项目级归档树根节点", notes = "传入token")
+	@ApiImplicitParams(value = {
+			@ApiImplicitParam(name = "Id", value = "节点id")
+	})
+	public R<ArchiveTree> syncProjectTree(Long id) {
+
+		ArchiveTreeContract archiveTree = archiveTreeContractService.getById(id);
+		if (archiveTree == null ) {
+			return R.fail(200, "节点错误");
+		}
+		boolean b = archiveTreeContractService.syncProjectTree(archiveTree);
+		if (b) {
+			return R.success("同步成功");
+		}
+		return R.fail(200, "同步失败");
+	}
+
 }

+ 23 - 0
blade-service/blade-manager/src/main/java/org/springblade/manager/controller/ArchiveTreeController.java

@@ -241,4 +241,27 @@ public class ArchiveTreeController extends BladeController {
         return R.data(ruleMap);
     }
 
+
+    /**
+     * 初始化归档树根节点
+     */
+    @PostMapping("/syncProjectTree")
+    @ApiOperationSupport(order = 12)
+    @ApiOperation(value = "初始化项目级归档树根节点", notes = "传入token")
+    @ApiImplicitParams(value = {
+            @ApiImplicitParam(name = "Id", value = "节点id")
+    })
+    public R<ArchiveTree> syncProjectTree(Long id) {
+
+        ArchiveTree archiveTree = archiveTreeService.getById(id);
+        if (archiveTree == null ) {
+            return R.fail(200, "节点错误");
+        }
+        boolean b = archiveTreeService.syncProjectTree(archiveTree);
+        if (b) {
+            return R.success("同步成功");
+        }
+        return R.fail(200, "同步失败");
+    }
+
 }

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

@@ -41,6 +41,7 @@
         <result column="archive_auto_node_id" property="archiveAutoNodeId"/>
         <result column="archive_auto_group_select" property="archiveAutoGroupSelect"/>
         <result column="archive_auto_group_id" property="archiveAutoGroupId"/>
+        <result column="tree_code" property="treeCode"/>
     </resultMap>
 
 
@@ -97,6 +98,8 @@
         <result column="archive_auto_node_id" property="archiveAutoNodeId"/>
         <result column="archive_auto_group_select" property="archiveAutoGroupSelect"/>
         <result column="archive_auto_group_id" property="archiveAutoGroupId"/>
+        <result column="tree_sort" property="treeSort"/>
+        <result column="tree_code" property="treeCode"/>
     </resultMap>
 
 
@@ -186,6 +189,7 @@
         d.archive_auto_node_id,
         d.archive_auto_group_select,
         d.archive_auto_group_id,
+        tree_sort,
         (SELECT CASE WHEN count(1) > 0 THEN 1 ELSE 0 END FROM m_archive_tree_contract WHERE parent_id = d.id and is_deleted = 0 and project_id = #{projectId})
         AS "has_children"
         FROM
@@ -224,7 +228,10 @@
         archive_auto_type,
         archive_auto_node_id,
         archive_auto_group_select,
-        archive_auto_group_id
+        archive_auto_group_id,
+        from_id,
+        tree_sort,
+        tree_code
         FROM m_archive_tree_contract
         WHERE is_deleted = 0 and project_id = #{projectId}
         <if test=" tenantId!=null and tenantId!='' ">

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

@@ -48,6 +48,7 @@
 
     <resultMap id="WbsTreeResultMap2" type="org.springblade.manager.vo.WbsTreeVO2">
         <id column="id" property="id"/>
+        <result column="primaryKeyId" property="primaryKeyId"/>
         <result column="parent_id" property="parentId"/>
         <result column="title" property="title"/>
         <result column="value" property="value"/>
@@ -401,7 +402,7 @@
     </select>
 
     <select id="tree2" resultMap="WbsTreeResultMap2">
-        select
+        select p_key_id as "primaryKeyId",
         id, parent_id , node_name as title,type as "type", id as "value", id as "key" ,
         node_type AS "nodeType", is_exist_form AS "isExistForm",major_data_type,
         wbs_type as "wbsType"

+ 2 - 0
blade-service/blade-manager/src/main/java/org/springblade/manager/service/IArchiveTreeContractService.java

@@ -79,5 +79,7 @@ public interface IArchiveTreeContractService extends BaseService<ArchiveTreeCont
 
 	boolean submitDisplayConfigTree(String ids);
 
+	public boolean syncProjectTree(ArchiveTreeContract dstNode);
+
 
 }

+ 2 - 0
blade-service/blade-manager/src/main/java/org/springblade/manager/service/IArchiveTreeService.java

@@ -18,6 +18,8 @@ public interface IArchiveTreeService extends BaseService<ArchiveTree> {
 
 	boolean submit(ArchiveTreeDTO archiveTreeDTO);
 
+	public boolean syncProjectTree(ArchiveTree archiveTree);
+
 //	List<ArchiveTreeVO> lazyTree(String tenantId, Long parentId);
 //	List<ArchiveTreeVO> tree(String tenantI, Integer disPlayTree, Integer nodeType);
 

+ 160 - 1
blade-service/blade-manager/src/main/java/org/springblade/manager/service/impl/ArchiveTreeContractServiceImpl.java

@@ -17,7 +17,7 @@
 package org.springblade.manager.service.impl;
 
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
-import com.baomidou.mybatisplus.core.toolkit.StringUtils;
+import com.mixsmart.utils.StringUtils;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import com.baomidou.mybatisplus.core.toolkit.StringPool;
 import lombok.AllArgsConstructor;
@@ -74,6 +74,8 @@ public class ArchiveTreeContractServiceImpl extends BaseServiceImpl<ArchiveTreeC
 
 	private final IProjectInfoService projectInfoService;
 
+	private final ArchiveTreeContractSyncImpl archiveTreeContractSync;
+
 
 	@Override
 	public IPage<ArchiveTreeContractVO> selectArchiveTreeContractPage(IPage<ArchiveTreeContractVO> page, ArchiveTreeContractVO archiveTreeContract) {
@@ -326,4 +328,161 @@ public class ArchiveTreeContractServiceImpl extends BaseServiceImpl<ArchiveTreeC
 		return code;
 	}
 
+	/**
+	 *  同步项目级
+	 * @param dstNode
+	 * @return
+	 */
+	public boolean syncProjectTree(ArchiveTreeContract dstNode) {
+		if ( dstNode.getProjectId() == 0) {
+			return false;
+		}
+
+		ArchiveTree srcNode = null;
+		if (dstNode.isContractRoot() && dstNode.getFromId() == null ) {
+			ArchiveTreeContract parentNode = this.getById(dstNode.getParentId());
+			if (parentNode!= null) {
+				srcNode = archiveTreeService.getById(parentNode.getFromId());
+			}
+		}else {
+			srcNode = archiveTreeService.getById(dstNode.getFromId());
+		}
+
+		if (srcNode == null ) {
+			return false;
+		}
+
+		// 0,业主树同步, 1,根节点同步,  2. 建设单位或者施工单位同步添加合同段 3.  合同段内部同步
+
+
+		List<ArchiveTreeVO2> srcTrees = archiveTreeService.tree2(AuthUtil.getTenantId(), dstNode.getProjectId(),
+				null, null,null,false);
+		List<ArchiveTreeContractVO2> dstTrees = this.tree2(AuthUtil.getTenantId(),null,null,dstNode.getProjectId(),null);
+		List<ArchiveTreeContract> saveList = new ArrayList<>();
+		ArchiveTreeContractVO2 dstTree = dstTrees.get(0);
+		if (dstTree == null ) {
+			return false;
+		}
+
+		List<ContractInfo> contractInfos = contractInfoService.selectContractInfoPageByPid(dstNode.getProjectId().toString());
+		Map<Long,ContractInfo> contractMap = new LinkedHashMap<>();
+
+		boolean bHasContract = true;
+		if (contractInfos == null || contractInfos.size() == 0) {
+			bHasContract = false;
+		}
+
+		//预处理
+		if (bHasContract) {
+
+			for (ContractInfo contractInfo: contractInfos) {
+				contractInfo.setStatus(0);
+				contractMap.put(contractInfo.getId(),contractInfo);
+			}
+
+			for (ArchiveTreeContractVO2 ar: dstTree.getChildren()) {
+				//施工和监理
+
+				ar.setValue(1L);
+				if (ar.getTreeCode()!= null && (
+						ar.getTreeCode().equals("C") || ar.getTreeCode().equals("S"))) {
+
+					if (ar.getChildren() == null ) {
+						continue;
+					}
+
+					//处理合同节点
+					int contractNum = 0;
+					for (ArchiveTreeContractVO2 contractNode : ar.getChildren()) {
+						if (contractNode.isContractRoot()){
+							//需要删除
+							contractNum++;
+
+							contractNode.setValue(1L);
+
+							//设置哪个合同已经设置了。
+							ContractInfo c = contractMap.get(Long.parseLong(contractNode.getTreeCode()));
+							if (c!= null) {
+								c.setStatus(1);
+							}
+						}
+					}
+
+					if (contractNum == 0) {
+						//删除树的子节点
+						deleteTreeChildren(ar);
+					}
+
+
+					for(Map.Entry<Long,ContractInfo> entry : contractMap.entrySet()){
+						ContractInfo contractInfo = entry.getValue();
+
+						if (contractInfo.getStatus() == 0) {
+							if (ar.getTreeCode().equals("C") && contractInfo.getContractType() == 1) {
+								//复制施工
+							}
+							if (ar.getTreeCode().equals("S") && contractInfo.getContractType() == 2) {
+								//复制监理
+							}
+						}
+					}
+
+				}
+			}
+		}
+
+
+		if (!bHasContract) {
+			saveList = archiveTreeContractSync.getNormalSaveList(srcNode.getId(),
+					srcTrees.get(0),dstNode.getId(),dstTrees.get(0));
+		}else {
+
+			ArchiveTreeContractVO2 dstScopeTree = ForestNodeMergerEx.getSubTreeByValue(dstTree,dstNode.getId(),1L);
+			for (ArchiveTreeContractVO2 ar: dstTree.getChildren()) {
+				if (StringUtils.isEmpty(ar.getTreeCode())) {
+					//同步
+					if (dstNode.getParentId() == 0 || dstScopeTree.getId() == ar.getId()) {
+						//同步
+						List<ArchiveTreeContract> tmpSaveList = archiveTreeContractSync.getNormalSaveList(srcNode.getId(),
+								srcTrees.get(0),dstNode.getId(),ar);
+						saveList.addAll(tmpSaveList);
+					}
+
+
+				}else {
+
+					for (ArchiveTreeContractVO2 contractNode : ar.getChildren()){
+						if (dstNode.getParentId() == 0 || dstScopeTree.getId() == contractNode.getId()) {
+
+							List<ArchiveTreeContract> tmpSaveList = archiveTreeContractSync.getNormalSaveList(srcNode.getId(),
+									srcTrees.get(0),dstNode.getId(),contractNode);
+							saveList.addAll(tmpSaveList);
+						}
+					}
+
+				}
+			}
+		}
+
+		this.saveBatch(saveList);
+		return true;
+	}
+
+	/**
+	 * 删除树的所有子节点
+	 * @param tree
+	 * @return
+	 */
+	public  boolean deleteTreeChildren(ArchiveTreeContractVO2 tree) {
+		List<Long> ids = new ArrayList<>();
+
+		ForestNodeMergerEx.getChildrenIds(tree,ids);
+
+		return this.deleteLogic(ids);
+	}
+
+
+
+
+
 }

+ 58 - 44
blade-service/blade-manager/src/main/java/org/springblade/manager/service/impl/ArchiveTreeServiceImpl.java

@@ -142,49 +142,6 @@ public class ArchiveTreeServiceImpl extends BaseServiceImpl<ArchiveTreeMapper, A
         return true;
     }
 
-    public boolean initArchiveProjectTree1(Long projectId) {
-        QueryWrapper<ArchiveTree> queryWrapper = new QueryWrapper<>();
-        queryWrapper.eq("parent_id", 0);
-        queryWrapper.eq("project_id", 0);
-        queryWrapper.eq("status", 1);
-        queryWrapper.eq("is_deleted", 0);
-        ArchiveTree archiveTree1 = archiveTreeMapper.selectOne(queryWrapper);
-        if (archiveTree1 != null) {
-            throw new ServiceException("根节点已存在,请先删除后再进行初始化");
-        }
-
-        List<ArchiveTreeVO2> sysTrees = this.tree2(AuthUtil.getTenantId(), projectId,null, null,null,false);
-        if (sysTrees == null || sysTrees.size() == 0) {
-            return false;
-        }
-
-        List<ArchiveTreeVO2> trees = new ArrayList<>();
-        ForestNodeMergerEx.getTreeList(sysTrees.get(0),trees);
-
-        List<ArchiveTree> archiveTrees = new ArrayList<>();
-        Map<Long,Long> oldNewMap = new LinkedHashMap<>();
-
-        Map<Long,ArchiveTreeVO2> archiveMap = new LinkedHashMap<>();
-
-        for (ArchiveTreeVO2 archiveTreeVO :trees) {
-            oldNewMap.put(archiveTreeVO.getId(), SnowFlakeUtil.getId());
-            archiveMap.put(archiveTreeVO.getId(), archiveTreeVO);
-        }
-        oldNewMap.put(0L,0L);
-
-        for (ArchiveTreeVO2 archiveTreeVO :trees) {
-
-            ArchiveTree archiveTree = new ArchiveTree(archiveTreeVO);
-            archiveTree.setId(oldNewMap.get(archiveTreeVO.getId()));
-            archiveTree.setParentId(oldNewMap.get(archiveTreeVO.getParentId()));
-            archiveTree.setCreateUser(AuthUtil.getUserId());
-            archiveTree.setProjectId(projectId);
-            archiveTrees.add(archiveTree);
-        }
-
-
-        return true;
-    }
 
 
 //    @Override
@@ -401,6 +358,13 @@ public class ArchiveTreeServiceImpl extends BaseServiceImpl<ArchiveTreeMapper, A
         List<WbsTreeVO2> wbsTreeVO2List = new ArrayList<>();
         ForestNodeMerger.getTreeList(wbsTreeVO2s.get(0),wbsTreeVO2List);
 
+        Map<Long,Long> idPkidMap = new LinkedHashMap<>();
+        if (projectId != 0) {
+            for (WbsTreeVO2 wbsTreeVO2:wbsTreeVO2List) {
+                idPkidMap.put(wbsTreeVO2.getId(),wbsTreeVO2.getPrimaryKeyId());
+            }
+        }
+
         //遍历构建
         for (WbsTreeVO2 wbsTreeVO2:wbsTreeVO2List) {
             //只展示指定层级之上的
@@ -413,10 +377,22 @@ public class ArchiveTreeServiceImpl extends BaseServiceImpl<ArchiveTreeMapper, A
                 continue;
             }
             ArchiveTreeVO2 archiveTree = new ArchiveTreeVO2();
+            archiveTree.setTitle(wbsTreeVO2.getTitle());
+
             archiveTree.setId(wbsTreeVO2.getId());
             archiveTree.setParentId(wbsTreeVO2.getParentId());
-            archiveTree.setTitle(wbsTreeVO2.getTitle());
             archiveTree.setExtId(wbsTreeVO2.getId());
+            if (projectId != 0) {
+                archiveTree.setId(idPkidMap.get(wbsTreeVO2.getId()));
+                int i = 0;
+                Long pid = idPkidMap.get(wbsTreeVO2.getParentId());
+                if (pid == null) {
+                    pid = 0L;
+                }
+                archiveTree.setParentId(pid);
+                archiveTree.setExtId(idPkidMap.get(wbsTreeVO2.getId()));
+            }
+
             archiveTree.setDisplayHierarchy(level.toString());
             archiveTreeList.add(archiveTree);
         }
@@ -780,4 +756,42 @@ public class ArchiveTreeServiceImpl extends BaseServiceImpl<ArchiveTreeMapper, A
         }
         return map;
     }
+
+
+    public boolean syncProjectTree(ArchiveTree dstNode) {
+        if (dstNode.getFromId() == null || dstNode.getProjectId() == 0) {
+            return false;
+        }
+
+        ArchiveTree srcNode = this.getById(dstNode.getFromId());
+        if (srcNode == null || srcNode.getProjectId() != 0) {
+            return false;
+        }
+
+        List<ArchiveTreeVO2> srcTrees = this.tree2(AuthUtil.getTenantId(), 0L,null, null,null,false);
+        List<ArchiveTreeVO2> dstTrees = this.tree2(AuthUtil.getTenantId(), dstNode.getProjectId(),null, null,null,false);
+
+        ArchiveTreeVO2 srcTree = ForestNodeMergerEx.getSubTree(srcTrees.get(0),srcNode.getId());
+        ArchiveTreeVO2 dstTree = ForestNodeMergerEx.getSubTree(dstTrees.get(0),dstNode.getId());
+        List<ArchiveTreeVO2> addDst = new ArrayList<>();
+
+        ForestNodeMergerEx.syncTreeList(srcTree ,dstTree,addDst);
+
+        List<ArchiveTree> saveList = new ArrayList<>();
+        for (ArchiveTreeVO2 addD : addDst) {
+            ArchiveTree archiveTree = new ArchiveTree(addD);
+            archiveTree.setCreateUser(AuthUtil.getUserId());
+            archiveTree.setProjectId(dstNode.getProjectId());
+
+            saveList.add(archiveTree);
+        }
+
+        //刷新treeCode
+
+        //相同的属性刷新?
+
+        this.saveBatch(saveList);
+
+        return true;
+    }
 }

+ 148 - 0
blade-service/blade-manager/src/main/java/org/springblade/manager/utils/ForestNodeMergerEx.java

@@ -1,9 +1,16 @@
 package org.springblade.manager.utils;
 
+import org.springblade.common.utils.SnowFlakeUtil;
 import org.springblade.core.tool.node.INode;
 import org.springblade.common.utils.INodeEx;
+import org.springblade.manager.vo.ArchiveTreeContractVO2;
+import org.springframework.beans.BeanUtils;
 
+import java.util.ArrayList;
+import java.util.LinkedHashMap;
 import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
 
 public class ForestNodeMergerEx {
     public static <T extends INodeEx<T>> List<T> merge(List<T> items) {
@@ -37,5 +44,146 @@ public class ForestNodeMergerEx {
         }
     }
 
+    public static <T extends INodeEx<T>> void getChildrenIds(T tree, List<Long> ids){
+        if (tree == null) {
+            return;
+        }
+
+        List<T> nodes = new ArrayList<>();
+        getTreeList(tree,nodes);
+
+        ids = nodes.stream().map(o->o.getId()).collect(Collectors.toList());
+        if (ids.size() > 0) {
+            ids.remove(0);
+        }
+    }
+
+
+    public static <T extends INodeEx<T>> T getSubTree(T tree,Long nodeId) {
+        List<T> srcList = new ArrayList<>();
+
+        getTreeList(tree,srcList);
+
+        for (T src : srcList) {
+            if (src.getId().equals(nodeId)) {
+                return  src;
+            }
+        }
+        return null;
+    }
+
+    public static <T extends INodeEx<T>> T getSubTreeByValue(T tree,Long srcNodeId,Long value) {
+        List<T> srcList = new ArrayList<>();
+
+        getTreeList(tree,srcList);
+
+        Map<Long,T> map = new LinkedHashMap<>();
+        for (T src : srcList) {
+            map.put(src.getId(),src);
+        }
+
+        T srcNode = map.get(srcNodeId);
+        while (true ) {
+            if (srcNode == null || srcNode.getValue() == value) {
+                break;
+            }
+            srcNode = map.get(srcNode.getParentId());
+        }
+        return srcNode;
+    }
+
+
+
+    public static <T extends INodeEx<T>,E extends INodeEx<E>> void syncTreeList(T srcTree, E dstTree, List<E> outList){
+        List<T> srcList = new ArrayList<>();
+        List<T> srcAddList = new ArrayList<>();
+        List<E> dstList = new ArrayList<>();
+        Map<Long,Long> srcDstMap = new LinkedHashMap<>();
+        Map<Long,E> srcTMap = new LinkedHashMap<>();
+
+
+        getTreeList(srcTree,srcList);
+        getTreeList(dstTree,dstList);
+
+        //将dst fromID全部入MAP,看看哪个没有
+        for (E dst :dstList) {
+            if (dst.getFromId() != null ) {
+                srcDstMap.put(dst.getFromId(),dst.getId());
+                srcTMap.put(dst.getFromId(),dst);
+            }
+        }
+
+
+
+        for (T src :srcList) {
+            if (srcDstMap.get(src.getId())!= null) {
+                continue;
+            }
+            srcAddList.add(src);
+        }
+
+        for (T src :srcAddList) {
+            srcDstMap.put(src.getId(), SnowFlakeUtil.getId());
+        }
+
+
+        for (T srcAdd :srcAddList) {
+
+            try {
+                E e = (E) create(dstTree.getClass());
+
+                BeanUtils.copyProperties(srcAdd,e);
+                e.setId(srcDstMap.get(srcAdd.getId()) );
+
+                Long pid = srcDstMap.get(srcAdd.getParentId());
+                if (pid == null ) {
+                    pid = dstTree.getId();
+                }
+                e.setParentId(pid);
+                e.setFromId(srcAdd.getId());
+                outList.add(e);
+
+            } catch (Exception exception) {
+                exception.printStackTrace();
+                continue;
+            }
+        }
+    }
+
+    static <T> T create(Class<T> clazz) throws Exception {
+        T a = clazz.newInstance();
+        return a;
+    }
+
+    public  <T extends INodeEx<T>> void InitAncestors(T tree, String ancestors) {
+        String localAncestors = ancestors + "," + tree.getId();
+        tree.setAncestors(ancestors);
+
+        List<T> childrens = tree.getChildren();
+        if (childrens!= null) {
+            for (T child :childrens) {
+                InitAncestors(child,localAncestors);
+            }
+        }
+    }
+
+    public <T extends INodeEx<T>> void InitTreeSort(T tree, String treeSort) {
+
+        Integer localSort = 100;
+        if (tree.getSort() != null ) {
+            localSort =  tree.getSort() + 100;
+        }
+
+        String localTreeSort = treeSort + localSort ;
+        tree.setTreeSort(localTreeSort);
+
+        List<T> childrens = tree.getChildren();
+        if (childrens!= null) {
+            for (T child :childrens) {
+                InitTreeSort(child,localTreeSort);
+            }
+        }
+    }
+
 
 }