فهرست منبع

Merge branch 'test-merge' of http://219.151.181.73:3000/zhuwei/bladex into test-merge

lvy 2 هفته پیش
والد
کامیت
4dd72adce8
55فایلهای تغییر یافته به همراه1701 افزوده شده و 494 حذف شده
  1. 1 6
      blade-common/src/main/java/org/springblade/common/utils/AsyncConfig.java
  2. 19 0
      blade-common/src/main/java/org/springblade/common/utils/CommonUtil.java
  3. 107 0
      blade-common/src/main/java/org/springblade/common/utils/SafeURLEncoder.java
  4. 1 1
      blade-common/src/main/java/org/springblade/common/utils/singleEexConfigurerConfig.java
  5. 4 0
      blade-gateway/src/main/java/org/springblade/gateway/provider/AuthProvider.java
  6. 6 0
      blade-service-api/blade-archive-api/src/main/java/org/springblade/archive/feign/ArchiveAutoClient.java
  7. 4 0
      blade-service-api/blade-archive-api/src/main/java/org/springblade/archive/vo/ArchivesAutoVO.java
  8. 4 0
      blade-service-api/blade-business-api/src/main/java/org/springblade/business/vo/ArchiveFileVO.java
  9. 2 0
      blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/feign/ArchiveTreeContractClient.java
  10. 3 2
      blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/vo/RebateIncentiveAdvPay.java
  11. 10 6
      blade-service/blade-archive/src/main/java/org/springblade/archive/controller/ArchiveFileAutoController.java
  12. 9 6
      blade-service/blade-archive/src/main/java/org/springblade/archive/controller/ArchiveFileController.java
  13. 31 6
      blade-service/blade-archive/src/main/java/org/springblade/archive/controller/ArchivesAutoController.java
  14. 5 0
      blade-service/blade-archive/src/main/java/org/springblade/archive/external/impl/ExternalDataArchiveAutoService.java
  15. 2 3
      blade-service/blade-archive/src/main/java/org/springblade/archive/external/impl/ExternalDataArchiveMetaService.java
  16. 44 11
      blade-service/blade-archive/src/main/java/org/springblade/archive/external/utils/TransUtil.java
  17. 5 1
      blade-service/blade-archive/src/main/java/org/springblade/archive/feign/ArchiveAutoClientImpl.java
  18. 4 0
      blade-service/blade-archive/src/main/java/org/springblade/archive/mapper/ArchivesAutoMapper.java
  19. 101 19
      blade-service/blade-archive/src/main/java/org/springblade/archive/mapper/ArchivesAutoMapper.xml
  20. 3 1
      blade-service/blade-archive/src/main/java/org/springblade/archive/mapper/TaskSplitMapper.java
  21. 7 4
      blade-service/blade-archive/src/main/java/org/springblade/archive/mapper/TaskSplitMapper.xml
  22. 2 0
      blade-service/blade-archive/src/main/java/org/springblade/archive/service/IArchivesAutoService.java
  23. 1 0
      blade-service/blade-archive/src/main/java/org/springblade/archive/service/impl/ArchiveExpertConclusionServiceImpl.java
  24. 35 0
      blade-service/blade-archive/src/main/java/org/springblade/archive/service/impl/ArchivesAutoServiceImpl.java
  25. 4 3
      blade-service/blade-archive/src/main/java/org/springblade/archive/service/impl/TaskSplitServiceImpl.java
  26. 28 5
      blade-service/blade-business/src/main/java/org/springblade/business/controller/InformationWriteQueryController.java
  27. 2 2
      blade-service/blade-business/src/main/java/org/springblade/business/controller/NeiYeController.java
  28. 56 52
      blade-service/blade-business/src/main/java/org/springblade/business/mapper/ArchiveFileMapper.xml
  29. 1 2
      blade-service/blade-business/src/main/java/org/springblade/business/service/impl/ArchiveFileServiceImpl.java
  30. 5 1
      blade-service/blade-business/src/main/java/org/springblade/business/service/impl/InformationQueryServiceImpl.java
  31. 7 2
      blade-service/blade-e-visa/src/main/java/org/springblade/evisa/EVisaApplication.java
  32. 433 0
      blade-service/blade-e-visa/src/main/java/org/springblade/evisa/controller/Archive2Controller.java
  33. 137 125
      blade-service/blade-e-visa/src/main/java/org/springblade/evisa/controller/ArchiveController.java
  34. 5 4
      blade-service/blade-e-visa/src/main/java/org/springblade/evisa/controller/Chek.java
  35. 8 3
      blade-service/blade-e-visa/src/main/java/org/springblade/evisa/controller/ChekSignData.java
  36. 35 0
      blade-service/blade-e-visa/src/main/java/org/springblade/evisa/utils/ArchivePoolExecutorConfig.java
  37. 3 3
      blade-service/blade-manager/src/main/java/org/springblade/manager/controller/ExcelTabController.java
  38. 5 0
      blade-service/blade-manager/src/main/java/org/springblade/manager/feign/ArchiveTreeContractImpl.java
  39. 4 1
      blade-service/blade-manager/src/main/java/org/springblade/manager/formula/impl/ExecutorMeter.java
  40. 10 0
      blade-service/blade-manager/src/main/java/org/springblade/manager/mapper/WbsFormElementMapper.xml
  41. 2 0
      blade-service/blade-manager/src/main/java/org/springblade/manager/service/IArchiveTreeContractService.java
  42. 28 0
      blade-service/blade-manager/src/main/java/org/springblade/manager/service/impl/ArchiveTreeContractServiceImpl.java
  43. 13 7
      blade-service/blade-manager/src/main/java/org/springblade/manager/service/impl/ExcelTabServiceImpl.java
  44. 8 3
      blade-service/blade-manager/src/main/java/org/springblade/manager/service/impl/FormulaServiceImpl.java
  45. 11 0
      blade-service/blade-manager/src/main/java/org/springblade/manager/service/impl/TextdictInfoServiceImpl.java
  46. 30 11
      blade-service/blade-manager/src/main/java/org/springblade/manager/service/impl/WbsFormElementServiceImpl.java
  47. 40 6
      blade-service/blade-manager/src/main/java/org/springblade/manager/service/impl/WbsSynchronousEViSaServiceImpl.java
  48. 70 127
      blade-service/blade-manager/src/main/java/org/springblade/manager/service/impl/WbsSynchronousServiceImpl.java
  49. 6 1
      blade-service/blade-manager/src/main/java/org/springblade/manager/service/impl/WbsTreeContractServiceImpl.java
  50. 32 5
      blade-service/blade-meter/src/main/java/org/springblade/meter/service/impl/InterimPayCertificateServiceImpl.java
  51. 23 0
      blade-service/blade-user/src/main/java/org/springblade/system/user/bean/CyGetToken.java
  52. 35 0
      blade-service/blade-user/src/main/java/org/springblade/system/user/bean/ResultCYData.java
  53. 37 0
      blade-service/blade-user/src/main/java/org/springblade/system/user/bean/ResultCYKey.java
  54. 151 20
      blade-service/blade-user/src/main/java/org/springblade/system/user/controller/UserController.java
  55. 62 45
      blade-service/blade-user/src/main/java/org/springblade/system/user/util/RsaUtils.java

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

@@ -1,16 +1,11 @@
 package org.springblade.common.utils;
 
-import lombok.extern.slf4j.Slf4j;
 import org.springframework.context.annotation.Bean;
 import org.springframework.context.annotation.Configuration;
-import org.springframework.scheduling.annotation.EnableAsync;
 
 import java.util.concurrent.*;
-
-@Slf4j
 @Configuration
