Files
2025-07-07 16:05:18 +08:00

235 lines
5.5 KiB
Plaintext

<template>
<!-- #ifdef MP -->
<canvas :style="styles" type="2d" :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>
import { type PropType, nextTick } from 'vue'
// #ifndef APP
import { QRCodeCanvas } from './qrcode.js';
import { QRCodePropsTypes , ImageSettings } from './type'
// #endif
// #ifdef APP
import { QRCodeCanvas, QRCodePropsTypes , ImageSettings } from '@/uni_modules/lime-qrcodegen'
// #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
}
// 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);
// #ifdef WEB
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
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
}
qrcode?.render(param)
if(props.useCanvasToTempFilePath){
setTimeout(()=>{
canvasToTempFilePath({
success: (res: TakeSnapshotSuccess)=>{
emits('success', res.tempFilePath)
}
})
},100)
}
}
defineExpose({
canvasToTempFilePath
})
onMounted(()=>{
nextTick(()=>{
// #ifdef APP
const ctx = drawableRef.value!.getDrawableContext();
qrcode = new QRCodeCanvas(ctx!)
// #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();
image.crossOrigin = 'anonymous';
return image;
}
})
// #endif
watchEffect(()=>{
render()
})
})
})
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>