vue3笔记(37)页面转 pdf 导出

新需求,报价管理中每个报价单的明细需要转换成 pdf 导出,调研后完美实现。

安装包

1
2
npm i html2canvas
npm i jspdf

html 转 pdf

utils文件夹下新建html2pdf.ts文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
import html2canvas from 'html2canvas';
import jsPDF from 'jspdf'

export const htmlToPDF = async (htmlId: string, title: string = "报表", bgColor = "#fff") => {
let pdfDom: HTMLElement | null = document.getElementById(htmlId) as HTMLElement
pdfDom.style.padding = '0 10px !important'
const A4Width = 595.28;
const A4Height = 841.89;
let canvas = await html2canvas(pdfDom, {
scale: 2,
useCORS: true,
backgroundColor: bgColor,
});
let pageHeight = (canvas.width / A4Width) * A4Height;
let leftHeight = canvas.height;
let position = 0;
let imgWidth = A4Width;
let imgHeight = (A4Width / canvas.width) * canvas.height;
/*
自定义水印代码
*/
const ctx: any = canvas.getContext('2d');
ctx.textAlign = 'center';
ctx.textBaseline = 'middle';
ctx.rotate((20 * Math.PI) / 180);
ctx.font = '20px Microsoft Yahei';
ctx.fillStyle = 'rgba(184, 184, 184, 0.8)';
for (let i = canvas.width * -1; i < canvas.width; i += 240) {
for (let j = canvas.height * -1; j < canvas.height; j += 200) {
// 填充文字,x 间距, y 间距
ctx.fillText('水印名', i, j);
}
}
/*
自定义水印代码
*/
let pageData = canvas.toDataURL("image/jpeg", 1.0);
let PDF = new jsPDF("p", 'pt', 'a4');
if (leftHeight < pageHeight) {
PDF.addImage(pageData, "JPEG", 0, 0, imgWidth, imgHeight);
} else {
while (leftHeight > 0) {
PDF.addImage(pageData, "JPEG", 0, position, imgWidth, imgHeight);
leftHeight -= pageHeight;
position -= A4Height;
if (leftHeight > 0) PDF.addPage();
}
}
PDF.save(title + ".pdf");
}

项目中使用

1
2
3
4
5
6
7
8
9
10
11
12
13
<template>
<div class="quote" id="test-id">
<!-- 这里是导出内容 -->
</div>
<el-button type="text" @click="handleExport">导出</el-button>
</template>

<script lang="ts" setup>
import { htmlToPDF } from '@/utils/html2pdf'
const handleExport = () => {
htmlToPDF('test-id', state.quote.quotation_number)
}
</script>

点击按钮触发导出功能,最终效果如下:
预览效果