Browse Source

build 图片列表展示

mamingxu 1 month ago
parent
commit
cb1aa7655b

+ 4 - 5
easier-report-biz/pom.xml

@@ -87,14 +87,13 @@
             <version>4.0.5</version>
         </dependency>
 
-        <!-- 中文字体支持 -->
+
         <dependency>
-            <groupId>com.itextpdf</groupId>
-            <artifactId>font-asian</artifactId>
-            <version>7.2.5</version>
+            <groupId>com.github.librepdf</groupId>
+            <artifactId>openpdf</artifactId>
+            <version>1.3.30</version>
         </dependency>
 
-        <!-- Apache POI 4.1.2 -->
         <dependency>
             <groupId>org.apache.poi</groupId>
             <artifactId>poi</artifactId>

+ 1 - 1
easier-report-biz/src/main/java/com/yaoyicloud/config/FilerepoProperties.java

@@ -52,7 +52,7 @@ public class FilerepoProperties {
     }
 
     public String getReportImagePath() {
-        return getRootPath() + "/file/image";
+        return getRootPath() + "/file/image/word/media/";
     }
 
     /**

+ 88 - 37
easier-report-biz/src/main/java/com/yaoyicloud/service/impl/ReportServiceImpl.java

@@ -11,11 +11,13 @@ import cn.hutool.core.util.StrUtil;
 import com.deepoove.poi.data.NumberingFormat;
 import com.deepoove.poi.data.NumberingRenderData;
 import com.deepoove.poi.data.ParagraphRenderData;
+import com.deepoove.poi.data.PictureType;
 import com.deepoove.poi.data.Pictures;
 import com.deepoove.poi.data.Texts;
 import com.yaoyicloud.constant.enums.ReportType;
 import com.yaoyicloud.service.ReportService;
 import com.yaoyicloud.template.PlatformCompanyReport;
+import org.apache.commons.collections4.CollectionUtils;
 import org.springframework.stereotype.Service;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
@@ -61,62 +63,82 @@ public class ReportServiceImpl implements ReportService {
         }
 
         String socialSecurityDetailsLink = (String) data.get("socialSecurityDetailsLink");
-        data.put("socialSecurityDetailsLink", Texts.of(socialSecurityDetailsLink).link(socialSecurityDetailsLink).create());
+        data.put("socialSecurityDetailsLink",
+            Texts.of(socialSecurityDetailsLink).link(socialSecurityDetailsLink).create());
 
         String taxDeclarationImage = (String) data.get("taxDeclarationImage");
         data.put("taxDeclarationImage", Texts.of(taxDeclarationImage).link(taxDeclarationImage).create());
 
         String financialInfoLink = (String) data.get("financialInfoLink");
         data.put("financialInfoLink", Texts.of(financialInfoLink).link(financialInfoLink).create());
-
-
-
         List<ParagraphRenderData> paragraphImages = new ArrayList<>();
-        List<Map<String, Object>> relatedEntitiesImage = (List<Map<String, Object>>) data.get("relatedEntitiesImage");
-        for (Map<String, Object> relatedEntity : relatedEntitiesImage) {
-            ParagraphRenderData paragraphRenderData = new ParagraphRenderData();
-            paragraphRenderData.addPicture(Pictures.of((String) relatedEntity.get("url"))
-                .size((Integer) relatedEntity.get("width"), (Integer) relatedEntity.get("height")).create());
-            paragraphImages.add(paragraphRenderData);
-        }
-        NumberingFormat numberingFormat = new NumberingFormat(1, "");
-        NumberingRenderData numberedImages = new NumberingRenderData(
-            numberingFormat,
-            paragraphImages);
-        data.put("relatedEntitiesImage", numberedImages);
 
+        List<Map<String, Object>> imageDataList = (List<Map<String, Object>>) data.get("relatedEntitiesImage");
+        if (CollectionUtils.isNotEmpty(imageDataList)) {
+            for (Map<String, Object> imageData : imageDataList) {
+                ParagraphRenderData paragraphRenderData = new ParagraphRenderData();
+
+                if (imageData.containsKey("base64")) {
+                    String base64 = (String) imageData.get("base64");
+
+                    String fileExtension = (String) imageData.get("fileExtension");
+                    PictureType pictureType = PictureType.PNG; // 默认PNG
+                    if (fileExtension != null) {
+                        if (fileExtension.equalsIgnoreCase(".jpg") || fileExtension.equalsIgnoreCase(".jpeg")) {
+                            pictureType = PictureType.JPEG;
+                        } else if (fileExtension.equalsIgnoreCase(".gif")) {
+                            pictureType = PictureType.GIF;
+                        } else if (fileExtension.equalsIgnoreCase(".bmp")) {
+                            pictureType = PictureType.BMP;
+                        } else if (fileExtension.equalsIgnoreCase(".png")) {
+                            pictureType = PictureType.PNG;
+                        } else if (fileExtension.equalsIgnoreCase(".tiff")) {
+                            pictureType = PictureType.TIFF;
+                        }
+                    }
+                    paragraphRenderData.addPicture(
+                        Pictures.ofBase64(base64, pictureType)
+                            .size((Integer) imageData.get("width"), (Integer) imageData.get("height"))
+                            .create());
+                }
+                paragraphImages.add(paragraphRenderData);
+            }
+            NumberingFormat numberingFormat = new NumberingFormat(1, "");
+            NumberingRenderData numberedImages = new NumberingRenderData(numberingFormat, paragraphImages);
+            data.put("relatedEntitiesImage", numberedImages);
+        }
 
-// 处理 businessLicenseImage
+        // 处理 businessLicenseImage
         processImageListToNumberedRenderData("businessLicenseImage", data);
 
-// 处理 bankCertificateImage
+        // 处理 bankCertificateImage
         processImageListToNumberedRenderData("bankCertificateImage", data);
 
-// 处理 isoCertificationImage
+        // 处理 isoCertificationImage
         processImageListToNumberedRenderData("isoCertificationImage", data);
 
-// 处理 securityLevelCertification
+        // 处理 securityLevelCertification
         processImageListToNumberedRenderData("securityLevelCertification", data);
 
-// 处理 otherCertifications
+        // 处理 otherCertifications
         processImageListToNumberedRenderData("otherCertifications", data);
 
-// 处理 organizationalStructureImage
+        // 处理 organizationalStructureImage
         processImageListToNumberedRenderData("organizationalStructureImage", data);
 
-// 处理 taxPaymentCertificateImage
+        // 处理 taxPaymentCertificateImage
         processImageListToNumberedRenderData("taxPaymentCertificateImage", data);
 
-// 处理 nsxydjwj
+        // 处理 nsxydjwj
         processImageListToNumberedRenderData("nsxydjwj", data);
 
-// 处理 interestConflict
+        // 处理 interestConflict
         processImageListToNumberedRenderData("interestConflict", data);
 
-// 处理 disanfangcangzhao
+        // 处理 disanfangcangzhao
         processImageListToNumberedRenderData("disanfangcangzhao", data);
 
-// 处理 overallGuaranteeStatement
+        // 处理 overallGuaranteeStatement
         processImageListToNumberedRenderData("overallGuaranteeStatement", data);
         switch (reportType) {
             case PLATFORM_COMPANY:
@@ -133,35 +155,64 @@ public class ReportServiceImpl implements ReportService {
     }
 
     private void processImageListToNumberedRenderData(String key, Map<String, Object> data) {
-        // 从 data 中获取原始图片数据列表
+        // 从data中获取原始图片数据列表
         List<Map<String, Object>> rawImageDataList = (List<Map<String, Object>>) data.get(key);
 
+        // 处理空数据情况
         if (rawImageDataList == null || rawImageDataList.isEmpty()) {
             String textKey = key + "Text";
             if (data.containsKey(textKey)) {
                 return;
             }
-
         }
-
         // 处理非空图片数据
         List<ParagraphRenderData> paragraphImages = new ArrayList<>();
         for (Map<String, Object> imageInfo : rawImageDataList) {
-            ParagraphRenderData paragraphRenderData = new ParagraphRenderData();
-            // 从原始数据中获取图片属性
+            ParagraphRenderData paragraph = new ParagraphRenderData();
+            // 提取Base64数据和文件扩展名
+            String base64 = (String) imageInfo.get("base64");
             String url = (String) imageInfo.get("url");
+            String fileExtension = (String) imageInfo.get("fileExtension");
             Integer width = (Integer) imageInfo.get("width");
             Integer height = (Integer) imageInfo.get("height");
 
+            // 确定图片类型(默认为PNG)
+            PictureType pictureType = this.determinePictureType(fileExtension);
+
             // 添加图片到段落渲染数据
-            paragraphRenderData.addPicture(Pictures.of(url)
-                    .size(width, height)
-                    .create());
-            paragraphImages.add(paragraphRenderData);
-        }
+            paragraph.addPicture(Pictures.ofBase64(base64, pictureType)
+                .size(width, height)
+                .create());
+
+            paragraphImages.add(paragraph);
 
+        }
         NumberingFormat numberingFormat = new NumberingFormat(1, "");
         NumberingRenderData numberedImages = new NumberingRenderData(numberingFormat, paragraphImages);
         data.put(key, numberedImages);
     }
+    // 辅助方法:根据文件扩展名确定图片类型
+    private PictureType determinePictureType(String fileExtension) {
+        if (fileExtension == null) {
+            return PictureType.PNG;
+        }
+
+        String ext = fileExtension.toLowerCase();
+
+        // 提取扩展名部分(去除可能的前缀点)
+        String normalizedExt = ext.startsWith(".")
+                ? ext.substring(1)
+                : ext;
+
+        return switch (normalizedExt) {
+            case "jpg", "jpeg" -> PictureType.JPEG;
+            case "gif" -> PictureType.GIF;
+            case "bmp" -> PictureType.BMP;
+            case "tiff" -> PictureType.TIFF;
+            default -> PictureType.PNG; // 默认返回 PNG
+        };
+    }
 }
+
+
+

+ 1 - 1
easier-report-biz/src/main/java/com/yaoyicloud/template/PlatformCompanyReport.java

@@ -51,7 +51,7 @@ public class PlatformCompanyReport extends AbstractReportExporter {
 
     @Override
     protected String imagePath() {
-        return filerepoProperties.getReportImagePath() + "/coverBackageimage.jpeg";
+        return filerepoProperties.getReportImagePath();
     }
 
 

+ 65 - 59
easier-report-biz/src/main/java/com/yaoyicloud/tools/OfficeUtil1.java

@@ -1,5 +1,4 @@
 package com.yaoyicloud.tools;
-
 import com.lowagie.text.Image;
 import com.lowagie.text.PageSize;
 import com.lowagie.text.pdf.BaseFont;
@@ -21,6 +20,7 @@ import org.jsoup.select.Elements;
 import org.xhtmlrenderer.pdf.ITextFontResolver;
 import org.xhtmlrenderer.pdf.ITextRenderer;
 
+import java.awt.Color;
 import java.io.ByteArrayOutputStream;
 import java.io.File;
 import java.io.FileInputStream;
@@ -31,9 +31,11 @@ import java.io.OutputStream;
 import java.nio.file.Path;
 import java.nio.file.Paths;
 import java.util.ArrayList;
+import java.util.HashSet;
 import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Map;
+import java.util.Set;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 
@@ -78,8 +80,7 @@ public class OfficeUtil1 {
                 .URIResolver(new FileURIResolver(imageDirFile) {
                     @Override
                     public String resolve(String uri) {
-                        String filename = uri.replace("word/media/", "");
-                        return new File(imageDirFile, filename).getAbsolutePath().replace("/", "\\");
+                        return new File(imageDirFile, uri).getAbsolutePath().replace("/", "\\");
                     }
                 });
 
@@ -341,7 +342,7 @@ public class OfficeUtil1 {
 
     }
 
-    public static String convertHtmlToPdf(String html, String outputPdfPath, List<String> fontPaths, boolean flag) throws Exception {
+    public static String convertHtmlToPdf(String html, String outputPdfPath, List<String> fontPaths, String imagePath, boolean flag) throws Exception {
         String formattedHtml = formatHtml(html);
         try (OutputStream os = new FileOutputStream(outputPdfPath)) {
             ITextRenderer renderer = new ITextRenderer();
@@ -391,68 +392,27 @@ public class OfficeUtil1 {
         String newFileName = baseName + "1" + extension;
         // 构建完整新路径
         String newFilePath = path.resolveSibling(newFileName).toString();
-        pdfReader(outputPdfPath, newFilePath, "C:\\Users\\yyy\\dev\\yyc3\\easier-be\\file\\image\\image1.jpeg", flag);
+        pdfReader(outputPdfPath, newFilePath, imagePath + "\\image1.jpeg", flag);
 
         return newFilePath;
     }
 
-//    public static void convertHtmlToPdf2(String html, String outputPdfPath) throws Exception {
-//        String s = formatHtml(html);
-//
-//        try (OutputStream os = new FileOutputStream(outputPdfPath)) {
-//            ITextRenderer renderer = new ITextRenderer();
-//            ITextFontResolver fontResolver = renderer.getFontResolver();
-//
-//            // 字体路径
-//            String mediumFont = "C:/Users/yyy/AppData/Local/Microsoft/Windows/Fonts/SourceHanSansSC-Medium-2.otf";
-//            String boldFont = "C:/Users/yyy/AppData/Local/Microsoft/Windows/Fonts/SourceHanSansSC-Bold-2.otf";
-//
-//            // 注册字体并强制指定别名为 "思源黑体"
-//            fontResolver.addFont(
-//                    mediumFont,                // 字体文件路径
-//                    "思源黑体",                 // fontFamilyNameOverride:覆盖默认字体名
-//                    BaseFont.IDENTITY_H,       // 编码(必须用于中文)
-//                    true,                      // 是否嵌入PDF
-//                    null                       // PFB路径(仅AFM/PFM字体需要)
-//            );
-//
-//            fontResolver.addFont(
-//                    boldFont,
-//                    "思源黑体 Medium",
-//                    BaseFont.IDENTITY_H,
-//                    true,
-//                    null
-//            );
-//            html = html.replace("C:\\", "file:///C:/")
-//                    .replace("\\", "/");
-//
-//            // 设置HTML(确保CSS中使用相同的font-family)
-//            renderer.setDocumentFromString(s, "file:///");
-//
-//            // 渲染PDF
-//            renderer.layout();
-//            renderer.createPDF(os);
-//        }
-//        Path path = Paths.get(outputPdfPath);
-//        // 获取文件名和扩展名
-//        String fileName = path.getFileName().toString();
-//        int dotIndex = fileName.lastIndexOf('.');
-//        String baseName = (dotIndex == -1) ? fileName : fileName.substring(0, dotIndex);
-//        String extension = (dotIndex == -1) ? "" : fileName.substring(dotIndex);
-//        // 构建新文件名
-//        String newFileName = baseName + "1" + extension;
-//        // 构建完整新路径
-//        String newFilePath = path.resolveSibling(newFileName).toString();
-//
-//    }
-
+    /**
+     *  操作已生成的pdf
+     * @param inputPdfPath   输入pdf
+     * @param outputPdfPath  输出pdf
+     * @param backgroundImagePath  图片文件夹位置
+     * @param onlyCollectPageNumbers 是否是遍历目录获取标题位置
+     * @throws Exception
+     */
     private static void pdfReader(String inputPdfPath, String outputPdfPath,
-                                           String backgroundImagePath, boolean onlyCollectPageNumbers)
+                                  String backgroundImagePath, boolean onlyCollectPageNumbers)
             throws Exception {
         PdfReader reader = new PdfReader(inputPdfPath);
         PdfStamper stamper = new PdfStamper(reader, new FileOutputStream(outputPdfPath));
+        int startPage = 0;
         if (onlyCollectPageNumbers) {
-            int startPage = 0;
+
             Pattern startPattern = Pattern.compile("^1\\.\\s+报告概述$");
 
             // 查找起始页
@@ -500,15 +460,61 @@ public class OfficeUtil1 {
                 }
             }
         }
