From 3adfcc5a9829a0231bf95c1a7e3aaad1d28b05d5 Mon Sep 17 00:00:00 2001
From: liujie <1793218484@qq.com>
Date: 星期四, 09 四月 2026 15:46:11 +0800
Subject: [PATCH] update

---
 admin-server/src/main/resources/application.yml                                            |   40 +---
 admin-server/src/main/java/com/estate/expert/admin/controller/stat/ReportController.java   |    2 
 admin-server/src/main/java/com/estate/expert/admin/utils/wordtopdf/WordToPdfConverter.java |  444 +++++++++++++++++++++++++++++-------------------
 admin-server/src/main/java/com/estate/expert/admin/utils/wordtopdf/WordToPdfTest.java      |    6 
 4 files changed, 285 insertions(+), 207 deletions(-)

diff --git a/admin-server/src/main/java/com/estate/expert/admin/controller/stat/ReportController.java b/admin-server/src/main/java/com/estate/expert/admin/controller/stat/ReportController.java
index 8fc2a60..9a1a8b0 100644
--- a/admin-server/src/main/java/com/estate/expert/admin/controller/stat/ReportController.java
+++ b/admin-server/src/main/java/com/estate/expert/admin/controller/stat/ReportController.java
@@ -373,9 +373,11 @@
             Files.write(filePath, fileBytes, StandardOpenOption.CREATE, StandardOpenOption.TRUNCATE_EXISTING);
 
             log.info("文件已保存到服务器: {}", filePath.toString());
+            System.out.println("文件已保存到服务器: " + filePath.toString());
             return fileName;
         } catch (Exception e) {
             log.error("保存文件到服务器失败: {}", fileName, e);
+            System.out.println("保存文件到服务器失败: " + e.getMessage());
             // 不抛出异常,避免影响用户下载
         }
         return null;
diff --git a/admin-server/src/main/java/com/estate/expert/admin/utils/wordtopdf/WordToPdfConverter.java b/admin-server/src/main/java/com/estate/expert/admin/utils/wordtopdf/WordToPdfConverter.java
index 5821913..0459544 100644
--- a/admin-server/src/main/java/com/estate/expert/admin/utils/wordtopdf/WordToPdfConverter.java
+++ b/admin-server/src/main/java/com/estate/expert/admin/utils/wordtopdf/WordToPdfConverter.java
@@ -1,6 +1,15 @@
 package com.estate.expert.admin.utils.wordtopdf;
 
 import lombok.extern.slf4j.Slf4j;
+import org.apache.poi.xwpf.usermodel.IBodyElement;
+import org.apache.poi.xwpf.usermodel.XWPFDocument;
+import org.apache.poi.xwpf.usermodel.XWPFFooter;
+import org.apache.poi.xwpf.usermodel.XWPFHeader;
+import org.apache.poi.xwpf.usermodel.XWPFParagraph;
+import org.apache.poi.xwpf.usermodel.XWPFRun;
+import org.apache.poi.xwpf.usermodel.XWPFTable;
+import org.apache.poi.xwpf.usermodel.XWPFTableCell;
+import org.apache.poi.xwpf.usermodel.XWPFTableRow;
 import org.jodconverter.core.office.OfficeException;
 import org.jodconverter.core.office.OfficeManager;
 import org.jodconverter.local.LocalConverter;
@@ -8,298 +17,379 @@
 
 import javax.annotation.PreDestroy;
 import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.nio.file.Files;
+import java.nio.file.Path;
 import java.util.Arrays;
+import java.util.LinkedHashSet;
 import java.util.List;
+import java.util.Locale;
+import java.util.Set;
 import java.util.concurrent.atomic.AtomicInteger;
 
