<template> <view class="page"> <u-navbar title="设备详情" :border-bottom="false" :background="bgc" title-color='#2E4975' title-size='36' height='45'></u-navbar> <!-- <view class="map"> </view> --> <map class="map" id="map" ref="map" :scale="zoomSize" :latitude="latitude" :longitude="longitude" :show-location="true" :markers="markers" :polygon="polyline"> </map> <view class="park" @click="toggleIconAndCallout"> <image class="img" src="https://lxnapi.ccttiot.com/bike/img/static/uRiYQZQEb3l2LsltEsyW" mode="aspectFit"></image> </view> <view class="track" @click="toTrack"> <image class="img" src="https://lxnapi.ccttiot.com/bike/img/static/ufaAAtlirJYs1QwJF25P" mode="aspectFit"></image> </view> <view class="info_card"> <view class="info_tit"> 设备信息 </view> <view class="lines"></view> <view class="cont"> <view class="info_li"> <view class="half_infoli"> SN:<span>{{ deviceInfos.sn }}</span> </view> <view class="half_infoli"> MAC:<span>{{ deviceInfos.mac }}</span> </view> </view> <view class="info_li"> <view class="half_infoli"> 车牌号:<span v-if="deviceInfos.vehicleNum">{{ deviceInfos.vehicleNum }}</span> <span v-else>--</span> </view> <view class="half_infoli"> 车辆型号: <span v-if="deviceInfos.model">{{ deviceInfos.model }}</span> <span v-else>--</span> </view> </view> <view class="info_li"> 运营区域: <span v-if="deviceInfos.areaName">{{ deviceInfos.areaName }}</span> <span v-else>--</span> </view> </view> <view class="lines"></view> <view class="cont"> <view class="info_li"> <view class="half_infoli"> 车辆状态:<span>{{ status() }}</span> </view> <view class="half_infoli" v-if="deviceInfos.onlineStatus == 0"> 网络状态:<span>离线</span> </view> <view class="half_infoli" v-if="deviceInfos.onlineStatus == 1"> 网络状态:<span>在线</span> </view> </view> <view class="info_li"> <view class="half_infoli"> 电池电量: <span v-if="deviceInfos.remainingPower">{{ deviceInfos.remainingPower }}%</span> <span v-else>--</span> </view> <view class="half_infoli"> 续航里程: <span v-if="deviceInfos.remainingMileage">{{ deviceInfos.remainingMileage }} KM</span> <span v-else>--</span> </view> </view> <view class="info_li"> <view class="half_infoli"> 电池电压: <span v-if="deviceInfos.voltage">{{ deviceInfos.voltage }}V</span> <span v-else>--</span> </view> <view class="half_infoli"> 4G信号: <span v-if="deviceInfos.satellites">{{ deviceInfos.satellites }}</span> <span v-else>--</span> </view> </view> </view> <view class="lines"></view> <view class="cont"> <view class="info_li"> 最后定位坐标: <span v-if="deviceInfos.latitude">{{ deviceInfos.latitude }},{{ deviceInfos.longitude }}</span> <span v-else>--</span> </view> <view class="info_li" style="flex-wrap: wrap;display: inline-block;"> 最后定位地址: <span v-if="deviceInfos.location">{{ deviceInfos.location }}</span> <span v-else>--</span> </view> <view class="info_li"> 最后定位时间: <span v-if="deviceInfos.lastTime">{{ deviceInfos.lastTime }}</span> <span v-else>--</span> </view> </view> </view> <view class="info_card" style="margin-top: 20rpx;" v-if="deviceInfos.etOrders > 0 && deviceInfos.etOrders[0] && deviceInfos.sn"> <view class="info_tit"> 最后订单信息 </view> <view class="lines"></view> <view class="cont"> <view class="info_li"> 最后用户姓名: <span v-if="deviceInfos.etOrders[0].realName && deviceInfos.sn">{{ deviceInfos.etOrders[0].realName }}</span> <span v-else>--</span> </view> <view class="info_li"> 最后用户电话: <span v-if="deviceInfos.etOrders[0].phonenumber && deviceInfos.sn">{{ deviceInfos.etOrders[0].phonenumber }}</span> <span v-else>--</span> </view> <view class="info_li" style="flex-wrap: wrap;display: inline-block;"> 最后订单编号: <span v-if="deviceInfos.etOrders[0].orderNo && deviceInfos.sn">{{ deviceInfos.etOrders[0].orderNo }}</span> <span v-else>--</span> </view> <view class="info_li"> 订单开始时间: <span v-if="deviceInfos.etOrders[0].createTime && deviceInfos.sn">{{ deviceInfos.etOrders[0].createTime }}</span> <span v-else>--</span> </view> <view class="info_li"> <view class="info_li" v-if="deviceInfos.sn"> 订单状态:<span>{{ statuss() }}</span> </view> </view> </view> </view> <view class="bot_btn"> <view class="btn" @click="checkbtn(0)"> 开锁 </view> <view class="btn" @click="checkbtn(1)"> 关锁 </view> <view class="btn" @click="btn(4)"> 响铃寻车 </view> <!-- <view class="btn" @click="bulebtn(1)"> 蓝牙响铃 </view> <view class="btn" @click="bulebtn(2)"> 蓝牙开锁 </view> <view class="btn" @click="bulebtn(3)"> 蓝牙关锁 </view> --> <view class="btn" @click="btn(8)"> 设备重启 </view> <view class="btn" @click="btn(2)" v-if="deviceInfos.status != 8"> 车辆禁用 </view> <view class="btn" @click="btn(3)" v-if="deviceInfos.status == 8"> 车辆解禁 </view> <view class="btn" @click="btn(5)" v-if="deviceInfos.status != 0"> 车辆回仓 </view> <view class="btn" @click="btn(6)" v-if="deviceInfos.status == 0"> 车辆出仓 </view> <view class="btn" @click="btn(7)"> 车牌修改 </view> <view class="btn" @click="btn(9)"> 坐垫锁 </view> <view class="btn" @click="btn(10)"> 定位更新 </view> <!-- <view class="btn" @click="tipshow=true" v-if="info.type==1"> 维修处理 </view> <view class="btn" @click="tipshow=true" v-if="info.type==2"> 换电处理 </view> --> <view class="btn" @click="changeShwoList"> 修改车型 </view> <view class="btn" @click="generateQrcode()"> 设备二维码 </view> </view> <u-mask :show="false" @click="show = false" :z-index='100' /> <!-- <view class="bot"> <view class="btn"> 退款 </view> </view> --> <u-mask :show="maskloading" :z-index='100' duration='0' /> <view class="maskloadpage" v-if="maskloading"> <view class="maskpage1" v-if="maskepage == 4"> <view class="top_info"> <image :src="loadimg" mode="aspectFit"></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="aspectFit"> </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="aspectFit"> </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="aspectFit"> </image> </view> <view class="btn_box"> <view class="btn4" @click="closemask()"> 返回 </view> <view class="btn3" @click="Binddevice"> 重新连接 </view> </view> </view> </view> <u-mask :show="showvehicle" @click="closevehicle()" :z-index='100' /> <view class="tip_box" v-if="showvehicle"> <view class="top" v-if="showvehicle"> <view class="tip"> 设备信息修改 </view> <view class="ipt_box"> <view class="text"> 车牌号 </view> <view class="ipt"> <input type="text" v-model="vehicleNum" placeholder=" " class="input" placeholder-style="color:#C7CDD3"> </view> </view> </view> <view class="bots"> <view class="bot_left" @click="closevehicle()"> 取消 </view> <view class="bot_right" @click="putvehicle()"> 确定 </view> </view> </view> <u-mask :show="showqr" @click="closeQr()" :z-index='100' /> <view class="tip_box" v-if="showqr"> <view class="ewm" style="padding-top: 50rpx;"> <canvas id="qrcode" canvas-id="qrcode" style="width: 350rpx;height:350rpx;margin-left: 164rpx;" /> </view> <view class="saveQr" @click="saveQrcode()"> 保存二维码 </view> </view> <u-mask :show="showbtntip" @click="closevehicle()" :z-index='100' /> <view class="tip_box" v-if="showbtntip"> <view class="top" v-if="showbtntip"> <view class="tip"> 操作提示 </view> <view class="ipt_box" style="justify-content: center;"> <view class="text" style="width: 80%;text-align: center;"> 车辆有正在进行中的订单,是否进行该操作 </view> </view> </view> <view class="bots"> <view class="bot_left" @click="closeshowtip()"> 取消 </view> <view class="bot_right" @click="btn(btnnum)"> 确定 </view> </view> </view> <u-select v-model="showModelList" :list="ModelList" title='修改车型' @confirm="confirm"></u-select> </view> </template> <script> import UQRCode from 'uqrcodejs'; const app = getApp(); var xBlufi = require("@/utils/blufi/xBlufi.js"); let _this = null; export default { data() { return { devicesList: [ // {name:'110000', // mac:'11111'} ], searching: false, texts: '正在扫描蓝牙设备...', btnflag: true, tishiflag: false, option: '', bluthlist: [], //蓝牙数组 // status: 'loading', statusflag: false, Bluetoothmac: '', mac: '', ishave: false, ver_data: null, deviceInfoss: {}, gps: {}, isband: false, // status: false, deviceIds: '', name: '', orderinfo: {}, dl: 0, czmoney: true, iscz: true, bgc: { backgroundColor: "#F7FAFE", }, show: true, showgj: true, searchKeyword: '11', latitude: 39.916527, longitude: 116.397128, isMap: false, zoomSize: 15, markers: [], polyline: [], polygons: [], cardId: '001区域', sn: '', deviceInfos: {}, carstause: 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: '', showbtntip: false, btnnum: null, showqr: false, canvasWidth: 300, deptId: null, showModelList: false, ModelList: [] } }, onLoad(e) { this.sn = e.id this.deviceInfo() this.deptId = uni.getStorageSync('deptId'); }, onUnload: function () { xBlufi.listenDeviceMsgEvent(false, this.funListenDeviceMsgEvent); xBlufi.notifyStartDiscoverBle({ 'isStart': false }); }, onHide() { xBlufi.listenDeviceMsgEvent(false, this.funListenDeviceMsgEvent); xBlufi.notifyStartDiscoverBle({ 'isStart': false }); }, onBeforeUnmount() { xBlufi.listenDeviceMsgEvent(false, this.funListenDeviceMsgEvent); xBlufi.notifyStartDiscoverBle({ 'isStart': false }); }, watch: { }, methods: { toTrack(){ uni.navigateTo({ url:'/pages_adminSet/bike_track?sn='+this.deviceInfos.sn+'&type=1' }) }, changeShwoList() { console.log('diaoyongle '); this.showModelList = true }, confirm(e) { let modelId = e[0].value this.$u.put('/appVerify/device/editModel?sn=' + this.deviceInfos.sn + '&modelId=' + modelId).then((res) => { if (res.code == 200) { this.showModelList = false this.deviceInfo() uni.showToast({ title: '修改成功', icon: 'none', duration: 2000 }); } else { uni.showToast({ title: res.msg, icon: 'none', duration: 2000 }); } }) }, getModelList() { this.$u.get('/system/area/selectDeptByAreaId/' + this.deviceInfos.areaId).then((res) => { if (res.code == 200) { this.ModelList = res.data.modelList.map(item => ({ value: item.modelId, label: item.model })); } else { uni.showToast({ title: res.msg, icon: 'none', duration: 2000 }); } }) }, closeQr() { this.showqr = false }, generateQrcode() { uni.navigateTo({ url: '/pages_admin/Qrcode?sn=' + this.deviceInfos.sn }) }, saveQrcode() { uni.canvasToTempFilePath({ canvasId: 'qrcode', x: -10, // 裁剪区域的 x y: 0, // 裁剪区域的 y width: 155, // 裁剪区域的宽度,包含边距 height: 157 + 15, // 裁剪区域的高度,包含边距 success: (res) => { uni.saveImageToPhotosAlbum({ filePath: res.tempFilePath, success: () => { uni.showToast({ title: '保存成功', icon: 'success' }); this.showqr = false; }, fail: (err) => { uni.showToast({ title: '保存失败', icon: 'none' }); } }); }, fail: (err) => { uni.showToast({ title: '生成二维码失败', icon: 'none' }); } }); }, closeshowtip() { this.showbtntip = false }, checkbtn(num) { if (this.deviceInfos.status == 3 || this.deviceInfos.status == 2 || this.deviceInfos.status == 4) { this.showbtntip = true this.btnnum = num } else { this.btn(num) } }, putvehicle() { this.$u.put('/appVerify/device/edit?sn=' + this.sn + '&vehicleNum=' + this.vehicleNum).then((res) => { if (res.code == 200) { this.deviceInfo() this.showvehicle = false uni.showToast({ title: '修改成功', icon: 'none', duration: 2000 }); } else { uni.showToast({ title: res.msg, icon: 'none', duration: 2000 }); } }) }, closemask() { this.maskloading = false }, statuss() { if (this.deviceInfos.sn) { if (this.deviceInfos.etOrders[0]) { if (this.deviceInfos.etOrders[0].status == 0) { return '预约中' } else if (this.deviceInfos.etOrders[0].status == 1) { return '取消预约' } else if (this.deviceInfos.etOrders[0].status == 2) { return '骑行中' } else if (this.deviceInfos.etOrders[0].status == 3) { return '骑行结束' } else if (this.deviceInfos.etOrders[0].status == 4) { return '订单完成' } } } }, closevehicle() { this.showvehicle = false }, bulebtn(num) { if (num == 1) { if (this.carstause) { this.ring() } else { this.bulering = true this.Binddevice() } } else if (num == 2) { if (this.carstause) { this.open() } else { this.buleopen = true this.Binddevice() } } else if (num == 3) { if (this.carstause) { this.close() } else { this.buleclose = true this.Binddevice() } } else if (num == 4) { if (this.carstause) { this.reboot() } else { this.bulerebort = true this.Binddevice() } } }, btn(num) { this.showbtntip = false if (num == 0) { uni.showLoading({ title: '加载中...' }) console.log('点击了....1'); this.$u.post('/appVerify/admin/unlocking?sn=' + this.sn).then((res) => { if (res.code == 200) { uni.hideLoading() // 处理接口返回的数据,将边界数据转换为地图组件需要的折线结构 this.deviceInfo() uni.showToast({ title: '操作成功', icon: 'none', duration: 2000 }); } else { uni.hideLoading() this.bulebtn(2) } }).catch(error => { console.error("Error fetching area data:", error); }); } else if (num == 1) { uni.showLoading({ title: '加载中...' }) console.log('点击了....2'); this.$u.post('/appVerify/admin/lock?sn=' + this.sn).then((res) => { if (res.code == 200) { // 处理接口返回的数据,将边界数据转换为地图组件需要的折线结构 this.deviceInfo() uni.showToast({ title: '操作成功', icon: 'none', duration: 2000 }); } else { uni.hideLoading() this.bulebtn(3) } }).catch(error => { console.error("Error fetching area data:", error); }); } else if (num == 2) { uni.showLoading({ title: '加载中...' }) this.$u.post('/appVerify/device/offline?sn=' + this.sn).then((res) => { if (res.code == 200) { uni.showToast({ title: '解禁成功', icon: 'none', duration: 2000 }); // 处理接口返回的数据,将边界数据转换为地图组件需要的折线结构 this.deviceInfo() } else { uni.showToast({ title: res.msg, icon: 'none', duration: 2000 }); } }).catch(error => { console.error("Error fetching area data:", error); }); } else if (num == 3) { uni.showLoading({ title: '加载中...' }) this.$u.post('/appVerify/device/online?sn=' + this.sn).then((res) => { if (res.code == 200) { // 处理接口返回的数据,将边界数据转换为地图组件需要的折线结构 uni.showToast({ title: '解禁成功', icon: 'none', duration: 2000 }); this.deviceInfo() } else { uni.showToast({ title: res.msg, icon: 'none', duration: 2000 }); } }).catch(error => { console.error("Error fetching area data:", error); }); } else if (num == 4) { uni.showLoading({ title: '加载中...' }) this.$u.post('/app/device/ring?sn=' + this.sn).then((res) => { if (res.code == 200) { uni.hideLoading() uni.showToast({ title: '操作成功', icon: 'none', duration: 2000 }); } else { uni.hideLoading() uni.showToast({ title: res.msg, icon: 'none', duration: 2000 }); this.bulebtn(1) } }) } else if (num == 5) { uni.showLoading({ title: '加载中...' }) this.$u.put('/appVerify/device/edit?status=0&sn=' + this.sn).then((res) => { if (res.code == 200) { uni.showToast({ title: '回仓成功', icon: 'none', duration: 2000 }); this.deviceInfo() } else { uni.showToast({ title: res.msg, icon: 'none', duration: 2000 }); } }) } else if (num == 6) { uni.showLoading({ title: '加载中...' }) this.$u.put('/appVerify/device/edit?status=1&sn=' + this.sn).then((res) => { if (res.code == 200) { this.deviceInfo() uni.showToast({ title: '出仓成功', icon: 'none', duration: 2000 }); } else { uni.showToast({ title: res.msg, icon: 'none', duration: 2000 }); } }) } else if (num == 7) { this.showvehicle = true } else if (num == 8) { uni.showLoading({ title: '加载中...' }) this.$u.post('/appVerify/device/reboot?sn=' + this.sn).then((res) => { if (res.code == 200) { this.deviceInfo() uni.showToast({ title: '操作成功', icon: 'none', duration: 2000 }); } else { // uni.hideLoading() // this.bulebtn(4) } }) } else if (num == 9) { uni.showLoading({ title: '加载中...' }) this.$u.post('/appVerify/device/seatCushionLock?sn=' + this.sn).then((res) => { if (res.code == 200) { this.deviceInfo() uni.showToast({ title: '操作成功', icon: 'none', duration: 2000 }); } else { uni.showToast({ title: res.msg, icon: 'none', duration: 2000 }); } }) } else if (num == 10) { uni.showLoading({ title: '加载中...' }) this.$u.post('/appVerify/refreshDevice?sn=' + this.sn).then((res) => { if (res.code == 200) { this.deviceInfo() uni.showToast({ title: '操作成功', icon: 'none', duration: 2000 }); } else { uni.showToast({ title: res.msg, icon: 'none', duration: 2000 }); } }) } }, Binddevice() { console.log('Binddevice'); // 检查蓝牙状态 // my.getBluetoothAdapterState({ // success: (res) => { // console.log('蓝牙状态:', res.available); // if (!res.available) { // this.maskepage = 5; // this.buletxt = '请打开手机蓝牙'; // return; // } // }, // fail: () => { // this.maskepage = 5; // this.buletxt = '获取蓝牙状态失败'; // } // }); // 初始化蓝牙模块并开始扫描 this.maskloading = true; this.devicesList = []; this.maskepage = 4; this.buletxt = '蓝牙连接中'; // 初始化蓝牙模块 xBlufi.initXBlufi(0); xBlufi.listenDeviceMsgEvent(true, this.funListenDeviceMsgEvent); // 开始扫描设备 xBlufi.notifyStartDiscoverBle({ 'isStart': true }); // 设置扫描超时 setTimeout(() => { xBlufi.notifyStartDiscoverBle({ 'isStart': false }); setTimeout(() => { if (this.devicesList.length === 0) { this.maskepage = 5; this.buletxt = '未发现设备'; return; } // 过滤并去重设备列表 let uniqueDevicesList = Array.from(new Set(this.devicesList)); this.devicesList = uniqueDevicesList.filter(device => device.name && device.name.startsWith('BBLE') ); // 查找目标设备 const targetDevice = this.devicesList.find(device => { const macFromName = device.name.substring(device.name.length - 12); return macFromName === this.mac; }); if (targetDevice) { this.deviceInfoss = targetDevice; // 连接设备 // xBlufi.notifyConnectBle({ // connect: true, // deviceId: targetDevice.deviceId, // name: targetDevice.name // }); this.connectToDevice(targetDevice); } else { this.buletxt = '蓝牙连接失败'; setTimeout(() => { this.maskepage = 5; }, 500); } }, 200); }, 5000); }, // 连接到设备 connectToDevice(device) { xBlufi.notifyConnectBle({ connect: true, deviceId: device.deviceId, name: device.name }); // 监听连接状态 xBlufi.listenDeviceMsgEvent(true, (res) => { if (res.type === xBlufi.XBLUFI_TYPE.TYPE_STATUS_CONNECTED) { if (res.result) { this.carstause = true; if (this.maskloading && this.maskepage === 4) { if (!this.buleclose && !this.buleopen && !this.bulerebort && !this.bulering) { this.buletxt = '蓝牙连接成功!'; } // 处理各种蓝牙操作 if (this.buleclose) { this.buleclose = false; this.close(); } if (this.buleopen) { this.buleopen = false; this.open(); } if (this.bulerebort) { this.bulerebort = 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); } } } }); // 初始化设备 setTimeout(() => { xBlufi.notifyInitBleEsp32({ deviceId: device.deviceId }); }, 1000); }, 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" }); setTimeout(() => { vm.maskloading = false }, 1000); vm.deviceInfo() // 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.deviceInfo() // uni.hideLoading() // vm.remakr() }, fail(err) { uni.hideLoading() console.error('获取已连接蓝牙设备信息失败:', err); } }); } else { console.log('手机未连接网络'); } } }); }, ring() { 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: "11play1@" }); vm.maskloading = false vm.deviceInfo() // 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 }); 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) } } 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) } } } 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; } }, btnyc() { this.titleflag = false }, // 解析自定义数据 //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: '连接蓝牙设备中...' // }); // } // } }, funListenDeviceMsgEvents: function (options) { let that = this; switch (options.type) { case xBlufi.XBLUFI_TYPE.TYPE_STATUS_CONNECTED: { console.log('状态', options.result) if (options.result == false) { this.carstause = false 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_RECIEVE_MY_DATA: this.loadPercent = options.data; this.loadText = '文件读取中' console.log("文件读取中", options.data); break; case xBlufi.XBLUFI_TYPE.TYPE_RECIEVE_CUSTON_DATA: // this.isband = true // this.ver_data = this.parseCustomData(options.data) console.log("1收到设备发来的自定义数据结果:", options.data); if (options.data) { this.carstause = true } break; case xBlufi.XBLUFI_TYPE.TYPE_INIT_ESP32_RESULT: uni.hideLoading(); if (options.result) { console.log('初始化成功'); } else { console.log('初始化失败'); } break; } }, // 点击隐藏没有设备提示 btnhd() { this.tishiflag = false }, status() { // if (this.deviceInfos.onlineStatus == 0) { // return '离线' // } else { // } if (this.deviceInfos.status == 0) { return '仓库中' } else if (this.deviceInfos.status == 1) { return '待租' } else if (this.deviceInfos.status == 2) { return '预约中' } else if (this.deviceInfos.status == 3) { return '骑行中' } else if (this.deviceInfos.status == 4) { return '临时锁车中' } else if (this.deviceInfos.status == 6) { return '调度中' } else if (this.deviceInfos.status == 8) { return '下线' } }, deviceInfo() { this.markers = [] this.$u.get('/app/device/info?sn=' + this.sn).then((res) => { if (res.code === 200) { this.deviceInfos = res.data console.log('设备信息:', this.deviceInfos) // 添加日志 if (this.getnum == 0) { this.getArea() } this.getnum = 1 this.vehicleNum = res.vehicleNum this.mac = res.data.mac this.getModelList() this.latitude = parseFloat(this.deviceInfos.latitude) this.longitude = parseFloat(this.deviceInfos.longitude) // 创建marker的通用方法 const createMarker = (device, iconConfig) => { const marker = { id: parseFloat(device.sn), latitude: parseFloat(device.latitude), longitude: parseFloat(device.longitude), width: 40, height: 47, iconPath: device.onlineStatus == 0 ? iconConfig.offline : iconConfig.online, label: { content: device.remainingPower + '%', color: iconConfig.labelColor || '#ffffff', fontSize: 12, borderRadius: 6, bgColor: iconConfig.labelBgColor || '#000000', padding: 10, display: 'ALWAYS' } } console.log('创建的marker:', marker) // 添加日志 return marker } // 定义各状态的图标配置 const iconConfigs = { status0: { online: 'https://lxnapi.ccttiot.com/bike/img/static/uocjFo8Ar2BJVpzC2G2f', offline: 'https://lxnapi.ccttiot.com/bike/img/static/uQRng4QNKA38Amk8Wgt5', labelColor: '#ffffff', labelBgColor: '#000000' }, status1: { online: 'https://lxnapi.ccttiot.com/bike/img/static/uheL17wVZn24BwCwEztT', offline: 'https://lxnapi.ccttiot.com/bike/img/static/uzhMeExOQJbMcZtrfGUV', labelColor: '#2679D1', labelBgColor: '#D4ECFF' }, status2: { online: 'https://lxnapi.ccttiot.com/bike/img/static/u460R1NKWHEpHbt0U4H7', offline: 'https://lxnapi.ccttiot.com/bike/img/static/uR3DQEssiK62ovhh88y8', labelColor: '#2679D1', labelBgColor: '#D4ECFF' }, status3: { online: 'https://lxnapi.ccttiot.com/bike/img/static/uHQIdWCTmtUztl49wBKU', offline: 'https://lxnapi.ccttiot.com/bike/img/static/uG13E7BpUFF44wVYC9no', labelColor: '#2679D1', labelBgColor: '#D4ECFF' }, status4: { online: 'https://lxnapi.ccttiot.com/bike/img/static/uZpXq3TBtM5gVgJJeImY', offline: 'https://lxnapi.ccttiot.com/bike/img/static/uRod2zf3t9dAOYafWoWt', labelColor: '#2679D1', labelBgColor: '#D4ECFF' }, status6: { online: 'https://lxnapi.ccttiot.com/bike/img/static/ujur6TezvPf4buFAqPHo', offline: 'https://lxnapi.ccttiot.com/bike/img/static/uhZudZM3nEKj0tYKlho2', labelColor: '#2679D1', labelBgColor: '#D4ECFF' }, status8: { online: 'https://lxnapi.ccttiot.com/bike/img/static/uyK7Vg4Lu8xb3oNVuG2l', offline: 'https://lxnapi.ccttiot.com/bike/img/static/ucBKG3ebYRAToVweJihu', labelColor: '#ffffff', labelBgColor: '#000000' } } console.log('设备状态:', this.deviceInfos.status) // 添加日志 // 根据设备状态创建对应的marker const status = this.deviceInfos.status if (status >= 0 && status <= 8) { // 确保状态值有效 const configKey = `status${status}` if (iconConfigs[configKey]) { const marker = createMarker(this.deviceInfos, iconConfigs[configKey]) this.markers.push(marker) } } console.log('最终的markers数组:', this.markers) // 添加日志 this.$forceUpdate() } else { uni.showToast({ title: res.msg, icon: 'none', duration: 2000 }); } }).catch(err => { console.error('获取设备信息失败:', err) // 添加错误日志 }) }, convertBoundaryToPolyline(boundary) { if (!boundary) return null; const points = JSON.parse(boundary).map(coord => ({ latitude: coord[1], longitude: coord[0] })); const polyline = { points: points, fillColor: "#55888870", //填充颜色 color: "#22FF0090", //描边颜色 width: 2, //描边宽度 zIndex: 1, //层级 }; return polyline; }, convertBoundaryToPolylines(boundaries, num) { if (num == 1) { console.log('判断'); return boundaries.map(boundary => { if (!boundary) return null; let coords; try { coords = JSON.parse(boundary); } catch (error) { console.error("Error parsing boundary JSON:", error); return null; } if (!Array.isArray(coords)) { console.error("Parsed boundary is not an array:", coords); return null; } const points = coords.map(coord => ({ latitude: coord[1], longitude: coord[0] })); return { points: points, fillColor: "#3A7EDB70", //填充颜色 color: "#3A7EDB90", //描边颜色 width: 2, //描边宽度 zIndex: 1, //层级 }; }).filter(polyline => polyline !== null); // 过滤掉无效的折线数据 } else if (num == 2) { return boundaries.map(boundary => { if (!boundary) return null; let coords; try { coords = JSON.parse(boundary); } catch (error) { console.error("Error parsing boundary JSON:", error); return null; } if (!Array.isArray(coords)) { console.error("Parsed boundary is not an array:", coords); return null; } const points = coords.map(coord => ({ latitude: coord[1], longitude: coord[0] })); return { points: points, fillColor: "#FFF5D670", //填充颜色 color: "#FFC10790", //描边颜色 width: 2, //描边宽度 zIndex: 1, //层级 }; }).filter(polyline => polyline !== null); // 过滤掉无效的折线数据 } else if (num == 3) { return boundaries.map(boundary => { if (!boundary) return null; let coords; try { coords = JSON.parse(boundary); } catch (error) { console.error("Error parsing boundary JSON:", error); return null; } if (!Array.isArray(coords)) { console.error("Parsed boundary is not an array:", coords); return null; } const points = coords.map(coord => ({ latitude: coord[1], longitude: coord[0] })); return { points: points, fillColor: "#FFD1CF70", //填充颜色 color: "#FF473E90", //描边颜色 width: 2, //描边宽度 zIndex: 1, //层级 }; }).filter(polyline => polyline !== null); // 过滤掉无效的折线数据 } }, toggleIconAndCallout() { this.showIconAndCallout = !this.showIconAndCallout; const updatedMarkers = this.markers.map(marker => { if (marker.isParking) { return { ...marker, label: this.showIconAndCallout ? marker.originalLabel : null }; } return marker; }); // 更新 markers 数组 this.$set(this, 'markers', updatedMarkers); }, getParking() { // 发送请求获取数据 let data = { areaId: this.deviceInfos.areaId } this.$u.get('/app/parking/list?', data).then((res) => { if (res.code === 200) { // 处理接口返回的数据 const newMarkers = []; const type1Data = []; const type2Data = []; const type3Data = []; res.rows.forEach(row => { if (row.type == 1) { type1Data.push(row); } else if (row.type == 2) { type2Data.push(row); } else if (row.type == 3) { type3Data.push(row); } newMarkers.push({ id: String(row.parkingId), latitude: parseFloat(row.latitude), longitude: parseFloat(row.longitude), width: 20, height: 29, iconPath: row.type == 1 ? 'https://lxnapi.ccttiot.com/bike/img/static/up2xXqAgwCX5iER600k3' : row.type == 2 ? 'https://lxnapi.ccttiot.com/bike/img/static/u53BAQcFIX3vxsCzEZ7t' : 'https://lxnapi.ccttiot.com/bike/img/static/uDNY5Q4zOiZTCBTA2Jdq', label: null, // 初始设置为 null originalLabel: { // 存储原始 label 信息 content: row.parkingName, color: '#ffffff', fontSize: 14, bgColor: row.type == 1 ? '#3A7EDB' : row.type == 2 ? '#FFC107' : '#FF473E', padding: 6, borderRadius: 10, anchorX: 0.5, anchorY: 1, textAlign: 'center' }, isParking: true }); }); console.log(this.markers, 'aaaaaaaaaaaaaaa'); this.$set(this, 'markers', [...this.markers, ...newMarkers]); const validBoundaries1 = type1Data.map(row => row.boundaryStr).filter(boundary => typeof boundary === 'string' && boundary.trim() !== ''); const polylines1 = this.convertBoundaryToPolylines(validBoundaries1, 1); const validBoundaries2 = type2Data.map(row => row.boundaryStr).filter(boundary => typeof boundary === 'string' && boundary.trim() !== ''); const polylines2 = this.convertBoundaryToPolylines(validBoundaries2, 2); const validBoundaries3 = type3Data.map(row => row.boundaryStr).filter(boundary => typeof boundary === 'string' && boundary.trim() !== ''); const polylines3 = this.convertBoundaryToPolylines(validBoundaries3, 3); // 将处理后的数据添加到 this.polyline 中 this.polyline = this.polyline.concat(polylines1, polylines2, polylines3); this.parkingList = res.rows // console.log(this.polyline); } }).catch(error => { console.error("Error fetching parking data:", error); }); }, getArea() { // 发送请求获取数据 let id = this.deviceInfos.areaId this.$u.get("/app/area/" + id).then((res) => { if (res.code === 200) { // 处理接口返回的数据,将边界数据转换为地图组件需要的折线结构 const polylines = this.convertBoundaryToPolyline(res.data.boundaryStr) // 更新折线数据 this.polyline.push(polylines) // console.log(this.polyline); this.getParking() } }).catch(error => { console.error("Error fetching area data:", error); }); }, } } </script> <style lang="scss"> page { overflow-x: hidden; background-color: #F3F3F3; } .page { padding-bottom: 400rpx; width: 750rpx; .tip_box { position: fixed; left: 72rpx; top: 628rpx; width: 610rpx; // height: 282rpx; background: #FFFFFF; border-radius: 30rpx 30rpx 30rpx 30rpx; z-index: 110; padding-bottom: 100rpx; .saveQr { margin: 0 auto; margin-top: 30rpx; display: flex; align-items: center; justify-content: center; width: 502rpx; height: 68rpx; background: #4C97E7; border-radius: 10rpx 10rpx 10rpx 10rpx; font-weight: 500; font-size: 36rpx; color: #FFFFFF; } .top { padding: 52rpx 38rpx 42rpx 36rpx; .ipt_box { margin-top: 22rpx; display: flex; flex-wrap: nowrap; align-items: center; .text { width: 350rpx; font-weight: 400; font-size: 32rpx; color: #3D3D3D; } .ipt { padding: 10rpx 18rpx; display: flex; align-items: center; justify-content: space-between; margin-left: 26rpx; width: 420rpx; height: 64rpx; border-radius: 0rpx 0rpx 0rpx 0rpx; border: 2rpx solid #979797; .input { width: 80%; } } } .tip { width: 100%; text-align: center; font-weight: 700; font-size: 32rpx; color: #3D3D3D; } .txt { margin-top: 32rpx; width: 100%; text-align: center; font-weight: 500; font-size: 32rpx; color: #3D3D3D; } } .bots { position: absolute; width: 610rpx; // border-top: 2rpx solid #D8D8D8; display: flex; flex-wrap: nowrap; // height: 100%; bottom: -20rpx; .bot_left { border-radius: 0rpx 0rpx 0rpx 30rpx; width: 50%; height: 86rpx; display: flex; align-items: center; justify-content: center; font-weight: 500; font-size: 32rpx; color: #3D3D3D; background: #EEEEEE; } .bot_right { border-radius: 0rpx 0rpx 30rpx 0rpx; width: 50%; height: 86rpx; background: #4C97E7; display: flex; align-items: center; justify-content: center; color: #FFFFFF; // border-left: 2rpx solid #D8D8D8; font-weight: 500; font-size: 32rpx; // color: #4C97E7; } } } .maskloadpage { position: fixed; padding: 46rpx; bottom: 0; width: 752rpx; height: 780rpx; background: #FFFFFF; border-radius: 40rpx 40rpx 0rpx 0rpx; z-index: 101; .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; } } } } .track { // 更改类名 position: absolute; right: 30rpx; top: 800rpx; display: flex; align-items: center; justify-content: center; left: 30rpx; bottom: 40rpx; border-radius: 50%; width: 82rpx; height: 82rpx; z-index: 10000; // 增加 z-index 确保控件在地图上层 .img { width: 82rpx; height: 82rpx; } } .park { position: absolute; right: 30rpx; top: 800rpx; display: flex; align-items: center; justify-content: center; right: 30rpx; bottom: 40rpx; border-radius: 50%; width: 82rpx; height: 82rpx; z-index: 10000; // 增加 z-index 确保控件在地图上层 .img { width: 82rpx; height: 82rpx; } } .map { position: relative; width: 750rpx; height: 752rpx; } // .tip_box { // position: fixed; // left: 72rpx; // top: 628rpx; // width: 610rpx; // // height: 282rpx; // background: #FFFFFF; // border-radius: 30rpx 30rpx 30rpx 30rpx; // z-index: 110; // padding-bottom: 100rpx; // .top { // padding: 52rpx 38rpx 42rpx 36rpx; // .ipt_box { // margin-top: 22rpx; // display: flex; // flex-wrap: nowrap; // align-items: center; // .text { // width: 96rpx; // font-weight: 400; // font-size: 32rpx; // color: #3D3D3D; // } // .ipt { // padding: 10rpx 18rpx; // display: flex; // align-items: center; // justify-content: space-between; // margin-left: 26rpx; // width: 420rpx; // height: 64rpx; // border-radius: 0rpx 0rpx 0rpx 0rpx; // border: 2rpx solid #979797; // .input { // width: 80%; // } // } // } // .tip { // width: 100%; // text-align: center; // font-weight: 700; // font-size: 32rpx; // color: #3D3D3D; // } // .txt { // margin-top: 32rpx; // width: 100%; // text-align: center; // font-weight: 500; // font-size: 32rpx; // color: #3D3D3D; // } // } // .bot { // position: absolute; // width: 610rpx; // // border-top: 2rpx solid #D8D8D8; // display: flex; // flex-wrap: nowrap; // // height: 100%; // bottom: -20rpx; // .bot_left { // border-radius: 0rpx 0rpx 0rpx 30rpx; // width: 50%; // height: 86rpx; // display: flex; // align-items: center; // justify-content: center; // font-weight: 500; // font-size: 32rpx; // color: #3D3D3D; // background: #EEEEEE; // } // .bot_right { // border-radius: 0rpx 0rpx 30rpx 0rpx; // width: 50%; // height: 86rpx; // background: #4C97E7; // display: flex; // align-items: center; // justify-content: center; // color: #FFFFFF; // // border-left: 2rpx solid #D8D8D8; // font-weight: 500; // font-size: 32rpx; // // color: #4C97E7; // } // } // } .bot_btn { position: fixed; bottom: 0; display: flex; flex-wrap: wrap; padding: 40rpx 18rpx; width: 750rpx; // height: 230rpx; background: #fff; // background: linear-gradient( 180deg, #FFFFFF 0%, rgba(255,255,255,0) 100%); box-shadow: 0rpx 10rpx 64rpx 0rpx rgba(0, 0, 0, 0.08); border-radius: 0rpx 0rpx 0rpx 0rpx; .btn:nth-child(4n) { margin-right: 0; } .btn { margin-top: 10rpx; margin-right: 18rpx; display: flex; align-items: center; justify-content: center; width: 164rpx; height: 66rpx; background: #E2F2FF; border-radius: 0rpx 0rpx 0rpx 0rpx; border: 2rpx solid #4C97E7; font-weight: 400; font-size: 28rpx; color: #3D3D3D; } } .info_card { background: #FFFFFF; .info_tit { display: flex; flex-wrap: nowrap; padding: 22rpx 28rpx; font-weight: 600; font-size: 32rpx; color: #3D3D3D; .money { margin-left: auto; font-weight: 500; font-size: 32rpx; color: #4C97E7; } } .lines { width: 750rpx; // height: 2rpx; border-bottom: 2rpx solid #E7E7E7; } .cont { padding: 26rpx 28rpx; .info_li { width: 98%; display: flex; flex-wrap: nowrap; font-weight: 400; font-size: 28rpx; color: #808080; span { color: #3D3D3D; } white-space: nowrap; /* 禁止换行 */ overflow: hidden; /* 超出部分隐藏 */ text-overflow: ellipsis; /* 显示省略号 */ line-height: 48rpx; .half_infoli { display: flex; flex-wrap: nowrap; width: 50%; font-weight: 400; font-size: 28rpx; color: #808080; span { color: #3D3D3D; } .input { width: 30%; } } } } } } </style>