二维码

This commit is contained in:
曹磊 2025-07-10 17:57:51 +08:00
parent e65263cffb
commit dd18a1a720
3 changed files with 178 additions and 157 deletions

View File

@ -1,14 +1,13 @@
<template> <template>
<div class="qrcode-container"> <main class="qrcode">
<div class="code" ref="code">
<!-- 直接绑定ref到QRCodeVue3组件 --> <!-- 直接绑定ref到QRCodeVue3组件 -->
<QRCodeVue3 ref="qrcodeInstance" render-as="canvas" :margin="margin" :width="width" :height="height" :value="value" <QRCodeVue3 render-as="canvas" :margin="margin" :width="width" :height="height" :value="value"
:qrOptions="qrOptions" :image="image" :imageOptions="imageOptions" :dotsOptions="dotsOptions" :qrOptions="qrOptions" :image="image" :imageOptions="imageOptions" :dotsOptions="dotsOptions"
:backgroundOptions="backgroundOptions" :cornersSquareOptions="cornersSquareOptions" :backgroundOptions="backgroundOptions" :cornersSquareOptions="cornersSquareOptions"
:cornersDotOptions="cornersDotOptions" :key="key" /> :cornersDotOptions="cornersDotOptions" :download="download" :buttonName="buttonName" :key="key" />
<button @click="downloadQRCode" :disabled="isDownloading" class="download-btn"> </div>
{{ isDownloading ? '生成中...' : '下载二维码' }} </main>
</button>
</div>
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
@ -16,11 +15,6 @@ import { ref, reactive, toRefs, nextTick } from 'vue'
import QRCodeVue3 from 'qrcode-vue3' import QRCodeVue3 from 'qrcode-vue3'
import type { PropType } from 'vue' import type { PropType } from 'vue'
//
interface QRCodeExpose {
$el: HTMLCanvasElement
}
const props = defineProps({ const props = defineProps({
key: { key: {
type: String as PropType<string>, type: String as PropType<string>,
@ -130,12 +124,17 @@ const props = defineProps({
] ]
} }
}) })
} },
download: {
type: Boolean as PropType<boolean>,
default: false,
},
buttonName: {
type: String as PropType<string>,
default: "下载二维码",
},
}) })
const qrcodeInstance = ref<QRCodeExpose | null>(null)
const isDownloading = ref(false)
const data = reactive({ const data = reactive({
key: props.key, key: props.key,
width: props.width, width: props.width,
@ -160,6 +159,8 @@ const data = reactive({
dotsOptions: props.dotsOptions, dotsOptions: props.dotsOptions,
cornersSquareOptions: props.cornersSquareOptions, cornersSquareOptions: props.cornersSquareOptions,
cornersDotOptions: props.cornersDotOptions, cornersDotOptions: props.cornersDotOptions,
download: props.download,
buttonName: props.buttonName,
}) })
const { const {
@ -174,60 +175,21 @@ const {
imageOptions, imageOptions,
dotsOptions, dotsOptions,
cornersSquareOptions, cornersSquareOptions,
cornersDotOptions cornersDotOptions,
download,
buttonName
} = toRefs(data) } = toRefs(data)
const downloadQRCode = async () => {
isDownloading.value = true
await nextTick() // DOM
// img
const imgEl = qrcodeInstance.value?.$el?.querySelector?.('img')
if (imgEl && imgEl.src) {
const imgSrc = imgEl.src
const link = document.createElement('a')
link.href = imgSrc
link.download = 'qrcode.png'
link.click()
} else {
console.error('未找到二维码 img 或 src 为空')
}
isDownloading.value = false
}
</script> </script>
<style scoped> <style lang="less">
.qrcode-container { .qrcode {
display: flex; .code {
flex-direction: column; padding: 8px;
align-items: center; width: 360px;
gap: 16px; height: 360px;
} border-radius: 6px;
border: 1px solid gray;
.download-btn { }
padding: 8px 16px;
background-color: #42b983;
color: white;
border: none;
border-radius: 4px;
cursor: pointer;
transition: all 0.3s ease;
font-size: 14px;
min-width: 120px;
}
.download-btn:hover {
background-color: #3aa876;
transform: translateY(-1px);
}
.download-btn:disabled {
background-color: #cccccc;
cursor: not-allowed;
transform: none;
} }
</style> </style>

View File

@ -0,0 +1,86 @@
<template>
<QRCodeVue3
ref="qrcodeInstance"
margin="5"
width="400"
height="400"
:key="qrCodeKey"
:value="data.value"
:logo="data.logoImage"
download="true"
/>
<button @click="downloadQRCode" :disabled="isDownloading" class="download-btn">
{{ isDownloading ? '生成中...' : '下载二维码' }}
</button>
</template>
<script lang="ts" name="qrcode" setup>
import {computed, nextTick, reactive, ref} from "vue";
import { QRCodeVue3 } from '/@/components/QrcodeVue3';
import image from "@/assets/images/logo.png";
//
interface QRCodeExpose {
$el: HTMLCanvasElement
}
const data = reactive({
value: 'www.baidu.com',
logoImage: image,
})
const qrCodeKey = computed(()=>data.value.length + data.logoImage.length);
const qrcodeInstance = ref<QRCodeExpose | null>(null)
const isDownloading = ref(false)
const downloadQRCode = async () => {
isDownloading.value = true
await nextTick() // DOM
// img
const imgEl = qrcodeInstance.value?.$el?.querySelector?.('img')
if (imgEl && imgEl.src) {
const imgSrc = imgEl.src
const link = document.createElement('a')
link.href = imgSrc
link.download = 'qrcode.png'
link.click()
} else {
console.error('未找到二维码 img 或 src 为空')
}
isDownloading.value = false
}
</script>
<style lang="less">
.download-btn {
margin-top:20px;
padding: 8px 16px;
background-color: #42b983;
color: white;
border: none;
border-radius: 4px;
cursor: pointer;
transition: all 0.3s ease;
font-size: 14px;
min-width: 120px;
}
.download-btn:hover {
background-color: #3aa876;
transform: translateY(-1px);
}
.download-btn:disabled {
background-color: #cccccc;
cursor: not-allowed;
transform: none;
}
</style>

View File

@ -1,113 +1,86 @@
<template> <template>
<main class="qrcode"> <QRCodeVue3
<div class="form"> ref="qrcodeInstance"
<input margin="5"
type="text" width="400"
v-model="data.value" height="400"
placeholder="请在这里输入要生成的内容!" :key="qrCodeKey"
@change="changeValue" :value="data.value"
/> :logo="data.logoImage"
<JImageUpload download="true"
text="上传LOGO" />
ref="uploadRef" <button @click="downloadQRCode" :disabled="isDownloading" class="download-btn">
v-model:value="data.logoImage" {{ isDownloading ? '生成中...' : '下载二维码' }}
@change="upFile" </button>
/>
</div>
<div class="code" ref="code">
<QRCodeVue3
margin="5"
width="400"
height="400"
:key="qrCodeKey"
:value="data.value"
:logo="data.logoImage"
/>
</div>
</main>
</template> </template>
<script lang="ts" name="qrcode" setup> <script lang="ts" name="qrcode" setup>
import {computed, nextTick, reactive, ref} from "vue"; import {computed, nextTick, reactive, ref} from "vue";
import { QRCodeVue3 } from '/@/components/QrcodeVue3'; import { QRCodeVue3 } from '/@/components/QrcodeVue3';
import { JImageUpload } from '/@/components/Form/index';
import image from "@/assets/images/logo.png"; import image from "@/assets/images/logo.png";
const uploadUrl = ref(''); //
interface QRCodeExpose {
$el: HTMLCanvasElement
}
const data = reactive({ const data = reactive({
value: 'www.baidu.com', value: 'www.baidu.com',
logoImage: image, logoImage: image,
}) })
// const qrCodeKey = ref(0);
const qrCodeKey = computed(()=>data.value.length + data.logoImage.length); const qrCodeKey = computed(()=>data.value.length + data.logoImage.length);
// console.log(qrCodeKey.value);
function upFile(){ const qrcodeInstance = ref<QRCodeExpose | null>(null)
// console.log(data.logoImage); const isDownloading = ref(false)
// qrCodeKey.value = qrCodeKey.value + 1;
// console.log(qrCodeKey.value);
}
function changeValue(){ const downloadQRCode = async () => {
// qrCodeKey.value = qrCodeKey.value + 1; isDownloading.value = true
await nextTick() // DOM
// img
const imgEl = qrcodeInstance.value?.$el?.querySelector?.('img')
if (imgEl && imgEl.src) {
const imgSrc = imgEl.src
const link = document.createElement('a')
link.href = imgSrc
link.download = 'qrcode.png'
link.click()
} else {
console.error('未找到二维码 img 或 src 为空')
}
isDownloading.value = false
} }
</script> </script>
<style lang="less"> <style lang="less">
.qrcode {
.form {
margin: 30px auto;
width: 86%;
input { .download-btn {
box-sizing: border-box; margin-top:20px;
padding: 0 10px; padding: 8px 16px;
width: 80%; background-color: #42b983;
height: 50px; color: white;
font-size: 18px; border: none;
border: 1px solid #767676; border-radius: 4px;
border-radius: 6px 0 0 6px; cursor: pointer;
} transition: all 0.3s ease;
font-size: 14px;
button { min-width: 120px;
box-sizing: border-box;
position: relative;
width: 20%;
height: 50px;
font-size: 18px;
vertical-align: top;
color: white;
background: #42b983;
border: 1px solid #767676;
border-radius: 0 6px 6px 0;
border-left: none;
overflow: hidden;
cursor: pointer;
input {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
cursor: pointer;
opacity: 0;
}
}
}
.code {
margin: auto;
padding: 8px;
width: 360px;
height: 360px;
border-radius: 6px;
border: 1px solid gray;
}
} }
.download-btn:hover {
background-color: #3aa876;
transform: translateY(-1px);
}
.download-btn:disabled {
background-color: #cccccc;
cursor: not-allowed;
transform: none;
}
</style> </style>