Explorar el Código

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

# Conflicts:
#	blade-service-api/blade-archive-api/src/main/java/org/springblade/archive/entity/ScanFile.java
#	blade-service/blade-archive/src/main/java/org/springblade/archive/controller/ArchivesAutoController.java
#	blade-service/blade-archive/src/main/java/org/springblade/archive/controller/ScanFileController.java
#	blade-service/blade-archive/src/main/java/org/springblade/archive/mapper/ScanFileMapper.java
#	blade-service/blade-archive/src/main/java/org/springblade/archive/mapper/ScanFileMapper.xml
#	blade-service/blade-archive/src/main/java/org/springblade/archive/service/ScanFileService.java
#	blade-service/blade-archive/src/main/java/org/springblade/archive/service/impl/ScanFileServiceImpl.java
#	blade-service/blade-business/src/main/java/org/springblade/business/controller/InformationWriteQueryController.java
#	blade-service/blade-business/src/main/java/org/springblade/business/mapper/ArchiveFileMapper.xml
#	blade-service/blade-business/src/main/java/org/springblade/business/service/impl/InformationQueryServiceImpl.java
cr hace 2 semanas
padre
commit
99ab9943ed
Se han modificado 23 ficheros con 597 adiciones y 88 borrados
  1. 14 0
      blade-service-api/blade-archive-api/src/main/java/org/springblade/archive/dto/ScanFileMoveDTO.java
  2. 2 0
      blade-service-api/blade-archive-api/src/main/java/org/springblade/archive/entity/ScanFile.java
  3. 3 0
      blade-service-api/blade-business-api/src/main/java/org/springblade/business/feign/ArchiveFileClient.java
  4. 41 0
      blade-service-api/blade-business-api/src/main/java/org/springblade/business/vo/ChekPdfVo.java
  5. 49 20
      blade-service/blade-archive/src/main/java/org/springblade/archive/controller/ArchivesAutoController.java
  6. 10 2
      blade-service/blade-archive/src/main/java/org/springblade/archive/controller/ScanFileController.java
  7. 1 1
      blade-service/blade-archive/src/main/java/org/springblade/archive/mapper/ScanFileMapper.java
  8. 4 0
      blade-service/blade-archive/src/main/java/org/springblade/archive/mapper/ScanFileMapper.xml
  9. 10 0
      blade-service/blade-archive/src/main/java/org/springblade/archive/service/IArchivesAutoService.java
  10. 3 1
      blade-service/blade-archive/src/main/java/org/springblade/archive/service/ScanFileService.java
  11. 9 2
      blade-service/blade-archive/src/main/java/org/springblade/archive/service/impl/ArchiveNameServiceImpl.java
  12. 173 4
      blade-service/blade-archive/src/main/java/org/springblade/archive/service/impl/ArchivesAutoServiceImpl.java
  13. 62 4
      blade-service/blade-archive/src/main/java/org/springblade/archive/service/impl/ScanFileServiceImpl.java
  14. 4 5
      blade-service/blade-business/src/main/java/org/springblade/business/controller/InformationWriteQueryController.java
  15. 5 0
      blade-service/blade-business/src/main/java/org/springblade/business/feignClient/ArchiveFileClientImpl.java
  16. 3 2
      blade-service/blade-business/src/main/java/org/springblade/business/mapper/ArchiveFileMapper.xml
  17. 15 3
      blade-service/blade-business/src/main/java/org/springblade/business/service/impl/ArchiveFileServiceImpl.java
  18. 1 1
      blade-service/blade-business/src/main/java/org/springblade/business/service/impl/InformationQueryServiceImpl.java
  19. 1 0
      blade-service/blade-business/src/main/java/org/springblade/business/service/impl/TrialSelfInspectionRecordServiceImpl.java
  20. 6 3
      blade-service/blade-e-visa/src/main/java/org/springblade/evisa/controller/ChekSignData.java
  21. 4 4
      blade-service/blade-e-visa/src/main/java/org/springblade/evisa/service/impl/EVDataServiceImpl.java
  22. 167 34
      blade-service/blade-e-visa/src/main/java/org/springblade/evisa/service/impl/ScrDataServiceImpl.java
  23. 10 2
      blade-service/blade-e-visa/src/main/java/org/springblade/evisa/utils/PdfAddimgUtil.java

+ 14 - 0
blade-service-api/blade-archive-api/src/main/java/org/springblade/archive/dto/ScanFileMoveDTO.java

@@ -0,0 +1,14 @@
+package org.springblade.archive.dto;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.util.List;
+@Data
+@AllArgsConstructor
+@NoArgsConstructor
+public class ScanFileMoveDTO {
+   private List<Long> ids;
+   private Long nodeId;
+}

+ 2 - 0
blade-service-api/blade-archive-api/src/main/java/org/springblade/archive/entity/ScanFile.java

@@ -47,4 +47,6 @@ public class ScanFile {
     private String responsible;
     @ApiModelProperty(value = "是否删除")
     private Integer isDeleted;
+    @ApiModelProperty(value = "是否移动")
+    private Integer isMove;
 }

+ 3 - 0
blade-service-api/blade-business-api/src/main/java/org/springblade/business/feign/ArchiveFileClient.java

@@ -175,4 +175,7 @@ public interface ArchiveFileClient {
 
     @PostMapping(API_PREFIX + "/getAllArchiveFileByIds")
     List<ArchiveFile> getAllArchiveFileByIds(@RequestBody List<String> strList);
+
+    @PostMapping(API_PREFIX + "/saveBatchArchiveFile")
+    void saveBatchArchiveFile(@RequestBody List<ArchiveFile> list);
 }

+ 41 - 0
blade-service-api/blade-business-api/src/main/java/org/springblade/business/vo/ChekPdfVo.java

@@ -0,0 +1,41 @@
+/*
+ *      Copyright (c) 2018-2028, Chill Zhuang All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are met:
+ *
+ *  Redistributions of source code must retain the above copyright notice,
+ *  this list of conditions and the following disclaimer.
+ *  Redistributions in binary form must reproduce the above copyright
+ *  notice, this list of conditions and the following disclaimer in the
+ *  documentation and/or other materials provided with the distribution.
+ *  Neither the name of the dreamlu.net developer nor the names of its
+ *  contributors may be used to endorse or promote products derived from
+ *  this software without specific prior written permission.
+ *  Author: Chill 庄骞 (smallchill@163.com)
+ */
+package org.springblade.business.vo;
+
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+/**
+ * 视图实体类
+ *
+ * @author BladeX
+ * @since 2022-07-08
+ */
+@Data
+public class ChekPdfVo {
+    private static final long serialVersionUID = 1L;
+
+
+    @ApiModelProperty("1:节点添加 2:文件添加")
+    private String type;
+
+    @ApiModelProperty("ids")
+    private String ids;
+
+    @ApiModelProperty("1施工2监理")
+    private String classify;
+}

+ 49 - 20
blade-service/blade-archive/src/main/java/org/springblade/archive/controller/ArchivesAutoController.java

