<template> <view class="pages"> <view class="title"> <image src="https://api.ccttiot.com/smartmeter/img/static/ux6MC6FBl41qHB3f2SZh" mode="" style="width: 54rpx;height: 56rpx;margin-right: 10rpx;vertical-align: bottom;vertical-align: bottom;" @click="btnshouye"></image> <text style="width: 80%;text-align: center;display: inline-block;">{{obj.deviceName}}</text> <view class="wz" @click="call" style="text-align: right;padding-right: 50rpx;" v-if="obj.storeContactMobile == null"> <image style="width: 48rpx;height: 50rpx;vertical-align: middle;" src="https://api.ccttiot.com/smartmeter/img/static/u9bYsfyXGAMwKMFfQAmL" mode=""></image> <!-- <text>客服</text> --> </view> <view class="wz" @click="call" style="text-align: right;padding-right: 50rpx;" v-else> <image style="width: 60rpx;height: 64rpx;vertical-align: middle;" src="https://api.ccttiot.com/smartmeter/img/static/u9bYsfyXGAMwKMFfQAmL" mode=""></image> <!-- <text>客服</text> --> </view> </view> <view class=""> <!-- 套餐 --> <view class="list"> <view class="list_item" :class="activeindex == item.suitId ? 'active' : ''" v-for="(item,index) in list" :key="index" @click="btnactive(item)"> <view class="tit"> <text class="tc" :class="activeindex == item.suitId ? 'active' : ''">{{item.name}}</text> <text class="yh" :class="activeindex == item.suitId ? 'actives' : ''">{{item.usePoint}}%用户选择</text> </view> <view class="bot"> <view class="price" :class="activeindex == item.suitId ? 'active' : ''"> ¥{{item.price}} </view> <view class="time" :class="activeindex == item.suitId ? 'active' : ''"> 可使用{{item.value}} {{item.timeUnit == 3 ? '分钟' : '小时'}} </view> </view> </view> </view> <!-- 说明 --> <view class="shuom"> <view class="shuomtit"> 功能介绍 </view> <view class="cont" style="height: 208rpx;"> {{obj.funcInfo == undefined ? '暂无介绍...' : obj.funcInfo}} </view> </view> <view class="shuom" style="max-height: 220rpx;margin-top: 30rpx;"> <view class="shuomtit"> 设备地址 </view> <view class="shuomwz"> <image style="width: 30rpx;height: 30rpx;margin-right: 6rpx;" src="https://api.ccttiot.com/smartmeter/img/static/umUFE9oFeYo2Q7atp3jv" mode=""></image> {{obj.storeName == undefined ? '' : obj.storeName}} {{obj.room == undefined ? '--' : obj.room}}室 </view> <view class="shuomwz"> <image style="width: 30rpx;height: 30rpx;margin-right: 6rpx;" src="https://api.ccttiot.com/smartmeter/img/static/uHHgD7nRON3WTmomzKVE" mode=""></image> {{obj.storeAddress ? (obj.storeAddress.length > 18 ? obj.storeAddress.substring(0, 18) + '...' : obj.storeAddress) : '' }} </view> </view> <!-- 支付 --> <view class="tongyi"> <u-checkbox-group> <u-checkbox v-model="checked" @change="checkboxChange" active-color="#8883F0 ">我已同意 </u-checkbox><text @click="btnxieyi">《用户服务协议》</text> </u-checkbox-group> <view class="zf" v-if="zhifuflag" @click="btnzhifu"> 立即支付 </view> <view class="zf" v-else> 立即支付 </view> </view> </view> <!-- <view class="mask" v-if="zfflag"></view> --> <!-- 背景 --> <view class="" style="position: fixed;top: 0;left: 0;width: 100%;height: 100vh;z-index: -1;"> <image style="width: 100%;height: 100vh;" src="https://api.ccttiot.com/smartmeter/img/static/uOiCQSDjukktdvbx5oPw" mode=""></image> </view> <!-- 客服列表 --> <view class="kflist" v-if="kfflag"> <view class="kftit"> 请选择您要联系的客服 </view> <view class="kfwz"> 我们根据选择为您提供服务 </view> <view class="kfshuzu"> <view class="item_val" v-for="(item,index) in kefulist" :key="index" @click="btncall(item.mobile)"> <view class="lt"> <image v-if="item.type == 2" src="https://api.ccttiot.com/smartmeter/img/static/urCSQTavLmUje5oTIsE6" mode=""></image> <image v-if="item.type == 3" src="https://api.ccttiot.com/smartmeter/img/static/uE5rZZvVutxxUj9I06m5" mode=""></image> <image v-if="item.type == 4" src="https://api.ccttiot.com/smartmeter/img/static/uruHLe3W460sdXr2lcxF" mode=""></image> </view> <view class="rt"> <view class="" v-if="item.type == 2">{{item.name}}</view> <view class="" v-if="item.type == 3">运维人员:{{item.name}}</view> <view class="" v-if="item.type == 4">酒店客服:{{item.name}}</view> <view class="" style="margin-top: 10rpx;">{{item.mobile}}</view> </view> </view> </view> </view> <view class="qx" @click="kfflag = false" v-if="kfflag"> × </view> <view class="mask" v-if="kfflag"></view> <!-- 蓝牙充值动画 --> <view class="czdh" v-if="jzflag"> <view class="bj"> <view class="tittop"> 正在充值中,请稍后 </view> <view class="bfb"> {{progress}} % </view> </view> </view> </view> </template> <script> var xBlufi = require("@/components/blufi/xBlufi.js"); export default { data() { return { jine:'', zfflag:false, jzflag:false, progress: 0, mac:'', deviceId: '', name: '', czflag: false, lanyaflag: false, ver_data: '', devicesList: [], bgc: { // backgroundColor: "#8883f0", }, checked: false, zhifuflag: true, activeindex: -1, id: '', list: [], obj:{}, orderno:'', payNo:'', prices:'', sytime:'', zfobj:{}, suitTimeUnit:'', suitPrice:'', suitGearAmount:'', suitGearTime:'', suitFeeMode:'', suitFeeType:'', title:'', sbobj:{}, onlineStatus:'', kfflag:false, timer:null, titflag:false, kefulist:[] } }, onLoad(option) { if (option.q) { function getQueryParam(url, paramName) { let regex = new RegExp(`[?&]${paramName}=([^&]*)`) let results = regex.exec(url); return results ? decodeURIComponent(results[1].replace(/\+/g, ' ')) : null } this.sceneValue = option.q let decodedValue = decodeURIComponent(this.sceneValue) this.id = getQueryParam(decodedValue, 's') this.$u.get(`/app/user/userInfo`).then(res => { if(res.code == 200){ this.getlist() }else if(res.code == 401){ uni.navigateTo({ url:'/pages/login/login?id=' + this.id }) } }) } else { this.id = option.id this.$u.get(`/app/user/userInfo`).then(res => { if(res.code == 200){ this.getlist() }else if(res.code == 401){ uni.navigateTo({ url:'/pages/login/login?id=' + this.id }) } }) } }, onUnload: function() { if (this.timer) { clearInterval(this.timer) this.timer = null; } xBlufi.listenDeviceMsgEvent(false, this.funListenDeviceMsgEvent); xBlufi.notifyStartDiscoverBle({ 'isStart': false }) }, // 分享到好友(会话) onShareAppMessage: function() { return { title: '创亿康', path: '/pages/index/index' } }, // 分享到朋友圈 onShareTimeline: function() { return { title: '创亿康', query: '', path: '/pages/index/index' } }, methods: { // 点击协议跳转 btnxieyi(){ uni.navigateTo({ url: '/page_fenbao/shiyong?tit=' + '用户服务协议' + '&type=' + 'user' }) }, // 获取设备客服 getkefu(){ this.$u.get(`/app/device/${this.obj.deviceId}/service`).then(res => { if(res.code == 200){ this.kefulist = res.data } }) }, // 获取设备套餐列表 getlist() { this.$u.get(`app/device/${this.id}/withSuitList`).then((res) => { if (res.code == 200) { this.list = res.data.suitList this.obj = res.data this.onlineStatus = res.data.onlineStatus this.mac = 'CTKG-' + res.data.mac this.getkefu() }else if(res.code == 401){ uni.navigateTo({ url:'/pages/login/login' }) } }) }, // 点击支付 btnzhifu() { if(this.onlineStatus == 0){ if (this.ver_data == '') { this.czflag = 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, }) setTimeout(()=>{ if(that.ver_data == ''){ uni.showToast({ title: '未连接成功,如多次失败请点击右上角联系客服咨询', icon: 'none', duration: 5000 }) that.czflag = false setTimeout(()=>{ uni.hideLoading() },5000) } },18000) }else{ this.zhifuflag = false let that = this let data = { deviceNo: that.id, suitId: that.zfobj.suitId, money: that.zfobj.price, suitTime: that.zfobj.value, suitTimeUnit:that.suitTimeUnit, suitFeeMode:that.suitFeeMode, suitFeeType:that.suitFeeType, suitGearAmount:that.suitGearAmount, suitGearTime:that.suitGearTime, suitPrice:that.suitPrice } that.$u.post('/app/bill/recharge', data).then(res => { if(res.code == 200){ that.orderno = res.data that.$u.get(`/app/pay/wx/${that.orderno}`).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) => { if (that.timer) { clearInterval(this.timer); that.timer = null; } // 111111111111111111111111 that.$u.put(`/app/bill/${that.orderno}/refreshPayResult`).then(res =>{ // if(res.code == 200){ that.$u.get('/app/bill/recharge/device/fail/list').then(res => { if (res.code == 200) { if(res.data.length != 0){ let dingobj = res.data[0].billNo uni.getNetworkType({ success(res) { if (res.networkType !== 'none') { uni.getConnectedBluetoothDevices({ success(res) { that.jzflag = true that.startLoading() setTimeout(()=> { xBlufi.notifySendCustomData({ customData: "time@" + that.jine }) },1500) }, fail(err) { console.error('获取已连接蓝牙设备信息失败:',err) } }) that.$u.get(`/app/bill/recharge/${dingobj}/bluetoothSuccess`).then(res => { if (res.code == 200) { that.zhifuflag = true console.log('蓝牙离线充值成功11') setTimeout(() => { uni.reLaunch({ url:'/pages/index/index?id=' + that.orderno }) },1000) } }) } else { console.log('手机未连接网络') // this.baiflag = false } } }) }else{ uni.getNetworkType({ success(res) { if (res.networkType !== 'none') { uni.getConnectedBluetoothDevices({ success(res) { that.jzflag = true that.startLoading() setTimeout(()=> { xBlufi.notifySendCustomData({ customData: "time@" + that.jine }) },1500) }, fail(err) { console.error('获取已连接蓝牙设备信息失败:',err) } }) that.zhifuflag = true setTimeout(() => { uni.reLaunch({ url:'/pages/index/index?id=' + that.orderno }) },1000) } else { console.log('手机未连接网络') // this.baiflag = false } } }) } } }) // } }) // 支付成功逻辑 uni.setStorageSync('time', that.expireTimeStr) }, fail(err) { this.zhifuflag = true setTimeout(() => { this.czflag = false uni.hideLoading() }, 500) // 支付失败逻辑 uni.showToast({ title: '支付失败', icon: 'none', duration: 2000 }); } }) }else{ this.zhifuflag = true } }) } }) } }else{ if(this.checked == false){ uni.showToast({ title: '请勾选用户服务协议 !', icon: 'none', duration: 1000 }) }else if(this.activeindex == -1){ uni.showToast({ title: '请选择套餐 !', icon: 'none', duration: 1000 }) }else{ // 不允许一直点击支付 this.zhifuflag = false let that = this let data = { deviceNo: that.id, suitId: that.zfobj.suitId, money: that.zfobj.price, suitTime: that.zfobj.value, suitTimeUnit:that.suitTimeUnit, suitFeeMode:that.suitFeeMode, suitFeeType:that.suitFeeType, suitGearAmount:that.suitGearAmount, suitGearTime:that.suitGearTime, suitPrice:that.suitPrice } that.$u.post('/app/bill/recharge', data).then(res => { if(res.code == 200){ that.orderno = res.data let data = { billNo:that.orderno, channelId:1 } that.$u.get(`app/pay/wx/${that.orderno}`).then(res => { if(res.code == 200){ that.payNo = res.data.payBill.payNo 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.zhifuflag = true that.$u.put(`/app/bill/${that.payNo}/refreshPayResult`).then(res => {}) // 支付成功逻辑 uni.reLaunch({ url:'/pages/index/index' }) }, fail(err) { that.zhifuflag = true // 支付失败逻辑 uni.showToast({ title: '支付失败', icon: 'none', duration: 2000 }) } }) }else{ uni.showToast({ title: res.msg, icon: 'none', duration: 2000 }) setTimeout(()=>{ this.zhifuflag = true },2000) } }) }else{ uni.showToast({ title: res.msg, icon: 'none', duration: 2000 }) setTimeout(()=>{ this.zhifuflag = true },2000) } }) } } }, // 蓝牙充值动画 startLoading() { this.isLoading = true; const intervalId = setInterval(() => { this.progress += 100 / 100; // 每次增加 1 if (this.progress >= 99) { clearInterval(intervalId); this.isLoading = false; this.progress = 98; // 确保进度条最终达到98 } }, 15); }, // 获取附近蓝牙设备列表 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.mac.slice(5, 17)) { this.deviceId = device.deviceId this.name = device.name this.devicesList.push(device); let uniqueDevicesList = Array.from(new Set(this.devicesList)); // 将去重后的数组重新赋值给 this.devicesList this.devicesList = uniqueDevicesList; } }) } 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); setTimeout(()=>{ this.czflag = 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 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 }; }, btnactive(item) { this.activeindex = item.suitId this.prices = item.price this.sytime = item.value this.zfobj = item this.suitTimeUnit = item.timeUnit this.suitPrice = item.price this.suitGearAmount = item.gearAmount this.suitGearTime = item.gearTime this.suitFeeMode = item.feeMode this.suitFeeType = item.feeType if(item.timeUnit == 1){ this.jine = item.value * 24 * 60 * 60 }else if(item.timeUnit == 2){ this.jine = item.value * 60 * 60 }else if(item.timeUnit == 3){ this.jine = item.value * 60 }else if(item.timeUnit == 4){ this.jine = item.value } }, btnshouye() { uni.reLaunch({ url: '/pages/index/index' }) }, checkboxChange(e) { this.checked = e.value }, // 联系客服 call() { this.kfflag = true }, // 拨打客服电话 btncall(mobile){ uni.makePhoneCall({ phoneNumber: mobile, success: function(res) { console.log('拨打电话成功', res) }, fail: function(err) { console.error('拨打电话失败', err) uni.showToast({ title: '拨打电话失败', icon: 'none' }) } }) } } } </script> <style lang="scss" scoped> .active { background-color: #918CFF !important; color: #fff !important; } .actives { background-color: #fff !important; } /deep/ .u-title { padding-bottom: 15rpx; } .czdh{ width: 100%; height: 100vh; position: fixed; top: 0; left: 0; background-color: rgba(0, 0, 0, .5); padding-top: 700rpx; .bj{ width: 500rpx; height: 300rpx; background-color: #fff; margin: auto; border-radius: 20rpx; .tittop{ width: 100%; text-align: center; padding-top: 50rpx; box-sizing: border-box; } .bfb{ width: 100%; text-align: center; padding-top: 50rpx; box-sizing: border-box; font-size: 50rpx; } } } .qx{ width: 68rpx; height: 68rpx; background: #fff; border-radius: 50%; text-align: center; line-height: 68rpx; font-size: 50rpx; color: #3D3D3D; margin: auto; bottom: 420rpx; z-index: 1; position: fixed; left: 50%; transform: translateX(-50%); } .kflist{ width: 590rpx; height: 778rpx; background: #FFFFFF; border-radius: 28rpx 28rpx 28rpx 28rpx; position: fixed; top: 326rpx; left: 50%; transform: translateX(-50%); z-index: 1; padding-top: 48rpx; box-sizing: border-box; .kftit{ font-size: 40rpx; color: #3D3D3D; font-weight: 600; width: 100%; text-align: center; } .kfwz{ font-size: 28rpx; color: #3D3D3D; margin-top: 16rpx; width: 100%; text-align: center; } .kfshuzu{ height: 580rpx; overflow: scroll; .item_val{ display: flex; align-items: center; padding-left: 30rpx; box-sizing: border-box; width: 528rpx; height: 144rpx; background: #FFFFFF; box-shadow: 0rpx 4rpx 22rpx 0rpx rgba(0,0,0,0.1); border-radius: 20rpx 20rpx 20rpx 20rpx; margin: auto; margin-top: 42rpx; .lt{ margin-right: 34rpx; padding-top: 10rpx; box-sizing: border-box; image{ width: 76rpx; height: 78rpx; } } .rt{ font-size: 32rpx; color: #3D3D3D; } } } } .mask{ position: fixed; top: 0; left: 0; width: 100%; height: 100vh; background-color: #000; opacity: .5; } page { background-color: #F7FAFE; overflow: hidden; } .shibai { margin-top: 50rpx; text-align: center; padding-bottom: 600rpx; height: 100vh; overflow: scroll; .jxcz { width: 563rpx; height: 100rpx; background: #8883F0; border-radius: 60rpx 60rpx 60rpx 60rpx; text-align: center; line-height: 100rpx; font-size: 45rpx; color: #FFFFFF; position: fixed; bottom: 62rpx; left: 50%; transform: translateX(-50%); } .top { font-size: 40rpx; color: #3D3D3D; } .tishi { font-size: 31rpx; color: #3D3D3D; margin-top: 50rpx; } .li { margin-top: 50rpx; font-size: 31rpx; color: #3D3D3D; image { margin-top: 30rpx; } } } .pages { width: 750rpx; box-sizing: border-box; .shuom { width: 650rpx; height: 100%; background: #FFFFFF; box-shadow: 0rpx 16rpx 40rpx 0rpx rgba(42, 130, 228, 0.1); filter: blur(0px); margin: auto; margin-top: 50rpx; border-radius: 20rpx; padding: 20rpx; box-sizing: border-box; .cont{ margin-top: 10rpx; max-height: 120rpx; overflow: scroll; line-height: 40rpx; } .shuomtit { font-weight: 700; font-size: 34rpx; color: #383838; } .shuomwz { font-size: 28rpx; color: #383838; margin-top: 16rpx; display: flex; align-items: center; } } .list { width: 648rpx; margin: auto; height: 42vh; overflow: scroll; .list_item { width: 648rpx; height: 192rpx; background: #FFFFFF; box-shadow: 0rpx 16rpx 40rpx 0rpx rgba(42, 130, 228, 0.1); filter: blur(0px); border-radius: 20rpx; margin-top: 30rpx; padding-left: 36rpx; box-sizing: border-box; overflow: hidden; .tit { display: flex; justify-content: space-between; .tc { font-weight: 600; font-size: 34rpx; color: #3D3D3D; padding-top: 26rpx; box-sizing: border-box; } .yh { width: 213rpx; height: 67rpx; background: #DCDBFF; border-radius: 0 0 0 20rpx; font-size: 28rpx; color: #918CFF; text-align: center; line-height: 67rpx; } } .bot { margin-top: 40rpx; display: flex; .price { font-weight: 600; font-size: 36rpx; color: #3D3D3D; margin-right: 46rpx; } .time { font-size: 32rpx; color: #3D3D3D; } } } } .tongyi { width: 590rpx; position: fixed; bottom: 50rpx; left: 50%; transform: translateX(-50%); text { color: #638DFF; height: 50rpx; line-height: 50rpx; } .zf { width: 590rpx; height: 84rpx; background: #8883F0; filter: blur(0px); border-radius: 50rpx; text-align: center; line-height: 84rpx; font-size: 36rpx; color: #FFFFFF; margin-top: 20rpx; } } .title { margin-top: 40rpx; padding-left: 32rpx; font-weight: 600; font-size: 40rpx; color: #3D3D3D; margin-top: 100rpx; height: 126rpx; .wz { font-weight: 400; font-size: 32rpx; margin-top: 10rpx; } } } </style>