实际项目中有时会有根据填写的表单数据或者其他格式的数据,将数据自动填充到pdf文件中根据固定模板生成pdf文件的需求
文章目录
利用pdfmake生成pdf文件
1.下载安装pdfmake第三方包
npm i pdfmake
2.封装生成pdf文件的共用配置
可以在utils文件夹下新建pdf文件夹,所有的pdf文件模板/共用配置等文件都放在该文件夹下
新建文件pdfUtils.js,该文件是一些公用配置项
c
import pdfMake from 'pdfmake/build/pdfmake';
pdfMake.fonts={
Msyh:{
italics: 'https://example.com/fonts/fontFile3.ttf',
bold: 'https://example.com/fonts/fontFile4.ttf',
}
//可以设置文件的字体
}
export const PdfMake = pdfMake
export const baseDocDefinition={
//pdfmake中margin值的设置,4个值分别是[左,上,右,下]
pageMargins:[40,70,40,40],//文档边距,不影响页眉页脚
pageSize: 'A4', //设置纸张大小为A4
pageOrientation: 'portrait', //portrait:纵向; langscape:横向,默认是纵向的
//默认文本设置,这里的属性都是比较常见的就不赘述了
defaultStyle:{
font: 'Msyh',
color: '#000000',
bold: false,
fontSize: 12,
lineHeight: 1.2
}
}
//pdf展示图片,不能直接展示url,需要对文件进行转换
export async function getImageUrl(url){
const response=await fetch(url)
const blob=await response.blob()
return new Promise((resolve,reject)=>{
const reader=new FileReader()
reader.onload=()=>{
const base64data=reader.result
resolve(base64data)
}
reader.onerror=reject
reader.readAdDataURL(blob)
})
}
3.生成pdf文件的文件模板内容
新建getPdfDoc.js文件,该文件是具体要生成文件的配置
c
import { PdfMake } from './pdfUtils.js'
import { baseDocDefinition, getImageUrl } from './pdfUtils.js'
//由于文件中某些数据是自动填充上去的,所以调用生成pdf的方法时要传填充的数据
export function getDocPDF=async(data){
const docDefinition={
...baseDocDefinition,
//独有配置,这里可以参考文档最后
content:[
//独有的配置
...
]
}
PdfMake.createPDF(docDefinition).open()//生成pdf文件并打开,可以进行预览/导出
}
4.调用方法生成pdf
在需要的地方进行调用
例如:
c
<template>
...
<el-button @click='exportDoc'>导出PDF文件</el-button>
...
</template>
import { getDocPDF } from '@/utils/getPdfDoc.js'
<script>
export default {
data(){
return {
form:{}
}
},
methods:{
async exportDoc(){
await getDocPDF(this.form)
}
}
}
</script>
pdfmake的文档没有中文版的,这里我列举一些我用过的也是比较常用的配置
c
export function getDocPDF=async(data){
const docDefinition={
...baseDocDefinition,
//页眉
header: {
absolutePosition: { x: 40, y: 10 },
stack: [
{ text: `${data.fullName}`, fontSize: 10, absolutePosition: { x: 0, y: 13 }, alignment: 'center' },
{
canvas: [{
type: 'line',
x1: 0,
y1: 30,
x2: 515,
y2: 30,
lineWidth: 1,
absolutePosition: { x: 0, y: 10 }
}]
},// 分割线
],
},
//页脚
footer: function (currentPage, pageCount) {
return [
{
canvas: [
{
type: 'line',
x1: 40, y1: 0,
x2: 555, y2: 0,
lineWidth: 1
}
]
},
{
text: `${data.fullName}\n` + currentPage,
alignment: 'center',
fontSize: 10,
margin: [0, 10]
}
];
},
content:[
//独有的配置
...,
//文本段落
{
text:'***',
fontSize:16,//该段text的字体大小
bold:true,//该段字体加粗
lendingIndent: 25//首行缩进
},
//表格
{
layout:{
paddingTop: () => 5,
paddingBottom: () => 5,
paddingLeft: () => 5,
paddingRight: () => 5
},
table: {
widths: ['10%', '22%', '20%', '30%', '20%'],
body: [
[
//第一行的数据,即表格的表头
{ text: '序号', alignment: 'center' },
{ text: '姓名', alignment: 'center' },
{ text: '手机号', alignment: 'center' },
{ text: '性别', alignment: 'center' },
],
//后面的数据行,如果不是静态的数据,传入的数据展示我们可能还需要进行一下转换,转换成这里展示需要的数据格式
[
{ text: '1', alignment: 'center' },
{ text: '张三', alignment: 'center' },
{ text: '18888888888', alignment: 'center' },
{ text: '男', alignment: 'center' },
],
]
}
},
//左右布局
{
alignment: 'justify',
margin: [0, 20, 0, 5],
columns: [
{
//text可以直接是字符串,也可以是字符串数组
text: [
'签字日期:','\u00A0\u00A0\u00A0\u00A0','年','\u00A0\u00A0\u00A0\u00A0','月','\u00A0\u00A0\u00A0\u00A0','日'//这里的\u00A0是导出来展示是空格
],
fontSize: 12
},
{
text: '签字日期:','\u00A0\u00A0\u00A0\u00A0','年','\u00A0\u00A0\u00A0\u00A0','月','\u00A0\u00A0\u00A0\u00A0','日',
fontSize: 12
}
]
},
//如果需要换页,即下面的内容为新起一页的内容,可以通过给文本块加上pageBreak属性
{
text:' ',
pageBreak:'after',//表示该文本块后换页
},
//如果需要展示像图片,或者文本块较多,要放在stack中,图片不能直接展示url,要进行格式转换
stack:[
{
image: await getImageUrl(data.url)
width: 200,
}
]
]
}
PdfMake.createPDF(docDefinition).open()//生成pdf文件并打开,可以进行预览/导出
}
页眉效果
页脚效果