index.vue 2.9 KB

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