pdfmake生成pdf的使用

实际项目中有时会有根据填写的表单数据或者其他格式的数据,将数据自动填充到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文件并打开,可以进行预览/导出
}

页眉效果

页脚效果

相关推荐
2401_873479404 小时前
如何利用IP查询定位识别电商刷单?4个关键指标+工具配置方案
开发语言·tcp/ip·php
我爱cope4 小时前
【从0开始学设计模式-10| 装饰模式】
java·开发语言·设计模式
菜鸟学Python4 小时前
Python生态在悄悄改变:FastAPI全面反超,Django和Flask还行吗?
开发语言·python·django·flask·fastapi
浪浪小洋5 小时前
c++ qt课设定制
开发语言·c++
charlie1145141915 小时前
嵌入式C++工程实践第16篇:第四次重构 —— LED模板,从通用GPIO到专用抽象
c语言·开发语言·c++·驱动开发·嵌入式硬件·重构
故事和你915 小时前
洛谷-数据结构1-4-图的基本应用1
开发语言·数据结构·算法·深度优先·动态规划·图论
幺风6 小时前
Claude Code 源码分析 — Tool/MCP/Skill 可扩展工具系统
前端·javascript·ai编程
程序猿编码6 小时前
给你的网络流量穿件“隐形衣“:手把手教你用对称加密打造透明安全隧道
linux·开发语言·网络·安全·linux内核
ID_180079054736 小时前
淘宝 API 上货 / 商品搬家 业务场景实现 + JSON 返回示例
前端·javascript·json
M ? A6 小时前
Vue 动态组件在 React 中,VuReact 会如何实现?
前端·javascript·vue.js·经验分享·react.js·面试·vureact