@@ -592,7 +592,33 @@ public class ArchivesAutoController extends BladeController {
 	 * @return
 	 */
 	@PostMapping("/archiveAutoMethod")
-	public R archiveAutoMethod(Long projectId,Long contractId,Long nodeId) {
+	public R archiveAutoMethod(Long projectId, Long contractId, Long nodeId,
+							   @RequestParam(required = false) String childNodeIds) {
+		List<Long> childNodes = null;
+		if (StringUtils.isNotBlank(childNodeIds)) {
+			childNodes = Arrays.stream(childNodeIds.split(","))
+					.map(String::trim)
+					.filter(s -> !s.isEmpty())
+					.map(Long::valueOf)
+					.collect(Collectors.toList());
+		}
+		return archiveAutoMethod(projectId, contractId, nodeId, childNodes);
+	}
+
+	/**
+	 * 自动组卷入口(带childNodes参数)
+	 * projectId 为当前项目
+	 * contractId 为客户端当前选定的合同段
+	 * nodeId 为左侧树选定的节点id
+	 * childNodes 为指定的子节点列表,用于过滤
+	 * @param projectId
+	 * @param contractId
+	 * @param nodeId
+	 * @param childNodes
+	 * @return
+	 */
+	@PostMapping("/archiveAutoMethodWithChildNodes")
+	public R archiveAutoMethod(Long projectId,Long contractId,Long nodeId, @RequestParam(required = false) List<Long> childNodes) {
 		try{
 			//先验证当前项目是否在自动组卷中,组卷中直接返回
 			//ProjectInfo projectInfo = projectClient.getById(String.valueOf(projectId));
@@ -610,7 +636,7 @@ public class ArchivesAutoController extends BladeController {
 			//设置自动组卷中
 			contractClient.updateIsArchivesAutoById(contractId,1);
 
-			archivesAutoService.archiveAutoMethodThread(projectId,contractId,nodeId,traceId);
+			archivesAutoService.archiveAutoMethodThread(projectId,contractId,nodeId,traceId, childNodes);
 			return R.data("开始自动组卷中,请耐心等待");
 		}catch (Exception e){
 			e.printStackTrace();
@@ -625,21 +651,15 @@ public class ArchivesAutoController extends BladeController {
 	@ApiOperationSupport(order = 13)
 	@ApiOperation(value = "重新生成案卷", notes = "传入ids")
 	@Transactional
-	public R reCreateArchiveAuto(@ApiParam(value = "主键集合", required = true) @RequestParam String ids,@ApiParam(value = "合并后的文件题目", required = true)String name){
-		//先查出勾选的案卷
-		List<ArchivesAuto> archivesAutoList=archivesAutoService.listByIds(Func.toLongList(ids));
-//		if(archivesAutoList.size()<=1){
-//			return R.fail("请选择多个案卷进行合并");
-//		}
-		//查出所有案卷文件
-		List<ArchiveFile>archiveFileList=new ArrayList<>();
-		List<Long> longList = Func.toLongList(ids);
-		for (Long id : longList) {
-			archiveFileList.addAll(archiveFileClient.getArchiveFileByArchiveIds(id+""));
-		}
-		//根据档号后缀排序 拿到第一个
-		ArchivesAuto auto = archivesAutoList.get(0);
-		if(longList.size()>1){
+	public R reCreateArchiveAuto(@ApiParam(value = "主键集合", required = true) @RequestParam String ids,@ApiParam(value = "合并后的文件题目", required = true)String name,Integer type){
+		if(type==1){
+			//先查出勾选的案卷
+			List<ArchivesAuto> archivesAutoList=archivesAutoService.listByIds(Func.toLongList(ids));
+			if(archivesAutoList.size()<=1){
+				return R.fail("请选择多个案卷进行合并");
+			}
+			//根据档号后缀排序 拿到第一个
+			ArchivesAuto auto = archivesAutoList.get(0);
 			archivesAutoList.sort(Comparator.comparingInt(a -> {
 				String fileNumber = a.getFileNumber();
 				if (fileNumber == null || fileNumber.isEmpty()) {
@@ -664,6 +684,12 @@ public class ArchivesAutoController extends BladeController {
 			}));
 			//将除第一个以外的案卷文件archiveId 设置成第一个的id
 			List<ArchiveFile>updateArchiveFileList=new ArrayList<>();
+			//查出所有案卷文件
+			List<ArchiveFile>archiveFileList=new ArrayList<>();
+			List<Long> longList = Func.toLongList(ids);
+			for (Long id : longList) {
+				archiveFileList.addAll(archiveFileClient.getArchiveFileByArchiveIds(id+""));
+			}
 			int i=1;
 			for (ArchiveFile file : archiveFileList) {
 				if (!file.getArchiveId().equals(auto.getId())) {
@@ -677,10 +703,13 @@ public class ArchivesAutoController extends BladeController {
 			//删除其他案卷
 			archivesAutoList.remove(auto);
 			archivesAutoService.deleteLogic(archivesAutoList.stream().map(o->o.getId()).collect(Collectors.toList()));
+			//设置案卷页码和四要素
+			archivesAutoService.reCreateArchiveAuto(auto, archiveFileList);
+			return R.status(true);
+		}else {
+			archivesAutoService.reCreateArchiveAuto1(ids);
+			return R.success("正在重组,请稍后查看");
 		}
-		//设置案卷页码和四要素
-		archivesAutoService.reCreateArchiveAuto(auto, archiveFileList);
-		return R.status(true);
 	}
 
 	@PostMapping("/creatFileNameFormAI")

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

@@ -6,6 +6,7 @@ import io.swagger.annotations.ApiImplicitParam;
 import io.swagger.annotations.ApiImplicitParams;
 import io.swagger.annotations.ApiOperation;
 import lombok.AllArgsConstructor;
+import org.springblade.archive.dto.ScanFileMoveDTO;
 import org.springblade.archive.entity.ScanFile;
 import org.springblade.archive.entity.ScanFolder;
 import org.springblade.archive.service.ScanFileService;
@@ -116,8 +117,8 @@ public class ScanFileController {
     @GetMapping("/getScanFile")
     @ApiOperation("获取扫描文件")
     @ApiImplicitParams({@ApiImplicitParam(name = "contractId", value = "合同ID"),@ApiImplicitParam(name = "projectId", value = "项目ID"),@ApiImplicitParam(name = "folderId", value = "文件夹ID"),@ApiImplicitParam(name = "query", value = "查询参数")})
-    public R<IPage<ScanFile>> getScanFile(Long contractId, Long projectId, Long folderId, Query query){
-        IPage<ScanFile> page=scanFileService.getScanFile(contractId,projectId,folderId,query);
+    public R<IPage<ScanFile>> getScanFile(Long contractId, Long projectId, Long folderId, Query query,Integer move){
+        IPage<ScanFile> page=scanFileService.getScanFile(contractId,projectId,folderId,query,move);
         return R.data(page);
     }
     @GetMapping("/getDetil")
@@ -165,6 +166,13 @@ public class ScanFileController {
        return R.status(scanFileService.autoRecognize(ids));
     }
 
+    @PostMapping("/moveScanFile")
+    @ApiOperation("移动文件")
+    @ApiImplicitParams({@ApiImplicitParam(name = "ids", value = "文件IDs"),@ApiImplicitParam(name = "nodeId", value = "目标文件夹ID") })
+    public R moveScanFile(@RequestBody ScanFileMoveDTO dto){
+        return R.status(scanFileService.moveScanFile(dto.getIds(),dto.getNodeId()));
+    }
+
 
 
 }

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

@@ -20,7 +20,7 @@ public interface ScanFileMapper extends BaseMapper<ScanFile> {
 
     List<ScanFolder> getScanFolder(@Param("contractId") Long contractId, @Param("projectId") Long projectId);
 
-    IPage<ScanFile> getScanFile(IPage<ScanFile> page, @Param("contractId") Long contractId, @Param("projectId") Long projectId, @Param("folderId") Long folderId);
+    IPage<ScanFile> getScanFile(IPage<ScanFile> page, @Param("contractId") Long contractId, @Param("projectId") Long projectId, @Param("folderId") Long folderId,@Param("move")Integer  move);
 
     void removeScan(@Param("longList") List<Long> longList);
 }

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

@@ -22,5 +22,9 @@
     </select>
     <select id="getScanFile" resultType="org.springblade.archive.entity.ScanFile">
         select * from scan_file where project_id = #{projectId} and contract_id = #{contractId} and folder_id = #{folderId} and is_deleted = 0
+        <if test="move!= null">
+            and is_move = #{move}
+        </if>
+        order by digital_num
     </select>
 </mapper>

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

@@ -76,8 +76,14 @@ public interface IArchivesAutoService extends BaseService<ArchivesAuto> {
 
 	void archiveAutoMethod(Long project,Long contractId,Long nodeId,Long traceId);
 
+	void archiveAutoMethod(Long project,Long contractId,Long nodeId,Long traceId,List<Long> childNodes);
+
+	void archiveAutoMethodThread(Long projectId, Long contractId, Long nodeId, Long traceId, List<Long> childNodes);
+
 	void splitArchvies(Long project,Long contractId,Long nodeId);
 
+	void splitArchvies(Long project,Long contractId,Long nodeId,List<Long> childNodes);
+
 	public String getMergeArchivesFile(Long archiveId);
 
 	//拆卷
@@ -90,6 +96,8 @@ public interface IArchivesAutoService extends BaseService<ArchivesAuto> {
 	//刷新某个项目的档号
 	void refreshFileNumberNoSlipt(Long projectId,Long contractId,Long nodeId,boolean bforce, Long traceId);
 
+	void refreshFileNumberNoSlipt(Long projectId,Long contractId,Long nodeId,boolean bforce, Long traceId,List<Long> childNodes);
+
 	void test666();
 
     List<DictBiz> getCarrierTypeByDict();
@@ -177,4 +185,6 @@ public interface IArchivesAutoService extends BaseService<ArchivesAuto> {
 	List<Long> getArchiveIdsByNodes(List<Long> ids);
 
 	void reomoveArchiveAndFile(List<Long> archiveIds);
+
+    void reCreateArchiveAuto1(String ids);
 }

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

@@ -21,9 +21,11 @@ public interface ScanFileService extends IService<ScanFile> {
 
     List<ScanFolderVO> getScanFolder(Long contractId, Long projectId);
 
-    IPage<ScanFile> getScanFile(Long contractId, Long projectId, Long folderId, Query query);
+    IPage<ScanFile> getScanFile(Long contractId, Long projectId, Long folderId, Query query,Integer move);
 
     String deleteScanFile(String ids);
 
     Boolean autoRecognize(String ids);
+
+    boolean moveScanFile(List<Long> ids, Long nodeId);
 }

+ 9 - 2
blade-service/blade-archive/src/main/java/org/springblade/archive/service/impl/ArchiveNameServiceImpl.java

@@ -283,7 +283,11 @@ public class ArchiveNameServiceImpl implements IArchiveNameService {
                                 }
                             }
 
-                            if (allGroupsFullyCovered && useCovering) {
+                            // 检查祖父节点是否为单位工程,如果是则跳过此处理
+                            boolean isUnitProject = grandParentNode.getExtNodeType() != null && 
+                                                  grandParentNode.getExtNodeType() == 1;
+                            
+                            if (allGroupsFullyCovered && useCovering && !isUnitProject) {
                                 nameParts.add(getLevelName(hierarchy, grandParentId));
                                 canUseGrandParentName = true;
                             }
@@ -316,8 +320,11 @@ public class ArchiveNameServiceImpl implements IArchiveNameService {
                 List<ArchiveTreeContract> allChildren = hierarchy.getChildren(groupId);
                 int childrenCount = (allChildren != null) ? allChildren.size() : 0;
 
+                boolean isUnitProject = parent.getExtNodeType() != null &&
+                        parent.getExtNodeType() == 1;
+
                 // 检查是否全覆盖所有子节点
-                if (childrenCount > 0 && groupNodes.size() == childrenCount ) {
+                if (childrenCount > 0 && groupNodes.size() == childrenCount && !isUnitProject) {
                     // 只有组内第一个父节点使用完整层级名称
                     String parentName = firstParentInGroup ?
                             getLevelName(hierarchy, groupId) :

+ 173 - 4
blade-service/blade-archive/src/main/java/org/springblade/archive/service/impl/ArchivesAutoServiceImpl.java

@@ -771,7 +771,69 @@ public class ArchivesAutoServiceImpl extends BaseServiceImpl<ArchivesAutoMapper,
 
 	@Override
 	public void splitArchvies(Long projectId, Long contractId, Long nodeId) {
+		splitArchvies(projectId, contractId, nodeId, null);
+	}
+
+	public void splitArchvies(Long projectId, Long contractId, Long nodeId, List<Long> childNodes) {
 		List<String> removeFiles = new ArrayList<>();
+		
+		// 如果 childNodes 不为空,使用 childNodes 进行拆卷
+		if (childNodes != null && !childNodes.isEmpty()) {
+			log.info("[自动组卷-拆卷]{}", "对指定childNodes进行拆卷,childNodes: " + childNodes);
+			
+			// 从 childNodes 分别获取节点信息并合并处理
+			for (Long childNodeId : childNodes) {
+				ArchiveTreeContract childNode = archiveTreeContractClient.getArchiveTreeContractById(childNodeId);
+				if (childNode != null) {
+					// 如果指定了 contractId,检查节点是否属于该合同段
+					if (contractId != null && !contractId.equals(childNode.getContractId())) {
+						continue; // 跳过不属于指定合同段的节点
+					}
+					
+					String ancestors = childNode.getAncestors() + "," + childNodeId;
+					String strChildNodeId = childNodeId.toString();
+					
+					// 清除案卷封面等pdf
+					List<String> archivesOutUrlList = baseMapper.getArchivesOutUrlListByNode(projectId, ancestors, strChildNodeId);
+					if (archivesOutUrlList != null && archivesOutUrlList.size() > 0) {
+						for (String outUrl : archivesOutUrlList) {
+							String[] splits = outUrl.split(",");
+							for (String url : splits) {
+								if (StringUtils.isNotEmpty(url) && StringUtils.isNotEmpty(url.trim())) {
+									removeFiles.add(FileUtils.getAliYunSubUrl(url));
+								}
+							}
+						}
+						// 删除四要素文件记录
+						baseMapper.deleteIsElementFileByNode(projectId, ancestors, strChildNodeId);
+					}
+					
+					// 清除文件页面pdf
+					List<String> filePageUrlList = baseMapper.getFilePageUrlListByNode(projectId, ancestors, strChildNodeId);
+					if (filePageUrlList != null && filePageUrlList.size() > 0) {
+						for (String url : filePageUrlList) {
+							if (StringUtils.isNotEmpty(url) && StringUtils.isNotEmpty(url.trim())) {
+								removeFiles.add(FileUtils.getAliYunSubUrl(url));
+							}
+						}
+					}
+					
+					// 执行拆卷操作
+					baseMapper.splitArchviesByNode(projectId, ancestors, strChildNodeId);
+				}
+			}
+			
+			// 异步删除文件
+			if (!removeFiles.isEmpty()) {
+				executorService.execute(() -> {
+					log.info("[自动组卷-拆卷]{}", "删除旧封面,页码文件开始" + removeFiles);
+					iossClient.removeFiles(removeFiles);
+					log.info("[自动组卷-拆卷]{}", "删除旧封面,页码文件结束" + removeFiles);
+				});
+			}
+			return;
+		}
+		
 		//没合同段的默认整个项目
 		if (contractId == null) {
 			log.info("[自动组卷-拆卷]{}", "对全项目未锁定案卷拆卷");
@@ -901,6 +963,10 @@ public class ArchivesAutoServiceImpl extends BaseServiceImpl<ArchivesAutoMapper,
 
 	@Override
 	public void archiveAutoMethod(Long projectId, Long contractId, Long nodeId, Long traceId) {
+		archiveAutoMethod(projectId, contractId, nodeId, traceId, null);
+	}
+
+	public void archiveAutoMethod(Long projectId, Long contractId, Long nodeId, Long traceId, List<Long> childNodes) {
 		//步骤一:把档号集合初始化
 		indexMap = new HashMap<>();
 		//步list = {ArrayList@18238}  size = 19骤二:查询归档树节点。存在未归档文件的节点。
@@ -919,6 +985,40 @@ public class ArchivesAutoServiceImpl extends BaseServiceImpl<ArchivesAutoMapper,
 		//按合同段过滤
 		List<ArchiveTreeContract> authlist = authFilter(list, contractId, nodeId);
 
+		// 新增:处理 childNodes 参数
+		if (childNodes != null && !childNodes.isEmpty()) {
+			// 创建合并列表(包含原始 authlist)
+			List<ArchiveTreeContract> mergedAuthlist = new ArrayList<>();
+
+			// 遍历每个子节点ID,应用过滤并合并结果
+			for (Long childNodeId : childNodes) {
+				List<ArchiveTreeContract> childAuthlist = authFilter(list, contractId, childNodeId);
+				mergedAuthlist.addAll(childAuthlist);
+			}
+
+			// 去重处理(根据节点ID)
+			authlist = mergedAuthlist;
+		}
+		
+		// 如果 childNodes 不为空,进行祖先节点过滤
+//		if (childNodes != null && !childNodes.isEmpty()) {
+//			authlist = authlist.stream()
+//				.filter(node -> {
+//					// 检查节点的祖先是否包含 childNodes 中的任一元素
+//					if (StringUtils.isNotEmpty(node.getAncestors())) {
+//						String[] ancestors = node.getAncestors().split(",");
+//						for (String ancestor : ancestors) {
+//							if (StringUtils.isNotEmpty(ancestor.trim()) && childNodes.contains(Long.valueOf(ancestor.trim()))) {
+//								return true;
+//							}
+//						}
+//					}
+//					// 检查节点本身是否在 childNodes 中
+//					return childNodes.contains(node.getId());
+//				})
+//				.collect(Collectors.toList());
+//		}
+
 		//步骤三:遍历归档树节点整理出 默认规则节点,分类并卷节点,单独组卷节点 三个集合。
 		List<ArchiveTreeContract> list0 = new ArrayList<>();
 		List<ArchiveTreeContract> list1 = new ArrayList<>();
@@ -954,7 +1054,7 @@ public class ArchivesAutoServiceImpl extends BaseServiceImpl<ArchivesAutoMapper,
 		archiveAutoMethod2_new(list2, listTop, projectId, boxMap, boxFileMap, traceId);//分类组卷
 		//设置完成度50%
 		projectClient.updateIsArchivesAutoById(projectId, 50);
-		archiveAutoMethod1(list1, boxMap, boxFileMap, traceId);//默认组卷
+		archiveAutoMethod3(list1, boxMap, boxFileMap, traceId);//默认组卷
 
 		//分盒组卷的且节点没配置组卷类型的
 		archiveAutoMethod0(list0, boxMap, boxFileMap);//默认组卷
@@ -963,6 +1063,8 @@ public class ArchivesAutoServiceImpl extends BaseServiceImpl<ArchivesAutoMapper,
 		archiveAutoMethodBox(boxMap, traceId);//分盒组卷
 	}
 
+
+
 	private void addBoxMap(ArchiveFile file, Map<String, List<ArchiveFile>> boxMap, Map<Long, String> boxFileMap) {
 		String boxName = file.getBoxName();
 		if (boxFileMap.containsKey(file.getId())) {
@@ -2618,6 +2720,10 @@ public class ArchivesAutoServiceImpl extends BaseServiceImpl<ArchivesAutoMapper,
 	 * @param nodeId
 	 */
 	public void refreshFileNumberNoSlipt(Long projectId, Long contractId, Long nodeId, boolean bforce, Long traceId) {
+		refreshFileNumberNoSlipt(projectId, contractId, nodeId, bforce, traceId, null);
+	}
+
+	public void refreshFileNumberNoSlipt(Long projectId, Long contractId, Long nodeId, boolean bforce, Long traceId, List<Long> childNodes) {
 		List<ArchiveTreeContract> list = archiveTreeContractClient.getListByProjectId(projectId);
 		if (nodeId != null) {
 			ArchiveTreeContract node = archiveTreeContractClient.getArchiveTreeContractById(nodeId);
@@ -2629,7 +2735,7 @@ public class ArchivesAutoServiceImpl extends BaseServiceImpl<ArchivesAutoMapper,
 		Integer indexType = 0;
 		ArchiveProjectConfig config = archiveProjectConfigService.getByProjectIdOrNew(projectId);
 
-		this.refreshFileNumberNoSlipt(list, contractId, nodeId, bforce, config.getIndexType(), config.getDirType(), config.getIndexNum(), traceId);
+		this.refreshFileNumberNoSlipt(list, contractId, nodeId, bforce, config.getIndexType(), config.getDirType(), config.getIndexNum(), traceId, childNodes);
 	}
 
 	/**
@@ -2639,6 +2745,11 @@ public class ArchivesAutoServiceImpl extends BaseServiceImpl<ArchivesAutoMapper,
 	 */
 	public void refreshFileNumberNoSlipt(List<ArchiveTreeContract> archiveTreeContracts, Long contractId, Long nodeId,
 										 boolean bforce, Integer indexType, Integer dirType, Integer indexNum, Long traceId) {
+		refreshFileNumberNoSlipt(archiveTreeContracts, contractId, nodeId, bforce, indexType, dirType, indexNum, traceId, null);
+	}
+
+	public void refreshFileNumberNoSlipt(List<ArchiveTreeContract> archiveTreeContracts, Long contractId, Long nodeId,
+										 boolean bforce, Integer indexType, Integer dirType, Integer indexNum, Long traceId, List<Long> childNodes) {
 
 		List<ArchiveTreeContractVO2> subTreeList = new ArrayList<>();
 		List<List<ArchiveTreeContract>> subGroupedList = new ArrayList<>();
@@ -2659,6 +2770,26 @@ public class ArchivesAutoServiceImpl extends BaseServiceImpl<ArchivesAutoMapper,
 
 			//根据 authFilter函数过滤
 			subList = authFilterNum(subList, contractId, nodeId);
+			
+			// 如果 childNodes 不为空,进行祖先节点过滤
+			if (childNodes != null && !childNodes.isEmpty()) {
+				subList = subList.stream()
+					.filter(node -> {
+						// 检查节点的祖先是否包含 childNodes 中的任一元素
+						if (StringUtils.isNotEmpty(node.getAncestors())) {
+							String[] ancestors = node.getAncestors().split(",");
+							for (String ancestor : ancestors) {
+								if (StringUtils.isNotEmpty(ancestor.trim()) && childNodes.contains(Long.valueOf(ancestor.trim()))) {
+									return true;
+								}
+							}
+						}
+						// 检查节点本身是否在 childNodes 中
+						return childNodes.contains(node.getId());
+					})
+					.collect(Collectors.toList());
+			}
+			
 			List<Long> ids = subList.stream()
 					.map(ArchiveTreeContract::getId)
 					.collect(Collectors.toList());
@@ -3284,10 +3415,17 @@ public class ArchivesAutoServiceImpl extends BaseServiceImpl<ArchivesAutoMapper,
 
 	@Override
 	public void archiveAutoMethodThread(Long projectId, Long contractId, Long nodeId, Long traceId) {
+		archiveAutoMethodThread(projectId, contractId, nodeId, traceId, null);
+	}
+
+	public void archiveAutoMethodThread(Long projectId, Long contractId, Long nodeId, Long traceId, List<Long> childNodes) {
 		executorService.execute(() -> {
 			try {
 				// 将项目未锁定案卷拆卷
 				String startSplitMsg = "[自动组卷] 开始对未锁定案卷拆卷。projectId:" + projectId + "-contractId:" + contractId + "-nodeId:" + nodeId + "-traceId:" + traceId;
+				if (childNodes != null && !childNodes.isEmpty()) {
+					startSplitMsg += "-childNodes:" + childNodes;
+				}
 				//log.info(startSplitMsg);
 				iTraceLogService.saveLog(traceId, startSplitMsg);
 
@@ -3296,31 +3434,49 @@ public class ArchivesAutoServiceImpl extends BaseServiceImpl<ArchivesAutoMapper,
 				//     return;
 				// }
 
-				splitArchvies(projectId, contractId, nodeId);
+				splitArchvies(projectId, contractId, nodeId, childNodes);
 				// 设置完成度10%
 				contractClient.updateIsArchivesAutoById(contractId, 10);
 
 				// 项目自动组卷入口
 				String startAutoArchiveMsg = "[自动组卷] 开始自动组卷。projectId:" + projectId + "-contractId:" + contractId + "-nodeId:" + nodeId + "-traceId:" + traceId;
+				if (childNodes != null && !childNodes.isEmpty()) {
+					startAutoArchiveMsg += "-childNodes:" + childNodes;
+				}
 				//log.info(startAutoArchiveMsg);
 				iTraceLogService.saveLog(traceId, startAutoArchiveMsg);
 
 				archiveAutoPdfService.assignArchiveTableUrl();
 
-				archiveAutoMethod(projectId, contractId, nodeId, traceId);
+				if (childNodes != null && !childNodes.isEmpty()) {
+					archiveAutoMethod(projectId, contractId, nodeId, traceId, childNodes);
+				} else {
+					archiveAutoMethod(projectId, contractId, nodeId, traceId);
+				}
 				// 设置完成度80%
 				contractClient.updateIsArchivesAutoById(contractId, 80);
 
 				// 刷新项目档号
 				String startRefreshMsg = "[自动组卷] 开始刷新组卷档号。projectId:" + projectId + "-contractId:" + contractId + "-nodeId:" + nodeId + "-traceId:" + traceId;
+				if (childNodes != null && !childNodes.isEmpty()) {
+					startRefreshMsg += "-childNodes:" + childNodes;
+				}
 				//log.info(startRefreshMsg);
 				iTraceLogService.saveLog(traceId, startRefreshMsg);
 
 				refreshFileNumberNoSlipt(projectId, contractId, nodeId, true, traceId);
+//				if (childNodes != null && !childNodes.isEmpty()) {
+//					refreshFileNumberNoSlipt(projectId, contractId, nodeId, true, traceId, childNodes);
+//				} else {
+//					refreshFileNumberNoSlipt(projectId, contractId, nodeId, true, traceId);
+//				}
 
 				// 设置自动组卷结束
 				contractClient.updateIsArchivesAutoById(contractId, 0);
 				String completeMsg = "[自动组卷] 自动组卷完成。projectId:" + projectId + "-contractId:" + contractId + "-nodeId:" + nodeId + "-traceId:" + traceId;
+				if (childNodes != null && !childNodes.isEmpty()) {
+					completeMsg += "-childNodes:" + childNodes;
+				}
 				//log.info(completeMsg);
 				iTraceLogService.saveLog(traceId, completeMsg);
 
@@ -5001,6 +5157,19 @@ public class ArchivesAutoServiceImpl extends BaseServiceImpl<ArchivesAutoMapper,
 		autoMapper.removeFilesByArchiveIds(archiveIds);
 	}
 
+	@Override
+	@Async
+	public void reCreateArchiveAuto1(String ids) {
+		for (Long id : Func.toLongList(ids)) {
+			//先查出勾选的案卷
+			ArchivesAuto archivesAuto=this.getById(id);
+			//查出所有案卷文件
+			List<ArchiveFile>archiveFileList=archiveFileClient.getArchiveFileByArchiveIds(id+"");
+			//设置案卷页码和四要素
+			this.reCreateArchiveAuto(archivesAuto, archiveFileList);
+		}
+	}
+
 	/**
 	 * 分组适配方法:按nodeId分组文件并进行页数合并处理
 	 *

+ 62 - 4
blade-service/blade-archive/src/main/java/org/springblade/archive/service/impl/ScanFileServiceImpl.java

@@ -4,7 +4,9 @@ import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import io.swagger.annotations.ApiModelProperty;
 import lombok.AllArgsConstructor;
+import org.springblade.archive.entity.ArchivesAuto;
 import org.springblade.archive.entity.ScanFile;
 import org.springblade.archive.entity.ScanFolder;
 import org.springblade.archive.mapper.ScanFileMapper;
@@ -12,14 +14,19 @@ import org.springblade.archive.mapper.ScanFolderMapper;
 import org.springblade.archive.service.ScanFileService;
 import org.springblade.archive.utils.FileUtils;
 import org.springblade.archive.vo.ScanFolderVO;
+import org.springblade.business.entity.ArchiveFile;
+import org.springblade.business.feign.ArchiveFileClient;
 import org.springblade.common.utils.SnowFlakeUtil;
 import org.springblade.core.mp.support.Query;
 import org.springblade.core.oss.model.BladeFile;
 import org.springblade.core.tool.api.R;
 import org.springblade.core.tool.utils.Func;
 import org.springblade.core.tool.utils.StringUtil;
+import org.springblade.manager.entity.ArchiveTreeContract;
+import org.springblade.manager.feign.ArchiveTreeContractClient;
 import org.springblade.resource.feign.NewIOSSClient;
 import org.springframework.beans.BeanUtils;
+import org.springframework.jdbc.core.JdbcTemplate;
 import org.springframework.stereotype.Service;
 import java.io.File;
 import java.io.IOException;
@@ -31,6 +38,7 @@ import java.nio.file.attribute.BasicFileAttributes;
 import java.security.DigestInputStream;
 import java.security.MessageDigest;
 import java.text.SimpleDateFormat;
+import java.time.LocalDateTime;
 import java.util.*;
 import java.util.stream.Collectors;
 
@@ -50,6 +58,10 @@ public class ScanFileServiceImpl  extends ServiceImpl<ScanFileMapper, ScanFile>
     private final ScanFolderMapper scanFolderMapper;
     private final ScanFileMapper scanFileMapper;
     private final NewIOSSClient newIOSSClient;
+    private final ArchiveTreeContractClient archiveTreeContractClient;
+    private final JdbcTemplate jdbcTemplate;
+    private final ArchiveFileClient archiveFileClient;
+
 
 
 
@@ -104,9 +116,9 @@ public class ScanFileServiceImpl  extends ServiceImpl<ScanFileMapper, ScanFile>
     }
 
     @Override
-    public IPage<ScanFile> getScanFile(Long contractId, Long projectId, Long folderId, Query query) {
+    public IPage<ScanFile> getScanFile(Long contractId, Long projectId, Long folderId, Query query,Integer move) {
         IPage<ScanFile> page = new Page<>(query.getCurrent(), query.getSize());
-        page=baseMapper.getScanFile(page,contractId,projectId,folderId);
+        page=baseMapper.getScanFile(page,contractId,projectId,folderId,move);
         return page;
     }
 
@@ -124,10 +136,55 @@ public class ScanFileServiceImpl  extends ServiceImpl<ScanFileMapper, ScanFile>
     public Boolean autoRecognize(String ids) {
         List<Long> longList = Func.toLongList(ids);
         List<ScanFile> scanFiles = baseMapper.selectList(new LambdaQueryWrapper<>(ScanFile.class).in(ScanFile::getId, longList));
-
         return true;
     }
 
+
+    @Override
+    public boolean moveScanFile(List<Long> ids, Long nodeId) {
+        try {
+            List<ScanFile> scanFiles = baseMapper.selectList(new LambdaQueryWrapper<>(ScanFile.class).in(ScanFile::getId, ids));
+            ArchiveTreeContract contract = archiveTreeContractClient.getArchiveTreeContractById(nodeId);
+            String sql="select IFNULL(max(sort),0) from u_archive_file where project_id="+contract.getProjectId()+" and contract_id="+contract.getContractId()+" and is_deleted=0";
+            Integer sort = jdbcTemplate.queryForObject(sql, Integer.class);
+            List<ArchiveFile>list=new ArrayList<>();
+            if(contract!=null){
+                for (ScanFile file : scanFiles) {
+                    ArchiveFile archiveFile = new ArchiveFile();
+                    archiveFile.setId(SnowFlakeUtil.getId());
+                    archiveFile.setProjectId(contract.getProjectId()+"");
+                    archiveFile.setContractId(contract.getContractId()+"");
+                    archiveFile.setNodeId(nodeId+"");
+                    archiveFile.setFileNumber(file.getFileNum());
+                    archiveFile.setFileName(file.getFileName());
+                    archiveFile.setFileTime(file.getFileDate());
+                    archiveFile.setFileUrl(file.getOssUrl());
+                    archiveFile.setPdfFileUrl(file.getOssUrl());
+                    archiveFile.setFilePage(file.getFileSize()!=null?Integer.parseInt(file.getFileSize()):0);
+                    archiveFile.setIsApproval(0);
+                    archiveFile.setIsNeedCertification(0);
+                    archiveFile.setIsCertification(0);
+                    archiveFile.setDutyUser(file.getResponsible());
+                    archiveFile.setIsArchive(0);
+                    archiveFile.setSourceType(2);
+                    archiveFile.setIsElement(0);
+                    archiveFile.setClassify(contract.getClassify());
+                    archiveFile.setNodeTreeStructure(contract.getTreeStructure());
+                    archiveFile.setSort(sort++);
+                    list.add(archiveFile);
+                }
+                archiveFileClient.saveBatchArchiveFile(list);
+                for (ScanFile file : scanFiles) {
+                    file.setIsMove(1);
+                }
+                this.updateBatchById(scanFiles);
+            }
+            return true;
+        }catch (Exception e){
+            return false;
+        }
+    }
+
     /**
      * 入口方法:扫描并入库指定contractId的所有文件夹
      * @param contractId 传入的合同ID(对应D:\PDF下的文件夹名)
@@ -259,7 +316,7 @@ public class ScanFileServiceImpl  extends ServiceImpl<ScanFileMapper, ScanFile>
 
     @Override
     public void sortNumber(Long contractId, Long projectId) {
-        List<ScanFile> scanFiles = scanFileMapper.selectList(new LambdaQueryWrapper<ScanFile>().eq(ScanFile::getContractId, contractId).eq(ScanFile::getProjectId, projectId).isNull(ScanFile::getSort).isNull(ScanFile::getDigitalNum).orderByDesc(ScanFile::getFileDate));
+        List<ScanFile> scanFiles = scanFileMapper.selectList(new LambdaQueryWrapper<ScanFile>().eq(ScanFile::getContractId, contractId).eq(ScanFile::getProjectId, projectId).isNull(ScanFile::getSort).isNull(ScanFile::getDigitalNum).orderByAsc(ScanFile::getCreatTime));
         Integer maxDigitalNum=scanFileMapper.selectMaxDigitalNum(contractId,projectId);
         if(maxDigitalNum==null||maxDigitalNum<1){
             maxDigitalNum=0;
@@ -359,6 +416,7 @@ public class ScanFileServiceImpl  extends ServiceImpl<ScanFileMapper, ScanFile>
                     filePath,
                     bladeFile.getLink(),//OSS路径
                     null,//负责人
+                    0,
                     0
             );
             // 入库

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

@@ -1739,7 +1739,7 @@ public R<String> batchDownloadFileToZip(String ids, HttpServletResponse response
                 String sql = "";
                 String sql1 = "";
                 if (primaryKeyId != null && primaryKeyId.indexOf("*") > 0) {
-                    primaryKeyId = primaryKeyId.substring(0, primaryKeyId.length() - 1);
+                    primaryKeyId=primaryKeyId.replaceAll("\\*","");
                     sql = "update u_trial_self_inspection_record set task_status = '未上报' where id=" + primaryKeyId;
                     sql1 = "SELECT e.* from u_entrust_info e left join u_trial_self_inspection_record t on t.entrust_id=e.id where t.id=" + primaryKeyId;
                 } else {
@@ -5393,7 +5393,7 @@ public R<Object> customAddContractNode(@RequestBody CustomAddContractNodeDTO dto
      *
      * @return 结果
      */
-    @GetMapping("/updateCheckPdfInfo")
+    @PostMapping("/updateCheckPdfInfo")
     @ApiOperationSupport(order = 40)
     @ApiOperation(value = "添加pdf检查接口")
     @ApiImplicitParams(value = {
@@ -5401,9 +5401,8 @@ public R<Object> customAddContractNode(@RequestBody CustomAddContractNodeDTO dto
             @ApiImplicitParam(name = "classify", value = "1施工2监理",required = true),
             @ApiImplicitParam(name = "ids", value = "多个用,拼接", required = true)
     })
-    public  R updateCheckPdfInfo(@RequestParam String type, @RequestParam String ids,@RequestParam String classify) {
-        R r = informationQueryService.updateCheckPdfInfo(type, ids, classify);
-        return R.success("操作成功");
+    public  R updateCheckPdfInfo(@RequestBody ChekPdfVo chekPdfVo) {
+        return informationQueryService.updateCheckPdfInfo(chekPdfVo.getType(), chekPdfVo.getIds(), chekPdfVo.getClassify());
     }
 
     /**

+ 5 - 0
blade-service/blade-business/src/main/java/org/springblade/business/feignClient/ArchiveFileClientImpl.java

@@ -455,4 +455,9 @@ public class ArchiveFileClientImpl implements ArchiveFileClient {
         return fileMapper.getAllArchiveFileByIds(strList);
     }
 
+    @Override
+    public void saveBatchArchiveFile(List<ArchiveFile> list) {
+        iArchiveFileService.saveBatch(list);
+    }
+
 }

+ 3 - 2
blade-service/blade-business/src/main/java/org/springblade/business/mapper/ArchiveFileMapper.xml

@@ -156,7 +156,7 @@
     </select>
 
     <select id="selectArchiveFilePage" resultMap="archiveFileResultMap">
-        select u.id,u.project_id,u.contract_id,u.node_id,u.file_number,u.file_name,u.file_time,u.file_url,u.pdf_file_url,u.file_page,u.is_approval,u.is_certification,u.is_need_certification,u.duty_user,u.create_user,u.create_dept,u.create_time,u.update_user,u.update_time,u.status,u.is_deleted,u.sheet_type,u.sheet_source,u.drawing_no,u.cite_change_number,u.certification_time,u.e_visa_file,u.node_ext_id,u.file_type,u.archive_id,u.origin_id,u.filming_time,u.filmingor_time,u.tag_id,u.pic_code,u.refer_code,u.film_code,u.width,u.height,u.ftime,u.del_time,u.sort,u.box_name,u.box_number,u.is_auto_file,u.is_archive,u.page_num,u.file_size,u.source_type,u.is_element,u.pdf_page_url,u.fid,u.rectification,u.classify,u.m_wbs_tree_contract_p_key_id,u.u_image_classification_file_id,u.archive_file_storage_type,u.node_tree_structure,u.date_name,u.archive_file_stroage_type,u.out_id,u.sort_num,u.is_lock,u.archive_sort,u.remark,u.m_album_id
+        select u.id,u.project_id,u.contract_id,u.node_id,u.file_number,u.file_name,u.file_time,u.file_url,u.pdf_file_url,u.file_page,u.is_approval,u.is_certification,u.is_need_certification,u.duty_user,u.create_user,u.create_dept,u.create_time,u.update_user,u.update_time,u.status,u.is_deleted,u.sheet_type,u.sheet_source,u.drawing_no,u.cite_change_number,u.certification_time,u.e_visa_file,u.node_ext_id,u.file_type,u.archive_id,u.origin_id,u.tag_id,u.pic_code,u.refer_code,u.film_code,u.width,u.height,u.sort,u.box_name,u.box_number,u.is_auto_file,u.is_archive,u.page_num,u.file_size,u.source_type,u.is_element,u.pdf_page_url,u.fid,u.rectification,u.classify,u.m_wbs_tree_contract_p_key_id,u.u_image_classification_file_id,u.archive_file_storage_type,u.node_tree_structure,u.date_name,u.archive_file_stroage_type,u.out_id,u.sort_num,u.is_lock,u.archive_sort,u.remark,u.m_album_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 and t.is_deleted= 0
@@ -240,6 +240,7 @@
             )
         </if>
         order by
+        u.sort,
         <if test="vo.nodeIds != null and vo.nodeIds != ''">
             case
             when t.tree_sort regexp '^[a-zA-Z]' then 0  -- 字母开头的排在前面
@@ -248,7 +249,7 @@
             end,
             t.tree_sort,
         </if>
-        u.sort,u.sort_num,u.create_time
+        u.sort_num,u.create_time
         limit #{current}, #{size}
     </select>
 

+ 15 - 3
blade-service/blade-business/src/main/java/org/springblade/business/service/impl/ArchiveFileServiceImpl.java

@@ -328,13 +328,20 @@ public class ArchiveFileServiceImpl extends BaseServiceImpl<ArchiveFileMapper, A
 
     @Override
     public boolean sortByFileTime(Long nodeId) {
-        String sql = "SELECT id,file_time,node_id FROM u_archive_file WHERE node_id IN (SELECT id FROM m_archive_tree_contract WHERE  FIND_IN_SET(" + nodeId + ",ancestors)) AND is_deleted=0";
+        String sql = "SELECT id,file_time,node_id,sort FROM u_archive_file WHERE node_id IN (SELECT id FROM m_archive_tree_contract WHERE  FIND_IN_SET(" + nodeId + ",ancestors)) AND is_deleted=0";
         List<ArchiveFile> list = jdbcTemplate.query(sql, new BeanPropertyRowMapper<>(ArchiveFile.class));
         if (list.size() > 0) {
             Map<String, List<ArchiveFile>> group = list.stream()
                     .collect(Collectors.groupingBy(ArchiveFile::getNodeId));
             for (Map.Entry<String, List<ArchiveFile>> entry : group.entrySet()) {
                 List<ArchiveFile> archiveFiles = entry.getValue();
+                // 从archiveFiles列表中提取sort字段,处理null值
+                List<Integer> sortValues = archiveFiles.stream()
+                        .map(file -> {
+                            // 如果sort字段为null,返回0;否则返回实际值
+                            return file.getSort() != null ? file.getSort() : 0;
+                        })
+                        .collect(Collectors.toList());
                 archiveFiles.sort((a, b) -> {
                     if (a.getFileTime() == null && b.getFileTime() == null) return 0;
                     if (a.getFileTime() == null) return -1;
@@ -342,8 +349,13 @@ public class ArchiveFileServiceImpl extends BaseServiceImpl<ArchiveFileMapper, A
                     return a.getFileTime().compareTo(b.getFileTime());
                 });
                 int sort = 0;
-                for (ArchiveFile file : archiveFiles) {
-                    file.setSort(sort++);
+                for (int i = 0; i < archiveFiles.size(); i++ ) {
+                    Integer sortValue = sortValues.get(i);
+                    if(sortValue!=0){
+                        archiveFiles.get(i).setSort(sortValue);
+                    }else {
+                        archiveFiles.get(i).setSort(sort++);
+                    }
                 }
                 this.updateBatchById(archiveFiles);
             }

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

@@ -1114,7 +1114,7 @@ public class InformationQueryServiceImpl extends BaseServiceImpl<InformationQuer
     }
 
     @Override
-    @Async
+//    @Async
     public R updateCheckPdfInfo(String type, String ids,String classify) {
         if(type==null || Func.isNull(type)){
             return R.fail("type不能weinull");

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

@@ -1161,6 +1161,7 @@ public class TrialSelfInspectionRecordServiceImpl extends BaseServiceImpl<TrialS
             }
 
             //------保存实体表数据、试验记录信息、生成PDF------
+            dto.setTableIds(tableIds);
             this.submitTrialData(obj, dto);
 
             //------关联原材料检测报告------

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

@@ -14,9 +14,11 @@ import org.springframework.web.bind.annotation.RestController;
 
 import javax.annotation.Resource;
 import java.util.List;
+import java.util.Map;
 import java.util.concurrent.CompletableFuture;
 import java.util.concurrent.ThreadPoolExecutor;
 import java.util.concurrent.TimeUnit;
+import java.util.stream.Collectors;
 
 /**
  * 清表基础数据表 控制器
@@ -55,16 +57,17 @@ public class ChekSignData {
             for (ScrSignInfoVO dataInfo : query) {
                 if (executor.getQueue().size()<=30 ) {
                     Long nodeId = dataInfo.getId();
-                    Boolean aBoolean = RedisTemplate.hasKey("chek-" + nodeId);
+                    // 兼容以前 u_information_query 与 u_task 一对多的关系
+                    Boolean aBoolean = RedisTemplate.hasKey("chek-" + nodeId + dataInfo.getProcessInstanceId());
 
                     if (!aBoolean) {
-                        RedisTemplate.opsForValue().set("chek-" + nodeId, "1",3600, TimeUnit.SECONDS);
+                        RedisTemplate.opsForValue().set("chek-" + nodeId + dataInfo.getProcessInstanceId(), "1",3600, TimeUnit.SECONDS);
                         CompletableFuture<Void> runAsync = CompletableFuture.runAsync(() -> {
                             try {
                                 /*===============执行批量任务===============*/
                                 scrDataService.sctTaskBatch(dataInfo);
                             } catch (Exception e) {
-                                RedisTemplate.delete("chek-" + nodeId);
+                                RedisTemplate.delete("chek-" + nodeId + dataInfo.getProcessInstanceId());
                                 e.printStackTrace();
                             }
                         }, executor);

+ 4 - 4
blade-service/blade-e-visa/src/main/java/org/springblade/evisa/service/impl/EVDataServiceImpl.java

@@ -590,7 +590,7 @@ public class EVDataServiceImpl implements EVDataService {
     public void addSignatureDataByAXQZ(List<SealStrategyVO> strategyListByAXQ,String formDataId,String markType) {
         System.out.println("www");
         String deleteSql = "delete from m_sign_data where query_id = '" + formDataId + "' and user_id in( ";
-        String insertsql = "INSERT INTO m_sign_data (id, query_id, text_id, user_id, sign_time, type, img_url, sign_type) VALUES (?, ?, ?, ?, SYSDATE(), ?, ?, ?)";
+        String insertsql = "INSERT INTO m_sign_data (id, query_id, text_id, user_id, sign_time, type, img_url, sign_type, pyzbx, pyzby) VALUES (?, ?, ?, ?, SYSDATE(), ?, ?, ?, ?, ?)";
         List<Object[]> batchArgs = new ArrayList<>();
         for (SealStrategyVO sealStrategyVO : strategyListByAXQ) {
             long newPkId = SnowFlakeUtil.getId(); //主键Id
@@ -598,7 +598,7 @@ public class EVDataServiceImpl implements EVDataService {
             if(sealStrategyVO.isCompanySeal()){
                 type = "2";
             }
-            batchArgs.add(new Object[]{newPkId, formDataId, sealStrategyVO.getKeyword(), sealStrategyVO.getUserId(), type, sealStrategyVO.getImageUrl(), markType});
+            batchArgs.add(new Object[]{newPkId, formDataId, sealStrategyVO.getKeyword(), sealStrategyVO.getUserId(), type, sealStrategyVO.getImageUrl(), markType, sealStrategyVO.getOffSetX(), sealStrategyVO.getOffSetY()});
             deleteSql+= sealStrategyVO.getUserId() +",";
         }
         // 添加更多数据...
@@ -611,13 +611,13 @@ public class EVDataServiceImpl implements EVDataService {
     public void addSignatureDataByDFZX(List<Map<String, Object>> strategyListByAXQ,String formDataId,String markType) {
         System.out.println("www");
         String deleteSql = "delete from m_sign_data where query_id = '" + formDataId + "' and user_id in( ";
-        String insertsql = "INSERT INTO m_sign_data (id, query_id, text_id, user_id, sign_time, type, img_url, sign_type) VALUES (?, ?, ?, ?, SYSDATE(), ?, ?, ?)";
+        String insertsql = "INSERT INTO m_sign_data (id, query_id, text_id, user_id, sign_time, type, img_url, sign_type, pyzbx, pyzby) VALUES (?, ?, ?, ?, SYSDATE(), ?, ?, ?, ?, ?)";
         List<Object[]> batchArgs = new ArrayList<>();
         for (Map<String, Object> map : strategyListByAXQ) {
             long newPkId = SnowFlakeUtil.getId(); //主键Id
             String userId = map.get("userId")+"";
             String type = map.get("type")+"";
-            batchArgs.add(new Object[]{newPkId, formDataId, map.get("keyWord"), userId, type, map.get("sealId"), markType});
+            batchArgs.add(new Object[]{newPkId, formDataId, map.get("keyWord"), userId, type, map.get("sealId"), markType, map.get("pyzbx"), map.get("pyzby")});
             deleteSql+=userId +",";
          }
         // 添加更多数据...

+ 167 - 34
blade-service/blade-e-visa/src/main/java/org/springblade/evisa/service/impl/ScrDataServiceImpl.java

@@ -7,11 +7,10 @@ import org.apache.pdfbox.pdmodel.common.PDRectangle;
 import org.apache.pdfbox.pdmodel.interactive.annotation.PDAnnotation;
 import org.apache.pdfbox.pdmodel.interactive.annotation.PDAnnotationWidget;
 import org.springblade.business.vo.ScrSignInfoVO;
-import org.springblade.business.vo.TaskSignInfoVO;
 import org.springblade.common.utils.CommonUtil;
-import org.springblade.core.tool.utils.BeanUtil;
 import org.springblade.core.tool.utils.CollectionUtil;
 import org.springblade.core.tool.utils.Func;
+import org.springblade.core.tool.utils.StringUtil;
 import org.springblade.evisa.service.ScrDataService;
 import org.springblade.evisa.utils.PdfAddimgUtil;
 import org.springblade.evisa.vo.SignKeyVO;
@@ -73,7 +72,7 @@ public class ScrDataServiceImpl implements ScrDataService {
             String sql2 = "UPDATE u_information_query set chek_status=3 where id='"+taskApp.getId()+"'";
             jdbcTemplate.execute(sql2);
 
-            RedisTemplate.delete("chek-" + taskApp.getId());
+            RedisTemplate.delete("chek-" + taskApp.getId() + taskApp.getProcessInstanceId());
             System.out.println(taskApp.getProcessInstanceId()+"-"+"总共:" );
             return;
         }
@@ -221,7 +220,7 @@ public class ScrDataServiceImpl implements ScrDataService {
             String sql2 = "UPDATE u_information_query set chek_status=3 where id='"+taskApp.getId()+"'";
             jdbcTemplate.execute(sql2);
         }
-        RedisTemplate.delete("chek-" + taskApp.getId());
+        RedisTemplate.delete("chek-" + taskApp.getId() + taskApp.getProcessInstanceId());
       //  System.out.println(taskApp.getProcessInstanceId()+"-"+"总共:" );
       //  System.out.println(taskApp.getId() +"-"+"总共:" + positions.size() + "-剩下-" + differentElements.size());
     }
@@ -230,16 +229,14 @@ public class ScrDataServiceImpl implements ScrDataService {
 
     // 添加电签策略 -- 安心签
     public List<Map<String, Object>> getStrategyListByAXQ(ScrSignInfoVO task, String ids) {
-        String sql = "select task_user,count(1) as total,initiative,status,(select  count(1) from u_task_parallel where process_instance_id = '" + task.getProcessInstanceId() + "' and initiative=2 and status=2) as pCount from u_task_parallel where process_instance_id = '" + task.getProcessInstanceId() + "'";
+        String sql = "select task_user,initiative,status,(select  count(1) from u_task_parallel where process_instance_id = '" + task.getProcessInstanceId() + "' and initiative=2 and status=2) as pCount from u_task_parallel where process_instance_id = '" + task.getProcessInstanceId() + "'";
         List<Map<String, Object>> mapList = jdbcTemplate.queryForList(sql);
         ArrayList<String> strArray = new ArrayList();
-        int total = 0;
         int pCount = 0;
         if (mapList != null && mapList.size() >= 1) {
             for (int i = 0; i < mapList.size(); i++) {
                 Map<String, Object> map = mapList.get(i);
                 if(i==0){
-                    total = Func.toInt(map.get("total"));
                     pCount = Func.toInt(map.get("pCount"));
                 }
                 if((map.get("initiative")+"").equals("2") && (map.get("status")+"").equals("2")){
@@ -270,8 +267,8 @@ public class ScrDataServiceImpl implements ScrDataService {
             for (int i = 0; i < strArray.size(); i++) {
                 List<Map<String, Object>> maps2 = null;
                 if (dqIds.length() > 0) {
-                    String sqlinfo = " SELECT * from ( SELECT a.id as keyWord,a.project_id,a.pyzbx ,a.pyzby,(SELECT acc_code from blade_user where id='" + strArray.get(i) + "' and is_deleted=0  ) as sealId from m_textdict_info a where  a.type =2 and a.id in (" + dqIds + ")  and sig_role_id in (SELECT DISTINCT c.role_id from m_project_assignment_user c  where c.contract_id=" + task.getContractId() + " and user_id=" + strArray.get(i) + " and c.is_deleted=0 ) ) x where x.sealId is not null ";
-                    System.out.println("东方中讯--签字--" + sqlinfo);
+                    String sqlinfo = " SELECT * from ( SELECT a.id as keyWord,a.project_id,a.pyzbx ,a.pyzby,(SELECT signature_file_url from m_sign_pfx_file where is_register=1 and certificate_user_id='" + strArray.get(i) + "' and is_deleted=0  ) as signature_file_url, '1' as type from m_textdict_info a where  a.type =2 and a.id in (" + dqIds + ")  and sig_role_id in (SELECT DISTINCT c.role_id from m_project_assignment_user c  where c.contract_id=" + task.getContractId() + " and user_id=" + strArray.get(i) + " and c.is_deleted=0 ) ) x where x.signature_file_url is not null ";
+                    System.out.println("安心签--签字--" + sqlinfo);
                     maps2 = jdbcTemplate.queryForList(sqlinfo);
                 }
                 if(CollectionUtil.isNotEmpty(maps2)) {
@@ -295,13 +292,19 @@ public class ScrDataServiceImpl implements ScrDataService {
                             maps.add(keyList.get(0));
                         }
                     }
+                } else {
+                    // 查询 sign_data 表
+                    List<Map<String, Object>> list = jdbcTemplate.queryForList("SELECT * from m_sign_data where query_id = ? and text_id in (?) and user_id = ? and type = 1", task.getId(), dqIds, strArray.get(i));
+                    if (!list.isEmpty()) {
+                        System.out.println("1111111111111111111");
+                    }
                 }
             }
 
 
 
-            String sqlinfo = "SELECT a.id as keyWord,a.pyzbx,a.pyzby,b.certificate_number as sealId from m_textdict_info a ,m_sign_pfx_file b where a.sig_role_id = b.pfx_type and b.project_contract_role like '%" + task.getContractId() + "%' and a.is_deleted=0 and b.is_deleted=0 and a.type=6 and a.id in(" + dqIds + ")";
-            System.out.println("东方中讯--签章--" + sqlinfo);
+            String sqlinfo = "SELECT a.id as keyWord,a.pyzbx,a.pyzby,b.certificate_number as sealId, '2' as type from m_textdict_info a ,m_sign_pfx_file b where a.sig_role_id = b.pfx_type and b.project_contract_role like '%" + task.getContractId() + "%' and a.is_deleted=0 and b.is_deleted=0 and a.type=6 and a.id in(" + dqIds + ")";
+            System.out.println("安心签--签章--" + sqlinfo);
             List<Map<String, Object>> maps2 = jdbcTemplate.queryForList(sqlinfo);
             if(CollectionUtil.isNotEmpty(maps2)) {
                 Map<String, List<Map<String, Object>>> peopleByAge = maps2.stream()
@@ -324,6 +327,8 @@ public class ScrDataServiceImpl implements ScrDataService {
                         maps.add(keyList.get(0));
                     }
                 }
+            } else {
+                System.out.println("22222222222222222222");
             }
         }
         return maps;
@@ -409,6 +414,8 @@ public class ScrDataServiceImpl implements ScrDataService {
             List<String> positions = pdfSignIds.getEVisaConfigList();
             Map<String, String> dataMap = pdfSignIds.getDataMap();
 
+            Map<String, String> dataMap1 = checkSignByPdf(taskApp, pdfSignIds, pdfData);
+
             List<String> sucessUser = new ArrayList<>();
             List<String> sucessCompan = new ArrayList<>();
             String ids = String.join(",", positions);
@@ -423,10 +430,10 @@ public class ScrDataServiceImpl implements ScrDataService {
 
             if (strategyListByDFZX == null || strategyListByDFZX.size() == 0) {
 
-                String sql2 = "UPDATE u_information_query set chek_status=10 where id='" + taskApp.getId() + "'";
+                String sql2 = "UPDATE u_information_query set chek_status=3 where chek_status != 2 and id='" + taskApp.getId() + "'";
                 jdbcTemplate.execute(sql2);
 
-                RedisTemplate.delete("chek-" + taskApp.getId());
+                RedisTemplate.delete("chek-" + taskApp.getId() + taskApp.getProcessInstanceId());
                 System.out.println(taskApp.getProcessInstanceId() + "-" + "总共:");
                 return;
             }
@@ -569,8 +576,8 @@ public class ScrDataServiceImpl implements ScrDataService {
                                 if (pkeyid.length() < 19) {
                                     keyw = keyw - (float) (10 - pkeyid.length() / 2.0);
                                 }
-//                                System.out.println("page = " + (i + 1) + ", type = " + type + ", keyid = " + pkeyid + ", imgX : " + imgX + ", keyw : " + keyw + ", imgY : "
-//                                        + imgY + ", keyh : " + keyh + ", keyword =" + keyData.replace("\r", "\\r") + ", remarkType = " + taskApp.getRemarkType());
+                                System.out.println("page = " + (i + 1) + ", type = " + type + ", keyid = " + pkeyid + ", imgX : " + imgX + ", keyw : " + keyw + ", imgY : "
+                                        + imgY + ", keyh : " + keyh + ", keyword =" + keyData.replace("\r", "\\r") + ", remarkType = " + taskApp.getRemarkType());
                                 if (Math.abs(imgX - keyw) <= threshold && Math.abs(imgY - keyh) <= threshold) {
                                     if (type.equals("1")) { //个人
                                         sucessUser.add(pkeyid);
@@ -603,22 +610,6 @@ public class ScrDataServiceImpl implements ScrDataService {
                 }
             }
 
-//            boolean isSign1 = true;
-//            //判断个人是否签完
-//            List<String> userList = strategyListByDFZX.stream().filter(item -> item.get("type").equals("1")).map(map -> map.get("keyWord").toString()).collect(Collectors.toList());
-//            if (!userList.isEmpty()) {
-//                Set<String> differentElements = new HashSet<>(userList);
-//                sucessUser.forEach(differentElements::remove);
-//                if (!differentElements.isEmpty()) {
-//                    isSign1 = false;
-//                    StringBuilder sb = new StringBuilder();
-//                    sb.append("id = ").append(taskApp.getId()).append(", 人总共:").append(userList.size()).append(", 剩下:").append(differentElements.size());
-//                    for (String element : differentElements) {
-//                        sb.append(", ").append(element);
-//                    }
-//                    System.err.println(sb);
-//                }
-//            }
             if(!sucessUser.isEmpty() && isSign){
                 for(String user:sucessUser){
                     for(String mapkey:dataMap.keySet()){
@@ -637,7 +628,42 @@ public class ScrDataServiceImpl implements ScrDataService {
                     }
                 }
                 if(!dataUserMap.isEmpty()){
-                    isSign = false ;
+                    Map<String, float[]> allKeyPositions = getKeyPositions(pdfSignIds, pdfData);
+                    Set<String> removeKeys = new HashSet<>();
+                    dataUserMap.forEach((id, value) -> {
+                        float[] floats = allKeyPositions.get(value);
+                        if (floats == null || floats.length < 6) {
+                            return;
+                        }
+                        dataMap.forEach((key, value1) -> {
+                            float[] floats1 = allKeyPositions.get(value);
+                            if (floats1.length < 2) {
+                                return;
+                            }
+                            if (floats[0] != floats1[0]) {
+                                return;
+                            }
+                            PDPage page = document.getPage((int) floats[0] - 1);
+                            float pageHeight = page.getMediaBox().getHeight();
+                            float pageWidth = page.getMediaBox().getWidth();
+                            if (Math.abs(floats[5] * pageHeight - floats1[3] * pageHeight) < 1 && Math.abs(floats[4] * pageWidth - floats1[1] * pageWidth) < 1 && !dataUserMap.containsKey(key)) {
+                                removeKeys.add(id);
+                            }
+                        });
+                    });
+                    if (!removeKeys.isEmpty()) {
+                        dataUserMap.entrySet().removeIf(entry -> removeKeys.contains(entry.getKey()));
+                    }
+                    if (!dataUserMap.isEmpty()) {
+                        if (dataMap1 == null) {
+                            dataUserMap.entrySet().removeIf(item -> true);
+                        } else {
+                            dataUserMap.entrySet().removeIf(entry -> !dataMap1.containsKey(entry.getKey()));
+                        }
+                    }
+                    if (!dataUserMap.isEmpty()) {
+                        isSign = false ;
+                    }
                 }
                 System.out.println(taskApp.getId() +"-"+"个人总共:" + sucessUser.size() + "-剩下-" +dataUserMap.keySet().size());
             }
@@ -645,10 +671,117 @@ public class ScrDataServiceImpl implements ScrDataService {
                 String sql2 = "UPDATE u_information_query set chek_status=2 where id='" + taskApp.getId() + "'";
                 jdbcTemplate.execute(sql2);
             } else {
-                String sql2 = "UPDATE u_information_query set chek_status=3 where id='" + taskApp.getId() + "'";
+                String sql2 = "UPDATE u_information_query set chek_status=3 where chek_status != 2 and id='" + taskApp.getId() + "'";
                 jdbcTemplate.execute(sql2);
             }
-            RedisTemplate.delete("chek-" + taskApp.getId());
+            RedisTemplate.delete("chek-" + taskApp.getId() + taskApp.getProcessInstanceId());
+        }
+    }
+
+    /**
+     * 获取所有电签关键字的位置
+     */
+    public Map<String, float[]> getKeyPositions(SignKeyVO pdfSignIds,byte[] pdfData) throws Exception {
+        if (pdfSignIds == null) {
+            return  null;
+        }
+        Map<String, String> dataMap = pdfSignIds.getDataMap();
+        Collection<String> keys = dataMap.values();
+        if (keys.isEmpty()) {
+            return null;
+        }
+        List<PDFIndexInfo> pdfIndexInfo = PdfAddimgUtil.findKeywordPostions(pdfData,  String.join(",", keys));
+        if (pdfIndexInfo.isEmpty()) {
+            return  null;
+        }
+        Map<String, float[]> map = new HashMap<>();
+        for (PDFIndexInfo info : pdfIndexInfo) {
+            map.put(info.getPkeyid(), info.getDataInfo());
+        }
+        return map;
+    }
+
+    public Map<String, String> checkSignByPdf(ScrSignInfoVO taskApp,SignKeyVO pdfSignIds,byte[] pdfData) throws Exception {
+        int threshold = 5;
+        //转换
+        try (PDDocument document = PDDocument.load(pdfData);) {
+            List<String> positions = pdfSignIds.getEVisaConfigList();
+            Map<String, String> dataMap = pdfSignIds.getDataMap();
+            String keyWord = String.join(",", positions);
+            List<String> sucessList = new ArrayList<>();
+            List<PDFIndexInfo> pdfIndexInfo = PdfAddimgUtil.findKeywordPostions(pdfData, keyWord);
+            Map<String, List<PDFIndexInfo>> groupBy = pdfIndexInfo.stream().collect(Collectors.groupingBy(da -> Func.toStr(da.getDataInfo()[0])));
+            for (int i = 0; i < document.getPages().getCount(); i++) {
+                PDPage page = document.getPage(i);
+                List<PDAnnotation> annotations = page.getAnnotations();
+                for (PDAnnotation annotation : annotations) {
+                    if (annotation instanceof PDAnnotationWidget) {
+                        PDRectangle rect = annotation.getRectangle();
+                        float imgW = rect.getWidth();
+                        float imgH = rect.getHeight();
+                        float imgX = rect.getLowerLeftX() + imgW / 2;
+                        float imgY = rect.getLowerLeftY() + imgH / 2;
+                        List<PDFIndexInfo> pdfIndexInfos = groupBy.get((i + 1) + ".0");
+                        if (pdfIndexInfos != null && !pdfIndexInfos.isEmpty()) {
+                            for (PDFIndexInfo pdfInfo : pdfIndexInfos) {
+                                String pkeyid = pdfInfo.getPkeyid();
+                                float[] dataInfo = pdfInfo.getDataInfo();
+                                float keyX = dataInfo[1];
+                                float keyY = dataInfo[2];
+                                float pageHeight = page.getMediaBox().getHeight();
+                                float pageWidth = page.getMediaBox().getWidth();
+
+                                float keyw = keyX * pageWidth;
+                                float keyh = pageHeight - keyY * pageHeight;
+                                float pyzbx = 0.0f;
+                                float pyzby = 0.0f;
+                                if (taskApp.getRemarkType().equals("3")) { //东方中讯
+                                    if (imgH >= 100) {
+                                        // 签章
+                                        keyw = keyw + pyzbx - 21;
+                                        keyh = keyh + pyzby - 16;
+                                    } else {
+                                        keyw = keyw + pyzbx + 10;
+                                        keyh = keyh + pyzby;
+                                    }
+                                } else if (taskApp.getRemarkType().equals("2")) { //东方中讯
+                                    if (imgH >= 100) {
+                                        // 签章
+                                        keyw = keyw + pyzbx - 21;
+                                        keyh = keyh + pyzby - 15;
+                                    } else {
+                                        keyw = keyw + pyzbx + 10;
+                                        keyh = keyh + pyzby;
+                                    }
+                                } else {
+                                    keyw = keyw + pyzbx + 5;
+                                    keyh = keyh + pyzby;
+                                }
+                                if (pkeyid.length() < 19) {
+                                    keyw = keyw - (float) (10 - pkeyid.length() / 2.0);
+                                }
+                                if (Math.abs(imgX - keyw) <= threshold && Math.abs(imgY - keyh) <= threshold) {
+                                    sucessList.add(pkeyid);
+                                    break;
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+            Map<String, String> dataUserMap = new HashMap<>(dataMap);
+            //判断章是否签完
+            if (!sucessList.isEmpty()) {
+                for (String user : sucessList) {
+                    for (String mapkey : dataMap.keySet()) {
+                        String mapval = dataMap.get(mapkey);
+                        if (mapval.contains(user)) {
+                            dataUserMap.remove(mapkey);
+                        }
+                    }
+                }
+            }
+            return dataUserMap;
         }
     }
 }

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

@@ -265,6 +265,16 @@ public class PdfAddimgUtil {
                 }
 
                 float[] postions = charPositions.get(positionIndex);
+                try {
+                    // 获取text的结束位置
+                    int endPos = positionIndex + text.length();
+                    if (endPos < content.length()) {
+                        float[] floats = charPositions.get(endPos);
+                        postions = new float[]{postions[0], postions[1], postions[2], floats[0], floats[1], floats[2]};
+                    }
+                } catch (Exception e) {
+                    e.printStackTrace();
+                }
                 data.setDataInfo(postions);
                 data.setPkeyid(text);
                 result.add(data);
@@ -406,8 +416,6 @@ public class PdfAddimgUtil {
             String text = stripper.getText(document);
             String[] lines = text.split("[ \\n]+");
 
-            Pattern pattern = Pattern.compile("(\\d{4}[年-]\\d{2}[月-]\\d{2}日?)");
-
             for(int k=0;k<lines.length;k++){
                 String textStr = lines[k];
                 int index = textStr.indexOf("*");