当前位置: 首页 > article >正文

Vue环境下数据导出PDF的全面指南

在这里插入图片描述

文章目录

    • 1. 前言
    • 2. 原生浏览器打印方案
      • 2.1 使用window.print()实现
      • 2.2 使用CSS Paged Media模块
    • 3. 常用第三方库方案
      • 3.1 使用jsPDF
      • 3.2 使用html2canvas + jsPDF
      • 3.3 使用pdfmake
      • 3.4 使用vue-pdf
    • 4. 服务器端导出方案
      • 4.1 前端请求服务器生成PDF
      • 4.2 使用无头浏览器生成PDF
    • 5. 方法对比与选择指南
      • 5.1 功能对比表
      • 5.2 选择建议
      • 5.3 性能优化建议
    • 6. 最佳实践示例
      • 6.1 完整的Vue PDF导出组件

在这里插入图片描述

1. 前言

在现代Web应用开发中,将数据导出为PDF是一项常见且重要的功能需求。PDF作为一种通用的文档格式,具有跨平台、保持格式一致、易于打印等优势。Vue.js作为当前流行的前端框架,提供了多种实现PDF导出的方法。本文将全面探讨Vue环境下实现PDF导出的7种主要方法,包括原生浏览器API、常用第三方库方案以及服务器端导出方案,每种方法都将提供详细的代码示例和优劣分析。

2. 原生浏览器打印方案

2.1 使用window.print()实现

这种方法利用浏览器自带的打印功能,通过CSS媒体查询控制打印样式。

实现原理

  1. 创建专门用于打印的组件或视图
  2. 使用@media print定义打印样式
  3. 调用window.print()触发浏览器打印对话框

代码示例

<template><div><button @click="print">打印PDF</button><div ref="printContent" class="print-container"><h1>销售报表</h1><table><thead><tr><th>日期</th><th>产品</th><th>数量</th><th>金额</th></tr></thead><tbody><tr v-for="item in salesData" :key="item.id"><td>{{ item.date }}</td><td>{{ item.product }}</td><td>{{ item.quantity }}</td><td>{{ formatCurrency(item.amount) }}</td></tr></tbody></table></div></div>
</template><script>
export default {data() {return {salesData: [{ id: 1, date: '2023-01-01', product: '产品A', quantity: 10, amount: 1000 },{ id: 2, date: '2023-01-02', product: '产品B', quantity: 5, amount: 2500 }]}},methods: {print() {window.print()},formatCurrency(value) {return '¥' + value.toLocaleString()}}
}
</script><style>
@media print {body * {visibility: hidden;}.print-container, .print-container * {visibility: visible;}.print-container {position: absolute;left: 0;top: 0;width: 100%;}/* 打印分页控制 */table {page-break-inside: auto;}tr {page-break-inside: avoid;page-break-after: auto;}thead {display: table-header-group;}tfoot {display: table-footer-group;}
}/* 屏幕样式与打印样式分离 */
.print-container {display: none;
}
@media print {.print-container {display: block;}
}
</style>

优点

  • 零依赖,不增加项目体积
  • 实现简单,适合简单打印需求
  • 用户可以选择"另存为PDF"(大多数现代浏览器支持)

缺点

  • 依赖用户操作,无法自动化
  • 打印样式控制有限
  • 无法生成复杂的PDF文档
  • 不同浏览器表现可能不一致

2.2 使用CSS Paged Media模块

对于更专业的打印需求,可以使用CSS Paged Media模块定义分页、页眉页脚等。

代码示例

