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,一经查实,立即删除!

相关文章

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

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

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…

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

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

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

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

element+vue 表格行拖拽功能

解决方案 使用 sortable.js 步骤一&#xff1a; 安装 npm install vuedraggable步骤二&#xff1a;引入 import Sortable from sortablejs;步骤三&#xff1a; el-table 添加row-key属性&#xff0c;外层包一层 sortableDiv <div class"sortableDiv"> 拖…

分类预测 | MATLAB实现WOA-CNN-BiLSTM-Attention数据分类预测

分类预测 | MATLAB实现WOA-CNN-BiLSTM-Attention数据分类预测 目录 分类预测 | MATLAB实现WOA-CNN-BiLSTM-Attention数据分类预测分类效果基本描述程序设计参考资料 分类效果 基本描述 1.MATLAB实现WOA-CNN-BiLSTM-Attention数据分类预测&#xff0c;运行环境Matlab2023b及以上…

seata 的部署和集成

文章目录 seata的部署和集成一、部署Seata的tc-server1.下载2.解压3.修改配置4.在nacos添加配置5.创建数据库表6.启动TC服务 二、微服务集成seata1.引入依赖2.修改配置文件 TODO三、TC服务的高可用和异地容灾1.模拟异地容灾的TC集群2.将事务组映射配置到nacos3.微服务读取nacos…

中期国际:MT4数据挖掘与分析方法:以数据为导向,制定有效的交易策略

在金融市场中&#xff0c;制定有效的交易策略是成功交易的关键。而要制定一份可靠的交易策略&#xff0c;数据挖掘与分析方法是不可或缺的工具。本文将介绍如何以数据为导向&#xff0c;利用MT4进行数据挖掘与分析&#xff0c;从而制定有效的交易策略。 首先&#xff0c;我们需…

操作系统搭建相关知识

文章目录 系统篇netstat命令systemctl命令Systemd系统资源分类&#xff08;12类&#xff09; 网络篇ifconfig命令操作系统配置动态IP脚本dhcp服务的安装与配置防火墙相关知识 操作系统常用配置文件 系统篇 netstat命令 netstat指路 systemctl命令 常用于重启系统的每个服务…

Jetpack Compose:探索声明式UI开发的未来

Jetpack Compose&#xff1a;探索声明式UI开发的未来 1. 引言 在移动应用开发领域&#xff0c;用户界面&#xff08;UI&#xff09;开发一直是开发过程中的关键挑战之一。传统的UI开发方式往往涉及大量繁琐的布局代码、手动管理状态和事件处理&#xff0c;不仅容易引发错误&a…

Google浏览器点击链接打开新标签页

由于新安装的谷歌浏览器点击链接时默认在当前窗口打开非常不方便&#xff0c;这里提供一下解决思路 1、打开浏览器输入任意内容&#xff0c;点击右上角的设置 2、在弹出的选项栏中点击See all Search settings 3、点击Other settings&#xff0c;将指定选项打开即可

C#__事件event的简单使用:工具人下楼问题

// 工具人类 namespace DownStair {delegate void DownStairDelegate(); // 定义了一个下楼委托class ToolMan{public string Name { get; set; } // 声明工具人的名字属性// public DownStairDelegate downStairDelegate null; // 初始化委托downStair为空委托// 解决方案pu…

gromacs教程练习1

gromacs能在win上运行&#xff0c;还是个开源的软件&#xff0c;这都很值得入手学习 记录下gromacs教程的练习情况&#xff1a; Lysozyme in water 水中的溶菌酶&#xff0c;嗯&#xff0c;估计就是把蛋白处理后放在显试溶剂里跑MD这个模拟。 1、文件的准备&#xff1a; 1、…

【STM32+ESP8266上云连载①】给ESP8266烧录AT固件

文章目录 一、给NodeMCU烧录固件1.1硬件准备1.2软件准备1.3AT固件下载1.4配置设置1.5开始烧录 二、给ESP8266-01S烧录固件2.1硬件准备2.2AT固件下载2.3连线2.4烧录配置 三、给ESP-12E/F/S单片烧录固件四、指令测试4.1HTTP测试4.2MQTT测试 我在使用ESP8266的时候遇到了一些问题&…