Преглед изворни кода

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

yangyj пре 1 година
родитељ
комит
852f6c82cf
17 измењених фајлова са 447 додато и 80 уклоњено
  1. 1 1
      blade-common/src/main/java/org/springblade/common/utils/CommonUtil.java
  2. 5 0
      blade-service-api/blade-archive-api/src/main/java/org/springblade/archive/vo/ArchivesAutoVO.java
  3. 2 2
      blade-service/blade-archive/src/main/java/org/springblade/archive/controller/ArchiveFileTaskController.java
  4. 17 1
      blade-service/blade-archive/src/main/java/org/springblade/archive/controller/ArchivesAutoController.java
  5. 6 0
      blade-service/blade-archive/src/main/java/org/springblade/archive/mapper/ArchivesAutoMapper.java
  6. 29 0
      blade-service/blade-archive/src/main/java/org/springblade/archive/mapper/ArchivesAutoMapper.xml
  7. 3 0
      blade-service/blade-archive/src/main/java/org/springblade/archive/service/IArchiveOfflineVersionInfoService.java
  8. 4 1
      blade-service/blade-archive/src/main/java/org/springblade/archive/service/IArchivesAutoService.java
  9. 1 1
      blade-service/blade-archive/src/main/java/org/springblade/archive/service/impl/ArchiveOfflineVersionInfoServiceImpl.java
  10. 190 59
      blade-service/blade-archive/src/main/java/org/springblade/archive/service/impl/ArchivesAutoServiceImpl.java
  11. 3 3
      blade-service/blade-business/src/main/java/org/springblade/business/controller/TaskController.java
  12. 1 1
      blade-service/blade-business/src/main/java/org/springblade/business/service/impl/InformationQueryServiceImpl.java
  13. 4 3
      blade-service/blade-manager/src/main/java/org/springblade/manager/controller/ArchiveTreeContractController.java
  14. 2 0
      blade-service/blade-manager/src/main/java/org/springblade/manager/service/IArchiveTreeContractService.java
  15. 81 1
      blade-service/blade-manager/src/main/java/org/springblade/manager/service/impl/ArchiveTreeContractServiceImpl.java
  16. 29 3
      blade-service/blade-manager/src/main/java/org/springblade/manager/service/impl/ContractInfoServiceImpl.java
  17. 69 4
      blade-service/blade-manager/src/main/java/org/springblade/manager/service/impl/WbsTreeContractServiceImpl.java

+ 1 - 1
blade-common/src/main/java/org/springblade/common/utils/CommonUtil.java