-/**
- * Word 转 PDF 工具类(使用 LibreOffice/OpenOffice)
- * 支持图表、图片、表格等复杂格式
- */
 @Slf4j
 public class WordToPdfConverter {
-    
-    private OfficeManager officeManager;
-    private static WordToPdfConverter instance;
-    private final AtomicInteger conversionCount = new AtomicInteger(0);
-    
-    // LibreOffice 安装路径(根据您的安装位置调整)
-    private static final String LIBRE_OFFICE_PATH = "C:\\Program Files\\LibreOffice";
-    //private static final String LIBRE_OFFICE_PATH = "C:\\Program Files (x86)\\LibreOffice";
-    
-    // 支持转换的文件格式
+
+    private static final String LIBRE_OFFICE_PATH = "/usr/lib/libreoffice";
+    private static final String DEFAULT_FALLBACK_FONT = "Noto Sans CJK SC";
+    private static final Set<String> WINDOWS_CJK_FONTS = new LinkedHashSet<>(Arrays.asList(
+            "\u5b8b\u4f53", "SimSun",
+            "\u5fae\u8f6f\u96c5\u9ed1", "Microsoft YaHei",
+            "\u9ed1\u4f53", "SimHei",
+            "\u4eff\u5b8b", "FangSong",
+            "\u6977\u4f53", "KaiTi",
+            "\u65b0\u5b8b\u4f53", "NSimSun",
+            "\u7b49\u7ebf", "DengXian"
+    ));
     private static final List<String> SUPPORTED_EXTENSIONS = Arrays.asList(
             ".doc", ".docx", ".rtf", ".txt", ".odt"
     );
-    
+
+    private static WordToPdfConverter instance;
+
+    private final AtomicInteger conversionCount = new AtomicInteger(0);
+    private OfficeManager officeManager;
+
     private WordToPdfConverter() {
         initializeOfficeManager();
     }
-    
-    /**
-     * 获取单例实例
-     */
+
     public static synchronized WordToPdfConverter getInstance() {
         if (instance == null) {
             instance = new WordToPdfConverter();
         }
         return instance;
     }
-    
-    /**
-     * 初始化 Office 管理器
-     */
+
     private void initializeOfficeManager() {
         try {
-            log.info("正在初始化 LibreOffice 管理器...");
-            
-            // 检查 LibreOffice 是否安装
+            log.info("Initializing LibreOffice manager");
+
             File officeHome = new File(LIBRE_OFFICE_PATH);
             if (!officeHome.exists() || !officeHome.isDirectory()) {
-                throw new RuntimeException("未找到 LibreOffice 安装目录: " + LIBRE_OFFICE_PATH + 
-                                         "\n请安装 LibreOffice 或修改 LIBRE_OFFICE_PATH 配置");
+                throw new RuntimeException("LibreOffice home not found: " + LIBRE_OFFICE_PATH);
             }
-            
-            // 创建 Office 管理器
+
             officeManager = LocalOfficeManager.builder()
                     .officeHome(officeHome)
-                    .portNumbers(2002)  // 使用 2002 端口
-                    .processTimeout(300000L) // 5分钟超时
-                    .taskExecutionTimeout(300000L) // 5分钟任务超时
-                    .maxTasksPerProcess(20) // 每个进程最大任务数
-                    .install() // 如果未安装则尝试安装
+                    .portNumbers(2002)
+                    .processTimeout(300000L)
+                    .taskExecutionTimeout(300000L)
+                    .maxTasksPerProcess(20)
+                    .install()
                     .build();
-            
-            // 启动服务
+
             officeManager.start();
-            log.info("LibreOffice 管理器启动成功,服务端口: 2002");
-            
+            log.info("LibreOffice manager started on port 2002");
         } catch (Exception e) {
-            log.error("初始化 LibreOffice 管理器失败", e);
-            throw new RuntimeException("无法启动 LibreOffice 服务: " + e.getMessage(), e);
+            log.error("Failed to initialize LibreOffice manager", e);
+            throw new RuntimeException("Unable to start LibreOffice service: " + e.getMessage(), e);
         }
     }
-    
-    /**
-     * 转换 Word 文件为 PDF
-     * @param wordFilePath Word 文件路径
-     * @param pdfFilePath  PDF 输出路径
-     * @return 是否转换成功
-     */
+
     public boolean convert(String wordFilePath, String pdfFilePath) {
         return convert(new File(wordFilePath), new File(pdfFilePath));
     }
-    
-    /**
-     * 转换 Word 文件为 PDF
-     * @param wordFile Word 文件
-     * @param pdfFile  PDF 输出文件
-     * @return 是否转换成功
-     */
+
     public boolean convert(File wordFile, File pdfFile) {
         long startTime = System.currentTimeMillis();
         int currentCount = conversionCount.incrementAndGet();
-        
+        File conversionSource = wordFile;
+
         try {
-            // 验证输入文件
             validateInputFile(wordFile);
-            
-            // 准备输出目录
             prepareOutputDirectory(pdfFile);
-            
-            log.info("开始转换 [{}]: {} -> {}", currentCount, 
-                    wordFile.getName(), pdfFile.getName());
-            
-            // 执行转换
+            conversionSource = prepareConversionSource(wordFile);
+
+            log.info("Start conversion [{}]: {} -> {}", currentCount, wordFile.getName(), pdfFile.getName());
+
             LocalConverter.builder()
                     .officeManager(officeManager)
                     .build()
-                    .convert(wordFile)
+                    .convert(conversionSource)
                     .to(pdfFile)
                     .execute();
-            
-            // 验证输出文件
+
             boolean success = validateOutputFile(pdfFile);
-            
             long costTime = System.currentTimeMillis() - startTime;
             if (success) {
-                log.info("转换成功 [{}]: {} -> {} (耗时: {}ms)", 
+                log.info("Conversion succeeded [{}]: {} -> {} ({} ms)",
                         currentCount, wordFile.getName(), pdfFile.getName(), costTime);
             } else {
-                log.warn("转换完成但文件可能异常 [{}]: {} (耗时: {}ms)", 
+                log.warn("Conversion finished with invalid output [{}]: {} ({} ms)",
                         currentCount, wordFile.getName(), costTime);
             }
-            
             return success;
-            
         } catch (Exception e) {
-            log.error("转换失败 [{}]: {}", currentCount, wordFile.getName(), e);
+            log.error("Conversion failed [{}]: {}", currentCount, wordFile.getName(), e.getMessage(), e);
             return false;
+        } finally {
+            cleanupTemporarySource(wordFile, conversionSource);
         }
     }
-    
-    /**
-     * 验证输入文件
-     */
-    private void validateInputFile(File wordFile) {
-        if (wordFile == null) {
-            throw new IllegalArgumentException("输入文件不能为空");
+
+    private File prepareConversionSource(File wordFile) {
+        if (!shouldNormalizeDocxFonts(wordFile)) {
+            return wordFile;
         }
-        
-        if (!wordFile.exists()) {
-            throw new IllegalArgumentException("输入文件不存在: " + wordFile.getAbsolutePath());
-        }
-        
-        if (!wordFile.isFile()) {
-            throw new IllegalArgumentException("输入路径不是文件: " + wordFile.getAbsolutePath());
-        }
-        
-        // 检查文件格式
-        String fileName = wordFile.getName().toLowerCase();
-        boolean supported = SUPPORTED_EXTENSIONS.stream()
-                .anyMatch(fileName::endsWith);
-        
-        if (!supported) {
-            throw new IllegalArgumentException("不支持的文件格式: " + fileName + 
-                    "\n支持的格式: " + SUPPORTED_EXTENSIONS);
-        }
-        
-        // 检查文件大小(限制 100MB)
-        long fileSize = wordFile.length();
-        long maxSize = 100 * 1024 * 1024; // 100MB
-        if (fileSize > maxSize) {
-            throw new IllegalArgumentException("文件过大: " + (fileSize / 1024 / 1024) + 
-                    "MB (最大支持 100MB)");
+
+        try {
+            return normalizeDocxFonts(wordFile);
+        } catch (Exception e) {
+            log.warn("Docx font normalization failed, fallback to original file: {}", wordFile.getAbsolutePath(), e);
+            return wordFile;
         }
     }
-    
-    /**
-     * 准备输出目录
-     */
-    private void prepareOutputDirectory(File pdfFile) {
-        File parentDir = pdfFile.getParentFile();
-        if (parentDir != null && !parentDir.exists()) {
-            boolean created = parentDir.mkdirs();
-            if (!created) {
-                throw new RuntimeException("无法创建输出目录: " + parentDir.getAbsolutePath());
+
+    private boolean shouldNormalizeDocxFonts(File wordFile) {
+        return isLinux() && wordFile.getName().toLowerCase(Locale.ROOT).endsWith(".docx");
+    }
+
+    private boolean isLinux() {
+        return System.getProperty("os.name", "").toLowerCase(Locale.ROOT).contains("linux");
+    }
+
+    private File normalizeDocxFonts(File sourceFile) throws IOException {
+        Path tempFile = Files.createTempFile("estate-word-font-normalized-", ".docx");
+        String fallbackFont = resolveFallbackFont();
+        int replacedRuns = 0;
+
+        try (InputStream inputStream = Files.newInputStream(sourceFile.toPath());
+             XWPFDocument document = new XWPFDocument(inputStream);
+             OutputStream outputStream = Files.newOutputStream(tempFile)) {
+            replacedRuns += normalizeParagraphs(document.getParagraphs(), fallbackFont);
+            replacedRuns += normalizeTables(document.getTables(), fallbackFont);
+
+            for (XWPFHeader header : document.getHeaderList()) {
+                replacedRuns += normalizeParagraphs(header.getParagraphs(), fallbackFont);
+                replacedRuns += normalizeTables(header.getTables(), fallbackFont);
+            }
+
+            for (XWPFFooter footer : document.getFooterList()) {
+                replacedRuns += normalizeParagraphs(footer.getParagraphs(), fallbackFont);
+                replacedRuns += normalizeTables(footer.getTables(), fallbackFont);
+            }
+
+            document.write(outputStream);
+        }
+
+        log.info("Docx font normalization finished, fallbackFont={}, replacedRuns={}, source={}, temp={}",
+                fallbackFont, replacedRuns, sourceFile.getAbsolutePath(), tempFile);
+        return tempFile.toFile();
+    }
+
+    private int normalizeParagraphs(List<XWPFParagraph> paragraphs, String fallbackFont) {
+        int replacedRuns = 0;
+        for (XWPFParagraph paragraph : paragraphs) {
+            replacedRuns += normalizeParagraph(paragraph, fallbackFont);
+        }
+        return replacedRuns;
+    }
+
+    private int normalizeParagraph(XWPFParagraph paragraph, String fallbackFont) {
+        int replacedRuns = 0;
+        for (XWPFRun run : paragraph.getRuns()) {
+            if (normalizeRunFont(run, fallbackFont)) {
+                replacedRuns++;
             }
         }
+        return replacedRuns;
     }
-    
-    /**
-     * 验证输出文件
-     */
+
+    private int normalizeTables(List<XWPFTable> tables, String fallbackFont) {
+        int replacedRuns = 0;
+        for (XWPFTable table : tables) {
+            for (XWPFTableRow row : table.getRows()) {
+                for (XWPFTableCell cell : row.getTableCells()) {
+                    replacedRuns += normalizeBodyElements(cell.getBodyElements(), fallbackFont);
+                }
+            }
+        }
+        return replacedRuns;
+    }
+
+    private int normalizeBodyElements(List<IBodyElement> bodyElements, String fallbackFont) {
+        int replacedRuns = 0;
+        for (IBodyElement bodyElement : bodyElements) {
+            if (bodyElement instanceof XWPFParagraph paragraph) {
+                replacedRuns += normalizeParagraph(paragraph, fallbackFont);
+            } else if (bodyElement instanceof XWPFTable table) {
+                replacedRuns += normalizeTables(List.of(table), fallbackFont);
+            }
+        }
+        return replacedRuns;
+    }
+
+    private boolean normalizeRunFont(XWPFRun run, String fallbackFont) {
+        boolean shouldReplace = shouldReplaceFont(run.getFontFamily())
+                || shouldReplaceFont(run.getFontFamily(XWPFRun.FontCharRange.ascii))
+                || shouldReplaceFont(run.getFontFamily(XWPFRun.FontCharRange.cs))
+                || shouldReplaceFont(run.getFontFamily(XWPFRun.FontCharRange.eastAsia))
+                || shouldReplaceFont(run.getFontFamily(XWPFRun.FontCharRange.hAnsi));
+
+        if (!shouldReplace) {
+            return false;
+        }
+
+        run.setFontFamily(fallbackFont);
+        run.setFontFamily(fallbackFont, XWPFRun.FontCharRange.ascii);
+        run.setFontFamily(fallbackFont, XWPFRun.FontCharRange.cs);
+        run.setFontFamily(fallbackFont, XWPFRun.FontCharRange.eastAsia);
+        run.setFontFamily(fallbackFont, XWPFRun.FontCharRange.hAnsi);
+        return true;
+    }
+
+    private boolean shouldReplaceFont(String fontName) {
+        return fontName != null && WINDOWS_CJK_FONTS.contains(fontName.trim());
+    }
+
+    private String resolveFallbackFont() {
+        String systemProperty = System.getProperty("estate.word.pdf.font");
+        if (systemProperty != null && !systemProperty.isBlank()) {
+            return systemProperty.trim();
+        }
+
+        String environmentValue = System.getenv("ESTATE_WORD_PDF_FONT");
+        if (environmentValue != null && !environmentValue.isBlank()) {
+            return environmentValue.trim();
+        }
+
+        return DEFAULT_FALLBACK_FONT;
+    }
+
+    private void cleanupTemporarySource(File originalFile, File conversionSource) {
+        if (conversionSource == null || conversionSource.equals(originalFile)) {
+            return;
+        }
+
+        try {
+            Files.deleteIfExists(conversionSource.toPath());
+        } catch (IOException e) {
+            log.warn("Failed to delete temporary docx: {}", conversionSource.getAbsolutePath(), e);
+        }
+    }
+
+    private void validateInputFile(File wordFile) {
+        if (wordFile == null) {
+            throw new IllegalArgumentException("Input file must not be null");
+        }
+
+        if (!wordFile.exists()) {
+            throw new IllegalArgumentException("Input file does not exist: " + wordFile.getAbsolutePath());
+        }
+
+        if (!wordFile.isFile()) {
+            throw new IllegalArgumentException("Input path is not a file: " + wordFile.getAbsolutePath());
+        }
+
+        String fileName = wordFile.getName().toLowerCase(Locale.ROOT);
+        boolean supported = SUPPORTED_EXTENSIONS.stream().anyMatch(fileName::endsWith);
+        if (!supported) {
+            throw new IllegalArgumentException("Unsupported file type: " + fileName + ", supported: " + SUPPORTED_EXTENSIONS);
+        }
+
+        long fileSize = wordFile.length();
+        long maxSize = 100L * 1024L * 1024L;
+        if (fileSize > maxSize) {
+            throw new IllegalArgumentException("File is too large: " + (fileSize / 1024 / 1024) + "MB, max is 100MB");
+        }
+    }
+
+    private void prepareOutputDirectory(File pdfFile) {
+        File parentDir = pdfFile.getParentFile();
+        if (parentDir != null && !parentDir.exists() && !parentDir.mkdirs()) {
+            throw new RuntimeException("Unable to create output directory: " + parentDir.getAbsolutePath());
+        }
+    }
+
     private boolean validateOutputFile(File pdfFile) {
         if (!pdfFile.exists()) {
-            log.error("输出文件未创建: {}", pdfFile.getAbsolutePath());
+            log.error("Output file was not created: {}", pdfFile.getAbsolutePath());
             return false;
         }
-        
+
         if (pdfFile.length() == 0) {
-            log.error("输出文件为空: {}", pdfFile.getAbsolutePath());
+            log.error("Output file is empty: {}", pdfFile.getAbsolutePath());
             return false;
         }
-        
-        // 检查文件头是否为 PDF
-        try (java.io.FileInputStream fis = new java.io.FileInputStream(pdfFile)) {
+
+        try (FileInputStream inputStream = new FileInputStream(pdfFile)) {
             byte[] header = new byte[4];
-            int read = fis.read(header);
+            int read = inputStream.read(header);
             if (read >= 4) {
-                // PDF 文件头应该是 "%PDF"
-                boolean isPdf = header[0] == '%' && 
-                                header[1] == 'P' && 
-                                header[2] == 'D' && 
-                                header[3] == 'F';
+                boolean isPdf = header[0] == '%'
+                        && header[1] == 'P'
+                        && header[2] == 'D'
+                        && header[3] == 'F';
                 if (!isPdf) {
-                    log.warn("输出文件可能不是有效的 PDF 文件: {}", pdfFile.getAbsolutePath());
+                    log.warn("Output file is not a valid pdf: {}", pdfFile.getAbsolutePath());
                 }
                 return isPdf;
             }
         } catch (Exception e) {
-            log.warn("验证 PDF 文件头失败", e);
+            log.warn("Failed to validate pdf header", e);
         }
-        
+
         return true;
     }
-    
-    /**
-     * 批量转换
-     * @param wordFiles Word 文件列表
-     * @param outputDir 输出目录
-     * @return 成功转换的文件数量
-     */
+
     public int batchConvert(List<File> wordFiles, File outputDir) {
-        if (!outputDir.exists()) {
-            outputDir.mkdirs();
+        if (!outputDir.exists() && !outputDir.mkdirs()) {
+            throw new RuntimeException("Unable to create batch output directory: " + outputDir.getAbsolutePath());
         }
-        
+
         int successCount = 0;
         for (int i = 0; i < wordFiles.size(); i++) {
             File wordFile = wordFiles.get(i);
             try {
                 String baseName = getFileBaseName(wordFile);
                 File pdfFile = new File(outputDir, baseName + ".pdf");
-                
-                log.info("批量转换进度: {}/{} - {}", i + 1, wordFiles.size(), wordFile.getName());
-                
+                log.info("Batch conversion progress: {}/{} - {}", i + 1, wordFiles.size(), wordFile.getName());
                 if (convert(wordFile, pdfFile)) {
                     successCount++;
                 }
-                
             } catch (Exception e) {
-                log.error("批量转换失败: {}", wordFile.getName(), e);
+                log.error("Batch conversion failed: {}", wordFile.getName(), e);
             }
         }
-        
-        log.info("批量转换完成: 成功 {}/{}", successCount, wordFiles.size());
+
+        log.info("Batch conversion finished: {}/{}", successCount, wordFiles.size());
         return successCount;
     }
-    
-    /**
-     * 获取文件名(不含扩展名)
-     */
+
     private String getFileBaseName(File file) {
         String name = file.getName();
         int dotIndex = name.lastIndexOf('.');
-        return (dotIndex == -1) ? name : name.substring(0, dotIndex);
+        return dotIndex == -1 ? name : name.substring(0, dotIndex);
     }
-    
-    /**
-     * 获取转换统计
-     */
+
     public int getConversionCount() {
         return conversionCount.get();
     }
-    
-    /**
-     * 重启 Office 服务
-     */
+
     public void restart() {
-        log.info("正在重启 LibreOffice 服务...");
+        log.info("Restarting LibreOffice service");
         shutdown();
         initializeOfficeManager();
-        log.info("LibreOffice 服务重启完成");
+        log.info("LibreOffice service restarted");
     }
-    
-    /**
-     * 关闭 Office 管理器
-     */
+
     @PreDestroy
     public void shutdown() {
         if (officeManager != null && officeManager.isRunning()) {
             try {
                 officeManager.stop();
-                log.info("LibreOffice 服务已关闭");
+                log.info("LibreOffice service stopped");
             } catch (OfficeException e) {
-                log.error("关闭 LibreOffice 服务时出错", e);
+                log.error("Failed to stop LibreOffice service", e);
             }
         }
     }
-    
-    /**
-     * 检查服务状态
-     */
+
     public boolean isServiceRunning() {
         return officeManager != null && officeManager.isRunning();
     }
-}
\ No newline at end of file
+}
diff --git a/admin-server/src/main/java/com/estate/expert/admin/utils/wordtopdf/WordToPdfTest.java b/admin-server/src/main/java/com/estate/expert/admin/utils/wordtopdf/WordToPdfTest.java
index 8de703d..73c2b82 100644
--- a/admin-server/src/main/java/com/estate/expert/admin/utils/wordtopdf/WordToPdfTest.java
+++ b/admin-server/src/main/java/com/estate/expert/admin/utils/wordtopdf/WordToPdfTest.java
@@ -39,8 +39,8 @@
         System.out.println("\n--- 测试1:单文件转换 ---");
         WordToPdfConverter converter = WordToPdfConverter.getInstance();
         // 请修改为您的 Word 文件路径
-        String wordFilePath = "F:\\file\\estate\\reports\\"+uuid+".docx"; // 包含图表的 Word 文件
-        String pdfFilePath = "F:\\file\\estate\\reports\\"+uuid+".pdf";
+        String wordFilePath = "/data/uploads/reports/"+uuid+".docx"; // 包含图表的 Word 文件
+        String pdfFilePath = "/data/uploads/reports/"+uuid+".pdf";
         
         File wordFile = new File(wordFilePath);
         if (!wordFile.exists()) {
@@ -68,7 +68,7 @@
         } else {
             System.out.println("✗ 单文件转换失败");
         }
-        return "http://221.182.45.100:11225/images/reports/"+uuid+".pdf";
+        return "http://xllpgzx.com/report/"+uuid+".pdf";
     }
     
     /**
diff --git a/admin-server/src/main/resources/application.yml b/admin-server/src/main/resources/application.yml
index d3f442f..1e86f90 100644
--- a/admin-server/src/main/resources/application.yml
+++ b/admin-server/src/main/resources/application.yml
@@ -1,10 +1,5 @@
 server:
-  port: 8080
-
-logging:
-  config: classpath:logback.xml
-  level:
-      root: info
+  port: 8182
 
 spring:
   profiles:
@@ -30,9 +25,9 @@
       max-request-size: 100MB
 
   datasource:
-    url: jdbc:mysql://localhost:3306/estate?useSSL=false&autoReconnect=true&useUnicode=true&characterEncoding=utf8&allowMultiQueries=true&zeroDateTimeBehavior=convertToNull
-    username: root
-    password: 123456
+    url: jdbc:mysql://localhost:3306/estate_dgzp?useSSL=false&autoReconnect=true&useUnicode=true&characterEncoding=utf8&allowMultiQueries=true&zeroDateTimeBehavior=convertToNull&allowPublicKeyRetrieval=true
+    username: admin
+    password: ZXtzbsMuCIFbmBW4HtOjRd
     driver-class-name: com.mysql.jdbc.Driver
     hikari:
       auto-commit: true
@@ -45,32 +40,23 @@
   # JPA
   jpa:
     hibernate:
-      ddl-auto: update
+    #      ddl-auto: update
     show-sql: false
-    
-  # MyBatis-Plus
-  mybatis-plus:
-    mapper-locations: classpath:mapper/*.xml
-    type-aliases-package: com.estate.expert.admin.domain.entity
-    configuration:
-      map-underscore-to-camel-case: true
-      use-generated-keys: true
-      default-statement-timeout: 30
-    global-config:
-      db-config:
-        logic-delete-field: deleted
-        logic-delete-value: 1
-        logic-not-delete-value: 0
 
-
+# 上传文件目录
 file:
   upload:
-    #    dir: /data/uploads
-    dir: F:\file\estate
+    dir: /data/uploads
 
+# 高德地图API密钥
 map:
   api:
     key: 5ad97434d47b7cc74b4145d5509d28d2
 
+# 模糊评估API地址
+fuzzy:
+  api:
+    url: http://localhost:5000/api/Fuzzy_evaluation
+
 license:
   key: lI0Qvh4sExRSocj5hUsiykvZzzEkquy04aydOb22zh70O58gdourrlAMZAu/BdATBk3xqmDxn0y8+AM1BYgwEOREcS9+S8V6FUFtoJpPDu4=
\ No newline at end of file

--
Gitblit v1.7.1