Sfoglia il codice sorgente

合同段划分树新增节点

huangjn 3 anni fa
parent
commit
c2de7c3630
22 ha cambiato i file con 614 aggiunte e 57 eliminazioni
  1. 12 0
      blade-common/src/main/java/org/springblade/common/utils/CommonUtil.java
  2. 44 8
      blade-ops/blade-resource/src/main/java/org/springblade/resource/feign/CommonFileClientImpl.java
  3. 34 0
      blade-service-api/blade-business-api/src/main/java/org/springblade/business/dto/RecycleBinDTO.java
  4. 79 0
      blade-service-api/blade-business-api/src/main/java/org/springblade/business/entity/RecycleBin.java
  5. 18 0
      blade-service-api/blade-business-api/src/main/java/org/springblade/business/vo/RecycleBinVO.java
  6. 29 0
      blade-service-api/blade-business-api/src/main/java/org/springblade/business/vo/SaveNodeVO.java
  7. 2 2
      blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/entity/WbsTreeContract.java
  8. 3 0
      blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/feign/WbsTreeContractClient.java
  9. 9 1
      blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/feign/WbsTreePrivateClient.java
  10. 10 0
      blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/vo/TreeNodeVO.java
  11. 3 0
      blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/vo/WbsTreeContractTreeVOS.java
  12. 28 10
      blade-service/blade-business/src/main/java/org/springblade/business/controller/ImageClassificationFileController.java
  13. 136 25
      blade-service/blade-business/src/main/java/org/springblade/business/controller/InformationWriteQueryController.java
  14. 52 0
      blade-service/blade-business/src/main/java/org/springblade/business/controller/RecycleBinController.java
  15. 1 1
      blade-service/blade-business/src/main/java/org/springblade/business/controller/TaskController.java
  16. 42 0
      blade-service/blade-business/src/main/java/org/springblade/business/mapper/RecycleBinMapper.java
  17. 30 0
      blade-service/blade-business/src/main/java/org/springblade/business/mapper/RecycleBinMapper.xml
  18. 41 0
      blade-service/blade-business/src/main/java/org/springblade/business/service/impl/RecycleBinServiceImpl.java
  19. 8 3
      blade-service/blade-manager/src/main/java/org/springblade/manager/feign/WbsTreeContractClientImpl.java
  20. 29 6
      blade-service/blade-manager/src/main/java/org/springblade/manager/feign/WbsTreePrivateClientImpl.java
  21. 3 1
      blade-service/blade-manager/src/main/java/org/springblade/manager/mapper/ContractInfoMapper.xml
  22. 1 0
      blade-service/blade-manager/src/main/java/org/springblade/manager/mapper/WbsTreeContractMapper.xml

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

@@ -1,7 +1,9 @@
 package org.springblade.common.utils;
 
+import cn.hutool.core.io.FileUtil;
 import org.apache.commons.lang.StringUtils;
 
+import java.io.File;
 import java.io.InputStream;
 import java.math.BigDecimal;
 import java.net.HttpURLConnection;