@page {size: A4;margin: 1cm;@top-left {content: "公司名称";font-size: 10pt;}@top-right {content: "页码 " counter(page) " / " counter(pages);font-size: 10pt;}@bottom-center {content: "机密文件";font-size: 8pt;color: #999;}
}@media print {h1 {page-break-before: always;}table {page-break-inside: avoid;}.page-break {page-break-after: always;}
}

优点

  • 更专业的打印控制
  • 支持页码、页眉页脚等高级功能
  • 仍然是纯CSS方案,无JavaScript依赖

缺点

  • 浏览器支持不一致(特别是复杂特性)
  • 学习曲线较陡
  • 仍然依赖浏览器打印功能

3. 常用第三方库方案

3.1 使用jsPDF

jsPDF是最流行的JavaScript PDF生成库之一,可以直接在浏览器中生成PDF。

安装

npm install jspdf

基础实现

import jsPDF from 'jspdf'export function generatePDF(title, data, columns, filename = 'export.pdf') {const doc = new jsPDF()// 添加标题doc.setFontSize(18)doc.text(title, 14, 15)// 添加表头doc.setFontSize(12)let y = 30columns.forEach((col, index) => {doc.text(col.label, 14 + index * 40, y)})// 添加数据行doc.setFontSize(10)data.forEach((row, rowIndex) => {y = 40 + rowIndex * 10if (y > 280) { // 接近页面底部doc.addPage()y = 20}columns.forEach((col, colIndex) => {doc.text(String(row[col.field]), 14 + colIndex * 40, y)})})// 保存文件doc.save(filename)
}// Vue组件中使用
methods: {exportPDF() {const data = [{ id: 1, name: '产品A', price: 100, stock: 50 },{ id: 2, name: '产品B', price: 200, stock: 30 }]const columns = [{ label: 'ID', field: 'id' },{ label: '产品名称', field: 'name' },{ label: '价格', field: 'price' },{ label: '库存', field: 'stock' }]generatePDF('产品列表', data, columns)}
}

高级功能示例

function generateAdvancedPDF() {const doc = new jsPDF({orientation: 'landscape',unit: 'mm',format: 'a4'})// 设置元数据doc.setProperties({title: '高级报表',subject: '2023年度销售数据',author: '销售系统',keywords: '销售, 报表, 2023',creator: '公司销售系统'})// 添加公司logoconst imgData = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUg...'doc.addImage(imgData, 'PNG', 10, 10, 50, 15)// 添加标题doc.setFont('helvetica', 'bold')doc.setFontSize(22)doc.setTextColor(40, 40, 40)doc.text('2023年度销售报表', 105, 20, { align: 'center' })// 添加表格const headers = [['产品', 'Q1', 'Q2', 'Q3', 'Q4', '总计']]const salesData = [['产品A', 1000, 1500, 1200, 1800, 5500],['产品B', 800, 900, 1000, 1200, 3900],['产品C', 500, 600, 700, 900, 2700]]doc.autoTable({head: headers,body: salesData,startY: 40,theme: 'grid',headStyles: {fillColor: [22, 160, 133],textColor: 255,fontStyle: 'bold'},alternateRowStyles: {fillColor: [240, 240, 240]},margin: { top: 40 },didDrawPage: function(data) {// 页脚doc.setFontSize(10)doc.setTextColor(150)const pageCount = doc.internal.getNumberOfPages()doc.text(`${doc.internal.getCurrentPageInfo().pageNumber} 页 / 共 ${pageCount}`, data.settings.margin.left, doc.internal.pageSize.height - 10)}})// 添加折线图(使用jsPDF的简单绘图功能)doc.setDrawColor(100, 100, 255)doc.setFillColor(100, 100, 255)const points = [{ x: 60, y: 150, q: 'Q1' },{ x: 90, y: 130, q: 'Q2' },{ x: 120, y: 140, q: 'Q3' },{ x: 150, y: 120, q: 'Q4' }]// 绘制折线points.forEach((point, i) => {if (i > 0) {doc.line(points[i-1].x, points[i-1].y, point.x, point.y)}doc.circle(point.x, point.y, 2, 'F')doc.text(point.q, point.x, point.y + 10)})doc.save('advanced_report.pdf')
}

优点

  • 纯前端实现,不依赖服务器
  • 功能丰富,支持文本、表格、简单图形等
  • 支持自定义字体
  • 活跃的社区和良好的文档

缺点

  • 复杂布局实现较困难
  • 原生不支持复杂表格样式(需要插件)
  • 中文支持需要额外配置字体

3.2 使用html2canvas + jsPDF

这种方案先将HTML转换为canvas,再将canvas转为PDF,适合需要精确复制页面样式的场景。

安装

npm install html2canvas jspdf

基础实现

import html2canvas from 'html2canvas'
import jsPDF from 'jspdf'export async function exportHTMLToPDF(element, filename = 'export.pdf', options = {}) {const canvas = await html2canvas(element, {scale: 2, // 提高分辨率logging: false,useCORS: true,allowTaint: true,...options})const imgData = canvas.toDataURL('image/png')const pdf = new jsPDF({orientation: canvas.width > canvas.height ? 'landscape' : 'portrait',unit: 'mm'})const pageWidth = pdf.internal.pageSize.getWidth()const pageHeight = pdf.internal.pageSize.getHeight()const imgWidth = pageWidthconst imgHeight = (canvas.height * imgWidth) / canvas.widthpdf.addImage(imgData, 'PNG', 0, 0, imgWidth, imgHeight)pdf.save(filename)
}// Vue组件中使用
methods: {async exportPage() {const element = this.$refs.pdfContentawait exportHTMLToPDF(element, 'page_export.pdf', {scale: 3 // 更高分辨率})}
}

高级功能示例

async function exportMultiPagePDF() {const elements = document.querySelectorAll('.report-page')const pdf = new jsPDF('p', 'mm', 'a4')for (let i = 0; i < elements.length; i++) {const element = elements[i]const canvas = await html2canvas(element, {scale: 2,logging: true})const imgData = canvas.toDataURL('image/png')const imgWidth = pdf.internal.pageSize.getWidth()const imgHeight = (canvas.height * imgWidth) / canvas.widthif (i > 0) {pdf.addPage()}pdf.addImage(imgData, 'PNG', 0, 0, imgWidth, imgHeight)// 添加页脚pdf.setFontSize(10)pdf.setTextColor(150)pdf.text(`${i + 1}`, pdf.internal.pageSize.getWidth() / 2,pdf.internal.pageSize.getHeight() - 10,{ align: 'center' })}pdf.save('multi_page_report.pdf')
}

优点

  • 精确复制页面样式和布局
  • 支持复杂HTML结构和CSS样式
  • 可以处理动态生成的内容
  • 支持多页导出

缺点

  • 生成的PDF本质是图片,文字不可选择
  • 大页面可能导致内存问题
  • 性能较差,特别是复杂页面
  • 分页控制较困难

3.3 使用pdfmake

pdfmake是一个声明式的PDF生成库,使用JSON格式定义文档结构。

安装

npm install pdfmake

基础实现

import pdfMake from 'pdfmake/build/pdfmake'
import pdfFonts from 'pdfmake/build/vfs_fonts'pdfMake.vfs = pdfFonts.pdfMake.vfsexport function generatePDFWithPdfMake(data, filename = 'document.pdf') {const docDefinition = {content: [{ text: '销售报表', style: 'header' },'\n\n',{table: {headerRows: 1,widths: ['*', 'auto', 'auto', 'auto'],body: [['产品', '季度1', '季度2', '季度3'],...data.map(item => [item.product,{ text: item.q1, alignment: 'right' },{ text: item.q2, alignment: 'right' },{ text: item.q3, alignment: 'right' }])]}}],styles: {header: {fontSize: 18,bold: true,alignment: 'center'}},defaultStyle: {font: 'SimSun'}}pdfMake.createPdf(docDefinition).download(filename)
}// Vue组件中使用
methods: {exportData() {const data = [{ product: '产品A', q1: 1000, q2: 1500, q3: 1200 },{ product: '产品B', q1: 800, q2: 900, q3: 1000 }]generatePDFWithPdfMake(data, 'sales_report.pdf')}
}

高级功能示例

function generateAdvancedPdfMakeDocument() {const docDefinition = {pageSize: 'A4',pageMargins: [40, 60, 40, 60],header: function(currentPage, pageCount) {return {text: `${currentPage} 页 / 共 ${pageCount}`,alignment: 'right',margin: [0, 20, 20, 0]}},footer: function(currentPage, pageCount) {return {text: '公司机密 - 未经授权禁止复制',alignment: 'center',fontSize: 8,margin: [0, 0, 0, 20]}},content: [{columns: [{width: 100,image: 'logo',fit: [80, 80]},{width: '*',text: '2023年度财务报告',style: 'reportTitle'}]},'\n\n',{text: '1. 销售概览',style: 'sectionHeader'},{text: '本年度公司整体销售额达到¥1,200万,同比增长15%。主要增长来自产品线A和B。',style: 'paragraph'},'\n',{style: 'tableExample',table: {widths: ['*', '*', '*', '*'],body: [[{ text: '产品线', style: 'tableHeader' },{ text: 'Q1', style: 'tableHeader' },{ text: 'Q2', style: 'tableHeader' },{ text: 'Q3', style: 'tableHeader' }],['产品A', '320万', '350万', '380万'],['产品B', '280万', '300万', '320万'],['产品C', '150万', '160万', '170万'],[{ text: '总计', style: 'tableHeader' },{ text: '750万', colSpan: 3, style: 'tableHeader' },{},{}]]}},'\n\n',{text: '2. 成本分析',style: 'sectionHeader',pageBreak: 'before'},{canvas: [{type: 'rect',x: 0, y: 0,w: 500, h: 20,color: '#eeeeee'},{type: 'rect',x: 0, y: 0,w: 350, h: 20,color: '#cc0000'}]},{text: '成本构成示意图',alignment: 'center',italics: true,fontSize: 10,margin: [0, 5, 0, 0]}],styles: {reportTitle: {fontSize: 24,bold: true,alignment: 'center',margin: [0, 20, 0, 0]},sectionHeader: {fontSize: 16,bold: true,margin: [0, 15, 0, 5]},paragraph: {fontSize: 12,lineHeight: 1.5,margin: [0, 0, 0, 10]},tableExample: {margin: [0, 5, 0, 15]},tableHeader: {bold: true,fontSize: 13,color: 'black',fillColor: '#dddddd'}},images: {logo: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAA...'}}pdfMake.createPdf(docDefinition).open()
}

优点

  • 声明式API,易于理解和使用
  • 强大的布局和样式控制能力
  • 内置分页、页眉页脚支持
  • 支持表格、列表、图片等多种元素

缺点

  • 中文支持需要额外配置字体
  • 学习曲线较陡(特别是复杂布局)
  • 文档结构可能变得复杂
  • 性能不如原生jsPDF

3.4 使用vue-pdf

vue-pdf是一个Vue专用的PDF生成和显示组件库。

安装

npm install @tato30/vue-pdf

基础实现

<template><div><button @click="generatePDF">生成PDF</button><div ref="pdfContent"><h1>员工信息</h1><table><tr><th>ID</th><th>姓名</th><th>部门</th></tr><tr v-for="emp in employees" :key="emp.id"><td>{{ emp.id }}</td><td>{{ emp.name }}</td><td>{{ emp.department }}</td></tr></table></div></div>
</template><script>
import VuePdf from '@tato30/vue-pdf'export default {components: {VuePdf},data() {return {employees: [{ id: 1, name: '张三', department: '研发' },{ id: 2, name: '李四', department: '市场' }]}},methods: {async generatePDF() {const pdf = new VuePdf()// 添加内容pdf.addText('员工信息', { fontSize: 18, align: 'center' })pdf.addBreak(20)// 添加表格pdf.addTable({headers: ['ID', '姓名', '部门'],rows: this.employees.map(emp => [emp.id, emp.name, emp.department]),styles: {cellPadding: 5,headerColor: '#eeeeee'}})// 生成并下载pdf.download('员工信息.pdf')}}
}
</script>

优点

  • 专为Vue设计,API更符合Vue习惯
  • 轻量级,易于集成
  • 支持基本的PDF生成功能

缺点

  • 功能相对有限
  • 社区支持不如jsPDF或pdfmake
  • 文档较少

4. 服务器端导出方案

4.1 前端请求服务器生成PDF

这种方案将PDF生成逻辑放在服务器端,前端只负责触发和下载。

前端代码

export function requestPDFExport(params) {return axios({url: '/api/export-pdf',method: 'POST',data: params,responseType: 'blob'}).then(response => {const blob = new Blob([response.data], { type: 'application/pdf' })const url = window.URL.createObjectURL(blob)const link = document.createElement('a')link.href = urllink.setAttribute('download', 'server_export.pdf')document.body.appendChild(link)link.click()document.body.removeChild(link)})
}// Vue组件中使用
methods: {async exportFromServer() {try {this.loading = trueawait requestPDFExport({reportType: 'sales',year: 2023,format: 'A4'})} catch (error) {console.error('导出失败:', error)} finally {this.loading = false}}
}

Node.js服务器端示例(使用pdfkit)

const express = require('express')
const PDFDocument = require('pdfkit')
const app = express()app.post('/api/export-pdf', async (req, res) => {try {const { reportType, year, format } = req.body// 创建PDF文档const doc = new PDFDocument({ size: format || 'A4' })// 设置响应头res.setHeader('Content-Type', 'application/pdf')res.setHeader('Content-Disposition', 'attachment; filename="report.pdf"')// 管道传输到响应doc.pipe(res)// 添加内容doc.fontSize(25).text(`${year}年度${getReportTitle(reportType)}`, {align: 'center'})doc.moveDown()doc.fontSize(12).text('生成日期: ' + new Date().toLocaleDateString())// 添加表格数据const data = await getReportData(reportType, year)drawTable(doc, data)// 结束并发送doc.end()} catch (error) {console.error('PDF生成错误:', error)res.status(500).send('PDF生成失败')}
})function drawTable(doc, data) {const startY = 150const rowHeight = 30const colWidth = 150const headers = ['产品', 'Q1', 'Q2', 'Q3', 'Q4', '总计']// 表头doc.font('Helvetica-Bold')headers.forEach((header, i) => {doc.text(header, 50 + i * colWidth, startY, {width: colWidth,align: 'center'})})// 表格内容doc.font('Helvetica')data.forEach((row, rowIndex) => {const y = startY + (rowIndex + 1) * rowHeight// 绘制行背景if (rowIndex % 2 === 0) {doc.fillColor('#f5f5f5').rect(50, y - 10, colWidth * headers.length, rowHeight).fill()doc.fillColor('black')}// 绘制单元格文本Object.values(row).forEach((value, colIndex) => {doc.text(String(value), 50 + colIndex * colWidth, y, {width: colWidth,align: colIndex > 0 ? 'right' : 'left'})})})
}app.listen(3000, () => console.log('Server running on port 3000'))

优点

  • 处理大数据量更高效
  • 减轻前端压力
  • 可以复用服务器端数据处理逻辑
  • 更安全,业务逻辑不暴露在客户端
  • 支持更复杂的PDF生成(如使用专业PDF库)

缺点

  • 增加服务器负载
  • 需要网络请求,可能有延迟
  • 实现复杂度更高

4.2 使用无头浏览器生成PDF

对于需要精确复制网页样式的场景,可以在服务器端使用无头浏览器(如Puppeteer)生成PDF。

Node.js服务器示例(使用Puppeteer)

const express = require('express')
const puppeteer = require('puppeteer')
const app = express()app.post('/api/export-pdf', async (req, res) => {let browser = nulltry {const { url, options } = req.bodybrowser = await puppeteer.launch({headless: true,args: ['--no-sandbox', '--disable-setuid-sandbox']})const page = await browser.newPage()// 如果是URL,直接导航;如果是HTML内容,设置内容if (url.startsWith('http')) {await page.goto(url, { waitUntil: 'networkidle2' })} else {await page.setContent(url)}// 生成PDFconst pdf = await page.pdf({format: 'A4',printBackground: true,margin: {top: '20mm',right: '20mm',bottom: '20mm',left: '20mm'},...options})// 发送PDFres.setHeader('Content-Type', 'application/pdf')res.setHeader('Content-Disposition', 'attachment; filename="export.pdf"')res.send(pdf)} catch (error) {console.error('PDF生成错误:', error)res.status(500).send('PDF生成失败')} finally {if (browser) {await browser.close()}}
})app.listen(3000, () => console.log('Server running on port 3000'))

优点

  • 精确复制网页样式和布局
  • 支持所有现代CSS特性
  • 可以处理动态内容
  • 支持截图、PDF等多种输出

缺点

  • 资源消耗大(需要运行浏览器实例)
  • 性能较差
  • 部署复杂度高

5. 方法对比与选择指南

5.1 功能对比表

方法生成方式样式保真度复杂度性能适用场景
浏览器打印客户端中等简单打印需求
jsPDF客户端编程式生成简单PDF
html2canvas+jsPDF客户端精确复制页面样式
pdfmake客户端结构化文档生成
vue-pdf客户端简单Vue集成
服务器生成服务端可高可低依赖实现复杂/大数据量PDF
无头浏览器服务端极高很高精确复制复杂页面

5.2 选择建议

  1. 简单打印需求:使用浏览器打印方案,成本最低
  2. 编程式生成简单PDF:选择jsPDF,纯前端实现
  3. 精确复制页面样式:html2canvas+jsPDF组合或服务器端无头浏览器方案
  4. 结构化文档生成:pdfmake提供更直观的声明式API
  5. Vue项目快速集成:考虑vue-pdf组件
  6. 大数据量或复杂处理:优先服务器端方案
  7. 最高样式保真度:无头浏览器方案(如Puppeteer)

5.3 性能优化建议

  1. 分页处理:对于大数据集,实现分页或分块生成
  2. 懒加载资源:只在需要时加载PDF生成库
  3. Web Worker:将耗时的生成过程放在Worker线程
  4. 服务器缓存:对频繁请求的相同内容缓存生成的PDF
  5. 按需生成:提供预览功能,只在用户确认后生成完整PDF
  6. 资源优化:压缩图片等资源减少PDF体积

6. 最佳实践示例

6.1 完整的Vue PDF导出组件

<template><div class="pdf-export"><button @click="showModal = true"class="export-button"><i class="icon-pdf"></i> 导出PDF</button><div v-if="showModal" class="export-modal"><div class="modal-content"><h3>PDF导出选项</h3><div class="form-group"><label>文件名</label><input v-model="filename" type="text" placeholder="请输入文件名"></div><div class="form-group"><label>纸张大小</label><select v-model="pageSize"><option value="A4">A4</option><option value="A3">A3</option><option value="Letter">Letter</option></select></div><div class="form-group"><label>方向</label><select v-model="orientation"><option value="portrait">纵向</option><option value="landscape">横向</option></select></div><div class="form-group"><label><input v-model="includeHeaderFooter" type="checkbox"> 包含页眉页脚</label></div><div class="form-group"><label><input v-model="onlySelected" type="checkbox"> 仅导出选中项</label></div><div class="button-group"><button @click="showModal = false">取消</button><button @click="exportPDF" :disabled="exporting">{{ exporting ? '导出中...' : '确认导出' }}</button></div><div v-if="progress > 0" class="progress-bar"><div class="progress" :style="{ width: progress + '%' }"></div></div></div></div></div>
</template><script>
import { jsPDF } from 'jspdf'
import html2canvas from 'html2canvas'export default {name: 'PdfExport',props: {tableData: {type: Array,required: true},selectedRows: {type: Array,default: () => []},tableColumns: {type: Array,default: () => []},title: {type: String,default: '导出数据'}},data() {return {showModal: false,filename: 'export',pageSize: 'A4',orientation: 'portrait',includeHeaderFooter: true,onlySelected: false,exporting: false,progress: 0}},methods: {async exportPDF() {this.exporting = truethis.progress = 0try {// 确定导出数据const exportData = this.onlySelected && this.selectedRows.length > 0? this.selectedRows: this.tableData// 创建PDFconst doc = new jsPDF({orientation: this.orientation,unit: 'mm',format: this.pageSize})// 添加标题doc.setFont('helvetica', 'bold')doc.setFontSize(16)doc.text(this.title, 105, 20, { align: 'center' })// 添加生成时间doc.setFont('helvetica', 'normal')doc.setFontSize(10)doc.text(`生成时间: ${new Date().toLocaleString()}`, 105, 30, { align: 'center' })// 添加表格await this.addTableToPDF(doc, exportData)// 添加页脚if (this.includeHeaderFooter) {const pageCount = doc.internal.getNumberOfPages()for (let i = 1; i <= pageCount; i++) {doc.setPage(i)doc.setFontSize(8)doc.text(`第 ${i} 页 / 共 ${pageCount} 页`,doc.internal.pageSize.getWidth() - 20,doc.internal.pageSize.getHeight() - 10)}}// 保存文件doc.save(`${this.filename}.pdf`)this.$emit('export-success')this.showModal = false} catch (error) {console.error('导出失败:', error)this.$emit('export-error', error)} finally {this.exporting = falsethis.progress = 0}},async addTableToPDF(doc, data) {const columns = this.tableColumns.filter(col => !col.hidden)const headers = columns.map(col => col.label)// 准备表格数据const tableData = data.map(row => {return columns.map(col => {let value = row[col.prop]if (col.formatter) {value = col.formatter(row, col)}return value !== undefined ? String(value) : ''})})// 自动调整列宽const pageWidth = doc.internal.pageSize.getWidth() - 20 // 左右边距const colWidth = pageWidth / columns.lengthconst colWidths = columns.map(() => colWidth)// 分页添加表格let startY = 40let remainingData = tableDatawhile (remainingData.length > 0) {// 计算当前页能容纳的行数const pageHeight = doc.internal.pageSize.getHeight()const rowHeight = 7const maxRows = Math.floor((pageHeight - startY - 20) / rowHeight)const chunk = remainingData.slice(0, maxRows)remainingData = remainingData.slice(maxRows)// 添加表格部分doc.autoTable({head: [headers],body: chunk,startY,margin: { left: 10, right: 10 },styles: {fontSize: 8,cellPadding: 2,overflow: 'linebreak'},columnStyles: columns.reduce((styles, col, index) => {styles[index] = { cellWidth: colWidths[index],halign: col.align || 'left'}return styles}, {})})// 更新进度this.progress = ((tableData.length - remainingData.length) / tableData
http://www.lryc.cn/news/2379731.html

相关文章:

  • Linux中的DNS的安装与配置
  • linux服务器与时间服务器同步时间
  • 【数据结构篇】排序1(插入排序与选择排序)
  • 《Linux服务与安全管理》| DNS服务器安装和配置
  • 【NLP】34. 数据专题:如何打造高质量训练数据集
  • Notepad++ 学习(三)使用python插件编写脚本:实现跳转指定标签页(自主研发)
  • Stable Diffusion 学习笔记02
  • python:pymysql概念、基本操作和注入问题讲解
  • Scala语言基础与函数式编程详解
  • 类的加载过程详解
  • 机器学习-人与机器生数据的区分模型测试 - 模型融合与检验
  • 机器学习 day03
  • 《社交应用动态表情:RN与Flutter实战解码》
  • 嵌入式软件--stm32 DAY 6 USART串口通讯(下)
  • 问题处理——在ROS2(humble)+Gazebo+rqt下,无法显示仿真无人机的相机图像
  • 69、微服务保姆教程(十二)容器化与云原生
  • 朱老师,3518e系列,第六季
  • ElasticSearch-集群
  • 一文掌握工业相机选型计算
  • 记录心态和工作变化
  • 深入理解 TypeScript 中的 unknown 类型:安全处理未知数据的最佳实践
  • LabVIEW机械振动信号分析与故障诊断
  • Helm配置之为特定Deployment配置特定Docker仓库(覆盖全局配置)
  • 【Spring】Spring中的适配器模式
  • GO学习指南
  • 2、ubuntu系统配置OpenSSH | 使用vscode或pycharm远程连接
  • MySQL面试知识点详解
  • 小白入门:GitHub 远程仓库使用全攻略
  • RPC与SOAP的区别
  • Day11-苍穹外卖(数据统计篇)