Files
WAI_Project_UNIX/uni_modules/cool-ui/components/cl-qrcode/cl-qrcode.uvue

183 lines
3.5 KiB
Plaintext
Raw Normal View History

2025-07-21 16:47:04 +08:00
<template>
2025-07-29 13:26:31 +08:00
<view :style="{ width: getPx(props.width) + 'px', height: getPx(props.height) + 'px' }">
2025-07-21 16:47:04 +08:00
<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,
2025-07-29 13:26:31 +08:00
onUnmounted,
shallowRef
2025-07-21 16:47:04 +08:00
} from "vue";
import { drawQrcode, type QrcodeOptions } from "./draw";
2025-07-29 13:26:31 +08:00
import { canvasToPng, getPx, isHarmony, uuid } from "@/cool";
2025-07-21 16:47:04 +08:00
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 单位
logoSize: {
type: String,
default: "50px"
},
// 二维码边距,单位 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());
// 二维码组件画布
2025-07-29 13:26:31 +08:00
const canvasRef = shallowRef<UniElement | null>(null);
2025-07-21 16:47:04 +08:00
/**
* 主绘制方法,根据当前 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> {
2025-08-02 17:17:13 +08:00
return canvasToPng(canvasRef.value!);
2025-07-21 16:47:04 +08:00
}
// 自动重绘
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() ? 50 : 0
);
});
onUnmounted(() => {
stopWatch();
});
defineExpose({
toPng
});
</script>