项目需求:批量导出报名二维码海报
思路:
1、根据后台返回的Url 生成二维码
2、把二维码 、内容、背景批量合成为海报
3、导出合成海报的压缩包文件
第一步:安装qrcode、html2canvas、jszip、file-saver 插件
npm install --save qrcode
npm install --save html2canvas
npm install --save jszip
npm install --save file-saver
第二步:页面引入
import QRCode from 'qrcode'
import html2canvas from "html2canvas"
import JSZip from 'jszip'
import FileSaver from "file-saver"
第三步:使用
后台返回接口结构:
页面按钮:
<el-button type="primary" plain size="mini" @click="exportCanvas(item)">导出报名二维码</el-button>
需要合成海报的html展示:html2canvas 将html的dom结构生成图片,所以需要先展示出来,但是默认用户是看不到的,在页面的最下方
<div class="codePanel" v-if="codeData!=''">
<div class="codeBox" v-for="(item,index) in codeData.term_urls" :key="index" :id="`code_${index+1}`">
<div class="code">
<img :src="codelist[index]" />
</div>
<div class="flexBox">
<div class="p1">课程名称:</div>
<div class="p2">{{codeData.lesson.name}}</div>
</div>
<div class="flexBox">
<div class="p1">班级名称:</div>
<div class="p2">{{item.class_name}}</div>
</div>
<div class="flexBox">
<div class="p1">开课时间:</div>
<div class="p2">{{item.started_at==''?'待定':`${item.started_at}`.substring(0,10)}}</div>
</div>
<div class="flexBox">
<div class="p1">报名截止:</div>
<div class="p2">{{item.final_paid_at==''?'待定':`${item.final_paid_at}`.substring(0,10)}}</div>
</div>
</div>
</div>
.codePanel {
padding-top: 9999px;
}
导出时进度条弹窗:默认不允许用户关闭弹窗
<el-dialog center title="提示" :visible.sync="loadDialog" width="400px" center :show-close='false'
:close-on-click-modal="false" :close-on-press-escape="false">
<el-progress :percentage="loadprogress"></el-progress>
<p style="font-size: 12px;color: #999;margin-top: 10px;" v-if="loadOK">导出中,请不要关闭页面</p>
<p style="font-size: 12px;color: #999;margin-top: 10px;" v-else>导出完成</p>
<span slot="footer" class="dialog-footer">
<el-button @click="loadDialog = false" :disabled="loadOK">关闭弹窗</el-button>
</span>
</el-dialog>
js部分:
export default {
data() {
return {
//批量合成海报下载
codeData: '', //当前选中要下载的数据
imgI: 0, //当前合成的海报
imglist: [], //已合成海报列表
codelist: [], //二维码列表
loadDialog: false, //海报合成进度弹窗
loadprogress: 0, //海报合成进度
loadOK: true, //压缩包下载是否完成 完成后状态为false(这里是按钮是否可点击的状态)
}
},
exportCanvas(data) { //导出海报二维码
this.loadDialog = true
this.imgI = 0
this.imglist = []
this.codelist = []
this.loadprogress = 0
this.getCode(data) //生成二维码
},
// 合成二维码
getCode(data) {
this.$nextTick(() => {
data.term_urls.forEach((item, index) => {
QRCode.toDataURL(item.url).then(url => {
console.log(url)
this.codelist.push(url)
if (index+1==data.term_urls.length) {
this.codeData = data
console.log('生成二维码结束,合成海报')
this.getCanvas()
}
}).catch(err => {
console.error(err)
})
});
}, 500)
},
//合成海报
getCanvas() {
this.$nextTick(() => {
let _this = this;
this.imgI++
html2canvas(document.getElementById("code_" + this.imgI), {
useCORS: true
}).then(canvas => {
var url = canvas.toDataURL("image/png");
this.imglist.push(url)
this.loadprogress = Math.floor((this.imgI / this.codeData.term_urls.length) * 100) //已合成除以总张数
if (this.imgI > this.codeData.term_urls.length) {
} else {
this.getCanvas()
}
}).catch((e) => {
console.log('合成完毕,准备下载')
this.downImg()
});
});
},
// 合成海报批量下载
downImg() {
let _this = this;
let zip = new JSZip();
let zipName = _this.codeData.school_name;
let images = this.imglist
for (let i = 0; i < images.length; i++) {
var fliename = _this.codeData.term_urls[i].class_name
let imageFile = images[i].replace(/^data:image\/(png|jpg|jpeg);base64,/, "");
zip.file(`${fliename}.jpg`, imageFile, {
base64: true
})
}
zip.generateAsync({
type: "blob"
}).then(content => {
FileSaver.saveAs(content, zipName);
this.loadOK = false
this.codeData=''
}).catch((res) => {
alert("文件压缩失败");
});
},