<template> <div ref="printArea" style="font-family: ProximaNova-Regular;background-color: #fff;padding:20px;word-break: break-word;box-sizing: border-box;"> <table> <tbody> <tr> <td style="margin-right: 14px;"> <img :src="comInfo.image" width="320" height="320" v-if="isImgSrc"> <img ref="productImg" width="250" height="250" v-else> </td> <td style="vertical-align: top;"> <p style="font-weight: bold;font-size: 22px;padding-bottom: 24px;color:#00213B"> <span style="margin-right: 5px;">{{pageData.product_code}}</span> <span>{{pageData.product_name}}</span> </p> <p style="line-height: 20px;color:#00213B;font-size: 14px;" v-html="comInfo.description"></p> </td> </tr> </tbody> </table> <div> <p style="font-weight: bold;font-size: 17px;margin: 12px 0 8px;color:#00213B">Specifications</p> <table style="width:100%;border-collapse: collapse;font-size: 14px;table-layout: fixed;text-align:center;"> <tbody> <tr style="background-color: #F7F8FC;font-weight: bold;"> <td v-for="(item,key) in headerColumns" :key="key" style="padding:10px 0;color:#00213B;width: 25%;font-size: 14px;border:1px solid #EFEFEF">{{item.label}}</td> </tr> <tr> <td v-for="(item,key) in headerColumns" :key="key" style="padding:10px 0 6px;color:#00213B;border:1px solid #EFEFEF"> <div v-if="specificationsObj[item.prop]"> <span v-if="item.prop != 'addonArr' ">{{specificationsObj[item.prop]}}</span> <div v-else v-for="(opt,idx) in specificationsObj.addonArr" :key="idx" style="padding-bottom:4px;" >{{opt}}</div> </div> <span v-else>-</span> </td> </tr> </tbody> </table> </div> <div> <p style="font-weight: bold;font-size: 17px;margin: 12px 0 8px;color:#00213B">Quote</p> <table style="width:100%;border-collapse: collapse;font-size: 14px;table-layout: fixed;text-align:center;"> <tbody> <tr style="background-color: #F7F8FC;font-weight: bold;" v-if="comLocationNum !== 1"> <td style="padding:10px 0;color:#00213B;border:1px solid #EFEFEF" :colspan="tableColumns.length-1">Quote</td> <td style="padding:10px 0;color:#00213B;border:1px solid #EFEFEF" :style="{width:comWidth}">Total</td> </tr> <tr style="background-color: #F7F8FC;font-weight: bold;"> <td v-for="(item,key) in tableColumns" :key="key" style="padding:10px 0;color:#00213B;border:1px solid #EFEFEF" :style="{width:comWidth}">{{item.label}}</td> </tr> <tr style="padding:10px 0;" v-for="row in tableData" :key="row.project"> <td v-for="column in tableColumns" :key="column.prop" style="padding:10px 0;color:#00213B;border:1px solid #EFEFEF;white-space: nowrap;" :style="getColumnHeaderStyle(column)"> {{ row[column.prop].includes('.')?'$':'' }} {{ row[column.prop]?row[column.prop]:'0.00' }} </td> </tr> </tbody> </table> </div> <div v-if="emailForm.Comments" style="color:#00213B"> <p style="margin: 20px 0;">{{emailForm.Comments}}</p> </div> </div> </template> <script> import html2Canvas from "html2canvas"; export default { props: { pageData: { type: Object, default: {}, }, specificationsObj: { type: Object, default: {}, }, tableData: { type: Array, default: [], }, tableColumns: { type: Array, default: [], }, comLocationNum: { type: Number, default: 1, }, emailForm:{ type: Object, default: {}, }, loading: { type: Boolean, default: false }, isImgSrc: { type: Boolean, default: true }, width: { type: String, default: '100%' } }, data(){ return { headerColumns: [ { label: "LeadTime", prop: "time", type: "pre" //去掉$符号 }, { label: "Model", prop: "model", type: "pre" //去掉$符号 }, { label: "Decoration", prop: "decoration", type: "pre" //去掉$符号 }, { label: "Add On", prop: "addonArr", type: "pre" //去掉$符号 }, ], } }, computed:{ comInfo(){ return this.pageData?.main }, comWidth(){ return 100/this.tableColumns.length + '%' } }, created(){ if(!this.isImgSrc){ this.getBase64Image(this.comInfo.image,'productImg') } }, methods: { getColumnHeaderStyle(column) { if (column.prop === 'project') { return { 'font-weight': 'bold' }; } return {}; }, //Base64生成产品图片,因为跨域 getBase64Image (url, ref) { var that = this var image = new Image() image.src = url + '?v=' + Math.random() // 处理缓存 image.crossOrigin = '*' // 支持跨域图片 image.onload = function () { var base64 = that.drawBase64Image(image) that.$refs[ref].src = base64 } }, drawBase64Image (img) { var canvas = document.createElement('canvas') canvas.width = img.width canvas.height = img.height var ctx = canvas.getContext('2d') ctx.drawImage(img, 0, 0, img.width, img.height) var dataURL = canvas.toDataURL('image/png') return dataURL }, htmlToPdf(title){ const element = this.$refs.printArea; const clientWidth = element.offsetWidth; const clientHeight = element.offsetHeight; const kh = [clientWidth, clientHeight]; const opts = { scale: 1.5, // 缩放比例,提高生成图片清晰度 useCORS: true, // 允许加载跨域的图片 // allowTaint: true, // 允许图片跨域,和 useCORS 二者不可共同使用 tainttest: true, // 检测每张图片已经加载完成 logging: true, // 日志开关,发布的时候记得改成 false }; html2Canvas(element, opts).then((canvas) => { const dataURL = canvas.toDataURL('image/png'); this.downloadImage(dataURL, kh, title); this.$emit('update:loading', false) }) .catch(() => { this.$emit('update:loading', false) // Bus.$emit("finishDownload"); }); }, getUrlBase64(url, kh) { return new Promise((resolve) => { let canvas = document.createElement('canvas'); const ctx = canvas.getContext('2d'); const img = new Image(); img.crossOrigin = 'Anonymous'; // 允许跨域 img.src = url; img.onload = () => { // eslint-disable-next-line prefer-destructuring canvas.height = kh[1]; // eslint-disable-next-line prefer-destructuring canvas.width = kh[0]; ctx.drawImage(img, 0, 0, kh[0], kh[1]); const dataURL = canvas.toDataURL('image/png'); canvas = null; resolve(dataURL); }; }); }, downloadImage (imgUrl, kh, title) { this.getUrlBase64(imgUrl, kh).then((base64) => { const link = document.createElement('a'); link.href = base64; link.download = `${title}.png`; link.click(); }); }, }, }; </script>