<template> <view class="page"> <u-navbar title="换车骑行" :border-bottom="false" :background="bgc" title-color='#000' title-size='36' height='45' back-icon-color='#000'></u-navbar> <view class="cont_box"> <view class="tit"> <image src="https://lxnapi.ccttiot.com/bike/img/static/uByIrgaV23PDGZWReKHW" mode=""></image> 请选择换车原因 </view> <!-- https://lxnapi.ccttiot.com/bike/img/static/uZQYJi6D7tPy4CszHtau --> <view class="choose_li"> <view class="li_cont" @click="checkIdx=1"> <view class="img_box"> <image src="https://lxnapi.ccttiot.com/bike/img/static/uZQYJi6D7tPy4CszHtau" mode="" v-if="checkIdx==1"></image> </view> 电量不足 </view> <view class="li_cont" @click="checkIdx=2"> <view class="img_box"> <image src="https://lxnapi.ccttiot.com/bike/img/static/uZQYJi6D7tPy4CszHtau" mode="" v-if="checkIdx==2"></image> </view> 车辆损坏 </view> </view> <view class="tit" style="margin-top: 20rpx;"> SN:{{orderinfo.sn}} </view> </view> <view class="cont_box" v-show="checkIdx==2"> <view class="tit"> <image src="https://lxnapi.ccttiot.com/bike/img/static/uByIrgaV23PDGZWReKHW" mode=""></image> 请选择车辆故障部位 </view> <!-- https://lxnapi.ccttiot.com/bike/img/static/uZQYJi6D7tPy4CszHtau --> <view class="txt"> 车头故障 </view> <view class="checkbox"> <view v-for="(item, index) in cbgz" :key="index" class="check_li" :class="item.checked === true ? 'act1' : ''" @click="toggleCheckbox(index)"> {{ item.dictLabel }} <image src="https://lxnapi.ccttiot.com/bike/img/static/ufYwbVclwhX64u4eGu6u" mode="" v-if="item.checked === true "></image> </view> </view> <view class="txt"> 车身故障 </view> <view class="checkbox"> <view v-for="(item, index) in csgz" :key="index" class="check_li" :class="item.checked === true ? 'act1' : ''" @click="csCheckbox(index)"> {{ item.dictLabel }} <image src="https://lxnapi.ccttiot.com/bike/img/static/ufYwbVclwhX64u4eGu6u" mode="" v-if="item.checked === true "></image> </view> </view> <view class="txt"> 特殊故障 </view> <view class="checkbox"> <view v-for="(item, index) in tsgz" :key="index" class="check_li" :class="item.checked === true ? 'act1' : ''" @click="tsCheckbox(index)"> {{ item.dictLabel }} <image src="https://lxnapi.ccttiot.com/bike/img/static/ufYwbVclwhX64u4eGu6u" mode="" v-if="item.checked === true "></image> </view> </view> <view class="input-container"> <view class="placeholder" v-if="!textValue">如选项未涵盖,请输入故障问题</view> <textarea class="custom-textarea" v-model="textValue" @focus="hidePlaceholder" style="border: none;" @input="updateWordCount" @blur="showPlaceholder"></textarea> <text class="word-count">{{ currentCount }}/500</text> </view> </view> <view class="cont_box" v-if="checkIdx==2&&areainfo.returnVerify==0"> <view class="tit"> <image src="https://lxnapi.ccttiot.com/bike/img/static/uByIrgaV23PDGZWReKHW" mode=""></image> 请对故障部位拍照 </view> <view class="icon"> <view class="imgbox" v-for="(item,index) in imglist " :key="index"> <image :src="item" mode=""></image> </view> <view class="imgbox" @click="btn"> <image src="https://api.ccttiot.com/smartmeter/img/static/uY8CPw9YE6JxPzcHUaqf" mode=""></image> </view> </view> <!-- https://lxnapi.ccttiot.com/bike/img/static/uZQYJi6D7tPy4CszHtau --> </view> <view class="cont" v-if="areainfo.returnVerify==1"> <view class="tip_txt" style="font-weight: 500;font-size: 32rpx;color: #3D3D3D;"> 保持车辆录像的完整清晰,不要随意拍摄,确保视频中车辆出境,并且出现车牌号 </view> <view class="vadio_png1" @click="recordVideo"> <image class="backimg" src="https://lxnapi.ccttiot.com/bike/img/static/uEP0UPJw6a1WuxA7ZlMo" mode="" v-if="videoUrl==''"> <image class="tip_img" src="https://lxnapi.ccttiot.com/bike/img/static/uXFG7Vee8MWx5y7pha2U" mode=""></image> </image> <video class="vad" :src="videoUrl" controls="controls" style="width: 100%;" v-if="videoUrl!=''"></video> <view class="glass" v-if="videoUrl!=''"></view> <image class="tip_img" src="https://lxnapi.ccttiot.com/bike/img/static/uXFG7Vee8MWx5y7pha2U" mode="" v-if="videoUrl!=''"></image> </view> </view> <view class="tits"> 点击扫码或输入车辆编号 </view> <view class="iptbox"> <view class="qrcode" @click="qrcode()"> <image src="https://api.ccttiot.com/smartmeter/img/static/uy7BNwAMIKwvstqFnRhs" mode=""></image> </view> <input type="text" class="ips" v-model="sncode" placeholder="请扫描设备上的二维码" style="margin-left: 32rpx;" placeholder-class="my-placeholder" /> </view> <view class="conts_box" v-if="deviceinfo.sn"> <view class="cont_li"> <view class="left"> <view class="km"> 可继续行驶{{deviceinfo.remainingMileage}}公里 </view> <view class="speed"> <view class="speeds" :style="{ width: deviceinfo.remainingPower + '%' }"> </view> </view> <view class="NO"> NO.{{deviceinfo.sn}} </view> </view> <view class="right"> <image src="https://lxnapi.ccttiot.com/bike/img/static/uqKmFMF9YHTX8lAQARSd" mode=""></image> </view> </view> <view class="cont_li" style="margin-top: 10rpx;"> <view class="left" style="font-size: 32rpx;font-weight: 400;"> 已骑行 </view> <view class="right" style="font-size: 32rpx;font-weight: 400;"> {{timeString}} </view> </view> <view class="cont_li" style="margin-top: 10rpx;"> <view class="left" style="font-size: 32rpx;font-weight: 400;"> 预估金额 </view> <view class="right" style="font-size: 32rpx;font-weight: 400;"> {{ parseFloat(money).toFixed(2)}}元 </view> </view> <view class="txtss"> 扫码开锁后将自动合并订单,骑行时间将继续计时 </view> </view> <!-- <view class="conts_box"> <view class="left"> 已骑行 </view> <view class="right"> {{timeString}} </view> </view> <view class="conts_box"> <view class="left"> 预估金额 </view> <view class="right"> {{money}}元 </view> </view> --> <view class="btns" @click="subs(0)"> 提交 </view> <view class="maskloadpage" v-if="maskloading"> <view class="maskpage0" v-if="maskepage==0"> <view class="top_info"> <image :src="loadimg" mode=""></image> <view class="masktxt"> {{toploadtxt}} </view> </view> <view class="masktips"> {{tiptxt}} </view> <view class="tipsimg"> <image src="https://lxnapi.ccttiot.com/bike/img/static/ugvqmfB3QYujZ6SnfTia" mode=""></image> </view> </view> <view class="maskpage1" v-if="maskepage==4"> <view class="top_info"> <image :src="loadimg" mode=""></image> <view class="masktxt"> {{buletxt}} </view> </view> <view class="masktips" style="width: 100%;"> 请确保与车辆的距离小于3米 </view> <view class="tipsimg"> <image src="https://lxnapi.ccttiot.com/bike/img/static/ugvqmfB3QYujZ6SnfTia" mode=""></image> </view> </view> <!-- 不允许停车点外还车 --> <view class="maskpage1" v-if="maskepage==5"> <view class="top_info"> <image src="https://lxnapi.ccttiot.com/bike/img/static/uG3cbPgvPDzwlq6IHHxK" mode=""></image> <view class="masktxt" v-if="orderinfo.sn"> 蓝牙连接失败 </view> </view> <view class="masktips" style="width: 100%;"> 请确保手机蓝牙已经打开 </view> <view class="masktips" @click="totxtpage()" style="width: 100%;color: #4C97E7;text-decoration-line: underline;margin-top: 0; font-size: 28rpx;"> 点击查看教程 </view> <view class="tipsimg"> <image src="https://lxnapi.ccttiot.com/bike/img/static/ugvqmfB3QYujZ6SnfTia" mode=""></image> </view> <view class="btn_box"> <view class="btn4" @click="closemask()"> 返回 </view> <view class="btn3" @click="subs(1)"> 重新尝试 </view> </view> </view> </view> </view> </template> <script> const app = getApp(); var xBlufi = require("@/utils/blufi/xBlufi.js"); let _this = null; export default { data() { return { bgc: { backgroundColor: "#fff", }, cbgz: [], csgz: [], tsgz: [ ], textValue: '', currentCount: 0, imglist: [], token: '', sn: '', upurl: '', checkIdx: 1, maskloading: false, maskepage: 0, sn: 0, mac: 0, orderinfo: {}, sncode: '', money: '', timer: null, timeString: '', deviceinfo: {}, issend: false, isback: false, isopen: false, upvideo: false, maskloading: false, toploadtxt: "开锁中0%", loadimg: 'https://lxnapi.ccttiot.com/bike/img/static/urJQJnOI1DEjWatFqHYh', tiptxt: '请定点停放,规范用车', maskepage: 0, backgps: {}, buletxt: '', buleclose: false, buleopen: false, bulering: false, bulerebort: false, getnum: 0, showvehicle: false, vehicleNum: '', gps: {}, areainfo: {}, areaId: '', videoUrl: '' } }, onLoad(e) { this.getlist() }, watch: { sncode(newValue, oldValue) { if (newValue && newValue.length === 7) { this.getdevice(); } } }, onHide() { clearInterval(this.timer); // 页面隐藏时清除定时器 if (this.timers) { clearInterval(this.timers); this.timers = null; console.log('定时器已清除'); } xBlufi.listenDeviceMsgEvent(false, this.funListenDeviceMsgEvent); xBlufi.notifyStartDiscoverBle({ 'isStart': false }); }, onUnload() { clearInterval(this.timer); // 页面卸载时清除定时器 if (this.timers) { clearInterval(this.timers); this.timers = null; console.log('定时器已清除'); } xBlufi.listenDeviceMsgEvent(false, this.funListenDeviceMsgEvent); xBlufi.notifyStartDiscoverBle({ 'isStart': false }); }, onBeforeUnmount() { clearInterval(this.timer); if (this.timers) { clearInterval(this.timers); this.timers = null; console.log('定时器已清除'); } xBlufi.listenDeviceMsgEvent(false, this.funListenDeviceMsgEvent); xBlufi.notifyStartDiscoverBle({ 'isStart': false }); }, onShow() { // if (uni.getStorageSync('adminAreaid')) { // } this.$store.dispatch('userInfo', this.$u).then(() => { this.getQiniuToken() this.getisInOrder() // 执行其他操作... }); let that = this uni.getLocation({ type: 'gcj02', success: function(lb) { that.gps.latitude = lb.latitude; that.gps.longitude = lb.longitude; }, fail: function(error) { uni.showToast({ title: '未获取到定位信息,请点击设置勾选允许位置信息,即可使用全部功能', icon: 'none', duration: 2000 }); // that.getmarks() // 在这里处理获取位置信息失败的情况 } }) }, computed: { userId() { return this.$store.getters.userId; }, }, methods: { totxtpage() { // this.seeDetail = true uni.navigateTo({ url: '/page_user/bulelink' }) }, getQiniuToken() { console.log('diaou'); this.$u.get("/common/qiniu/uploadInfo").then((res) => { if (res.code == 200) { this.token = res.token console.log(res, 'resres'); this.upurl = res.domain } }); // this.$u.get('https://v2.ielts.langsi.online/file/getToken').then(res => { // console.log(res.data); // this.token = res.data.token // }).catch(err => { // console.log(err) // }) }, btn() { let _this = this let math = 'static/' + _this.$u.guid(20) uni.chooseImage({ count: 9, type: 'all', success(res) { // tempFilePath可以作为img标签的src属性显示图片 const tempFilePaths = res.tempFiles // let tempFilePaths = chooseImageRes.tempFilePaths; // console.log(tempFilePaths) // tempFilePaths.forEach(item=>{ // // 上传图片到七牛云 // }) wx.uploadFile({ url: 'https://up-z2.qiniup.com', name: 'file', filePath: tempFilePaths[0].path, formData: { token: _this.token, //后端返回的token key: 'smartmeter/img/' + math }, success: function(res) { console.log(res, 'resres'); let str = JSON.parse(res.data) console.log(str.key) _this.userImgs = _this.upurl + '/' + str.key console.log(_this.userImgs) _this.imglist.push(_this.userImgs) } }); } }) }, getArea() { let id = this.areaId this.$u.get("/app/area/" + id).then((res) => { if (res.code == 200) { this.areainfo = res.data // this.areainfo.returnVerify = 0 } else { uni.showToast({ title: res.msg, icon: 'none', duration: 2000 }); } }); }, closemask() { this.maskloading = false }, sub() { let data = { userId: this.orderinfo.userId, detail: this.textValue, sn: this.orderinfo.sn, orderNo:this.orderinfo.orderNo, types: [] // Initialize the type array }; if (this.areainfo.returnVerify == 0) { data.picture = this.imglist.join(',') } else { data.picture = this.videoUrl } // Check for checked items in cbgz this.cbgz.forEach(item => { if (item.checked) { data.types.push(item.dictValue); } }); // Check for checked items in csgz this.csgz.forEach(item => { if (item.checked) { data.types.push(item.dictValue); } }); // Check for checked items in tsgz this.tsgz.forEach(item => { if (item.checked) { data.types.push(item.dictValue); } }); console.log(data, 'dadadad'); this.$u.post("/appVerify/fault", data).then((res) => { if (res.code == 200) { this.issend = true uni.showToast({ title: '提交成功', icon: 'none', duration: 1000 }); } else { uni.showToast({ title: res.msg, icon: 'none', duration: 1000 }); } }); }, subvadio() { let data = { orderNo: this.orderinfo.orderNo, } if (!this.orderinfo.videoUrl) { data.videoUrl = this.videoUrl } if (this.orderinfo.videoUrl) { data.videoUrl = this.orderinfo.videoUrl + ',' + this.videoUrl } this.$u.put('/appVerify/order/saveVideoUrl', data).then((res) => { // uni.hideLoading()· if (res.code === 200) { this.upvideo = true } else { } }) }, recordVideo() { // 调用录像API uni.chooseVideo({ sourceType: ['camera'], // 指定使用相机录像 camera: 'back', // 指定使用后置摄像头,可选值有front、back maxDuration: 15, // 最大录制时长(秒) success: (res) => { // 获取视频录制文件的临时路径 this.videoPath = res.tempFilePath; console.log(res.tempFilePath); this.upload() }, fail: (err) => { console.log('录像失败:', err); } }); }, upload() { uni.showLoading({ title: '上传中' }) let _this = this let math = 'static/' + _this.$u.guid(20) wx.uploadFile({ url: 'https://up-z2.qiniup.com', name: 'file', filePath: this.videoPath, formData: { token: _this.token, //后端返回的token key: 'bike/video/' + math }, success: function(res) { uni.hideLoading() console.log(res, 'resres'); let str = JSON.parse(res.data) console.log(str.key) _this.videoUrl = _this.upurl + '/' + str.key console.log(_this.userImgs) // _this.imglist.push(_this.userImgs) } }); }, subs(num) { if(this.deviceinfo.onlineStatus==0){ uni.showToast({ title: '当前设备离线中,请使用其他车辆', icon: 'none', duration: 1000 }); return } if (this.orderinfo.sn === this.sncode) { uni.showToast({ title: '换车设备不能和当前设备相同', icon: 'none', duration: 1000 }); } else if (this.areainfo.returnVerify == 1 && this.videoUrl == '') { uni.showToast({ title: '请拍摄还车视频', icon: 'none', duration: 1000 }); } else if (this.areainfo.returnVerify === 0 && this.checkIdx === 2) { if (this.imglist.length < 1) { uni.showToast({ title: '请对损坏部位拍照', icon: 'none', duration: 1000 }); } else { uni.showToast({ title: '请选择损坏部位', icon: 'none', duration: 1000 }); } } else if (!this.deviceinfo.sn) { uni.showToast({ title: '请扫码或者输入车辆编号', icon: 'none', duration: 1000 }); } else { // if(this.) if (num === 0) { this.maskloading = true; this.maskepage = 0; this.loadimg = 'https://lxnapi.ccttiot.com/bike/img/static/uRxPPoVoqmnmng6wKlij'; let percentage = 0; const interval = setInterval(() => { if (percentage < 98) { percentage += 2; // 每次增加的百分比,可以调整 this.toploadtxt = `换车中${percentage}%`; } else { clearInterval(interval); this.toploadtxt = "换车中98%"; } }, 40); // 每40毫秒更新一次,可以调整 } if (!this.upvideo && this.orderinfo.returnVerify === 1) { this.subvadio(); } if (this.checkIdx === 2 && !this.issend) { this.sub(); } if (!this.isback) { this.changeback(); } else if (!this.isopen) { setTimeout(()=>{ this.changeOpne(); },300) } setTimeout(() => { if (this.isback && this.isopen) { this.loadimg = 'https://lxnapi.ccttiot.com/bike/img/static/ukD735zCS1yQXw2aGun8'; this.toploadtxt = '换车成功'; setTimeout(() => { this.resetState(); this.getisInOrder(); uni.navigateBack({ delta: 1 // delta值为1时表示返回的页面层数 }); }, 1000); } }, 2000); } }, resetState() { this.isback = false; this.isopen = false; this.issend = false; this.upvideo = false; this.deviceinfo = {}; this.maskloading = false; this.sncode = ''; }, changeback() { // this.mac=this.orderinfo.mac // this.buleclose=true // this.Binddevice() this.$u.post('/appVerify/changeVehicle/lock?orderNo=' + this.orderinfo.orderNo + '&changeReason=' + this.checkIdx+"&newSn="+this .deviceinfo.sn).then((res) => { if (res.code == 200) { this.isback = true this.subs(1) } else { uni.showToast({ title: '换车关锁失败', icon: 'none', duration: 1000 }); // 处理接口返回错误的情况 this.mac = this.orderinfo.mac this.buleclose = true this.Binddevice() } }).catch(error => { // 处理接口请求失败的情况 }); }, buleback() { this.$u.post('/appVerify/changeVehicle/lock?orderNo=' + this.orderinfo.orderNo + '&changeReason=' + this .checkIdx + '&isBluetooth=true' + '&lon=' + lb.longitude + '&lat=' + lb.latitude).then((res) => { if (res.code == 200) { this.isback = true this.subs(1) } }).catch(error => { // 处理接口请求失败的情况 }); }, changeOpne() { this.$u.post('/appVerify/changeVehicle/unlocking?orderNo=' + this.orderinfo.orderNo + '&newSn=' + this .deviceinfo.sn).then((res) => { if (res.code == 200) { this.isopen = true this.subs(1) } else { uni.showToast({ title: '换车开锁失败', icon: 'none', duration: 1000 }); this.mac = this.deviceinfo.mac this.buleopen = true this.Binddevice() // 处理接口返回错误的情况 } }).catch(error => { // 处理接口请求失败的情况 }); }, changebuleOpne() { this.$u.post('/appVerify/changeVehicle/unlocking?orderNo=' + this.orderinfo.orderNo + '&newSn=' + this .deviceinfo.sn + '&isBluetooth=true' + '&lon=' + this.gps.longitude + '&lat=' + this.gps.latitude) .then((res) => { if (res.code == 200) { this.isopen = true this.subs(1) } }).catch(error => { // 处理接口请求失败的情况 }); }, getdevice() { this.deviceinfo={} this.$u.get('/app/device/info?sn=' + this.sncode).then((res) => { if (res.code == 200) { if(this.orderinfo.areaId==res.data.areaId){ this.deviceinfo = res.data // this.deviceinfo.onlineStatus=0 }else{ uni.showToast({ title: '换车设备和当前运营区不同,请使用其他车辆换车', icon: 'none', duration: 2000 }); } } else { // 处理接口返回错误的情况 } }).catch(error => { // 处理接口请求失败的情况 }); }, qrcode() { uni.scanCode({ onlyFromCamera: true, scanType: ['qrCode'], success: res => { let sn = null; let queryParams = res.result.split('?')[1]; if (queryParams) { let params = queryParams.split('&'); params.forEach(param => { let [key, value] = param.split('='); if (key === 'sn') { sn = value; } }); } this.sncode = sn console.log(res.result); if (this.sncode != '') { this.getdevice() } }, fail: err => { console.error('扫描失败:', err); uni.showToast({ title: '扫描失败', icon: 'none' }); } }); }, Binddevice() { uni.getBluetoothAdapterState({ success: function(res) { console.log('蓝牙状态:', res.available) }, fail: function(res) { console.log('获取蓝牙状态失败') } }) this.maskloading = true this.devicesList = [] this.maskepage = 4 this.buletxt = '蓝牙连接中' // uni.showLoading({ // title: '蓝牙扫描中..' // }) xBlufi.initXBlufi(1); console.log("xBlufi", xBlufi.XMQTT_SYSTEM); xBlufi.listenDeviceMsgEvent(true, this.funListenDeviceMsgEvent); xBlufi.notifyStartDiscoverBle({ 'isStart': true }); // 两秒后停止蓝牙搜索 setTimeout(() => { xBlufi.notifyStartDiscoverBle({ 'isStart': false }); setTimeout(() => { // uni.hideLoading() if (this.devicesList.length == 0) { // uni.showToast({ // title: '暂无发现对应设备,请靠近设备', // icon: 'none', // duration: 1500 // }); this.maskepage = 5 } else { let uniqueDevicesList = Array.from(new Set(this.devicesList)); // 将去重后的数组重新赋值给 this.devicesList this.devicesList = uniqueDevicesList; console.log(this.devicesList, 'this.devicesListthis.devicesList'); let istrue = false this.devicesList.forEach(device => { // 从设备名称中提取 MAC 地址(假设 MAC 地址是设备名称的后6个字符) let macFromName = device.name.substring(device.name.length - 12); console.log(macFromName, 'macFromNamemacFromName'); // 与 this.mac 进行比较 if (macFromName == this.mac) { // 如果相同,则将 this.ishave 设置为 true console.log(device); this.deviceInfoss = device // this.ishave = true; istrue = true this.createBLEConnection(device) console.log('对比正确1111111111'); } else { console.log('对比错误'); } }); setTimeout(() => { if (!istrue) { this.buletxt = '蓝牙连接失败' setTimeout(() => { this.maskepage = 5 }, 500) } }, 500) } }, 200) // 判断是否存在浇花器设备 // this.status = true }, 5000) }, reboot() { let vm = this; // 将外部的 this 绑定到 vm 上 uni.getNetworkType({ success(res) { if (res.networkType !== 'none') { uni.getConnectedBluetoothDevices({ success(res) { console.log('已连接的蓝牙设备信息:', res); // vm.dl = (vm.orderinfo.deviceAmount / vm.orderinfo.unitPrice).toFixed(2); // 使用 vm 访问 Vue 实例的属性 xBlufi.notifySendCustomData({ customData: "11reboot" }); // vm.maskloading=false // uni.hideLoading() // vm.remakr() }, fail(err) { uni.hideLoading() console.error('获取已连接蓝牙设备信息失败:', err); } }); } else { console.log('手机未连接网络'); } } }); }, open() { let vm = this; // 将外部的 this 绑定到 vm 上 uni.getNetworkType({ success(res) { if (res.networkType !== 'none') { uni.getConnectedBluetoothDevices({ success(res) { console.log('已连接的蓝牙设备信息:', res); // vm.dl = (vm.orderinfo.deviceAmount / vm.orderinfo.unitPrice).toFixed(2); // 使用 vm 访问 Vue 实例的属性 xBlufi.notifySendCustomData({ customData: "11open" }); vm.maskepage = 0 vm.toploadtxt = '换车中'; vm.changebuleOpne() // uni.hideLoading() // vm.remakr() }, fail(err) { // uni.hideLoading() console.error('获取已连接蓝牙设备信息失败:', err); } }); } else { console.log('手机未连接网络'); } } }); }, close() { let vm = this; // 将外部的 this 绑定到 vm 上 uni.getNetworkType({ success(res) { if (res.networkType !== 'none') { uni.getConnectedBluetoothDevices({ success(res) { console.log('已连接的蓝牙设备信息:', res); // vm.dl = (vm.orderinfo.deviceAmount / vm.orderinfo.unitPrice).toFixed(2); // 使用 vm 访问 Vue 实例的属性 xBlufi.notifySendCustomData({ customData: "11close" }); // vm.maskloading=false vm.buleback() vm.maskepage = 0 vm.toploadtxt = '换车中'; // uni.hideLoading() // vm.remakr() }, fail(err) { // uni.hideLoading() console.error('获取已连接蓝牙设备信息失败:', err); } }); } else { console.log('手机未连接网络'); } } }); }, funListenDeviceMsgEvent: function(options) { switch (options.type) { case xBlufi.XBLUFI_TYPE.TYPE_GET_DEVICE_LISTS: if (options.result) { let devicesarr = options.data // this.devicesList = options.data devicesarr.forEach(device => { // this.$u.get(`/app/device/${mac}/isBind`, data).then((res) => { // if (res.data == false) { 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) { // uni.hideLoading(); xBlufi.notifyInitBleEsp32({ deviceId: options.data.deviceId }); // xBlufi.listenDeviceMsgEvent(true, this.funListenDeviceMsgEvents); // this.deviceIds = options.data.deviceId // this.name = options.data.name // 连接成功绑定设备 // let params = { // mac: this.Bluetoothmac, // userId: this.$store.state.user.userId // } let systemInfo = uni.getSystemInfoSync(); if (systemInfo.platform === 'android') { // 当前设备是 Android } else if (systemInfo.platform === 'ios') { // 当前设备是 iOS // uni.navigateTo({ // url: '/pages/wifilist/index?deviceId=' + options // .data.deviceId + '&name=' + options.data.name // }) } } if (options.result == false) { // this.loadingmask=false this.carstause = false if (this.maskepage == 4) { this.buletxt = '设备连接失败' setTimeout(() => { this.maskepage = 5 }, 800) } // uni.showModal({ // title: '很抱歉提醒你!', // content: '小程序与设备异常断开', // showCancel: false, // success: function(res) { // // uni.navigateBack({ // // url: '../search/search' // // }); // } // }); // this.statusflag = false // uni.hideLoading(); } break; case xBlufi.XBLUFI_TYPE.TYPE_RECIEVE_CUSTON_DATA: // this.ver_data = this.parseCustomData(options.data) if (options.data) { this.carstause = true if (this.maskloading && this.maskepage == 4) { // setTimeout(() => { // this.maskloading = false // }, 700) if (this.buleclose == false && this.buleopen == false && this.bulerebort == false && this .bulering == false) { if (this.buletxt == '蓝牙连接中') { this.buletxt = '蓝牙连接成功!' } } if (this.buleclose) { this.buleclose = false this.close() } if (this.buleopen) { this.buleopen = false this.open() } if (this.bulerebort) { this.buleopen = false this.reboot() } if (this.bulering) { this.bulering = false this.ring() } } } else { this.carstause = false if (this.maskepage == 4) { this.buletxt = '设备连接失败' setTimeout(() => { this.maskepage = 5 }, 800) } } console.log("1收到设备发来的自定义数据结果:", options.data); break; case xBlufi.XBLUFI_TYPE.TYPE_STATUS_CONNECTED: { console.log('状态', options.result) if (options.result == false) { this.carstause = false if (this.maskepage == 4) { this.buletxt = '设备连接失败' setTimeout(() => { this.maskepage = 5 }, 800) } // uni.showToast({ // title: '设备断开链接,请重新点击蓝牙链接', // icon: 'none' // }); // uni.showModal({ // title: '很抱歉提醒你!', // content: '小程序与设备异常断开', // showCancel: false, // success: function(res) { // // uni.navigateBack({ // // url: '../search/search' // // }); // } // }); // this.statusflag = false // uni.hideLoading(); } } break; case xBlufi.XBLUFI_TYPE.TYPE_GET_DEVICE_LISTS_STOP: if (options.result) { let uniqueDevicesList = Array.from(new Set(this.devicesList)); // 过滤出名称字段的前五个字母为 "CTPOW" 的项 let filteredDevices = uniqueDevicesList.filter(device => device.name.substring(0, 4) === "BBLE"); // 将过滤后的数组重新赋值给 this.devicesList this.devicesList = filteredDevices; // console.log('蓝牙停止搜索ok',this.devicesList); } else { //蓝牙停止搜索失败 // console.log('蓝牙停止搜索失败'); } this.searching = false // _this.setData({ // searching: false // }); break; } }, // 解析自定义数据 //4、建立连接 createBLEConnection(e) { console.log('调用了'); xBlufi.notifyStartDiscoverBle({ 'isStart': false }); console.log(e, '蓝牙信息') const deviceId = e.deviceId this.Bluetoothmac = e.localName.substring(5) //从第七位开始截取 只取后面的mac号 console.log(this.Bluetoothmac, '11111'); let name = e.name; console.log('点击了,蓝牙准备连接的deviceId:' + e.deviceId); xBlufi.notifyConnectBle({ isStart: true, deviceId: e.deviceId, name }); // for (var i = 0; i < this.devicesList.length; i++) { // if (e.deviceId === this.devicesList[i].deviceId) { // uni.showLoading({ // title: '连接蓝牙设备中...' // }); // } // } }, getisInOrder() { // uni.showLoading({ // }) this.orderinfo = {} if (this.userId) { this.$u.post('/app/user/isInOrder?userId=' + this.userId, ).then((res) => { // uni.hideLoading() if (res.code === 200) { // this.freList=res.rows this.orderinfo = res.data[0] this.areaId = this.orderinfo.areaId this.getArea() const createTimeTimestamp = new Date(this.orderinfo.unlockTime).getTime(); this.$u.get('/app/device/info?sn=' + this.orderinfo.sn).then((res) => { if (res.code == 200) { this.orderinfo.mac = res.data.mac } else { // 处理接口返回错误的情况 } }).catch(error => { // 处理接口请求失败的情况 }); // 定义定时器 this.timer = setInterval(() => { const currentTime = Date.now(); const timePassed = currentTime - createTimeTimestamp; const secondsPassed = Math.floor(timePassed / 1000); // 转换为时分秒格式 const hours = Math.floor(secondsPassed / 3600); const minutes = Math.floor((secondsPassed % 3600) / 60); const seconds = secondsPassed % 60; const timeString = `${hours < 10 ? '0' : ''}${hours}:${minutes < 10 ? '0' : ''}${minutes}:${seconds < 10 ? '0' : ''}${seconds}`; let totalMinutes = hours * 60 + minutes; let totalTime; if (this.orderinfo.rule.rentalUnit === 'minutes') { totalTime = totalMinutes; } else if (this.orderinfo.rule.rentalUnit === 'hours') { totalTime = hours + minutes / 60; } else if (this.orderinfo.rule.rentalUnit === 'day') { totalTime = hours / 24 + minutes / 1440; } // 计费规则计算 if (this.orderinfo.rule.ridingRule == 1) { const ridingRuleJson = JSON.parse(this.orderinfo.rule.ridingRuleJson); const timeoutTime = parseFloat(ridingRuleJson.timeoutTime); const startingPrice = parseFloat(ridingRuleJson.startingPrice); const startingTime = parseFloat(ridingRuleJson.startingTime); const timeoutPrice = parseFloat(ridingRuleJson.timeoutPrice); let totalCharge; if (totalTime <= startingTime) { totalCharge = startingPrice; } else { const extraTime = totalTime - startingTime; const extraCharge = Math.ceil(extraTime / timeoutTime) * timeoutPrice; totalCharge = startingPrice + extraCharge; } // 更新money值 this.money = totalCharge + this.orderinfo.appointmentFee } else if (this.orderinfo.rule.ridingRule == 2) { const ridingRuleJson = JSON.parse(this.orderinfo.rule.ridingRuleJson); const rules = ridingRuleJson.rule; let totalCharge = 0; for (let rule of rules) { const start = parseFloat(rule.start); const end = parseFloat(rule.end); const eachUnit = parseFloat(rule.eachUnit); const fee = parseFloat(rule.fee); if (totalTime > start && (end === 9999 || totalTime <= end)) { // 所有时间都按照该区间的费率来计算 totalCharge = Math.ceil(totalTime / eachUnit) * fee; break; } } // 更新money值 this.money = totalCharge + this.orderinfo.appointmentFee } // 更新时间字符串 this.timeString = timeString; }, 1000); } else { uni.showToast({ title: res.msg, icon: 'none', duration: 2000 }); } }) } }, toggleCheckbox(index) { this.cbgz[index].checked = !this.cbgz[index].checked; this.$forceUpdate() }, csCheckbox(index) { this.csgz[index].checked = !this.csgz[index].checked; }, tsCheckbox(index) { this.tsgz[index].checked = !this.tsgz[index].checked; }, hidePlaceholder() { this.placeholderVisible = false; }, showPlaceholder() { if (!this.textValue) { this.placeholderVisible = true; } }, getlist() { // checked this.$u.get("/appVerify/fault/allList?dictType=et_fault_type").then((res) => { if (res.code == 200) { this.cbgz = res.data.headstock.map(item => ({ ...item, checked: false })); this.csgz = res.data.body.map(item => ({ ...item, checked: false })); this.tsgz = res.data.special.map(item => ({ ...item, checked: false })); } else { uni.showToast({ title: '未登录,请登录后尝试', icon: 'none', duration: 2000 }); } }); }, } } </script> <style lang="scss"> page { background-color: #F7FAFE; } .page { padding-bottom: 100rpx; // width: 750rpx; width: 750rpx; // height: 530rpx; // background: linear-gradient( 180deg, #64B6A7 0%, rgba(255,255,255,0) 100%), #FFFFFF; border-radius: 0rpx 0rpx 0rpx 0rpx; padding-bottom: 200rpx; .tip_box { padding: 44rpx 36rpx; font-weight: 400; font-size: 32rpx; color: #FFFFFF; background: #64B6A7; } .vadio_png1 { position: relative; width: 672rpx; height: 370rpx; .backimg { width: 672rpx; height: 370rpx; } .tip_img { position: absolute; top: 72rpx; left: 210rpx; width: 252rpx; height: 194rpx; z-index: 11; } .vad { width: 672rpx; height: 370rpx; border-radius: 40rpx; z-index: 1; } .glass { position: absolute; top: 0; left: 0; width: 672rpx; height: 370rpx; background: rgba(255, 255, 255, 0.2); border-radius: 40rpx; // box-shadow: 0 rgba(0, 0, 0, 0.1); backdrop-filter: blur(10rpx); -webkit-backdrop-filter: blur(10rpx); /* For Safari */ // border: 1rpx solid rgba(255, 255, 255, 0.3); z-index: 10; } } .cont { width: 100%; padding: 0 39rpx; .tip_txt { margin-top: 38rpx; width: 100%; font-weight: 400; font-size: 28rpx; color: #3D3D3D; } .vadio_png { margin-top: 52rpx; image { width: 672rpx; height: 370rpx; } } .btn { position: fixed; bottom: 100rpx; left: 38rpx; // margin-top: 128rpx; display: flex; align-items: center; justify-content: center; width: 680rpx; height: 90rpx; background: rgba(100, 182, 167, 0.5); border-radius: 54rpx 54rpx 54rpx 54rpx; z-index: 10; font-weight: 500; font-size: 40rpx; color: #FFFFFF; } .act1 { background: #64B6A7; } } .maskloadpage { position: fixed; padding: 46rpx; bottom: 0; width: 752rpx; height: 780rpx; background: #FFFFFF; border-radius: 40rpx 40rpx 0rpx 0rpx; z-index: 101; box-shadow: 0rpx 0rpx 8rpx 0rpx rgba(0, 0, 0, 0.15); .maskpage0 { .top_info { width: 100%; display: flex; align-items: center; justify-content: center; image { margin-right: 16rpx; width: 50rpx; height: 50rpx; } .masktxt { font-weight: 500; font-size: 44rpx; color: #3D3D3D; } } .masktips { margin-top: 20rpx; width: 100%; text-align: center; font-weight: 400; font-size: 32rpx; color: #3D3D3D; } .tipsimg { margin-top: 60rpx; display: flex; // align-items: center; justify-content: center; width: 100%; image { width: 554rpx; height: 262rpx; } } } .maskpage1 { .top_info { width: 100%; display: flex; align-items: center; justify-content: center; image { margin-right: 16rpx; width: 50rpx; height: 50rpx; } .masktxt { font-weight: 500; font-size: 44rpx; color: #3D3D3D; } } .masktips { margin-top: 20rpx; width: 100%; text-align: center; font-weight: 400; font-size: 32rpx; color: #3D3D3D; } .tipsimg { margin-top: 60rpx; display: flex; // align-items: center; justify-content: center; width: 100%; image { width: 554rpx; height: 262rpx; } } .btn_box { width: 750rpx; padding: 0 36rpx; position: absolute; bottom: 60rpx; left: 0; display: flex; justify-content: space-between; align-items: center; .btn3 { // margin-right: 16rpx; display: flex; align-items: center; justify-content: center; width: 300rpx; height: 90rpx; background: #4C97E7; border-radius: 45rpx 45rpx 45rpx 45rpx; font-weight: 500; font-size: 40rpx; color: #FFFFFF; } .btn4 { display: flex; align-items: center; justify-content: center; width: 300rpx; height: 90rpx; border-radius: 45rpx 45rpx 45rpx 45rpx; border: 2rpx solid #808080; font-weight: 500; font-size: 40rpx; color: #808080; } } } } .btns { position: fixed; bottom: 70rpx; left: 34rpx; display: flex; align-items: center; justify-content: center; font-weight: 500; font-size: 40rpx; color: #FFFFFF; width: 680rpx; height: 90rpx; background: #64B6A7; border-radius: 54rpx 54rpx 54rpx 54rpx; z-index: 100; } .iptbox { display: flex; align-items: center; flex-wrap: nowrap; padding: 22rpx; margin: 28rpx auto 0; width: 680rpx; height: 88rpx; background: #FFFFFF; box-shadow: 0rpx 0rpx 8rpx 0rpx rgba(0, 0, 0, 0.15); border-radius: 20rpx 20rpx 20rpx 20rpx; .qrcode { padding-right: 20rpx; border-right: 2rpx solid #D8D8D8; image { width: 54rpx; height: 54rpx; } } .ips { width: 630rpx; } image { width: 18rpx; height: 32rpx; } .my-placeholder { font-weight: 400; font-size: 32rpx; color: #808080; } } .conts_box { width: 680rpx; margin: 0 auto; display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; margin-top: 38rpx; background: #FFFFFF; box-shadow: 0rpx 10rpx 64rpx 0rpx rgba(0, 0, 0, 0.08); border-radius: 20rpx 20rpx 20rpx 20rpx; padding-bottom: 20rpx; .txtss { margin-top: 18rpx; padding-left: 20rpx; width: 100%; font-weight: 500; font-size: 28rpx; color: #808080; } .cont_li { width: 100%; display: flex; flex-wrap: nowrap; align-items: center; justify-content: space-between; .left { padding-left: 20rpx; display: flex; flex-wrap: wrap; font-weight: 600; font-size: 36rpx; color: #3D3D3D; .km { font-weight: 400; font-size: 28rpx; color: #3D3D3D; } .speed { margin-top: 18rpx; width: 226rpx; height: 22rpx; background: #ccc; border-radius: 16rpx 16rpx 16rpx 16rpx; .speeds { // width: 90%; height: 100%; background: #64B6A7; border-radius: 16rpx 16rpx 16rpx 16rpx; } } .NO { width: 100%; font-weight: 400; font-size: 24rpx; color: #3D3D3D; } } .right { padding-right: 20rpx; font-weight: 600; font-size: 36rpx; color: #3D3D3D; image { width: 244rpx; height: 196rpx; } } } } .tits { width: 680rpx; margin: 0 auto; font-weight: 400; margin-top: 38rpx; font-size: 36rpx; color: #3D3D3D; } .cont_box { margin: 0 auto; padding: 24rpx 32rpx; width: 680rpx; margin-top: 38rpx; background: #FFFFFF; box-shadow: 0rpx 10rpx 64rpx 0rpx rgba(0, 0, 0, 0.08); border-radius: 20rpx 20rpx 20rpx 20rpx; .tit { width: 100%; display: flex; flex-wrap: nowrap; align-items: center; image { margin-right: 12rpx; width: 24rpx; height: 24rpx; } } .choose_li { margin-top: 34rpx; width: 100%; display: flex; flex-wrap: nowrap; align-items: center; // justify-content: space-between; .li_cont { width: 50%; display: flex; flex-wrap: nowrap; .img_box { margin-right: 30rpx; width: 38rpx; height: 38rpx; border-radius: 50%; border: 2rpx solid #3D3D3D; } } } .tip { display: flex; flex-wrap: nowrap; // align-items: center; font-weight: 700; font-size: 32rpx; color: #3D3D3D; line-height: 44rpx; .ipnt { margin-top: 10rpx; margin-right: 12rpx; color: #FF4444; font-size: 48rpx; } } .iptbox { display: flex; align-items: center; margin-top: 30rpx; width: 592rpx; height: 80rpx; border-radius: 20rpx 20rpx 20rpx 20rpx; border: 2rpx solid #979797; .ips { margin-left: 30rpx; width: 80%; } .iptbtn { display: flex; align-items: center; justify-content: center; width: 112rpx; height: 80rpx; background: #64B6A7; border-radius: 20rpx 20rpx 20rpx 20rpx; image { width: 37rpx; height: 37rpx; } } } .txt { margin-top: 18rpx; font-weight: 400; font-size: 28rpx; color: #3D3D3D; } .icon { display: flex; flex-wrap: wrap; align-items: center; margin-top: 40rpx; .imgbox { width: 33%; image { width: 142rpx; height: 142rpx; } } } .checkbox { display: flex; flex-wrap: wrap; .check_li { position: relative; margin-right: 10rpx; margin-top: 18rpx; display: flex; align-items: center; justify-content: center; width: 142rpx; height: 65rpx; border-radius: 20rpx 20rpx 20rpx 20rpx; border: 2rpx solid #C7C7C7; image { position: absolute; right: 0; bottom: 0; width: 40rpx; height: 20rpx; } } .check_li:nth-child(4n) { margin-right: 0; } .act1 { // background-image: url(https://api.ccttiot.com/smartmeter/img/static/uaqN5qdoGNCs7Dumzr3F); width: 142rpx; height: 65rpx; // background-size: cover; border: 2rpx solid #1E807A; // background: #4C97E7; } } .input-container { position: relative; width: 612rpx; height: 248rpx; background: #FFFFFF; box-shadow: 0rpx 16rpx 40rpx 0rpx rgba(42, 130, 228, 0.1); border-radius: 20rpx; margin-top: 40rpx; overflow: hidden; padding-right: 38rpx; box-sizing: border-box; border: 2rpx solid #C7C7C7; } .placeholder { position: absolute; top: 18rpx; left: 38rpx; color: #999; /* placeholder颜色 */ pointer-events: none; /* 确保点击事件可以穿透到textarea上 */ } .custom-textarea { width: 100%; height: 100%; /* 设置一个合适高度 */ padding-top: 18rpx; /* 为placeholder留出空间 */ padding-left: 38rpx; box-sizing: border-box; border: 1px solid #ccc; } .word-count { position: absolute; right: 10px; bottom: 10px; font-size: 12px; color: #999; } } } </style>