145 lines
3.3 KiB
Vue
145 lines
3.3 KiB
Vue
|
|
<template>
|
|||
|
|
<view
|
|||
|
|
:style="`${tools._style([customStyle])}; width:${containerSize}px; height: ${containerSize}px; background-color: ${bgColor};`"
|
|||
|
|
:class="`${classPrefix} ${borderless ? prefix + '-' + 'borderless' : ''} ${tClass}`"
|
|||
|
|
>
|
|||
|
|
<QrcodeCanvas
|
|||
|
|
ref="qrcodeCanvas"
|
|||
|
|
:t-class="tClassCanvas"
|
|||
|
|
:size="size"
|
|||
|
|
:value="value"
|
|||
|
|
:level="level"
|
|||
|
|
:color="color"
|
|||
|
|
:bg-color="bgColor"
|
|||
|
|
:icon="icon"
|
|||
|
|
:icon-size="iconSize"
|
|||
|
|
@drawError="handleDrawError"
|
|||
|
|
@drawCompleted="handleDrawCompleted"
|
|||
|
|
/>
|
|||
|
|
|
|||
|
|
<view
|
|||
|
|
v-if="showMask && canvasReady"
|
|||
|
|
:class="`${prefix}-mask`"
|
|||
|
|
>
|
|||
|
|
<QrcodeStatus
|
|||
|
|
:status="status"
|
|||
|
|
:status-render="statusRender"
|
|||
|
|
@refresh="handleRefresh"
|
|||
|
|
>
|
|||
|
|
<template #statusRender>
|
|||
|
|
<slot name="statusRender" />
|
|||
|
|
</template>
|
|||
|
|
</QrcodeStatus>
|
|||
|
|
</view>
|
|||
|
|
</view>
|
|||
|
|
</template>
|
|||
|
|
|
|||
|
|
<script>
|
|||
|
|
import QrcodeCanvas from './components/qrcode-canvas/qrcode-canvas.vue';
|
|||
|
|
import QrcodeStatus from './components/qrcode-status/qrcode-status.vue';
|
|||
|
|
import { prefix } from '../common/config';
|
|||
|
|
import props from './props';
|
|||
|
|
import { uniComponent } from '../common/src/index';
|
|||
|
|
import tools from '../common/utils.wxs';
|
|||
|
|
|
|||
|
|
const name = `${prefix}-qrcode`;
|
|||
|
|
|
|||
|
|
export default uniComponent({
|
|||
|
|
name,
|
|||
|
|
options: {
|
|||
|
|
styleIsolation: 'shared',
|
|||
|
|
},
|
|||
|
|
externalClasses: [
|
|||
|
|
`${prefix}-class`,
|
|||
|
|
`${prefix}-class-canvas`,
|
|||
|
|
],
|
|||
|
|
components: {
|
|||
|
|
QrcodeCanvas,
|
|||
|
|
QrcodeStatus,
|
|||
|
|
},
|
|||
|
|
props: {
|
|||
|
|
...props,
|
|||
|
|
},
|
|||
|
|
data() {
|
|||
|
|
return {
|
|||
|
|
prefix,
|
|||
|
|
tools,
|
|||
|
|
showMask: false,
|
|||
|
|
classPrefix: name,
|
|||
|
|
canvasReady: false,
|
|||
|
|
canvasNode: null,
|
|||
|
|
};
|
|||
|
|
},
|
|||
|
|
computed: {
|
|||
|
|
// 容器尺寸 = Canvas 尺寸 + padding * 2
|
|||
|
|
// padding 为 12px,所以容器需要额外 24px
|
|||
|
|
containerSize() {
|
|||
|
|
return this.size + 24;
|
|||
|
|
},
|
|||
|
|
},
|
|||
|
|
watch: {
|
|||
|
|
status: {
|
|||
|
|
handler(newVal) {
|
|||
|
|
this.showMask = newVal !== 'active';
|
|||
|
|
},
|
|||
|
|
immediate: true,
|
|||
|
|
},
|
|||
|
|
},
|
|||
|
|
mounted() {
|
|||
|
|
this.initCanvas();
|
|||
|
|
},
|
|||
|
|
methods: {
|
|||
|
|
async initCanvas() {
|
|||
|
|
// 获取 canvas 实例
|
|||
|
|
const canvasComp = this.$refs.qrcodeCanvas;
|
|||
|
|
if (canvasComp) {
|
|||
|
|
const canvas = await canvasComp.getCanvasNode();
|
|||
|
|
this.canvasNode = canvas;
|
|||
|
|
}
|
|||
|
|
},
|
|||
|
|
|
|||
|
|
// 用于外部调用,重新绘制二维码
|
|||
|
|
init() {
|
|||
|
|
const canvasComp = this.$refs.qrcodeCanvas;
|
|||
|
|
if (canvasComp) {
|
|||
|
|
canvasComp.initCanvas();
|
|||
|
|
}
|
|||
|
|
},
|
|||
|
|
|
|||
|
|
handleDrawCompleted() {
|
|||
|
|
this.canvasReady = true;
|
|||
|
|
},
|
|||
|
|
handleDrawError(err) {
|
|||
|
|
console.error('二维码绘制失败', err);
|
|||
|
|
},
|
|||
|
|
handleRefresh() {
|
|||
|
|
this.$emit('refresh');
|
|||
|
|
},
|
|||
|
|
// 二维码下载方法
|
|||
|
|
async handleDownload() {
|
|||
|
|
if (!this.canvasNode) {
|
|||
|
|
console.error('未找到 canvas 节点');
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 注意:此方法在非小程序环境需要适配
|
|||
|
|
if (typeof wx !== 'undefined' && uni.canvasToTempFilePath) {
|
|||
|
|
uni.canvasToTempFilePath({
|
|||
|
|
canvas: this.canvasNode,
|
|||
|
|
success: (res) => {
|
|||
|
|
uni.saveImageToPhotosAlbum({ filePath: res.tempFilePath });
|
|||
|
|
},
|
|||
|
|
fail: (err) => {
|
|||
|
|
console.error('canvasToTempFilePath failed', err);
|
|||
|
|
},
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
},
|
|||
|
|
},
|
|||
|
|
});
|
|||
|
|
</script>
|
|||
|
|
|
|||
|
|
<style lang="less" scoped>
|
|||
|
|
@import './qrcode.css';
|
|||
|
|
</style>
|