一、打开一个生成二维码页面
<template>
<div @click="handleGenerateQrCode ">生成二维码</div>
// 省略表格选中
<QR/ ref="qrRef">
</template>
<script>
const qrRef= ref()
const multipleSelection = ref([])
const handleSelectionChange = (val) => {
multipleSelection.value = val
console.log(val)
}
const handleGenerateQrCode = () => {
// 批量生成二维码
try {
qrRef.value.open(multipleSelection)
} finally {
qrCodeLoading.value = false
}
}
二、一个二维码页面
<template>
<Dialog
v-model="dialogVisible"
:title="dialogTitle"
width="1000px"
height="1200px"
@close="handleCloseModal"
>
<e-row>
<el-button type="success" plain v-print="printObj">
<Icon icon="ep:search" />
预览打印
</el-button>
<el-button type="success" plain @click="handleDownloadClick" :loading="printLoding">
<Icon icon="ep:download" />
下载全部
</el-button>
</e-row>
<el-row class="row-con" id="printMe">
<!-- 1-->
<div
v-for="(item, index) in tableData"
:ref="setItemRef"
:key="item.equCode"
style="width: 50%"
>
<div style="border: dot-dash">
<div style="width: 100%; display: flex; flex-direction: row">
<div style="width: 40%">
<img
:src="imageData[index]"
alt="QR Code"
crossorigin="anonymous"
style="border-style: none; height: 200px; width: 200px; object-fit: cover"
/>
</div>
<div
style="
width: 60%;
display: flex;
flex-direction: column;
justify-content: center;
background-color: white;
"
>
<div class="textMargin">这里可以自定义:{{ item.equCode }}</div>
</div>
</div>
</div>
</div>
</el-row>
</Dialog>
</template>
<script setup lang="ts">
import JSZip from 'JSZip'
import FileSaver from 'file-saver'
import qrcode from 'qrcode'
import html2canvas from 'html2canvas'
const dialogVisible = ref(false)
const dialogTitle = ref('生成二维码')
const printLoding = ref(false)
const handleCloseModal = () => {
dialogVisible.value = false
}
const tableData = ref([])
const printObj = ref({
id: 'printMe',
popTitle: '',
extraCss:
'https://cdn.bootcdn.net/ajax/libs/animate.css/4.1.1/animate.compat.css, https://cdn.bootcdn.net/ajax/libs/hover.css/2.3.1/css/hover-min.css',
extraHead: '<meta http-equiv="Content-Language"content="zh-cn"/>',
beforeOpenCallback(vue) {
vue.printLoading = true
console.log('打开之前')
},
openCallback(vue) {
vue.printLoading = false
console.log('执行了打印', vue)
},
closeCallback(vue) {
console.log('关闭了打印工具', vue)
}
})
const itemRefs = ref([])
const setItemRef = (el) => {
if (el) {
itemRefs.value.push(el)
}
}
const handleCanvas = ref([]) as any
const imageData = ref([]) as any
const open = (data) => {
dialogVisible.value = true
console.log('data', data)
tableData.value = data.value
console.log('tableData', tableData.value)
imageData.value = []
tableData.value.forEach((item) => {
//var code = 'your-data' // 替换为你需要生成二维码的数据
qrcode.toDataURL(item.equCode, (err, url) => {
if (err) {
console.error(err)
} else {
console.log('toDataURL', url)
imageData.value.push(url)
}
})
})
}
defineExpose({ open }) // 提供 open 方法,用于打开弹窗
const handleDownloadClick = () => {
printLoding.value = true
handleCanvas.value = []
itemRefs.value.forEach((item, index) => {
html2canvas(itemRefs.value[index], {
backgroundColor: '#f5f5f9',
useCORS: true, // 解决文件跨域问题
scrollY: 0,
scrollX: 0
})
.then((canvas) => {
var dataURL = canvas.toDataURL('image/png')
console.log('tableData', index, tableData)
handleCanvas.value.push({
fileUrl: dataURL,
renameFileName: tableData.value[index]['equCode'] + '.png'
})
console.log('handleCanvas.value.', handleCanvas.value)
if (handleCanvas.value.length == tableData.value.length) {
filesToRar()
}
// t.handleCanvas.push({
// fileUrl: dataURL,
// renameFileName: '准考证' + index + '.png'
// })
//注意 文件名不可重复 如果重复zip包里只会有一张图片
// if(生成图片结束后的判断){
// this.filesToRar()
// }
})
.catch((err) => {
console.log(err)
})
.finally(() => {
printLoding.value = false
})
})
}
const filesToRar = () => {
console.log('filesToRar')
let zip = new JSZip()
let cache = {}
let promises = []
for (let item of handleCanvas.value) {
const promise = getImage(item.fileUrl).then((data) => {
// 下载文件, 并存成ArrayBuffer对象(blob)
zip.file(item.renameFileName, data, {
binary: true
}) // 逐个添加文件
// zip.file(item.renameFileName, data, {base64: true}); // 逐个添加文件
cache[item.renameFileName] = data
})
promises.push(promise)
}
console.log('Promise')
Promise.all(promises)
.then(() => {
zip
.generateAsync({
type: 'blob'
})
.then((content) => {
console.log('Promise.then')
const date = new Date()
// 生成二进制流
FileSaver.saveAs(content, date.toLocaleString('zh-CN', { timeZone: 'Asia/Shanghai' })) // 利用file-saver保存文件 自定义文件名
})
})
.catch((res) => {
console.log('Promisecatch', res)
// _this.$message.error('文件压缩失败')
})
}
获取文件blob
const getImage = (url) => {
return new Promise((resolve, reject) => {
//通过请求获取文件blob格式
let xmlhttp = new XMLHttpRequest()
xmlhttp.open('GET', url, true)
xmlhttp.responseType = 'blob'
xmlhttp.onload = function () {
if (this.status == 200) {
resolve(this.response)
} else {
reject(this.status)
}
}
xmlhttp.send()
})
}
</script>
<style scoped lang="scss">
.row-con {
display: flex;
flex-flow: row wrap;
}
.row-con .card {
height: 100%;
}
.textMargin {
//margin: 3% 2%;
margin-bottom: 3%;
font-size: 20px;
font-weight: bold;
color: black;
}
</style>