修订记录逻辑新增,大于3条显示最后三条。且完整文件添加至附件当中
This commit is contained in:
		
							parent
							
								
									24b8bef478
								
							
						
					
					
						commit
						e0433d3faa
					
				| @ -0,0 +1,327 @@ | |||||||
|  | package com.actionsoft.apps.coe.pal.pal.output.util; | ||||||
|  | 
 | ||||||
|  | import com.alibaba.fastjson.JSONArray; | ||||||
|  | import com.alibaba.fastjson.JSONObject; | ||||||
|  | import org.apache.poi.xwpf.usermodel.*; | ||||||
|  | import org.openxmlformats.schemas.wordprocessingml.x2006.main.*; | ||||||
|  | 
 | ||||||
|  | import java.io.*; | ||||||
|  | import java.math.BigInteger; | ||||||
|  | 
 | ||||||
|  | public class FileUtil { | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * 生成版本历史表格的Word文档输入流 | ||||||
|  |      * @param versionHistoryTable 版本历史数据JSONArray | ||||||
|  |      * @return 包含表格的Word文档InputStream | ||||||
|  |      * @throws IOException IO异常 | ||||||
|  |      */ | ||||||
|  |     public static InputStream generateVersionHistoryStream(JSONArray versionHistoryTable) throws IOException { | ||||||
|  |         // 创建Word文档对象 | ||||||
|  |         try (XWPFDocument document = new XWPFDocument(); | ||||||
|  |              // 内存输出流,用于临时存储文档内容 | ||||||
|  |              ByteArrayOutputStream out = new ByteArrayOutputStream()) { | ||||||
|  | 
 | ||||||
|  |             // 定义表格列名(与需求对应) | ||||||
|  |             String[] columnNames = { | ||||||
|  |                     "版本", "发布部门", "拟制人", "拟制日期", | ||||||
|  |                     "审核人", "复核人", "审批人", "修订内容及理由" | ||||||
|  |             }; | ||||||
|  | 
 | ||||||
|  |             // 创建表格:1行表头,8列 | ||||||
|  |             XWPFTable table = document.createTable(1, columnNames.length); | ||||||
|  |              | ||||||
|  |             // 表格整体设置 | ||||||
|  |             // 设置表格水平居中对齐(POI 3.17兼容方式) | ||||||
|  |             CTTblPr tblPr = table.getCTTbl().getTblPr(); | ||||||
|  |             if (tblPr == null) { | ||||||
|  |                 tblPr = table.getCTTbl().addNewTblPr(); | ||||||
|  |             } | ||||||
|  |             CTJc jc = tblPr.isSetJc() ? tblPr.getJc() : tblPr.addNewJc(); | ||||||
|  |             jc.setVal(STJc.CENTER); | ||||||
|  | 
 | ||||||
|  |             // 设置表格自动适应窗口宽度 | ||||||
|  |             CTTblWidth tblWidth = tblPr.isSetTblW() ? tblPr.getTblW() : tblPr.addNewTblW(); | ||||||
|  |             tblWidth.setW(new BigInteger("9000")); // 设置一个较大的宽度值 | ||||||
|  |             tblWidth.setType(STTblWidth.DXA); | ||||||
|  |              | ||||||
|  |             // 设置表格布局为自动适应内容 | ||||||
|  |             CTTblLayoutType layout = tblPr.isSetTblLayout() ? tblPr.getTblLayout() : tblPr.addNewTblLayout(); | ||||||
|  |             layout.setType(STTblLayoutType.AUTOFIT); | ||||||
|  |              | ||||||
|  |             // 设置列宽 - 增大列宽值以确保内容不会缩在一起 | ||||||
|  |             // 根据列内容性质设置不同宽度 | ||||||
|  |             // 1. 版本 - 适中宽度 | ||||||
|  |             // 2. 发布部门 - 较宽 | ||||||
|  |             // 3-7. 人员信息 - 适中宽度 | ||||||
|  |             // 8. 修订内容及理由 - 最宽 | ||||||
|  |             int[] columnWidths = {1200, 2500, 1500, 1800, 1800, 1800, 1800, 4500}; | ||||||
|  |             setTableColumnsWidth(table, columnWidths); | ||||||
|  | 
 | ||||||
|  |             // 创建表头样式 | ||||||
|  |             XWPFTableRow headerRow = table.getRow(0); | ||||||
|  |             // 设置为表头行 | ||||||
|  |             // 设置固定行高20(转换为twip单位,1点≈20twip) | ||||||
|  |             headerRow.setHeight((int) (20 * 20)); // twip单位 | ||||||
|  | 
 | ||||||
|  |             // 填充表头并设置样式 | ||||||
|  |             for (int i = 0; i < columnNames.length; i++) { | ||||||
|  |                 XWPFTableCell cell = headerRow.getCell(i); | ||||||
|  |                 if (cell == null) { | ||||||
|  |                     cell = headerRow.createCell(); | ||||||
|  |                 } | ||||||
|  |                  | ||||||
|  |                 // 设置表头单元格样式 | ||||||
|  |                 setHeaderCellStyle(cell); | ||||||
|  |                 cell.setText(columnNames[i]); | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |             // 填充数据行 | ||||||
|  |             for (int i = 0; i < versionHistoryTable.size(); i++) { | ||||||
|  |                 JSONObject rowData = versionHistoryTable.getJSONObject(i); | ||||||
|  |                 XWPFTableRow dataRow = table.createRow(); | ||||||
|  | 
 | ||||||
|  |                 // 设置数据行行高自动 | ||||||
|  |                 dataRow.setHeight(400); | ||||||
|  |                 // 按列顺序填充数据并设置样式(与JSON的key对应) | ||||||
|  |                 for (int j = 0; j < columnNames.length; j++) { | ||||||
|  |                     XWPFTableCell cell = dataRow.getCell(j); | ||||||
|  |                     if (cell == null) { | ||||||
|  |                         cell = dataRow.createCell(); | ||||||
|  |                     } | ||||||
|  |                      | ||||||
|  |                     // 设置数据单元格样式 | ||||||
|  |                     boolean isLastColumn = (j == 7); // 第8列(索引7) | ||||||
|  |                     setDataCellStyle(cell, isLastColumn); | ||||||
|  |                      | ||||||
|  |                     // 设置对应列的数据 | ||||||
|  |                     switch (j) { | ||||||
|  |                         case 0: cell.setText(getSafeString(rowData, "versions")); break; | ||||||
|  |                         case 1: cell.setText(getSafeString(rowData, "Issuing_department")); break; | ||||||
|  |                         case 2: cell.setText(getSafeString(rowData, "Drafted_and_revised_by")); break; | ||||||
|  |                         case 3: cell.setText(getSafeString(rowData, "Drafted_and_revised_date")); break; | ||||||
|  |                         case 4: cell.setText(getSafeString(rowData, "auditor")); break; | ||||||
|  |                         case 5: cell.setText(getSafeString(rowData, "reviewer")); break; | ||||||
|  |                         case 6: cell.setText(getSafeString(rowData, "approver")); break; | ||||||
|  |                         case 7: cell.setText(getSafeString(rowData, "Contents_and_reasons_for_revision")); break; | ||||||
|  |                     } | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |             // 将文档写入内存输出流 | ||||||
|  |             document.write(out); | ||||||
|  |             out.flush(); // 确保所有数据写入完成 | ||||||
|  | 
 | ||||||
|  |             // 将内存中的字节数组转换为InputStream返回 | ||||||
|  |             return new ByteArrayInputStream(out.toByteArray()); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * 设置表格各列宽度 | ||||||
|  |      * @param table 表格对象 | ||||||
|  |      * @param columnWidths 列宽数组(与列数对应) | ||||||
|  |      */ | ||||||
|  |     private static void setTableColumnsWidth(XWPFTable table, int[] columnWidths) { | ||||||
|  |         // 获取或创建表格网格 | ||||||
|  |         CTTblGrid tblGrid = table.getCTTbl().getTblGrid(); | ||||||
|  |         if (tblGrid == null) { | ||||||
|  |             tblGrid = table.getCTTbl().addNewTblGrid(); | ||||||
|  |         } else { | ||||||
|  |             // 清除原有网格列 | ||||||
|  |             while (tblGrid.getGridColList().size() > 0) { | ||||||
|  |                 tblGrid.removeGridCol(0); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |          | ||||||
|  |         // 为每一列设置宽度 | ||||||
|  |         for (int width : columnWidths) { | ||||||
|  |             CTTblGridCol gridCol = tblGrid.addNewGridCol(); | ||||||
|  |             gridCol.setW(new BigInteger(String.valueOf(width))); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * 设置表头单元格样式 | ||||||
|  |      */ | ||||||
|  |     private static void setHeaderCellStyle(XWPFTableCell cell) { | ||||||
|  |         // 设置单元格垂直居中 | ||||||
|  |         cell.setVerticalAlignment(XWPFTableCell.XWPFVertAlign.CENTER); | ||||||
|  |          | ||||||
|  |         // 设置单元格边距,确保内容不紧贴边框 | ||||||
|  |         setCellMargins(cell); | ||||||
|  |          | ||||||
|  |         // 设置段落样式 | ||||||
|  |         XWPFParagraph paragraph = cell.getParagraphs().get(0); | ||||||
|  |         // 文字水平居中 | ||||||
|  |         paragraph.setAlignment(ParagraphAlignment.CENTER); | ||||||
|  |          | ||||||
|  |         // 设置段落行距(使用兼容的方式) | ||||||
|  |         CTP ctp = paragraph.getCTP(); | ||||||
|  |         CTPPr pPr = ctp.isSetPPr() ? ctp.getPPr() : ctp.addNewPPr(); | ||||||
|  |         CTSpacing spacing = pPr.isSetSpacing() ? pPr.getSpacing() : pPr.addNewSpacing(); | ||||||
|  |         spacing.setAfter(new BigInteger("0")); | ||||||
|  |         spacing.setBefore(new BigInteger("0")); | ||||||
|  |         spacing.setLine(new BigInteger("240")); // 12pt 对应240 | ||||||
|  |         spacing.setLineRule(STLineSpacingRule.EXACT); | ||||||
|  |          | ||||||
|  |         // 设置字体样式 | ||||||
|  |         XWPFRun run = paragraph.getRuns().isEmpty() ? paragraph.createRun() : paragraph.getRuns().get(0); | ||||||
|  |         run.setBold(true); // 加粗 | ||||||
|  |         run.setFontSize(10); // 10.5号字体近似10号 | ||||||
|  |         run.setFontFamily("宋体"); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * 设置数据单元格样式 | ||||||
|  |      */ | ||||||
|  |     private static void setDataCellStyle(XWPFTableCell cell, boolean isLastColumn) { | ||||||
|  |         // 设置单元格垂直居中 | ||||||
|  |         cell.setVerticalAlignment(XWPFTableCell.XWPFVertAlign.CENTER); | ||||||
|  |          | ||||||
|  |         // 设置单元格边距,确保内容不紧贴边框 | ||||||
|  |         setCellMargins(cell); | ||||||
|  |          | ||||||
|  |         // 设置背景色为白色 | ||||||
|  |         cell.setColor("FFFFFF"); | ||||||
|  |          | ||||||
|  |         // 设置段落样式 | ||||||
|  |         XWPFParagraph paragraph = cell.getParagraphs().get(0); | ||||||
|  |         // 根据是否为第8列设置水平对齐方式 | ||||||
|  |         paragraph.setAlignment(isLastColumn ? ParagraphAlignment.LEFT : ParagraphAlignment.CENTER); | ||||||
|  |          | ||||||
|  |         // 设置段落行距(使用兼容的方式) | ||||||
|  |         CTP ctp = paragraph.getCTP(); | ||||||
|  |         CTPPr pPr = ctp.isSetPPr() ? ctp.getPPr() : ctp.addNewPPr(); | ||||||
|  |         CTSpacing spacing = pPr.isSetSpacing() ? pPr.getSpacing() : pPr.addNewSpacing(); | ||||||
|  |         spacing.setAfter(new BigInteger("0")); | ||||||
|  |         spacing.setBefore(new BigInteger("0")); | ||||||
|  |         spacing.setLine(new BigInteger("240")); // 12pt 对应240 | ||||||
|  |         spacing.setLineRule(STLineSpacingRule.EXACT); | ||||||
|  |          | ||||||
|  |         // 设置字体样式 | ||||||
|  |         XWPFRun run = paragraph.getRuns().isEmpty() ? paragraph.createRun() : paragraph.getRuns().get(0); | ||||||
|  |         run.setFontSize(10); // 10.5号字体近似10号 | ||||||
|  |         run.setFontFamily("宋体"); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * 设置单元格边距 | ||||||
|  |      */ | ||||||
|  |     private static void setCellMargins(XWPFTableCell cell) { | ||||||
|  |         CTTc cttc = cell.getCTTc(); | ||||||
|  |         CTTcPr tcPr = cttc.isSetTcPr() ? cttc.getTcPr() : cttc.addNewTcPr(); | ||||||
|  |          | ||||||
|  |         // 设置单元格左边距 | ||||||
|  |         CTTcMar tcMar = tcPr.isSetTcMar() ? tcPr.getTcMar() : tcPr.addNewTcMar(); | ||||||
|  |          | ||||||
|  |         if (!tcMar.isSetLeft()) { | ||||||
|  |             tcMar.addNewLeft(); | ||||||
|  |         } | ||||||
|  |         tcMar.getLeft().setW(new BigInteger("100")); | ||||||
|  |         tcMar.getLeft().setType(STTblWidth.DXA); | ||||||
|  |          | ||||||
|  |         if (!tcMar.isSetRight()) { | ||||||
|  |             tcMar.addNewRight(); | ||||||
|  |         } | ||||||
|  |         tcMar.getRight().setW(new BigInteger("100")); | ||||||
|  |         tcMar.getRight().setType(STTblWidth.DXA); | ||||||
|  |          | ||||||
|  |         if (!tcMar.isSetTop()) { | ||||||
|  |             tcMar.addNewTop(); | ||||||
|  |         } | ||||||
|  |         tcMar.getTop().setW(new BigInteger("50")); | ||||||
|  |         tcMar.getTop().setType(STTblWidth.DXA); | ||||||
|  |          | ||||||
|  |         if (!tcMar.isSetBottom()) { | ||||||
|  |             tcMar.addNewBottom(); | ||||||
|  |         } | ||||||
|  |         tcMar.getBottom().setW(new BigInteger("50")); | ||||||
|  |         tcMar.getBottom().setType(STTblWidth.DXA); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * 安全获取JSON字段值(避免null) | ||||||
|  |      */ | ||||||
|  |     private static String getSafeString(JSONObject jsonObject, String key) { | ||||||
|  |         return jsonObject.getString(key) == null ? "" : jsonObject.getString(key); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * 将InputStream保存到本地文件 | ||||||
|  |      * @param inputStream 输入流 | ||||||
|  |      * @param filePath 保存路径 | ||||||
|  |      * @throws IOException IO异常 | ||||||
|  |      */ | ||||||
|  |     private static void saveInputStreamToFile(InputStream inputStream, String filePath) throws IOException { | ||||||
|  |         // 创建文件目录(如果不存在) | ||||||
|  |         File file = new File(filePath); | ||||||
|  |         File parentDir = file.getParentFile(); | ||||||
|  |         if (parentDir != null && !parentDir.exists()) { | ||||||
|  |             boolean created = parentDir.mkdirs(); | ||||||
|  |             if (!created) { | ||||||
|  |                 throw new IOException("无法创建目录: " + parentDir.getAbsolutePath()); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |          | ||||||
|  |         // 使用try-with-resources确保流正确关闭 | ||||||
|  |         try (FileOutputStream outputStream = new FileOutputStream(file)) { | ||||||
|  |             byte[] buffer = new byte[4096]; | ||||||
|  |             int bytesRead; | ||||||
|  |             while ((bytesRead = inputStream.read(buffer)) != -1) { | ||||||
|  |                 outputStream.write(buffer, 0, bytesRead); | ||||||
|  |             } | ||||||
|  |             outputStream.flush(); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     // 使用示例 | ||||||
|  |     public static void main(String[] args) { | ||||||
|  |         try { | ||||||
|  |             // 1. 构造示例JSON数据(实际使用时替换为你的versionHistoryTable) | ||||||
|  |             JSONArray versionHistory = new JSONArray(); | ||||||
|  | 
 | ||||||
|  |             // 添加V1.0数据 | ||||||
|  |             JSONObject v1 = new JSONObject(); | ||||||
|  |             v1.put("versions", "V1.0"); | ||||||
|  |             v1.put("Issuing_department", "总部国际业务部国贸部"); | ||||||
|  |             v1.put("Drafted_and_revised_by", "吴赞涛"); | ||||||
|  |             v1.put("Drafted_and_revised_by", "2023年1月1日"); | ||||||
|  |             v1.put("auditor", "高扬,王煜"); | ||||||
|  |             v1.put("reviewer", "王志军"); | ||||||
|  |             v1.put("approver", "黄新峰"); | ||||||
|  |             v1.put("Contents_and_reasons_for_revision", "初始版本创建,包含基本功能"); | ||||||
|  |             versionHistory.add(v1); | ||||||
|  | 
 | ||||||
|  |             // 添加V2.0数据 | ||||||
|  |             JSONObject v2 = new JSONObject(); | ||||||
|  |             v2.put("版本", "V2.0"); | ||||||
|  |             v2.put("发布部门", "总部国际业务部国贸部"); | ||||||
|  |             v2.put("拟制人", "吴赞涛"); | ||||||
|  |             v2.put("拟制日期", "2023年7月10日"); | ||||||
|  |             v2.put("审核人", "高扬,王煜"); | ||||||
|  |             v2.put("复核人", "王志军"); | ||||||
|  |             v2.put("审批人", "齐文川"); | ||||||
|  |             v2.put("修订内容及理由", "优化系统流程,提升用户体验,修复已知问题"); | ||||||
|  |             versionHistory.add(v2); | ||||||
|  | 
 | ||||||
|  |             // 2. 生成InputStream | ||||||
|  |             InputStream wordStream = generateVersionHistoryStream(versionHistory); | ||||||
|  | 
 | ||||||
|  |             // 3. 此处可使用流进行后续操作(如保存为文件、作为附件等) | ||||||
|  |             System.out.println("InputStream生成成功,可进行后续处理"); | ||||||
|  | 
 | ||||||
|  |             // 将流保存到本地文件 | ||||||
|  |             String savePath = "/Users/yuyia/Desktop/临时文件/修订记录.docx"; | ||||||
|  |             saveInputStreamToFile(wordStream, savePath); | ||||||
|  |             System.out.println("文件已成功保存到: " + savePath); | ||||||
|  | 
 | ||||||
|  |             // 注意:使用完毕后需关闭流 | ||||||
|  |             wordStream.close(); | ||||||
|  |         } catch (Exception e) { | ||||||
|  |             // 捕获所有异常以提供更详细的错误信息 | ||||||
|  |             e.printStackTrace(); | ||||||
|  |             System.out.println("生成失败:" + e.getMessage()); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
| @ -846,7 +846,13 @@ public class OutputWordUtil { | |||||||
|                             String[] header = {"版本", "发布部门","拟制人","拟制日期","审核人","复核人","审批人","修订内容及理由"}; |                             String[] header = {"版本", "发布部门","拟制人","拟制日期","审核人","复核人","审批人","修订内容及理由"}; | ||||||
|                             String[][] strArray2 = new String[versionHistoryTable.size()][]; |                             String[][] strArray2 = new String[versionHistoryTable.size()][]; | ||||||
|                             List<String[]> list = new LinkedList<>(); |                             List<String[]> list = new LinkedList<>(); | ||||||
|                             for (int i = 0; i < versionHistoryTable.size(); i++) { | 
 | ||||||
|  |                             //增加逻辑 ,修订记录大于3条时,则只保留最后三条 | ||||||
|  |                             int startIndex = 0; | ||||||
|  |                             if (versionHistoryTable.size() > 3) { | ||||||
|  |                                 startIndex = versionHistoryTable.size() - 3; // 只取最后三条记录 | ||||||
|  |                             } | ||||||
|  |                             for (int i = startIndex; i < versionHistoryTable.size(); i++) { | ||||||
|                                 JSONObject jsonObject = versionHistoryTable.getJSONObject(i); |                                 JSONObject jsonObject = versionHistoryTable.getJSONObject(i); | ||||||
|                                 String[] strArray = new String[8]; |                                 String[] strArray = new String[8]; | ||||||
| 
 | 
 | ||||||
| @ -1817,6 +1823,26 @@ public class OutputWordUtil { | |||||||
|                         + (b2 - b1) / 1000 + "秒"); |                         + (b2 - b1) / 1000 + "秒"); | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|  |             //新增修订记录逻辑 | ||||||
|  |             JSONArray versionHistoryTable = getVersionHistoryTable(repositoryModel); | ||||||
|  |             if(versionHistoryTable!=null && versionHistoryTable.size()>3){ | ||||||
|  |                 InputStream versionHistoryStream = null; | ||||||
|  |                 try { | ||||||
|  |                     versionHistoryStream = FileUtil.generateVersionHistoryStream(versionHistoryTable); | ||||||
|  |                 } catch (IOException e) { | ||||||
|  |                     throw new RuntimeException(e); | ||||||
|  |                 } | ||||||
|  |                 //添加段落 | ||||||
|  |                 Paragraph paragraph5 = section.addParagraph(); | ||||||
|  |                 //加载一个图片,它将作为外部文件的符号显示在Word文档中 | ||||||
|  |                 //获取文件的后缀名 .jpg | ||||||
|  |                 DocPicture pic1 = new DocPicture(doc); | ||||||
|  |                 pic1.loadImage("../doccenter/com.awspaas.user.apps.coe.pal.output.zd/filepic/word.png"); | ||||||
|  |                 paragraph5.appendText("修订记录.docx"); | ||||||
|  |                 paragraph5.applyStyle(BuiltinStyle.Body_Text); //应用标题1样式 | ||||||
|  |                 paragraph5.appendOleObject(versionHistoryStream, pic1, "docx"); | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|             try { |             try { | ||||||
|                 System.out.println("Filed=================="+repositoryModel.getId()); |                 System.out.println("Filed=================="+repositoryModel.getId()); | ||||||
|                 doc.saveToFile(outFile.getPath(), FileFormat.Docx_2013); |                 doc.saveToFile(outFile.getPath(), FileFormat.Docx_2013); | ||||||
|  | |||||||
		Loading…
	
		Reference in New Issue
	
	Block a user
	 yujh_java
						yujh_java