+        //一级标题图形背景
+        Pattern firstLevelTitlePattern = Pattern.compile("^(\\d+)\\.\\s+([\\u4e00-\\u9fa5a-zA-Z].*)$");
+        Set<Integer> styledPages = new HashSet<>();
+        startPage = pageNumberMap.get("startPage");
+        for (Map.Entry<String, Integer> stringIntegerEntry : pageNumberMap.entrySet()) {
+            String key = stringIntegerEntry.getKey();
+            int value = stringIntegerEntry.getValue();
+            if (firstLevelTitlePattern.matcher(key).find()) {
+                styledPages.add(value + startPage - 1);
+            }
+        }
+
+        // 在识别出的页面添加标题样式
+        for (Integer pageNum : styledPages) {
+            if (pageNum < 1 || pageNum > reader.getNumberOfPages()) {
+                continue;
+            }
+            PdfContentByte underContent = stamper.getUnderContent(pageNum);
+
+            // 固定位置参数(可根据需要调整)
+            float pageWidth = reader.getPageSize(pageNum).getWidth();
+            float pageHeight = reader.getPageSize(pageNum).getHeight();
+            float xPos = 50; // 左侧边距
+            float yPos = pageHeight - 50; // 距离顶部50单位
+
+            // 1. 绘制圆形背景
+            underContent.saveState();
+            underContent.setColorFill(new Color(210, 235, 255)); // 浅蓝色填充
+            underContent.circle(
+                    xPos,
+                    yPos - 8,  // 圆形中心Y
+                    10         // 半径
+            );
+            underContent.fill();
+            underContent.restoreState();
+
+            // 2. 绘制横线
+            underContent.saveState();
+            underContent.setColorStroke(new Color(0x16, 0x77, 0xFF)); // 浅蓝色线条
+            underContent.setLineWidth(1.5f); // 线宽
+            underContent.moveTo(xPos - 10, yPos - 20);
+            underContent.lineTo(pageWidth - xPos + 10, yPos - 20);
+            underContent.stroke();
+            underContent.restoreState();
+
+        }
 
