You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用PDFKit生成带自动分页的多页装箱单PDF遇问题求助

PDFKit装箱单分页问题修复方案

针对你用PDFKit生成装箱单时分页不生效的问题,先梳理原代码的核心错误,再给出修正后的完整代码:

原代码核心问题

  1. 分页判断逻辑错误:用未定义的nfs.length判断,且错误以总数据长度作为分页触发条件,正确应该是当前页面已渲染40条时新增页面
  2. 模板字符串失效:单引号包裹的字符串无法解析${data}这类变量,需改用反引号
  3. 表头数据无法传递:generateHeader函数未接收参数,无法动态填充运输车辆等信息
  4. 分页后缺少表头:新增页面未重新生成表头,导致新页无标题信息
  5. 索引与位置计算错误:分页后索引重置逻辑错误,导致条目位置偏移
  6. 核心函数未调用:漏了执行generateInnerPdf(doc),导致整个生成逻辑未启动

修正后的完整代码

var doc = new PDFDocument({ size: 'A4'});
var stream = doc.pipe(blobStream());
 
const layoutX = { align: 'center' }
const layoutY = 20
const PAGE_ITEM_LIMIT = 40; // 每页最大条目数
let currentPageItems = 0; // 当前页面已渲染条目数
let tableStartY = layoutY + 40; // 表头下方开始渲染条目的Y坐标,预留表头空间

// 模拟当前日期(按巴西格式生成)
const currentDate = new Date().toLocaleDateString('pt-BR');

function generateInnerPdf(doc) {
    const notes = [
        { vehiclePlate: 'MTG7200', logisticName: 'PAC', numNf: 01 },
        { vehiclePlate: 'MTG7200', logisticName: 'PAC', numNf: 02 },
        { vehiclePlate: 'MTG7200', logisticName: 'PAC', numNf: 03 },
        { vehiclePlate: 'MTG7200', logisticName: 'PAC', numNf: 04 },
        { vehiclePlate: 'MTG7200', logisticName: 'PAC', numNf: 05 },
        { vehiclePlate: 'MTG7200', logisticName: 'PAC', numNf: 06 },
        { vehiclePlate: 'MTG7200', logisticName: 'PAC', numNf: 07 },
        { vehiclePlate: 'MTG7200', logisticName: 'PAC', numNf: 08 },
        { vehiclePlate: 'MTG7200', logisticName: 'PAC', numNf: 09 },
        { vehiclePlate: 'MTG7200', logisticName: 'PAC', numNf: 10 },
        { vehiclePlate: 'MTG7200', logisticName: 'PAC', numNf: 11 },
        { vehiclePlate: 'MTG7200', logisticName: 'PAC', numNf: 12 },
        { vehiclePlate: 'MTG7200', logisticName: 'PAC', numNf: 13 },
        { vehiclePlate: 'MTG7200', logisticName: 'PAC', numNf: 14 },
        { vehiclePlate: 'MTG7200', logisticName: 'PAC', numNf: 15 },
        { vehiclePlate: 'MTG7200', logisticName: 'PAC', numNf: 16 },
        { vehiclePlate: 'MTG7200', logisticName: 'PAC', numNf: 17 },
        { vehiclePlate: 'MTG7200', logisticName: 'PAC', numNf: 18 },
        { vehiclePlate: 'MTG7200', logisticName: 'PAC', numNf: 19 },
        { vehiclePlate: 'MTG7200', logisticName: 'PAC', numNf: 20 },
        { vehiclePlate: 'MTG7200', logisticName: 'PAC', numNf: 21 },
        { vehiclePlate: 'MTG7200', logisticName: 'PAC', numNf: 22 },
        { vehiclePlate: 'MTG7200', logisticName: 'PAC', numNf: 23 },
        { vehiclePlate: 'MTG7200', logisticName: 'PAC', numNf: 24 },
        { vehiclePlate: 'MTG7200', logisticName: 'PAC', numNf: 25 },
        { vehiclePlate: 'MTG7200', logisticName: 'PAC', numNf: 26 },
        { vehiclePlate: 'MTG7200', logisticName: 'PAC', numNf: 27 },
        { vehiclePlate: 'MTG7200', logisticName: 'PAC', numNf: 28 },
        { vehiclePlate: 'MTG7200', logisticName: 'PAC', numNf: 29 },
        { vehiclePlate: 'MTG7200', logisticName: 'PAC', numNf: 30 },
        { vehiclePlate: 'MTG7200', logisticName: 'PAC', numNf: 31 },
        { vehiclePlate: 'MTG7200', logisticName: 'PAC', numNf: 32 },
        { vehiclePlate: 'MTG7200', logisticName: 'PAC', numNf: 33 },
        { vehiclePlate: 'MTG7200', logisticName: 'PAC', numNf: 34 },
        { vehiclePlate: 'MTG7200', logisticName: 'PAC', numNf: 35 },
        { vehiclePlate: 'MTG7200', logisticName: 'PAC', numNf: 36 },
        { vehiclePlate: 'MTG7200', logisticName: 'PAC', numNf: 37 },
        { vehiclePlate: 'MTG7200', logisticName: 'PAC', numNf: 38 },
        { vehiclePlate: 'MTG7200', logisticName: 'PAC', numNf: 39 },
        { vehiclePlate: 'MTG7200', logisticName: 'PAC', numNf: 40 },
        { vehiclePlate: 'MTG7200', logisticName: 'PAC', numNf: 41 }
    ];

    // 生成第一页表头
    generateHeader(doc, notes[0].vehiclePlate, notes[0].logisticName);
    
    // 渲染条目
    notes.forEach((item, index) => {
        // 计算当前条目的Y坐标:表头下方 + 条目索引*行高
        const itemY = tableStartY + (currentPageItems * 20);
        
        // 渲染当前条目
        generateTableBody(doc, itemY, item.numNf, item.logisticName);
        currentPageItems++;

        // 达到每页最大条目数时,新增页面并重置计数器、重新生成表头
        if (currentPageItems === PAGE_ITEM_LIMIT && index !== notes.length - 1) {
            doc.addPage();
            currentPageItems = 0;
            generateHeader(doc, item.vehiclePlate, item.logisticName);
        }
    });

    // 生成最后一页页脚
    generateFooter(doc);
}

