196 lines
4.6 KiB
Vue
196 lines
4.6 KiB
Vue
<template>
|
|
<BasePage>
|
|
<div class="paycode-page">
|
|
<div class="paycode-wrap">
|
|
<!-- 生成后的图片 -->
|
|
<div v-if="generatedImage" class="paycode-generated">
|
|
<img :src="generatedImage" alt="收款码">
|
|
</div>
|
|
<!-- 原始元素 -->
|
|
<div v-else class="paycode-original" ref="paycodeOriginalRef">
|
|
<img src="/img/paycode.jpg" alt="" style="width: 100%; display: block;" class="bg-img" @load="onBgLoad">
|
|
<div class="user-info">
|
|
<div class="info">
|
|
<img :src="$file(shopimg)" alt="" style="border-radius: 50%;">
|
|
</div>
|
|
<div class="name">
|
|
<span>{{ shopname?.length > 8 ? shopname.slice(0, 8) + '...' : shopname }}</span>
|
|
</div>
|
|
</div>
|
|
<div class="code">
|
|
<vue-qr v-if="link" :margin="0" :text="link" backgroundColor="rgb(255,255,255)"
|
|
colorLight="rgb(255,255,255)"></vue-qr>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="save-btn">
|
|
<van-button type="primary" color="#ca2904" round block :loading="loading" @click="handleSave">{{ loading ?
|
|
'生成中...' : ('保存图片')
|
|
}}</van-button>
|
|
</div>
|
|
</div>
|
|
</BasePage>
|
|
</template>
|
|
|
|
<script>
|
|
import { toDataURL } from '@/utils/html2image'
|
|
|
|
export default {
|
|
name: 'PayCode',
|
|
data() {
|
|
return {
|
|
shopname: '',
|
|
shopimg: '',
|
|
link: '',
|
|
loading: false,
|
|
generatedImage: '',
|
|
bgLoaded: false,
|
|
}
|
|
},
|
|
mounted() {
|
|
this.init()
|
|
},
|
|
methods: {
|
|
init() {
|
|
const id = this.$route.query.id
|
|
this.$get(`/v1/client/DShopsClient/${id}`).then(res => {
|
|
this.shopname = res.data.shopname
|
|
this.shopimg = res.data.shopimg
|
|
this.link = `${location.origin}${location.pathname}#/Checkout?id=${res.data.userid}`
|
|
}).catch(err => {
|
|
this.$showFailToast('加载失败')
|
|
})
|
|
},
|
|
|
|
onBgLoad() {
|
|
this.bgLoaded = true
|
|
// 背景图加载完成后自动生成图片
|
|
this.generateImage()
|
|
},
|
|
|
|
async generateImage() {
|
|
if (!this.bgLoaded || this.loading) return
|
|
this.loading = true
|
|
try {
|
|
await this.$nextTick()
|
|
await document.fonts.ready
|
|
await new Promise(resolve => setTimeout(resolve, 300))
|
|
const el = this.$refs.paycodeOriginalRef
|
|
this.generatedImage = await toDataURL(el, { format: 'png', pixelRatio: 3, useCORS: true })
|
|
} catch (e) {
|
|
this.$showFailToast('生成失败')
|
|
} finally {
|
|
this.loading = false
|
|
}
|
|
},
|
|
|
|
async handleSave() {
|
|
if (this.loading) return
|
|
// 如果已生成图片,直接下载
|
|
if (this.generatedImage) {
|
|
this.downloadByBlob(this.generatedImage, `收款码_${this.shopname}.png`)
|
|
this.$showSuccessToast('保存成功')
|
|
return
|
|
}
|
|
// 否则生成图片
|
|
await this.generateImage()
|
|
if (this.generatedImage) {
|
|
this.downloadByBlob(this.generatedImage, `收款码_${this.shopname}.png`)
|
|
this.$showSuccessToast('保存成功')
|
|
}
|
|
},
|
|
|
|
downloadByBlob(dataUrl, filename) {
|
|
const arr = dataUrl.split(',')
|
|
const mime = arr[0].match(/:(.*?);/)[1]
|
|
const bstr = atob(arr[1])
|
|
let n = bstr.length
|
|
const u8arr = new Uint8Array(n)
|
|
while (n--) {
|
|
u8arr[n] = bstr.charCodeAt(n)
|
|
}
|
|
const blob = new Blob([u8arr], { type: mime })
|
|
const url = URL.createObjectURL(blob)
|
|
const link = document.createElement('a')
|
|
link.download = filename
|
|
link.href = url
|
|
document.body.appendChild(link)
|
|
link.click()
|
|
document.body.removeChild(link)
|
|
URL.revokeObjectURL(url)
|
|
},
|
|
},
|
|
}
|
|
</script>
|
|
|
|
<style lang="less" scoped>
|
|
.paycode-page {
|
|
// min-height: 100vh;
|
|
background: #f5f5f5;
|
|
padding-bottom: 20px;
|
|
}
|
|
|
|
.paycode-generated {
|
|
img {
|
|
width: 100%;
|
|
display: block;
|
|
}
|
|
}
|
|
|
|
.paycode-original {
|
|
position: relative;
|
|
width: 100%;
|
|
font-family: 'PingFang SC';
|
|
|
|
>img {
|
|
width: 100%;
|
|
display: block;
|
|
}
|
|
|
|
.user-info {
|
|
position: absolute;
|
|
left: 50%;
|
|
transform: translateX(-50%);
|
|
top: 32.27vw;
|
|
display: flex;
|
|
align-items: center;
|
|
}
|
|
|
|
.info {
|
|
display: flex;
|
|
align-items: center;
|
|
|
|
img {
|
|
width: 6.4vw;
|
|
height: 6.4vw;
|
|
border-radius: 50%;
|
|
}
|
|
}
|
|
|
|
.name {
|
|
margin-left: 2.67vw;
|
|
// margin-bottom: 2.4vw;
|
|
|
|
span {
|
|
font-size: 4vw;
|
|
color: #333;
|
|
}
|
|
}
|
|
|
|
.code {
|
|
position: absolute;
|
|
top: 42.4vw;
|
|
left: 23.33vw;
|
|
|
|
canvas,
|
|
img {
|
|
width: 53.33vw;
|
|
height: 53.33vw;
|
|
}
|
|
}
|
|
}
|
|
|
|
.save-btn {
|
|
margin: 20px;
|
|
}
|
|
</style> |