Files
2026-09-24 16:25:22 +08:00

361 lines
8.3 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.
<script lang="ts">
import { type PropType } from "vue"
import { getUid, rpx2px } from "../../core/util/xCoreUtil.uts"
import { getDefaultColor } from "../../core/util/xCoreColorUtil.uts"
import { checkIsCssUnit } from "../../core/util/xCoreUtil.uts"
import { xConfig } from "../../config/xConfig.uts"
import {drawQrcode} from "./drawQrcoder.uts"
import {XQrcoderProps} from "./interface.uts"
import { toPngFile } from "@/uni_modules/x-base642file-s"
type DATATYP = {
action : string
}
/**
* @name 二维码 xQrcoder
* @description 本组件使用UTS原生代码绘制,性能非常高,如果你是在1.1.9之前版本请使用x-qrcoder-s原生插件获得高性能。从1.1.9版本后请
* 使用组件绘制QR码来获得更高性能和更多样式配置。
* @page /pages/index/qrcoder
* @category 其它组件
* @constant 平台兼容
* | Harmony | H5 | andriod | IOS | 小程序 | UTS | UNIAPP-X SDK | version |
| --- | --- | --- | --- | --- | --- | --- | --- |
| ☑ | ☑ | ☑️ | ☑️ | ☑️ | ☑️ | 4.76+ | 1.1.18 |
*/
export default {
data() {
return {
id: ("xQrcode-" + getUid()) as string,
id2: ("xQrcode1" + getUid()) as string,
isLoaded: false,
tid2: 0
}
},
props: {
/**
* 窗口宽
*/
width: {
type: String,
default: '250px'
},
/**
* 宽器高,这将影响条码的高度
*/
height: {
type: String,
default: '250px'
},
/**
* 码颜色
*/
color: {
type: String,
default: "primary"
},
/**
* 码背景颜色
*/
bgColor: {
type: String,
default: "white"
},
/**
* 码的定位点颜色,不填写和原前景一致
*/
posColor: {
type: String,
default: ""
},
/**
* 条码内容
*/
text: {
type: String,
default: "https://xui.tmui.design"
},
/**
* 是否绘制Logo到qr上。
*/
logo: {
type: String,
default: ""
},
/**
* 是否绘制Logo到qr上。
*/
logoBgColor: {
type: String,
default: "#fff"
},
/**
* logo大小。
*/
logoSize: {
type: String,
default: "50px"
},
/**
* 边距
*/
padding:{
type: Number,
default: 2
},
/**
* 绘制的样式目前提供
* rect :普通码矩形
* circular :小圆点
* line :线条
* rectSmall :小方格
* xing :星形
* vertical :竖圆形
*/
mode:{
type: String,
default: "rect"
},
/**
* 定位位点是否使用圆角。
*/
pdRounded:{
type:Boolean,
default:false
},
/**
* 生成自动连接的wifi码,手机原生相机扫码时,可以根据你设置帐号密码自动连接你的wifi.
* 包含的字段:ssid:wifi名称,auth:授权方式(NONEWPAWEP)的一种,password:密码,hidden:是否隐藏密码,字符串'true'/'false'
*/
wifi:{
type:Object as PropType<UTSJSONObject>,
default:():UTSJSONObject => ({} as UTSJSONObject)
}
},
computed: {
_width() : number {
let p = parseInt(this.width);
if (this.width.lastIndexOf('rpx') > -1 || this.width.lastIndexOf('px') == -1) {
p = rpx2px(p);
}
return Math.floor(p)
},
_height() : number {
let p = parseInt(this.height);
if (this.height.lastIndexOf('rpx') > -1 || this.height.lastIndexOf('px') == -1) {
p = rpx2px(p);
}
return Math.floor(p)
},
_color() : string {
return getDefaultColor(this.color);
},
_bgColor() : string {
return getDefaultColor(this.bgColor);
},
_posColor() : string {
if(this.posColor=='') return this._color
return getDefaultColor(this.posColor);
},
_text() : string {
let wifisize = this.wifi.toMap().size
if(wifisize>0){
return `WIFI:T:${this.wifi['auth']??''};S:${this.wifi['ssid']??''};P:${this.wifi['password']??''};H:${this.wifi['hidden']??'true'};`
}
return this.text;
},
_logo() : string {
return this.logo;
},
_logoBgColor() : string {
return this.logoBgColor;
},
_padding() : number {
return this.padding;
},
_logoSize() : number {
let p = parseInt(this.logoSize);
if (this.logoSize.lastIndexOf('rpx') > -1 || this.logoSize.lastIndexOf('px') == -1) {
p = rpx2px(p);
}
return Math.floor(p)
},
},
watch: {
text(newValue : string) {
if (newValue == "") return;
this.drawer();
},
wifi:{
handler(){
this.drawer();
},
deep:true
},
mode() {
this.drawer();
},
logo() {
this.drawer();
},
color(newValue : string) {
if (newValue == "") return;
this.drawer();
},
bgColor(newValue : string) {
if (newValue == "") return;
this.drawer();
},
logoSize(newValue : string) {
if (newValue == "") return;
this.drawer();
},
padding(newValue : string) {
if (newValue == "") return;
this.drawer();
},
width(newValue : string) {
if (newValue == "") return;
this.drawer();
},
height(newValue : string) {
if (newValue == "") return;
this.drawer();
}
},
mounted() {
// #ifndef APP-HARMONY
this.drawer()
// #endif
// #ifdef APP-HARMONY
let t = this;
this.tid2 = setTimeout(function() {
t.drawer()
}, 120);
// #endif
},
beforeUnmount() {
clearTimeout(this.tid2)
},
methods: {
drawer(){
let _this = this;
// #ifdef APP || MP
uni.createCanvasContextAsync({
id:this.id2,
component:this,
success(context){
let ctx = context.getContext('2d')!;
let canvas = ctx.canvas
if (ctx == null) return;
let ratio = uni.getWindowInfo()?.pixelRatio??1
ctx!.clearRect(0,0, canvas.offsetWidth,canvas.offsetHeight)
canvas.width = canvas.offsetWidth * ratio
canvas.height = canvas.offsetHeight * ratio
// #ifdef APP
ctx.reset();
// #endif
ctx.scale(ratio, ratio);
let img =null as null|any
// #ifdef MP-WEIXIN||APP-HARMONY
img = context.createImage()
// #endif
drawQrcode({
ctx:ctx,
text:_this._text,
size:_this._width,
foreground:_this._color,
background:_this._bgColor,
padding:_this._padding,
logo:_this._logo,
logoSize:_this._logoSize,
logoBgColor:_this._logoBgColor,
ecc:"H",
mode:_this.mode,
pdColor:_this._posColor,
pdRounded:_this.pdRounded,
} as XQrcoderProps,img)
},
fail(){
uni.showToast({title:'错误',icon:'none'})
}
})
// #endif
// #ifdef WEB
let canvas = this.$refs['canvas'] as UniCanvasElement
let ratio = window.devicePixelRatio;
canvas.width = canvas.offsetWidth * ratio
canvas.height = canvas.offsetHeight * ratio
let ctx = canvas.getContext('2d')!
ctx.scale(ratio, ratio);
drawQrcode({
ctx:ctx,
text:this._text,
size:this._width,
foreground:this._color,
background:this._bgColor,
padding:this._padding,
logoBgColor:_this._logoBgColor,
logo:this._logo,
logoSize:this._logoSize,
ecc:"H",
mode:this.mode,
pdColor:_this._posColor,
pdRounded:_this.pdRounded
} as XQrcoderProps)
// #endif
},
/**
* 返回一个上传图片的临时文件地址
* @param call(string) 返回图片路径,失败返回的是空字符串
*/
getQrImg(call:(imgstr:string)=>void) {
// #ifdef APP
let ele = this.$refs['xQrcodeEle'] as UniElement;
ele.takeSnapshot({
success(res) {
call(res.tempFilePath)
},
fail() {
call('')
}
})
// #endif
// #ifdef WEB
let ele2= this.$refs['canvas'] as HTMLCanvasElement;
toPngFile(ele2.toDataURL('image/png',1)).then(furl=>call(furl)).catch(call(''))
// #endif
// #ifdef MP-WEIXIN
uni.createCanvasContextAsync({
id:this.id2,
component:this,
success(context){
let ctx = context.getContext('2d')!;
let canvas = ctx.canvas
var imageData = canvas.toDataURL('image/png',1);
toPngFile(imageData).then(furl=>call(furl)).catch(call(''))
},
fail(err){
console.error(err)
call('')
}
},this)
// #endif
},
}
}
</script>
<template>
<view ref="xQrcodeEle" :style="{width:_width+'px',height:_height+'px'}">
<canvas ref="canvas" :canvas-id="id2" type="2d" :id="id2" :style="{width:_width+'px',height:_height+'px'}"></canvas>
</view>
</template>
<style scoped>
</style>