Sfoglia il codice sorgente

Merge remote-tracking branch 'origin/master' into master

yangyj 2 anni fa
parent
commit
cad7999af2

+ 1 - 1
blade-ops/blade-resource/src/main/java/org/springblade/resource/builder/oss/AliOssBuilder.java

@@ -57,7 +57,7 @@ public class AliOssBuilder {
 		ossProperties.setBucketName(oss.getBucketName());
 		CredentialsProvider credentialsProvider = new DefaultCredentialProvider(ossProperties.getAccessKey(), ossProperties.getSecretKey());
 		OSSClient ossClient = new OSSClient(ossProperties.getEndpoint(), credentialsProvider, conf);
-		return new AliossTemplate(ossClient, ossProperties, ossRule);
+		return new AliossTemplateRe(ossClient, ossProperties, ossRule);
 	}
 
 }

+ 291 - 0
blade-ops/blade-resource/src/main/java/org/springblade/resource/builder/oss/AliossTemplateRe.java

@@ -0,0 +1,291 @@
+package org.springblade.resource.builder.oss;
+
+import com.aliyun.oss.OSSClient;
+import com.aliyun.oss.common.utils.BinaryUtil;
+import com.aliyun.oss.model.MatchMode;
+import com.aliyun.oss.model.ObjectMetadata;
+import com.aliyun.oss.model.PolicyConditions;
+import com.aliyun.oss.model.PutObjectResult;
+import java.io.InputStream;
+import java.nio.charset.StandardCharsets;
+import java.util.Date;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+
+import lombok.SneakyThrows;
+import org.springblade.core.oss.OssTemplate;
+import org.springblade.core.oss.model.BladeFile;
+import org.springblade.core.oss.model.OssFile;
+import org.springblade.core.oss.props.OssProperties;
+import org.springblade.core.oss.rule.OssRule;
+import org.springblade.core.tool.jackson.JsonUtil;
+import org.springframework.util.StringUtils;
+import org.springframework.web.multipart.MultipartFile;
+
+public class AliossTemplateRe implements OssTemplate {
+    private final OSSClient ossClient;
+    private final OssProperties ossProperties;
+    private final OssRule ossRule;
+
+    public void makeBucket(String bucketName) {
+        try {
+            if (!this.bucketExists(bucketName)) {
+                this.ossClient.createBucket(this.getBucketName(bucketName));
+            }
+
+        } catch (Throwable var3) {
+            throw var3;
+        }
+    }
+
+    public void removeBucket(String bucketName) {
+        try {
+            this.ossClient.deleteBucket(this.getBucketName(bucketName));
+        } catch (Throwable var3) {
+            throw var3;
+        }
+    }
+
+    public boolean bucketExists(String bucketName) {
+        try {
+            return this.ossClient.doesBucketExist(this.getBucketName(bucketName));
+        } catch (Throwable var3) {
+            throw var3;
+        }
+    }
+
+    public void copyFile(String bucketName, String fileName, String destBucketName) {
+        try {
+            this.ossClient.copyObject(this.getBucketName(bucketName), fileName, this.getBucketName(destBucketName), fileName);
+        } catch (Throwable var5) {
+            throw var5;
+        }
+    }
+
+    public void copyFile(String bucketName, String fileName, String destBucketName, String destFileName) {
+        try {
+            this.ossClient.copyObject(this.getBucketName(bucketName), fileName, this.getBucketName(destBucketName), destFileName);
+        } catch (Throwable var6) {
+            throw var6;
+        }
+    }
+
+    public OssFile statFile(String fileName) {
+        try {
+            return this.statFile(this.ossProperties.getBucketName(), fileName);
+        } catch (Throwable var3) {
+            throw var3;
+        }
+    }
+
+    public OssFile statFile(String bucketName, String fileName) {
+        try {
+            ObjectMetadata stat = this.ossClient.getObjectMetadata(this.getBucketName(bucketName), fileName);
+            OssFile ossFile = new OssFile();
+            ossFile.setName(fileName);
+            ossFile.setLink(this.fileLink(ossFile.getName()));
+            ossFile.setHash(stat.getContentMD5());
+            ossFile.setLength(stat.getContentLength());
+            ossFile.setPutTime(stat.getLastModified());
+            ossFile.setContentType(stat.getContentType());
+            return ossFile;
+        } catch (Throwable var5) {
+            throw var5;
+        }
+    }
+
+    public String filePath(String fileName) {
+        try {
+            return this.getOssHost().concat("/").concat(fileName);
+        } catch (Throwable var3) {
+            throw var3;
+        }
+    }
+
+    public String filePath(String bucketName, String fileName) {
+        try {
+            return this.getOssHost(bucketName).concat("/").concat(fileName);
+        } catch (Throwable var4) {
+            throw var4;
+        }
+    }
+
+    public String fileLink(String fileName) {
+        try {
+            return this.getOssHost().concat("/").concat(fileName);
+        } catch (Throwable var3) {
+            throw var3;
+        }
+    }
+
+    public String fileLink(String bucketName, String fileName) {
+        try {
+            return this.getOssHost(bucketName).concat("/").concat(fileName);
+        } catch (Throwable var4) {
+            throw var4;
+        }
+    }
+
+    public BladeFile putFile(MultipartFile file) {
+        try {
+            return this.putFile(this.ossProperties.getBucketName(), file.getOriginalFilename(), file);
+        } catch (Throwable var3) {
+            throw var3;
+        }
+    }
+
+    public BladeFile putFile(String fileName, MultipartFile file) {
+        try {
+            return this.putFile(this.ossProperties.getBucketName(), fileName, file);
+        } catch (Throwable var4) {
+            throw var4;
+        }
+    }
+
+    @SneakyThrows
+    public BladeFile putFile(String bucketName, String fileName, MultipartFile file) {
+        try {
+            return this.putFile(bucketName, fileName, file.getInputStream());
+        } catch (Throwable var5) {
+            throw var5;
+        }
+    }
+
+    public BladeFile putFile(String fileName, InputStream stream) {
+        try {
+            return this.putFile(this.ossProperties.getBucketName(), fileName, stream);
+        } catch (Throwable var4) {
+            throw var4;
+        }
+    }
+
+    public BladeFile putFile(String bucketName, String fileName, InputStream stream) {
+        try {
+            return this.put(bucketName, stream, fileName, false);
+        } catch (Throwable var5) {
+            throw var5;
+        }
+    }
+
+    public BladeFile put(String bucketName, InputStream stream, String key, boolean cover) {
+        try {
+            this.makeBucket(bucketName);
+            String originalName = key;
+            key = this.getFileName(key);
+            if (cover) {
+                this.ossClient.putObject(this.getBucketName(bucketName), key, stream);
+            } else {
+                PutObjectResult response = this.ossClient.putObject(this.getBucketName(bucketName), key, stream);
+                int retry = 0;
+
+                for(byte retryCount = 5; StringUtils.isEmpty(response.getETag()) && retry < retryCount; ++retry) {
+                    response = this.ossClient.putObject(this.getBucketName(bucketName), key, stream);
+                }
+            }
+
+            BladeFile file = new BladeFile();
+            file.setOriginalName(originalName);
+            file.setName(key);
+            file.setDomain(this.getOssHost(bucketName));
+            file.setLink(this.fileLink(bucketName, key));
+            return file;
+        } catch (Throwable var9) {
+            throw var9;
+        }
+    }
+
+    public void removeFile(String fileName) {
+        try {
+            this.ossClient.deleteObject(this.getBucketName(), fileName);
+        } catch (Throwable var3) {
+            throw var3;
+        }
+    }
+
+    public void removeFile(String bucketName, String fileName) {
+        try {
+            this.ossClient.deleteObject(this.getBucketName(bucketName), fileName);
+        } catch (Throwable var4) {
+            throw var4;
+        }
+    }
+
+    public void removeFiles(List<String> fileNames) {
+        try {
+            fileNames.forEach(this::removeFile);
+        } catch (Throwable var3) {
+            throw var3;
+        }
+    }
+
+    public void removeFiles(String bucketName, List<String> fileNames) {
+        try {
+            fileNames.forEach((fileName) -> {
+                this.removeFile(this.getBucketName(bucketName), fileName);
+            });
+        } catch (Throwable var4) {
+            throw var4;
+        }
+    }
+
+    private String getBucketName() {
+        return this.getBucketName(this.ossProperties.getBucketName());
+    }
+
+    private String getBucketName(String bucketName) {
+        return this.ossRule.bucketName(bucketName);
+    }
+
+    private String getFileName(String originalFilename) {
+        return this.ossRule.fileName(originalFilename);
+    }
+
+    public String getUploadToken() {
+        return this.getUploadToken(this.ossProperties.getBucketName());
+    }
+
+    public String getUploadToken(String bucketName) {
+        return this.getUploadToken(bucketName, (Long)this.ossProperties.getArgs().get("expireTime", 3600L));
+    }
+
+    public String getUploadToken(String bucketName, long expireTime) {
+        String baseDir = "upload";
+        long expireEndTime = System.currentTimeMillis() + expireTime * 1000L;
+        Date expiration = new Date(expireEndTime);
+        PolicyConditions policyConds = new PolicyConditions();
+        policyConds.addConditionItem("content-length-range", 0L, (long)(Integer)this.ossProperties.getArgs().get("contentLengthRange", 10485760));
+        policyConds.addConditionItem(MatchMode.StartWith, "key", baseDir);
+        String postPolicy = this.ossClient.generatePostPolicy(expiration, policyConds);
+        byte[] binaryData = postPolicy.getBytes(StandardCharsets.UTF_8);
+        String encodedPolicy = BinaryUtil.toBase64String(binaryData);
+        String postSignature = this.ossClient.calculatePostSignature(postPolicy);
+        Map<String, String> respMap = new LinkedHashMap(16);
+        respMap.put("accessid", this.ossProperties.getAccessKey());
+        respMap.put("policy", encodedPolicy);
+        respMap.put("signature", postSignature);
+        respMap.put("dir", baseDir);
+        respMap.put("host", this.getOssHost(bucketName));
+        respMap.put("expire", String.valueOf(expireEndTime / 1000L));
+        return JsonUtil.toJson(respMap);
+    }
+
+    public String getOssHost(String bucketName) {
+        String prefix = this.ossProperties.getEndpoint().contains("https://") ? "https://" : "http://";
+        if(this.ossProperties.getEndpoint().indexOf("-internal")>=0){
+            return prefix + this.getBucketName(bucketName) + "." + this.ossProperties.getEndpoint().replaceAll("-internal","").replaceFirst(prefix, "");
+        }else{
+            return prefix + this.getBucketName(bucketName) + "." + this.ossProperties.getEndpoint().replaceFirst(prefix, "");
+        }
+    }
+
+    public String getOssHost() {
+        return this.getOssHost(this.ossProperties.getBucketName());
+    }
+
+    public AliossTemplateRe(final OSSClient ossClient, final OssProperties ossProperties, final OssRule ossRule) {
+        this.ossClient = ossClient;
+        this.ossProperties = ossProperties;
+        this.ossRule = ossRule;
+    }
+}

