const puppeteer = require('puppeteer');
const hbs = require('handlebars');
const fs = require('fs');
const path = require('path');
const data = require('./data.json');
const ThermalPrinterHelper = require('./ThermalPrinterHelper');
const { generateQrCode, generateBarCode } = require('./generator');
hbs.registerHelper('inc', function (value, options) {
return parseInt(value) + 1;
});
// Function to compile Handlebars template
const compile = async function (template, data) {
const filePath = path.join(__dirname, 'templates', `${template}.hbs`);
const templateSource = await fs.promises.readFile(filePath, 'utf-8');
return hbs.compile(templateSource)(data);
};
const styleContent = `
<style>
.invoice-code {
display: flex;
justify-content: space-between;
align-items: center;
width: 100%;
min-height: 100px;
font-size: 10px;
}
</style>
`;
function groupBySubtotalQuantity(poItems) {
const groupedPayload = {};
poItems.forEach((item) => {
const groupKey = item.article_no.toString().substring(0, 9); // Get the first 4 characters of article_no
const totalQuantity = parseFloat(item.quantity); // Convert quantity to a floating-point number
if (!groupedPayload[groupKey]) {
groupedPayload[groupKey] = {
total_quantity: 0, // Initialize total quantity to 0
items: [],
};
}
groupedPayload[groupKey].items.push(item);
groupedPayload[groupKey].total_quantity += totalQuantity; // Add quantity to total quantity
});
// Format total_quantity to have up to 3 decimal places and convert to string
Object.keys(groupedPayload).forEach((key) => {
groupedPayload[key].total_quantity = parseFloat(
groupedPayload[key].total_quantity.toFixed(3)
).toFixed(3);
});
// Sort items within each group based on the last number of the material description
Object.keys(groupedPayload).forEach((key) => {
groupedPayload[key].items.sort((a, b) => {
const getLastNumber = (str) => parseInt(str.match(/\d+$/)[0]); // Extract last number from string
return (
getLastNumber(a.material_description) -
getLastNumber(b.material_description)
);
});
});
const result = Object.keys(groupedPayload).map((key) => groupedPayload[key]);
return { po_item: result };
}
// Function to generate PDF
const generatePDF = async () => {
try {
const browser = await puppeteer.launch({
args: ['--no-sandbox'],
devtools: true,
});
const page = await browser.newPage();
const payloadJSON = data;
const groupedPayload = groupBySubtotalQuantity(payloadJSON.po_item);
payloadJSON.po_item = groupedPayload.po_item;
// Compile template with user and seller information
const content = await compile('index', payloadJSON);
const barcodeMarkup = await generateBarCode({ value: '123456789' });
// Add the formatted text and barcode to your content
const modifiedContent = content;
await page.setContent(modifiedContent);
await page.addStyleTag({
content: `
body { margin-top: 1cm; }
@page:first { margin-top: 0; }
`,
});
// Generate PDF for each page
await page.pdf({
path: 'output.pdf',
format: 'A4',
printBackground: true,
preferCSSPageSize: true,
displayHeaderFooter: true,
margin: {
top: '100px',
},
headerTemplate: `
${styleContent}
<div class='invoice-code'>
<div style='width:40%; font-size: 10px;'></div>
<div style='width:30%; font-size: 10pt; font-family:Helvetica, sans-serif; font-style: normal; font-weight: bold;'>PURCHASE ORDER</div>
<div style='width:30%; font-size: 10px; line-height:1.2;'>
<div style=' font-size: 10pt; font-family:Helvetica, sans-serif; font-style: normal; font-weight: bold;'>Number<span style="font-weight: normal;"> : ${payloadJSON.po_number}</span></div>
<div style=' font-size: 10pt; font-family:Helvetica, sans-serif; font-style: normal; font-weight: bold;'>Po Date<span style="font-weight: normal;"> : ${payloadJSON.po_date}</span></div>
<div style=' font-size: 10pt; font-family:Helvetica, sans-serif; font-style: normal; font-weight: bold;'>Page No <span style="font-weight: normal;">:</span> <span style="font-weight: normal;" class="pageNumber"> </span></div>
</div>
</div>
`,
footerTemplate: `
${styleContent}
<div class='invoice-code'>
<div style='width:40%; font-size: 12px;'></div>
</div>
`,
});
console.log('PDF generated successfully');
// await browser.close();
} catch (e) {
console.log(e);
}
};
// Call the function to generate PDF
generatePDF();
我尝试了很多选项来从 0 开始 pdf 的页码。我尝试使用 addScriptTag 的选项,评估页面的方法,添加脚本标签来修改 pageNumber 类,也使用 CSS 处理它,做 -1我知道这很蹩脚,但我尝试过,阅读了 15-20 个有关该问题的博客和论坛,但没有发现任何有用的内容,并且所有尝试都失败了。我正在使用 puppeteer 生成 PDF,它基于 Chromium 引擎,页码从 1 开始,我想从 0 开始页码,它有内置的 pageNumber 类,几乎无法编辑。怎么做?否则,我们可以从第二页开始页码,因为第一页是封面,我使用 css 隐藏 headerTemplate。
我想要一个单一的输出 pdf,其中页码应从第二页开始,因为第一页是封面。
这不是一个令人满意的答案,只是一个分析。
puppeteer 的headerTemplate
方法的
footerTemplate
和
page.pdf()
options被传递给 Chromium 的“另存为 PDF”方法。此方法允许在 Javascript 函数
setupHeaderFooterTemplate
here中注入几个变量。例如,模板中的元素<span class="pageNumber"></span>
将注入当前页码
options.pageNumber
。Chromium 所认为的“当前页码”定义于
here。请注意,此代码必须显式调用 Javascript 函数 kPageSetupScriptFormat = "setupHeaderFooterTemplate"
。因此,将您自己的 Javascript 添加到
headerTemplate
或
footerTemplate
没有任何效果,它根本不会被执行。如果您想偏离这些页码规则,您应该使用 CSS 概念 和
counter()
在 HTML 文档上定义自己的规则。