@@ -112,7 +112,7 @@ public class CommonUtil {
      */
     public static InputStream getOSSInputStream(String urlStr) throws Exception {
         //获取OSS文件流
-        urlStr = replaceOssUrl(urlStr);
+//        urlStr = replaceOssUrl(urlStr);
         URL imageUrl = new URL(urlStr);
         try {
             HttpURLConnection conn = (HttpURLConnection) imageUrl.openConnection();

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

@@ -75,6 +75,11 @@ public class ArchivesAutoVO extends ArchivesAuto {
 	@ApiModelProperty("输入框查询条件")
 	private String queryValue;
 
+	/**
+	 * 输入框查询条件集合
+	 */
+	private List<String> queryList;
+
 	/**
 	 * 节点查询条件
 	 */

+ 2 - 2
blade-service/blade-archive/src/main/java/org/springblade/archive/controller/ArchiveFileTaskController.java

@@ -311,8 +311,8 @@ public class ArchiveFileTaskController extends BladeController {
                     vo.setTaskReportUserName(nameMap.get(Long.parseLong(task.getReportUser())));
                     List<TaskParallel> taskParallelList = finalTaskParallelGroupMap.get(task.getProcessInstanceId());
                     if (taskParallelList != null && taskParallelList.size() > 0) {
-                        //如果是垂直签,判断是否是当前用户审批轮次,不是当前用户审批轮次就不显示该任务
-                        if (projectInfo != null && projectInfo.getApprovalType() == 1) {
+                        //如果是垂直签,且是待办页面,判断是否是当前用户审批轮次,不是当前用户审批轮次就不显示该任务
+                        if (projectInfo != null && projectInfo.getApprovalType() == 1 && dto.getSelectedType() == 1) {
                             boolean shouldDisplayTask = false; //标记是否显示当前任务
                             for (TaskParallel taskParallel : taskParallelList) {
                                 if (SecureUtil.getUserId().equals(Long.parseLong(taskParallel.getTaskUser()))) {

+ 17 - 1
blade-service/blade-archive/src/main/java/org/springblade/archive/controller/ArchivesAutoController.java

@@ -19,10 +19,12 @@ package org.springblade.archive.controller;
 import cn.hutool.core.text.split.SplitIter;
 import com.alibaba.fastjson.JSONArray;
 import com.alibaba.fastjson.JSONObject;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import io.swagger.annotations.*;
 import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
 import lombok.AllArgsConstructor;
 
+import javax.servlet.http.HttpServletResponse;
 import javax.validation.Valid;
 
 import lombok.SneakyThrows;
@@ -34,6 +36,7 @@ import org.springblade.archive.utils.CallBgrsjk;
 import org.springblade.archive.utils.FileUtils;
 import org.springblade.archive.vo.CheckoutVO;
 import org.springblade.business.entity.ArchiveFile;
+import org.springblade.business.entity.InformationQuery;
 import org.springblade.common.constant.CommonConstant;
 import org.springblade.common.utils.CommonUtil;
 import org.springblade.core.mp.support.Condition;
@@ -49,6 +52,7 @@ import org.springblade.manager.feign.ContractClient;
 import org.springblade.manager.feign.ProjectClient;
 import org.springblade.system.cache.ParamCache;
 import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.MediaType;
 import org.springframework.web.bind.annotation.*;
 import org.springframework.web.bind.annotation.RequestParam;
 import com.baomidou.mybatisplus.core.metadata.IPage;
@@ -59,6 +63,7 @@ import org.springblade.archive.service.IArchivesAutoService;
 import org.springblade.core.boot.ctrl.BladeController;
 import org.springframework.web.multipart.MultipartFile;
 
+import java.io.File;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.List;
@@ -512,7 +517,7 @@ public class ArchivesAutoController extends BladeController {
 	@ApiOperationSupport(order = 3)
 	@ApiOperation(value = "刷新项目档案", notes = "传入projectId,contractId")
 	public R<String> refreshProjectArchive(@RequestParam Long projectId, @RequestParam Long contractId,@RequestParam Long nodeId) {
-		archivesAutoService.refreshFileNumberNoSlipt(projectId,contractId,nodeId);
+		archivesAutoService.refreshFileNumberNoSlipt(projectId,contractId,null,false);
 		return R.data("刷新成功");
 	}
 
@@ -644,4 +649,15 @@ public class ArchivesAutoController extends BladeController {
 		List<CheckoutVO> list = archivesAutoService.getArchivesAutoViewByUnit(unitType,projectId);
 		return R.data(list);
 	}
+
+	/**
+	 * 批量下载档案
+	 */
+	@PostMapping(value = "/batchDownloadFileToZip", produces = {
+		MediaType.APPLICATION_OCTET_STREAM_VALUE, MediaType.APPLICATION_JSON_VALUE})
+	@ApiOperationSupport(order = 19)
+	@ApiOperation(value = "批量下载档案")
+	public void batchDownloadFileToZip(String ids, HttpServletResponse response) {
+		archivesAutoService.batchDownloadFileToZip(ids,response);
+	}
 }

+ 6 - 0
blade-service/blade-archive/src/main/java/org/springblade/archive/mapper/ArchivesAutoMapper.java

@@ -17,6 +17,7 @@
 package org.springblade.archive.mapper;
 
 import org.apache.ibatis.annotations.MapKey;
+import org.apache.ibatis.annotations.Mapper;
 import org.apache.ibatis.annotations.Param;
 import org.springblade.archive.dto.ArchivesAutoDTO;
 import org.springblade.archive.entity.ArchivesAuto;
@@ -24,6 +25,7 @@ import org.springblade.archive.vo.ArchivesAutoVO;
 import com.baomidou.mybatisplus.core.mapper.BaseMapper;
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import org.springblade.archive.vo.ArchivesAutoVO2;
+import org.springblade.business.entity.ArchiveFile;
 import org.springblade.manager.entity.ArchiveTreeContract;
 import org.springblade.system.entity.DictBiz;
 import org.springblade.system.user.entity.User;
@@ -157,4 +159,8 @@ public interface ArchivesAutoMapper extends BaseMapper<ArchivesAuto> {
     List<ArchiveTreeContract> getUnitNodeByProjectId(@Param("projectId") Long projectId);
 
 	List<ArchivesAutoVO2> getUnitAllArchive(@Param("node") String node);
+
+    List<ArchiveFile> batchSearchArchiveFile(@Param("ids") List<Long> longs);
+
+	List<ArchivesAuto> getArchives(@Param("ids") List<Long> longs);
 }

+ 29 - 0
blade-service/blade-archive/src/main/java/org/springblade/archive/mapper/ArchivesAutoMapper.xml

@@ -467,6 +467,13 @@
         <if test="vo.queryValue != null and vo.queryValue != ''">
             and (uaa.name like concat('%',#{vo.queryValue},'%') or uaa.file_number like concat('%',#{vo.queryValue},'%'))
         </if>
+        <if test="vo.searchType == 1 and vo.queryList != null and vo.queryList.size > 0">
+            and (
+            <foreach collection="vo.queryList" item="query" separator="or" >
+                uaa.name like concat('%',#{query},'%')
+            </foreach>
+            )
+        </if>
         <if test="vo.projectId != null and vo.projectId != ''">
             and matc.project_id = #{vo.projectId}
         </if>
@@ -523,6 +530,13 @@
         <if test="vo.searchType == 1 and vo.queryValue != null and vo.queryValue != ''">
             and uaa.name like concat('%',#{vo.queryValue},'%')
         </if>
+        <if test="vo.searchType == 1 and vo.queryList != null and vo.queryList.size > 0">
+            and (
+            <foreach collection="vo.queryList" item="query" separator="or" >
+                uaa.name like concat('%',#{query},'%')
+            </foreach>
+            )
+        </if>
         <if test="vo.searchType == 2 and vo.queryValue != null and vo.queryValue != ''">
             and uaf.file_name like concat('%',#{vo.queryValue},'%')
         </if>
@@ -942,6 +956,21 @@
         from (select * from m_archive_tree_contract WHERE is_deleted = 0 and ancestors like concat('%',#{node},'%')) atc
                  join u_archives_auto uaa on atc.id = uaa.node_id  and uaa.is_deleted = 0
     </select>
+    <select id="batchSearchArchiveFile" resultType="org.springblade.business.entity.ArchiveFile">
+        select id,file_name,pdf_file_url,archive_id,project_id FROM u_archive_file
+        WHERE is_element = 0 and is_deleted = 0 and archive_id in
+        <foreach collection="ids" item="id" open="(" close=")" separator=",">
+            #{id}
+        </foreach>
+    </select>
+    <select id="getArchives" resultType="org.springblade.archive.entity.ArchivesAuto">
+        select id,name
+        from u_archives_auto
+        where   id in
+        <foreach collection="ids" item="id" open="(" separator="," close=")">
+            #{id}
+        </foreach>
+    </select>
 
 
     <update id="splitFiles">

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

@@ -14,4 +14,7 @@ public interface IArchiveOfflineVersionInfoService extends BaseService<ArchiveOf
     public void metadataToSqlite(Long projectId) ;
 
     int getPackStatus();
+
+    void packageZip2(String zipUrl,String packUrl) throws Exception ;
+
 }

+ 4 - 1
blade-service/blade-archive/src/main/java/org/springblade/archive/service/IArchivesAutoService.java

@@ -28,6 +28,7 @@ import org.springblade.system.entity.DictBiz;
 import org.springblade.system.user.entity.User;
 import org.springframework.web.multipart.MultipartFile;
 
+import javax.servlet.http.HttpServletResponse;
 import java.io.IOException;
 import java.util.List;
 import java.util.Map;
@@ -79,7 +80,7 @@ public interface IArchivesAutoService extends BaseService<ArchivesAuto> {
 
 
 	//刷新某个项目的档号
-	void refreshFileNumberNoSlipt(Long projectId,Long contractId,Long nodeId);
+	void refreshFileNumberNoSlipt(Long projectId,Long contractId,Long nodeId,boolean bforce);
 
 	void test();
 
@@ -104,4 +105,6 @@ public interface IArchivesAutoService extends BaseService<ArchivesAuto> {
 	R searchInfo(MultipartFile file) throws IOException;
 
     List<CheckoutVO> getArchivesAutoViewByUnit(Integer unitType, Long projectId);
+
+    void batchDownloadFileToZip(String ids, HttpServletResponse response);
 }

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

@@ -109,7 +109,7 @@ public class ArchiveOfflineVersionInfoServiceImpl extends BaseServiceImpl<Archiv
      * @param
      * @throws Exception
      */
-    public static void packageZip2(String zipUrl,String packUrl) throws Exception {
+    public void packageZip2(String zipUrl,String packUrl) throws Exception {
         // 要被压缩的文件夹
         File folder = new File(zipUrl);
         if (!folder.exists() && !folder.isDirectory()) {

+ 190 - 59
blade-service/blade-archive/src/main/java/org/springblade/archive/service/impl/ArchivesAutoServiceImpl.java

@@ -32,6 +32,7 @@ import org.apache.commons.lang.StringUtils;
 import org.springblade.archive.entity.ArchiveProjectConfig;
 import org.springblade.archive.entity.ArchivesAuto;
 import org.springblade.archive.service.IArchiveAutoPdfService;
+import org.springblade.archive.service.IArchiveOfflineVersionInfoService;
 import org.springblade.archive.service.IArchiveProjectConfigService;
 import org.springblade.archive.utils.ArchiveTreeUtil;
 import org.springblade.archive.utils.FileTransJavaDemo;
@@ -82,9 +83,14 @@ import org.springframework.stereotype.Service;
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import org.springframework.web.multipart.MultipartFile;
 
+import javax.servlet.http.HttpServletResponse;
 import java.io.File;
 import java.io.FileInputStream;
 import java.io.IOException;
+import java.io.InputStream;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
 import java.time.LocalDateTime;
 import java.util.*;
 import java.util.concurrent.ExecutorService;
@@ -120,6 +126,8 @@ public class ArchivesAutoServiceImpl extends BaseServiceImpl<ArchivesAutoMapper,
 
 	private final MetadataClassificationClient metadataClassificationClient;
 
+	private final IArchiveOfflineVersionInfoService versionInfoService;
+
 
 	@Override
 	public IPage<ArchivesAutoVO> selectArchivesAutoPage(IPage<ArchivesAutoVO> page, ArchivesAutoVO archivesAuto) {
@@ -147,6 +155,19 @@ public class ArchivesAutoServiceImpl extends BaseServiceImpl<ArchivesAutoMapper,
 		if (StringUtils.isNotBlank(vo.getCarrierType())) {
 			vo.setCarrierTypes(Arrays.asList(vo.getCarrierType().split(",")));
 		}
+		//判断是否多字段查询
+		if (StringUtils.isNotBlank(vo.getQueryValue())){
+			String queryValue = vo.getQueryValue();
+			if (queryValue.contains(",") || queryValue.contains(",")){
+				if (queryValue.contains(",")){
+					vo.setQueryList(Func.toStrList(",",queryValue));
+				}else if (queryValue.contains(",")){
+					vo.setQueryList(Func.toStrList(",",queryValue));
+				}
+				vo.setQueryValue(null);
+			}
+		}
+		//新增
 		List<ArchivesAutoVO> archivesAutos = null;
 		//获取合同段类型
 		ContractInfo contractInfo = contractClient.getContractById(vo.getContractId());
@@ -1658,9 +1679,9 @@ public class ArchivesAutoServiceImpl extends BaseServiceImpl<ArchivesAutoMapper,
 	 * @param contractId
 	 * @param nodeId
 	 */
-	public void refreshFileNumberNoSlipt(Long projectId,Long contractId,Long nodeId) {
+	public void refreshFileNumberNoSlipt(Long projectId,Long contractId,Long nodeId,boolean bforce) {
 		List<ArchiveTreeContract> list = archiveTreeContractClient.getListByProjectId(projectId);
-		this.refreshFileNumberNoSlipt(list,contractId,nodeId);
+		this.refreshFileNumberNoSlipt(list,contractId,nodeId,bforce);
 	}
 
 	/**
@@ -1669,7 +1690,7 @@ public class ArchivesAutoServiceImpl extends BaseServiceImpl<ArchivesAutoMapper,
 	 * @param contractId
 	 * @param nodeId
 	 */
-	public void refreshFileNumberNoSlipt(List<ArchiveTreeContract> archiveTreeContracts,Long contractId,Long nodeId) {
+	public void refreshFileNumberNoSlipt(List<ArchiveTreeContract> archiveTreeContracts,Long contractId,Long nodeId,boolean bforce) {
 
 		List<ArchiveTreeContractVO2> subTreeList = new ArrayList<>();
 		List<List<ArchiveTreeContract>>  subGroupedList = new ArrayList<>();
@@ -1726,9 +1747,16 @@ public class ArchivesAutoServiceImpl extends BaseServiceImpl<ArchivesAutoMapper,
 				}
 
 				String fileNumber = fileNumberPrefix +"_"+ index;
-				if (archiveAutoPdfService.refreshFileNumberForce(archivesAuto,fileNumber)){
-					changeList.add(archivesAuto);
+				if (bforce) {
+					if (archiveAutoPdfService.refreshFileNumberForce(archivesAuto,fileNumber)){
+						changeList.add(archivesAuto);
+					}
+				}else {
+					if (archiveAutoPdfService.refreshFileNumber(archivesAuto,fileNumber)){
+						changeList.add(archivesAuto);
+					}
 				}
+
 				index++;
 			}
 		}
@@ -1767,71 +1795,75 @@ public class ArchivesAutoServiceImpl extends BaseServiceImpl<ArchivesAutoMapper,
 		String back = "";
 
 
-		if(frontUrls != null ) {
-			for (String frontUrl : frontUrls) {
-				if (frontUrl.contains(ArchiveAutoPdfServiceImpl.ARCHIVE_NUMBER[0]) && config.getFactorType().contains("1")) {
-					front = frontUrl;
-				} else if (frontUrl.contains(ArchiveAutoPdfServiceImpl.ARCHIVE_NUMBER[1]) && config.getFactorType().contains("2")) {
-					cataLog = frontUrl;
-				} else if (frontUrl.contains(ArchiveAutoPdfServiceImpl.ARCHIVE_NUMBER[2]) && config.getFactorType().contains("3")) {
-					spare = frontUrl;
-				} else if (frontUrl.contains(ArchiveAutoPdfServiceImpl.ARCHIVE_NUMBER[3]) && config.getFactorType().contains("4")) {
-					back = frontUrl;
+		try {
+			if(frontUrls != null ) {
+				for (String frontUrl : frontUrls) {
+					if (frontUrl.contains(ArchiveAutoPdfServiceImpl.ARCHIVE_NUMBER[0]) && config.getFactorType().contains("1")) {
+						front = frontUrl;
+					} else if (frontUrl.contains(ArchiveAutoPdfServiceImpl.ARCHIVE_NUMBER[1]) && config.getFactorType().contains("2")) {
+						cataLog = frontUrl;
+					} else if (frontUrl.contains(ArchiveAutoPdfServiceImpl.ARCHIVE_NUMBER[2]) && config.getFactorType().contains("3")) {
+						spare = frontUrl;
+					} else if (frontUrl.contains(ArchiveAutoPdfServiceImpl.ARCHIVE_NUMBER[3]) && config.getFactorType().contains("4")) {
+						back = frontUrl;
+					}
 				}
 			}
-		}
-		List<String> fileUrls =new ArrayList<>();
-		//if (!archivesAuto.isMedia())
-		if (true)
-		{
-			List<ArchiveFile> result = this.archiveFileClient.getArchiveFileByArchivesId(archivesAuto.getId().toString(),"");
-			if(result != null && result.size() > 0){
-				//循环访问result,如果pdfpageurl不为空则取出,否则取pdffileurl
-				for (ArchiveFile archiveFile : result) {
-					String pdfPageUrl = archiveFile.getPdfPageUrl();
-					if (StringUtils.isEmpty(pdfPageUrl)) {
-						pdfPageUrl = archiveFile.getPdfFileUrl();
-					}else{
+			List<String> fileUrls =new ArrayList<>();
+			//if (!archivesAuto.isMedia())
+			if (true)
+			{
+				List<ArchiveFile> result = this.archiveFileClient.getArchiveFileByArchivesId(archivesAuto.getId().toString(),"");
+				if(result != null && result.size() > 0){
+					//循环访问result,如果pdfpageurl不为空则取出,否则取pdffileurl
+					for (ArchiveFile archiveFile : result) {
+						String pdfPageUrl = archiveFile.getPdfPageUrl();
+						if (StringUtils.isEmpty(pdfPageUrl)) {
+							pdfPageUrl = archiveFile.getPdfFileUrl();
+						}else{
+							fileUrls.add(pdfPageUrl);
+						}
+						if (StringUtils.isEmpty(pdfPageUrl) || !pdfPageUrl.contains("pdf")) {
+							continue;
+						}
 						fileUrls.add(pdfPageUrl);
 					}
-					if (StringUtils.isEmpty(pdfPageUrl) || !pdfPageUrl.contains("pdf")) {
-						continue;
-					}
-					fileUrls.add(pdfPageUrl);
 				}
 			}
-		}
 
-		if (fileUrls.size() > 0){
-			//此处暂时这么处理,等oss上传接口里文件名可以区分后,再单独取
-//			if (frontUrls != null && frontUrls.length > 3){
-//
-//				urlList.add(frontUrls[0]);
-//				urlList.add(frontUrls[1]);
-//			}
-			if (StringUtils.isNotEmpty(front)) {
-				urlList.add(front);
-			}
+			if (fileUrls.size() > 0){
+				//此处暂时这么处理,等oss上传接口里文件名可以区分后,再单独取
+	//			if (frontUrls != null && frontUrls.length > 3){
+	//
+	//				urlList.add(frontUrls[0]);
+	//				urlList.add(frontUrls[1]);
+	//			}
+				if (StringUtils.isNotEmpty(front)) {
+					urlList.add(front);
+				}
 
-			if (StringUtils.isNotEmpty(cataLog)) {
-				urlList.add(cataLog);
-			}
+				if (StringUtils.isNotEmpty(cataLog)) {
+					urlList.add(cataLog);
+				}
 
-			urlList.addAll(fileUrls);
+				urlList.addAll(fileUrls);
 
-//			if (frontUrls != null && frontUrls.length > 3){
-//				urlList.add(frontUrls[2]);
-//				urlList.add(frontUrls[3]);
-//			}
-			if (StringUtils.isNotEmpty(spare)) {
-				urlList.add(spare);
-			}
+	//			if (frontUrls != null && frontUrls.length > 3){
+	//				urlList.add(frontUrls[2]);
+	//				urlList.add(frontUrls[3]);
+	//			}
+				if (StringUtils.isNotEmpty(spare)) {
+					urlList.add(spare);
+				}
 
-			if (StringUtils.isNotEmpty(back)) {
-				urlList.add(back);
+				if (StringUtils.isNotEmpty(back)) {
+					urlList.add(back);
+				}
+				String fileName = SnowFlakeUtil.getId().toString();
+				url = archiveAutoPdfService.MergePdfAndUpload(urlList,fileName,null,archivesAuto.getProjectId());
 			}
-			String fileName = SnowFlakeUtil.getId().toString();
-			url = archiveAutoPdfService.MergePdfAndUpload(urlList,fileName,null,archivesAuto.getProjectId());
+		} catch (Exception e) {
+			e.printStackTrace();
 		}
 		return  url;
 	}
@@ -2084,7 +2116,7 @@ public class ArchivesAutoServiceImpl extends BaseServiceImpl<ArchivesAutoMapper,
 
 				//刷新项目档号
 				log.info("[自动组卷]{}","开始刷新组卷档号。projectId:"+projectId+"-contractId:"+contractId+"-nodeId:"+nodeId);
-				refreshFileNumberNoSlipt(projectId,contractId,nodeId);
+				refreshFileNumberNoSlipt(projectId,contractId,nodeId,true);
 
 
 				//设置自动组卷结束
@@ -2322,4 +2354,103 @@ public class ArchivesAutoServiceImpl extends BaseServiceImpl<ArchivesAutoMapper,
 		}
 		return null;
 	}
+
+	@Override
+	public void batchDownloadFileToZip(String ids, HttpServletResponse response) {
+		List<Long> longs = Func.toLongList(ids);
+		//获取档案下的文件
+		List<ArchiveFile> result = baseMapper.batchSearchArchiveFile(longs);
+		//判断是否存在文件
+		if (result != null && result.size() > 0) {
+			//获取选择的案卷,只要id和文件提名字段
+			Map<Long, String> nameMap = baseMapper.getArchives(longs).stream().filter(l -> StringUtils.isNotBlank(l.getName())).collect(Collectors.toMap(l -> l.getId(), l -> l.getName()));
+			//默认下载地址
+			String defaultDir = "/www/wwwroot/Users/hongchuangyanfa/Desktop/archiveDownload";
+			//项目下地址
+			String projectDir = defaultDir+"/" + result.get(0).getProjectId();
+			File file = new File(projectDir);
+			//获取项目名称
+			ProjectInfo projectInfo = projectClient.getById(result.get(0).getProjectId());
+			//判断文件夹是否存在,存在则该项目正在下载打包,不存在则生成
+			if (file.exists()) {
+				throw new ServiceException("当前项目正在下载档案,请稍后再试");
+			} else {
+				file.mkdir();
+			}
+			//删除掉pdfUrl为空的数据
+			result.removeIf(query -> StringUtils.isEmpty(query.getPdfFileUrl()));
+			//按照档案id分组
+			Map<Long, List<ArchiveFile>> map = result.stream().collect(Collectors.groupingBy(ArchiveFile::getArchiveId));
+			try {
+				//为每个档案分别设置
+				for (Long archiveId : map.keySet()) {
+					String initName = nameMap.get(archiveId);
+					String[] split = initName.split(")");
+					String name = split[split.length-1];
+					String archiveDir = projectDir + "/" + name;
+					//创建档案文件夹
+					File file2 = new File(archiveDir);
+					file2.mkdir();
+					//组卷,下载PDF
+					String mergeArchivesFile = this.getMergeArchivesFile(archiveId);
+					InputStream file_out2 = CommonUtil.getOSSInputStream(mergeArchivesFile);
+					if (file_out2 != null) {
+						CommonUtil.inputStreamToFile(file_out2, new File(archiveDir+"/" + name+".pdf"));
+						file_out2.close();
+					}
+
+					//下载卷内文件
+					String archiveFileDir = archiveDir + "/" + "卷内文件";
+					File file3 = new File(archiveFileDir);
+					file3.mkdir();
+					List<ArchiveFile> files = map.get(archiveId);
+					for (ArchiveFile archiveFile : files) {
+						String fileUrl = archiveFile.getPdfFileUrl();
+						String initFileName = archiveFile.getFileName();
+						if (initFileName.length() > 100){
+							initFileName = initFileName.substring(0,100);
+						}
+						String fileName = "/" + initFileName+".pdf";
+						InputStream file_out = CommonUtil.getOSSInputStream(fileUrl);
+						if (file_out != null) {
+							CommonUtil.inputStreamToFile(file_out, new File(archiveFileDir + fileName));
+							file_out.close();
+						}
+					}
+				}
+				//下载完成,打包文件
+				this.packageZip2(defaultDir,projectDir,projectInfo.getId());
+				String zipFile = defaultDir + "/"+projectInfo.getId()+".zip";
+				Path path = Paths.get(zipFile);
+				response.setContentType("application/octet-stream");
+				response.setHeader("Content-Disposition", "attachment;filename="+projectInfo.getProjectName());
+				// 获取文件内容流并写入响应
+				Files.copy(path, response.getOutputStream());
+
+			}catch (Exception e){
+				throw new ServiceException(e.getMessage());
+			}
+		}
+	}
+
+	/**
+	 * 压缩指定路径下的文件夹-直接执行linux命令,多线程,速度快几十倍
+	 *
+	 * @param
+	 * @throws Exception
+	 */
+	public void packageZip2(String defaultDir,String projectDir,Long id) throws Exception {
+		// 要被压缩的文件夹
+		File folder = new File(defaultDir);
+		if (!folder.exists() && !folder.isDirectory()) {
+			folder.mkdirs();
+		}
+		// 执行脚本文件
+		// 多条命令执行
+		String[] cmds = {"/bin/sh", "-c", "cd "+defaultDir+" && zip -q -r "+projectDir+".zip "+id};
+		System.out.println("开始执行命令:" + Arrays.toString(cmds));
+		//主要在这步写入后调用命令
+		Process process = Runtime.getRuntime().exec(cmds);
+		process.waitFor();
+	}
 }

+ 3 - 3
blade-service/blade-business/src/main/java/org/springblade/business/controller/TaskController.java

@@ -1342,8 +1342,8 @@ public class TaskController extends BladeController {
                     vo.setProcessInstanceId(task.getProcessInstanceId());
                     List<TaskParallel> taskParallelList = finalTaskParallelGroupMap.get(task.getProcessInstanceId());
                     if (taskParallelList != null && taskParallelList.size() > 0) {
-                        //如果是垂直签,判断是否是当前用户审批轮次,不是当前用户审批轮次就不显示该任务
-                        if (projectInfo != null && projectInfo.getApprovalType() == 1) {
+                        //如果是垂直签,且是待办页面,判断是否是当前用户审批轮次,不是当前用户审批轮次就不显示该任务
+                        if (projectInfo != null && projectInfo.getApprovalType() == 1 && dto.getSelectedType() == 1) {
                             boolean shouldDisplayTask = false; //标记是否显示当前任务
                             for (TaskParallel taskParallel : taskParallelList) {
                                 if (SecureUtil.getUserId().equals(Long.parseLong(taskParallel.getTaskUser()))) {
@@ -1603,7 +1603,7 @@ public class TaskController extends BladeController {
     @ApiOperation(value = "任务管理-一键重签", notes = "传入taskIds、下拉框的contractId、projectId")
     public R<Object> reSigningEVisa(@RequestParam String taskIds, @RequestParam String contractId, @RequestParam String projectId, HttpServletRequest request) {
         String header = request.getHeader("Blade-Auth");
-        taskService.reSigningEVisa(taskIds,contractId,projectId,header );
+        taskService.reSigningEVisa(taskIds, contractId, projectId, header);
         return R.success("任务已经成功提交重签,请耐心等待!");
     }
 

+ 1 - 1
blade-service/blade-business/src/main/java/org/springblade/business/service/impl/InformationQueryServiceImpl.java

@@ -520,7 +520,7 @@ public class InformationQueryServiceImpl extends BaseServiceImpl<InformationQuer
                     vor.setStartTime(DateUtil.format(vor.getCreateTime(), "yyyy-MM-dd"));
                 }
                 //已废除归到未上报
-                vor.setTaskStatusStr(new Integer("0").equals(vor.getStatus()) ? "未上报" : new Integer("1").equals(vor.getStatus()) ? "待审批" : new Integer("2").equals(vor.getStatus()) ? "已审批" : "未上报");
+                vor.setTaskStatusStr(new Integer("0").equals(vor.getStatus()) ? "未上报" : new Integer("1").equals(vor.getStatus()) ? "待审批" : new Integer("2").equals(vor.getStatus()) ? "已审批" : "已废除");
                 try {
                     //填报人
                     String fileUserIdAndName = vor.getFileUserIdAndName();

+ 4 - 3
blade-service/blade-manager/src/main/java/org/springblade/manager/controller/ArchiveTreeContractController.java

@@ -201,8 +201,6 @@ public class ArchiveTreeContractController extends BladeController {
 
         archiveTreeContractService.updateAllSonNodeIdsForArchiveAutoRule(ar);
 
-
-
         return R.status(b);
     }
 
@@ -357,7 +355,7 @@ public class ArchiveTreeContractController extends BladeController {
     }
 
     /**
-     * 初始化归档树根节点
+     * 同步客户级
      */
     @PostMapping("/syncProjectTree")
     @ApiOperationSupport(order = 14)
@@ -374,6 +372,9 @@ public class ArchiveTreeContractController extends BladeController {
         boolean b = archiveTreeContractService.syncProjectTree(archiveTree);
 
         //TODO 待节点都同步完了以后,再去设置wbs节点的组卷规则。(方式:客户级wbs节点-》项目级wbs节点-》wbs项目级组卷规则-》设置规则到客户级wbs节点以及子节点)
+        if (b) {
+            archiveTreeContractService.updateWbsRuleNodes(archiveTree.getProjectId());
+        }
 
         if (b) {
             return R.success("同步成功");

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

@@ -124,4 +124,6 @@ public interface IArchiveTreeContractService extends BaseService<ArchiveTreeCont
 
     ArchiveTreeContract getMeasurementPeriodNode(String projectName,String contractName,
                                                  String periodName);
+
+    public void updateWbsRuleNodes(Long projectId);
 }

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

@@ -31,6 +31,7 @@ import org.springblade.core.tool.utils.Func;
 import org.springblade.manager.dto.ArchiveTreeContractDTO;
 import org.springblade.manager.entity.*;
 import org.springblade.manager.feign.WbsTreeContractClient;
+import org.springblade.manager.mapper.ArchiveAutoRuleWbsMapper;
 import org.springblade.manager.mapper.ArchiveTreeMapper;
 import org.springblade.manager.service.*;
 import org.springblade.manager.utils.DiffListUtil;
@@ -75,6 +76,8 @@ public class ArchiveTreeContractServiceImpl extends BaseServiceImpl<ArchiveTreeC
 
 	private final IWbsTreeContractService wbsTreeContractService;
 
+	private final ArchiveAutoRuleWbsMapper archiveAutoRuleWbsMapper;
+
 
 
 
@@ -1214,7 +1217,7 @@ public class ArchiveTreeContractServiceImpl extends BaseServiceImpl<ArchiveTreeC
 	}
 
 	/**
-	 *
+	 *  刷新自动组卷规则
 	 * @param archiveAutoType
 	 * @param ar
 	 * @return
@@ -1252,5 +1255,82 @@ public class ArchiveTreeContractServiceImpl extends BaseServiceImpl<ArchiveTreeC
 		}
 	}
 
+	/**
+	 * 根据项目级配置的wbs组卷节点,配置客户级节点
+	 * @param autoRuleWbs
+	 * @param treeContracts
+	 * @return
+	 */
+	private  List<ArchiveTreeContract> getSelectRuleNodes(List<ArchiveAutoRuleWbs> autoRuleWbs,List<ArchiveTreeContract> treeContracts){
+		List<ArchiveTreeContract> selectRuleNodes = new ArrayList<>();
+		Map<Long,ArchiveAutoRuleWbs> autoRuleWbsMap = new HashMap<>();
+		for (ArchiveAutoRuleWbs ruleWbs:autoRuleWbs) {
+			autoRuleWbsMap.put(ruleWbs.getWbsId(),ruleWbs);
+		}
+
+		//根据fro
+		for (ArchiveTreeContract treeContract :treeContracts) {
+
+			ArchiveAutoRuleWbs ruleWbs = autoRuleWbsMap.get(treeContract.getExtId());
+			if (ruleWbs!= null ) {
+				treeContract.setArchiveAutoType(ruleWbs.getArchiveAutoType());
+				selectRuleNodes.add(treeContract);
+				continue;
+			}
+			if (treeContract.getFromId()!= null
+					&& !(treeContract.getFromId().equals(treeContract.getExtId()))) {
+
+				ruleWbs = autoRuleWbsMap.get(treeContract.getFromId());
+				if (ruleWbs!= null ) {
+					treeContract.setArchiveAutoType(ruleWbs.getArchiveAutoType());
+					selectRuleNodes.add(treeContract);
+					continue;
+				}
+			}
+		}
+
+		return selectRuleNodes;
+	}
+
+	/**
+	 * 更新wbs节点规则
+	 * @param projectId
+	 */
+	public void updateWbsRuleNodes(Long projectId){
+
+		//获取projectId ,获取wbs树的配置的规则
+		List<ArchiveAutoRuleWbs> autoRuleWbs =    archiveAutoRuleWbsMapper.selectList(Wrappers.<ArchiveAutoRuleWbs>lambdaQuery()
+				.eq(ArchiveAutoRuleWbs::getIsDeleted, 0)
+				.eq(ArchiveAutoRuleWbs::getProjectId, projectId));
+		if (autoRuleWbs.size() == 0) {
+			return;
+		}
+
+		//先清空原有规则
+		int updatedRows = archiveTreeContractMapper.update(
+				null,
+				Wrappers.<ArchiveTreeContract>lambdaUpdate()
+						.set(ArchiveTreeContract::getArchiveAutoType, null)
+						.eq(ArchiveTreeContract::getIsDeleted, 0)
+						.eq(ArchiveTreeContract::getProjectId, projectId)
+						.eq(ArchiveTreeContract::getExtType, 1)
+		);
+
+		//获取所有的wbs节点
+		List<ArchiveTreeContract> treeContracts = archiveTreeContractMapper.selectList(
+				Wrappers.<ArchiveTreeContract>lambdaQuery()
+						.eq(ArchiveTreeContract::getIsDeleted, 0)
+						.eq(ArchiveTreeContract::getProjectId, projectId)
+						.eq(ArchiveTreeContract::getExtType, 1)
+		);
+
+		//获取匹配的客户端wbs节点
+		List<ArchiveTreeContract> selectNodes = getSelectRuleNodes(autoRuleWbs,treeContracts);
+
+		if (selectNodes.size() > 0) {
+			updateArchiveContractAutoRule(selectNodes);
+		}
+	}
+
 
 }

+ 29 - 3
blade-service/blade-manager/src/main/java/org/springblade/manager/service/impl/ContractInfoServiceImpl.java

@@ -353,8 +353,21 @@ public class ContractInfoServiceImpl extends BaseServiceImpl<ContractInfoMapper,
                         if (data != null) {
                             nodesAllTemp = JSON.parseArray(data.toString(), WbsTreeContractLazyVO.class);
                         } else {
-                            nodesAllTemp = jdbcTemplate.query("select a.p_key_id,a.id,a.parent_id,(SELECT CASE WHEN count(1) > 0 THEN 1 ELSE 0 END FROM m_wbs_tree_contract b WHERE b.parent_id = a.id AND type = 1 AND b.contract_id = " + contractId + " AND b.is_deleted = 0 ) AS hasChildren from m_wbs_tree_contract a where type = 1 and status = 1 and is_deleted = 0 and contract_id = " + contractId, new BeanPropertyRowMapper<>(WbsTreeContractLazyVO.class));
+                            nodesAllTemp = jdbcTemplate.query("select a.p_key_id,a.id,a.parent_id from m_wbs_tree_contract a where a.type = 1 and a.status = 1 and a.is_deleted = 0 and a.contract_id = " + contractId, new BeanPropertyRowMapper<>(WbsTreeContractLazyVO.class));
                             if (nodesAllTemp.size() > 0) {
+                                //判断是否有子级,赋值
+                                Map<Long, List<WbsTreeContractLazyVO>> groupedByParentId = nodesAllTemp.stream().collect(Collectors.groupingBy(WbsTreeContractLazyVO::getParentId));
+                                for (WbsTreeContractLazyVO vo : nodesAllTemp) {
+                                    if (vo.getParentId() == 0) {
+                                        vo.setHasChildren(1);
+                                    }
+                                    List<WbsTreeContractLazyVO> childNodes = groupedByParentId.getOrDefault(vo.getId(), null);
+                                    if (childNodes != null && childNodes.size() > 0) {
+                                        vo.setHasChildren(1);
+                                    } else {
+                                        vo.setHasChildren(0);
+                                    }
+                                }
                                 JSONArray array = JSONArray.parseArray(JSON.toJSONString(nodesAllTemp));
                                 redisTemplate.opsForValue().set("blade-manager::contract:wbstree:" + contractId, JSON.toJSON(array).toString());
                             }
@@ -490,10 +503,23 @@ public class ContractInfoServiceImpl extends BaseServiceImpl<ContractInfoMapper,
                             if (data != null) {
                                 nodesAllTemp = JSON.parseArray(data.toString(), WbsTreeContractLazyVO.class);
                             } else {
-                                nodesAllTemp = jdbcTemplate.query("select a.p_key_id,a.id,a.parent_id,(SELECT CASE WHEN count(1) > 0 THEN 1 ELSE 0 END FROM m_wbs_tree_contract b WHERE b.parent_id = a.id AND type = 1 AND b.contract_id = " + contractRelationJlyz.getContractIdSg() + " AND b.is_deleted = 0 ) AS hasChildren from m_wbs_tree_contract a where type = 1 and status = 1 and is_deleted = 0 and contract_id = " + contractRelationJlyz.getContractIdSg(), new BeanPropertyRowMapper<>(WbsTreeContractLazyVO.class));
+                                nodesAllTemp = jdbcTemplate.query("select a.p_key_id,a.id,a.parent_id from m_wbs_tree_contract a where a.type = 1 and a.status = 1 and a.is_deleted = 0 and a.contract_id = " + contractRelationJlyz.getContractIdSg(), new BeanPropertyRowMapper<>(WbsTreeContractLazyVO.class));
                                 if (nodesAllTemp.size() > 0) {
+                                    //判断是否有子级,赋值
+                                    Map<Long, List<WbsTreeContractLazyVO>> groupedByParentId = nodesAllTemp.stream().collect(Collectors.groupingBy(WbsTreeContractLazyVO::getParentId));
+                                    for (WbsTreeContractLazyVO vo : nodesAllTemp) {
+                                        if (vo.getParentId() == 0) {
+                                            vo.setHasChildren(1);
+                                        }
+                                        List<WbsTreeContractLazyVO> childNodes = groupedByParentId.getOrDefault(vo.getId(), null);
+                                        if (childNodes != null && childNodes.size() > 0) {
+                                            vo.setHasChildren(1);
+                                        } else {
+                                            vo.setHasChildren(0);
+                                        }
+                                    }
                                     JSONArray array = JSONArray.parseArray(JSON.toJSONString(nodesAllTemp));
-                                    redisTemplate.opsForValue().set("blade-manager::contract:wbstree:" + contractId, JSON.toJSON(array).toString());
+                                    redisTemplate.opsForValue().set("blade-manager::contract:wbstree:" + contractRelationJlyz.getContractIdSg(), JSON.toJSON(array).toString());
                                 }
                             }
 

+ 69 - 4
blade-service/blade-manager/src/main/java/org/springblade/manager/service/impl/WbsTreeContractServiceImpl.java

@@ -690,8 +690,21 @@ public class WbsTreeContractServiceImpl extends BaseServiceImpl<WbsTreeContractM
                     if (data != null) {
                         nodesAll = JSON.parseArray(data.toString(), WbsTreeContractLazyVO.class);
                     } else {
-                        nodesAll = jdbcTemplate.query("select a.p_key_id,a.id,a.parent_id,(SELECT CASE WHEN count(1) > 0 THEN 1 ELSE 0 END FROM m_wbs_tree_contract b WHERE b.parent_id = a.id AND type = 1 AND b.contract_id = " + contractId + " AND b.is_deleted = 0 ) AS hasChildren from m_wbs_tree_contract a where type = 1 and status = 1 and is_deleted = 0 and contract_id = " + contractId, new BeanPropertyRowMapper<>(WbsTreeContractLazyVO.class));
+                        nodesAll = jdbcTemplate.query("select a.p_key_id,a.id,a.parent_id from m_wbs_tree_contract a where a.type = 1 and a.status = 1 and a.is_deleted = 0 and a.contract_id = " + contractId, new BeanPropertyRowMapper<>(WbsTreeContractLazyVO.class));
                         if (nodesAll.size() > 0) {
+                            //判断是否有子级,赋值
+                            Map<Long, List<WbsTreeContractLazyVO>> groupedByParentId = nodesAll.stream().collect(Collectors.groupingBy(WbsTreeContractLazyVO::getParentId));
+                            for (WbsTreeContractLazyVO vo : nodesAll) {
+                                if (vo.getParentId() == 0) {
+                                    vo.setHasChildren(1);
+                                }
+                                List<WbsTreeContractLazyVO> childNodes = groupedByParentId.getOrDefault(vo.getId(), null);
+                                if (childNodes != null && childNodes.size() > 0) {
+                                    vo.setHasChildren(1);
+                                } else {
+                                    vo.setHasChildren(0);
+                                }
+                            }
                             JSONArray array = JSONArray.parseArray(JSON.toJSONString(nodesAll));
                             redisTemplate.opsForValue().set("blade-manager::contract:wbstree:" + contractId, JSON.toJSON(array).toString());
                         }
@@ -817,7 +830,7 @@ public class WbsTreeContractServiceImpl extends BaseServiceImpl<WbsTreeContractM
                     for (String sgContractId : contractIds) {
                         ContractInfo sgContractInfo = jdbcTemplate.query("select contract_name from m_contract_info where id = " + sgContractId, new BeanPropertyRowMapper<>(ContractInfo.class)).stream().findAny().orElse(null);
                         if (sgContractInfo != null) {
-                            //获取当前合同段所有缓存节点信息
+                            /*//获取当前合同段所有缓存节点信息
                             List<WbsTreeContractLazyVO> nodesAll;
                             Object data = redisTemplate.opsForValue().get("blade-manager::contract:wbstree:" + sgContractId);
                             if (data != null) {
@@ -828,6 +841,32 @@ public class WbsTreeContractServiceImpl extends BaseServiceImpl<WbsTreeContractM
                                     JSONArray array = JSONArray.parseArray(JSON.toJSONString(nodesAll));
                                     redisTemplate.opsForValue().set("blade-manager::contract:wbstree:" + sgContractId, JSON.toJSON(array).toString());
                                 }
+                            }*/
+
+                            //获取当前合同段所有缓存节点信息
+                            List<WbsTreeContractLazyVO> nodesAll;
+                            Object data = redisTemplate.opsForValue().get("blade-manager::contract:wbstree:" + sgContractId);
+                            if (data != null) {
+                                nodesAll = JSON.parseArray(data.toString(), WbsTreeContractLazyVO.class);
+                            } else {
+                                nodesAll = jdbcTemplate.query("select a.p_key_id,a.id,a.parent_id from m_wbs_tree_contract a where a.type = 1 and a.status = 1 and a.is_deleted = 0 and a.contract_id = " + sgContractId, new BeanPropertyRowMapper<>(WbsTreeContractLazyVO.class));
+                                if (nodesAll.size() > 0) {
+                                    //判断是否有子级,赋值
+                                    Map<Long, List<WbsTreeContractLazyVO>> groupedByParentId = nodesAll.stream().collect(Collectors.groupingBy(WbsTreeContractLazyVO::getParentId));
+                                    for (WbsTreeContractLazyVO vo : nodesAll) {
+                                        if (vo.getParentId() == 0) {
+                                            vo.setHasChildren(1);
+                                        }
+                                        List<WbsTreeContractLazyVO> childNodes = groupedByParentId.getOrDefault(vo.getId(), null);
+                                        if (childNodes != null && childNodes.size() > 0) {
+                                            vo.setHasChildren(1);
+                                        } else {
+                                            vo.setHasChildren(0);
+                                        }
+                                    }
+                                    JSONArray array = JSONArray.parseArray(JSON.toJSONString(nodesAll));
+                                    redisTemplate.opsForValue().set("blade-manager::contract:wbstree:" + sgContractId, JSON.toJSON(array).toString());
+                                }
                             }
 
                             //获取当前层懒加载节点
@@ -956,8 +995,21 @@ public class WbsTreeContractServiceImpl extends BaseServiceImpl<WbsTreeContractM
                     if (data != null) {
                         nodesAll = JSON.parseArray(data.toString(), WbsTreeContractLazyVO.class);
                     } else {
-                        nodesAll = jdbcTemplate.query("select a.p_key_id,a.id,a.parent_id,(SELECT CASE WHEN count(1) > 0 THEN 1 ELSE 0 END FROM m_wbs_tree_contract b WHERE b.parent_id = a.id AND type = 1 AND b.contract_id = " + contractId + " AND b.is_deleted = 0 ) AS hasChildren from m_wbs_tree_contract a where type = 1 and status = 1 and is_deleted = 0 and contract_id = " + contractId, new BeanPropertyRowMapper<>(WbsTreeContractLazyVO.class));
+                        nodesAll = jdbcTemplate.query("select a.p_key_id,a.id,a.parent_id from m_wbs_tree_contract a where a.type = 1 and a.status = 1 and a.is_deleted = 0 and a.contract_id = " + contractId, new BeanPropertyRowMapper<>(WbsTreeContractLazyVO.class));
                         if (nodesAll.size() > 0) {
+                            //判断是否有子级,赋值
+                            Map<Long, List<WbsTreeContractLazyVO>> groupedByParentId = nodesAll.stream().collect(Collectors.groupingBy(WbsTreeContractLazyVO::getParentId));
+                            for (WbsTreeContractLazyVO vo : nodesAll) {
+                                if (vo.getParentId() == 0) {
+                                    vo.setHasChildren(1);
+                                }
+                                List<WbsTreeContractLazyVO> childNodes = groupedByParentId.getOrDefault(vo.getId(), null);
+                                if (childNodes != null && childNodes.size() > 0) {
+                                    vo.setHasChildren(1);
+                                } else {
+                                    vo.setHasChildren(0);
+                                }
+                            }
                             JSONArray array = JSONArray.parseArray(JSON.toJSONString(nodesAll));
                             redisTemplate.opsForValue().set("blade-manager::contract:wbstree:" + contractId, JSON.toJSON(array).toString());
                         }
@@ -1058,8 +1110,21 @@ public class WbsTreeContractServiceImpl extends BaseServiceImpl<WbsTreeContractM
                             if (data != null) {
                                 nodesAll = JSON.parseArray(data.toString(), WbsTreeContractLazyVO.class);
                             } else {
-                                nodesAll = jdbcTemplate.query("select a.p_key_id,a.id,a.parent_id,(SELECT CASE WHEN count(1) > 0 THEN 1 ELSE 0 END FROM m_wbs_tree_contract b WHERE b.parent_id = a.id AND type = 1 AND b.contract_id = " + sgContractId + " AND b.is_deleted = 0 ) AS hasChildren from m_wbs_tree_contract a where type = 1 and status = 1 and is_deleted = 0 and contract_id = " + sgContractId, new BeanPropertyRowMapper<>(WbsTreeContractLazyVO.class));
+                                nodesAll = jdbcTemplate.query("select a.p_key_id,a.id,a.parent_id from m_wbs_tree_contract a where a.type = 1 and a.status = 1 and a.is_deleted = 0 and a.contract_id = " + sgContractId, new BeanPropertyRowMapper<>(WbsTreeContractLazyVO.class));
                                 if (nodesAll.size() > 0) {
+                                    //判断是否有子级,赋值
+                                    Map<Long, List<WbsTreeContractLazyVO>> groupedByParentId = nodesAll.stream().collect(Collectors.groupingBy(WbsTreeContractLazyVO::getParentId));
+                                    for (WbsTreeContractLazyVO vo : nodesAll) {
+                                        if (vo.getParentId() == 0) {
+                                            vo.setHasChildren(1);
+                                        }
+                                        List<WbsTreeContractLazyVO> childNodes = groupedByParentId.getOrDefault(vo.getId(), null);
+                                        if (childNodes != null && childNodes.size() > 0) {
+                                            vo.setHasChildren(1);
+                                        } else {
+                                            vo.setHasChildren(0);
+                                        }
+                                    }
                                     JSONArray array = JSONArray.parseArray(JSON.toJSONString(nodesAll));
                                     redisTemplate.opsForValue().set("blade-manager::contract:wbstree:" + sgContractId, JSON.toJSON(array).toString());
                                 }