+ 0 - 7
blade-ops/blade-resource/src/main/java/org/springblade/resource/builder/oss/OssBuilder.java

@@ -94,11 +94,6 @@ public class OssBuilder {
                     OssRule ossRule;
                     // 若采用默认设置则开启多租户模式, 若是用户自定义oss则不开启
                     if (oss.getEndpoint().equals(ossProperties.getEndpoint()) && oss.getAccessKey().equals(ossProperties.getAccessKey()) && ossProperties.getTenantMode()) {
-                        /**
-                         * @author liuYc
-                         * @create 2023-03-31
-                         * @deprecated 重写BladeOssRule-》BladeOssRuleRe 修改文件名UUID -》原始名
-                         */
                         ossRule = new BladeOssRule(Boolean.TRUE);
                     } else {
                         ossRule = new BladeOssRule(Boolean.FALSE);
@@ -128,8 +123,6 @@ public class OssBuilder {
      */
     public Oss getOss(String tenantId, String code) {
         String key = StringUtils.isNotEmpty(tenantId) ? tenantId : OSS_TENANT_ID;
-        System.out.println("oss----"+tenantId);
-        System.out.println("oss_code=====--"+code);
         LambdaQueryWrapper<Oss> lqw = Wrappers.<Oss>query().lambda().eq(Oss::getTenantId, key);
         // 获取传参的资源编号并查询,若有则返回,若没有则调启用的配置
         String ossCode = StringUtil.isBlank(code) ? WebUtil.getParameter(OSS_PARAM_KEY) : code;

+ 2 - 0
blade-service-api/blade-archive-api/src/main/java/org/springblade/archive/vo/ArchivesAutoVO.java

@@ -178,5 +178,7 @@ public class ArchivesAutoVO extends ArchivesAuto {
 		private String dutyUser;
 
 		private  String archiveId;
+
+		private Long id;
 	}
 }

+ 3 - 0
blade-service/blade-archive/src/main/java/org/springblade/archive/service/IArchiveAutoPdfService.java

@@ -22,4 +22,7 @@ public interface IArchiveAutoPdfService {
 
     //获取文件的pdf文件的url
     String getPdfFileUrl(ArchiveFile file);
+
+    //只刷新档号
+    boolean refreshFileNumber(ArchivesAuto archive,String fileNumber);
 }

+ 7 - 1
blade-service/blade-archive/src/main/java/org/springblade/archive/service/impl/ArchiveAutoPdfServiceImpl.java

@@ -707,7 +707,12 @@ public class ArchiveAutoPdfServiceImpl implements IArchiveAutoPdfService {
      * @param archive
      * @param fileNumber
      */
-    public void RefreshFileNumber(ArchivesAuto archive,String fileNumber) {
+    public boolean refreshFileNumber(ArchivesAuto archive,String fileNumber) {
+        //没变化则不用刷新
+        if (fileNumber.equals(archive.getFileNumber())) {
+            return false;
+        }
+
         Long projectId = archive.getProjectId();
         archive.setFileNumber(fileNumber);
 
@@ -718,6 +723,7 @@ public class ArchiveAutoPdfServiceImpl implements IArchiveAutoPdfService {
                 .orderByAsc(ArchiveFile::getSort));
 
         buildArchiveFrontPdfs(projectId,archive,archiveFiles);
+        return true;
     }
 
 }

+ 47 - 1
blade-service/blade-archive/src/main/java/org/springblade/archive/service/impl/ArchivesAutoServiceImpl.java

@@ -26,6 +26,7 @@ import lombok.AllArgsConstructor;
 import org.apache.commons.lang.StringUtils;
 import org.springblade.archive.entity.ArchivesAuto;
 import org.springblade.archive.service.IArchiveAutoPdfService;
+import org.springblade.archive.utils.ArchiveTreeUtil;
 import org.springblade.archive.vo.ArchivesAutoVO;
 import org.springblade.archive.mapper.ArchivesAutoMapper;
 import org.springblade.archive.service.IArchivesAutoService;
@@ -35,6 +36,7 @@ import org.springblade.core.mp.base.BaseServiceImpl;
 import org.springblade.core.mp.support.Condition;
 import org.springblade.core.mp.support.Query;
 import org.springblade.core.tool.utils.Func;
+import org.springblade.core.tool.utils.StringUtil;
 import org.springblade.manager.entity.ArchiveTreeContract;
 import org.springblade.manager.entity.ContractInfo;
 import org.springblade.manager.entity.ProjectInfo;
@@ -42,6 +44,7 @@ import org.springblade.manager.feign.ArchiveTreeContractClient;
 import org.springblade.manager.feign.ContractClient;
 import org.springblade.manager.feign.ProjectClient;
 import org.springblade.manager.feign.WbsInfoClient;
+import org.springblade.manager.vo.ArchiveTreeContractVO2;
 import org.springblade.system.entity.DictBiz;
 import org.springblade.system.feign.IDictBizClient;
 import org.springframework.stereotype.Service;
@@ -329,6 +332,7 @@ public class ArchivesAutoServiceImpl extends BaseServiceImpl<ArchivesAutoMapper,
 		//archivesAuto.setIscheck(0);
 		archivesAuto.setIsAutoFile(0);//是否案卷收集上传的案卷
 		archivesAuto.setIsLock(0);//案卷锁定状态
+		archivesAuto.setIsDeleted(0);
 		baseMapper.insert(archivesAuto);
 		return archivesAuto;
 	}
@@ -769,11 +773,53 @@ public class ArchivesAutoServiceImpl extends BaseServiceImpl<ArchivesAutoMapper,
 	public List<ArchivesAuto> findArchivesAutosByIds(List<Long> ids) {
 		QueryWrapper<ArchivesAuto> queryWrapper = new QueryWrapper<>();
 		queryWrapper.in("node_id", ids)
-				.orderByDesc("tree_sort")
+				.eq("is_deleted",0)
+				.eq("is_archive",1)
+				.orderByAsc("tree_sort")
 				.orderByAsc("auto_file_sort");
 
 		return this.list(queryWrapper);
 	}
 
+	/**
+	 * 不重组的情况下刷新档号
+	 * @param archiveTreeContracts
+	 */
+	public void refreshFileNumberNoSlipt(List<ArchiveTreeContract> archiveTreeContracts) {
+
+		List<ArchiveTreeContractVO2> subTreeList = new ArrayList<>();
+		List<List<ArchiveTreeContract>>  subGroupedList = new ArrayList<>();
+		ArchiveTreeUtil.getGroupedList(archiveTreeContracts,subTreeList,subGroupedList);
+		Integer index = 1;
+
+		List<ArchivesAuto> changeList = new ArrayList<>();
+
+		//分组,分程 建设单位,各个合同段,电子单位等
+		for (List<ArchiveTreeContract> subList: subGroupedList) {
+			List<Long> ids = subList.stream()
+					.map(ArchiveTreeContract::getId)
+					.collect(Collectors.toList());
+
+			index =1;
+			List<ArchivesAuto> archivesAutos = findArchivesAutosByIds(ids);
+			if (archivesAutos == null || archivesAutos.size() == 0) {
+				return;
+			}
+			String fileNumberPrefix=subList.get(0).getFileNumberPrefix();
+			String archiveNameSuffix=subList.get(0).getArchiveNameSuffix();
+			if (StringUtils.isEmpty(archiveNameSuffix)) {
+				archiveNameSuffix = "";
+			}
+			for (ArchivesAuto archivesAuto: archivesAutos) {
+				String fileNumber = fileNumberPrefix + index + archiveNameSuffix;
+				if (archiveAutoPdfService.refreshFileNumber(archivesAuto,fileNumber)){
+					changeList.add(archivesAuto);
+				}
+				index++;
+			}
+		}
+		this.updateBatchById(changeList);
+	}
+
 
 }

+ 37 - 16
blade-service/blade-business/src/main/java/org/springblade/business/service/impl/ImageClassificationFileServiceImpl.java

@@ -30,6 +30,7 @@ import org.springblade.business.service.IImageClassificationFileService;
 import org.springblade.business.vo.TreeVo;
 import org.springblade.common.utils.CommonUtil;
 import org.springblade.core.mp.base.BaseServiceImpl;
+import org.springblade.core.tool.utils.ObjectUtil;
 import org.springblade.manager.entity.WbsParam;
 import org.springblade.manager.entity.WbsTree;
 import org.springblade.manager.entity.WbsTreeContract;
@@ -145,12 +146,25 @@ public class ImageClassificationFileServiceImpl extends BaseServiceImpl<ImageCla
 
     @Override
     public String getFileTitleName(String pKeyId) {
-        WbsTreeContract wbsTreeContract = jdbcTemplate.query("select id,ancestors,contract_id,project_id,wbs_id from m_wbs_tree_contract where is_deleted = 0 and status = 1 and p_key_id = " + pKeyId, new BeanPropertyRowMapper<>(WbsTreeContract.class)).stream().findAny().orElse(null);
+        WbsTreeContract wbsTreeContract = jdbcTemplate.query("select * from m_wbs_tree_contract where is_deleted = 0 and status = 1 and p_key_id = " + pKeyId, new BeanPropertyRowMapper<>(WbsTreeContract.class)).stream().findAny().orElse(null);
         if (wbsTreeContract != null) {
+            //获取当前节点所有父级节点
+            List<WbsTreeContract> result = new ArrayList<>();
+            this.recursiveGetParentNodes(result, wbsTreeContract);
+            result.add(wbsTreeContract);
+            result.sort(Comparator.comparing(WbsTreeContract::getNodeType).thenComparing(WbsTreeContract::getParentId));
+            List<String> allNodeIds = result.stream().map(WbsTreeContract::getId).map(String::valueOf).collect(Collectors.toList());
+
             WbsParam wbsParam = jdbcTemplate.query("select v from m_wbs_param where is_deleted = 0 and status = 1 and v is not null and k = 'FILE_TITLE' and name = '文件题名' and node_id = " + wbsTreeContract.getId(), new BeanPropertyRowMapper<>(WbsParam.class)).stream().findAny().orElse(null);
-            if (wbsParam != null) {
-                String[] titles = wbsParam.getV().split("-");
+
+            if (ObjectUtil.isNotEmpty(wbsTreeContract.getOldId())) {
+                //表示复制、新增节点
+                wbsParam = jdbcTemplate.query("select v from m_wbs_param where is_deleted = 0 and status = 1 and v is not null and k = 'FILE_TITLE' and name = '文件题名' and node_id = " + wbsTreeContract.getOldId(), new BeanPropertyRowMapper<>(WbsParam.class)).stream().findAny().orElse(null);
+            }
+
+            if (wbsParam != null && allNodeIds.size() > 0) {
                 List<String> nodeNumber = new ArrayList<>();
+                String[] titles = wbsParam.getV().split("-");
                 for (String title : titles) {
                     if (title.contains("c") || title.contains("C")) {
                         String lastStr = title.substring(title.length() - 1);
@@ -158,31 +172,29 @@ public class ImageClassificationFileServiceImpl extends BaseServiceImpl<ImageCla
                     }
                 }
 
-                List<String> ancestors = Arrays.asList(wbsTreeContract.getAncestors().split(","));
-
                 List<String> ids = new ArrayList<>();
                 for (String index : nodeNumber) {
-                    if ("0".equals(index)) {
-                        index = "1";
-                    }
-                    if (Integer.parseInt(index) <= ancestors.size()) {
-                        String id = ancestors.get(Integer.parseInt(index));
+                    if (Integer.parseInt(index) <= result.size()) {
+                        String id = allNodeIds.get(Integer.parseInt(index));
                         if (StringUtils.isNotEmpty(id)) {
                             ids.add(id);
                         }
                     }
                 }
 
-                List<WbsTreeContract> wbsTreeContractList = jdbcTemplate.query("select node_name from m_wbs_tree_contract where is_deleted = 0 and status = 1 and project_id = " + wbsTreeContract.getProjectId() + " and contract_id = " + wbsTreeContract.getContractId() + " and wbs_id = " + wbsTreeContract.getWbsId() + " and id in(" + StringUtils.join(ids, ",") + ")", new BeanPropertyRowMapper<>(WbsTreeContract.class));
-                if (wbsTreeContractList.size() > 0) {
-                    List<String> nameList = wbsTreeContractList.stream().map(WbsTreeContract::getNodeName).collect(Collectors.toList());
+                List<WbsTreeContract> filteredList = result.stream()
+                        .filter(e -> ids.stream().anyMatch(id -> id.equals(String.valueOf(e.getId()))))
+                        .collect(Collectors.toList());
+
+                if (filteredList.size() > 0) {
+                    List<String> nameList = filteredList.stream().map(WbsTreeContract::getFullName).collect(Collectors.toList());
                     if (nameList.size() > 0) {
                         return StringUtils.join(nameList, "");
                     }
                 } else {
-                    //如果私有是空的,就去公有WBS找
-                    List<WbsTree> wbsTreeList = jdbcTemplate.query("select node_name from m_wbs_tree where is_deleted = 0 and status = 1 and id in(" + StringUtils.join(ids, ",") + ")", new BeanPropertyRowMapper<>(WbsTree.class));
-                    List<String> nameList = wbsTreeList.stream().map(WbsTree::getNodeName).collect(Collectors.toList());
+                    //如果私有WBS为空,到公有WBS获取
+                    List<WbsTree> wbsTreeList = jdbcTemplate.query("select full_name from m_wbs_tree where is_deleted = 0 and status = 1 and id in(" + StringUtils.join(ids, ",") + ")", new BeanPropertyRowMapper<>(WbsTree.class));
+                    List<String> nameList = wbsTreeList.stream().map(WbsTree::getFullName).collect(Collectors.toList());
                     if (nameList.size() > 0) {
                         return StringUtils.join(nameList, "");
                     }
@@ -192,4 +204,13 @@ public class ImageClassificationFileServiceImpl extends BaseServiceImpl<ImageCla
         return null;
     }
 
+    //反向递归获取父级
+    private void recursiveGetParentNodes(List<WbsTreeContract> result, WbsTreeContract wbsTreeContract) {
+        WbsTreeContract parentNode = jdbcTemplate.query("select * from m_wbs_tree_contract where is_deleted = 0 and status = 1 and type = 1 and parent_id != 0 and id = " + wbsTreeContract.getParentId() + " and contract_id = " + wbsTreeContract.getContractId(), new BeanPropertyRowMapper<>(WbsTreeContract.class)).stream().findAny().orElse(null);
+        if (parentNode != null) {
+            result.add(parentNode);
+            this.recursiveGetParentNodes(result, parentNode);
+        }
+    }
+
 }