Vue项目中将界面转换为PDF并导出的实现方案

1. 主要技术栈

项目使用了以下库来实现PDF导出功能:

  • html2canvas:将HTML元素转换为canvas图像
  • jspdf:生成PDF文件
  • 自定义的打印插件:基于vue-print-nb改进,支持水印等功能
javascript 复制代码
npm install html2canvas jspdf

2. 核心实现方式

使用html2canvas + jspdf直接生成PDF

javascript 复制代码
// 生成PDF的核心方法
async generatePDF() {
  try {
    // 获取要导出的DOM元素
    const element = this.$refs.pdfContent;
    
    // 临时隐藏不需要打印的元素
    const noPrintElements = element.querySelectorAll('.no-print');
    const originalDisplays = [];
    noPrintElements.forEach((el, index) => {
      originalDisplays[index] = el.style.display;
      el.style.display = 'none';
    });

    // 临时添加PDF导出专用样式
    const style = document.createElement('style');
    style.id = 'pdf-export-style';
    style.textContent = `
      .duty-table {
        width: 1200px !important;
        max-width: none !important;
        font-size: 14px !important;
        // ... 更多样式
      }
    `;
    document.head.appendChild(style);

    // 创建canvas
    const canvas = await html2canvas(element, {
      scale: 2, // 清晰度
      useCORS: true,
      allowTaint: true,
      backgroundColor: '#ffffff',
      width: 1200,
      height: element.scrollHeight,
      ignoreElements: (el) => {
        return el.classList.contains('no-print');
      }
    });

    // 恢复隐藏的元素和样式
    noPrintElements.forEach((el, index) => {
      el.style.display = originalDisplays[index];
    });
    document.getElementById('pdf-export-style')?.remove();

    // 创建PDF
    const imgData = canvas.toDataURL('image/png', 1.0);
    const pdf = new jsPDF('p', 'mm', 'a4');
    
    // 计算图片在PDF中的尺寸并添加到PDF
    const a4Width = 210;
    const a4Height = 297;
    const margin = 5;
    // ... 尺寸计算逻辑
    pdf.addImage(imgData, 'PNG', xOffset, yOffset, imgWidth, imgHeight);

    // 转换为Blob对象
    const pdfBlob = pdf.output('blob');
    const fileName = `排班表_${this.currentDate}_${new Date().getTime()}.pdf`;
    
    return {
      fileName: fileName,
      pdfBlob: pdfBlob,
      message: "PDF生成成功"
    };
  } catch (error) {
    console.error('PDF导出错误:', error);
    return null;
  }
}

3. 实现要点总结

样式处理

  1. 为不需要打印的元素添加no-print类
  2. 临时添加专为PDF导出优化的CSS样式
  3. 处理字体和颜色(打印时通常需要将背景色设为白色)

导出流程

  1. 获取需要导出的DOM元素
  2. 使用html2canvas将其渲染为canvas
  3. 使用jspdf将canvas图像转换为PDF
  4. 通过Blob对象处理PDF数据,提供下载或上传功能

特殊处理

  1. 水印添加:通过CSS或在canvas上叠加实现
  2. 分页处理:计算内容高度,必要时分页
  3. 样式隔离:临时添加导出专用样式,处理完成后恢复

4. 使用示例

javascript 复制代码
// 直接下载PDF
async exportPDF() {
  const result = await this.generatePDF();
  if (result) {
    const url = URL.createObjectURL(result.pdfBlob);
    const link = document.createElement('a');
    link.href = url;
    link.download = result.fileName;
    link.click();
    URL.revokeObjectURL(url);
  }
}

// 上传PDF到服务器
async exportAndUpload() {
  const result = await this.generatePDF();
  if (result && result.pdfBlob) {
    const formData = new FormData();
    const pdfFile = new File([result.pdfBlob], result.fileName, {
      type: "application/pdf",
    });
    formData.append("pdfFile", pdfFile);
    // 发送请求上传文件
    await uploadPDF(formData);
  }
}
相关推荐
VimorphTech3 小时前
React 任务轮询,为什么不能只写一个 setInterval?
javascript·typescript
lexiangqicheng3 小时前
Docker的沙箱机制是怎样的?
前端·javascript
LCG米5 小时前
STM32 HardFault故障定位实测:压栈帧寄存器解析、CFSR故障源判读与出错地址回溯
前端·javascript·stm32·单片机·嵌入式
持敬chijing5 小时前
白盒测试与代码审计-JS 数据逆向
javascript·网络·安全·web安全·网络安全·网络攻击模型·安全威胁分析
weixin_BYSJ19876 小时前
【计算机毕设】基于Spring_Boot_Vue的马拉松报名与选手成绩追踪系统05445
java·vue.js·spring boot·学习·spring·django·课程设计
薛一半6 小时前
Redux实战:组件状态管理全解析
开发语言·前端·javascript·react.js
小羊没烦恼!19 小时前
T-SQL查询进阶--理解SQL SERVER中的分区表
服务器·开发语言·前端·javascript·html
星光不问赶路人19 小时前
Vue 3 + TypeScript 中 enum 的使用实践
前端·vue.js
Highcharts.js20 小时前
AI图表开发工具Highcharts Assist|自然语言生成图表代码
javascript·人工智能·highcharts·开发神器
志尊宝20 小时前
Vue3 零基础每日笔记(087):Vue3 高频面试题(下)
前端·javascript·vue.js·笔记·ecmascript·#vue.js