添加政策导出

This commit is contained in:
chenshaohua
2026-07-08 19:32:40 +08:00
parent f52d7f0eda
commit 3703b8e2bc
3 changed files with 171 additions and 0 deletions

View File

@@ -116,6 +116,12 @@
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-jsr310</artifactId>
</dependency>
<!-- openpdf -->
<dependency>
<groupId>com.github.librepdf</groupId>
<artifactId>openpdf</artifactId>
<version>1.3.30</version>
</dependency>
</dependencies>
</project>

View File

@@ -3,6 +3,7 @@ package com.ruoyi.cms.controller.cms;
import com.ruoyi.cms.domain.policy.PolicyInfo;
import com.ruoyi.cms.domain.policy.PolicyInfoQuery;
import com.ruoyi.cms.service.policy.IPolicyInfoService;
import com.ruoyi.cms.util.pdf.OpenPdfPolicyUtil;
import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
@@ -17,6 +18,7 @@ import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.IOException;
import java.time.LocalDate;
@@ -168,4 +170,13 @@ public class CmsPolicyInfoController extends BaseController {
return error("文件上传失败:" + e.getMessage());
}
}
@GetMapping("/exportUtil")
public void pdfByUtil(@RequestParam Long id, HttpServletResponse response) throws Exception {
PolicyInfo policyInfo=policyInfoService.selectById(id);
if (policyInfo == null) {
throw new RuntimeException("未查询到对应政策信息");
}
OpenPdfPolicyUtil.exportPolicyPdf(policyInfo, response);
}
}

View File

