Files
WAI_Project_UNIX/uni_modules/cool-ui/components/cl-qrcode/cl-qrcode.uvue
2025-09-03 19:03:39 +08:00

183 lines
3.5 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<view :style="{ width: getPx(props.width) + 'px', height: getPx(props.height) + 'px' }">
<canvas
ref="canvasRef"
:canvas-id="qrcodeId"
type="2d"
:id="qrcodeId"
:style="{ width: getPx(props.width) + 'px', height: getPx(props.height) + 'px' }"
></canvas>
</view>
</template>
<script lang="ts" setup>
import {
ref,
watch,
onMounted,
getCurrentInstance,
nextTick,
computed,
type PropType,
onUnmounted,
shallowRef
} from "vue";
import { drawQrcode, type QrcodeOptions } from "./draw";
import { canvasToPng, getPx, isAppIOS, isHarmony, uuid } from "@/cool";
import type { ClQrcodeMode } from "../../types";
defineOptions({
name: "cl-qrcode"
});
const props = defineProps({
// 二维码宽度,支持 px/rpx 单位
width: {
type: String,
default: "200px"
},
// 二维码高度,支持 px/rpx 单位
height: {
type: String,
default: "200px"
},
// 二维码前景色
foreground: {
type: String,
default: "#131313"
},
// 二维码背景色
background: {
type: String,
default: "#FFFFFF"
},
// 定位点颜色,不填写时与前景色一致
pdColor: {
type: String as PropType<string | null>,
default: null
},
// 定位图案圆角半径为0时绘制直角矩形
pdRadius: {
type: Number,
default: 10
},
// 二维码内容
text: {
type: String,
default: "https://cool-js.com/"
},
// logo 图片地址,支持网络、本地路径
logo: {
type: String,
default: ""
},
// logo 大小,支持 px/rpx 单位 (建议不超过二维码尺寸的20%以确保识别率)
logoSize: {
type: String,
default: "40px"
},
// 二维码边距,单位 px
padding: {
type: Number,
default: 5
},
// 二维码样式rect 普通矩形、circular 小圆点、line 线条、rectSmall 小方格
mode: {
type: String as PropType<ClQrcodeMode>,
default: "circular"
}
});
const { proxy } = getCurrentInstance()!;
// 二维码组件id
const qrcodeId = ref<string>("cl-qrcode-" + uuid());
// 二维码组件画布
const canvasRef = shallowRef<UniElement | null>(null);
/**
* 主绘制方法,根据当前 props 生成二维码并绘制到 canvas。
* 支持多平台APP、H5、微信小程序自动适配高分屏。
* 内部调用 drawQrcode 进行二维码点阵绘制。
*/
function drawer() {
const data = {
text: props.text,
size: getPx(props.width),
foreground: props.foreground,
background: props.background,
padding: props.padding,
logo: props.logo,
logoSize: getPx(props.logoSize),
ecc: "H", // 使用最高纠错级别
mode: props.mode,
pdColor: props.pdColor,
pdRadius: props.pdRadius
} as QrcodeOptions;
nextTick(() => {
// #ifdef APP || MP-WEIXIN
uni.createCanvasContextAsync({
id: qrcodeId.value,
component: proxy,
success(context) {
drawQrcode(context, data);
},
fail(err) {
console.error(err);
}
});
// #endif
// #ifdef H5
// @ts-ignore
drawQrcode(canvasRef.value, data);
// #endif
});
}
/**
* 获取当前二维码图片的临时文件地址
* @param call 回调函数,返回图片路径,失败返回空字符串
*/
function toPng(): Promise<string> {
return canvasToPng(canvasRef.value!);
}
// 自动重绘
const stopWatch = watch(
computed(() => [
props.pdColor,
props.pdRadius,
props.foreground,
props.background,
props.text,
props.logo,
props.logoSize,
props.mode,
props.padding
]),
() => {
drawer();
}
);
onMounted(() => {
setTimeout(
() => {
drawer();
},
isHarmony() || isAppIOS() ? 50 : 0
);
});
onUnmounted(() => {
stopWatch();
});
defineExpose({
toPng
});
</script>