uniapp + uview-plus 微信小程序二維碼生成和保存完整解決方案
?? 項目背景
在開發微信小程序時,經常需要實現二維碼的生成和保存功能。本文檔提供了一個基于 uniapp + uview-plus 框架的完整解決方案,徹底解決了以下常見問題:
- ? Canvas API 兼容性問題
- ? 微信小程序權限處理
- ? u-qrcode 組件保存方法不可用
- ? 組件內部方法依賴問題
- ? 時序問題和異步處理
?? 核心設計思路
采用純API方案,完全繞過Canvas操作:
- 使用 u-qrcode 組件顯示二維碼
- 保存時通過第三方API重新生成相同內容的二維碼
- 下載生成的圖片并保存到相冊
?? 技術棧
- 框架: uniapp
- UI庫: uview-plus v3.4.54
- 目標平臺: 微信小程序
- Vue版本: Vue 3 + Composition API
?? 完整代碼實現
1. QrcodeGenerator.vue 組件
<template><view class="qrcode-generator"><view class="qrcode-container"><u-qrcode ref="qrcodeRef":val="qrcodeText" :size="qrcodeSize":background="backgroundColor":foreground="foregroundColor":loadMake="loadMake"@click="onQrcodeClick"@result="onQrcodeResult"></u-qrcode></view></view>
</template><script setup>
import { ref, computed, watch, onMounted, nextTick } from 'vue'// 定義 props
const props = defineProps({// 二維碼內容(必傳)text: {type: String,required: true,default: ''},// 二維碼尺寸size: {type: Number,default: 200},// 二維碼邊距margin: {type: Number,default: 0},// 背景顏色backgroundColor: {type: String,default: '#ffffff'},// 前景顏色foregroundColor: {type: String,default: '#000000'},// 容錯級別 L/M/Q/HcorrectLevel: {type: String,default: 'M'},// 是否立即生成loadMake: {type: Boolean,default: true}
})// 定義 emits
const emit = defineEmits(['click', 'save', 'generated'])// 響應式數據
const qrcodeRef = ref(null)
const qrcodeResult = ref('') // 保存二維碼生成結果
const qrcodeTempFilePath = ref('') // 保存二維碼臨時文件路徑// 計算屬性
const qrcodeText = computed(() => props.text || 'https://example.com')
const qrcodeSize = computed(() => props.size)// 監聽文本變化,重新生成二維碼
watch(() => props.text, (newText, oldText) => {console.log('QrcodeGenerator文本變化:', { oldText, newText })if (newText && newText !== oldText && qrcodeRef.value) {console.log('觸發u-qrcode重新生成二維碼')// 使用nextTick確保DOM更新后再生成nextTick(() => {if (qrcodeRef.value && qrcodeRef.value._makeCode) {qrcodeRef.value._makeCode()}})}
}, { immediate: true })// 二維碼點擊事件
const onQrcodeClick = () => {emit('click', {text: qrcodeText.value,size: qrcodeSize.value})
}// 二維碼生成完成回調
const onQrcodeResult = (result) => {console.log('二維碼生成完成:', result)qrcodeResult.value = result// 保存臨時文件路徑,這是u-qrcode組件生成的可用于保存的路徑qrcodeTempFilePath.value = resultemit('generated', result)
}// 保存二維碼方法 - 完全不用Canvas的方案
const downloadQrcode = async () => {console.log('=== 純API方式保存二維碼 ===')try {// 第一步:獲取當前二維碼內容const qrText = qrcodeText.valueif (!qrText || qrText === 'https://example.com') {throw new Error('二維碼內容無效')}console.log('二維碼內容:', qrText)// 第二步:檢查相冊權限await checkAlbumPermission()// 第三步:使用第三方API生成二維碼圖片const tempFilePath = await generateQrcodeByAPI(qrText)// 第四步:保存到相冊await saveToAlbum(tempFilePath)// 第五步:顯示成功提示uni.showToast({title: '保存成功',icon: 'success',duration: 2000})} catch (error) {console.error('保存失敗:', error)uni.showToast({title: error.message || '保存失敗',icon: 'none',duration: 3000})}
}// 檢查相冊權限
const checkAlbumPermission = () => {return new Promise((resolve, reject) => {// #ifdef MP-WEIXINuni.getSetting({success: (