From efd229f59ecd8aae8e1e9764859824a82bf4b111 Mon Sep 17 00:00:00 2001
From: zhangmei <645025773@qq.com>
Date: 星期三, 19 三月 2025 09:50:11 +0800
Subject: [PATCH] 修改邮件
---
ruoyi-admin/src/main/java/com/ruoyi/web/controller/tool/WordUtil.java | 315 +++++++++++++++++++++++++++++++++++++++++++++++-----
1 files changed, 284 insertions(+), 31 deletions(-)
diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/tool/WordUtil.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/tool/WordUtil.java
index 85a55ce..60d821a 100644
--- a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/tool/WordUtil.java
+++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/tool/WordUtil.java
@@ -6,6 +6,7 @@
import freemarker.template.TemplateException;
import lombok.extern.slf4j.Slf4j;
+import org.apache.poi.xwpf.usermodel.*;
import org.springframework.mock.web.MockMultipartFile;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;
@@ -15,7 +16,9 @@
import java.io.*;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
-import java.util.Map;
+import java.util.*;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
@Slf4j
@Component
@@ -101,7 +104,7 @@
fis.read(fileContent);
}
MultipartFile mockMultipartFile = new MockMultipartFile(encodedFileName+".doc", fileContent);
- String s = tencentCosUtil.upLoadFile(mockMultipartFile);
+ String s = tencentCosUtil.upLoadFile(mockMultipartFile,"/wordGenerate");
return s;
} catch (IOException | TemplateException e) {
log.error("生成Word文档异常,异常原因:{}", e.getMessage(), e);
@@ -110,35 +113,38 @@
}
- public String generatePdf(String basePackagePath, String templateFileName, Object templateParam, String fileName, String saveDirectory) {
+ public String generatePdf(String basePackagePath, String templateFileName, Map<String,Object> templateParam, String fileName, String saveDirectory) {
try {
+
+ fillTemplate(basePackagePath+templateFileName, saveDirectory+fileName+".docx", templateParam);
+
// 创建 Freemarker 的 Configuration 对象,设置默认的不兼容改进选项
- Configuration configuration = new Configuration(Configuration.DEFAULT_INCOMPATIBLE_IMPROVEMENTS);
- configuration.setDefaultEncoding("utf-8");
- // 设置模板加载器,加载模板文件
- configuration.setTemplateLoader(new ClassTemplateLoader(getClass(), basePackagePath));
- Template t = configuration.getTemplate(templateFileName, "utf-8");
-
- // 使用 URLEncoder 对文件名进行编码,以防止中文文件名在不同浏览器和操作系统下出现乱码问题
-// String encodedFileName = URLEncoder.encode(fileName + "_" + System.currentTimeMillis(), "utf-8");
- String encodedFileName =fileName ;
-
- // 定义保存文件的路径
- File saveDir = new File(saveDirectory);
- if (!saveDir.exists()) {
- saveDir.mkdirs();
- }
-
- // 定义文件名
- String filePath = saveDir.getAbsolutePath() + File.separator + encodedFileName + ".doc";
-
- // 创建 Writer 对象,用于将生成的文档写到文件中,缓存区大小设为 10KB
- Writer out = new BufferedWriter(new FileWriter(filePath), 10240);
-
- // 将模型数据与模板结合生成 Word 文档,写入到 Writer 对象中
- t.process(templateParam, out);
- out.close();
-
+// Configuration configuration = new Configuration(Configuration.DEFAULT_INCOMPATIBLE_IMPROVEMENTS);
+// configuration.setDefaultEncoding("utf-8");
+// // 设置模板加载器,加载模板文件
+// configuration.setTemplateLoader(new ClassTemplateLoader(getClass(), basePackagePath));
+// Template t = configuration.getTemplate(templateFileName, "utf-8");
+//
+// // 使用 URLEncoder 对文件名进行编码,以防止中文文件名在不同浏览器和操作系统下出现乱码问题
+//// String encodedFileName = URLEncoder.encode(fileName + "_" + System.currentTimeMillis(), "utf-8");
+// String encodedFileName =fileName ;
+//
+// // 定义保存文件的路径
+// File saveDir = new File(saveDirectory);
+// if (!saveDir.exists()) {
+// saveDir.mkdirs();
+// }
+//
+// // 定义文件名
+// String filePath = saveDir.getAbsolutePath() + File.separator + encodedFileName + ".doc";
+//
+// // 创建 Writer 对象,用于将生成的文档写到文件中,缓存区大小设为 10KB
+// Writer out = new BufferedWriter(new FileWriter(filePath), 10240);
+//
+// // 将模型数据与模板结合生成 Word 文档,写入到 Writer 对象中
+// t.process(templateParam, out);
+// out.close();
+ String filePath = saveDirectory + File.separator + fileName + ".docx";
File file = new File(filePath);
// 检查文件是否存在
@@ -152,16 +158,263 @@
fis.read(fileContent);
}
- String test = pdfUtils.test(encodedFileName + ".doc");
+ String test = pdfUtils.test(fileName + ".docx");
// MultipartFile mockMultipartFile = new MockMultipartFile(encodedFileName+".doc", fileContent);
// String s = ObsUploadUtil.obsUpload(mockMultipartFile);
return test;
- } catch (IOException | TemplateException e) {
+ } catch (IOException e) {
log.error("生成pdf异常,异常原因:{}", e.getMessage(), e);
throw new RuntimeException("生成pdf异常,异常原因:" + e.getMessage());
}
}
+ public static void fillTemplate(String templatePath, String outputPath,Map<String, Object> dataMap) {
+ try (FileInputStream fis = new FileInputStream(templatePath)) {
+ // 设置默认编码为UTF-8
+ System.setProperty("file.encoding", "UTF-8");
+
+ XWPFDocument document = new XWPFDocument(fis);
+
+ // 处理段落
+ for (XWPFParagraph paragraph : document.getParagraphs()) {
+ replaceParagraph(paragraph, dataMap);
+ }
+
+ // 处理表格
+ for (XWPFTable table : document.getTables()) {
+ for (XWPFTableRow row : table.getRows()) {
+ for (XWPFTableCell cell : row.getTableCells()) {
+ for (XWPFParagraph paragraph : cell.getParagraphs()) {
+ replaceParagraph(paragraph, dataMap);
+ }
+ }
+ }
+ }
+
+ // 使用UTF-8编码保存文件
+ try (FileOutputStream fos = new FileOutputStream(outputPath)) {
+ document.write(fos);
+ }
+
+ System.out.println("模板填充完成!文件保存在: " + outputPath);
+
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ private static void replaceParagraph(XWPFParagraph paragraph, Map<String, Object> dataMap) {
+ // 获取段落中所有runs
+ List<XWPFRun> runs = paragraph.getRuns();
+ if (runs == null || runs.isEmpty()) return;
+
+ // 首先合并所有runs的文本,以便正确识别占位符
+ StringBuilder fullText = new StringBuilder();
+ for (XWPFRun run : runs) {
+ String text = run.getText(0);
+ if (text != null) {
+ fullText.append(text);
+ }
+ }
+
+ String paragraphText = fullText.toString();
+
+ // 使用正则表达式查找所有占位符,包括括号内的
+ Pattern pattern = Pattern.compile("\\$\\{[^}]+\\}|\\([^)]*\\$\\{[^}]+\\}[^)]*\\)");
+ Matcher matcher = pattern.matcher(paragraphText);
+
+ List<ReplacementInfo> replacements = new ArrayList<>();
+
+ // 收集所有需要替换的信息
+ while (matcher.find()) {
+ String matched = matcher.group();
+ int start = matcher.start();
+ int end = matcher.end();
+
+ // 找出涉及到的runs
+ int startRun = -1;
+ int endRun = -1;
+ int currentPos = 0;
+
+ for (int i = 0; i < runs.size(); i++) {
+ XWPFRun run = runs.get(i);
+ String runText = run.getText(0);
+ if (runText == null) continue;
+
+ int runLength = runText.length();
+ if (startRun == -1 && currentPos + runLength > start) {
+ startRun = i;
+ }
+ if (currentPos + runLength >= end) {
+ endRun = i;
+ break;
+ }
+ currentPos += runLength;
+ }
+
+ if (startRun != -1 && endRun != -1) {
+ // 处理括号内的占位符
+ String replacement = processPlaceholder(matched, dataMap);
+ replacements.add(new ReplacementInfo(startRun, endRun, matched, replacement));
+ }
+ }
+
+ // 从后向前替换,避免位置变化影响
+ Collections.sort(replacements, (a, b) -> b.startRun - a.startRun);
+
+ for (ReplacementInfo info : replacements) {
+ replaceRunRange(paragraph, info);
+ }
+ }
+
+ private static String processPlaceholder(String text, Map<String, Object> dataMap) {
+ // 处理括号内的占位符
+ Pattern placeholderPattern = Pattern.compile("\\$\\{([^}]+)\\}");
+ Matcher matcher = placeholderPattern.matcher(text);
+
+ StringBuffer result = new StringBuffer();
+ while (matcher.find()) {
+ String placeholder = matcher.group(0); // 完整的占位符
+ String key = matcher.group(1); // 占位符中的键
+ String replacement = Objects.nonNull(dataMap.get("${" + key + "}"))?String.valueOf(dataMap.get("${" + key + "}")):"";
+
+ if (replacement != null) {
+ // 如果在括号内,保留括号
+ if (text.startsWith("(") && text.endsWith(")")) {
+ matcher.appendReplacement(result, replacement);
+ } else {
+ matcher.appendReplacement(result, Matcher.quoteReplacement(replacement));
+ }
+ }
+ }
+ matcher.appendTail(result);
+
+ return result.toString();
+ }
+
+ private static class ReplacementInfo {
+ int startRun;
+ int endRun;
+ String originalText;
+ String replacementText;
+
+ ReplacementInfo(int startRun, int endRun, String originalText, String replacementText) {
+ this.startRun = startRun;
+ this.endRun = endRun;
+ this.originalText = originalText;
+ this.replacementText = replacementText;
+ }
+ }
+
+ private static void replaceRunRange(XWPFParagraph paragraph, ReplacementInfo info) {
+ List<XWPFRun> runs = paragraph.getRuns();
+
+ // 保存第一个run的样式
+ XWPFRun styleRun = runs.get(info.startRun);
+ RunStyle style = new RunStyle(styleRun);
+
+ // 删除范围内的所有runs
+ for (int i = info.endRun; i >= info.startRun; i--) {
+ paragraph.removeRun(i);
+ }
+
+ // 创建新的run并设置文本
+ XWPFRun newRun = paragraph.insertNewRun(info.startRun);
+ newRun.setText(info.replacementText);
+
+ // 应用样式
+ style.applyStyle(newRun);
+ }
+
+ // 用于保存和恢复运行样式的辅助类
+ private static class RunStyle {
+ String fontFamily;
+ int fontSize;
+ boolean bold;
+ boolean italic;
+ String color;
+ UnderlinePatterns underline;
+
+ RunStyle(XWPFRun run) {
+ this.fontFamily = run.getFontFamily();
+ this.fontSize = run.getFontSize();
+ this.bold = run.isBold();
+ this.italic = run.isItalic();
+ this.color = run.getColor();
+ this.underline = run.getUnderline();
+ }
+
+ void applyStyle(XWPFRun run) {
+ if (fontFamily != null) {
+ run.setFontFamily(fontFamily);
+ run.setFontFamily(fontFamily, XWPFRun.FontCharRange.eastAsia);
+ }
+ if (fontSize != -1) {
+ run.setFontSize(fontSize);
+ }
+ run.setBold(bold);
+ run.setItalic(italic);
+ if (color != null) {
+ run.setColor(color);
+ }
+ if (underline != null) {
+ run.setUnderline(underline);
+ }
+ }
+ }
+
+// public String generatePdf(String basePackagePath, String templateFileName, Object templateParam, String fileName, String saveDirectory) {
+// try {
+// // 创建 Freemarker 的 Configuration 对象,设置默认的不兼容改进选项
+// Configuration configuration = new Configuration(Configuration.DEFAULT_INCOMPATIBLE_IMPROVEMENTS);
+// configuration.setDefaultEncoding("utf-8");
+// // 设置模板加载器,加载模板文件
+// configuration.setTemplateLoader(new ClassTemplateLoader(getClass(), basePackagePath));
+// Template t = configuration.getTemplate(templateFileName, "utf-8");
+//
+// // 使用 URLEncoder 对文件名进行编码,以防止中文文件名在不同浏览器和操作系统下出现乱码问题
+//// String encodedFileName = URLEncoder.encode(fileName + "_" + System.currentTimeMillis(), "utf-8");
+// String encodedFileName =fileName ;
+//
+// // 定义保存文件的路径
+// File saveDir = new File(saveDirectory);
+// if (!saveDir.exists()) {
+// saveDir.mkdirs();
+// }
+//
+// // 定义文件名
+// String filePath = saveDir.getAbsolutePath() + File.separator + encodedFileName + ".doc";
+//
+// // 创建 Writer 对象,用于将生成的文档写到文件中,缓存区大小设为 10KB
+// Writer out = new BufferedWriter(new FileWriter(filePath), 10240);
+//
+// // 将模型数据与模板结合生成 Word 文档,写入到 Writer 对象中
+// t.process(templateParam, out);
+// out.close();
+//
+// File file = new File(filePath);
+//
+// // 检查文件是否存在
+// if (!file.exists()) {
+// throw new FileNotFoundException("文件不存在: " + filePath);
+// }
+//
+// // 读取文件内容
+// byte[] fileContent = new byte[(int) file.length()];
+// try (FileInputStream fis = new FileInputStream(file)) {
+// fis.read(fileContent);
+// }
+//
+// String test = pdfUtils.test(encodedFileName + ".doc");
+//// MultipartFile mockMultipartFile = new MockMultipartFile(encodedFileName+".doc", fileContent);
+//// String s = ObsUploadUtil.obsUpload(mockMultipartFile);
+// return test;
+// } catch (IOException | TemplateException e) {
+// log.error("生成pdf异常,异常原因:{}", e.getMessage(), e);
+// throw new RuntimeException("生成pdf异常,异常原因:" + e.getMessage());
+// }
+// }
+
--
Gitblit v1.7.1