From e95b2466e11243d60c348e04ecafd22e32930cc8 Mon Sep 17 00:00:00 2001 From: liub Date: Fri, 15 Aug 2025 16:39:00 +0800 Subject: [PATCH] =?UTF-8?q?6155=E5=AE=8C=E6=88=90=E9=83=A8=E5=88=86?= =?UTF-8?q?=E5=8D=8F=E8=AE=AE=E5=AF=B9=E6=8E=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../BottomSlideMenuPlus.vue | 88 +- components/TextToHex/TextToHex.vue | 341 +++--- components/global-loading/global-loading.vue | 6 +- pages/6155/deviceDetail.vue | 968 ++++++++++-------- pages/650/HBY650.vue | 20 +- pages/common/addBLE/LinkBle.vue | 15 +- pages/common/addBLE/addEquip.vue | 23 +- static/images/6155/DeviceDetail/close.png | Bin 0 -> 1336 bytes utils/BleHelper.js | 109 +- utils/loading.js | 9 +- 10 files changed, 871 insertions(+), 708 deletions(-) create mode 100644 static/images/6155/DeviceDetail/close.png diff --git a/components/BottomSlideMenuPlus/BottomSlideMenuPlus.vue b/components/BottomSlideMenuPlus/BottomSlideMenuPlus.vue index af0dd3b..ffe890d 100644 --- a/components/BottomSlideMenuPlus/BottomSlideMenuPlus.vue +++ b/components/BottomSlideMenuPlus/BottomSlideMenuPlus.vue @@ -2,17 +2,14 @@ + :style="{backgroundColor:config.maskBgColor,display:(config.showMask?'':'none')}"> {{ config.title }} - + @@ -29,7 +26,13 @@ - + + + + {{ item.text }} @@ -61,34 +64,34 @@ config: { type: Object, default: () => ({ - show: false,//是否显示 - showHeader: false,//是否显示标头 - showMask:true,//是否显示mask - showDivider: false,//是否在两个项之间显示分隔线 - showBtn: false,//是否显示底部按钮 - showClose:false,//是否显示右上角关闭按钮 - maskBgColor:'',//mask的颜色 - menuItems: [],//菜单项 包含icon text - activeIndex: -1,//当前已选中的项编号 - bgColor: '#2a2a2a',//主体背景 - itemBgColor: '#3a3a3a',//各项被选中后的背景 - textColor: '#ffffffde',//各项的文字颜色 - textAlign: 'flex-start',//各项的文字居中方式 - title: '',//header的文字 - dividerColor: '#00000000',//分隔线颜色 - dividerThickness: '0rpx',//分隔线宽度 - dividerMargin: '10rpx',//分隔线距离两边的宽度 - itemHeight: '80rpx',//各项的调试 - btnBgColor: "#bbe600",//按钮颜色 - btnText: "确定",//按钮文字 - btnTextColor: "#000000",//按钮文字颜色 - + show: false, //是否显示 + showHeader: false, //是否显示标头 + showMask: true, //是否显示mask + showDivider: false, //是否在两个项之间显示分隔线 + showBtn: false, //是否显示底部按钮 + showClose: false, //是否显示右上角关闭按钮 + maskBgColor: '', //mask的颜色 + menuItems: [], //菜单项 包含icon text + activeIndex: -1, //当前已选中的项编号 + bgColor: '#2a2a2a', //主体背景 + itemBgColor: '#3a3a3a', //各项被选中后的背景 + textColor: '#ffffffde', //各项的文字颜色 + textAlign: 'flex-start', //各项的文字居中方式 + title: '', //header的文字 + dividerColor: '#00000000', //分隔线颜色 + dividerThickness: '0rpx', //分隔线宽度 + dividerMargin: '10rpx', //分隔线距离两边的宽度 + itemHeight: '80rpx', //各项的调试 + btnBgColor: "#bbe600", //按钮颜色 + btnText: "确定", //按钮文字 + btnTextColor: "#000000", //按钮文字颜色 + }) }, }, - + methods: { closeMenu() { @@ -100,19 +103,18 @@ this.$emit('itemClick', item, index); }, btnClick() { - + let item = null; let index = null; if (this.config.activeIndex > -1) { item = this.config.menuItems[this.config.activeIndex]; } index = this.config.activeIndex; - this.$emit('btnClick', item, index); + this.$emit('btnClick', item, index); } - + } } - + fontSize: { + type: Number, + default: 16, + validator: (value) => value > 0 && value <= 100 + }, + bgColor: { + type: String, + default: "#ffffff" + }, + color: { + type: String, + default: "#000000" + } + }, + data() { + return { + // 当前Canvas的宽高(动态调整) + currentCanvasWidth: 0, + currentCanvasHeight: 0, + // Canvas上下文(复用) + ctx: null + }; + }, + computed: { + validTxts() { + return this.txts.filter(line => line.trim() !== ''); + } + }, + mounted() { + // 初始化Canvas上下文(只创建一次) + this.ctx = uni.createCanvasContext('reusableCanvas', this); + }, + methods: { + /** + * 估算单行文本所需的Canvas宽度 + */ + calcLineWidth(textLine) { + return textLine.length * this.fontSize; + }, + + /** + * 清除Canvas内容 + */ + clearCanvas() { + this.ctx.setFillStyle(this.bgColor); + this.ctx.fillRect(0, 0, this.currentCanvasWidth, this.currentCanvasHeight); + }, + + /** + * 复用单个Canvas处理所有文本行 + */ + async drawAndGetPixels() { + + let convertCharToMatrix=function(imageData) { + // console.log("imgData=",imageData) + let matrix = []; + + // 逐行处理 + for (let y = 0; y < 16; y++) { + let byte1 = 0, + byte2 = 0; + + // 每行16个像素,分为两个字节 + for (let x = 0; x < 16; x++) { + // 计算像素在imageData中的索引 (RGBA格式) + let index = (y * 16 + x) * 4; + let red = imageData[index]; + + // 黑色像素(R值较低)视为1,白色视为0 + let isBlack = red < 128; + + if (x < 8) { + // 第一个字节(左8位) + if (isBlack) { + byte1 |= 0x80 >> x; // 从左到右设置位 + } + } else { + // 第二个字节(右8位) + if (isBlack) { + byte2 |= 0x80 >> (x - 8); + } + } + } + + // 将字节转换为两位十六进制字符串 + matrix.push('0x' + byte1.toString(16).padStart(2, '0').toUpperCase()); + matrix.push('0x' + byte2.toString(16).padStart(2, '0').toUpperCase()); + } + + return matrix; + } + + let drawTxt=async (textLine)=> { + let result = {}; + let ctx = this.ctx; + + // 1. 动态调整Canvas尺寸 + this.currentCanvasWidth = this.calcLineWidth(textLine); + this.currentCanvasHeight = this.fontSize; + + // 2. 清空Canvas(绘制背景) + this.clearCanvas(); + + // 3. 设置文字样式 + ctx.setFillStyle(this.color); + ctx.setTextBaseline('middle'); + ctx.setFontSize(this.fontSize); + ctx.font = `${this.fontSize}px "PingFang SC", PingFang SC, Arial, sans-serif`; + + // 4. 绘制当前行文本 + let currentX = 0; + let currentY = this.fontSize / 2; + for (let j = 0; j < textLine.length; j++) { + let char = textLine[j]; + ctx.fillText(char, currentX, currentY); + // 按实际字符宽度计算间距 + let charWidth = ctx.measureText(char).width; + currentX += charWidth; + } + + // 5. 异步绘制并获取像素数据(串行处理避免冲突) + await new Promise((resolve, reject) => { + ctx.draw(false, () => { + uni.canvasGetImageData({ + canvasId: 'reusableCanvas', + x: 0, + y: 0, + width: this.currentCanvasWidth, + height: this.currentCanvasHeight, + success: res => { + + result={ + line: textLine, + pixelData: res.data, + width: this.currentCanvasWidth, + height: this.currentCanvasHeight + }; + resolve(); + }, + fail: err => { + // console.error(`处理第${i+1}行失败:`, err); + reject(err) + } + }); + }); + }); + + return result; + } + let arr = []; + // 循环处理每行文本 + for (let i = 0; i < this.validTxts.length; i++) { + + let linePixls = []; + let item = this.validTxts[i]; + console.log("item=",item); + for (var j = 0; j < item.length; j++) { + let result = await drawTxt(item[j]); + linePixls.push(convertCharToMatrix(result.pixelData)); + } + console.log("hexs=",linePixls.join(",")); + arr.push(linePixls); + } + + return arr; + } + } + }; + + + \ No newline at end of file diff --git a/components/global-loading/global-loading.vue b/components/global-loading/global-loading.vue index 427f5c1..0848bec 100644 --- a/components/global-loading/global-loading.vue +++ b/components/global-loading/global-loading.vue @@ -23,10 +23,10 @@ return { visible: false, dotsCount: 12, - dotColors: ['#CEF231c2'], + dotColors: ['#CEF231'], text: '请稍候...',//文本文字 textColor: '#FFFFFFde',//文本颜色 - radius: 35,//圆的半径 + radius: 32,//圆的半径 duration: 1200,//动画的播放速度 colorIndex: 0 } @@ -158,7 +158,7 @@ position: absolute; top: 50%; left: 50%; - width: 4rpx; + width: 6rpx; height: 30rpx; border-radius: 12rpx; /* margin-top: -4rpx; diff --git a/pages/6155/deviceDetail.vue b/pages/6155/deviceDetail.vue index 6f5c539..275555a 100644 --- a/pages/6155/deviceDetail.vue +++ b/pages/6155/deviceDetail.vue @@ -24,11 +24,11 @@ 蓝牙名称 - {{formData.name}} + {{formData.blename}} - 信号强度 - {{formData.RSSI}} + 设备名称 + {{formData.deviceName}} 设备状态 @@ -83,26 +83,23 @@ 人员信息登记 发送 - + 单位: - + + + + 部门: + 姓名: - - - - 职位: - - - - ID号: - + + 产品信息 @@ -141,25 +138,31 @@ - +