浏览代码

Merge branch 'dev' of http://219.151.181.73:3000/zhuwei/bladex into dev

laibulaizheli 2 月之前
父节点
当前提交
0b4bee9c2f
共有 100 个文件被更改,包括 2949 次插入771 次删除
  1. 10 0
      blade-common/pom.xml
  2. 5 1
      blade-common/src/main/java/org/springblade/common/constant/LauncherConstant.java
  3. 1 1
      blade-common/src/main/java/org/springblade/common/utils/AsyncConfigurer.java
  4. 166 76
      blade-common/src/main/java/org/springblade/common/utils/CommonUtil.java
  5. 10 0
      blade-common/src/main/java/org/springblade/common/utils/ForestNodeManagerEx.java
  6. 21 0
      blade-common/src/main/java/org/springblade/common/utils/ForestNodeMergerEx.java
  7. 35 21
      blade-common/src/main/java/org/springblade/common/utils/YiKeYunApiUtils.java
  8. 5 2
      blade-ops/blade-resource/src/main/java/org/springblade/resource/endpoint/SmsEndpoint.java
  9. 34 0
      blade-service-api/blade-archive-api/src/main/java/org/springblade/archive/dto/TaskSplitDTO.java
  10. 4 1
      blade-service-api/blade-archive-api/src/main/java/org/springblade/archive/entity/ArchivesAuto.java
  11. 73 0
      blade-service-api/blade-archive-api/src/main/java/org/springblade/archive/entity/TaskSplit.java
  12. 34 0
      blade-service-api/blade-archive-api/src/main/java/org/springblade/archive/vo/TaskSplitVO.java
  13. 1 0
      blade-service-api/blade-business-api/src/main/java/org/springblade/business/dto/TrialFileSubmitDTO.java
  14. 1 1
      blade-service-api/blade-business-api/src/main/java/org/springblade/business/feign/ContractLogClient.java
  15. 18 0
      blade-service-api/blade-e-visa-api/src/main/java/org/springblade/evisa/vo/TaskArchiveSplitVO.java
  16. 4 0
      blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/entity/ArchiveTree.java
  17. 1 0
      blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/entity/ArchiveTreeContract.java
  18. 3 0
      blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/entity/ContractInfo.java
  19. 12 0
      blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/entity/ProjectInfo.java
  20. 8 2
      blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/feign/ExcelTabClient.java
  21. 13 3
      blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/feign/ExcelTabClientFallBack.java
  22. 3 0
      blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/feign/WbsParamClient.java
  23. 5 0
      blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/vo/ArchiveTreeVO2.java
  24. 107 0
      blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/vo/ArchiveTreeVO3.java
  25. 6 0
      blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/vo/WbsTreeContractLazyVO.java
  26. 5 0
      blade-service-api/blade-meter-api/src/main/java/org/springblade/meter/dto/MeterApprovalDTO.java
  27. 135 0
      blade-service/blade-archive/src/main/java/org/springblade/archive/controller/TaskSplitController.java
  28. 43 0
      blade-service/blade-archive/src/main/java/org/springblade/archive/mapper/TaskSplitMapper.java
  29. 32 0
      blade-service/blade-archive/src/main/java/org/springblade/archive/mapper/TaskSplitMapper.xml
  30. 44 0
      blade-service/blade-archive/src/main/java/org/springblade/archive/service/ITaskSplitService.java
  31. 78 0
      blade-service/blade-archive/src/main/java/org/springblade/archive/service/impl/TaskSplitServiceImpl.java
  32. 0 104
      blade-service/blade-archive/src/main/java/org/springblade/archive/utils/SpeechRecognizerRESTfulDemo.java
  33. 2 2
      blade-service/blade-business/pom.xml
  34. 7 0
      blade-service/blade-business/src/main/java/org/springblade/business/controller/ArchiveFileController.java
  35. 1 1
      blade-service/blade-business/src/main/java/org/springblade/business/controller/ChekSignData.java
  36. 1 1
      blade-service/blade-business/src/main/java/org/springblade/business/controller/EVisaTaskCheckController.java
  37. 25 3
      blade-service/blade-business/src/main/java/org/springblade/business/controller/EntrustInfoController.java
  38. 1 1
      blade-service/blade-business/src/main/java/org/springblade/business/controller/FixedFlowController.java
  39. 50 0
      blade-service/blade-business/src/main/java/org/springblade/business/controller/InformationWriteQueryController.java
  40. 3 3
      blade-service/blade-business/src/main/java/org/springblade/business/controller/NeiYeController.java
  41. 0 2
      blade-service/blade-business/src/main/java/org/springblade/business/controller/OperationLogController.java
  42. 21 11
      blade-service/blade-business/src/main/java/org/springblade/business/controller/TaskController.java
  43. 2 2
      blade-service/blade-business/src/main/java/org/springblade/business/feignClient/ContractLogClientImpl.java
  44. 1 1
      blade-service/blade-business/src/main/java/org/springblade/business/mapper/EntrustInfoMapper.xml
  45. 2 0
      blade-service/blade-business/src/main/java/org/springblade/business/service/IArchiveFileService.java
  46. 27 0
      blade-service/blade-business/src/main/java/org/springblade/business/service/impl/ArchiveFileServiceImpl.java
  47. 22 12
      blade-service/blade-business/src/main/java/org/springblade/business/service/impl/EntrustInfoServiceImpl.java
  48. 7 8
      blade-service/blade-business/src/main/java/org/springblade/business/service/impl/TaskServiceImpl.java
  49. 21 8
      blade-service/blade-business/src/main/java/org/springblade/business/service/impl/TrialSelfInspectionRecordServiceImpl.java
  50. 29 19
      blade-service/blade-business/src/main/java/org/springblade/business/service/impl/WeatherInfoServiceImpl.java
  51. 169 0
      blade-service/blade-e-visa/src/main/java/org/springblade/evisa/controller/ArchiveController.java
  52. 1 1
      blade-service/blade-e-visa/src/main/java/org/springblade/evisa/controller/Chek.java
  53. 1 1
      blade-service/blade-e-visa/src/main/java/org/springblade/evisa/controller/EVController.java
  54. 0 1
      blade-service/blade-e-visa/src/main/java/org/springblade/evisa/service/impl/EVisaServiceImpl.java
  55. 0 2
      blade-service/blade-e-visa/src/main/java/org/springblade/evisa/utils/PDFUtils.java
  56. 2 2
      blade-service/blade-manager/pom.xml
  57. 1 1
      blade-service/blade-manager/src/main/java/org/springblade/manager/controller/ArchiveTreeContractController.java
  58. 38 4
      blade-service/blade-manager/src/main/java/org/springblade/manager/controller/ArchiveTreeController.java
  59. 10 98
      blade-service/blade-manager/src/main/java/org/springblade/manager/controller/ExcelTabController.java
  60. 677 0
      blade-service/blade-manager/src/main/java/org/springblade/manager/controller/HtmlTableToExcelConverter.java
  61. 25 136
      blade-service/blade-manager/src/main/java/org/springblade/manager/controller/WbsTreeContractController.java
  62. 28 10
      blade-service/blade-manager/src/main/java/org/springblade/manager/controller/WbsTreePrivateController.java
  63. 30 9
      blade-service/blade-manager/src/main/java/org/springblade/manager/feign/ExcelTabClientImpl.java
  64. 17 1
      blade-service/blade-manager/src/main/java/org/springblade/manager/feign/FormulaClientImpl.java
  65. 6 0
      blade-service/blade-manager/src/main/java/org/springblade/manager/feign/WbsParamClientImpl.java
  66. 3 0
      blade-service/blade-manager/src/main/java/org/springblade/manager/formula/impl/ExecutorMeter.java
  67. 6 2
      blade-service/blade-manager/src/main/java/org/springblade/manager/mapper/ArchiveTreeContractMapper.xml
  68. 2 0
      blade-service/blade-manager/src/main/java/org/springblade/manager/mapper/ArchiveTreeMapper.java
  69. 36 0
      blade-service/blade-manager/src/main/java/org/springblade/manager/mapper/ArchiveTreeMapper.xml
  70. 16 0
      blade-service/blade-manager/src/main/java/org/springblade/manager/mapper/WbsFormElementMapper.java
  71. 6 0
      blade-service/blade-manager/src/main/java/org/springblade/manager/mapper/WbsFormElementMapper.xml
  72. 1 1
      blade-service/blade-manager/src/main/java/org/springblade/manager/mapper/WbsTreeContractMapper.xml
  73. 1 1
      blade-service/blade-manager/src/main/java/org/springblade/manager/service/IArchiveTreeContractService.java
  74. 4 0
      blade-service/blade-manager/src/main/java/org/springblade/manager/service/IArchiveTreeService.java
  75. 1 1
      blade-service/blade-manager/src/main/java/org/springblade/manager/service/IExcelTabService.java
  76. 8 6
      blade-service/blade-manager/src/main/java/org/springblade/manager/service/impl/ArTreeContractInitServiceImpl.java
  77. 2 2
      blade-service/blade-manager/src/main/java/org/springblade/manager/service/impl/ArchiveAutoRuleSyncImpl.java
  78. 68 13
      blade-service/blade-manager/src/main/java/org/springblade/manager/service/impl/ArchiveTreeContractServiceImpl.java
  79. 288 8
      blade-service/blade-manager/src/main/java/org/springblade/manager/service/impl/ArchiveTreeServiceImpl.java
  80. 4 18
      blade-service/blade-manager/src/main/java/org/springblade/manager/service/impl/ContractInfoServiceImpl.java
  81. 71 49
      blade-service/blade-manager/src/main/java/org/springblade/manager/service/impl/ExcelTabServiceImpl.java
  82. 30 6
      blade-service/blade-manager/src/main/java/org/springblade/manager/service/impl/FormulaServiceImpl.java
  83. 74 23
      blade-service/blade-manager/src/main/java/org/springblade/manager/service/impl/WbsFormElementServiceImpl.java
  84. 10 6
      blade-service/blade-manager/src/main/java/org/springblade/manager/service/impl/WbsTreeContractServiceImpl.java
  85. 1 1
      blade-service/blade-manager/src/main/java/org/springblade/manager/service/impl/WbsTreePrivateServiceImpl.java
  86. 0 30
      blade-service/blade-manager/src/main/java/org/springblade/manager/utils/ExcelInfoUtils2.java
  87. 2 2
      blade-service/blade-manager/src/main/java/org/springblade/manager/utils/FormEndPayUtil.java
  88. 1 1
      blade-service/blade-manager/src/main/java/org/springblade/manager/utils/PdfAddContextUtils.java
  89. 3 3
      blade-service/blade-manager/src/main/java/org/springblade/manager/utils/WbsElementUtil.java
  90. 19 7
      blade-service/blade-meter/src/main/java/org/springblade/meter/controller/TaskController.java
  91. 8 0
      blade-service/blade-meter/src/main/java/org/springblade/meter/mapper/ChangeTokenFormMapper.java
  92. 29 2
      blade-service/blade-meter/src/main/java/org/springblade/meter/mapper/ChangeTokenFormMapper.xml
  93. 2 0
      blade-service/blade-meter/src/main/java/org/springblade/meter/mapper/ChangeTokenInventoryMapper.java
  94. 3 0
      blade-service/blade-meter/src/main/java/org/springblade/meter/mapper/ChangeTokenInventoryMapper.xml
  95. 2 0
      blade-service/blade-meter/src/main/java/org/springblade/meter/mapper/InventoryFormMeterMapper.java
  96. 4 0
      blade-service/blade-meter/src/main/java/org/springblade/meter/mapper/InventoryFormMeterMapper.xml
  97. 1 0
      blade-service/blade-meter/src/main/java/org/springblade/meter/service/IChangeTokenInventoryService.java
  98. 3 0
      blade-service/blade-meter/src/main/java/org/springblade/meter/service/IInventoryFormMeterService.java
  99. 91 37
      blade-service/blade-meter/src/main/java/org/springblade/meter/service/impl/ChangeTokenFormServiceImpl.java
  100. 5 0
      blade-service/blade-meter/src/main/java/org/springblade/meter/service/impl/ChangeTokenInventoryServiceImpl.java

+ 10 - 0
blade-common/pom.xml

@@ -28,6 +28,16 @@
             <artifactId>blade-core-auto</artifactId>
             <scope>provided</scope>
         </dependency>
+        <dependency>
+            <groupId>com.twelvemonkeys.imageio</groupId>
+            <artifactId>imageio-jpeg</artifactId>
+            <version>3.9.4</version>
+        </dependency>
+        <dependency>
+            <groupId>net.coobird</groupId>
+            <artifactId>thumbnailator</artifactId>
+            <version>0.4.14</version>
+        </dependency>
         <dependency>
             <groupId>com.alibaba</groupId>
             <artifactId>fastjson</artifactId>

+ 5 - 1
blade-common/src/main/java/org/springblade/common/constant/LauncherConstant.java

