<template> <view class="page" style="width: 100%;height: 88vh;overflow: scroll;"> <u-navbar :title="tittxt" :border-bottom="false" :background="bgc" back-icon-color="#fff" title-color='#fff' :custom-back="btns" title-size='36' height='50' id="navbar"> </u-navbar> <view class="dltop"> <view class="dian_list"> <view class=""> {{sbobj.voltage == undefined ? '--' : sbobj.voltage}} </view> <view class=""> {{sbobj.electricity == undefined ? '--' : sbobj.electricity}} </view> <view class=""> {{sbobj.realTimePower == undefined ? '--' : sbobj.realTimePower}} </view> </view> <view class="dian_list"> <view class=""> 电压(V) </view> <view class=""> 电流(A) </view> <view class=""> 功率(W) </view> </view> <view class="botwz"> <!-- 点击刷新实时信息 --> <view @click="shuaxin" style="width: 100%;display: flex;color: #fff;justify-content: center;align-items: center;padding-top:40rpx;padding-bottom: 30rpx;box-sizing: border-box;"> 点击刷新实时信息 </view> </view> </view> <!-- 操作 --> <view class="card2" style="padding-bottom: 30rpx;box-sizing: border-box;margin-top: 0;" v-if="detaobj.suitFeeType == 1 || detaobj.suitFeeType == 4"> <view class="" style="display: flex;box-sizing: border-box;width: 100%; height: 80rpx;align-items: center;justify-content: space-between;border-radius: 20rpx;font-size: 32rpx;color: #3D3D3D;"> <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="time_list"> <view class="time_top"> <!-- <view class="" v-if="detaobj.suitEndTime && detaobj.suitFeeType == 1"> {{formattedTime}} </view> --> <view class="" v-if="detaobj.suitEndTime && detaobj.suitFeeType != 1"> 已结束 </view> <view class="" v-else> <text v-if="detaobj.suitFeeType == 3 || detaobj.suitFeeType == 4">{{timeDifferenceString == '' ? '1分' : timeDifferenceString}}</text> <text v-if="detaobj.suitFeeType == 2">{{du}}度</text> <text v-if="detaobj.suitFeeType == 1">{{formattedTime == '1秒' ? '0' : formattedTime}}</text> </view> <view class="" v-if="detaobj.suitEndTime"> ¥{{detaobj.money}} </view> <view class="" v-else> <text v-if="detaobj.suitFeeType == 3 || detaobj.suitFeeType == 4">¥{{feeprice}}</text> <text v-else>¥{{detaobj.suitPrice == null ? '--' : detaobj.suitPrice}}</text> </view> </view> <view class="time_bot" v-if="!detaobj.suitEndTime || detaobj.suitFeeType == 1"> <view class=""> <text v-if="detaobj.suitFeeType == 3 || detaobj.suitFeeType == 4">已使用时长</text> <text v-else>订单剩余</text> </view> <view class=""> <text v-if="detaobj.suitFeeType == 3 || detaobj.suitFeeType == 4">预估金额,以实际金额为准</text> <text v-else>金额</text> </view> </view> </view> <view class="price_list"> <view class="top_price"> 价格明细 </view> <view class="qian"> <view class="yajin"> <text v-if="detaobj.suitFeeType == 1">{{detaobj.suitTime == null ? '--' : detaobj.suitTime}}<text v-if="detaobj.suitTimeUnit == 2">时</text> <text v-if="detaobj.suitTimeUnit == 3">分钟</text> <text v-if="detaobj.suitTimeUnit == 4">秒</text></text> <text v-if="detaobj.suitFeeType == 2">{{detaobj.suitTime}}度</text> <text v-if="detaobj.suitFeeType == 3 || detaobj.suitFeeType == 4">押金</text> </view> <view class="yuan"> {{detaobj.suitPrice == null ? '--' : detaobj.suitPrice}}元 </view> </view> <view class="jisuan"> 计价方式:<text v-if="detaobj.suitFeeType == 1">计时收费</text> <text v-if="detaobj.suitFeeType == 2">按量收费</text> <text v-if="detaobj.suitFeeType == 3">分时段按量收费</text> <text v-if="detaobj.suitFeeType == 4">分时段按时收费</text> </view> <view class="list_box" style="width: 100%" v-if="detaobj.suitFeeType == 3 || detaobj.suitFeeType == 4"> <view class="ulbox"> <view class="ulli"> <view class="li" v-for="(val,gearAmountindex) in newArr" :key="gearAmountindex"> {{val}}元 </view> </view> <view class="olli"> <view class="li" v-for="(vals,timeindex) in 24" :key="timeindex"> {{timeindex + ':00'}} </view> </view> </view> </view> </view> <view class="zujie"> <view class="toptit"> 订单信息 </view> <view class="emilist"> <view class=""> 开始时间 </view> <view class=""> {{detaobj.suitStartTime == null ? '--' : detaobj.suitStartTime}} </view> </view> <!-- <view class="emilist"> <view class=""> 结束时间 </view> <view class=""> {{detaobj.suitEndTime == null ? '--' : detaobj.suitEndTime}} </view> </view> --> <view class="emilist"> <view class=""> 店铺名称 </view> <view class=""> {{detaobj.storeName == null ? '--' : detaobj.storeName}} </view> </view> <view class="emilist"> <view class=""> 详细地址 </view> <view class=""> {{detaobj.storeAddress == null ? '--' : detaobj.storeAddress}} </view> </view> <view class="emilist"> <view class=""> 套餐名称 </view> <view class=""> {{detaobj.suitName == null ? '--' : detaobj.suitName}} </view> </view> <view class="emilist"> <view class=""> 设备编号 </view> <view class=""> {{detaobj.deviceNo == null ?'--' : detaobj.deviceNo}} </view> </view> <view class="emilist"> <view class=""> 订单编号 </view> <view class=""> {{detaobj.billNo == null ? '--' : detaobj.billNo}} </view> </view> </view> <!-- 电话客服 --> <image class="imgtel" @click="btncall" src="https://api.ccttiot.com/smartmeter/img/static/uJtDyokYXyBVzIs6hXHv" mode=""></image> <view class=""> <view class="jieshu" v-if="jieshuflag"> <text v-if="detaobj.status == 1">立即支付</text> <text v-else>结束订单</text> </view> <view class="jieshu" v-else> <text v-if="detaobj.status == 1" @click="btnljzf">立即支付</text> <text v-else @click="btnjieshu">结束订单</text> </view> </view> <view class="mask" v-if="jieshufalg"></view> <!-- 点击结束弹窗 --> <view class="truebox" v-if="trueboxfalg"> <view class="titvalue"> 您要提前结束此订单吗? </view> <view class="titvalue"> 当前预估消费金额为{{Number(feeprice) < 0.01 ? '0.01' : feeprice}}元,实际消费以实际金额为准 <text v-if="detaobj.suitFeeMode == 2 && detaobj.suitFeeType == 3">用电量为{{Number(totalElectriQuantity) - Number(suitStartEle)}}度</text> </view> <view class="truebtn"> <view class="quxiao" @click="trueboxfalg = false"> 取消 </view> <view class="queding" @click="btnbox"> 确定 </view> </view> </view> <view class="mask" v-if="trueboxfalg"></view> </view> </template> <script> var xBlufi = require("@/page_components/blufi/xBlufi.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 { tdtxt: '开启', imgflag: false, checkeds: false, trueboxfalg: false, bgc: { backgroundColor: "#8883f0", }, ec: { lazyLoad: true }, deviceInfo: {}, loadings: false, info: '', tittxt: "设备详情", titlist: [ "全部", "电表", "水表", ], curtitidx: 0, id: '', timeday: '', imglist: '', token: '', userImgs: '', imgflag: true, mac: "", name: '', deviceId: '', storeId: '', qrResult: '', devicesList: [], setMode: null, vipflag: false, cztime: '', opflag: '', timer: null, newArr: [], detaobj: {}, timeDifferenceString: 0, timerId: null, sbid: '', onlineStatus: '', billId: '', orderno: '', jieshuflag: false, feeprice: '', temperature: null, du: '', totalElectriQuantity: '', suitStartEle: '', sbobj: {}, jieshufalg:false, channelId:'' } }, onLoad(option) { let id = option.id this.id = id this.$u.put(`/app/bill/${this.id}/refreshPayResult`).then(res => { this.getDevice() }) if (option.flag) { this.opflag = option.flag } }, 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.getDevice() this.timeday.seconds = 0 } else { // 展示秒或0(如果秒也为0) return this.timeday.seconds > 0 ? `${this.timeday.seconds}秒` : '0' } } }, onUnload: function() { console.log("unload "); xBlufi.listenDeviceMsgEvent(false, this.funListenDeviceMsgEvent); wx.closeBLEConnection({ deviceId: this.deviceId, }) }, // 分享到好友(会话) onShareAppMessage: function() { return { title: '创想物联', path: '/pages/shouye/index' } }, // 分享到朋友圈 onShareTimeline: function() { return { title: '创想物联', query: '', path: '/pages/shouye/index' } }, onShow() { setTimeout(() => { this.startTimers() if (this.id) { //判断有没有id 没有的话则直接返回首页 } else { uni.reLaunch({ url: '/pages/shouye/index' }) } }, 100) }, onHide() { this.stopTimer(); }, beforeDestroy() { // 组件销毁前清除定时器,防止内存泄漏 if (this.timer) { clearInterval(this.timer) this.timer = null; console.log('已销毁') } }, onUnload() { this.stopTimer(); }, methods: { // 点击拨打客服电话 btncall(){ let phoneNumber = '' phoneNumber = this.sbobj.userMobile uni.makePhoneCall({ phoneNumber: phoneNumber, success: function(res) { console.log('拨打电话成功', res) }, fail: function(err) { console.error('拨打电话失败', err) uni.showToast({ title: '拨打电话失败', icon: 'none' }) } }) }, // 开启和关闭 btnkq() { if (this.onlineStatus == 1) { if (this.tdtxt == '开启') { this.$u.put(`/app/device/${this.sbid}/changePower?status=0`).then((res) => { if (res.code == 200) { this.tdtxt = '关闭' this.imgflag = false 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.sbid}/changePower?status=1`).then((res) => { if (res.code == 200) { this.imgflag = true this.tdtxt = '开启' 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.ver_data == null) { this.jieshufalg = true uni.showLoading({ title: '切换中' }) 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.sbobj.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 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 xBlufi.notifySendCustomData({ customData: 'open' }) xBlufi.notifySendCustomData({ customData: '11open' }) }, 1000) }, fail(err) { console.error('获取已连接蓝牙设备信息失败:', err) } }) } } }) } } } }, // 点击进行强刷数据 shuaxin(){ this.$u.get(`/app/device/${this.sbid}/refreshIot`).then((res) => { if(res.code == 200){ this.getDevice() this.getsb() uni.showToast({ title: res.msg, icon: 'success', duration: 1500 }) }else{ uni.showToast({ title: res.msg, icon: 'none', duration: 1500 }) } }) }, // 获取channelId getzfqd(){ this.$u.get(`/app/channel/recharge/enabledList`).then(res =>{ if(res.code == 200){ this.channelId = res.data[0].channelId } }) }, // 点击默认返回首页 btns() { // if(this.opflag){ // uni.navigateBack() // }else{ uni.reLaunch({ url: '/pages/shouye/index' }) // } }, // 点击立即支付订单 btnljzf() { this.getzfqd() let data = { billNo: this.orderno, channelId: this.channelId } this.$u.put(`/app/bill/pay`, data).then((res) => { if (res.code == 200) { let that = this uni.requestPayment({ provider: 'wxpay', timeStamp: res.data.payParams.timeStamp, nonceStr: res.data.payParams.nonceStr, package: res.data.payParams.packageVal, signType: res.data.payParams.signType, paySign: res.data.payParams.paySign, success: (res) => { that.$u.put(`/app/bill/${that.orderno}/refreshPayResult`).then( res => {}) // 支付成功逻辑 uni.showToast({ title: res.msg, icon: 'success', duration: 1000 }) setTimeout(() => { that.jieshuflag = false uni.reLaunch({ url: '/pages/shouye/index' }) }, 2000) }, fail(err) { that.jieshuflag = false // 支付失败逻辑 uni.showToast({ title: '支付失败', icon: 'none', duration: 2000 }); } }) }else{ uni.showToast({ title: res.msg, icon: 'none', duration: 2000 }) } }) }, // 点击结束订单 btnjieshu() { this.getzfqd() if (this.detaobj.suitFeeMode == 1) { if (this.onlineStatus == 1) { let that = this uni.showModal({ title: '提示', content: '您确定要提前结束订单吗,将不会产生任何退款和赔偿?', success: function(res) { if (res.confirm) { let data = { billId: that.billId } that.$u.put(`/app/bill/endUse`, data).then(res => { if (res.code == 200) { if(res.data.deviceResult == false){ uni.showToast({ title: res.data.deviceMsg, icon: 'none', duration: 2000 }) setTimeout(()=>{ uni.reLaunch({ url: '/pages/shouye/index' }) },1500) }else{ uni.reLaunch({ url: '/pages/shouye/index' }) } } else { uni.showToast({ title: res.msg, icon: 'none', duration: 1000 }) } }) } } }) } else { if (this.temperature == null) { this.jieshufalg = true uni.showLoading({ title: '切换中' }) let that = this xBlufi.initXBlufi(1); xBlufi.listenDeviceMsgEvent(true, that.funListenDeviceMsgEvent); xBlufi.notifyStartDiscoverBle({ 'isStart': true }) setTimeout(() => { xBlufi.notifyStartDiscoverBle({ 'isStart': false }) if (that.devicesList.length > 0) { xBlufi.notifyConnectBle({ isStart: true, deviceId: that.deviceId, name: that.name }) } }, 2000) uni.showModal({ title: '温馨提示', content: `检测到该设备未联网,为您切换为蓝牙模式,支付的时候靠近该设备,并打开蓝牙`, showCancel: false, success: function(res) { } }) } else { this.jieshufalg = true let data = { billId: this.billId, } this.$u.put(`/app/bill/endUse`, data).then(res => { if (res.code == 200) { uni.getNetworkType({ success(res) { if (res.networkType !== 'none') { uni.getConnectedBluetoothDevices({ success(res) { setTimeout(() => { xBlufi.notifySendCustomData({ customData: 'close' }) xBlufi.notifySendCustomData({ customData: '11close' }) uni.showToast({ title: res.msg, icon: 'success', duration: 2000 }) this.jieshufalg = false setTimeout(() => { uni.reLaunch({ url: '/pages/shouye/index' }) }, 1000) }, 1500) }, fail(err) { console.error('获取已连接蓝牙设备信息失败:', err) } }) } else { console.log('手机未连接网络') // this.baiflag = false } } }) } else { uni.showToast({ title: res.msg, icon: 'none', duration: 2000 }) } }) } } } else { this.getsb() this.trueboxfalg = true } }, // 分时段支付订单 btnbox() { this.trueboxfalg = false this.jieshuflag = true if (this.onlineStatus == 1) { if (this.detaobj.suitFeeType == 1 || this.detaobj.suitFeeType == 2) { let data = { billId: this.billId } this.$u.put(`/app/bill/endUse`, data).then(res => { if (res.code == 200) { uni.showToast({ title: res.msg, icon: 'success', duration: 1000 }) setTimeout(() => { this.jieshuflag = false uni.reLaunch({ url: '/pages/shouye/index' }) }, 1500) } else { this.getDevice() this.jieshuflag = false uni.showToast({ title: res.msg, icon: 'none', duration: 2000 }) } }) } else { if (this.detaobj.status == 1) { let data = { billNo: this.orderno, channelId: this.channelId } this.$u.put(`/app/bill/pay`, data).then((res) => { if (res.code == 200) { let that = this uni.requestPayment({ provider: 'wxpay', timeStamp: res.data.payParams.timeStamp, nonceStr: res.data.payParams.nonceStr, package: res.data.payParams.packageVal, signType: res.data.payParams.signType, paySign: res.data.payParams.paySign, success: (res) => { that.$u.put(`/app/bill/${that.orderno}/refreshPayResult`).then(res => {}) // 支付成功逻辑 uni.showToast({ title: res.msg, icon: 'success', duration: 1000 }) setTimeout(() => { that.jieshuflag = false uni.reLaunch({ url: '/pages/shouye/index' }) }, 1500) }, fail(err) { that.getDevice() that.jieshuflag = false // 支付失败逻辑 uni.showToast({ title: '支付失败', icon: 'none', duration: 2000 }); } }) }else{ uni.showToast({ title: res.msg, icon: 'none', duration: 2000 }) } }) } else { let data = { billId: this.billId } this.$u.put(`/app/bill/endUse`, data).then(res => { if (res.code == 200) { let data = { billNo: this.orderno, channelId: this.channelId } this.$u.put(`/app/bill/pay`, data).then((res) => { if (res.code == 200) { let that = this uni.requestPayment({ provider: 'wxpay', timeStamp: res.data.payParams.timeStamp, nonceStr: res.data.payParams.nonceStr, package: res.data.payParams.packageVal, signType: res.data.payParams.signType, paySign: res.data.payParams.paySign, success: (res) => { that.$u.put(`/app/bill/${that.orderno}/refreshPayResult`).then(res => {}) // 支付成功逻辑 uni.showToast({ title: res.msg, icon: 'success', duration: 1000 }) setTimeout(() => { that.jieshuflag = false uni.reLaunch({ url: '/pages/shouye/index' }) }, 1500) }, fail(err) { that.jieshuflag = false // 支付失败逻辑 uni.showToast({ title: '支付失败', icon: 'none', duration: 2000 }) } }) } }) } else { this.getDevice() this.jieshuflag = false uni.showToast({ title: res.msg, icon: 'none', duration: 2000 }) } }) } } } else { // console.log(this.temperature,'this.temperature'); if (this.temperature == null) { uni.showLoading({ title: '切换中' }) let that = this xBlufi.initXBlufi(1); xBlufi.listenDeviceMsgEvent(true, that.funListenDeviceMsgEvent); xBlufi.notifyStartDiscoverBle({ 'isStart': true }) setTimeout(() => { xBlufi.notifyStartDiscoverBle({ 'isStart': false }) if (that.devicesList.length > 0) { xBlufi.notifyConnectBle({ isStart: true, deviceId: that.deviceId, name: that.name }) } }, 2000) uni.showModal({ title: '温馨提示', content: `检测到该设备未联网,为您切换为蓝牙模式,支付的时候靠近该设备,并打开蓝牙`, showCancel: false, success: function(res) { } }) } else { if (this.detaobj.suitFeeType == 1 || this.detaobj.suitFeeType == 2) { let data = { billId: this.billId, totalEle: this.temperature } this.$u.put(`/app/bill/endUse`, data).then(res => { if (res.code == 200) { uni.getNetworkType({ success(res) { if (res.networkType !== 'none') { uni.getConnectedBluetoothDevices({ success(res) { setTimeout(() => { xBlufi.notifySendCustomData({ customData: 'close', }) xBlufi.notifySendCustomData({ customData: '11close', }) setTimeout(() => { this.jieshuflag = false uni.reLaunch({ url: '/pages/shouye/index' }) }, 1000) }, 1500) }, fail(err) { console.error('获取已连接蓝牙设备信息失败:', err) } }) } else { console.log('手机未连接网络') // this.baiflag = false } } }) } else { this.jieshuflag = false uni.showToast({ title: res.msg, icon: 'none', duration: 2000 }) } }) } else { let data = { billId: this.billId, totalEle: this.temperature } this.$u.put(`/app/bill/endUse`, data).then(res => { if (res.code == 200) { let that = this uni.getNetworkType({ success(res) { if (res.networkType !== 'none') { uni.getConnectedBluetoothDevices({ success(res) { setTimeout(() => { xBlufi.notifySendCustomData({ customData: 'close', }) xBlufi.notifySendCustomData({ customData: '11close', }) setTimeout(() => { let data = { billNo: that.orderno, channelId: that.channelId } that.$u.put(`/app/bill/pay`,data).then((res) => { if (res.code ==200) { uni.requestPayment({ provider: 'wxpay', timeStamp: res.data.payParams.timeStamp, nonceStr: res.data.payParams.nonceStr, package: res.data.payParams.packageVal, signType: res.data.payParams.signType, paySign: res.data.payParams.paySign, success: (res) => { that.$u.put(`/app/bill/${that.orderno}/refreshPayResult`).then(res => {}) // 支付成功逻辑 uni.showToast({ title: res .msg, icon: 'success', duration: 1000 }) setTimeout(() => { that.jieshuflag = false uni.reLaunch({ url: '/pages/shouye/index' }) },1500) }, fail(err) { that.jieshuflag = false // 支付失败逻辑 uni.showToast({ title: '支付失败', icon: 'none', duration: 2000 }) } }) } }) }, 1000) }, 1500) }, fail(err) { console.error('获取已连接蓝牙设备信息失败:', err) } }) } else { console.log('手机未连接网络') // this.baiflag = false } } }) } else { this.getDevice() this.jieshuflag = false uni.showToast({ title: res.msg, icon: 'none', duration: 2000 }) } }) } } } }, // 每一分钟请求更新一次 startTimers() { // 确保没有重复的定时器 if (this.timerId !== null) { clearInterval(this.timerId) } // 设置定时器,每分钟执行一次 timerCallback 函数 this.timerId = setInterval(this.getDevice, 60000) }, // 销毁定时器 stopTimer() { if (this.timerId !== null) { clearInterval(this.timerId) this.timerId = null } }, // 预估金额 getprice() { this.$u.get(`app/bill/calcPrice?billId=${this.billId}`).then(res => { if (res.code == 200) { this.feeprice = res.data.toFixed(2) } }) }, // 获取设备详情 getDevice() { this.$u.get(`/app/bill/byNo/${this.id}`).then(res => { if (res.code == 200) { this.sbid = res.data.deviceId this.suitStartEle = res.data.suitStartEle //设备开始前用电 this.getsb() this.detaobj = res.data this.billId = res.data.billId this.orderno = res.data.billNo this.getprice() let dateTimeString = res.data.suitStartTime // 示例时间字符串 this.timeDifferenceString = this.calculateTimeDifference(dateTimeString); // 调用函数 // console.log(timeDifferenceString); if (res.data.suitGearAmount.length > 0) { this.newArr = [] for (let i = 0; i < res.data.suitGearTime.length; i++) { let value = res.data.suitGearAmount[res.data.suitGearTime[i]]; this.newArr.push(value) } } if (this.detaobj.suitEndEle) { let du = Number(this.detaobj.suitEndEle) - Number(this.detaobj.deviceTotalEle) this.du = du.toFixed(2) } if (this.detaobj.suitExpireTime == null) { this.timeday = 0 } else { let expireTimeStr = this.detaobj.suitExpireTime 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 { if (this.timeday == '') { this.timeday = this.formatMilliseconds(differenceInMs) this.startTimer() } } } } }) }, getsb() { this.$u.get(`/app/device/${this.sbid}`).then(res => { if (res.code == 200) { this.sbobj = res.data if (this.sbobj.powerStatus == 0) { this.imgflag = false } else { this.imgflag = true } this.onlineStatus = res.data.onlineStatus this.qrResult = res.data.mac this.totalElectriQuantity = res.data.totalElectriQuantity } }) }, calculateTimeDifference(dateTimeString) { // 将时间字符串转换为Date对象 const date = new Date(dateTimeString) // 获取当前时间 const now = new Date() // 计算时间差(毫秒) const diff = now - date // 将毫秒转换为天、小时、分钟和秒 const days = Math.floor(diff / (1000 * 60 * 60 * 24)) const hours = Math.floor((diff % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60)) const minutes = Math.floor((diff % (1000 * 60 * 60)) / (1000 * 60)) const seconds = Math.floor((diff % (1000 * 60)) / 1000) // 创建一个对象来存储结果,并忽略零值 const timeDifference = { days: days > 0 ? days : undefined, hours: hours > 0 ? hours : undefined, minutes: minutes > 0 ? minutes : undefined, seconds: seconds > 0 ? seconds : undefined }; // 转换为字符串,忽略未定义的属性 let result = '' if (timeDifference.days !== undefined) { result += `${timeDifference.days}天` } if (timeDifference.hours !== undefined) { result += `${timeDifference.hours}时` } if (timeDifference.minutes !== undefined) { result += `${timeDifference.minutes + 1}分` } // if (timeDifference.seconds !== undefined) { // result += `${timeDifference.seconds}秒` // } return result; }, 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) => { // this.$forceUpdate() if (res.code == 200) { // this.groupList=res.rows setTimeout(() => { this.getDevice() }, 2000) // this.loadings=true // this.initChart() } 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 }) }, funListenDeviceMsgEvent: function(options) { switch (options.type) { case xBlufi.XBLUFI_TYPE.TYPE_GET_DEVICE_LISTS: if (options.result) { let devicesarr = options.data console.log(devicesarr, this.mac, '111'); devicesarr.forEach(device => { const mac = device.name.substring(4); if (device.name.slice(5, 17) == this.qrResult) { this.deviceId = device.deviceId this.name = device.name // console.log(device.name,this.mac,'222'); this.devicesList.push(device); let uniqueDevicesList = Array.from(new Set(this.devicesList)); // 将去重后的数组重新赋值给 this.devicesList this.devicesList = uniqueDevicesList; } else { // uni.showToast({ // title: '未找到该设备,请确认该设备在附近', // icon: 'none', // duration: 3000 // }) } }) } break; case xBlufi.XBLUFI_TYPE.TYPE_CONNECTED: console.log("连接回调:" + JSON.stringify(options)); if (options.result) { // console.log('125451245') { xBlufi.notifyInitBleEsp32({ deviceId: this.deviceId }) xBlufi.listenDeviceMsgEvent(true, this.funListenDeviceMsgEvents); this.deviceIds = options.data.deviceId this.name = this.name } } else { } break; case xBlufi.XBLUFI_TYPE.TYPE_RECIEVE_CUSTON_DATA: this.ver_data = this.parseCustomData(options.data) console.log("1收到设备发来的自定义数据结果:", this.ver_data) this.temperature = this.ver_data.temperature / 1000 setTimeout(() => { // this.czflag = false this.jieshuflag = false this.jieshufalg = false uni.hideLoading() }, 1000) break case xBlufi.XBLUFI_TYPE.TYPE_GET_DEVICE_LISTS_STOP: if (options.result) { let uniqueDevicesList = Array.from(new Set(this.devicesList)); let filteredDevices = uniqueDevicesList.filter(device => device.name.substring(0, 4) === "CTKG"); // 将过滤后的数组重新赋值给 this.devicesList this.devicesList = filteredDevices; } break case xBlufi.XBLUFI_TYPE.TYPE_GET_DEVICE_LISTS_START: if (!options.result) { this.lanyaflag = true uni.showToast({ title: '蓝牙未开启', icon: 'none', duration: 3000 }) return } else { this.lanyaflag = false } break } }, 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 }, // 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 // } // }, } } </script> <style lang="scss"> /deep/ .u-title { padding-bottom: 22rpx; } /deep/ .u-icon__icon { padding-bottom: 22rpx; } .imgtel{ position: fixed; left: 36rpx; bottom: 78rpx; width: 90rpx; height: 90rpx; z-index: 99; } page { background-color: #F7FAFE; padding: 0 30rpx; box-sizing: border-box; padding-bottom: 300rpx; overflow: scroll; } .card2 { padding-top: 40rpx; margin-top: 70rpx; // width: 670rpx; max-height: 314rpx; // background: #FFFFFF; // box-shadow: 0rpx 16rpx 40rpx 0rpx rgba(53, 140, 255, 0.1); border-radius: 28rpx; .aa{ padding-left: 40rpx; padding-right: 40rpx; box-sizing: border-box; display: flex; justify-content: space-between; margin-top: 10rpx; font-size: 28rpx; color: #808080; } .tit { margin-left: 40rpx; font-size: 36rpx; color: #3D3D3D; font-weight: 600; } .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; } } } } .truebox { width: 500rpx; max-height: 380rpx; border-radius: 20rpx; background-color: #fff; position: fixed; top: 40%; left: 50%; transform: translateX(-50%); z-index: 99; padding: 30rpx; box-sizing: border-box; .titvalue { width: 100%; text-align: center; margin-top: 30rpx; font-size: 32rpx; } .truebtn { display: flex; margin-top: 30rpx; .quxiao { border-right: 1px solid #ccc; } view { width: 50%; text-align: center; height: 90rpx; line-height: 90rpx; border-top: 1px solid #ccc; } } } .jieshu { width: 558rpx; height: 90rpx; text { width: 558rpx; height: 90rpx; display: block; } line-height: 90rpx; background: #8883F0; border-radius: 54rpx 54rpx 54rpx 54rpx; font-size: 36rpx; color: #FFFFFF; // font-weight: 600; text-align: center; position: fixed; bottom: 76rpx; left: 58%; transform: translateX(-50%); } .zujie { margin-top: 32rpx; .toptit { font-size: 32rpx; color: #333333; font-weight: 600; } .emilist { display: flex; justify-content: space-between; margin-top: 28rpx; view { font-size: 24rpx; color: #808080; } } } .price_list { border-bottom: 1px solid #D8D8D8; padding-bottom: 26rpx; box-sizing: border-box; .top_price { font-size: 32rpx; color: #333333; font-weight: 600; margin-top: 24rpx; margin-bottom: 28rpx; } .jisuan { font-size: 24rpx; color: #333333; margin-top: 24rpx; margin-bottom: 30rpx; } .qian { width: 100%; display: flex; justify-content: space-between; .yuan { font-size: 24rpx; color: #333333; } .yajin { font-size: 24rpx; color: #808080; } } } .list_box { .ulbox { width: 100%; overflow: scroll; .ulli { display: flex; width: 170vh; .li { flex: 1; border: 1rpx solid #ccc; text-align: center; font-size: 32rpx; color: #8883F0; height: 88rpx; line-height: 88rpx; } } .olli { display: flex; width: 170vh; .li { flex: 1; border: 1rpx solid #ccc; text-align: center; font-size: 22rpx; color: #262B37; height: 88rpx; line-height: 88rpx; } } } } .time_list { width: 100%; border-bottom: 1px solid #D8D8D8; padding-bottom: 34rpx; box-sizing: border-box; .time_top { display: flex; justify-content: space-between; margin-top: 20rpx; view { font-size: 40rpx; color: #3D3D3D; font-weight: 600; } } .time_bot { display: flex; justify-content: space-between; margin-top: 30rpx; view { font-size: 24rpx; color: #666666; } } } .dltop { width: 100%; height: 224rpx; background: #8883F0; border-radius: 16rpx 16rpx 16rpx 16rpx; margin: auto; margin-top: 36rpx; padding-bottom: 20rpx; box-sizing: border-box; .dian_list { display: flex; justify-content: space-between; text-align: center; font-size: 34rpx; color: #FFFFFF; view { width: 180rpx; text-align: center; margin-top: 22rpx; } } .botwz { font-size: 28rpx; color: #FFFFFF; width: 100%; text-align: center; } } .mask { 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; height: 282rpx; background: #FFFFFF; border-radius: 30rpx 30rpx 30rpx 30rpx; position: fixed; top: 628rpx; 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: 62rpx; background: #EEEEEE; border-radius: 6rpx 6rpx 6rpx 6rpx; margin: auto; margin-top: 22rpx; padding-left: 20rpx; } .xian { width: 610rpx; height: 2rpx; background: #D8D8D8; 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: 260rpx; background: #FFFFFF; box-shadow: 0rpx 14rpx 35rpx 0rpx rgba(53, 140, 255, 0.1); border-radius: 28rpx 28rpx 0rpx 0rpx; .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: 40rpx; 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; .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: 19rpx; // width: 38rpx; // height: 23rpx; 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: 53rpx; display: flex; flex-wrap: nowrap; align-items: center; .bot_left { width: 210rpx; height: 180rpx; margin-right: 34rpx; .echarts { // width: 210rpx; height: 200rpx; .uni-ec-canvas { width: 100%; height: 100rpx !important; display: block; // margin-top: 30rpx; } } } .bot_right { // margin-top: 50rpx; display: flex; // flex-wrap: nowrap; width: 100%; justify-content: space-between; padding-left: 210rpx; 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 { // margin-top: 50rpx; display: flex; // flex-wrap: nowrap; width: 100%; justify-content: space-between; padding-left: 220rpx; 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; margin-left: 0; } .txt { font-size: 26rpx; font-family: HarmonyOS Sans SC, HarmonyOS Sans SC; font-weight: 400; color: #262B37; } } } .card2 { padding-top: 0rpx; width: 100%; height: 60rpx; // background: #FFFFFF; border-radius: 0 0 28rpx 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: 110rpx; 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; // height: 318rpx; 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-left: 30rpx; // padding-right: 30rpx; padding: 0 40rpx; margin-top: 32rpx; display: flex; flex-wrap: nowrap; justify-content: space-around; .cont:last-child { margin-right: 0rpx; } .cont { width: 112rpx; display: flex; flex-wrap: wrap; align-items: center; justify-content: center; margin-right: 80rpx; .top { image { width: 56rpx; height: 56rpx; } } .bot { margin-top: 15rpx; 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>