微信小程序二维码展示组件

2023-03-20  本文已影响0人  Sasoli
<template>
  <canvas
    v-if="!state.canvasImg"
    id="myQrcode"
    type="2d"
    style="width: 100%;height: 100%;"
  />
  <image
    v-else
    :src="state.canvasImg"
    mode="scaleToFill"
    style="width: 100%;height: 100%;"
  />
</template>
<script setup lang="ts">
import {
  createSelectorQuery,
  canvasToTempFilePath,
  getSetting,
  authorize,
  saveImageToPhotosAlbum,
  showToast,
  openSetting,
  showModal,
} from '@tarojs/taro';
import { ref, watch, reactive } from 'vue';
import drawQrcode from 'weapp-qrcode-canvas-2d';
import { debounce } from '@/utils';

const nodeCanvas = ref(null);
const emit = defineEmits(['update:tempFilePath']);
const state = reactive({
  canvasImg: '',
});

const handleWriteFile = () => {
  // 存入相册
  saveImageToPhotosAlbum({
    filePath: state.canvasImg,
    success: () => {
      showToast({
        title: '保存成功',
        icon: 'none',
      });
    },
  });
};

const saveQrCode = () => {
  getSetting({
    success: ({ authSetting }) => {
      // 没有权限则申请
      if (!authSetting['scope.writePhotosAlbum']) {
        authorize({
          scope: 'scope.writePhotosAlbum',
          success: () => {
            handleWriteFile();
          },
          fail: (err) => {
            showModal({
              content: '无保存权限,请开启',
              success: (res) => {
                if (res.confirm) {
                  openSetting();
                }
              },
            });
            console.log(err);
          },
        });
      } else {
        handleWriteFile();
      }
    },
  });
};

interface Props {
  url: string;
  img?: string;
  options?: {
    status: Number | null;
  };
}
const props = withDefaults(defineProps<Props>(), {
  url: '',
  img: '',
  options: () => ({
    status: null,
  }),
});

function emitTempFilePath(canvas) {
  // 获取临时路径
  canvasToTempFilePath({
    canvas,
    destWidth: 1000,
    destHeight: 1000,
    success(res) {
      state.canvasImg = res.tempFilePath;
      emit('update:tempFilePath', res.tempFilePath);
    },
    fail(res) {
      console.error(res);
    },
  });
}

function makeQrCode() {
  state.canvasImg = '';
  const query = createSelectorQuery();
  query
    .select('#myQrcode')
    .fields({
      node: true,
      size: true,
    })
    .exec((res) => {
      const canvas = res[0].node;
      nodeCanvas.value = canvas;
      if (props.img) {
        const img = canvas.createImage();
        img.src = props.img;

        img.onload = () => {
          const options = {
            canvas,
            canvasId: 'myQrcode',
            correctLevel: 1,
            text: props.url,
            ...props.options,
            image: {
              imageResource: img,
              width: 50, // 建议不要设置过大,以免影响扫码
              height: 50, // 建议不要设置过大,以免影响扫码
              round: false,
            },
          };

          drawQrcode(options);
          emitTempFilePath(canvas);
        };
      } else {
        drawQrcode({
          canvas,
          canvasId: 'myQrcode',
          correctLevel: 1,
          text: props.url,
          ...props.options,
        });
        emitTempFilePath(canvas);
      }
    });
}

// 观察属性
watch(props, debounce(makeQrCode, 400), {
  immediate: true, // 立即执行
  deep: true, // 深度监听
});

defineExpose({
  saveQrCode,
});
</script>

使用

<QrImg
  :url="state.codeInfo.buyerCode"
  :img="codeLogo"
/>
上一篇 下一篇

猜你喜欢

热点阅读