-        //添加背景
+        //封面背景
         PdfContentByte background = stamper.getUnderContent(1);
         Image image = Image.getInstance(backgroundImagePath);
         image.scaleAbsolute(PageSize.A4.getWidth(), PageSize.A4.getHeight());
         image.setAbsolutePosition(0, 0);
         background.addImage(image);
         int lastPageIndex = reader.getNumberOfPages();
-        //删除空白页
+        //删除最后一页空白页
         String lastPageText = new PdfTextExtractor(reader).getTextFromPage(lastPageIndex);
         // 使用 selectPages 方法删除最后一页
         ArrayList<Integer> pagesToKeep = new ArrayList<>();

+ 63 - 13
easier-report-biz/src/test/java/com/yaoyicloud/render/test/TestPdf.java

@@ -21,6 +21,7 @@ import org.jsoup.select.Elements;
 import org.xhtmlrenderer.pdf.ITextFontResolver;
 import org.xhtmlrenderer.pdf.ITextRenderer;
 
+import java.awt.*;
 import java.io.BufferedWriter;
 import java.io.ByteArrayOutputStream;
 import java.io.File;
@@ -33,8 +34,10 @@ import java.io.OutputStream;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.HashMap;
+import java.util.HashSet;
 import java.util.LinkedHashMap;
 import java.util.Map;
