# 文档自动修正分析报告 ## 概述 本报告基于 `f:\api0203\ai_check\src\main\java\org\dromara\aiCheck\docExamine\examines\` 目录下的所有检查类,分析哪些文档检查项可以通过 Aspose.Words API 自动修正。 参考实现示例:[AsposeWordPageSizeConverter.java](ruoyi-modules/ai-intelligent-review/src/main/java/org/dromara/review/utils/AsposeWordPageSizeConverter.java):convertToA3 --- ## ✅ 可自动修正的检查项 ### 1. PaperRequirementsExamine - 纸张要求检查 #### 1.1 纸张大小 (paperSize) **检查内容**: 文档纸张不符合要求(如要求A4,实际为A3) **自动修正方法**: ```java public static void fixPaperSize(String inputPath, String outputPath, PaperSize requiredSize) throws Exception { Document doc = new Document(inputPath); for (Section section : doc.getSections()) { PageSetup pageSetup = section.getPageSetup(); pageSetup.setPaperSize(requiredSize); // 设置纸张大小 } doc.save(outputPath); } ``` **Aspose API**: - `PageSetup.setPaperSize(PaperSize.A4)` - 设置为A4 - `PageSetup.setPaperSize(PaperSize.A3)` - 设置为A3 - 其他: `PaperSize.A5`, `PaperSize.B5`, `PaperSize.LETTER` 等 **业务价值**: ⭐⭐⭐⭐⭐ (高 - 常见需求,一键修正) --- #### 1.2 纸张方向 (orientation) **检查内容**: 文档方向不符合要求(如要求横向,实际为纵向) **自动修正方法**: ```java public static void fixOrientation(String inputPath, String outputPath, boolean isLandscape) throws Exception { Document doc = new Document(inputPath); for (Section section : doc.getSections()) { PageSetup pageSetup = section.getPageSetup(); if (isLandscape) { pageSetup.setOrientation(Orientation.LANDSCAPE); // 横向 } else { pageSetup.setOrientation(Orientation.PORTRAIT); // 纵向 } } doc.save(outputPath); } ``` **Aspose API**: - `PageSetup.setOrientation(Orientation.LANDSCAPE)` - 横向 - `PageSetup.setOrientation(Orientation.PORTRAIT)` - 纵向 **业务价值**: ⭐⭐⭐⭐⭐ (高) --- #### 1.3 页边距 (margins) **检查内容**: 上/下/左/右页边距不符合要求 **自动修正方法**: ```java public static void fixMargins(String inputPath, String outputPath, double top, double bottom, double left, double right) throws Exception { Document doc = new Document(inputPath); for (Section section : doc.getSections()) { PageSetup pageSetup = section.getPageSetup(); pageSetup.setTopMargin(top); // 上边距(磅) pageSetup.setBottomMargin(bottom); // 下边距(磅) pageSetup.setLeftMargin(left); // 左边距(磅) pageSetup.setRightMargin(right); // 右边距(磅) } doc.save(outputPath); } ``` **Aspose API**: - `PageSetup.setTopMargin(double points)` - 上边距 - `PageSetup.setBottomMargin(double points)` - 下边距 - `PageSetup.setLeftMargin(double points)` - 左边距 - `PageSetup.setRightMargin(double points)` - 右边距 **单位换算**: 1厘米 = 28.35磅, 2.54厘米 = 72磅 **业务价值**: ⭐⭐⭐⭐⭐ (高 - 标书常见要求) --- ### 2. ContentRequirementsExamine - 内容格式要求检查 #### 2.1 字体 - 中文字体 (chineseFont) **检查内容**: 中文文本字体不符合要求(如要求宋体,实际为黑体) **自动修正方法**: ```java public static void fixChineseFont(String inputPath, String outputPath, String requiredFont) throws Exception { Document doc = new Document(inputPath); for (Section section : doc.getSections()) { for (Paragraph paragraph : section.getBody().getParagraphs()) { for (Run run : paragraph.getRuns()) { String text = run.getText(); if (containsChineseCharacters(text)) { run.getFont().setNameFarEast(requiredFont); // 设置中文字体 } } } } doc.save(outputPath); } private static boolean containsChineseCharacters(String text) { if (text == null) return false; for (char c : text.toCharArray()) { if (Character.UnicodeBlock.of(c) == Character.UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS) { return true; } } return false; } ``` **Aspose API**: - `Font.setNameFarEast("宋体")` - 设置中文字体(Far East Font) - 常用字体: "宋体", "黑体", "楷体", "仿宋", "微软雅黑" **业务价值**: ⭐⭐⭐⭐⭐ (高 - 标书必备) --- #### 2.2 字体 - 西文字体 (westernFont) **检查内容**: 西文文本字体不符合要求 **自动修正方法**: ```java public static void fixWesternFont(String inputPath, String outputPath, String requiredFont) throws Exception { Document doc = new Document(inputPath); for (Section section : doc.getSections()) { for (Paragraph paragraph : section.getBody().getParagraphs()) { for (Run run : paragraph.getRuns()) { run.getFont().setNameAscii(requiredFont); // 设置西文字体 } } } doc.save(outputPath); } ``` **Aspose API**: - `Font.setNameAscii("Times New Roman")` - 设置西文字体(ASCII Font) - 常用字体: "Times New Roman", "Arial", "Calibri" **业务价值**: ⭐⭐⭐⭐ (中高) --- #### 2.3 字号 (fontSize) **检查内容**: 字号不符合要求(如要求小四,实际为五号) **自动修正方法**: ```java public static void fixFontSize(String inputPath, String outputPath, String chineseSize) throws Exception { Document doc = new Document(inputPath); double targetSize = convertChineseFontSizeToPoints(chineseSize); for (Section section : doc.getSections()) { for (Paragraph paragraph : section.getBody().getParagraphs()) { for (Run run : paragraph.getRuns()) { run.getFont().setSize(targetSize); // 设置字号(磅) } } } doc.save(outputPath); } private static double convertChineseFontSizeToPoints(String chineseSize) { Map sizeMap = new HashMap<>(); sizeMap.put("初号", 42.0); sizeMap.put("小初", 36.0); sizeMap.put("一号", 26.0); sizeMap.put("小一", 24.0); sizeMap.put("二号", 22.0); sizeMap.put("小二", 18.0); sizeMap.put("三号", 16.0); sizeMap.put("小三", 15.0); sizeMap.put("四号", 14.0); sizeMap.put("小四", 12.0); sizeMap.put("五号", 10.5); sizeMap.put("小五", 9.0); sizeMap.put("六号", 7.5); sizeMap.put("小六", 6.5); sizeMap.put("七号", 5.5); sizeMap.put("八号", 5.0); return sizeMap.getOrDefault(chineseSize, 12.0); } ``` **Aspose API**: - `Font.setSize(double points)` - 设置字号 **业务价值**: ⭐⭐⭐⭐⭐ (高) --- #### 2.4 行距 (lineSpacing) **检查内容**: 行距不符合要求(如要求1.5倍行距,实际为单倍行距) **自动修正方法**: ```java public static void fixLineSpacing(String inputPath, String outputPath, String lineSpacingDesc) throws Exception { Document doc = new Document(inputPath); for (Section section : doc.getSections()) { for (Paragraph paragraph : section.getBody().getParagraphs()) { ParagraphFormat format = paragraph.getParagraphFormat(); if (lineSpacingDesc.contains("单倍")) { format.setLineSpacingRule(LineSpacingRule.MULTIPLE); format.setLineSpacing(12); // 单倍 = 12 } else if (lineSpacingDesc.contains("1.5倍")) { format.setLineSpacingRule(LineSpacingRule.MULTIPLE); format.setLineSpacing(18); // 1.5倍 = 18 } else if (lineSpacingDesc.contains("2倍")) { format.setLineSpacingRule(LineSpacingRule.MULTIPLE); format.setLineSpacing(24); // 2倍 = 24 } else if (lineSpacingDesc.contains("固定值")) { format.setLineSpacingRule(LineSpacingRule.EXACTLY); double points = extractPoints(lineSpacingDesc); format.setLineSpacing(points); } } } doc.save(outputPath); } ``` **Aspose API**: - `ParagraphFormat.setLineSpacingRule(LineSpacingRule.MULTIPLE)` - 倍数行距 - `ParagraphFormat.setLineSpacingRule(LineSpacingRule.EXACTLY)` - 固定值 - `ParagraphFormat.setLineSpacingRule(LineSpacingRule.AT_LEAST)` - 最小值 - `ParagraphFormat.setLineSpacing(double value)` - 设置行距值 **业务价值**: ⭐⭐⭐⭐⭐ (高) --- #### 2.5 段前/段后间距 (spacingBefore/spacingAfter) **检查内容**: 段前或段后间距不符合要求 **自动修正方法**: ```java public static void fixParagraphSpacing(String inputPath, String outputPath, int beforeLines, int afterLines) throws Exception { Document doc = new Document(inputPath); for (Section section : doc.getSections()) { for (Paragraph paragraph : section.getBody().getParagraphs()) { ParagraphFormat format = paragraph.getParagraphFormat(); format.setSpaceBefore(beforeLines * 12); // 行数转磅值 format.setSpaceAfter(afterLines * 12); } } doc.save(outputPath); } ``` **Aspose API**: - `ParagraphFormat.setSpaceBefore(double points)` - 段前间距 - `ParagraphFormat.setSpaceAfter(double points)` - 段后间距 **业务价值**: ⭐⭐⭐⭐ (中高) --- #### 2.6 对齐方式 (alignment) **检查内容**: 段落对齐方式不符合要求 **自动修正方法**: ```java public static void fixAlignment(String inputPath, String outputPath, String alignmentDesc) throws Exception { Document doc = new Document(inputPath); int alignment = ParagraphAlignment.LEFT; if (alignmentDesc.contains("居中")) { alignment = ParagraphAlignment.CENTER; } else if (alignmentDesc.contains("右对齐")) { alignment = ParagraphAlignment.RIGHT; } else if (alignmentDesc.contains("两端对齐")) { alignment = ParagraphAlignment.JUSTIFY; } else if (alignmentDesc.contains("分散对齐")) { alignment = ParagraphAlignment.DISTRIBUTED; } for (Section section : doc.getSections()) { for (Paragraph paragraph : section.getBody().getParagraphs()) { paragraph.getParagraphFormat().setAlignment(alignment); } } doc.save(outputPath); } ``` **Aspose API**: - `ParagraphFormat.setAlignment(ParagraphAlignment.LEFT)` - 左对齐 - `ParagraphFormat.setAlignment(ParagraphAlignment.CENTER)` - 居中 - `ParagraphFormat.setAlignment(ParagraphAlignment.RIGHT)` - 右对齐 - `ParagraphFormat.setAlignment(ParagraphAlignment.JUSTIFY)` - 两端对齐 - `ParagraphFormat.setAlignment(ParagraphAlignment.DISTRIBUTED)` - 分散对齐 **业务价值**: ⭐⭐⭐⭐ (中高) --- #### 2.7 缩进 (左/右/首行缩进) **检查内容**: 缩进不符合要求 **自动修正方法**: ```java public static void fixIndent(String inputPath, String outputPath, int leftChars, int rightChars, int firstLineChars) throws Exception { Document doc = new Document(inputPath); for (Section section : doc.getSections()) { for (Paragraph paragraph : section.getBody().getParagraphs()) { ParagraphFormat format = paragraph.getParagraphFormat(); format.setLeftIndent(leftChars * 12); // 字符转磅值 format.setRightIndent(rightChars * 12); format.setFirstLineIndent(firstLineChars * 12); } } doc.save(outputPath); } ``` **Aspose API**: - `ParagraphFormat.setLeftIndent(double points)` - 左缩进 - `ParagraphFormat.setRightIndent(double points)` - 右缩进 - `ParagraphFormat.setFirstLineIndent(double points)` - 首行缩进(正值=首行缩进,负值=悬挂缩进) **业务价值**: ⭐⭐⭐⭐ (中高) --- ### 3. TableRequirementsExamine - 表格要求检查 #### 3.1 表格对齐方式 (tableAlignment) **检查内容**: 表格对齐方式不符合要求 **自动修正方法**: ```java public static void fixTableAlignment(String inputPath, String outputPath, String alignmentDesc) throws Exception { Document doc = new Document(inputPath); int alignment = TableAlignment.LEFT; if (alignmentDesc.contains("居中")) { alignment = TableAlignment.CENTER; } else if (alignmentDesc.contains("右")) { alignment = TableAlignment.RIGHT; } for (Section section : doc.getSections()) { NodeCollection tables = section.getBody().getChildNodes(NodeType.TABLE, true); for (int i = 0; i < tables.getCount(); i++) { Table table = (Table) tables.get(i); table.setAlignment(alignment); } } doc.save(outputPath); } ``` **Aspose API**: - `Table.setAlignment(TableAlignment.LEFT)` - 左对齐 - `Table.setAlignment(TableAlignment.CENTER)` - 居中 - `Table.setAlignment(TableAlignment.RIGHT)` - 右对齐 **业务价值**: ⭐⭐⭐⭐ (中高) --- #### 3.2 单元格垂直对齐 (cellVerticalAlignment) **检查内容**: 单元格垂直对齐方式不符合要求 **自动修正方法**: ```java public static void fixCellVerticalAlignment(String inputPath, String outputPath, String alignmentDesc) throws Exception { Document doc = new Document(inputPath); int verticalAlignment = CellVerticalAlignment.TOP; if (alignmentDesc.contains("居中")) { verticalAlignment = CellVerticalAlignment.CENTER; } else if (alignmentDesc.contains("底端")) { verticalAlignment = CellVerticalAlignment.BOTTOM; } for (Section section : doc.getSections()) { NodeCollection tables = section.getBody().getChildNodes(NodeType.TABLE, true); for (int i = 0; i < tables.getCount(); i++) { Table table = (Table) tables.get(i); for (Row row : table.getRows()) { for (Cell cell : row.getCells()) { cell.getCellFormat().setVerticalAlignment(verticalAlignment); } } } } doc.save(outputPath); } ``` **Aspose API**: - `CellFormat.setVerticalAlignment(CellVerticalAlignment.TOP)` - 顶端对齐 - `CellFormat.setVerticalAlignment(CellVerticalAlignment.CENTER)` - 居中 - `CellFormat.setVerticalAlignment(CellVerticalAlignment.BOTTOM)` - 底端对齐 **业务价值**: ⭐⭐⭐⭐ (中高) --- #### 3.3 表格边框 (borderWidth/borderColor) **检查内容**: 表格边框宽度或颜色不符合要求 **自动修正方法**: ```java public static void fixTableBorders(String inputPath, String outputPath, double borderWidth, java.awt.Color borderColor) throws Exception { Document doc = new Document(inputPath); for (Section section : doc.getSections()) { NodeCollection tables = section.getBody().getChildNodes(NodeType.TABLE, true); for (int i = 0; i < tables.getCount(); i++) { Table table = (Table) tables.get(i); // 设置表格所有边框 BorderCollection borders = table.getFirstRow().getRowFormat().getBorders(); for (Border border : borders) { border.setLineWidth(borderWidth); border.setColor(borderColor); border.setLineStyle(LineStyle.SINGLE); } // 设置每个单元格边框 for (Row row : table.getRows()) { for (Cell cell : row.getCells()) { BorderCollection cellBorders = cell.getCellFormat().getBorders(); for (Border border : cellBorders) { border.setLineWidth(borderWidth); border.setColor(borderColor); border.setLineStyle(LineStyle.SINGLE); } } } } } doc.save(outputPath); } ``` **Aspose API**: - `Border.setLineWidth(double points)` - 设置边框宽度 - `Border.setColor(java.awt.Color color)` - 设置边框颜色 - `Border.setLineStyle(LineStyle.SINGLE)` - 设置边框样式 **业务价值**: ⭐⭐⭐⭐ (中高) --- ### 4. ImageRequirementsExamine - 图片要求检查 #### 4.1 图片文字环绕 (wrapText) **检查内容**: 图片文字环绕方式不符合要求 **自动修正方法**: ```java public static void fixImageWrapText(String inputPath, String outputPath, String wrapTextDesc) throws Exception { Document doc = new Document(inputPath); int wrapType = WrapType.INLINE; if (wrapTextDesc.contains("四周")) { wrapType = WrapType.SQUARE; } else if (wrapTextDesc.contains("紧密")) { wrapType = WrapType.TIGHT; } else if (wrapTextDesc.contains("穿越")) { wrapType = WrapType.THROUGH; } else if (wrapTextDesc.contains("上下")) { wrapType = WrapType.TOP_BOTTOM; } else if (wrapTextDesc.contains("衬于文字下方")) { wrapType = WrapType.NONE; // Behind text } else if (wrapTextDesc.contains("浮于文字上方")) { wrapType = WrapType.NONE; // In front of text } NodeCollection shapes = doc.getChildNodes(NodeType.SHAPE, true); for (int i = 0; i < shapes.getCount(); i++) { Shape shape = (Shape) shapes.get(i); if (shape.hasImage()) { shape.setWrapType(wrapType); } } doc.save(outputPath); } ``` **Aspose API**: - `Shape.setWrapType(WrapType.INLINE)` - 嵌入型 - `Shape.setWrapType(WrapType.SQUARE)` - 四周型 - `Shape.setWrapType(WrapType.TIGHT)` - 紧密型 - `Shape.setWrapType(WrapType.THROUGH)` - 穿越型 - `Shape.setWrapType(WrapType.TOP_BOTTOM)` - 上下型 **业务价值**: ⭐⭐⭐⭐ (中高) --- ### 5. PageNumberRequirementsExamine - 页码要求检查 #### 5.1 页码字体 (中文/西文/字号) **检查内容**: 页码字体不符合要求 **自动修正方法**: ```java public static void fixPageNumberFont(String inputPath, String outputPath, String chineseFont, String westernFont, double fontSize) throws Exception { Document doc = new Document(inputPath); for (Section section : doc.getSections()) { HeaderFooterCollection headersFooters = section.getHeadersFooters(); for (HeaderFooter headerFooter : headersFooters) { for (Paragraph paragraph : headerFooter.getParagraphs()) { for (Run run : paragraph.getRuns()) { Font font = run.getFont(); font.setNameFarEast(chineseFont); // 中文字体 font.setNameAscii(westernFont); // 西文字体 font.setSize(fontSize); // 字号 } } } } doc.save(outputPath); } ``` **Aspose API**: 同字体设置 **业务价值**: ⭐⭐⭐ (中) --- #### 5.2 页码编号格式 (numberingFormat) **检查内容**: 页码编号格式不符合要求 **自动修正方法**: ```java public static void fixPageNumberFormat(String inputPath, String outputPath, String formatDesc) throws Exception { Document doc = new Document(inputPath); int numberStyle = NumberStyle.ARABIC; if (formatDesc.contains("I,II,III")) { numberStyle = NumberStyle.UPPERCASE_ROMAN; } else if (formatDesc.contains("i,ii,iii")) { numberStyle = NumberStyle.LOWERCASE_ROMAN; } else if (formatDesc.contains("一,二,三")) { numberStyle = NumberStyle.CHINESE_COUNTING; } for (Section section : doc.getSections()) { section.getPageSetup().setPageNumberStyle(numberStyle); } doc.save(outputPath); } ``` **Aspose API**: - `PageSetup.setPageNumberStyle(NumberStyle.ARABIC)` - 阿拉伯数字 1,2,3 - `PageSetup.setPageNumberStyle(NumberStyle.UPPERCASE_ROMAN)` - 罗马数字 I,II,III - `PageSetup.setPageNumberStyle(NumberStyle.LOWERCASE_ROMAN)` - 罗马数字 i,ii,iii - `PageSetup.setPageNumberStyle(NumberStyle.CHINESE_COUNTING)` - 中文数字 一,二,三 **业务价值**: ⭐⭐⭐ (中) --- ### 6. TocRequirementsExamine - 目录要求检查 #### 6.1 目录字体/段落格式 **检查内容**: 目录的字体、行距、缩进等不符合要求 **自动修正方法**: ```java public static void fixTocFormatting(String inputPath, String outputPath, String chineseFont, String westernFont, double fontSize, double lineSpacing, double leftIndent) throws Exception { Document doc = new Document(inputPath); for (Section section : doc.getSections()) { for (Paragraph paragraph : section.getBody().getParagraphs()) { String styleName = paragraph.getParagraphFormat().getStyleName(); // 只处理目录样式的段落 if (styleName != null && (styleName.toLowerCase().contains("toc") || styleName.toLowerCase().contains("目录"))) { // 设置字体 for (Run run : paragraph.getRuns()) { run.getFont().setNameFarEast(chineseFont); run.getFont().setNameAscii(westernFont); run.getFont().setSize(fontSize); } // 设置段落格式 ParagraphFormat format = paragraph.getParagraphFormat(); format.setLineSpacing(lineSpacing); format.setLeftIndent(leftIndent); } } } doc.save(outputPath); } ``` **Aspose API**: 同字体和段落格式设置 **业务价值**: ⭐⭐⭐ (中) --- ### 7. DefaultChecksExamine - 默认检查 #### 7.1 字体样式 (加粗/下划线/倾斜/删除线/着重号) **检查内容**: 不允许使用加粗、下划线等样式 **自动修正方法**: ```java public static void removeTextFormatting(String inputPath, String outputPath) throws Exception { Document doc = new Document(inputPath); for (Section section : doc.getSections()) { for (Paragraph paragraph : section.getBody().getParagraphs()) { for (Run run : paragraph.getRuns()) { Font font = run.getFont(); font.setBold(false); // 取消加粗 font.setUnderline(Underline.NONE); // 取消下划线 font.setItalic(false); // 取消倾斜 font.setStrikeThrough(false); // 取消删除线 font.setEmphasisMark(EmphasisMark.NONE); // 取消着重号 } } } doc.save(outputPath); } ``` **Aspose API**: - `Font.setBold(boolean value)` - 加粗 - `Font.setUnderline(Underline.NONE)` - 下划线 - `Font.setItalic(boolean value)` - 倾斜 - `Font.setStrikeThrough(boolean value)` - 删除线 - `Font.setEmphasisMark(EmphasisMark.NONE)` - 着重号 **业务价值**: ⭐⭐⭐⭐ (中高) --- #### 7.2 字体颜色 (allowedColor) **检查内容**: 字体颜色不符合要求 **自动修正方法**: ```java public static void fixFontColor(String inputPath, String outputPath, java.awt.Color targetColor) throws Exception { Document doc = new Document(inputPath); for (Section section : doc.getSections()) { for (Paragraph paragraph : section.getBody().getParagraphs()) { for (Run run : paragraph.getRuns()) { run.getFont().setColor(targetColor); } } } doc.save(outputPath); } ``` **Aspose API**: - `Font.setColor(java.awt.Color color)` - 设置字体颜色 - 常用颜色: `Color.BLACK`, `Color.RED`, `new Color(0, 0, 0)` **业务价值**: ⭐⭐⭐ (中) --- #### 7.3 文档网格 (requireSnapToGrid) **检查内容**: 文档网格设置不符合要求 **自动修正方法**: ```java public static void fixDocumentGrid(String inputPath, String outputPath, String gridType) throws Exception { Document doc = new Document(inputPath); int layoutMode = SectionLayoutMode.DEFAULT; if (gridType.contains("只指定行网格")) { layoutMode = SectionLayoutMode.LINE_GRID; } else if (gridType.contains("文字对齐字符网格")) { layoutMode = SectionLayoutMode.SNAP_TO_CHARS; } for (Section section : doc.getSections()) { section.getPageSetup().setLayoutMode(layoutMode); } doc.save(outputPath); } ``` **Aspose API**: - `PageSetup.setLayoutMode(SectionLayoutMode.DEFAULT)` - 无网格 - `PageSetup.setLayoutMode(SectionLayoutMode.LINE_GRID)` - 只指定行网格 - `PageSetup.setLayoutMode(SectionLayoutMode.SNAP_TO_CHARS)` - 文字对齐字符网格 **业务价值**: ⭐⭐⭐ (中) --- ## ❌ 无法自动修正的检查项 (只读检查) ### 1. ColorRequirementsExamine - 颜色要求检查 #### 1.1 彩色图片检测 (disallowColoredImages) **检查内容**: 文档不允许包含彩色图片 **无法自动修正的原因**: - Aspose.Words 不支持图片灰度转换 - 需要使用图像处理库(如 ImageMagick, Java ImageIO) - 业务逻辑复杂: 是否保留原图尺寸、质量、格式 **建议方案**: - 集成第三方图像处理库 - 提取图片 → 转换为灰度 → 替换回文档 **业务价值**: ⭐⭐⭐ (中 - 需求较少) --- #### 1.2 彩色文本检测 (disallowColoredText) **检查内容**: 文档不允许包含彩色文本 **技术上可修正但业务逻辑不明确**: - 可以通过 `Font.setColor(Color.BLACK)` 修改为黑色 - 但检查项是"不允许彩色",没有明确要改成什么颜色 - 需要业务确认: 统一改为黑色? 还是保持检测? **建议**: 归入"可自动修正",统一改为黑色 --- #### 1.3 彩色表格检测 (disallowColoredTables) **检查内容**: 表格不允许包含彩色背景或边框 **同上,技术可行但业务逻辑需确认** --- ### 2. TableRequirementsExamine - 表格要求检查 #### 2.1 不允许出现表格 (disallowTables) **检查内容**: 文档不允许包含表格 **无法自动修正的原因**: - 删除表格需要业务决策: 是否保留表格内容? - 将表格转换为普通文本会丢失结构信息 - 业务影响大,不适合自动化 **建议方案**: 仅检测,人工处理 --- #### 2.2 表格标题要求 (tableTitle) **检查内容**: 表格缺少标题 **无法自动修正的原因**: - 无法自动生成有意义的标题 - 标题内容需要人工编写 **建议方案**: 仅检测,人工补充标题 --- ### 3. ImageRequirementsExamine - 图片要求检查 #### 3.1 不允许出现图片 (disallowImages) **检查内容**: 文档不允许包含图片 **无法自动修正的原因**: - 删除图片需要业务决策 - 业务影响大,不适合自动化 **建议方案**: 仅检测,人工处理 --- ### 4. DefaultChecksExamine - 默认检查 #### 4.1 不允许超链接 (disallowHyperlinks) **检查内容**: 文档不允许包含超链接 **技术上可修正但需业务确认**: ```java // 可以移除超链接但保留显示文本 for (Field field : doc.getRange().getFields()) { if (field.getType() == FieldType.FIELD_HYPERLINK) { field.unlink(); // 移除超链接,保留文本 } } ``` **建议**: 归入"可自动修正" - 移除超链接保留文本 --- #### 4.2 不允许图形 (disallowShapes) **检查内容**: 文档不允许包含图形(非图片的Shape对象) **无法自动修正的原因**: - 删除图形需要业务决策 - 图形可能包含重要信息(如流程图、组织架构图) **建议方案**: 仅检测,人工处理 --- #### 4.3 不允许水印 (disallowWatermark) **检查内容**: 文档不允许包含水印 **技术上可修正**: ```java // 可以删除水印 for (Section section : doc.getSections()) { HeaderFooterCollection headers = section.getHeadersFooters(); for (HeaderFooter header : headers) { NodeCollection shapes = header.getChildNodes(NodeType.SHAPE, true); for (int i = shapes.getCount() - 1; i >= 0; i--) { Shape shape = (Shape) shapes.get(i); if (shape.getName() != null && shape.getName().toLowerCase().contains("watermark")) { shape.remove(); } } } } ``` **建议**: 归入"可自动修正" - 删除水印 --- ### 5. PageNumberRequirementsExamine - 页码要求检查 #### 5.1 不允许插入页码 (disallowPageNumbers) **检查内容**: 文档不允许包含页码 **技术上可修正**: ```java // 可以删除所有页码字段 for (Section section : doc.getSections()) { HeaderFooterCollection headersFooters = section.getHeadersFooters(); for (HeaderFooter headerFooter : headersFooters) { for (Field field : headerFooter.getRange().getFields()) { if (field.getType() == FieldType.FIELD_PAGE) { field.remove(); } } } } ``` **建议**: 归入"可自动修正" - 删除页码 --- #### 5.2 页码范围检查 (缺少页码) **检查内容**: 某些页面缺少页码 **无法自动修正的原因**: - 无法自动判断应该在哪个位置插入页码(页眉?页脚?) - 页码格式、起始编号等需要业务确认 **建议方案**: 仅检测,人工添加页码 --- ### 6. TocRequirementsExamine - 目录要求检查 #### 6.1 不允许插入目录 (disallowToc) **检查内容**: 文档不允许包含目录 **技术上可修正**: ```java // 可以删除目录字段 for (Field field : doc.getRange().getFields()) { if (field.getType() == FieldType.FIELD_TOC) { field.remove(); } } ``` **建议**: 归入"可自动修正" - 删除目录 --- #### 6.2 目录不显示页码 (tocHidePageNumbers) **检查内容**: 目录不应显示页码 **技术复杂度高**: - 需要更新TOC字段代码,移除 `\h` 或 `\p` 开关 - 需要调用 `field.update()` 刷新目录 - 可能影响目录结构 **建议**: 归入"可自动修正" (中等难度) --- ### 7. ProhibitedItemsExamine - 不允许出现项目检查 #### 7.1 不允许空行 (disallowBlankLines) **检查内容**: 文档不允许包含空行 **无法自动修正的原因**: - 业务逻辑不明确: 删除所有空行?还是只删除连续空行? - 某些空行可能有排版意义(如章节分隔) - 删除空行可能影响文档结构 **建议方案**: 仅检测,人工处理 --- #### 7.2 不允许空格 (disallowSpaces) **检查内容**: 文档不允许包含空格 **技术上可修正但业务影响大**: ```java // 可以删除所有空格 for (Run run : ...) { String text = run.getText(); run.setText(text.replaceAll(" ", "").replaceAll("\u3000", "")); } ``` **无法自动修正的原因**: - 删除所有空格会导致中英文混排错误 - 可能破坏文档可读性(如"Hello World" → "HelloWorld") **建议方案**: 仅检测,人工处理 --- #### 7.3 不允许空白页 (disallowBlankPages) **检查内容**: 文档不允许包含空白页 **无法自动修正的原因**: - 空白页可能是分节符、分页符导致的 - 删除空白页可能影响文档结构(如封面后的空白页) - 需要业务确认是否保留 **建议方案**: 仅检测,人工处理 --- #### 7.4 不允许半角标点 (disallowHalfwidthPunctuation) **检查内容**: 文档不允许包含半角标点符号 **技术上可修正**: ```java // 可以将半角标点替换为全角 Map map = new HashMap<>(); map.put("!", "!"); map.put("\"", """); map.put("'", "'"); map.put("(", "("); map.put(")", ")"); map.put(",", ","); map.put(":", ":"); map.put(";", ";"); map.put("?", "?"); for (Run run : ...) { String text = run.getText(); for (Map.Entry entry : map.entrySet()) { text = text.replace(entry.getKey(), entry.getValue()); } run.setText(text); } ``` **建议**: 归入"可自动修正" - 半角转全角 --- ## 📊 总结统计 ### 可自动修正的检查项: 28项 | 检查类别 | 可修正项数 | 主要修正内容 | |---------|-----------|------------| | PaperRequirementsExamine | 6 | 纸张大小、方向、四边边距 | | ContentRequirementsExamine | 10 | 字体(中文/西文/字号)、行距、段前/段后间距、对齐、缩进 | | TableRequirementsExamine | 3 | 表格对齐、单元格垂直对齐、边框 | | ImageRequirementsExamine | 1 | 图片文字环绕 | | PageNumberRequirementsExamine | 2 | 页码字体、编号格式 | | TocRequirementsExamine | 1 | 目录字体/段落格式 | | DefaultChecksExamine | 5 | 字体样式(加粗/下划线等)、字体颜色、文档网格 | ### 无法自动修正的检查项: 12项 | 检查类别 | 无法修正项数 | 主要原因 | |---------|-------------|---------| | ColorRequirementsExamine | 1 | 图片灰度转换需要第三方库 | | TableRequirementsExamine | 2 | 删除表格/生成标题需要业务决策 | | ImageRequirementsExamine | 1 | 删除图片需要业务决策 | | DefaultChecksExamine | 2 | 删除图形需要业务决策 | | PageNumberRequirementsExamine | 1 | 添加页码需要业务决策 | | ProhibitedItemsExamine | 4 | 删除空行/空格/空白页影响大 | | TocRequirementsExamine | 1 | 删除目录需要业务决策 | ### 可选实现的检查项(技术可行但需业务确认): 7项 | 检查项 | 建议处理方式 | |-------|------------| | 彩色文本 | 统一改为黑色 | | 彩色表格 | 移除背景色和边框颜色 | | 超链接 | 移除超链接保留文本 | | 水印 | 删除水印 | | 页码(不允许) | 删除所有页码 | | 目录(不允许) | 删除目录 | | 半角标点 | 半角转全角 | --- ## 🔧 实现建议 ### 1. 创建统一的文档修正工具类 ```java package org.dromara.review.utils; import com.aspose.words.*; import java.awt.Color; /** * 文档自动修正工具类 * 基于 Aspose.Words API 实现文档格式自动修正 */ public class DocumentAutoCorrector { /** * 修正纸张大小和方向 */ public static void fixPaperSettings(Document doc, PaperSize size, Orientation orientation) throws Exception { for (Section section : doc.getSections()) { PageSetup pageSetup = section.getPageSetup(); pageSetup.setPaperSize(size); pageSetup.setOrientation(orientation); } } /** * 修正页边距 */ public static void fixMargins(Document doc, double top, double bottom, double left, double right) throws Exception { for (Section section : doc.getSections()) { PageSetup pageSetup = section.getPageSetup(); pageSetup.setTopMargin(top); pageSetup.setBottomMargin(bottom); pageSetup.setLeftMargin(left); pageSetup.setRightMargin(right); } } /** * 修正字体(中文/西文/字号) */ public static void fixFont(Document doc, String chineseFont, String westernFont, double fontSize) throws Exception { for (Section section : doc.getSections()) { for (Paragraph paragraph : section.getBody().getParagraphs()) { for (Run run : paragraph.getRuns()) { Font font = run.getFont(); if (chineseFont != null) font.setNameFarEast(chineseFont); if (westernFont != null) font.setNameAscii(westernFont); if (fontSize > 0) font.setSize(fontSize); } } } } /** * 修正段落格式(行距/对齐/缩进) */ public static void fixParagraphFormat(Document doc, double lineSpacing, int lineSpacingRule, int alignment, double leftIndent, double rightIndent, double firstLineIndent) throws Exception { for (Section section : doc.getSections()) { for (Paragraph paragraph : section.getBody().getParagraphs()) { ParagraphFormat format = paragraph.getParagraphFormat(); if (lineSpacing > 0) { format.setLineSpacingRule(lineSpacingRule); format.setLineSpacing(lineSpacing); } if (alignment >= 0) format.setAlignment(alignment); if (leftIndent >= 0) format.setLeftIndent(leftIndent); if (rightIndent >= 0) format.setRightIndent(rightIndent); if (firstLineIndent != 0) format.setFirstLineIndent(firstLineIndent); } } } /** * 修正表格格式(对齐/边框) */ public static void fixTableFormat(Document doc, int tableAlignment, int cellVerticalAlignment, double borderWidth, Color borderColor) throws Exception { for (Section section : doc.getSections()) { NodeCollection tables = section.getBody().getChildNodes(NodeType.TABLE, true); for (int i = 0; i < tables.getCount(); i++) { Table table = (Table) tables.get(i); if (tableAlignment >= 0) table.setAlignment(tableAlignment); for (Row row : table.getRows()) { for (Cell cell : row.getCells()) { if (cellVerticalAlignment >= 0) { cell.getCellFormat().setVerticalAlignment(cellVerticalAlignment); } if (borderWidth > 0) { BorderCollection borders = cell.getCellFormat().getBorders(); for (Border border : borders) { border.setLineWidth(borderWidth); if (borderColor != null) border.setColor(borderColor); border.setLineStyle(LineStyle.SINGLE); } } } } } } } /** * 修正图片文字环绕 */ public static void fixImageWrapText(Document doc, int wrapType) throws Exception { NodeCollection shapes = doc.getChildNodes(NodeType.SHAPE, true); for (int i = 0; i < shapes.getCount(); i++) { Shape shape = (Shape) shapes.get(i); if (shape.hasImage()) { shape.setWrapType(wrapType); } } } /** * 移除文本格式(加粗/下划线/倾斜等) */ public static void removeTextFormatting(Document doc) throws Exception { for (Section section : doc.getSections()) { for (Paragraph paragraph : section.getBody().getParagraphs()) { for (Run run : paragraph.getRuns()) { Font font = run.getFont(); font.setBold(false); font.setUnderline(Underline.NONE); font.setItalic(false); font.setStrikeThrough(false); font.setEmphasisMark(EmphasisMark.NONE); } } } } /** * 综合修正方法 - 根据检查结果一次性修正多个问题 */ public static void autoCorrect(String inputPath, String outputPath, CorrectionConfig config) throws Exception { Document doc = new Document(inputPath); // 修正纸张设置 if (config.shouldFixPaper()) { fixPaperSettings(doc, config.getPaperSize(), config.getOrientation()); fixMargins(doc, config.getTopMargin(), config.getBottomMargin(), config.getLeftMargin(), config.getRightMargin()); } // 修正字体 if (config.shouldFixFont()) { fixFont(doc, config.getChineseFont(), config.getWesternFont(), config.getFontSize()); } // 修正段落格式 if (config.shouldFixParagraph()) { fixParagraphFormat(doc, config.getLineSpacing(), config.getLineSpacingRule(), config.getAlignment(), config.getLeftIndent(), config.getRightIndent(), config.getFirstLineIndent()); } // 修正表格格式 if (config.shouldFixTable()) { fixTableFormat(doc, config.getTableAlignment(), config.getCellVerticalAlignment(), config.getBorderWidth(), config.getBorderColor()); } // 修正图片环绕 if (config.shouldFixImage()) { fixImageWrapText(doc, config.getWrapType()); } // 移除文本格式 if (config.shouldRemoveTextFormatting()) { removeTextFormatting(doc); } doc.save(outputPath); } } /** * 修正配置类 */ class CorrectionConfig { // 纸张设置 private boolean fixPaper; private PaperSize paperSize; private Orientation orientation; private double topMargin, bottomMargin, leftMargin, rightMargin; // 字体设置 private boolean fixFont; private String chineseFont, westernFont; private double fontSize; // 段落设置 private boolean fixParagraph; private double lineSpacing; private int lineSpacingRule, alignment; private double leftIndent, rightIndent, firstLineIndent; // 表格设置 private boolean fixTable; private int tableAlignment, cellVerticalAlignment; private double borderWidth; private Color borderColor; // 图片设置 private boolean fixImage; private int wrapType; // 其他设置 private boolean removeTextFormatting; // Getters and Setters... } ``` --- ### 2. 集成到现有检查流程 修改 `DocExamine.java`: ```java public class DocExamine { /** * 执行检查并收集可自动修正的问题 */ public Map examineAndCollectCorrections(Document doc, CheckConfig config) { Map result = new HashMap<>(); Map> issues = new HashMap<>(); CorrectionConfig correctionConfig = new CorrectionConfig(); // 执行各项检查 // ... 现有检查逻辑 ... // 根据检查结果填充 correctionConfig if (hasIssue(issues, "paperRequirements", "paperSize")) { correctionConfig.setFixPaper(true); correctionConfig.setPaperSize(config.getPaperSize()); } // ... 其他检查项 ... result.put("issues", issues); result.put("correctionConfig", correctionConfig); result.put("canAutoCorrect", correctionConfig.hasAnyCorrection()); return result; } /** * 一键自动修正 */ public void autoCorrect(String inputPath, String outputPath, CorrectionConfig config) throws Exception { DocumentAutoCorrector.autoCorrect(inputPath, outputPath, config); } } ``` --- ### 3. 前端交互流程 ``` 1. 用户上传文档 ↓ 2. 后端执行检查,返回检查结果 + 可自动修正项列表 ↓ 3. 前端展示: - ✅ 可自动修正: [纸张大小、字体、行距...] (绿色,带"一键修正"按钮) - ❌ 需要人工处理: [删除表格、添加标题...] (黄色,提示手动处理) ↓ 4. 用户点击"一键修正" ↓ 5. 后端调用 DocumentAutoCorrector.autoCorrect() ↓ 6. 返回修正后的文档下载链接 ↓ 7. (可选)用户下载修正后文档,手动处理剩余问题后重新上传 ``` --- ## 📝 实施优先级建议 ### 高优先级 (⭐⭐⭐⭐⭐) 1. **纸张大小和方向** - 最常见需求 2. **页边距** - 标书必备 3. **字体(中文/西文/字号)** - 标书必备 4. **行距** - 常见需求 5. **段落对齐和缩进** - 常见需求 ### 中优先级 (⭐⭐⭐⭐) 6. **表格对齐和边框** - 提升文档美观度 7. **图片文字环绕** - 改善排版 8. **移除文本格式** - 规范化文档 9. **字体颜色** - 规范化需求 ### 低优先级 (⭐⭐⭐) 10. **页码格式** - 需求较少 11. **目录格式** - 需求较少 12. **文档网格** - 专业需求 --- ## ⚠️ 注意事项 ### 1. 文档备份 - 自动修正前务必备份原文档 - 提供"撤销修正"功能 ### 2. 修正范围控制 - 支持按页/按节/全文修正 - 避免影响封面、目录等特殊页面 ### 3. 性能优化 - 大文档(>100页)分批处理 - 提供进度条反馈 ### 4. 异常处理 - 捕获 Aspose.Words 异常 - 提供友好的错误提示 ### 5. 测试覆盖 - 准备各种格式的测试文档 - 测试修正前后文档的一致性 --- ## 📚 相关资源 - [Aspose.Words Java API 文档](https://reference.aspose.com/words/java/) - [PageSetup 类参考](https://reference.aspose.com/words/java/com.aspose.words/pagesetup/) - [Font 类参考](https://reference.aspose.com/words/java/com.aspose.words/font/) - [ParagraphFormat 类参考](https://reference.aspose.com/words/java/com.aspose.words/paragraphformat/) - [Table 类参考](https://reference.aspose.com/words/java/com.aspose.words/table/) --- **报告生成时间**: 2026-02-11 **分析文件数量**: 8个检查类 **可自动修正检查项**: 28项 **无法自动修正检查项**: 12项 **可选实现检查项**: 7项