lowagie(itext)老版本手绘PDF,包含页码、水印、图片、复选框、复杂行列合并、行高设置等。

news2025/2/28 16:39:08

入口类: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.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 {
        // 单据id
        String 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();
            // 标题1
            Paragraph 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);
            // -------审核得分
            buildAuditScore(document, entryResults);
            // -------审核结论
            buildAuditResult(document, entryResults);
            // 标题2
            Paragraph 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);
            // 标题3
            Paragraph 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);
            // 标题4
            Paragraph 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 = setCell(3f, 1f, rowspan, content.getString("eo45_import_area"));
                        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 = setCell(3f, 1f, rowspan, contentContext);
                        PdfPCell cell4 = setCell(3f, 1f, rowspan, content.getString("eo45_content_suggestion"));
                        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 = setCell(3f, 1f, 1, selectContent);
                                cell9 = setCell(3f, 1f, 1, problem.getString("problem_desc"));
                                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 = setCell(3f, 1f, 1, result + "、" + projectName);
            // 获取对应项目的总分和得分
            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 = setCell(3f, 1f, 1, projectSeq[0] + "." + sortSeq + " " + categorysDynamicObject.getString("eo45_sort_name"));
                    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 = setCell(3f, 1f, 1, contents.get(i).getString("eo45_import_area"));
            // 富文本处理
            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 = setCell(3f, 1f, 1, contentContext);
            // 获取选项
            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 = setCell(3f, 1f, 1, selectContent);

            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_conclusion_qu"), 0, null, contentFont));

        table.addCell(createCenteredCell("数字化能力评估审核意见:", 15, null, contentFont));
        table.addCell(createCenteredCell(entryResults.getString("eo45_audit_advice"), 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 buildAuditScore(Document document, DynamicObject entryResults) throws DocumentException {
        // 设置标题
        document.add(createTitle("审核得分"));
        PdfPTable table = new PdfPTable(1);
        // 段落在其上方留出的空间量
        table.setSpacingBefore(5f);
        // 设置表格宽度为100%
        table.setWidthPercentage(100.0F);
        String scoreStr = "";
        if (StringUtils.isNotBlank(entryResults.getString("eo45_audit_scorestr"))) {
            org.jsoup.nodes.Document documentResult = Jsoup.parse(entryResults.getString("eo45_audit_scorestr"));
            scoreStr = documentResult.text();
        }
        table.addCell(createCenteredCell(scoreStr, 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(3f, 1);
        PdfPCell cell = new PdfPCell();
        // 重点--这样行高才生效
        cell.addElement(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));
    }

    /**
     * 设置行高
     *
     * @param v       固定间距值
     * @param v1      多倍间距值
     * @param rowspan 合并行数
     * @param value   值
     */
    private PdfPCell setCell(float v, float v1, int rowspan, Object value) {
        PdfPCell cell = new PdfPCell();
        Paragraph paragraph = new Paragraph(String.valueOf(value), contentFont);
        paragraph.setLeading(v, v1);
        cell.addElement(paragraph);
        if (rowspan > 1) {
            cell.setRowspan(rowspan);
        }
        cell.setPaddingBottom(3f);
        return cell;
    }

}

 头部添加水印/图片工具类

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);
    }

    @Override
    public 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 {
    @Override
    public 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 {
    @Override
    public 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;
    }

    /**
     *
     * 文档打开时创建模板
     */
    @Override
    public void onOpenDocument(PdfWriter writer, Document document) {
        // 共 页 的矩形的长宽高
        total = writer.getDirectContent().createTemplate(50, 50);
    }

    /**
     *
     *关闭每页的时候,写入页眉,写入'第几页共'这几个字。
     */
    @Override
    public 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轴坐标,字体长度也要计算进去 = len
        float len = bf.getWidthPoint(foot1, presentFontSize);

        // 4.拿到当前的PdfContentByte
        PdfContentByte cb = writer.getDirectContent();

        // 5.写入页脚1,x轴就是(右margin+左margin + right() -left()- len)/2.0F
        ColumnText
                .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();
//        }
//    }

    /**
     *
     * 关闭文档时,替换模板,完成整个页眉页脚组件
     */
    @Override
    public 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();
    }
}

