uniapp + uview-plus 微信小程序二维码生成和保存完整解决方案

发布于:2025-07-28 ⋅ 阅读:(21) ⋅ 点赞:(0)

uniapp + uview-plus 微信小程序二维码生成和保存完整解决方案

📋 项目背景

在开发微信小程序时,经常需要实现二维码的生成和保存功能。本文档提供了一个基于 uniapp + uview-plus 框架的完整解决方案,彻底解决了以下常见问题:

  • ✅ Canvas API 兼容性问题
  • ✅ 微信小程序权限处理
  • ✅ u-qrcode 组件保存方法不可用
  • ✅ 组件内部方法依赖问题
  • ✅ 时序问题和异步处理

🎯 核心设计思路

采用纯API方案,完全绕过Canvas操作

  1. 使用 u-qrcode 组件显示二维码
  2. 保存时通过第三方API重新生成相同内容的二维码
  3. 下载生成的图片并保存到相册

🔧 技术栈

  • 框架: 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/H
	correctLevel: {
     
     
		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 = result
	emit('generated', result)
}

// 保存二维码方法 - 完全不用Canvas的方案
const downloadQrcode = async () => {
     
     
	console.log('=== 纯API方式保存二维码 ===')
	
	try {
     
     
		// 第一步:获取当前二维码内容
		const qrText = qrcodeText.value
		if (!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-WEIXIN
		uni.getSetting({
     
     
			success: (

网站公告

今日签到

点亮在社区的每一天
去签到