+import java.util.Set;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 
@@ -52,7 +55,7 @@ public class TestPdf {
         String imageDir = "D:\\li312\\Desktop\\image";
 
         String docxHtml = convert(
-                "C:\\Users\\yyy\\dev\\yyc3\\easier-be\\temp\\1917398743161577473_e512b527cc4e4604bdf359131cfb323a.docx",
+                "C:\\Users\\yyy\\dev\\yyc3\\easier-be\\temp\\1917480583499137025_d3055874bb63496f9950d71139ff82b5.docx",
                 "C:\\Users\\yyy\\dev\\yyc3\\easier-be\\file\\image");
         // String docxHtml = convert("C:\\Users\\yyy\\dev\\yyc3\\easier-be\\temp\\1922178317200191489_d60ec021eb6b497eb6360ea8d78d8245.docx",
         // "C:\\Users\\yyy\\dev\\yyc3\\easier-be\\file\\image");
@@ -65,16 +68,16 @@ public class TestPdf {
             e.printStackTrace();
         }
 
-        String docxHtml1 = formatHtml(docxHtml,true);
-        try (BufferedWriter writer1 = new BufferedWriter(new FileWriter("1.html"))) {
-            writer1.write(docxHtml1);
-        } catch (IOException e) {
-            System.err.println("写入 1.html 文件时发生错误: " + e.getMessage());
-            e.printStackTrace();
-        }
-        convertHtmlToPdf(docxHtml1, "./output.pdf");
-
-        convertHtmlToPdf2(docxHtml, "./output2.pdf");
+     //   String docxHtml1 = formatHtml(docxHtml,true);
+//        try (BufferedWriter writer1 = new BufferedWriter(new FileWriter("1.html"))) {
+//            writer1.write(docxHtml1);
+//        } catch (IOException e) {
+//            System.err.println("写入 1.html 文件时发生错误: " + e.getMessage());
+//            e.printStackTrace();
+//        }
+//        convertHtmlToPdf(docxHtml1, "./output.pdf");
+//
+//        convertHtmlToPdf2(docxHtml, "./output2.pdf");
 
     }
 
