179 lines
4.4 KiB
Plaintext
179 lines
4.4 KiB
Plaintext
<template>
|
|
<view class="l-qrcode" ref="l-qrcode" :style="[styles]">
|
|
<image class="l-qrcode__icon" v-if="icon !=''" :src="icon" :style="[iconStyle]"></image>
|
|
</view>
|
|
</template>
|
|
<script lang="ts">
|
|
import { type PropType } from 'vue'
|
|
import { QRCodeCanvas, QRCodePropsTypes , ImageSettings } from '@/uni_modules/lime-qrcodegen'
|
|
// import { addUnit } from '@/uni_modules/lime-shared/addUnit'
|
|
// import { unitConvert } from '@/uni_modules/lime-shared/unitConvert'
|
|
import { addUnit, unitConvert } from './utils'
|
|
import { TakeSnapshotFailCallback, TakeSnapshotCompleteCallback, TakeSnapshotSuccessCallback} from './type'
|
|
|
|
const name = 'l-qrcode'
|
|
export default {
|
|
name,
|
|
props: {
|
|
value: {
|
|
type: String,
|
|
default: ''
|
|
},
|
|
icon: {
|
|
type: String,
|
|
default: ''
|
|
},
|
|
size: {
|
|
type: Object,
|
|
default: 160
|
|
},
|
|
iconSize: {
|
|
type: Object,
|
|
default: 40
|
|
},
|
|
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
|
|
// }
|
|
},
|
|
emits: ['success'],
|
|
data() {
|
|
return {
|
|
qrcode: null as QRCodeCanvas | null
|
|
}
|
|
},
|
|
computed: {
|
|
styles() : Map<string, any> {
|
|
const style = new Map<string, any>()
|
|
const size = addUnit(this.size);
|
|
style.set('width', size)
|
|
style.set('height', size)
|
|
style.set('background', this.bgColor)
|
|
return style
|
|
},
|
|
iconStyle() : Map<string, any> {
|
|
const style = new Map<string, any>()
|
|
const size = addUnit(this.iconSize);
|
|
style.set('width', size)
|
|
style.set('height', size)
|
|
return style
|
|
},
|
|
qrCodeProps() : QRCodePropsTypes {
|
|
const param = {
|
|
value: this.value,
|
|
size: unitConvert(this.size),
|
|
fgColor: this.color,
|
|
level: ['L', 'M', 'Q', 'H'].includes(this.errorLevel) ? this.errorLevel : 'M',
|
|
marginSize: this.marginSize,
|
|
imageSettings: null,
|
|
includeMargin: this.bordered,
|
|
} as QRCodePropsTypes
|
|
|
|
if(this.iconSize != '' && this.icon != ''){
|
|
const size = unitConvert(this.iconSize)
|
|
param.imageSettings = {
|
|
width: size,
|
|
height: size,
|
|
excavate: true
|
|
} as ImageSettings
|
|
}
|
|
return param
|
|
}
|
|
},
|
|
methods: {
|
|
canvasToTempFilePath(options :UTSJSONObject) : void {
|
|
const el = (this.$refs['l-qrcode'] as Element);
|
|
const format = options.getString('format') ?? 'png';
|
|
const fail = options.get('fail') as TakeSnapshotFailCallback | null;
|
|
const complete = options.get('complete') as TakeSnapshotCompleteCallback | null;
|
|
const success = options.get('success') as TakeSnapshotSuccessCallback | null;
|
|
const newOptions = {
|
|
format,
|
|
fail,
|
|
complete,
|
|
success,
|
|
} as TakeSnapshotOptions
|
|
el.takeSnapshot(newOptions)
|
|
|
|
}
|
|
},
|
|
mounted() {
|
|
const el = (this.$refs['l-qrcode'] as Element)
|
|
const ctx = el.getDrawableContext();
|
|
if (ctx == null) return
|
|
this.qrcode = new QRCodeCanvas(ctx)
|
|
const render = (v : QRCodePropsTypes) => {
|
|
this.qrcode!.render(v);
|
|
if (this.useCanvasToTempFilePath) {
|
|
setTimeout(() => {
|
|
this.canvasToTempFilePath({
|
|
success: (res: TakeSnapshotSuccess) => {
|
|
this.$emit('success', res.tempFilePath)
|
|
},
|
|
fail: (_: TakeSnapshotFail) => {
|
|
uni.showToast({
|
|
icon: 'error',
|
|
title: '截图失败'
|
|
})
|
|
}
|
|
})
|
|
// TakeSnapshotOptions
|
|
},200)
|
|
}
|
|
}
|
|
this.$watch('qrCodeProps', (v: QRCodePropsTypes) => {
|
|
render(v)
|
|
}, {immediate: true})
|
|
}
|
|
}
|
|
</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> |