vben
2021-08-24 56a966cfbf8db5b29a42185f0f25a0e800c30dbb
提交 | 用户 | age
2f6253 1 <template>
2   <div>
9edc28 3     <component :is="tag" ref="wrapRef" />
2f6253 4   </div>
5 </template>
6 <script lang="ts">
26f251 7   import { defineComponent, watch, PropType, ref, unref, onMounted } from 'vue';
2f6253 8   import { toCanvas, QRCodeRenderersOptions, LogoType } from './qrcodePlus';
9   import { toDataURL } from 'qrcode';
661db0 10   import { downloadByUrl } from '/@/utils/file/download';
1c1755 11   import { QrcodeDoneEventParams } from './typing';
2f6253 12
13   export default defineComponent({
14     name: 'QrCode',
15     props: {
16       value: {
17         type: [String, Array] as PropType<string | any[]>,
18         default: null,
19       },
20       // 参数
21       options: {
22         type: Object as PropType<QRCodeRenderersOptions>,
23         default: null,
24       },
25       // 宽度
26       width: {
27         type: Number as PropType<number>,
28         default: 200,
29       },
30       // 中间logo图标
31       logo: {
32         type: [String, Object] as PropType<Partial<LogoType> | string>,
33         default: '',
34       },
35       // img 不支持内嵌logo
36       tag: {
37         type: String as PropType<'canvas' | 'img'>,
38         default: 'canvas',
39         validator: (v: string) => ['canvas', 'img'].includes(v),
40       },
41     },
2b76b8 42     emits: { done: (data: QrcodeDoneEventParams) => !!data, error: (error: any) => !!error },
2f6253 43     setup(props, { emit }) {
44       const wrapRef = ref<HTMLCanvasElement | HTMLImageElement | null>(null);
45       async function createQrcode() {
46         try {
47           const { tag, value, options = {}, width, logo } = props;
48           const renderValue = String(value);
49           const wrapEl = unref(wrapRef);
50
51           if (!wrapEl) return;
52
53           if (tag === 'canvas') {
54             const url: string = await toCanvas({
55               canvas: wrapEl,
56               width,
57               logo: logo as any,
58               content: renderValue,
59               options: options || {},
60             });
2b76b8 61             emit('done', { url, ctx: (wrapEl as HTMLCanvasElement).getContext('2d') });
2f6253 62             return;
63           }
64
65           if (tag === 'img') {
66             const url = await toDataURL(renderValue, {
67               errorCorrectionLevel: 'H',
68               width,
69               ...options,
70             });
71             (unref(wrapRef) as HTMLImageElement).src = url;
2b76b8 72             emit('done', { url });
2f6253 73           }
74         } catch (error) {
75           emit('error', error);
76         }
77       }
78       /**
79        * file download
80        */
81       function download(fileName?: string) {
2b76b8 82         let url = '';
N 83         const wrapEl = unref(wrapRef);
84         if (wrapEl instanceof HTMLCanvasElement) {
85           url = wrapEl.toDataURL();
86         } else if (wrapEl instanceof HTMLImageElement) {
87           url = wrapEl.src;
88         }
2f6253 89         if (!url) return;
90         downloadByUrl({
91           url,
92           fileName,
93         });
94       }
95
26f251 96       onMounted(createQrcode);
97
fe4eae 98       // 监听参数变化重新生成二维码
99       watch(
100         props,
101         () => {
26f251 102           createQrcode();
fe4eae 103         },
104         {
105           deep: true,
56a966 106         },
26f251 107       );
2f6253 108
109       return { wrapRef, download };
110     },
111   });
112 </script>