最后大致效果图

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2307476.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

第002文-kali虚拟机安全与网络配置

1、kali系统介绍 kali是一个基于Linux kernel的操作系统&#xff0c;由BackTrack(简称BT)发展而来。BackTrack是2006年推出的一个用于渗透测试及黑客攻防的专用平台&#xff0c;基于Knoppix(linux的一个发行版)开发。BackTrack版本周期&#xff1a;2006年的起始版本BackTrack …

软件工程复试专业课-软件生命周期

文章目录 软件过程模型瀑布模型模型图特点优缺点改进后的瀑布模型 快速原型模型模型图优缺点 增量模型&#xff08;迭代-递增模型&#xff09;原型图与瀑布和快速原型的区别优缺点风险更大的增量模型 螺旋模型简介模型图优缺点 喷泉模型模型图优缺点 编码修补模型敏捷过程优缺点…

DILLEMA:扩散模型+大语言模型,多模态数据增强框架

引言&#xff1a;深度学习模型的鲁棒性测试需要全面且多样化的测试数据。现有的方法通常基于简单的数据增强技术或生成对抗网络&#xff0c;但这些方法在生成真实且多样化的测试数据集方面存在局限性。为了克服这些限制&#xff0c;DILLEMA框架应运而生&#xff0c;旨在通过结合…

C++程序员内功修炼——Linux C/C++编程技术汇总

在软件开发的宏大版图中&#xff0c;C 语言宛如一座巍峨的高山&#xff0c;吸引着无数开发者攀登探索。而 Linux 操作系统&#xff0c;以其开源、稳定、高效的特性&#xff0c;成为了众多开发者钟爱的开发平台。将 C 与 Linux 相结合&#xff0c;就如同为开发者配备了一把无坚不…

苍穹外卖-阿里云OSS文件上传

苍穹外卖-阿里云OSS文件上传 一、阿里云OSS简介**获取AccessKey**获取enpoint 二、代码实现1 引入依赖2 定义OSS相关配置2.1 application-dev.yml2.2 application.yml 3 读取OSS配置3.1 AliOssProperties 4 生成OSS工具类对象4.1 AliOssUtil4.2 OssConfiguration2.5 CommonCont…

DeepSeek 提示词:常见指令类型

&#x1f9d1; 博主简介&#xff1a;CSDN博客专家&#xff0c;历代文学网&#xff08;PC端可以访问&#xff1a;https://literature.sinhy.com/#/?__c1000&#xff0c;移动端可微信小程序搜索“历代文学”&#xff09;总架构师&#xff0c;15年工作经验&#xff0c;精通Java编…

springai系列(二)从0开始搭建和接入azure-openai实现智能问答

文章目录 前言1.从0开始搭建项目2.进入微软openai申请key3.配置application.yaml4.编写controller5.测试源码下载地址总结 前言 之前使用openai的官网的api需要科学上网&#xff0c;但是我们可以使用其他的代理间接实现使用chatgpt的相关模型&#xff0c;解决这个问题。比如:本…

Go在1.22版本修复for循环陷阱

记录 前段时间升级Go版本碰到一个大坑&#xff0c;先记录。 先上代码案例&#xff1a; func main() {testClosure() }func testClosure() {for i : 0; i < 5; i {defer func() {fmt.Println(i)}()} }在1.22之下&#xff08;不包括1.22&#xff09;版本&#xff1a; 输出的…

可视化约瑟夫生死环小游戏

这是一个基于Tkinter的图形界面应用程序&#xff0c;用于模拟约瑟夫环问题。约瑟夫环问题是一个经典的数学问题&#xff0c;描述的是N个人围成一圈&#xff0c;从第一个人开始报数&#xff0c;每数到第M个人就将其淘汰&#xff0c;然后从下一个人继续报数&#xff0c;直到剩下最…

