Kaynağa Gözat

档案优化节点删除 最终版

cr 4 gün önce
ebeveyn
işleme
2adfa9acfb

+ 6 - 0
blade-service/blade-manager/src/main/java/org/springblade/manager/mapper/ArchiveTreeContractMapper.java

@@ -194,4 +194,10 @@ public interface ArchiveTreeContractMapper extends BaseMapper<ArchiveTreeContrac
     List<ArchiveTreeContract> getArchiveTreeContractListByListOrderByTreeSort(@Param("nodeIds") List<Long> nodeIds);
 
     void callGetChildIds(@Param("params") Map<String, Object> params);
+
+    List<Long> listAllChildIdsByCte(@Param("parentId") Long parentId, @Param("projectId") Long projectId, @Param("tenantId") String tenantId);
+
+    Integer checkNodeExists(@Param("parentId") Long parentId, @Param("projectId") Long projectId, @Param("tenantId") String tenantId);
+
+    List<Long> listDirectChildIds(@Param("parentId") Long parentId, @Param("projectId") Long projectId, @Param("tenantId") String tenantId);
 }

+ 41 - 0
blade-service/blade-manager/src/main/java/org/springblade/manager/mapper/ArchiveTreeContractMapper.xml

@@ -1051,4 +1051,45 @@
             #{params.outIds, mode=OUT, jdbcType=VARCHAR}
             )
     </select>
+    <select id="listAllChildIdsByCte" resultType="java.lang.Long">
+        WITH RECURSIVE child_nodes AS (
+            -- 初始节点:用MyBatis参数占位符,避免硬编码
+            SELECT id FROM m_archive_tree_contract
+            WHERE id = #{parentId}
+              AND is_deleted = 0
+              AND project_id = #{projectId}
+              AND tenant_id = #{tenantId}
+            UNION ALL
+            -- 递归子节点:关联CTE结果
+            SELECT t.id FROM m_archive_tree_contract t
+                                 INNER JOIN child_nodes cn ON t.parent_id = cn.id
+            WHERE t.is_deleted = 0
+              AND t.project_id = #{projectId}
+              AND t.tenant_id = #{tenantId}
+        )
+        SELECT id FROM child_nodes;
+    </select>
+    <!-- 查询单个节点的直接子节点(非递归,仅一级) -->
+    <select id="listDirectChildIds" resultType="java.lang.Long">
+        SELECT id
+        FROM m_archive_tree_contract
+        WHERE parent_id = #{parentId}
+        AND is_deleted = 0
+        AND project_id = #{projectId}
+        <if test="tenantId != null and tenantId != ''">
+            AND tenant_id = #{tenantId}
+        </if>
+    </select>
+
+    <!-- 校验节点是否存在(可选,优化性能) -->
+    <select id="checkNodeExists" resultType="java.lang.Integer">
+        SELECT COUNT(1)
+        FROM m_archive_tree_contract
+        WHERE id = #{parentId}
+        AND is_deleted = 0
+        AND project_id = #{projectId}
+        <if test="tenantId != null and tenantId != ''">
+            AND tenant_id = #{tenantId}
+        </if>
+    </select>
 </mapper>

+ 30 - 18
blade-service/blade-manager/src/main/java/org/springblade/manager/service/impl/ArchiveTreeContractServiceImpl.java

@@ -781,8 +781,8 @@ public class ArchiveTreeContractServiceImpl extends BaseServiceImpl<ArchiveTreeC
 		String tenantId = AuthUtil.getTenantId();
 		Long projectId = dstNode.getProjectId();
 
-		// 调用优化后的listAllChildIds(CTE/存储过程均可)
-		List<Long> ids = this.listAllChildIds(id, projectId, tenantId);
+		// 调用纯Java递归方法,替代CTE/存储过程
+		List<Long> ids = listAllChildIds(id, projectId, tenantId);
 		if (CollectionUtils.isEmpty(ids)) {
 			return false;
 		}
@@ -792,24 +792,36 @@ public class ArchiveTreeContractServiceImpl extends BaseServiceImpl<ArchiveTreeC
 	}
 
 	public List<Long> listAllChildIds(Long parentId, Long projectId, String tenantId) {
-		// 1. 构建存储过程入参
-		Map<String, Object> params = new HashMap<>(4);
-		params.put("parentId", parentId);
-		params.put("projectId", projectId);
-		params.put("tenantId", tenantId);
-		params.put("outIds", "");  // 初始化出参
-
-		// 2. 调用存储过程
-		baseMapper.callGetChildIds(params);
-
-		// 3. 解析出参(逗号分隔的ID字符串转Long列表)
-		String outIds = (String) params.get("outIds");
-		if (StringUtils.isEmpty(outIds)) {
+		// 1. 先校验节点是否存在,避免无效递归
+		Integer exists = baseMapper.checkNodeExists(parentId, projectId, tenantId);
+		if (exists == null || exists == 0) {
 			return Collections.emptyList();
 		}
-		return Arrays.stream(outIds.split(","))
-				.map(Long::valueOf)
-				.collect(Collectors.toList());
+
+		// 2. 递归收集所有子节点ID(含自身)
+		List<Long> allChildIds = new ArrayList<>();
+		collectAllChildIds(parentId, projectId, tenantId, allChildIds);
+		return allChildIds;
+	}
+
+	private void collectAllChildIds(Long currentId, Long projectId, String tenantId, List<Long> allChildIds) {
+		// 防止循环引用(如父节点引用子节点)导致死循环
+		if (allChildIds.contains(currentId)) {
+			return;
+		}
+		// 添加当前节点ID
+		allChildIds.add(currentId);
+
+		// 查询当前节点的直接子节点
+		List<Long> directChildIds = baseMapper.listDirectChildIds(currentId, projectId, tenantId);
+		if (CollectionUtils.isEmpty(directChildIds)) {
+			return; // 无直接子节点,递归终止
+		}
+
+		// 递归查询子节点的子节点
+		for (Long childId : directChildIds) {
+			collectAllChildIds(childId, projectId, tenantId, allChildIds);
+		}
 	}
 
 	/**