NodeJs导出PDF

(优于别人,并不高贵,真正的高贵应该是优于过去的自己。——海明威)

在这里插入图片描述

场景

根据订单参数生成账单PDF

结果

在这里插入图片描述

示例代码

/* eslint-disable no-unused-vars */
/* eslint-disable no-undef */
/* eslint-disable complexity */
const PDFDocument = require('pdfkit');
const fs = require('fs');
const dayjs = require('dayjs');
const AgencyWithdrawOrderStatus = {Completed: 'Completed',Submitted: 'Submitted',Rejected: 'Rejected',
}
const agencyName = 'Jasin';
const agencyEmail = 'pdfkit@dev.com';
const order = {"id": "FI-AWO-20230718-8657637839","accountID": {"id": "ID-AGE-20230707-6351711990","type": "AGENCY"},"transactionNo": "FIAWO202307180650601146","referenceID": "","transferWay": "Bank card","walletID": "FI-WAL-20230707-5401898911","transferID": "FI-TRF-20230718-4134849682","transactionID": "FI-TRA-20230718-2048728248","somoServiceFee": 345,"somoServiceFeeRate": 0.05,"bankTransferFee": 3000,"bankTransferFeeRate": 3000,"paypalTransferFee": 345,"paypalTransferFeeRate": 0.05,"paypalRemittanceAmount": 6555,"bankRemittanceAmount": 6900,"totalAmount": 6900,"status": "Submitted","transactionList": [{"brandName": "asdasdads","transactionID": "FI-TRA-20230710-1494352833","brandID": "ID-BRA-20230627-2309656536","campaignID": "AC-CAM-20230710-3827733853","campaignTitle": "Jack","orderID": "AC-ORD-20230710-2795223591","type": "AGENCY_CAMPAIGN_ORDER_PAYMENT","amount": 6900,"somoServiceFee": 345,"paypalTransferFee": 345,"bankTransferFee": 0}, {"brandName": "asdasdads","transactionID": "FI-TRA-20230710-5284753385","brandID": "ID-BRA-20230627-2309656536","campaignID": "AC-CAM-20230710-4072616238","campaignTitle": "Kami","orderID": "AC-ORD-20230710-7402268061","type": "AGENCY_CAMPAIGN_ORDER_PAYMENT","amount": 0,"somoServiceFee": 0,"paypalTransferFee": 0,"bankTransferFee": 0}],"transactionCount": 2,"accountBalance": 888750099,"withdrawalMethod": {"bankEnabled": true,"bankAccountName": "12213","bankAccountNumber": "22","bankName": "333","bankAddress": "444","bankSwiftCode": "555"},"reason": "","createdAt": {"$date": "2023-07-18T09:53:45.568Z"},"updatedAt": {"$date": "2023-07-18T09:53:45.568Z"},"__v": 0
};
const method = async () => {const pdfBuffer = await new Promise((resolve) => {// 实例化PDF对象const doc = new PDFDocument({ size: 'A4' });const fontSize = 14;const remittanceText = 'Remittance amount:';const remittanceTitleColor = '#8792A2';const remittanceAmountColor = '#181C1F';const remittanceAmountSize = 40;const orderStatusText = order.status;const orderStatusColor = {Submitted: '#4E515C',Completed: '#009944',Rejected: '#FF0000',}[orderStatusText];const orderStatusBackColor = {Submitted: '#f2f4f9',Completed: '#d8f7e6',Rejected: '#f0dede',}[orderStatusText];const orderStatusOffset = {Submitted: -6,Completed: -8,Rejected: 0,}[orderStatusText];const getFloatNumber = (number) => {return parseFloat(number.toString()).toFixed(2);};const getConvertAmount = (number) => {return number / 100;};const rejectedOffset = order.status === 'Rejected' ? 45 : 0;const remittanceAmount = order.withdrawalMethod.paypalEnabled? order.paypalRemittanceAmount: order.bankRemittanceAmount;const transferFee = order.withdrawalMethod.paypalEnabled? order.paypalTransferFee: order.bankTransferFee;const remittanceAmountLength = getFloatNumber(getConvertAmount(remittanceAmount),).length;const remittanceAmoutOffset =remittanceAmountLength - 4 > 0 ? remittanceAmountLength - 4 : 0;const transferAccount =(order.withdrawalMethod.paypalEnabled? order.withdrawalMethod.paypalAccountID: order.withdrawalMethod.bankAccountName) ?? ' ';const transferDetailTitleColor = '#F2F3F7';const transferDetailTitleSize = 16;const transferDetailBackgroundColor = '#171A1F';const transferDetailTitleText = 'Transfer detail:';const orderStatusX = 100;const orderStatusY = 105;const startX = 73;const transferDetailRectY = 150;const transferDetailX = 80;const transferDetailY = 168;const transferDetailWidth = 500;const transferDetailHeight = 60;const sideWidth = 500;const sideHeight = 1;const valueColor = '#272A33';const linceColor = '#F5F7F7';doc.// 使用字体font(`${__dirname}/Montserrat-Bold.ttf`).// 字体大小fontSize(fontSize).// 字体颜色fillColor(remittanceTitleColor).// 这一行的文本text(remittanceText).fontSize(remittanceAmountSize).fillColor(remittanceAmountColor).text(`$ ${getFloatNumber(getConvertAmount(remittanceAmount))}`).// 渲染块,指定x,y坐标以及宽高rect(orderStatusX + 112 + remittanceAmoutOffset * 23,orderStatusY - 8,92,34,).// 块的颜色fill(orderStatusBackColor).// 块的字体大小fontSize(fontSize).// 字体的颜色fillColor(orderStatusColor).font(`${__dirname}/Montserrat-Regular.ttf`).// 指定x,y坐标text(orderStatusText,orderStatusX +16 +112 +orderStatusOffset +remittanceAmoutOffset * 23,orderStatusY,);if (orderStatusText === AgencyWithdrawOrderStatus.Rejected) {doc.rect(startX, transferDetailRectY, 469, 30).fill('#FFE58F').// 插入图片image('withdraw.pdf.rejected.png',startX + 10,transferDetailRectY + 5,{ width: 20, height: 20 },).fontSize(12).fillColor('#000000').text(` ${order.reason}`, startX + 35, transferDetailRectY + 6.5);}doc.rect(startX,transferDetailRectY + rejectedOffset,transferDetailWidth,transferDetailHeight,).fill(transferDetailTitleColor).fontSize(transferDetailTitleSize).fillColor(transferDetailBackgroundColor).font(`${__dirname}/Montserrat-Bold.ttf`).text(transferDetailTitleText,transferDetailX,transferDetailY + rejectedOffset,{continued: false,baseline: 'top',},).font(`${__dirname}/Montserrat-Regular.ttf`).fontSize(fontSize).fillColor(remittanceTitleColor).text('Agency:',startX,transferDetailRectY + transferDetailHeight + 20 + rejectedOffset,{ lineBreak: false },).fillColor(valueColor).text(agencyName, startX + 200, doc.y, { lineGap: 5 }).fontSize(fontSize).fillColor(remittanceTitleColor).text(`Email:`, startX, doc.y, { lineBreak: false, lineGap: 5 }).fillColor(valueColor).text(agencyEmail, startX + 200, doc.y, { lineGap: 5 }).fontSize(fontSize).fillColor(remittanceTitleColor).text('Transaction No. :', startX, doc.y, { lineBreak: false }).fillColor(valueColor).text(order.transactionNo, startX + 200, doc.y, { lineGap: 5 }).fontSize(fontSize).fillColor(remittanceTitleColor).text('Reference ID. :', startX, doc.y, { lineBreak: false }).fillColor(valueColor).text(order.referenceID || ' ', startX + 200, doc.y, { lineGap: 5 }).fontSize(fontSize).fillColor(remittanceTitleColor).text('Transfer way:', startX, doc.y, { lineBreak: false }).fillColor(valueColor).text(order.transferWay, startX + 200, doc.y, { lineGap: 5 }).fontSize(fontSize).fillColor(remittanceTitleColor).text('Transfer account:', startX, doc.y, { lineBreak: false }).fillColor(valueColor).text(transferAccount, startX + 200, doc.y, { lineGap: 5 }).fontSize(fontSize).fillColor(remittanceTitleColor).text('Transfer status:', startX, doc.y, { lineBreak: false }).fillColor(valueColor).text(orderStatusText, startX + 200, doc.y, { lineGap: 5 }).fontSize(fontSize).fillColor(remittanceTitleColor).text('Created time:', startX, doc.y, { lineBreak: false }).fillColor(valueColor).text(dayjs(order.createdAt.valueOf()).format('YYYY-MM-DD HH:mm:ss'),startX + 200,doc.y,{ lineGap: 5 },).fontSize(fontSize).fillColor(remittanceTitleColor).text('Update time:', startX, doc.y, { lineBreak: false }).fillColor(valueColor).text(dayjs(order.updatedAt.valueOf()).format('YYYY-MM-DD HH:mm:ss'),startX + 200,doc.y,{ lineGap: 5 },).rect(startX, doc.y + 10, sideWidth, sideHeight).fill(linceColor).fontSize(fontSize).fillColor(remittanceTitleColor).text('Order total amount:', startX, doc.y + 20, { lineBreak: false }).fillColor(valueColor).text(`$ ${getFloatNumber(getConvertAmount(order.totalAmount))}`,startX + 200,doc.y,{lineGap: 5,},).fontSize(fontSize).fillColor(remittanceTitleColor).text('SOMO service fee:', startX, doc.y, {lineBreak: false,}).fillColor(remittanceTitleColor).text(`$ ${getFloatNumber(getConvertAmount(order.somoServiceFee))}`,startX + 200,doc.y,{lineGap: 5,strike: true,},).fontSize(fontSize).fillColor(remittanceTitleColor).text('Transfer fee:', startX, doc.y, { lineBreak: false }).fillColor(valueColor).text(`$ ${getFloatNumber(getConvertAmount(transferFee))}`,startX + 200,doc.y,{lineGap: 5,},).fontSize(fontSize).fillColor(remittanceTitleColor).text('Remittance amount:', startX, doc.y, { lineBreak: false }).fillColor(valueColor).text(`$ ${getFloatNumber(getConvertAmount(remittanceAmount))}`,startX + 200,doc.y,{lineGap: 5,},).rect(startX, doc.y + 10, sideWidth, 60).fill('#F2F3F7').fontSize(transferDetailTitleSize).fillColor('#171A1F').font(`${__dirname}/Montserrat-Bold.ttf`).text('Associated with the order', transferDetailX, doc.y + 30, {lineBreak: false,baseline: 'top',}).text(' ', { lineGap: 10 }).font(`${__dirname}/Montserrat-Regular.ttf`);for (let i = 0; i < order.transactionList.length; i++) {const item = order.transactionList[i];const itemTransferFee = order.withdrawalMethod.paypalEnabled? item.paypalTransferFee: item.bankTransferFee;doc.text(' ', { lineGap: 10 });doc.fontSize(fontSize).fillColor(remittanceTitleColor).text('Brand:', startX, doc.y, { paragraphGap: -20 }).fillColor(valueColor).text(item.brandName, startX + 200, doc.y, { lineGap: 8 });doc.fontSize(fontSize).fillColor(remittanceTitleColor).text('Campaign:', startX, doc.y, { paragraphGap: -20 }).fillColor(valueColor).text(item.campaignTitle, startX + 200, doc.y, { lineGap: 8 });doc.fontSize(fontSize).fillColor(remittanceTitleColor).text('Order ID:', startX, doc.y, { paragraphGap: -20 }).fillColor(valueColor).text(item.orderID, startX + 200, doc.y, { lineGap: 8 });doc.fontSize(fontSize).fillColor(remittanceTitleColor).text('Oder price:', startX, doc.y, { paragraphGap: -20 }).fillColor(valueColor).text(`$ ${getFloatNumber(getConvertAmount(item.amount))}`,startX + 200,doc.y,{lineGap: 8,},);doc.fontSize(fontSize).fillColor(remittanceTitleColor).text('SOMO service fee:', startX, doc.y, {paragraphGap: -20,}).fillColor(remittanceTitleColor).text(`$ ${getFloatNumber(getConvertAmount(item.somoServiceFee))}`,startX + 200,doc.y,{lineGap: 8,strike: true,},);doc.fontSize(fontSize).fillColor(remittanceTitleColor).text('Transfer fee:', startX, doc.y, { paragraphGap: -20 }).fillColor(valueColor).text(`$ ${getFloatNumber(getConvertAmount(itemTransferFee))}`,startX + 200,doc.y,{lineGap: 8,},);doc.rect(startX, doc.y + 20, sideWidth, sideHeight).fill(linceColor);}doc.end();const buffers = [];// 使用pdfkit的监听方法收集buffer,便于后续文件处理doc.on('data', buffers.push.bind(buffers));doc.on('end', () => {const pdfData = Buffer.concat(buffers);return resolve(pdfData);});});fs.writeFileSync(`${__dirname}/file.pdf`, pdfBuffer);
};
method();

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/41220.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【jquery实现动态给表格添加删除行,合并指定单元格】

jquery实现动态给表格添加删除行&#xff0c;合并指定单元格 前端技术 jspjquery 动态添加行 //新增行 $("#addRowBtn").click(function(){var rowEl$("<tr><td><input typecheckbox classcheckItem/></td><td><input nam…

NPOI 读取和写入Excel

在C#中使用NPOI库读取和写入Excel文件&#xff0c;你需要先下载并安装NPOI库。你可以在NuGet管理器中搜索NPOI并进行安装。 以下是一个使用NPOI库进行Excel文件读取和写入的示例&#xff1a; 读取Excel文件&#xff1a; using NPOI.SS.UserModel; using NPOI.XSSF.UserModel…

【仿写tomcat】二、扫描java文件,获取带有@WebServlet注解的类

tomcat仿写 项目结构扫描文件servlet注解map容器servlet工具类启动类调用 项目结构 扫描文件之前当然要确定一下项目结构了&#xff0c;我这里的方案是tomcat和项目同级 项目的话就仿照我们平时使用的结构就好了&#xff0c;我们规定所有的静态资源文件都在webApp目录下存放…

【数据库】P1 数据库基本常识

数据库基本常识 数据库 ≠ 数据库管理系统表&#xff08;Table&#xff09;SQL是什么 数据库 ≠ 数据库管理系统 数据库是保存有组织的数据的容器&#xff0c;数据库称为 DB&#xff08;DataBase&#xff09;&#xff1b;数据库管理系统是创建和操纵数据库的软件&#xff0c;数…

充气泵方案设计——便携无线充气泵方案

充气泵方案的进化史是人类历史上电子技术发展史中的一环。电子技术&#xff0c;特别是微电子技术是 20 世纪发展最为迅速、影响最为广泛的技术成就。电子技术的核心是电子器件,电子器件的进步和换代&#xff0c;引起了电子电路极大的变化&#xff0c;出现了很多新的电路和应用。…

java解决mysql大数据联查问题

java解决mysql大数据联查问题 近期有一个需求是联查两张表比对三个字段 一般用mysql就可以解决 SELECT* FROMtb_a aLEFT JOIN b ON a.test b.testAND a.NAME b.NAME AND a.type b.type但是表a和表b的数据量都很不小&#xff0c;大概在10w左右&#xff0c;由于并不是以固定…

Webpact学习笔记记录

Webpact学习笔记记录 一.初始化项目1.生成package.json2.安装webpack3.执行webpack体验 二、webpack的配置文件三、less-loader解析less1.安装loader2.配置 四、eslint-loader语法检查1.安装loader2.配置loader3.在package.json中加入 五、js语法转换1.安装loader2.配置loader …

前端能正常跑起来但是控制台报错数据undefined之onMounted最好不要用异步写法

记录问题 在做项目的时候&#xff0c;项目可以正常运行&#xff0c;但是控制台总是报错&#xff0c;有一个数据是undefined。 分析问题 一般遇到这种情况&#xff0c;就是vue找不到这个数据。但是为什么能正常运行&#xff1f;说明是开始加载的时候找不到数据&#xff0c;但…

Java进阶篇--数据结构

目录 一.数组&#xff08;Array&#xff09;&#xff1a; 1.1 特点&#xff1a; 1.2 基本操作&#xff1a; 1.3 使用数组的好处包括&#xff1a; 1.4 数组也有一些限制&#xff1a; 二.集合框架&#xff08;Collections Framework&#xff09;&#xff1a; 2.1 列表…

当你出差在外时,怎样轻松访问远程访问企业局域网象过河ERP系统?

文章目录 概述1.查看象过河服务端端口2.内网穿透3. 异地公网连接4. 固定公网地址4.1 保留一个固定TCP地址4.2 配置固定TCP地址 5. 使用固定地址连接 概述 ERP系统对于企业来说重要性不言而喻&#xff0c;不管是财务、生产、销售还是采购&#xff0c;都需要用到ERP系统来协助。…

miniconda克隆arcpy

arcpy环境克隆 前言尝试思考到此结束 前言 最近遇到了一些问题&#xff0c;需要用到arcpy来处理一些东西&#xff0c;但众所周知&#xff0c;arcgis的arcpy是python 2.0的&#xff0c;我不是很喜欢&#xff1b;所以我安装了arcgis pro 2.8&#xff0c;我发现这也是个坑&#x…

Git分布式版本控制系统

目录 2、安装git 2.1 初始环境 2.2 Yum安装Git 2.3 编译安装 2.4 初次运行 Git 前的配置 2.5 初始化及获取 Git 仓库 2.6 Git命令常规操作 2.6.2 添加新文件 2.6.3 删除git内的文件 2.6.4 重命名暂存区数据 2.6.5 查看历史记录 2.6.6 还原历史数据 2.6.7 还原未来…

react使用antd的table组件,实现点击弹窗显示对应列的内容

特别提醒&#xff1a;不能在table的columns的render里面设置弹窗组件渲染&#xff0c;因为这会导致弹窗显示的始终是最后一行的内容&#xff0c;因为这样渲染的结果是每一行都会重新渲染一遍这个弹窗并且会给传递一个content的值&#xff0c;渲染到最后一行的时候&#xff0c;就…

Unity的TimeScale的影响范围分析

大家好&#xff0c;我是阿赵。 这期来说一下Unity的TimeScale。 一、前言 Unity提供了Time这个类&#xff0c;来控制时间。其实我自己倒是很少使用这个Time&#xff0c;因为做网络同步的游戏&#xff0c;一般是需要同步服务器时间&#xff0c;所以我比较多是在使用System.Date…

linux驱动 - 20230817

练习: 通过字符设备驱动分步注册方式编写LED灯的驱动&#xff0c;应用程序使用ioctl函数编写硬件控制逻辑 头文件 head.h #ifndef __HEAD_H__ #define __HEAD_H__ typedef struct{unsigned int MODER;unsigned int OTYPER;unsigned int OSPEEDR;unsigned int PUPDR;unsigned…

问道管理:机器人概念走势活跃,新时达涨停,拓斯达、丰立智能等大涨

机器人概念17日盘中走势活跃&#xff0c;到发稿&#xff0c;拓斯达大涨18%&#xff0c;昊志机电涨近16%&#xff0c;丰立智能涨超13%&#xff0c;步科股份、优德精细涨超10%&#xff0c;新时达涨停&#xff0c;天玑科技、兆龙互联、中大力德涨逾9%。 消息面上&#xff0c;8月16…

HTTP 介绍

HTTP 介绍 HTTP 协议一般指 HTTP&#xff08;超文本传输协议&#xff09;。超文本传输协议&#xff08;英语&#xff1a;HyperText Transfer Protocol&#xff0c;缩写&#xff1a;HTTP&#xff09;是一种用于分布式、协作式和超媒体信息系统的应用层协议&#xff0c;是因特网…

Java 计算两个字符的相似度

在Java中&#xff0c;要计算两个字符的相似度&#xff0c;可以借助一些字符串相似度算法。以下是几种常见的字符串相似度算法&#xff1a; Levenshtein距离&#xff1a;也称为编辑距离&#xff0c;用于计算两个字符串之间的最小编辑操作次数&#xff08;插入、删除、替换&…

解决ios隔空播放音频到macos没有声音的问题

解决ios隔空播放音频到macos没有声音的问题 一、检查隔空播放支持设备和系统要求二、打开隔空播放接收器三、重置MAC控制中心进程END 一、检查隔空播放支持设备和系统要求 Mac、iPhone、iPad 和 Apple Watch 上“连续互通”的系统要求 二、打开隔空播放接收器 ps;我设备是同一…