<template> <view class="page"> <u-navbar :title="tittxt" :border-bottom="false" :background="bgc" back-icon-color="#fff" title-color='#fff' title-size='36' height='50' id="navbar"> </u-navbar> <view class="zhuhu"> <view class="card1"> <view class="top"> <view class="left"> 设备 </view> <view class="right"> </view> </view> <view class="mid"> <view class="mid_left"> <view v-if="opflag" style="border: 0;outline: none;width: 143rpx;padding-left: 0rpx;height: 143rpx;border-radius: 16rpx;" @click="btnpic"> <image :src="imglist" mode="aspectFit" style="width: 142rpx;height: 142rpx;border-radius: 20rpx;"></image> </view> <image v-else :src="imglist" mode="aspectFit" style="width: 142rpx;height: 142rpx;border-radius: 20rpx;"></image> <ksp-cropper mode="free" :width="142" :height="142" :maxWidth="1024" :maxHeight="1024" :url="url" @cancel="oncancel" @ok="onok"></ksp-cropper> </view> <view class="mid_right"> <view class="mid_top"> {{ deviceInfo.deviceName == null ? '' : deviceInfo.deviceName }} <view class="" style="font-size: 26rpx;margin-top: 8rpx;"> 更新时间:{{deviceInfo.lastPullTime == null ? '--' : deviceInfo.lastPullTime}}</view> <text style="font-size: 24rpx;color: #8883F0;display: inline-block;border: 1px solid #8883F0;padding: 5rpx;box-sizing: border-box;border-radius: 10rpx;">{{deviceInfo.model == undefined ? '' : deviceInfo.model}}</text> </view> <view class="mid_bot"> <view class="txt" v-if="deviceInfo"> S/N码:{{ deviceInfo.deviceNo == null ? '' : deviceInfo.deviceNo }}</view> <div class="tip" v-if="deviceInfo.onlineStatus==1" style="color: seagreen;border: 2rpx solid;">在线</div> <div class="tip" v-if="deviceInfo.onlineStatus==0" style="color: red;border: 2rpx solid;">离线 </div> <div class="tip" v-if="deviceInfo.status==1" style="color: seagreen;border: 2rpx solid;">空闲 </div> <div class="tip" v-if="deviceInfo.status==2" style="color: seagreen;border: 2rpx solid;">使用中 </div> <div class="tip" v-if="deviceInfo.status==3" style="color: red;">维修中</div> </view> </view> </view> <view class="bot"> <!-- 设备租期到期时间: {{deviceInfo.rentTime}} --> </view> </view> <view class="card2"> <view class="tit">实时</view> <view class="bot_right"> <view class="cont" style="text-align: center;"> <view class="tit"> {{deviceInfo.orderAmount == null ? 0 : deviceInfo.orderAmount}} </view> <view class="txt"> 订单金额 </view> </view> <view class="cont" style="text-align: center;"> <view class="tit"> {{deviceInfo.orderCount == null ? 0 : deviceInfo.orderCount}} </view> <view class="txt"> 订单数 </view> </view> <view class="cont" style="text-align: center;"> <view class="tit"> {{formattedTime}} <!-- sb:{{setMode}} --> </view> <view class="txt"> 剩余时长 </view> </view> </view> </view> <view class="card3" v-if="opflag"> <view class="tit">其他</view> <view class="cont_box" style="display: block;"> <view class="" style="display: flex;"> <view class="cont" @click="topage(0)"> <view class="top"> <image src="https://api.ccttiot.com/smartmeter/img/static/uKrpw3p37UHW56IypPJU" mode="" style="width: 58rpx;height: 58rpx;"></image> </view> <view class="bot">充值记录</view> </view> <view class="cont" @click="topage(1)"> <view class="top"> <image src="https://api.ccttiot.com/smartmeter/img/static/uaS4iFmD786AtBt2tKFs" mode="" style="width: 58rpx;height: 58rpx;"></image> </view> <view class="bot">归零</view> </view> <view class="cont" @click="topage(6)"> <view class="top"> <image style="width: 58rpx;height: 58rpx;" src="https://api.ccttiot.com/smartmeter/img/static/uAnBmmayp3tVGwXntdaM" mode=""> </image> </view> <view class="bot">充值</view> </view> <view class="cont" @click="topage(2)"> <view class="top"> <image src="https://api.ccttiot.com/smartmeter/img/static/ue0X00T1C3fh7TCgjopm" mode="" style="width: 58rpx;height: 58rpx;"></image> </view> <view class="bot">上报异常</view> </view> </view> <view class="" style="display: flex;margin-top: 20rpx;padding-right: 5rpx;box-sizing: border-box;"> <view class="cont" @click="topage(3)"> <view class="top"> <image src="https://api.ccttiot.com/smartmeter/img/static/umjPUc8nDKf1JwVqRAeb" mode="" style="width: 50rpx;height: 58rpx;"></image> </view> <view class="bot">收费方式</view> </view> <view class="cont" @click="topage(5)" v-if="modelId.some(tag => tag == 2)"> <view class="top"> <image style="width: 58rpx;height: 58rpx;" src="https://api.ccttiot.com/smartmeter/img/static/uik9veDG6pMVG5M1Vxze" mode=""> </image> </view> <view class="bot">配网</view> </view> <view class="cont" @click="topage(4)"> <view class="top"> <image style="width: 58rpx;height: 58rpx;" src="https://api.ccttiot.com/smartmeter/img/static/u2Uco0iXf8aure0H2ihz" mode=""> </image> </view> <view class="bot">设置</view> </view> <view class="cont" @click="qrFun"> <view class="top"> <image style="width: 58rpx;height: 58rpx;" src="https://api.ccttiot.com/smartmeter/img/static/u7o1YnOGEKxM6KZ4WGXO" mode=""> </image> </view> <view class="bot">分享</view> </view> </view> </view> <view class="cont_box" style="padding-left: 30rpx;"> </view> </view> <view class="" style="display: flex;margin-top: 20rpx;padding: 50rpx;box-sizing: border-box;width: 100%; height: 80rpx;align-items: center;justify-content: space-between;background-color: #fff;border-radius: 20rpx;"> <view class="bot">手动操作:{{tdtxt}}</view> <view class="cont" @click="btnkq"> <view class="top" style="padding-top: 10rpx;"> <!-- <u-switch v-model="checked" active-color="#8883F0"></u-switch> --> <view class="rt"> <image v-if="imgflag" style="width: 160rpx;height: 80rpx;" src="https://api.ccttiot.com/smartmeter/img/static/uccaWar4FDp37op7haWM " mode=""> </image> <image style="width: 160rpx;height: 80rpx;" v-else src="https://api.ccttiot.com/smartmeter/img/static/ur9HRtZKY7YcxGewJARz" mode=""> </image> </view> </view> </view> </view> </view> <view class="tanc" v-if="vipflag"> <view class="tit">请输入您需要充值的时长或度数</view> <input type="number" :focus="focus" v-model="cztime" placeholder="请输入时长或度数" /> <input type="text" placeholder="请选择单位时长或度数" v-model="danwei" disabled="false" @click="showflag = true" /> <u-icon name="arrow-down" style="position: fixed;top: 234rpx;right: 60rpx;" color="#999" size="28"></u-icon> <view class="xian"></view> <view class="anniu"> <text @click="btnqx">取消</text> <text style="border-left: 1px solid #eee;color: #8883F0;" @click="trueje">确定</text> </view> </view> <view class="maskss" v-if="vipflag"></view> <!-- 蓝牙连接 --> <view class="bluetoothbox" v-if="bluetoothflag"> <view class="stop"> 正在连接该设备蓝牙 </view> <view class="xtop"> 请将手机与设备尽量靠近 </view> <image src="https://api.ccttiot.com/smartmeter/img/static/ucDphMKsozqwwllJTAKL" mode=""></image> </view> <!-- 蓝牙连接失败 --> <view class="bluetoothbox" v-if="shibaiflag"> <image class="img" src="https://api.ccttiot.com/smartmeter/img/static/uTb3vSlbcHdPMFQMBjyL" mode=""></image> <view class="one"> 蓝牙连接失败 </view> <view class="two"> 请确保手机足够靠近设备 </view> <view class="thr"> 并且设备处于上电状态 </view> <view class="anfour"> <view class="qx" @click="btnlyqx"> 取消 </view> <view class="cx" @click="topage(5)"> 重新连接 </view> </view> </view> <!-- 选择单位 --> <u-select v-model="showflag" :list="listdanwei" title='选择单位' @confirm="btnconfirm"></u-select> <!-- 展示二维码 --> <view class="imgewm" v-if="wemflag" @longpress="saveCanvas"> <canvas canvas-id="qrcode" style="height: 100%;margin: 0 auto;" /> <view class="" style="width: 100%;text-align: center;margin-top: 20rpx;"> SN:{{deviceNo}} </view> <view class="" style="border: 1px solid; padding: 20rpx;box-sizing: border-box;width: 100%;text-align: center;margin-top: 400rpx;" @click="wemflag = false"> 关闭二维码 </view> </view> <view class="imgewmflag" v-if="wemflag" @click.stop="ewmyc"></view> <view v-if="btnmsk" style="width: 100%;height: 100vh;position: fixed;top: 0;left: 0;background-color: #000;opacity: .1;z-index: 999;"> </view> </view> </template> <script> var xBlufi = require("@/page_components/blufi/xBlufi.js") import uQRCode from '@/common/uqrcode.js' import uniEcCanvas from '@/components/uni-ec-canvas/uni-ec-canvas.vue' import * as echarts from '@/components/uni-ec-canvas/echarts' let chart = null export default { components: { uniEcCanvas }, data() { return { showflag: false, imgflag: false, wemflag: false, btnmsk: false, bluetoothflag: false, shibaiflag: false, danwei: '', listdanwei: [{ value: 2, label: '小时' }, { value: 3, label: '分钟' }, { value: 4, label: '秒钟' }, { value: 0, label: '度' }], bgc: { backgroundColor: "#8883f0", }, ec: { lazyLoad: true }, deviceInfo: {}, loadings: false, info: '', checked: false, tittxt: "设备详情", titlist: [], tdtxt: '开启', curtitidx: 0, id: '', focus: false, timeday: '', imglist: '', token: '', userImgs: '', imgflag: true, mac: "", name: '', deviceId: '', storeId: '', qrResult: '', devicesList: [], setMode: null, vipflag: false, cztime: '', opflag: true, timer: null, url: "", deviceNo: '', modelId: [], damweiid:'' } }, onLoad(option) { let id = option.id this.id = id // this.getDevice(id) if (option.flag) { this.opflag = false } else { this.opflag = true } }, // 分享到好友(会话) onShareAppMessage: function() { return { title: '创想物联', path: '/pages/shouye/index' } }, // 分享到朋友圈 onShareTimeline: function() { return { title: '创想物联', query: '', path: '/pages/shouye/index' } }, computed: { formattedTime() { if (this.timeday.days > 0) { // 只展示天和小时 return `${this.timeday.days}天${this.timeday.hours}小时` } else if (this.timeday.hours > 0) { // 展示小时和分钟 return `${this.timeday.hours}小时${this.timeday.minutes}分钟` } else if (this.timeday.minutes > 0) { // 展示分钟和秒 return `${this.timeday.minutes}分钟${this.timeday.seconds}秒` } else if(this.timeday.seconds == 0){ this.deviceInfo.status = 1 this.imgflag = false this.tdtxt = '关闭' return this.timeday.seconds > 0 ? `${this.timeday.seconds}秒` : '0' } else { // 展示秒或0(如果秒也为0) return this.timeday.seconds > 0 ? `${this.timeday.seconds}秒` : '0' } } }, beforeDestroy() { // 组件销毁前清除定时器,防止内存泄漏 if (this.timer) { clearInterval(this.timer) this.timer = null console.log('已销毁') } }, onHide() { if (this.timer) { clearInterval(this.timer) this.timer = null console.log('已销毁') } }, onUnload: function() { console.log("unload "); xBlufi.listenDeviceMsgEvent(false, this.funListenDeviceMsgEvent); wx.closeBLEConnection({ deviceId: this.deviceId, }) }, onShow() { this.getshuax() this.getQiniuToken() }, mounted() { this.drawCanvas() }, methods: { getshuax(){ this.$u.get(`/app/device/${this.id}/refreshIot`).then((res) => { this.getDevice(this.id) }) }, // 选择时长单位 btnconfirm(e) { this.danwei = e[0].label this.damweiid = e[0].value }, capture() { var pages = getCurrentPages(); //获取当前页面信息 var page = pages[pages.length - 1]; var bitmap = null; var currentWebview = page.$getAppWebview(); bitmap = new plus.nativeObj.Bitmap('amway_img'); // 将webview内容绘制到Bitmap对象中 currentWebview.draw(bitmap, function() { // console.log('截屏绘制图片成功'); //这里我将文件名用四位随机数拼接了,不然会出现当前图片替换上一张图片只能保存一张图片的问题 let rand = Math.floor(Math.random() * 10000) let saveUrl = '_doc/' + rand + 'a.jpg' bitmap.save(saveUrl, {}, function(i) { // console.log('保存图片成功:' + JSON.stringify(i)); uni.saveImageToPhotosAlbum({ filePath: i.target, success: function() { // bitmap.clear(); //销毁Bitmap图片 uni.showToast({ title: '保存图片成功', mask: false, duration: 1500 }); } }); }, function(e) { console.log('保存图片失败:' + JSON.stringify(e)); }); }, function(e) { console.log('截屏绘制图片失败:' + JSON.stringify(e)); }); //currentWebview.append(amway_bit); }, drawCanvas() { const ctx = uni.createCanvasContext('qrcode', this); ctx.setFillStyle('#fff'); ctx.fillRect(10, 10, 250, 250); ctx.draw(); }, // 长按保存二维码 saveCanvas() { uni.canvasToTempFilePath({ canvasId: 'qrcode', success: (res) => { console.log(res.tempFilePath); // 打印图片路径 uni.saveImageToPhotosAlbum({ filePath: res.tempFilePath, success: function() { uni.showToast({ title: '保存成功', icon: 'success' }); } }); }, fail: (err) => { console.error(err); } }); }, //**生成二维码**// qrFun: function() { this.wemflag = true uQRCode.make({ canvasId: 'qrcode', // componentInstance: this, text: 'https://kg.chuantewulian.cn/w?s=' + this.deviceNo, size: 250, margin: 0, backgroundColor: '#ffffff', foregroundColor: '#000000', fileType: 'jpg', errorCorrectLevel: uQRCode.errorCorrectLevel.H, }) }, ewmyc() { this.wemflag = false }, btnlyqx() { this.shibaiflag = false this.bluetoothflag = false }, // 开启和关闭 btnkq() { if (this.deviceInfo.onlineStatus == 1) { if (this.tdtxt == '开启') { this.$u.put(`/app/device/${this.id}/changePower?status=0`).then((res) => { if (res.code == 200) { this.tdtxt = '关闭' this.imgflag = false this.deviceInfo.status = 1 uni.showToast({ title: res.msg, icon: 'success', duration: 2000 }) } else { this.imgflag = true this.tdtxt = '开启' uni.showToast({ title: res.msg, icon: 'none', duration: 2000 }) } }) } else { this.$u.put(`/app/device/${this.id}/changePower?status=1`).then((res) => { if (res.code == 200) { this.imgflag = true this.tdtxt = '开启' this.deviceInfo.status = 2 uni.showToast({ title: res.msg, icon: 'success', duration: 2000 }) } else { this.imgflag = false this.tdtxt = '关闭' uni.showToast({ title: res.msg, icon: 'none', duration: 2000 }) } }) } } else { if (this.setMode == null) { this.btnmsk = false this.shibaiflag = false this.bluetoothflag = true xBlufi.initXBlufi(1) xBlufi.listenDeviceMsgEvent(true, this.funListenDeviceMsgEvent) xBlufi.notifyStartDiscoverBle({ 'isStart': true }) // 停止蓝牙搜索 setTimeout(() => { xBlufi.notifyStartDiscoverBle({ 'isStart': false }) xBlufi.notifyConnectBle({ isStart: true, deviceId: this.deviceId, name: this.name }) xBlufi.notifyInitBleEsp32({ deviceId: this.deviceId }) let name = '' let index = this.name.indexOf('-') if (index !== -1) { name = this.name.slice(index + 1) } if (this.deviceInfo.powerStatus == 0) { this.imgflag = false } else { this.imgflag = true } }, 1000) } else { // console.log(this.tdtxt,'020202'); if (this.tdtxt == '开启') { let that = this uni.getNetworkType({ success(res) { if (res.networkType !== 'none') { uni.getConnectedBluetoothDevices({ success(res) { setTimeout(() => { // console.log('close关闭'); that.tdtxt = '关闭' that.imgflag = false that.deviceInfo.status = 1 xBlufi.notifySendCustomData({ customData: 'close' }) xBlufi.notifySendCustomData({ customData: '11close' }) }, 1000) }, fail(err) { console.error('获取已连接蓝牙设备信息失败:', err) } }) } } }) } else { let that = this uni.getNetworkType({ success(res) { if (res.networkType !== 'none') { uni.getConnectedBluetoothDevices({ success(res) { setTimeout(() => { // console.log('open开启'); that.tdtxt = '开启' that.imgflag = true that.deviceInfo.status = 2 xBlufi.notifySendCustomData({ customData: 'open' }) xBlufi.notifySendCustomData({ customData: '11open' }) }, 1000) }, fail(err) { console.error('获取已连接蓝牙设备信息失败:', err) } }) } } }) } } } }, getQiniuToken() { this.$u.get("/common/qiniu/uploadInfo").then((res) => { if (res.code == 200) { this.token = res.token } }); }, btnpic() { uni.chooseImage({ count: 1, success: (rst) => { this.url = rst.tempFilePaths[0] } }) }, onok(ev) { this.url = "" this.path = ev.path; let _this = this let math = 'static/' + _this.$u.guid(20) wx.uploadFile({ url: 'https://up-z2.qiniup.com', name: 'file', filePath: _this.path, formData: { token: _this.token, key: 'smartmeter/img/' + math }, success: function(res) { // console.log(res); let str = JSON.parse(res.data) _this.userImgs = 'https://api.ccttiot.com/' + str.key _this.imglist = _this.userImgs // console.log(_this.imglist,'_this.imglist_this.imglist') let data = { deviceId: _this.id, customPicture: _this.imglist } _this.putdevice(data) } }) }, oncancel() { // url设置为空,隐藏控件 this.url = "" }, putdevice(data) { this.$u.put('/app/device', data).then((res) => { if (res.code == 200) { uni.showToast({ title: '修改成功', icon: 'success', duration: 2000 }) } else { uni.showToast({ title: res.msg, icon: 'none', duration: 2000 }) } }) }, // 获取设备详情 getDevice(id) { this.$u.get("/app/device/" + id).then((res) => { if (res.code == 200) { this.deviceInfo = res.data this.modelId = res.data.modelTags this.storeId = res.data.storeId this.deviceNo = res.data.deviceNo // this.qrResult = 'CTKG-' + res.data.mac this.qrResult = res.data.mac if (res.data.customPicture != null) { this.imglist = res.data.customPicture } else { this.imglist = res.data.picture } if (this.deviceInfo.expireTime == null) { this.timeday = 0 } else { let expireTimeStr = this.deviceInfo.expireTime let expireTimeParts = expireTimeStr.split(" "); let expireDateParts = expireTimeParts[0].split("-"); let expireTimePartsTime = expireTimeParts[1].split(":"); let expireDate = new Date(expireDateParts[0], expireDateParts[1] - 1, expireDateParts[ 2], expireTimePartsTime[0], expireTimePartsTime[1], expireTimePartsTime[2]) let now = new Date() let differenceInMs = expireDate - now if (differenceInMs <= 0) { this.timeday = 0 } else { this.timeday = this.formatMilliseconds(differenceInMs) this.startTimer() } } if (res.data.powerStatus == 0) { this.imgflag = false this.tdtxt = '关闭' } else { this.imgflag = true this.tdtxt = '开启' } this.loadings = true } }) }, startTimer() { this.timer = setInterval(() => { if (this.timeday.seconds > 0) { this.timeday.seconds-- } else if (this.timeday.minutes > 0) { this.timeday.seconds = 59 // 重置秒数为59 this.timeday.minutes-- } else if (this.timeday.hours > 0) { this.timeday.minutes = 59 // 重置分钟数为59 this.timeday.hours-- this.timeday.seconds = 0 // 同时重置秒数为0 } else if (this.timeday.days > 0) { this.timeday.hours = 23 // 重置小时数为23 this.timeday.minutes = 59 // 重置分钟数为59 this.timeday.seconds = 0 // 重置秒数为0 this.timeday.days-- } else { // 所有时间单位都已减为0,停止定时器 clearInterval(this.timer) this.timer = null; // console.log('时间已到期') } }, 1000); // 每秒执行一次 }, // 计算天时分秒 formatMilliseconds(milliseconds) { // 计算天数 let days = Math.floor(milliseconds / (1000 * 60 * 60 * 24)) // 计算剩余的小时数 let hours = Math.floor((milliseconds % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60)) // 计算剩余的分钟数 let minutes = Math.floor((milliseconds % (1000 * 60 * 60)) / (1000 * 60)) // 计算剩余的秒数 let seconds = Math.floor((milliseconds % (1000 * 60)) / 1000) // 返回一个对象,包含天、小时、分钟和秒 return { days: days, hours: hours, minutes: minutes, seconds: seconds } }, opendevice() { let stause = 0 if (this.deviceInfo.powerStatus == 1) { stause = 0 } else { stause = 1 } // console.log(stause, 'stausestause'); this.$u.put(`/app/device/${this.deviceInfo.deviceId}/changePower?status=` + stause).then((res) => { if (res.code == 200) { // this.groupList=res.rows setTimeout(() => { this.getDevice(this.id) }, 2000) // this.loadings=true } else { uni.showToast({ title: res.msg, icon: 'none' }) } }) }, opendevices() { }, swiperchange(e) { this.curtitidx = e.detail.current // console.log(e, 'aaaa'); }, changeidx(index) { this.curtitidx = index }, toydfx() { uni.navigateTo({ url: "/page_components/eletj?id=" + this.id }) }, // 其他部分 点击进行跳转 topage(num) { this.btnmsk = true if (num == 0) { this.btnmsk = false uni.navigateTo({ //抄表 url: '/page_user/cbRecord?id=' + this.id }) } else if (num == 1) { console.log(this.deviceInfo.onlineStatus,'this.deviceInfo.onlineStatusthis.deviceInfo.onlineStatus'); if(this.deviceInfo.onlineStatus == 1){ let that = this uni.showModal({ title: '提示', content: '您确定要将设备时间归零吗?', success: function(res) { if (res.confirm) { that.btnmsk = false //归零 that.$u.put(`/app/device/${that.id}/reset`).then((res) => { if (res.code == 200) { // console.log(res.data); uni.showToast({ title: res.msg, icon: 'none', duration: 2000 }) that.getshuax() that.deviceInfo.status = 1 that.imgflag = false that.tdtxt = '关闭' } else if (res.msg == '设备剩余时间不足,无需归零') { uni.showToast({ title: '设备剩余时间不足,无需归零', icon: 'none', duration: 2000 }) } else if (res.code == 500) { uni.showToast({ title: res.msg, icon: 'none', duration: 2000 }) } }) } else if (res.cancel) { that.btnmsk = false console.log('用户点击了取消') } } }) }else{ if (this.setMode == null) { this.btnmsk = false this.shibaiflag = false this.bluetoothflag = true xBlufi.initXBlufi(1) xBlufi.listenDeviceMsgEvent(true, this.funListenDeviceMsgEvent) xBlufi.notifyStartDiscoverBle({ 'isStart': true }) // 停止蓝牙搜索 setTimeout(() => { xBlufi.notifyStartDiscoverBle({ 'isStart': false }) xBlufi.notifyConnectBle({ isStart: true, deviceId: this.deviceId, name: this.name }) xBlufi.notifyInitBleEsp32({ deviceId: this.deviceId }) }, 1000) } else { let that = this uni.showModal({ title: '提示', content: '您确定要将设备时间归零吗?', success: function(res) { if (res.confirm) { that.btnmsk = false uni.getNetworkType({ success(res) { if (res.networkType !== 'none') { uni.getConnectedBluetoothDevices({ success(res) { setTimeout(() => { that.$u.put(`/app/device/${that.id}/reset?requiredIot=false`).then(res => { if(res.code == 200){ that.deviceInfo.status = 1 that.imgflag = false that.tdtxt = '关闭' that.timeday = 0 xBlufi.notifySendCustomData({ customData: '@time0' }) xBlufi.notifySendCustomData({ customData: '@mmney0' }) xBlufi.notifySendCustomData({ customData: 'close' }) uni.showToast({ title: res.msg, icon: 'success', duration: 2000 }) }else{ uni.showToast({ title: res.msg, icon: 'none', duration: 2000 }) } }) }, 1000) }, fail(err) { console.error('获取已连接蓝牙设备信息失败:', err) } }) } } }) } } }) } } } else if (num == 2) { //异常 this.btnmsk = false uni.navigateTo({ url: '/page_fenbao/statulist/fault/yichang/index' }) } else if (num == 3) { this.btnmsk = false uni.navigateTo({ url: "/page_fenbao/statulist/taocanlist/index?id=" + this.id }) } else if (num == 4) { //设置 this.btnmsk = false uni.navigateTo({ url: '/page_user/setting?id=' + this.id }) } else if (num == 5) { // uni.showLoading({ // title: '蓝牙连接中...' // }) this.btnmsk = false this.shibaiflag = false this.bluetoothflag = true console.log(this.deviceId, 'idididididdidii'); if (this.setMode == null) { xBlufi.initXBlufi(1) xBlufi.listenDeviceMsgEvent(true, this.funListenDeviceMsgEvent) xBlufi.notifyStartDiscoverBle({ 'isStart': true }) // 停止蓝牙搜索 setTimeout(() => { xBlufi.notifyStartDiscoverBle({ 'isStart': false }) xBlufi.notifyConnectBle({ isStart: true, deviceId: this.deviceId, name: this.name }) xBlufi.notifyInitBleEsp32({ deviceId: this.deviceId }) let name = '' let index = this.name.indexOf('-') if (index !== -1) { name = this.name.slice(index + 1) } let data = { storeId: this.storeId, mac: this.mac } this.$u.put('/app/device/bind', data).then((res) => { if (res.code == 200) { uni.hideLoading(); this.shibaiflag = false this.bluetoothflag = false uni.removeStorageSync('mac'); let systemInfo = uni.getSystemInfoSync() if (systemInfo.platform == 'android') { // 当前设备是 Android uni.navigateTo({ url: '/page_components/wifilist/index?deviceId=' + this .deviceId + '&name=' + this.name }) } else if (systemInfo.platform == 'ios') { // 当前设备是 iOS uni.navigateTo({ url: '/page_fenbao/device/wifivideo?deviceId=' + this .deviceId + '&name=' + this.name }) } } else if (res.msg == '设备编号和mac不能同时为空') { this.shibaiflag = true this.bluetoothflag = false // uni.showToast({ // title: '连接失败', // icon: 'none', // duration: 2000 // }); } else { // uni.showToast({ // title: res.msg, // icon: 'none', // duration: 2000 // }); // uni.navigateBack() } }) }, 2000) } else { let name = '' let index = this.name.indexOf('-') if (index !== -1) { name = this.name.slice(index + 1) } let data = { storeId: this.storeId, mac: this.mac } this.$u.put('/app/device/bind', data).then((res) => { if (res.code == 200) { // uni.showToast({ // title: '绑定成功', // icon: 'none', // duration: 2000 // }) this.shibaiflag = false this.bluetoothflag = false uni.hideLoading(); uni.removeStorageSync('mac'); let systemInfo = uni.getSystemInfoSync() if (systemInfo.platform == 'android') { // 当前设备是 Android uni.navigateTo({ url: '/page_components/wifilist/index?deviceId=' + this.deviceId + '&name=' + this.name }) } else if (systemInfo.platform == 'ios') { // 当前设备是 iOS uni.navigateTo({ url: '/page_fenbao/device/wifivideo?deviceId=' + this.deviceId + '&name=' + this.name }) } } else { if (res.msg == '设备编号和mac不能同时为空') { this.shibaiflag = true this.bluetoothflag = false uni.hideLoading() // uni.showToast({ // title: '连接失败', // icon: 'none', // duration: 2000 // }) } else { this.shibaiflag = true this.bluetoothflag = false uni.hideLoading() uni.showToast({ title: res.msg, icon: 'none', duration: 2000 }) // uni.navigateBack() } } }) } } else if (num == 6) { this.btnmsk = false this.vipflag = true this.focus = true } }, getaddtime(){ this.$u.put('/app/device/addTime/' + this.id + '?amount=' + this.cztime + '&timeUnit=' + this.damweiid + '&withIot=false').then(res => {}) }, trueje() { if (this.timer) { clearInterval(this.timer) this.timer = null } let id = this.deviceInfo.deviceId this.vipflag = false if (this.deviceInfo.onlineStatus == 1) { this.$u.put('/app/device/addTime/' + id + '?amount=' + this.cztime + '&timeUnit=' + this.damweiid).then(res => { if (res.code == 200) { uni.showToast({ title: '充值成功', icon: 'success', duration: 2000 }) // this.getshuax() this.getDevice(this.id) setTimeout(()=>{ this.cztime = '' this.danwei = '' this.deviceInfo.status = 2 this.tdtxt = '开启' this.imgflag = true },1000) } else if (res.code == 500) { uni.showToast({ title: res.msg, icon: 'none', duration: 2000 }) } }) } else { if (this.setMode == null) { this.cztime = '' this.danwei = '' this.btnmsk = false this.shibaiflag = false this.bluetoothflag = true xBlufi.initXBlufi(1) xBlufi.listenDeviceMsgEvent(true, this.funListenDeviceMsgEvent) xBlufi.notifyStartDiscoverBle({ 'isStart': true }) // 停止蓝牙搜索 setTimeout(() => { xBlufi.notifyStartDiscoverBle({ 'isStart': false }) xBlufi.notifyConnectBle({ isStart: true, deviceId: this.deviceId, name: this.name }) xBlufi.notifyInitBleEsp32({ deviceId: this.deviceId }) }, 1000) } else { let that = this uni.getNetworkType({ success(res) { if (res.networkType !== 'none') { uni.getConnectedBluetoothDevices({ success(res) { setTimeout(() => { that.deviceInfo.status = 2 that.imgflag = true that.tdtxt = '开启' if(that.damweiid == 4){ xBlufi.notifySendCustomData({ customData: 'mmney@' + that.cztime }) xBlufi.notifySendCustomData({ customData: '11mmney@' + that.cztime }) that.getaddtime() }else if(that.damweiid == 4){ xBlufi.notifySendCustomData({ customData: 'time@' + that.cztime }) xBlufi.notifySendCustomData({ customData: '11time@' + that.cztime }) that.getaddtime() }else if(that.damweiid == 3){ xBlufi.notifySendCustomData({ customData: 'time@' + that.cztime * 60 }) xBlufi.notifySendCustomData({ customData: '11time@' + that.cztime * 60 }) that.getaddtime() }else if(that.damweiid == 2){ xBlufi.notifySendCustomData({ customData: 'time@' + that.cztime * 60 * 60 }) xBlufi.notifySendCustomData({ customData: '11time@' + that.cztime * 60 * 60 }) that.getaddtime() } }, 1000) }, fail(err) { console.error('获取已连接蓝牙设备信息失败:', err) } }) } } }) } } }, btnqx() { this.vipflag = false this.cztime = '' }, funListenDeviceMsgEvent: function(options) { switch (options.type) { case xBlufi.XBLUFI_TYPE.TYPE_RECIEVE_MY_DATA: let loadPercent = options.data; let loadText = '文件读取中' // console.log("文件读取中", options.data) break; case xBlufi.XBLUFI_TYPE.TYPE_RECIEVE_CUSTON_DATA: let ver_data = this.parseCustomData(options.data) this.setMode = Math.floor(ver_data.setMode / 60) this.bluetoothflag = false console.log("1收到设备发来的自定义数据结果:", ver_data, this.setMode) break; case xBlufi.XBLUFI_TYPE.TYPE_GET_DEVICE_LISTS: if (options.result) { let devicesarr = options.data // console.log(devicesarr, 'devicesarrdevicesarr') devicesarr.forEach(device => { const mac = device.name.substring(5) // console.log(device.name,device.name(5,15), 'macmacmac') if (device.name.slice(5, 17) == this.qrResult) { this.deviceId = device.deviceId this.name = device.name this.mac = device.name.slice(5, 17) // console.log(this.mac, this.deviceId, this.name, 'macmacmac') // this.devicesList = uniqueDevicesList } }) } break; case xBlufi.XBLUFI_TYPE.TYPE_CONNECTED: // console.log("连接回调:" + JSON.stringify(options)) if (options.result) { this.bluetoothflag = false uni.hideLoading(); // uni.showToast({ // title: '连接成功', // icon: 'none' // }); { console.log("连接回调options.data.deviceId:" + options.data.deviceId, "连接回调options.data.name:" + options.data.name) } } else { this.shibaiflag = true this.bluetoothflag = false uni.hideLoading() // uni.showToast({ // title: '设备离线或不在范围内', // icon: 'none', // duration: 2000 // }) } break; case xBlufi.XBLUFI_TYPE.TYPE_GET_DEVICE_LISTS_START: if (!options.result) { setTimeout(() => { uni.hideLoading() this.bluetoothflag = false }, 3000) console.log("蓝牙未开启", options) this.shibaiflag = true // uni.showToast({ // title: '蓝牙未开启', // icon: 'none', // duration: 3000 // }); return } else { // this.searching = true //蓝牙搜索开始 // _this.setData({ // searching: true // }); } break; case xBlufi.XBLUFI_TYPE.TYPE_GET_DEVICE_LISTS_STOP: if (options.result) { let uniqueDevicesList = Array.from(new Set(this.devicesList)) // 将去重后的数组重新赋值给 this.devicesList this.devicesList = uniqueDevicesList let list = [] // filteredDevices.forEach(device => { // // 从设备名称中提取 MAC 地址(假设 MAC 地址是设备名称的后6个字符) // let macFromName = device.name.substring(device.name.length - 12) // this.$u.get(`/app/device/${macFromName}/isBind`).then((res) => { // if (res.data == false) { // list.push(device) // } else { // } // }) // }); setTimeout(() => { this.devicesList = list }, 200) console.log('蓝牙停止搜索ok') } else { //蓝牙停止搜索失败 console.log('蓝牙停止搜索失败') } this.searching = false break } }, // parseCustomData(data) { // // 将字符串按照 "@" 分割成数组 // const dataArray = data.split('@') // // 根据约定,解析各个字段的值 // const voltage = parseFloat(dataArray[0].substring(1)) // 去除前缀 "V",并将字符串转换为浮点数 // const switchState = dataArray[1].substring(1)// 去除前缀 "S" // const current = parseFloat(dataArray[2].substring(1)) // 去除前缀 "A",并将字符串转换为浮点数 // const power = parseFloat(dataArray[4].substring(1)) // 去除前缀 "P",并将字符串转换为浮点数 // const remainingPower = parseFloat(dataArray[5].substring(1)) // 去除前缀 "M",并将字符串转换为浮点数 // const setMode = dataArray[6].substring(1) // 去除前缀 "T" // // 返回解析后的数据对象 // return { // voltage, // switchState, // current, // power, // remainingPower, // setMode // }; // }, parseCustomData(data) { // 将字符串按照 "@" 分割成数组 const dataArray = data.split('@'); // 初始化一个空对象来存储解析后的数据 const parsedData = {}; // 前缀到属性名的映射 const prefixMap = { 'V': 'voltage', 'S': 'switchState', 'A': 'current', 'P': 'power', 'M': 'remainingPower', 'T': 'setMode', 'W': 'temperature' }; // 遍历数组并解析每个字段 for (let i = 0; i < dataArray.length; i++) { const field = dataArray[i]; for (const prefix in prefixMap) { if (field.startsWith(prefix)) { // 去除前缀并将剩余部分转换为适当的类型(这里默认为浮点数或字符串) const value = field.substring(1); const propertyName = prefixMap[prefix]; // 根据需要,这里可以添加更复杂的类型转换逻辑 // 但为了简单起见,我们总是尝试将其转换为浮点数,如果失败则保留为字符串 parsedData[propertyName] = isNaN(parseFloat(value)) ? value : parseFloat(value); // 找到了匹配的前缀,跳出内层循环 break; } } } // 返回解析后的数据对象 return parsedData; }, } } </script> <style lang="scss"> /deep/ .panel { position: fixed; width: 100%; height: 100%; top: 0; bottom: 0; left: 0; z-index: 99 !important; overflow: hidden; } .imgewmflag { width: 750rpx; height: 100vh; background: #fff; border-radius: 0rpx 0rpx 0rpx 0rpx; z-index: 1; position: fixed; top: 0; left: 0; } .imgewm { width: 250px; height: 250px; position: fixed; top: 20%; left: 50%; transform: translateX(-50%); z-index: 2; } .conts { display: flex; justify-content: space-between; margin-top: 50rpx; align-items: center; width: 100%; height: 100%; padding: 20rpx; border-radius: 30rpx; box-sizing: border-box; background-color: #fff; .bot { // width: 100%; // height: 80rpx; // line-height: 80rpx; // text-align: center; // border-radius: 30rpx; // background-color: #fff; // margin-top: 30rpx; font-size: 30rpx; } } .picjt { position: fixed; top: 190rpx; right: 60rpx; width: 16rpx; height: 30rpx; } .bluetoothbox { width: 100%; height: 100vh; background-color: #f4f1f6; position: fixed; top: 0; left: 0; z-index: 99; text-align: center; .img { margin-top: 400rpx; width: 320rpx; height: 320rpx; } .one { font-size: 36rpx; color: #000; } .two { margin-top: 30rpx; font-size: 24rpx; color: #ccc; } .thr { margin-top: 30rpx; font-size: 28rpx; color: #ccc; } .anfour { display: flex; margin-top: 30rpx; justify-content: space-between; padding: 0 220rpx; box-sizing: border-box; .qx { width: 100rpx; height: 70rpx; line-height: 70rpx; text-align: center; border: 1px solid #3D3D3D; border-radius: 10rpx; } .cx { width: 200rpx; height: 70rpx; line-height: 70rpx; text-align: center; background-color: #8883F0; color: #fff; border-radius: 10rpx; } } .stop { font-size: 36rpx; color: #000; margin-top: 380rpx; } .xtop { margin-top: 30rpx; font-size: 24rpx; color: #ccc; } .xqx { width: 530rpx; height: 90rpx; line-height: 90rpx; border-radius: 20rpx; text-align: center; background-color: #fff; margin: auto; margin-top: 200rpx; } image { width: 500rpx; height: 500rpx; margin-top: 100rpx; } } /deep/ .u-title { padding-bottom: 22rpx; } /deep/ .u-icon__icon { padding-bottom: 22rpx; } page { background-color: #F7FAFE; } .maskss { width: 750rpx; height: 100vh; background: #000000; border-radius: 0rpx 0rpx 0rpx 0rpx; opacity: 0.2; z-index: 1; position: fixed; top: 0; left: 0; } .tanc { width: 610rpx; max-height: 430rpx; background: #FFFFFF; border-radius: 30rpx 30rpx 30rpx 30rpx; position: fixed; top: 528rpx; left: 50%; transform: translateX(-50%); z-index: 2; .tit { width: 100%; text-align: center; margin-top: 28rpx; font-weight: 500; font-size: 32rpx; color: #3D3D3D; } input { width: 504rpx; height: 90rpx; background: #EEEEEE; border-radius: 6rpx 6rpx 6rpx 6rpx; margin: auto; margin-top: 22rpx; padding-left: 20rpx; } .xian { width: 610rpx; height: 2rpx; background: #eee; border-radius: 0rpx 0rpx 0rpx 0rpx; margin-top: 26rpx; } .anniu { display: flex; justify-content: space-between; height: 98rpx; text { padding: 24rpx; text-align: center; box-sizing: border-box; font-weight: 500; font-size: 36rpx; color: #3D3D3D; display: inline-block; width: 100%; height: 100rpx; } } } .page { .zhuhu { margin-top: 60rpx; padding: 0 40rpx; .card1 { padding: 34rpx 0 0 40rpx; width: 670rpx; height: 320rpx; background: #FFFFFF; box-shadow: 0rpx 14rpx 35rpx 0rpx rgba(53, 140, 255, 0.1); border-radius: 28rpx 28rpx 28rpx 28rpx; .top { display: flex; flex-wrap: nowrap; justify-content: space-between; align-items: center; .left { font-size: 35rpx; font-family: HarmonyOS Sans SC, HarmonyOS Sans SC; font-weight: 400; color: #8883F0; } .right { margin-right: 56rpx; .img1 { width: 76rpx; height: 76rpx; } } } .mid { margin-top: 20rpx; display: flex; flex-wrap: nowrap; align-content: flex-start; .mid_left { image { width: 160rpx; height: 160rpx; border-radius: 20rpx; } } .mid_right { margin-left: 20rpx; display: flex; flex-wrap: wrap; .mid_top { width: 100%; font-size: 42rpx; font-family: HarmonyOS Sans SC, HarmonyOS Sans SC; font-weight: 400; color: #262B37; } .mid_bot { display: flex; flex-wrap: nowrap; align-items: center; margin-top: 6rpx; .txt { font-size: 26rpx; font-family: HarmonyOS Sans SC, HarmonyOS Sans SC; font-weight: 400; color: #95989D; } .tip { display: flex; align-items: center; justify-content: center; margin-left: 10rpx; padding: 0 10rpx; box-sizing: border-box; background: rgba(204, 204, 204, 0); opacity: 1; border: 2rpx solid #8883F0; border-radius: 15rpx; font-size: 26rpx; font-family: HarmonyOS Sans SC, HarmonyOS Sans SC; font-weight: 400; color: #8883F0; } } } } .bot { margin-top: 20rpx; display: flex; flex-wrap: nowrap; align-items: center; .bot_left { width: 210rpx; height: 180rpx; margin-right: 34rpx; .echarts { height: 200rpx; .uni-ec-canvas { width: 100%; height: 100rpx !important; display: block; } } } .bot_right { display: flex; width: 100%; justify-content: space-between; padding-left: 80rpx; padding-right: 80rpx; box-sizing: border-box; .cont { .tit { font-size: 28rpx; font-family: HarmonyOS Sans SC, HarmonyOS Sans SC; font-weight: 600; color: #262B37; line-height: 49rpx; } .txt { font-size: 26rpx; font-family: HarmonyOS Sans SC, HarmonyOS Sans SC; font-weight: 400; color: #262B37; } } } } } .bot_right { display: flex; width: 100%; justify-content: space-between; padding-left: 80rpx; padding-right: 80rpx; box-sizing: border-box; margin-top: 30rpx; .cont { .tit { font-size: 28rpx; font-family: HarmonyOS Sans SC, HarmonyOS Sans SC; font-weight: 600; color: #262B37; line-height: 49rpx; margin-left: 0; } .txt { font-size: 26rpx; font-family: HarmonyOS Sans SC, HarmonyOS Sans SC; font-weight: 400; color: #262B37; } } } .card2 { padding-top: 40rpx; margin-top: 24rpx; width: 670rpx; height: 254rpx; background: #FFFFFF; box-shadow: 0rpx 16rpx 40rpx 0rpx rgba(53, 140, 255, 0.1); border-radius: 28rpx; .tit { margin-left: 40rpx; font-size: 35rpx; font-family: HarmonyOS Sans SC, HarmonyOS Sans SC; font-weight: 400; color: #8883F0; } .cont_box { margin-top: 32rpx; display: flex; flex-wrap: nowrap; justify-content: space-around; .cont { width: 25%; display: flex; flex-wrap: wrap; align-items: center; justify-content: center; text-align: center; .top { width: 100%; font-size: 32rpx; font-family: HarmonyOS Sans SC, HarmonyOS Sans SC; font-weight: 400; color: #262B37; } .bot { margin-top: 20rpx; font-size: 26rpx; font-family: HarmonyOS Sans SC, HarmonyOS Sans SC; font-weight: 400; color: #262B37; } } } } .card3 { padding-top: 40rpx; margin-top: 24rpx; width: 670rpx; background: #FFFFFF; box-shadow: 0rpx 16rpx 40rpx 0rpx rgba(53, 140, 255, 0.1); border-radius: 28rpx; padding-bottom: 20rpx; .tit { margin-left: 40rpx; font-size: 35rpx; font-family: HarmonyOS Sans SC, HarmonyOS Sans SC; font-weight: 400; color: #8883F0; } .cont_box { padding: 0 40rpx; margin-top: 32rpx; display: flex; flex-wrap: nowrap; justify-content: space-around; .cont:last-child { margin-right: 0rpx; } .cont { width: 25%; text-align: center; .top { image { width: 56rpx; height: 56rpx; } } .bot { margin-top: 8rpx; font-size: 28rpx; font-family: HarmonyOS Sans SC, HarmonyOS Sans SC; font-weight: 400; color: #808080; } } } } .button { margin-left: 76rpx; margin-top: 178rpx; display: flex; justify-content: center; align-items: center; width: 520rpx; height: 104rpx; background: #8883F0; box-shadow: 0rpx 16rpx 40rpx 0rpx rgba(42, 130, 228, 0.1); border-radius: 52rpx 52rpx 52rpx 52rpx; font-size: 32rpx; font-family: HarmonyOS Sans SC, HarmonyOS Sans SC; font-weight: 400; color: #FFFFFF; } } } </style>