【深入理解JWT】从认证授权到网关安全

最近的项目学习中&#xff0c;在进行登陆模块的用户信息验证这一部分又用到了JWT的一些概念和相关知识&#xff0c;特在此写了这篇文章、方便各位笔者理解JWT相关概念 目录 先来理解JWT是什么&#xff1f; 区分有状态认证和无状态认证 有状态认证 VS 无状态认证 JWT令牌的…

学习路之PHP --TP6异步执行功能 (无需安装任何框架)

学习路之PHP --异步执行功能 &#xff08;无需安装任何框架&#xff09; 简介一、工具类二、调用三、异步任务的操作四、效果&#xff1a; 简介 执行异步任务是一种很常见的需求&#xff0c;如批量发邮箱&#xff0c;短信等等执行耗时任务时&#xff0c;需要程序异步执行&…

九、数据治理架构流程

一、总体结构 《数据治理架构流程图》&#xff08;Data Governance Architecture Flowchart&#xff09; 水平结构&#xff1a;流程图采用水平组织&#xff0c;显示从数据源到数据应用的进程。 垂直结构&#xff1a;每个水平部分进一步划分为垂直列&#xff0c;代表数据治理的…

【数据结构】 最大最小堆实现优先队列 python

堆的定义 堆&#xff08;Heap&#xff09;是一种特殊的完全二叉树结构&#xff0c;通常分为最大堆和最小堆两种类型。 在最大堆中&#xff0c;父节点的值总是大于或等于其子节点的值&#xff1b; 而在最小堆中&#xff0c;父节点的值总是小于或等于其子节点的值。 堆常用于实…

51c自动驾驶~合集52

我自己的原文哦~ https://blog.51cto.com/whaosoft/13383340 #世界模型如何推演未来的千万种可能 驾驶世界模型&#xff08;DWM&#xff09;&#xff0c;专注于预测驾驶过程中的场景演变&#xff0c;已经成为追求自动驾驶的一种有前景的范式。这些方法使自动驾驶系统能够更…

【我的 PWN 学习手札】House of Husk

House of Husk House of Husk是利用格式化输出函数如printf、vprintf在打印输出时&#xff0c;会解析格式化字符如%x、%lld从而调用不同的格式化打印方法&#xff08;函数&#xff09;。同时C语言还提供了注册自定义格式化字符的方法。注册自定义格式化字符串输出方法&#xf…

Nmap使用指南

Nmap使用指南 Nmap (网络映射器) 是一款强大的应用网络扫描和安全核查工具&#xff0c;适合于网络管理和安全专家。本文将介绍Nmap的基本使用方法&#xff0c;包括基本命令和常用功能。 1. 基本使用方式 Nmap的基本命令格式如下&#xff1a; nmap [选项] 目标地址目标地址 可…

傅里叶分析

傅里叶分析之掐死教程&#xff08;完整版&#xff09;更新于2014.06.06 要让读者在不看任何数学公式的情况下理解傅里叶分析。 傅里叶分析不仅仅是一个数学工具&#xff0c;更是一种可以彻底颠覆一个人以前世界观的思维模式。但不幸的是&#xff0c;傅里叶分析的公式看起来太复…

从零开始用react + tailwindcss + express + mongodb实现一个聊天程序(五) 实现登录功能

1.登录页面 完善登录页面 和注册差不多 直接copy signUpPage 内容 再稍微修改下 import { useState } from "react"; import { useAuthStore } from "../store/useAuthStore"; import { MessageSquare,Mail,Lock,Eye, EyeOff,Loader2} from "lucide…

【机器学习】Logistic回归#1基于Scikit-Learn的简单Logistic回归

主要参考学习资料&#xff1a; 《机器学习算法的数学解析与Python实现》莫凡 著 前置知识&#xff1a;线性代数-Python 目录 问题背景数学模型类别表示Logistic函数假设函数损失函数训练步骤 代码实现特点 问题背景 分类问题是一类预测非连续&#xff08;离散&#xff09;值的…