Commit 90e36664 authored by wangxl's avatar wangxl

Merge remote-tracking branch 'origin/master'

# Conflicts:
#	science-admin/src/main/java/com/yiboshi/science/rest/v1/ComProjectController.java
parents 83d9d057 8e4417e9
......@@ -49,10 +49,10 @@ public class ComProjectKpitDTO extends BaseDTO {
private Integer displayOrder;
/** 一级指标显示 */
@ApiModelProperty(value = "一级指标显示", position = 7)
private boolean oneDisplay;
private Boolean oneDisplay;
/** 二级指标显示 */
@ApiModelProperty(value = "二级指标显示", position = 7)
private boolean towDisplay;
private Boolean towDisplay;
/** 一级指标行合并数 */
@ApiModelProperty(value = "一级指标行合并数", position = 7)
private Integer oneRowSpan;
......
......@@ -6,10 +6,7 @@ import com.yiboshi.arch.base.ResponseDataModel;
import com.yiboshi.science.base.Pagination;
import com.yiboshi.science.config.annotation.Logs;
import com.yiboshi.science.config.security.SecurityUserHolder;
import com.yiboshi.science.entity.ComProject;
import com.yiboshi.science.entity.ComProjectAudit;
import com.yiboshi.science.entity.ComProjectTask;
import com.yiboshi.science.entity.SelectListItem;
import com.yiboshi.science.entity.*;
import com.yiboshi.science.enumeration.CommonEnum;
import com.yiboshi.science.param.dto.*;
import com.yiboshi.science.param.query.ComProjectQueryVO;
......@@ -18,6 +15,9 @@ import com.yiboshi.science.service.ComFileService;
import com.yiboshi.science.service.ComProjectService;
import com.yiboshi.science.service.ComProjectTaskService;
import com.yiboshi.science.utils.*;
import com.yiboshi.science.service.SystemParameterService;
import com.yiboshi.science.utils.ProjectInfoToPDF;
import com.yiboshi.science.utils.StringUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
......@@ -87,19 +87,8 @@ public class ComProjectController extends BaseController<ComProjectService, ComP
@ApiOperation(value = "项目信息导出", httpMethod = "POST", notes = "项目信息导出")
@RequestMapping("/export/{id}")
@PostMapping
public ResponseDataModel<byte[]> export(@PathVariable String id) {
try {
return ResponseDataModel.ok(PDF.createPDF(response,"tmp-report.html",new ComProjectDTO()));
} catch (Exception e) {
return new ResponseDataModel(ResponseCode.SERVER_ERROR, "");
}
}
@ApiOperation(value = "项目信息导出", httpMethod = "POST", notes = "项目信息导出")
@RequestMapping("/export1/{id}")
@PostMapping
public void export1(@PathVariable String id) {
comProjectService.export(id, request, response);
public void export(@PathVariable String id) {
comProjectService.export(id,request,response);
}
/**
......@@ -171,7 +160,7 @@ public class ComProjectController extends BaseController<ComProjectService, ComP
@PostMapping
@RequestMapping("/audit")
@Logs(value = CommonEnum.logType.projectAudit)
public ResponseDataModel<String> audit(@Validated @RequestBody ComProjectAuditDTO comProjectAudit, BindingResult bindingResult) {
public ResponseDataModel<String> audit(@Validated @RequestBody ComProjectAuditDTO comProjectAudit, BindingResult bindingResult) {
comProjectService.audit(comProjectAudit, SecurityUserHolder.getUnitId(), SecurityUserHolder.getUnitCode());
return ResponseDataModel.ok("审核成功");
}
......@@ -231,5 +220,4 @@ public class ComProjectController extends BaseController<ComProjectService, ComP
ProjectInfoToPDF.generateProjectPDF(dto, outputPath);
return ResponseDataModel.ok("项目信息导入成功!");
}
}
\ No newline at end of file
......@@ -16,4 +16,26 @@ public class DateUtils {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
return sdf.format(date);
}
/**
* 格式化起止年限
* @param date 开始日期
* @return 格式化后的日期范围字符串
*/
public static String formatDateRange(Date date, int type) {
// 定义日期格式
SimpleDateFormat sdf;
if (type == 1)
sdf = new SimpleDateFormat("yyyy年MM月");
else
sdf = new SimpleDateFormat("yyyy年MM月dd日");
return sdf.format(date);
}
public static int getDateYear(Date date) {
Calendar calendar = Calendar.getInstance();
calendar.setTime(date); // 将Date对象设置到Calendar对象中
return calendar.get(Calendar.YEAR);
}
}
package com.yiboshi.science.utils;
import com.itextpdf.kernel.font.PdfFont;
import com.itextpdf.kernel.font.PdfFontFactory;
import com.itextpdf.text.*;
import com.itextpdf.text.pdf.*;
import com.yiboshi.science.param.dto.ComProjectDTO;
import org.springframework.core.io.ClassPathResource;
import com.yiboshi.science.entity.SystemParameter;
import com.yiboshi.science.enumeration.CommonEnum;
import com.yiboshi.science.param.dto.*;
import java.io.*;
import java.util.Objects;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
public class ProjectInfoToPDF {
......@@ -14,47 +21,62 @@ public class ProjectInfoToPDF {
* @param project 项目信息
* @param outputPath 输出路径
*/
public static void generateProjectPDF(ComProjectDTO project, String outputPath) throws DocumentException, IOException {
public static void generateProjectPDF(ComProjectDTO project, String outputPath, List<SystemParameter> projAttributeList) throws DocumentException, IOException {
Document document = new Document(PageSize.A4);
PdfWriter writer = PdfWriter.getInstance(document, new FileOutputStream(outputPath));
document.open();
// 文件水印
String watermark = project.getAppNo();
if (project.getProjState() >= CommonEnum.projState.pass.getCode()) {
watermark = project.getProjNo();
}
// 宋体
BaseFont bfChinese = loadChineseFont("/fonts/simsun.ttc");
// 仿宋
BaseFont fsChinese = loadChineseFont("/fonts/方正仿宋简体.ttf");
BaseFont fsChinese = loadChineseFont("/fonts/simfang.ttf");
// WINGDNG2
BaseFont WINGDNG2 = loadChineseFont("/fonts/WINGDNG2.ttf");
// 添加水印
writer.setPageEvent(new WatermarkPageEvent(watermark, fsChinese));
document.open();
Font labelFont = new Font(bfChinese, 16, Font.NORMAL);
Font valueFont = new Font(bfChinese, 16, Font.NORMAL);
Font normalFont = new Font(bfChinese, 12, Font.NORMAL);
Font boldFont = new Font(bfChinese, 12, Font.BOLD);
//首页内容
FirstPageInfo(document, project, bfChinese);
FirstPageInfo(document, project, bfChinese, fsChinese);
// 添加新页面
document.newPage();
// 添加项目基本信息表格
PdfPTable table = new PdfPTable(2);
table.setWidthPercentage(100);
table.setSpacingBefore(10f);
table.setSpacingAfter(10f);
// 添加项目内容章节
addSection(document, "一、项目基本情况", boldFont);
addProjectBasicTable(document, project, bfChinese, fsChinese); // 添加项目基本信息表格
// 添加横向页面
document.setPageSize(PageSize.A4.rotate());
document.newPage();
// 设置列宽度
float[] columnWidths = {0.3f, 0.7f};
table.setWidths(columnWidths);
// 添加项目组主要成员表格
addProjectMembersTable(document, project, bfChinese, fsChinese);
document.newPage();
// 添加表格内容
addTableRow(table, "项目名称:", project.getProjName(), labelFont, valueFont);
addTableRow(table, "项目申报单位:", project.getProjNo(), labelFont, valueFont);
addTableRow(table, "申请单位:", project.getAppUnitName(), labelFont, valueFont);
addTableRow(table, "项目负责人:", project.getAppPersonName(), labelFont, valueFont);
addTableRow(table, "联系电话:", project.getMobile(), labelFont, valueFont);
addTableRow(table, "电子邮箱:", project.getEmail(), labelFont, valueFont);
// 添加项目绩效目标表
addProjectKPITable(document, project, projAttributeList, bfChinese, fsChinese, WINGDNG2);
document.add(table);
// 恢复为纵向页面
document.setPageSize(PageSize.A4);
document.newPage();
// 添加项目内容章节
addSection(document, "一、项目实施目标", boldFont);
addContent(document, project.getResearchContent(), normalFont);
// 项目经费预算表
addProjectBudgetTable(document, project, bfChinese, fsChinese);
// 添加新页面
document.newPage();
addSection(document, "二、主要技术指标", boldFont);
addContent(document, project.getTechnologyTarget(), normalFont);
......@@ -86,39 +108,34 @@ public class ProjectInfoToPDF {
private static BaseFont loadChineseFont(String fontPath) {
try {
// 从资源文件夹加载字体
InputStream fontStream = ProjectInfoToPDF.class.getResourceAsStream(fontPath);
if (fontStream == null) {
throw new FileNotFoundException("找不到字体文件:" + fontPath);
}
String path = ProjectInfoToPDF.class.getResource(fontPath).getPath();
// 获取文件名作为临时文件的前缀
String fileName = fontPath.substring(fontPath.lastIndexOf('/') + 1);
String prefix = fileName.substring(0, fileName.lastIndexOf('.'));
String suffix = fileName.substring(fileName.lastIndexOf('.'));
// 将字体文件复制到临时文件
File tempFile = File.createTempFile(prefix, suffix);
tempFile.deleteOnExit();
try (FileOutputStream fos = new FileOutputStream(tempFile)) {
byte[] buffer = new byte[1024];
int length;
while ((length = fontStream.read(buffer)) > 0) {
fos.write(buffer, 0, length);
}
// 根据字体文件类型使用不同的加载方式
if (fontPath.toLowerCase().endsWith(".ttc")) {
return BaseFont.createFont(path + ",0", BaseFont.IDENTITY_H, BaseFont.EMBEDDED);
} else {
return BaseFont.createFont(path, BaseFont.IDENTITY_H, BaseFont.EMBEDDED);
}
return BaseFont.createFont(tempFile.getAbsolutePath() + ",0", BaseFont.IDENTITY_H, BaseFont.EMBEDDED);
} catch (Exception e) {
throw new RuntimeException("加载字体文件失败,请确保resources目录下存在字体文件 " + fontPath + ":" + e.getMessage(), e);
}
}
//首页
private static Document FirstPageInfo(Document document, ComProjectDTO project, BaseFont bfChinese) throws DocumentException {
/**
* 首页项目信息
* @param document
* @param project
* @param bfChinese
* @param fsChinese
* @return
* @throws DocumentException
*/
private static Document FirstPageInfo(Document document, ComProjectDTO project, BaseFont bfChinese, BaseFont fsChinese) throws DocumentException {
Font titleFont = new Font(bfChinese, 20, Font.BOLD);
Font normalFont = new Font(bfChinese, 12, Font.NORMAL);
Font labelFont = new Font(fsChinese, 16, Font.NORMAL);
Font valueFont = new Font(bfChinese, 16, Font.NORMAL);
// 添加项目编号到左上角
Paragraph projNo;
......@@ -146,46 +163,674 @@ public class ProjectInfoToPDF {
projNo.add(Chunk.NEWLINE);
}
projNo.setAlignment(Element.ALIGN_LEFT);
projNo.setSpacingAfter(10);
projNo.setSpacingAfter(50f);
document.add(projNo);
// 添加标题
Paragraph title = new Paragraph("省级临床医学中心科研项目申请书", titleFont);
title.setAlignment(Element.ALIGN_CENTER);
title.setSpacingAfter(20);
title.setSpacingAfter(50f); // 增加标题后的间距
document.add(title);
// 添加项目基本信息表格
PdfPTable table = new PdfPTable(2);
table.setWidthPercentage(95);
table.setSpacingBefore(50f); // 增加表格前的间距
table.setSpacingAfter(10f);
table.setHorizontalAlignment(Element.ALIGN_LEFT); // 设置表格左对齐
// 设置列宽度
float[] columnWidths = {0.35f, 0.65f};
table.setWidths(columnWidths);
// 添加表格内容
addTableRow(table, "项目名称:", project.getProjName(), labelFont, valueFont);
addTableRow(table, "申报单位:", project.getAppUnitName(), labelFont, valueFont);
addTableRow(table, "推荐部门(丙方):", "", labelFont, valueFont);
addTableRow(table, "项目负责人:", project.getAppPersonName(), labelFont, valueFont);
addTableRow(table, "联系电话:", project.getMobile(), labelFont, valueFont);
addTableRow(table, "起止年限:", DateUtils.formatDateRange(project.getStartDate(), 1) + "至" + DateUtils.formatDateRange(project.getEndDate(), 1), labelFont, valueFont);
addTableRow(table, "填报日期:", DateUtils.formatDateRange(project.getCreated(), 2), labelFont, valueFont);
document.add(table);
return document;
}
//添加表格
/**
* 添加首页项目表格信息
* @param table
* @param label
* @param value
* @param labelFont
* @param valueFont
*/
private static void addTableRow(PdfPTable table, String label, String value, Font labelFont, Font valueFont) {
// 标签单元格
PdfPCell labelCell = new PdfPCell(new Phrase(label, labelFont));
labelCell.setMinimumHeight(25f);
labelCell.setMinimumHeight(28f);
labelCell.setVerticalAlignment(Element.ALIGN_MIDDLE);
labelCell.setHorizontalAlignment(Element.ALIGN_RIGHT);
labelCell.setPaddingRight(5f);
labelCell.setBorder(Rectangle.NO_BORDER);
// 创建带下划线的值
Chunk valueChunk;
// 值单元格
Phrase valuePhrase;
if (value != null && !value.trim().isEmpty()) {
valueChunk = new Chunk(value, valueFont);
valuePhrase = new Phrase(value, valueFont);
} else {
valueChunk = new Chunk(" ", valueFont);
valuePhrase = new Phrase(" ", valueFont); // 空值时使用一个空格
}
valueChunk.setUnderline(0.1f, -2f); // 添加下划线
PdfPCell valueCell = new PdfPCell(new Phrase(valueChunk));
valueCell.setMinimumHeight(25f);
PdfPCell valueCell = new PdfPCell(valuePhrase);
valueCell.setMinimumHeight(28f);
valueCell.setVerticalAlignment(Element.ALIGN_MIDDLE);
valueCell.setHorizontalAlignment(Element.ALIGN_LEFT); // 修改为左对齐
valueCell.setPaddingLeft(5f);
valueCell.setPaddingRight(10f);
valueCell.setBorder(Rectangle.NO_BORDER);
// 添加自定义事件来绘制下划线
valueCell.setCellEvent(new PdfPCellEvent() {
public void cellLayout(PdfPCell cell, Rectangle position, PdfContentByte[] canvases) {
PdfContentByte cb = canvases[PdfPTable.LINECANVAS];
cb.setLineWidth(0.5f);
float y = position.getBottom() + 2; // 调整下划线位置
cb.moveTo(position.getLeft(), y);
cb.lineTo(position.getRight(), y);
cb.stroke();
}
});
table.addCell(labelCell);
table.addCell(valueCell);
}
/**
* 项目基本信息
* @param document
* @param project
* @param bfChinese
* @param fsChinese
* @throws DocumentException
*/
private static void addProjectBasicTable(Document document, ComProjectDTO project, BaseFont bfChinese, BaseFont fsChinese) throws DocumentException {
Font labelFont = new Font(bfChinese, 12, Font.NORMAL);
Font valueFont = new Font(fsChinese, 12, Font.NORMAL);
Font titleFont = new Font(bfChinese, 12, Font.BOLD);
// 创建一个大表格
PdfPTable mainTable = new PdfPTable(1); // 单列表格
mainTable.setWidthPercentage(95);
mainTable.setSpacingBefore(10f);
// 申请人信息部分
PdfPTable personTable = new PdfPTable(9); // 9列,第一列用于标题
float[] personWidths = {1f, 1.5f, 2f, 1f, 2f, 1.5f, 2f, 2f, 2f}; // 调整第一列宽度
personTable.setWidths(personWidths);
// 申请人信息标题行
PdfPCell titleCell = new PdfPCell(new Phrase("申\n请\n人\n信\n息", titleFont));
titleCell.setRowspan(6); // 合并6行
titleCell.setHorizontalAlignment(Element.ALIGN_CENTER);
titleCell.setVerticalAlignment(Element.ALIGN_MIDDLE);
titleCell.setMinimumHeight(150f); // 调整高度以适应内容
personTable.addCell(titleCell);
// 第一行
addBasicTableCell(personTable, "姓 名", project.getAppPersonName(), 2, labelFont, valueFont);
addBasicTableCell(personTable, "性别", project.getSex(), 2, labelFont, valueFont);
addBasicTableCell(personTable, "出生年月", DateUtils.formatDateRange(project.getBirthday(), 1), 2, labelFont, valueFont);
addBasicTableCell(personTable, "民族", project.getNationName(), 2, labelFont, valueFont);
// 第二行
addBasicTableCell(personTable, "学 位", project.getDegreeName(), 2, labelFont, valueFont);
addBasicTableCell(personTable, "职称", project.getTitleName(), 2, labelFont, valueFont);
addBasicTableCell(personTable, "每年工作时间(月)", project.getJobTime().toString(), 4, labelFont, valueFont);
// 第三行
addBasicTableCell(personTable, "电 话", project.getMobile(), 4, labelFont, valueFont);
addBasicTableCell(personTable, "电子邮箱", project.getEmail(), 4, labelFont, valueFont);
// 第四行
addBasicTableCell(personTable, "个人通讯地址", project.getAddress(), 8, labelFont, valueFont);
// 第五行
addBasicTableCell(personTable, "工作单位", project.getAppUnitName(), 8, labelFont, valueFont);
// 第六行
addBasicTableCell(personTable, "主要研究领域", project.getMainResearchAreas(), 8, labelFont, valueFont);
// 将申请人信息表格添加到主表格
PdfPCell personCell = new PdfPCell(personTable);
personCell.setPadding(0);
personCell.setBorder(Rectangle.BOX);
mainTable.addCell(personCell);
// 申请单位信息部分
PdfPTable unitTable = new PdfPTable(5); // 5列,第一列用于标题
float[] unitWidths = {1.2f, 3f, 5f, 3f, 5f}; // 调整所有列的比例,保持第一列宽度一致
unitTable.setWidths(unitWidths);
// 申请单位信息标题行
titleCell = new PdfPCell(new Phrase("申\n请\n单\n位\n信\n息", titleFont));
titleCell.setRowspan(5); // 合并5行
titleCell.setHorizontalAlignment(Element.ALIGN_CENTER);
titleCell.setVerticalAlignment(Element.ALIGN_MIDDLE);
titleCell.setMinimumHeight(100f);
unitTable.addCell(titleCell);
// 单位信息内容
addBasicTableCell(unitTable, "单位名称", project.getAppUnitName(), 4, labelFont, valueFont);
addBasicTableCell(unitTable, "联系人", project.getUnitLinkName(), 2, labelFont, valueFont);
addBasicTableCell(unitTable, "电话", project.getUnitLinkMobile(), 2, labelFont, valueFont);
addBasicTableCell(unitTable, "电子信箱", project.getUnitLinkEmail(), 2, labelFont, valueFont);
addBasicTableCell(unitTable, "传真", project.getUnitLinkFax(), 2, labelFont, valueFont);
// 将申请单位信息表格添加到主表格
PdfPCell unitCell = new PdfPCell(unitTable);
unitCell.setPadding(0);
unitCell.setBorder(Rectangle.BOX);
mainTable.addCell(unitCell);
// 项目基本情况部分
PdfPTable projTable = new PdfPTable(5); // 5列,第一列用于标题
float[] projWidths = {1.2f, 3f, 5f, 3f, 5f}; // 与申请单位信息表格使用相同的比例
projTable.setWidths(projWidths);
// 项目基本情况标题行
titleCell = new PdfPCell(new Phrase("项\n目\n基\n本\n信\n息", titleFont));
titleCell.setRowspan(8); // 合并8行
titleCell.setHorizontalAlignment(Element.ALIGN_CENTER);
titleCell.setVerticalAlignment(Element.ALIGN_MIDDLE);
titleCell.setMinimumHeight(200f);
projTable.addCell(titleCell);
// 项目基本情况内容
addBasicTableCell(projTable, "项目名称", project.getProjName(), 4, labelFont, valueFont);
addBasicTableCell(projTable, "学科代码", project.getKnowledgeName(), 2, labelFont, valueFont);
addBasicTableCell(projTable, "选题范围", project.getSubjectScope(), 2, labelFont, valueFont);
addBasicTableCell(projTable, "项目类别", project.getProjClassName(), 2, labelFont, valueFont);
addBasicTableCell(projTable, "研究期限", DateUtils.formatDateRange(project.getStartDate(), 1), 2, labelFont, valueFont);
addBasicTableCell(projTable, "项目总经费(万元)", project.getTotalFunding().toString(), 2, labelFont, valueFont);
addBasicTableCell(projTable, "申请经费", project.getGovFunding().toString(), 2, labelFont, valueFont);
addBasicTableCell(projTable, "项目摘要", project.getProjAbstract(), 4, labelFont, valueFont);
addBasicTableCell(projTable, "关键词", project.getProjKeywords(), 4, labelFont, valueFont);
// 将项目基本情况表格添加到主表格
PdfPCell projCell = new PdfPCell(projTable);
projCell.setPadding(0);
projCell.setBorder(Rectangle.BOX);
mainTable.addCell(projCell);
document.add(mainTable);
}
/**
* 添加基本信息表格单元格
* @param table
* @param label
* @param value
* @param colspan
* @param labelFont
* @param valueFont
*/
private static void addBasicTableCell(PdfPTable table, String label, String value, int colspan, Font labelFont, Font valueFont) {
PdfPCell labelCell = new PdfPCell(new Phrase(label, labelFont));
labelCell.setMinimumHeight(25f);
labelCell.setVerticalAlignment(Element.ALIGN_MIDDLE);
labelCell.setHorizontalAlignment(Element.ALIGN_CENTER);
table.addCell(labelCell);
PdfPCell valueCell = new PdfPCell(new Phrase(value != null ? value : "", valueFont));
valueCell.setMinimumHeight(25f);
valueCell.setVerticalAlignment(Element.ALIGN_MIDDLE);
valueCell.setHorizontalAlignment(Element.ALIGN_LEFT);
valueCell.setColspan(colspan - 1);
table.addCell(valueCell);
}
/**
* 添加项目组主要成员表格
* @param document PDF文档
* @param project 项目信息
* @param bfChinese 宋体字体
* @param fsChinese 仿宋字体
* @throws DocumentException
*/
private static void addProjectMembersTable(Document document, ComProjectDTO project, BaseFont bfChinese, BaseFont fsChinese) throws DocumentException {
Font titleFont = new Font(bfChinese, 12, Font.BOLD);
Font contentFont = new Font(bfChinese, 12, Font.NORMAL);
// 添加表格标题
Paragraph title = new Paragraph("项目组主要成员", titleFont);
title.add(new Chunk(" (注:不包括项目申请人)", contentFont));
title.setAlignment(Element.ALIGN_CENTER);
title.setSpacingAfter(10f);
document.add(title);
// 创建表格
PdfPTable table = new PdfPTable(12); // 12列
table.setWidthPercentage(98);
// 设置列宽度比例
float[] widths = {0.5f, 1f, 1f, 0.8f, 0.8f, 0.8f, 2f, 0.8f, 1.2f, 1f, 1.2f, 1f};
table.setWidths(widths);
// 添加表头
String[] headers = {"序号", "姓名", "出生年月", "性别", "职称", "学位", "工作单位", "电话", "电子邮箱", "证件号码", "项目分工", "每年工作时间(月)"};
for (String header : headers) {
PdfPCell cell = new PdfPCell(new Phrase(header, contentFont));
cell.setHorizontalAlignment(Element.ALIGN_CENTER);
cell.setVerticalAlignment(Element.ALIGN_MIDDLE);
cell.setMinimumHeight(25f);
table.addCell(cell);
}
List<ComProjectMembersDTO> members = project.getMembers();
// 添加成员数据
if (members != null && !members.isEmpty()) {
int index = 1;
for (ComProjectMembersDTO member : members) {
// 序号
addCenterCell(table, String.valueOf(index++), contentFont);
// 姓名
addCenterCell(table, member.getName(), contentFont);
// 出生年月
addCenterCell(table, DateUtils.formatDateRange(member.getBirthday(), 1), contentFont);
// 性别
addCenterCell(table, member.getSex(), contentFont);
// 职称
addCenterCell(table, member.getTitleName(), contentFont);
// 学位
addCenterCell(table, member.getDegreeName(), contentFont);
// 工作单位
addCenterCell(table, member.getWorkUnit(), contentFont);
// 电话
addCenterCell(table, member.getMobile(), contentFont);
// 电子邮箱
addCenterCell(table, member.getEmail(), contentFont);
// 证件号码
addCenterCell(table, member.getCertId(), contentFont);
// 项目分工
addCenterCell(table, member.getProjWork(), contentFont);
// 每年工作时间
addCenterCell(table, member.getForMonths().toString(), contentFont);
}
}
// 如果成员数量少于9个,添加空行到9行
int emptyRows = 9 - (members != null ? members.size() : 0);
for (int i = 0; i < emptyRows; i++) {
for (int j = 0; j < 12; j++) {
addCenterCell(table, "", contentFont);
}
}
document.add(table);
// 项目组成员统计表格
PdfPTable statsTable = new PdfPTable(7); // 7列
statsTable.setWidthPercentage(98);
statsTable.setSpacingBefore(20f); // 与上表格保持间距
// 设置列宽度比例
float[] statsWidths = {1f, 1f, 1f, 1f, 1f, 1f, 1f};
statsTable.setWidths(statsWidths);
// 添加表头
String[] statsHeaders = {"总人数", "高级", "中级", "初级", "博士后", "博士生", "硕士生"};
for (String header : statsHeaders) {
PdfPCell cell = new PdfPCell(new Phrase(header, contentFont));
cell.setHorizontalAlignment(Element.ALIGN_CENTER);
cell.setVerticalAlignment(Element.ALIGN_MIDDLE);
cell.setMinimumHeight(25f);
statsTable.addCell(cell);
}
// 添加数据行
addCenterCell(statsTable, project.getMemCount() != null ? project.getMemCount().toString() : "", contentFont);
addCenterCell(statsTable, project.getMemHighCount() != null ? project.getMemHighCount().toString() : "", contentFont);
addCenterCell(statsTable, project.getMemMiddleCount() != null ? project.getMemMiddleCount().toString() : "", contentFont);
addCenterCell(statsTable, project.getMemLowCount() != null ? project.getMemLowCount().toString() : "", contentFont);
addCenterCell(statsTable, project.getMemBshCount() != null ? project.getMemBshCount().toString() : "", contentFont);
addCenterCell(statsTable, project.getMemBsCount() != null ? project.getMemBsCount().toString() : "", contentFont);
addCenterCell(statsTable, project.getMemSsCount() != null ? project.getMemSsCount().toString() : "", contentFont);
document.add(statsTable);
}
/**
* 添加项目绩效目标表
* @param document PDF文档
* @param project 项目信息
* @param bfChinese 宋体字体
* @param fsChinese 仿宋字体
* @throws DocumentException
*/
private static void addProjectKPITable(Document document, ComProjectDTO project, List<SystemParameter> projAttributeList, BaseFont bfChinese, BaseFont fsChinese, BaseFont WINGDNG2) throws DocumentException, IOException {
ProjectKPIStatisticDTO kpitDTO = project.getProjectKPI();
List<ComProjectKpitDTO> detail = project.getProjectKPI().getThreeLevel();
Font titleFont = new Font(bfChinese, 12, Font.BOLD);
Font contentFont = new Font(bfChinese, 12, Font.NORMAL);
Font wingdng2Font = new Font(WINGDNG2, 12, Font.NORMAL);
// 添加表格标题
Paragraph title = new Paragraph("绩效目标表", titleFont);
title.setAlignment(Element.ALIGN_CENTER);
title.setSpacingAfter(10f);
document.add(title);
// 创建主表格
PdfPTable mainTable = new PdfPTable(5);
mainTable.setWidthPercentage(98);
float[] widths = {0.8f, 1f, 2f, 1f, 2f};
mainTable.setWidths(widths);
// 添加年度标题
PdfPCell yearCell = new PdfPCell(new Phrase(kpitDTO.getReportYear() + "年度", titleFont));
yearCell.setColspan(5);
yearCell.setHorizontalAlignment(Element.ALIGN_CENTER);
yearCell.setMinimumHeight(25f);
mainTable.addCell(yearCell);
// 项目名称
addLabelValueRow(mainTable, "项目名称", kpitDTO.getProjName(), 5, titleFont, contentFont);
// 主管处室和实施单位
addLabelValueRow(mainTable, "主管处室", kpitDTO.getManagerDept(), 2, titleFont, contentFont);
addLabelValueRow(mainTable, "实施单位", kpitDTO.getAppUnitName(), 1, titleFont, contentFont);
// 项目属性
PdfPCell labelCell = new PdfPCell(new Phrase("项目属性", titleFont));
labelCell.setMinimumHeight(25f);
labelCell.setHorizontalAlignment(Element.ALIGN_CENTER);
mainTable.addCell(labelCell);
// 创建复选框和文字组合
Phrase checkboxPhrase = new Phrase();
if (Objects.nonNull(kpitDTO.getProjAttribute())) {
for (SystemParameter param : projAttributeList) {
if (param.getId().toLowerCase().equals(kpitDTO.getProjAttribute().toLowerCase())) {
checkboxPhrase.add(new Chunk("R", wingdng2Font)); // 选中状态
} else {
checkboxPhrase.add(new Chunk("£", wingdng2Font)); // 未选中状态
}
checkboxPhrase.add(new Chunk(" " + param.getName() + " ", contentFont)); // 使用中文字体显示文字
}
} else {
checkboxPhrase.add(new Chunk("£", wingdng2Font));
checkboxPhrase.add(new Chunk(" 新增项目 ", contentFont));
checkboxPhrase.add(new Chunk("£", wingdng2Font));
checkboxPhrase.add(new Chunk(" 延续项目", contentFont));
}
PdfPCell valueCell = new PdfPCell(checkboxPhrase);
valueCell.setMinimumHeight(25f);
valueCell.setColspan(2);
mainTable.addCell(valueCell);
// 项目期
addLabelValueRow(mainTable, "项目期", kpitDTO.getProjDeadline(), 1, titleFont, contentFont);
// 项目资金(万元)标题行
PdfPCell fundTitle = new PdfPCell(new Phrase("项目资金\n(万元)", titleFont));
fundTitle.setRowspan(3);
fundTitle.setVerticalAlignment(Element.ALIGN_MIDDLE);
fundTitle.setHorizontalAlignment(Element.ALIGN_CENTER);
mainTable.addCell(fundTitle);
// 总体资金总额和年度资金总额
addLabelValueRow(mainTable, "总体资金总额", kpitDTO.getTotalBudget().toString(), 1, titleFont, contentFont);
addLabelValueRow(mainTable, "年度资金总额", kpitDTO.getYearTotal().toString(), 1, titleFont, contentFont);
// 其中:财政拨款(两行)
addLabelValueRow(mainTable, "其中:财政拨款", kpitDTO.getApplyFunds().toString(), 1, titleFont, contentFont);
addLabelValueRow(mainTable, "其中:财政拨款", kpitDTO.getYearApply().toString(), 1, titleFont, contentFont);
// 其他资金(两行)
addLabelValueRow(mainTable, "其他资金", kpitDTO.getSelfFunds().toString(), 1, titleFont, contentFont);
addLabelValueRow(mainTable, "其他资金", kpitDTO.getYearSelf().toString(), 1, titleFont, contentFont);
document.add(mainTable);
// 总体考核目标
PdfPTable middleTable = new PdfPTable(5);
middleTable.setWidthPercentage(98);
float[] middleWidths = {0.8f, 3.2f, 1f, 1f, 1f};
middleTable.setWidths(middleWidths);
// 添加左侧标题单元格
PdfPCell titleCell = new PdfPCell(new Phrase("总体考核\n目标", titleFont));
titleCell.setRowspan(3); // 合并三行
titleCell.setVerticalAlignment(Element.ALIGN_MIDDLE);
titleCell.setHorizontalAlignment(Element.ALIGN_CENTER);
middleTable.addCell(titleCell);
// 添加总体目标标题行
int startYear = DateUtils.getDateYear(kpitDTO.getStartDate());
int endYear = DateUtils.getDateYear(kpitDTO.getEndDate());
PdfPCell totalTargetCell = new PdfPCell(new Phrase("总体目标(" + startYear + "年—" + endYear + "年)", titleFont));
totalTargetCell.setHorizontalAlignment(Element.ALIGN_CENTER);
totalTargetCell.setMinimumHeight(25f);
middleTable.addCell(totalTargetCell);
// 添加分年度指标标题行
PdfPCell yearlyTitleCell = new PdfPCell(new Phrase("分年度指标", titleFont));
yearlyTitleCell.setColspan(3); // 合并三列
yearlyTitleCell.setHorizontalAlignment(Element.ALIGN_CENTER);
yearlyTitleCell.setMinimumHeight(25f);
middleTable.addCell(yearlyTitleCell);
// 添加总体目标内容
PdfPCell totalTargetContentCell = new PdfPCell(new Phrase(kpitDTO.getYearTarget(), contentFont));
totalTargetContentCell.setRowspan(2); // 合并两行
totalTargetContentCell.setVerticalAlignment(Element.ALIGN_MIDDLE);
totalTargetContentCell.setMinimumHeight(50f); // 设置较大的高度以容纳多行内容
middleTable.addCell(totalTargetContentCell);
// 添加年度标题行
for (int i = 0; i < 3; i++) {
PdfPCell yearCCell = new PdfPCell(new Phrase((startYear + i) + "年", titleFont));
yearCCell.setHorizontalAlignment(Element.ALIGN_CENTER);
yearCCell.setVerticalAlignment(Element.ALIGN_MIDDLE);
yearCCell.setMinimumHeight(25f);
middleTable.addCell(yearCCell);
}
// 添加年度内容
PdfPCell yearContentCell = new PdfPCell(new Phrase(kpitDTO.getYear1Goal(), contentFont));
yearContentCell.setMinimumHeight(50f);
yearContentCell.setVerticalAlignment(Element.ALIGN_MIDDLE);
middleTable.addCell(yearContentCell);
yearContentCell = new PdfPCell(new Phrase(kpitDTO.getYear2Goal(), contentFont));
yearContentCell.setMinimumHeight(50f);
yearContentCell.setVerticalAlignment(Element.ALIGN_MIDDLE);
middleTable.addCell(yearContentCell);
yearContentCell = new PdfPCell(new Phrase(kpitDTO.getYear3Goal(), contentFont));
yearContentCell.setMinimumHeight(50f);
yearContentCell.setVerticalAlignment(Element.ALIGN_MIDDLE);
middleTable.addCell(yearContentCell);
document.add(middleTable);
addTargetDetailTable(document, kpitDTO, titleFont, contentFont);
}
private static void addTargetDetailTable(Document document, ProjectKPIStatisticDTO kpitDTO, Font titleFont, Font contentFont) throws DocumentException {
PdfPTable detailTable = new PdfPTable(11);
detailTable.setWidthPercentage(98);
float[] detailWidths = {0.5f, 0.5f, 0.5f, 1.5f, 0.5f, 0.5f, 0.5f, 1.5f, 0.5f, 0.5f, 0.5f};
detailTable.setWidths(detailWidths);
//总考核目标
addTitleCell(detailTable, "总体考核目标", 0, kpitDTO.getTotalRowSpan(), titleFont);
//一级指标
addTitleCell(detailTable, "一级指标", 0, 2, titleFont);
//二级指标
addTitleCell(detailTable, "二级指标", 0, 2, titleFont);
//三级指标
addTitleCell(detailTable, "三级指标", 0, 2, titleFont);
//指标值
addTitleCell(detailTable, "指标值", 0, 2, titleFont);
//绩效标准
addTitleCell(detailTable, "绩效标准", 0, 2, titleFont);
//二级指标
addTitleCell(detailTable, "二级指标", 0, 2, titleFont);
//三级指标
addTitleCell(detailTable, "三级指标", 0, 2, titleFont);
//指标值
addTitleCell(detailTable, "指标值", 3, 0, titleFont);
int startYear = DateUtils.getDateYear(kpitDTO.getStartDate());
addTitleCell(detailTable, startYear + "年", 0, 0, contentFont);
addTitleCell(detailTable, (startYear + 1) + "年", 0, 0, contentFont);
addTitleCell(detailTable, (startYear + 2) + "年", 0, 0, contentFont);
List<ComProjectKpitDTO> list = kpitDTO.getThreeLevel();
for (int i = 0; i < list.size(); i++) {
ComProjectKpitDTO model = list.get(i);
if (model.getOneDisplay())
addTitleCell(detailTable, model.getOneLevelName(), 0, model.getOneRowSpan(), contentFont);
if (model.getTowDisplay())
addTitleCell(detailTable, model.getTowLevelName(), 0, model.getTowRowSpan(), contentFont);
addTitleCell(detailTable, model.getKpitName(), 0, 0, contentFont);
addTitleCell(detailTable, model.getTargetValue() != null ? model.getTargetValue().toString() : "", 0, 0, contentFont);
addTitleCell(detailTable, model.getPerformanceStandard() != null ? model.getPerformanceStandard().toString() : "", 0, 0, contentFont);
if (model.getTowDisplay())
addTitleCell(detailTable, model.getTowLevelName(), 0, model.getTowRowSpan(), contentFont);
addTitleCell(detailTable, model.getKpitName(), 0, 0, contentFont);
addTitleCell(detailTable, model.getYearValue1() != null ? model.getYearValue1().toString() : "", 0, 0, contentFont);
addTitleCell(detailTable, model.getYearValue2() != null ? model.getYearValue2().toString() : "", 0, 0, contentFont);
addTitleCell(detailTable, model.getYearValue3() != null ? model.getYearValue3().toString() : "", 0, 0, contentFont);
}
document.add(detailTable);
}
private static void addTitleCell(PdfPTable detailTable, String title, int colSpan, int rowSpan, Font contentFont) {
PdfPCell titleCell = new PdfPCell(new Phrase(title, contentFont));
if (colSpan > 1)
titleCell.setColspan(colSpan);
if (rowSpan > 1)
titleCell.setRowspan(rowSpan);
titleCell.setVerticalAlignment(Element.ALIGN_MIDDLE);
titleCell.setHorizontalAlignment(Element.ALIGN_CENTER);
detailTable.addCell(titleCell);
}
/**
* 项目经费预算表
* @param document
* @param project
* @param bfChinese
* @param fsChinese
* @throws DocumentException
*/
private static void addProjectBudgetTable(Document document, ComProjectDTO project, BaseFont bfChinese, BaseFont fsChinese) throws DocumentException {
Font titleFont = new Font(bfChinese, 12, Font.BOLD);
Font contentFont = new Font(bfChinese, 12, Font.NORMAL);
Font detailFont = new Font(fsChinese, 9, Font.NORMAL);
// 添加表格标题
Paragraph title = new Paragraph("项目经费预算表", titleFont);
title.setAlignment(Element.ALIGN_CENTER);
title.setSpacingAfter(10f);
document.add(title);
// 添加金额单位说明
Paragraph unit = new Paragraph("金额单位:万元(保留两位小数)", detailFont);
unit.setAlignment(Element.ALIGN_RIGHT);
unit.setSpacingAfter(10f);
document.add(unit);
// 创建预算表格
PdfPTable budgetTable = new PdfPTable(5);
budgetTable.setWidthPercentage(98);
float[] widths = {2f, 0.5f, 0.5f, 0.5f, 1f};
budgetTable.setWidths(widths);
// 添加表头
String[] headers = {"预算科目", "总预算数", "财政资金", "自筹资金", "备注"};
for (String header : headers) {
addTitleCell(budgetTable, header, 0, 0, titleFont);
}
for (ComProjectBudgetDTO dto : project.getBudget()) {
if (dto.getBudgetId().toLowerCase().equals("3b1f57d3-6aec-4129-aef5-702a1accfe01") || dto.getBudgetId().toLowerCase().equals("3b1f57d3-6aec-4129-aef5-702a1accfe08"))
addBudgetTitleCell(budgetTable, dto.getBudgetName(), titleFont, Element.ALIGN_LEFT, 0, 0);
else
addBudgetTitleCell(budgetTable, dto.getBudgetName(), contentFont, Element.ALIGN_LEFT, 0, 0);
addBudgetTitleCell(budgetTable, dto.getTotalBudget().toString(), contentFont, Element.ALIGN_CENTER, 0, 0);
addBudgetTitleCell(budgetTable, dto.getApplyFunds().toString(), contentFont, Element.ALIGN_CENTER, 0, 0);
addBudgetTitleCell(budgetTable, dto.getSelfFunds().toString(), contentFont, Element.ALIGN_CENTER, 0, 0);
addBudgetTitleCell(budgetTable, dto.getCalculationBasis(), contentFont, Element.ALIGN_LEFT, 0, 0);
}
addBudgetTitleCell(budgetTable, "三、分年度用款计划", titleFont, Element.ALIGN_LEFT, 5, 0);
addBudgetTitleCell(budgetTable, "年度", titleFont, Element.ALIGN_CENTER, 0, 0);
addBudgetTitleCell(budgetTable, "第一年", titleFont, Element.ALIGN_CENTER, 0, 0);
addBudgetTitleCell(budgetTable, "第二年", titleFont, Element.ALIGN_CENTER, 0, 0);
addBudgetTitleCell(budgetTable, "第三年", titleFont, Element.ALIGN_CENTER, 0, 0);
addBudgetTitleCell(budgetTable, "合计", titleFont, Element.ALIGN_CENTER, 0, 0);
for (ComProjectFundPlanDTO dto : project.getFundPlan()) {
addBudgetTitleCell(budgetTable, dto.getFundName(), titleFont, Element.ALIGN_CENTER, 0, 0);
addBudgetTitleCell(budgetTable, dto.getYearValue1().toString(), contentFont, Element.ALIGN_CENTER, 0, 0);
addBudgetTitleCell(budgetTable, dto.getYearValue2().toString(), contentFont, Element.ALIGN_CENTER, 0, 0);
addBudgetTitleCell(budgetTable, dto.getYearValue3().toString(), contentFont, Element.ALIGN_CENTER, 0, 0);
addBudgetTitleCell(budgetTable, dto.getTotalAmount().toString(), contentFont, Element.ALIGN_CENTER, 0, 0);
}
document.add(budgetTable);
}
private static void addBudgetTitleCell(PdfPTable table, String title, Font contentFont, int HorizontalAlignment, int colSpan, int rowSpan) {
PdfPCell titleCell = new PdfPCell(new Phrase(title, contentFont));
if (colSpan > 1)
titleCell.setColspan(colSpan);
if (rowSpan > 1)
titleCell.setRowspan(rowSpan);
titleCell.setVerticalAlignment(Element.ALIGN_MIDDLE);
titleCell.setHorizontalAlignment(HorizontalAlignment);
table.addCell(titleCell);
}
/**
* 添加标签值行
*/
private static void addLabelValueRow(PdfPTable table, String label, String value, int valueColspan, Font titleFont, Font contentFont) {
PdfPCell labelCell = new PdfPCell(new Phrase(label, titleFont));
labelCell.setMinimumHeight(25f);
labelCell.setVerticalAlignment(Element.ALIGN_MIDDLE);
labelCell.setHorizontalAlignment(Element.ALIGN_CENTER);
table.addCell(labelCell);
PdfPCell valueCell = new PdfPCell(new Phrase(value != null ? value : "", contentFont));
valueCell.setMinimumHeight(25f);
valueCell.setVerticalAlignment(Element.ALIGN_MIDDLE);
valueCell.setHorizontalAlignment(Element.ALIGN_LEFT);
valueCell.setColspan(valueColspan);
table.addCell(valueCell);
}
/**
* 添加居中对齐的单元格
*/
private static void addCenterCell(PdfPTable table, String content, Font font) {
PdfPCell cell = new PdfPCell(new Phrase(content != null ? content : "", font));
cell.setHorizontalAlignment(Element.ALIGN_CENTER);
cell.setVerticalAlignment(Element.ALIGN_MIDDLE);
cell.setMinimumHeight(25f);
table.addCell(cell);
}
private static void addSection(Document document, String title, Font font) throws DocumentException {
Paragraph section = new Paragraph(title, font);
section.setSpacingBefore(15);
......@@ -221,4 +866,74 @@ public class ProjectInfoToPDF {
unitSignature.setSpacingBefore(30);
document.add(unitSignature);
}
/**
* 水印页面事件
*/
private static class WatermarkPageEvent extends PdfPageEventHelper {
private String watermarkText;
private BaseFont baseFont;
public WatermarkPageEvent(String watermarkText, BaseFont baseFont) {
this.watermarkText = watermarkText;
this.baseFont = baseFont;
}
@Override
public void onEndPage(PdfWriter writer, Document document) {
try {
PdfContentByte canvas = writer.getDirectContentUnder();
Rectangle pageSize = document.getPageSize();
float width = pageSize.getWidth();
float height = pageSize.getHeight();
// 设置水印字体
canvas.saveState();
canvas.beginText();
canvas.setFontAndSize(baseFont, 30); // 减小字体大小
canvas.setGrayFill(0.9f);
// 计算水印间距
float xStep = width / 2; // 水平间距
float yStep = height / 3; // 垂直间距
// 在页面上添加多个水印
for (float y = yStep/2; y < height; y += yStep) {
for (float x = xStep/2; x < width; x += xStep) {
canvas.showTextAligned(Element.ALIGN_CENTER,
watermarkText,
x,
y,
45);
}
}
canvas.endText();
canvas.restoreState();
// 添加页码
PdfContentByte canvasOver = writer.getDirectContent();
canvasOver.saveState();
canvasOver.beginText();
canvasOver.setFontAndSize(baseFont, 12); // 设置页码字体大小
canvasOver.setColorFill(BaseColor.BLACK);
// 页码文本
String text = String.format("第 %d 页", writer.getPageNumber());
// 在页面底部居中添加页码
canvasOver.showTextAligned(Element.ALIGN_CENTER,
text,
width / 2, // 页面中心
15, // 距离底部15单位,降低页码位置
0); // 不旋转
canvasOver.endText();
canvasOver.restoreState();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment