|
@@ -418,6 +418,9 @@
|
|
|
</view>
|
|
</view>
|
|
|
</uni-popup>
|
|
</uni-popup>
|
|
|
|
|
|
|
|
|
|
+ <!-- 用于生成带支付宝背景和文字的结账二维码 -->
|
|
|
|
|
+ <canvas canvas-id="shareCanvas" style="width: 360px; height: 490px; position: fixed; left: -9999px; top: -9999px; z-index: -1;"></canvas>
|
|
|
|
|
+
|
|
|
</view>
|
|
</view>
|
|
|
</template>
|
|
</template>
|
|
|
<script>
|
|
<script>
|
|
@@ -560,29 +563,150 @@ export default {
|
|
|
if (isNaN(n)) return 0
|
|
if (isNaN(n)) return 0
|
|
|
return parseFloat(n.toFixed(2))
|
|
return parseFloat(n.toFixed(2))
|
|
|
},
|
|
},
|
|
|
|
|
+ /**
|
|
|
|
|
+ * @description 获取并下载支付宝收款码海报
|
|
|
|
|
+ * 职责:从后端 API 获取付款二维码,下载图片后,通过 Canvas 绘制成带支付宝蓝色背景和“支付宝扫一扫”文字的精美海报并保存到相册。
|
|
|
|
|
+ * 副作用:会调用系统下载文件和保存相册 API,并显示 Loading 状态。
|
|
|
|
|
+ */
|
|
|
downloadCode(){
|
|
downloadCode(){
|
|
|
let that = this
|
|
let that = this
|
|
|
|
|
+ uni.showLoading({
|
|
|
|
|
+ title: '正在生成收款码...',
|
|
|
|
|
+ mask: true
|
|
|
|
|
+ })
|
|
|
getGatheringCode({id:this.option.id}).then(res=>{
|
|
getGatheringCode({id:this.option.id}).then(res=>{
|
|
|
if(res.code == 1){
|
|
if(res.code == 1){
|
|
|
let url = res.data.imgUrl ? res.data.imgUrl: ''
|
|
let url = res.data.imgUrl ? res.data.imgUrl: ''
|
|
|
- that.downloadImg(url)
|
|
|
|
|
|
|
+ if (!url) {
|
|
|
|
|
+ uni.hideLoading()
|
|
|
|
|
+ uni.showToast({ title: '未获取到二维码链接', icon: 'none' })
|
|
|
|
|
+ return
|
|
|
|
|
+ }
|
|
|
|
|
+ // 下载二维码图片到本地临时路径,以便 Canvas 能够进行绘制
|
|
|
|
|
+ uni.downloadFile({
|
|
|
|
|
+ url: url,
|
|
|
|
|
+ success: (downloadRes) => {
|
|
|
|
|
+ if (downloadRes.statusCode === 200) {
|
|
|
|
|
+ // 下载成功后,开始绘制支付宝收款码海报
|
|
|
|
|
+ that.drawAlipayPoster(downloadRes.tempFilePath)
|
|
|
|
|
+ } else {
|
|
|
|
|
+ uni.hideLoading()
|
|
|
|
|
+ uni.showToast({ title: '下载二维码失败', icon: 'none' })
|
|
|
|
|
+ }
|
|
|
|
|
+ },
|
|
|
|
|
+ fail: (err) => {
|
|
|
|
|
+ uni.hideLoading()
|
|
|
|
|
+ uni.showToast({ title: '下载二维码失败', icon: 'none' })
|
|
|
|
|
+ }
|
|
|
|
|
+ })
|
|
|
|
|
+ } else {
|
|
|
|
|
+ uni.hideLoading()
|
|
|
}
|
|
}
|
|
|
|
|
+ }).catch(err => {
|
|
|
|
|
+ uni.hideLoading()
|
|
|
})
|
|
})
|
|
|
},
|
|
},
|
|
|
- downloadImg(url){
|
|
|
|
|
- uni.downloadFile({
|
|
|
|
|
- url: url,
|
|
|
|
|
- success: (res) => {
|
|
|
|
|
- if (res.statusCode === 200) {
|
|
|
|
|
- uni.saveImageToPhotosAlbum({
|
|
|
|
|
- filePath: res.tempFilePath,
|
|
|
|
|
- success: function (data) {
|
|
|
|
|
- uni.showToast({title:'保存成功'})
|
|
|
|
|
- }
|
|
|
|
|
- });
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
- });
|
|
|
|
|
|
|
+ /**
|
|
|
|
|
+ * @description 使用 Canvas 绘制支付宝收款码海报并保存到相册
|
|
|
|
|
+ * @param {String} qrPath 二维码本地临时路径
|
|
|
|
|
+ * 职责:通过 Canvas 绘制支付宝蓝色背景(带圆角剪裁)、白色圆角卡片、二维码图片、以及“推荐使用支付宝”、“支付宝扫一扫”等文字,最后导出并保存到用户相册。
|
|
|
|
|
+ */
|
|
|
|
|
+ drawAlipayPoster(qrPath) {
|
|
|
|
|
+ const that = this
|
|
|
|
|
+ const ctx = uni.createCanvasContext('shareCanvas', this)
|
|
|
|
|
+
|
|
|
|
|
+ const width = 360
|
|
|
|
|
+ const height = 490
|
|
|
|
|
+ const posterRadius = 24 // 整个海报的圆角大小
|
|
|
|
|
+
|
|
|
|
|
+ // 1. 绘制整个海报的圆角裁剪区域
|
|
|
|
|
+ ctx.save()
|
|
|
|
|
+ ctx.beginPath()
|
|
|
|
|
+ ctx.moveTo(posterRadius, 0)
|
|
|
|
|
+ ctx.lineTo(width - posterRadius, 0)
|
|
|
|
|
+ ctx.arcTo(width, 0, width, posterRadius, posterRadius)
|
|
|
|
|
+ ctx.lineTo(width, height - posterRadius)
|
|
|
|
|
+ ctx.arcTo(width, height, width - posterRadius, height, posterRadius)
|
|
|
|
|
+ ctx.lineTo(posterRadius, height)
|
|
|
|
|
+ ctx.arcTo(0, height, 0, height - posterRadius, posterRadius)
|
|
|
|
|
+ ctx.lineTo(0, posterRadius)
|
|
|
|
|
+ ctx.arcTo(0, 0, posterRadius, 0, posterRadius)
|
|
|
|
|
+ ctx.closePath()
|
|
|
|
|
+ ctx.clip() // 剪裁画布,使后续绘制的所有内容都限制在圆角矩形内
|
|
|
|
|
+
|
|
|
|
|
+ // 2. 绘制背景 (支付宝经典蓝 #3385FF)
|
|
|
|
|
+ ctx.setFillStyle('#3385FF')
|
|
|
|
|
+ ctx.fillRect(0, 0, width, height)
|
|
|
|
|
+
|
|
|
|
|
+ // 3. 绘制顶部标题 "推荐使用支付宝"
|
|
|
|
|
+ ctx.setFontSize(24)
|
|
|
|
|
+ ctx.setFillStyle('#ffffff')
|
|
|
|
|
+ ctx.setTextAlign('center')
|
|
|
|
|
+ ctx.fillText('推荐使用支付宝', 180, 55)
|
|
|
|
|
+
|
|
|
|
|
+ // 4. 绘制白色圆角卡片,作为二维码的容器
|
|
|
|
|
+ const cardX = 24
|
|
|
|
|
+ const cardY = 85
|
|
|
|
|
+ const cardW = 312
|
|
|
|
|
+ const cardH = 380
|
|
|
|
|
+ const radius = 16
|
|
|
|
|
+
|
|
|
|
|
+ ctx.beginPath()
|
|
|
|
|
+ ctx.moveTo(cardX + radius, cardY)
|
|
|
|
|
+ ctx.lineTo(cardX + cardW - radius, cardY)
|
|
|
|
|
+ ctx.arcTo(cardX + cardW, cardY, cardX + cardW, cardY + radius, radius)
|
|
|
|
|
+ ctx.lineTo(cardX + cardW, cardY + cardH - radius)
|
|
|
|
|
+ ctx.arcTo(cardX + cardW, cardY + cardH, cardX + cardW - radius, cardY + cardH, radius)
|
|
|
|
|
+ ctx.lineTo(cardX + radius, cardY + cardH)
|
|
|
|
|
+ ctx.arcTo(cardX, cardY + cardH, cardX, cardY + cardH - radius, radius)
|
|
|
|
|
+ ctx.lineTo(cardX, cardY + radius)
|
|
|
|
|
+ ctx.arcTo(cardX, cardY, cardX + radius, cardY, radius)
|
|
|
|
|
+ ctx.closePath()
|
|
|
|
|
+ ctx.setFillStyle('#ffffff')
|
|
|
|
|
+ ctx.fill()
|
|
|
|
|
+
|
|
|
|
|
+ // 5. 绘制二维码图片
|
|
|
|
|
+ const qrSize = 240
|
|
|
|
|
+ const qrX = 180 - qrSize / 2 // 居中计算:180 - 120 = 60
|
|
|
|
|
+ const qrY = 120
|
|
|
|
|
+ ctx.drawImage(qrPath, qrX, qrY, qrSize, qrSize)
|
|
|
|
|
+
|
|
|
|
|
+ // 6. 绘制卡片内底部文字 "扫一扫,向商家付款"
|
|
|
|
|
+ ctx.setFontSize(20)
|
|
|
|
|
+ ctx.setFillStyle('#3385FF') // 使用支付宝蓝色字体,使其更醒目
|
|
|
|
|
+ ctx.setTextAlign('center')
|
|
|
|
|
+ ctx.fillText('扫一扫,向商家付款', 180, 415)
|
|
|
|
|
+
|
|
|
|
|
+ ctx.restore() // 恢复画布状态
|
|
|
|
|
+
|
|
|
|
|
+ // 8. 渲染并导出保存
|
|
|
|
|
+ ctx.draw(false, () => {
|
|
|
|
|
+ // 延迟 300ms 确保 Canvas 渲染引擎已完全绘制,防止部分平台导出空白图片
|
|
|
|
|
+ setTimeout(() => {
|
|
|
|
|
+ uni.canvasToTempFilePath({
|
|
|
|
|
+ canvasId: 'shareCanvas',
|
|
|
|
|
+ fileType: 'jpg',
|
|
|
|
|
+ quality: 1,
|
|
|
|
|
+ success: (res) => {
|
|
|
|
|
+ uni.hideLoading()
|
|
|
|
|
+ // 保存图片到系统相册
|
|
|
|
|
+ uni.saveImageToPhotosAlbum({
|
|
|
|
|
+ filePath: res.tempFilePath,
|
|
|
|
|
+ success: () => {
|
|
|
|
|
+ uni.showToast({ title: '保存成功', icon: 'success' })
|
|
|
|
|
+ },
|
|
|
|
|
+ fail: (err) => {
|
|
|
|
|
+ uni.showToast({ title: '保存失败,请检查相册权限', icon: 'none' })
|
|
|
|
|
+ }
|
|
|
|
|
+ })
|
|
|
|
|
+ },
|
|
|
|
|
+ fail: (err) => {
|
|
|
|
|
+ uni.hideLoading()
|
|
|
|
|
+ uni.showToast({ title: '生成图片失败', icon: 'none' })
|
|
|
|
|
+ }
|
|
|
|
|
+ }, that)
|
|
|
|
|
+ }, 300)
|
|
|
|
|
+ })
|
|
|
},
|
|
},
|
|
|
inviteToPay(){
|
|
inviteToPay(){
|
|
|
let that = this
|
|
let that = this
|