@@ -21,6 +23,16 @@ import java.util.stream.Collectors;
  */
 public class CommonUtil {
 
+    public static void removeFile(List<String> removeList){
+        for(String fileUrl : removeList){
+            try{
+                FileUtil.del(new File(fileUrl));
+            }catch (Exception e){
+                e.printStackTrace();
+            }
+        }
+    }
+
     public static String handleNull(Object obj) {
         if (null == obj) {
             return "";

+ 44 - 8
blade-ops/blade-resource/src/main/java/org/springblade/resource/feign/CommonFileClientImpl.java

@@ -10,6 +10,7 @@ import org.apache.poi.ss.usermodel.Sheet;
 import org.apache.poi.ss.usermodel.WorkbookFactory;
 import org.springblade.core.oss.model.BladeFile;
 import org.springblade.core.tenant.annotation.NonDS;
+import org.springblade.core.tool.utils.IoUtil;
 import org.springblade.resource.builder.oss.OssBuilder;
 import org.springblade.resource.vo.NewBladeFile;
 import org.springframework.web.bind.annotation.RestController;
@@ -34,6 +35,7 @@ public class CommonFileClientImpl implements CommonFileClient {
     @Override
     public NewBladeFile pngOrJpgToPdf(MultipartFile file){
         String pdfFileUrl = "";
+        InputStream pdfInput = null;
         try{
             com.itextpdf.text.Document document = new com.itextpdf.text.Document();
             document.setMargins(0,0,0,0);
@@ -51,7 +53,7 @@ public class CommonFileClientImpl implements CommonFileClient {
             document.close();
 
             //上传文件
-            InputStream pdfInput = new ByteArrayInputStream(bos.toByteArray());
+            pdfInput = new ByteArrayInputStream(bos.toByteArray());
             String originalFilename = Objects.requireNonNull(file.getOriginalFilename()).replaceAll(".png", ".pdf").replaceAll(".jpg", ".pdf");
 
             BladeFile bladeFile = this.ossBuilder.template().putFile(originalFilename,pdfInput);
@@ -59,6 +61,10 @@ public class CommonFileClientImpl implements CommonFileClient {
 
         }catch (Exception e){
             e.printStackTrace();
+        } finally {
+            if(pdfInput != null){
+                IoUtil.closeQuietly(pdfInput);
+            }
         }
 
         NewBladeFile newBladeFile = new NewBladeFile();
@@ -88,6 +94,8 @@ public class CommonFileClientImpl implements CommonFileClient {
     public NewBladeFile wordToPdf(MultipartFile file){
         String pdfFileUrl = "";
         int page = 0;
+        InputStream pdfInput = null;
+        ByteArrayOutputStream bos = null;
         try{
             com.aspose.words.Document document = new com.aspose.words.Document(file.getInputStream());
 
@@ -96,11 +104,11 @@ public class CommonFileClientImpl implements CommonFileClient {
 
             font.setName("宋体");
 
-            ByteArrayOutputStream bos = new ByteArrayOutputStream();
+            bos = new ByteArrayOutputStream();
             document.save(bos,com.aspose.words.SaveFormat.PDF);
 
             //上传文件
-            InputStream pdfInput = new ByteArrayInputStream(bos.toByteArray());
+            pdfInput = new ByteArrayInputStream(bos.toByteArray());
             String originalFilename = Objects.requireNonNull(file.getOriginalFilename()).replaceAll(".docx", ".pdf");
 
             BladeFile bladeFile = this.ossBuilder.template().putFile(originalFilename,pdfInput);
@@ -111,6 +119,13 @@ public class CommonFileClientImpl implements CommonFileClient {
 
         }catch (Exception e){
             e.printStackTrace();
+        } finally {
+            if(bos != null){
+                IoUtil.closeQuietly(bos);
+            }
+            if(pdfInput != null){
+                IoUtil.closeQuietly(pdfInput);
+            }
         }
         NewBladeFile newBladeFile = new NewBladeFile();
         newBladeFile.setPdfUrl(pdfFileUrl);
@@ -125,8 +140,12 @@ public class CommonFileClientImpl implements CommonFileClient {
     public NewBladeFile excelToPdf(MultipartFile file){
         String pdfFileUrl = "";
         int page = 0;
+        org.apache.poi.ss.usermodel.Workbook ss = null;
+        ByteArrayInputStream byteArrayInputStream = null;
+        InputStream pdfInput = null;
+        ByteArrayOutputStream outReport = null, bos = null;
         try{
-            org.apache.poi.ss.usermodel.Workbook ss = WorkbookFactory.create(file.getInputStream());
+            ss = WorkbookFactory.create(file.getInputStream());
 
             for(int i = 0, l = ss.getNumberOfSheets(); i < l; i ++){
                 Sheet sheet = ss.getSheetAt(i);
@@ -136,15 +155,16 @@ public class CommonFileClientImpl implements CommonFileClient {
                 sheet.setFitToPage(true);
             }
 
-            ByteArrayOutputStream outReport = new ByteArrayOutputStream();
+            outReport = new ByteArrayOutputStream();
             ss.write(outReport);
-            com.aspose.cells.Workbook wb = new com.aspose.cells.Workbook(new ByteArrayInputStream(outReport.toByteArray()));
+            byteArrayInputStream = new ByteArrayInputStream(outReport.toByteArray());
+            com.aspose.cells.Workbook wb = new com.aspose.cells.Workbook(byteArrayInputStream);
 
-            ByteArrayOutputStream bos = new ByteArrayOutputStream();
+            bos = new ByteArrayOutputStream();
             wb.save(bos, SaveFormat.PDF);
             bos.flush();
             //上传文件
-            InputStream pdfInput = new ByteArrayInputStream(bos.toByteArray());
+            pdfInput = new ByteArrayInputStream(bos.toByteArray());
 
             String originalFilename;
             if(Objects.requireNonNull(file.getOriginalFilename()).contains("xlsx")){
@@ -162,6 +182,22 @@ public class CommonFileClientImpl implements CommonFileClient {
             bos.close();
         }catch (Exception e){
             e.printStackTrace();
+        } finally {
+            if(bos != null){
+                IoUtil.closeQuietly(bos);
+            }
+            if(outReport != null){
+                IoUtil.closeQuietly(outReport);
+            }
+            if(pdfInput != null){
+                IoUtil.closeQuietly(pdfInput);
+            }
+            if(byteArrayInputStream != null){
+                IoUtil.closeQuietly(byteArrayInputStream);
+            }
+            if(ss != null){
+                IoUtil.closeQuietly(ss);
+            }
         }
         NewBladeFile newBladeFile = new NewBladeFile();
         newBladeFile.setPdfUrl(pdfFileUrl);

+ 34 - 0
blade-service-api/blade-business-api/src/main/java/org/springblade/business/dto/RecycleBinDTO.java

@@ -0,0 +1,34 @@
+/*
+ *      Copyright (c) 2018-2028, Chill Zhuang All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are met:
+ *
+ *  Redistributions of source code must retain the above copyright notice,
+ *  this list of conditions and the following disclaimer.
+ *  Redistributions in binary form must reproduce the above copyright
+ *  notice, this list of conditions and the following disclaimer in the
+ *  documentation and/or other materials provided with the distribution.
+ *  Neither the name of the dreamlu.net developer nor the names of its
+ *  contributors may be used to endorse or promote products derived from
+ *  this software without specific prior written permission.
+ *  Author: Chill 庄骞 (smallchill@163.com)
+ */
+package org.springblade.business.dto;
+
+import org.springblade.business.entity.RecycleBin;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+/**
+ * 数据传输对象实体类
+ *
+ * @author BladeX
+ * @since 2022-07-19
+ */
+@Data
+@EqualsAndHashCode(callSuper = true)
+public class RecycleBinDTO extends RecycleBin {
+	private static final long serialVersionUID = 1L;
+
+}

+ 79 - 0
blade-service-api/blade-business-api/src/main/java/org/springblade/business/entity/RecycleBin.java

@@ -0,0 +1,79 @@
+/*
+ *      Copyright (c) 2018-2028, Chill Zhuang All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are met:
+ *
+ *  Redistributions of source code must retain the above copyright notice,
+ *  this list of conditions and the following disclaimer.
+ *  Redistributions in binary form must reproduce the above copyright
+ *  notice, this list of conditions and the following disclaimer in the
+ *  documentation and/or other materials provided with the distribution.
+ *  Neither the name of the dreamlu.net developer nor the names of its
+ *  contributors may be used to endorse or promote products derived from
+ *  this software without specific prior written permission.
+ *  Author: Chill 庄骞 (smallchill@163.com)
+ */
+package org.springblade.business.entity;
+
+import com.baomidou.mybatisplus.annotation.TableName;
+
+import io.swagger.annotations.ApiModelProperty;
+import org.springblade.core.mp.base.BaseEntity;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+/**
+ * 实体类
+ *
+ * @author BladeX
+ * @since 2022-07-19
+ */
+@Data
+@TableName("u_recycle_bin")
+@EqualsAndHashCode(callSuper = true)
+public class RecycleBin extends BaseEntity {
+
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 项目ID
+     */
+    @ApiModelProperty("项目ID")
+    private Long projectId;
+    /**
+     * 合同段ID
+     */
+    @ApiModelProperty("合同段ID")
+    private Long contractId;
+    /**
+     * 删除的类型,文件资料1,工程划分2
+     */
+	@ApiModelProperty("删除的类型,文件资料1,工程划分2")
+    private Integer delType;
+    /**
+     * 文件名称
+     */
+	@ApiModelProperty("文件名称")
+    private String fileName;
+    /**
+     * 所在位置,即节点路径
+     */
+	@ApiModelProperty("所在位置,即节点路径")
+    private String position;
+    /**
+     * 业务ID
+     */
+	@ApiModelProperty("业务ID")
+    private String businessId;
+    /**
+     * 操作时间,与创建时间相同
+     */
+	@ApiModelProperty("操作时间,与创建时间相同")
+    private String operationTime;
+
+	@ApiModelProperty("操作人姓名")
+    private String createUserName;
+
+
+}

+ 18 - 0
blade-service-api/blade-business-api/src/main/java/org/springblade/business/vo/RecycleBinVO.java

@@ -0,0 +1,18 @@
+package org.springblade.business.vo;
+
+import org.springblade.business.entity.RecycleBin;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+/**
+ * 视图实体类
+ *
+ * @author BladeX
+ * @since 2022-07-19
+ */
+@Data
+@EqualsAndHashCode(callSuper = true)
+public class RecycleBinVO extends RecycleBin {
+	private static final long serialVersionUID = 1L;
+
+}

+ 29 - 0
blade-service-api/blade-business-api/src/main/java/org/springblade/business/vo/SaveNodeVO.java

@@ -0,0 +1,29 @@
+package org.springblade.business.vo;
+
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.util.List;
+
+@Data
+public class SaveNodeVO {
+
+    @ApiModelProperty("项目ID")
+    private String projectId;
+
+    @ApiModelProperty("合同段ID")
+    private String contractId;
+
+    @ApiModelProperty("当前需要新增节点的primaryKeyId")
+    private String currentNodePrimaryKeyId;
+
+    @ApiModelProperty("半选集合")
+    private List<String> halfSelectedList;
+
+    @ApiModelProperty("全选集合")
+    private List<String> allSelectedList;
+
+    @ApiModelProperty("新增类型")
+    private String saveType;
+
+}

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

@@ -1,7 +1,6 @@
 package org.springblade.manager.entity;
 
 
-import com.baomidou.mybatisplus.annotation.TableId;
 import com.baomidou.mybatisplus.annotation.TableName;
 import com.fasterxml.jackson.annotation.JsonProperty;
 import io.swagger.annotations.ApiModelProperty;
@@ -189,5 +188,6 @@ public class WbsTreeContract extends BaseEntity {
     @ApiModelProperty(value = "html路径")
     private String htmlUrl;
 
-
+    @ApiModelProperty(value = "原id,如果当前字段有数据则说明这条数据是复制节点")
+    private String oldId;
 }

+ 3 - 0
blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/feign/WbsTreeContractClient.java

@@ -21,6 +21,9 @@ public interface WbsTreeContractClient {
      */
     String API_PREFIX = "/api/manager/WbsTreeContract";
 
+    @PostMapping(API_PREFIX + "/saveBatch")
+    Boolean saveBatch(@RequestBody List<WbsTreeContract> list);
+
     /**
      * 监理、业主获取划分树
      */

+ 9 - 1
blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/feign/WbsTreePrivateClient.java

@@ -1,9 +1,11 @@
 package org.springblade.manager.feign;
 
 import org.springblade.manager.entity.WbsTreePrivate;
+import org.springblade.manager.vo.WbsTreeContractTreeVOS;
 import org.springblade.manager.vo.WbsTreePrivateVO;
 import org.springframework.cloud.openfeign.FeignClient;
 import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
 import org.springframework.web.bind.annotation.RequestParam;
 
 import java.util.List;
@@ -18,10 +20,16 @@ public interface WbsTreePrivateClient {
      */
     String API_PREFIX = "/api/manager/WbsTreePrivate";
 
+    @PostMapping(API_PREFIX + "/queryChildByParentId")
+    List<WbsTreePrivate> queryChildByParentId(@RequestBody WbsTreePrivate treePrivate);
+
+    @PostMapping(API_PREFIX + "/queryByPKeyIds")
+    List<WbsTreePrivate> queryByPKeyIds(@RequestParam List<String> ids);
+
     @PostMapping(API_PREFIX + "/queryPeersNodeByProjectIdAndId")
     WbsTreePrivate queryPeersNodeByProjectIdAndId(@RequestParam String projectId, @RequestParam Long id);
 
     @PostMapping(API_PREFIX + "/queryWbsTreePrivateByProjectIdAndId")
-    List<WbsTreePrivateVO> queryWbsTreePrivateByProjectIdAndId(@RequestParam String projectId, @RequestParam Long id);
+    List<WbsTreeContractTreeVOS> queryWbsTreePrivateByProjectIdAndId(@RequestParam String projectId, @RequestParam Long id);
 
 }

+ 10 - 0
blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/vo/TreeNodeVO.java

@@ -44,6 +44,8 @@ public class TreeNodeVO extends BaseNode<TreeNode> {
 
     private String ancestors;
 
+    private String oldId;
+
     public TreeNodeVO() {
     }
 
@@ -159,6 +161,14 @@ public class TreeNodeVO extends BaseNode<TreeNode> {
         this.partitionCode = partitionCode;
     }
 
+    public String getOldId() {
+        return oldId;
+    }
+
+    public void setOldId(String oldId) {
+        this.oldId = oldId;
+    }
+
     public String toString() {
         return "TreeNode(deptCategory=" + this.getDeptCategory() + ",tenantId" + this.getTenantId() + ",contractType" + this.getContractType()
                 + ",contractId" + this.getContractId()

+ 3 - 0
blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/vo/WbsTreeContractTreeVOS.java

@@ -64,4 +64,7 @@ public class WbsTreeContractTreeVOS {
     @ApiModelProperty("合同段ID")
     private String contractIdRelation;
 
+    @ApiModelProperty("原id,如果当前字段有数据则说明这条数据是复制节点")
+    private String oldId;
+
 }

+ 28 - 10
blade-service/blade-business/src/main/java/org/springblade/business/controller/ImageClassificationFileController.java

@@ -26,6 +26,7 @@ import org.springblade.core.oss.model.BladeFile;
 import org.springblade.core.secure.utils.AuthUtil;
 import org.springblade.core.tool.api.R;
 import org.springblade.core.tool.utils.Func;
+import org.springblade.core.tool.utils.IoUtil;
 import org.springblade.manager.entity.ExcelTab;
 import org.springblade.manager.entity.ImageClassificationConfig;
 import org.springblade.manager.feign.ExcelTabClient;
@@ -102,7 +103,8 @@ public class ImageClassificationFileController extends BladeController {
 
 			try{
 				if(fileResult != null && fileResult.size() > 0){
-
+					//需要删除的本地文件集合
+					List<String> removeList = new ArrayList<>();
 					for(ImageClassificationFile file : fileResult){
 						//获取图片文件流
 						String[] uris = file.getImageUrl().split(",");
@@ -110,7 +112,9 @@ public class ImageClassificationFileController extends BladeController {
 						if(uris.length > 0){
 							//获取模板文件流
 							InputStream modInput = null;
+							FileInputStream excelFileInput = null;
 							FileOutputStream outputStream = null;
+							Workbook workbook = null;
 
 							List<String> pdfFileList = new ArrayList<>();
 							//每个图片就是一个文件
@@ -118,7 +122,7 @@ public class ImageClassificationFileController extends BladeController {
 								try{
 									//创建模板Workbook
 									modInput = CommonUtil.getOSSInputStream(excelTab.getFileUrl());
-									Workbook workbook = WorkbookFactory.create(modInput);
+									workbook = WorkbookFactory.create(modInput);
 									CreationHelper helper = workbook.getCreationHelper();
 									Sheet sheet = workbook.getSheetAt(0);
 									Drawing<?> drawing = sheet.createDrawingPatriarch();
@@ -147,28 +151,36 @@ public class ImageClassificationFileController extends BladeController {
 									//参见号
 									sheet.getRow(32).getCell(4).setCellValue(file.getShootingUser());
 
-									String locationFile = "D:\\project\\file\\" + SnowFlakeUtil.getId() + ".xlsx";
+									String locationFile = "doc/print/" + SnowFlakeUtil.getId() + ".xlsx";
 									outputStream = new FileOutputStream(locationFile);
+									//记录文件删除
+									removeList.add(locationFile);
 
 									//生成一份新的excel
 									workbook.write(outputStream);
 									//将excel转PDF
 									File excelFile = new File(locationFile);
-									MultipartFile files = new MockMultipartFile("file", excelFile.getName(), "text/plain", IOUtils.toByteArray(new FileInputStream(excelFile)));
+									excelFileInput = new FileInputStream(excelFile);
+									MultipartFile files = new MockMultipartFile("file", excelFile.getName(), "text/plain", IOUtils.toByteArray(excelFileInput));
 									NewBladeFile bladeFile = this.commonFileClient.excelToPdf(files);
 									if(bladeFile != null){
 										pdfFileList.add(bladeFile.getPdfUrl());
 									}
-									outputStream.close();
-									modInput.close();
+
 								}catch (Exception e){
 									e.printStackTrace();
 								} finally {
+									if(outputStream != null){
+										IoUtil.closeQuietly(outputStream);
+									}
 									if(modInput != null){
-										modInput.close();
+										IoUtil.closeQuietly(modInput);
 									}
-									if(outputStream != null){
-										outputStream.close();
+									if(excelFileInput != null){
+										IoUtil.closeQuietly(excelFileInput);
+									}
+									if(workbook != null){
+										IoUtil.closeQuietly(workbook);
 									}
 								}
 							}
@@ -179,8 +191,10 @@ public class ImageClassificationFileController extends BladeController {
 								String[] urls = file.getMargePdfUrl().split("/");
 								mergeName = urls[urls.length - 1];
 							}
-							String mergeUrl = "D:\\project\\file\\" + mergeName;
+							String mergeUrl = "doc/print/" + mergeName;
 							FileUtils.mergePdfPublicMethods(pdfFileList, mergeUrl);
+							//记录文件删除
+							removeList.add(mergeUrl);
 							//上传
 							BladeFile bladeFile = this.newIOSSClient.uploadFile(mergeName, mergeUrl);
 							if(bladeFile != null){
@@ -192,6 +206,10 @@ public class ImageClassificationFileController extends BladeController {
 							}
 						}
 					}
+					if(removeList.size() > 0){
+						//删除本地文件
+						CommonUtil.removeFile(removeList);
+					}
 				}
 			}catch (Exception e){
 				e.printStackTrace();

+ 136 - 25
blade-service/blade-business/src/main/java/org/springblade/business/controller/InformationWriteQueryController.java

@@ -31,6 +31,8 @@ import org.springblade.business.service.IContractTreeDrawingsService;
 import org.springblade.business.service.ITreeContractFirstService;
 import org.springblade.business.vo.FileUserVO;
 import org.springblade.business.vo.InformationQueryVO;
+import org.springblade.business.vo.SaveNodeVO;
+import org.springblade.common.utils.SnowFlakeUtil;
 import org.springblade.core.mp.support.Condition;
 import org.springblade.core.mp.support.Query;
 import org.springblade.core.tool.api.R;
@@ -42,17 +44,16 @@ import org.springblade.manager.feign.ContractClient;
 import org.springblade.manager.feign.WbsTreeContractClient;
 import org.springblade.manager.feign.WbsTreePrivateClient;
 import org.springblade.manager.vo.WbsTreeContractTreeVOS;
-import org.springblade.manager.vo.WbsTreePrivateVO;
 import org.springblade.system.entity.DictBiz;
 import org.springblade.system.feign.IDictBizClient;
+import org.springframework.beans.BeanUtils;
 import org.springframework.web.bind.annotation.*;
 import org.springframework.web.bind.annotation.RequestParam;
 import org.springblade.business.entity.InformationQuery;
 import org.springblade.business.service.IInformationQueryService;
 import org.springblade.core.boot.ctrl.BladeController;
 
-import java.util.ArrayList;
-import java.util.List;
+import java.util.*;
 
 /**
  *  资料填报及查询控制器
@@ -100,7 +101,7 @@ public class InformationWriteQueryController extends BladeController {
 		//获取合同段,检查是否是监理合同段
 		ContractInfo contractInfo = this.contractClient.getContractById(Long.parseLong(contractId));
 
-		if(new Integer("2").equals(contractInfo.getContractType())){
+		if(contractInfo.getContractType() != null && new Integer("2").equals(contractInfo.getContractType())){
 			//监理合同段
 			List<WbsTreeContractTreeVOS> childList = this.wbsTreeContractClient.lazyTree(StringUtils.isNotEmpty(parentId) ? Long.parseLong(parentId) : 0, contractId, contractIdRelation, contractInfo.getContractType());
 			if(childList != null && childList.size() == 1){
@@ -208,26 +209,136 @@ public class InformationWriteQueryController extends BladeController {
 		return R.data(this.wbsTreeContractClient.removeContractTreeNode(ids));
 	}
 
-//	/**
-//	 * 新增子节点
-//	 * @param contractNodePrimaryKeyId 新增的节点所在位置,即当前点出菜单栏的节点PrimaryKeyId
-//	 * @param projectNodePrimaryKeyId 被选中的新增节点
-//	 * @return 新增结果
-//	 */
-//	@PostMapping("/saveContractTreeNode")
-//	@ApiOperationSupport(order = 10)
-//	@ApiOperation(value = "新增节点及其子节点")
-//	@ApiImplicitParams({
-//			@ApiImplicitParam(name = "contractNodePrimaryKeyId", value = "新增的节点所在位置,即当前点出菜单栏的节点PrimaryKeyId", required = true),
-//			@ApiImplicitParam(name = "projectNodePrimaryKeyId", value = "被选中的新增节点", required = true)
-//	})
-//	public R<Boolean> saveContractTreeNode(@RequestParam String contractNodePrimaryKeyId, @RequestParam String projectNodePrimaryKeyId){
-//		//先获取当前节点的信息
-//		WbsTreeContract treeContract = this.wbsTreeContractClient.getContractWbsTreeByPrimaryKeyId(Long.parseLong(contractNodePrimaryKeyId));
-//		//检查当前节点下是否添加了子节点
-//
-//		return null;
-//	}
+	/**
+	 * 新增子节点
+	 * @return 新增结果
+	 */
+	@PostMapping("/saveContractTreeNode")
+	@ApiOperationSupport(order = 10)
+	@ApiOperation(value = "新增节点及其子节点")
+	public R<Boolean> saveContractTreeNode(@RequestBody SaveNodeVO vo){
+		//先获取当前节点的信息
+		WbsTreeContract treeContract = this.wbsTreeContractClient.getContractWbsTreeByPrimaryKeyId(Long.parseLong(vo.getCurrentNodePrimaryKeyId()));
+
+		//半选
+		List<String> halfSelectedList = vo.getHalfSelectedList();
+		//全选
+		List<String> allSelectedList = vo.getAllSelectedList();
+		//所有相关节点集合
+		List<WbsTreePrivate> selectedNodeList = new ArrayList<>();
+
+		//检查新增类型
+		if("1".equals(vo.getSaveType())){
+			//todo 当前节点及其子节点
+			//当前节点及其子节点时,半选说明其下的子节点并不是全部选中的,所以这时候只需要根据全选的查询其全部子节点即可
+			if(allSelectedList != null && allSelectedList.size() > 0){
+				selectedNodeList = this.wbsTreePrivateClient.queryByPKeyIds(allSelectedList);
+				//剔除与当前操作节点相同的ID
+				selectedNodeList.removeIf(wbsTreePrivate -> vo.getCurrentNodePrimaryKeyId().equals(wbsTreePrivate.getId().toString()));
+
+				//全选的集合则进一步向下查询
+				List<WbsTreePrivate> childList = new ArrayList<>();
+				this.foreachQueryChild(selectedNodeList, childList);
+
+				if(childList.size() > 0){
+					//处理重复的数据
+					Iterator<WbsTreePrivate> iterator = childList.iterator();
+					while (iterator.hasNext()){
+						WbsTreePrivate next = iterator.next();
+						for(WbsTreePrivate treePrivate : selectedNodeList){
+							if(treePrivate.getPKeyId().equals(next.getPKeyId())){
+								//删掉重复数据
+								iterator.remove();
+							}
+						}
+					}
+				}
+				//处理完重复数据后,设置进集合中
+				selectedNodeList.addAll(childList);
+			}
+			//处理半选
+			if(halfSelectedList != null && halfSelectedList.size() > 0){
+				List<WbsTreePrivate> halfSelectedNodeList = this.wbsTreePrivateClient.queryByPKeyIds(halfSelectedList);
+				//剔除与当前操作节点相同的ID
+				halfSelectedNodeList.removeIf(wbsTreePrivate -> vo.getCurrentNodePrimaryKeyId().equals(wbsTreePrivate.getId().toString()));
+				//设置到集合中
+				selectedNodeList.addAll(halfSelectedNodeList);
+			}
+
+		} else {
+			//todo 仅当前节点操作
+			if(halfSelectedList != null && halfSelectedList.size() > 0){
+				selectedNodeList = this.wbsTreePrivateClient.queryByPKeyIds(halfSelectedList);
+				//剔除与当前操作节点相同的ID
+				selectedNodeList.removeIf(wbsTreePrivate -> vo.getCurrentNodePrimaryKeyId().equals(wbsTreePrivate.getId().toString()));
+			}
+
+			if(allSelectedList != null && allSelectedList.size() > 0){
+				List<WbsTreePrivate> allSelectedNodeList = this.wbsTreePrivateClient.queryByPKeyIds(allSelectedList);
+				//剔除与当前操作节点相同的ID
+				allSelectedNodeList.removeIf(wbsTreePrivate -> vo.getCurrentNodePrimaryKeyId().equals(wbsTreePrivate.getId().toString()));
+				//设置到集合中
+				selectedNodeList.addAll(allSelectedNodeList);
+			}
+
+		}
+
+		//保存集合
+		List<WbsTreeContract> saveList = new ArrayList<>();
+		if(selectedNodeList.size() > 0){
+			//重塑关键信息
+			Map<Long, Long> OldIdToNewIdMap = new HashMap<>();
+			selectedNodeList.forEach(half -> OldIdToNewIdMap.put(half.getId(), SnowFlakeUtil.getId()));
+
+			//处理数据
+			selectedNodeList.forEach(half -> {
+				//处理合同段数据
+				WbsTreeContract newData = new WbsTreeContract();
+				BeanUtils.copyProperties(half, newData);
+
+				//重塑pKeyId、id和parentId
+				newData.setPKeyId(SnowFlakeUtil.getId());
+				newData.setId(OldIdToNewIdMap.containsKey(half.getId()) ? OldIdToNewIdMap.get(half.getId()) : SnowFlakeUtil.getId());
+				newData.setParentId(OldIdToNewIdMap.containsKey(half.getParentId()) ? OldIdToNewIdMap.get(half.getParentId()) : treeContract.getId().equals(half.getParentId()) ? treeContract.getId() : SnowFlakeUtil.getId());
+				//记录旧ID
+				newData.setOldId(half.getId().toString());
+				//设置合同段等信息
+				newData.setWbsType(treeContract.getWbsType());
+				newData.setContractId(vo.getContractId());
+				newData.setContractIdRelation(treeContract.getContractIdRelation());
+				newData.setContractType(treeContract.getContractType());
+				newData.setCreateTime(new Date());
+				//设置到保存集合中
+				saveList.add(newData);
+			});
+		}
+
+		if(saveList.size() > 0){
+			this.wbsTreeContractClient.saveBatch(saveList);
+		}
+
+		return R.data(true);
+	}
+
+	/**
+	 * 循环查询子节点
+	 * @param parentList 父节点集合
+	 * @param childList 保存集合
+	 */
+	private void foreachQueryChild(List<WbsTreePrivate> parentList, List<WbsTreePrivate> childList){
+		parentList.forEach(parent -> {
+			if(!new Integer("6").equals(parent.getDeptCategory())){
+				//查询子节点
+				List<WbsTreePrivate> childs = this.wbsTreePrivateClient.queryChildByParentId(parent);
+				if(childs != null && childs.size() > 0){
+					//添加入结果集
+					childList.addAll(childs);
+					//还有子级,继续向下
+					this.foreachQueryChild(childs, childList);
+				}
+			}
+		});
+	}
 
 	/**
 	 * 懒加载项目级工程划分树
@@ -242,7 +353,7 @@ public class InformationWriteQueryController extends BladeController {
 			@ApiImplicitParam(name = "projectId", value = "项目ID"),
 			@ApiImplicitParam(name = "id", value = "点击节点ID")
 	})
-	public R<List<WbsTreePrivateVO>> queryWbsTreePrivateByProjectIdAndId(@RequestParam String projectId, @RequestParam String id){
+	public R<List<WbsTreeContractTreeVOS>> queryWbsTreePrivateByProjectIdAndId(@RequestParam String projectId, @RequestParam String id){
 		return R.data(this.wbsTreePrivateClient.queryWbsTreePrivateByProjectIdAndId(projectId, Long.parseLong(id)));
 	}
 

+ 52 - 0
blade-service/blade-business/src/main/java/org/springblade/business/controller/RecycleBinController.java

@@ -0,0 +1,52 @@
+package org.springblade.business.controller;
+
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
+import lombok.AllArgsConstructor;
+
+import org.springblade.core.mp.support.Condition;
+import org.springblade.core.mp.support.Query;
+import org.springblade.core.tool.api.R;
+import org.springframework.web.bind.annotation.*;
+import org.springframework.web.bind.annotation.RequestParam;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import org.springblade.business.entity.RecycleBin;
+import org.springblade.business.service.IRecycleBinService;
+import org.springblade.core.boot.ctrl.BladeController;
+
+/**
+ *  控制器
+ *
+ * @author BladeX
+ * @since 2022-07-19
+ */
+@RestController
+@AllArgsConstructor
+@RequestMapping("/recyclebin")
+@Api(value = "客户端回收站", tags = "客户端回收站")
+public class RecycleBinController extends BladeController {
+
+	private final IRecycleBinService recycleBinService;
+
+	@PostMapping("/regain")
+	@ApiOperationSupport(order = 2)
+	@ApiOperation(value = "恢复")
+	public R<Boolean> regain(@RequestParam String ids){
+//		if(){
+//
+//		}
+		return null;
+	}
+
+	/**
+	 * 分页 
+	 */
+	@GetMapping("/list")
+	@ApiOperationSupport(order = 1)
+	@ApiOperation(value = "分页")
+	public R<IPage<RecycleBin>> list(RecycleBin recycleBin, Query query) {
+		return R.data(this.recycleBinService.page(Condition.getPage(query), Condition.getQueryWrapper(recycleBin)));
+	}
+	
+}

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

@@ -538,7 +538,7 @@ public class TaskController extends BladeController {
 			//转换数据
 			TaskApprovalVO vo = new TaskApprovalVO();
 			for(ArchiveFile archiveFile : archiveFileList){
-				vo.setApprovalFileList(archiveFile.getFileName(), archiveFile.getPdfFileUrl());
+				vo.setApprovalFileList(archiveFile.getFileName(), StringUtils.isEmpty(archiveFile.getPdfFileUrl()) ? archiveFile.getFileUrl() : archiveFile.getPdfFileUrl());
 			}
 			return vo;
 		}

+ 42 - 0
blade-service/blade-business/src/main/java/org/springblade/business/mapper/RecycleBinMapper.java

@@ -0,0 +1,42 @@
+/*
+ *      Copyright (c) 2018-2028, Chill Zhuang All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are met:
+ *
+ *  Redistributions of source code must retain the above copyright notice,
+ *  this list of conditions and the following disclaimer.
+ *  Redistributions in binary form must reproduce the above copyright
+ *  notice, this list of conditions and the following disclaimer in the
+ *  documentation and/or other materials provided with the distribution.
+ *  Neither the name of the dreamlu.net developer nor the names of its
+ *  contributors may be used to endorse or promote products derived from
+ *  this software without specific prior written permission.
+ *  Author: Chill 庄骞 (smallchill@163.com)
+ */
+package org.springblade.business.mapper;
+
+import org.springblade.business.entity.RecycleBin;
+import org.springblade.business.vo.RecycleBinVO;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import java.util.List;
+
+/**
+ *  Mapper 接口
+ *
+ * @author BladeX
+ * @since 2022-07-19
+ */
+public interface RecycleBinMapper extends BaseMapper<RecycleBin> {
+
+	/**
+	 * 自定义分页
+	 *
+	 * @param page
+	 * @param recycleBin
+	 * @return
+	 */
+	List<RecycleBinVO> selectRecycleBinPage(IPage page, RecycleBinVO recycleBin);
+
+}

+ 30 - 0
blade-service/blade-business/src/main/java/org/springblade/business/mapper/RecycleBinMapper.xml

@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="org.springblade.business.mapper.RecycleBinMapper">
+
+    <!-- 通用查询映射结果 -->
+    <resultMap id="recycleBinResultMap" type="org.springblade.business.entity.RecycleBin">
+        <result column="id" property="id"/>
+        <result column="create_user" property="createUser"/>
+        <result column="create_dept" property="createDept"/>
+        <result column="create_time" property="createTime"/>
+        <result column="update_user" property="updateUser"/>
+        <result column="update_time" property="updateTime"/>
+        <result column="status" property="status"/>
+        <result column="is_deleted" property="isDeleted"/>
+        <result column="project_id" property="projectId"/>
+        <result column="contract_id" property="contractId"/>
+        <result column="del_type" property="delType"/>
+        <result column="file_name" property="fileName"/>
+        <result column="position" property="position"/>
+        <result column="business_id" property="businessId"/>
+        <result column="operation_time" property="operationTime"/>
+        <result column="create_user_name" property="createUserName"/>
+    </resultMap>
+
+
+    <select id="selectRecycleBinPage" resultMap="recycleBinResultMap">
+        select * from u_recycle_bin where is_deleted = 0
+    </select>
+
+</mapper>

+ 41 - 0
blade-service/blade-business/src/main/java/org/springblade/business/service/impl/RecycleBinServiceImpl.java

@@ -0,0 +1,41 @@
+/*
+ *      Copyright (c) 2018-2028, Chill Zhuang All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are met:
+ *
+ *  Redistributions of source code must retain the above copyright notice,
+ *  this list of conditions and the following disclaimer.
+ *  Redistributions in binary form must reproduce the above copyright
+ *  notice, this list of conditions and the following disclaimer in the
+ *  documentation and/or other materials provided with the distribution.
+ *  Neither the name of the dreamlu.net developer nor the names of its
+ *  contributors may be used to endorse or promote products derived from
+ *  this software without specific prior written permission.
+ *  Author: Chill 庄骞 (smallchill@163.com)
+ */
+package org.springblade.business.service.impl;
+
+import org.springblade.business.entity.RecycleBin;
+import org.springblade.business.vo.RecycleBinVO;
+import org.springblade.business.mapper.RecycleBinMapper;
+import org.springblade.business.service.IRecycleBinService;
+import org.springblade.core.mp.base.BaseServiceImpl;
+import org.springframework.stereotype.Service;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+
+/**
+ *  服务实现类
+ *
+ * @author BladeX
+ * @since 2022-07-19
+ */
+@Service
+public class RecycleBinServiceImpl extends BaseServiceImpl<RecycleBinMapper, RecycleBin> implements IRecycleBinService {
+
+	@Override
+	public IPage<RecycleBinVO> selectRecycleBinPage(IPage<RecycleBinVO> page, RecycleBinVO recycleBin) {
+		return page.setRecords(baseMapper.selectRecycleBinPage(page, recycleBin));
+	}
+
+}

+ 8 - 3
blade-service/blade-manager/src/main/java/org/springblade/manager/feign/WbsTreeContractClientImpl.java

@@ -27,6 +27,11 @@ public class WbsTreeContractClientImpl implements WbsTreeContractClient {
 
     private final IDictBizClient dictBizClient;
 
+    @Override
+    public Boolean saveBatch(List<WbsTreeContract> list) {
+        return this.wbsTreeContractService.saveBatch(list);
+    }
+
     @Override
     public List<WbsTreeContractTreeVOS> lazyTree(Long parentId, String contractId, String contractIdRelation, Integer type) {
         List<WbsTreeContractTreeVO> result = this.wbsTreeContractService.lazyTreeTwo(contractIdRelation, parentId, type, contractId);
@@ -44,7 +49,7 @@ public class WbsTreeContractClientImpl implements WbsTreeContractClient {
 
     @Override
     public Boolean updateContractNodeParameter(WbsTreeContract node) {
-        return this.wbsTreeContractService.update(Wrappers.<WbsTreeContract>lambdaUpdate().set(WbsTreeContract::getDeptName, node.getDeptName()).set(WbsTreeContract::getFullName, node.getDeptName()).set(WbsTreeContract::getPartitionCode, node.getPartitionCode()).eq(WbsTreeContract::getPKeyId, node.getPKeyId()));
+        return this.wbsTreeContractService.update(Wrappers.<WbsTreeContract>lambdaUpdate().set(WbsTreeContract::getFullName, node.getDeptName()).set(WbsTreeContract::getPartitionCode, node.getPartitionCode()).eq(WbsTreeContract::getPKeyId, node.getPKeyId()));
     }
 
     @Override
@@ -76,8 +81,8 @@ public class WbsTreeContractClientImpl implements WbsTreeContractClient {
         vos.forEach(voData -> {
             voData.setLeaf(new Integer("6").equals(voData.getDeptCategory()));
             //检查是否有下级
-            List<WbsTreeContractTreeVO> childs = this.contractInfoService.queryContractWbsTreeByContractIdAndType(contractId, wbsType, voData.getId());
-            voData.setExsitChild(childs == null || childs.size() == 0);
+            long count = this.wbsTreeContractService.count(Wrappers.<WbsTreeContract>lambdaQuery().eq(WbsTreeContract::getParentId, voData.getId()).eq(WbsTreeContract::getContractId, contractId));
+            voData.setExsitChild(count == 0);
         });
         return vos;
     }

+ 29 - 6
blade-service/blade-manager/src/main/java/org/springblade/manager/feign/WbsTreePrivateClientImpl.java

@@ -1,14 +1,13 @@
 package org.springblade.manager.feign;
 
-import com.alibaba.fastjson.JSONArray;
-import com.alibaba.fastjson.JSONObject;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import lombok.AllArgsConstructor;
 import org.springblade.manager.entity.WbsTreePrivate;
 import org.springblade.manager.service.IWbsTreePrivateService;
-import org.springblade.manager.vo.WbsTreePrivateVO;
+import org.springblade.manager.vo.WbsTreeContractTreeVOS;
 import org.springframework.web.bind.annotation.RestController;
 
+import java.util.ArrayList;
 import java.util.List;
 
 @RestController
@@ -18,11 +17,35 @@ public class WbsTreePrivateClientImpl implements WbsTreePrivateClient {
     private final IWbsTreePrivateService wbsTreePrivateService;
 
     @Override
-    public List<WbsTreePrivateVO> queryWbsTreePrivateByProjectIdAndId(String projectId, Long id) {
+    public List<WbsTreePrivate> queryChildByParentId(WbsTreePrivate treePrivate) {
+        return this.wbsTreePrivateService.list(Wrappers.<WbsTreePrivate>lambdaQuery().eq(WbsTreePrivate::getParentId, treePrivate.getId()).eq(WbsTreePrivate::getProjectId, treePrivate.getProjectId()));
+    }
+
+    @Override
+    public List<WbsTreePrivate> queryByPKeyIds(List<String> ids) {
+        return this.wbsTreePrivateService.list(Wrappers.<WbsTreePrivate>lambdaQuery().in(WbsTreePrivate::getPKeyId, ids));
+    }
+
+    @Override
+    public List<WbsTreeContractTreeVOS> queryWbsTreePrivateByProjectIdAndId(String projectId, Long id) {
         List<WbsTreePrivate> result =  this.wbsTreePrivateService.list(Wrappers.<WbsTreePrivate>lambdaQuery().eq(WbsTreePrivate::getProjectId, projectId).eq(WbsTreePrivate::getParentId, id).eq(WbsTreePrivate::getIsDeleted, 0));
         if(result != null && result.size() != 0){
-            //转换vo
-            return JSONArray.parseArray(JSONObject.toJSONString(result), WbsTreePrivateVO.class);
+            List<WbsTreeContractTreeVOS> vosResult = new ArrayList<>();
+            result.forEach(wbsTreePrivate -> {
+                WbsTreeContractTreeVOS vos = new WbsTreeContractTreeVOS();
+                vos.setId(wbsTreePrivate.getId().toString());
+                vos.setKey(wbsTreePrivate.getId().toString());
+                vos.setPrimaryKeyId(wbsTreePrivate.getPKeyId().toString());
+                vos.setParentId(wbsTreePrivate.getParentId().toString());
+                vos.setTitle(wbsTreePrivate.getDeptName());
+                vos.setType(wbsTreePrivate.getType());
+                vos.setWbsType(Integer.parseInt(wbsTreePrivate.getWbsType()));
+                long count = this.wbsTreePrivateService.count(Wrappers.<WbsTreePrivate>lambdaQuery().eq(WbsTreePrivate::getProjectId, projectId).eq(WbsTreePrivate::getParentId, wbsTreePrivate.getId()));
+                vos.setExsitChild(count == 0);
+
+                vosResult.add(vos);
+            });
+            return vosResult;
         }
         return null;
     }

+ 3 - 1
blade-service/blade-manager/src/main/java/org/springblade/manager/mapper/ContractInfoMapper.xml

@@ -60,6 +60,7 @@
         <result column="primaryKeyId" property="primaryKeyId"/>
         <result column="wbsType" property="wbsType"/>
         <result column="partition_code" property="partitionCode"/>
+        <result column="old_id" property="oldId"/>
     </resultMap>
 
     <resultMap id="resultMap2" type="org.springblade.manager.vo.ContractInfoVO">
@@ -173,7 +174,8 @@
         dept_category AS deptCategory,
         id AS "value",
         id AS "key",
-        partition_code
+        partition_code,
+        old_id
         FROM
         m_wbs_tree_contract
         WHERE

+ 1 - 0
blade-service/blade-manager/src/main/java/org/springblade/manager/mapper/WbsTreeContractMapper.xml

@@ -38,6 +38,7 @@
         <result column="is_link_table" property="isLinkTable"/>
         <result column="wbs_type" property="wbsType"/>
         <result column="excel_id" property="excelId"/>
+        <result column="old_id" property="oldId"/>
     </resultMap>
 
     <resultMap id="resultMap2" type="org.springblade.manager.vo.WbsTreeContractVO">