lowagie(itext)老版本手绘PDF,包含页码、水印、图片、复选框、复杂行列合并等。
入口类:exportPdf
package xcsy.qms.webapi.service;import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.nacos.common.utils.StringUtils;
import com.ibm.icu.text.RuleBasedNumberFormat;
import com.lowagie.text.*;
import com.lowagie.text.Font;
import com.lowagie.text.Rectangle;
import com.lowagie.text.pdf.*;
import kd.bos.dataentity.entity.DynamicObject;
import kd.bos.dataentity.entity.DynamicObjectCollection;
import kd.bos.logging.Log;
import kd.bos.logging.LogFactory;
import kd.bos.openapi.common.result.CustomApiResult;
import kd.bos.servicehelper.BusinessDataServiceHelper;
import org.jsoup.Jsoup;
import xcsy.zjy.webapi.utils.AddImageToEachPageHeader;
import xcsy.zjy.webapi.utils.CheckBoxCellEvent;
import xcsy.zjy.webapi.utils.CheckBoxCellNotEvent;
import xcsy.zjy.webapi.utils.PdfPageUtil;import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.awt.*;
import java.io.IOException;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.net.URLEncoder;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.List;
import java.util.stream.Collectors;/*** @program: xcsy-cosmic* @description: 准入报告pdf导出实现* @author: lyw* @create: 2025-02-13 09:31**/public class ReportsPDFService {private static final Log log = LogFactory.getLog(ReportsPDFService.class);// 定义全局的字体静态变量Font headFont;Font headFont2;Font contentFont;Font titleFont;Font titleFont2;Font titleFontW;SimpleDateFormat format = new SimpleDateFormat("yyyy年MM月dd日");public CustomApiResult<String> exportPdf(HttpServletRequest request, HttpServletResponse response) throws IOException {// 单据idString id = request.getParameter("id");DynamicObject accessReportsDO = BusinessDataServiceHelper.loadSingle(id, "eo45_access_reports");// 防止日志记录获取session异常request.getSession();// 设置编码格式response.setContentType("application/pdf;charset=UTF-8");response.setCharacterEncoding("utf-8");SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMddHHmmss");String fileName = URLEncoder.encode(accessReportsDO.getString("eo45_fac_name") + "联盟工厂质量专项评审报告" + dateFormat.format(new Date()), "UTF-8");response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileName + ".pdf");download(response, accessReportsDO);return CustomApiResult.success("成功");}private void download(HttpServletResponse response, DynamicObject reportData) {// 最大宽度try {// 不同字体(这里定义为同一种字体:包含不同字号、不同style)BaseFont bfChinese = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED);BaseFont bf = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED);headFont = new Font(bf, 18, Font.BOLD, new Color(0, 0, 0));headFont2 = new Font(bf, 14, Font.BOLD, new Color(0, 0, 0));titleFont = new Font(bf, 10, Font.BOLD, new Color(0, 103, 255));titleFont2 = new Font(bf, 12, Font.BOLD, new Color(0, 0, 0));titleFontW = new Font(bf, 12, Font.BOLD, new Color(251, 251, 251));contentFont = new Font(bfChinese, 10, Font.NORMAL, new Color(0, 0, 0));Document document = new Document(new RectangleReadOnly(842F, 595F));// 设置页边距document.setMargins(60, 60, 60, 30);PdfWriter writer = PdfWriter.getInstance(document, response.getOutputStream());// 添加页码writer.setPageEvent(new PdfPageUtil());// 每页表头添加水印(图片)writer.setPageEvent(new AddImageToEachPageHeader());// 打开生成的pdf文件document.open();// 标题1Paragraph paragraph = new Paragraph(reportData.getString("eo45_fac_name") + "联盟工厂质量专项评审报告", headFont);paragraph.setAlignment(1);document.add(paragraph);// 评审总结DynamicObjectCollection resultsDO = reportData.getDynamicObjectCollection("eo45_report_results");DynamicObject entryResults = resultsDO.get(0);// -------基本信息buildBasicInformation(document, entryResults);// -------审核目的buildAuditAim(document, entryResults);// -------审核类型buildAuditType(document, reportData);// -------审核范围buildAuditRange(document, entryResults);// -------审核内容buildAuditContent(document, entryResults);// -------审核方法buildAuditMethod(document, entryResults);// -------审核方背景资料buildAuditData(document, entryResults);// -------审核结论buildAuditResult(document, entryResults);// 标题2Paragraph paragraph2 = new Paragraph("质量专项评审“否决项”评分标准", headFont2);paragraph2.setAlignment(1);document.add(paragraph2);float[] widthsOne = {10f, 20f, 60f, 10f};PdfPTable tableOne = new PdfPTable(widthsOne);handleTableOne(reportData, tableOne);document.add(tableOne);// 标题3Paragraph paragraph3 = new Paragraph("分值汇总", headFont2);paragraph3.setAlignment(1);document.add(paragraph3);float[] widthsTwo = {60f, 20f, 20f};PdfPTable tableTwo = new PdfPTable(widthsTwo);handleTableTwo(reportData, tableTwo);document.add(tableTwo);// 标题4Paragraph paragraph4 = new Paragraph("联盟工厂质量专项评审表", headFont2);paragraph4.setAlignment(1);document.add(paragraph4);float[] widthsThree = {5f, 15f, 30f, 25f, 5f, 5f, 5f, 7f, 25f};PdfPTable tableThree = new PdfPTable(widthsThree);handleTableThree(reportData, tableThree);document.add(tableThree);// 关闭文档document.close();} catch (DocumentException e) {log.error("导出pdf失败DocumentException:{}", e);} catch (Exception e) {log.error("导出pdf失败Exception:{}", e);}}private void handleTableThree(DynamicObject reportData, PdfPTable table) {// 项目分类集合DynamicObjectCollection projectCollection = reportData.getDynamicObjectCollection("eo45_report_projects");// 按eo45_project_id分组Map<String, String> projectMap = new LinkedHashMap<>();// 获取项目,以项目id作为key,排除第一项否决项,按项目seq排序projectCollection.stream().filter(e -> !"0".equals(e.getString("eo45_project_seq"))).sorted(Comparator.comparing(dynamicObject -> dynamicObject.getString("eo45_project_seq"))).forEach(e -> projectMap.put(e.getString("eo45_project_id"), e.getString("eo45_project")));// 段落在其上方留出的空间量table.setSpacingBefore(10f);// 设置表格宽度为100%// 设置表格宽度为100%table.setWidthPercentage(100.0F);table.setHeaderRows(2);table.getDefaultCell().setHorizontalAlignment(1);// 第一行PdfPCell titleCell1 = createCenteredCellForTable("条款编号", 30, new Color(40, 120, 255), titleFontW, "border", "center");titleCell1.setRowspan(2);table.addCell(titleCell1);PdfPCell titleCell2 = createCenteredCellForTable("条款性质", 0, new Color(40, 120, 255), titleFontW, "border", "center");titleCell2.setRowspan(2);table.addCell(titleCell2);PdfPCell titleCell3 = createCenteredCellForTable("审核条款标准", 0, new Color(40, 120, 255), titleFontW, "border", "center");titleCell3.setRowspan(2);table.addCell(titleCell3);PdfPCell titleCell4= createCenteredCellForTable("审核正面发现", 0, new Color(40, 120, 255), titleFontW, "border", "center");titleCell4.setRowspan(2);table.addCell(titleCell4);PdfPCell titleCell10 = createCenteredCellForTable("审核记录及说明", 0, new Color(40, 120, 255), titleFontW, "border", "center");titleCell10.setColspan(6);table.addCell(titleCell10);PdfPCell titleCell5 = createCenteredCellForTable("审核配分", 0, new Color(40, 120, 255), titleFontW, "border", "center");table.addCell(titleCell5);PdfPCell titleCell6 = createCenteredCellForTable("符合程度", 0, new Color(40, 120, 255), titleFontW, "border", "center");table.addCell(titleCell6);PdfPCell titleCell7 = createCenteredCellForTable("实际得分", 0, new Color(40, 120, 255), titleFontW, "border", "center");table.addCell(titleCell7);PdfPCell titleCell8 = createCenteredCellForTable("不符合类型", 0, new Color(40, 120, 255), titleFontW, "border", "center");table.addCell(titleCell8);PdfPCell titleCell9 = createCenteredCellForTable("问题描述", 0, new Color(40, 120, 255), titleFontW, "border", "center");table.addCell(titleCell9);int[] x = {0}; // 项目序号// 添加一级项目projectMap.forEach((projectId, projectName) -> {x[0]++;// 1转一RuleBasedNumberFormat formatter = new RuleBasedNumberFormat(Locale.CHINA, RuleBasedNumberFormat.SPELLOUT);String result = formatter.format(x[0]);// 项目总分BigDecimal projectScoreAll = projectCollection.stream().filter(e -> projectId.equals(e.getString("eo45_project_id"))).map(e -> e.getBigDecimal("eo45_project_scoreall")).findFirst().orElse(BigDecimal.ZERO);PdfPCell projectCell = new PdfPCell(new Paragraph(result + "、" + projectName+ "(" + projectScoreAll.setScale(2, RoundingMode.HALF_UP) + "分)", titleFont));projectCell.setColspan(9);tableCellStyle(projectCell, new Color(237, 239, 240), new Color(242, 247, 255), "border");table.addCell(projectCell);int y = 0; // 分类序号// 二级分类for (DynamicObject categorysDynamicObject : projectCollection) {if (projectId.equals(categorysDynamicObject.getString("eo45_project_id"))) {y++;PdfPCell cellClass = new PdfPCell(new Paragraph(x[0] + "." + y + " "+ categorysDynamicObject.getString("eo45_sort_name") + "(" + categorysDynamicObject.getBigDecimal("eo45_sort_scoreall").setScale(2, RoundingMode.HALF_UP) + "分)", titleFont));cellClass.setColspan(9);tableCellStyle(cellClass, new Color(237, 239, 240), new Color(242, 247, 255), "border");table.addCell(cellClass);// 三级分类内容DynamicObjectCollection contents = categorysDynamicObject.getDynamicObjectCollection("eo45_report_contents");int z = 0; // 内容序号for (DynamicObject content : contents) {z++;String ratio = ""; // 系数// 单选题JSONArray optionArray = JSONArray.parseArray(content.getString("eo45_option_json_tag"));// 问题JSONArray problemArray = JSONArray.parseArray(content.getString("eo45_problem_json_tag"));// 合并行的数量int rowspan = 1;if (problemArray != null && !problemArray.isEmpty()) {rowspan = problemArray.size();}if (optionArray != null && !optionArray.isEmpty()) {for (int j = 0; j < optionArray.size(); j++) {JSONObject option = optionArray.getJSONObject(j);if (option.getInteger("choose") == 1) {if (!"N/A".equals(option.getString("scoreCoefficient"))&& StringUtils.isNotEmpty(option.getString("scoreCoefficient"))) {double decimal = Double.parseDouble(option.getString("scoreCoefficient"));// 转换为百分比并四舍五入到最接近的整数int percentage = (int) Math.round(decimal * 100);ratio = percentage + "%";}break;}}}PdfPCell cell1 = new PdfPCell(new Paragraph(x[0] + "." + y + "." + z, contentFont));cell1.setRowspan(rowspan);PdfPCell cell2 = new PdfPCell(new Paragraph(content.getString("eo45_import_area"), contentFont));cell2.setRowspan(rowspan);String contentContext = "";if (StringUtils.isNotBlank(content.getString("eo45_project_context"))) {org.jsoup.nodes.Document documentResult = Jsoup.parse(content.getString("eo45_project_context"));contentContext = documentResult.text();}PdfPCell cell3 = new PdfPCell(new Paragraph(contentContext, contentFont));cell3.setRowspan(rowspan);PdfPCell cell4 = new PdfPCell(new Paragraph(content.getString("eo45_content_suggestion"), contentFont));cell4.setRowspan(rowspan);PdfPCell cell5 = new PdfPCell(new Paragraph(String.valueOf(content.getBigDecimal("eo45_sum_score").setScale(2, RoundingMode.HALF_UP)), contentFont));cell5.setRowspan(rowspan);PdfPCell cell6 = new PdfPCell(new Paragraph(ratio, contentFont));cell6.setRowspan(rowspan);PdfPCell cell7 = new PdfPCell(new Paragraph(String.valueOf(content.getBigDecimal("eo45_content_score").setScale(2, RoundingMode.HALF_UP)), contentFont));cell7.setRowspan(rowspan);//单元格对齐方式水平、垂直tableCellStyle(cell1, new Color(237, 239, 240), null, "border");cell1.setFixedHeight(20);tableCellStyle(cell2, new Color(237, 239, 240), null, "border");tableCellStyle(cell3, new Color(237, 239, 240), null, "border");tableCellStyle(cell4, new Color(237, 239, 240), null, "border");tableCellStyle(cell5, new Color(237, 239, 240), null, "border");tableCellStyle(cell6, new Color(237, 239, 240), null, "border");tableCellStyle(cell7, new Color(237, 239, 240), null, "border");table.addCell(cell1);table.addCell(cell2);table.addCell(cell3);table.addCell(cell4);table.addCell(cell5);table.addCell(cell6);table.addCell(cell7);PdfPCell cell8, cell9;if (problemArray != null && !problemArray.isEmpty()) {for (int j = 0; j < problemArray.size(); j++) {JSONObject problem = problemArray.getJSONObject(j);String selectContent = "";JSONArray options = JSONArray.parseArray(problem.getString("options"));for (int k = 0; k < options.size(); k++) {JSONObject option = options.getJSONObject(k);if (option.getInteger("choose") == 1) {selectContent = option.getString("selectContent");break;}}cell8 = new PdfPCell(new Paragraph(selectContent, contentFont));cell9 = new PdfPCell(new Paragraph(problem.getString("problem_desc"), contentFont));tableCellStyle(cell8, new Color(237, 239, 240), null, "border");tableCellStyle(cell9, new Color(237, 239, 240), null, "border");table.addCell(cell8);table.addCell(cell9);}} else {cell8 = new PdfPCell(new Paragraph("", contentFont));cell9 = new PdfPCell(new Paragraph("", contentFont));tableCellStyle(cell8, new Color(237, 239, 240), null, "border");tableCellStyle(cell9, new Color(237, 239, 240), null, "border");table.addCell(cell8);table.addCell(cell9);}}}}});}private void handleTableTwo(DynamicObject reportData, PdfPTable table) {// 项目分类集合DynamicObjectCollection projectCollection = reportData.getDynamicObjectCollection("eo45_report_projects");// 按eo45_project_id分组// Map<String, List<DynamicObject>> projectMap = projectCollection.stream().collect(Collectors.groupingBy(dynamicObject -> dynamicObject.getString("eo45_project_id")));Map<String, String> projectMap = new LinkedHashMap<>();// 获取项目,以项目id作为key,排除第一项否决项,按项目seq排序projectCollection.stream().filter(e -> !"0".equals(e.getString("eo45_project_seq"))).sorted(Comparator.comparing(dynamicObject -> dynamicObject.getString("eo45_project_seq"))).forEach(e -> projectMap.put(e.getString("eo45_project_id"), e.getString("eo45_project")));// 段落在其上方留出的空间量table.setSpacingBefore(10f);// 距离下方空间table.setSpacingAfter(20f);// 设置表格宽度为100%table.setWidthPercentage(100.0F);table.setHeaderRows(1);table.getDefaultCell().setHorizontalAlignment(1);// 第一行table.addCell(createCenteredCellForTable("主要项目", 30, new Color(242, 247, 255), titleFont2, null, null));table.addCell(createCenteredCellForTable("项目配分", 0, new Color(242, 247, 255), titleFont2, null, null));table.addCell(createCenteredCellForTable("实际得分", 0, new Color(242, 247, 255), titleFont2, null, null));// 计数int[] projectSeq = {0};// 添加一级项目final BigDecimal[] allScore = {BigDecimal.ZERO}; // 审核分数合计final BigDecimal[] allGetScore = {BigDecimal.ZERO}; // 审核得分projectMap.forEach((projectId, projectName) -> {projectSeq[0]++;// 1转一RuleBasedNumberFormat formatter = new RuleBasedNumberFormat(Locale.CHINA, RuleBasedNumberFormat.SPELLOUT);String result = formatter.format(projectSeq[0]);PdfPCell cell1 = new PdfPCell(new Paragraph(result + "、" + projectName, contentFont));// 获取对应项目的总分和得分BigDecimal eo45ProjectScoreAll = projectCollection.stream().filter(e -> projectId.equals(e.getString("eo45_project_id"))).map(e -> e.getBigDecimal("eo45_project_scoreall")).findFirst().orElse(BigDecimal.ZERO);allScore[0] = allScore[0].add(eo45ProjectScoreAll);BigDecimal eo45ProjectScore = projectCollection.stream().filter(e -> projectId.equals(e.getString("eo45_project_id"))).map(e -> e.getBigDecimal("eo45_project_score")).findFirst().orElse(BigDecimal.ZERO);allGetScore[0] = allGetScore[0].add(eo45ProjectScore);PdfPCell cell2 = new PdfPCell(new Paragraph(String.valueOf(eo45ProjectScoreAll.setScale(2, RoundingMode.HALF_UP)), contentFont));PdfPCell cell3 = new PdfPCell(new Paragraph(String.valueOf(eo45ProjectScore.setScale(2, RoundingMode.HALF_UP)), contentFont));//单元格对齐方式水平、垂直tableCellStyle(cell1, new Color(237, 239, 240), new Color(242, 247, 255), null);cell1.setFixedHeight(20);tableCellStyle(cell2, new Color(237, 239, 240), new Color(242, 247, 255), null);tableCellStyle(cell3, new Color(237, 239, 240), new Color(242, 247, 255), null);table.addCell(cell1);table.addCell(cell2);table.addCell(cell3);// 项目下添加二级分类int sortSeq = 0;for (DynamicObject categorysDynamicObject : projectCollection) {if (projectId.equals(categorysDynamicObject.getString("eo45_project_id"))) {sortSeq++;PdfPCell cell4 = new PdfPCell(new Paragraph(projectSeq[0] + "." + sortSeq + " " + categorysDynamicObject.getString("eo45_sort_name"), contentFont));PdfPCell cell5 = new PdfPCell(new Paragraph(String.valueOf(categorysDynamicObject.getBigDecimal("eo45_sort_scoreall").setScale(2, RoundingMode.HALF_UP)), contentFont));PdfPCell cell6 = new PdfPCell(new Paragraph(String.valueOf(categorysDynamicObject.getBigDecimal("eo45_sort_score").setScale(2, RoundingMode.HALF_UP)), contentFont));tableCellStyle(cell4, new Color(237, 239, 240), null, null);cell4.setFixedHeight(20);tableCellStyle(cell5, new Color(237, 239, 240), null, null);tableCellStyle(cell6, new Color(237, 239, 240), null, null);table.addCell(cell4);table.addCell(cell5);table.addCell(cell6);}}});// 添加分汇总PdfPCell cell4 = new PdfPCell(new Paragraph("审核分合计", titleFont));PdfPCell cell5 = new PdfPCell(new Paragraph(String.valueOf(allScore[0].setScale(2, RoundingMode.HALF_UP)), titleFont));PdfPCell cell6 = new PdfPCell(new Paragraph(String.valueOf(allGetScore[0].setScale(2, RoundingMode.HALF_UP)), titleFont));tableCellStyle(cell4, new Color(237, 239, 240), new Color(242, 247, 255), null);cell4.setFixedHeight(20);tableCellStyle(cell5, new Color(237, 239, 240), new Color(242, 247, 255), null);tableCellStyle(cell6, new Color(237, 239, 240), new Color(242, 247, 255), null);table.addCell(cell4);table.addCell(cell5);table.addCell(cell6);}private void handleTableOne(DynamicObject accessReportDO, PdfPTable table) {// 项目分类集合DynamicObjectCollection projectCollection = accessReportDO.getDynamicObjectCollection("eo45_report_projects");// 获取“否决项”数据DynamicObject oneProject = projectCollection.stream().filter(e -> "0".equals(e.getString("eo45_project_seq"))).collect(Collectors.toList()).get(0);DynamicObjectCollection contents = oneProject.getDynamicObjectCollection("eo45_report_contents");// 段落在其上方留出的空间量table.setSpacingBefore(10f);// 距离下方空间table.setSpacingAfter(20f);// 设置表格宽度为100%table.setWidthPercentage(100.0F);table.setHeaderRows(1);table.getDefaultCell().setHorizontalAlignment(1);// 第一行table.addCell(createCenteredCellForTable("序号", 30, new Color(242, 247, 255), titleFont2, null, null));table.addCell(createCenteredCellForTable("关键领域", 0, new Color(242, 247, 255), titleFont2, null, null));table.addCell(createCenteredCellForTable("检查项目内容", 0, new Color(242, 247, 255), titleFont2, null, null));table.addCell(createCenteredCellForTable("是/否", 0, new Color(242, 247, 255), titleFont2, null, null));// 数据for (int i = 0; i < contents.size(); i++) {PdfPCell cell1 = new PdfPCell(new Paragraph(String.valueOf(i + 1), contentFont));PdfPCell cell2 = new PdfPCell(new Paragraph(contents.get(i).getString("eo45_import_area"), contentFont));// 富文本处理String contentContext = "";if (StringUtils.isNotBlank(contents.get(i).getString("eo45_project_context"))) {org.jsoup.nodes.Document documentResult = Jsoup.parse(contents.get(i).getString("eo45_project_context"));contentContext = documentResult.text();}PdfPCell cell3 = new PdfPCell(new Paragraph(contentContext, contentFont));// 获取选项JSONArray optionJsonArray = JSONArray.parseArray(contents.get(i).getString("eo45_option_json_tag"));String selectContent = "";if (optionJsonArray != null && !optionJsonArray.isEmpty()) {for (int j = 0; j < optionJsonArray.size(); j++) {JSONObject optionJson = optionJsonArray.getJSONObject(j);if (optionJson.getInteger("choose") == 1) {selectContent = optionJson.getString("options_content");break;}}}PdfPCell cell4 = new PdfPCell(new Paragraph(selectContent, contentFont));tableCellStyle(cell1, new Color(237, 239, 240), null, null);//单元格对齐方式水平、垂直cell1.setFixedHeight(20);tableCellStyle(cell2, new Color(237, 239, 240), null, null);tableCellStyle(cell3, new Color(237, 239, 240), null, null);tableCellStyle(cell4, new Color(237, 239, 240), null, null);table.addCell(cell1);table.addCell(cell2);table.addCell(cell3);table.addCell(cell4);}}private void buildAuditResult(Document document, DynamicObject entryResults) throws DocumentException {// 设置标题document.add(createTitle("审核结论"));// 设置两列float[] widths = {20f, 80f};PdfPTable table = new PdfPTable(widths);// 段落在其上方留出的空间量table.setSpacingBefore(5f);// 设置表格宽度为100%table.setWidthPercentage(100.0F);table.addCell(createCenteredCell("业务审核意见:", 15, null, contentFont));table.addCell(createCenteredCell(entryResults.getString("eo45_audit_conclusion_bus"), 0, null, contentFont));table.addCell(createCenteredCell("研发审核意见:", 15, null, contentFont));table.addCell(createCenteredCell(entryResults.getString("eo45_audit_conclusion_dev"), 0, null, contentFont));table.addCell(createCenteredCell("质量审核意见:", 15, null, contentFont));table.addCell(createCenteredCell(entryResults.getString("eo45_audit_obj"), 0, null, contentFont));table.addCell(createCenteredCell("数字化能力评估审核意见:", 15, null, contentFont));table.addCell(createCenteredCell(entryResults.getString("eo45_audit_conclusion_qu"), 0, null, contentFont));table.addCell(createCenteredCell("综合意见:", 15, null, contentFont));table.addCell(createCenteredCell(entryResults.getString("eo45_audit_conclusion_res"), 0, null, contentFont));document.add(table);}private void buildAuditData(Document document, DynamicObject entryResults) throws DocumentException {// 设置标题document.add(createTitle("审核方背景资料"));PdfPTable table = new PdfPTable(1);// 段落在其上方留出的空间量table.setSpacingBefore(5f);// 设置表格宽度为100%table.setWidthPercentage(100.0F);table.addCell(createCenteredCell(entryResults.getString("eo45_audit_information"), 0, null, contentFont));document.add(table);}private void buildAuditMethod(Document document, DynamicObject entryResults) throws DocumentException {// 设置标题document.add(createTitle("审核方法"));PdfPTable table = new PdfPTable(1);// 段落在其上方留出的空间量table.setSpacingBefore(5f);// 设置表格宽度为100%table.setWidthPercentage(100.0F);table.addCell(createCenteredCell(entryResults.getString("eo45_audit_method"), 0, null, contentFont));document.add(table);}private void buildAuditContent(Document document, DynamicObject entryResults) throws DocumentException {// 设置标题document.add(createTitle("审核内容"));PdfPTable table = new PdfPTable(1);// 段落在其上方留出的空间量table.setSpacingBefore(5f);// 设置表格宽度为100%table.setWidthPercentage(100.0F);table.addCell(createCenteredCell(entryResults.getString("eo45_audit_context"), 0, null, contentFont));document.add(table);}private void buildAuditRange(Document document, DynamicObject entryResults) throws DocumentException {// 设置标题document.add(createTitle("审核范围"));PdfPTable table = new PdfPTable(1);// 段落在其上方留出的空间量table.setSpacingBefore(5f);// 设置表格宽度为100%table.setWidthPercentage(100.0F);table.addCell(createCenteredCell(entryResults.getString("eo45_audit_scope"), 0, null, contentFont));document.add(table);}private void buildAuditType(Document document, DynamicObject data) throws DocumentException {// 设置标题document.add(createTitle("审核类型"));float[] widths = {2f, 8f, 2f, 8f, 2f, 8f, 70f};PdfPTable table = new PdfPTable(widths);// 段落在其上方留出的空间量table.setSpacingBefore(5f);// 设置表格宽度为100%table.setWidthPercentage(100.0F);PdfPCell cell = createCenteredCell("准入审核", 0, null, contentFont);PdfPCell cell2 = new PdfPCell();// 添加复选框绘制事件到单元格if ("0".equals(data.getString("eo45_report_type"))) {cell2.setCellEvent(new CheckBoxCellEvent());} else {cell2.setCellEvent(new CheckBoxCellNotEvent());}cell2.setHorizontalAlignment(PdfPCell.ALIGN_RIGHT);cell2.setVerticalAlignment(PdfPCell.ALIGN_MIDDLE);cell2.setBorder(Rectangle.NO_BORDER);table.addCell(cell2);table.addCell(cell);PdfPCell cell3 = createCenteredCell("年度审核", 0, null, contentFont);PdfPCell cell4 = new PdfPCell();// 添加复选框绘制事件到单元格if ("1".equals(data.getString("eo45_report_type"))) {cell4.setCellEvent(new CheckBoxCellEvent());} else {cell4.setCellEvent(new CheckBoxCellNotEvent());}cell4.setHorizontalAlignment(PdfPCell.ALIGN_RIGHT);cell4.setVerticalAlignment(PdfPCell.ALIGN_MIDDLE);cell4.setBorder(Rectangle.NO_BORDER);table.addCell(cell4);table.addCell(cell3);PdfPCell cell5 = createCenteredCell("跟踪审核", 0, null, contentFont);PdfPCell cell6 = new PdfPCell();// 添加复选框绘制事件到单元格if ("2".equals(data.getString("eo45_report_type"))) {cell6.setCellEvent(new CheckBoxCellEvent());} else {cell6.setCellEvent(new CheckBoxCellNotEvent());}cell6.setHorizontalAlignment(PdfPCell.ALIGN_RIGHT);cell6.setVerticalAlignment(PdfPCell.ALIGN_MIDDLE);cell6.setBorder(Rectangle.NO_BORDER);table.addCell(cell6);table.addCell(cell5);PdfPCell cell7 = new PdfPCell();cell7.setBorder(Rectangle.NO_BORDER);table.addCell(cell7);document.add(table);}private void buildAuditAim(Document document, DynamicObject entryResults) throws DocumentException {// 设置标题document.add(createTitle("审核目的"));PdfPTable table = new PdfPTable(1);// 段落在其上方留出的空间量table.setSpacingBefore(5f);// 设置表格宽度为100%table.setWidthPercentage(100.0F);table.addCell(createCenteredCell(entryResults.getString("eo45_audit_purpose"), 0, null, contentFont));document.add(table);}private void buildBasicInformation(Document document, DynamicObject entryResults) throws DocumentException {// 设置标题document.add(createTitle("基本信息"));// 设置两列float[] widths = {17f, 83f};PdfPTable table = new PdfPTable(widths);// 段落在其上方留出的空间量table.setSpacingBefore(5f);// 设置表格宽度为100%table.setWidthPercentage(100.0F);table.addCell(createCenteredCell("审核对象", 15, null, contentFont));table.addCell(createCenteredCell(entryResults.getString("eo45_audit_obj"), 0, null, contentFont));table.addCell(createCenteredCell("审核地址", 15, null, contentFont));table.addCell(createCenteredCell(entryResults.getString("eo45_audit_addr"), 0, null, contentFont));table.addCell(createCenteredCell("审核日期", 15, null, contentFont));table.addCell(createCenteredCell(format.format(entryResults.getDate("eo45_audit_date")), 0, null, contentFont));table.addCell(createCenteredCell("审核人员", 15, null, contentFont));table.addCell(createCenteredCell(entryResults.getString("eo45_audit_person"), 0, null, contentFont));table.addCell(createCenteredCell("被审核方人员", 15, null, contentFont));table.addCell(createCenteredCell(entryResults.getString("eo45_beaudited_person"), 0, null, contentFont));table.addCell(createCenteredCell("本次审核后评级", 15, null, contentFont));table.addCell(createCenteredCell(entryResults.getString("eo45_score") + "级", 0, null, contentFont));document.add(table);}/*** 标题样式** @param value 标题* @return*/public PdfPTable createTitle(String value) {PdfPTable table = new PdfPTable(1);// 段落在其上方留出的空间量table.setSpacingBefore(5f);if ("基本信息".equals(value)) {table.setSpacingBefore(15f);}table.setWidthPercentage(100.0F);table.addCell(createCenteredCell(value, 20, new Color(242, 247, 255), titleFont));return table;}/*** 创建cell基本内容** @param value 值* @param fixedHeight 高度* @param color 背景色* @param font 字体样式* @return*/public PdfPCell createCenteredCell(String value, float fixedHeight, Color color, Font font) {Paragraph paragraph = new Paragraph(value, font);// paragraph.setLeading(10);PdfPCell cell = new PdfPCell(paragraph);// 水平对齐cell.setHorizontalAlignment(PdfPCell.ALIGN_LEFT);// 垂直对齐// cell.setVerticalAlignment(Element.ALIGN_MIDDLE);// 边框cell.setBorder(Rectangle.NO_BORDER);// 设置背景色if (color != null) {cell.setBackgroundColor(color);}// 设置单元格高度if (fixedHeight != 0) {cell.setFixedHeight(fixedHeight);}return cell;}/*** 表格表头** @param value* @param fixedHeight* @param color* @param font* @return*/private PdfPCell createCenteredCellForTable(String value, float fixedHeight, Color color, Font font, String border, String alignment) {PdfPCell cell = new PdfPCell(new Paragraph(value, font));cell.setHorizontalAlignment(Element.ALIGN_LEFT);if ("center".equals(alignment)) {cell.setHorizontalAlignment(Element.ALIGN_CENTER);}cell.setVerticalAlignment(Element.ALIGN_MIDDLE);cell.setBorderColor(new Color(230, 230, 230));if (border == null) {cell.setBorder(Rectangle.TOP | Rectangle.BOTTOM);}// 设置背景色if (color != null) {cell.setBackgroundColor(color);}// 设置单元格高度if (fixedHeight != 0) {cell.setFixedHeight(fixedHeight);}return cell;}/*** 设置单元格样式** @param cell*/private void tableCellStyle(PdfPCell cell, Color borderColor, Color backgroundColor, String border) {cell.setHorizontalAlignment(Element.ALIGN_LEFT);cell.setVerticalAlignment(Element.ALIGN_MIDDLE);// 只显示上下边框if (border == null) {cell.setBorder(Rectangle.TOP | Rectangle.BOTTOM);}// 边框颜色if (borderColor != null) {cell.setBorderColorTop(borderColor);cell.setBorderColorBottom(borderColor);}// 背景色if (backgroundColor != null) {cell.setBackgroundColor(backgroundColor);}cell.setBorderColor(new Color(230, 230, 230));}}
头部添加水印/图片工具类
package xcsy.zjy.webapi.utils;import com.lowagie.text.Document;
import com.lowagie.text.DocumentException;
import com.lowagie.text.Image;
import com.lowagie.text.pdf.PdfPageEventHelper;
import com.lowagie.text.pdf.PdfWriter;
import kd.bos.logging.Log;
import kd.bos.logging.LogFactory;import java.io.IOException;
import java.net.URL;/*** @program: xcsy-cosmic* @description: pdf添加头部水印图片* @author: lyw* @create: 2025-02-17 16:51**/public class AddImageToEachPageHeader extends PdfPageEventHelper {private static final Log log = LogFactory.getLog(AddImageToEachPageHeader.class);// 图片路径public static final String IMG = "img/logo.png";// 图片路径public static final String LINEIMG = "img/line.png";// 自定义页面事件监听器Image headerImage;Image lineImage;public AddImageToEachPageHeader() throws IOException, DocumentException {URL resourceUrl = AddImageToEachPageHeader.class.getClassLoader().getResource(IMG);assert resourceUrl != null;headerImage = Image.getInstance(resourceUrl);// scaleToFit按比例缩放图像、调整大小以适应您的需求headerImage.scaleToFit(50, 50);URL resourceUrl2 = AddImageToEachPageHeader.class.getClassLoader().getResource(LINEIMG);assert resourceUrl2 != null;lineImage = Image.getInstance(resourceUrl2);}@Overridepublic void onEndPage(PdfWriter writer, Document document) {try {// 计算图片1放置的位置// float x = (document.right() - document.left()) / 2 + document.leftMargin() - headerImage.getScaledWidth() / 2; // 居中float x = document.leftMargin();// 适当调整距离顶部的距离float y = document.top() + headerImage.getScaledHeight() + 10;headerImage.setAbsolutePosition(x, y);writer.getDirectContent().addImage(headerImage);// 图2// 获取页面宽度float pageWidth = document.getPageSize().getWidth();float x2 = 0;// 适当调整距离顶部的距离float y2 = document.top() + headerImage.getScaledHeight();// scaleAbsolute直接设置图像的确切宽度和高度,不考虑原始宽高比。lineImage.scaleAbsolute(pageWidth, 10);lineImage.setAbsolutePosition(x2, y2);writer.getDirectContent().addImage(lineImage);} catch (DocumentException e) {log.error("pdf添加头部水印图片DocumentException:{}", e);}}}
复选框(选中)绘制工具类
package xcsy.zjy.webapi.utils;import com.lowagie.text.Rectangle;
import com.lowagie.text.pdf.PdfContentByte;
import com.lowagie.text.pdf.PdfPCell;
import com.lowagie.text.pdf.PdfPCellEvent;
import com.lowagie.text.pdf.PdfPTable;import java.awt.*;/*** @program: xcsy-cosmic* @description: pdf复选框* @author: lyw* @create: 2025-02-18 10:30**/public class CheckBoxCellEvent implements PdfPCellEvent {@Overridepublic void cellLayout(PdfPCell cell, Rectangle position, PdfContentByte[] canvases) {PdfContentByte canvas = canvases[PdfPTable.LINECANVAS];// 绘制复选框的位置和大小float x = position.getLeft() + 2; // X坐标,相对于单元格左下角float y = position.getBottom() + 2; // Y坐标,相对于单元格左下角float size = 10; // 复选框大小// 开始写入操作canvas.saveState();// 绘制复选框canvas.rectangle(x, y, size, size);canvas.setColorStroke(new Color( 190, 198, 205));canvas.stroke();// 确保勾选标记的起点、中点和终点位置合理,以形成一个清晰的√符号float rotatedMarkStartX = x + size - 2; // 原始markStartX关于x轴+size的对称点float rotatedMarkStartY = y + size - ((size / 2) - 2); // 原始markStartY关于y轴+size的对称点float rotatedMarkMidX = x + size - (size / 2); // 原始markMidX关于x轴+size的对称点float rotatedMarkMidY = y + 3; // 原始markMidY关于y轴+size的对称点float rotatedMarkEndX = x + 2; // 原始markEndX关于x轴+size的对称点float rotatedMarkEndY = y + size - 4; // 原始markEndY关于y轴+size的对称点canvas.moveTo(rotatedMarkStartX, rotatedMarkStartY); // 设置旋转后的起点canvas.lineTo(rotatedMarkMidX, rotatedMarkMidY); // 经过旋转后的中间点canvas.lineTo(rotatedMarkEndX, rotatedMarkEndY); // 结束于旋转后的右上角canvas.setColorStroke(new Color(0, 103, 255));canvas.setColorFill(new Color(0, 103, 255));canvas.stroke();// 结束写入操作canvas.restoreState();}
}
复选框(不选中)绘制工具类
package xcsy.zjy.webapi.utils;import com.lowagie.text.Rectangle;
import com.lowagie.text.pdf.PdfContentByte;
import com.lowagie.text.pdf.PdfPCell;
import com.lowagie.text.pdf.PdfPCellEvent;
import com.lowagie.text.pdf.PdfPTable;import java.awt.*;/*** @program: xcsy-cosmic* @description: pdf复选框(不选中)* @author: lyw* @create: 2025-02-18 10:30**/public class CheckBoxCellNotEvent implements PdfPCellEvent {@Overridepublic void cellLayout(PdfPCell cell, Rectangle position, PdfContentByte[] canvases) {PdfContentByte canvas = canvases[PdfPTable.LINECANVAS];// 绘制复选框的位置和大小float x = position.getLeft() + 2; // X坐标,相对于单元格左下角float y = position.getBottom() + 2; // Y坐标,相对于单元格左下角float size = 10; // 复选框大小// 开始写入操作canvas.saveState();// 绘制复选框canvas.rectangle(x, y, size, size);canvas.setColorStroke(new Color( 190, 198, 205));canvas.stroke();// 结束写入操作canvas.restoreState();}
}
页码工具类
package xcsy.zjy.webapi.utils;import com.lowagie.text.*;
import com.lowagie.text.pdf.*;import java.io.IOException;/*** @Author xx* @Date 2023/12/15 10:05* @Description: 导出pdf添加页数* @Version 1.0*/
public class PdfPageUtil extends PdfPageEventHelper {/*** 页眉*///public String header = "itext测试页眉";/*** 文档字体大小,页脚页眉最好和文本大小一致*/public int presentFontSize = 9;/*** 文档页面大小,最好前面传入,否则默认为A4纸张*/public Rectangle pageSize = PageSize.A4;// 模板public PdfTemplate total;// 基础字体对象public BaseFont bf = null;// 利用基础字体生成的字体对象,一般用于生成中文文字public Font fontDetail = null;/**** 无参构造方法.**/public PdfPageUtil() {}/**** 构造方法.** @param** @param presentFontSize* 数据体字体大小* @param pageSize* 页面文档大小,A4,A5,A6横转翻转等Rectangle对象*/public PdfPageUtil( int presentFontSize, Rectangle pageSize) {this.presentFontSize = presentFontSize;this.pageSize = pageSize;}public void setPresentFontSize(int presentFontSize) {this.presentFontSize = presentFontSize;}/**** 文档打开时创建模板*/@Overridepublic void onOpenDocument(PdfWriter writer, Document document) {// 共 页 的矩形的长宽高total = writer.getDirectContent().createTemplate(50, 50);}/****关闭每页的时候,写入页眉,写入'第几页共'这几个字。*/@Overridepublic void onEndPage(PdfWriter writer, Document document) {this.addPage(writer, document);}//加分页public void addPage(PdfWriter writer, Document document){//设置分页页眉页脚字体try {if (bf == null) {bf = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", false);}if (fontDetail == null) {fontDetail = new Font(bf, presentFontSize, Font.NORMAL);// 数据体字体}} catch (DocumentException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();}// 1.写入页眉
// ColumnText.showTextAligned(writer.getDirectContent(),
// Element.ALIGN_LEFT, new Phrase(header, fontDetail),
// document.left(), document.top() + 20, 0);// 2.写入前半部分的 第 X页/共int pageS = writer.getPageNumber();//String foot1 = "第 " + pageS + " 页 /共";String foot1 = pageS +"/";Phrase footer = new Phrase(foot1, fontDetail);// 3.计算前半部分的foot1的长度,后面好定位最后一部分的'Y页'这俩字的x轴坐标,字体长度也要计算进去 = lenfloat len = bf.getWidthPoint(foot1, presentFontSize);// 4.拿到当前的PdfContentBytePdfContentByte cb = writer.getDirectContent();// 5.写入页脚1,x轴就是(右margin+左margin + right() -left()- len)/2.0FColumnText.showTextAligned(cb,Element.ALIGN_CENTER,footer,(document.rightMargin() + document.right()+ document.leftMargin() - document.left() - len) / 2.0F ,document.bottom() - 10, 0);cb.addTemplate(total, (document.rightMargin() + document.right()+ document.leftMargin() - document.left()) / 2.0F ,document.bottom() - 10); // 调节模版显示的位置}// //加水印
// public void addWatermark(PdfWriter writer){
// // 水印图片
// Image image;
// try {
// image = Image.getInstance("./web/images/001.jpg");
// PdfContentByte content = writer.getDirectContentUnder();
// content.beginText();
// // 开始写入水印
// for(int k=0;k<5;k++){
// for (int j = 0; j <4; j++) {
// image.setAbsolutePosition(150*j,170*k);
// content.addImage(image);
// }
// }
// content.endText();
// } catch (IOException | DocumentException e) {
// // TODO Auto-generated catch block
// e.printStackTrace();
// }
// }/**** 关闭文档时,替换模板,完成整个页眉页脚组件*/@Overridepublic void onCloseDocument(PdfWriter writer, Document document) {// 关闭文档的时候,将模板替换成实际的 Y 值total.beginText();// 生成的模版的字体、颜色total.setFontAndSize(bf, presentFontSize);//页脚内容拼接 如 第1页/共2页//String foot2 = " " + (writer.getPageNumber()) + " 页";//页脚内容拼接 如 第1页/共2页String foot2 = String.valueOf(writer.getPageNumber() - 1);// 模版显示的内容total.showText(foot2);total.endText();total.closePath();}
}
最后大致效果图


静态图片文件存放位置项目下:

相关文章:
lowagie(itext)老版本手绘PDF,包含页码、水印、图片、复选框、复杂行列合并等。
入口类:exportPdf package xcsy.qms.webapi.service;import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.alibaba.nacos.common.utils.StringUtils; import com.ibm.icu.text.RuleBasedNumberFormat; import com.lowa…...
MySQL undo log,redo log和bin log日志文件的生成时间点、层级归属、存储位置及生命周期详解
问题: 假如库名叫做A库,表名叫B表,undo log,redo log和bin log,这些日志文件的生成的时间点是什么?是在mysql的哪一层生成的?哪些文件是有buffer的?哪些日志文件是存在磁盘上的?哪些…...
吃一堑长一智
工作中经历,有感触记录下 故事一 以前在一家公司时,自己是一名开发人员,遇到问题请教领导解决方案,当时领导给了建议,后来上线后出问题了,背了锅。心里想的是领导说这样做的呀,为什么出问题还…...
DeepSeek基础之机器学习
文章目录 一、核心概念总结(一)机器学习基本定义(二)基本术语(三)假设空间(四)归纳偏好(五)“没有免费的午餐”定理(NFL 定理) 二、重…...
达梦有没有类似oerr的功能
在oracle 23ai的sqlplus中,直接看异常信息说明: 达梦没有此功能,但是可以造一个 cd /home/dmdba cat >err.sql<<eof set echo off set ver off set timing off set lineshow off set feedback off select * from V\$ERR_INFO wher…...
实战-网安
面试感受:网安公司前端实习 今天我有幸面试了一家网络安全公司的前端开发实习岗位,整个过程让我受益匪浅,也让我对未来的职业发展有了更清晰的认识。 首先,面试官非常专业且友好,整个面试氛围轻松但不失严谨。面试一开始,面试官简单介绍了公司背景和团队文化,让我对公…...
一文掌握Splash的详细使用
文章目录 1. 安装与启动 Splash1.1 使用 Docker 安装1.2 直接安装 2. 基本用法2.1 访问 Splash 界面2.2 使用 Splash 渲染页面2.3 使用 Lua 脚本 3. 高级用法3.1 处理 JavaScript3.2 截图与 PDF3.3 处理 AJAX 请求3.4 设置请求头3.5 处理 Cookies 4. 与 Scrapy 集成4.1 安装 Sc…...
从 Linux 服务器到前端到网关到后端业务逻辑的分析
前言 在现代 Web 应用程序的架构中,一个完整的请求处理流程涉及多个组件,涵盖了用户界面、服务器环境、网关层和后端业务逻辑。理解这一过程有助于优化系统性能、提高用户体验,并确保系统的可维护性和可扩展性。本文将详细分析从 Linux 服务…...
Java中的Stream API:从入门到实战
引言 在现代Java开发中,Stream API 是处理集合数据的强大工具。它不仅让代码更加简洁易读,还能通过并行处理提升性能。本文将带你从基础概念入手,逐步深入Stream API的使用,并通过实战案例展示其强大功能。 1. 什么是Stream API…...
【python随手记】——读取文本文件内容转换为json格式
文章目录 前言一、TXT文件转换为JSON数组1.txt文件内容2.python代码3.输出结果 二、TXT文件转换为JSON对象1.txt文件2.python代码3.输出结果 前言 场景:用于读取包含空格分隔数据的TXT文件,并将其转换为结构化JSON文件 一、TXT文件转换为JSON数组 1.tx…...
【蓝桥杯】第十五届省赛大学真题组真题解析
【蓝桥杯】第十五届省赛大学真题组真题解析 一、智能停车系统 1、知识点 (1)flex-wrap 控制子元素的换行方式 属性值有: no-wrap不换行wrap伸缩容器不够则自动往下换行wrap-reverse伸缩容器不够则自动往上换行 (2࿰…...
MybatisPlus-扩展功能-枚举处理器
在Mybatis里有一个叫TypeHandler的类型处理器,我们常见的PO当中的这些成员变量的数据类型,它都有对应的处理器,因此它就能自动实现这些Java数据类型与数据库类型的相互转换。 它里面还有一个叫EnumOrdinalTypeHandler的枚举处理器࿰…...
力扣2454. 下一个更大元素 IV
力扣2454. 下一个更大元素 IV 题目 题目解析及思路 题目要求对于每个数,找到右边比它大的第二个数,并记录在ans数组中 如果是右边第一个大的,就用一个递减栈即可,栈顶元素如果<当前元素则弹出 第二个大数就要利用弹出的栈顶…...
unity学习51:所有UI的父物体:canvas画布
目录 1 下载资源 1.1 在window / Asset store下下载一套免费的UI资源 1.2 下载,导入import 1.3 导入后在 project / Asset下面可以看到 2 画布canvas,UI的父物体 2.1 创建canvas 2.1.1 画布的下面是 event system是UI相关的事件系统 2.2 canvas…...
Ollama部署与常用命令
Ollama是一款开源工具,其目标是简化大语言模型在本地环境的部署和使用。它支持多种流行的开源大语言模型,如 Llama 2、Qwen2.5等。 通过Ollama,用户无需具备深厚的技术背景,就能在普通的消费级硬件上快速搭建一个强大的语言处理环…...
Visual Studio Code 远程开发方法
方法1 共享屏幕远程控制,如 to desk, 向日葵 ,像素太差,放弃 方法2 内网穿透 ssh 第二个方法又很麻烦,尤其是对于 windows 电脑,要使用 ssh 还需要额外安装杂七杂八的东西;并且内网穿透服务提供商提供的…...
C语言预编译
大家好,这里是小编的博客频道 小编的博客:就爱学编程 很高兴在CSDN这个大家庭与大家相识,希望能在这里与大家共同进步,共同收获更好的自己!!! 本文目录 引言正文一、预处理的作用与流程…...
汽车智能制造企业数字化转型SAP解决方案总结
一、项目实施概述 项目阶段划分: 蓝图设计阶段主数据管理方案各模块蓝图设计方案下一阶段工作计划 关键里程碑: 2022年6月6日:项目启动会2022年12月1日:系统上线 二、总体目标 通过SAP实施,构建研产供销协同、业财一…...
flowable-ui 的会签功能实现
场景:在进行智慧保时通开发时,有个协作合同入围功能,这个功能的流程图里有个评审小组,这个评审小组就需要进行会签操作,会签完成后,需要依据是否有不通过的情况选择下一步走的流程 思考步骤: 首…...
Spring Boot 与 MyBatis 数据库操作
一、核心原理 Spring Boot 的自动配置 通过 mybatis-spring-boot-starter 自动配置 DataSource(连接池)、SqlSessionFactory 和 SqlSessionTemplate。 扫描 Mapper 接口或指定包路径,生成动态代理实现类。 MyBatis 的核心组件 SqlSessionF…...
大连指令数据集的创建--数据收集与预处理_02
1.去哪儿爬虫 编程语言:Python爬虫框架:Selenium(用于浏览器自动化)解析库:BeautifulSoup(用于解析HTML) 2.爬虫策略 目标网站:去哪儿(https://travel.qunar.com/trav…...
vLLM专题(十四)-自动前缀缓存
一、介绍 自动前缀缓存(Automatic Prefix Caching,简称 APC)缓存现有查询的 KV 缓存,以便新查询如果与现有查询共享相同的前缀,可以直接重用 KV 缓存,从而跳过共享部分的计算。 注意 有关 vLLM 如何实现 APC 的技术细节,请参阅此处。 二、在 vLLM 中启用 APC 在 vLLM …...
STM32MP157A-FSMP1A单片机移植Linux系统SPI总线驱动
SPI总线驱动整体上与I2C总线驱动类型,差别主要在设备树和数据传输上,由于SPI是由4根线实现主从机的通信,在设备树上配置时需要对SPI进行设置。 原理图可知,数码管使用的SPI4对应了单片机上的PE11-->SPI4-NSS,PE12-->SPI4-S…...
linux-c 字节序问题--大小端
今天面试被问了一个网络字节系列的问题分享一下: 1.如何将Int转换成byte数组在网络上传输。 2.计算机世界里的大小端问题。 计算机世界里为什么有大小端 硬件设计因素 CPU 架构差异 不同的 CPU 架构在设计时,对于多字节数据在内存中的存储顺序…...
java医院多维度综合绩效考核源码,医院绩效管理系统,支持一键核算和批量操作,设有审核机制,允许数据修正
医院绩效考核管理系统,java医院绩效核算系统源码,采用多维度综合绩效考核的形式,针对院内实际情况分别对工作量、KPI指标、科研、教学、管理等进行全面考核。医院可结合实际需求,对考核方案中各维度进行灵活配置,对各维…...
C语言学习笔记-初阶(13)scanf介绍
当我们有了变量,我们需要给变量输入值就可以使用 scanf 函数,如果需要将变量的值输出在屏幕上的时候可以使用 printf 函数,下面看⼀个例子: #include <stdio.h> int main() {int score 0;printf("请输⼊成绩:")…...
Android MMKV集成指南
首先简单介绍一下MMKV当下Android Studio最版本及Gradle8.7 MMKV集成根据官方文档重新对mmkv重新包了一次(便于开发)总结首先简单介绍一下MMKV MMKV 是腾讯开源的一款专为移动端设计的高性能键值存储组件,旨在替代传统的 SharedPreferences 和 SQLite,尤其在频繁读写和数据…...
如何让传统制造企业从0到1实现数字化突破?
随着全球制造业不断向智能化、数字化转型,传统制造企业面临着前所未有的机遇与挑战。数字化转型不仅是技术的革新,更是管理、文化、业务流程等全方位的变革。从零开始,如何带领一家传统制造企业走向数字化突破,是许多企业领导者面…...
Centos7安装Python3.13
Centos7.5环境上安装Python3.13 # 安装依赖 yum install -y zlib zlib-devel openssl-devel sqlite-devel bzip2-devel libffi libffi-devel gcc gcc-c mkdir -p /opt/software cd /opt/software # openssl高版本安装 # 如果 Centos7 系统默认自带的 openssl 版本太低…...
C++之string类的模拟实现(超详细)
们学习东西,先学习如果使用它,然后再学习如何实现它 文章目录 目录 1. 命名空间以及头文件 2.string类的成员变量 3.string类的成员函数 3.1 构造函数 3.2 析构函数 3.3 拷贝构造函数 3.4 赋值运算符重载 3.5 c_str函数 3.6 size函数 3.7 clea…...
