From ac4bf3bccb266666a60fd0addb73bce125d43758 Mon Sep 17 00:00:00 2001
From: xuhy <3313886187@qq.com>
Date: 星期四, 06 三月 2025 19:15:26 +0800
Subject: [PATCH] bug修改

---
 ruoyi-admin/src/main/java/com/ruoyi/web/controller/tool/WordUtil.java |  313 +++++++++++++++++++++++++++++++++++++++++++++++-----
 1 files changed, 283 insertions(+), 30 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 ce14b96..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
@@ -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