From 0a941e1a8ab69002370bd6e276a058c3409103f8 Mon Sep 17 00:00:00 2001 From: RuicyWu <1063154311@qq.com> Date: Mon, 6 Jul 2026 10:40:09 +0800 Subject: [PATCH] =?UTF-8?q?=E6=9B=B4=E6=96=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../seeyon/apps/esign/node/A4CheckNode.java | 28 ++++++-- .../apps/esign/node/EsignOneSignerNode.java | 2 +- .../esign/po/signer/JsonSignerBuilder.java | 3 - .../apps/esign/utils/DocumentA4Checker.java | 65 +++++++++++++++++++ 4 files changed, 87 insertions(+), 11 deletions(-) diff --git a/src/main/java/com/seeyon/apps/esign/node/A4CheckNode.java b/src/main/java/com/seeyon/apps/esign/node/A4CheckNode.java index 6c1fd9b..9ba8dbb 100644 --- a/src/main/java/com/seeyon/apps/esign/node/A4CheckNode.java +++ b/src/main/java/com/seeyon/apps/esign/node/A4CheckNode.java @@ -13,6 +13,7 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import java.io.File; +import java.io.FileInputStream; import java.util.List; @@ -45,15 +46,28 @@ public class A4CheckNode extends ACommonSuperNode { List paths = fileUtil.fieldFileDownload(Long.parseLong(attachmentId), tempDir + File.separator + "oafile" + File.separator); for (String path : paths) { file = new File(path); - boolean firstPageA4 = DocumentA4Checker.isFirstPageA4(file); - if (!firstPageA4) { - String errMsg = "上传的附件中" + file.getName() +"非标准A4格式的,请修改后再上传(标准A4为21:29)"; - formDataVo.getNewFieldDataMap().put("合同审批附件格式校验结果", errMsg); - return context.back(errMsg); - }else { + try { + String fileName = file.getName().toLowerCase(); + // 检测 docx 批注/痕迹:会导致转PDF后页面撑大,不再是A4 + if (fileName.endsWith(".docx") || fileName.endsWith(".doc")) { + try (FileInputStream fis = new FileInputStream(file)) { + if (DocumentA4Checker.hasCommentsOrTrackChanges(fis)) { + String errMsg = "上传的附件" + file.getName() + "包含批注或修订痕迹,请清除后再上传"; + formDataVo.getNewFieldDataMap().put("合同审批附件格式校验结果", errMsg); + return context.back(errMsg); + } + } + } + boolean firstPageA4 = DocumentA4Checker.isFirstPageA4(file); + if (!firstPageA4) { + String errMsg = "上传的附件中" + file.getName() + "非标准A4格式的,请修改后再上传(标准A4为210:297)"; + formDataVo.getNewFieldDataMap().put("合同审批附件格式校验结果", errMsg); + return context.back(errMsg); + } formDataVo.getNewFieldDataMap().put("合同审批附件格式校验结果", ""); + } finally { + file.delete(); } - file.delete(); } return context.success("文件A4格式校验通过"); diff --git a/src/main/java/com/seeyon/apps/esign/node/EsignOneSignerNode.java b/src/main/java/com/seeyon/apps/esign/node/EsignOneSignerNode.java index b0aa6b2..9fd9ff5 100644 --- a/src/main/java/com/seeyon/apps/esign/node/EsignOneSignerNode.java +++ b/src/main/java/com/seeyon/apps/esign/node/EsignOneSignerNode.java @@ -208,7 +208,7 @@ public class EsignOneSignerNode extends ACommonSuperNode { param.setPageSize(1); param.setOrderField("UPDATE_DATE"); param.setSortType("DESC"); - Map sqlMap = FormTableExecutor.generateSql(param); + Map sqlMap = SqlGenerator.generateSql(param); JDBCAgent agent = new JDBCAgent(); try { agent.execute((String)sqlMap.get("sql"), (List)sqlMap.get("params")); diff --git a/src/main/java/com/seeyon/apps/esign/po/signer/JsonSignerBuilder.java b/src/main/java/com/seeyon/apps/esign/po/signer/JsonSignerBuilder.java index aa11565..ecf4b3c 100644 --- a/src/main/java/com/seeyon/apps/esign/po/signer/JsonSignerBuilder.java +++ b/src/main/java/com/seeyon/apps/esign/po/signer/JsonSignerBuilder.java @@ -1,6 +1,5 @@ package com.seeyon.apps.esign.po.signer; -import com.seeyon.apps.esign.config.EsignConfigProvider; import com.seeyon.apps.esign.po.signfield.NormalSignFieldConfig; import com.seeyon.apps.esign.po.signfield.SignField; import com.seeyon.apps.esign.po.signfield.SignFieldPosition; @@ -13,8 +12,6 @@ import java.util.Map; public class JsonSignerBuilder implements SignerBuilder{ - private EsignConfigProvider esignConfigProvider = EsignConfigProvider.getInstance(); - @Override public Signer build(List fileIds, List keywordPos, SignParty party,String appId) { if (party.getSignerType() == SignerType.PERSON) { diff --git a/src/main/java/com/seeyon/apps/esign/utils/DocumentA4Checker.java b/src/main/java/com/seeyon/apps/esign/utils/DocumentA4Checker.java index 8483b16..c275c5d 100644 --- a/src/main/java/com/seeyon/apps/esign/utils/DocumentA4Checker.java +++ b/src/main/java/com/seeyon/apps/esign/utils/DocumentA4Checker.java @@ -94,6 +94,71 @@ public class DocumentA4Checker { } } + /** + * 检测 docx 中是否包含批注或修订痕迹 + * 批注:word/comments.xml + * 痕迹:document.xml 中的 w:ins / w:del / w:delText / w:moveFrom / w:moveTo + */ + public static boolean hasCommentsOrTrackChanges(InputStream in) { + try { + byte[] docXmlBytes = null; + boolean hasComments = false; + + try (ZipInputStream zis = new ZipInputStream(in)) { + ZipEntry entry; + while ((entry = zis.getNextEntry()) != null) { + if ("word/comments.xml".equals(entry.getName())) { + hasComments = true; + } + if ("word/document.xml".equals(entry.getName())) { + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + byte[] buf = new byte[4096]; + int len; + while ((len = zis.read(buf)) != -1) { + bos.write(buf, 0, len); + } + docXmlBytes = bos.toByteArray(); + } + } + } + + if (hasComments) { + return true; + } + + // 解析 document.xml 检测修订痕迹 + if (docXmlBytes != null) { + DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); + Document doc = factory.newDocumentBuilder() + .parse(new ByteArrayInputStream(docXmlBytes)); + return hasTrackChanges(doc.getDocumentElement()); + } + } catch (Exception e) { + // 读取失败不拦截 + } + return false; + } + + /** + * 递归检测 XML 树中是否包含修订痕迹元素 + */ + private static boolean hasTrackChanges(Node node) { + if (node.getNodeType() == Node.ELEMENT_NODE) { + String name = node.getNodeName(); + if ("w:ins".equals(name) || "w:del".equals(name) || "w:delText".equals(name) + || "w:moveFrom".equals(name) || "w:moveTo".equals(name)) { + return true; + } + } + NodeList children = node.getChildNodes(); + for (int i = 0; i < children.getLength(); i++) { + if (hasTrackChanges(children.item(i))) { + return true; + } + } + return false; + } + /** * 校验 docx 第一页是否竖版 A4 * 直接读取 ZIP 中的 word/document.xml,不依赖 POI ooxml 模块