@@ -127,8 +130,8 @@ public class TestPdf {
                 .URIResolver(new FileURIResolver(imageDirFile) {
                     @Override
                     public String resolve(String uri) {
-                        String filename = uri.replace("word/media/", "");
-                        return new File(imageDirFile, filename).getAbsolutePath().replace("/", "\\");
+                       // String filename = uri.replace("word/media/", "");
+                        return new File(imageDirFile, uri).getAbsolutePath().replace("/", "\\");
                     }
                 });
 
@@ -811,6 +814,53 @@ divs.last().addClass("start-counting");
                 }
             }
         }
+
+
+        Pattern firstLevelTitlePattern = Pattern.compile("^(\\d+)\\.\\s+([\\u4e00-\\u9fa5a-zA-Z].*)$");
+        Set<Integer> styledPages = new HashSet<>();
+        startPage = pageNumberMap.get("startPage");
+        for (Map.Entry<String, Integer> stringIntegerEntry : pageNumberMap.entrySet()) {
+            String key = stringIntegerEntry.getKey();
+            int value = stringIntegerEntry.getValue();
+            if (firstLevelTitlePattern.matcher(key).find()) {
+                styledPages.add(value + startPage-1);
+            }
+        }
+
+        // 在识别出的页面添加标题样式
+        for (Integer pageNum : styledPages) {
+            if (pageNum < 1 || pageNum > reader.getNumberOfPages()) {
+                continue;
+            }
+            PdfContentByte underContent = stamper.getUnderContent(pageNum);
+
+            // 固定位置参数(可根据需要调整)
+            float pageWidth = reader.getPageSize(pageNum).getWidth();
+            float pageHeight = reader.getPageSize(pageNum).getHeight();
+            float xPos = 50; // 左侧边距
+            float yPos = pageHeight - 50; // 距离顶部50单位
+
+            // 1. 绘制圆形背景
+            underContent.saveState();
+            underContent.setColorFill(new Color(210, 235, 255)); // 浅蓝色填充
+            underContent.circle(
+                    xPos ,  // 圆形中心X
+                    yPos - 8,  // 圆形中心Y
+                    10         // 半径
+            );
+            underContent.fill();
+            underContent.restoreState();
+
+            // 2. 绘制横线
+            underContent.saveState();
+            underContent.setColorStroke(new Color(0x16, 0x77, 0xFF)); // 浅蓝色线条
+            underContent.setLineWidth(1.5f); // 线宽
+            underContent.moveTo(xPos-10, yPos - 20); // 起点(左边界 + margin)
+            underContent.lineTo(pageWidth -xPos+10 , yPos - 20);
+            underContent.stroke();
+            underContent.restoreState();
+
+        }
         int lastPageIndex = reader.getNumberOfPages();
         String lastPageText = new PdfTextExtractor(reader).getTextFromPage(lastPageIndex);
         // 使用 selectPages 方法删除最后一页