vue实现套打
Vue 实现套打(套印)功能
套打通常指在已有模板(如发票、合同)上精准打印动态数据。Vue 结合浏览器打印 API 或第三方库可实现该功能。
方案一:使用 CSS 控制打印样式
通过 CSS @media print 定义打印时的样式,隐藏无关元素并精确定位数据区域。
<template>
<div class="template-container">
<!-- 模板背景(通常为透明背景的图片或绝对定位的边框) -->
<img src="/path/to/template.png" class="template-bg" />
<!-- 动态数据区域 -->
<div class="print-field" style="top: 100px; left: 150px;">
{{ invoiceNumber }}
</div>
</div>
<button @click="print">打印</button>
</template>
<script>
export default {
data() {
return {
invoiceNumber: 'INV20230001'
}
},
methods: {
print() {
window.print();
}
}
}
</script>
<style>
@media print {
/* 隐藏非打印元素 */
.no-print {
display: none;
}
/* 模板容器 */
.template-container {
position: relative;
width: 210mm; /* A4 宽度 */
height: 297mm; /* A4 高度 */
}
/* 背景模板 */
.template-bg {
width: 100%;
height: 100%;
position: absolute;
z-index: 0;
}
/* 打印字段 */
.print-field {
position: absolute;
z-index: 1;
font-size: 12pt;
color: black;
}
}
</style>
方案二:使用 PDF.js 与动态叠加
如需处理 PDF 模板,可使用 Mozilla 的 PDF.js 库动态叠加数据:
-
安装依赖:
npm install pdfjs-dist -
实现代码:
<template> <div> <canvas ref="pdfCanvas"></canvas> <div ref="printContent" class="print-content"> <!-- 动态数据通过绝对定位覆盖在 PDF 上 --> <div v-for="item in fields" :style="item.style"> {{ item.value }} </div> </div> <button @click="printOverlay">打印</button> </div> </template>
export default { data() { return { fields: [ { value: '张三', style: { top: '120px', left: '80px' } }, { value: '1000.00', style: { top: '150px', left: '300px' } } ] } }, methods: { async loadPdf() { const loadingTask = pdfjsLib.getDocument('/path/to/template.pdf'); const pdf = await loadingTask.promise; const page = await pdf.getPage(1); const viewport = page.getViewport({ scale: 1.5 });
const canvas = this.$refs.pdfCanvas;
const context = canvas.getContext('2d');
canvas.height = viewport.height;
canvas.width = viewport.width;
await page.render({
canvasContext: context,
viewport: viewport
}).promise;
},
printOverlay() {
const printWindow = window.open('', '_blank');
printWindow.document.write(`
<!DOCTYPE html>
<html>
<body>
${this.$refs.printContent.innerHTML}
</body>
</html>
`);
printWindow.print();
printWindow.close();
}
}, mounted() { this.loadPdf(); } }
.print-content { position: relative; }.print-content > div { position: absolute; font-family: Arial; font-size: 12pt; }
```方案三:使用第三方库(Vue-print-nb)
对于快速实现,可使用现成的 Vue 打印库:
-
安装:
npm install vue-print-nb -
示例:
<template> <div> <div id="printArea" class="invoice-template"> <div class="field" style="top: 50mm; left: 30mm;"> 客户:{{ customerName }} </div> </div> <button v-print="printConfig">打印</button> </div> </template>
export default { directives: { print }, data() { return { customerName: 'ABC公司', printConfig: { id: 'printArea', popTitle: '发票打印', extraCss: 'https://example.com/print-styles.css' } } } }
.invoice-template { position: relative; width: 210mm; height: 297mm; background: url('/path/to/template.png') no-repeat; }.field { position: absolute; }
```关键注意事项
- 单位一致性:使用
mm单位能更好匹配物理打印尺寸 - 打印预览调试:Chrome 开发者工具的
Rendering > Emulate CSS media type: print可调试打印样式 - 模板校准:建议先用空白模板打印测试,调整定位参数后再填充数据
- 浏览器差异:不同浏览器对打印边距处理不同,需测试多平台
以上方案可根据实际需求选择,CSS 方案适合简单套打,PDF.js 适合复杂模板,第三方库能快速集成但灵活性较低。







