需要引入的依賴:
import * as utils from '../../utils/utils'
import html2canvas from "html2canvas";
import JSZip from "jszip";
import JSPDF from "jspdf";
import FileSaver from "file-saver"import { Loading } from "element-ui";
importDetailPdf(title) {// 顯示加載提示(告知用戶正在生成導出 PDF)this.showLoading("正在處理數據,請等待...")let that = this// 需要導出為 PDF 的 DOM 容器(整頁內容區域)var element = document.getElementById("pdfDom")// 將 DOM 渲染為畫布(canvas)html2canvas(element, {logging: false // 關閉調試日志,減少控制臺輸出}).then(function (canvas) {// 創建 A4 縱向 PDF 文檔:單位 mm,紙張 a4var pdf = new JSPDF("p", "mm", "a4") // A4紙,縱向// 畫布上下文var ctx = canvas.getContext("2d")// A4 內容顯示區域:210 x 297(mm),預留四周 20mm 邊距 => 內容 170 x 257(mm)var a4w = 170;var a4h = 257 // A4大小,210mm x 297mm,四邊各保留20mm的邊距,顯示區域170x257// 計算一頁可容納的圖像像素高度(按 A4 內容區域等比換算)var imgHeight = Math.floor(a4h * canvas.width / a4w) // 按A4顯示比例換算一頁圖像的像素高度// 已經渲染(導出)的高度累計var renderedHeight = 0// 循環切割整張長畫布,分頁寫入 PDFwhile (renderedHeight < canvas.height) {// 針對當前頁創建一個臨時畫布,寬度與原始畫布一致,高度為“單頁可顯示高度”或剩余高度var page = document.createElement("canvas")page.width = canvas.widthpage.height = Math.min(imgHeight, canvas.height - renderedHeight)// 可能內容不足一頁// 從原始畫布中截取當前頁區域像素并繪制到臨時畫布page.getContext("2d").putImageData(ctx.getImageData(0, renderedHeight, // 起始坐標canvas.width, // 截取寬度Math.min(imgHeight, canvas.height - renderedHeight) // 截取高度),0, 0)// 將當前頁畫布作為圖片添加到 PDF:// 位置 (10,10) mm(四周 10mm 邊距),寬度 a4w,高度按比例縮放(不超過 a4h)pdf.addImage(page.toDataURL("image/jpeg", 1.0), // 圖片數據,JPEG,質量 1.0"JPEG",10, 10, // PDF 內左上角定位(mm)a4w, // 顯示寬度(mm)Math.min(a4h, a4w * page.height / page.width) // 按比例計算的顯示高度(mm))// 遞增已渲染高度renderedHeight += imgHeight// 如果還有未導出的內容,則在 PDF 中新增一頁if (renderedHeight < canvas.height) {pdf.addPage()}// 如果后面還有內容,添加一個空頁// delete page; // 如需主動釋放可在合適場景處理}// 未傳入標題時,采用當前時間作為標題(注意:此處 this 作用域為 then 回調,不是 Vue 實例)if (title == undefined) {title = this.nowTimeDesc()}// 輸出 PDF 為 dataURL 字符串let datauri = pdf.output('dataurlstring')// 截取 base64 數據體(去掉前綴 data:application/pdf;base64, => 28 字符)let base64 = datauri.substring(28)// 將 PDF 打包進 ziplet zip = new JSZip()let fileName = title + ".pdf"zip.file(fileName, base64, {base64: true})// 如果有其他需要一并下載的附件,這里繼續打包后統一下載that.downloadOtherFile(zip, title)})},downloadOtherFile(zip, title) {this.showLoading("正在打包文檔,請等待...")//查找所有的文檔// zip.generateAsync({type:"blob"}).then(content => {// FileSaver.saveAs(content,title + ".zip")// })// returnlet list = this.allProjectFileListif (utils.isEmpty(list) || list.length == 0) {//沒有要下載的文檔,直接打包并保存成文件zip.generateAsync({ type: "blob" }).then(content => {FileSaver.saveAs(content, title + ".zip")}).finally(() => {this.endLoading()})return}let promises = []list.forEach(item => {let promise = this.downloadProFile(item).then((res, file) => {filezip.file(this.parseFileType(item) + item.archiveName, res.data, { binary: true })})promises.push(promise)})Promise.all(promises).then(() => {zip.generateAsync({ type: "blob" }).then(content => {FileSaver.saveAs(content, title + ".zip")}).finally(() => {this.endLoading()})})},endLoading() {this.$nextTick(() => {if (this.loading) {this.loading.close()}})},
如果需要對頁面中的內容進行判斷,手動選擇pdf中的內容則:
? ? ? ? 對頁面中的內容使用v-if來進行邏輯渲染,根據邏輯判斷此時是否是導出pdf。
showProjectTeam() {if (!this.isExport) {return true}return this.projectTeam},