<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"
/>