1.需求如下:
绘制如上格式的小票为pdf,再进行打印(帮别人做的哈哈)
第一步:
安装插件:pdf-lib 以及 qrcode
npm install @pdf-lib/pdf-lib qrcode
第二步:
绘制表格:
const drawText = (page: any, text: string, x: number, y: number, font: any, fontSize = 12) => {
page.drawText(text, {
x,
y,
size: fontSize,
color: rgb(0, 0, 0),
font,
});
};
const drawBox = (page: any, x: number, y: number, boxWidth: number, boxHeight: number) => {
page.drawRectangle({
x,
y,
width: boxWidth,
height: boxHeight,
borderWidth: 1,
borderColor: rgb(0, 0, 0),
});
};
创建以上两个方法来绘制文本和表格单元格
定义表格的尺寸:
const startX = 50;
const startY = height - 50;
const rowHeight = 30;
const boxWidth = 500;
const boxHeight = rowHeight;
const labelWidth = 100;
const valueWidth = boxWidth - labelWidth;
实现绘制逻辑:
const generatePdf = async () => {
const pdfDoc = await PDFDocument.create();
const page = pdfDoc.addPage([600, 800]);
const { width, height } = page.getSize();
const font = await pdfDoc.embedFont(StandardFonts.Helvetica);
const fontSize = 12;
const rows = [
{ label: 'chepaihao', value: '[#CH#]' },
{ label: 'gongyingshang', value: '[#GYSQC#]' },
{ label: 'wuliao', value: '[#MZMC#]' },
{ label: 'yicizhongliang', value: '[#MZ#]', secondLabel: 'ercijingzhong', secondValue: '[#PZ#]' },
{ label: 'jingzhong', value: '[#JZ#]' },
{ label: 'yicishijian', value: '[#ZHONGCSJ#]' },
{ label: 'ercishijian', value: '[#HUIPSJ#]' },
{ label: 'dayinshijian', value: '[#dangqianshijianshiqi#]' },
{ label: 'beizhu', value: '' },
];
const startX = 50;
const startY = height - 50;
const rowHeight = 30;
const boxWidth = 500;
const boxHeight = rowHeight;
const labelWidth = 100;
const valueWidth = boxWidth - labelWidth;
let currentY = startY;
// 绘制表头
drawText(page, '[#DCMC#]', startX + boxWidth / 2 - 20, currentY + 10, font, 16);
currentY -= rowHeight;
// Draw the table rows
rows.forEach((row, index) => {
drawBox(page, startX, currentY, boxWidth, boxHeight);
if (row.secondLabel) {
const firstColumnWidth = labelWidth;
const remainingWidth = boxWidth - firstColumnWidth;
const cellWidth = remainingWidth / 3;
drawText(page, row.label, startX + 10, currentY + 10, font);
drawText(page, row.value, startX + firstColumnWidth + 10, currentY + 10, font);
drawText(page, row.secondLabel, startX + firstColumnWidth + cellWidth + 10, currentY + 10, font);
drawText(page, row.secondValue, startX + firstColumnWidth + cellWidth * 2 + 10, currentY + 10, font);
// Draw vertical lines for columns
page.drawLine({
start: { x: startX + firstColumnWidth, y: currentY },
end: { x: startX + firstColumnWidth, y: currentY + boxHeight },
thickness: 1,
color: rgb(0, 0, 0),
});
page.drawLine({
start: { x: startX + firstColumnWidth + cellWidth, y: currentY },
end: { x: startX + firstColumnWidth + cellWidth, y: currentY + boxHeight },
thickness: 1,
color: rgb(0, 0, 0),
});
page.drawLine({
start: { x: startX + firstColumnWidth + cellWidth * 2, y: currentY },
end: { x: startX + firstColumnWidth + cellWidth * 2, y: currentY + boxHeight },
thickness: 1,
color: rgb(0, 0, 0),
});
} else {
drawText(page, row.label, startX + 10, currentY + 10, font);
drawText(page, row.value, startX + labelWidth, currentY + 10, font);
// Draw vertical line between label and value
page.drawLine({
start: { x: startX + labelWidth, y: currentY },
end: { x: startX + labelWidth, y: currentY + boxHeight },
thickness: 1,
color: rgb(0, 0, 0),
});
}
currentY -= rowHeight;
});
//绘制并插入二维码
const qrCodeValue = 'https://example.com';
const qrCodeDataUrl = await QRCode.toDataURL(qrCodeValue);
const qrImageBytes = await fetch(qrCodeDataUrl).then((res) => res.arrayBuffer());
const qrImage = await pdfDoc.embedPng(qrImageBytes);
const qrImageSize = 100;
page.drawImage(qrImage, {
x: startX + (boxWidth - qrImageSize) / 2,
y: currentY - qrImageSize - 10,
width: qrImageSize,
height: qrImageSize,
});
const pdfBytes = await pdfDoc.save();
// 下载pdf
const blob = new Blob([pdfBytes], { type: 'application/pdf' });
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = 'output.pdf';
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
};
这里的表格绘制列有点头痛,定好规则,根据每一列的宽度和高度来进行计算
最后添加个按钮看看效果:
<template>
<div>
<button @click="generatePdf">生成 PDF</button>
</div>
</template>
实现效果导出后如下:
大功告成!