@@ -0,0 +1,154 @@
package com.ruoyi.cms.util.pdf;
import com.lowagie.text.*;
import com.lowagie.text.pdf.BaseFont;
import com.lowagie.text.pdf.PdfWriter;
import com.ruoyi.cms.domain.policy.PolicyInfo;
import javax.servlet.http.HttpServletResponse;
import java.io.OutputStream;
import java.net.URLEncoder;
import java.text.SimpleDateFormat;
/**
* OpenPDF 政策PDF导出工具
* 优化:表格列宽、文本清洗、自动换行、去除多余空行、增加边框区分
*/
public class OpenPdfPolicyUtil {
private static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd");
private static BaseFont baseFont;
static {
try {
// OpenPDF内置中文字体无需外部ttfLinux/Windows通用
baseFont = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED);
} catch (Exception e) {
throw new RuntimeException("初始化PDF宋体字体失败", e);
}
}
public static void exportPolicyPdf(PolicyInfo policy, HttpServletResponse response) throws Exception {
String rawName = getCleanText(policy.getZcmc());
String fileName = URLEncoder.encode(rawName + ".pdf", "UTF-8");
response.setContentType("application/pdf");
response.setHeader("Content-Disposition", "attachment;filename=" + fileName);
response.setHeader("Cache-Control", "no-cache");
try (OutputStream out = response.getOutputStream();
Document document = new Document(PageSize.A4, 40, 40, 60, 60)) {
PdfWriter writer = PdfWriter.getInstance(document, out);
document.open();
// ========== 1、文档主标题 ==========
Font titleFont = new Font(baseFont, 20, Font.BOLD);
Paragraph titlePara = new Paragraph(getCleanText(policy.getZcmc()), titleFont);
titlePara.setAlignment(Element.ALIGN_CENTER);
titlePara.setSpacingAfter(25);
document.add(titlePara);
// ========== 2、基础信息表格调整列宽20/30/20/30加宽标题列 ==========
Font tableHeadFont = new Font(baseFont, 12, Font.BOLD);
Font tableValFont = new Font(baseFont, 12);
Table infoTable = new Table(4);
float[] colWidth = new float[]{20, 30, 20, 30};
infoTable.setWidths(colWidth);
infoTable.setWidth(100);
infoTable.setBorderWidth(0.6f); // 增加边框,区分单元格
// 第一行
infoTable.addCell(buildCell(getCleanText("政策类型"), tableHeadFont));
infoTable.addCell(buildCell(getCleanText(policy.getZclx()), tableValFont));
infoTable.addCell(buildCell(getCleanText("政策级别"), tableHeadFont));
infoTable.addCell(buildCell(getCleanText(policy.getZcLevel()), tableValFont));
// 第二行
infoTable.addCell(buildCell(getCleanText("发文单位"), tableHeadFont));
infoTable.addCell(buildCell(getCleanText(policy.getSourceUnit()), tableValFont));
infoTable.addCell(buildCell(getCleanText("受理单位"), tableHeadFont));
infoTable.addCell(buildCell(getCleanText(policy.getAcceptUnit()), tableValFont));
// 第三行
String publishDate = policy.getPublishTime() == null ? "" : DATE_FORMAT.format(policy.getPublishTime());
infoTable.addCell(buildCell(getCleanText("发文时间"), tableHeadFont));
infoTable.addCell(buildCell(publishDate, tableValFont));
infoTable.addCell(buildCell(getCleanText("浏览数量"), tableHeadFont));
infoTable.addCell(buildCell(String.valueOf(policy.getViewNum()), tableValFont));
document.add(infoTable);
document.add(new Paragraph(" "));
// ========== 3、政策四大章节 ==========
Font sectionTitleFont = new Font(baseFont, 14, Font.BOLD);
Font contentFont = new Font(baseFont, 11);
float lineMulti = 1.45f;
addSection(document, "一、政策内容", policy.getZcContent(), sectionTitleFont, contentFont, lineMulti);
addSection(document, "二、补贴标准", policy.getSubsidyStandard(), sectionTitleFont, contentFont, lineMulti);
addSection(document, "三、申报条件", policy.getApplyCondition(), sectionTitleFont, contentFont, lineMulti);
addSection(document, "四、经办渠道", policy.getHandleChannel(), sectionTitleFont, contentFont, lineMulti);
/*// ========== 4、附件信息 ==========
Paragraph fileTitlePara = new Paragraph("五、附件文件信息", sectionTitleFont);
fileTitlePara.setSpacingBefore(18);
fileTitlePara.setSpacingAfter(8);
document.add(fileTitlePara);
String fileInfo = "文件名称:" + getCleanText(policy.getFileName()) + "\n文件地址" + getCleanText(policy.getFileUrl());
Paragraph filePara = new Paragraph(fileInfo, contentFont);
filePara.setMultipliedLeading(lineMulti);
filePara.setIndentationLeft(5);
document.add(filePara);*/
document.close();
writer.flush();
out.flush();
}
}
/**
* 构建单元格:移除多余\n换行仅靠段落间距消除大量空白行
*/
private static Cell buildCell(String text, Font font) {
Cell cell = new Cell();
Paragraph cellPara = new Paragraph(text, font);
cellPara.setSpacingBefore(4);
cellPara.setSpacingAfter(4);
cell.add(cellPara);
return cell;
}
/**
* 新增:统一处理章节标题+正文,自动清洗文本、缩进、行间距
*/
private static void addSection(Document doc, String title, String rawContent, Font titleFont, Font contentFont, float lineHeight) throws DocumentException {
Paragraph titlePara = new Paragraph(title, titleFont);
titlePara.setSpacingBefore(14);
titlePara.setSpacingAfter(7);
doc.add(titlePara);
String cleanContent = getCleanText(rawContent);
Paragraph contentPara = new Paragraph(cleanContent, contentFont);
contentPara.setMultipliedLeading(lineHeight);
contentPara.setIndentationLeft(5);
doc.add(contentPara);
}
/**
* 核心文本清洗:清除多余换行、空格、统一全角符号,解决公文排版错乱
*/
private static String getCleanText(String str) {
if (str == null || str.trim().isEmpty()) {
return "";
}
// 去除首尾空白
String temp = str.trim();
// 多个换行替换为单个换行
temp = temp.replaceAll("\\s*\n\\s*", "\n");
// 多个空格压缩为单个
temp = temp.replaceAll(" +", " ");
// 全角顿号统一(可选,按需开启)
temp = temp.replace("", "");
return temp;
}
}