function generateHeader(doc, vehiclePlate, logisticName) {
    doc
    .fontSize(11)
    .text(
        `Lupo S.A Notas fiscais liberadas para despacho em ${currentDate}`,
        layoutX,
        layoutY
    )
    .text(
        `Transportador: ${vehiclePlate} - ${logisticName}`,
        layoutX,
        layoutY + 20
    );
}

function generateTableBody(doc, y, numNf, logisticName) {
    doc
      .fontSize(10)
      .text(numNf, 50, y)
      .text(logisticName, 150, y);
}

function generateFooter(doc){
    doc
      .fontSize(11)
      .text(
        'Declaro ter recebido as notas fiscais acima relacionadas e suas respectivas mercadorias em perfeitas condições',
        layoutX,
        layoutY + 660
      )
      .text(`Araraquara, ${currentDate}`, layoutX, layoutY + 690)
      .text(
        '____________________________________________________________',
        layoutX,
        layoutY + 720
      )
      .text('Assinatura', layoutX, layoutY + 735);
}

// 启动生成并渲染到iframe
generateInnerPdf(doc);
doc.end();

stream.on('finish', function() {
  iframe.src = stream.toBlobURL('application/pdf');
});

关键修改点说明

  1. 新增分页控制变量:用PAGE_ITEM_LIMIT定义每页最大条目数,currentPageItems追踪当前页面已渲染数量,避免硬编码
  2. 修正分页判断逻辑:当当前页面条目数达到40,且不是最后一条数据时,新增页面并重置计数器,同时重新生成表头
  3. 修复模板字符串:所有包含变量的字符串改用反引号包裹,确保变量正常解析
  4. 传递表头数据:generateHeader函数接收车辆牌号和物流公司参数,动态填充内容
  5. 修复位置计算:条目Y坐标基于当前页面已渲染数量计算,分页后自动从新页面表头下方开始
  6. 补全函数调用:添加generateInnerPdf(doc)执行生成逻辑

内容的提问来源于stack exchange,提问作者Wilton Santos

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.24 08:04:55