添加政策导出
This commit is contained in:
@@ -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>
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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内置中文字体,无需外部ttf,Linux/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;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user