太原招聘网站开发,数字校园建设专题网站,平台经济,河北廊坊做网站简介
项目上有个需求#xff0c;需要根据表单填写一些信息#xff0c;来生成定制的二维码图片#xff0c;并且支持批量下载二维码图片。 之前的实现方式是直接后端生成二维码图片#xff0c;点击下载时后端直接返回一个zip包即可。但是项目经理说后端实现方式每次改个东西…简介
项目上有个需求需要根据表单填写一些信息来生成定制的二维码图片并且支持批量下载二维码图片。 之前的实现方式是直接后端生成二维码图片点击下载时后端直接返回一个zip包即可。但是项目经理说后端实现方式每次改个东西都要改大半天所以让前端来实现。
方案
1.后端返回二维码的base64url数据流就是下图红框中的二维码图片。 2.前端负责展示成交互上的二维码图片样式如下图。 3.点击批量下载时用户自己选择下载数量然后后端返回二维码base64url的数组前端自己实现下载且是以zip的形式下载。下载的每张图片都是前端页面上所展示的样子。
思路
比如批量下载50个首先10个一组处理每个二维码编号生成一个blob流塞入生成的zip中50个二维码编号全部处理完成后开始下载zip将zip转为blob流触发下载等待下载完成。
耗时较久的是每个二维码编号生成一个blob流需要前端拿到后端返回的二维码base64 url, 通过js代码组装成最终的图片样式的DOM然后需要塞到页面中再使用dom-to-image 转成图片形式的blob流。
实现
1.比如选择下载数量是50张点击下载,触发handleDownload 函数 2.使用jszip 生成一个zip 3.print_set_root 是该页面组件中最外层的div元素 4.分10个一组进行处理
完整代码如下
import JSZip from jszip
import { chunk } from lodash
import domtoimage from dom-to-imageasync handleDownload (val) {this.downBtnLoading truetry {const { data } await downQuas({ count: Number(val), randomNum: 6, start: this.ruleForm.code })this.zip new JSZip()const rod document.getElementById(print_set_root)const arr chunk(data, 10)for (let i 0; i arr.length; i) {await this.usePromiseArr(arr[i], rod)}this.downBtnLoading falseconst that thisthis.zip.generateAsync({ type: blob }).then(function (base64) {const url URL.createObjectURL(base64)const link document.createElement(a)link.download ${that.regionName}.ziplink.href urllink.click()setTimeout(() { window.URL.revokeObjectURL(url) })})} catch (e) {this.downBtnLoading false}
},
usePromiseArr (data, rod) {const allPromise []data.forEach(v {allPromise.push(this.renderImg(v, rod))})return Promise.all(allPromise)
},
renderImg (data, rod) {return new Promise((resolve, reject) {let num 0const useSrc data:image/png;base64,${data.value}const template2 div classtitle-normal报修电话/divdiv classtitle${this.ruleForm.phoneNumber || xxxxxxxx}/divconst leftDiv document.createElement(div)leftDiv.setAttribute(class, left downLeft)leftDiv.setAttribute(id, erweima-common)const header document.createElement(div)header.setAttribute(class, left-header)const large1 document.createElement(div)large1.setAttribute(class, font-large)large1.textContent xxxxconst large2 document.createElement(div)large2.setAttribute(class, font-large)large2.textContent xxxxconst topImage document.createElement(div)topImage.setAttribute(class, top-img)const img1 document.createElement(img)img1.src /xxxxxx.pngimg1.onload () {topImage.appendChild(img1)numthis.downloadImg(num, leftDiv, rod, data.key, resolve)}header.appendChild(large1)header.appendChild(topImage)header.appendChild(large2)leftDiv.appendChild(header)const safe document.createElement(div)safe.setAttribute(class, safe)safe.textContent xxxxxxxxxxconst borderDiv document.createElement(div)borderDiv.setAttribute(class, left-border)const dashedDiv document.createElement(div)dashedDiv.setAttribute(class, dashed-border)const Img2 document.createElement(img)Img2.src /xxxxxxxx.pngImg2.onload () {dashedDiv.appendChild(Img2)numthis.downloadImg(num, leftDiv, rod, data.key, resolve)}const title1 document.createElement(div)title1.setAttribute(class, title)title1.textContent xxxxconst title2 document.createElement(div)title2.setAttribute(class, title)title2.textContent xxxxxxxxxxconst title3 document.createElement(div)title3.setAttribute(class, title-min)title3.textContent Area Under 24-hour MonitoringborderDiv.appendChild(dashedDiv)borderDiv.appendChild(title1)borderDiv.appendChild(title2)borderDiv.appendChild(title3)const border2 document.createElement(div)border2.setAttribute(class, left-border)border2.innerHTML template2const small document.createElement(div)small.setAttribute(class, title-small)small.textContent ${this.ruleForm.producer || xxxxxxxxx}const leftcontent document.createElement(div)leftcontent.setAttribute(class, left-content)const useImg document.createElement(img)useImg.setAttribute(class, erwei)useImg.src useSrcuseImg.onload () {leftcontent.appendChild(useImg)leftcontent.appendChild(safe)leftcontent.appendChild(borderDiv)leftcontent.appendChild(border2)leftcontent.appendChild(small)leftDiv.appendChild(leftcontent)rod.appendChild(leftDiv)numthis.downloadImg(num, leftDiv, rod, data.key, resolve)}})
},
downloadImg (num, leftDiv, rod, name, resolve) {if (num ! 3) returnconst that thisdomtoimage.toBlob(leftDiv).then(function (dataUrl) {rod.removeChild(leftDiv)that.zip.file(${name}.jpeg, dataUrl)resolve()})
}使用技术dom-to-image JSZip
注意点元素在appendChild图片时一定要等到图片onload后再执行appendChild操作。