106 lines
3.0 KiB
Plaintext
106 lines
3.0 KiB
Plaintext
<template>
|
|
<div>
|
|
<component :is="tag" ref="wrapRef" />
|
|
</div>
|
|
</template>
|
|
<script lang="ts">
|
|
import { defineComponent, watch, PropType, ref, unref, onMounted } from 'vue';
|
|
import { toCanvas, QRCodeRenderersOptions, LogoType } from './qrcodePlus';
|
|
import { toDataURL } from 'qrcode';
|
|
import { downloadByUrl } from '@/utils/file/download';
|
|
import { QrcodeDoneEventParams } from './typing';
|
|
export default defineComponent({
|
|
name: 'QrCode',
|
|
props: {
|
|
value: {
|
|
type: [String, Array] as PropType<string | any[]>,
|
|
default: null,
|
|
},
|
|
// 参数
|
|
options: {
|
|
type: Object as PropType<QRCodeRenderersOptions>,
|
|
default: null,
|
|
},
|
|
// 宽度
|
|
width: {
|
|
type: Number as PropType<number>,
|
|
default: 200,
|
|
},
|
|
// 中间logo图标
|
|
logo: {
|
|
type: [String, Object] as PropType<Partial<LogoType> | string>,
|
|
default: '',
|
|
},
|
|
// img 不支持内嵌logo
|
|
tag: {
|
|
type: String as PropType<'canvas' | 'img'>,
|
|
default: 'canvas',
|
|
validator: (v: string) => ['canvas', 'img'].includes(v),
|
|
},
|
|
},
|
|
emits: { done: (data: QrcodeDoneEventParams) => !!data, error: (error: any) => !!error },
|
|
setup(props, { emit }) {
|
|
const wrapRef = ref<HTMLCanvasElement | HTMLImageElement | null>(null);
|
|
async function createQrcode() {
|
|
try {
|
|
const { tag, value, options = {}, width, logo } = props;
|
|
const renderValue = String(value);
|
|
const wrapEl = unref(wrapRef);
|
|
if (!wrapEl) return;
|
|
if (tag === 'canvas') {
|
|
const url: string = await toCanvas({
|
|
canvas: wrapEl,
|
|
width,
|
|
logo: logo as any,
|
|
content: renderValue,
|
|
options: options || {},
|
|
});
|
|
emit('done', { url, ctx: (wrapEl as HTMLCanvasElement).getContext('2d') });
|
|
return;
|
|
}
|
|
if (tag === 'img') {
|
|
const url = await toDataURL(renderValue, {
|
|
errorCorrectionLevel: 'H',
|
|
width,
|
|
...options,
|
|
});
|
|
(unref(wrapRef) as HTMLImageElement).src = url;
|
|
emit('done', { url });
|
|
}
|
|
} catch (error) {
|
|
emit('error', error);
|
|
}
|
|
}
|
|
/**
|
|
* file download
|
|
*/
|
|
function download(fileName?: string) {
|
|
let url = '';
|
|
const wrapEl = unref(wrapRef);
|
|
if (wrapEl instanceof HTMLCanvasElement) {
|
|
url = wrapEl.toDataURL();
|
|
} else if (wrapEl instanceof HTMLImageElement) {
|
|
url = wrapEl.src;
|
|
}
|
|
if (!url) return;
|
|
downloadByUrl({
|
|
url,
|
|
fileName,
|
|
});
|
|
}
|
|
onMounted(createQrcode);
|
|
// 监听参数变化重新生成二维码
|
|
watch(
|
|
props,
|
|
() => {
|
|
createQrcode();
|
|
},
|
|
{
|
|
deep: true,
|
|
},
|
|
);
|
|
return { wrapRef, download };
|
|
},
|
|
});
|
|
</script>
|