272 lines
5.4 KiB
Vue
272 lines
5.4 KiB
Vue
<template xlang="wxml" minapp="mpvue">
|
|
<view class="tki-qrcode">
|
|
<!-- #ifndef MP-ALIPAY -->
|
|
<canvas
|
|
class="tki-qrcode-canvas"
|
|
:canvas-id="cid"
|
|
:style="{ width: cpSize + 'px', height: cpSize + 'px' }"
|
|
/>
|
|
<!-- #endif -->
|
|
<!-- #ifdef MP-ALIPAY -->
|
|
<canvas
|
|
:id="cid"
|
|
:width="cpSize"
|
|
:height="cpSize"
|
|
class="tki-qrcode-canvas"
|
|
/>
|
|
<!-- #endif -->
|
|
<image
|
|
v-show="show"
|
|
:src="result"
|
|
:style="{ width: cpSize + 'px', height: cpSize + 'px' }"
|
|
/>
|
|
</view>
|
|
</template>
|
|
|
|
<script setup>
|
|
import { ref, computed, watch, onMounted, getCurrentInstance } from "vue";
|
|
import QRCode from "./qrcode.js";
|
|
|
|
let qrcode;
|
|
|
|
// 定义props
|
|
const props = defineProps({
|
|
cid: {
|
|
type: String,
|
|
default: "tki-qrcode-canvas",
|
|
},
|
|
size: {
|
|
type: Number,
|
|
default: 200,
|
|
},
|
|
unit: {
|
|
type: String,
|
|
default: "upx",
|
|
},
|
|
show: {
|
|
type: Boolean,
|
|
default: true,
|
|
},
|
|
val: {
|
|
type: String,
|
|
default: "",
|
|
},
|
|
background: {
|
|
type: String,
|
|
default: "#ffffff",
|
|
},
|
|
foreground: {
|
|
type: String,
|
|
default: "#000000",
|
|
},
|
|
pdground: {
|
|
type: String,
|
|
default: "#000000",
|
|
},
|
|
icon: {
|
|
type: String,
|
|
default: "",
|
|
},
|
|
iconSize: {
|
|
type: Number,
|
|
default: 40,
|
|
},
|
|
lv: {
|
|
type: Number,
|
|
default: 3,
|
|
},
|
|
onval: {
|
|
type: Boolean,
|
|
default: false,
|
|
},
|
|
loadMake: {
|
|
type: Boolean,
|
|
default: false,
|
|
},
|
|
usingComponents: {
|
|
type: Boolean,
|
|
default: true,
|
|
},
|
|
showLoading: {
|
|
type: Boolean,
|
|
default: true,
|
|
},
|
|
loadingText: {
|
|
type: String,
|
|
default: "二维码生成中",
|
|
},
|
|
});
|
|
|
|
// 定义emits
|
|
const emit = defineEmits(["result"]);
|
|
|
|
// 获取当前实例
|
|
const instance = getCurrentInstance()
|
|
|
|
// 创建一个安全的上下文对象
|
|
const getContext = () => {
|
|
return instance?.proxy || instance?.ctx || {}
|
|
};
|
|
|
|
// 响应式数据
|
|
const result = ref("");
|
|
|
|
// 计算属性
|
|
const cpSize = computed(() => {
|
|
if (props.unit === "upx") {
|
|
return uni.upx2px(props.size);
|
|
} else {
|
|
return props.size;
|
|
}
|
|
});
|
|
|
|
// 工具函数
|
|
const _empty = (v) => {
|
|
let tp = typeof v;
|
|
let rt = false;
|
|
if (tp === "number" && String(v) === "") {
|
|
rt = true;
|
|
} else if (tp === "undefined") {
|
|
rt = true;
|
|
} else if (tp === "object") {
|
|
if (JSON.stringify(v) === "{}" || JSON.stringify(v) === "[]" || v === null)
|
|
rt = true;
|
|
} else if (tp === "string") {
|
|
if (
|
|
v === "" ||
|
|
v === "undefined" ||
|
|
v === "null" ||
|
|
v === "{}" ||
|
|
v === "[]"
|
|
)
|
|
rt = true;
|
|
} else if (tp === "function") {
|
|
rt = false;
|
|
}
|
|
return rt;
|
|
};
|
|
|
|
// 方法定义
|
|
const _makeCode = () => {
|
|
console.log('开始生成二维码,内容:', props.val, '大小:', cpSize.value)
|
|
if (!_empty(props.val)) {
|
|
try {
|
|
qrcode = new QRCode({
|
|
context: getContext(), // 上下文环境
|
|
canvasId: props.cid, // canvas-id
|
|
usingComponents: props.usingComponents, // 是否是自定义组件
|
|
showLoading: props.showLoading, // 是否显示loading
|
|
loadingText: props.loadingText, // loading文字
|
|
text: props.val, // 生成内容
|
|
size: cpSize.value, // 二维码大小
|
|
background: props.background, // 背景色
|
|
foreground: props.foreground, // 前景色
|
|
pdground: props.pdground, // 定位角点颜色
|
|
correctLevel: props.lv, // 容错级别
|
|
image: props.icon, // 二维码图标
|
|
imageSize: props.iconSize, // 二维码图标大小
|
|
cbResult: function (res) {
|
|
// 生成二维码的回调
|
|
console.log('二维码生成完成:', res)
|
|
_result(res);
|
|
},
|
|
});
|
|
} catch (error) {
|
|
console.error('二维码生成失败:', error)
|
|
}
|
|
} else {
|
|
console.log('二维码内容为空')
|
|
uni.showToast({
|
|
title: "二维码内容不能为空",
|
|
icon: "none",
|
|
duration: 2000,
|
|
});
|
|
}
|
|
};
|
|
|
|
const _clearCode = () => {
|
|
_result("");
|
|
if (qrcode) {
|
|
qrcode.clear();
|
|
}
|
|
};
|
|
|
|
const _saveCode = () => {
|
|
if (result.value !== "") {
|
|
uni.saveImageToPhotosAlbum({
|
|
filePath: result.value,
|
|
success: function () {
|
|
uni.showToast({
|
|
title: "二维码保存成功",
|
|
icon: "success",
|
|
duration: 2000,
|
|
});
|
|
},
|
|
});
|
|
}
|
|
};
|
|
|
|
const _result = (res) => {
|
|
result.value = res;
|
|
emit("result", res);
|
|
};
|
|
|
|
// 监听器
|
|
watch(
|
|
() => props.size,
|
|
(newVal, oldVal) => {
|
|
if (newVal !== oldVal && !_empty(newVal)) {
|
|
if (!_empty(props.val)) {
|
|
setTimeout(() => {
|
|
_makeCode();
|
|
}, 100);
|
|
}
|
|
}
|
|
}
|
|
);
|
|
|
|
watch(
|
|
() => props.val,
|
|
(newVal, oldVal) => {
|
|
if (props.onval) {
|
|
if (newVal !== oldVal && !_empty(newVal)) {
|
|
setTimeout(() => {
|
|
_makeCode();
|
|
}, 0);
|
|
}
|
|
}
|
|
}
|
|
);
|
|
|
|
// 生命周期
|
|
onMounted(() => {
|
|
if (props.loadMake) {
|
|
if (!_empty(props.val)) {
|
|
setTimeout(() => {
|
|
_makeCode();
|
|
}, 0);
|
|
}
|
|
}
|
|
});
|
|
|
|
// 暴露方法给父组件
|
|
defineExpose({
|
|
_makeCode,
|
|
_clearCode,
|
|
_saveCode,
|
|
});
|
|
</script>
|
|
|
|
<style>
|
|
.tki-qrcode {
|
|
position: relative;
|
|
}
|
|
|
|
.tki-qrcode-canvas {
|
|
position: fixed;
|
|
top: -99999upx;
|
|
left: -99999upx;
|
|
z-index: -99999;
|
|
}
|
|
</style>
|