-@EnableAsync
-public class AsyncConfigurer {
+public class AsyncConfig {
 
     /**
      * cpu 核心数量

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

@@ -140,6 +140,25 @@ public class CommonUtil {
         inputStream.close();
     }
 
+
+    public static InputStream getOSSInputStream3(String urlStr) {
+        try {
+            System.out.println("----前-------"+urlStr);
+            int lastIndex = urlStr.lastIndexOf("/") + 1;
+            String fileName = urlStr.substring(lastIndex);
+            urlStr = urlStr.substring(0, lastIndex) + URLEncoder.encode(fileName, "UTF-8").replace("+", "%20");
+            //获取OSS文件流
+            URL url = new URL(urlStr);
+            URLConnection conn = url.openConnection();
+
+            conn.setRequestProperty("User-Agent", "Mozilla/4.0 (compatible; MSIE 5.0; Windows NT; DigExt)");
+            return conn.getInputStream();
+        } catch (Exception e) {
+            System.out.println("-----后------"+urlStr);
+            return null;
+        }
+    }
+
     /**
      * 根据OSS文件路径获取文件输入流
      */

+ 107 - 0
blade-common/src/main/java/org/springblade/common/utils/SafeURLEncoder.java

@@ -0,0 +1,107 @@
+package org.springblade.common.utils;
+
+import java.net.URLEncoder;
+import java.nio.charset.StandardCharsets;
+
+public class SafeURLEncoder {
+
+
+    public static String encodeFullUrl(String fullUrl) {
+        if (fullUrl == null || fullUrl.isEmpty()) {
+            return fullUrl;
+        }
+
+        // 查找最后一个斜杠位置
+        int lastSlashIndex = fullUrl.lastIndexOf('/');
+
+        // 如果没有斜杠,直接返回原URL
+        if (lastSlashIndex == -1) {
+            return fullUrl;
+        }
+
+        // 分割URL为基本部分和文件名
+        String baseUrl = fullUrl.substring(0, lastSlashIndex + 1);
+        String fileName = fullUrl.substring(lastSlashIndex + 1);
+
+        // 只对文件名进行安全编码
+        String safeFileName = encodeURLComponent(fileName);
+
+        // 重新组合URL
+        return baseUrl + safeFileName;
+    }
+
+
+    private static String encodeURLComponent(String input) {
+        if (input == null || input.isEmpty()) {
+            return input;
+        }
+
+        // 检查是否只包含安全字符
+        if (isSafeString(input)) {
+            return input;
+        }
+
+        // 需要编码的特殊处理
+        return encodeSpecial(input);
+    }
+
+
+    private static boolean isSafeString(String input) {
+        for (int i = 0; i < input.length(); i++) {
+            char c = input.charAt(i);
+            if (!isSafeCharacter(c)) {
+                return false;
+            }
+        }
+        return true;
+    }
+
+
+    private static boolean isSafeCharacter(char c) {
+        return (c >= 'a' && c <= 'z') ||
+                (c >= 'A' && c <= 'Z') ||
+                (c >= '0' && c <= '9') ||
+                c == '-' || c == '_' || c == '.' ||
+                c == '~' || c == '*';
+    }
+
+
+    private static String encodeSpecial(String input) {
+        try {
+            // 首先处理百分号(防止双重编码)
+            String percentFixed = input.replace("%", "%25");
+
+            // 执行URL编码
+            String encoded = URLEncoder.encode(percentFixed, StandardCharsets.UTF_8.name());
+
+            // 处理空格和修复双重编码问题
+            return encoded.replace("+", "%20")
+                    .replace("%2525", "%25");
+        } catch (Exception e) {
+            return input; // 出错时返回原始输入
+        }
+    }
+
+    // 测试用例
+    public static void main(String[] args) {
+        // 需要编码的复杂URL
+        String complexUrl = "http://100.86.2.1:80/huazheng2021/folderFile/0cc855e1e2524a4183e03cc500e4/aff588c4a69d4b9c977cfa71c32d3b8f/5.G7522天峨至北海公路(平塘至天峨广西段)月里互通A匝道桥、月里6号桥、拉堡1号桥、拉京高架桥、老寨高架大桥、罗屯1号桥荷载试验报告,桥梁外观检测报告 (2)-20250717033205.pdf";
+        System.out.println("编码后的URL: " + encodeFullUrl(complexUrl));
+
+        // 不需要编码的简单URL
+        String safeUrl = "https://example.com/reports/annual_report_2025.pdf";
+        System.out.println("安全URL: " + encodeFullUrl(safeUrl));
+
+        // 带有空格的URL
+        String withSpace = "https://example.com/reports/Q1 financial report.docx";
+        System.out.println("带空格URL: " + encodeFullUrl(withSpace));
+
+        // 只有基础URL没有文件名
+        String baseOnly = "https://example.com/downloads/";
+        System.out.println("只有基础URL: " + encodeFullUrl(baseOnly));
+
+        // 没有斜杠的URL
+        String noSlash = "downloads/annual-report.pdf";
+        System.out.println("没有斜杠: " + encodeFullUrl(noSlash));
+    }
+}

+ 1 - 1
blade-common/src/main/java/org/springblade/common/utils/singleEexConfigurer.java → blade-common/src/main/java/org/springblade/common/utils/singleEexConfigurerConfig.java

@@ -11,7 +11,7 @@ import java.util.concurrent.*;
 @Slf4j
 @Configuration
 @EnableAsync
-public class singleEexConfigurer {
+public class singleEexConfigurerConfig {
 
     /**
      * 线程池配置

+ 4 - 0
blade-gateway/src/main/java/org/springblade/gateway/provider/AuthProvider.java

@@ -63,6 +63,10 @@ public class AuthProvider {
         DEFAULT_SKIP_URL.add("/appVersion/page");
         DEFAULT_SKIP_URL.add("/appVersionDetail/**");
         DEFAULT_SKIP_URL.add("/websocket/**");
+        DEFAULT_SKIP_URL.add("/getPk"); //成渝第三方登录获取公钥
+        DEFAULT_SKIP_URL.add("/getQualityTestingToken"); //成渝第三方登录获取质检系统tokne
+        DEFAULT_SKIP_URL.add("/getArchiveToken"); //成渝第三方登录获取档案系统tokne
+
     }
 
     /**

+ 6 - 0
blade-service-api/blade-archive-api/src/main/java/org/springblade/archive/feign/ArchiveAutoClient.java

@@ -43,5 +43,11 @@ public interface ArchiveAutoClient {
     @PostMapping(API_PREFIX + "/batchUpdateExpertId")
     R<Boolean> batchUpdateExpertId(@RequestBody UpdateExpertVO vo);
 
+    /**
+     * 批量修改档案申请验收状态
+     */
+    @PostMapping(API_PREFIX + "/removeArchivesByNodeIds")
+    void removeArchivesByNodeIds(@RequestBody List<Long> ids);
+
 
 }

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

@@ -169,6 +169,10 @@ public class ArchivesAutoVO extends ArchivesAuto {
 	 * 柜子内部搜索
 	 */
 	private String innerSearch;
+	/**
+	 * 权限标识码
+	 */
+	private String authCode;
 
 	/**
 	 * 排序规则

+ 4 - 0
blade-service-api/blade-business-api/src/main/java/org/springblade/business/vo/ArchiveFileVO.java

@@ -102,4 +102,8 @@ public class ArchiveFileVO extends ArchiveFile {
      * 是否已组卷
      */
     private Integer isArchive;
+    /**
+     * 权限码
+     */
+    private String authCode;
 }

+ 2 - 0
blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/feign/ArchiveTreeContractClient.java

@@ -88,4 +88,6 @@ public interface ArchiveTreeContractClient {
                          @RequestParam("contractName") String contractName,
                          @RequestParam("nodeName") String nodeName);
 
+    @PostMapping(API_PREFIX + "/getAuthCode")
+    public String getAuthCode(@RequestParam Long contractId);
 }

+ 3 - 2
blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/vo/RebateIncentiveAdvPay.java

@@ -36,9 +36,10 @@ public class RebateIncentiveAdvPay implements  DataModel{
     private String previousPay ;
     @JSONField(name = "key_7",label="本期扣回金额",ordinal = 10)
     private String currentPay ;
-    public void calc(String contractAmount,String dyTotalAmount){
+    public void calc(String contractAmount,String dyTotalAmount,String currentPeriodEndPay){
         double contractAmountD=BaseUtils.obj2DoubleZero(contractAmount);
-        double x=(2*(BaseUtils.obj2DoubleZero(subtotal)-0.3*contractAmountD)*BaseUtils.obj2DoubleZero(dyTotalAmount))/contractAmountD;
+        //2025/7/23  修改逻辑 将最后算出来的值需要减去上期末的扣回动员预付款 currentPeriodEndPay
+        double x=((2*(BaseUtils.obj2DoubleZero(subtotal) -0.3*contractAmountD)*BaseUtils.obj2DoubleZero(dyTotalAmount))/contractAmountD)-BaseUtils.obj2DoubleZero(currentPeriodEndPay);
         if(x>0){
             /*扣回款本身就是负数*/
             String s=new BigDecimal(x).setScale(5,BigDecimal.ROUND_HALF_UP).toPlainString();

+ 10 - 6
blade-service/blade-archive/src/main/java/org/springblade/archive/controller/ArchiveFileAutoController.java

@@ -261,12 +261,16 @@ ArchiveFileAutoController extends BladeController {
         if (queryVo.getNodeIds() == null || queryVo.getNodeIds().equals("")) {
             return R.data(null);
         }
-        List<ArchiveTreeContract> archiveTreeContracts = this.archiveTreeContractClient.queryAllChildByAncestors(queryVo.getNodeIds(), queryVo.getContractId());
-        if (archiveTreeContracts != null && archiveTreeContracts.size() > 0) {
-            List<String> ids = JSONArray.parseArray(JSONObject.toJSONString(archiveTreeContracts.stream().map(ArchiveTreeContract::getId).distinct().collect(Collectors.toList())), String.class);
-            ids.add(queryVo.getNodeIds());
-            queryVo.setNodeIdArray(ids);
-        }
+//        List<ArchiveTreeContract> archiveTreeContracts = this.archiveTreeContractClient.queryAllChildByAncestors(queryVo.getNodeIds(), queryVo.getContractId());
+//        if (archiveTreeContracts != null && archiveTreeContracts.size() > 0) {
+//            List<String> ids = JSONArray.parseArray(JSONObject.toJSONString(archiveTreeContracts.stream().map(ArchiveTreeContract::getId).distinct().collect(Collectors.toList())), String.class);
+//            ids.add(queryVo.getNodeIds());
+//            queryVo.setNodeIdArray(ids);
+//        }
+
+        //优化 获取权限表示码
+        String authCode = archiveTreeContractClient.getAuthCode(queryVo.getContractId());
+        queryVo.setAuthCode(authCode);
 
         return R.data(archivesAutoService.selectArchivesAutoFilePage(queryVo));
     }

+ 9 - 6
blade-service/blade-archive/src/main/java/org/springblade/archive/controller/ArchiveFileController.java

@@ -161,12 +161,15 @@ public class ArchiveFileController extends BladeController {
                 queryVo.setExtType(1);
             }
 
-            List<ArchiveTreeContract> archiveTreeContracts = this.archiveTreeContractClient.queryAllChildByAncestors(queryVo.getNodeIds(), queryVo.getContractId() == null ? null : Long.parseLong(queryVo.getContractId()));
-            if (archiveTreeContracts != null && archiveTreeContracts.size() > 0) {
-                List<String> ids = JSONArray.parseArray(JSONObject.toJSONString(archiveTreeContracts.stream().map(ArchiveTreeContract::getId).distinct().collect(Collectors.toList())), String.class);
-                ids.add(queryVo.getNodeIds());
-                queryVo.setNodeIdArray(ids);
-            }
+//            List<ArchiveTreeContract> archiveTreeContracts = this.archiveTreeContractClient.queryAllChildByAncestors(queryVo.getNodeIds(), queryVo.getContractId() == null ? null : Long.parseLong(queryVo.getContractId()));
+//            if (archiveTreeContracts != null && archiveTreeContracts.size() > 0) {
+//                List<String> ids = JSONArray.parseArray(JSONObject.toJSONString(archiveTreeContracts.stream().map(ArchiveTreeContract::getId).distinct().collect(Collectors.toList())), String.class);
+//                ids.add(queryVo.getNodeIds());
+//                queryVo.setNodeIdArray(ids);
+//            }
+            //优化
+            String authCode = this.archiveTreeContractClient.getAuthCode(queryVo.getContractId() == null ? null : Long.parseLong(queryVo.getContractId()));
+            queryVo.setAuthCode(authCode);
         }
         return R.data(this.archiveFileClient.selectArchiveFilePage(queryVo));
     }

+ 31 - 6
blade-service/blade-archive/src/main/java/org/springblade/archive/controller/ArchivesAutoController.java

@@ -144,13 +144,38 @@ public class ArchivesAutoController extends BladeController {
 		if(queryVo.getNodeIds() == null || queryVo.getNodeIds().equals("")){
 			return  R.data(null);
 		}
-		List<ArchiveTreeContract> archiveTreeContracts = this.archiveTreeContractClient.queryAllChildByAncestors(queryVo.getNodeIds(),queryVo.getContractId());
-		if(archiveTreeContracts != null && archiveTreeContracts.size() > 0){
-			List<String> ids = JSONArray.parseArray(JSONObject.toJSONString(archiveTreeContracts.stream().map(ArchiveTreeContract::getId).distinct().collect(Collectors.toList())), String.class);
-			ids.add(queryVo.getNodeIds());
-			queryVo.setNodeIdArray(ids);
-		}
+//		List<ArchiveTreeContract> archiveTreeContracts = this.archiveTreeContractClient.queryAllChildByAncestors(queryVo.getNodeIds(),queryVo.getContractId());
+//		if(archiveTreeContracts != null && archiveTreeContracts.size() > 0){
+//			List<String> ids = JSONArray.parseArray(JSONObject.toJSONString(archiveTreeContracts.stream().map(ArchiveTreeContract::getId).distinct().collect(Collectors.toList())), String.class);
+//			ids.add(queryVo.getNodeIds());
+//			queryVo.setNodeIdArray(ids);
+//		}
+
+		//优化 获取权限表示码
+		String authCode = archiveTreeContractClient.getAuthCode(queryVo.getContractId());
+		queryVo.setAuthCode(authCode);
 		IPage<ArchivesAutoVO> pages = archivesAutoService.selectArchivesAutoFilePage(queryVo);
+		int test = 0;
+		//todo 后续去掉
+		if (test > 1) {
+			List<String> nodeIdArray = queryVo.getNodeIdArray();
+			// 注意:在设置nodeIdArray的条件分支外,nodeIdArray可能为null
+			if (nodeIdArray != null) {
+				// 转换为List<Long>
+				List<Long> nodeIds = nodeIdArray.stream()
+						.map(Long::valueOf)
+						.collect(Collectors.toList());
+				// 调用方法
+				List<Long> archiveIds = archivesAutoService.getArchiveIdsByNodes(nodeIds);
+
+				// 新增代码:打印结果(保持一行输出)
+				String idsStr = archiveIds.stream()
+						.map(Object::toString)
+						.collect(Collectors.joining(", "));
+				System.out.println("Archive IDs: (" + idsStr + ")");
+
+			}
+		}
 		return R.data(pages);
 	}
 

+ 5 - 0
blade-service/blade-archive/src/main/java/org/springblade/archive/external/impl/ExternalDataArchiveAutoService.java

@@ -196,6 +196,11 @@ public class ExternalDataArchiveAutoService {
                     localArchive.setName(externalArchive.getName());
                     localArchive.setFileNumber(externalArchive.getFileNumber());
                     localArchive.setNodeId(externalArchive.getNodeId());
+                    if (externalArchive.getAutoFileSort()!= null) {
+                        localArchive.setAutoFileSort(externalArchive.getAutoFileSort());
+                    }
+
+
                     upArchives.add(localArchive);
                 }
             }

+ 2 - 3
blade-service/blade-archive/src/main/java/org/springblade/archive/external/impl/ExternalDataArchiveMetaService.java

@@ -25,10 +25,9 @@ public class ExternalDataArchiveMetaService {
 
     private final JdbcTemplate jdbcTemplate;
 
-    @Resource(name = "singleExecutor")
-    private ExecutorService executorService;
+    private final ExecutorService executorService;
 
-    private ArchivesAutoMapper autoMapper;
+    private final ArchivesAutoMapper autoMapper;
     public void handleArchiveMetas(Long projectId, ArchiveReq req, ExternalDataInfo externalDataInfo){
         syncData(projectId, req, externalDataInfo);
     }

+ 44 - 11
blade-service/blade-archive/src/main/java/org/springblade/archive/external/utils/TransUtil.java

@@ -34,11 +34,22 @@ public class TransUtil {
 
         //====建设单位数字化扫描档案(第一部分 综合文件)
         //三、征地拆迁资料
-        put("8d69b1589c8d47bcac6ee0579f21", 1927614316916244487L);
+//        put("8d69b1589c8d47bcac6ee0579f21", 1927614316916244487L);
+//
+//        //=======建设单位数字化扫描档案(第二部分 决算和审计文件)
+//        //一、支付报表及计算单
+//        put("c3073682882249cb83fb87ef83d4", 1927614316916244492L);
+        //建设单位数字化扫描档案(第一部分 综合文件)-一、竣(交)工验收文件
+        put("3b843c05e00c4b65a1e666db80cf", 1945670728317665282L);
+
+        //建设单位数字化扫描档案(第一部分 综合文件)-二、建设依据及上级有关指示
+        put("7255be0dc52543929cbe9c431930", 1945670728317665286L);
 
-        //=======建设单位数字化扫描档案(第二部分 决算和审计文件)
-        //一、支付报表及计算单
-        put("c3073682882249cb83fb87ef83d4", 1927614316916244492L);
+        //建设单位数字化扫描档案(第一部分 综合文件)-三、征地拆迁资料
+        put("ced7daa78cc040d1b731dfedd51f", 1945670728317665291L);
+
+        //建设单位数字化扫描档案(第二部分 决算和审计文件) 一、支付报表及计算单
+        put("c3073682882249cb83fb87ef83d4", 1945670728317665296L);
 
         //====监理
         //====================【第一总监】
@@ -51,16 +62,18 @@ public class TransUtil {
 
         //NoJL1合同段数字化扫描档案
         //一、监理管理文件
-        put("dfe39a7134c34aea833b51ecd889", 1927992314584629252L);
+        put("55fe4f6011294050b65210d814e0", 1927992314584629250L);
+
         //一、监理管理文件
         //(一)质量控制措施、规定
-        put("55fe4f6011294050b65210d814e0", 1927992314584629250L);
+        put("dfe39a7134c34aea833b51ecd889", 1927992314584629252L);
         //(二)质量控制往来文件
         put("f72d6d2c24564e01a456c8f49593", 1927992314584629253L);
         //(三)监理独立抽检资料(试验)
         put("972d06c557924952abaa8257dc71", 1927992314584629272L);
         //(四)监理独立抽检报告
         put("535f2dca3d4a4c6f84d3b154e961", 1927992314584629255L);
+
         //三、工程进度计划管理文件
         put("487c6416e2f34158838588773454", 1927992314584629286L);
         //五、其它文件
@@ -68,6 +81,9 @@ public class TransUtil {
         //六、其它资料
         put("1817a9c924fc4a9686ab5b02e077", 1927992314584629296L);
 
+
+
+
 //        //印章启用文件、监理人员变更的函和批复文件
 //        put("465c2ebad85e44e9b4217d7ae415", 1892759789402849282L);
 //        //工程监理月报(2022年1月至2023年2月)
@@ -111,16 +127,16 @@ public class TransUtil {
 
         //NoJL2合同段数字化扫描档案
         //一、监理管理文件
-
+        put("745caecba1834af6afca86f5bedc", 1927992314593017857L);
         //一、监理管理文件
         //(一)质量控制措施、规定
-
+        put("5d69bc7d2184458c89380fad8976", 1927992314593017859L);
         //(二)质量控制往来文件
-
+        put("6e07daf941574aa4b253f8bef735", 1927992314593017860L);
         //(三)监理独立抽检资料(试验)
-
+        put("68129b2bfcbb48dca9e0cc2ec5d9", 1927992314593017879L);
         //(四)监理独立抽检报告
-
+        put("425429964d674e3e969379a0e6b7", 1927992314593017862L);
         //三、工程进度计划管理文件
         put("a341cabc10834e42836424489eb9", 1927992314593017893L);
         //五、其它文件
@@ -151,6 +167,7 @@ public class TransUtil {
         put("f1ed755800004c4cb46440bc7ecb", 1927992314593017932L);
         //(四)监理独立抽检报告
         put("7bb1ceb7d69941e5a22a3343c266", 1927992314593017915L);
+
         //三、工程进度计划管理文件
         put("0d73872e37a14328a667510da2b7", 1927992314593017946L);
         //五、其它文件
@@ -200,6 +217,22 @@ public class TransUtil {
         //交工验收质量评定
         put("5831fc73d47a4f35b7df75e862df", 1927992314597212235L);
 
+        //----------------------数字化上传
+        //一、监理管理文件
+        put("e7e623e2efe247bf81fba84d48ba", 1945029232140746752L);
+
+        //二、工程质量控制文件
+        //(一)质量控制措施、规定
+        put("42e2e9d60ada40978022b43dc535", 1927992314597212216L);
+        //(二)质量控制往来文件
+        put("b41270b2c06748fe9a22deee9915", 1927992314597212217L);
+
+        //三、工程进度计划管理文件
+        put("a12760cc1afd4f319082d79c6ed0", 1927992314597212250L);
+        //五、其它文件
+        put("7fa912992c914825b2be2557bf06", 1927992314597212252L);
+        //六、其它资料
+        put("b4df96ff55384ad099686384dd8e", 1927992314597212260L);
 
 
         //===========施工单位归档资料

+ 5 - 1
blade-service/blade-archive/src/main/java/org/springblade/archive/feign/ArchiveAutoClientImpl.java

@@ -68,6 +68,10 @@ public class ArchiveAutoClientImpl implements ArchiveAutoClient {
         return R.data(true);
     }
 
+    @Override
+    public void removeArchivesByNodeIds(List<Long> ids) {
+        List<Long> archiveIds = archivesAutoService.getArchiveIdsByNodes(ids);
 
-
+        archivesAutoService.reomoveArchiveAndFile(archiveIds);
+    }
 }

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

@@ -138,6 +138,8 @@ public interface ArchivesAutoMapper extends BaseMapper<ArchivesAuto> {
 
 	Integer splitFiles(@Param("ids") List<Long> ids);
 
+	Integer removeFilesByArchiveIds(@Param("ids") List<Long> ids);
+
 	List<DictBiz> getCarrierTypeByDict();
 
 	void batchDestroyByIds(@Param("ids")List<String> ids,@Param("userId") Long userId);
@@ -186,6 +188,8 @@ public interface ArchivesAutoMapper extends BaseMapper<ArchivesAuto> {
 	IPage<ArchiveInspectVO> getNodeArchives2(IPage<ArchiveInspectVO> page,@Param("id") Long nodeId,@Param("projectId") Long projectId,@Param("searchType") Integer searchType,@Param("searchValue") String searchValue,@Param("userId") Long userId,@Param("conclusionId") Long conclusionId);
 
     List<ArchivesAuto> getNodeAllArchive(@Param("ids") List<Long> ids);
+	List<ArchivesAuto> getArchiveIdsByNodes(@Param("ids") List<Long> ids);
+
 
     Integer getUserArchiveTotal(@Param("projectId") Long projectId,@Param("userId") Long userId);
 

+ 101 - 19
blade-service/blade-archive/src/main/java/org/springblade/archive/mapper/ArchivesAutoMapper.xml

@@ -262,7 +262,8 @@
 
 
     <select id="selectArchivesAutoFileCount" resultType="java.lang.Integer">
-        select count(0) from u_archives_auto u LEFT JOIN m_archive_tree_contract m ON u.node_id = m.id where u.is_deleted = 0
+        select count(0) from u_archives_auto u LEFT JOIN m_archive_tree_contract m ON u.node_id = m.id
+        where u.is_deleted = 0 and m.is_deleted = 0
         <if test="vo.projectId != null and vo.projectId != ''">
             and u.project_id = #{vo.projectId}
         </if>
@@ -281,10 +282,10 @@
             and u.is_auto_file = #{vo.isAutoFile}
         </if>
         <if test="vo.nodeIds != null and vo.nodeIds != ''">
-            and u.node_id in
-            <foreach collection="vo.nodeIdArray" item="nodeId" open="(" separator="," close=")">
-                #{nodeId}
-            </foreach>
+            and (find_in_set(#{vo.nodeIds},m.ancestors) or m.id = #{vo.nodeIds})
+        </if>
+        <if test="vo.authCode != null and vo.authCode != ''">
+            AND (m.tree_code = #{authCode} or m.tree_code = #{contractId} or m.parent_id = 0)
         </if>
         <if test="vo.queryValueSize != null and vo.queryValueSize != ''">
             <choose>
@@ -305,7 +306,30 @@
     </select>
 
     <select id="selectArchivesAutoFilePage" resultMap="archivesAutoResultMap">
-        select * from u_archives_auto u LEFT JOIN m_archive_tree_contract m ON u.node_id = m.id where u.is_deleted = 0
+        select
+            * ,
+            CAST(
+                CASE
+                    WHEN SUBSTRING_INDEX(file_number, '-', -1) REGEXP '^[0-9]+$'
+                        THEN SUBSTRING_INDEX(file_number, '-', -1)
+                    WHEN SUBSTRING_INDEX(file_number, '•', -1) REGEXP '^[0-9]+$'
+                        THEN SUBSTRING_INDEX(file_number, '•', -1)
+                    WHEN SUBSTRING_INDEX(file_number, '·', -1) REGEXP '^[0-9]+$'
+                        THEN SUBSTRING_INDEX(file_number, '·', -1)
+                    WHEN SUBSTRING_INDEX(file_number, '_', -1) REGEXP '^[0-9]+$'
+                        THEN SUBSTRING_INDEX(file_number, '_', -1)
+                    ELSE
+                        REVERSE(
+                            SUBSTRING(
+                                REVERSE(file_number),
+                                1,
+                                LENGTH(REVERSE(file_number)) - LENGTH(TRIM(LEADING '0123456789' FROM REVERSE(file_number)))
+                            )
+                        )
+                END AS UNSIGNED
+            ) AS trailing_number
+        from u_archives_auto u LEFT JOIN m_archive_tree_contract m ON u.node_id = m.id
+        where u.is_deleted = 0 and m.is_deleted = 0
         <if test="vo.projectId != null and vo.projectId != ''">
             and u.project_id = #{vo.projectId}
         </if>
@@ -324,10 +348,10 @@
             and u.is_auto_file = #{vo.isAutoFile}
         </if>
         <if test="vo.nodeIds != null and vo.nodeIds != ''">
-            and u.node_id in
-            <foreach collection="vo.nodeIdArray" item="nodeId" open="(" separator="," close=")">
-                #{nodeId}
-            </foreach>
+            and (find_in_set(#{vo.nodeIds},m.ancestors) or m.id = #{vo.nodeIds})
+        </if>
+        <if test="vo.authCode != null and vo.authCode != ''">
+            AND (m.tree_code = #{authCode} or m.tree_code = #{contractId} or m.parent_id = 0)
         </if>
         <if test="vo.queryValueSize != null and vo.queryValueSize != ''">
             <choose>
@@ -350,12 +374,12 @@
                 ORDER BY
                     m.tree_sort,
                     CASE WHEN u.file_number IS NULL THEN 1 ELSE 0 END,
-                    CAST(SUBSTRING_INDEX(file_number, '_', -1) AS SIGNED)
+                    trailing_number
             </when>
             <when test="vo.sortRuleType != null and vo.sortRuleType == 2 and vo.isArchive != null and vo.isArchive != ''">
                 order by
                     CASE WHEN u.file_number IS NULL THEN 1 ELSE 0 END,
-                    CAST(SUBSTRING_INDEX(file_number, '_', -1) AS SIGNED)
+                    trailing_number
             </when>
             <otherwise>
                 order by m.tree_sort,u.auto_file_sort is null ,u.auto_file_sort,u.file_number is null,
@@ -631,7 +655,27 @@
         where project_id = #{projectId} and is_deleted = 0;
     </select>
     <select id="pageByArchivesAuto" resultMap="archivesAutoResultMap">
-        select uaa.*
+        select uaa.*,
+            CAST(
+                CASE
+                    WHEN SUBSTRING_INDEX(file_number, '-', -1) REGEXP '^[0-9]+$'
+                        THEN SUBSTRING_INDEX(file_number, '-', -1)
+                    WHEN SUBSTRING_INDEX(file_number, '•', -1) REGEXP '^[0-9]+$'
+                        THEN SUBSTRING_INDEX(file_number, '•', -1)
+                    WHEN SUBSTRING_INDEX(file_number, '·', -1) REGEXP '^[0-9]+$'
+                        THEN SUBSTRING_INDEX(file_number, '·', -1)
+                    WHEN SUBSTRING_INDEX(file_number, '_', -1) REGEXP '^[0-9]+$'
+                        THEN SUBSTRING_INDEX(file_number, '_', -1)
+                    ELSE
+                        REVERSE(
+                            SUBSTRING(
+                                REVERSE(file_number),
+                                1,
+                                LENGTH(REVERSE(file_number)) - LENGTH(TRIM(LEADING '0123456789' FROM REVERSE(file_number)))
+                            )
+                        )
+                END AS UNSIGNED
+            ) AS trailing_number
         from m_archive_tree_contract matc left join u_archives_auto uaa on matc.id = uaa.node_id left join
         u_archive_file uaf on uaa.id = uaf.archive_id
         where uaa.is_deleted = 0  and matc.is_deleted = 0 and uaa.is_archive = 1
@@ -697,12 +741,12 @@
                 ORDER BY
                 matc.tree_sort,
                 CASE WHEN uaa.file_number IS NULL THEN 1 ELSE 0 END,
-                CAST(SUBSTRING_INDEX(uaa.file_number, '_', -1) AS SIGNED)
+                trailing_number
             </when>
             <when test="vo.sortRuleType != null and vo.sortRuleType == 2">
                 ORDER BY
                 CASE WHEN uaa.file_number IS NULL THEN 1 ELSE 0 END,
-                CAST(SUBSTRING_INDEX(uaa.file_number, '_', -1) AS SIGNED)
+                trailing_number
             </when>
             <otherwise>
                 order by uaa.tree_sort,uaa.auto_file_sort,uaa.file_number asc
@@ -711,7 +755,27 @@
     </select>
 
     <select id="pageByArchivesAuto11" resultMap="archivesAutoResultMap">
-        select uaa.*
+        select uaa.*,
+            CAST(
+                CASE
+                    WHEN SUBSTRING_INDEX(file_number, '-', -1) REGEXP '^[0-9]+$'
+                        THEN SUBSTRING_INDEX(file_number, '-', -1)
+                    WHEN SUBSTRING_INDEX(file_number, '•', -1) REGEXP '^[0-9]+$'
+                        THEN SUBSTRING_INDEX(file_number, '•', -1)
+                    WHEN SUBSTRING_INDEX(file_number, '·', -1) REGEXP '^[0-9]+$'
+                        THEN SUBSTRING_INDEX(file_number, '·', -1)
+                    WHEN SUBSTRING_INDEX(file_number, '_', -1) REGEXP '^[0-9]+$'
+                        THEN SUBSTRING_INDEX(file_number, '_', -1)
+                    ELSE
+                        REVERSE(
+                            SUBSTRING(
+                                REVERSE(file_number),
+                                1,
+                                LENGTH(REVERSE(file_number)) - LENGTH(TRIM(LEADING '0123456789' FROM REVERSE(file_number)))
+                            )
+                        )
+                END AS UNSIGNED
+            ) AS trailing_number
         from m_archive_tree_contract matc left join u_archives_auto uaa on matc.id = uaa.node_id
         where uaa.is_deleted = 0 and matc.is_deleted = 0 and uaa.is_archive = 1
         <if test="vo.queryValue != null and vo.queryValue != ''">
@@ -771,12 +835,12 @@
                 ORDER BY
                 matc.tree_sort,
                 CASE WHEN uaa.file_number IS NULL THEN 1 ELSE 0 END,
-                CAST(SUBSTRING_INDEX(uaa.file_number, '_', -1) AS SIGNED)
+                trailing_number
             </when>
             <when test="vo.sortRuleType != null and vo.sortRuleType == 2">
                 ORDER BY
                 CASE WHEN uaa.file_number IS NULL THEN 1 ELSE 0 END,
-                CAST(SUBSTRING_INDEX(uaa.file_number, '_', -1) AS SIGNED)
+                trailing_number
             </when>
             <otherwise>
                 order by uaa.tree_sort,uaa.auto_file_sort,uaa.file_number asc
@@ -1272,7 +1336,7 @@
         (select id from m_archive_tree_contract
         WHERE project_id = #{projectId} and is_deleted = 0 and parent_id = 0)
         <if test="nodeType == null">
-            and tree_code is null
+            and (tree_code is null or tree_code = 'null')
         </if>
         <if test="nodeType != null and nodeType != ''">
             and tree_code = #{nodeType}
@@ -1340,6 +1404,15 @@
             #{id}
         </foreach>
     </select>
+
+    <select id="getArchiveIdsByNodes" resultType="org.springblade.archive.entity.ArchivesAuto">
+        select id
+        from u_archives_auto where is_deleted = 0  and node_id in
+        <foreach collection="ids" item="id" open="(" separator="," close=")">
+            #{id}
+        </foreach>
+    </select>
+
     <select id="getUserArchiveTotal" resultType="java.lang.Integer">
         SELECT COUNT(1) from u_archives_auto
         WHERE project_id = #{projectId} and is_deleted = 0 and FIND_IN_SET(#{userId},expert_id)
@@ -1425,6 +1498,15 @@
             #{id}
         </foreach>
     </update>
+
+    <update id="removeFilesByArchiveIds">
+        update u_archive_file set is_deleted = 1 where
+        archive_id in
+        <foreach collection="ids" item="id" open="(" separator="," close=")">
+            #{id}
+        </foreach>
+    </update>
+
     <update id="batchDestroyByIds">
         update u_archives_auto set is_deleted = 1 ,is_destroy = 1 ,update_user = #{userId} where
         id in

+ 3 - 1
blade-service/blade-archive/src/main/java/org/springblade/archive/mapper/TaskSplitMapper.java

@@ -46,5 +46,7 @@ public interface TaskSplitMapper extends BaseMapper<TaskSplit> {
 	// 获取分解任务是否存在
 	Integer getSpliteTaskCount(String contractId);
 
-	//Integer updateArchiveByIds(String contractId,);
+	Integer updateArchiveByContratId(String contractId);
+
+	Integer updateArchiveByIds(@Param("split") List<String> split);
 }

+ 7 - 4
blade-service/blade-archive/src/main/java/org/springblade/archive/mapper/TaskSplitMapper.xml

@@ -33,13 +33,16 @@
     <select id="getSpliteTaskCount" resultType="java.lang.Integer">
         select count(1) from u_task_split where contract_id = #{contractId} and type=2
     </select>
+    <update id="updateArchiveByContratId" >
+        update u_archives_auto set split_status = 0 where contract_id = #{contractId} and is_deleted = 0
+    </update>
 
-<!--    <update id="updateArchiveByIds">
-        update u_archives_auto set status = 1 where contract_id = #{contractId} and id in
-        <foreach item="item" collection="ids" separator="," close=")" open="(" index="index">
+    <update id="updateArchiveByIds">
+        update u_archives_auto set split_status = 0 where is_deleted = 0 and id in
+        <foreach item="item" collection="split" separator="," close=")" open="(" index="index">
             #{item}
         </foreach>
-    </update>-->
+    </update>
 
 
 </mapper>

+ 2 - 0
blade-service/blade-archive/src/main/java/org/springblade/archive/service/IArchivesAutoService.java

@@ -174,5 +174,7 @@ public interface IArchivesAutoService extends BaseService<ArchivesAuto> {
 
 	boolean sortRule(Long projectId, Integer type);
 
+	List<Long> getArchiveIdsByNodes(List<Long> ids);
 
+	void reomoveArchiveAndFile(List<Long> archiveIds);
 }

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

@@ -336,6 +336,7 @@ public class ArchiveExpertConclusionServiceImpl extends BaseServiceImpl<ArchiveE
         //创建字体
 //        BaseFont baseFont2 =BaseFont.createFont("C:/WINDOWS/Fonts/simsun.ttc,0", BaseFont.IDENTITY_H,BaseFont.NOT_EMBEDDED);
         BaseFont baseFont2 =BaseFont.createFont("/usr/share/fonts/chinese/simsun.ttc,0", BaseFont.IDENTITY_H,BaseFont.NOT_EMBEDDED);
+       // BaseFont baseFont2 =BaseFont.createFont("/Users/hongchuangyanfa/fsdownload/simsun.ttc,0", BaseFont.IDENTITY_H,BaseFont.NOT_EMBEDDED);
       //  BaseFont baseFont2 =BaseFont.createFont("/Users/hongchuangyanfa/fsdownload/simsun.ttc", BaseFont.IDENTITY_H,BaseFont.NOT_EMBEDDED);
      //   BaseFont baseFont2 =BaseFont.createFont(); //BaseFont.createFont("/Users/hongchuangyanfa/fsdownload/simsun.ttc", BaseFont.IDENTITY_H,BaseFont.NOT_EMBEDDED);
         //字体对象,这里可以创建一个方法

+ 35 - 0
blade-service/blade-archive/src/main/java/org/springblade/archive/service/impl/ArchivesAutoServiceImpl.java

@@ -5005,4 +5005,39 @@ public class ArchivesAutoServiceImpl extends BaseServiceImpl<ArchivesAutoMapper,
 		archivesSortRuleService.saveOrUpdate(one);
 		return true;
 	}
+
+	@Override
+	public List<Long> getArchiveIdsByNodes(List<Long> nodeIds) {
+		// 处理空输入
+		if (nodeIds == null || nodeIds.isEmpty()) {
+			return Collections.emptyList();
+		}
+
+		// 获取ArchivesAuto对象列表
+		List<ArchivesAuto> list = autoMapper.getArchiveIdsByNodes(nodeIds);
+
+		// 处理空结果
+		if (list == null || list.isEmpty()) {
+			return Collections.emptyList();
+		}
+
+		// 提取ID并返回
+		return list.stream()
+				.map(ArchivesAuto::getId)
+				.collect(Collectors.toList());
+	}
+
+	@Override
+	public void reomoveArchiveAndFile(List<Long> archiveIds) {
+		// 处理空输入
+		if (archiveIds == null || archiveIds.isEmpty()) {
+			return ;
+		}
+
+		// 获取ArchivesAuto对象列表
+		this.deleteLogic(archiveIds);
+
+		// 处理空结果
+		autoMapper.removeFilesByArchiveIds(archiveIds);
+	}
 }

+ 4 - 3
blade-service/blade-archive/src/main/java/org/springblade/archive/service/impl/TaskSplitServiceImpl.java

@@ -84,6 +84,9 @@ public class TaskSplitServiceImpl extends BaseServiceImpl<TaskSplitMapper, TaskS
 			taskSplit.setTaskName("整个合同段 "+archiveCount+" 条的分解任务");
 			data.put("fileCount",archiveCount);
 			data.put("taskTime",i);
+			// 修改整个合同任务状态为 未分解
+			baseMapper.updateArchiveByContratId(contractId);
+
 		}else{ // 指定文件解析
 			taskSplit.setType(3);
 			//String[] split = splitIds.split(",");
@@ -92,9 +95,6 @@ public class TaskSplitServiceImpl extends BaseServiceImpl<TaskSplitMapper, TaskS
 			taskSplit.setFinished(0);
 
 			// 修改当前文件的状体
-			// baseMapper.updateArchiveByIds(contractId,splitIds);
-
-
 			Random random = new Random();
 			int randomNumber = random.nextInt(30) + 150;// 生成10到20之间的随机数
 			int i = (int) Math.ceil(randomNumber * split.size()/60.0 );
@@ -104,6 +104,7 @@ public class TaskSplitServiceImpl extends BaseServiceImpl<TaskSplitMapper, TaskS
 			DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMdd HH:mm:ss");
 			String formattedDateTime = now.format(formatter)+"_"+split.size()+"条分解任务";
 			taskSplit.setTaskName(formattedDateTime);
+			baseMapper.updateArchiveByIds(split);
 		}
 
 		int insert = baseMapper.insert(taskSplit);

+ 28 - 5
blade-service/blade-business/src/main/java/org/springblade/business/controller/InformationWriteQueryController.java

@@ -1870,6 +1870,10 @@ public R<Boolean> copyContractTreeNode(@RequestBody CopyContractTreeNodeVO vo) {
                     //根据表明查询指定数据集合
                     List<WbsTreeContract> tabs = tabsGroup.get(tabName);
                     for (WbsTreeContract tab : tabs) {
+                        // 在复制数据时,测量记录表 的数据不需要复制
+                        if(tab.getType()==2 && tab.getTableType()==6){
+                            continue;
+                        }
                         //根据字段
                         String dataSql = "SELECT " + keys + " FROM " + tabName + " WHERE p_key_id = " + tab.getPKeyId() + " LIMIT 1;";
                         try {
@@ -2664,7 +2668,11 @@ private void addCopyTabData(WbsTreeContract needCopyNode, WbsTreeContract toCopy
                             String testColVal = reviseCols(eMap, colVal, oldPKeyId, tableName);
                             StaticLog.info("KT3356:" + testColVal);
                             copyDataSql.append(delSql).append("insert into ").append(tableName).append("  (").append(col).append(") select ").append(testColVal).append(" from ").append(tableName).append(" where p_key_id='").append(oldPKeyId).append("' LIMIT 1;");
-                            resultTablesData.add(copyDataSql.toString());
+                            if(needTab.getType()==2 && needTab.getTableType()==6){
+                                continue;
+                            }else{
+                                resultTablesData.add(copyDataSql.toString());
+                            }
                         }
                     }
 
@@ -2723,7 +2731,11 @@ private void addCopyTabData(WbsTreeContract needCopyNode, WbsTreeContract toCopy
                                 String testColVal = reviseCols(eMap, colVal, oldPKeyId, tableName);
                                 StaticLog.info("KT3356:" + testColVal);
                                 copyDataSql.append(delSql).append("insert into ").append(tableName).append("  (").append(col).append(") select ").append(testColVal).append(" from ").append(tableName).append(" where p_key_id='").append(oldPKeyId).append("' LIMIT 1;");
-                                resultTablesData.add(copyDataSql.toString());
+                                if(needTab.getType()==2 && needTab.getTableType()==6){
+                                    continue;
+                                }else{
+                                    resultTablesData.add(copyDataSql.toString());
+                                }
                             }
                         }
                     }
@@ -2852,7 +2864,11 @@ private void addCopyNodesAndTabsBuildData(List<WbsTreeContract> addNodeList, Lis
                         String testColVal = reviseCols(eMap, colVal, oldPKeyId, tableName);
                         /*StaticLog.info("KT3356:" + testColVal);*/
                         copyDataSql.append(delSql).append("insert into ").append(tableName).append("  (").append(col).append(") select ").append(testColVal).append(" from ").append(tableName).append(" where p_key_id='").append(oldPKeyId).append("' LIMIT 1;");
-                        resultTablesData.add(copyDataSql.toString());
+                        if(needTab.getType()==2 && needTab.getTableType()==6){
+                            continue;
+                        }else{
+                            resultTablesData.add(copyDataSql.toString());
+                        }
                     }
                 }
             }
@@ -2998,7 +3014,11 @@ private void addCopyNodesAndTabsBuildData(List<WbsTreeContract> addNodeList, Lis
                                     String testColVal = reviseCols(eMap, colVal, oldPKeyId, tableName);
                                     StaticLog.info("KT3356:" + testColVal);
                                     copyDataSql.append(delSql).append("insert into ").append(tableName).append("  (").append(col).append(") select ").append(testColVal).append(" from ").append(tableName).append(" where p_key_id='").append(oldPKeyId).append("' LIMIT 1;");
-                                    resultTablesData.add(copyDataSql.toString());
+                                    if(needTab.getType()==2 && needTab.getTableType()==6){
+                                        continue;
+                                    }else{
+                                        resultTablesData.add(copyDataSql.toString());
+                                    }
                                 }
                             }
                         }
@@ -3529,7 +3549,10 @@ public R removeContractTreeNodeJudge(@RequestParam String ids) {
 
             JSONObject json = new JSONObject();
             json.put("operationObjIds", idArray);
-            String positionStr = position.substring(1);
+            String positionStr="";
+            if(position.length()>1){
+                positionStr=position.substring(1);
+            }
             json.put("operationObjName", positionStr);
             json.put("projectId", projectId);
             json.put("contractId", contractId);

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

@@ -350,7 +350,7 @@ public class NeiYeController {
                    vo1.setUnitName(unitName);
                    vo1.setUnitCount(1);
                }else {
-                   return R.data(300,null,"该节点暂未设置单元工程名称");
+                   return R.fail("该节点暂未设置单元工程名称");
                }
                //查询合格,优良,优良率
                 //查出当前节点下的单元工程施工质量验收评定表 后面需要改一下pid
@@ -462,7 +462,7 @@ public class NeiYeController {
                 }
             }
         }
-        return R.data(300,null,"未查询到数据");
+        return R.fail("未查询到数据");
     }
 
     @SneakyThrows

+ 56 - 52
blade-service/blade-business/src/main/java/org/springblade/business/mapper/ArchiveFileMapper.xml

@@ -74,6 +74,9 @@
         select count(u.id) from u_archive_file u
         <if test="vo.nodeIds != null and vo.nodeIds != ''">
             left join m_archive_tree_contract t on t.id = u.node_id
+            <if test="vo.extType != null">
+                LEFT JOIN m_archive_tree_contract m ON m.id = u.node_ext_id
+            </if>
         </if>
         where u.is_deleted = 0
         <if test="vo.isApprovalValue != null and vo.isApprovalValue != ''">
@@ -107,37 +110,36 @@
         <if test="vo.rectification == null and vo.archiveId == null">
             and (u.is_auto_file is null or u.is_auto_file != 1)
         </if>
-<!--        <choose>-->
-<!--            <when test="vo.isArchive != null and vo.isArchive != ''">-->
-<!--                and u.is_auto_file = #{vo.isArchive}-->
-<!--            </when>-->
-<!--            <when test="vo.archiveId != null and vo.archiveId != ''">-->
-<!--                and 1=1-->
-<!--            </when>-->
-<!--            <otherwise>-->
-<!--                and (u.is_auto_file is null or u.is_auto_file != 1)-->
-<!--            </otherwise>-->
-<!--        </choose>-->
+        <!--        <choose>-->
+        <!--            <when test="vo.isArchive != null and vo.isArchive != ''">-->
+        <!--                and u.is_auto_file = #{vo.isArchive}-->
+        <!--            </when>-->
+        <!--            <when test="vo.archiveId != null and vo.archiveId != ''">-->
+        <!--                and 1=1-->
+        <!--            </when>-->
+        <!--            <otherwise>-->
+        <!--                and (u.is_auto_file is null or u.is_auto_file != 1)-->
+        <!--            </otherwise>-->
+        <!--        </choose>-->
         <if test="vo.nodeIds != null and vo.nodeIds != ''">
-            and
             <choose>
-                <!-- 当存在扩展类型时,同时查 node_id 和 node_ext_id -->
                 <when test="vo.extType != null">
-                    (u.node_id in
-                    <foreach collection="vo.nodeIdArray" item="nodeId" open="(" separator="," close=")">
-                        #{nodeId}
-                    </foreach>
-                    OR u.node_ext_id in
-                    <foreach collection="vo.nodeIdArray" item="nodeId" open="(" separator="," close=")">
-                        #{nodeId}
-                    </foreach>)
+                    and (find_in_set( #{vo.nodeIds}, t.ancestors ) or t.id = #{vo.nodeIds} or find_in_set( #{vo.nodeIds}, m.ancestors ) or m.id = #{vo.nodeIds})
                 </when>
-                <!-- 默认只查 node_id -->
                 <otherwise>
-                    u.node_id in
-                    <foreach collection="vo.nodeIdArray" item="nodeId" open="(" separator="," close=")">
-                        #{nodeId}
-                    </foreach>
+                    and (find_in_set( #{vo.nodeIds}, t.ancestors ) or t.id = #{vo.nodeIds})
+                </otherwise>
+            </choose>
+        </if>
+        <if test="vo.authCode !=null and vo.authCode !=''">
+            <choose>
+                <when test="vo.extType != null">
+                    AND (t.tree_code = #{vo.authCode} or t.tree_code = #{vo.contractId} or t.parent_id = 0
+                        or m.tree_code = #{vo.authCode} or m.tree_code = #{vo.contractId} or m.parent_id = 0
+                    )
+                </when>
+                <otherwise>
+                    AND (t.tree_code = #{vo.authCode} or t.tree_code = #{vo.contractId} or t.parent_id = 0)
                 </otherwise>
             </choose>
         </if>
@@ -157,6 +159,9 @@
         select u.* from u_archive_file u
         <if test="vo.nodeIds != null and vo.nodeIds != ''">
             left join m_archive_tree_contract t on t.id = u.node_id
+            <if test="vo.extType != null">
+                LEFT JOIN m_archive_tree_contract m ON m.id = u.node_ext_id
+            </if>
         </if>
         where u.is_deleted = 0
         <if test="vo.isApprovalValue != null and vo.isApprovalValue != ''">
@@ -190,37 +195,36 @@
         <if test="vo.rectification == null and vo.archiveId == null">
             and (u.is_auto_file is null or u.is_auto_file != 1)
         </if>
-<!--        <choose>-->
-<!--            <when test="vo.isArchive != null and vo.isArchive != ''">-->
-<!--                and u.is_auto_file = #{vo.isArchive}-->
-<!--            </when>-->
-<!--            <when test="vo.archiveId != null and vo.archiveId != ''">-->
-<!--                and 1=1-->
-<!--            </when>-->
-<!--            <otherwise>-->
-<!--                and (u.is_auto_file is null or u.is_auto_file != 1)-->
-<!--            </otherwise>-->
-<!--        </choose>-->
+        <!--        <choose>-->
+        <!--            <when test="vo.isArchive != null and vo.isArchive != ''">-->
+        <!--                and u.is_auto_file = #{vo.isArchive}-->
+        <!--            </when>-->
+        <!--            <when test="vo.archiveId != null and vo.archiveId != ''">-->
+        <!--                and 1=1-->
+        <!--            </when>-->
+        <!--            <otherwise>-->
+        <!--                and (u.is_auto_file is null or u.is_auto_file != 1)-->
+        <!--            </otherwise>-->
+        <!--        </choose>-->
         <if test="vo.nodeIds != null and vo.nodeIds != ''">
-            and
             <choose>
-                <!-- 当存在扩展类型时,同时查 node_id 和 node_ext_id -->
                 <when test="vo.extType != null">
-                    (u.node_id in
-                    <foreach collection="vo.nodeIdArray" item="nodeId" open="(" separator="," close=")">
-                        #{nodeId}
-                    </foreach>
-                    OR u.node_ext_id in
-                    <foreach collection="vo.nodeIdArray" item="nodeId" open="(" separator="," close=")">
-                        #{nodeId}
-                    </foreach>)
+                    and (find_in_set( #{vo.nodeIds}, t.ancestors ) or t.id = #{vo.nodeIds} or find_in_set( #{vo.nodeIds}, m.ancestors ) or m.id = #{vo.nodeIds})
+                </when>
+                <otherwise>
+                    and (find_in_set( #{vo.nodeIds}, t.ancestors ) or t.id = #{vo.nodeIds})
+                </otherwise>
+            </choose>
+        </if>
+        <if test="vo.authCode !=null and vo.authCode !=''">
+            <choose>
+                <when test="vo.extType != null">
+                    AND (t.tree_code = #{vo.authCode} or t.tree_code = #{vo.contractId} or t.parent_id = 0
+                    or m.tree_code = #{vo.authCode} or m.tree_code = #{vo.contractId} or m.parent_id = 0
+                    )
                 </when>
-                <!-- 默认只查 node_id -->
                 <otherwise>
-                    u.node_id in
-                    <foreach collection="vo.nodeIdArray" item="nodeId" open="(" separator="," close=")">
-                        #{nodeId}
-                    </foreach>
+                    AND (t.tree_code = #{vo.authCode} or t.tree_code = #{vo.contractId} or t.parent_id = 0)
                 </otherwise>
             </choose>
         </if>

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

@@ -42,8 +42,7 @@ public class ArchiveFileServiceImpl extends BaseServiceImpl<ArchiveFileMapper, A
     private final IDictBizClient dictBizClient;
     private final NewIOSSClient iossClient;
 
-    @Resource(name = "singleExecutor")
-    private ExecutorService executorService;
+    private final ExecutorService executorService;
 
     private final ArchiveInspectionInfoClient archiveInspectionInfoClient;
     private final JdbcTemplate jdbcTemplate;

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

@@ -387,7 +387,11 @@ public class InformationQueryServiceImpl extends BaseServiceImpl<InformationQuer
         } else {
             //首先根据wbsId获取合同段ID和项目ID
             WbsTreeContract contractTree = this.wbsTreeContractClient.getContractWbsTreeByPrimaryKeyId(Long.parseLong(primaryKeyId));
-            int type = (contractTree.getIsExpernode() == null || contractTree.getIsExpernode() <= 0) ? 1 : 2;
+           // int type = (contractTree.getIsExpernode() == null || contractTree.getIsExpernode() <= 0) ? 1 : 2;
+            int type = contractTree.getWbsType(); // 1质检,2试验
+            if(type>=3 || type<=0){
+                type = 1;
+            }
             if (DistributedRedisLock.acquire("saveOrUpdateInformationQueryData:" + primaryKeyId + ":" + contractTree.getContractId() + ":" + classify + ":" + type,5)) {
                 try {
                     //判断当前填报节点下是否已经存在相应数据

+ 7 - 2
blade-service/blade-e-visa/src/main/java/org/springblade/evisa/EVisaApplication.java

@@ -4,6 +4,10 @@ import org.springblade.common.constant.EVisaConstant;
 import org.springblade.core.cloud.feign.EnableBladeFeign;
 import org.springblade.core.launch.BladeApplication;
 import org.springframework.cloud.client.SpringCloudApplication;
+import org.springframework.context.ConfigurableApplicationContext;
+
+import java.util.Arrays;
+import java.util.concurrent.ThreadPoolExecutor;
 
 /**
  * 电签服务启动类
@@ -13,8 +17,9 @@ import org.springframework.cloud.client.SpringCloudApplication;
 public class EVisaApplication {
 
     public static void main(String[] args) {
-
-        BladeApplication.run(EVisaConstant.APPLICATION_WEATHER_NAME, EVisaApplication.class, args);
+        ConfigurableApplicationContext ctx = BladeApplication.run(EVisaConstant.APPLICATION_WEATHER_NAME, EVisaApplication.class, args);
+        System.out.println("ThreadPoolExecutor beans: " +
+                Arrays.toString(ctx.getBeanNamesForType(ThreadPoolExecutor.class)));
     }
 
 }

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

@@ -0,0 +1,433 @@
+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.apache.pdfbox.rendering.PDFRenderer;
+import org.jsoup.Jsoup;
+import org.jsoup.nodes.Document;
+import org.jsoup.nodes.Element;
+import org.jsoup.select.Elements;
+import org.springblade.common.utils.CommonUtil;
+import org.springblade.common.utils.SnowFlakeUtil;
+import org.springblade.core.oss.model.BladeFile;
+import org.springblade.core.tool.utils.Func;
+import org.springblade.core.tool.utils.IoUtil;
+import org.springblade.evisa.utils.FileUtils;
+import org.springblade.evisa.vo.ArchivesSplitInfoVO;
+import org.springblade.evisa.vo.TaskArchiveSplitVO;
+import org.springblade.resource.feign.NewIOSSClient;
+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 javax.imageio.ImageIO;
+import java.awt.image.BufferedImage;
+import java.io.*;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.ThreadPoolExecutor;
+import java.util.concurrent.TimeUnit;
+
+
+/**
+ * 清表基础数据表 控制器
+ *
+ * @author BladeX
+ * @since 2022-05-18
+ */
+@RestController
+@AllArgsConstructor
+@Api(value = "电签类", tags = "电签类接口")
+@Slf4j
+public class Archive2Controller {
+
+    private final StringRedisTemplate RedisTemplate;
+
+    private final JdbcTemplate jdbcTemplate;
+
+    private final NewIOSSClient newIOSSClient;
+
+    // 线程池
+    @Resource(name = "archivePoolExecutor")
+    private ThreadPoolExecutor archExecutor;
+
+    @Scheduled(cron = "0/30 * * * * ?")
+    public void SignTaskBatchPng() {
+        //执行代码
+        log.info("分解pdf专图片");
+       // String sql = "SELECT distinct b.id,b.archive_id as archiveId ,REPLACE(b.file_url,'https://xinan1.zos.ctyun.cn','http://100.86.2.1:80') as fileUrl from u_archives_auto a ,u_archive_file b  where a.id=b.archive_id  and a.is_deleted=0 and b.is_deleted=0 and a.split_status=10 LIMIT 20";
+        String sql = "SELECT distinct b.id,b.archive_id as archiveId ,b.file_url as fileUrl from u_archives_auto a ,u_archive_file b  where a.id=b.archive_id  and a.is_deleted=0 and b.is_deleted=0 and a.split_status=10 and a.id=1945020959844990977 LIMIT 20";
+        List<TaskArchiveSplitVO> query = jdbcTemplate.query(sql, new BeanPropertyRowMapper<>(TaskArchiveSplitVO.class));
+
+        if (query != null && query.size() >= 1) {
+            for (TaskArchiveSplitVO dataInfo : query) {
+                if (archExecutor.getQueue().size() <= 20) {
+                    Boolean aBoolean = RedisTemplate.hasKey("splitpng-" + dataInfo.getArchiveId());
+                    if (!aBoolean) {
+                        RedisTemplate.opsForValue().setIfAbsent("splitpng-" + dataInfo.getArchiveId(), "1", 600, TimeUnit.SECONDS);
+                        CompletableFuture<Void> runAsync = CompletableFuture.runAsync(() -> {
+                            try {
+                                signTaskBatchpngToHtml(dataInfo);
+                            } catch (Exception e) {
+                                e.printStackTrace();
+                            }
+                        }, archExecutor);
+                    }
+                }
+            }
+        }
+        System.out.println("队列数量_img" + archExecutor.getQueue().size());
+        System.out.println("活跃数量_img" + archExecutor.getActiveCount());
+        System.out.println("总共数量_img" + archExecutor.getTaskCount());
+        System.out.println("完成数量_img" + archExecutor.getCompletedTaskCount());
+    }
+
+    // 分解第一页的任务
+
+    public void signTaskBatchpngToHtml(TaskArchiveSplitVO taskSign) {
+        try {
+
+            String archiveId = taskSign.getArchiveId();
+            String fileUrl = taskSign.getFileUrl();
+            List<String> listPdf = new ArrayList<>();
+            int startPage = 0;
+            for (int i = 2; i <= 10; i++) {
+
+                // 获取pdf第二页的数据
+                String firstUrl = FileUtils.getSysLocalFileUrl() + "archiveSplit/" + archiveId + "first__" + i + "__.pdf";
+                int pdfByPage = getPdfByPage(i, i, fileUrl, firstUrl);
+                File file = new File(firstUrl);
+
+                // 保存第一页为300DPI图片
+                String imagePath = FileUtils.getSysLocalFileUrl() + "archiveSplit/" + archiveId + "first__" + i + "__.png";
+                File imgfile = new File(imagePath);
+                int dataNum = savePdfAsImage(1, firstUrl, imagePath);
+
+                // 删除pdf
+                file.delete();
+                String state = OcrTitle(imagePath, "1");
+                if (state.equals("1")) {
+                    if (startPage < 2) {
+                        startPage = i;
+                    }
+                    listPdf.add(imagePath);
+                } else {
+                    imgfile.delete();
+                    break;
+                }
+            }
+
+            String filePath = startPage + "--" + (listPdf.size() + 1);
+            //
+            ArchivesSplitInfoVO data =new ArchivesSplitInfoVO();
+            data.setId(taskSign.getId());
+            data.setArchiveId(taskSign.getArchiveId());
+            data.setFileUrl(taskSign.getFileUrl());
+            data.setFirstFileUrl(filePath);
+            signTaskBatchpng(data);
+
+        } catch (Exception e) {
+            System.out.println("12321312");
+            e.printStackTrace();
+        }
+    }
+
+    public void signTaskBatchpng(ArchivesSplitInfoVO taskSign) {
+        try {
+            System.out.println("分解001");
+            String archiveId = taskSign.getArchiveId();
+            String fileUlr = taskSign.getFileUrl();
+            String firstPage = FileUtils.getSysLocalFileUrl() + "archiveSplit/";
+            String firstFileUrl = taskSign.getFirstFileUrl();
+            String firstUrl[] = firstFileUrl.split("--");
+            int basePage = Integer.parseInt(firstUrl[1]);
+            int baseStart = Integer.parseInt(firstUrl[0]);
+            String dutyUser = "";
+            int bkb = 0;
+            //将imagePath 的数据转成一个可解析的html
+            String htmlUrl = pngToHtml(firstPage, archiveId, taskSign.getFirstFileUrl());
+            System.out.println("分解002=" + htmlUrl);
+
+            if (htmlUrl.indexOf("_001.html") >= 0 && htmlUrl.indexOf("archiveSplit") >= 0) {
+                String htmlString = IoUtil.readToString(new FileInputStream(htmlUrl));
+                Document doc = Jsoup.parse(htmlString);
+                Element table = doc.select("table").first();
+                Elements trs = table.select("tr");
+                //由于解析已经成功,可能数据已经分解过,需要删除
+                if (trs != null && trs.size() >= 1) {
+                    String sql = "delete from u_archive_file where id<>'" + taskSign.getId() + "' and archive_id='" + archiveId + "'";
+                    jdbcTemplate.execute(sql);
+                }
+
+                for (int i = 0; i <= trs.size() - 1; i++) {
+                    Element tr = trs.get(i);
+                    String zrz = tr.select("td").get(0).text();
+                    String wjtm = tr.select("td").get(1).text();
+                    String rq = tr.select("td").get(2).text();
+                    String ym = tr.select("td").get(3).text();
+                    if (zrz.equals("责任者") && wjtm.equals("文件题名") && rq.equals("日期")) {
+                        continue;
+                    }
+                    int startYm = 0;
+                    int endYm = 0;
+                    if (i < trs.size() - 1) {
+                        startYm = Func.toInt(ym);
+                        String enData = trs.get(i + 1).select("td").get(3).text();
+                        if (enData.indexOf("页") >= 0) {
+                            enData = trs.get(i + 2).select("td").get(3).text();
+                        }
+
+                        String[] parts = enData.split("(?<=\\D)(?=\\d)|(?<=\\d)(?=\\D)");
+                        if (parts != null && parts.length >= 1) {
+                            endYm = Func.toInt(parts[0]);
+                        }
+                    } else {
+                        String[] split = ym.split("(?<=\\D)(?=\\d)|(?<=\\d)(?=\\D)");
+                        if (split != null && split.length >= 3) {
+                            startYm = Func.toInt(split[0]);
+                            endYm = Func.toInt(split[2]);
+                        } else {
+                            startYm = Func.toInt(split[0]);
+                            endYm = Func.toInt(split[0]);
+                        }
+                    }
+                    startYm = basePage + startYm;
+                    endYm = basePage + endYm;
+                    dutyUser = zrz;
+                    System.out.println("序号=" + i + "--文件提名:" + wjtm + "--开始(" + startYm + "-" + endYm + ")---页数" + (endYm - startYm + 1));
+                    // 分解文件
+                    String fmlUrl = FileUtils.getSysLocalFileUrl() + "archiveSplit/" + archiveId + "_cf_00" + i + ".pdf";
+                    getPdfByPage(startYm, endYm, fileUlr, fmlUrl);
+                    saveDataToMysql(fmlUrl, wjtm, taskSign.getId(), endYm - startYm + 1, i, zrz, rq);
+                    bkb = endYm;
+                }
+            } else {
+                return;
+            }
+
+            // 添加封面信息
+            String fmlUrl = FileUtils.getSysLocalFileUrl() + "archiveSplit/" + archiveId + "_fm_001.pdf";
+            getPdfByPage(1, 1, fileUlr, fmlUrl);
+            saveDataToMysql(fmlUrl, "封面", taskSign.getId(), 1, -4, dutyUser, "");
+
+            // 卷内目录
+            String jnmuUrl = FileUtils.getSysLocalFileUrl() + "archiveSplit/" + archiveId + "_jnml_001.pdf";
+            getPdfByPage(baseStart, basePage, fileUlr, jnmuUrl);
+            saveDataToMysql(jnmuUrl, "卷内目录", taskSign.getId(), 1, -3, dutyUser, "");
+
+            // 卷内备考表
+            String jnbkbUrl = FileUtils.getSysLocalFileUrl() + "archiveSplit/" + archiveId + "_jnbkb_001.pdf";
+            getPdfByPage(bkb + 1, bkb + 1, fileUlr, jnbkbUrl);
+
+            File jlPdfFile = new File(jnbkbUrl);
+            if (jlPdfFile.exists()) {
+                saveDataToMysql(jnbkbUrl, "卷内备考表", taskSign.getId(), 1, 100, dutyUser, "");
+            }
+
+            // 背脊表
+            String bjbUrl = FileUtils.getSysLocalFileUrl() + "archiveSplit/" + archiveId + "_beiji_001.pdf";
+            String bjbUrlPng = FileUtils.getSysLocalFileUrl() + "archiveSplit/" + archiveId + "_beiji_001.png";
+
+            int pdfByPage = getPdfByPage(bkb + 2, bkb + 2, fileUlr, bjbUrl);
+            if(pdfByPage==0){
+                File bgImgFile = new File(bjbUrlPng);
+                if (!bgImgFile.exists()) {
+                    int dataNum = savePdfAsImage(1, bjbUrl, bjbUrlPng);
+                }
+                String state = OcrTitle(bjbUrlPng, "3");
+                if (state.equals("1")) {
+                    saveDataToMysql(bjbUrl, "背脊表", taskSign.getId(), 1, 101, dutyUser, "");
+                }
+                bgImgFile.delete();
+            }
+            // 修改任务状态
+            String updateSql = "update u_archives_split_info set status=3 where id=" + taskSign.getId();
+            jdbcTemplate.execute(updateSql);
+            // 修改 u_archives_auto 为 已经分解
+            String updateSqlAuto = "update u_archives_auto set split_status=1 where id=" + taskSign.getArchiveId();
+            jdbcTemplate.execute(updateSqlAuto);
+
+            // 统计各个任务的结果
+            String taxkSql = "UPDATE u_task_split a set finished = (SELECT count(1) from u_archives_auto b where FIND_IN_SET(b.id,a.ids) and b.split_status=1) where FIND_IN_SET(" + taskSign.getArchiveId() + ",a.ids)  and a.type=3";
+            String taxkSql2 = "UPDATE u_task_split a set finished = (SELECT count(1) from u_archives_auto b where a.contract_id=b.contract_id) where a.id=" + taskSign.getTaskId() + " and a.type=2";
+            jdbcTemplate.execute(taxkSql);
+            jdbcTemplate.execute(taxkSql2);
+
+            // 删除html
+            File fileHtml = new File(fmlUrl);
+            fileHtml.delete();
+
+            // 修改完成情况
+            RedisTemplate.delete("splithtml-" + archiveId);
+        } catch (Exception e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    public static String pngToHtml(String fileUrl, String pKeyId, String pageNum) {
+        String lasHhtmlUrl = "";
+        try {
+            // 定义Python解释器路径和脚本路径
+            String pythonScript = "/Users/hongchuangyanfa/Desktop/PycharmProjects/splitPngToHtml.py";
+            // 构建命令
+            ProcessBuilder pb = new ProcessBuilder("python3", pythonScript, fileUrl, pKeyId, pageNum);
+            Process process = pb.start();
+
+            // 读取Python脚本输出
+            BufferedReader reader = new BufferedReader(
+                    new InputStreamReader(process.getInputStream()));
+            String htmlUrl;
+            while ((htmlUrl = reader.readLine()) != null) {
+                System.out.println(htmlUrl);
+                if (htmlUrl.indexOf("html文件路径") >= 0 && htmlUrl.indexOf("_001.html") >= 0 && htmlUrl.indexOf("archiveSplit") >= 0) {
+                    lasHhtmlUrl = htmlUrl.replace("html文件路径", "");
+                }
+            }
+            // 等待进程结束
+            int exitCode = process.waitFor();
+            if (exitCode == 0) {
+                return lasHhtmlUrl;
+            } else {
+                return "1";
+            }
+        } catch (Exception e) {
+            e.printStackTrace();
+            return "1";
+        }
+    }
+
+    public static String OcrTitle(String fileUrl, String type) {
+        String lasHhtmlUrl = "";
+        try {
+            // 定义Python解释器路径和脚本路径
+            String pythonScript = "/Users/hongchuangyanfa/Desktop/PycharmProjects/splitPngByTitle.py";
+            // 构建命令
+            ProcessBuilder pb = new ProcessBuilder("python3", pythonScript, fileUrl, type);
+            Process process = pb.start();
+
+            // 读取Python脚本输出
+            BufferedReader reader = new BufferedReader(
+                    new InputStreamReader(process.getInputStream()));
+            String htmlUrl;
+            while ((htmlUrl = reader.readLine()) != null) {
+                System.out.println("222" + htmlUrl);
+                if (htmlUrl.indexOf("图片中是否有卷内目录") >= 0 && htmlUrl.indexOf("True") >= 0) {
+                    return "1";
+                }
+            }
+            // 等待进程结束
+            int exitCode = process.waitFor();
+            if (exitCode == 0) {
+                return lasHhtmlUrl;
+            } else {
+                return "1";
+            }
+        } catch (Exception e) {
+            e.printStackTrace();
+            return "1";
+        }
+    }
+
+
+    public static int getPdfByPage(int startPage, int endPage, String filePath, String savePath) {
+        try {
+            InputStream inputStreamByUrl = CommonUtil.getOSSInputStream3(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();
+            return 0;
+        } catch (Exception e) {
+            return 1;
+        }
+    }
+
+    public static int savePdfAsImage(int pageNum, String filePath, String outputPath) {
+        try (InputStream inputStream = FileUtils.getInputStreamByUrl(filePath);
+             PDDocument document = PDDocument.load(inputStream)) {
+
+            // 验证页码范围
+            if (pageNum < 1 || pageNum > document.getNumberOfPages()) {
+                return 1;
+            }
+
+            PDFRenderer renderer = new PDFRenderer(document);
+
+            // 设置DPI为300
+            final int DPI = 300;
+
+            // 渲染指定页面(注意PDFBox使用0-based索引)
+            //BufferedImage image = renderer.renderImage(pageNum - 1, DPI / 72f);
+            BufferedImage image = renderer.renderImageWithDPI(0, DPI); // 0 表示第一页
+            // 确保输出目录存在
+            File outputFile = new File(outputPath);
+            outputFile.getParentFile().mkdirs();
+
+            // 保存为PNG格式(可改为JPG等)
+            ImageIO.write(image, "PNG", outputFile);
+
+            log.info("PDF页面已成功保存为图片: {}", outputPath);
+            inputStream.close();
+            document.close();
+            return 0;
+        } catch (Exception e) {
+            log.error("PDF转图片失败", e);
+            return 1;
+        }
+    }
+
+    public int saveDataToMysql(String upFileUrl, String fileName, String fileId, int filePage, int sort, String dutyUser, String fileTime) {
+        // 获取封面信息
+        long newPkId = SnowFlakeUtil.getId(); //主键Id
+        File fmfile = new File(upFileUrl);
+        if (fmfile.exists()) {
+            BladeFile bladeFile = this.newIOSSClient.uploadFile(fileName + ".pdf", upFileUrl);
+            if (bladeFile != null && Func.isNotEmpty(bladeFile.getLink())) {
+                String FmPdfUrl = bladeFile.getLink();
+                String sql = " insert into u_archive_file( " +
+                        " id,project_id,contract_id,node_id,file_number,file_name,file_time,file_url,pdf_file_url,file_page,is_approval,is_certification,is_need_certification,duty_user,create_user,create_dept,create_time,update_user,update_time,status,is_deleted,sheet_type,sheet_source, " +
+                        " drawing_no,cite_change_number,certification_time,e_visa_file,node_ext_id,file_type,archive_id,origin_id,filming_time,filmingor_time,tag_id,pic_code,refer_code,film_code,width,height,ftime,utime,del_time,sort,box_name,box_number,is_auto_file,is_archive,page_num, " +
+                        " file_size,source_type,is_element,pdf_page_url,fid,rectification,classify,m_wbs_tree_contract_p_key_id,u_image_classification_file_id,archive_file_storage_type,node_tree_structure,date_name,archive_file_stroage_type,out_id,sort_num " +
+                        "   ) " +
+                        " SELECT " + newPkId + ",project_id,contract_id,node_id,file_number,'" + fileName + "','" + fileTime + "','" + FmPdfUrl + "','" + FmPdfUrl + "'," + filePage + ",is_approval,is_certification,is_need_certification,'" + dutyUser + "',create_user,create_dept,create_time,update_user,update_time,status,is_deleted,sheet_type,sheet_source, " +
+                        "        drawing_no,cite_change_number,certification_time,e_visa_file,node_ext_id,file_type,archive_id,origin_id,filming_time,filmingor_time,tag_id,pic_code,refer_code,film_code,width,height,ftime,utime,del_time," + sort + ",box_name,box_number,is_auto_file,is_archive,page_num, " +
+                        "        file_size,source_type,is_element,pdf_page_url,fid,rectification,classify,m_wbs_tree_contract_p_key_id,u_image_classification_file_id,archive_file_storage_type,node_tree_structure,date_name,archive_file_stroage_type,out_id,sort_num " +
+                        " from u_archive_file where id=" + fileId;
+                System.out.println(fileName + "----" + sql);
+                jdbcTemplate.execute(sql);
+
+            } else {
+                // 检查一下oss是否启动
+                System.out.println("oss服务未启动,无法上传文件到oss");
+                return 500;
+            }
+        } else {
+            return 404;
+        }
+        fmfile.delete();
+        return 200;
+    }
+}

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

@@ -2,6 +2,7 @@ package org.springblade.evisa.controller;
 
 import io.swagger.annotations.Api;
 import lombok.AllArgsConstructor;
+import lombok.Synchronized;
 import lombok.extern.slf4j.Slf4j;
 import org.apache.pdfbox.pdmodel.PDDocument;
 import org.apache.pdfbox.pdmodel.PDPage;
@@ -9,6 +10,8 @@ import org.jsoup.Jsoup;
 import org.jsoup.nodes.Document;
 import org.jsoup.nodes.Element;
 import org.jsoup.select.Elements;
+import org.springblade.common.utils.CommonUtil;
+import org.springblade.common.utils.SafeURLEncoder;
 import org.springblade.common.utils.SnowFlakeUtil;
 import org.springblade.core.oss.model.BladeFile;
 import org.springblade.core.tool.utils.Func;
@@ -52,53 +55,49 @@ import javax.imageio.ImageIO;
 @Slf4j
 public class ArchiveController {
 
-    @Autowired
-    StringRedisTemplate RedisTemplate;
-    // jdbc
+    private final StringRedisTemplate RedisTemplate;
+
     private final JdbcTemplate jdbcTemplate;
 
     private final NewIOSSClient newIOSSClient;
 
     // 线程池
-    @Resource(name = "taskExecutor1")
-    private ThreadPoolExecutor executor;
+    @Resource(name = "archivePoolExecutor")
+    private ThreadPoolExecutor archExecutor;
 
-   @Scheduled(cron = "0 0/1 * * * ?")
-    public void SignInfo() {
+   // @Scheduled(cron = "0/30 * * * * ?")
+    public void SignTaskBatchPng() {
         //执行代码
-
         log.info("分解pdf专图片");
-        String sql = "SELECT distinct b.id,b.archive_id as archiveId ,b.file_url as fileUrl,c.id as taskId from u_archives_auto a , u_archive_file b ,u_task_split c  where a.id=b.archive_id and ((FIND_IN_SET(a.id,c.ids) and c.type=3) or (a.contract_id=c.contract_id and c.type=2)) and a.is_deleted=0 and b.is_deleted=0 and a.split_status not in(1,2) ";
+        String sql = "SELECT distinct b.id,b.archive_id as archiveId ,REPLACE(b.file_url,'https://xinan1.zos.ctyun.cn','http://100.86.2.1:80') as fileUrl,c.id as taskId from u_archives_auto a , u_archive_file b ,u_task_split c  where a.id=b.archive_id and ((FIND_IN_SET(a.id,c.ids) and c.type=3) or (a.contract_id=c.contract_id and c.type=2)) and a.is_deleted=0 and b.is_deleted=0 and a.split_status not in(1,2) LIMIT 20";
+      //  String sql = "SELECT distinct b.id,b.archive_id as archiveId ,b.file_url as fileUrl,c.id as taskId from u_archives_auto a , u_archive_file b ,u_task_split c  where a.id=b.archive_id and ((FIND_IN_SET(a.id,c.ids) and c.type=3) or (a.contract_id=c.contract_id and c.type=2)) and a.is_deleted=0 and b.is_deleted=0 and a.split_status not in(1,2) and a.id=1947207326716919808 LIMIT 20";
         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) {
+                if (archExecutor.getQueue().size() <= 20) {
                     Boolean aBoolean = RedisTemplate.hasKey("splitpng-" + dataInfo.getArchiveId());
                     if (!aBoolean) {
-
-                        if (!aBoolean) {
-                            RedisTemplate.opsForValue().set("splitpng-" + dataInfo.getArchiveId(), "1", 600, TimeUnit.SECONDS);
-                            CompletableFuture<Void> runAsync = CompletableFuture.runAsync(() -> {
-                                try {
-                                    /*===============执行批量任务===============*/
-                                    signTaskBatchpngToHtml(dataInfo);
-                                } catch (Exception e) {
-                                    e.printStackTrace();
-                                }
-                            }, executor);
-                        }
+                        RedisTemplate.opsForValue().setIfAbsent("splitpng-" + dataInfo.getArchiveId(), "1", 600, TimeUnit.SECONDS);
+                        CompletableFuture<Void> runAsync = CompletableFuture.runAsync(() -> {
+                            try {
+                                signTaskBatchpngToHtml(dataInfo);
+                            } catch (Exception e) {
+                                e.printStackTrace();
+                            }
+                        }, archExecutor);
                     }
                 }
             }
         }
-        System.out.println("队列数量_img2" + executor.getQueue().size());
-        System.out.println("活跃数量_img2" + executor.getActiveCount());
-        System.out.println("总共数量_img2" + executor.getTaskCount());
-        System.out.println("完成数量_img2" + executor.getCompletedTaskCount());
+        System.out.println("队列数量_img" + archExecutor.getQueue().size());
+        System.out.println("活跃数量_img" + archExecutor.getActiveCount());
+        System.out.println("总共数量_img" + archExecutor.getTaskCount());
+        System.out.println("完成数量_img" + archExecutor.getCompletedTaskCount());
     }
 
     // 分解第一页的任务
+
     public void signTaskBatchpngToHtml(TaskArchiveSplitVO taskSign) {
         try {
             String fileUrl = taskSign.getFileUrl();
@@ -109,90 +108,100 @@ public class ArchiveController {
             int startPage = 0;
             for (int i = 2; i <= 10; i++) {
                 // 获取pdf第二页的数据
-                String firstUrl = FileUtils.getSysLocalFileUrl() + "archiveSplit/" + archiveId + "first__"+i+"__.pdf";
+                String firstUrl = FileUtils.getSysLocalFileUrl() + "archiveSplit/" + archiveId + "first__" + i + "__.pdf";
                 File file = new File(firstUrl);
                 if (!file.exists()) {
-                    getPdfByPage(i, i, fileUrl, firstUrl);
+                    int pdfByPage = getPdfByPage(i, i, fileUrl, firstUrl);
+                    if(pdfByPage==1){
+                        String sql22 = "INSERT INTO u_archives_split_info(id,status,file_url,first_file_url,task_id,archive_id,create_time) VALUES(?,?,?,?,?,?,SYSDATE())";
+                        int addCount = jdbcTemplate.update(sql22, id, 4, fileUrl, "获取数据源失败", taskId, archiveId);
+                        String updateSql = "UPDATE u_archives_auto SET split_status=? WHERE id=?";
+                        int delCount = jdbcTemplate.update(updateSql, 1, archiveId);
+                        return;
+                    }
                 }
 
                 // 保存第一页为300DPI图片
-                String imagePath = FileUtils.getSysLocalFileUrl() + "archiveSplit/" + archiveId + "first__"+i+"__.png";
+                String imagePath = FileUtils.getSysLocalFileUrl() + "archiveSplit/" + archiveId + "first__" + i + "__.png";
                 File imgfile = new File(imagePath);
                 if (!imgfile.exists()) {
-                    savePdfAsImage(1, firstUrl, imagePath);
+                    int dataNum = savePdfAsImage(1, firstUrl, imagePath);
                 }
                 // 删除pdf
                 file.delete();
-                String state = OcrTitle(imagePath,"1");
-                if(state.equals("1")){
-                    if(startPage<2){
-                        startPage = i ;
+                String state = OcrTitle(imagePath, "1");
+                if (state.equals("1")) {
+                    if (startPage < 2) {
+                        startPage = i;
                     }
                     listPdf.add(imagePath);
-                }else{
+                } else {
                     imgfile.delete();
                     break;
                 }
             }
             System.out.println(listPdf.size());
-            String filePath = startPage+"--"+(listPdf.size()+1);
+            String filePath = startPage + "--" + (listPdf.size() + 1);
             //判断
             List<Map<String, Object>> mapList = jdbcTemplate.queryForList("select * from u_archives_split_info where id=" + id + "");
             if (mapList != null && Func.isNotEmpty(mapList) && mapList.size() >= 1) {
                 String status = mapList.get(0).get("status") + "";
-                if (status.equals("3")) {
-                    String updateSql = "update u_archives_auto set split_status=1 where id=" + archiveId;
-                    jdbcTemplate.execute(updateSql);
-                }
-            } else {
-                String sql22 = "insert into u_archives_split_info(id,status,file_url,first_file_url,task_id,archive_id,create_time) VALUES(" + id + ",2,'" + fileUrl + "','" + filePath + "'," + taskId + "," + archiveId + ",SYSDATE())";
-                jdbcTemplate.execute(sql22);
-                String updateSql = "update u_archives_auto set split_status=2 where id=" + archiveId;
-                jdbcTemplate.execute(updateSql);
-            }
+               // if (status.equals("3")) {
+                    String updateSql = "update u_archives_split_info set status=2 ,file_url='"+fileUrl+"',first_file_url ='"+filePath+"' where id=" + id;
+                    jdbcTemplate.update(updateSql);
+                String uateSql = "UPDATE u_archives_auto SET split_status=? WHERE id=?";
+                int delCount = jdbcTemplate.update(uateSql, 2, archiveId);
+              //  }
 
-            String sql = "delete from u_archive_file where id<>'"+id+"' and archive_id='"+archiveId+"'";
-            jdbcTemplate.execute(sql);
+            } else {
+                // 所有SQL都改为参数化查询
+                String sql22 = "INSERT INTO u_archives_split_info(id,status,file_url,first_file_url,task_id,archive_id,create_time) VALUES(?,?,?,?,?,?,SYSDATE())";
+                int addCount = jdbcTemplate.update(sql22, id, 2, fileUrl, filePath, taskId, archiveId);
 
+                String updateSql = "UPDATE u_archives_auto SET split_status=? WHERE id=?";
+                int delCount = jdbcTemplate.update(updateSql, 2, archiveId);
+            }
+            String delSql = "DELETE FROM u_archive_file WHERE id<>? AND archive_id=?";
+            jdbcTemplate.update(delSql, id, archiveId);
             RedisTemplate.delete("splitpng-" + archiveId);
+
         } catch (Exception e) {
+            System.out.println("12321312");
             e.printStackTrace();
         }
     }
-
-    @Scheduled(cron = "0/30 * * * * ?")
+   // @Scheduled(cron = "0/30 * * * * ?")
     public void SplitPdfInfo() {
         //执行代码
-
         log.info("分解html开始");
-        String sql = "select  * from u_archives_split_info where status =2 "; // and TIMESTAMPDIFF(MINUTE, create_time, NOW()) >=3";
+        String sql = "select  * from u_archives_split_info where status =2 LIMIT 20 "; // and TIMESTAMPDIFF(MINUTE, create_time, NOW()) >=3";
         List<ArchivesSplitInfoVO> query = jdbcTemplate.query(sql, new BeanPropertyRowMapper<>(ArchivesSplitInfoVO.class));
-        log.info("分解html开始==="+query.size());
+        log.info("分解html开始===" + query.size());
         if (query != null && query.size() >= 1) {
             for (ArchivesSplitInfoVO dataInfo : query) {
-                if (executor.getQueue().size() <= 10) {
+                if (archExecutor.getQueue().size() <= 10) {
                     Boolean aBoolean = RedisTemplate.hasKey("splithtml-" + dataInfo.getArchiveId());
                     if (!aBoolean) {
 
                         if (!aBoolean) {
-                            RedisTemplate.opsForValue().set("splithtml-" + dataInfo.getArchiveId(), "1", 1200, TimeUnit.SECONDS);
+                            RedisTemplate.opsForValue().setIfAbsent("splithtml-" + dataInfo.getArchiveId(), "1", 1200, TimeUnit.SECONDS);
                             CompletableFuture<Void> runAsync = CompletableFuture.runAsync(() -> {
                                 try {
                                     /*===============执行批量任务===============*/
                                     signTaskBatchpng(dataInfo);
-                                } catch (Exception e) {
-                                    e.printStackTrace();
+                                } finally {
+                                    RedisTemplate.delete("splithtml-" + dataInfo.getArchiveId());
                                 }
-                            }, executor);
+                            }, archExecutor);
                         }
                     }
                 }
             }
         }
-        System.out.println("队列数量_html" + executor.getQueue().size());
-        System.out.println("活跃数量_html" + executor.getActiveCount());
-        System.out.println("总共数量_html" + executor.getTaskCount());
-        System.out.println("完成数量_html" + executor.getCompletedTaskCount());
+        System.out.println("队列数量_html" + archExecutor.getQueue().size());
+        System.out.println("活跃数量_html" + archExecutor.getActiveCount());
+        System.out.println("总共数量_html" + archExecutor.getTaskCount());
+        System.out.println("完成数量_html" + archExecutor.getCompletedTaskCount());
     }
 
     public void signTaskBatchpng(ArchivesSplitInfoVO taskSign) {
@@ -206,10 +215,10 @@ public class ArchiveController {
             int basePage = Integer.parseInt(firstUrl[1]);
             int baseStart = Integer.parseInt(firstUrl[0]);
             String dutyUser = "";
-            int bkb = 0 ;
+            int bkb = 0;
             //将imagePath 的数据转成一个可解析的html
-            String htmlUrl = pngToHtml(firstPage, archiveId,taskSign.getFirstFileUrl());
-            System.out.println("分解002="+htmlUrl);
+            String htmlUrl = pngToHtml(firstPage, archiveId, taskSign.getFirstFileUrl());
+            System.out.println("分解002=" + htmlUrl);
 
             if (htmlUrl.indexOf("_001.html") >= 0 && htmlUrl.indexOf("archiveSplit") >= 0) {
                 String htmlString = IoUtil.readToString(new FileInputStream(htmlUrl));
@@ -217,8 +226,8 @@ public class ArchiveController {
                 Element table = doc.select("table").first();
                 Elements trs = table.select("tr");
                 //由于解析已经成功,可能数据已经分解过,需要删除
-                if(trs!=null && trs.size()>=1){
-                    String sql = "delete from u_archive_file where id<>'"+taskSign.getId()+"' and archive_id='"+archiveId+"'";
+                if (trs != null && trs.size() >= 1) {
+                    String sql = "delete from u_archive_file where id<>'" + taskSign.getId() + "' and archive_id='" + archiveId + "'";
                     jdbcTemplate.execute(sql);
                 }
 
@@ -228,78 +237,81 @@ public class ArchiveController {
                     String wjtm = tr.select("td").get(1).text();
                     String rq = tr.select("td").get(2).text();
                     String ym = tr.select("td").get(3).text();
-                   if(zrz.equals("责任者") && wjtm.equals("文件题名") && rq.equals("日期")){
+                    if (zrz.equals("责任者") && wjtm.equals("文件题名") && rq.equals("日期")) {
                         continue;
-                   }
+                    }
                     int startYm = 0;
                     int endYm = 0;
-                    if(i<trs.size()-1){
+                    if (i < trs.size() - 1) {
                         startYm = Func.toInt(ym);
-                        String enData = trs.get(i+1).select("td").get(3).text();
-                        if(enData.indexOf("页")>=0){
-                            enData = trs.get(i+2).select("td").get(3).text();
+                        String enData = trs.get(i + 1).select("td").get(3).text();
+                        if (enData.indexOf("页") >= 0) {
+                            enData = trs.get(i + 2).select("td").get(3).text();
                         }
 
                         String[] parts = enData.split("(?<=\\D)(?=\\d)|(?<=\\d)(?=\\D)");
-                        if(parts!=null && parts.length>=1){
+                        if (parts != null && parts.length >= 1) {
                             endYm = Func.toInt(parts[0]);
                         }
-                    }else{
+                    } else {
                         String[] split = ym.split("(?<=\\D)(?=\\d)|(?<=\\d)(?=\\D)");
-                        if(split!=null && split.length>=3){
+                        if (split != null && split.length >= 3) {
                             startYm = Func.toInt(split[0]);
                             endYm = Func.toInt(split[2]);
-                        }else{
+                        } else {
                             startYm = Func.toInt(split[0]);
                             endYm = Func.toInt(split[0]);
                         }
                     }
-                    startYm = basePage+startYm ;
-                    endYm = basePage+endYm ;
+                    startYm = basePage + startYm;
+                    endYm = basePage + endYm;
                     dutyUser = zrz;
-                    System.out.println("序号="+i+"--文件提名:"+wjtm +"--开始("+startYm+"-"+endYm+")---页数"+(endYm-startYm+1));
+                    System.out.println("序号=" + i + "--文件提名:" + wjtm + "--开始(" + startYm + "-" + endYm + ")---页数" + (endYm - startYm + 1));
                     // 分解文件
-                    String fmlUrl = FileUtils.getSysLocalFileUrl() + "archiveSplit/"+archiveId+"_cf_00"+i+".pdf";
-                    getPdfByPage(startYm,endYm,fileUlr,fmlUrl);
-                    saveDataToMysql(fmlUrl,wjtm,taskSign.getId(),endYm-startYm+1,i,zrz,rq);
-                    bkb =  endYm ;
+                    String fmlUrl = FileUtils.getSysLocalFileUrl() + "archiveSplit/" + archiveId + "_cf_00" + i + ".pdf";
+                    getPdfByPage(startYm, endYm, fileUlr, fmlUrl);
+                    saveDataToMysql(fmlUrl, wjtm, taskSign.getId(), endYm - startYm + 1, i, zrz, rq);
+                    bkb = endYm;
                 }
             } else {
                 return;
             }
 
             // 添加封面信息
-            String fmlUrl = FileUtils.getSysLocalFileUrl() + "archiveSplit/"+archiveId+"_fm_001.pdf";
-            getPdfByPage(1,1,fileUlr,fmlUrl);
-            saveDataToMysql(fmlUrl,"封面",taskSign.getId(),1,-4,dutyUser,"");
+            String fmlUrl = FileUtils.getSysLocalFileUrl() + "archiveSplit/" + archiveId + "_fm_001.pdf";
+            getPdfByPage(1, 1, fileUlr, fmlUrl);
+            saveDataToMysql(fmlUrl, "封面", taskSign.getId(), 1, -4, dutyUser, "");
 
             // 卷内目录
-            String jnmuUrl = FileUtils.getSysLocalFileUrl() + "archiveSplit/"+archiveId+"_jnml_001.pdf";
-            getPdfByPage(baseStart,basePage,fileUlr,jnmuUrl);
-            saveDataToMysql(jnmuUrl,"卷内目录",taskSign.getId(),1,-3,dutyUser,"");
+            String jnmuUrl = FileUtils.getSysLocalFileUrl() + "archiveSplit/" + archiveId + "_jnml_001.pdf";
+            getPdfByPage(baseStart, basePage, fileUlr, jnmuUrl);
+            saveDataToMysql(jnmuUrl, "卷内目录", taskSign.getId(), 1, -3, dutyUser, "");
 
             // 卷内备考表
-            String jnbkbUrl = FileUtils.getSysLocalFileUrl() + "archiveSplit/"+archiveId+"_jnbkb_001.pdf";
-            getPdfByPage(bkb+1,bkb+1,fileUlr,jnbkbUrl);
-            saveDataToMysql(jnbkbUrl,"卷内备考表",taskSign.getId(),1,100,dutyUser,"");
-
-            // 背脊表
-            String bjbUrl = FileUtils.getSysLocalFileUrl() + "archiveSplit/"+archiveId+"_beiji_001.pdf";
-            String bjbUrlPng = FileUtils.getSysLocalFileUrl() + "archiveSplit/"+archiveId+"_beiji_001.png";
-
-            getPdfByPage(bkb+2,bkb+2,fileUlr,bjbUrl);
+            String jnbkbUrl = FileUtils.getSysLocalFileUrl() + "archiveSplit/" + archiveId + "_jnbkb_001.pdf";
+            getPdfByPage(bkb + 1, bkb + 1, fileUlr, jnbkbUrl);
 
-            File bgImgFile = new File(bjbUrlPng);
-            if (!bgImgFile.exists()) {
-                savePdfAsImage(1, bjbUrl, bjbUrlPng);
+            File jlPdfFile = new File(jnbkbUrl);
+            if (jlPdfFile.exists()) {
+                saveDataToMysql(jnbkbUrl, "卷内备考表", taskSign.getId(), 1, 100, dutyUser, "");
             }
-            String state = OcrTitle(bjbUrlPng,"3");
-            if(state.equals("1")){
-                saveDataToMysql(bjbUrl,"背脊表",taskSign.getId(),1,101,dutyUser,"");
-            }
-            bgImgFile.delete();
-
 
+            // 背脊表
+            String bjbUrl = FileUtils.getSysLocalFileUrl() + "archiveSplit/" + archiveId + "_beiji_001.pdf";
+            String bjbUrlPng = FileUtils.getSysLocalFileUrl() + "archiveSplit/" + archiveId + "_beiji_001.png";
+
+            int pdfByPage = getPdfByPage(bkb + 2, bkb + 2, fileUlr, bjbUrl);
+            if(pdfByPage==0){
+                File bgImgFile = new File(bjbUrlPng);
+                if (!bgImgFile.exists()) {
+                    int dataNum = savePdfAsImage(1, bjbUrl, bjbUrlPng);
+                }
+                String state = OcrTitle(bjbUrlPng, "3");
+                if (state.equals("1")) {
+                    saveDataToMysql(bjbUrl, "背脊表", taskSign.getId(), 1, 101, dutyUser, "");
+                }
+                bgImgFile.delete();
+            }
             // 修改任务状态
             String updateSql = "update u_archives_split_info set status=3 where id=" + taskSign.getId();
             jdbcTemplate.execute(updateSql);
@@ -308,8 +320,8 @@ public class ArchiveController {
             jdbcTemplate.execute(updateSqlAuto);
 
             // 统计各个任务的结果
-            String taxkSql = "UPDATE u_task_split a set finished = (SELECT count(1) from u_archives_auto b where FIND_IN_SET(b.id,a.ids) and b.split_status=1) where FIND_IN_SET("+taskSign.getArchiveId()+",a.ids)  and a.type=3";
-            String taxkSql2 = "UPDATE u_task_split a set finished = (SELECT count(1) from u_archives_auto b where a.contract_id=b.contract_id) where a.id="+taskSign.getTaskId()+" and a.type=2";
+            String taxkSql = "UPDATE u_task_split a set finished = (SELECT count(1) from u_archives_auto b where FIND_IN_SET(b.id,a.ids) and b.split_status=1) where FIND_IN_SET(" + taskSign.getArchiveId() + ",a.ids)  and a.type=3";
+            String taxkSql2 = "UPDATE u_task_split a set finished = (SELECT count(1) from u_archives_auto b where a.contract_id=b.contract_id) where a.id=" + taskSign.getTaskId() + " and a.type=2";
             jdbcTemplate.execute(taxkSql);
             jdbcTemplate.execute(taxkSql2);
 
@@ -324,7 +336,7 @@ public class ArchiveController {
         }
     }
 
-    public static String pngToHtml(String fileUrl, String pKeyId,String pageNum) {
+    public static String pngToHtml(String fileUrl, String pKeyId, String pageNum) {
         String lasHhtmlUrl = "";
         try {
             // 定义Python解释器路径和脚本路径
@@ -371,7 +383,7 @@ public class ArchiveController {
             String htmlUrl;
             while ((htmlUrl = reader.readLine()) != null) {
                 System.out.println("222" + htmlUrl);
-                if (htmlUrl.indexOf("图片中是否有卷内目录") >= 0 && htmlUrl.indexOf("True") >=0) {
+                if (htmlUrl.indexOf("图片中是否有卷内目录") >= 0 && htmlUrl.indexOf("True") >= 0) {
                     return "1";
                 }
             }
@@ -389,12 +401,11 @@ public class ArchiveController {
     }
 
 
-    public static void getPdfByPage(int startPage, int endPage, String filePath, String savePath) {
+    public static int getPdfByPage(int startPage, int endPage, String filePath, String savePath) {
         try {
-            InputStream inputStreamByUrl = FileUtils.getInputStreamByUrl(filePath);
+            InputStream inputStreamByUrl = CommonUtil.getOSSInputStream3(filePath);
             // 加载PDF文件
             PDDocument document = PDDocument.load(inputStreamByUrl);
-
             // 创建新文档
             PDDocument newDocument = new PDDocument();
 
@@ -412,19 +423,19 @@ public class ArchiveController {
             newDocument.save(savePath);
             newDocument.close();
             document.close();
+            return 0;
         } catch (Exception e) {
-            log.error("提取PDF页面失败", e);
-            throw new RuntimeException("提取PDF页面失败", e);
+            return 1;
         }
     }
 
-    public static void savePdfAsImage(int pageNum, String filePath, String outputPath) {
+    public static int 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("无效的页码");
+                return 1;
             }
 
             PDFRenderer renderer = new PDFRenderer(document);
@@ -445,18 +456,19 @@ public class ArchiveController {
             log.info("PDF页面已成功保存为图片: {}", outputPath);
             inputStream.close();
             document.close();
+            return 0;
         } catch (Exception e) {
             log.error("PDF转图片失败", e);
-            throw new RuntimeException("PDF转图片失败", e);
+            return 1;
         }
     }
 
-    public int saveDataToMysql(String upFileUrl,String fileName,String fileId,int filePage,int sort,String dutyUser,String fileTime) {
+    public int saveDataToMysql(String upFileUrl, String fileName, String fileId, int filePage, int sort, String dutyUser, String fileTime) {
         // 获取封面信息
         long newPkId = SnowFlakeUtil.getId(); //主键Id
         File fmfile = new File(upFileUrl);
         if (fmfile.exists()) {
-            BladeFile bladeFile = this.newIOSSClient.uploadFile(fileName+".pdf", upFileUrl);
+            BladeFile bladeFile = this.newIOSSClient.uploadFile(fileName + ".pdf", upFileUrl);
             if (bladeFile != null && Func.isNotEmpty(bladeFile.getLink())) {
                 String FmPdfUrl = bladeFile.getLink();
                 String sql = " insert into u_archive_file( " +
@@ -464,8 +476,8 @@ public class ArchiveController {
                         " drawing_no,cite_change_number,certification_time,e_visa_file,node_ext_id,file_type,archive_id,origin_id,filming_time,filmingor_time,tag_id,pic_code,refer_code,film_code,width,height,ftime,utime,del_time,sort,box_name,box_number,is_auto_file,is_archive,page_num, " +
                         " file_size,source_type,is_element,pdf_page_url,fid,rectification,classify,m_wbs_tree_contract_p_key_id,u_image_classification_file_id,archive_file_storage_type,node_tree_structure,date_name,archive_file_stroage_type,out_id,sort_num " +
                         "   ) " +
-                        " SELECT "+newPkId+",project_id,contract_id,node_id,file_number,'" + fileName + "','"+fileTime+"','" + FmPdfUrl + "','" + FmPdfUrl + "',"+filePage+",is_approval,is_certification,is_need_certification,'"+dutyUser+"',create_user,create_dept,create_time,update_user,update_time,status,is_deleted,sheet_type,sheet_source, " +
-                        "        drawing_no,cite_change_number,certification_time,e_visa_file,node_ext_id,file_type,archive_id,origin_id,filming_time,filmingor_time,tag_id,pic_code,refer_code,film_code,width,height,ftime,utime,del_time,"+sort+",box_name,box_number,is_auto_file,is_archive,page_num, " +
+                        " SELECT " + newPkId + ",project_id,contract_id,node_id,file_number,'" + fileName + "','" + fileTime + "','" + FmPdfUrl + "','" + FmPdfUrl + "'," + filePage + ",is_approval,is_certification,is_need_certification,'" + dutyUser + "',create_user,create_dept,create_time,update_user,update_time,status,is_deleted,sheet_type,sheet_source, " +
+                        "        drawing_no,cite_change_number,certification_time,e_visa_file,node_ext_id,file_type,archive_id,origin_id,filming_time,filmingor_time,tag_id,pic_code,refer_code,film_code,width,height,ftime,utime,del_time," + sort + ",box_name,box_number,is_auto_file,is_archive,page_num, " +
                         "        file_size,source_type,is_element,pdf_page_url,fid,rectification,classify,m_wbs_tree_contract_p_key_id,u_image_classification_file_id,archive_file_storage_type,node_tree_structure,date_name,archive_file_stroage_type,out_id,sort_num " +
                         " from u_archive_file where id=" + fileId;
                 System.out.println(fileName + "----" + sql);
@@ -476,7 +488,7 @@ public class ArchiveController {
                 System.out.println("oss服务未启动,无法上传文件到oss");
                 return 500;
             }
-        }else{
+        } else {
             return 404;
         }
         fmfile.delete();

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

@@ -46,10 +46,11 @@ import java.util.concurrent.TimeUnit;
 public class  Chek {
 
     @Autowired
-    StringRedisTemplate RedisTemplate;
-    // jdbc
-    private final JdbcTemplate jdbcTemplate;
-    private final NewIOSSClient newIOSSClient;
+    private StringRedisTemplate RedisTemplate;
+    @Autowired
+    private JdbcTemplate jdbcTemplate;
+    @Autowired
+    private NewIOSSClient newIOSSClient;
     // 线程池
     @Resource(name = "taskExecutor1")
     private ThreadPoolExecutor executor;

+ 8 - 3
blade-service/blade-e-visa/src/main/java/org/springblade/evisa/controller/ChekSignData.java

@@ -31,11 +31,16 @@ import java.util.concurrent.TimeUnit;
 public class ChekSignData {
 
     @Autowired
-    StringRedisTemplate RedisTemplate;
+    private StringRedisTemplate RedisTemplate;
+
     // jdbc
-    private final JdbcTemplate jdbcTemplate;
+    @Autowired
+    private JdbcTemplate jdbcTemplate;
+
     //电签服务类
-    private final ScrDataService scrDataService;
+    @Autowired
+    private ScrDataService scrDataService;
+
     // 线程池
     @Resource(name = "taskExecutor1")
     private ThreadPoolExecutor executor;

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

@@ -0,0 +1,35 @@
+package org.springblade.evisa.utils;
+
+import org.springblade.common.utils.ThreadPoolMonitor;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.Primary;
+
+import java.util.concurrent.LinkedBlockingQueue;
+import java.util.concurrent.ThreadPoolExecutor;
+import java.util.concurrent.TimeUnit;
+
+@Configuration
+public class ArchivePoolExecutorConfig {
+
+    /**
+     * cpu 核心数量
+     */
+    public static final int cpuNum = 5 ;//Runtime.getRuntime().availableProcessors();
+
+    /**
+     * 线程池配置
+     * @return
+     */
+    @Bean("archivePoolExecutor")
+    @Primary
+    public ThreadPoolExecutor gerArchivePoolExecutor() {
+        return new ThreadPoolMonitor(cpuNum
+                , 10
+                , 180
+                , TimeUnit.SECONDS
+                , new LinkedBlockingQueue<>(200)
+                , new ThreadPoolExecutor.DiscardOldestPolicy(), "ArchivePoolExecutor-pool");
+    }
+
+}

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

@@ -2074,11 +2074,11 @@ public class ExcelTabController extends BladeController {
             tableInfoList.parallelStream().forEach(tableInfo -> {
                 R bussPdfInfo = null;
                 try {
-                    if(finalSingnType.equals("1") && tableInfo.getProjectId().equals("1630011899725201410") && (tableInfo.getIsTypePrivatePid().equals("1559714325173080065") || tableInfo.getIsTypePrivatePid().equals("1559479719236702210") )){
+                    /*if(finalSingnType.equals("1") && tableInfo.getProjectId().equals("1630011899725201410") && (tableInfo.getIsTypePrivatePid().equals("1559714325173080065") || tableInfo.getIsTypePrivatePid().equals("1559479719236702210") )){
                         System.out.println("12312312");
-                    }else{
+                    }else{*/
                         bussPdfInfo = excelTabService.getBussPdfInfo(Long.parseLong(tableInfo.getPkeyId()));
-                    }
+                 //   }
                 } catch (Exception e) {
                     e.printStackTrace();
                 }

+ 5 - 0
blade-service/blade-manager/src/main/java/org/springblade/manager/feign/ArchiveTreeContractImpl.java

@@ -40,6 +40,11 @@ public class ArchiveTreeContractImpl implements ArchiveTreeContractClient {
         return archiveTreeList;
     }
 
+    @Override
+    public String getAuthCode(Long contractId){
+        return this.archiveTreeContractService.getAuthCode(contractId);
+    }
+
     /**
      * 获取项目下存在未组卷文件的归档树节点
      *

+ 4 - 1
blade-service/blade-manager/src/main/java/org/springblade/manager/formula/impl/ExecutorMeter.java

@@ -1349,13 +1349,16 @@ public class ExecutorMeter extends FormulaExecutor {
                                      }
                                      rebateIncentiveAdvPay.setRetained(rebateIncentiveAdvPay.getCurrentPay());
                                  } else {
-                                     rebateIncentiveAdvPay.calc(baseInfo.getContractAmount().toPlainString(), dyTotalAmount);
+                                     rebateIncentiveAdvPay.calc(baseInfo.getContractAmount().toPlainString(), dyTotalAmount,preSubTotal.getCurrentPeriodEndPay());
                                  }
                                  if (preSubTotal != null) {
                                      rebateIncentiveAdvPay.setEndPay(addFc.apply(rebateIncentiveAdvPay.getCurrentPay(), preSubTotal.getCurrentPeriodEndPay()));
                                  } else {
                                      rebateIncentiveAdvPay.setEndPay(rebateIncentiveAdvPay.getCurrentPay());
                                  }
+                                 if(preSubTotal!=null){
+                                     rebateIncentiveAdvPay.setPreviousPay(preSubTotal.getCurrentPeriodEndPay());
+                                 }
                              }
 
                          }else if("材料预付款".equals(certificate.getChapterSeq())){

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

@@ -182,5 +182,15 @@
             AND TABLE_NAME = #{tableName}
             AND DATA_TYPE = 'varchar'
     </select>
+    <select id="selectSumColumnLength" resultType="java.lang.Integer">
+        SELECT
+            SUM( CHARACTER_MAXIMUM_LENGTH )
+        FROM
+            information_schema.COLUMNS
+        WHERE
+            TABLE_SCHEMA = #{database}
+            AND TABLE_NAME = #{tableName}
+            AND DATA_TYPE = 'varchar'
+    </select>
 
 </mapper>

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

@@ -145,4 +145,6 @@ public interface IArchiveTreeContractService extends BaseService<ArchiveTreeCont
     void addArchiveTreeContract(List<ArchiveTreeContract> archiveTreeContracts, Long rootId);
 
     Long getNodeIdByName(String projectName, String contractName, String nodeName);
+
+    boolean deleteTreeEx(Long id);
 }

+ 28 - 0
blade-service/blade-manager/src/main/java/org/springblade/manager/service/impl/ArchiveTreeContractServiceImpl.java

@@ -769,6 +769,34 @@ public class ArchiveTreeContractServiceImpl extends BaseServiceImpl<ArchiveTreeC
 		return true;
 	}
 
+	/**
+	 * 更轻量的删除节点树,同时删除节点下的案卷和文件
+	 * @param id
+	 * @return
+	 */
+	public boolean deleteTreeEx(Long id){
+
+		ArchiveTreeContract dstNode = this.getById(id);
+		if (dstNode == null ) {
+			return false;
+		}
+
+		List<Long> ids = new ArrayList<>();
+		List<ArchiveTreeContract> archiveTreeContracts = this.queryAllChildByAncestors(id.toString(),dstNode.getContractId());
+		//遍历archiveTreeContracts 取id,放到ids
+		for (ArchiveTreeContract archiveTreeContract : archiveTreeContracts) {
+			ids.add(archiveTreeContract.getId());
+		}
+
+		ids.add(id);
+		this.deleteLogic(ids);
+
+		//删除案卷
+		archiveAutoClient.removeArchivesByNodeIds(ids);
+
+		return true;
+	}
+
 
 	/**
 	 * 批量更新

+ 13 - 7
blade-service/blade-manager/src/main/java/org/springblade/manager/service/impl/ExcelTabServiceImpl.java

@@ -1241,7 +1241,9 @@ public class ExcelTabServiceImpl extends BaseServiceImpl<ExcelTabMapper, ExcelTa
                     String delSql = "delete from " + tabName + " where p_key_id=" + tableInfo.getPkeyId();
                     String sqlInfo = "";
                     LinkedHashMap<String, String> dataMap2 = tableInfo.getDataMap();
-                    updateFieldLength(tabName, dataMap2);
+                    if (!updateFieldLength(tabName, dataMap2)) {
+                        throw new ServiceException("字段长度超出限制, 系统无法进行自增,请前往后台管理系统手动设置");
+                    }
                     /*检查发现有p_key_id缺失的情况,导致表单数据丢失,所以强制覆盖*/
                     dataMap2.put("p_key_id", tableInfo.getPkeyId());
                     //统计保存的字段
@@ -1352,14 +1354,17 @@ public class ExcelTabServiceImpl extends BaseServiceImpl<ExcelTabMapper, ExcelTa
        // return R.success(fileName1);
     }
 
-    public void updateFieldLength(String tableName, Map<String, String> fieldNameAndLengthMap) {
+    public boolean updateFieldLength(String tableName, Map<String, String> fieldNameAndLengthMap) {
         if (fieldNameAndLengthMap == null || fieldNameAndLengthMap.isEmpty()) {
-            return;
+            return true;
         }
-        String fields = fieldNameAndLengthMap.keySet().stream().filter(key -> !key.equals("id") && !key.equals("p_key_id") && !key.equals("group_id")).map(key -> "'" + key + "'").collect(Collectors.joining(","));
-        if (fields.isEmpty()) {
-            return;
+        fieldNameAndLengthMap.remove("id");
+        fieldNameAndLengthMap.remove("p_key_id");
+        fieldNameAndLengthMap.remove("group_id");
+        if (fieldNameAndLengthMap.isEmpty()) {
+            return true;
         }
+        String fields = fieldNameAndLengthMap.keySet().stream().map(key -> "'" + key + "'").collect(Collectors.joining(","));
         List<Map<String, Object>> fieldMap = jdbcTemplate.queryForList("select distinct COLUMN_NAME as fieldName, CHARACTER_MAXIMUM_LENGTH as fieldLength from information_schema.COLUMNS where  TABLE_NAME = '" + tableName +
                 "' and COLUMN_NAME in (" + fields + ")");
         Map<String, Integer> map = fieldMap.stream().collect(toMap(k -> k.get("fieldName") + "", v -> {
@@ -1400,9 +1405,10 @@ public class ExcelTabServiceImpl extends BaseServiceImpl<ExcelTabMapper, ExcelTa
             } catch (Exception e) {
                 transactionManager1.rollback(transactionStatus);
                 log.error("更新字段长度失败, error: " + e.getMessage());
-                throw new ServiceException("字段长度超出限制, 系统无法进行自增,请前往后台管理系统手动设置");
+                return false;
             }
         }
+        return true;
     }
 
     public String reason(String log) {

+ 8 - 3
blade-service/blade-manager/src/main/java/org/springblade/manager/service/impl/FormulaServiceImpl.java

@@ -3791,12 +3791,14 @@ public class FormulaServiceImpl extends BaseServiceImpl<FormulaMapper, Formula>
             BigDecimal o=getMeterFormNumber(periodId,key,"now_money");
             if (ObjectUtil.isNotEmpty(o)) {
                 monthlyReport.setNowMoney(o);
-                BigDecimal percentage = monthlyReport.getNowMoney().divide(monthlyReport.getAfterCurrentMeterMoney(), 10, BigDecimal.ROUND_HALF_UP).multiply(new BigDecimal("100"));
+                BigDecimal percentage=BigDecimal.ZERO;
+                if(o.compareTo(BigDecimal.ZERO)!=0&&monthlyReport.getAfterCurrentMeterMoney().compareTo(BigDecimal.ZERO)!=0){
+                    percentage=monthlyReport.getNowMoney().divide(monthlyReport.getAfterCurrentMeterMoney(), 10, BigDecimal.ROUND_HALF_UP).multiply(new BigDecimal("100"));
+                }
                 percentage = percentage.setScale(2, BigDecimal.ROUND_HALF_UP); // 设置小数位数为2
                 if (percentage.compareTo(BigDecimal.ZERO) != 0) {
                     monthlyReport.setNowC(percentage + "%");
                 }
-
             }
             //到本期末完成
             //如果有到上期末完成金额,和本期完成金额  则到本期末完成金额=到上期末完成金额+本期完成金额
@@ -3812,7 +3814,10 @@ public class FormulaServiceImpl extends BaseServiceImpl<FormulaMapper, Formula>
                 monthlyReport.setNowEndMoney(BigDecimal.ZERO);
             }
             if (ObjectUtil.isNotEmpty(monthlyReport.getNowEndMoney())) {
-                BigDecimal percentage = monthlyReport.getNowEndMoney().divide(monthlyReport.getAfterCurrentMeterMoney(), 10, BigDecimal.ROUND_HALF_UP).multiply(new BigDecimal("100"));
+                BigDecimal percentage=BigDecimal.ZERO;
+                if(o.compareTo(BigDecimal.ZERO)!=0&&monthlyReport.getAfterCurrentMeterMoney().compareTo(BigDecimal.ZERO)!=0){
+                    percentage= monthlyReport.getNowEndMoney().divide(monthlyReport.getAfterCurrentMeterMoney(), 10, BigDecimal.ROUND_HALF_UP).multiply(new BigDecimal("100"));
+                }
                 percentage = percentage.setScale(2, BigDecimal.ROUND_HALF_UP); // 设置
                 if (percentage.compareTo(BigDecimal.ZERO) != 0) {
                     monthlyReport.setNowEndC(percentage + "%");

+ 11 - 0
blade-service/blade-manager/src/main/java/org/springblade/manager/service/impl/TextdictInfoServiceImpl.java

@@ -20,6 +20,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper;
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import org.apache.commons.lang.StringUtils;
 import org.jetbrains.annotations.NotNull;
@@ -33,6 +34,12 @@ import org.springblade.common.utils.CommonUtil;
 import org.springblade.common.utils.SnowFlakeUtil;
 import org.springblade.common.utils.SystemUtils;
 import org.springblade.core.tool.utils.*;
+import org.springblade.common.constant.CommonConstant;
+import org.springblade.common.utils.CommonUtil;
+import org.springblade.core.tool.utils.FileUtil;
+import org.springblade.core.tool.utils.Func;
+import org.springblade.core.tool.utils.IoUtil;
+import org.springblade.core.tool.utils.ResourceUtil;
 import org.springblade.manager.entity.TextdictInfo;
 import org.springblade.manager.entity.WbsTreeContract;
 import org.springblade.manager.entity.WbsTreePrivate;
@@ -48,6 +55,10 @@ import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 
 import javax.annotation.Resource;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.InputStream;
 import java.io.*;
 import java.util.*;
 import java.util.concurrent.atomic.AtomicBoolean;

+ 30 - 11
blade-service/blade-manager/src/main/java/org/springblade/manager/service/impl/WbsFormElementServiceImpl.java

@@ -314,6 +314,22 @@ public class WbsFormElementServiceImpl extends BaseServiceImpl<WbsFormElementMap
         //修改元素基础信息
         wbsFormElementList.forEach(obj -> obj.setStatus(1));
         boolean b = this.updateBatchById(wbsFormElementList);
+
+
+        //当前设置的字段总长度
+        Integer nowTotalLength = 0;
+        for (WbsFormElement wbsFormElement : wbsFormElementList) {
+            // + 10 预留字段长度,用来保存在excel中的位置信息,比如:xx_^_12_12, 不适合一个字段存储多个位置
+            nowTotalLength += wbsFormElement.getELength() + 10;
+        }
+        //当前表总字段长度
+        int sumLength = baseMapper.selectSumColumnLength(jdbcTemplate.queryForObject("SELECT DATABASE()", String.class), initTableName);
+        if (nowTotalLength > MYSQL_MAX_COLUMN_LENGTH) {
+            //修改元素字段长度
+            throw new ServiceException("无法添加字段,可用长度:" + (MYSQL_MAX_COLUMN_LENGTH - sumLength));
+        }
+
+
         //修改实体表信息
         if (b) {
             String fId = "";
@@ -352,18 +368,21 @@ public class WbsFormElementServiceImpl extends BaseServiceImpl<WbsFormElementMap
 //                } else if (eLength >= 0 && eLength <= 65) {
 //                    eLength = DEFAULT_ELEMENT_LENGTH_NUMBER;
 //                }
-                Integer length = eLengthMap.get(wbsFormElement.getId());
-                if (length == null || !length.equals(eLength)) {
-                    //判断是否存在该Key字段
-                    int row1 = wbsTreeMapper.isThereAField(initTableName, eKey);
-                    if (row1 > 0) {
-                        try {
-                            baseMapper.updateFiledType(initTableName, eKey, "varchar", eLength);
-                        } catch (Exception e) {
-                            e.printStackTrace();
-                            this.updateBatchById(beforeUpdateWbsFormElements);
-                            return R.fail(eName + "长度范围超出总最大限制,请尝试缩小当前字段长度或其他字段长度");
+
+                //判断是否存在该Key字段
+                int row1 = wbsTreeMapper.isThereAField(initTableName, eKey);
+                if (row1 > 0) {
+                    try {
+                        // + 10 预留字段长度,用来保存在excel中的位置信息,比如:xx_^_12_12, 不适合一个字段存储多个位置
+                        baseMapper.updateFiledType(initTableName, eKey, "varchar", eLength + 10);
+                    } catch (Exception e) {
+                        // 数据库字段长度大于修改长度,则忽略
+                        if (e.getMessage().contains("Data truncated for column '" + eKey + "' at row 1")) {
+                            continue;
                         }
+                        e.printStackTrace();
+                        this.updateBatchById(beforeUpdateWbsFormElements);
+                        throw new RuntimeException("字段长度范围超出总最大限制,请尝试缩小当前字段长度或其他字段长度");
                     }
                 }
             }

+ 40 - 6
blade-service/blade-manager/src/main/java/org/springblade/manager/service/impl/WbsSynchronousEViSaServiceImpl.java

@@ -4,9 +4,11 @@ import cn.hutool.core.date.DateTime;
 import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
 import com.baomidou.mybatisplus.core.toolkit.StringUtils;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.google.common.collect.Lists;
 import org.springblade.common.utils.SnowFlakeUtil;
 import org.springblade.core.log.exception.ServiceException;
 import org.springblade.core.tool.utils.CollectionUtil;
+import org.springblade.core.tool.utils.StringUtil;
 import org.springblade.manager.entity.*;
 import org.springblade.manager.feign.ExcelTabClient;
 import org.springblade.manager.feign.WbsTreeContractOldHtmlClient;
@@ -66,7 +68,7 @@ public class WbsSynchronousEViSaServiceImpl {
     }
 
     @Transactional(rollbackFor = Exception.class)
-    public void updateSyncPrivateForm(WbsTreePrivate wbsTreePrivate, List<WbsTreePrivate> collect,Long createUserId, Long id,String errorMsg) {
+    public void updateSyncPrivateForm(WbsTreePrivate wbsTreePrivate, List<WbsTreePrivate> collect, Long createUserId, Long id, String errorMsg) {
         List<Long> ids = collect.stream().map(WbsTreePrivate::getPKeyId).collect(Collectors.toList());
         List<Long> parentIds = collect.stream().map(WbsTreePrivate::getParentId).collect(Collectors.toList());
         //节点公式同步
@@ -78,7 +80,7 @@ public class WbsSynchronousEViSaServiceImpl {
                 .set(WbsTreePrivate::getInitTableId, wbsTreePrivate.getInitTableId())
                 .set(WbsTreePrivate::getInitTableName, wbsTreePrivate.getInitTableName())
                 .set(WbsTreePrivate::getHtmlUrl, wbsTreePrivate.getHtmlUrl())
-                .set(wbsTreePrivate.getExcelId()!=null,WbsTreePrivate::getIsLinkTable, 2)
+                .set(wbsTreePrivate.getExcelId() != null, WbsTreePrivate::getIsLinkTable, 2)
                 .set(WbsTreePrivate::getExcelId, wbsTreePrivate.getExcelId())
                 .set(WbsTreePrivate::getUpdateTime, DateTime.now())
                 .set(WbsTreePrivate::getUpdateUser, createUserId)
@@ -93,7 +95,7 @@ public class WbsSynchronousEViSaServiceImpl {
     }
 
     @Transactional(rollbackFor = Exception.class)
-    public void syncPrivateForceForm(WbsTreePrivate wbsTreePrivate,Long createUserId, String nodeId, Long id) {
+    public void syncPrivateForceForm(WbsTreePrivate wbsTreePrivate, Long createUserId, String nodeId, Long id) {
         WbsTreePrivate wbsTreePrivate1 = wbsTreePrivateMapper.selectById(nodeId);
 
         wbsTreePrivateMapper.update(null, Wrappers.<WbsTreePrivate>lambdaUpdate()
@@ -101,7 +103,7 @@ public class WbsSynchronousEViSaServiceImpl {
                 .set(WbsTreePrivate::getInitTableName, wbsTreePrivate.getInitTableName())
                 .set(WbsTreePrivate::getInitTableId, wbsTreePrivate.getInitTableId())
                 .set(WbsTreePrivate::getHtmlUrl, wbsTreePrivate.getHtmlUrl())
-                .set(StringUtils.isBlank(wbsTreePrivate.getFullName()),WbsTreePrivate::getFullName, wbsTreePrivate1.getNodeName())
+                .set(StringUtils.isBlank(wbsTreePrivate.getFullName()), WbsTreePrivate::getFullName, wbsTreePrivate1.getNodeName())
                 .set(WbsTreePrivate::getNodeName, wbsTreePrivate.getNodeName())
                 .set(WbsTreePrivate::getUpdateTime, DateTime.now())
                 .set(WbsTreePrivate::getUpdateUser, createUserId)
@@ -286,9 +288,10 @@ public class WbsSynchronousEViSaServiceImpl {
 
     /**
      * 同项目下不同节点 不同的节点公式
-     * @param projectId 项目id
+     *
+     * @param projectId    项目id
      * @param tempParentId 源节点父级id
-     * @param parentId 节点父级id
+     * @param parentId     节点父级id
      */
     public void saveFormula(Long projectId, Long tempParentId, Long parentId) {
 
@@ -315,4 +318,35 @@ public class WbsSynchronousEViSaServiceImpl {
         elementFormulaMappingService.saveBatch(collect1);
 
     }
+    @Transactional(rollbackFor = Exception.class)
+    public int insertContractForm(WbsTreeSynchronousRecord wbsTreeSynchronousRecord, List<WbsTreeContract> list, Long pId) {
+
+        //新增-----------------------------------------------------------------------------------------------------------------
+        //排序调整
+        if (wbsTreeSynchronousRecord.getType().contains("7")) {
+            list.sort(Comparator.comparingInt(WbsTreeContract::getSort));
+            //获取节点下的当前表单
+            List<WbsTreeContract> resourceData = wbsTreeContractMapper.selectList(Wrappers.<WbsTreeContract>lambdaQuery()
+                    .select(WbsTreeContract::getPKeyId, WbsTreeContract::getSort)
+                    .eq(WbsTreeContract::getPId, pId)
+                    .eq(WbsTreeContract::getIsDeleted, 0)
+                    .orderByAsc(WbsTreeContract::getSort));
+            if (CollectionUtil.isNotEmpty(resourceData)) {
+                for (int i = 0; i < resourceData.size(); i++) {
+                    resourceData.get(i).setSort(i + 1);
+                }
+                //修改排序为连续排序
+                wbsTreeContractMapper.updateSortBatchByPKeyId(resourceData);
+            }
+
+
+            for (WbsTreeContract wbsTreePrivate : list) {
+                wbsTreeContractMapper.updateSortByPId(pId, wbsTreePrivate.getSort());
+            }
+        }
+
+        //单个批次一个事务,只会回滚当前批次数据
+        Integer i = wbsTreeContractMapper.insertBatchSomeColumn(list);
+        return i;
+    }
 }

+ 70 - 127
blade-service/blade-manager/src/main/java/org/springblade/manager/service/impl/WbsSynchronousServiceImpl.java

@@ -24,14 +24,12 @@ import org.springframework.scheduling.annotation.Async;
 import org.springframework.stereotype.Service;
 
 import java.io.File;
-import java.io.FileInputStream;
 import java.io.IOException;
 import java.io.InputStream;
 import java.nio.file.Files;
 import java.nio.file.StandardCopyOption;
 import java.rmi.ServerException;
 import java.util.*;
-import java.util.function.Function;
 import java.util.stream.Collectors;
 
 /**
@@ -597,6 +595,7 @@ public class WbsSynchronousServiceImpl {
         //获取当前项目所有合同---------------------------------------------------------------------------------------------------
         List<ContractInfo> contractInfos = contractInfoMapper.selectContractIdByProjectId(String.valueOf(wbsTreeSynchronousRecord.getProjectId()));
 
+        List<WbsTreeContract> addData = new ArrayList<>();
         List<WbsTreeContract> editData = new ArrayList<>();
         List<WbsTreeContract> oldHtml = new ArrayList<>();
         StringBuilder errorMsg = new StringBuilder("");
@@ -718,9 +717,10 @@ public class WbsSynchronousServiceImpl {
                                                     //未填报 101
                                                     isSync = true;
                                                 } else {
-                                                    if (i == 0) {
-                                                        isSync = false;
+                                                    //没有选择未填报,但是表单查不到数据,表示这个节点有问题
+                                                    if (i == 0 && !contractRanges.contains(WbsSyncTypeEnum.NOT_FILLED_IN.code)) {
                                                         errorMsg.append(editContractNode.getNodeName() + "(" + editContractNode.getPKeyId() + ")").append("未填报;");
+                                                        continue;
                                                     }
                                                     if (contractRanges.contains(WbsSyncTypeEnum.ALREADY_FILLED_IN_NOT_REPORTED.code) && (submit == null || submit == 0)) {
                                                         //已填报-未上报 102
@@ -812,7 +812,7 @@ public class WbsSynchronousServiceImpl {
                         switch (i) {
                             //添加表单
                             case 1:
-                                insertContractForm(wbsTreeSynchronousRecord, contractInfo, wbsTreeContracts, addContractNode);
+                                addData.addAll(insertContractForm(wbsTreeSynchronousRecord, contractInfo, wbsTreeContracts, addContractNode,errorMsg));
                                 //如果同时选择新增表单和其他的同步类型  在操作其他类型的时候需要添加新的表单
 //                                    if (CollectionUtil.isNotEmpty(addContractNode)) {
 //                                        editContractNodes.addAll(addContractNode.stream().filter(f -> f.getType() == 2).collect(Collectors.toList()));
@@ -837,20 +837,60 @@ public class WbsSynchronousServiceImpl {
 
         }
 
-
-        //合同段同步同时记录数量
+        Set<Long> pIdsNew = new HashSet<>();
+        //新增数据
+        Map<Long, List<WbsTreeContract>> collect2 = addData.stream().collect(Collectors.groupingBy(WbsTreeContract::getPId));
+        if(CollectionUtil.isNotEmpty(addData)){
+            pIdsNew.addAll(collect2.keySet());
+        }
+        //修改数据
         Map<Long, List<WbsTreeContract>> collect1 = editData.stream().collect(Collectors.groupingBy(WbsTreeContract::getPId));
-        Set<Long> pIds = collect1.keySet();
+        if(CollectionUtil.isNotEmpty(editData)){
+            pIdsNew.addAll(collect1.keySet());
+        }
+        //计数 同步节点数量 按最小节点统计
         Integer nodeNumEnd = 0;
 
-        Map<Long, List<WbsTreeContract>> collect2 = oldHtml.stream().collect(Collectors.groupingBy(WbsTreeContract::getPId));
+        //需要记录历史html的表单
+        Map<Long, List<WbsTreeContract>> collect3 = oldHtml.stream().collect(Collectors.groupingBy(WbsTreeContract::getPId));
 
-        for (Long pId : pIds) {
+        for (Long pId : pIdsNew) {
             nodeNumEnd++;
-            List<WbsTreeContract> list = collect1.get(pId);
-            List<WbsTreeContract> oldHtmlPId = collect2.get(pId);
 
-            wbsSynchronousEViSaService.updateContract(wbsTreeSynchronousRecord.getType(), pId, wbsTreeSynchronousRecord.getCreateUserId(), list, oldHtmlPId);
+            //新增数据
+            List<WbsTreeContract> addContractNode = collect2.get(pId);
+            if(CollectionUtil.isNotEmpty(addContractNode)){
+                int i = wbsSynchronousEViSaService.insertContractForm(wbsTreeSynchronousRecord, addContractNode, pId);
+                //如果失败  -- - - - - 继续执行   或者把当前节点的p_key_id 记录到某个地方 方便后续处理
+                if (i == 0) {
+                    //这里可以保存到数据库指定错误日志表
+                    //这里可以保存到数据库指定错误日志表
+                } else {
+                    //排序调整
+                    if (wbsTreeSynchronousRecord.getType().contains("7")) {
+                        //获取节点下的当前表单
+                        List<WbsTreeContract> resourceData = wbsTreeContractMapper.selectList(Wrappers.<WbsTreeContract>lambdaQuery()
+                                .select(WbsTreeContract::getPKeyId, WbsTreeContract::getSort)
+                                .eq(WbsTreeContract::getPId, pId)
+                                .eq(WbsTreeContract::getIsDeleted, 0)
+                                .orderByAsc(WbsTreeContract::getSort));
+                        if (CollectionUtil.isNotEmpty(resourceData)) {
+                            for (int j = 0; j < resourceData.size(); j++) {
+                                resourceData.get(j).setSort(j + 1);
+                            }
+                            //修改排序为连续排序
+                            wbsTreeContractMapper.updateSortBatchByPKeyId(resourceData);
+                        }
+                    }
+                }
+            }
+
+            List<WbsTreeContract> list = collect1.get(pId);
+            if(CollectionUtil.isNotEmpty(list)){
+                //历史html 只会在更新数据的时候取记录
+                List<WbsTreeContract> oldHtmlPId = collect3.get(pId);
+                wbsSynchronousEViSaService.updateContract(wbsTreeSynchronousRecord.getType(), pId, wbsTreeSynchronousRecord.getCreateUserId(), list, oldHtmlPId);
+            }
             synchronousRecordMapper.update(null, Wrappers.<WbsTreeSynchronousRecord>lambdaUpdate()
                     .set(WbsTreeSynchronousRecord::getNodeNumEnd, nodeNumEnd)
                     .set(WbsTreeSynchronousRecord::getUpdateTime, DateTime.now())
@@ -952,21 +992,6 @@ public class WbsSynchronousServiceImpl {
                 throw new ServiceException("重置表单路径错误");
             }
 
-            //查询出当前项目所有节点---------------------------------------------------------------------------------------------------
-//            List<WbsTreePrivate> addList = wbsTreePrivateMapper.selectList(Wrappers.<WbsTreePrivate>lambdaQuery()
-//                    .select(WbsTreePrivate::getPKeyId, WbsTreePrivate::getPId)
-//                    .eq(WbsTreePrivate::getIsDeleted, 0)
-//                    .eq(WbsTreePrivate::getProjectId, addData.get(0).getProjectId()));
-//
-//            addList.addAll(addData);
-//            //组合祖级路径 根据当前选中节点为开始
-//            Map<Long, WbsTreePrivate> collect = addList.stream().collect(Collectors.toMap(WbsTreePrivate::getPKeyId, Function.identity()));
-//
-//            addData.forEach(node -> {
-//                String correctAncestors = createAncestorsPId(node, collect);
-//                node.setAncestorsPId(correctAncestors);
-//            });
-
             //新增-----------------------------------------------------------------------------------------------------------------
             Map<Long, List<WbsTreePrivate>> collect = addData.stream().collect(Collectors.groupingBy(WbsTreePrivate::getPId));
             Set<Long> longs = collect.keySet();
@@ -1043,35 +1068,37 @@ public class WbsSynchronousServiceImpl {
      * @param wbsTreeContracts         当前合同节点数据
      * @param addContractNodes         新增节点数据
      */
-    public void insertContractForm(WbsTreeSynchronousRecord wbsTreeSynchronousRecord, ContractInfo contractInfo, List<WbsTreeContract> wbsTreeContracts, List<WbsTreeContract> addContractNodes) {
+    public List<WbsTreeContract> insertContractForm(WbsTreeSynchronousRecord wbsTreeSynchronousRecord, ContractInfo contractInfo, List<WbsTreeContract> wbsTreeContracts, List<WbsTreeContract> addContractNodes, StringBuilder errorMsg) {
         List<WbsTreeContract> addData = new ArrayList<>();
 
 
         if (CollectionUtil.isNotEmpty(addContractNodes)) {
+            //项目级:p_key_id:p_id
+            HashMap<Long, Long> map = new HashMap<>();
+
+
 
             //选给新增的节点赋值
             addContractNodes.forEach(f -> {
+                Long id = SnowFlakeUtil.getId();
+                map.put(id,f.getPId());
+
                 f.setIsTypePrivatePid(f.getPKeyId());
-                f.setPKeyId(SnowFlakeUtil.getId());
+                f.setPKeyId(id);
             });
 
             for (WbsTreeContract addContractNode : addContractNodes) {
                 if (addContractNode.getParentId() == 0) {
                     continue;
                 }
-
-                //查询出当前模板节点的父节点 去获取对应项目节点  如果父节点为0就跳过
-                List<WbsTreeContract> addContractParentNodes = wbsTreeContracts.stream().filter(f -> Objects.equals(f.getTreePId(), addContractNode.getParentId())).collect(Collectors.toList());
-
-                //如果没有数据  就表示这条数据的父节点也时新增节点 就需要从新增节点集合中找父级节点
-                if (addContractParentNodes.isEmpty()) {
-                    addContractParentNodes = addContractNodes.stream().filter(f -> f.getTreePId().equals(addContractNode.getParentId())).collect(Collectors.toList());
-                }
-                //如果现在还找不到当前节点的父节点就表示数据有问题
-                if (addContractParentNodes.isEmpty()) {
-                    //TODO
-                    throw new ServiceException(addContractNode.getNodeName()  + "( " + addContractNode.getPKeyId() + ")-找不到父节点");
+                //新增的数据只有表单,所以找父节点可以直接在合同段中找,如果找不到就说明当前表单的父节点在合同段中不存在 数据有问题
+                List<WbsTreeContract> addContractParentNodes = wbsTreeContracts.stream().filter(f -> Objects.equals(f.getIsTypePrivatePid(), map.get(addContractNode.getPKeyId()))).collect(Collectors.toList());
+                //获取新增数据中的父级节点
+                if (CollectionUtil.isEmpty(addContractParentNodes)) {
+                    errorMsg.append("未在合同段[" + contractInfo.getContractName() + "]找到当前节点父节点-p_key_id(" + map.get(addContractNode.getPKeyId()) + ");");
+                    continue;
                 }
+
                 //当前新增节点的父节点
                 WbsTreeContract parent = addContractParentNodes.get(0);
 
@@ -1093,91 +1120,7 @@ public class WbsSynchronousServiceImpl {
             }
             addData.addAll(addContractNodes);
         }
-
-
-        //查询出当前项目所有节点---------------------------------------------------------------------------------------------------
-//        List<WbsTreeContract> addList = wbsTreeContractMapper.selectList(Wrappers.<WbsTreeContract>lambdaQuery()
-//                .select(WbsTreeContract::getPKeyId, WbsTreeContract::getPId)
-//                .eq(WbsTreeContract::getIsDeleted, 0)
-//                .eq(WbsTreeContract::getContractId, contractInfo.getId()));
-//
-//        addList.addAll(addData);
-//
-//
-//        //组合祖级路径 根据当前选中节点为开始
-//        Map<Long, WbsTreeContract> collect = addList.stream().collect(Collectors.toMap(WbsTreeContract::getPKeyId, Function.identity()));
-//
-//        addData.forEach(node -> {
-//            //通过转换为WbsTreePrivate的方式 去获取祖级节点
-//            String correctAncestors = createAncestorsPId(node, collect);
-//            node.setAncestorsPId(correctAncestors);
-//        });
-
-        //新增-----------------------------------------------------------------------------------------------------------------
-        Map<Long, List<WbsTreeContract>> collect = addData.stream().collect(Collectors.groupingBy(WbsTreeContract::getPId));
-        Set<Long> longs = collect.keySet();
-
-        List<Long> pIds = new ArrayList<>(longs);
-        List<WbsTreeContract> saveData = new ArrayList<>();
-        //按最小节点批量新增
-        List<List<Long>> partition = Lists.partition(pIds, 100);
-        for (List<Long> data : partition) {
-            for (Long pId : data) {
-                List<WbsTreeContract> list = collect.get(pId);
-                //排序调整
-                if (wbsTreeSynchronousRecord.getType().contains("7")) {
-                    list.sort(Comparator.comparingInt(WbsTreeContract::getSort));
-                    //获取节点下的当前表单
-                    List<WbsTreeContract> resourceData = wbsTreeContractMapper.selectList(Wrappers.<WbsTreeContract>lambdaQuery()
-                            .select(WbsTreeContract::getPKeyId, WbsTreeContract::getSort)
-                            .eq(WbsTreeContract::getPId, pId)
-                            .eq(WbsTreeContract::getIsDeleted, 0)
-                            .orderByAsc(WbsTreeContract::getSort));
-                    if (CollectionUtil.isNotEmpty(resourceData)) {
-                        for (int i = 0; i < resourceData.size(); i++) {
-                            resourceData.get(i).setSort(i + 1);
-                        }
-                        //修改排序为连续排序
-                        wbsTreeContractMapper.updateSortBatchByPKeyId(resourceData);
-                    }
-
-
-                    for (WbsTreeContract wbsTreePrivate : list) {
-                        wbsTreeContractMapper.updateSortByPId(pId, wbsTreePrivate.getSort());
-                    }
-                }
-                boolean b = saveData.addAll(list);
-
-
-                //单个批次一个事务,只会回滚当前批次数据
-                Integer i = wbsTreeContractMapper.insertBatchSomeColumn(saveData);
-                //如果失败  -- - - - - 继续执行   或者把当前节点的p_key_id 记录到某个地方 方便后续处理
-                if (i == 0) {
-                    List<Long> collect1 = addData.stream().map(WbsTreeContract::getPKeyId).collect(Collectors.toList());
-                    //这里可以保存到数据库指定错误日志表
-                    //这里可以保存到数据库指定错误日志表
-                    throw new ServiceException("添加失败:" + StringUtil.join(collect1, ","));
-                } else {
-                    //排序调整
-                    if (wbsTreeSynchronousRecord.getType().contains("7")) {
-                        //获取节点下的当前表单
-                        List<WbsTreeContract> resourceData = wbsTreeContractMapper.selectList(Wrappers.<WbsTreeContract>lambdaQuery()
-                                .select(WbsTreeContract::getPKeyId, WbsTreeContract::getSort)
-                                .eq(WbsTreeContract::getPId, pId)
-                                .eq(WbsTreeContract::getIsDeleted, 0)
-                                .orderByAsc(WbsTreeContract::getSort));
-                        if (CollectionUtil.isNotEmpty(resourceData)) {
-                            for (int j = 0; i < resourceData.size(); j++) {
-                                resourceData.get(j).setSort(j + 1);
-                            }
-                            //修改排序为连续排序
-                            wbsTreeContractMapper.updateSortBatchByPKeyId(resourceData);
-                        }
-
-                    }
-                }
-            }
-        }
+        return addData;
     }
 
 

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

@@ -2025,7 +2025,12 @@ public class WbsTreeContractServiceImpl extends BaseServiceImpl<WbsTreeContractM
                                 continue;
                             }
                             //设置实际标高的值
-                            values.set(keys.indexOf(deviationNew), String.join("☆",list));
+                            if(keys.indexOf(deviationNew) > -1){
+                                values.set(keys.indexOf(deviationNew), String.join("☆",list));
+                            }else{
+                                keys.add(deviationNew);
+                                values.add(String.join("☆",list));
+                            }
                         }
 
 

+ 32 - 5
blade-service/blade-meter/src/main/java/org/springblade/meter/service/impl/InterimPayCertificateServiceImpl.java

@@ -25,11 +25,13 @@ import net.logstash.logback.encoder.org.apache.commons.lang3.ObjectUtils;
 import org.springblade.business.entity.Task;
 import org.springblade.business.entity.TaskParallel;
 import org.springblade.common.constant.CommonConstant;
+import org.springblade.common.constant.EVisaConstant;
 import org.springblade.common.utils.CommonUtil;
 import org.springblade.core.log.exception.ServiceException;
 import org.springblade.core.mp.support.Query;
 import org.springblade.core.oss.model.BladeFile;
 import org.springblade.core.tool.utils.Func;
+import org.springblade.evisa.vo.SealStrategyVO;
 import org.springblade.meter.controller.TaskController;
 import org.springblade.meter.entity.InterimPayCertificate;
 import org.springblade.meter.entity.InterimPayCertificateItem;
@@ -52,10 +54,7 @@ import org.springframework.transaction.annotation.Transactional;
 import org.springframework.web.bind.annotation.RequestParam;
 
 import java.io.InputStream;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-import java.util.Map;
+import java.util.*;
 import java.util.stream.Collectors;
 
 /**
@@ -290,7 +289,7 @@ public class InterimPayCertificateServiceImpl extends BaseServiceImpl<InterimPay
                             }
                         }
                     }
-
+                    filterMaps(maps, task.getProjectId());
                     if (Func.isNotEmpty(maps) || maps.size() >= 1) {
                         InputStream ossInputStream = CommonUtil.getOSSInputStream(pdfUrl);
                         String localPdfPath = FileUtils.getSysLocalFileUrl() + "/pdf/" + task.getId() + ".pdf";
@@ -319,4 +318,32 @@ public class InterimPayCertificateServiceImpl extends BaseServiceImpl<InterimPay
         }
         System.out.println("");
     }
+
+    public static void filterMaps(List<Map<String, Object>> maps, Object projectId) {
+        // 1. 统计每个 id 出现的次数
+        Map<Object, Integer> idCountMap = new HashMap<>();
+        for (Map<String, Object> map : maps) {
+            Object id = map.get("id");
+            idCountMap.put(id, idCountMap.getOrDefault(id, 0) + 1);
+        }
+
+        // 2. 找出所有重复的 id(出现次数 > 1)
+        Set<Object> duplicateIds = idCountMap.entrySet().stream()
+                .filter(entry -> entry.getValue() > 1)
+                .map(Map.Entry::getKey)
+                .collect(Collectors.toSet());
+
+        // 3. 遍历 maps,删除重复 id 中 project_id 不等于传入值的记录
+        Iterator<Map<String, Object>> iterator = maps.iterator();
+        while (iterator.hasNext()) {
+            Map<String, Object> map = iterator.next();
+            Object id = map.get("id");
+            Object currentProjectId = map.get("project_id");
+
+            // 如果 id 是重复的,并且 project_id 不等于传入的 projectId,则删除
+            if (duplicateIds.contains(id) && !Objects.equals(currentProjectId+"", projectId)) {
+                iterator.remove();
+            }
+        }
+    }
 }

+ 23 - 0
blade-service/blade-user/src/main/java/org/springblade/system/user/bean/CyGetToken.java

@@ -0,0 +1,23 @@
+package org.springblade.system.user.bean;
+
+import lombok.Data;
+
+/**
+ * 成渝单点登录获取token请求参数
+ * @author LHB
+ */
+@Data
+public class CyGetToken {
+    /**
+     * 获取公钥接口中返回的随机字符
+     */
+    private String uuid;
+    /**
+     * 使用公钥接口中返回的公钥对身份证进行加密,第三方系统需要使用公钥对应的私钥进行解密。
+     */
+    private String idcard;
+    /**
+     * 使用公钥接口中返回的公钥对身份证进行加密,第三方系统需要使用公钥对应的私钥进行解密。
+     */
+    private String mobile;
+}

+ 35 - 0
blade-service/blade-user/src/main/java/org/springblade/system/user/bean/ResultCYData.java

@@ -0,0 +1,35 @@
+package org.springblade.system.user.bean;
+
+import lombok.Data;
+
+/**
+ * @author LHB
+ */
+@Data
+public class ResultCYData<T> {
+    private Integer code;
+    private T data;
+    private String msg;
+
+    public static <T> ResultCYData<T> data(T data){
+        ResultCYData resultCYKey = new ResultCYData();
+        resultCYKey.setCode(200);
+        resultCYKey.setData(data);
+        resultCYKey.setMsg("");
+        return resultCYKey;
+    }
+
+    public static ResultCYData fail(String msg){
+        ResultCYData resultCYKey = new ResultCYData();
+        resultCYKey.setCode(400);
+        resultCYKey.setMsg(msg);
+        return resultCYKey;
+    }
+
+    public static ResultCYData fail(Integer code,String msg){
+        ResultCYData resultCYKey = new ResultCYData();
+        resultCYKey.setCode(code);
+        resultCYKey.setMsg(msg);
+        return resultCYKey;
+    }
+}

+ 37 - 0
blade-service/blade-user/src/main/java/org/springblade/system/user/bean/ResultCYKey.java

@@ -0,0 +1,37 @@
+package org.springblade.system.user.bean;
+
+import lombok.Data;
+
+/**
+ * @author LHB
+ */
+@Data
+public class ResultCYKey {
+    private Integer code;
+    /**
+     * 随机字符
+     */
+    private String uuid;
+    /**
+     * 公钥
+     */
+    private String pk;
+    private String msg;
+
+
+    public static ResultCYKey success(String uuid,String pk){
+        ResultCYKey resultCYKey = new ResultCYKey();
+        resultCYKey.setCode(200);
+        resultCYKey.setUuid(uuid);
+        resultCYKey.setPk(pk);
+        resultCYKey.setMsg("公钥有效期为5分组,请尽快通过公钥获取token");
+        return resultCYKey;
+    }
+
+    public static ResultCYKey fail(String msg){
+        ResultCYKey resultCYKey = new ResultCYKey();
+        resultCYKey.setCode(400);
+        resultCYKey.setMsg(msg);
+        return resultCYKey;
+    }
+}

+ 151 - 20
blade-service/blade-user/src/main/java/org/springblade/system/user/controller/UserController.java

@@ -17,22 +17,16 @@
 package org.springblade.system.user.controller;
 
 
-import cn.hutool.jwt.JWT;
-import cn.hutool.jwt.JWTUtil;
 import com.alibaba.fastjson.JSON;
-import com.alibaba.fastjson.JSONArray;
 import com.alibaba.fastjson.JSONObject;
 import com.alibaba.nacos.common.utils.MD5Utils;
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
-import feign.Request;
-import io.jsonwebtoken.Claims;
 import io.swagger.annotations.*;
 import lombok.AllArgsConstructor;
 import org.apache.http.Consts;
-import org.apache.http.HttpRequest;
 import org.apache.http.HttpResponse;
 import org.apache.http.NameValuePair;
 import org.apache.http.client.HttpClient;
@@ -43,7 +37,6 @@ import org.apache.http.impl.client.HttpClientBuilder;
 import org.apache.http.message.BasicNameValuePair;
 import org.springblade.common.cache.CacheNames;
 import org.springblade.common.constant.CommonConstant;
-import org.springblade.common.utils.SnowFlakeUtil;
 import org.springblade.core.cache.utils.CacheUtil;
 import org.springblade.core.excel.util.ExcelUtil;
 import org.springblade.core.mp.support.Condition;
@@ -58,26 +51,21 @@ import org.springblade.core.tool.constant.BladeConstant;
 import org.springblade.core.tool.constant.RoleConstant;
 import org.springblade.core.tool.utils.*;
 import org.springblade.manager.dto.SaveUserInfoByProjectDTO;
-import org.springblade.manager.entity.ContractInfo;
-import org.springblade.manager.entity.TextdictInfo;
-import org.springblade.manager.entity.WbsTreeContract;
-import org.springblade.manager.entity.WbsTreePrivate;
 import org.springblade.manager.feign.SaveUserInfoByProjectClient;
 import org.springblade.system.cache.ParamCache;
+import org.springblade.system.user.bean.CyGetToken;
+import org.springblade.system.user.bean.ResultCYData;
+import org.springblade.system.user.bean.ResultCYKey;
 import org.springblade.system.user.dto.UserDTO;
 import org.springblade.system.user.entity.User;
 import org.springblade.system.user.excel.UserExcel;
 import org.springblade.system.user.excel.UserExcel2;
 import org.springblade.system.user.excel.UserImporter;
 import org.springblade.system.user.service.IUserService;
-import org.springblade.system.user.util.AesInfoUtil;
-import org.springblade.system.user.vo.DeptUserVO;
+import org.springblade.system.user.util.RsaUtils;
 import org.springblade.system.user.vo.UserVO;
 import org.springblade.system.user.wrapper.UserWrapper;
-import org.springframework.jdbc.core.BeanPropertyRowMapper;
 import org.springframework.jdbc.core.JdbcTemplate;
-import org.springframework.jdbc.core.RowMapper;
-import org.springframework.scheduling.annotation.Scheduled;
 import org.springframework.web.bind.annotation.*;
 import org.springframework.web.multipart.MultipartFile;
 import springfox.documentation.annotations.ApiIgnore;
@@ -88,9 +76,6 @@ import javax.validation.Valid;
 import java.io.ByteArrayOutputStream;
 import java.io.IOException;
 import java.io.InputStream;
-import java.io.UnsupportedEncodingException;
-import java.net.URLDecoder;
-import java.text.ParseException;
 import java.util.*;
 
 import static org.springblade.core.cache.constant.CacheConstant.USER_CACHE;
@@ -586,7 +571,7 @@ public class UserController {
         System.out.println("密码" + md5Pass);
 
         HttpClient httpClient = HttpClientBuilder.create().build();
-        String url = "http://user.hcxxy.com:8090/blade-auth/oauth/token";
+        String url = "http://localhost:8090/blade-auth/oauth/token";
         String sys_isonline = ParamCache.getValue(CommonConstant.SYS_ISONLINE);
         if("20".equals(sys_isonline)){
             url = "http://152.168.2.11:8090/blade-auth/oauth/token";
@@ -620,4 +605,150 @@ public class UserController {
         return R.fail("获取token失败");
     }
 
+    /**
+     * 成渝第三方登录接口 获取私钥
+     */
+    /**
+     * 获取公钥key
+     * @return
+     */
+    @GetMapping("/getPk")
+    public ResultCYKey getPublicKey(String appKey){
+        if(StringUtil.isBlank(appKey)){
+            return ResultCYKey.fail("授权码为空");
+        }
+
+        String sql = "select count(0) from blade_param where param_key = 'appKey' and param_value = '" + appKey + "' and is_deleted = 0";
+        //后管配置appKey
+        Integer localAppKey = jdbcTemplate.queryForObject(sql, Integer.class);
+        if(localAppKey == 0){
+            return ResultCYKey.fail("授权码未知");
+        }
+        //判断appKey是否为指定值
+        try {
+            String uuid = UUID.randomUUID().toString().trim().replaceAll("-", "");
+            //生成rsa公钥私钥
+            Map<String, String> keyPair = RsaUtils.createKeyPair();
+            bladeRedis.setEx("cy_public_key:"+uuid, keyPair, 300L);
+            return ResultCYKey.success(uuid,keyPair.get("pk"));
+        } catch (Exception e) {
+            return ResultCYKey.fail("生成公钥失败");
+        }
+    }
+    /**
+     * 成渝 获取质检 token
+     * @return
+     */
+    @PostMapping("/getQualityTestingToken")
+    public ResultCYData getQualityTestingToken(@RequestBody CyGetToken cyGetToken, HttpServletRequest request){
+        if(cyGetToken == null){
+            return ResultCYData.fail("参数不能为空");
+        }
+        if(StringUtil.isBlank(cyGetToken.getUuid())){
+            return ResultCYData.fail("随机字符不能为空");
+        }
+        if(StringUtil.isBlank(cyGetToken.getMobile())){
+            return ResultCYData.fail("手机号码(密文)不能为空");
+        }
+
+        Map<String, String> keyPair = bladeRedis.get("cy_public_key:" + cyGetToken.getUuid());
+        if(keyPair == null){
+            return ResultCYData.fail("uuid 未知/已过期");
+        }
+        //私钥
+        String sk = keyPair.get("sk");
+
+        //手机号
+        String mobile = RsaUtils.decryptWithSk(cyGetToken.getMobile(), sk);
+
+        //掉用获取token接口
+        R r = loginByToken3(mobile, 1, request);
+        if(r.isSuccess()){
+            return ResultCYData.data(r.getData());
+        } else {
+            if(r.getMsg().equals("用户名或密码错误")){
+                return ResultCYData.fail(451,"用户不存在");
+            }
+            return ResultCYData.fail(r.getMsg());
+        }
+    }
+
+    /**
+     * 成渝 获取档案 token
+     * @return
+     */
+    @PostMapping("/getArchiveToken")
+    public ResultCYData getArchiveToken(@RequestBody CyGetToken cyGetToken, HttpServletRequest request){
+        if(cyGetToken == null){
+            return ResultCYData.fail("参数不能为空");
+        }
+        if(StringUtil.isBlank(cyGetToken.getUuid())){
+            return ResultCYData.fail("随机字符不能为空");
+        }
+        if(StringUtil.isBlank(cyGetToken.getMobile())){
+            return ResultCYData.fail("手机号码(密文)不能为空");
+        }
+
+        Map<String, String> keyPair = bladeRedis.get("cy_public_key:" + cyGetToken.getUuid());
+        if(keyPair == null){
+            return ResultCYData.fail("uuid 未知/已过期");
+        }
+        //私钥
+        String sk = keyPair.get("sk");
+
+        //手机号
+        String mobile = RsaUtils.decryptWithSk(cyGetToken.getMobile(), sk);
+
+        //掉用获取token接口
+        R r = loginByToken3(mobile, 3, request);
+        if(r.isSuccess()){
+            return ResultCYData.data(r.getData());
+        } else {
+            if(r.getMsg().equals("用户名或密码错误")){
+                return ResultCYData.fail(451,"用户不存在");
+            }
+            return ResultCYData.fail(r.getMsg());
+        }
+    }
+
+
+
+    /**
+     * 成渝获取token接口
+     * @param account
+     * @param userType 1-质检,3-档案
+     * @param request
+     * @return
+     */
+    public R loginByToken3(String account, Integer userType, HttpServletRequest request) {
+        if(account==null || Func.isNull(account) || Func.isEmpty(account)){
+            return R.fail("account值不能为空");
+        }
+        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
+        queryWrapper.eq("account", account);
+        queryWrapper.eq("sys_type", 2);
+        User userInfo = userService.getOne(queryWrapper);
+        if (userInfo == null) {
+            return R.fail("用户名或密码错误");
+        }
+
+        String Authorization = request.getHeader("Authorization");
+
+        if (Authorization == null || StringUtil.isEmpty(Authorization)) {
+            String dataInfo = "";
+            if(userType == 1){ //质量/试验平台
+                dataInfo ="client:client_secret";
+            }else if(userType == 3){ //档案平台"
+                dataInfo ="archives:archives_secret";
+            }
+            Authorization = "Basic "+Func.encodeBase64(dataInfo);
+            //Basic bWVhc3VyZTptZWFzdXJlX3NlY3JldA==
+            //Basic bWVhc3VyZTptZWFzdXJlX3NlY3JldA==
+            R loginInfo = this.getLoginInfo(Authorization, userInfo);
+            if(loginInfo.getCode()==200){
+                return loginInfo;
+            }
+        }
+        return this.getLoginInfo(Authorization, userInfo);
+    }
 }

+ 62 - 45
blade-service/blade-user/src/main/java/org/springblade/system/user/util/RsaUtils.java

@@ -1,5 +1,7 @@
 package org.springblade.system.user.util;
 
+import sun.misc.BASE64Encoder;
+
 import javax.crypto.Cipher;
 import java.nio.charset.StandardCharsets;
 import java.security.KeyFactory;
@@ -13,6 +15,7 @@ import java.security.spec.X509EncodedKeySpec;
 import java.util.Base64;
 import java.util.HashMap;
 import java.util.Map;
+import java.util.UUID;
 
 public final class RsaUtils {
     /**
@@ -159,51 +162,65 @@ public final class RsaUtils {
         }
     }
 
-    /*private static void testCreateKeyPair() {
-        //生成公钥和私钥
-        Map<String, String> keyMap = createKeyPair();
-        //加密字符串
-        long temp = System.currentTimeMillis();
-        System.out.println("公钥:" + keyMap.get("pk"));
-        System.out.println("私钥:" + keyMap.get("sk"));
-        System.out.println("生成密钥消耗时间:" + (System.currentTimeMillis() - temp) / 1000.0 + "秒");
-
-        String message = "RSA测试aaa";
-        System.out.println("原文:" + message);
-        System.out.println("--------------------------------------");
-        temp = System.currentTimeMillis();
-        String messagePEn = encryptWithPk(message, keyMap.get("pk"));
-        System.out.println("密文:" + messagePEn);
-        System.out.println("加密消耗时间:" + (System.currentTimeMillis() - temp) / 1000.0 + "秒");
-
-        temp = System.currentTimeMillis();
-        String messageSDe = decryptWithSk(messagePEn, keyMap.get("sk"));
-        System.out.println("解密:" + messageSDe);
-        System.out.println("解密消耗时间:" + (System.currentTimeMillis() - temp) / 1000.0 + "秒");
-        System.out.println("--------------------------------------");
-
-        temp = System.currentTimeMillis();
-        String messageSEn = encryptWithSk(message, keyMap.get("sk"));
-        System.out.println("密文:" + messageSEn);
-        System.out.println("加密消耗时间:" + (System.currentTimeMillis() - temp) / 1000.0 + "秒");
-
-        temp = System.currentTimeMillis();
-        String messagePDe = decryptWithPk(messageSEn, keyMap.get("pk"));
-        System.out.println("解密:" + messagePDe);
-        System.out.println("解密消耗时间:" + (System.currentTimeMillis() - temp) / 1000.0 + "秒");
-    }
+//    private static void testCreateKeyPair() {
+//        //生成公钥和私钥
+//        Map<String, String> keyMap = createKeyPair();
+//        //加密字符串
+//        long temp = System.currentTimeMillis();
+//        System.out.println("公钥:" + keyMap.get("pk"));
+//        System.out.println("私钥:" + keyMap.get("sk"));
+//        System.out.println("生成密钥消耗时间:" + (System.currentTimeMillis() - temp) / 1000.0 + "秒");
+//
+//        String message = "lihb";
+//        System.out.println("原文:" + message);
+//        System.out.println("--------------------------------------");
+//        temp = System.currentTimeMillis();
+//        String messagePEn = encryptWithPk(message, keyMap.get("pk"));
+//        System.out.println("密文:" + messagePEn);
+//        System.out.println("加密消耗时间:" + (System.currentTimeMillis() - temp) / 1000.0 + "秒");
+//
+//        temp = System.currentTimeMillis();
+//        String messageSDe = decryptWithSk(messagePEn, keyMap.get("sk"));
+//        System.out.println("解密:" + messageSDe);
+//        System.out.println("解密消耗时间:" + (System.currentTimeMillis() - temp) / 1000.0 + "秒");
+//        System.out.println("--------------------------------------");
+//
+//        temp = System.currentTimeMillis();
+//        String messageSEn = encryptWithSk(message, keyMap.get("sk"));
+//        System.out.println("密文:" + messageSEn);
+//        System.out.println("加密消耗时间:" + (System.currentTimeMillis() - temp) / 1000.0 + "秒");
+//
+//        temp = System.currentTimeMillis();
+//        String messagePDe = decryptWithPk(messageSEn, keyMap.get("pk"));
+//        System.out.println("解密:" + messagePDe);
+//        System.out.println("解密消耗时间:" + (System.currentTimeMillis() - temp) / 1000.0 + "秒");
+//    }
+
+    // 定义授权码字符集(62个字符:0-9, A-Z, a-z)
+    private static final String CHAR_SET =
+        "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
+    // 线程安全的SecureRandom实例
+    private static final SecureRandom random = new SecureRandom();
+
+    public static String generateAuthCode() {
+        StringBuilder sb = new StringBuilder(16);
+
+        // 生成8位随机字符
+        for (int i = 0; i < 16; i++) {
+            // 从字符集中随机选取一个字符
+            int randomIndex = random.nextInt(CHAR_SET.length());
+            char randomChar = CHAR_SET.charAt(randomIndex);
+            sb.append(randomChar);
+        }
 
-    public static void main(String[] args) throws Exception {
-        testCreateKeyPair();
-        String pk = "MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBALZL9pOjNpDs1wu15o8xmoeNg4YGCUO5zoLrKiGlmFl7\\r\\nCKXKwJ83pDmu/bE4Szf2RAyzwr33bViqoNH45/EaCrECAwEAAQ==\\r\\n";
-        System.out.println(encryptWithPk("admin", pk));
-        System.out.println(encryptWithPk("admin123", pk));
-
-        String str1 = Base64.getEncoder().encodeToString(pk.getBytes());
-        String str2 = (new BASE64Encoder()).encodeBuffer(pk.getBytes());
-        System.out.println("# " + str1);
-        System.out.println("# " + str2);
-        System.out.println(str1.equals(str2));
-    }*/
+        return sb.toString();
+    }
+    public static void testmain(String[] args) throws Exception {
+        System.out.println("授权码示例: " + generateAuthCode());
+        String uuid = UUID.randomUUID().toString().trim().replaceAll("-", "");
+        System.out.println(uuid);
+        String s = encryptWithPk("13709467119", "MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAI0Uny+3+OS9ZeO0jERNhnztulQC1tgbJS2+mYk3c8BjG2yi3sDl+JbJ7VgfVV86xZ/BJwTQk07soFBe4RfLhs0CAwEAAQ==");
+        System.out.println(s);
+    }
 
 }