@@ -77,12 +77,16 @@ public interface LauncherConstant {
      */
     String APPLICATION_XXLJOB_ADMIN_NAME = APPLICATION_NAME_PREFIX + "xxljob-admin";
 
+
+    String  APPLICATION_REPAIR_NAME = APPLICATION_NAME_PREFIX + "repair";
+
+
     /**
      * nacos dev 地址 215==172.31.222.127   192.168.0.109     127.0.0.1  210-=-172.30.224.81
      * nacos dev 地址 172.31.222.127   192.168.0.109     127.0.0.1    172.30.224.81(39.108.216.210) 152.168.2.11
      */
     //更107服务器时打包的时候要改成192.168.0.109
-    //127.0.0.1
+    // 73用这个 127.0.0.1    113要用这个 10.0.0.6
     String NACOS_DEV_ADDR = "127.0.0.1:8848";
 
     /**

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

@@ -15,7 +15,7 @@ public class AsyncConfigurer {
     /**
      * cpu 核心数量
      */
-    public static final int cpuNum = 5 ;//Runtime.getRuntime().availableProcessors();
+    public static final int cpuNum = 3 ;//Runtime.getRuntime().availableProcessors();
 
     /**
      * 线程池配置

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

@@ -18,7 +18,6 @@ import org.apache.commons.imaging.Imaging;
 import org.apache.commons.lang.StringUtils;
 import org.springframework.util.CollectionUtils;
 
-import javax.imageio.*;
 import java.awt.*;
 import java.awt.color.ColorSpace;
 import java.awt.color.ICC_ColorSpace;
@@ -40,9 +39,13 @@ import java.util.zip.ZipEntry;
 import java.util.zip.ZipOutputStream;
 
 import com.drew.metadata.MetadataException;
-import org.springframework.util.ResourceUtils;
-import org.springframework.web.util.UriUtils;
 
+import javax.imageio.IIOImage;
+import javax.imageio.ImageIO;
+import javax.imageio.ImageWriteParam;
+import javax.imageio.ImageWriter;
+
+import net.coobird.thumbnailator.Thumbnails;
 /**
  * 通用工具类
  *
@@ -140,7 +143,7 @@ public class CommonUtil {
     /**
      * 根据OSS文件路径获取文件输入流
      */
-    public static  InputStream getOSSInputStream(String urlStr) {
+    public static InputStream getOSSInputStream(String urlStr) {
         try {
             System.out.println("----前-------"+urlStr);
             urlStr = replaceOssUrl(urlStr);
@@ -183,7 +186,7 @@ public class CommonUtil {
     /**
      * 获取字节数组
      */
-    public static  byte[] InputStreamToBytes(InputStream is) {
+    public static synchronized byte[] InputStreamToBytes(InputStream is) {
         BufferedInputStream bis = new BufferedInputStream(is);
         ByteArrayOutputStream os = new ByteArrayOutputStream();
         int date = -1;
@@ -580,93 +583,104 @@ public class CommonUtil {
         System.out.println("图片转换并保存成功!");
     }*/
 
-    public static byte[] compressImage(String url) throws IOException, ImageProcessingException, MetadataException{
+    public static byte[] compressImage(String url) {
         // 读取原始图像(处理旋转问题)
         InputStream file = CommonUtil.getOSSInputStream(url);
         InputStream file2 = CommonUtil.getOSSInputStream(url);
+        InputStream file3 = CommonUtil.getOSSInputStream(url);
         byte[] imageData = InputStreamToBytes(file);
-
-        Metadata metadata = ImageMetadataReader.readMetadata(new ByteArrayInputStream(imageData));
-        if (metadata.containsDirectoryOfType(ExifIFD0Directory.class)) {
-            ExifIFD0Directory exifIFD0Directory = metadata.getFirstDirectoryOfType(ExifIFD0Directory.class);
-            if (exifIFD0Directory.containsTag(ExifIFD0Directory.TAG_ORIENTATION)) {
-                // 获取 Orientation 标签的值
-                int orientation = exifIFD0Directory.getInt(ExifIFD0Directory.TAG_ORIENTATION);
-                // 需要旋转图片
-                // 1 无需纠正 2 水平翻转(镜像)3 垂直翻转(旋转180°) 4 水平翻转+垂直翻转 5 水平翻转+旋转90°
-                // 6 旋转90° 7 水平翻转+旋转270° 8 +旋转270°
-                if (orientation > 1) {
-                    BufferedImage originalImage = ImageIO.read(new ByteArrayInputStream(imageData));
-                    AffineTransform transform = new AffineTransform();
-                    if (orientation == 3) {
-                        transform.rotate(Math.PI, originalImage.getWidth() / 2, originalImage.getHeight() / 2);
-                    } else if (orientation == 6) {
-                        transform.rotate(Math.PI / 2, originalImage.getWidth() / 2, originalImage.getHeight() / 2);
-                    } else if (orientation == 8) {
-                        transform.rotate(-Math.PI / 2, originalImage.getWidth() / 2, originalImage.getHeight() / 2);
+        long sizeLimit = 1024 * 1024 * 5; //5M 1920 ×1080
+        if (imageData.length <= sizeLimit) {
+            return imageData;
+        }
+        try {
+            Metadata metadata = ImageMetadataReader.readMetadata(new ByteArrayInputStream(imageData));
+            if (metadata.containsDirectoryOfType(ExifIFD0Directory.class)) {
+                ExifIFD0Directory exifIFD0Directory = metadata.getFirstDirectoryOfType(ExifIFD0Directory.class);
+                if (exifIFD0Directory.containsTag(ExifIFD0Directory.TAG_ORIENTATION)) {
+                    // 获取 Orientation 标签的值
+                    int orientation = exifIFD0Directory.getInt(ExifIFD0Directory.TAG_ORIENTATION);
+                    // 需要旋转图片
+                    // 1 无需纠正 2 水平翻转(镜像)3 垂直翻转(旋转180°) 4 水平翻转+垂直翻转 5 水平翻转+旋转90°
+                    // 6 旋转90° 7 水平翻转+旋转270° 8 +旋转270°
+                    if (orientation > 1) {
+                        ImageIO.scanForPlugins();
+                        BufferedImage originalImage = Imaging.getBufferedImage(file2);
+                        AffineTransform transform = new AffineTransform();
+                        if (orientation == 3) {
+                            transform.rotate(Math.PI, originalImage.getWidth() / 2, originalImage.getHeight() / 2);
+                        } else if (orientation == 6) {
+                            transform.rotate(Math.PI / 2, originalImage.getWidth() / 2, originalImage.getHeight() / 2);
+                        } else if (orientation == 8) {
+                            transform.rotate(-Math.PI / 2, originalImage.getWidth() / 2, originalImage.getHeight() / 2);
+                        }
+                        AffineTransformOp op = new AffineTransformOp(transform, AffineTransformOp.TYPE_BILINEAR);
+                        originalImage = op.filter(originalImage, null);
+                        ByteArrayOutputStream baos = new ByteArrayOutputStream();
+                        ImageIO.write(originalImage, "jpg", baos);
+                        imageData = baos.toByteArray();
                     }
-                    AffineTransformOp op = new AffineTransformOp(transform, AffineTransformOp.TYPE_BILINEAR);
-                    originalImage = op.filter(originalImage, null);
-                    ByteArrayOutputStream baos = new ByteArrayOutputStream();
-                    ImageIO.write(originalImage, "jpg", baos);
-                    imageData = baos.toByteArray();
                 }
             }
-        }
 
-        // 缩放图像
-        String formatName = "JPEG";
-        ByteArrayInputStream bais = new ByteArrayInputStream(imageData);
-        BufferedImage   originalImage =ImageIO.read(file2);
+            // 缩放图像
+            String formatName = "JPEG";
+            ByteArrayInputStream bais = new ByteArrayInputStream(imageData);
+            String[] formats = ImageIO.getReaderFormatNames();
+            System.out.println("----支持的格式-----: " + Arrays.toString(formats));
+            // BufferedImage originalImage = ImageIO.read(file2);
+            BufferedImage originalImage = Imaging.getBufferedImage(imageData); //.getBufferedImage(file3);
+
+            int width = 1080;
+            int height = 1920;
+            Image scaledImage = originalImage.getScaledInstance(width, height, Image.SCALE_SMOOTH);
+            BufferedImage resizedImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
+            resizedImage.getGraphics().drawImage(scaledImage, 0, 0, null);
 
-        long sizeLimit = 1024*1024*5; //5M 1920 ×1080
-        int width = 1080;
-        int height = 1920;
-        Image scaledImage = originalImage.getScaledInstance(width, height, Image.SCALE_SMOOTH);
-        BufferedImage resizedImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
-        resizedImage.getGraphics().drawImage(scaledImage, 0, 0, null);
+            // 压缩图像
+            ByteArrayOutputStream baos = new ByteArrayOutputStream();
+            ImageIO.write(resizedImage, formatName, baos);
 
-        // 压缩图像
-        ByteArrayOutputStream baos = new ByteArrayOutputStream();
-        ImageIO.write(resizedImage, formatName, baos);
+            if (baos.size() <= sizeLimit) {
+                // 图片大小已经小于等于目标大小,直接返回原始数据
+                return baos.toByteArray();
+            }
 
-        if (baos.size() <= sizeLimit) {
-            // 图片大小已经小于等于目标大小,直接返回原始数据
-            return baos.toByteArray();
-        }
+            float quality = 0.9f; // 初始化压缩质量
+            int retries = 10; // 最多尝试 10 次
 
-        float quality = 0.9f; // 初始化压缩质量
-        int retries = 10; // 最多尝试 10 次
+            while (baos.size() > sizeLimit && retries > 0) {
+                // 压缩图像并重新计算压缩质量
+                byte[] data = baos.toByteArray();
+                bais = new ByteArrayInputStream(data);
+                BufferedImage compressedImage = ImageIO.read(bais);
+                baos.reset();
 
-        while (baos.size() > sizeLimit && retries > 0) {
-            // 压缩图像并重新计算压缩质量
-            byte[] data = baos.toByteArray();
-            bais = new ByteArrayInputStream(data);
-            BufferedImage compressedImage = ImageIO.read(bais);
-            baos.reset();
+                ImageWriter writer = null;
+                Iterator<ImageWriter> writers = ImageIO.getImageWritersByFormatName(formatName);
+                if (writers.hasNext()) {
+                    writer = writers.next();
+                } else {
+                    throw new IllegalArgumentException("Unsupported image format: " + formatName);
+                }
 
-            ImageWriter writer = null;
-            Iterator<ImageWriter> writers = ImageIO.getImageWritersByFormatName(formatName);
-            if (writers.hasNext()) {
-                writer = writers.next();
-            } else {
-                throw new IllegalArgumentException("Unsupported image format: " + formatName);
-            }
+                ImageWriteParam writeParam = writer.getDefaultWriteParam();
+                writeParam.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
+                writeParam.setCompressionQuality(1);
 
-            ImageWriteParam writeParam = writer.getDefaultWriteParam();
-            writeParam.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
-            writeParam.setCompressionQuality(1);
+                writer.setOutput(ImageIO.createImageOutputStream(baos));
+                writer.write(null, new IIOImage(compressedImage, null, null), writeParam);
+                writer.dispose();
 
-            writer.setOutput(ImageIO.createImageOutputStream(baos));
-            writer.write(null, new IIOImage(compressedImage, null, null), writeParam);
-            writer.dispose();
+                float ratio = sizeLimit * 1.0f / baos.size();
+                quality *= Math.sqrt(ratio);
+                retries--;
+            }
 
-            float ratio = sizeLimit * 1.0f / baos.size();
-            quality *= Math.sqrt(ratio);
-            retries--;
+            return baos.toByteArray();
+        } catch (Exception e) {
+            return imageData;
         }
-
-        return baos.toByteArray();
     }
 
     public static byte[] compressImage(byte[] imageData) throws IOException, ImageProcessingException, MetadataException{
@@ -706,7 +720,7 @@ public class CommonUtil {
         try {
             originalImage = Imaging.getBufferedImage(imageData);
         } catch (ImageReadException e) {
-
+            e.printStackTrace();
         }
 
         long sizeLimit = 1024*1024*5; //5M 1920 ×1080
@@ -840,6 +854,82 @@ public class CommonUtil {
         return baos.toByteArray();
     }
 
+    public static byte[] compressImage3(String url) throws IOException, ImageProcessingException, MetadataException {
+        try(InputStream file = CommonUtil.getOSSInputStream(url)) {
+            byte[] imageData = InputStreamToBytes(file);
+            return compressImage3(imageData);
+        }
+    }
+
+    public static byte[] compressImage3(byte[] imageData) throws ImageProcessingException, IOException, MetadataException {
+        // 读取原始图像(处理旋转问题)
+        int orientation = 1;
+        Metadata metadata = ImageMetadataReader.readMetadata(new ByteArrayInputStream(imageData));
+        if (metadata.containsDirectoryOfType(ExifIFD0Directory.class)) {
+            ExifIFD0Directory exifIFD0Directory = metadata.getFirstDirectoryOfType(ExifIFD0Directory.class);
+            if (exifIFD0Directory.containsTag(ExifIFD0Directory.TAG_ORIENTATION)) {
+                // 获取 Orientation 标签的值
+                orientation = exifIFD0Directory.getInt(ExifIFD0Directory.TAG_ORIENTATION);
+            }
+        }
+        // 缩放图像
+        String formatName = "JPEG";
+        ByteArrayOutputStream baos = new ByteArrayOutputStream();
+        long sizeLimit = 1024*1024*5; //5M 1920 ×1080
+        int width = 1080;
+        int height = 1920;
+        // 需要旋转图片
+        // 1 无需纠正 2 水平翻转(镜像)3 垂直翻转(旋转180°) 4 水平翻转+垂直翻转 5 水平翻转+旋转90°
+        // 6 旋转90° 7 水平翻转+旋转270° 8 +旋转270°
+        float quality = 0.99f; // 初始化压缩质量
+        int retries = 10; // 最多尝试 10 次
+        double rotate = 0;
+        if (orientation > 1) {
+            if (orientation == 3) {
+                rotate = 180;
+            } else if (orientation == 6) {
+                rotate = 90;
+            } else if (orientation == 8) {
+                rotate = 270;
+            }
+        }
+        rotateAndScaleImageByThumbnails(new ByteArrayInputStream(imageData),baos, rotate, formatName, quality, width, height, true);
+        if (baos.size() <= sizeLimit) {
+            // 图片大小已经小于等于目标大小,直接返回原始数据
+            return baos.toByteArray();
+        }
+        ByteArrayInputStream bais;
+        while (baos.size() > sizeLimit && retries > 0) {
+            // 压缩图像并重新计算压缩质量
+            byte[] data = baos.toByteArray();
+            bais = new ByteArrayInputStream(data);
+            rotateAndScaleImageByThumbnails(bais,baos, 0, formatName, quality, width, height, true);
+            float ratio = sizeLimit * 1.0f / baos.size();
+            quality *= Math.sqrt(ratio);
+            retries--;
+        }
+        return baos.toByteArray();
+    }
+
+    /**
+     * @param is URL InputStream File BufferedImage path
+     * @param os 输出流
+     * @param rotate 旋转角度(正数顺时针,负数逆时针)
+     * @param format 输出格式,jpg,jpeg,png等
+     * @param quality  输出质量(0.0-1.0)
+     * @param width 宽
+     * @param height 高
+     * @param keepAspectRatio 是否保持原比例
+     */
+    public static void rotateAndScaleImageByThumbnails(InputStream is, OutputStream os, double rotate, String format, double quality, int width, int height, boolean keepAspectRatio) throws IOException {
+        Thumbnails.of(is)
+                .size(width, height)
+                .keepAspectRatio(keepAspectRatio)
+                .rotate(rotate)
+                .outputFormat(format)
+                .outputQuality(quality)
+                .toOutputStream(os);
+    }
 
     /**
      * 根据起止日期获取工作日
@@ -919,4 +1009,4 @@ public class CommonUtil {
         //保留两位小数
         return Math.round(px * cmPerPixel * 100) / 100.0;
     }
-}
+}

+ 10 - 0
blade-common/src/main/java/org/springblade/common/utils/ForestNodeManagerEx.java

@@ -35,4 +35,14 @@ public class ForestNodeManagerEx<T extends INodeEx<T>> {
         });
         return roots;
     }
+    public List<T> getStartRoot() {
+        List<T> roots = new ArrayList();
+        this.nodeMap.forEach((key, node) -> {
+            if ((node.getParentId() != null && node.getParentId() == 0L)) {
+                roots.add(node);
+            }
+
+        });
+        return roots;
+    }
 }

+ 21 - 0
blade-common/src/main/java/org/springblade/common/utils/ForestNodeMergerEx.java

@@ -33,6 +33,27 @@ public class ForestNodeMergerEx {
 
         return forestNodeManager.getRoot();
     }
+    public static <T extends INodeEx<T>> List<T> mergeRoot(List<T> items) {
+
+        for (T item : items) {
+            item.clearChildren();
+        }
+
+        ForestNodeManagerEx<T> forestNodeManager = new ForestNodeManagerEx(items);
+        items.forEach((forestNode) -> {
+            if (forestNode.getParentId() != null && forestNode.getParentId() != 0L) {
+                INodeEx<T> node = forestNodeManager.getTreeNodeAt(forestNode.getParentId());
+                if (node != null) {
+                    node.getChildren().add(forestNode);
+                } else {
+                    forestNodeManager.addParentId(forestNode.getId());
+                }
+            }
+
+        });
+
+        return forestNodeManager.getStartRoot();
+    }
 
     public static <T extends INodeEx<T>> List<T> mergeOnlyRoot(List<T> items) {
 

+ 35 - 21
blade-common/src/main/java/org/springblade/common/utils/YiKeYunApiUtils.java

@@ -7,6 +7,7 @@ import lombok.extern.slf4j.Slf4j;
 import java.io.BufferedReader;
 import java.io.IOException;
 import java.io.InputStreamReader;
+import java.net.ConnectException;
 import java.net.URL;
 import java.nio.charset.StandardCharsets;
 import java.util.HashMap;
@@ -17,6 +18,24 @@ public class YiKeYunApiUtils {
     private static final String API_YIKEYUN_APPID = "97543277";
     private static final String API_YIKEYUN_APPSECRET = "PXd7GE2j";
 
+    public static Map<String, String> getTodayWeatherByAdcodeTry(String adcode) {
+        for (int i = 0; i < 3; i++) {
+            try {
+                return getTodayWeatherByAdcode(adcode);
+            } catch (IOException e) {
+                // 重试
+                try {
+                    Thread.sleep(500);
+                } catch (InterruptedException ex) {
+                    e.printStackTrace();
+                }
+            } catch (Exception e) {
+                e.printStackTrace();
+                return null;
+            }
+        }
+        return null;
+    }
 
 
     /**
@@ -25,29 +44,24 @@ public class YiKeYunApiUtils {
      * @param adcode
      * @return
      */
-    public static Map<String, String> getTodayWeatherByAdcode(String adcode) {
+    public static Map<String, String> getTodayWeatherByAdcode(String adcode) throws IOException {
         String getUrl = String.format("http://v1.yiketianqi.com/free/day?appid=%s&appsecret=%s&unescape=1&adcode=%s", API_YIKEYUN_APPID, API_YIKEYUN_APPSECRET, adcode);
         Map<String, String> map = new HashMap<>();
-        try {
-            URL url = new URL(getUrl);
-            BufferedReader in = new BufferedReader(new InputStreamReader(url.openStream(), StandardCharsets.UTF_8));
-            String res;
-            StringBuilder sb = new StringBuilder();
-            while ((res = in.readLine()) != null) {
-                sb.append(res.trim());
-            }
-            log.info("获取当天天气 ======= sb.toString():" + sb);
-            JSONObject jsonData = JSONObject.parseObject(sb.toString());
-            map.put("temp", jsonData.get("tem").toString());
-            map.put("weather", jsonData.get("wea").toString());
-            map.put("high", jsonData.get("tem_day").toString());
-            map.put("low", jsonData.get("tem_night").toString());
-            map.put("windLevel", jsonData.get("win_speed").toString());
-            map.put("nums", jsonData.getInteger("nums").toString());
-        } catch (IOException e) {
-            e.printStackTrace();
-            return null;
+        URL url = new URL(getUrl);
+        BufferedReader in = new BufferedReader(new InputStreamReader(url.openStream(), StandardCharsets.UTF_8));
+        String res;
+        StringBuilder sb = new StringBuilder();
+        while ((res = in.readLine()) != null) {
+            sb.append(res.trim());
         }
+        log.info("获取当天天气 ======= sb.toString():" + sb);
+        JSONObject jsonData = JSONObject.parseObject(sb.toString());
+        map.put("temp", jsonData.get("tem").toString());
+        map.put("weather", jsonData.get("wea").toString());
+        map.put("high", jsonData.get("tem_day").toString());
+        map.put("low", jsonData.get("tem_night").toString());
+        map.put("windLevel", jsonData.get("win_speed").toString());
+        map.put("nums", jsonData.getInteger("nums").toString());
         return map;
     }
 
@@ -119,7 +133,7 @@ public class YiKeYunApiUtils {
             });
 
 
-        } catch (IOException e) {
+        } catch (Exception e) {
             e.printStackTrace();
             return null;
         }

+ 5 - 2
blade-ops/blade-resource/src/main/java/org/springblade/resource/endpoint/SmsEndpoint.java

@@ -19,6 +19,7 @@ package org.springblade.resource.endpoint;
 import io.swagger.annotations.Api;
 import lombok.AllArgsConstructor;
 import lombok.SneakyThrows;
+import org.springblade.core.secure.BladeUser;
 import org.springblade.core.sms.model.SmsCode;
 import org.springblade.core.sms.model.SmsData;
 import org.springblade.core.sms.model.SmsResponse;
@@ -91,8 +92,10 @@ public class SmsEndpoint {
      */
     @SneakyThrows
     @PostMapping("/send-message")
-    public R sendMessage(@RequestParam String code, @RequestParam String params, @RequestParam String phones) {
-        SmsData smsData = new SmsData(JsonUtil.readMap(params, String.class, String.class));
+    public R sendMessage(BladeUser user, @RequestParam String code, @RequestParam String params, @RequestParam String phones) {
+        Map<String, String> paramss = JsonUtil.readMap(params, String.class, String.class);
+        //paramss.put("name",user.getNickName());
+        SmsData smsData = new SmsData(paramss);
         return send(code, smsData, phones);
     }
 

+ 34 - 0
blade-service-api/blade-archive-api/src/main/java/org/springblade/archive/dto/TaskSplitDTO.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.archive.dto;
+
+import org.springblade.archive.entity.TaskSplit;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+/**
+ * 解析主标任务数据传输对象实体类
+ *
+ * @author BladeX
+ * @since 2025-05-23
+ */
+@Data
+@EqualsAndHashCode(callSuper = true)
+public class TaskSplitDTO extends TaskSplit {
+	private static final long serialVersionUID = 1L;
+
+}

+ 4 - 1
blade-service-api/blade-archive-api/src/main/java/org/springblade/archive/entity/ArchivesAuto.java

@@ -32,7 +32,7 @@ import lombok.EqualsAndHashCode;
 import org.springframework.beans.BeanUtils;
 
 /**
- * 实体类
+ * 案卷主题信息
  *
  * @author BladeX
  * @since 2023-02-17
@@ -183,6 +183,9 @@ public class ArchivesAuto extends BaseEntity {
     @ApiModelProperty("是否抽检,0未抽检1已抽检")
     private Integer isInspect;
 
+    @ApiModelProperty("是否解析,其他=未解析 1=已解析")
+    private Integer splitStatus;
+
     //是否是影音
     public boolean isMedia() {
         return (this.getCarrierType() != null &&

+ 73 - 0
blade-service-api/blade-archive-api/src/main/java/org/springblade/archive/entity/TaskSplit.java

@@ -0,0 +1,73 @@
+/*
+ *      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.archive.entity;
+
+import com.baomidou.mybatisplus.annotation.TableName;
+import java.io.Serializable;
+
+import io.swagger.annotations.ApiModelProperty;
+import org.springblade.core.mp.base.BaseEntity;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+/**
+ * 解析主标任务实体类
+ *
+ * @author BladeX
+ * @since 2025-05-23
+ */
+@Data
+@TableName("u_task_split")
+@EqualsAndHashCode(callSuper = true)
+public class TaskSplit extends BaseEntity {
+
+	private static final long serialVersionUID = 1L;
+
+	/**
+	* 项目ID
+	*/
+	@ApiModelProperty("项目ID")
+		private String projectId;
+	/**
+	* 合同段ID
+	*/
+	@ApiModelProperty("合同段ID")
+		private String contractId;
+	/**
+	* 解析id字符串
+	*/
+
+	@ApiModelProperty("解析id字符串")
+		private String ids;
+	/**
+	* 类型 1:项目 2:合同段 3:id解析
+	*/
+	@ApiModelProperty("1:项目 2:合同段 3:id解析")
+		private Integer type;
+	/**
+	* 总条数
+	*/
+	@ApiModelProperty("总条数")
+		private Integer toolCount;
+	/**
+	* 完成数量
+	*/
+	@ApiModelProperty("完成数量")
+		private Integer finished;
+
+
+}

+ 34 - 0
blade-service-api/blade-archive-api/src/main/java/org/springblade/archive/vo/TaskSplitVO.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.archive.vo;
+
+import org.springblade.archive.entity.TaskSplit;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+/**
+ * 解析主标任务视图实体类
+ *
+ * @author BladeX
+ * @since 2025-05-23
+ */
+@Data
+@EqualsAndHashCode(callSuper = true)
+public class TaskSplitVO extends TaskSplit {
+	private static final long serialVersionUID = 1L;
+
+}

+ 1 - 0
blade-service-api/blade-business-api/src/main/java/org/springblade/business/dto/TrialFileSubmitDTO.java

@@ -1,6 +1,7 @@
 package org.springblade.business.dto;
 
 import io.swagger.annotations.ApiModelProperty;
+import io.swagger.models.auth.In;
 import lombok.Data;
 
 import java.io.Serializable;

+ 1 - 1
blade-service-api/blade-business-api/src/main/java/org/springblade/business/feign/ContractLogClient.java

@@ -38,7 +38,7 @@ public interface ContractLogClient {
     JSONObject queryContractLogByPrimaryKeyIdAndRecordTime(@RequestParam String nodePrimaryKeyId, @RequestParam String recordTime, @RequestParam String contractId);
 
     @GetMapping(API_PREFIX + "/queryContractLogByPrimaryKeyIdAndRecordTimeList")
-    List<ContractLog> queryContractLogByPrimaryKeyIdAndRecordTimeList(@RequestParam String nodePrimaryKeyId, @RequestParam String recordTime, @RequestParam String contractId);
+    List<ContractLog> queryContractLogByPrimaryKeyIdAndRecordTimeList(@RequestParam String nodePrimaryKeyId, @RequestParam String recordTime, @RequestParam String contractId,@RequestParam(required = false) Long createUser);
 
     @GetMapping(API_PREFIX + "/queryContractLogByPrimaryKeyIdAndRecordTimeAndCreateUserList")
     List<ContractLog> queryContractLogByPrimaryKeyIdAndRecordTimeAndCreateUserList(@RequestParam String nodePrimaryKeyId, @RequestParam String recordTime, @RequestParam String contractId, @RequestParam Long createUser);

+ 18 - 0
blade-service-api/blade-e-visa-api/src/main/java/org/springblade/evisa/vo/TaskArchiveSplitVO.java

@@ -0,0 +1,18 @@
+package org.springblade.evisa.vo;
+
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+@Data
+public class TaskArchiveSplitVO {
+
+    @ApiModelProperty("id")
+    private String id;
+
+    @ApiModelProperty("archiveId")
+    private String archiveId;
+
+    @ApiModelProperty("fileUrl")
+    private String fileUrl;
+
+}

+ 4 - 0
blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/entity/ArchiveTree.java

@@ -185,6 +185,9 @@ public class ArchiveTree extends BaseEntity {
     @ApiModelProperty(value = "试验资料类型(归档树)对应字典试验节点类型,数字逗号拼接")
     private String contractTrialType;
 
+    @ApiModelProperty(value = "保存期限")
+    private String storageTime;
+
     public ArchiveTree() {
     }
 
@@ -237,5 +240,6 @@ public class ArchiveTree extends BaseEntity {
         this.archiveAutoGroupId = archiveTree.getArchiveAutoGroupId();
         this.archiveAutoGroupSelect = archiveTree.getArchiveAutoGroupSelect();
         this.isUploadFileDisplayConfigurationTree = archiveTree.getIsDisplayTree();
+        this.storageTime=archiveTree.getStorageTime();
     }
 }

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

@@ -325,6 +325,7 @@ public class ArchiveTreeContract extends BaseEntity {
         this.isUploadFileDisplayConfigurationTree = archiveTree.getIsUploadFileDisplayConfigurationTree();
         this.contractLogType = archiveTree.getContractLogType();
         this.contractTrialType = archiveTree.getContractTrialType();
+        this.storageTime=archiveTree.getStorageTime();
     }
 
     public void sync(ArchiveTreeVO2 archiveTree) {

+ 3 - 0
blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/entity/ContractInfo.java

@@ -178,6 +178,9 @@ public class ContractInfo extends BaseEntity {
     @ApiModelProperty(value = "模板引用 1.模版节点 2.底层节点")
     private Integer templateType;
 
+    @ApiModelProperty(value = "卷盒规格")
+    private String specification;
+
     public BigDecimal getProjectMileage() {
         if (projectMileage == null){
             return null;

+ 12 - 0
blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/entity/ProjectInfo.java

@@ -198,5 +198,17 @@ public class ProjectInfo extends BaseEntity {
     @ApiModelProperty(value = "模板引用 1.模版节点 2.底层节点")
     private Integer templateType;
 
+    /**
+     * 施工后缀
+     */
+    @ApiModelProperty(value = "施工后缀")
+    private String sgSuffix;
+
+    /**
+     * 监理前缀
+     */
+    @ApiModelProperty(value = "监理后缀")
+    private String jlSuffix;
+
 
 }

+ 8 - 2
blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/feign/ExcelTabClient.java

@@ -77,11 +77,17 @@ public interface ExcelTabClient {
     R getPdfS(@RequestParam String nodeId, @RequestParam String classify, @RequestParam String contractId) throws IOException;
 
     @PostMapping(API_PREFIX + "/saveOrUpdate")
-    void saveOrUpdate(@RequestBody ExcelTab detail);
+    boolean saveOrUpdate(@RequestBody ExcelTab detail);
 
     @PostMapping(API_PREFIX + "/expailHtmlInfo")
     void expailHtmlInfo(@RequestParam String thmlUrl, @RequestParam Long id, @RequestParam String s) throws Exception;
 
     @PostMapping(API_PREFIX + "/excelInfo")
-    void excelInfo(@RequestParam InputStream inputStream, @RequestParam String exceUrl, @RequestParam String thmlUrl, @RequestParam String number);
+    void excelInfo(@RequestPart("file") MultipartFile file, @RequestParam String exceUrl, @RequestParam String thmlUrl, @RequestParam String number) throws IOException;
+
+    @PostMapping(API_PREFIX + "/saveLinkTab")
+    void saveLinkTab(@RequestParam Long excelId,@RequestParam Long pKeyId) throws IOException;
+
+    @PostMapping(API_PREFIX + "/getTheLogPdInfo")
+    void getTheLogPdInfo(@RequestParam String logPkeyId,  @RequestParam String nodePrimaryKeyId, @RequestParam String recordTime, @RequestParam String contractId,@RequestParam Long createUser) throws Exception;
 }

+ 13 - 3
blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/feign/ExcelTabClientFallBack.java

@@ -77,8 +77,8 @@ public class ExcelTabClientFallBack implements ExcelTabClient {
     }
 
     @Override
-    public void saveOrUpdate(ExcelTab detail) {
-
+    public boolean saveOrUpdate(ExcelTab detail) {
+        return true;
     }
 
     @Override
@@ -87,7 +87,17 @@ public class ExcelTabClientFallBack implements ExcelTabClient {
     }
 
     @Override
-    public void excelInfo(InputStream inputStream, String exceUrl, String thmlUrl, String number) {
+    public void excelInfo(MultipartFile file, String exceUrl, String thmlUrl, String number) throws IOException {
+
+    }
+
+    @Override
+    public void saveLinkTab(Long excelId, Long pKeyId) throws IOException {
+
+    }
+
+    @Override
+    public void getTheLogPdInfo(String logPkeyId, String nodePrimaryKeyId, String recordTime, String contractId,Long createUser) throws Exception {
 
     }
 

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

@@ -2,6 +2,7 @@ package org.springblade.manager.feign;
 
 
 import org.springblade.manager.entity.WbsParam;
+import org.springblade.manager.entity.WbsTreeContract;
 import org.springframework.cloud.openfeign.FeignClient;
 import org.springframework.web.bind.annotation.GetMapping;
 import org.springframework.web.bind.annotation.PostMapping;
@@ -23,4 +24,6 @@ public interface WbsParamClient {
     @GetMapping(API_PREFIX + "/getWbsParam")
     WbsParam getWbsParam(@RequestParam Long nodeId);
 
+    @PostMapping(API_PREFIX + "/createFileTitle")
+    String createFileTitle(@RequestBody WbsTreeContract contract);
 }

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

@@ -182,6 +182,9 @@ public class ArchiveTreeVO2 implements INodeEx<ArchiveTreeVO2> {
     @ApiModelProperty(value = "排序")
     private Integer sort;
 
+    @ApiModelProperty(value = "保管期限")
+    private String storageTime;
+
     private String expDataType;
 
     /**
@@ -220,6 +223,7 @@ public class ArchiveTreeVO2 implements INodeEx<ArchiveTreeVO2> {
                 Objects.equals(this.archiveAutoNodeId, b.getArchiveAutoNodeId()) &&
                 Objects.equals(this.archiveAutoGroupId, b.getArchiveAutoGroupId()) &&
                 Objects.equals(this.archiveAutoGroupSelect, b.getArchiveAutoGroupSelect()) &&
+                Objects.equals(this.storageTime, b.getStorageTime()) &&
                 this.isDisplayTree == b.getIsDisplayTree();
     }
 
@@ -245,6 +249,7 @@ public class ArchiveTreeVO2 implements INodeEx<ArchiveTreeVO2> {
         this.archiveAutoGroupSelect = archiveTree.getArchiveAutoGroupSelect();
         this.isUploadFileDisplayConfigurationTree = archiveTree.getIsDisplayTree();
         this.isDisplayTree = archiveTree.getIsDisplayTree();
+        this.storageTime=archiveTree.getStorageTime();
         this.flag = 1;
     }
 

+ 107 - 0
blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/vo/ArchiveTreeVO3.java

@@ -0,0 +1,107 @@
+package org.springblade.manager.vo;
+
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.databind.annotation.JsonSerialize;
+import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import org.springblade.common.utils.INodeEx;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Objects;
+
+@Data
+public class ArchiveTreeVO3 implements INodeEx<ArchiveTreeVO3> {
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 主键ID
+     */
+    @JsonSerialize(using = ToStringSerializer.class)
+    @ApiModelProperty(value = "主键id")
+    private Long id;
+
+
+    /**
+     * 父节点ID
+     */
+    @JsonSerialize(using = ToStringSerializer.class)
+    @ApiModelProperty(value = "父级id")
+    private Long parentId;
+
+    /**
+     * title
+     */
+    @JsonSerialize(using = ToStringSerializer.class)
+    @ApiModelProperty(value = "节点名称")
+    private String title;
+
+    /**
+     * 子孙节点
+     */
+    @JsonInclude(JsonInclude.Include.NON_EMPTY)
+    @ApiModelProperty(value = "子孙节点")
+    private List<ArchiveTreeVO3> children;
+
+    /**
+     * 是否有子孙节点
+     */
+    @JsonInclude(JsonInclude.Include.NON_EMPTY)
+    @ApiModelProperty(value = "是否有子孙节点")
+    private Boolean hasChildren;
+
+    @Override
+    public List<ArchiveTreeVO3> getChildren() {
+        if (this.children == null) {
+            this.children = new ArrayList<>();
+        }
+        return this.children;
+    }
+
+    @Override
+    public void clearChildren() {
+        if (children != null) {
+            children.clear();
+        }
+    }
+
+    /**
+     * 显示层级(用于显示控制)
+     */
+    @ApiModelProperty(value = "显示层级(用于显示控制)")
+    private String displayHierarchy;
+
+
+    @JsonSerialize(
+            using = ToStringSerializer.class
+    )
+    private Long value;
+    /**
+     * 是否显示
+     */
+    private Integer isDisplayTree;
+
+
+
+    /**
+     * 关联类型
+     */
+    @ApiModelProperty(value = "关联类型")
+    private Integer associationType;
+
+    @ApiModelProperty(value = "排序")
+    private Integer sort;
+
+
+
+
+    /**
+     * 选中的节点集合
+     */
+    private List<String> selectAllNodes;
+    private String treeSort;
+
+    private String ancestors;
+
+}

+ 6 - 0
blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/vo/WbsTreeContractLazyVO.java

@@ -127,4 +127,10 @@ public class WbsTreeContractLazyVO implements Serializable {
     @ApiModelProperty(value = "WbsId")
     private Long WbsId;
 
+    @ApiModelProperty(value = "系统模板,后管项目级位置")
+    private String privateTemplate;
+
+    @ApiModelProperty(value = "关联后管节点ID")
+    private Long isTypePrivatePid;
+
 }

+ 5 - 0
blade-service-api/blade-meter-api/src/main/java/org/springblade/meter/dto/MeterApprovalDTO.java

@@ -5,6 +5,8 @@ import lombok.Data;
 
 import java.io.Serializable;
 import java.math.BigDecimal;
+import java.util.ArrayList;
+import java.util.List;
 
 @Data
 public class MeterApprovalDTO implements Serializable {
@@ -45,5 +47,8 @@ public class MeterApprovalDTO implements Serializable {
     @ApiModelProperty("施工单位送审金额")
     private BigDecimal submitApprovalMoney;
 
+    @ApiModelProperty("变更令批量上报ids")
+    private String ids;
+
 
 }

+ 135 - 0
blade-service/blade-archive/src/main/java/org/springblade/archive/controller/TaskSplitController.java

@@ -0,0 +1,135 @@
+/**
+ * Copyright (c) 2018-2028, Chill Zhuang 庄骞 (smallchill@163.com).
+ * <p>
+ * Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0;
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * <p>
+ * http://www.gnu.org/licenses/lgpl.html
+ * <p>
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.springblade.archive.controller;
+
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import io.swagger.annotations.ApiParam;
+import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
+import lombok.AllArgsConstructor;
+import javax.validation.Valid;
+
+import org.springblade.core.mp.support.Condition;
+import org.springblade.core.mp.support.Query;
+import org.springblade.core.tool.api.R;
+import org.springblade.core.tool.utils.Func;
+import org.springframework.web.bind.annotation.*;
+import org.springframework.web.bind.annotation.RequestParam;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import org.springblade.archive.entity.TaskSplit;
+import org.springblade.archive.vo.TaskSplitVO;
+import org.springblade.archive.service.ITaskSplitService;
+import org.springblade.core.boot.ctrl.BladeController;
+
+/**
+ * 解析主标任务 控制器
+ *
+ * @author BladeX
+ * @since 2025-05-23
+ */
+@RestController
+@AllArgsConstructor
+@RequestMapping("/tasksplit")
+@Api(value = "解析主标任务", tags = "解析主标任务接口")
+public class TaskSplitController extends BladeController {
+
+	private final ITaskSplitService taskSplitService;
+
+
+/*	*//**
+	 * 详情
+	 *//*
+	@GetMapping("/detail")
+	@ApiOperationSupport(order = 1)
+	@ApiOperation(value = "详情", notes = "传入taskSplit")
+	public R<TaskSplit> detail(TaskSplit taskSplit) {
+		TaskSplit detail = taskSplitService.getOne(Condition.getQueryWrapper(taskSplit));
+		return R.data(detail);
+	}
+
+	*//**
+	 * 分页 解析主标任务
+	 *//*
+	@GetMapping("/list")
+	@ApiOperationSupport(order = 2)
+	@ApiOperation(value = "分页", notes = "传入taskSplit")
+	public R<IPage<TaskSplit>> list(TaskSplit taskSplit, Query query) {
+		IPage<TaskSplit> pages = taskSplitService.page(Condition.getPage(query), Condition.getQueryWrapper(taskSplit));
+		return R.data(pages);
+	}*/
+
+	/**
+	 * 查询任务任务信息
+	 */
+	@GetMapping("/selectTaskSplit")
+	@ApiOperationSupport(order = 1)
+	@ApiOperation(value = "查询任务任务信息", notes = "传入taskSplit")
+	public R<IPage<TaskSplitVO>> page(TaskSplitVO taskSplit, Query query) {
+		IPage<TaskSplitVO> pages = taskSplitService.selectTaskSplitPage(Condition.getPage(query), taskSplit);
+		return R.data(pages);
+	}
+
+	/**
+	 * 新增 解析主标任务
+	 */
+	@PostMapping("/save")
+	@ApiOperationSupport(order = 2)
+	@ApiOperation(value = "新增", notes = "传入taskSplit")
+	public R save(@Valid @RequestBody TaskSplit taskSplit) {
+		return taskSplitService.saveTaskSplit(taskSplit);
+	}
+
+/*
+	*/
+/**
+	 * 修改 解析主标任务
+	 *//*
+
+	@PostMapping("/update")
+	@ApiOperationSupport(order = 5)
+	@ApiOperation(value = "修改", notes = "传入taskSplit")
+	public R update(@Valid @RequestBody TaskSplit taskSplit) {
+		return R.status(taskSplitService.updateById(taskSplit));
+	}
+
+	*/
+/**
+	 * 新增或修改 解析主标任务
+	 *//*
+
+	@PostMapping("/submit")
+	@ApiOperationSupport(order = 6)
+	@ApiOperation(value = "新增或修改", notes = "传入taskSplit")
+	public R submit(@Valid @RequestBody TaskSplit taskSplit) {
+		return R.status(taskSplitService.saveOrUpdate(taskSplit));
+	}
+
+	
+	*/
+/**
+	 * 删除 解析主标任务
+	 *//*
+
+	@PostMapping("/remove")
+	@ApiOperationSupport(order = 7)
+	@ApiOperation(value = "逻辑删除", notes = "传入ids")
+	public R remove(@ApiParam(value = "主键集合", required = true) @RequestParam String ids) {
+		return R.status(taskSplitService.deleteLogic(Func.toLongList(ids)));
+	}
+*/
+
+	
+}

+ 43 - 0
blade-service/blade-archive/src/main/java/org/springblade/archive/mapper/TaskSplitMapper.java

@@ -0,0 +1,43 @@
+/*
+ *      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.archive.mapper;
+
+import org.springblade.archive.entity.TaskSplit;
+import org.springblade.archive.vo.TaskSplitVO;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import java.util.List;
+
+/**
+ * 解析主标任务 Mapper 接口
+ *
+ * @author BladeX
+ * @since 2025-05-23
+ */
+public interface TaskSplitMapper extends BaseMapper<TaskSplit> {
+
+	/**
+	 * 自定义分页
+	 *
+	 * @param page
+	 * @param taskSplit
+	 * @return
+	 */
+	List<TaskSplitVO> selectTaskSplitPage(IPage page, TaskSplitVO taskSplit);
+
+	Integer getArchiveCount(String contractId);
+}

+ 32 - 0
blade-service/blade-archive/src/main/java/org/springblade/archive/mapper/TaskSplitMapper.xml

@@ -0,0 +1,32 @@
+<?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.archive.mapper.TaskSplitMapper">
+
+    <!-- 通用查询映射结果 -->
+    <resultMap id="taskSplitResultMap" type="org.springblade.archive.entity.TaskSplit">
+        <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="ids" property="ids"/>
+        <result column="type" property="type"/>
+        <result column="tool_count" property="toolCount"/>
+        <result column="finished" property="finished"/>
+    </resultMap>
+
+
+    <select id="selectTaskSplitPage" resultMap="taskSplitResultMap">
+        select * from u_task_split where is_deleted = 0
+    </select>
+
+    <select id="getArchiveCount" resultType="java.lang.Integer">
+        select count(1) from u_archives_auto where contract_id = #{contractId}
+    </select>
+
+</mapper>

+ 44 - 0
blade-service/blade-archive/src/main/java/org/springblade/archive/service/ITaskSplitService.java

@@ -0,0 +1,44 @@
+/*
+ *      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.archive.service;
+
+import org.springblade.archive.entity.TaskSplit;
+import org.springblade.archive.vo.TaskSplitVO;
+import org.springblade.core.mp.base.BaseService;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import org.springblade.core.tool.api.R;
+
+/**
+ * 解析主标任务 服务类
+ *
+ * @author BladeX
+ * @since 2025-05-23
+ */
+public interface ITaskSplitService extends BaseService<TaskSplit> {
+
+	/**
+	 * 自定义分页
+	 *
+	 * @param page
+	 * @param taskSplit
+	 * @return
+	 */
+	IPage<TaskSplitVO> selectTaskSplitPage(IPage<TaskSplitVO> page, TaskSplitVO taskSplit);
+
+	R saveTaskSplit(TaskSplit taskSplit);
+
+}

+ 78 - 0
blade-service/blade-archive/src/main/java/org/springblade/archive/service/impl/TaskSplitServiceImpl.java

@@ -0,0 +1,78 @@
+/*
+ *      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.archive.service.impl;
+
+import org.springblade.archive.entity.TaskSplit;
+import org.springblade.archive.mapper.ArchivesAutoMapper;
+import org.springblade.archive.vo.TaskSplitVO;
+import org.springblade.archive.mapper.TaskSplitMapper;
+import org.springblade.archive.service.ITaskSplitService;
+import org.springblade.core.mp.base.BaseService;
+import org.springblade.core.mp.base.BaseServiceImpl;
+import org.springblade.core.tool.api.R;
+import org.springblade.core.tool.utils.Func;
+import org.springframework.stereotype.Service;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+
+import javax.annotation.Resource;
+
+/**
+ * 解析主标任务 服务实现类
+ *
+ * @author BladeX
+ * @since 2025-05-23
+ */
+@Service
+public class TaskSplitServiceImpl extends BaseServiceImpl<TaskSplitMapper, TaskSplit> implements ITaskSplitService {
+
+	//  注入mapper
+	@Resource
+    ArchivesAutoMapper autoMapper;
+
+	@Override
+	public IPage<TaskSplitVO> selectTaskSplitPage(IPage<TaskSplitVO> page, TaskSplitVO taskSplit) {
+		return page.setRecords(baseMapper.selectTaskSplitPage(page, taskSplit));
+	}
+
+	@Override
+	public R saveTaskSplit(TaskSplit taskSplit) {
+		// 数据校验区
+		String contractId = taskSplit.getContractId();
+		String splitIds = taskSplit.getIds();
+		if (contractId=="" || contractId==null || contractId.length()==0 || Func.isEmpty(contractId)){
+			return R.fail("合同段Id为空");
+		}
+
+		if (splitIds=="" || splitIds==null || splitIds.length()==0 || Func.isEmpty(splitIds)){ // 代表整个合同解析
+			taskSplit.setType(2);
+			// 查询整个合同段下的所有文件
+			Integer archiveCount = baseMapper.getArchiveCount(contractId);
+			taskSplit.setToolCount(archiveCount);
+			taskSplit.setFinished(0);
+
+		}else{ // 指定文件解析
+			taskSplit.setType(3);
+			String[] split = splitIds.split(",");
+			taskSplit.setToolCount(split.length);
+			taskSplit.setFinished(0);
+		}
+
+		int insert = baseMapper.insert(taskSplit);
+		return R.success("dddd");
+	}
+
+}

+ 0 - 104
blade-service/blade-archive/src/main/java/org/springblade/archive/utils/SpeechRecognizerRESTfulDemo.java

@@ -1,104 +0,0 @@
-/*
-package org.springblade.archive.utils;
-
-import com.alibaba.fastjson.JSONPath;
-
-import java.io.File;
-import java.util.HashMap;
-public class SpeechRecognizerRESTfulDemo {
-    private String accessToken;
-    private String appkey;
-
-    public SpeechRecognizerRESTfulDemo(String appkey, String token) {
-        this.appkey = appkey;
-        this.accessToken = token;
-    }
-
-    public String process(File fileName, String format, int sampleRate,
-                          boolean enablePunctuationPrediction,
-                          boolean enableInverseTextNormalization,
-                          boolean enableVoiceDetection) {
-
-        */
-/**
- * 设置HTTPS RESTful POST请求:
- * 1.使用HTTPS协议。
- * 2.语音识别服务域名:nls-gateway-cn-shanghai.aliyuncs.com。
- * 3.语音识别接口请求路径:/stream/v1/asr。
- * 4.设置必选请求参数:appkey、format、sample_rate。
- * 5.设置可选请求参数:enable_punctuation_prediction、enable_inverse_text_normalization、enable_voice_detection。
- * <p>
- * 设置HTTPS头部字段:
- * 1.鉴权参数。
- * 2.Content-Type:application/octet-stream。
- * <p>
- * 发送HTTPS POST请求,返回服务端的响应。
- *//*
-
-        String url = "https://nls-gateway-cn-shanghai.aliyuncs.com/stream/v1/asr";
-        String request = url;
-        request = request + "?appkey=" + appkey;
-        request = request + "&format=" + format;
-        request = request + "&sample_rate=" + sampleRate;
-        if (enablePunctuationPrediction) {
-            request = request + "&enable_punctuation_prediction=" + true;
-        }
-        if (enableInverseTextNormalization) {
-            request = request + "&enable_inverse_text_normalization=" + true;
-        }
-        if (enableVoiceDetection) {
-            request = request + "&enable_voice_detection=" + true;
-        }
-
-        System.out.println("Request: " + request);
-
-        */
-/**
- * 设置HTTPS头部字段:
- * 1.鉴权参数。
- * 2.Content-Type:application/octet-stream。
- *//*
-
-        HashMap<String, String> headers = new HashMap<String, String>();
-        headers.put("X-NLS-Token", this.accessToken);
-        headers.put("Content-Type", "application/octet-stream");
-
-        */
-/**
- * 发送HTTPS POST请求,返回服务端的响应。
- *//*
-
-        String response = HttpUtil.sendPostFile(request, headers, fileName);
-
-        if (response != null) {
-            System.out.println("Response: " + response);
-            String result = JSONPath.read(response, "result").toString();
-            System.out.println("识别结果:" + result);
-            return result;
-        }
-        else {
-            System.err.println("识别失败!");
-        }
-
-        return "1";
-    }
-
-    public static void main(String[] args) {
-
-
-        String token = "cc96fcdce38f49f1af2298a949d39800";
-        String appkey = "7T7TkowOxND01n1y";
-
-        SpeechRecognizerRESTfulDemo demo = new SpeechRecognizerRESTfulDemo(appkey, token);
-
-        String fileName = "/Users/hongchuangyanfa/Downloads/nls-sample-16k.wav" ;//SpeechRecognizerRESTfulDemo.class.getClassLoader().getResource("/Users/hongchuangyanfa/Downloads/nls-sample-16k.wav").getPath();
-        String format = "pcm";
-        int sampleRate = 16000;
-        boolean enablePunctuationPrediction = true;
-        boolean enableInverseTextNormalization = true;
-        boolean enableVoiceDetection = false;
-   //     String dataInfo = demo.process(fileName, format, sampleRate, enablePunctuationPrediction, enableInverseTextNormalization, enableVoiceDetection);
-        System.out.println("123");
-        //System.out.println(dataInfo);
-    }
-}*/

+ 2 - 2
blade-service/blade-business/pom.xml

@@ -194,7 +194,7 @@
                     <target>${java.version}</target>
                     <encoding>${project.build.sourceEncoding}</encoding>
                     <compilerArguments>
-                        <bootclasspath>${java.home}/lib/rt.jar:${java.home}/lib/jce.jar:${java.home}/lib/jsse.jar
+                        <bootclasspath>${java.home}/lib/rt.jar;${java.home}/lib/jce.jar;${java.home}/lib/jsse.jar
                         </bootclasspath>
                     </compilerArguments>
                 </configuration>
@@ -202,4 +202,4 @@
         </plugins>
     </build>
 
-</project>
+</project>

+ 7 - 0
blade-service/blade-business/src/main/java/org/springblade/business/controller/ArchiveFileController.java

@@ -417,6 +417,13 @@ public class ArchiveFileController extends BladeController {
 
         return R.data(this.archiveFileService.selectArchiveFilePage(queryVo));
     }
+    @PostMapping("/sortByFileTime")
+    @ApiOperationSupport(order = 3)
+    @ApiOperation("按文件日期排序")
+    public R<Boolean> sortByFileTime(@RequestParam Long nodeId){
+
+        return R.status(this.archiveFileService.sortByFileTime(nodeId));
+    }
 
     /**
      * 批量新增

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

@@ -142,7 +142,7 @@ public class ChekSignData {
         if(maps!=null & maps.size()==0 && mapList.size()>=4 ){
 
             String header = "bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ0ZW5hbnRfaWQiOiIwMDAwMDAiLCJ1c2VyX25hbWUiOiJ6aHV3ZWkiLCJyZWFsX25hbWUiOiLnpZ3ngpwiLCJhdmF0YXIiOiIiLCJhdXRob3JpdGllcyI6WyJhZG1pbmlzdHJhdG9yIl0sImNsaWVudF9pZCI6ImNsaWVudCIsInJvbGVfbmFtZSI6ImFkbWluaXN0cmF0b3IiLCJsaWNlbnNlIjoicG93ZXJlZCBieSBibGFkZXgiLCJwb3N0X2lkIjoiIiwidXNlcl9pZCI6IjE3Mzk5NDQ2MTMyNjUxODY4MTgiLCJyb2xlX2lkIjoiMTEyMzU5ODgxNjczODY3NTIwMSIsInBob25lIjoiMTg5ODI4Nzc2MDciLCJzY29wZSI6WyJhbGwiXSwibmlja19uYW1lIjoi56Wd54KcIiwib2F1dGhfaWQiOiIiLCJkZXRhaWwiOnsidHlwZSI6IndlYiJ9LCJleHAiOjE3NDU1OTU2MDksImRlcHRfaWQiOiIxNTkyMzk0MTMxMTc3ODczNDEwIiwianRpIjoiZTMzN2QyNGMtNzkzZC00OTIwLTliMzEtZTU3MDYyNTIyZTBlIiwiYWNjb3VudCI6InpodXdlaSJ9.jihRZbcZrrCArbMcp6ON9H-1uCDn07juxlXPcHLU07A";
-            taskService.reSigningEVisa("1", taskApp.getTaskId(), taskApp.getContractId(), taskApp.getProjectId(), 1, header);
+          //  taskService.reSigningEVisa("1", taskApp.getTaskId(), taskApp.getContractId(), taskApp.getProjectId(), 1, header);
             String sql2 = "update u_task set batch=10 where id="+taskApp.getTaskId();
             jdbcTemplate.execute(sql2);
         }

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

@@ -678,7 +678,7 @@ public class EVisaTaskCheckController {
         if (projectId != null && StringUtils.isNotEmpty(projectId)) {
 
             ProjectInfo projectInfo = projectClient.getById(projectId);
-            if (projectInfo.getRemarkType() == 2) {
+            if (projectInfo.getRemarkType() == 2 || projectInfo.getRemarkType() == 3) {
                 User data = userClient.userInfoById(AuthUtil.getUserId()).getData();
                 if(StringUtils.isNotEmpty(data.getAccCode())){
                     return R.data(true);

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

@@ -33,10 +33,13 @@ import org.springblade.core.mp.support.Condition;
 import org.springblade.core.mp.support.Query;
 import org.springblade.core.tool.api.R;
 import org.springblade.core.tool.utils.Func;
+import org.springblade.manager.entity.WbsTreePrivate;
+import org.springblade.manager.feign.WbsTreePrivateClient;
 import org.springframework.transaction.annotation.Transactional;
 import org.springframework.web.bind.annotation.*;
 
 import javax.validation.Valid;
+import java.util.Collections;
 import java.util.Date;
 import java.util.List;
 
@@ -53,6 +56,7 @@ import java.util.List;
 public class  EntrustInfoController extends BladeController {
 
 	private final IEntrustInfoService entrustInfoService;
+	private final WbsTreePrivateClient wbsTreePrivateClient;
 
 	/**
 	 * 详情
@@ -117,8 +121,6 @@ public class  EntrustInfoController extends BladeController {
 	@Transactional
 	public R update(@Valid @RequestBody EntrustInfo entrustInfo) {
 			// rfid--绑定 需要判断 委托单的状态和创建情况
-
-
 			if(Func.isNotEmpty(entrustInfo.getRepealType()) && entrustInfo.getRepealType()==1){
 				entrustInfo.setSampleStatus("6");
 				entrustInfo.setRepealTime(new Date());
@@ -168,7 +170,27 @@ public class  EntrustInfoController extends BladeController {
 		if(id==null && Func.isNull(id)){
 			return R.fail("id不能为空");
 		}
-		EntrustDataInfoVO reportDetail = entrustInfoService.getReportDetail(id);
+		EntrustInfo entrustInfo = entrustInfoService.getById(id);
+		if (entrustInfo == null) {
+			return R.fail("id不存在");
+		}
+		WbsTreePrivate wbsTreePrivate = null;
+		if (entrustInfo.getNodeId() != null) {
+			List<WbsTreePrivate> wbsTreePrivates = wbsTreePrivateClient.queryByPKeyIds(Collections.singletonList(entrustInfo.getNodeId()));
+			if (wbsTreePrivates != null && !wbsTreePrivates.isEmpty()) {
+				wbsTreePrivate = wbsTreePrivates.get(0);
+			}
+		}
+		EntrustDataInfoVO reportDetail;
+		if (wbsTreePrivate != null && wbsTreePrivate.getNodeType() == 51) {
+			reportDetail = new EntrustDataInfoVO();
+			reportDetail.setId(entrustInfo.getId() + "");
+			reportDetail.setEntrustInfo(entrustInfo.getEntrustInfo());
+			reportDetail.setEntrustName(wbsTreePrivate.getNodeName());
+			reportDetail.setExpCount(entrustInfo.getExpCount());
+		} else {
+			reportDetail = entrustInfoService.getReportDetail(id);
+		}
 		return R.data(reportDetail);
 	}
 

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

@@ -78,7 +78,7 @@ public class FixedFlowController extends BladeController {
         //获取当前系统配置的角色划分
         List<RoleVO> roleVOS = this.sysClient.search().getData();
         //获取项目人员
-        List<SaveUserInfoByProjectDTO> contractUserList = this.projectAssignmentUserClient.queryContractDownAllUser(contractId, 2);
+        List<SaveUserInfoByProjectDTO> contractUserList = this.projectAssignmentUserClient.queryContractDownAllUser(contractId, 1);
 
         //先处理管理员
         for (RoleVO vos : roleVOS) {

+ 50 - 0
blade-service/blade-business/src/main/java/org/springblade/business/controller/InformationWriteQueryController.java

@@ -9,6 +9,7 @@ import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.baomidou.mybatisplus.extension.conditions.query.QueryChainWrapper;
 import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
 import com.google.common.collect.Lists;
 import io.swagger.annotations.*;
@@ -149,6 +150,7 @@ public class InformationWriteQueryController extends BladeController {
 
     private final IRecycleBinService recycleBinService;
 
+
     @Autowired
     StringRedisTemplate RedisTemplate;
 
@@ -188,6 +190,54 @@ public class InformationWriteQueryController extends BladeController {
         return R.data(300, null, "未找到文件题名");
     }
 
+    @PostMapping("/flushQueryName")
+    @ApiModelProperty(value = "刷新文件题名")
+    @ApiOperationSupport(order = 28)
+    public R<Boolean> flushQueryName(@RequestParam String ids){
+        if(ids==null){
+            throw new ServiceException("请选择要刷新的文件");
+        }
+        List<Long> idList = Arrays.stream(ids.split(","))
+            .map(Long::valueOf)
+            .collect(Collectors.toList());
+        List<InformationQuery> queryList = this.informationQueryService.list(Wrappers.<InformationQuery>lambdaQuery()
+            .select(InformationQuery::getId, InformationQuery::getName,InformationQuery::getProjectId,InformationQuery::getClassify,InformationQuery::getStatus,InformationQuery::getWbsId).in(InformationQuery::getId, idList));
+        String sgSuffix="";
+        String jlSuffix="";
+        if(queryList.size()>0){
+            String sql1="Select sg_suffix,jl_suffix from m_project_info where id="+queryList.get(0).getProjectId()+" and is_deleted=0";
+            List<ProjectInfo> projectInfos = jdbcTemplate.query(sql1, new BeanPropertyRowMapper<>(ProjectInfo.class));
+            if(projectInfos.size()>0){
+                sgSuffix=projectInfos.get(0).getSgSuffix()==null?"":projectInfos.get(0).getSgSuffix();
+                jlSuffix=projectInfos.get(0).getJlSuffix()==null?"":projectInfos.get(0).getJlSuffix();
+            }
+            for (InformationQuery query : queryList) {
+                String sql="select * from m_wbs_tree_contract where p_key_id="+query.getWbsId()+" and is_deleted=0";
+                WbsTreeContract contract = jdbcTemplate.queryForObject(sql, new BeanPropertyRowMapper<>(WbsTreeContract.class));
+                  String result=wbsParamClient.createFileTitle(contract);
+                if(query.getClassify()!=null&&query.getClassify()==1&&StringUtils.isNotEmpty(sgSuffix)){
+                    result=result+sgSuffix;
+                   if(!query.getName().equals(result)){
+                       query.setName(result);
+                   }
+                }else if(query.getClassify()!=null&&query.getClassify()==2&&StringUtils.isNotEmpty(jlSuffix)){
+                    result=result+jlSuffix;
+                    if(!query.getName().equals(result)){
+                        query.setName(result);
+                    }
+                }
+            }
+        }
+        List<InformationQuery> taskList = queryList.stream().filter(o -> o.getStatus() == 1 || o.getStatus() == 2).collect(Collectors.toList());
+        if(taskList.size()>0){
+            for (InformationQuery query : taskList) {
+                String update="update u_task set task_name='"+query.getName()+"' where form_data_id='"+query.getId()+"' and is_deleted=0";
+                jdbcTemplate.update(update);
+            }
+        }
+        return R.status(this.informationQueryService.updateBatchById(queryList));
+    }
+
     /**
      * 初始化合同段导图树
      */

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

@@ -369,7 +369,7 @@ public class NeiYeController {
                     if(info!=null){
                         if(info.indexOf("优良")>=0){
                             vo1.setGoodCount(1);
-                            vo1.setPassCount(0);
+                            vo1.setPassCount(1);
                             vo1.setGoodRate("100%");
                         }else {
                             vo1.setGoodCount(0);
@@ -427,7 +427,7 @@ public class NeiYeController {
                             if(info.indexOf("优良")>=0){
                                 if(type==2){
                                     vo2.setGoodCount(1);
-                                    vo2.setPassCount(0);
+                                    vo2.setPassCount(1);
                                     vo2.setGoodRate("100%");
                                 }else {
                                     goodCount++;
@@ -454,7 +454,7 @@ public class NeiYeController {
                 else if(type==1){
                     vo1.setUnitCount(unitCount);
                     vo1.setGoodCount(goodCount);
-                    vo1.setPassCount(passCount);
+                    vo1.setPassCount(passCount + goodCount);
                     vo1.setGoodRate(calculatePercentage(goodCount,unitCount));
                     vo1.setId(SnowFlakeUtil.getId());
                     voList.add(vo1);

+ 0 - 2
blade-service/blade-business/src/main/java/org/springblade/business/controller/OperationLogController.java

@@ -158,8 +158,6 @@ public class OperationLogController extends BladeController {
         if (StringUtils.isNotEmpty(operationLog.getQueryValue())) {
             wrapper.lambda().like(OperationLog::getOperationContent, operationLog.getQueryValue());
         }
-
-
         IPage<OperationLog> pages = new Page<>(query.getCurrent(),query.getSize());
 //        IPage<OperationLog> pages = operationLogService.page(Condition.getPage(query), wrapper.lambda().orderBy(true, false, OperationLog::getCreateTime));
         pages = logMapper.getPage(pages,operationLog);

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

@@ -42,9 +42,7 @@ import org.springblade.core.secure.utils.SecureUtil;
 import org.springblade.core.sms.model.SmsResponse;
 import org.springblade.core.tool.api.R;
 import org.springblade.core.tool.jackson.JsonUtil;
-import org.springblade.core.tool.utils.DateUtil;
-import org.springblade.core.tool.utils.Func;
-import org.springblade.core.tool.utils.ObjectUtil;
+import org.springblade.core.tool.utils.*;
 import org.springblade.evisa.feign.EVisaClient;
 import org.springblade.feign.ArchiveFileTaskClient;
 import org.springblade.flow.core.entity.BladeFlow;
@@ -114,14 +112,16 @@ public class TaskController extends BladeController {
     @ApiOperation(value = "记录短信验证码超时时间")
     public void saveSmsTimeout(@RequestParam String code) {
         //获取账户记录
+     ///   String aesKey = "O2BEeIv399qHQNhD6aGW8R8DEj4bqHXm";
+     //   String accode = AesUtil.decryptFormBase64ToString(code, aesKey);
         DefaultConfig config = this.defaultConfigService.getOne(Wrappers.<DefaultConfig>lambdaQuery()
                 .eq(DefaultConfig::getCreateUser, AuthUtil.getUserId())
                 .isNotNull(DefaultConfig::getSmsCode));
         if (config != null) {
             //获取当前时间
             Date now = DateUtil.now();
-            //默认16小时后超时
-            now = DateUtil.plusHours(now, 16);
+            // 16 改为 1小时后超时
+            now = DateUtil.plusHours(now, 1);
 
             LambdaUpdateWrapper<DefaultConfig> wrapper = new LambdaUpdateWrapper<>();
             wrapper.set(DefaultConfig::getSmsTimeOut, DateUtil.format(now, "yyyy-MM-dd HH:mm:ss"));
@@ -190,11 +190,12 @@ public class TaskController extends BladeController {
     @PostMapping("/send-notice")
     @ApiOperationSupport(order = 10)
     @ApiOperation(value = "短信验证")
-    public R<Boolean> sendNotice(@RequestParam String phone) {
-//        String code = CommonUtil.getCharAndNumber(4);
+    public R<Boolean> sendNotice(BladeUser user,@RequestParam String phone) {
+      //  String code = CommonUtil.getCharAndNumber(4);
         String code = String.valueOf((int) (Math.random() * 9000 + 1000));
         Map<String, String> params = new HashMap<>(3);
         params.put("code", code);
+        //params.put("name", user.getNickName());
         R<SmsResponse> result = this.newSmsClient.sendMessage("test_code", JsonUtil.toJson(params), phone);
         if (result.getData().isSuccess()) {
             //记录当前验证码
@@ -213,6 +214,9 @@ public class TaskController extends BladeController {
                 this.defaultConfigService.save(config);
             }
         }
+        // 加密处理
+       // String aesKey = "O2BEeIv399qHQNhD6aGW8R8DEj4bqHXm";
+      //  String codeInfo= AesUtil.encryptToBase64(code,aesKey);
         return result.getData().isSuccess() ? R.data(200, true, code) : R.data(499, false, String.valueOf(JSONObject.parseObject(result.getData().getMsg(), Map.class).get("Message")));
     }
 
@@ -1376,6 +1380,8 @@ public class TaskController extends BladeController {
             }
             sqlString.append(")");
         }
+        //是否填报过
+//        sqlString.append(" AND (SELECT COUNT(1)  FROM u_information_query WHERE u_task.form_data_id = id and is_deleted=0) > 0");
 
         //总数量
         String sqlCount = sqlString.toString().replace("*", "count(1)");
@@ -1511,7 +1517,7 @@ public class TaskController extends BladeController {
                             task -> task));
         }
         //所有满足条件的日志 转map
-        String logQuery = "select business_id,create_user_name ,create_time, operation_type, save_data from u_operation_log where  operation_content like '%废除%'";
+        String logQuery = "select business_id,create_user_name ,create_time, operation_type, save_data from u_operation_log where operation_type in (6,9,12,15,18,21,24,26,61,62)";
         List<OperationLog> operationLogs = jdbcTemplate.query(logQuery, new BeanPropertyRowMapper<>(OperationLog.class));
         if(ObjectUtil.isNotEmpty(operationLogs)){
              operationLogMap = operationLogs.stream().collect(Collectors.groupingBy(OperationLog::getBusinessId));
@@ -1674,6 +1680,8 @@ public class TaskController extends BladeController {
             }
             sqlString.append(")");
         }
+        //是否填报过
+        sqlString.append(" AND (SELECT COUNT(1)  FROM u_information_query WHERE u_task.form_data_id = id and is_deleted=0) > 0");
 
         //总数量
         String sqlCount = sqlString.toString().replace("*", "count(1)");
@@ -1804,7 +1812,7 @@ public class TaskController extends BladeController {
                             task -> task));
         }
         //所有满足条件的日志 转map
-        String logQuery = "select business_id,create_user_name ,create_time from u_operation_log where  operation_content like '%废除%'";
+        String logQuery = "select business_id,create_user_name ,create_time, operation_type, save_data from u_operation_log where operation_type in (6,9,26,61,62)";
         List<OperationLog> operationLogs = jdbcTemplate.query(logQuery, new BeanPropertyRowMapper<>(OperationLog.class));
         if(ObjectUtil.isNotEmpty(operationLogs)){
             operationLogMap = operationLogs.stream().collect(Collectors.groupingBy(OperationLog::getBusinessId));
@@ -1865,7 +1873,7 @@ public class TaskController extends BladeController {
             throw new ServiceException("未获取到当前登陆的用户信息");
         } else {
             if (!SecureUtil.getUser().getRoleName().contains("administrator")) {
-                return R.data(200, null, "当前用户不是超管角色,未查询到信息");
+                return R.fail(200, "当前用户不是超管角色,未查询到信息");
             }
         }
         if (ObjectUtil.isEmpty(dto.getContractId())) {
@@ -1881,7 +1889,7 @@ public class TaskController extends BladeController {
         //封装入参SQL
         List<Object> params = new ArrayList<>();
         Integer eVisaStatus = dto.getVisaStatus();
-        StringBuilder sqlString = new StringBuilder("SELECT * FROM u_task WHERE approval_type not in (4, 5, 6, 7, 8) AND status != 3 AND is_deleted=0 AND contract_id = " + dto.getContractId()); //approval_type != 4 非档案的任务就是1填报资料,2工程文件,3日志资料
+        StringBuilder sqlString = new StringBuilder("SELECT * FROM u_task WHERE approval_type not in (4, 5, 6, 7, 11) AND status != 3 AND is_deleted=0 AND contract_id = " + dto.getContractId()); //approval_type != 4 非档案的任务就是1填报资料,2工程文件,3日志资料
 
         if (StringUtils.isNotBlank(dto.getStartTimeValue()) && StringUtils.isNotBlank(dto.getEndTimeValue())) {
             if (dto.getStartTimeValue().equals(dto.getEndTimeValue())) {
@@ -1917,6 +1925,8 @@ public class TaskController extends BladeController {
                     "(SELECT COUNT(1)  FROM u_task_parallel WHERE u_task.process_instance_id = u_task_parallel.process_instance_id AND u_task_parallel.e_visa_status = 1 AND u_task_parallel.status = 2 and is_deleted=0)");
 
         }
+        //是否填报过
+        sqlString.append(" AND (SELECT COUNT(1)  FROM u_information_query WHERE u_task.form_data_id = id and is_deleted=0) > 0");
 
         //总数量
         String sqlCount = sqlString.toString().replace("*", "count(1)");

+ 2 - 2
blade-service/blade-business/src/main/java/org/springblade/business/feignClient/ContractLogClientImpl.java

@@ -105,12 +105,12 @@ public class ContractLogClientImpl implements ContractLogClient {
     }
 
     @Override
-    public List<ContractLog> queryContractLogByPrimaryKeyIdAndRecordTimeList(String nodePrimaryKeyId, String recordTime, String contractId) {
+    public List<ContractLog> queryContractLogByPrimaryKeyIdAndRecordTimeList(String nodePrimaryKeyId, String recordTime, String contractId,Long createUser) {
         return this.contractLogService.getBaseMapper().selectList(Wrappers.<ContractLog>lambdaQuery()
                 .eq(ContractLog::getWbsNodeId, nodePrimaryKeyId)
                 .eq(ContractLog::getRecordTime, recordTime)
                 .eq(ContractLog::getContractId, contractId)
-                .eq(ContractLog::getCreateUser, AuthUtil.getUserId()));
+                .eq(ContractLog::getCreateUser, createUser==null?AuthUtil.getUserId():createUser));
     }
 
     @Override

+ 1 - 1
blade-service/blade-business/src/main/java/org/springblade/business/mapper/EntrustInfoMapper.xml

@@ -69,7 +69,7 @@
             and a.status = #{param2.status}
         </if>
         <if test="param2.entrustName != null and param2.entrustName != ''">
-            AND a.entrust_name like CONCAT(CONCAT('%', #{param2.entrustName}), '%')
+            AND ( a.entrust_name like CONCAT(CONCAT('%', #{param2.entrustName}), '%') or a.entrust_no like CONCAT(CONCAT('%', #{param2.entrustName}), '%') )
         </if>
     </select>
 

+ 2 - 0
blade-service/blade-business/src/main/java/org/springblade/business/service/IArchiveFileService.java

@@ -74,4 +74,6 @@ public interface IArchiveFileService extends BaseService<ArchiveFile> {
     public void addArchiveFileEx(List<ArchiveFile> files);
 
     public void updateArchiveFileEx(List<ArchiveFile> files);
+
+    boolean sortByFileTime(Long nodeId);
 }

+ 27 - 0
blade-service/blade-business/src/main/java/org/springblade/business/service/impl/ArchiveFileServiceImpl.java

@@ -307,4 +307,31 @@ public class ArchiveFileServiceImpl extends BaseServiceImpl<ArchiveFileMapper, A
         });
     }
 
+    @Override
+    public boolean sortByFileTime(Long nodeId) {
+     String sql="SELECT id,file_time,node_id FROM u_archive_file WHERE node_id IN (SELECT id FROM m_archive_tree_contract WHERE  FIND_IN_SET("+nodeId+",ancestors)) AND is_deleted=0";
+     List<ArchiveFile> list=jdbcTemplate.query(sql,new BeanPropertyRowMapper<>(ArchiveFile.class));
+     if(list.size()>0){
+         Map<String, List<ArchiveFile>> group = list.stream()
+             .collect(Collectors.groupingBy(ArchiveFile::getNodeId));
+         for (Map.Entry<String, List<ArchiveFile>> entry : group.entrySet()) {
+             List<ArchiveFile> archiveFiles = entry.getValue();
+             archiveFiles.sort((a, b) -> {
+                 if (a.getFileTime() == null && b.getFileTime() == null) return 0;
+                 if (a.getFileTime() == null) return -1;
+                 if (b.getFileTime() == null) return 1;
+                 return a.getFileTime().compareTo(b.getFileTime());
+             });
+             int sort = 0;
+             for (ArchiveFile file : archiveFiles) {
+                 file.setSort(sort++);
+             }
+             this.updateBatchById(archiveFiles);
+         }
+         return true;
+     }else {
+         return false;
+     }
+    }
+
 }

+ 22 - 12
blade-service/blade-business/src/main/java/org/springblade/business/service/impl/EntrustInfoServiceImpl.java

@@ -122,9 +122,11 @@ public class EntrustInfoServiceImpl extends BaseServiceImpl<EntrustInfoMapper, E
 		}
 		String sampleId = "";
 		String contractId = "";
-        String sqlNodeName="select node_name from m_wbs_tree_private where p_key_id="+dataInfo.getString("nodeId");
-        String nodeName = jdbcTemplate.queryForObject(sqlNodeName, new SingleColumnRowMapper<>(String.class));
-        if(!nodeName.equals("回弹法检测混凝土抗压强度")&&!nodeName.equals("路基压实度")&&!nodeName.equals("地基承载力")&&!nodeName.equals("路基路面弯沉")&&!nodeName.equals("锚杆")&&!nodeName.equals("喷射混凝土厚度")){
+        String sqlNodeName="select node_name, node_type from m_wbs_tree_private where p_key_id="+dataInfo.getString("nodeId");
+		Map<String, Object> wbsTreePrivateMap = jdbcTemplate.queryForMap(sqlNodeName);
+		String nodeName = wbsTreePrivateMap.get("node_name").toString();
+		String nodeType = wbsTreePrivateMap.get("node_type").toString();
+		if(!"51".equals(nodeType) && !nodeName.equals("回弹法检测混凝土抗压强度")&&!nodeName.equals("路基压实度")&&!nodeName.equals("地基承载力")&&!nodeName.equals("路基路面弯沉")&&!nodeName.equals("锚杆")&&!nodeName.equals("喷射混凝土厚度")){
             // 创建 委托单信息
             if(!dataInfo.containsKey("sampleId")){
                 return R.fail("取样信息为sampleId不存在");
@@ -149,7 +151,7 @@ public class EntrustInfoServiceImpl extends BaseServiceImpl<EntrustInfoMapper, E
         if(!dataInfo.containsKey("sampleId")){
             entrustInfo.setSampleStatus("0");
         }else {
-            if(!nodeName.equals("回弹法检测混凝土抗压强度")&&!nodeName.equals("路基压实度")&&!nodeName.equals("地基承载力")&&!nodeName.equals("路基路面弯沉")&&!nodeName.equals("锚杆")){
+            if(!"51".equals(nodeType) && !nodeName.equals("回弹法检测混凝土抗压强度")&&!nodeName.equals("路基压实度")&&!nodeName.equals("地基承载力")&&!nodeName.equals("路基路面弯沉")&&!nodeName.equals("锚杆")){
                 entrustInfo = baseMapper.selectOne(Wrappers.<EntrustInfo>query().lambda().eq(EntrustInfo::getSampleId, sampleId).eq(EntrustInfo::getContractId,contractId));
             }else {
                 entrustInfo = baseMapper.selectOne(Wrappers.<EntrustInfo>query().lambda().eq(EntrustInfo::getId,dataInfo.get("id")).eq(EntrustInfo::getContractId,contractId));
@@ -194,6 +196,13 @@ public class EntrustInfoServiceImpl extends BaseServiceImpl<EntrustInfoMapper, E
         this.saveOrUpdate(entrustInfo);
 		dataInfo.put("groupId",entrustInfo.getId());
 		dataInfo.put("pkeyId", dataInfo.getString("nodeErTreeId"));
+        if(StringUtils.isEmpty(entrustInfo.getEntrustNo())){
+            entrustInfo.setEntrustNo("");
+        }
+        if(StringUtils.isEmpty(entrustInfo.getEntrustName())){
+            entrustInfo.setEntrustName("");
+        }
+        dataInfo.put("entrustInfoName",entrustInfo.getEntrustNo()+entrustInfo.getEntrustName());
         String pdfUrl = excelTabClient.saveEntrustTabData(dataInfo);
         return R.data(200,pdfUrl,"操作成功");
 	}
@@ -267,7 +276,8 @@ public class EntrustInfoServiceImpl extends BaseServiceImpl<EntrustInfoMapper, E
             if(formDataIds.size()>0){
                 for (String formDataId : formDataIds) {
                     String sql="Select * from u_task where form_data_id="+formDataId +" and status!=3 and is_deleted=0";
-                    Task task = jdbcTemplate.queryForObject(sql, new BeanPropertyRowMapper<>(Task.class));
+					List<Task> tasks = jdbcTemplate.query(sql, new BeanPropertyRowMapper<>(Task.class));
+					Task task = tasks.isEmpty() ? null : tasks.get(0);
                     if(task!=null){
                         String updateTaskParallel="update u_task_parallel set status=3 , e_visa_content = '撤回成功' where process_instance_id='" + task.getProcessInstanceId() + "'";
                         String updateTask="update u_task set status=3 where id="+task.getId()+" and status!=3 and is_deleted=0";
@@ -275,16 +285,16 @@ public class EntrustInfoServiceImpl extends BaseServiceImpl<EntrustInfoMapper, E
                         jdbcTemplate.update(updateTaskParallel);
                         jdbcTemplate.update(updateTask);
                         jdbcTemplate.execute(deleted);
+						JSONObject json = new JSONObject();
+						json.put("operationObjIds", Func.toStrList(task.getFormDataId()));
+						json.put("operationObjName", "批量废除");
+						json.put("projectId", task.getProjectId());
+						json.put("contractId", task.getContractId());
+						//保存操作记录
+						this.operationLogClient.saveUserOperationLog(62, "资料撤回废除", "委托单", json);
                     }
                     String updateinformationQuery="update u_information_query set status=3,e_visa_pdf_url= null where id="+formDataId;
                     jdbcTemplate.update(updateinformationQuery);
-					JSONObject json = new JSONObject();
-					json.put("operationObjIds", Func.toStrList(task.getFormDataId()));
-					json.put("operationObjName", "批量废除");
-					json.put("projectId", task.getProjectId());
-					json.put("contractId", task.getContractId());
-					//保存操作记录
-					this.operationLogClient.saveUserOperationLog(62, "资料撤回废除", "委托单", json);
 				}
 			}
 

+ 7 - 8
blade-service/blade-business/src/main/java/org/springblade/business/service/impl/TaskServiceImpl.java

@@ -25,12 +25,11 @@ import org.springblade.common.utils.CommonUtil;
 import org.springblade.common.utils.SnowFlakeUtil;
 import org.springblade.core.log.exception.ServiceException;
 import org.springblade.core.mp.base.BaseServiceImpl;
-import org.springblade.core.mp.support.Query;
 import org.springblade.core.oss.model.BladeFile;
 import org.springblade.core.secure.utils.AuthUtil;
 import org.springblade.core.secure.utils.SecureUtil;
 import org.springblade.core.tool.api.R;
-import org.springblade.core.tool.support.Kv;
+
 import org.springblade.core.tool.utils.DateUtil;
 import org.springblade.core.tool.utils.Func;
 import org.springblade.core.tool.utils.ObjectUtil;
@@ -38,12 +37,10 @@ import org.springblade.core.tool.utils.ResourceUtil;
 import org.springblade.evisa.feign.EVisaClient;
 import org.springblade.evisa.vo.EVisaTaskApprovalVO;
 import org.springblade.flow.core.constant.ProcessConstant;
-import org.springblade.flow.core.entity.BladeFlow;
 import org.springblade.flow.core.feign.IFlowClient;
 import org.springblade.flow.core.feign.NewFlowClient;
 import org.springblade.flow.core.utils.FlowUtil;
-import org.springblade.flow.core.utils.TaskUtil;
-import org.springblade.flow.core.vo.FlowProcessVO;
+
 import org.springblade.manager.entity.ContractInfo;
 import org.springblade.manager.entity.ProjectInfo;
 import org.springblade.manager.entity.TabBusstimeInfo;
@@ -1995,7 +1992,8 @@ public class TaskServiceImpl extends BaseServiceImpl<TaskMapper, Task> implement
                 contractLogService.update(new LambdaUpdateWrapper<ContractLog>().eq(ContractLog::getId, contractLog.getId())
                     .set(ContractLog::getEVisaPdfUrl, null)
                     .set(ContractLog::getPdfUrl, null));
-                excelTabClient.getTheContractLogBusinessData(dto.getLogPkeyId(), dto.getNodePrimaryKeyId(), contractLog.getRecordTime(), dto.getContractId(), contractLog.getCreateUser());
+                //excelTabClient.getTheContractLogBusinessData(dto.getLogPkeyId(), dto.getNodePrimaryKeyId(), contractLog.getRecordTime(), dto.getContractId(), contractLog.getCreateUser());
+                excelTabClient.getTheLogPdInfo(dto.getLogPkeyId(), dto.getNodePrimaryKeyId(), contractLog.getRecordTime(), dto.getContractId(),contractLog.getCreateUser());
             }
         }
     }
@@ -2029,7 +2027,8 @@ public class TaskServiceImpl extends BaseServiceImpl<TaskMapper, Task> implement
                          b = informationQueryService.update(new LambdaUpdateWrapper<InformationQuery>()
                                 .eq(InformationQuery::getId, task.getFormDataId())
                                 .set(InformationQuery::getEVisaPdfUrl, null)
-                                .set(InformationQuery::getPdfUrl, null));
+//                                .set(InformationQuery::getPdfUrl, null)
+                         );
                     }else {
                         if(task.getApprovalType()==3){
                            b=contractLogService.update(new LambdaUpdateWrapper<ContractLog>()
@@ -2051,7 +2050,7 @@ public class TaskServiceImpl extends BaseServiceImpl<TaskMapper, Task> implement
                         //重新保存
                         long startTime_1 = System.currentTimeMillis();
                         //质检资料
-                        if(task.getApprovalType()==1){
+                        if(task.getApprovalType()==1 || task.getApprovalType()== 9){
                             String sql="select type from u_information_query where id="+task.getFormDataId();
                             Integer InformationType = jdbcTemplate.queryForObject(sql, new SingleColumnRowMapper<>(Integer.class));
                             if(InformationType==1){

+ 21 - 8
blade-service/blade-business/src/main/java/org/springblade/business/service/impl/TrialSelfInspectionRecordServiceImpl.java

@@ -62,7 +62,6 @@ import org.springframework.jdbc.core.JdbcTemplate;
 import org.springframework.jdbc.core.SingleColumnRowMapper;
 import org.springframework.scheduling.annotation.Async;
 import org.springframework.stereotype.Service;
-import org.springframework.transaction.annotation.Isolation;
 import org.springframework.transaction.annotation.Transactional;
 import org.springframework.web.multipart.MultipartFile;
 
@@ -188,7 +187,7 @@ public class TrialSelfInspectionRecordServiceImpl extends BaseServiceImpl<TrialS
                      }
                 }
                 //合并的pdfUrl
-                String pdf = this.getMergePdfToTrialNew(record.getContractId(), record.getId());
+                String pdf = this.getMergePdfToTrialNew(record.getContractId(), record.getId(), dto.getType());
                 record.setPdfUrl(pdf);
             }
 
@@ -264,11 +263,12 @@ public class TrialSelfInspectionRecordServiceImpl extends BaseServiceImpl<TrialS
      *新增返回该试验材料报告关联的委托单pdf也拼接在后面
      * @param contractId
      * @param nodeId
+     * @param type
      * @return
      * @throws FileNotFoundException
      */
-    private String getMergePdfToTrialNew(Long contractId, Long nodeId) throws FileNotFoundException {
-        String sql = "select pdf_url,e_visa_pdf_url from u_information_query where wbs_id='" + nodeId + "' and contract_id ='" + contractId + "'";
+    private String getMergePdfToTrialNew(Long contractId, Long nodeId, Integer type) throws FileNotFoundException {
+        String sql = "select pdf_url,e_visa_pdf_url from u_information_query where wbs_id='" + nodeId + "' and contract_id ='" + contractId + "' and classify = '" + type + "'" ;
         List<Map<String, Object>> maps = jdbcTemplate.queryForList(sql);
         if (maps.size() >= 1) {
             Map<String, Object> stringObjectMap = maps.get(0);
@@ -1138,6 +1138,9 @@ public class TrialSelfInspectionRecordServiceImpl extends BaseServiceImpl<TrialS
           for (Map.Entry<String, List<JSONObject>> entry : groupedByType.entrySet()) {
               List<JSONObject> jsonObjects = groupedByType.get(entry.getKey());
               JSONObject   jsonObject = jsonObjects.get(0);
+              if(entry.getKey().equals("2")&&jsonObjects.size()>1){
+                  jsonObject = jsonObjects.get(1);
+              }
               String pkeyId = jsonObject.getString("pkeyId");
               String sql = "select * from m_wbs_tree_private where p_key_id =" + pkeyId;
               WbsTreePrivate table = jdbcTemplate.queryForObject(sql, new BeanPropertyRowMapper<>(WbsTreePrivate.class));
@@ -1244,6 +1247,11 @@ public class TrialSelfInspectionRecordServiceImpl extends BaseServiceImpl<TrialS
         String recordOrReportNo = jsonObject.getString(key);
         if(!"".equals(recordOrReportNo) && !(recordOrReportNo == null)){
             String updateSql = "update u_trial_self_inspection_record set " + fileVlue +"='" + recordOrReportNo + "' where id='" + dto.getId()+"'";
+            if(fileVlue.equals("record_no")){
+               dto.setRecordNo(recordOrReportNo);
+            }else {
+                dto.setReportNo(recordOrReportNo);
+            }
             jdbcTemplate.execute(updateSql);
         }
     }
@@ -1887,11 +1895,16 @@ public class TrialSelfInspectionRecordServiceImpl extends BaseServiceImpl<TrialS
 
                     //自检pdf
                     List<TrialSelfInspectionRecord> trialSelfInspectionRecords = baseMapper.selectList(Wrappers.<TrialSelfInspectionRecord>lambdaQuery()
-                            .select(TrialSelfInspectionRecord::getPdfUrl)
+                            .select(TrialSelfInspectionRecord::getPdfUrl,TrialSelfInspectionRecord::getContractId,TrialSelfInspectionRecord::getId,TrialSelfInspectionRecord::getType)
                             .in(TrialSelfInspectionRecord::getId, Func.toLongList(dto.getIds())));
-                    List<String> pdfURLs = trialSelfInspectionRecords.stream().map(TrialSelfInspectionRecord::getPdfUrl).collect(Collectors.toList());
-                    pdfList.addAll(pdfURLs);
-
+                    if(trialSelfInspectionRecords.size()>0){
+                        for (TrialSelfInspectionRecord record : trialSelfInspectionRecords) {
+                            String pdf = this.getMergePdfToTrialNew(record.getContractId(), record.getId(), record.getType());
+                            pdfList.add(pdf);
+                        }
+                    }
+//                    List<String> pdfURLs = trialSelfInspectionRecords.stream().map(TrialSelfInspectionRecord::getPdfUrl).collect(Collectors.toList());
+//                    pdfList.addAll(pdfURLs);
                     //------第三方、外委------
                 } else if (dto.getType().equals(2) || dto.getType().equals(3)) {
                     if (informationQuery.getPdfTrialUrl() != null) {

+ 29 - 19
blade-service/blade-business/src/main/java/org/springblade/business/service/impl/WeatherInfoServiceImpl.java

@@ -37,12 +37,10 @@ import java.io.IOException;
 import java.math.BigDecimal;
 import java.sql.ResultSet;
 import java.sql.SQLException;
-import java.time.Duration;
-import java.time.LocalDate;
-import java.time.LocalDateTime;
-import java.time.ZoneId;
+import java.time.*;
 import java.time.format.DateTimeFormatter;
 import java.util.*;
+import java.util.concurrent.TimeUnit;
 import java.util.stream.Collectors;
 
 @Slf4j
@@ -141,20 +139,21 @@ public class WeatherInfoServiceImpl extends ServiceImpl<WeatherInfoMapper, Weath
                 }
                 Map<String, String> weatherMap = cachedWeatherMap.get(area.getCity_code());
                 if (weatherMap == null) {
-                    //获取天气信息(百度天气)
                     String nums = stringRedisTemplate.opsForValue().get("blade-business::contractArea:yiKeYun:todayWeatherNums");
-                    if (nums != null && Integer.parseInt(nums) <= 19000) {
-                        weatherMap = YiKeYunApiUtils.getTodayWeatherByAdcode(area.getCity_code() + "000000");
-                    }
-                    if (weatherMap == null) {
-                        weatherMap = BaiduApiUtil.getTodayWeather(area.getCity_code());
-                    }
-                    if (weatherMap != null) {
-                        cachedWeatherMap.put(area.getCity_code(), weatherMap);
-                        if (weatherMap.get("nums") != null) {
-                            stringRedisTemplate.opsForValue().set("blade-business::contractArea:yiKeYun:todayWeatherNums", weatherMap.get("nums"));
+                    if (nums == null || Integer.parseInt(nums) <= 19000) {
+                        // 重试三次
+                        weatherMap = YiKeYunApiUtils.getTodayWeatherByAdcodeTry(area.getCity_code() + "000000");
+                        if (weatherMap != null) {
+                            cachedWeatherMap.put(area.getCity_code(), weatherMap);
+                            if (weatherMap.get("nums") != null) {
+                                stringRedisTemplate.opsForValue().set("blade-business::contractArea:yiKeYun:todayWeatherNums", weatherMap.get("nums"), getSecondsUntilMidnight(), TimeUnit.SECONDS);
+                            }
                         }
                     }
+                    //获取天气信息(百度天气)
+//                    if (weatherMap == null) {
+//                        weatherMap = BaiduApiUtil.getTodayWeather(area.getCity_code());
+//                    }
                 }
                 if (weatherMap != null) {
                     //计算平均气温
@@ -419,7 +418,7 @@ public class WeatherInfoServiceImpl extends ServiceImpl<WeatherInfoMapper, Weath
 
     public Map<String, Map<String, String>> getHistoryWeather(ProjectContractArea area, String month) {
         String nums = stringRedisTemplate.opsForValue().get("blade-business::contractArea:yiKeYun:historyWeatherNums");
-        if (nums == null || Integer.parseInt(nums) > 19000) {
+        if (nums != null && Integer.parseInt(nums) > 19000) {
             log.info("获取历史天气失败:易客云获取历史天气的api次数已用完。");
             return null;
         }
@@ -432,11 +431,16 @@ public class WeatherInfoServiceImpl extends ServiceImpl<WeatherInfoMapper, Weath
             city = city.substring(0, city.length() - 1);
         }
         Integer count = jdbcTemplate.queryForObject("select count(*) from m_yikeyun_weather_city where cityZh like '" + county + "%'", Integer.class);
-        String cityId = null;
+        String cityId;
         if (count == null || count == 0) {
+            log.warn("获取历史天气失败:" + area.getCity()+"-"+area.getCounty());
             return null;
         } else if (count > 1) {
-            cityId = jdbcTemplate.queryForObject("select id from m_yikeyun_weather_city where cityZh like '" + county + "%' and leaderZh like '" + city + "%' limit 1", String.class);
+            try {
+                cityId = jdbcTemplate.queryForObject("select id from m_yikeyun_weather_city where cityZh like '" + county + "%' and leaderZh like '" + city + "%' limit 1", String.class);
+            } catch (Exception e) {
+                cityId = jdbcTemplate.queryForObject("select id from m_yikeyun_weather_city where cityZh like '" + county + "%' and leaderZh like '" + county + "%' limit 1", String.class);
+            }
         } else {
             cityId = jdbcTemplate.queryForObject("select id from m_yikeyun_weather_city where cityZh like '" + county + "%'", String.class);
         }
@@ -445,7 +449,7 @@ public class WeatherInfoServiceImpl extends ServiceImpl<WeatherInfoMapper, Weath
             if (historyWeather != null) {
                 Map<String, String> map = historyWeather.get("nums");
                 if (map != null && map.get("nums") != null) {
-                    stringRedisTemplate.opsForValue().set("blade-business::contractArea:yiKeYun:historyWeatherNums", map.get("nums"));
+                    stringRedisTemplate.opsForValue().set("blade-business::contractArea:yiKeYun:historyWeatherNums", map.get("nums"), getSecondsUntilMidnight(), TimeUnit.SECONDS);
                 }
             }
             return historyWeather;
@@ -493,4 +497,10 @@ public class WeatherInfoServiceImpl extends ServiceImpl<WeatherInfoMapper, Weath
         return map;
     }
 
+    public static long getSecondsUntilMidnight() {
+        LocalDateTime now = LocalDateTime.now();
+        LocalDateTime nextMidnight = now.with(LocalTime.MIDNIGHT).plusDays(1);
+        return TimeUnit.MILLISECONDS.toSeconds(nextMidnight.atZone(java.time.ZoneId.systemDefault()).toInstant().toEpochMilli()
+                - now.atZone(java.time.ZoneId.systemDefault()).toInstant().toEpochMilli());
+    }
 }

+ 169 - 0
blade-service/blade-e-visa/src/main/java/org/springblade/evisa/controller/ArchiveController.java

@@ -0,0 +1,169 @@
+package org.springblade.evisa.controller;
+
+import io.swagger.annotations.Api;
+import lombok.AllArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.pdfbox.pdmodel.PDDocument;
+import org.apache.pdfbox.pdmodel.PDPage;
+import org.springblade.business.vo.TaskSignInfoVO;
+import org.springblade.evisa.service.EVDataService;
+import org.springblade.evisa.utils.FileUtils;
+import org.springblade.evisa.vo.TaskArchiveSplitVO;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.redis.core.StringRedisTemplate;
+import org.springframework.jdbc.core.BeanPropertyRowMapper;
+import org.springframework.jdbc.core.JdbcTemplate;
+import org.springframework.scheduling.annotation.Scheduled;
+import org.springframework.web.bind.annotation.RestController;
+
+import javax.annotation.Resource;
+import java.io.File;
+import java.io.InputStream;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.ThreadPoolExecutor;
+import java.util.concurrent.TimeUnit;
+
+import org.apache.pdfbox.rendering.PDFRenderer;
+import java.awt.image.BufferedImage;
+import javax.imageio.ImageIO;
+
+
+/**
+ * 清表基础数据表 控制器
+ *
+ * @author BladeX
+ * @since 2022-05-18
+ */
+@RestController
+@AllArgsConstructor
+@Api(value = "电签类", tags = "电签类接口")
+@Slf4j
+public class ArchiveController {
+
+    @Autowired
+    StringRedisTemplate RedisTemplate;
+    // jdbc
+    private final JdbcTemplate jdbcTemplate;
+
+    //电签服务类
+    private final EVDataService evDataService;
+
+    // 线程池
+    @Resource(name = "taskExecutor1")
+    private ThreadPoolExecutor executor;
+
+    @Scheduled(cron = "0/10 * * * * ?")
+    public void SignInfo() {
+        //执行代码
+
+        log.info("扫描开始");
+
+        String sql = "SELECT a.id,a.archive_id as archiveId,a.file_url as fileUrl from u_archive_file a, u_task_split b where FIND_IN_SET(a.archive_id,b.ids) and b.type=3 ";
+        List<TaskArchiveSplitVO> query = jdbcTemplate.query(sql, new BeanPropertyRowMapper<>(TaskArchiveSplitVO.class));
+
+        if (query != null && query.size() >= 1) {
+            for (TaskArchiveSplitVO dataInfo : query) {
+                if (executor.getQueue().size() <= 10) {
+                    Boolean aBoolean = RedisTemplate.hasKey("sign-" + dataInfo.getArchiveId());
+                    if (!aBoolean) {
+
+                        if(!aBoolean){
+                            RedisTemplate.opsForValue().set("sign-" + dataInfo.getArchiveId(), "1", 7200, TimeUnit.SECONDS);
+                            CompletableFuture<Void> runAsync = CompletableFuture.runAsync(() -> {
+                                try {
+                                    /*===============执行批量任务===============*/
+                                    signTaskBatch(dataInfo);
+                                } catch (Exception e) {
+                                    e.printStackTrace();
+                                }
+                            }, executor);
+                        }
+                    }
+                }
+            }
+        }
+
+        System.out.println("队列数量" + executor.getQueue().size());
+        System.out.println("活跃数量" + executor.getActiveCount());
+        System.out.println("总共数量" + executor.getTaskCount());
+        System.out.println("完成数量" + executor.getCompletedTaskCount());
+    }
+
+    public void signTaskBatch(TaskArchiveSplitVO taskSign) {
+        try {
+            String fileUrl = taskSign.getFileUrl();
+            String archiveId = taskSign.getArchiveId();
+            String id = taskSign.getId();
+            // 获取pdf第一页的数据
+            String firstUrl = FileUtils.getSysLocalFileUrl()+"archiveSplit/"+archiveId+"_001.pdf";
+            getPdfByPage(2,2,fileUrl,firstUrl);
+            // 保存第一页为300DPI图片
+            String imagePath = FileUtils.getSysLocalFileUrl() + "archiveSplit/" + archiveId + "_001.png";
+            savePdfAsImage(1, firstUrl, imagePath);
+
+        } catch (Exception e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    public void getPdfByPage(int startPage, int endPage, String filePath, String savePath) {
+        try {
+            InputStream inputStreamByUrl = FileUtils.getInputStreamByUrl(filePath);
+            // 加载PDF文件
+            PDDocument document = PDDocument.load(inputStreamByUrl);
+
+            // 创建新文档
+            PDDocument newDocument = new PDDocument();
+
+            // 注意:PDFBox中的页面索引从0开始
+            int actualStart = Math.max(0, startPage - 1); // 将用户输入的1转换为0
+            int actualEnd = Math.min(document.getNumberOfPages() - 1, endPage - 1); // 将用户输入的10转换为9
+
+            // 添加指定范围的页面
+            for (int i = actualStart; i <= actualEnd; i++) {
+                PDPage page = document.getPage(i);
+                newDocument.addPage(page);
+            }
+
+            // 保存为新文件
+            newDocument.save(savePath);
+            newDocument.close();
+            document.close();
+        } catch (Exception e) {
+            log.error("提取PDF页面失败", e);
+            throw new RuntimeException("提取PDF页面失败", e);
+        }
+    }
+
+    public void savePdfAsImage(int pageNum, String filePath, String outputPath) {
+        try (InputStream inputStream = FileUtils.getInputStreamByUrl(filePath);
+             PDDocument document = PDDocument.load(inputStream)) {
+
+            // 验证页码范围
+            if (pageNum < 1 || pageNum > document.getNumberOfPages()) {
+                throw new IllegalArgumentException("无效的页码");
+            }
+
+            PDFRenderer renderer = new PDFRenderer(document);
+
+            // 设置DPI为300
+            final int DPI = 300;
+
+            // 渲染指定页面(注意PDFBox使用0-based索引)
+            BufferedImage image = renderer.renderImage(pageNum - 1, DPI / 72f);
+
+            // 确保输出目录存在
+            File outputFile = new File(outputPath);
+            outputFile.getParentFile().mkdirs();
+
+            // 保存为PNG格式(可改为JPG等)
+            ImageIO.write(image, "PNG", outputFile);
+            log.info("PDF页面已成功保存为图片: {}", outputPath);
+        } catch (Exception e) {
+            log.error("PDF转图片失败", e);
+            throw new RuntimeException("PDF转图片失败", e);
+        }
+    }
+}

+ 1 - 1
blade-service/blade-e-visa/src/main/java/org/springblade/evisa/controller/Chek.java

@@ -56,7 +56,7 @@ public class  Chek {
 
 
 
-    @Scheduled(cron = "0/10 * * * * ?")
+   // @Scheduled(cron = "0/10 * * * * ?")
     public void SignInfo() {
         // 质检SQL
        // String sql = "select id,file_url as eVisaPdfUrl from u_archive_file where length(file_url)!=char_length(file_url) and file_name not in('封面.pdf','封面1.pdf','卷内目录.pdf','卷内目录1.pdf','背脊.pdf','背脊1.pdf','备考表.pdf','备考表1.pdf') and is_deleted<>10  and  contract_id in(1890322575534399490,1890328157624541186,1887771910584999937) and file_url is not null and file_url like '%.pdf%' LIMIT 30  ";

+ 1 - 1
blade-service/blade-e-visa/src/main/java/org/springblade/evisa/controller/EVController.java

@@ -58,7 +58,7 @@ public class EVController {
     @Resource(name = "taskExecutor1")
     private ThreadPoolExecutor executor;
 
-  //  @Scheduled(cron = "0/10 * * * * ?")
+    @Scheduled(cron = "0/10 * * * * ?")
     public void SignInfo() {
         //执行代码
 

+ 0 - 1
blade-service/blade-e-visa/src/main/java/org/springblade/evisa/service/impl/EVisaServiceImpl.java

@@ -794,7 +794,6 @@ public class EVisaServiceImpl implements EVisaService {
         if ("20".equals(sys_isonline) || SystemUtils.isWindows() || SystemUtils.isMacOs()) {
             url = "http://219.151.181.73:9125/FrontSys/SealServicezx/FileSignByKeyWord";
         }
-
         String sysLocalFileUrl = FileUtils.getSysLocalFileUrl();
         String filecode = SnowFlakeUtil.getId() + "";
         String dataFileUrl = sysLocalFileUrl + "/pdf/" + filecode + ".pdf";

+ 0 - 2
blade-service/blade-e-visa/src/main/java/org/springblade/evisa/utils/PDFUtils.java

@@ -10,8 +10,6 @@ import java.io.File;
 import java.io.FileInputStream;
 import java.io.InputStream;
 import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Comparator;
 import java.util.List;
 import java.util.regex.Pattern;
 import java.util.stream.Collectors;

+ 2 - 2
blade-service/blade-manager/pom.xml

@@ -234,11 +234,11 @@
                     <target>${java.version}</target>
                     <encoding>${project.build.sourceEncoding}</encoding>
                     <compilerArguments>
-                        <bootclasspath>${java.home}/lib/rt.jar:${java.home}/lib/jce.jar:${java.home}/lib/jsse.jar
+                        <bootclasspath>${java.home}/lib/rt.jar;${java.home}/lib/jce.jar;${java.home}/lib/jsse.jar
                         </bootclasspath>
                     </compilerArguments>
                 </configuration>
             </plugin>
         </plugins>
     </build>
-</project>
+</project>

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

@@ -261,7 +261,7 @@ public class ArchiveTreeContractController extends BladeController {
                 newTrees.add(tree.get(0));
                 tree = newTrees;
             }
-            archiveTreeContractService.fillDefaultArchiveAutoInfo(tree, projectId);
+            archiveTreeContractService.fillDefaultArchiveAutoInfo(tree, projectId,contractId);
             return R.data(tree);
         }
         return R.fail(200, "未查询到信息");

+ 38 - 4
blade-service/blade-manager/src/main/java/org/springblade/manager/controller/ArchiveTreeController.java

@@ -12,12 +12,18 @@ import org.springblade.core.mp.support.Condition;
 import org.springblade.core.secure.BladeUser;
 import org.springblade.core.secure.utils.AuthUtil;
 import org.springblade.core.tool.api.R;
+import org.springblade.core.tool.utils.BeanUtil;
 import org.springblade.core.tool.utils.Func;
 import org.springblade.manager.dto.ArchiveTreeContractAutoRuleMapDTO;
 import org.springblade.manager.dto.ArchiveTreeDTO;
 import org.springblade.manager.dto.ArchiveTreeSortDTO;
+import org.springblade.manager.entity.WbsTree;
 import org.springblade.manager.service.IArchiveTreeContractService;
 import org.springblade.manager.vo.ArchiveTreeVO2;
+import org.springblade.manager.vo.ArchiveTreeVO3;
+import org.springframework.jdbc.core.BeanPropertyRowMapper;
+import org.springframework.jdbc.core.JdbcTemplate;
+import org.springframework.scheduling.annotation.Scheduled;
 import org.springframework.web.bind.annotation.*;
 import org.springframework.web.bind.annotation.RequestParam;
 import org.springblade.manager.entity.ArchiveTree;
@@ -40,6 +46,8 @@ public class ArchiveTreeController extends BladeController {
 
     private final IArchiveTreeContractService archiveTreeContractService;
 
+    private final JdbcTemplate jdbcTemplate;
+
     /**
      * 初始化归档树根节点
      */
@@ -92,10 +100,36 @@ public class ArchiveTreeController extends BladeController {
     @ApiOperation(value = "修改", notes = "传入ArchiveTree")
     public R update(@Valid @RequestBody ArchiveTree archiveTree) {
         archiveTree.setFullName(archiveTree.getNodeName());
-        if (archiveTree.getProjectId() != null && archiveTree.getProjectId() > 0) {
+        if(archiveTree.getProjectId()==null||archiveTree.getProjectId()==0){
+            //先查出所有引用了该系统级的项目级节点
+            String sql="select * from m_archive_tree where from_id="+archiveTree.getId()+" and is_deleted=0";
+            List<ArchiveTree> query = jdbcTemplate.query(sql, new BeanPropertyRowMapper<>(ArchiveTree.class));
+            if(query.size()>0){
+                for (ArchiveTree tree : query) {
+                    tree.setNodeType(archiveTree.getNodeType());
+                    tree.setPostType(archiveTree.getPostType());
+                    tree.setAssociationType(archiveTree.getAssociationType());
+                    tree.setMajorDataType(archiveTree.getMajorDataType());
+                    tree.setDisplayHierarchy(archiveTree.getDisplayHierarchy());
+                    tree.setIsStorageNode(archiveTree.getIsStorageNode());
+                    tree.setIsBuiltDrawing(archiveTree.getIsBuiltDrawing());
+                    tree.setIsInterfaceNode(archiveTree.getIsInterfaceNode());
+                    tree.setProjectType(archiveTree.getProjectType());
+                    tree.setStorageType(archiveTree.getStorageType());
+                    tree.setExpDataType(archiveTree.getExpDataType());
+                    tree.setArchiveAutoType(archiveTree.getArchiveAutoType());
+                    tree.setArchiveAutoNodeId(archiveTree.getArchiveAutoNodeId());
+                    tree.setArchiveAutoGroupId(archiveTree.getArchiveAutoGroupId());
+                    tree.setArchiveAutoGroupSelect(archiveTree.getArchiveAutoGroupSelect());
+                    tree.setIsUploadFileDisplayConfigurationTree(archiveTree.getIsUploadFileDisplayConfigurationTree());
+                    tree.setStorageTime(archiveTree.getStorageTime());
+                    archiveTreeService.updateById(tree);
+                    archiveTreeContractService.UpdateByArchiveTree(tree);
+                }
+            }
+        }else if (archiveTree.getProjectId() != null && archiveTree.getProjectId() > 0) {
             archiveTreeContractService.UpdateByArchiveTree(archiveTree);
         }
-
         return R.status(archiveTreeService.updateById(archiveTree));
     }
 
@@ -149,9 +183,9 @@ public class ArchiveTreeController extends BladeController {
             @ApiImplicitParam(name = "nodeType", value = "'null'=全加载 '1'=关联电子原生文件类型树 '2'=文件上传类型树"),
             @ApiImplicitParam(name = "wbsId", value = "对应的wbs树,用于展示关联质检节点下的"),
     })
-    public R<List<ArchiveTreeVO2>> tree(Long projectId, Integer disPlayTree, Integer nodeType, String wbsId) {
+    public R<List<ArchiveTreeVO3>> tree(Long projectId, Integer disPlayTree, Integer nodeType, String wbsId) {
 
-        List<ArchiveTreeVO2> tree = archiveTreeService.tree2(AuthUtil.getTenantId(), projectId, disPlayTree, nodeType, wbsId, true);
+        List<ArchiveTreeVO3> tree = archiveTreeService.tree3(AuthUtil.getTenantId(), projectId, disPlayTree, nodeType, wbsId, true);
         if (tree != null && tree.size() > 0) {
             return R.data(tree);
         }

+ 10 - 98
blade-service/blade-manager/src/main/java/org/springblade/manager/controller/ExcelTabController.java

@@ -547,7 +547,7 @@ public class ExcelTabController extends BladeController {
         // 复制模版htmlURL
         File file_in = ResourceUtil.getFile(excelTab.getHtmlUrl());
         String filecode = SnowFlakeUtil.getId() + "";
-        String thmlUrl = file_path + "/privateUrlCopy/" + aPrivate.getProjectId()+"/"+filecode + ".html";
+        String thmlUrl = file_path + "privateUrlCopy/" + aPrivate.getProjectId()+"/"+filecode + ".html";
         File file_out = ResourceUtil.getFile(thmlUrl);
         if(!file_out.exists()){
             FileUtils.ensureFileExists(thmlUrl);
@@ -2359,13 +2359,13 @@ public class ExcelTabController extends BladeController {
             @ApiImplicitParam(name = "String pkeyId", value = "当前表pKeyId"),
             @ApiImplicitParam(name = "recordTime", value = "当前选择的填写日期,即右侧日期控件所选日期,格式为 yyyy-MM-dd")
     })
-    public R<String> getTheLogPdInfo(String pkeyId, String nodePrimaryKeyId, String recordTime, String contractId) throws Exception {
+    public R<String> getTheLogPdInfo(String pkeyId, String nodePrimaryKeyId, String recordTime, String contractId,Long createUser) throws Exception {
         //获取配置的路径
         String file_path = FileUtils.getSysLocalFileUrl();
         if (StringUtils.isEmpty(recordTime)) {
             recordTime = DateUtil.format(DateUtil.now(), "yyyy-MM-dd");
         }
-        List<ContractLog> contractLogList = this.contractLogClient.queryContractLogByPrimaryKeyIdAndRecordTimeList(nodePrimaryKeyId, recordTime, contractId);
+        List<ContractLog> contractLogList = this.contractLogClient.queryContractLogByPrimaryKeyIdAndRecordTimeList(nodePrimaryKeyId, recordTime, contractId,createUser);
         List<String> ids = contractLogList.stream().map(ContractLog::getId).map(String::valueOf).collect(Collectors.toList());
         if (ids.size() > 0) {
             //PDF路径
@@ -2528,10 +2528,10 @@ public class ExcelTabController extends BladeController {
                                                             myData = dataDate[0].replace("\"", "") + "-" + dataDate[1].trim().replace("\"", "");
                                                         }
                                                     } else {
-                                                        myData = Func.convert(dataDate, String.class).replaceAll(" ", "");
+                                                        myData = Func.convert(dataDate, String.class).replaceAll(" ", "").replaceAll(",","、");
                                                         if (myData.startsWith("[") && myData.endsWith("]")) {
                                                             // 去掉两端的中括号
-                                                            myData = myData.substring(1, myData.length() - 1);
+                                                            myData=myData.replaceAll("\\[","").replaceAll("]","");
                                                         }
                                                     }
 
@@ -2672,7 +2672,7 @@ public class ExcelTabController extends BladeController {
             }
             dataIds = ids.stream().filter(Objects::nonNull).collect(Collectors.joining(","));
         } else {
-            List<ContractLog> contractLogs = this.contractLogClient.queryContractLogByPrimaryKeyIdAndRecordTimeList(nodePrimaryKeyId, recordTime, contractId);
+            List<ContractLog> contractLogs = this.contractLogClient.queryContractLogByPrimaryKeyIdAndRecordTimeList(nodePrimaryKeyId, recordTime, contractId,null);
             if (contractLogs.size() == 0) {
                 logId2 = "";
             } else {
@@ -2821,7 +2821,6 @@ public class ExcelTabController extends BladeController {
                         e.printStackTrace();
                     }
                     for (Map<String, Object> mysqlData : businessDataMap) {
-
                         String querySqlx = "SELECT tree_primary_key_id as primaryKeyId,title as path from u_contract_log_wbs where  business_id ='" + dataId + "' and is_deleted = 0";
                         List<Map<String, Object>> businessDat = this.jdbcTemplate.queryForList(querySqlx);
                         reData.put("linkTabIds", businessDat);
@@ -2865,7 +2864,8 @@ public class ExcelTabController extends BladeController {
                                             reData.put(key + "__" + tabData[1], strings);
                                         } else {
                                             if (tabVal.contains("[") && tabVal.contains("]")) {
-                                                reData.put(key + "__" + tabData[1], tabData);
+                                                String[] strings = new String[]{tabData[0].replaceAll("\\[","").replaceAll("]","")};
+                                                reData.put(key + "__" + tabData[1],strings);
                                             } else {
                                                 reData.put(key + "__" + tabData[1], tabData[0]);
                                             }
@@ -3110,7 +3110,7 @@ public class ExcelTabController extends BladeController {
                     return fail("没有数据可复制");
                 } else {
                     //查询当前所在日期日志记录
-                    List<ContractLog> contractLogs = this.contractLogClient.queryContractLogByPrimaryKeyIdAndRecordTimeList(nodePrimaryKeyId, currentTime, contractId);
+                    List<ContractLog> contractLogs = this.contractLogClient.queryContractLogByPrimaryKeyIdAndRecordTimeList(nodePrimaryKeyId, currentTime, contractId,null);
                     if (ObjectUtil.isEmpty(contractLogs)) {
                         String id = this.contractLogClient.saveContractLog(new SaveContractLogVO(
                                 dataIds,
@@ -3483,7 +3483,7 @@ public class ExcelTabController extends BladeController {
             //保存日志
             data = this.excelTabService.saveOrUpdateTheLog(tableInfoList);
         }
-        this.getTheLogPdInfo(pkeyId, nodePrimaryKeyId, recordTime, contractId);
+        this.getTheLogPdInfo(pkeyId, nodePrimaryKeyId, recordTime, contractId,null);
         return R.data(data);
     }
 
@@ -4424,96 +4424,8 @@ public class ExcelTabController extends BladeController {
         }
     }
 
-    //@Scheduled(cron = "0 01 15 * * ?")
-    //检查excel路径有错的
-    public void cheackExcel() throws IOException {
-        StringBuilder result=new StringBuilder("");
-        String sql = "Select * from m_excel_tab where parent_id=0 and is_deleted=0";
-        List<ExcelTab> query = jdbcTemplate.query(sql, new BeanPropertyRowMapper<>(ExcelTab.class));
-        for (ExcelTab excelTab : query) {
-            String sql1 = "Select * from m_excel_tab where parent_id=" + excelTab.getId() + " and is_deleted=0";
-            List<ExcelTab> query1 = jdbcTemplate.query(sql1, new BeanPropertyRowMapper<>(ExcelTab.class));
-            for (ExcelTab tab : query1) {
-                String sql2 = "Select * from m_excel_tab where parent_id=" + tab.getId() + " and is_deleted=0";
-                List<ExcelTab> query2 = jdbcTemplate.query(sql2, new BeanPropertyRowMapper<>(ExcelTab.class));
-                List<String> names = new ArrayList<>();
-                for (ExcelTab excelTab1 : query2) {
-                    if (excelTab1.getFileUrl() != null) {
-                        if (excelTab1.getFileUrl().endsWith(".xlsx") || excelTab1.getFileUrl().endsWith(".xls")) {
-                            long resourceLength = CommonUtil.getResourceLength(excelTab1.getFileUrl());
-                            if (resourceLength <= 500) {
-                                names.add(excelTab1.getName());
-                                result.append(excelTab.getName() + "--" + tab.getName() + "--" + excelTab1.getName()+"\n");
-                            }
-                        }
-                    }
-                }
-            }
-        }
-    }
 
-    /**
-     * 检查清表html是否存在,不存在就下载重新上传
-     * 如果excel都不存在,就输出出来
-     * @throws Exception
-     */
-    //@Scheduled(cron = "00 13 10 * * ?")
-    public void checkHtmlIsExist() throws Exception {
-        StringBuilder result=new StringBuilder("");
-        StringBuilder result1=new StringBuilder("");
-        String sql = "Select * from m_excel_tab where parent_id=0 and is_deleted=0";
-        List<ExcelTab> query = jdbcTemplate.query(sql, new BeanPropertyRowMapper<>(ExcelTab.class));
-        String excelPath="E:\\excel\\";
-        try {
-            for (ExcelTab excelTab : query) {
-                String sql1 = "Select * from m_excel_tab where parent_id=" + excelTab.getId() + " and is_deleted=0";
-                List<ExcelTab> query1 = jdbcTemplate.query(sql1, new BeanPropertyRowMapper<>(ExcelTab.class));
-                for (ExcelTab tab : query1) {
-                    String sql2 = "Select * from m_excel_tab where parent_id=" + tab.getId() + " and is_deleted=0 and file_url is not null ";
-                    List<ExcelTab> query2 = jdbcTemplate.query(sql2, new BeanPropertyRowMapper<>(ExcelTab.class));
-                    for (ExcelTab excelTab1 : query2) {
-                        if(!signFtpUtil.isExist(excelTab1.getHtmlUrl())){
-                            if(excelTab1.getFileUrl() != null&&excelTab1.getFileUrl().endsWith(".xlsx") || excelTab1.getFileUrl().endsWith(".xls")){
-                                long resourceLength = CommonUtil.getResourceLength(excelTab1.getFileUrl());
-                                if(resourceLength>=500){
-                                    //先下载这个文件,再上传
-                                    String fileUrl = excelTab1.getFileUrl();
-                                    String localPath=excelPath+excelTab1.getId()+".xlsx";
-                                    InputStream inputStreamByUrl = FileUtils.getInputStreamByUrl(fileUrl);
-                                    FileUtils.saveFile(inputStreamByUrl,localPath);
-                                    File file = new File(localPath);
-                                    if(file.exists()){
-                                        Map<String, Object> paramMap = new HashMap<>();
-                                        paramMap.put("nodeId", excelTab1.getId());
-                                        paramMap.put("type",2);
-                                        HashMap<String,String> headers=new HashMap<>();
-                                        headers.put("Content-Type", "multipart/form-data; boundary=----WebKitFormBoundary4tcP4daRPIFDBRvm");
-                                        headers.put("Authorization","Basic c2FiZXI6c2FiZXJfc2VjcmV0");
-                                        headers.put("Blade-auth","bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ0ZW5hbnRfaWQiOiIwMDAwMDAiLCJ1c2VyX25hbWUiOiJjciIsInJlYWxfbmFtZSI6IumZiOeEtiIsImF2YXRhciI6IiIsImF1dGhvcml0aWVzIjpbImFkbWluaXN0cmF0b3IiXSwiY2xpZW50X2lkIjoiY2xpZW50Iiwicm9sZV9uYW1lIjoiYWRtaW5pc3RyYXRvciIsImxpY2Vuc2UiOiJwb3dlcmVkIGJ5IGJsYWRleCIsInBvc3RfaWQiOiIiLCJ1c2VyX2lkIjoiMTkxMjcwMTM4Mzk4MjQyNDA2NSIsInJvbGVfaWQiOiIxMTIzNTk4ODE2NzM4Njc1MjAxIiwicGhvbmUiOiIxNTIxNTA1Mjc4NiIsInNjb3BlIjpbImFsbCJdLCJuaWNrX25hbWUiOiLpmYjnhLYiLCJvYXV0aF9pZCI6IiIsImRldGFpbCI6eyJ0eXBlIjoid2ViIn0sImV4cCI6MTc0NjY4ODQxOCwiZGVwdF9pZCI6IjE1MzY5ODMwNTYzNjIzODEzMTMiLCJqdGkiOiI3ZjEwY2U0NC1lOWE2LTRlYjMtYjBjYi1iYTJlY2U2MDk3ZjAiLCJhY2NvdW50IjoiY3IifQ.2v68wLgQvCUXanrNdXE6WPnXSrnjjW6mmepPgeWbAMo");
-                                        headers.put("Tenant-Id","000000");
-                                        String url="http://testmanger.hcxxy.com/api/blade-manager/exceltab/put-file-attach";
-                                        String body = HttpUtil.createPost(url).addHeaders(headers).form(paramMap).form("file", file).execute().body();
-                                        Map map = JSON.parseObject(body, Map.class);
-                                        if((int)map.get("code")!=200){
-                                            result1.append(excelTab.getName() + "--" + tab.getName() + "--" + excelTab1.getName()+"\n");
-                                        }
-                                    }
-                                }else {
-                                    result.append(excelTab.getName() + "--" + tab.getName() + "--" + excelTab1.getName()+"\n");
-                                }
-                            }
-                        }
-                    }
-                }
-            }
-        } catch (Exception e) {
-            throw new RuntimeException(e);
-        }
 
-        System.out.println("完成");
-        System.out.println(result);
-        System.out.println(result1);
-    }
     @GetMapping("/checkParamElement")
     @ApiOperationSupport(order = 30)
     @ApiOperation(value = "检查参数元素", notes = "检查参数元素")

+ 677 - 0
blade-service/blade-manager/src/main/java/org/springblade/manager/controller/HtmlTableToExcelConverter.java

@@ -0,0 +1,677 @@
+package org.springblade.manager.controller;
+
+import org.apache.poi.ss.usermodel.*;
+import org.apache.poi.ss.util.CellRangeAddress;
+import org.apache.poi.ss.util.RegionUtil;
+import org.apache.poi.xssf.usermodel.XSSFWorkbook;
+import org.jsoup.Jsoup;
+import org.jsoup.nodes.Document;
+import org.jsoup.nodes.Element;
+import org.jsoup.select.Elements;
+import org.springblade.core.tool.utils.IoUtil;
+import org.springblade.core.tool.utils.StringUtil;
+import org.springblade.manager.utils.FileUtils;
+
+import java.io.FileOutputStream;
+import java.io.InputStream;
+import java.util.*;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import java.util.stream.Collectors;
+
+public class HtmlTableToExcelConverter {
+
+//    public static void main(String[] args) throws Exception {
+//        String html = "D:\\tools\\html\\1927983851351572480.html";
+//
+//
+//        InputStream inputStreamByUrl = FileUtils.getInputStreamByUrl(html);
+//        String htmlString = IoUtil.readToString(inputStreamByUrl);
+//
+//        convertHtmlTableToExcel(htmlString);
+//
+//
+//    }
+
+    public static Workbook convertHtmlTableToExcel(String html) throws Exception {
+        Document doc = Jsoup.parse(html);
+        Element table = doc.select("table").first();
+
+        // 创建Excel工作簿
+        Workbook workbook = new XSSFWorkbook();
+        Sheet sheet = workbook.createSheet("Sheet1");
+
+        // 设置默认列宽(字符宽度)
+        sheet.setDefaultColumnWidth(10);
+
+        // 存储列宽(单位:字符)
+        Map<Integer, Float> columnWidths = new HashMap<>();
+
+        // 样式缓存
+        Map<String, CellStyle> styleCache = new HashMap<>();
+        Map<String, Font> fontCache = new HashMap<>();
+        // 预解析CSS样式
+        Map<String, String> cssRules = parseCssRules(doc);
+
+        // 合并区域跟踪列表
+        List<CellRangeAddress> mergedRegions = new ArrayList<>();
+        // 合并区域是否存在边框
+        Map<CellRangeAddress, CellStyle> mergedFrame = new HashMap<>();
+        // 单元格占用跟踪器
+        Map<Integer, Set<Integer>> occupiedCells = new HashMap<>();
+
+        int excelRowNum = 0;
+        for (Element tr : table.select("tr")) {
+            // 跳过空行
+            if (tr.children().isEmpty()) {
+                excelRowNum++;
+                continue;
+            }
+
+            // 创建行并设置默认行高(比默认值小)
+            Row excelRow = sheet.createRow(excelRowNum);
+
+
+            // 初始化当前行占用集合
+            occupiedCells.putIfAbsent(excelRowNum, new HashSet<>());
+
+            int excelColNum = 0;
+
+
+            //是否设置行高
+            Boolean isHeight = false;
+
+            for (Element td : tr.select("td")) {
+
+                //设置行高
+                String style1 = td.attr("style");
+                if (!isHeight && StringUtil.isNotBlank(style1)) {
+                    List<String> collect = Arrays.stream(style1.split(";")).collect(Collectors.toList());
+                    HashMap<String, String> map = new HashMap<>();
+                    collect.forEach(s -> {
+                        map.put(s.split(":")[0], s.split(":")[1]);
+                    });
+
+                    String height = map.get("height");
+                    Float rowHeight = 16f; // 默认16点
+                    if (StringUtil.isNotBlank(height)) {
+                        isHeight = true;
+                        height = height.replace("px", "");
+                        try {
+                            Float px = Float.valueOf(height);
+                            rowHeight = px * 0.75f; // 像素转点 (1px ≈ 0.75pt)
+                        } catch (Exception ignored) {
+                            ignored.printStackTrace();
+                        }
+
+                        excelRow.setHeightInPoints(rowHeight);
+                    }
+                }
+
+
+                // 跳过已被占用的单元格
+                while (isCellOccupied(occupiedCells, excelRowNum, excelColNum)) {
+                    excelColNum++;
+                }
+
+                // 处理列跨度和行跨度
+                int colspan = getSpan(td, "colspan");
+                int rowspan = getSpan(td, "rowspan");
+
+                // 获取单元格内容
+                String cellText = extractCellText(td);
+
+                // 创建单元格
+                Cell cell = excelRow.createCell(excelColNum);
+                cell.setCellValue(cellText);
+
+                // 应用样式
+                String styleKey = getCellStyleKey(td, cssRules);
+                if (!styleCache.containsKey(styleKey)) {
+                    CellStyle style = createCellStyle(workbook, td, cssRules, fontCache);
+                    styleCache.put(styleKey, style);
+
+                    // 检查是否需要自动换行
+                    if (shouldWrapText(td, cssRules, cellText)) {
+                        style.setWrapText(true);
+                    }
+                }
+                cell.setCellStyle(styleCache.get(styleKey));
+
+                // 记录列宽(优先使用HTML中的宽度)
+                if (td.hasAttr("width")) {
+                    String widthStr = td.attr("width").replace("px", "");
+                    try {
+                        float px = Float.parseFloat(widthStr);
+                        float charWidth = px / 7f; // 像素转字符宽度 (1字符≈7px)
+
+                        // 考虑跨列情况:总宽度分配到各列
+                        for (int i = 0; i < colspan; i++) {
+                            int colIdx = excelColNum + i;
+                            float perColWidth = charWidth / colspan;
+
+                            // 取最大宽度作为列宽
+                            columnWidths.putIfAbsent(colIdx, 0f);
+                            if (perColWidth > columnWidths.get(colIdx)) {
+                                columnWidths.put(colIdx, perColWidth);
+                            }
+                        }
+                    } catch (NumberFormatException ignored) {
+                    }
+                }
+
+                // 标记当前单元格占据的所有位置
+                markCellsAsOccupied(occupiedCells, excelRowNum, excelColNum, rowspan, colspan);
+
+                // 创建合并区域
+                if (colspan > 1 || rowspan > 1) {
+                    CellRangeAddress region = new CellRangeAddress(
+                            excelRowNum,
+                            excelRowNum + rowspan - 1,
+                            excelColNum,
+                            excelColNum + colspan - 1
+                    );
+
+                    // 检查是否与现有区域重叠
+                    if (!isOverlapping(mergedRegions, region)) {
+                        sheet.addMergedRegion(region);
+                        mergedRegions.add(region);
+                        CellStyle cellStyle = styleCache.get(styleKey);
+                        mergedFrame.put(region, cellStyle);
+                        // 为合并区域设置边框(使用左上角单元格的样式)
+//                        setMergedRegionBorders(workbook, sheet, region, styleCache.get(styleKey));
+                    }
+                }
+
+                excelColNum += colspan;
+            }
+            excelRowNum++;
+        }
+        // 修复合并单元格边框问题
+        fixMergedRegionBorders(workbook, sheet, mergedRegions, mergedFrame);
+
+        // 应用列宽
+        for (Map.Entry<Integer, Float> entry : columnWidths.entrySet()) {
+            int colIdx = entry.getKey();
+            float width = entry.getValue();
+
+            // 限制列宽范围(0.5-100字符)
+            if (width < 0.5f) width = 0.5f;
+            if (width > 100f) width = 100f;
+
+            // 转换字符宽度为Excel单位(1字符=256单位)
+            sheet.setColumnWidth(colIdx, (int) (width * 256));
+        }
+
+        // 自动调整未设置宽度的列
+        int maxColumn = columnWidths.keySet().stream().max(Integer::compare).orElse(0) + 1;
+        for (int i = 0; i < maxColumn; i++) {
+            if (!columnWidths.containsKey(i)) {
+                sheet.autoSizeColumn(i);
+                // 限制自动调整的最大宽度
+                int currentWidth = sheet.getColumnWidth(i);
+                if (currentWidth > 30 * 256) {
+                    sheet.setColumnWidth(i, 30 * 256);
+                }
+            }
+        }
+
+        // 调整行高以适应换行文本
+        adjustRowHeights(sheet);
+
+        // 写入文件
+//        try (FileOutputStream fos = new FileOutputStream("D:\\tools\\html\\234.xlsx")) {
+//            workbook.write(fos);
+//        }
+//        workbook.close();
+
+        return workbook;
+    }
+
+    // 修复合并单元格边框问题(使用指定样式)
+    private static void setMergedRegionBorders(Workbook workbook, Sheet sheet,
+                                               CellRangeAddress region, CellStyle style) {
+        // 设置合并区域的边框样式
+        RegionUtil.setBorderTop(style.getBorderTopEnum(), region, sheet);
+        RegionUtil.setBorderRight(style.getBorderRightEnum(), region, sheet);
+        RegionUtil.setBorderBottom(style.getBorderBottomEnum(), region, sheet);
+        RegionUtil.setBorderLeft(style.getBorderLeftEnum(), region, sheet);
+
+        // 设置边框颜色
+        RegionUtil.setTopBorderColor(style.getTopBorderColor(), region, sheet);
+        RegionUtil.setRightBorderColor(style.getRightBorderColor(), region, sheet);
+        RegionUtil.setBottomBorderColor(style.getBottomBorderColor(), region, sheet);
+        RegionUtil.setLeftBorderColor(style.getLeftBorderColor(), region, sheet);
+
+        // 特殊处理:确保内部单元格边框完整
+        int firstRow = region.getFirstRow();
+        int lastRow = region.getLastRow();
+        int firstCol = region.getFirstColumn();
+        int lastCol = region.getLastColumn();
+
+        // 对于多行多列的合并区域,需要额外设置内部边框
+        if (lastRow - firstRow > 0 || lastCol - firstCol > 0) {
+            // 设置内部水平边框
+            for (int r = firstRow; r <= lastRow; r++) {
+                Row excelRow = sheet.getRow(r);
+                if (excelRow == null) continue;
+
+                for (int c = firstCol; c <= lastCol; c++) {
+                    Cell cell = excelRow.getCell(c);
+                    if (cell == null) continue;
+
+                    CellStyle cellStyle = cell.getCellStyle();
+
+                    // 设置顶部边框(如果是区域的第一行)
+                    if (r == firstRow) {
+                        cellStyle.setBorderTop(style.getBorderTopEnum());
+                    }
+
+                    // 设置底部边框(如果是区域的最后一行)
+                    if (r == lastRow) {
+                        cellStyle.setBorderBottom(style.getBorderBottomEnum());
+                    }
+
+                    // 设置左侧边框(如果是区域的第一列)
+                    if (c == firstCol) {
+                        cellStyle.setBorderLeft(style.getBorderLeftEnum());
+                    }
+
+                    // 设置右侧边框(如果是区域的最后一列)
+                    if (c == lastCol) {
+                        cellStyle.setBorderRight(style.getBorderRightEnum());
+                    }
+                }
+            }
+        }
+    }
+
+    // 修复合并单元格边框问题
+    private static void fixMergedRegionBorders(Workbook workbook, Sheet sheet, List<CellRangeAddress> mergedRegions, Map<CellRangeAddress, CellStyle> mergedFrame) {
+        for (CellRangeAddress region : mergedRegions) {
+            CellStyle cellStyle = mergedFrame.get(region);
+            BorderStyle borderTopEnum = cellStyle.getBorderTopEnum();
+            BorderStyle borderBottomEnum = cellStyle.getBorderBottomEnum();
+            BorderStyle borderLeftEnum = cellStyle.getBorderLeftEnum();
+            BorderStyle borderRightEnum = cellStyle.getBorderRightEnum();
+            // 设置合并区域的外边框
+            if (borderTopEnum != BorderStyle.NONE) {
+                RegionUtil.setBorderTop(BorderStyle.THIN, region, sheet);
+                RegionUtil.setTopBorderColor(IndexedColors.BLACK.getIndex(), region, sheet);
+            }
+            if (borderBottomEnum != BorderStyle.NONE) {
+                RegionUtil.setBorderBottom(BorderStyle.THIN, region, sheet);
+                RegionUtil.setRightBorderColor(IndexedColors.BLACK.getIndex(), region, sheet);
+            }
+            if (borderLeftEnum != BorderStyle.NONE) {
+                RegionUtil.setBorderLeft(BorderStyle.THIN, region, sheet);
+                RegionUtil.setBottomBorderColor(IndexedColors.BLACK.getIndex(), region, sheet);
+            }
+            if (borderRightEnum != BorderStyle.NONE) {
+                RegionUtil.setBorderRight(BorderStyle.THIN, region, sheet);
+                RegionUtil.setLeftBorderColor(IndexedColors.BLACK.getIndex(), region, sheet);
+            }
+        }
+    }
+
+
+    // 新增方法:检查是否需要自动换行
+    private static boolean shouldWrapText(Element td, Map<String, String> cssRules, String cellText) {
+        // 1. 检查内联样式
+        String style = td.attr("style");
+        if (style != null && style.toLowerCase().contains("overflow-wrap") ||
+                style != null && style.toLowerCase().contains("word-wrap") ||
+                style != null && style.toLowerCase().contains("white-space") ||
+                style != null && style.toLowerCase().contains("line-break") ||
+                style != null && style.toLowerCase().contains("hyphens")) {
+            return true;
+        }
+
+        // 2. 检查CSS类样式
+        String classes = td.attr("class");
+        for (String cls : classes.split(" ")) {
+            String selector = "." + cls;
+            if (cssRules.containsKey(selector)) {
+                String css = cssRules.get(selector).toLowerCase();
+                if (css.contains("overflow-wrap") ||
+                        css.contains("word-wrap") ||
+                        css.contains("white-space") ||
+                        css.contains("line-break") ||
+                        css.contains("hyphens")) {
+                    return true;
+                }
+            }
+        }
+
+        // 3. 默认不自动换行(除非内容中有换行符)
+        return cellText.contains("\n");
+    }
+
+
+    // 新增方法:调整行高以适应换行文本
+    private static void adjustRowHeights(Sheet sheet) {
+        for (int rowNum = 0; rowNum <= sheet.getLastRowNum(); rowNum++) {
+            Row row = sheet.getRow(rowNum);
+            if (row == null) continue;
+
+            // 计算该行所需的最大行高
+            int maxLines = 1;
+            for (Cell cell : row) {
+                if (cell.getCellStyle().getWrapText()) {
+                    String text = cell.getStringCellValue();
+                    if (text != null) {
+                        int lines = text.split("\n").length;
+                        if (lines > maxLines) maxLines = lines;
+                    }
+                }
+            }
+
+            // 根据行数调整行高(每行约16点)
+            if (maxLines > 1) {
+                float newHeight = row.getHeightInPoints() * (maxLines * 0.8f);
+                row.setHeightInPoints(Math.max(row.getHeightInPoints(), newHeight));
+            }
+        }
+    }
+
+
+    // 辅助方法:检查单元格是否被占用
+    private static boolean isCellOccupied(Map<Integer, Set<Integer>> occupiedCells, int row, int col) {
+        if (!occupiedCells.containsKey(row)) {
+            return false;
+        }
+        return occupiedCells.get(row).contains(col);
+    }
+
+
+    // 辅助方法:标记占用单元格
+    private static void markCellsAsOccupied(Map<Integer, Set<Integer>> occupiedCells,
+                                            int startRow, int startCol,
+                                            int rowspan, int colspan) {
+        for (int r = startRow; r < startRow + rowspan; r++) {
+            for (int c = startCol; c < startCol + colspan; c++) {
+                occupiedCells.putIfAbsent(r, new HashSet<>());
+                occupiedCells.get(r).add(c);
+            }
+        }
+    }
+
+    // 辅助方法:检查区域重叠
+    private static boolean isOverlapping(List<CellRangeAddress> existingRegions, CellRangeAddress newRegion) {
+        for (CellRangeAddress region : existingRegions) {
+            if (region.intersects(newRegion)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    // 辅助方法:获取跨行/跨列值
+    private static int getSpan(Element element, String attr) {
+        String span = element.attr(attr);
+        return span.isEmpty() ? 1 : Integer.parseInt(span);
+    }
+
+    // 辅助方法:提取单元格文本内容
+    private static String extractCellText(Element td) {
+        //复选框
+        Elements select = td.select("hc-form-checkbox-group");
+        if(select.size() > 0){
+            Element element = select.get(0);
+            return "□ " + element.attr("placeholder");
+        }
+
+
+        // 优先获取直接文本内容
+        if (!td.ownText().isEmpty()) {
+            return td.ownText().trim();
+        }
+
+
+        return "";
+    }
+
+    // 辅助方法:解析CSS规则
+    private static Map<String, String> parseCssRules(Document doc) {
+        Map<String, String> rules = new HashMap<>();
+        Elements styles = doc.select("style");
+
+        for (Element style : styles) {
+            String css = style.data();
+            // 简化解析:提取类样式
+            Pattern pattern = Pattern.compile("(\\.[^{]+)\\s*\\{([^}]+)\\}");
+            Matcher matcher = pattern.matcher(css);
+
+            while (matcher.find()) {
+                String selector = matcher.group(1).trim();
+                String properties = matcher.group(2).trim();
+                rules.put(selector, properties);
+            }
+        }
+        return rules;
+    }
+
+    // 辅助方法:获取单元格样式键
+    private static String getCellStyleKey(Element td, Map<String, String> cssRules) {
+        StringBuilder key = new StringBuilder();
+        String classes = td.attr("class");
+
+        for (String cls : classes.split(" ")) {
+            String selector = "." + cls;
+            if (cssRules.containsKey(selector)) {
+                key.append(cssRules.get(selector)).append(";");
+            }
+        }
+
+        key.append(td.attr("style"));
+        return key.toString();
+    }
+
+    // 修改后的辅助方法:创建Excel单元格样式
+    private static CellStyle createCellStyle(Workbook workbook, Element td,
+                                             Map<String, String> cssRules,
+                                             Map<String, Font> fontCache) {
+        CellStyle style = workbook.createCellStyle();
+        Font font = workbook.createFont();
+
+        // 设置默认字体(避免过大)
+        font.setFontName("宋体");
+
+        String classes = td.attr("class");
+
+        // 应用CSS类样式
+        for (String cls : classes.split(" ")) {
+            String selector = "." + cls;
+            if (cssRules.containsKey(selector)) {
+//                applyCssStyle(style, font, cssRules.get(selector));
+            }
+        }
+
+        // 应用内联样式
+        applyCssStyle(style, font, td.attr("style"));
+
+        // 限制最大字体大小
+        if (font.getFontHeightInPoints() > 16) {
+            font.setFontHeightInPoints((short) 16);
+        }
+
+        // 字体缓存
+        String fontKey = font.getFontName() + font.getFontHeightInPoints() + font.getBold();
+        if (!fontCache.containsKey(fontKey)) {
+            Font newFont = workbook.createFont();
+            newFont.setFontName(font.getFontName());
+            newFont.setFontHeightInPoints(font.getFontHeightInPoints());
+            newFont.setBold(font.getBold());
+            fontCache.put(fontKey, newFont);
+        }
+        style.setFont(fontCache.get(fontKey));
+
+        // 设置边框(细线)
+//        style.setBorderTop(BorderStyle.THIN);
+//        style.setBorderBottom(BorderStyle.THIN);
+//        style.setBorderLeft(BorderStyle.THIN);
+//        style.setBorderRight(BorderStyle.THIN);
+//        style.setTopBorderColor(IndexedColors.BLACK.getIndex());
+//        style.setBottomBorderColor(IndexedColors.BLACK.getIndex());
+//        style.setLeftBorderColor(IndexedColors.BLACK.getIndex());
+//        style.setRightBorderColor(IndexedColors.BLACK.getIndex());
+
+        return style;
+    }
+
+    // 辅助方法:应用CSS样式
+    private static void applyCssStyle(CellStyle style, Font font, String css) {
+        if (css == null || css.isEmpty()) return;
+
+        String[] properties = css.split(";");
+        for (String prop : properties) {
+            String[] parts = prop.split(":");
+            if (parts.length < 2) continue;
+
+            String key = parts[0].trim().toLowerCase();
+            String value = parts[1].trim().toLowerCase();
+
+            switch (key) {
+                case "background-color":
+                    setBackgroundColor(style, value);
+                    break;
+                case "font-family":
+                    font.setFontName(value);
+                    break;
+                case "font-size":
+                    setFontSize(font, value);
+                    break;
+                case "font-weight":
+                    if ("bold".equals(value)) {
+                        font.setBold(true);
+                    }
+                    break;
+                case "text-align":
+                    setAlignment(style, value);
+                    break;
+                case "vertical-align":
+                    setVerticalAlignment(style, value);
+                    break;
+                case "white-space":
+                    // 这个属性在shouldWrapText方法中处理
+                    break;
+                // 处理边框样式
+                case "border-top-style":
+                    style.setBorderTop(mapBorderStyle(value));
+                    break;
+                case "border-right-style":
+                    style.setBorderRight(mapBorderStyle(value));
+                    break;
+                case "border-bottom-style":
+                    style.setBorderBottom(mapBorderStyle(value));
+                    break;
+                case "border-left-style":
+                    style.setBorderLeft(mapBorderStyle(value));
+                    break;
+                case "border-style": // 简写属性,设置所有边框
+                    style.setBorderTop(mapBorderStyle(value));
+                    style.setBorderRight(mapBorderStyle(value));
+                    style.setBorderBottom(mapBorderStyle(value));
+                    style.setBorderLeft(mapBorderStyle(value));
+                    break;
+                // 处理边框宽度
+                case "border-top-width":
+                case "border-right-width":
+                case "border-bottom-width":
+                case "border-left-width":
+                    // POI中边框宽度由BorderStyle控制,这里忽略具体数值
+                    break;
+            }
+        }
+    }
+
+    // 辅助方法:映射CSS边框样式到POI的BorderStyle
+    private static BorderStyle mapBorderStyle(String cssStyle) {
+        switch (cssStyle.toLowerCase()) {
+            case "solid":
+                return BorderStyle.THIN;
+            case "dashed":
+                return BorderStyle.DASHED;
+            case "dotted":
+                return BorderStyle.DOTTED;
+            case "double":
+                return BorderStyle.DOUBLE;
+            case "thick":
+                return BorderStyle.MEDIUM;
+            case "none":
+                return BorderStyle.NONE;
+            default:
+                return BorderStyle.THIN; // 默认为细线
+        }
+    }
+
+    // 辅助方法:设置背景色
+    private static void setBackgroundColor(CellStyle style, String color) {
+        // 简化处理:只处理rgb格式
+        if (color.startsWith("rgb(")) {
+            String[] rgb = color.substring(4, color.length() - 1).split(",");
+            if (rgb.length == 3) {
+                // 实际应用中应使用IndexedColors或自定义颜色
+                style.setFillForegroundColor(IndexedColors.GREY_25_PERCENT.getIndex());
+                style.setFillPattern(FillPatternType.SOLID_FOREGROUND);
+            }
+        }
+    }
+
+    // 修改后的辅助方法:设置字体大小(添加上限)
+    private static void setFontSize(Font font, String size) {
+        if (size == null || size.isEmpty()) return;
+
+        if (size.endsWith("pt")) {
+            try {
+                float pt = Float.parseFloat(size.substring(0, size.length() - 2));
+                // 限制最大字体大小为16pt
+                if (pt > 16) pt = 16;
+                font.setFontHeightInPoints((short) pt);
+            } catch (NumberFormatException ignored) {
+            }
+        } else if (size.endsWith("px")) {
+            try {
+                float px = Float.parseFloat(size.substring(0, size.length() - 2));
+                // 将像素转换为点 (1pt ≈ 1.33px)
+                float pt = px / 1.33f;
+                if (pt > 16) pt = 16;
+                font.setFontHeightInPoints((short) pt);
+            } catch (NumberFormatException ignored) {
+            }
+        }
+    }
+
+    // 辅助方法:设置水平对齐
+    private static void setAlignment(CellStyle style, String align) {
+        switch (align.toLowerCase()) {
+            case "center":
+                style.setAlignment(HorizontalAlignment.CENTER);
+                break;
+            case "left":
+                style.setAlignment(HorizontalAlignment.LEFT);
+                break;
+            case "right":
+                style.setAlignment(HorizontalAlignment.RIGHT);
+                break;
+            case "justify":
+                style.setAlignment(HorizontalAlignment.JUSTIFY);
+                break;
+        }
+    }
+
+    // 辅助方法:设置垂直对齐
+    private static void setVerticalAlignment(CellStyle style, String align) {
+        switch (align.toLowerCase()) {
+            case "center":
+                style.setVerticalAlignment(VerticalAlignment.CENTER);
+                break;
+            case "top":
+                style.setVerticalAlignment(VerticalAlignment.TOP);
+                break;
+            case "bottom":
+                style.setVerticalAlignment(VerticalAlignment.BOTTOM);
+                break;
+        }
+    }
+}

+ 25 - 136
blade-service/blade-manager/src/main/java/org/springblade/manager/controller/WbsTreeContractController.java

@@ -26,6 +26,7 @@ import org.jsoup.nodes.Element;
 import org.jsoup.select.Elements;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
+import org.springblade.common.utils.CommonUtil;
 import org.springblade.common.utils.SnowFlakeUtil;
 import org.springblade.core.boot.ctrl.BladeController;
 import org.springblade.core.log.exception.ServiceException;
@@ -65,6 +66,7 @@ import java.util.*;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 import java.util.stream.Collectors;
+import org.springframework.http.ContentDisposition;
 
 @RestController
 @AllArgsConstructor
@@ -345,18 +347,10 @@ public class WbsTreeContractController extends BladeController {
                 WbsTreePrivate treePrivateTab = jdbcTemplate.query("select * from m_wbs_tree_private where p_key_id = " + pKeyId, new BeanPropertyRowMapper<>(WbsTreePrivate.class)).stream().findAny().orElse(null);
                 if (treePrivateTab != null && treePrivateTab.getHtmlUrl() != null) {
                     htmlUrl = treePrivateTab.getHtmlUrl();
-                    //<开始>-----------本地测试  下载html到本地
-//                    htmlUrl = FileUtils.getNetUrl(htmlUrl);
-//                    String localFilePath = "D:\\file\\downfile\\1792757075013533696.html";
-//                    downloadHtmlAndSave(htmlUrl, localFilePath);
-//                    htmlUrl =localFilePath;
-                    //本地测试  下载html到本地-----------<结束>
                     fileName = ObjectUtil.isNotEmpty(treePrivateTab.getFullName()) ? treePrivateTab.getFullName() : treePrivateTab.getNodeName();
                 }
             } else {
                 htmlUrl = tab.getHtmlUrl();
-//                htmlUrl = "C:\\Users\\泓创研发01\\Desktop\\fsdownload\\1783774897227431936.html";
-//                htmlUrl="D:\\web\\html\\1848904722870697984.html";
                 fileName = ObjectUtil.isNotEmpty(tab.getFullName()) ? tab.getFullName() : tab.getNodeName();
             }
 
@@ -364,134 +358,25 @@ public class WbsTreeContractController extends BladeController {
                 throw new ServiceException("未获取到对应的表的html信息");
             }
 
-            //将html转换为excel
-            ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
-            LoadOptions lo = new LoadOptions(LoadFormat.HTML);
-            workbook = new Workbook(htmlUrl,lo);
-//            InputStream inputStreamByUrl = FileUtils.getInputStreamByUrl(htmlUrl);
-//            workbook = new com.spire.xls.Workbook();
-//            workbook.loadFromHtml(inputStreamByUrl);
-//            workbook.loadFromHtml("D:\\BaiduNetdiskDownload\\1783381225877012480.html");
-            workbook.save(byteArrayOutputStream, SaveFormat.XLSX);
-
-            //将转换的spireExcel存储到流中
-            byte[] excelBytes = byteArrayOutputStream.toByteArray();
-
-            //把spireExcel转为poiExcel
-            try (InputStream inputStream = new ByteArrayInputStream(excelBytes)) {
-                org.apache.poi.ss.usermodel.Workbook poiWorkbook = new XSSFWorkbook(inputStream);
-                Sheet poiSheet = poiWorkbook.getSheetAt(0); //获取第一个工作表
-                //存储需要修改的单元格和相关信息的列表
-                List<CellModificationInfo> cellsToModify = new ArrayList<>();
-                //解析html 获取合并单元格
-                InputStream inputStreamByUrl = FileUtils.getInputStreamByUrl(tab.getHtmlUrl());
-                String htmlString = IoUtil.readToString(inputStreamByUrl);
-                Document doc = Jsoup.parse(htmlString);
-                Element table = doc.select("table").first();
-                Elements rows = table.select("tr");
-                //最大列数
-                int maxColumns = calculateMaxColumns(rows);
-                List<CellRangeAddress> mergedRegions = new ArrayList<>();
-                // 保存需要保留的单元格内容和样式
-                Map<CellRangeAddress, String> data = new HashMap<>();
-                // 记录每个单元格的位置和合并信息
-                for (Element row1 : rows) {
-                    Elements cells = row1.select("td, th");
-                    for (Element cell : cells) {
-
-                        int rowspan = cell.hasAttr("rowspan") ? Integer.parseInt(cell.attr("rowspan")) : -1;
-                        int colspan = cell.hasAttr("colspan") ? Integer.parseInt(cell.attr("colspan")) : -1;
-                        int x1 = cell.hasAttr("x1") ? Integer.parseInt(cell.attr("x1")) - 1 : -1;//起始列
-                        int x2 = cell.hasAttr("x2") ? Integer.parseInt(cell.attr("x2")) - 1 : -1;//结束列
-                        int y1 = cell.hasAttr("y1") ? Integer.parseInt(cell.attr("y1")) - 1 : -1;//起始行
-                        int y2 = cell.hasAttr("y2") ? Integer.parseInt(cell.attr("y2")) - 1 : -1;//结束行
-                        // 记录合并区域
-                        if (x1 != -1 && x2 != -1 && y1 != -1 && y2 != -1) {
-                            if(rowspan != -1 || colspan != -1){
-                                CellRangeAddress region = new CellRangeAddress(y1, y2, x1, x2);
-                                mergedRegions.add(region);
-                                data.put(region, cell.text());
-                            }
-                        }
-                    }
-                }
-                // 按顺序合并单元格(从上到下、从左到右)
-                for (int i = poiSheet.getNumMergedRegions() - 1; i >= 0; i--) {
-                    poiSheet.removeMergedRegion(i);
-                }
-                for (CellRangeAddress region : mergedRegions) {
-                    poiSheet.addMergedRegion(region);
-                }
-
-                for (Row row : poiSheet) {
-                    //判断当前行是否是最大列 如果不是 就补充到最大列
-                    short lastCellNum = row.getLastCellNum();
-                    if(maxColumns > lastCellNum){
-                        for (int i = maxColumns - 1; i > lastCellNum; i--) {
-                            row.createCell(i);
-                            Cell cell = row.getCell(i);
-                            //设置新单元格的样式为第一个单元格的样式
-                            cell.setCellStyle(row.getCell(0).getCellStyle());
-                        }
-                    }
-                    for (Cell cell : row) {
-                        int cellType = cell.getCellType();
-                        if (cellType == CellType.STRING.getCode() && ObjectUtil.isNotEmpty(cell.getStringCellValue())) {
-                            //存储需要修改的单元格信息
-                            cellsToModify.add(new CellModificationInfo(cell, cell.getStringCellValue().trim()));
-                        }
-                        //获取单元格所属的合并单元格区域
-                        CellRangeAddress mergedRegion = findMergedRegion(poiSheet, cell.getRowIndex(), cell.getColumnIndex());
-                        if (mergedRegion != null) {
-                            //合并单元格的数据 为之前记录的数据
-                            cell.setCellValue(data.get(mergedRegion));
-
-                            //存储需要修改的合并单元格信息
-                            cellsToModify.add(new CellModificationInfo(cell, mergedRegion));
-                        }
-                    }
-                }
-
-                //遍历结束后,实际修改单元格样式和内容
-                for (CellModificationInfo info : cellsToModify) {
-                    Cell cell = info.getCell();
-                    //只更新非合并单元格的数据
-                    if (info.getMergedRegion() == null && info.hasStringContent()) {
-                        cell.setCellValue(info.getStringContent());
-                    }
-                    //复制单元格样式
-                    CellStyle cellStyle = poiWorkbook.createCellStyle();
-                    CellStyle sourceCellStyle = cell.getCellStyle(); //获取原单元格的样式
-                    cellStyle.cloneStyleFrom(sourceCellStyle); //复制样式
-                    setBlackBorder(cellStyle); //设置边框
-                    cell.setCellStyle(cellStyle);
-
-//                    if (info.hasMergedRegion()) { //修改合并单元格边框线
-//                        CellRangeAddress mergedRegion = info.getMergedRegion();
-//                        RegionUtil.setBorderTop(BorderStyle.THIN, mergedRegion, poiSheet);
-//                        RegionUtil.setTopBorderColor(IndexedColors.BLACK.getIndex(), mergedRegion, poiSheet);
-//                        RegionUtil.setBorderBottom(BorderStyle.THIN, mergedRegion, poiSheet);
-//                        RegionUtil.setBottomBorderColor(IndexedColors.BLACK.getIndex(), mergedRegion, poiSheet);
-//                        RegionUtil.setBorderLeft(BorderStyle.THIN, mergedRegion, poiSheet);
-//                        RegionUtil.setLeftBorderColor(IndexedColors.BLACK.getIndex(), mergedRegion, poiSheet);
-//                        RegionUtil.setBorderRight(BorderStyle.THIN, mergedRegion, poiSheet);
-//                        RegionUtil.setRightBorderColor(IndexedColors.BLACK.getIndex(), mergedRegion, poiSheet);
-//                    }
-                }
-
-                //返回响应
-                try (ServletOutputStream outputStream = response.getOutputStream();
-                     ByteArrayOutputStream byteArrayOutputStreamResult = new ByteArrayOutputStream()) {
-                    //设置响应头
-                    response.setHeader("Content-Disposition", "attachment; filename=" + URLEncoder.encode(fileName, "UTF-8") + ".xlsx");
-                    response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
-                    poiWorkbook.write(byteArrayOutputStreamResult);
-                    byte[] excelBytesResult = byteArrayOutputStreamResult.toByteArray();
-                    outputStream.write(excelBytesResult);
-                } catch (IOException e) {
-                    logger.error("下载excel时出现异常:" + e.getMessage(), e);
-                    e.printStackTrace();
-                }
+            InputStream inputStreamByUrl = FileUtils.getInputStreamByUrl(htmlUrl);
+            String htmlString = IoUtil.readToString(inputStreamByUrl);
+            //将html转换为excel]
+            org.apache.poi.ss.usermodel.Workbook workbook1 = HtmlTableToExcelConverter.convertHtmlTableToExcel(htmlString);
+
+
+            //返回响应
+            try (ServletOutputStream outputStream = response.getOutputStream();
+                 ByteArrayOutputStream byteArrayOutputStreamResult = new ByteArrayOutputStream()) {
+                //文件编码处理
+                String encode = URLEncoder.encode(fileName, "UTF-8");
+                encode = encode.replaceAll( "\\+", " ");
+                encode = encode.replaceAll( "%2B", "+");
+                //设置响应头
+                response.setHeader("Content-Disposition", "attachment; filename=" + encode + ".xlsx");
+                response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
+                workbook1.write(byteArrayOutputStreamResult);
+                byte[] excelBytesResult = byteArrayOutputStreamResult.toByteArray();
+                outputStream.write(excelBytesResult);
             } catch (IOException e) {
                 logger.error("下载excel时出现异常:" + e.getMessage(), e);
                 e.printStackTrace();
@@ -505,6 +390,10 @@ public class WbsTreeContractController extends BladeController {
             }
         }
     }
+
+
+
+
     // 计算最大列数以对齐所有行
     private static int calculateMaxColumns(Elements rows) {
         return rows.stream()

+ 28 - 10
blade-service/blade-manager/src/main/java/org/springblade/manager/controller/WbsTreePrivateController.java

@@ -860,17 +860,35 @@ public class WbsTreePrivateController extends BladeController {
     @GetMapping("/getTitleRange")
     @ApiOperationSupport(order = 33)
     @ApiOperation(value = "获取题名范围",notes = "获取题名范围")
-    public R<List<TitleRangeVo>> getTitleRange(@RequestParam String projectId){
+    public R<List<TitleRangeVo>> getTitleRange(@RequestParam String projectId,@RequestParam(required = false) Long nameId){
         List<WbsTreePrivate>list=wbsTreeService.getTitleRange(projectId);
         List<WbsParam> list1 = iWbsParamService.getBaseMapper().selectList(Wrappers.<WbsParam>lambdaQuery().eq(WbsParam::getK, "FILE_TITLE").eq(WbsParam::getProjectId, projectId));
         if(list1.size()>0){
-            List<Long> longs = list1.stream().filter(o->o.getNameType()!=null&&o.getNameType()==2).map(l -> l.getNodeId()).collect(Collectors.toList());
-            //判断是否已经被选中
-            for (WbsTreePrivate wbsTreePrivate : list) {
-                if(longs.contains(wbsTreePrivate.getId())){
-                    wbsTreePrivate.setStatus(11);
+                //修改
+            if(nameId!=null){
+                Map<Long, Long> map = list1.stream()
+                    .filter(o -> o.getNameType() != null && o.getNameType() == 2)
+                    .collect(Collectors.toMap(
+                        WbsParam::getNodeId,   // key:nodeId
+                        WbsParam::getNameId    // value:nameId
+                    ));
+                //判断是否已经被选中
+                for (WbsTreePrivate wbsTreePrivate : list) {
+                    if(map.containsKey(wbsTreePrivate.getId())&& !Objects.equals(map.get(wbsTreePrivate.getId()), nameId)){
+                        wbsTreePrivate.setStatus(11);
+                    }
+                }
+            }else {
+                //新增
+                List<Long> longs = list1.stream().filter(o->o.getNameType()!=null&&o.getNameType()==2).map(l -> l.getNodeId()).collect(Collectors.toList());
+                //判断是否已经被选中
+                for (WbsTreePrivate wbsTreePrivate : list) {
+                    if(longs.contains(wbsTreePrivate.getId())){
+                        wbsTreePrivate.setStatus(11);
+                    }
                 }
             }
+
         }
         return R.data(list.stream()
             .map(wbsTreePrivate -> {
@@ -962,8 +980,8 @@ public class WbsTreePrivateController extends BladeController {
     public String getNameRuleV(String string){
         // 定义工程名称到C格式的映射
         Map<String, String> mapping = new HashMap<>();
-        mapping.put("单位工程", "C0");
-        mapping.put("单位工程", "C1");
+        mapping.put("单位工程类型", "C0");
+        mapping.put("单位工程", "C1");
         mapping.put("分部工程", "C2");
         mapping.put("子分部工程", "C3");
         mapping.put("分项工程", "C4");
@@ -984,8 +1002,8 @@ public class WbsTreePrivateController extends BladeController {
     public String getNameRuleV1(String string){
         // 定义工程名称到C格式的映射
         Map<String, String> mapping = new HashMap<>();
-        mapping.put("C0", "单位工程");
-        mapping.put("C1", "单位工程");
+        mapping.put("C0", "单位工程类型");
+        mapping.put("C1", "单位工程");
         mapping.put("C2", "分部工程");
         mapping.put("C3", "子分部工程");
         mapping.put("C4", "分项工程");

+ 30 - 9
blade-service/blade-manager/src/main/java/org/springblade/manager/feign/ExcelTabClientImpl.java

@@ -142,10 +142,20 @@ public class ExcelTabClientImpl implements ExcelTabClient {
                             BladeFile bladeFile = newIOSSClient.uploadFile(id + "2.pdf", pdfPath);
                             if (bladeFile != null) {
                                 List<InformationQuery> query2 = jdbcTemplate.query("select id from u_information_query where classify ='" + type + "' and wbs_id ='" + id + "' and contract_id ='" + contractId + "'", new BeanPropertyRowMapper<>(InformationQuery.class));
+                                StringBuilder names=new StringBuilder("");
+                                if(StringUtils.isNotEmpty(dto.getReportNo())){
+                                    names.append("[");
+                                    names.append(dto.getReportNo());
+                                    names.append("]");
+                                }
+                                if(StringUtils.isNotEmpty(dto.getTrialProjectName())){
+                                    names.append(dto.getTrialProjectName());
+                                }
+                                names.append("试验检测报告及附件");
                                 if (query2.size() > 0) {
-                                    jdbcTemplate.execute("update u_information_query set pdf_url ='" + bladeFile.getLink() + "', name ='" + (StringUtils.isNotEmpty(dto.getTrialProjectName()) ? dto.getTrialProjectName() : "") + "'  where classify='" + type + "' and  wbs_id='" + id + "' and contract_id ='" + contractId + "'");
+                                    jdbcTemplate.execute("update u_information_query set pdf_url ='" + bladeFile.getLink() + "', name ='" + names + "'  where classify='" + type + "' and  wbs_id='" + id + "' and contract_id ='" + contractId + "'");
                                 } else {
-                                    informationQueryClient.saveData(id.toString(), projectId, contractId, type.toString(), bladeFile.getLink(), (StringUtils.isNotEmpty(dto.getTrialProjectName()) ? dto.getTrialProjectName() : ""));
+                                    informationQueryClient.saveData(id.toString(), projectId, contractId, type.toString(), bladeFile.getLink(), names.toString());
                                 }
                             }
                         }
@@ -205,6 +215,7 @@ public class ExcelTabClientImpl implements ExcelTabClient {
         String groupId = table.getString("groupId");
         String contractId = table.getString("contractId");
         String pkeyId = table.getString("pkeyId");
+        String entrustInfoName = table.getString("entrustInfoName");
         JSONArray dataArray = new JSONArray();
         dataArray.add(table);
 
@@ -220,7 +231,7 @@ public class ExcelTabClientImpl implements ExcelTabClient {
             //------试验填报数据保存,当前记录id作为groupId------
             this.excelTabService.saveOrUpdateInfoTrial(tableInfoList, Func.toLong(groupId));
 
-            pdfUrl = this.excelTabService.getEntrustPDFTrial(Func.toLong(pkeyId), contractId, Func.toLong(groupId));
+            pdfUrl = this.excelTabService.getEntrustPDFTrial(Func.toLong(pkeyId), contractId, Func.toLong(groupId),entrustInfoName);
 
         } catch (Exception e) {
             e.printStackTrace();
@@ -459,7 +470,7 @@ public class ExcelTabClientImpl implements ExcelTabClient {
     @Override
     public R saveReEntrustTabData(ReSigningEntrustDto dto, String header) {
         WbsTreePrivate wbsTreePrivate = jdbcTemplate.queryForObject("select * from m_wbs_tree_private where p_key_id=" + dto.getNodeId(), new BeanPropertyRowMapper<>(WbsTreePrivate.class));
-        Boolean isRemove=false;
+        Boolean isRemove=true;
         List<Map<String, Object>> list = excelTabService.getBussDataInfoTrialentrust(Long.parseLong(dto.getEntrustId()), wbsTreePrivate.getJlerTreeId(), Long.parseLong(dto.getContractId()), null, null,isRemove,false);
         Map<String, Object> map = list.get(0);
         if(!map.containsKey("contractId")){
@@ -481,8 +492,8 @@ public class ExcelTabClientImpl implements ExcelTabClient {
     }
 
     @Override
-    public void saveOrUpdate(ExcelTab detail) {
-        excelTabService.saveOrUpdate(detail);
+    public boolean saveOrUpdate(ExcelTab detail) {
+      return   excelTabService.saveOrUpdate(detail);
     }
 
     @Override
@@ -491,8 +502,18 @@ public class ExcelTabClientImpl implements ExcelTabClient {
     }
 
     @Override
-    public void excelInfo(InputStream inputStream, String exceUrl, String thmlUrl, String number) {
-        ExcelInfoUtils.excelInfo(inputStream, exceUrl, thmlUrl, number);
+    public void excelInfo(MultipartFile file, String exceUrl, String thmlUrl, String number) throws IOException {
+        ExcelInfoUtils.excelInfo(file.getInputStream(), exceUrl, thmlUrl, number);
+    }
+
+    @Override
+    public void saveLinkTab(Long excelId, Long pKeyId) throws IOException {
+        excelTabController.saveLinkeTab(excelId,pKeyId);
+    }
+
+    @Override
+    public void getTheLogPdInfo(String logPkeyId, String nodePrimaryKeyId, String recordTime, String contractId,Long createUser) throws Exception {
+        excelTabController.getTheLogPdInfo(logPkeyId, nodePrimaryKeyId, recordTime, contractId,createUser);
     }
 
 
@@ -526,7 +547,7 @@ public class ExcelTabClientImpl implements ExcelTabClient {
             }
             dataIds = ids.stream().filter(Objects::nonNull).collect(Collectors.joining(","));
         } else {
-            List<ContractLog> contractLogs = this.contractLogClient.queryContractLogByPrimaryKeyIdAndRecordTimeList(nodePrimaryKeyId, recordTime, contractId);
+            List<ContractLog> contractLogs = this.contractLogClient.queryContractLogByPrimaryKeyIdAndRecordTimeList(nodePrimaryKeyId, recordTime, contractId,null);
             if (contractLogs.size() == 0){
                 logId2="";
             }else {

+ 17 - 1
blade-service/blade-manager/src/main/java/org/springblade/manager/feign/FormulaClientImpl.java

@@ -49,7 +49,23 @@ public class FormulaClientImpl implements FormulaClient {
           return  "表id有误";
         }
         Map<String, String> keysMap = FormulaUtils.getElementCell(wtc.getHtmlUrl());
-        Long id = this.jdbcTemplate.queryForObject("select d.formula_id from m_wbs_tree_contract a join m_table_info b on a.init_table_name=b.tab_en_name join m_wbs_form_element c on c.f_id=b.id join m_element_formula_mapping d on c.id=d.element_id where a.p_key_id=" + pkId + " and c.e_key='" + key + "'  ORDER BY d.scope desc limit 1", Long.class);
+        String sql="SELECT d.formula_id \n" +
+            "FROM m_wbs_tree_contract a \n" +
+            "JOIN m_table_info b ON a.init_table_name = b.tab_en_name \n" +
+            "JOIN m_wbs_form_element c ON c.f_id = b.id \n" +
+            "JOIN m_element_formula_mapping d ON c.id = d.element_id \n" +
+            "WHERE a.p_key_id = "+pkId+"\n" +
+            "  AND c.e_key = '"+key+"' \n" +
+            "  AND (d.project_id = "+wtc.getProjectId()+" OR (d.project_id IS NULL))\n" +
+            "ORDER BY \n" +
+            "  CASE \n" +
+            "    WHEN d.project_id = "+wtc.getProjectId()+" THEN 0 \n" +
+            "    ELSE 1 \n" +
+            "  END,\n" +
+            "  d.scope DESC \n" +
+            "LIMIT 1";
+        // "select d.formula_id from m_wbs_tree_contract a join m_table_info b on a.init_table_name=b.tab_en_name join m_wbs_form_element c on c.f_id=b.id join m_element_formula_mapping d on c.id=d.element_id where a.p_key_id=" + pkId + " and c.e_key='" + key + "'  ORDER BY d.scope desc limit 1"
+        Long id = this.jdbcTemplate.queryForObject(sql, Long.class);
         if (Func.isNotEmpty(id)) {
             Formula formula = this.service.getById(id);
             if (Func.isNotEmpty(formula)) {

+ 6 - 0
blade-service/blade-manager/src/main/java/org/springblade/manager/feign/WbsParamClientImpl.java

@@ -3,6 +3,7 @@ package org.springblade.manager.feign;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import lombok.AllArgsConstructor;
 import org.springblade.manager.entity.WbsParam;
+import org.springblade.manager.entity.WbsTreeContract;
 import org.springblade.manager.service.IWbsParamService;
 import org.springframework.web.bind.annotation.RestController;
 
@@ -21,4 +22,9 @@ public class WbsParamClientImpl implements WbsParamClient{
     public WbsParam getWbsParam(Long nodeId) {
         return iWbsParamService.getBaseMapper().selectOne(Wrappers.lambdaQuery(WbsParam.class).eq(WbsParam::getNodeId, nodeId).eq(WbsParam::getType, 200).eq(WbsParam::getIsDeleted, 0).eq(WbsParam::getK,"FILE_TITLE"));
     }
+
+    @Override
+    public String createFileTitle(WbsTreeContract contract) {
+        return iWbsParamService.createFileTitle(contract);
+    }
 }

+ 3 - 0
blade-service/blade-manager/src/main/java/org/springblade/manager/formula/impl/ExecutorMeter.java

@@ -1775,6 +1775,9 @@ public class ExecutorMeter extends FormulaExecutor {
            /* List<String> numbers=  paymentsPeriodEnd.stream().map(Payment::getNumber).distinct().collect(Collectors.toList());*/
             LinkedHashMap<String,InventoryForm> numbersGroup=  tec.meterInfo.getInventoryForms().stream().filter(e->!tec.meterInfo.getChapter().contains(e)&&StringUtils.isNotEquals(0,e.getParentId())).collect(Collectors.toMap(InventoryForm::getFormNumber,e->e,(v1,v2)->v1,LinkedHashMap::new));
             numbersGroup.forEach((number, itf)->{
+                if(number.equals("410-2-4-3")){
+                    System.out.println("");
+                }
                 SubprojectInterimPaymentSummary sis = new SubprojectInterimPaymentSummary();
                 /*上期汇总*/
                 Summary pre =preSummary.get(number);

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

@@ -231,9 +231,13 @@
         d.contract_id,
         (SELECT CASE WHEN count(1) > 0 THEN 1 ELSE 0 END FROM m_archive_tree_contract WHERE parent_id = d.id and is_deleted = 0 and project_id = #{projectId})
         AS "has_children",
-        (SELECT  count(1)  FROM m_archive_tree_contract WHERE  is_deleted = 0 and project_id = #{projectId} and ancestors like CONCAT('%',d.id,'%')
+        (SELECT  count(1)  FROM m_archive_tree_contract a
+                        inner join u_archive_file b on b.node_id = a.id and b.is_deleted = a.is_deleted and b.project_id = a.project_id and (b.is_auto_file is null or b.is_auto_file != 1)
+                           WHERE  a.is_deleted = 0
+                             and a.project_id = #{projectId}
+                             and (FIND_IN_SET(d.id,a.ancestors) or a.id = d.id)
         <if test="code!=null and code!=''">
-            AND (tree_code = #{code} or tree_code = #{contractId} or parent_id = 0)
+            AND (a.tree_code = #{code} or a.tree_code = #{contractId} or a.parent_id = 0)
         </if>
         ) as tree_number
         FROM

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

@@ -6,6 +6,7 @@ import org.springblade.manager.vo.ArchiveTreeAutoRuleVO;
 import org.springblade.manager.vo.ArchiveTreeVO;
 import com.baomidou.mybatisplus.core.mapper.BaseMapper;
 import org.springblade.manager.vo.ArchiveTreeVO2;
+import org.springblade.manager.vo.ArchiveTreeVO3;
 
 import java.util.List;
 
@@ -18,6 +19,7 @@ public interface ArchiveTreeMapper extends BaseMapper<ArchiveTree> {
     List<ArchiveTreeVO2> lazyTree2(@Param("tenantId") String tenantId, @Param("projectId") Long projectId, @Param("parentId") Long parentId);
 
     List<ArchiveTreeVO2> tree2(@Param("tenantId") String tenantId, @Param("projectId") Long projectId, @Param("disPlayTree") Integer disPlayTree, @Param("nodeType") Integer nodeType);
+    List<ArchiveTreeVO3> tree3(@Param("tenantId") String tenantId, @Param("projectId") Long projectId, @Param("disPlayTree") Integer disPlayTree, @Param("nodeType") Integer nodeType);
 
     int updateBatch(@Param("diffRent") List<String> diffRent);
 

+ 36 - 0
blade-service/blade-manager/src/main/java/org/springblade/manager/mapper/ArchiveTreeMapper.xml

@@ -72,6 +72,17 @@
         <result column="interface_type" property="interfaceType"/>
         <result column="sort" property="sort"/>
     </resultMap>
+    <resultMap id="ArchiveTreeVOResultMap3" type="org.springblade.manager.vo.ArchiveTreeVO3">
+        <id column="id" property="id"/>
+        <result column="parent_id" property="parentId"/>
+        <result column="title" property="title"/>
+        <result column="value" property="value"/>
+        <result column="has_children" property="hasChildren"/>
+        <result column="displayHierarchy" property="displayHierarchy"/>
+        <result column="isDisplayTree" property="isDisplayTree"/>
+        <result column="association_type" property="associationType"/>
+        <result column="sort" property="sort"/>
+    </resultMap>
 
     <resultMap id="treeNodeResultMap" type="org.springblade.manager.vo.TreeNodeVO2">
         <id column="id" property="id"/>
@@ -282,6 +293,31 @@
         OR (parent_id = 0 and is_deleted = 0 AND project_id = #{projectId})
         ORDER BY sort
     </select>
+    <select id="tree3" resultMap="ArchiveTreeVOResultMap3">
+        SELECT
+        id,
+        parent_id,
+        node_name AS title,
+        display_hierarchy AS "displayHierarchy",
+        is_upload_file_display_configuration_tree AS "isDisplayTree",
+        association_type,
+        ( SELECT CASE WHEN count( 1 ) > 0 THEN 1 ELSE 0 END FROM m_archive_tree t2 WHERE t2.parent_id = t1 .id and
+        t2.node_type in (0, #{nodeType})) AS "has_children"
+        FROM m_archive_tree t1
+        WHERE is_deleted = 0 AND project_id = #{projectId}
+        <if test=" tenantId!=null and tenantId!='' ">
+            AND tenant_id = #{tenantId}
+        </if>
+        <if test=" disPlayTree!=null and disPlayTree!='' ">
+            AND is_upload_file_display_configuration_tree = 1
+        </if>
+        <if test=" nodeType !=null and nodeType !='' ">
+            /*根节点=0 关联电子原生文件=1 数字化上传文件=2*/
+            AND node_type in (0,#{nodeType})
+        </if>
+        OR (parent_id = 0 and is_deleted = 0 AND project_id = #{projectId})
+        ORDER BY sort
+    </select>
 
     <select id="getAllChildren" resultMap="ArchiveTreeVOResultMap">
         SELECT

+ 16 - 0
blade-service/blade-manager/src/main/java/org/springblade/manager/mapper/WbsFormElementMapper.java

@@ -12,6 +12,7 @@ import org.springblade.manager.entity.WbsTree;
 import org.springblade.manager.vo.WbsFormElementVO;
 
 import java.util.List;
+import java.util.Map;
 
 public interface WbsFormElementMapper extends BaseMapper<WbsFormElement> {
 
@@ -61,4 +62,19 @@ public interface WbsFormElementMapper extends BaseMapper<WbsFormElement> {
 
     //查询 元素与实体表字段不匹配的字段
     List<WbsFormElementDTO2> selColumnsByTabName(String parentId);
+
+    /**
+     * 查询表字段长度
+     * @param initTableName
+     * @return
+     */
+    List<Map<String, Object>> selectFiledLength(@Param("initTableName") String initTableName);
+
+    /**
+     * 查询指定字段最长数据的长度
+     * @param initTableName
+     * @param eKey
+     * @return
+     */
+    Integer selectFiledDataMaxLength(@Param("tableName") String initTableName,@Param("key") String eKey);
 }

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

@@ -166,5 +166,11 @@
     <select id="selColumnsByTabName" resultType="java.lang.String">
         SELECT data_type FROM information_schema.columns WHERE table_name=#{initTableName} AND column_name = #{eKey}
     </select>
+    <select id="selectFiledLength" resultType="java.util.Map">
+        select column_name `key`,character_octet_length length from INFORMATION_SCHEMA.COLUMNS  where table_name = #{initTableName}
+    </select>
+    <select id="selectFiledDataMaxLength" resultType="java.lang.Integer">
+        select MAX(LENGTH(${key})) from ${tableName}
+    </select>
 
 </mapper>

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

@@ -444,7 +444,7 @@
             html_url = #{aPrivate.htmlUrl}
         where type = 2
           and project_id = #{aPrivate.projectId}
-          and id = #{aPrivate.id};
+          and is_type_private_pid = #{aPrivate.pKeyId};
     </select>
 
     <select id="selectWbsTableOwnerRoleList" resultType="org.springblade.manager.entity.WbsTableOwnerRole">

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

@@ -99,7 +99,7 @@ public interface IArchiveTreeContractService extends BaseService<ArchiveTreeCont
 
     boolean deleteTree(Long id);
 
-    void fillDefaultArchiveAutoInfo(List<ArchiveTreeContractVO2> tree, Long projectId);
+    void fillDefaultArchiveAutoInfo(List<ArchiveTreeContractVO2> tree, Long projectId,Long contractId);
 
     void fillDefaultArchiveAutoInfo(List<ArchiveTreeContract> archiveTreeContracts);
 

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

@@ -8,6 +8,7 @@ import org.springblade.manager.vo.ArchiveTreeVO;
 import org.springblade.core.mp.base.BaseService;
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import org.springblade.manager.vo.ArchiveTreeVO2;
+import org.springblade.manager.vo.ArchiveTreeVO3;
 
 import java.util.List;
 import java.util.Map;
@@ -26,6 +27,7 @@ public interface IArchiveTreeService extends BaseService<ArchiveTree> {
     List<ArchiveTreeVO2> lazyTree2(String tenantId, Long projectId, Long parentId, Long extId, Long level);
 
     List<ArchiveTreeVO2> tree2(String tenantI, Long projectId, Integer disPlayTree, Integer nodeType, String wbsId, boolean bgetExtNodes);
+    List<ArchiveTreeVO3> tree3(String tenantI, Long projectId, Integer disPlayTree, Integer nodeType, String wbsId, boolean bgetExtNodes);
 
     List<ArchiveTree> selectByParentIdOrId(String id);
 
@@ -70,4 +72,6 @@ public interface IArchiveTreeService extends BaseService<ArchiveTree> {
 
     //删除子树
     boolean deleteTree(Long id);
+
+    List<ArchiveTreeVO2> getAllChildren(ArchiveTree node);
 }

+ 1 - 1
blade-service/blade-manager/src/main/java/org/springblade/manager/service/IExcelTabService.java

@@ -197,7 +197,7 @@ public interface IExcelTabService extends BaseService<ExcelTab> {
     /**
      * 试验委托单 生成 pdf
      */
-    String getEntrustPDFTrial(Long pKeyId, String contractId, Long groupId) throws Exception;
+    String getEntrustPDFTrial(Long pKeyId, String contractId, Long groupId,String entrustInfoName) throws Exception;
 
 
     // 添加

+ 8 - 6
blade-service/blade-manager/src/main/java/org/springblade/manager/service/impl/ArTreeContractInitServiceImpl.java

@@ -355,13 +355,15 @@ public class ArTreeContractInitServiceImpl {
                     addNodes.addAll(tmpList);
                 }else {
                     Long contractId = ar.getContractId();
-                    List<ContractRelationJlyz> list = contractInfoService.searchContractRelationInfo(contractId.toString());
-                    for (ContractRelationJlyz contractRelationJlyz: list) {
-                        ar.setContractId(contractRelationJlyz.getId());
-                        List<ArchiveTreeContract> tmpList = getTreeContractFromWbs(tenantId, projectId, wbsId, ar,classify);
-                        addNodes.addAll(tmpList);
+                    if (contractId != null) {
+                        List<ContractRelationJlyz> list = contractInfoService.searchContractRelationInfo(contractId.toString());
+                        for (ContractRelationJlyz contractRelationJlyz: list) {
+                            ar.setContractId(contractRelationJlyz.getId());
+                            List<ArchiveTreeContract> tmpList = getTreeContractFromWbs(tenantId, projectId, wbsId, ar,classify);
+                            addNodes.addAll(tmpList);
+                        }
+                        ar.setContractId(contractId);
                     }
-                    ar.setContractId(contractId);
                 }
             }
         }

+ 2 - 2
blade-service/blade-manager/src/main/java/org/springblade/manager/service/impl/ArchiveAutoRuleSyncImpl.java

@@ -253,7 +253,7 @@ public class ArchiveAutoRuleSyncImpl {
             if (contractVO2.getExtType() == null && fromId != null && archiveAutoType != null && archiveAutoType == 2) {
                 Long contract_groupId = contractVO2.getArchiveAutoGroupId();
                 //如果当前contractVO2的groupID是客户级(19位数),需要先保存关联集合
-                if (contract_groupId.toString().length() == 19) {
+                if (contract_groupId!=null&&contract_groupId.toString().length() == 19) {
                     //1.通过fromid找出项目级
                     ArchiveTreeVO2 proTreeVO2 = proMap.get(fromId);
                     //2.获取项目级groupID
@@ -332,7 +332,7 @@ public class ArchiveAutoRuleSyncImpl {
                         //分合同段的 给archiveAutoGroupId
                         Long groupId = contractVO2.getArchiveAutoGroupId();
                         //客户级的groupID用19位数字  系统级和项目级用16位数字
-                        if (groupId.toString().length() == 16) {
+                        if (groupId!=null&&groupId.toString().length() == 16) {
                             String key = "";
                             if (contractId == null) {
                                 key = groupId + "";

+ 68 - 13
blade-service/blade-manager/src/main/java/org/springblade/manager/service/impl/ArchiveTreeContractServiceImpl.java

@@ -27,6 +27,7 @@ import org.springblade.archive.entity.ArchiveExpertConclusion;
 import org.springblade.archive.feign.ArchiveAutoClient;
 import org.springblade.archive.vo.UpdateExpertVO;
 import org.springblade.business.feign.ArchiveFileClient;
+import org.springblade.common.utils.SnowFlakeUtil;
 import org.springblade.core.log.exception.ServiceException;
 import org.springblade.core.secure.BladeUser;
 import org.springblade.core.secure.utils.AuthUtil;
@@ -135,7 +136,7 @@ public class ArchiveTreeContractServiceImpl extends BaseServiceImpl<ArchiveTreeC
 		}
 
 
-		List<ArchiveTreeVO2> tree = archiveTreeService.tree2(AuthUtil.getTenantId(), projectId,null, null,null,false);
+		List<ArchiveTreeVO2> tree = archiveTreeService.getAllChildren(archiveTree);
 		if (tree == null || tree.size() == 0) {
 			return false;
 		}
@@ -430,8 +431,8 @@ public class ArchiveTreeContractServiceImpl extends BaseServiceImpl<ArchiveTreeC
 		}
 
 		//取出 -- 系统级 wbs树的数据
-		List<ArchiveTreeVO2> srcTrees = archiveTreeService.tree2(AuthUtil.getTenantId(), dstNode.getProjectId(),
-				null, null,null,false);
+//		List<ArchiveTreeVO2> srcTrees = archiveTreeService.tree2(AuthUtil.getTenantId(), dstNode.getProjectId(), null, null,null,false);
+		List<ArchiveTreeVO2> srcTrees = archiveTreeService.getAllChildren(srcNode);
 		ArchiveTreeVO2 srcTree = srcTrees.get(0);
 		if (srcTree == null) {
 			return false;
@@ -655,7 +656,7 @@ public class ArchiveTreeContractServiceImpl extends BaseServiceImpl<ArchiveTreeC
 
 						//getNormalSaveList 接口除了同步新增节点,还会同步已有节点的属性。
 						//因为关联工序的位置是固定的,先不考虑新增一个关联工序节点,且一次同步完成情况
-						tmpSaveList = archiveTreeContractSync.getNormalSaveListEx(srcNode.getId(),
+						tmpSaveList = archiveTreeContractSync.getNormalSaveListEx(tmpSubTree.getId(),
 								tmpSubTree,dstNodeId,contractNode);
 						saveList.addAll(tmpSaveList);
 
@@ -819,7 +820,7 @@ public class ArchiveTreeContractServiceImpl extends BaseServiceImpl<ArchiveTreeC
 	 * @param trees
 	 * @param projectId
 	 */
-	public  void  fillDefaultArchiveAutoInfo(List<ArchiveTreeContractVO2> trees,Long projectId){
+	public  void  fillDefaultArchiveAutoInfo(List<ArchiveTreeContractVO2> trees,Long projectId,Long contractId){
 
 		List<ContractInfo> contractInfos = contractInfoService.selectContractInfoPageByPid(projectId.toString());
 		if (contractInfos == null || contractInfos.size() == 0) {
@@ -834,11 +835,13 @@ public class ArchiveTreeContractServiceImpl extends BaseServiceImpl<ArchiveTreeC
 		}
 
 		for (ArchiveTreeContractVO2 child: trees) {
-			Long contractId = 0L;
+			Long contractId1 = 0L;
 			if (child.getContractId() != null ) {
-				contractId = child.getContractId();
-			}
-			ContractInfo contractInfo = contractMap.get(contractId);
+				contractId1 = child.getContractId();
+			}else {
+                contractId1 = contractId;
+            }
+			ContractInfo contractInfo = contractMap.get(contractId1);
 			if (contractInfo != null) {
 				fillDefaultArchiveAutoInfo(child,contractInfo);
 			}
@@ -867,7 +870,7 @@ public class ArchiveTreeContractServiceImpl extends BaseServiceImpl<ArchiveTreeC
 		}
 		if (StringUtils.isEmpty(node.getSpecification())) {
 			//默认30mm ,对应枚举 1
-			node.setSpecification("30");
+			node.setSpecification(contractInfo.getSpecification());
 		}
 		//没有默认
 		if (StringUtils.isEmpty(node.getArchiveNameSuffix())) {
@@ -883,7 +886,7 @@ public class ArchiveTreeContractServiceImpl extends BaseServiceImpl<ArchiveTreeC
 		if (archiveTreeContracts == null || archiveTreeContracts.size() == 0) {
 			return;
 		}
-		
+
 		Long projectId = archiveTreeContracts.get(0).getProjectId();
 		List<ContractInfo> contractInfos = contractInfoService.selectContractInfoPageByPid(projectId.toString());
 		if (contractInfos == null || contractInfos.size() == 0) {
@@ -1001,12 +1004,64 @@ public class ArchiveTreeContractServiceImpl extends BaseServiceImpl<ArchiveTreeC
 
 		for (ArchiveTreeVO2 src : srcChilds) {
 			if (dstMap.get(src.getId()) == null ) {
-				List<ArchiveTreeContract> tmpSaveList = archiveTreeContractSync.getNormalSaveListEx(src.getId(),src,dstNode.getId(),dstTree);
-				saveList.addAll(tmpSaveList);
+				boolean flag = false;
+				if (contractInfos != null && !contractInfos.isEmpty()) {
+					List<ArchiveTreeContract> tmpSaveList = new ArrayList<>();
+					flag = addNewContract1(contractInfos,src,dstTree,tmpSaveList);
+					saveList.addAll(tmpSaveList);
+				}
+				if (!flag) {
+					List<ArchiveTreeContract> tmpSaveList = archiveTreeContractSync.getNormalSaveListEx(src.getId(),src,dstNode.getId(),dstTree);
+					if (tmpSaveList != null) {
+						saveList.addAll(tmpSaveList);
+					}
+				}
 			}
 		}
 
 	}
+	boolean addNewContract1(List<ContractInfo> contractInfos,ArchiveTreeVO2 srcTree,ArchiveTreeContractVO2 dstTree,List<ArchiveTreeContract> saveList){
+
+		dstTree.setValue(1L);
+		ArchiveTreeContract contractNode = null;
+		ArchiveTreeContractVO2 destNode = null;
+		for(ContractInfo contractInfo : contractInfos){
+			List<ArchiveTreeContract> tmpSaveList = new ArrayList<>();
+
+			if (srcTree.getTitle().contains("施工单位归档资料") && contractInfo.getContractType() == 1) {
+				if (contractNode == null) {
+					contractNode = new ArchiveTreeContract(srcTree);
+					contractNode.setId(SnowFlakeUtil.getId());
+					contractNode.setParentId(dstTree.getId());
+					contractNode.setContractId(contractInfo.getId());
+					saveList.add(contractNode);
+					contractNode.setTreeCode("C");
+				}
+				if (destNode == null) {
+					destNode = new ArchiveTreeContractVO2(contractNode);
+				}
+				tmpSaveList = archiveTreeContractSync.getContractSaveList(srcTree,destNode,contractInfo,contractNode);
+			}
+			if (srcTree.getTitle().contains("监理单位归档资料") && contractInfo.getContractType() == 2) {
+				//复制监理
+				if (contractNode == null) {
+					contractNode = new ArchiveTreeContract(srcTree);
+					contractNode.setId(SnowFlakeUtil.getId());
+					contractNode.setParentId(dstTree.getId());
+					contractNode.setContractId(contractInfo.getId());
+					saveList.add(contractNode);
+					contractNode.setTreeCode("S");
+				}
+				if (destNode == null) {
+					destNode = new ArchiveTreeContractVO2(contractNode);
+				}
+//				dstTree.getChildren().add(destNode);
+				tmpSaveList = archiveTreeContractSync.getContractSaveList(srcTree,destNode,contractInfo,contractNode);
+			}
+			saveList.addAll(tmpSaveList);
+		}
+		return contractNode != null;
+	}
 
 	/**
 	 * 返回某个合同段关联质检资料的节点

+ 288 - 8
blade-service/blade-manager/src/main/java/org/springblade/manager/service/impl/ArchiveTreeServiceImpl.java

@@ -1,5 +1,6 @@
 package org.springblade.manager.service.impl;
 
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.baomidou.mybatisplus.core.toolkit.StringPool;
 import com.baomidou.mybatisplus.core.toolkit.StringUtils;
@@ -13,20 +14,23 @@ import org.springblade.core.tool.constant.BladeConstant;
 import org.springblade.core.tool.utils.BeanUtil;
 import org.springblade.core.tool.utils.Func;
 import org.springblade.manager.dto.ArchiveTreeContractAutoRuleMapDTO;
+import org.springblade.manager.dto.ArchiveTreeContractDTO;
 import org.springblade.manager.dto.ArchiveTreeDTO;
 import org.springblade.manager.dto.ArchiveTreeSortDTO;
 import org.springblade.manager.entity.*;
 import org.springblade.manager.mapper.ArchiveAutoRuleWbsMapper;
-import org.springblade.manager.service.IProjectInfoService;
-import org.springblade.manager.service.IWbsTreePrivateService;
-import org.springblade.manager.service.IWbsTreeService;
+import org.springblade.manager.mapper.ArchiveTreeContractMapper;
+import org.springblade.manager.service.*;
 import org.springblade.manager.utils.DiffListUtil;
 import org.springblade.manager.utils.ForestNodeMerger;
 import org.springblade.common.utils.ForestNodeMergerEx;
 import org.springblade.manager.vo.*;
 import org.springblade.manager.mapper.ArchiveTreeMapper;
-import org.springblade.manager.service.IArchiveTreeService;
 import org.springblade.core.mp.base.BaseServiceImpl;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Lazy;
+import org.springframework.jdbc.core.BeanPropertyRowMapper;
+import org.springframework.jdbc.core.JdbcTemplate;
 import org.springframework.stereotype.Service;
 
 import java.util.*;
@@ -37,14 +41,13 @@ import java.util.stream.Collectors;
 public class ArchiveTreeServiceImpl extends BaseServiceImpl<ArchiveTreeMapper, ArchiveTree> implements IArchiveTreeService {
 
     private final ArchiveTreeMapper archiveTreeMapper;
-    private final ArTreeContractInitServiceImpl archiveTreeContractInitService;
     private final IWbsTreeService wbsTreeService;
     private final IWbsTreePrivateService wbsTreePrivateService;
     private final IProjectInfoService projectInfoService;
-
     private final ArchiveAutoRuleWbsMapper archiveAutoRuleWbsMapper;
-
+    private final ArchiveTreeContractMapper archiveTreeContractMapper;
     private final ArchiveAutoRuleSyncImpl archiveAutoRuleSync;
+    private final JdbcTemplate jdbcTemplate;
 
     @Override
     public boolean initArchiveTree(Long projectId) {
@@ -262,6 +265,53 @@ public class ArchiveTreeServiceImpl extends BaseServiceImpl<ArchiveTreeMapper, A
         }
         return treeVO2s;
     }
+    @Override
+    public List<ArchiveTreeVO3> tree3(String tenantId, Long projectId, Integer disPlayTree, Integer nodeType, String wbsId, boolean bgetExtNodes) {
+        if (projectId == null) {
+            projectId = 0L;
+        }
+
+        List<ArchiveTreeVO3> archiveTreeVOList = baseMapper.tree3(tenantId, projectId, disPlayTree, nodeType);
+        List<ArchiveTreeVO3> treeVO2s = ForestNodeMergerEx.mergeRoot(archiveTreeVOList);
+        if (archiveTreeVOList != null && archiveTreeVOList.size() > 0) {
+            List<String> list = new ArrayList<>();
+            archiveTreeVOList.stream().forEach(l -> {
+                if (l.getHasChildren() == false && l.getIsDisplayTree() == 1) {
+                    list.add(l.getId() + "");
+                }
+            });
+            treeVO2s.get(0).setSelectAllNodes(list);
+        }
+        //todo 遍历树,找到质检节点,调用getWbsArchiveTree,根据关联层级,拼接上去
+
+        //是否获取扩展的wbs节点
+        if (StringUtils.isEmpty(wbsId) && projectId != null && projectId != 0 && bgetExtNodes) {
+            ProjectInfo projectInfo = projectInfoService.getOne(projectId);
+            if (projectInfo != null) {
+                Long lWbsId = projectInfo.getReferenceWbsTemplateId();
+                if (lWbsId != null) {
+                    wbsId = projectInfo.getReferenceWbsTemplateId().toString();
+                }
+            }
+        }
+
+        if (StringUtils.isNotEmpty(wbsId)) {
+            for (ArchiveTreeVO3 ar : archiveTreeVOList) {
+                //关联质检资料
+                if (ar.getAssociationType() != null
+                        && ar.getAssociationType() == 1
+                        && ar.getDisplayHierarchy() != null) {
+                    ArchiveTreeVO3 child = getWbsArchiveTree3(tenantId, projectId, ar.getId(),
+                            wbsId, "1", Long.parseLong(ar.getDisplayHierarchy()));
+
+                    if (child != null) {
+                        ar.getChildren().add(child);
+                    }
+                }
+            }
+        }
+        return treeVO2s;
+    }
 
     @Override
     public List<ArchiveTree> selectByParentIdOrId(String id) {
@@ -350,6 +400,7 @@ public class ArchiveTreeServiceImpl extends BaseServiceImpl<ArchiveTreeMapper, A
             archiveTreeDTO.setIsStorageNode(1);
         }
         if (archiveTreeDTO.getId() == null) {
+            archiveTreeDTO.setId(SnowFlakeUtil.getId());
             List<ArchiveTree> trees = baseMapper.selectList(Wrappers.<ArchiveTree>query().lambda()
                     .eq(ArchiveTree::getParentId, archiveTreeDTO.getParentId())
             );
@@ -367,10 +418,161 @@ public class ArchiveTreeServiceImpl extends BaseServiceImpl<ArchiveTreeMapper, A
             }
             archiveTreeDTO.setSort(sort + 1);
         }
-
+        //这一段是系统级新增,项目级,合同段级自动新增
+//        //如果是修改的系统级的,需要更新项目级+合同段级
+//        if(archiveTreeDTO.getProjectId()==null||archiveTreeDTO.getProjectId()==0){
+//            //查出引用了该系统节点的父节点的项目级节点
+//            String sql="select * from m_archive_tree where from_id="+archiveTreeDTO.getParentId()+" and is_deleted=0";
+//            List<ArchiveTreeDTO> query = jdbcTemplate.query(sql, new BeanPropertyRowMapper<>(ArchiveTreeDTO.class));
+//            if(query.size()>0){
+//                for (ArchiveTreeDTO dto : query) {
+//                    ArchiveTreeDTO treeDTO = new ArchiveTreeDTO();
+//                    BeanUtil.copy(archiveTreeDTO,treeDTO);
+//                    treeDTO.setId(null);
+//                    treeDTO.setProjectId(dto.getProjectId());
+//                    treeDTO.setParentId(dto.getId());
+//                    treeDTO.setAncestors(dto.getAncestors()+StringPool.COMMA+dto.getId());
+//                    treeDTO.setFromId(archiveTreeDTO.getId());
+//                    Long l = sumbit1(treeDTO);
+//                    //在新增合同段级的
+//                    String sql1="select * from m_archive_tree_contract where from_id="+treeDTO.getParentId()+" and is_deleted=0";
+//                    List<ArchiveTreeContractDTO> query1 = jdbcTemplate.query(sql1, new BeanPropertyRowMapper<>(ArchiveTreeContractDTO.class));
+//                    if(query1.size()>0){
+//                        for (ArchiveTreeContractDTO dto1 : query1) {
+//                            ArchiveTreeContractDTO contractDTO=new ArchiveTreeContractDTO();
+//                            BeanUtil.copy(treeDTO,contractDTO);
+//                            contractDTO.setId(null);
+//                            contractDTO.setParentId(dto1.getId());
+//                            contractDTO.setAncestors(dto1.getAncestors()+StringPool.COMMA+dto1.getId());
+//                            contractDTO.setFromId(l);
+//                            submit2(contractDTO);
+//                        }
+//                    }
+//                }
+//            }
+//        }else {
+//            //如果修改的是项目级就新增合同段级的
+//            String sql1="select * from m_archive_tree_contract where from_id="+archiveTreeDTO.getParentId()+" and is_deleted=0";
+//            List<ArchiveTreeContractDTO> query1 = jdbcTemplate.query(sql1, new BeanPropertyRowMapper<>(ArchiveTreeContractDTO.class));
+//            if(query1.size()>0){
+//                for (ArchiveTreeContractDTO dto1 : query1) {
+//                    ArchiveTreeContractDTO contractDTO=new ArchiveTreeContractDTO();
+//                    BeanUtil.copy(archiveTreeDTO,contractDTO);
+//                    contractDTO.setId(null);
+//                    contractDTO.setParentId(dto1.getId());
+//                    contractDTO.setAncestors(dto1.getAncestors()+StringPool.COMMA+dto1.getId());
+//                    contractDTO.setFromId(archiveTreeDTO.getId());
+//                    submit2(contractDTO);
+//                }
+//            }
+//        }
         return save(archiveTreeDTO);
     }
 
+    public int submit2(ArchiveTreeContractDTO archiveTreeContractDTO) {
+        if (Func.isEmpty(archiveTreeContractDTO.getParentId())) {
+            archiveTreeContractDTO.setTenantId(AuthUtil.getTenantId());
+            archiveTreeContractDTO.setParentId(BladeConstant.TOP_PARENT_ID);
+            archiveTreeContractDTO.setAncestors(String.valueOf(BladeConstant.TOP_PARENT_ID));
+        }
+        if (archiveTreeContractDTO.getParentId() > 0) {
+            ArchiveTreeContract parent = archiveTreeContractMapper.selectById(archiveTreeContractDTO.getParentId());
+            if (Func.toLong(archiveTreeContractDTO.getParentId()) == Func.toLong(archiveTreeContractDTO.getId())) {
+                throw new ServiceException("父节点不可选择自身!");
+            }
+            archiveTreeContractDTO.setTenantId(parent.getTenantId());
+            String ancestors = parent.getAncestors() + StringPool.COMMA + archiveTreeContractDTO.getParentId();
+            archiveTreeContractDTO.setAncestors(ancestors);
+            archiveTreeContractDTO.setTreeSort(parent.getTreeSort());
+            archiveTreeContractDTO.setContractId(parent.getContractId());
+            archiveTreeContractDTO.setTreeCode(parent.getTreeCode());
+
+            archiveTreeContractDTO.setArchiveAutoNodeId(parent.getArchiveAutoNodeId());
+            archiveTreeContractDTO.setArchiveAutoType(parent.getArchiveAutoType());
+            archiveTreeContractDTO.setArchiveAutoGroupId(parent.getArchiveAutoGroupId());
+            archiveTreeContractDTO.setArchiveAutoGroupSelect(0);
+        }
+
+        archiveTreeContractDTO.setIsDeleted(BladeConstant.DB_NOT_DELETED);
+        archiveTreeContractDTO.setFullName(archiveTreeContractDTO.getNodeName());
+        if (archiveTreeContractDTO.getNodeType() == 1) {
+            archiveTreeContractDTO.setIsStorageNode(1);
+        }
+        if (archiveTreeContractDTO.getId() == null) {
+            List<ArchiveTreeContract> trees = archiveTreeContractMapper.selectList(Wrappers.<ArchiveTreeContract>query().lambda()
+                .eq(ArchiveTreeContract::getParentId, archiveTreeContractDTO.getParentId())
+            );
+            List<ArchiveTreeContract> collect = trees.stream().filter(f -> {
+                if (f.getSort() == null) {
+                    f.setSort(0);
+                }
+                return true;
+            }).collect(Collectors.toList());
+            Optional<ArchiveTreeContract> max = collect.stream().max(Comparator.comparingInt(ArchiveTreeContract::getSort));
+            Integer sort = 0;
+            if (max.isPresent()) {
+                sort = max.get().getSort();
+            }
+            archiveTreeContractDTO.setSort(sort + 1);
+            String treeSort = archiveTreeContractDTO.getTreeSort();
+            if (com.mixsmart.utils.StringUtils.isNotEmpty(treeSort)) {
+                treeSort = treeSort + (100 + archiveTreeContractDTO.getSort());
+                archiveTreeContractDTO.setTreeSort(treeSort);
+            }
+        }
+
+        return archiveTreeContractMapper.insert(archiveTreeContractDTO);
+    }
+
+    public Long sumbit1(ArchiveTreeDTO archiveTreeDTO){
+        if (Func.isEmpty(archiveTreeDTO.getParentId())) {
+            archiveTreeDTO.setTenantId(AuthUtil.getTenantId());
+            archiveTreeDTO.setParentId(BladeConstant.TOP_PARENT_ID);
+            archiveTreeDTO.setAncestors(String.valueOf(BladeConstant.TOP_PARENT_ID));
+        }
+        if (archiveTreeDTO.getParentId() > 0) {
+            ArchiveTree parent = getById(archiveTreeDTO.getParentId());
+            if (Func.toLong(archiveTreeDTO.getParentId()) == Func.toLong(archiveTreeDTO.getId())) {
+                throw new ServiceException("父节点不可选择自身!");
+            }
+            archiveTreeDTO.setTenantId(parent.getTenantId());
+            String ancestors = parent.getAncestors() + StringPool.COMMA + archiveTreeDTO.getParentId();
+            archiveTreeDTO.setAncestors(ancestors);
+
+            archiveTreeDTO.setArchiveAutoType(parent.getArchiveAutoType());
+            archiveTreeDTO.setArchiveAutoNodeId(parent.getArchiveAutoNodeId());
+            archiveTreeDTO.setArchiveAutoGroupId(parent.getArchiveAutoGroupId());
+            archiveTreeDTO.setArchiveAutoGroupSelect(0);
+        }
+
+        archiveTreeDTO.setIsDeleted(BladeConstant.DB_NOT_DELETED);
+        archiveTreeDTO.setFullName(archiveTreeDTO.getNodeName());
+        if (archiveTreeDTO.getNodeType() == 1) {
+            archiveTreeDTO.setIsStorageNode(1);
+        }
+        if (archiveTreeDTO.getId() == null) {
+            archiveTreeDTO.setId(SnowFlakeUtil.getId());
+            List<ArchiveTree> trees = baseMapper.selectList(Wrappers.<ArchiveTree>query().lambda()
+                .eq(ArchiveTree::getParentId, archiveTreeDTO.getParentId())
+            );
+
+            List<ArchiveTree> collect = trees.stream().filter(f -> {
+                if (f.getSort() == null) {
+                    f.setSort(0);
+                }
+                return true;
+            }).collect(Collectors.toList());
+            Optional<ArchiveTree> max = collect.stream().max(Comparator.comparingInt(ArchiveTree::getSort));
+            Integer sort = 0;
+            if (max.isPresent()) {
+                sort = max.get().getSort();
+            }
+            archiveTreeDTO.setSort(sort + 1);
+        }
+        save(archiveTreeDTO);
+        return archiveTreeDTO.getId();
+    }
+
     @Override
     public List<ArchiveTree> treeList(String tenantId, Long projectId, Integer disPlayTree, Integer nodeType) {
         return baseMapper.selectList(Wrappers.<ArchiveTree>query().lambda()
@@ -452,6 +654,76 @@ public class ArchiveTreeServiceImpl extends BaseServiceImpl<ArchiveTreeMapper, A
         return null;
     }
 
+    /**
+     * 按照层次获取归档树链表
+     *
+     * @param parentId
+     * @param wbsId
+     * @param tenantId
+     * @param type
+     * @param level    层次,1,单位工程,2
+     * @return
+     */
+    public ArchiveTreeVO3 getWbsArchiveTree3(String tenantId, Long projectId, Long parentId, String wbsId, String type, Long level) {
+        List<ArchiveTreeVO3> archiveTreeList = new ArrayList<>();
+
+        List<WbsTreeVO2> wbsTreeVO2s = null;
+
+        if (projectId == 0) {
+            wbsTreeVO2s = wbsTreeService.tree(wbsId, tenantId, type);
+        } else {
+            wbsTreeVO2s = wbsTreePrivateService.tree2(wbsId, projectId.toString());
+        }
+
+        List<WbsTreeVO2> wbsTreeVO2List = new ArrayList<>();
+        ForestNodeMerger.getTreeList(wbsTreeVO2s.get(0), wbsTreeVO2List);
+
+        Map<Long, Long> idPkidMap = new LinkedHashMap<>();
+        if (projectId != 0) {
+            for (WbsTreeVO2 wbsTreeVO2 : wbsTreeVO2List) {
+                idPkidMap.put(wbsTreeVO2.getId(), wbsTreeVO2.getPrimaryKeyId());
+            }
+        }
+
+        //遍历构建
+        for (WbsTreeVO2 wbsTreeVO2 : wbsTreeVO2List) {
+            //只展示指定层级之上的
+
+//            if (!wbsTreeVO2.isProcessType()) {
+//                continue;
+//            }
+
+            if (!wbsTreeVO2.isMatchLevel(level)) {
+                continue;
+            }
+            ArchiveTreeVO3 archiveTree = new ArchiveTreeVO3();
+            archiveTree.setTitle(wbsTreeVO2.getTitle());
+
+            archiveTree.setId(wbsTreeVO2.getId());
+            archiveTree.setParentId(wbsTreeVO2.getParentId());
+            if (projectId != 0) {
+                archiveTree.setId(wbsTreeVO2.getId());
+                //archiveTree.setId(idPkidMap.get(wbsTreeVO2.getId()));
+                int i = 0;
+                Long pid = wbsTreeVO2.getParentId();
+                if (pid == null) {
+                    pid = 0L;
+                }
+                archiveTree.setParentId(pid);
+            }
+
+            archiveTree.setDisplayHierarchy(level.toString());
+            archiveTreeList.add(archiveTree);
+        }
+
+        //设置pid
+        List<ArchiveTreeVO3> archiveTreeVO2s = ForestNodeMergerEx.merge(archiveTreeList);
+        if (archiveTreeVO2s != null && archiveTreeVO2s.size() > 0) {
+            return archiveTreeVO2s.get(0);
+        }
+        return null;
+    }
+
 
     /**
      * 保存组卷规则设置
@@ -1050,6 +1322,14 @@ public class ArchiveTreeServiceImpl extends BaseServiceImpl<ArchiveTreeMapper, A
 
         this.saveBatch(saveList);
         this.updateBatchById(upList);
+//        for (ArchiveTree archiveTree : upList) {
+//            String sql="select * from m_archive_tree_contract where from_id="+archiveTree.getId()+" and project_id="+archiveTree.getProjectId()+" and is_deleted=0";
+//            List<ArchiveTreeContract> list = jdbcTemplate.query(sql, new BeanPropertyRowMapper<>(ArchiveTreeContract.class));
+//            for (ArchiveTreeContract archiveTreeContract : list) {
+//                archiveTreeContract.sync(archiveTree);
+//                archiveTreeContractMapper.update(archiveTreeContract,new LambdaQueryWrapper<>(ArchiveTreeContract.class).eq(ArchiveTreeContract::getId,archiveTreeContract.getId()));
+//            }
+//        }
         return true;
     }
 

+ 4 - 18
blade-service/blade-manager/src/main/java/org/springblade/manager/service/impl/ContractInfoServiceImpl.java

@@ -1065,34 +1065,20 @@ public class ContractInfoServiceImpl extends BaseServiceImpl<ContractInfoMapper,
                 position = BaiduApiUtil.getPosition(addressInfo.get("lat").toString()
                         + "," + addressInfo.get("lng").toString());
             } catch (Exception e) {
-                throw new ServiceException("施工台账初始化失败: 百度地理编码API配额超限,今日限制访问");
+                return true;
+             //   throw new ServiceException("施工台账初始化失败: 百度地理编码API配额超限,今日限制访问");
+
             }
             ProjectContractArea projectContractArea = new ProjectContractArea();
             projectContractArea.setProvince(position.get("province"));
             projectContractArea.setCity(position.get("city"));
             projectContractArea.setCounty(position.get("district"));
             projectContractArea.setCity_code(position.get("adcode"));
-//            projectContractArea.setProvince("重庆");
-//            projectContractArea.setCity("重庆市");
-//            projectContractArea.setCounty("永川区");
-//            projectContractArea.setCity_code("500118");
             projectContractArea.setProjectId(contractInfo.getPId());
             projectContractArea.setIsDeleted(0);
             projectContractArea.setContractId(String.valueOf(contractInfo.getId()));
             projectContractArea.setProjectId(contractInfo.getPId());
-//                QueryWrapper<ProjectContractArea> queryWrapper = new QueryWrapper<>();
-//                queryWrapper.eq("project_id", contractInfo.getPId());
-//                queryWrapper.eq("contract_id", contractInfo.getId());
-//                queryWrapper.eq("province", position.get("province"));
-//                queryWrapper.eq("city", position.get("city"));
-//                queryWrapper.eq("county", position.get("district"));
-//                queryWrapper.eq("city_code", position.get("adcode"));
-//                queryWrapper.eq("is_deleted", contractInfo.getIsDeleted());
-//                ProjectContractArea projectContractArea1 = projectContractAreaMapper.selectOne(queryWrapper);
-//                if (projectContractArea1 == null) {
-//                    int res = projectContractAreaMapper.insert(projectContractArea);
-//                    return res > 0;
-//                }
+
             //删除之前所有的地址,再新增
             projectContractAreaMapper.delete(new LambdaQueryWrapper<ProjectContractArea>()
                     .eq(ProjectContractArea::getContractId, projectContractArea.getContractId()));

+ 71 - 49
blade-service/blade-manager/src/main/java/org/springblade/manager/service/impl/ExcelTabServiceImpl.java

@@ -665,7 +665,7 @@ public class ExcelTabServiceImpl extends BaseServiceImpl<ExcelTabMapper, ExcelTa
         String ids = "";
         if (StringUtils.isEmpty(businessIds)) {
             //检查是否存在原本的数据
-            List<ContractLog> contractLogs = this.contractLogClient.queryContractLogByPrimaryKeyIdAndRecordTimeList(parentNode.getPKeyId().toString(), recordTime, tableInfoList.get(0).getContractId());
+            List<ContractLog> contractLogs = this.contractLogClient.queryContractLogByPrimaryKeyIdAndRecordTimeList(parentNode.getPKeyId().toString(), recordTime, tableInfoList.get(0).getContractId(),null);
             if (contractLogs.size() > 0) {
                 businessIds = contractLogs.stream().map(ContractLog::getDataId).filter(ObjectUtils::isNotEmpty).map(String::valueOf).collect(Collectors.joining(","));
                 ids = contractLogs.stream().map(ContractLog::getId).map(String::valueOf).collect(Collectors.joining(","));
@@ -1246,22 +1246,13 @@ public class ExcelTabServiceImpl extends BaseServiceImpl<ExcelTabMapper, ExcelTa
                     if (wbsTreeContractByP != null) {
                         //处理文件提名
                         String fileName = this.wbsParamService.createFileTitle(wbsTreeContractByP);
-                        String sql="select template_type from m_contract_info where id="+wbsTreeContractByP.getContractId();
-                        Integer type = jdbcTemplate.query(sql, rs -> {
-                            if (rs.next()) {
-                                return rs.getObject(1, Integer.class);
-                            } else {
-                                return 0; // 默认值
-                            }
-                        });
-                        if(type==2){
-                            if(wbsTreeContractByP.getMajorDataType()!=null&&wbsTreeContractByP.getMajorDataType()==4){
-                                if(tableInfo.getClassify()!=null&&tableInfo.getClassify().equals("1")){
-                                    //查询是否是底层节点
-                                    fileName=fileName+"检验申请批复单及附件";
-                                }else {
-                                    fileName=fileName+"抽检记录";
-                                }
+                        String sql1="Select sg_suffix,jl_suffix from m_project_info where id="+wbsTreeContractByP.getProjectId()+" and is_deleted=0";
+                        List<ProjectInfo> query = jdbcTemplate.query(sql1, new BeanPropertyRowMapper<>(ProjectInfo.class));
+                        if(query.size()>0){
+                            if(tableInfo.getClassify()!=null&&tableInfo.getClassify().equals("1")){
+                                fileName=fileName+(query.get(0).getSgSuffix()==null?"":query.get(0).getSgSuffix());
+                            }else {
+                                fileName=fileName+(query.get(0).getJlSuffix()==null?"":query.get(0).getJlSuffix());
                             }
                         }
                         //huangjn 保存成功后调用生成资料查询列表数据
@@ -1300,22 +1291,13 @@ public class ExcelTabServiceImpl extends BaseServiceImpl<ExcelTabMapper, ExcelTa
                         .eq(WbsTreeContract::getId, wbsTreeContract.getParentId()).eq(WbsTreeContract::getContractId, wbsTreeContract.getContractId()));
                 //处理文件提名
                 fileName1= this.wbsParamService.createFileTitle(wbsTreeContractByP);
-                String sql="select template_type from m_contract_info where id="+wbsTreeContractByP.getContractId();
-                Integer type = jdbcTemplate.query(sql, rs -> {
-                    if (rs.next()) {
-                        return rs.getObject(1, Integer.class);
-                    } else {
-                        return 0; // 默认值
-                    }
-                });
-                if(type==2){
-                    if(wbsTreeContractByP.getMajorDataType()!=null&&wbsTreeContractByP.getMajorDataType()==4){
-                        if(tableInfoList.get(0).getClassify()!=null&&tableInfoList.get(0).getClassify().equals("1")){
-                            //查询是否是底层节点
-                            fileName1=fileName1+"检验申请批复单及附件";
-                        }else {
-                            fileName1=fileName1+"抽检记录";
-                        }
+                String sql1="Select sg_suffix,jl_suffix from m_project_info where id="+wbsTreeContractByP.getProjectId()+" and is_deleted=0";
+                List<ProjectInfo> query = jdbcTemplate.query(sql1, new BeanPropertyRowMapper<>(ProjectInfo.class));
+                if(query.size()>0){
+                    if(tableInfoList.get(0).getClassify()!=null&&tableInfoList.get(0).getClassify().equals("1")){
+                        fileName1=fileName1+(query.get(0).getSgSuffix()==null?"":query.get(0).getSgSuffix());
+                    }else {
+                        fileName1=fileName1+(query.get(0).getJlSuffix()==null?"":query.get(0).getJlSuffix());
                     }
                 }
                 //huangjn 保存成功后调用生成资料查询列表数据
@@ -1723,7 +1705,9 @@ public class ExcelTabServiceImpl extends BaseServiceImpl<ExcelTabMapper, ExcelTa
         Map<String, Object> nodeBaseInfo = nodeBaseInfoService.getAllNodeBaseInfoByPkeyId(pkeyId, nodeId);
         if(nodeBaseInfo!=null){
             for (Map.Entry<String, Object> entry : nodeBaseInfo.entrySet()) {
-                reData.put(entry.getKey(), entry.getValue());
+                if (reData.get(entry.getKey()) == null || reData.get(entry.getKey()).toString().isEmpty()) {
+                    reData.put(entry.getKey(), entry.getValue());
+                }
             }
         }
 //        if(reData.size()>0){
@@ -2145,9 +2129,6 @@ public class ExcelTabServiceImpl extends BaseServiceImpl<ExcelTabMapper, ExcelTa
             Elements trs = table.select("tr");
             if (ObjectUtil.isNotEmpty(DataInfo)) {
                 for (String val : DataInfo.keySet()) {
-                    if(val.equals("key_23__12_1")){
-                        System.out.println("");
-                    }
                     Elements datas = doc.getElementsByAttributeValue("keyname", val);
                     Element data = null;
                     if (datas.size() >= 1) {
@@ -2227,7 +2208,7 @@ public class ExcelTabServiceImpl extends BaseServiceImpl<ExcelTabMapper, ExcelTa
                             if (myData.indexOf("http") >= 0 && (myData.indexOf("aliyuncs") >= 0 ||myData.indexOf("183.247.216.148") >= 0||myData.indexOf("xinan1.zos.ctyun.cn") >= 0)) {
                                 InputStream imageIn = CommonUtil.getOSSInputStream(myData);
                                 if (imageIn != null) {
-                                    byte[] bytes = CommonUtil.compressImage(myData);
+                                    byte[] bytes = CommonUtil.compressImage3(myData);
                                     // 这里根据实际需求选择图片类型
                                     int pictureIdx = workbook.addPicture(bytes, 6);
                                     CreationHelper helper = workbook.getCreationHelper();
@@ -2283,7 +2264,7 @@ public class ExcelTabServiceImpl extends BaseServiceImpl<ExcelTabMapper, ExcelTa
                             } else {
                                 Row row = sheet.getRow(y1 - 1);
                                 if (row != null) {
-                                    Cell cell = row.getCell(x1 - 1);
+                                    Cell cell = row.getCell(x1 - 1, Row.MissingCellPolicy.CREATE_NULL_AS_BLANK);
                                     if (cell != null || ObjectUtils.isNotEmpty(cell)) {
                                         short fontIndex = cell.getCellStyle().getFontIndex();
                                         Font fontAt = workbook.getFontAt(fontIndex);
@@ -2313,14 +2294,24 @@ public class ExcelTabServiceImpl extends BaseServiceImpl<ExcelTabMapper, ExcelTa
 
                     Row row = sheet.getRow(y1 - 1);
                     if (row != null) {
-                        Cell cell = row.getCell(x1 - 1);
+                        Cell cell = row.getCell(x1 - 1, Row.MissingCellPolicy.CREATE_NULL_AS_BLANK);
+                        if (cell == null) {
+                            cell = row.createCell(x1 - 1);
+                        }
                         if (cell != null || ObjectUtils.isNotEmpty(cell)) {
                              // 获取单元格的现有值
                             String existingValue = cell.getStringCellValue();
                             // 获取单元格的现有富文本字符串
                             RichTextString existingRichTextString = cell.getRichStringCellValue();
+                            String s = null;
+                            if(StringUtils.isEmpty(existingValue)){
+                                s = dqid;
+                            }else{
+                                s = existingValue + "*" + dqid;
+                            }
+
                              // 创建一个新的副文本字符串,原有值+电签ID
-                            RichTextString richTextString = workbook.getCreationHelper().createRichTextString(existingValue + dqid);
+                            RichTextString richTextString = workbook.getCreationHelper().createRichTextString(s);
                             // 复制原有部分的字体格式
                             if (existingRichTextString instanceof XSSFRichTextString) {
                                 XSSFRichTextString xssfRichTextString = (XSSFRichTextString) existingRichTextString;
@@ -2351,7 +2342,7 @@ public class ExcelTabServiceImpl extends BaseServiceImpl<ExcelTabMapper, ExcelTa
                             newFont.setColor(IndexedColors.WHITE.getIndex());
                             newFont.setFontHeightInPoints(Short.valueOf("1")); // 可根据需要调整字体大小
                             //从原有值之后,电签ID开始设置成新的格式。
-                            richTextString.applyFont(existingValue.length(), existingValue.length() + dqid.length(), newFont);
+                            richTextString.applyFont(existingValue.length(), s.length(), newFont);
                              // 将副文本字符串设置到单元格
                             cell.setCellValue(richTextString);
                         }
@@ -3105,8 +3096,29 @@ public class ExcelTabServiceImpl extends BaseServiceImpl<ExcelTabMapper, ExcelTa
                         }
 
                         if (cellValue != null && !cellValue.isEmpty()) {
-                            if (cellValue.contains(oldContext)) {
+                            if (cellValue.equals(oldContext) && j + 1 < cellNum) {
+                                Cell nextCell = row.getCell(j + 1);
+                                String nextCellValue;
+                                if (nextCell.getCellType() == 0) {
+                                    double numValue = cell.getNumericCellValue();
+                                    nextCellValue = String.valueOf(numValue);
+                                } else {
+                                    nextCellValue = nextCell.getStringCellValue();
+                                }
+                                if (nextCellValue == null || nextCellValue.isEmpty()) {
+                                    nextCell.setCellValue(newContext.replace(oldContext, ""));
+                                    CellStyle cellStyle = cell.getCellStyle();
+                                    // 设置自动换行
+                                    cellStyle.setWrapText(true);
+                                    cell.setCellStyle(cellStyle);
+                                    return true;
+                                }
+                            } else if (cellValue.contains(oldContext)) {
                                 cell.setCellValue(newContext);
+                                CellStyle cellStyle = cell.getCellStyle();
+                                cellStyle.setWrapText(true);
+                                cell.setCellStyle(cellStyle);
+                                row.setHeight((short) (row.getHeight() * 1.5));
                                 return true;
                             }
                         }
@@ -3566,11 +3578,21 @@ public class ExcelTabServiceImpl extends BaseServiceImpl<ExcelTabMapper, ExcelTa
             //修改合并后的pdf路径
             String querySql = "select id from u_information_query where classify ='" + classify + "' and wbs_id ='" + id + "' and contract_id ='" + contractId + "'";
             List<InformationQuery> query = jdbcTemplate.query(querySql, new BeanPropertyRowMapper<>(InformationQuery.class));
+            StringBuilder names=new StringBuilder("");
+            if(StringUtils.isNotEmpty(dto.getReportNo())){
+                names.append("[");
+                names.append(dto.getReportNo());
+                names.append("]");
+            }
+            if(StringUtils.isNotEmpty(dto.getTrialProjectName())){
+                names.append(dto.getTrialProjectName());
+            }
+            names.append("试验检测报告及附件");
             if (query.size() > 0) {
-                String updateSql = "update u_information_query set pdf_url ='" + bladeFile.getLink() + "', name ='" + (StringUtils.isNotEmpty(dto.getTrialProjectName()) ? dto.getTrialProjectName() : "") + "' where classify='" + classify + "' and wbs_id='" + id + "' and contract_id ='" + contractId + "'";
+                String updateSql = "update u_information_query set pdf_url ='" + bladeFile.getLink() + "', name ='" + names + "' where classify='" + classify + "' and wbs_id='" + id + "' and contract_id ='" + contractId + "'";
                 jdbcTemplate.execute(updateSql);
             } else {
-                informationQueryClient.saveData(id.toString(), projectId, contractId, classify, bladeFile.getLink(), StringUtils.isNotEmpty(dto.getTrialProjectName()) ? dto.getTrialProjectName() : "");
+                informationQueryClient.saveData(id.toString(), projectId, contractId, classify, bladeFile.getLink(), names.toString());
             }
             return bladeFile.getLink();
         }
@@ -4138,7 +4160,7 @@ public class ExcelTabServiceImpl extends BaseServiceImpl<ExcelTabMapper, ExcelTa
 
                     Row row = sheet.getRow(y1 - 1);
                     if (row != null) {
-                        Cell cell = row.getCell(x1 - 1);
+                        Cell cell = row.getCell(x1 - 1,  Row.MissingCellPolicy.CREATE_NULL_AS_BLANK);
                         if (cell != null || ObjectUtils.isNotEmpty(cell)) {
                             short fontIndex = cell.getCellStyle().getFontIndex();
                             Font oldfontAt = workbook.getFontAt(fontIndex);
@@ -4202,7 +4224,7 @@ public class ExcelTabServiceImpl extends BaseServiceImpl<ExcelTabMapper, ExcelTa
      * 试验 委托单 单pdf
      */
     @Override
-    public String getEntrustPDFTrial(Long pkeyId, String contractId, Long groupId) throws Exception {
+    public String getEntrustPDFTrial(Long pkeyId, String contractId, Long groupId,String entrustInfoName) throws Exception {
         String file_path = FileUtils.getSysLocalFileUrl();//ParamCache.getValue(CommonConstant.SYS_LOCAL_URL);
         String sys_file_net_url = ParamCache.getValue(CommonConstant.SYS_FILE_NET_URL);
         WbsTreePrivate wbsTreePrivate = wbsTreePrivateService.getBaseMapper().selectOne(Wrappers.<WbsTreePrivate>query().lambda()
@@ -4476,9 +4498,9 @@ public class ExcelTabServiceImpl extends BaseServiceImpl<ExcelTabMapper, ExcelTa
                 jdbcTemplate.update("update u_entrust_info set entrust_pdf = '" + pdfUrl + "' where id='" + groupId + "' ");
             List<InformationQuery> query2 = jdbcTemplate.query("select id from u_information_query where classify = 1 and wbs_id ='" + groupId + "' and contract_id ='" + contractId + "'", new BeanPropertyRowMapper<>(InformationQuery.class));
             if (query2.size() > 0) {
-                jdbcTemplate.execute("update u_information_query set pdf_url ='" + bladeFile.getLink() + "', name ='委托单'  where classify='1' and  wbs_id='" + groupId + "' and contract_id ='" + contractId + "'");
+                jdbcTemplate.execute("update u_information_query set pdf_url ='" + bladeFile.getLink() + "', name ='"+entrustInfoName+"'  where classify='1' and  wbs_id='" + groupId + "' and contract_id ='" + contractId + "'");
             } else {
-                informationQueryClient.saveData(groupId.toString(), projectInfo.getId().toString(), contractId, "1", bladeFile.getLink(), "委托单");
+                informationQueryClient.saveData(groupId.toString(), projectInfo.getId().toString(), contractId, "1", bladeFile.getLink(), entrustInfoName);
             }
             return bladeFile.getLink();
         }

+ 30 - 6
blade-service/blade-manager/src/main/java/org/springblade/manager/service/impl/FormulaServiceImpl.java

@@ -1181,9 +1181,12 @@ public class FormulaServiceImpl extends BaseServiceImpl<FormulaMapper, Formula>
             checkTable = op.get().getInitTableName();
         }
         for (FormData fd : tec.formDataList) {
+            if(fd.getCode().equals("m_20220928144828_1575014563634479104:key_24")){
+                System.out.println("111");
+            }
             if (fd.verify()) {
-                if(fd.getCode().equals("m_20220928143955_1575012411126054912:key_2")){
-                    System.out.println("111");
+                if(fd.getAddPages()!=0){
+                    System.out.println("");
                 }
                 Formula formula = fd.getFormula();
                 System.out.println(formula.getId() + ":" + fd.getEName());
@@ -1231,9 +1234,17 @@ public class FormulaServiceImpl extends BaseServiceImpl<FormulaMapper, Formula>
                                             List<Object> e1 = (List<Object>) ((HashMap<?, ?>) e).get(ele.get(0).getCode());
                                             List<Object> values = (List<Object>) data;
                                             if (e1.size() != values.size()) {
-                                                for (int i = 0; i < e1.size(); i++) {
-                                                    if (e1.get(i).equals("")) {
-                                                        values.add(i, "");
+                                                //JL815获取CL10 JL815只有6行,CL10有8行导致生成空表  JL814也一样
+                                                if(((HashMap<?, ?>) e).containsKey("m_20220920181735_1572168084863582208:key_19")){
+                                                    values = values.stream()
+                                                        .filter(obj -> !(obj instanceof String) ||
+                                                            (obj != null && !((String) obj).trim().isEmpty()))
+                                                        .collect(Collectors.toList());
+                                                }else {
+                                                    for (int i = 0; i < e1.size(); i++) {
+                                                        if (e1.get(i).equals("")) {
+                                                            values.add(i, "");
+                                                        }
                                                     }
                                                 }
                                             }
@@ -1288,6 +1299,7 @@ public class FormulaServiceImpl extends BaseServiceImpl<FormulaMapper, Formula>
                                         }
                                     }
                                 }
+
                                 write(tec, fd, data);
                             }
                             /*错位计算偏移量重置*/
@@ -3587,6 +3599,9 @@ public class FormulaServiceImpl extends BaseServiceImpl<FormulaMapper, Formula>
             monthlyReport.setChangeMeterMoney(monthlyReport.getAfterCurrentMeterMoney().subtract(monthlyReport.getCurrentMeterMoney()));
             monthlyReport.setChapterSeq(vo.getChapterNumber());
             String key = vo.getChapterNumber();
+            if(StringUtils.isEmpty(key)){
+                key=vo.getFormNumber();
+            }
             if (list.size() > 0) {
                 OptionalInt index = IntStream.range(0, list.size())
                         .filter(i -> list.get(i).getId().equals(periodId))
@@ -4258,7 +4273,16 @@ public class FormulaServiceImpl extends BaseServiceImpl<FormulaMapper, Formula>
             Map<String, List<MeterInventoryVO1>> groupedMeter = new HashMap<>();
             List<String> listUrl = new ArrayList<>();
             for (MeterInventoryVO1 vo1 : list1) {
-                String firstChar = vo1.getImportNumber().substring(0, 3);
+                String firstChar;
+                if(StringUtils.isEmpty(vo1.getImportNumber())){
+                    firstChar=vo1.getFormNumber();
+                }else if(vo1.getImportNumber().length()<3){
+                    firstChar=vo1.getFormNumber();
+                }else if(!vo1.getImportNumber().matches("\\d{3}")){
+                    firstChar=vo1.getFormNumber();
+                }else {
+                    firstChar = vo1.getImportNumber().substring(0, 3);
+                }
                 groupedMeter.computeIfAbsent(firstChar, k -> new ArrayList<>()).add(vo1);
             }
             //根据编号的不同建立不同的excel

+ 74 - 23
blade-service/blade-manager/src/main/java/org/springblade/manager/service/impl/WbsFormElementServiceImpl.java

@@ -36,6 +36,7 @@ import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 
 import java.io.IOException;
+import java.math.BigInteger;
 import java.text.ParseException;
 import java.util.*;
 import java.util.stream.Collectors;
@@ -58,7 +59,7 @@ public class WbsFormElementServiceImpl extends BaseServiceImpl<WbsFormElementMap
     //元素字符串、数值、时间类型默认长度
     public static final Integer DEFAULT_ELEMENT_LENGTH_VARCHAR = 200;
     public static final Integer DEFAULT_ELEMENT_LENGTH_NUMBER = 50;
-    public static final Integer DEFAULT_ELEMENT_LENGTH_DATE = 50;
+    public static final Integer DEFAULT_ELEMENT_LENGTH_DATE = 100;
     //实体表字段默认长度
     private static final String ELEMENT_LENGTH_ENTITY = "200";
 
@@ -235,8 +236,8 @@ public class WbsFormElementServiceImpl extends BaseServiceImpl<WbsFormElementMap
                     return wbsFormElement;
                 }
             } else if ("datetime".equals(fieldType)) {
-                if (wbsFormElement.getELength() > 50 || wbsFormElement.getELength() < 0) {
-                    throw new ServiceException("请输入正确的长度,范围为0-50");
+                if (wbsFormElement.getELength() > 100 || wbsFormElement.getELength() < 0) {
+                    throw new ServiceException("请输入正确的长度,范围为0-100");
                 } else {
                     //新增
                     baseMapper.insert(wbsFormElement);
@@ -282,6 +283,7 @@ public class WbsFormElementServiceImpl extends BaseServiceImpl<WbsFormElementMap
     }
 
     @Override
+    @Transactional(rollbackFor = Exception.class)
     public R updateAndSyn(List<WbsFormElement> wbsFormElementList, String initTableName) {
         if (StringUtils.isEmpty(initTableName)) {
             return R.fail("未获取到initTableName对应实体表名称,操作失败");
@@ -303,6 +305,19 @@ public class WbsFormElementServiceImpl extends BaseServiceImpl<WbsFormElementMap
         wbsFormElementList.forEach(obj -> obj.setStatus(1));
         boolean b = this.updateBatchById(wbsFormElementList);
 
+        //字段级字段长度缓存
+        Map<String, Integer> lengthMap = new HashMap<>();
+
+        //查询当前表的所有字段级字段长度
+        List<Map<String, Object>> filedLengths = baseMapper.selectFiledLength(initTableName);
+        for (Map<String, Object> filedLength : filedLengths) {
+            BigInteger length = (BigInteger) filedLength.get("length");
+            if (length == null) {
+                continue;
+            }
+            lengthMap.put(filedLength.get("key").toString(), length.intValue());
+        }
+
         //修改实体表信息
         if (b) {
             String fId = "";
@@ -321,16 +336,16 @@ public class WbsFormElementServiceImpl extends BaseServiceImpl<WbsFormElementMap
 
                 if (eType.equals("bigint") && (eLength > 255 || eLength < 10)) {
                     this.updateBatchById(beforeUpdateWbsFormElements);
-                    return R.fail(eKey+"元素名称:"+eName+"请输入正确长度,该类型范围为10-255之间");
+                    return R.fail(eKey + "元素名称:" + eName + "请输入正确长度,该类型范围为10-255之间");
                 } else if (eType.equals("varchar") && (eLength > 3000 || eLength < 10)) {
                     this.updateBatchById(beforeUpdateWbsFormElements);
-                    return  R.fail(eKey+"元素名称:"+eName+"请输入正确长度,该类型范围为10-3000之间");
+                    return R.fail(eKey + "元素名称:" + eName + "请输入正确长度,该类型范围为10-3000之间");
                 } else if (eType.equals("decimal") && (eLength > 65 || eLength < 10)) {
                     this.updateBatchById(beforeUpdateWbsFormElements);
-                    return  R.fail(eKey+"元素名称:"+eName+"请输入正确长度,该类型范围为10-65之间");
+                    return R.fail(eKey + "元素名称:" + eName + "请输入正确长度,该类型范围为10-65之间");
                 } else if (eType.equals("datetime") && (eLength > 400 || eLength < 0)) {
                     this.updateBatchById(beforeUpdateWbsFormElements);
-                    return  R.fail(eKey+"元素名称:"+eName+"请输入正确长度,该类型范围为0-400之间");
+                    return R.fail(eKey + "元素名称:" + eName + "请输入正确长度,该类型范围为0-400之间");
                 }
 
                 //设置默认长度
@@ -346,7 +361,39 @@ public class WbsFormElementServiceImpl extends BaseServiceImpl<WbsFormElementMap
                 int row1 = wbsTreeMapper.isThereAField(initTableName, eKey);
                 if (row1 > 0) {
                     try {
-                        baseMapper.updateFiledType(initTableName, eKey, "varchar", eLength);
+                        //1、查询当前表当前字段
+
+                        //字段配置的长度
+                        Integer filedLength = lengthMap.get(eKey);
+                        if(filedLength == null){
+                            throw new RuntimeException("字段不存在");
+                        }
+                        //获取当前字段数据的最长数据长度
+                        Integer maxLength = baseMapper.selectFiledDataMaxLength(initTableName, eKey);
+                        //初始长度
+                        int initLength = 250;
+                        //当前字段数据长度为null
+                        if (maxLength == null) {
+                            //设置初始长度
+                            baseMapper.updateFiledType(initTableName, eKey, "varchar", initLength);
+                            wbsFormElement.setELength(initLength);
+                            baseMapper.updateById(wbsFormElement);
+                        } else {
+                            //动态扩容 每次根据最大数据长度扩容100
+                            int newLength = maxLength + 100;
+                            //如果字段的长度与扩容后的值一致则不去修改字段
+                            if (filedLength == newLength) {
+                                continue;
+                            }
+                            //如果数据的最大长度 +100 都大于字段配置的长度  则重新设置字段的长度
+                            if (filedLength >= newLength) {
+                                baseMapper.updateFiledType(initTableName, eKey, "varchar", newLength);
+                                wbsFormElement.setELength(newLength);
+                                baseMapper.updateById(wbsFormElement);
+                                continue;
+                            }
+                            baseMapper.updateFiledType(initTableName, eKey, "varchar", eLength);
+                        }
                     } catch (Exception e) {
                         this.updateBatchById(beforeUpdateWbsFormElements);
                         throw new RuntimeException("字段长度范围超出总最大限制,请尝试缩小当前字段长度或其他字段长度");
@@ -868,23 +915,27 @@ public class WbsFormElementServiceImpl extends BaseServiceImpl<WbsFormElementMap
     }
 
     public boolean syncDataFiled(String initTableName, List<WbsFormElement> listData) {
-        for (WbsFormElement listDatum : listData) {
-            // String initTableFiledType = getInitTableFiledType(listDatum.getEType());
-            // int elementLength = getElementLength(initTableFiledType);
-            //同步
-            //判断是否存在该Key字段
-            int row1 = wbsTreeMapper.isThereAField(initTableName, listDatum.getEKey());
-            if (row1 == 0) {
-                //追加字段到实体表中
-                wbsTreeMapper.alterTableFiled(initTableName, listDatum.getEKey(), "varchar", DEFAULT_ELEMENT_LENGTH_VARCHAR);
-                //判断是否追加成功
-                int row2 = wbsTreeMapper.isThereAField(initTableName, listDatum.getEKey());
-                if (row2 != 1) {
-                    //追加失败,删除元素,跳过
-                    baseMapper.deleteElementByfId2(listDatum.getId());
+        try {
+            for (WbsFormElement listDatum : listData) {
+                // String initTableFiledType = getInitTableFiledType(listDatum.getEType());
+                // int elementLength = getElementLength(initTableFiledType);
+                //同步
+                //判断是否存在该Key字段
+                int row1 = wbsTreeMapper.isThereAField(initTableName, listDatum.getEKey());
+                if (row1 == 0) {
+                    //追加字段到实体表中
+                    wbsTreeMapper.alterTableFiled(initTableName, listDatum.getEKey(), "varchar", DEFAULT_ELEMENT_LENGTH_VARCHAR);
+                    //判断是否追加成功
+                    int row2 = wbsTreeMapper.isThereAField(initTableName, listDatum.getEKey());
+                    if (row2 != 1) {
+                        //追加失败,删除元素,跳过
+                        baseMapper.deleteElementByfId2(listDatum.getId());
+                    }
                 }
+                //baseMapper.addTableFiled(initTableName, listDatum.getEKey(), "varchar", DEFAULT_ELEMENT_LENGTH_VARCHAR);
             }
-            //baseMapper.addTableFiled(initTableName, listDatum.getEKey(), "varchar", DEFAULT_ELEMENT_LENGTH_VARCHAR);
+        } catch (Exception e) {
+            throw new RuntimeException("字段长度范围超出总最大限制,请尝试缩小当前字段长度或其他字段长度");
         }
         return true;
     }

+ 10 - 6
blade-service/blade-manager/src/main/java/org/springblade/manager/service/impl/WbsTreeContractServiceImpl.java

@@ -2386,7 +2386,6 @@ public class WbsTreeContractServiceImpl extends BaseServiceImpl<WbsTreeContractM
         //本次修改的节点
         List<String> updateList=new ArrayList<>();
 
-        //新增
         String sqlList="Select parent_id,node_name from m_wbs_tree_contract where contract_id="+wbsTreeContractRoot.getContractId()+" and wbs_id="+wbsTreeContractRoot.getWbsId()+" and is_deleted=0";
         List<WbsTreeContract> WbsTreeContractListupdate = jdbcTemplate.query(sqlList, new BeanPropertyRowMapper<>(WbsTreeContract.class));
         //导入节点与现有节点进行比较。进行修改编号
@@ -2425,7 +2424,7 @@ public class WbsTreeContractServiceImpl extends BaseServiceImpl<WbsTreeContractM
                     }
                 }
                 //wbs节点和分部工程的名称类型能对应上,并且编号不一样,并且祖级节点也都能对应上,就修改编号
-                if(vo.getNodeName().equals(dto.getDivisionName())&&vo.getNodeType()==2&&!vo.getPartitionCode().equals(dto.getDivisionCode())){
+                if(vo.getNodeName().equals(dto.getDivisionName())&&vo.getNodeType()==2&&(vo.getPartitionCode()==null||vo.getPartitionCode().equals(dto.getDivisionCode()))){
                     Boolean exist = this.isExist(dto, WbsTreeContractListupdate, 3, wbsTreeContractRoot);
                     if(exist){
                         if(isTrueNode(Arrays.asList(dto.getUnitName(),dto.getSubUnitName(),dto.getDivisionName()),vo)){
@@ -2481,7 +2480,7 @@ public class WbsTreeContractServiceImpl extends BaseServiceImpl<WbsTreeContractM
         int i=0;
         for (ImportTreeDto dto : list) {
             //新增
-            String sqlList1="Select parent_id,node_name from m_wbs_tree_contract where contract_id="+wbsTreeContractRoot.getContractId()+" and wbs_id="+wbsTreeContractRoot.getWbsId()+" and is_deleted=0";
+            String sqlList1="Select parent_id,node_name,p_id from m_wbs_tree_contract where contract_id="+wbsTreeContractRoot.getContractId()+" and wbs_id="+wbsTreeContractRoot.getWbsId()+" and is_deleted=0";
             List<WbsTreeContract> WbsTreeContractList = jdbcTemplate.query(sqlList1, new BeanPropertyRowMapper<>(WbsTreeContract.class));
             i++;
             //单位工程:如果没有被处理过,说明需要新增
@@ -2557,6 +2556,7 @@ public class WbsTreeContractServiceImpl extends BaseServiceImpl<WbsTreeContractM
                             String sql="Select node_name from m_wbs_tree_contract where p_key_id in("+String.join(",", ids)+")";
                             List<String> nodeNames = jdbcTemplate.query(sql, new SingleColumnRowMapper<>(String.class));
                             String result = String.join("",nodeNames);
+                            result=result+contract.getNodeName();
                             String ancestorsName= wbsTreeContractRoot.getNodeName()+StringUtils.defaultString(dto.getUnitName())
                                 + StringUtils.defaultString(dto.getSubUnitName());
                             if(result.equals(ancestorsName)){
@@ -2608,6 +2608,7 @@ public class WbsTreeContractServiceImpl extends BaseServiceImpl<WbsTreeContractM
                             String sql="Select node_name from m_wbs_tree_contract where p_key_id in("+String.join(",", ids)+")";
                             List<String> nodeNames = jdbcTemplate.query(sql, new SingleColumnRowMapper<>(String.class));
                             String result = String.join("",nodeNames);
+                            result=result+contract.getNodeName();
                             String ancestorsName= wbsTreeContractRoot.getNodeName()+StringUtils.defaultString(dto.getUnitName())
                                 + StringUtils.defaultString(dto.getSubUnitName())
                                 +StringUtils.defaultString(dto.getDivisionName());
@@ -2663,6 +2664,7 @@ public class WbsTreeContractServiceImpl extends BaseServiceImpl<WbsTreeContractM
                             String sql="Select node_name from m_wbs_tree_contract where p_key_id in("+String.join(",", ids)+")";
                             List<String> nodeNames = jdbcTemplate.query(sql, new SingleColumnRowMapper<>(String.class));
                             String result = String.join("",nodeNames);
+                            result=result+contract.getNodeName();
                             String ancestorsName= wbsTreeContractRoot.getNodeName()+StringUtils.defaultString(dto.getUnitName())
                                 + StringUtils.defaultString(dto.getSubUnitName())
                                 +StringUtils.defaultString(dto.getDivisionName())
@@ -2721,6 +2723,7 @@ public class WbsTreeContractServiceImpl extends BaseServiceImpl<WbsTreeContractM
                             String sql="Select node_name from m_wbs_tree_contract where p_key_id in("+String.join(",", ids)+")";
                             List<String> nodeNames = jdbcTemplate.query(sql, new SingleColumnRowMapper<>(String.class));
                             String result = String.join("",nodeNames);
+                            result=result+contract.getNodeName();
                             String ancestorsName= wbsTreeContractRoot.getNodeName()+StringUtils.defaultString(dto.getUnitName())
                                 + StringUtils.defaultString(dto.getSubUnitName())
                                 +StringUtils.defaultString(dto.getDivisionName())
@@ -3081,7 +3084,7 @@ public static boolean hasConflictingCodes(List<ImportTreeDto> list) {
                 return true;
             }
             //如果数据库中存在名称相同的节点,查询该节点的祖级节点
-            String sql="select p_key_id,node_name from m_wbs_tree_contract where is_deleted=0 and contract_id="+contractId+" and p_key_id in ("+String.join(",", list.stream().map(String::valueOf).collect(Collectors.toList()))+")";
+            String sql="select p_key_id,node_name,contract_id from m_wbs_tree_contract where is_deleted=0 and contract_id="+contractId+" and p_key_id in ("+String.join(",", list.stream().map(String::valueOf).collect(Collectors.toList()))+")";
             List<WbsTreeContract> wbsContracts = jdbcTemplate.query(sql, new BeanPropertyRowMapper<>(WbsTreeContract.class));
             String  fatherNodeName="";
             if(type==2){
@@ -3105,11 +3108,12 @@ public static boolean hasConflictingCodes(List<ImportTreeDto> list) {
                         String ancestors = jdbcTemplate.queryForObject(Sql, new SingleColumnRowMapper<>(String.class));
                         String[] ids = ancestors.split(",");
                         ids=Arrays.stream(ids)
-                            .filter(id -> !id.equals("0")) // 过滤掉值为 "0" 的元素
+                            .filter(i->!i.equals("0"))
                             .toArray(String[]::new);
-                        String sql1="Select node_name from m_wbs_tree_contract where p_key_id in("+String.join(",", ids)+")";
+                        String sql1="Select node_name from m_wbs_tree_contract where p_key_id in("+String.join(",", ids)+") and contract_id="+wbsContract.getContractId()+" and is_deleted=0";
                         List<String> nodeNames = jdbcTemplate.query(sql1, new SingleColumnRowMapper<>(String.class));
                         String join = String.join("", nodeNames);
+                        join=join+wbsContract.getNodeName();
                         if(join.equals(fatherNodeName)){
                             return true;
                         }

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

@@ -143,7 +143,7 @@ public class WbsTreePrivateServiceImpl extends BaseServiceImpl<WbsTreePrivateMap
             //如果className,unitName不为空,则要判断该节点是否是最小节点
             if (ObjectUtil.isNotEmpty(wbsTreePrivate.getClassName()) && ObjectUtil.isNotEmpty(wbsTreePrivate.getUnitName())) {
                 QueryWrapper<WbsTreePrivate> wrapper = new QueryWrapper<>();
-                wrapper.eq("parent_id", wbsTreePrivate.getId()).eq("is_deleted", 0);
+                wrapper.eq("parent_id", wbsTreePrivate.getId()).eq("project_id",  wbsTreePrivate.getProjectId());
                 //查出当前节点所有子节点。如果子节点中没有节点,说明是最小节点
                 List<WbsTreePrivate> wbsTreePrivates = baseMapper.selectList(wrapper);
                 if (wbsTreePrivates.size() > 0) {

+ 0 - 30
blade-service/blade-manager/src/main/java/org/springblade/manager/utils/ExcelInfoUtils2.java

@@ -269,34 +269,4 @@ public class ExcelInfoUtils2 {
         return 1;
     }
 
-
-/*            6pt     8px
-            7pt     9px
-            7.5pt   10px
-            8pt     11px
-            9pt     12px
-            10pt     13px
-            10.5pt   14px
-            11pt     15px
-            12pt     16px
-            13pt     17px
-            13.5pt   18px
-            14pt     19px
-            14.5pt   20px
-            15pt     21px
-            16pt     22px
-            17pt     23px
-            18pt     24px
-            20pt     26px
-            22pt     29px
-            24pt     32px
-            26pt     35px
-            27pt     36px
-            28pt     37px
-            29pt     38px
-            30pt     40px
-            32pt     42px
-            34pt     45px
-            36pt     48px */
-
 }

+ 2 - 2
blade-service/blade-manager/src/main/java/org/springblade/manager/utils/FormEndPayUtil.java

@@ -19,7 +19,7 @@ public class FormEndPayUtil {
         FormEndPayUtil.jdbcTemplate = jdbcTemplate;
     }
     public static FormEndPay selectFormEndPay(Long periodId,Long contractId,String formNumber){
-        String sql="Select * from s_meter_form_end_pay where period_id="+periodId+" and contract_id="+contractId+" and form_number="+"'"+formNumber+"'";
+        String sql="Select * from s_meter_form_end_pay where period_id="+periodId+" and contract_id="+contractId+" and form_number="+"'"+formNumber+"' and is_deleted=0";
         List<FormEndPay> query = jdbcTemplate.query(sql, new BeanPropertyRowMapper<>(FormEndPay.class));
         if(query.isEmpty()){
             return null;
@@ -54,7 +54,7 @@ public class FormEndPayUtil {
         );
     }
     public static ChapterEndPay selectChapterEndPay(Long periodId,Long contractId,String formNumber){
-        String sql="Select * from s_meter_chapter_end_pay where period_id="+periodId+" and contract_id="+contractId+" and form_number="+"'"+formNumber+"'";
+        String sql="Select * from s_meter_chapter_end_pay where period_id="+periodId+" and contract_id="+contractId+" and form_number="+"'"+formNumber+"' and is_deleted=0";
         List<ChapterEndPay> query = jdbcTemplate.query(sql, new BeanPropertyRowMapper<>(ChapterEndPay.class));
         if(query.isEmpty()){
             return null;

+ 1 - 1
blade-service/blade-manager/src/main/java/org/springblade/manager/utils/PdfAddContextUtils.java

@@ -67,7 +67,7 @@ public class PdfAddContextUtils {
         Sheet sheet = workbook.getSheetAt(0);
         sheet.setForceFormulaRecalculation(true);
         int rowNum = sheet.getLastRowNum();
-        for (int i = 0; i < rowNum; i++) {
+        for (int i = 0; i < 6; i++) {
             Row row = sheet.getRow(i);
             if (row != null) {
                 short cellNum = row.getLastCellNum();

+ 3 - 3
blade-service/blade-manager/src/main/java/org/springblade/manager/utils/WbsElementUtil.java

@@ -62,7 +62,7 @@ public class WbsElementUtil {
                 case 5:  //数值
                 case 3:  //小数
                 case 4:  //日期
-                    return "50";
+                    return "100";
                 default:
                     return "0";
             }
@@ -79,7 +79,7 @@ public class WbsElementUtil {
                 case "bigint":
                 case "decimal":
                 case "datetime":
-                    return 50;
+                    return 100;
                 default:
                     return 0;
             }
@@ -99,7 +99,7 @@ public class WbsElementUtil {
                 case "数值":
                 case "小数":
                 case "日期":
-                    return 50;
+                    return 100;
                 default:
                     return 0;
             }

+ 19 - 7
blade-service/blade-meter/src/main/java/org/springblade/meter/controller/TaskController.java

@@ -177,6 +177,7 @@ public class TaskController extends BladeController {
     @ApiOperation(value = "获取任务名称", notes = "传入合同段contractId、期数id(变更令传勾选的id字符串英文逗号拼接)、type=1(中间计量申请)、=2(材料计量单)、3=(开工预付款计量单)、=4(变更令)")
     public R<Object> name(@RequestParam String contractId, @RequestParam String id, @RequestParam String type) {
         String name = null;
+        String ids=null;
         BigDecimal bigDecimal=BigDecimal.ZERO;
         if (ObjectUtil.isNotEmpty(contractId) && ObjectUtil.isNotEmpty(id)) {
             ContractInfo contractInfo = jdbcTemplate.query("SELECT contract_name FROM m_contract_info WHERE id = " + contractId, new BeanPropertyRowMapper<>(ContractInfo.class)).stream().findAny().orElse(null);
@@ -200,10 +201,14 @@ public class TaskController extends BladeController {
                 List<Long> longs = Func.toLongList(id);
                 if (contractInfo != null && longs.size() > 0) {
                     List<ChangeTokenForm> changeTokenForms = changeTokenFormService.getBaseMapper().selectBatchIds(longs);
-                    if (changeTokenForms.size() > 0) {
-                        List<String> collect = changeTokenForms.stream().map(ChangeTokenForm::getChangeNumber).collect(Collectors.toList());
-                        name = "【" + contractInfo.getContractName() + "】" + date + " 变更令【" + StringUtils.join(collect, "、") + "】";
+                    StringBuilder s=new StringBuilder("");
+                    StringBuilder s1=new StringBuilder("");
+                    for (ChangeTokenForm form : changeTokenForms) {
+                        s=s.append("【" + contractInfo.getContractName() + "】" + date + " 变更令【"+form.getChangeNumber()+"】"+",");
+                        s1=s1.append(form.getId()+",");
                     }
+                    name=s.substring(0,s.length()-1);
+                    ids=s1.substring(0,s1.length()-1);
                 }
             }
             List<Long> longs = Func.toLongList(id);
@@ -216,8 +221,9 @@ public class TaskController extends BladeController {
 
         }
         Map<String,Object> map=new HashMap<>();
-        map.put("name",name);
+        map.put("name", name);
         map.put("submitApprovalMoney",bigDecimal);
+        map.put("ids", ids);
         return R.data(200, map, "操作成功");
     }
 
@@ -641,6 +647,7 @@ public class TaskController extends BladeController {
         if (!objectR.isSuccess()) {
             throw new ServiceException(objectR.getMsg());
         }
+        List<String> taskNameList =Arrays.asList(approvalDTO.getTaskName().split(","));
 
         String[] formDataIds = approvalDTO.getPeriodId().split(",");
         String[] taskIdList = taskId.split(",");
@@ -664,7 +671,9 @@ public class TaskController extends BladeController {
             task.setTaskContent(ObjectUtil.isNotEmpty(approvalDTO.getTaskDesc()) ? approvalDTO.getTaskDesc() : null);
             task.setTaskUser(null);
             task.setFormDataId(formDataIds[i]); //数据指向,指向期数id(变更令为id英文逗号拼接)
-            task.setTaskName(approvalDTO.getTaskName());
+            if(i<=taskNameList.size()-1){
+                task.setTaskName(taskNameList.get(i));
+            }
             task.setContractId(approvalDTO.getContractId().toString());
             task.setProjectId(approvalDTO.getProjectId().toString());
             task.setBatch(approvalDTO.getBatch());
@@ -1423,8 +1432,10 @@ public class TaskController extends BladeController {
                             Task::getId,
                             task -> task));
         }
+
         //所有满足条件的日志 转map
-        String logQuery = "select business_id,create_user_name ,create_time, operation_type  from u_operation_log where  operation_content like '%废除%'";
+        //String logQuery = "select business_id,create_user_name ,create_time, operation_type  from u_operation_log where  operation_content like '%废除%'";
+        String logQuery="select business_id,create_user_name ,create_time, operation_type  from u_operation_log where  operation_type IN (6,9,26,61,62)";
         List<OperationLog> operationLogs = jdbcTemplate.query(logQuery, new BeanPropertyRowMapper<>(OperationLog.class));
         if(ObjectUtil.isNotEmpty(operationLogs)){
             operationLogMap = operationLogs.stream().collect(Collectors.groupingBy(OperationLog::getBusinessId));
@@ -3938,6 +3949,7 @@ public class TaskController extends BladeController {
             }
             //查询出当前计量期对应的任务
             String selectTask = "SELECT * from u_task WHERE approval_type =? and form_data_id = ? and is_deleted = 0 and status in (1,2)";
+
             List<Task> list = jdbcTemplate.query(selectTask, new BeanPropertyRowMapper<>(Task.class), type1,periodId);
             System.out.println("wewecq"+selectTask);
             if (list.size() == 0){
@@ -5078,7 +5090,7 @@ public class TaskController extends BladeController {
         strings.add("造价机构现场咨询意见_现场造价人员");
         strings.add("造价机构现场咨询意见_现场造价人员_负责人");
         strings.add("建设单位签收");
-        strings.add("建设单位签收_日期");
+      //  strings.add("建设单位签收_日期");
         WbsTreePrivate aPrivate = r.getData();
         String fileUrl = null;
         String os = System.getProperty("os.name").toLowerCase();

+ 8 - 0
blade-service/blade-meter/src/main/java/org/springblade/meter/mapper/ChangeTokenFormMapper.java

@@ -94,4 +94,12 @@ public interface ChangeTokenFormMapper extends BaseMapper<ChangeTokenForm> {
     void deleteCollectForm(@Param("tokenId")Long id);
 
     List<MiddleMeterApply> getChangeMiddleTotal(@Param("contractId") Long contractId,@Param("tokenId") Long id);
+
+    List<ChangeTokenInventory> getAllContractFormByTokenId(@Param("id") Long id);
+
+    List<ChangeTokenInventory> getInventoryByMeterIdAndFormId(@Param("contractMeterId") Long contractMeterId, @Param("contractFormId") Long contractFormId);
+
+    List<ChangeTokenForm> getChangeTokenFormByCommandDate(@Param("tokenIds") List<Long> tokenIds,@Param("id") Long id);
+
+    List<ChangeFormVO2> getFormList4(@Param("id") Long id, @Param("contractId") Long contractId);
 }

+ 29 - 2
blade-service/blade-meter/src/main/java/org/springblade/meter/mapper/ChangeTokenFormMapper.xml

@@ -328,6 +328,33 @@
         where is_deleted = 0 and contract_id = #{contractId} and
             FIND_IN_SET(#{tokenId}, change_token_ids)
     </select>
-
-
+    <select id="getAllContractFormByTokenId" resultType="org.springblade.meter.entity.ChangeTokenInventory">
+        select * from s_change_token_inventory where change_token_id = #{id} and is_deleted = 0 and is_collect_form = 0
+    </select>
+    <select id="getInventoryByMeterIdAndFormId" resultType="org.springblade.meter.entity.ChangeTokenInventory">
+        select * from s_change_token_inventory where contract_meter_id=#{contractMeterId} and contract_form_id=#{contractFormId} and is_deleted = 0
+    </select>
+    <select id="getChangeTokenFormByCommandDate" resultType="org.springblade.meter.entity.ChangeTokenForm">
+        SELECT *
+        FROM s_change_token_form
+        WHERE id IN
+        <foreach collection="tokenIds" item="id" open="(" separator=", " close=")">
+            #{id}
+        </foreach>
+        AND command_status = 1
+        AND update_time > (
+        SELECT update_time
+        FROM s_change_token_form
+        WHERE id = #{id}
+        )
+        ORDER BY update_time ASC
+    </select>
+    <select id="getFormList4" resultType="org.springblade.meter.vo.ChangeFormVO2">
+        select cti.contract_form_id as id,cti.contract_meter_id as contractMeterId,
+               cti.change_total as changeTotal,
+               cti.current_price as currentPrice
+        from s_change_token_inventory as cti
+        where cti.contract_id = #{contractId} and cti.is_deleted = 0
+          AND cti.change_token_id = #{id} and is_collect_form = 0
+    </select>
 </mapper>

+ 2 - 0
blade-service/blade-meter/src/main/java/org/springblade/meter/mapper/ChangeTokenInventoryMapper.java

@@ -30,4 +30,6 @@ public interface ChangeTokenInventoryMapper extends BaseMapper<ChangeTokenInvent
 
 
     void deleteByTokenId(@Param("id") Long id);
+
+    ChangeTokenInventory getCollectForm(@Param("changeTokenId")Long changeTokenId,@Param("contractFormId")Long contractFormId);
 }

+ 3 - 0
blade-service/blade-meter/src/main/java/org/springblade/meter/mapper/ChangeTokenInventoryMapper.xml

@@ -24,6 +24,9 @@
         DELETE FROM s_change_token_inventory
         where change_token_id = #{id}
     </delete>
+    <select id="getCollectForm" resultType="org.springblade.meter.entity.ChangeTokenInventory">
+        SELECT * FROM s_change_token_inventory where  change_token_id=#{changeTokenId} and contract_form_id=#{contractFormId} and is_collect_form=1 and is_deleted=0
+    </select>
 
 
 </mapper>

+ 2 - 0
blade-service/blade-meter/src/main/java/org/springblade/meter/mapper/InventoryFormMeterMapper.java

@@ -43,4 +43,6 @@ public interface InventoryFormMeterMapper extends BaseMapper<InventoryFormMeter>
 
     //根据计量单元id,删除当前节点以及下层节点,关联的所有清单
     void deleteByNodeId(@Param("meterId") Long meterId,@Param("contractId") Long contractId);
+
+    InventoryFormMeter getifm(@Param("id") Long id, @Param("contractMeterId") Long contractMeterId);
 }

+ 4 - 0
blade-service/blade-meter/src/main/java/org/springblade/meter/mapper/InventoryFormMeterMapper.xml

@@ -54,5 +54,9 @@
             #{id}
         </foreach>
     </select>
+    <select id="getifm" resultType="org.springblade.meter.entity.InventoryFormMeter">
+        select * from s_inventory_form_meter
+        where contract_form_id = #{id} and contract_meter_id = #{contractMeterId}  and is_deleted = 0
+    </select>
 
 </mapper>

+ 1 - 0
blade-service/blade-meter/src/main/java/org/springblade/meter/service/IChangeTokenInventoryService.java

@@ -33,4 +33,5 @@ public interface IChangeTokenInventoryService extends BaseService<ChangeTokenInv
     //删除当前变更令下的清单
     void deleteByTokenId(Long tokenId);
 
+    ChangeTokenInventory getCollectForm(Long changeTokenId,Long contractFormId);
 }

+ 3 - 0
blade-service/blade-meter/src/main/java/org/springblade/meter/service/IInventoryFormMeterService.java

@@ -16,6 +16,7 @@
  */
 package org.springblade.meter.service;
 
+import org.apache.ibatis.annotations.Param;
 import org.springblade.core.tool.api.R;
 import org.springblade.meter.dto.MeterTreeContractDTO;
 import org.springblade.meter.entity.InventoryFormMeter;
@@ -49,4 +50,6 @@ public interface IInventoryFormMeterService extends BaseService<InventoryFormMet
      * 删除 同合计量 清单
      */
     R delInMeterInfo(String meterId, Long formIds);
+
+    InventoryFormMeter getifm(@Param("id") Long id, @Param("contractMeterId") Long contractMeterId);
 }

+ 91 - 37
blade-service/blade-meter/src/main/java/org/springblade/meter/service/impl/ChangeTokenFormServiceImpl.java

@@ -25,6 +25,7 @@ import org.apache.commons.lang.StringUtils;
 import org.springblade.business.entity.Task;
 import org.springblade.common.utils.SnowFlakeUtil;
 import org.springblade.core.log.exception.ServiceException;
+import org.springblade.core.mp.base.BaseEntity;
 import org.springblade.core.mp.support.Query;
 import org.springblade.core.tool.utils.Func;
 import org.springblade.core.tool.utils.ObjectUtil;
@@ -48,6 +49,7 @@ import java.time.LocalDate;
 import java.time.LocalDateTime;
 import java.util.*;
 import java.util.stream.Collectors;
+import java.util.stream.Stream;
 
 /**
  * 变更令表 服务实现类
@@ -715,12 +717,45 @@ public class ChangeTokenFormServiceImpl extends BaseServiceImpl<ChangeTokenFormM
         }
 
         //判断是否有清单执行过二次变更,执行过则不能撤销
-        List<ChangeFormVO2> vo2 = baseMapper.getMultipleChange(id);
-        if (vo2.size() != 0){
-            String s = vo2.stream().map(ChangeFormVO2::getFormName).distinct().collect(Collectors.joining(",", "[", "]"));
-            throw new ServiceException("清单:"+s+"在当前变更之后又发生过变更,请先撤销上一次变更");
-        }
-
+//        List<ChangeFormVO2> vo2 = baseMapper.getMultipleChange(id);
+//        if (vo2.size() != 0){
+//            String s = vo2.stream().map(ChangeFormVO2::getFormName).distinct().collect(Collectors.joining(",", "[", "]"));
+//            throw new ServiceException("清单:"+s+"在当前变更之后又发生过变更,请先撤销上一次变更");
+//        }
+        //取消上面的限制,允许跳过第二次变更去撤销第一次的变更,根据增减量,所有相关的全部都要改变  2025-05-14 王博念
+        boolean flag=false;
+          List<ChangeFormVO2> vo2 = baseMapper.getMultipleChange(id);
+           if(vo2.size()!=0){
+               flag=true;
+            //查出当前变更令所有的清单
+             List<ChangeTokenInventory> list=baseMapper.getAllContractFormByTokenId(id);
+               //根据清单查出当前部位用了当前清单的所有的变更令
+               for (ChangeTokenInventory inventory : list) {
+                   List<ChangeTokenInventory> list1=baseMapper.getInventoryByMeterIdAndFormId(inventory.getContractMeterId(),inventory.getContractFormId());
+                   //查出当前变更令的下达时间,根据时间排序
+                   List<Long> tokenIds = list1.stream().map(o -> o.getChangeTokenId()).collect(Collectors.toList());
+                   List<ChangeTokenForm> list2 = baseMapper.getChangeTokenFormByCommandDate(tokenIds, inventory.getChangeTokenId());
+//                   for (ChangeTokenForm tokenForm : list2) {
+//                       tokenForm.setChangeMoney(tokenForm.getChangeMoney().subtract(inventory.getChangeMoney()));
+//                       baseMapper.updateById(tokenForm);
+//                   }
+                   List<Long> changeTokenIds = list2.stream().map(O -> O.getId()).collect(Collectors.toList());
+                   List<ChangeTokenInventory> updateInventory = list1.stream().filter(o -> changeTokenIds.contains(o.getChangeTokenId())).collect(Collectors.toList());
+                   for (ChangeTokenInventory tokenInventory : updateInventory) {
+                       tokenInventory.setChangeBeforeTotal(tokenInventory.getChangeBeforeTotal().subtract(inventory.getChangeTotal()));
+                       tokenInventory.setChangeAfterTotal(tokenInventory.getChangeAfterTotal().subtract(inventory.getChangeTotal()));
+                       tokenInventory.setChangeBeforeMoney(tokenInventory.getChangeBeforeTotal().multiply(tokenInventory.getCurrentPrice()));
+                       tokenInventory.setChangeAfterMoney(tokenInventory.getChangeAfterTotal().multiply(tokenInventory.getCurrentPrice()));
+                       changeTokenInventoryService.getBaseMapper().updateById(tokenInventory);
+                       ChangeTokenInventory cti=changeTokenInventoryService.getCollectForm(tokenInventory.getChangeTokenId(),tokenInventory.getContractFormId());
+                       cti.setChangeBeforeTotal(cti.getChangeBeforeTotal().subtract(inventory.getChangeTotal()));
+                       cti.setChangeAfterTotal(cti.getChangeAfterTotal().subtract(inventory.getChangeTotal()));
+                       cti.setChangeBeforeMoney(cti.getChangeBeforeTotal().multiply(inventory.getCurrentPrice()));
+                       cti.setChangeAfterMoney(cti.getChangeAfterTotal().multiply(inventory.getCurrentPrice()));
+                       changeTokenInventoryService.getBaseMapper().updateById(cti);
+                   }
+               }
+          }
         //双重验证,中间计量申请存在先删除变更清单,又添加回来的操作
         List<MiddleMeterApply> middles = baseMapper.getChangeMiddleTotal(form.getContractId(),id);
         if (middles.size() > 0){
@@ -740,41 +775,60 @@ public class ChangeTokenFormServiceImpl extends BaseServiceImpl<ChangeTokenFormM
                 throw new ServiceException("当前变更令已经修改中间计量申请的清单:"+s+"的数据,不能撤销变更,删除计量清单之后允许撤销");
             }
         }
+        //取消限制后的
+        if(flag){
+            //修改合同清单
+            List<ChangeTokenInventory> list=baseMapper.getAllContractFormByTokenId(id);
+            for (ChangeTokenInventory inventory : list) {
+                ContractInventoryForm form1 = contractInventoryFormService.getById(inventory.getContractFormId());
+                form1.setChangeTotal(form1.getChangeTotal().subtract(inventory.getChangeTotal()));
+                form1.setChangeMoney(form1.getChangeTotal().multiply(form1.getCurrentPrice()));
+                contractInventoryFormService.updateById(form1);
+            }
+            //修改清单与合同计量单元中间表
+            List<ChangeFormVO2> allForm = baseMapper.getFormList4(id,form.getContractId());
+            for (ChangeFormVO2 cf2 : allForm) {
+             InventoryFormMeter ifm=inventoryFormMeterService.getifm(cf2.getId(),cf2.getContractMeterId());
+                ifm.setChangeBuildPictureTotal(ifm.getChangeBuildPictureTotal().subtract(cf2.getChangeTotal()));
+                ifm.setBuildPictureMoney(ifm.getChangeBuildPictureTotal().multiply(cf2.getCurrentPrice()));
+                inventoryFormMeterService.getBaseMapper().updateById(ifm);
+            }
+        }else {
+            //通过汇总项修改合同清单
+            List<ChangeFormVO2> vo3 = baseMapper.getAllCollectForm(id);
+            if (vo3.size() == 0){
+                throw new ServiceException("当前变更令的变更清单为空,撤销失败");
+            }
+            List<ContractInventoryForm> list2 = new ArrayList<>();
+            for (ChangeFormVO2 vo : vo3) {
+                // 修改清单数量与金额
+                ContractInventoryForm fo = new ContractInventoryForm();
+                fo.setId(vo.getId());
+                fo.setChangeTotal(vo.getContractTotal());
+                fo.setChangeMoney(vo.getContractMoney());
+                list2.add(fo);
+            }
+            //批量修改合同工程清单,因为mybatis的修改是伪批量,所以手动拼接
+            baseMapper.batchUpdateForm(list2);
+            //修改清单与合同计量单元中间表
+            //清单与合同计量单元中间表集合,用于批量修改
+            List<InventoryFormMeter> list4 = new ArrayList<>();
+            //获取当前变更令的所有变更清单
+            List<ChangeFormVO2> allForm = baseMapper.getFormList3(id,form.getContractId());
+            for (ChangeFormVO2 v : allForm) {
+                InventoryFormMeter meter = new InventoryFormMeter();
+                meter.setContractFormId(v.getId());
+                meter.setContractMeterId(v.getContractMeterId());
+                meter.setChangeBuildPictureTotal(v.getChangeTotal());
+                meter.setChangeBuildPictureMoney(v.getChangeMoney());
+                list4.add(meter);
+            }
+            baseMapper.batchUpdateMeterForm(list4);
+        }
 
 
-        //通过汇总项修改合同清单
-        List<ChangeFormVO2> vo3 = baseMapper.getAllCollectForm(id);
-        if (vo3.size() == 0){
-            throw new ServiceException("当前变更令的变更清单为空,撤销失败");
-        }
-        List<ContractInventoryForm> list2 = new ArrayList<>();
-        for (ChangeFormVO2 vo : vo3) {
-            // 修改清单数量与金额
-            ContractInventoryForm fo = new ContractInventoryForm();
-            fo.setId(vo.getId());
-            fo.setChangeTotal(vo.getContractTotal());
-            fo.setChangeMoney(vo.getContractMoney());
-            list2.add(fo);
-        }
-        //批量修改合同工程清单,因为mybatis的修改是伪批量,所以手动拼接
-        baseMapper.batchUpdateForm(list2);
         //批量删除汇总项,因为撤销变更后,是可以下达的状态,下达时会重新生成最新的清单数据
         baseMapper.deleteCollectForm(id);
-
-        //修改清单与合同计量单元中间表
-        //清单与合同计量单元中间表集合,用于批量修改
-        List<InventoryFormMeter> list4 = new ArrayList<>();
-        //获取当前变更令的所有变更清单
-        List<ChangeFormVO2> allForm = baseMapper.getFormList3(id,form.getContractId());
-        for (ChangeFormVO2 v : allForm) {
-            InventoryFormMeter meter = new InventoryFormMeter();
-            meter.setContractFormId(v.getId());
-            meter.setContractMeterId(v.getContractMeterId());
-            meter.setChangeBuildPictureTotal(v.getChangeTotal());
-            meter.setChangeBuildPictureMoney(v.getChangeMoney());
-            list4.add(meter);
-        }
-        baseMapper.batchUpdateMeterForm(list4);
         //获取当前变更令的变更节点
         List<ChangeNodeVO> allNode = baseMapper.getNodeList3(id, form.getContractId());
         if (allNode.size() == 0){

+ 5 - 0
blade-service/blade-meter/src/main/java/org/springblade/meter/service/impl/ChangeTokenInventoryServiceImpl.java

@@ -36,4 +36,9 @@ public class ChangeTokenInventoryServiceImpl extends BaseServiceImpl<ChangeToken
     public void deleteByTokenId(Long id) {
         baseMapper.deleteByTokenId(id);
     }
+
+    @Override
+    public ChangeTokenInventory getCollectForm(Long changeTokenId,Long contractFormId) {
+        return baseMapper.getCollectForm(changeTokenId,contractFormId);
+    }
 }

部分文件因为文件数量过多而无法显示