SmartParks_visitore/uni_modules/lime-qrcode/components/l-qrcode/l-qrcode.uvue
2025-08-21 11:23:54 +08:00

300 lines
8.1 KiB
Plaintext
Raw Permalink 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>
<!-- #ifndef APP || WEB -->
<canvas :style="styles" v-if="use2d" type="2d" :canvas-id="canvasId" :id="canvasId"></canvas>
<canvas :style="styles" v-else :canvas-id="canvasId" :id="canvasId"></canvas>
<!-- #endif -->
<!-- #ifdef APP -->
<view class="l-qrcode" ref="drawableRef" :style="[styles]">
<image class="l-qrcode__icon" v-if="icon" :src="icon" :style="[iconStyle]"></image>
</view>
<!-- #endif -->
<!-- #ifdef WEB -->
<view class="l-qrcode" ref="drawableRef" :style="[styles]"></view>
<!-- #endif -->
</template>
<script lang="uts" setup>
/**
* QRCode 二维码组件
* @description 用于生成二维码图形,支持自定义图标和样式配置
* <br>插件类型LQrcodeComponentPublicInstance
* @tutorial https://ext.dcloud.net.cn/plugin?name=lime-qrcode
*
* @property {string} value 二维码内容(支持文本/URL等
* @property {string} icon 中心图标路径(支持本地/网络路径)
* @property {number | string} size 二维码尺寸
* @property {number | string} iconSize 中心图标尺寸
* @property {number} marginSize 二维码外边距默认0
* @property {string} color 二维码颜色(默认:#000000
* @property {string} bgColor 背景颜色(默认:#ffffff
* @property {boolean} bordered 显示边框默认false
* @property {'L' | 'M' | 'Q' | 'H'} errorLevel 容错等级(默认:'H'
* @value L 可恢复7%的数据
* @value M 可恢复15%的数据
* @value Q 可恢复25%的数据
* @value H 可恢复30%的数据
* @property {boolean} useCanvasToTempFilePath 使用canvas生成临时路径H5端可能需要
* @property {boolean} use2d 启用2D上下文渲染性能优化默认false
*/
import { type PropType, nextTick } from 'vue'
// #ifndef APP
import { createImage } from '@/uni_modules/lime-shared/createImage'
import { getCanvas, isCanvas2d } from './useCanvas'
import { QRCodeCanvas } from './qrcode.js';
import { QRCodePropsTypes , ImageSettings } from './type'
// #endif
// #ifdef APP-ANDROID || APP-HARMONY
import { QRCodeCanvas, type QRCodePropsTypes , type ImageSettings } from '@/uni_modules/lime-qrcodegen'
// #endif
// #ifdef APP-IOS
import { QRCodeCanvas, type QRCodePropsTypes , type ImageSettings } from './ios'
// #endif
// import { addUnit } from '@/uni_modules/lime-shared/addUnit'
// import { unitConvert } from '@/uni_modules/lime-shared/unitConvert'
// import { toBoolean } from '@/uni_modules/lime-shared/toBoolean'
import { addUnit, unitConvert } from './utils'
import { LQrcodeFailCallback, LQrcodeCompleteCallback, LQrcodeSuccessCallback} from './type'
const name = 'l-qrcode'
const props = defineProps({
value: {
type: String
},
icon: {
type: String
},
// #ifdef APP-ANDROID
size: {
type: Object,
default: 160
},
iconSize: {
type: Object,
default: 40
},
// #endif
// #ifndef APP-ANDROID
size: {
type: [Number, String],
default: 160
},
iconSize: {
type: [Number, String],
default: 40
},
// #endif
marginSize: {
type: Number,
default: 0
},
color: {
type: String,
default: '#000'
},
bgColor: {
type: String,
default: 'transparent'
},
bordered: {
type: Boolean,
default: true
},
errorLevel: {
type: String as PropType<'L' | 'M' | 'Q' | 'H'>,
default: 'M' // 'L' | 'M' | 'Q' | 'H'
},
useCanvasToTempFilePath: {
type: Boolean,
default: false
},
use2d: {
type: Boolean,
default: true
}
// status: {
// type: String as PropType<'active'|'expired'|'loading'>,
// default: 'active' // active | expired | loading
// }
})
const emits = defineEmits(['success'])
const context = getCurrentInstance();
const canvasId = `l-qrcode${context!.uid}`
const styles = computed<Map<string, any>>(():Map<string, any>=>{
const style = new Map<string, any>()
const size = addUnit(props.size);
if(size!=null){
style.set('width', size)
style.set('height', size)
}
style.set('background', props.bgColor)
return style
})
// #ifdef APP
const iconStyle = computed<Map<string, any>>(():Map<string, any>=>{
const style = new Map<string, any>()
const size = addUnit(props.iconSize);
// if(size!=null){
style.set('width', size)
style.set('height', size)
// }
return style
})
// #endif
const drawableRef = ref<UniElement|null>(null);
// #ifndef APP
let canvas:HTMLCanvasElement|null = null
// #endif
let qrcode:QRCodeCanvas|null = null
const canvasToTempFilePath = (options: UTSJSONObject)=>{
const format = options.getString('format') ?? 'png';
const fail = options.get('fail') as LQrcodeFailCallback | null;
const complete = options.get('complete') as LQrcodeCompleteCallback | null;
const success = options.get('success') as LQrcodeSuccessCallback | null;
// #ifdef APP
const newOptions = {
format,
fail,
complete,
success,
} as TakeSnapshotOptions
drawableRef.value!.takeSnapshot(newOptions)
// #endif
// #ifdef WEB
success?.({
tempFilePath: canvas?.toDataURL('image/'+format)
})
// #endif
}
const render = ()=>{
const param:QRCodePropsTypes = {
value: props.value,
size: unitConvert(props.size),
fgColor: props.color,
level: ['L', 'M', 'Q', 'H'].includes(props.errorLevel) ? props.errorLevel : 'M',
marginSize: props.marginSize,
includeMargin: props.bordered,
imageSettings: null,
} as QRCodePropsTypes
// #ifdef APP-HARMONY
param.value = props.value
param.size = unitConvert(props.size)
param.fgColor = props.color
param.level = ['L', 'M', 'Q', 'H'].includes(props.errorLevel) ? props.errorLevel : 'M'
param.marginSize = props.marginSize
param.includeMargin = props.bordered
param.imageSettings = null
// #endif
if(props.icon != null){
// if(toBoolean(props.iconSize) && toBoolean(props.icon)){
const size = unitConvert(props.iconSize)
param.imageSettings = {
src: props.icon,
width: size,
height: size,
excavate: true
} as ImageSettings
// #ifdef APP-HARMONY
param.imageSettings.src = props.icon
param.imageSettings.width = size
param.imageSettings.height = size
param.imageSettings.excavate = true
// #endif
}
qrcode?.render(param)
if(props.useCanvasToTempFilePath){
setTimeout(()=>{
canvasToTempFilePath({
success: (res: TakeSnapshotSuccess)=>{
emits('success', res.tempFilePath)
}
})
},100)
}
}
defineExpose({
canvasToTempFilePath
})
onMounted(()=>{
nextTick(()=>{
// #ifdef APP
requestAnimationFrame(()=> {
drawableRef.value?.getBoundingClientRectAsync()?.then(res => {
const ctx = drawableRef.value!.getDrawableContext();
qrcode = new QRCodeCanvas(ctx!)
watchEffect(()=>{
render()
})
})
})
// #endif
// #ifdef WEB
canvas = document.createElement('canvas')
canvas!.style.width = '100%'
canvas!.style.height = '100%'
drawableRef.value!.appendChild(canvas!)
qrcode = new QRCodeCanvas(canvas, {
pixelRatio: uni.getSystemInfoSync().pixelRatio,
createImage: () => {
const image = new Image();
// @ts-ignore
image.crossOrigin = 'anonymous';
return image;
}
})
watchEffect(()=>{
render()
})
// #endif
// #ifndef APP || WEB
getCanvas(canvasId, { context }).then(res => {
canvas = res;
qrcode = new QRCodeCanvas(res, {
path2D: false,
pixelRatio: isCanvas2d && props.use2d ? uni.getSystemInfoSync().pixelRatio : 1,
createImage
})
watchEffect(()=>{
render()
})
})
// #endif
})
})
onUnmounted(()=>{
// #ifdef WEB
canvas?.remove();
// #endif
qrcode = null;
})
</script>
<style lang="scss">
.l-qrcode {
position: relative;
background-color: aqua;
justify-content: center;
align-items: center;
&-mask {
position: absolute;
// inset: 0;
// inset-block-start: 0;
// inset-inline-start: 0;
z-index: 10;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
// width: 100%;
// height: 100%;
color: rgba(0, 0, 0, 0.88);
line-height: 1.5714285714285714;
background: rgba(255, 255, 255, 0.96);
text-align: center;
}
}
</style>