fei
2 天以前 38553de8fe4a824919563db827019909caa65f9c
archiveManager/src/main/java/com/ruoyi/service/impl/pdfGenerateService.java
@@ -7,15 +7,15 @@
import com.itextpdf.text.Font;
import com.itextpdf.text.Image;
import com.itextpdf.text.Rectangle;
import com.itextpdf.text.pdf.BaseFont;
import com.itextpdf.text.pdf.PdfPCell;
import com.itextpdf.text.pdf.PdfPTable;
import com.itextpdf.text.pdf.PdfWriter;
import com.itextpdf.text.pdf.*;
import com.ruoyi.common.config.RuoYiConfig;
import com.ruoyi.domain.ArchiveRecords;
import com.ruoyi.domain.vo.DocumentMaterialFileStyle;
import com.ruoyi.domain.vo.DocumentMaterialsVo;
import com.ruoyi.domain.vo.DocumentMaterialsVoSmall;
import com.ruoyi.service.IArchiveRecordsService;
import com.ruoyi.service.IDocumentMaterialsService;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.*;
import org.springframework.beans.factory.annotation.Autowired;
@@ -28,6 +28,10 @@
import java.io.*;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
@Service
@@ -36,11 +40,14 @@
    private BarcodeService barcodeService;
    @Autowired
    private IDocumentMaterialsService documentMaterialsService;
    @Autowired
    private IArchiveRecordsService iArchiveRecordsService;
    //生产二维码
    public byte[] createQrCodeN(String content, int width, int height) throws IOException {
        QrConfig config = new QrConfig(width, height);
        config.setMargin(3);
        config.setMargin(0);
        // 高纠错级别
        config.setErrorCorrection(ErrorCorrectionLevel.H);
        // 设置前景色,既二维码颜色(自行选择颜色修改)
@@ -260,67 +267,130 @@
    }
    // 自定义页面事件类,用于在每个新页面添加卷内封面和卷号
    private class DirectoryHeaderPageEvent extends PdfPageEventHelper {
        private String volumeNumber;
        private BaseFont bfChinese;
        private Font chineseFont;
        private Font chineseFont1;
        private Image barcodeImage;
        public DirectoryHeaderPageEvent(String volumeNumber, BaseFont bfChinese, Font chineseFont, Font chineseFont1, Image barcodeImage) {
            this.volumeNumber = volumeNumber;
            this.bfChinese = bfChinese;
            this.chineseFont = chineseFont;
            this.chineseFont1 = chineseFont1;
            this.barcodeImage = barcodeImage;
        }
        @Override
        public void onStartPage(PdfWriter writer, Document document) {
            try {
                PdfContentByte cb = writer.getDirectContent();
                float pageWidth = document.getPageSize().getWidth();
                float pageHeight = document.getPageSize().getHeight();
                // 1. 添加条形码(居中显示,页面顶部)
                float barcodeWidth = barcodeImage.getScaledWidth();
                float barcodeHeight = barcodeImage.getScaledHeight();
                float barcodeX = (pageWidth - barcodeWidth) / 2;
                float barcodeY = pageHeight - 50 - barcodeHeight; // 页面顶部下方50点
                barcodeImage.setAbsolutePosition(barcodeX, barcodeY);
                cb.addImage(barcodeImage);
                // 2. 添加卷内目录标题(居中显示,条形码下方)
                String title = "卷    内    目    录";
                float titleX = pageWidth / 2;
                float titleY = pageHeight - 100; // 页面顶部下方100点
                cb.beginText();
                // 创建并设置标题为加粗字体
                Font boldTitleFont = new Font(bfChinese, 16, Font.BOLD);
                cb.setFontAndSize(boldTitleFont.getBaseFont(), boldTitleFont.getSize());
                cb.setColorFill(BaseColor.BLACK);
                cb.showTextAligned(PdfContentByte.ALIGN_CENTER, title, titleX, titleY, 0);
                cb.endText();
                // 3. 添加卷号(居右显示,标题下方)
                String label = "卷号:";
                String value = volumeNumber;
                float recordInfoX = pageWidth - 30;
                float recordInfoY = pageHeight - 130; // 页面顶部下方130点
                // 先绘制标签"卷号:"
                cb.beginText();
                // 设置加粗字体,通过Font.BOLD参数
                Font boldFont = new Font(bfChinese, 16, Font.BOLD);
                cb.setFontAndSize(boldFont.getBaseFont(), boldFont.getSize());
                cb.setColorFill(BaseColor.BLACK);
                cb.showTextAligned(PdfContentByte.ALIGN_RIGHT, label + value, recordInfoX, recordInfoY, 0);
                cb.endText();
                // 计算值的位置并绘制下划线
                float labelWidth = bfChinese.getWidthPoint(label, 12);
                float valueWidth = bfChinese.getWidthPoint(value, 12);
                float underlineStartX = recordInfoX - valueWidth;
                float underlineEndX = recordInfoX;
                float underlineY = recordInfoY - 2;
                cb.setColorStroke(BaseColor.BLACK);
                cb.setLineWidth(0.5f);
                cb.moveTo(underlineStartX, underlineY);
                cb.lineTo(underlineEndX, underlineY);
                cb.stroke();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
    //导出卷内目录的pdf
    public void generateFileDirectoryPdf(String pdfPath,List<DocumentMaterialsVo> dvss) throws DocumentException, IOException {
        Document document = new Document();
        PdfWriter.getInstance(document, new FileOutputStream(pdfPath));
        document.open();
        // 创建表格(5列)
        PdfPTable table = new PdfPTable(7);
        // 设置表格宽度(占页面宽度的100%)
        table.setWidthPercentage(100);
        //添加条形码
        String volumeNumber = dvss.get(0).getRecordId();
        Image img = Image.getInstance(barcodeService.generateBarcodeImage(volumeNumber));
        // 设置图片在PDF中的位置(可选)
//        img.setAbsolutePosition(100, 100);
        // 将图片添加到PDF文档中
        PdfPCell pdfPCell = new PdfPCell(img);
        pdfPCell.setBorder(Rectangle.NO_BORDER); // 移除单元格边框
        pdfPCell.setMinimumHeight(40);
        pdfPCell.setUseAscender(true); // 设置可以居中
        pdfPCell.setHorizontalAlignment(PdfPCell.ALIGN_RIGHT); // 设置水平居中
        pdfPCell.setVerticalAlignment(PdfPCell.ALIGN_MIDDLE); // 设置垂直居中
        pdfPCell.setColspan(2);
        pdfPCell.setPaddingBottom(30);
// 创建表格并设置列宽比例
        float[] columnWidths = {35f, 65f}; // 第一列30%,第二列70%
        PdfPTable table1 = new PdfPTable(columnWidths);
//        PdfPTable table = new PdfPTable(2);
        table1.setWidthPercentage(80); // 增大表格宽度百分比
        table1.setHorizontalAlignment(Element.ALIGN_LEFT); // 设置表格整体居中
        table1.setSpacingBefore(30f); // 设置表格前间距
        table1.addCell(pdfPCell);
        document.add(table1);
        // 添加表头
        PdfWriter writer = PdfWriter.getInstance(document, new FileOutputStream(pdfPath));
        // 设置中文字体
        BaseFont bfChinese = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED);
        Font chineseFont = new Font(bfChinese, 12);
        Font chineseFont1 = new Font(bfChinese, 16, Font.BOLD);
        // 添加标题
        Paragraph title = new Paragraph("卷    内    目    录", chineseFont1);
        title.setAlignment(Element.ALIGN_CENTER);
        document.add(title);
        Paragraph withNewLine = new Paragraph("\n");
        document.add(withNewLine);
        document.add(withNewLine);
        // 获取卷号
        String volumeNumber = dvss.get(0).getRecordId();
        // 创建条形码
        Image barcodeImage = Image.getInstance(barcodeService.generateBarcodeImage(volumeNumber));
        barcodeImage.scaleToFit(80, 40); // 设置条形码大小
        // 注册页面事件
        DirectoryHeaderPageEvent pageEvent = new DirectoryHeaderPageEvent(volumeNumber, bfChinese, chineseFont1, chineseFont1, barcodeImage);
        writer.setPageEvent(pageEvent);
        // 设置适当的边距,为卷内封面、条形码和卷号预留空间
        // setMargins(left, right, top, bottom) - 参数顺序:左、右、上、下
        // 增大上边距为160,确保页眉内容有足够空间
        document.setMargins(30, 30, 160, 30);
        document.open();
        // 这里不再需要在第一页手动添加卷内封面内容,页面事件会处理
        // 添加一个空白段落,确保表格内容不会与顶部元素重叠
        Paragraph blankParagraph = new Paragraph("");
        document.add(blankParagraph);
        // 创建表格(7列)
        PdfPTable table = new PdfPTable(7);
        //添加卷号
        Paragraph recordInfo = new Paragraph("卷号:" + volumeNumber, chineseFont);
        recordInfo.setAlignment(Element.ALIGN_RIGHT);
        document.add(recordInfo);
        document.add(withNewLine);
        document.add(withNewLine);
        // 设置表格宽度(占页面宽度的80%,居中显示)
        table.setWidthPercentage(90);
        table.setHorizontalAlignment(Element.ALIGN_CENTER);
        // 设置列宽比例,第4列(文件题名)和第2列(文件编号)设置得更宽
        float[] columnWidths = {10f, 16f, 14f, 30f, 10f, 10f, 10f}; // 调整列宽比例,增加文件编号列的宽度
        table.setWidths(columnWidths);
        // 设置表头行数,这样分页时每页都会自动重复表头
        table.setHeaderRows(1);
        // 添加表头
        String[] headers = {"序号", "文件编号", "责任者", "文件题名", "日期", "页号", "备注"};
        for (String header : headers) {
            PdfPCell cell = new PdfPCell(new Paragraph(header,
@@ -347,9 +417,9 @@
                table.addCell(cell);
                //序号
                //文件编号(档号)
                PdfPCell cell1 = new PdfPCell(new Paragraph(cellData.getDocumentNumber()==null?"":cellData.getDocumentNumber().toString(),
                        chineseFont));
                        new Font(bfChinese, 12)));
                cell1.setHorizontalAlignment(Element.ALIGN_CENTER);
                cell1.setVerticalAlignment(Element.ALIGN_MIDDLE);
@@ -413,6 +483,11 @@
// 创建PDF文档
       List<DocumentMaterialFileStyle> dmfs = documentMaterialsService.findFileStyleInfo(Math.toIntExact(id));
       if(dmfs.isEmpty())
           return;
       System.out.println(dmfs);
       PdfWriter.getInstance(document, new FileOutputStream("09-备考表"+".pdf"));
       document.open();
       // 设置中文字体
@@ -426,12 +501,22 @@
       // 添加内容
     //  String volumeNumber = "D3.4.1-05-2024-0002";
       Paragraph recordInfo = new Paragraph("卷号:" + volumeNumber, chineseFont);
       // 创建卷号段落,使用Chunk来单独处理卷号值并添加下划线
       Paragraph recordInfo = new Paragraph();
       Chunk labelChunk = new Chunk("卷号:", chineseFont);
       Chunk valueChunk = new Chunk(volumeNumber, chineseFont);
       valueChunk.setUnderline(0.5f, -2f); // 添加下划线,0.5f是线宽,-2f是线与文字的距离
       recordInfo.add(labelChunk);
       recordInfo.add(valueChunk);
       recordInfo.setAlignment(Element.ALIGN_RIGHT);
       document.add(recordInfo);
       int allCnt = dmfs.get(0).getCnt() + dmfs.get(1).getCnt() + dmfs.get(2).getCnt();
       int pcc = dmfs.size()<=1?0: dmfs.get(1).getCnt();
       int oth = dmfs.size()<=2?0: dmfs.get(2).getCnt();
       int allCnt = dmfs.get(0).getCnt() + pcc + oth;
       document.add(new Paragraph("          本 案 卷 共 有 文 件 材 料 " + allCnt + " 页"+",其中:文字材料 " +
               dmfs.get(1).getCnt() + " 页"+",图样材料 " + dmfs.get(2).getCnt() + " 页"+",照片 " + dmfs.get(0).getCnt() + " 张", chineseFont));
               pcc + " 页"+",图样材料 " + oth + " 页"+",照片 " + dmfs.get(0).getCnt() + " 张", chineseFont));
       document.add(new Paragraph("说明: ", chineseFont));
@@ -475,15 +560,31 @@
   }
    public void generatePdf(String pdfPath) throws IOException, DocumentException {
    public void generatePdf(String pdfPath, Long id) throws IOException, DocumentException {
        Document document = new Document();
        PdfWriter.getInstance(document, new FileOutputStream(pdfPath));
        document.open();
        String [] tits = {"档        号:","档案馆(室)号:","缩  微  号: ","发  文  号:",
                "案  卷  题  名:","编  制  日  期:","编  制  单  位:","保  管  期  限:","密     级:"};
        String [] cons = {"D3.4.1-05-2024-0002","","","穗规划资源建证〔2024〕2033号","广州市自来水有限公司白云区江高镇江高镇政府西侧、江府路北侧白云区江高镇江高镇政府西侧、江府路北侧新装供水管工程","2024-04-23","广州市规划和自然资源局白云区分局","永久",""};
        String [] tits = {"档号:","档案馆(室)号:","缩微号:","发文号:",
                "案卷题名:","编制日期:","编制单位:","保管期限:","密级:"};
        ArchiveRecords ard = iArchiveRecordsService.selectArchiveRecordsById(id);
        String formattedDate = "";
        if(ard.getPreparationDate()!=null) {
            LocalDate date = ard.getPreparationDate().toInstant()
                    .atZone(ZoneId.systemDefault())
                    .toLocalDate();
            ;
            System.out.println("当前日期: " + date);
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
      formattedDate = date.format(formatter);
        }
        String [] cons = {ard.getRecordId(),ard.getArchiveRoomNumber(),ard.getMicrofilmNumber(),ard.getInquiryNumber(),ard.getCaseTitle(),formattedDate,ard.getPreparationUnit(),
                ard.getRetentionPeriod(),ard.getSecurityClassification()};
        //把图片加入到pdf当中
        Image img = Image.getInstance(createQrCodeN(cons[0], 80, 80));
@@ -504,7 +605,7 @@
        float[] columnWidths = {35f, 65f}; // 第一列30%,第二列70%
        PdfPTable table = new PdfPTable(columnWidths);
//        PdfPTable table = new PdfPTable(2);
        table.setWidthPercentage(80); // 增大表格宽度百分比
        table.setWidthPercentage(78); // 减小表格宽度百分比使两列更紧凑
        table.setHorizontalAlignment(Element.ALIGN_LEFT); // 设置表格整体居中
        table.setSpacingBefore(30f); // 设置表格前间距
        table.setSpacingAfter(90f); // 设置表格后间距
@@ -528,12 +629,64 @@
        // 先计算所有标题的最长长度
        int maxTitleLength = 0;
        for (String tit : tits) {
            maxTitleLength = Math.max(maxTitleLength, tit.length()-1);
        }
        for(int i = 0; i < tits.length; i++) {
            // 使用PdfPTable实现精确对齐
            // 第一行:档号
            PdfPCell labelCell1 = new PdfPCell(new Phrase(tits[i], chineseFont));
            labelCell1.setHorizontalAlignment(Element.ALIGN_RIGHT); // 设置右对齐
            // 实现对齐:在文字之间填充空格,使所有标题总长度相同
            String originalText = tits[i];
            // 计算需要添加的空格数
            int spacesToAdd = maxTitleLength - originalText.length();
            String formattedText = originalText;
            if (spacesToAdd > 0) {
                // 在冒号前的文字之间均匀分配填充空格
                if (originalText.contains(":")) {
                    int colonIndex = originalText.indexOf(":");
                    String textBeforeColon = originalText.substring(0, colonIndex);
                    String textAfterColon = originalText.substring(colonIndex);
                    // 如果冒号前只有一个字符,直接在后面加空格
                    if (textBeforeColon.length() == 1) {
                        String fullWidthSpaces = StringUtils.repeat(" ", spacesToAdd);
                        formattedText = textBeforeColon + fullWidthSpaces + textAfterColon;
                    } else if (textBeforeColon.length() > 1) {
                        // 在文字之间均匀分配空格
                        StringBuilder sb = new StringBuilder();
                        int chars = textBeforeColon.length();
                        int spacesPerGap = spacesToAdd / (chars - 1);
                        int extraSpaces = spacesToAdd % (chars - 1);
                        for (int j = 0; j < chars; j++) {
                            sb.append(textBeforeColon.charAt(j));
                            if (j < chars - 1) {
                                // 添加基本空格
                                sb.append(StringUtils.repeat(" ", spacesPerGap));
                                // 分配剩余空格
                                if (j < extraSpaces) {
                                    sb.append(" ");
                                }
                            }
                        }
                        sb.append(textAfterColon);
                        formattedText = sb.toString();
                    }
                } else {
                    // 如果没有冒号,直接在末尾加空格(应该不会出现这种情况)
                    String fullWidthSpaces = StringUtils.repeat(" ", spacesToAdd);
                    formattedText = originalText + fullWidthSpaces;
                }
            }
            PdfPCell labelCell1 = new PdfPCell(new Phrase(formattedText, chineseFont));
            labelCell1.setHorizontalAlignment(Element.ALIGN_RIGHT); // 单元格右对齐
            labelCell1.setBorder(Rectangle.NO_BORDER);
//            PdfPCell valueCell1 = new PdfPCell(new Phrase(cons[i], chineseFont));
@@ -542,17 +695,18 @@
            labelCell1.setPaddingTop(10f);    // 上内边距10单位
            labelCell1.setPaddingBottom(10f); // 下内边距10单位
            labelCell1.setPaddingLeft(15f);   // 左内边距15单位
            labelCell1.setPaddingRight(15f);  // 右内边距15单位
            labelCell1.setPaddingRight(0f);  // 右内边距15单位
            PdfPCell valueCell1 = new PdfPCell(new Phrase(cons[i], chineseFont));
            valueCell1.setBorder(Rectangle.NO_BORDER);
            valueCell1.setUseBorderPadding(true);
            valueCell1.setUseBorderPadding(false); // 禁用边框内边距计算
            valueCell1.setBorderWidthBottom(0.5f); // 设置底部边框作为下划线
            valueCell1.setMinimumHeight(30);
            valueCell1.setPaddingTop(10f);    // 上内边距10单位
            valueCell1.setPaddingBottom(10f); // 下内边距10单位
            valueCell1.setPaddingLeft(15f);   // 左内边距15单位
            valueCell1.setPaddingLeft(0f);   // 左内边距0单位
            valueCell1.setExtraParagraphSpace(0f); // 移除段落额外空间
            valueCell1.setPaddingRight(15f);  // 右内边距15单位
            table.addCell(labelCell1);
            table.addCell(valueCell1);
@@ -567,7 +721,7 @@
                PdfPCell pdfPCell1 = new PdfPCell(img1);
                pdfPCell1.setBorder(Rectangle.NO_BORDER); // 移除单元格边框
                pdfPCell1.setMinimumHeight(40);
                pdfPCell1.setMinimumHeight(20);
                pdfPCell1.setUseAscender(true); // 设置可以居中
                pdfPCell1.setHorizontalAlignment(PdfPCell.ALIGN_RIGHT); // 设置水平居中
                pdfPCell1.setVerticalAlignment(PdfPCell.ALIGN_MIDDLE); // 设置垂直居中