3206 lines
96 KiB
Vue
3206 lines
96 KiB
Vue
<template>
|
||
<view class="page">
|
||
<u-navbar title="车辆详情" :border-bottom="false" :background="bgc" title-color='#2E4975' title-size='36'
|
||
height='45'></u-navbar>
|
||
<map class="map" id="map" ref="map" :scale="zoomSize" :latitude="latitude" :longitude="longitude"
|
||
:show-location="true" :markers="markers" :polygons="polyline">
|
||
<cover-view class="park" @click="toggleIconAndCallout" v-if="!showvehicle">
|
||
<cover-image class="img" src="https://lxnapi.ccttiot.com/bike/img/static/uRiYQZQEb3l2LsltEsyW" mode=""></cover-image>
|
||
</cover-view>
|
||
</map>
|
||
<view class="" style="position: fixed;top: 200rpx;left: 0;">
|
||
<view class="one" style="display: flex;justify-content: space-between;align-items: center;width: 100%;height: 50rpx;background-color: rgba(255, 255, 255, .5);padding: 0 20rpx;border-radius: 0 50rpx 50rpx 0;">
|
||
<view class="one" style="margin-bottom: 0;display: flex;align-items: center;color: #333;">
|
||
<image style="width: 32rpx;height: 32rpx;margin-right: 10rpx;" src="https://api.ccttiot.com/smartmeter/img/static/u5ouYhbxDvAVM6pImusK" mode="">
|
||
</image> {{deviceInfos.signalStrength == null ? '--' : deviceInfos.signalStrength}}
|
||
</view>
|
||
</view>
|
||
<view class="one" style="display: flex;justify-content: space-between;align-items: center;margin-top: 16rpx;width: 100%;height: 50rpx;background-color: rgba(255, 255, 255, .5);padding: 0 20rpx;border-radius: 0 50rpx 50rpx 0;" v-if="deviceInfos.satellites">
|
||
<view class="one" style="margin-bottom: 0;display: flex;align-items: center;color: #333;">
|
||
<image style="width: 32rpx;height: 32rpx;margin-right: 10rpx;" src="https://api.ccttiot.com/smartmeter/img/static/uesvOKQAO4eIFWSTIuQD" mode="">
|
||
</image> {{deviceInfos.satellites == null ? '--' : deviceInfos.satellites}}
|
||
</view>
|
||
</view>
|
||
</view>
|
||
|
||
<view class="new_infocard">
|
||
<view class="topsn">
|
||
<view class="lt" style="display: flex;align-items: center;">
|
||
<text style="width: 14rpx;height: 14rpx;border-radius: 50%;background-color: #28c445;margin-right: 10rpx;" v-if="deviceInfos.onlineStatus == 1"></text>
|
||
<text style="width: 14rpx;height: 14rpx;border-radius: 50%;background-color: red;margin-right: 10rpx;" v-if="deviceInfos.onlineStatus == 0"></text>
|
||
车牌:{{deviceInfos.vehicleNum == null ? '--' : deviceInfos.vehicleNum}}
|
||
</view>
|
||
<view class="" style="display: flex;justify-content: space-between;">
|
||
<view class="cent">
|
||
<view class="lypic" v-if="deviceInfos.music == 0" @click="btnsy">
|
||
<image src="https://api.ccttiot.com/smartmeter/img/static/uDORYeTuc2EQ1lSI2dbe" mode=""></image>
|
||
</view>
|
||
<view class="lypic" v-if="deviceInfos.music == 1" @click="btnsy">
|
||
<image src="https://api.ccttiot.com/smartmeter/img/static/u8ii1aiUgREfYyMVIjpO" mode=""></image>
|
||
</view>
|
||
<view class="lypic" v-if="deviceInfos.music == 2" @click="btnsy">
|
||
<image src="https://api.ccttiot.com/smartmeter/img/static/uP7BOVsjvWaGItgHtoKV" mode=""></image>
|
||
</view>
|
||
<view class="lypic" v-if="ver_dataflag == 3" @click="btnly">
|
||
<image src="https://api.ccttiot.com/smartmeter/img/static/uLw46jus4X9fposAvVD7" mode=""></image>
|
||
</view>
|
||
<view class="lypic" v-if="ver_dataflag == 1" @click="btnly">
|
||
<image class="glow-image" src="https://api.ccttiot.com/smartmeter/img/static/uCdHjNaNfD9aikVg9Cuk" mode="aspectFit" />
|
||
</view>
|
||
</view>
|
||
</view>
|
||
<view class="rt">
|
||
<view class="stutas">
|
||
<span style="background-color: #979797;" v-if="deviceInfos.status == 0">仓库</span>
|
||
<span style="background-color: #4c97e7;" v-if="deviceInfos.status == 1">待租</span>
|
||
<span style="background-color: #28c445;" v-if="deviceInfos.status == 2">预约中</span>
|
||
<span style="background-color: #ffc757;" v-if="deviceInfos.status == 3">骑行中</span>
|
||
<span style="background-color: #ff7429;" v-if="deviceInfos.status == 4">临时锁车</span>
|
||
<span style="background-color: #986cf0;" v-if="deviceInfos.status == 6">调度中</span>
|
||
<span style="background-color: red;" v-if="deviceInfos.status == 8">禁用</span>
|
||
<span style="background-color: #ff7429;" v-if="deviceInfos.status == 9">强制锁车</span>
|
||
</view>
|
||
<view class="issuo" v-if="deviceInfos.lockStatus == 0">
|
||
锁已关
|
||
</view>
|
||
<view class="issuo" style="background-color: #4C97E7;color: #fff;"
|
||
v-if="deviceInfos.lockStatus == 1">
|
||
锁已开
|
||
</view>
|
||
</view>
|
||
</view>
|
||
<view class="bikesn" style="border: none;padding-bottom: 6rpx;">
|
||
<view class="" style="width: 44%;">
|
||
SN:{{deviceInfos.sn == null ? '--' : deviceInfos.sn}}
|
||
</view>
|
||
<view class="" style="width: 30%;">
|
||
硬件:{{deviceInfos.hardwareVersion == null ? '--' : deviceInfos.hardwareVersion}}
|
||
</view>
|
||
<view class="" style="width: 30%;" @click="handleModelRowClick">
|
||
车型:<template v-if="deviceInfos && deviceInfos.modelName">{{(deviceInfos.modelName.length > 10)? deviceInfos.modelName.slice(0,10) + '...': deviceInfos.modelName}}</template>
|
||
<text v-else style="color:#4C97E7;">点击绑定</text>
|
||
</view>
|
||
</view>
|
||
<view style="display: flex;justify-content: space-between;">
|
||
<view class="" style="font-size: 24rpx;color: #7c7c7c;width: 44%;">
|
||
MAC:{{deviceInfos.mac == null ? '--' : deviceInfos.mac}}
|
||
</view>
|
||
|
||
<view class="" style="font-size: 24rpx;color: #7c7c7c;width: 30%;">
|
||
软件:{{deviceInfos.softwareVersion == null ? '--' : deviceInfos.softwareVersion}}
|
||
</view>
|
||
<view class="" style="width: 30%;">
|
||
<view class="" v-if="checkVersionflag && ver_dataflag == 3" @click="btnshengji" style="padding:6rpx 10rpx;border-radius: 6rpx;color: #fff;background-color: #4C97E7;font-size: 18rpx;margin-left: 10rpx;">
|
||
|
||
</view>
|
||
</view>
|
||
</view>
|
||
<view class="bikexx">
|
||
<view class="dianliang">
|
||
<image v-if="deviceInfos.remainingPower >= 0 && deviceInfos.remainingPower < 20 "
|
||
src="https://api.ccttiot.com/smartmeter/img/static/u8M9KmIfHXpmeifTwCzj" mode=""></image>
|
||
<image v-if="deviceInfos.remainingPower >= 20 && deviceInfos.remainingPower < 50 "
|
||
src="https://api.ccttiot.com/smartmeter/img/static/u2gp2pE9kPGwaJ4MKUxE" mode=""></image>
|
||
<image v-if="deviceInfos.remainingPower >= 50 && deviceInfos.remainingPower < 80 "
|
||
src="https://api.ccttiot.com/smartmeter/img/static/umm5Ruc5vhNSjeacslwX" mode=""></image>
|
||
<image v-if="deviceInfos.remainingPower >= 80 && deviceInfos.remainingPower <= 100 "
|
||
src="https://api.ccttiot.com/smartmeter/img/static/uo75cOfYZiQoxZQAI3FH" mode=""></image>
|
||
<view class="">
|
||
<view class="dl">
|
||
电量:<span style="font-size: 30rpx;color: #333;font-weight: 600;">{{deviceInfos.remainingPower == null ? '--' : deviceInfos.remainingPower}}</span>
|
||
<span style="color: #847f7f;font-size: 22rpx;">%</span>
|
||
</view>
|
||
<view class="dy">
|
||
电压:<span style="font-size: 30rpx;color: #333;font-weight: 600;">{{deviceInfos.voltage == null ? '--' : deviceInfos.voltage.toFixed(1)}}</span>
|
||
<span style="color: #847f7f;font-size: 22rpx;">V</span>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
<view class="xuhang">
|
||
<view class="">
|
||
<image src="https://api.ccttiot.com/smartmeter/img/static/uxFLA73NZnGm7gD5yxQK" mode=""></image>
|
||
续航:<span style="font-size: 30rpx;color: #333;font-weight: 600;">{{deviceInfos.remainEndurance == null ? '--' : deviceInfos.remainEndurance}}</span>km
|
||
</view>
|
||
</view>
|
||
<view class="ewm">
|
||
<view class="" @click="toTrack">
|
||
<image src="https://api.ccttiot.com/smartmeter/img/static/uJtMZ16iR2q8agQ4iLm3" mode=""></image>
|
||
轨迹
|
||
</view>
|
||
<view class="" style="margin-top: 14rpx;" @click="btndaohang">
|
||
<image src="https://api.ccttiot.com/smartmeter/img/static/u3De0EsfW6ZctTFCH9p7" mode=""></image>
|
||
导航
|
||
</view>
|
||
</view>
|
||
</view>
|
||
<view class="caozuoanniu">
|
||
<view class="dangeanniu" @click="checkbtn(0)">
|
||
<view class="pic">
|
||
<image src="https://api.ccttiot.com/smartmeter/img/static/uuHHQU2Yg2sReTadF51Y" mode=""></image>
|
||
</view>
|
||
开锁
|
||
</view>
|
||
<view class="dangeanniu" @click="checkbtn(1)">
|
||
<view class="pic">
|
||
<image src="https://api.ccttiot.com/smartmeter/img/static/uKear247uKM7Axwgh3Jc" mode=""></image>
|
||
</view>
|
||
关锁
|
||
</view>
|
||
<view class="dangeanniu" @click="btn(4)">
|
||
<view class="pic">
|
||
<image src="https://api.ccttiot.com/smartmeter/img/static/uE7zUe5bXdtGGyWA9WGG" mode=""></image>
|
||
</view>
|
||
响铃寻车
|
||
</view>
|
||
<view class="dangeanniu"
|
||
v-if="this.deviceInfos.hardwareVersion && this.deviceInfos.hardwareVersion.toLowerCase().includes('x')"
|
||
@click="btn(9)">
|
||
<view class="pic">
|
||
<image src="https://api.ccttiot.com/smartmeter/img/static/ujhsaJeL6KVrYgFSEKkj" mode=""></image>
|
||
</view>
|
||
坐垫锁
|
||
</view>
|
||
|
||
<view class="dangeanniu" @click="btn(10)">
|
||
<view class="pic">
|
||
<image src="https://api.ccttiot.com/smartmeter/img/static/uuuFxDo4XNzXJDTOQIeZ" mode=""></image>
|
||
</view>
|
||
刷新
|
||
</view>
|
||
<view class="dangeanniu" @click="btn(2)" v-if="deviceInfos.status!=8">
|
||
<view class="pic">
|
||
<image src="https://api.ccttiot.com/smartmeter/img/static/u1PlutiYn3alAcF2VuTH" mode=""></image>
|
||
</view>
|
||
禁用
|
||
</view>
|
||
<view class="dangeanniu" @click="btn(3)" v-if="deviceInfos.status==8">
|
||
<view class="pic">
|
||
<image src="https://api.ccttiot.com/smartmeter/img/static/u1PlutiYn3alAcF2VuTH" mode=""></image>
|
||
</view>
|
||
解禁
|
||
</view>
|
||
<view class="dangeanniu" @click="btn(5)" v-if="deviceInfos.status!=0">
|
||
<view class="pic">
|
||
<image src="https://api.ccttiot.com/smartmeter/img/static/ur58Qo0MoRfLynCIsrhV" mode=""></image>
|
||
</view>
|
||
回仓
|
||
</view>
|
||
<view class="dangeanniu" @click="btn(6)" v-if="deviceInfos.status==0">
|
||
<view class="pic">
|
||
<image src="https://api.ccttiot.com/smartmeter/img/static/uhhRNkjZJwiDZ2OFUPRF" mode=""></image>
|
||
</view>
|
||
出仓
|
||
</view>
|
||
<view class="dangeanniu" @click="btn(7)">
|
||
<view class="pic">
|
||
<image src="https://api.ccttiot.com/smartmeter/img/static/u277Tj0k5M7I8EO4V3ki" mode=""></image>
|
||
</view>
|
||
车牌修改
|
||
</view>
|
||
<view class="dangeanniu" @click="onModelBindClick">
|
||
<view class="pic">
|
||
<image src="https://api.ccttiot.com/smartmeter/img/static/uHj3BGlyN6dBWMiHwTTF" mode=""></image>
|
||
</view>
|
||
{{ deviceInfos && deviceInfos.modelName ? '修改车型' : '绑定车型' }}
|
||
</view>
|
||
<view class="dangeanniu" @click="btnhb">
|
||
<view class="pic">
|
||
<image src="https://api.ccttiot.com/smartmeter/img/static/uZuY3hgJBtCwnSnWTIC3" mode=""></image>
|
||
</view>
|
||
划拨
|
||
</view>
|
||
<view class="dangeanniu" v-if="Number(deviceInfos.softwareVersion) > 6000" @click="btnjingyin">
|
||
<view class="pic">
|
||
<image src="https://api.ccttiot.com/smartmeter/img/static/uFJGQN8dKzq06xR3b179" mode=""></image>
|
||
</view>
|
||
声音
|
||
</view>
|
||
<view class="dangeanniu" @click="btn(8)">
|
||
<view class="pic">
|
||
<image src="https://api.ccttiot.com/smartmeter/img/static/uWnOOwRQYpZxB14stYl8" mode=""></image>
|
||
</view>
|
||
重启
|
||
</view>
|
||
<view class="dangeanniu" @click="generateQrcode()">
|
||
<view class="pic">
|
||
<image src="https://api.ccttiot.com/smartmeter/img/static/uQdKTkDuXlwaZT5WFL2l" mode=""></image>
|
||
</view>
|
||
二维码
|
||
</view>
|
||
<view class="dangeanniu" @click="btnshoufei()">
|
||
<view class="pic">
|
||
<image src="https://api.ccttiot.com/smartmeter/img/static/um8ShZ4cBnh0weV1Qtz3" mode=""></image>
|
||
</view>
|
||
临时套餐
|
||
</view>
|
||
<view class="dangeanniu" v-if="isNfcHardwareByVersion(deviceInfos.hardwareVersion)" @click="toNfcList()">
|
||
<view class="pic">
|
||
<image src="https://api.ccttiot.com/smartmeter/img/static/uiBg5kMmVx4EMCQQrq50" mode=""></image>
|
||
</view>
|
||
NFC卡
|
||
</view>
|
||
|
||
</view>
|
||
<view class="zuche">
|
||
<view class="" style="margin-bottom: 26rpx;">
|
||
运营区域:<span>{{deviceInfos.areaName == null ? '--' : deviceInfos.areaName}}</span>
|
||
</view>
|
||
<view class="one" style="margin-bottom: 26rpx;">
|
||
最后租车客户: <span @click="btntel" style="color: #4C97E7;">
|
||
<image src="https://api.ccttiot.com/smartmeter/img/static/uCa86z0tr5WHiymtRJYt" mode=""></image>
|
||
{{deviceInfos.orderUserPhone == null ? '--' : deviceInfos.orderUserPhone}}
|
||
</span>
|
||
</view>
|
||
<view class="one" style="margin-bottom: 26rpx;" @click="btndd">
|
||
最后租车订单: <span
|
||
style="color: #4C97E7;">{{deviceInfos.orderNo == null ? '--' : deviceInfos.orderNo}}</span>
|
||
</view>
|
||
<view class="one" style="margin-bottom: 26rpx;">
|
||
最后用车时间: <span v-if="deviceInfos.orderDeviceStatus == 'USING'">使用中</span> <span
|
||
v-else>{{deviceInfos.orderDeviceEndTime == null ? '--' : deviceInfos.orderDeviceEndTime}}</span>
|
||
</view>
|
||
<view class="one" style="display: flex;justify-content: space-between;align-items: center;margin-bottom: 26rpx;">
|
||
<view class="one" style="margin-bottom: 0;">
|
||
最后定位时间:<image src="https://api.ccttiot.com/smartmeter/img/static/uesvOKQAO4eIFWSTIuQD" mode="">
|
||
</image> {{deviceInfos.satellites == null ? '--' : deviceInfos.satellites}}
|
||
</view>
|
||
<span>{{deviceInfos.lastLocationTime == null ? '--' : deviceInfos.lastLocationTime}}</span>
|
||
</view>
|
||
<view class="one" style="display: flex;justify-content: space-between;align-items: center;margin-bottom: 26rpx;">
|
||
<view class="one" style="margin-bottom: 0;">
|
||
最后在线时间:<image src="https://api.ccttiot.com/smartmeter/img/static/u5ouYhbxDvAVM6pImusK" mode="">
|
||
</image> {{deviceInfos.signalStrength == null ? '--' : deviceInfos.signalStrength}}
|
||
</view>
|
||
<span>{{deviceInfos.lastOnlineTime == null ? '--' : deviceInfos.lastOnlineTime}}</span>
|
||
</view>
|
||
<view class="one" style="display: flex;justify-content: space-between;align-items: center;">
|
||
<view class="one" style="margin-bottom: 0;display: flex;justify-content: space-between;align-items: center;width: 100%;">
|
||
<view class="" style="display: flex;align-items: center;">
|
||
手机定位时间:<u-switch v-model="mobileMarkerEnabled" active-color="#4C97E7" inactive-color="#C7CDD3" size="38" @change="onMobileMarkerSwitchChange"></u-switch>
|
||
</view>
|
||
<span>{{deviceInfos.mobileLocationTime == null ? '--' : deviceInfos.mobileLocationTime}}</span>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
<u-mask :show="false" @click="show = false" :z-index='100' />
|
||
<u-mask :show="maskloading" :z-index='100' duration='0' />
|
||
<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-mask :show="btProcessVisible" :z-index='101' duration='0' />
|
||
<view v-if="btProcessVisible" style="position: fixed;left: 50%;top: 50%;transform: translate(-50%, -50%);z-index: 102;width: 620rpx;background: #fff;border-radius: 16rpx;padding: 30rpx;box-sizing: border-box;">
|
||
<view style="font-size: 30rpx;color: #2E4975;font-weight: 600;text-align: center;">蓝牙自检中</view>
|
||
<view style="font-size: 24rpx;color: #666;text-align: center;margin-top: 18rpx;line-height: 1.6;">{{ btStepMessage }}</view>
|
||
<view style="margin-top: 22rpx;height: 16rpx;background: #EEF3FA;border-radius: 10rpx;overflow: hidden;">
|
||
<view :style="'height: 100%;background: #4C97E7;width:' + btProgress + '%;transition: width .25s;'"></view>
|
||
</view>
|
||
<view style="display:flex;justify-content: space-between;font-size: 20rpx;color:#7c7c7c;margin-top: 12rpx;">
|
||
<text>进度</text>
|
||
<text>{{ btProgress }}%</text>
|
||
</view>
|
||
<view v-if="btErrorMessage" style="margin-top: 16rpx;font-size: 24rpx;color: #E34D59;line-height: 1.6;">{{ btErrorMessage }}</view>
|
||
<view v-if="btErrorMessage" style="display:flex;justify-content:center;gap:16rpx;margin-top:18rpx;">
|
||
<view v-if="btErrorType === 'phone_bluetooth_off'" @click="goPhoneBluetoothSetting" style="width: 200rpx;height: 60rpx;line-height: 60rpx;text-align: center;border-radius: 30rpx;background: #28A745;color: #fff;font-size: 24rpx;">
|
||
去设置
|
||
</view>
|
||
<view v-if="btErrorType === 'wechat_auth_denied'" @click="openWechatBluetoothAuthSetting" style="width: 200rpx;height: 60rpx;line-height: 60rpx;text-align: center;border-radius: 30rpx;background: #28A745;color: #fff;font-size: 24rpx;">
|
||
去授权
|
||
</view>
|
||
<view @click="btProcessVisible = false" style="width: 180rpx;height: 60rpx;line-height: 60rpx;text-align: center;border-radius: 30rpx;background: #4C97E7;color: #fff;font-size: 24rpx;">
|
||
我知道了
|
||
</view>
|
||
</view>
|
||
<view v-if="btErrorMessage" style="text-align: center; margin-top: 18rpx; padding: 0 8rpx; font-size: 22rpx; color: #8A96A8; line-height: 1.5;">
|
||
蓝牙操作中请靠近车辆
|
||
</view>
|
||
</view>
|
||
<u-select v-model="showModelList" :list="ModelList" :title="deviceInfos && deviceInfos.modelName ? '修改车型' : '绑定车型'" @confirm="confirm"></u-select>
|
||
<u-select v-model="yunyingflag" :list="yunyingList" title='修改运营区' @confirm="yunyingconfirm"></u-select>
|
||
<!-- 删除原来的 u-select -->
|
||
|
||
<!-- 添加自定义声音选择弹出框 -->
|
||
<u-mask :show="shengyin" @click="shengyin = false" :z-index='100' />
|
||
<view class="sound-select" v-if="shengyin">
|
||
<view class="sound-header">
|
||
声音选项
|
||
<view class="close-btn" @click="shengyin = false">
|
||
×
|
||
</view>
|
||
</view>
|
||
<view class="sound-options">
|
||
<view class="sound-item" :class="{ active: deviceInfos.music == 0 }"
|
||
@click="shengyinaniu({value:0,label:'静音'})">
|
||
<view class="icon">
|
||
<image src="https://api.ccttiot.com/smartmeter/img/static/uDORYeTuc2EQ1lSI2dbe" mode=""></image>
|
||
</view>
|
||
<view class="label">静音模式</view>
|
||
<view class="desc">将模块所有声音全部设为静音</view>
|
||
</view>
|
||
<view class="sound-item" :class="{ active: deviceInfos.music == 1 }"
|
||
@click="shengyinaniu({value:1,label:'语音'})">
|
||
<view class="icon">
|
||
<image src="https://api.ccttiot.com/smartmeter/img/static/u8ii1aiUgREfYyMVIjpO" mode=""></image>
|
||
</view>
|
||
<view class="label">语音模式</view>
|
||
<view class="desc">将模块所有声音设为语音播报</view>
|
||
</view>
|
||
<view class="sound-item" :class="{ active: deviceInfos.music == 2 }"
|
||
@click="shengyinaniu({value:2,label:'彩铃'})">
|
||
<view class="icon">
|
||
<image src="https://api.ccttiot.com/smartmeter/img/static/uP7BOVsjvWaGItgHtoKV" mode=""></image>
|
||
</view>
|
||
<view class="label">彩铃模式</view>
|
||
<view class="desc">将开锁、关锁、报警声设为彩铃</view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</template>
|
||
|
||
<script>
|
||
import { showLoading } from "../../components/blufi/util"
|
||
const app = getApp()
|
||
var xBlufi = require("@/components/blufi/xBlufi.js")
|
||
let _this = null
|
||
export default {
|
||
data() {
|
||
return {
|
||
shengyin: false,
|
||
shengyinlist: [{
|
||
label: '静音',
|
||
value: 0
|
||
}, {
|
||
label: '语音',
|
||
value: 1
|
||
}, {
|
||
label: '彩铃',
|
||
value: 2
|
||
}],
|
||
|
||
devicesList: [],
|
||
searching: false,
|
||
texts: '正在扫描蓝牙设备...',
|
||
btnflag: true,
|
||
tishiflag: false,
|
||
option: '',
|
||
bluthlist: [], //蓝牙数组
|
||
statusflag: false,
|
||
Bluetoothmac: '',
|
||
mac: '',
|
||
ishave: false,
|
||
ver_data: null,
|
||
gps: {},
|
||
isband: false,
|
||
deviceIds: '',
|
||
name: '',
|
||
orderinfo: {},
|
||
dl: 0,
|
||
czmoney: true,
|
||
iscz: true,
|
||
bgc: {
|
||
backgroundColor: "#F7FAFE",
|
||
},
|
||
show: true,
|
||
showgj: true,
|
||
searchKeyword: '11',
|
||
latitude: '',
|
||
longitude: '',
|
||
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: [],
|
||
yunyingflag: false,
|
||
yunyingList: [],
|
||
jytxt: '',
|
||
|
||
ver_dataflag: 1,
|
||
mac: '',
|
||
deviceid: '',
|
||
devicename: '',
|
||
devicesarr: [],
|
||
findDeviceTimer: null,
|
||
jieliuflag: true,
|
||
|
||
isMarkerVisible: true,
|
||
mobileMarkerEnabled: false,
|
||
|
||
isVisible: true,
|
||
glowInterval: null,
|
||
lat:'',
|
||
lon:'',
|
||
shibainum:0,
|
||
jiance:false,
|
||
checkVersionflag:false,
|
||
btProcessVisible: false,
|
||
btProgress: 0,
|
||
btStepMessage: '',
|
||
btErrorMessage: '',
|
||
btErrorType: '',
|
||
btAdapterAvailable: null
|
||
}
|
||
},
|
||
onLoad(e) {
|
||
this.sn = e.id
|
||
this.deviceInfo()
|
||
this.deptId = uni.getStorageSync('deptId')
|
||
},
|
||
onShow() {
|
||
xBlufi.initXBlufi(1)
|
||
xBlufi.notifyStartDiscoverBle({
|
||
'isStart': true
|
||
})
|
||
xBlufi.listenDeviceMsgEvent(true, this.funListenDeviceMsgEvent)
|
||
this.bindBluetoothAdapterStateChange()
|
||
this.getyunying()
|
||
uni.getLocation({
|
||
type: 'gcj02', // 国内地图更兼容
|
||
isHighAccuracy: true,
|
||
accuracy:'best',
|
||
success: (res) => {
|
||
console.log('精确坐标:', res)
|
||
this.lat = res.latitude
|
||
this.lon = res.longitude
|
||
},
|
||
fail: (err) => {
|
||
this.lat = null
|
||
this.lon = null
|
||
console.error('获取位置失败:', err)
|
||
}
|
||
})
|
||
},
|
||
mounted() {
|
||
// 开启呼吸灯效果
|
||
this.startGlowEffect();
|
||
},
|
||
beforeDestroy() {
|
||
// 清除定时器
|
||
clearInterval(this.glowInterval);
|
||
},
|
||
onHide() {
|
||
this.clearPageRuntimeState()
|
||
},
|
||
onUnload: function() {
|
||
this.clearPageRuntimeState()
|
||
},
|
||
methods: {
|
||
clearPageRuntimeState() {
|
||
const oldDeviceId = this.deviceid
|
||
const oldDeviceName = this.devicename || this.name
|
||
this.unbindBluetoothAdapterStateChange()
|
||
try {
|
||
uni.hideLoading()
|
||
} catch (e) {}
|
||
this.btProcessVisible = false
|
||
this.btProgress = 0
|
||
this.btStepMessage = ''
|
||
this.btErrorMessage = ''
|
||
this.btErrorType = ''
|
||
this.wenbentxtflag = false
|
||
this.wenbentxt = ''
|
||
this.showbtntip = false
|
||
this.shibainum = 0
|
||
this.ver_dataflag = 1
|
||
this.jieliuflag = true
|
||
this.jiance = false
|
||
this.btAdapterAvailable = null
|
||
if (this.findDeviceTimer) {
|
||
clearTimeout(this.findDeviceTimer)
|
||
this.findDeviceTimer = null
|
||
}
|
||
xBlufi.notifyConnectBle({
|
||
isStart: false,
|
||
deviceId: oldDeviceId,
|
||
name: oldDeviceName
|
||
})
|
||
xBlufi.notifyStartDiscoverBle({
|
||
'isStart': false
|
||
})
|
||
xBlufi.listenDeviceMsgEvent(false, this.funListenDeviceMsgEvent)
|
||
this.deviceid = ''
|
||
this.devicename = ''
|
||
},
|
||
bindBluetoothAdapterStateChange() {
|
||
if (!uni.onBluetoothAdapterStateChange) {
|
||
return
|
||
}
|
||
if (uni.offBluetoothAdapterStateChange) {
|
||
try {
|
||
uni.offBluetoothAdapterStateChange(this.handleBluetoothAdapterStateChange)
|
||
} catch (e) {}
|
||
}
|
||
uni.onBluetoothAdapterStateChange(this.handleBluetoothAdapterStateChange)
|
||
},
|
||
unbindBluetoothAdapterStateChange() {
|
||
if (!uni.offBluetoothAdapterStateChange) {
|
||
return
|
||
}
|
||
try {
|
||
uni.offBluetoothAdapterStateChange(this.handleBluetoothAdapterStateChange)
|
||
} catch (e) {}
|
||
},
|
||
handleBluetoothAdapterStateChange(res) {
|
||
const available = !!(res && res.available)
|
||
if (available) {
|
||
this.btAdapterAvailable = true
|
||
return
|
||
}
|
||
const wasAvailable = this.btAdapterAvailable
|
||
this.btAdapterAvailable = false
|
||
this.ver_dataflag = 1
|
||
this.shibainum = 0
|
||
this.deviceid = ''
|
||
this.devicename = ''
|
||
if (this.btProcessVisible) {
|
||
this.showBtStepError('手机蓝牙未开启,请去系统设置打开', 'phone_bluetooth_off')
|
||
}
|
||
if (wasAvailable !== false) {
|
||
this.ver_dataflag = 1
|
||
uni.showToast({
|
||
title: '检测到手机蓝牙已关闭,连接已断开',
|
||
icon: 'none',
|
||
duration: 2000
|
||
})
|
||
}
|
||
},
|
||
resetBtProcessUI() {
|
||
this.btProcessVisible = true
|
||
this.btProgress = 0
|
||
this.btStepMessage = '准备开始蓝牙自检'
|
||
this.btErrorMessage = ''
|
||
this.btErrorType = ''
|
||
},
|
||
setBtProgress(stage) {
|
||
if (stage === 'scan') {
|
||
this.btProgress = 50
|
||
this.btStepMessage = '正在搜索设备...'
|
||
} else if (stage === 'connect') {
|
||
this.btProgress = 80
|
||
this.btStepMessage = '已搜索到设备,正在建立蓝牙连接...'
|
||
} else if (stage === 'send') {
|
||
this.btProgress = 100
|
||
this.btStepMessage = '蓝牙已连接,正在发送命令...'
|
||
}
|
||
},
|
||
showBtStepError(message, type = '') {
|
||
this.btErrorMessage = message
|
||
this.btErrorType = type
|
||
this.btStepMessage = '蓝牙自检未通过'
|
||
this.ver_dataflag = 1
|
||
this.shibainum = 0
|
||
this.jieliuflag = true
|
||
},
|
||
openWechatBluetoothAuthSetting() {
|
||
uni.openSetting({
|
||
success: () => {},
|
||
fail: () => {
|
||
uni.showToast({
|
||
title: '请在微信设置中开启蓝牙权限',
|
||
icon: 'none',
|
||
duration: 2000
|
||
})
|
||
}
|
||
})
|
||
},
|
||
goPhoneBluetoothSetting() {
|
||
// 微信小程序可直接拉起系统蓝牙设置页
|
||
// #ifdef MP-WEIXIN
|
||
if (typeof wx !== 'undefined' && wx.openSystemBluetoothSetting) {
|
||
wx.openSystemBluetoothSetting({
|
||
success: () => {},
|
||
fail: () => {
|
||
uni.showToast({
|
||
title: '无法直接跳转,请手动打开手机蓝牙',
|
||
icon: 'none',
|
||
duration: 2000
|
||
})
|
||
}
|
||
})
|
||
return
|
||
}
|
||
// #endif
|
||
uni.showToast({
|
||
title: '请手动进入系统设置打开蓝牙',
|
||
icon: 'none',
|
||
duration: 2000
|
||
})
|
||
},
|
||
waitForCondition(checker, timeout = 6000, interval = 250) {
|
||
return new Promise((resolve) => {
|
||
const start = Date.now()
|
||
const timer = setInterval(() => {
|
||
if (checker()) {
|
||
clearInterval(timer)
|
||
resolve(true)
|
||
return
|
||
}
|
||
if (Date.now() - start >= timeout) {
|
||
clearInterval(timer)
|
||
resolve(false)
|
||
}
|
||
}, interval)
|
||
})
|
||
},
|
||
sleep(ms = 300) {
|
||
return new Promise((resolve) => setTimeout(resolve, ms))
|
||
},
|
||
async connectMatchedDeviceWithRetry(matchedDevice, maxRetry = 3) {
|
||
for (let attempt = 1; attempt <= maxRetry; attempt++) {
|
||
this.btStepMessage = '已搜索到设备,正在建立蓝牙连接...(第' + attempt + '/' + maxRetry + '次)'
|
||
this.ver_dataflag = 2
|
||
try {
|
||
// 先清理上一轮连接状态,降低串线概率
|
||
if (this.deviceid) {
|
||
xBlufi.notifyConnectBle({
|
||
isStart: false,
|
||
deviceId: this.deviceid,
|
||
name: this.devicename || matchedDevice.name
|
||
})
|
||
await this.sleep(250)
|
||
}
|
||
} catch (e) {}
|
||
xBlufi.notifyConnectBle({
|
||
isStart: true,
|
||
deviceId: matchedDevice.deviceId,
|
||
name: matchedDevice.name
|
||
})
|
||
this.deviceid = matchedDevice.deviceId
|
||
this.devicename = matchedDevice.name
|
||
const connected = await this.waitForCondition(() => this.ver_dataflag === 3, 12000, 300)
|
||
if (connected) {
|
||
return true
|
||
}
|
||
const recheckConnected = await this.waitForCondition(() => this.ver_dataflag === 3, 2000, 200)
|
||
if (recheckConnected) {
|
||
return true
|
||
}
|
||
if (attempt < maxRetry) {
|
||
await this.sleep(500)
|
||
}
|
||
}
|
||
return false
|
||
},
|
||
safeIotPut(url, data, timeoutMs = 12000) {
|
||
const reqPromise = this.$u.put(url, data).catch(() => {
|
||
return {
|
||
code: 500,
|
||
msg: '网络异常,请稍后重试'
|
||
}
|
||
})
|
||
const timeoutPromise = new Promise((resolve) => {
|
||
setTimeout(() => {
|
||
resolve({
|
||
code: 20003,
|
||
msg: '请求超时'
|
||
})
|
||
}, timeoutMs)
|
||
})
|
||
return Promise.race([reqPromise, timeoutPromise])
|
||
},
|
||
/** 20001/20002/20003 视为可重试的超时/弱网;第一次失败后自动再请求一次,第二次仍如此则走蓝牙 */
|
||
_isIotTimeoutLike(res) {
|
||
return !!(res && (res.code == 20001 || res.code == 20002 || res.code == 20003))
|
||
},
|
||
iotRequestTwiceBeforeBle(url, data) {
|
||
return this.safeIotPut(url, data).then((res) => {
|
||
if (res && res.code == 200) {
|
||
return { type: 'success', res }
|
||
}
|
||
if (this._isIotTimeoutLike(res)) {
|
||
return this.safeIotPut(url, data).then((res2) => {
|
||
if (res2 && res2.code == 200) {
|
||
return { type: 'success', res: res2 }
|
||
}
|
||
if (this._isIotTimeoutLike(res2)) {
|
||
return { type: 'ble' }
|
||
}
|
||
return { type: 'error', res: res2 }
|
||
})
|
||
}
|
||
return { type: 'error', res }
|
||
})
|
||
},
|
||
/** IoT 开锁失败后走蓝牙自检 + 下发指令 + 二次上报(与原先 db/iot 分支一致) */
|
||
_merchantUnlockBluetoothSequence() {
|
||
uni.hideLoading()
|
||
this.runPreciseBluetoothSelfCheck().then((checkRes) => {
|
||
if (!checkRes.ok) {
|
||
return
|
||
}
|
||
setTimeout(() => {
|
||
xBlufi.notifySendCustomData({
|
||
customData: "11opensub5@"
|
||
})
|
||
this.btProcessVisible = false
|
||
this.jieliuflag = true
|
||
}, 1000)
|
||
let arrs = this.devicesarr.map(item => {
|
||
const name = item.name || ''
|
||
return name.slice(-12)
|
||
})
|
||
let datas = {
|
||
id: this.sn,
|
||
requiredIot: true,
|
||
lat: this.lat,
|
||
lon: this.lon,
|
||
macList: arrs,
|
||
sendIot: false
|
||
}
|
||
this.safeIotPut(`/bst/device/iot/unlock`, datas).then((res) => {
|
||
if (res.code == 200) {
|
||
this.deviceInfo()
|
||
uni.showToast({
|
||
title: '操作成功',
|
||
icon: 'success',
|
||
duration: 3000
|
||
})
|
||
let data = {
|
||
mac: this.mac,
|
||
reason: '商户开锁',
|
||
command: '11opensub5@',
|
||
longitude: this.lon,
|
||
latitude: this.lat,
|
||
result: '成功'
|
||
}
|
||
this.$u.post(`/app/commandLog/bluetooth`, data).then(res => {})
|
||
this.jieliuflag = true
|
||
} else {
|
||
uni.showToast({
|
||
title: res.msg,
|
||
icon: 'none',
|
||
duration: 2000
|
||
})
|
||
}
|
||
})
|
||
}).catch(() => {
|
||
this.showBtStepError('已找到设备,但连接失败,请重试')
|
||
})
|
||
},
|
||
/** IoT 关锁失败后走蓝牙自检 + 下发指令 + 二次上报 */
|
||
_merchantLockBluetoothSequence() {
|
||
uni.hideLoading()
|
||
this.runPreciseBluetoothSelfCheck().then((checkRes) => {
|
||
if (!checkRes.ok) {
|
||
return
|
||
}
|
||
setTimeout(() => {
|
||
xBlufi.notifySendCustomData({
|
||
customData: "11closesub200@"
|
||
})
|
||
this.btProcessVisible = false
|
||
}, 1000)
|
||
let arrs = this.devicesarr.map(item => {
|
||
const name = item.name || ''
|
||
return name.slice(-12)
|
||
})
|
||
let datas = {
|
||
id: this.sn,
|
||
requiredIot: false,
|
||
lat: this.lat,
|
||
lon: this.lon,
|
||
macList: arrs,
|
||
sendIot: false
|
||
}
|
||
this.safeIotPut(`/bst/device/iot/lock`, datas).then((res) => {
|
||
if (res.code == 200) {
|
||
this.deviceInfo()
|
||
uni.showToast({
|
||
title: '操作成功',
|
||
icon: 'success',
|
||
duration: 3000
|
||
})
|
||
let data = {
|
||
mac: this.mac,
|
||
reason: '商户关锁',
|
||
command: '11closesub200@',
|
||
longitude: this.lon,
|
||
latitude: this.lat,
|
||
result: '成功'
|
||
}
|
||
this.$u.post(`/app/commandLog/bluetooth`, data).then(res => {})
|
||
} else {
|
||
uni.showToast({
|
||
title: res.msg,
|
||
icon: 'none',
|
||
duration: 2000
|
||
})
|
||
}
|
||
})
|
||
}).catch(() => {
|
||
this.showBtStepError('已找到设备,但连接失败,请重试')
|
||
})
|
||
},
|
||
openBtAdapter() {
|
||
return new Promise((resolve, reject) => {
|
||
uni.openBluetoothAdapter({
|
||
success: () => resolve(true),
|
||
fail: (err) => reject(err || {})
|
||
})
|
||
})
|
||
},
|
||
getBtAuthState() {
|
||
return new Promise((resolve) => {
|
||
uni.getSetting({
|
||
success: (res) => {
|
||
const authSetting = (res && res.authSetting) || {}
|
||
resolve(authSetting['scope.bluetooth'])
|
||
},
|
||
fail: () => resolve(undefined)
|
||
})
|
||
})
|
||
},
|
||
authorizeBt() {
|
||
return new Promise((resolve) => {
|
||
uni.authorize({
|
||
scope: 'scope.bluetooth',
|
||
success: () => resolve(true),
|
||
fail: () => resolve(false)
|
||
})
|
||
})
|
||
},
|
||
async runPreciseBluetoothSelfCheck() {
|
||
this.resetBtProcessUI()
|
||
// 第一步:检测蓝牙是否开启
|
||
try {
|
||
await this.openBtAdapter()
|
||
} catch (err) {
|
||
const errMsg = (err && err.errMsg) || ''
|
||
if (errMsg.indexOf('auth deny') > -1 || errMsg.indexOf('authorize no response') > -1) {
|
||
this.showBtStepError('微信蓝牙未授权,请去微信授权', 'wechat_auth_denied')
|
||
} else {
|
||
this.showBtStepError('手机蓝牙未开启,请去系统设置打开', 'phone_bluetooth_off')
|
||
}
|
||
return { ok: false, step: 1 }
|
||
}
|
||
// 第二步:检测微信/小程序蓝牙权限
|
||
let authState = await this.getBtAuthState()
|
||
if (authState === false) {
|
||
this.showBtStepError('微信蓝牙未授权,请去微信授权', 'wechat_auth_denied')
|
||
return { ok: false, step: 2 }
|
||
}
|
||
if (typeof authState === 'undefined') {
|
||
const authorized = await this.authorizeBt()
|
||
if (!authorized) {
|
||
this.showBtStepError('微信蓝牙未授权,请去微信授权', 'wechat_auth_denied')
|
||
return { ok: false, step: 2 }
|
||
}
|
||
}
|
||
// 第三步:搜索设备
|
||
this.setBtProgress('scan')
|
||
xBlufi.notifyStartDiscoverBle({
|
||
'isStart': true
|
||
})
|
||
const found = await this.waitForCondition(() => {
|
||
return this.devicesarr.some((device) => {
|
||
const name = (device && device.name) || ''
|
||
const mac = this.mac || ''
|
||
return name && mac && name.slice(-12) === mac.slice(-12)
|
||
})
|
||
}, 8000, 400)
|
||
if (!found) {
|
||
this.showBtStepError('未搜索到目标设备,请检查设备是否开机', 'device_not_found')
|
||
return { ok: false, step: 3 }
|
||
}
|
||
// 第四步:连接设备
|
||
const matchedDevice = this.devicesarr.find((device) => {
|
||
const name = (device && device.name) || ''
|
||
const mac = this.mac || ''
|
||
return name && mac && name.slice(-12) === mac.slice(-12)
|
||
})
|
||
if (!matchedDevice) {
|
||
this.showBtStepError('未搜索到目标设备,请检查设备是否开机', 'device_not_found')
|
||
return { ok: false, step: 3 }
|
||
}
|
||
this.setBtProgress('connect')
|
||
xBlufi.notifyStartDiscoverBle({
|
||
'isStart': false
|
||
})
|
||
// 连接失败自动重连 3 次,提升弱网/抖动场景稳定性
|
||
const connected = await this.connectMatchedDeviceWithRetry(matchedDevice, 3)
|
||
if (!connected) {
|
||
this.showBtStepError('已找到设备,但连接失败,请重试', 'connect_failed')
|
||
return { ok: false, step: 4 }
|
||
}
|
||
// 连接刚建立时给设备留一点准备时间,避免命令下发过早丢包
|
||
this.btStepMessage = '蓝牙已连接,正在准备发送命令...'
|
||
await this.sleep(2000)
|
||
this.setBtProgress('send')
|
||
return { ok: true }
|
||
},
|
||
// 点击进行硬件升级
|
||
btnshengji(){
|
||
xBlufi.notifySendCustomData({
|
||
customData: "11update@"
|
||
})
|
||
uni.showModal({
|
||
title: '命令发送成功',
|
||
content: '五分钟内会自行升级成功,中途请勿断开电源或对设备进行操作',
|
||
showCancel: false,
|
||
success: function(res) {
|
||
if (res.confirm) {
|
||
|
||
} else if (res.cancel) {
|
||
|
||
}
|
||
}
|
||
})
|
||
},
|
||
// 判断是否能升级
|
||
checkVersion(hardwareVersion, softwareVersion) {
|
||
const isHardwareStartWithX = hardwareVersion && (hardwareVersion.startsWith('x') || hardwareVersion.startsWith('X'));
|
||
const softwareVerNum = Number(softwareVersion) || 0;
|
||
const isSoftwareValid = softwareVerNum <= 8014;
|
||
console.log(isHardwareStartWithX && isSoftwareValid,'4545457878787989+8');
|
||
this.checkVersionflag = isHardwareStartWithX && isSoftwareValid;
|
||
return isHardwareStartWithX && isSoftwareValid;
|
||
},
|
||
|
||
// 点击跳转到临时收费
|
||
btnshoufei(){
|
||
uni.navigateTo({
|
||
url:'/page_shanghu/linshishoufei?sn=' + this.deviceInfos.sn + '&cxid=' + this.deviceInfos.modelId
|
||
})
|
||
},
|
||
// 硬件是否为 D 系(NFC):兼容全角D、前导零宽字符;与详情「硬件」字段一致
|
||
isNfcHardwareByVersion(hw) {
|
||
if (hw == null || hw === '') return false
|
||
let s = String(hw).replace(/[\u200B-\u200D\uFEFF]/g, '').trim()
|
||
if (!s.length) return false
|
||
if (typeof s.normalize === 'function') {
|
||
try {
|
||
s = s.normalize('NFKC')
|
||
} catch (e) {}
|
||
}
|
||
const c = s.charCodeAt(0)
|
||
return c === 68 || c === 100 || c === 0xff24 || c === 0xff44
|
||
},
|
||
// 点击跳转到NFC卡管理
|
||
toNfcList() {
|
||
uni.navigateTo({
|
||
url: '/page_shanghu/guanli/device_nfc?deviceId=' + this.sn
|
||
})
|
||
},
|
||
|
||
startGlowEffect() {
|
||
// 每1.5秒切换一次显隐状态
|
||
this.glowInterval = setInterval(() => {
|
||
this.isVisible = !this.isVisible;
|
||
}, 1500);
|
||
},
|
||
// 点击隐藏手机定位
|
||
btnsjyc() {
|
||
this.isMarkerVisible = !this.isMarkerVisible;
|
||
this.markers = this.markers.map(item => {
|
||
if (item.id === 0.1) {
|
||
return {
|
||
...item,
|
||
alpha: this.isMarkerVisible ? 1 : 0, // 0为完全透明,1为完全不透明
|
||
callout: {
|
||
...item.callout,
|
||
display: this.isMarkerVisible ? 'ALWAYS' : 'NONE'
|
||
}
|
||
}
|
||
}
|
||
return item;
|
||
})
|
||
this.$forceUpdate(); // 强制更新视图
|
||
},
|
||
hasMobileLocation() {
|
||
const lat = Number(this.deviceInfos.mobileLat)
|
||
const lon = Number(this.deviceInfos.mobileLon)
|
||
return Number.isFinite(lat) && Number.isFinite(lon)
|
||
},
|
||
updateMobileMarker() {
|
||
this.markers = this.markers.filter(item => item.id !== -9999)
|
||
if (!this.mobileMarkerEnabled || !this.hasMobileLocation()) {
|
||
return
|
||
}
|
||
const mobileLat = Number(this.deviceInfos.mobileLat)
|
||
const mobileLon = Number(this.deviceInfos.mobileLon)
|
||
this.markers.push({
|
||
id: -9999,
|
||
latitude: mobileLat,
|
||
longitude: mobileLon,
|
||
width: 40,
|
||
height: 47,
|
||
iconPath: 'https://api.ccttiot.com/smartmeter/img/static/uOMlphYYJ4wgaJVhNW4z',
|
||
callout: {
|
||
content: '手机定位',
|
||
color: '#2679D1',
|
||
fontSize: 10,
|
||
borderRadius: 10,
|
||
bgColor: '#D4ECFF',
|
||
padding: 4,
|
||
display: 'ALWAYS',
|
||
}
|
||
})
|
||
},
|
||
onMobileMarkerSwitchChange(val) {
|
||
this.mobileMarkerEnabled = !!val
|
||
if (this.mobileMarkerEnabled && !this.hasMobileLocation()) {
|
||
this.mobileMarkerEnabled = false
|
||
uni.showToast({
|
||
title: '暂无手机定位经纬度',
|
||
icon: 'none',
|
||
duration: 1500
|
||
})
|
||
return
|
||
}
|
||
if (this.mobileMarkerEnabled) {
|
||
this.latitude = Number(this.deviceInfos.mobileLat)
|
||
this.longitude = Number(this.deviceInfos.mobileLon)
|
||
uni.pageScrollTo({
|
||
scrollTop: 0,
|
||
duration: 300
|
||
})
|
||
}
|
||
this.updateMobileMarker()
|
||
this.$forceUpdate()
|
||
},
|
||
// 点击跳转到订单详情
|
||
btndd() {
|
||
uni.navigateTo({
|
||
url: '/page_shanghu/guanli/order_detail?orid=' + this.deviceInfos.orderId + '&id=' + this
|
||
.deviceInfos.sn
|
||
})
|
||
},
|
||
// 点击提示什么声音模式
|
||
btnsy() {
|
||
if (this.deviceInfos.music == 0) {
|
||
uni.showToast({
|
||
title: '当前设备为静音模式',
|
||
icon: 'none',
|
||
duration: 2000
|
||
})
|
||
} else if (this.deviceInfos.music == 1) {
|
||
uni.showToast({
|
||
title: '当前设备为语音模式',
|
||
icon: 'none',
|
||
duration: 2000
|
||
})
|
||
} else {
|
||
uni.showToast({
|
||
title: '当前设备为彩铃模式',
|
||
icon: 'none',
|
||
duration: 2000
|
||
})
|
||
}
|
||
},
|
||
// 点击提示蓝牙
|
||
btnly() {
|
||
if (this.ver_dataflag == 3) {
|
||
uni.showToast({
|
||
title: '当前设备蓝牙已连接',
|
||
icon: 'none',
|
||
duration: 2000
|
||
})
|
||
} else {
|
||
uni.showToast({
|
||
title: '当前设备蓝牙未连接',
|
||
icon: 'none',
|
||
duration: 2000
|
||
})
|
||
}
|
||
},
|
||
// 请求自己所有运营区
|
||
getyunying() {
|
||
this.$u.get(`/bst/area/list?pageNum=1&pageSize=999`).then(res => {
|
||
if (res.code == 200) {
|
||
this.yunyingList = res.rows.map(item => ({
|
||
value: item.id,
|
||
label: item.name
|
||
}))
|
||
}
|
||
})
|
||
},
|
||
// 点击拨打最近租车人电话
|
||
btntel() {
|
||
uni.makePhoneCall({
|
||
phoneNumber: this.deviceInfos.orderUserPhone,
|
||
success: function(res) {
|
||
console.log('拨打电话成功', res)
|
||
},
|
||
fail: function(err) {
|
||
console.error('拨打电话失败', err)
|
||
}
|
||
})
|
||
},
|
||
// 选择彩铃
|
||
shengyinaniu(e) {
|
||
uni.showLoading({
|
||
title: '加载中...',
|
||
mask: true
|
||
})
|
||
let arrs = this.devicesarr.map(item => {
|
||
const name = item.name || ''
|
||
return name.slice(-12)
|
||
})
|
||
let datas = {
|
||
id: this.sn,
|
||
requiredIot:true,
|
||
lat: this.lat,
|
||
lon: this.lon,
|
||
macList:arrs,
|
||
music:e.value
|
||
}
|
||
this.$u.put(`/bst/device/iot/music`,datas).then(res => {
|
||
if (res.code == 200) {
|
||
this.jytxt = e.label
|
||
this.deviceInfos.music = e.value
|
||
this.shengyin = false
|
||
uni.showToast({
|
||
title: '操作成功',
|
||
icon: 'success',
|
||
duration: 2000
|
||
})
|
||
setTimeout(() => {
|
||
uni.hideLoading()
|
||
}, 2000)
|
||
} else {
|
||
uni.hideLoading()
|
||
uni.showToast({
|
||
title: res.msg,
|
||
icon: 'none',
|
||
duration: 2000
|
||
})
|
||
}
|
||
})
|
||
},
|
||
// 点击进行导航
|
||
btndaohang() {
|
||
uni.openLocation({
|
||
latitude: this.deviceInfos.latitude, //纬度-目的地/坐标点
|
||
longitude: this.deviceInfos.longitude, //经度-目的地/坐标点
|
||
name: '', //地点名称
|
||
address: '' //详细地点名称
|
||
})
|
||
},
|
||
// 连接蓝牙
|
||
lanya(num) {
|
||
if (this.jieliuflag == true) {
|
||
this.jieliuflag = false
|
||
if (num == 0) {
|
||
uni.showLoading({
|
||
title: '连接中...', // 提示文字
|
||
mask: true // 是否显示透明遮罩层(防止触摸穿透)
|
||
})
|
||
this.getlanya()
|
||
} else if (num == 1) {
|
||
xBlufi.notifySendCustomData({
|
||
customData: "11opensub5@"
|
||
})
|
||
uni.showToast({
|
||
title: '发送成功',
|
||
icon: 'success',
|
||
duration: 2000
|
||
})
|
||
} else if (num == 2) {
|
||
xBlufi.notifySendCustomData({
|
||
customData: "11closesub200@"
|
||
})
|
||
uni.showToast({
|
||
title: '发送成功',
|
||
icon: 'success',
|
||
duration: 2000
|
||
})
|
||
} else if (num == 3) {
|
||
xBlufi.notifySendCustomData({
|
||
customData: "11reboot@"
|
||
})
|
||
uni.showToast({
|
||
title: '发送成功',
|
||
icon: 'success',
|
||
duration: 2000
|
||
})
|
||
} else if (num == 4) {
|
||
xBlufi.notifySendCustomData({
|
||
customData: "11play1@"
|
||
})
|
||
uni.showToast({
|
||
title: '发送成功',
|
||
icon: 'success',
|
||
duration: 2000
|
||
})
|
||
} else {
|
||
xBlufi.notifySendCustomData({
|
||
customData: "11hpen@"
|
||
})
|
||
uni.showToast({
|
||
title: '发送成功',
|
||
icon: 'success',
|
||
duration: 2000
|
||
})
|
||
}
|
||
this.jieliuflag = true
|
||
}
|
||
},
|
||
getlanya() {
|
||
xBlufi.notifyStartDiscoverBle({
|
||
'isStart': true
|
||
})
|
||
xBlufi.listenDeviceMsgEvent(true, this.funListenDeviceMsgEvent)
|
||
console.log("进入111蓝牙连接")
|
||
if (this.ver_dataflag != 3) {
|
||
this.ver_dataflag = 1
|
||
this.findDevice()
|
||
}
|
||
},
|
||
findDevice() {
|
||
// 使用 find 方法查找匹配的设备
|
||
const matchedDevice = this.devicesarr.find(device => {
|
||
// console.log(device.name, this.mac, '111')
|
||
return device.name.slice(-12) == this.mac.slice(-12)
|
||
})
|
||
if (matchedDevice) {
|
||
// 找到匹配的设备
|
||
xBlufi.notifyStartDiscoverBle({
|
||
'isStart': false
|
||
})
|
||
xBlufi.notifyConnectBle({
|
||
isStart: true,
|
||
deviceId: matchedDevice.deviceId,
|
||
name: matchedDevice.name
|
||
})
|
||
this.deviceid = matchedDevice.deviceId
|
||
this.devicename = matchedDevice.name
|
||
// console.log(this.deviceid, '11221')
|
||
} else {
|
||
// console.log("未找到匹配的设备,继续查找...")
|
||
this.findDeviceTimer = setTimeout(this.findDevice.bind(this), 1000) // 使用 bind 保持 this 上下文
|
||
}
|
||
},
|
||
// 获取附近蓝牙设备列表
|
||
funListenDeviceMsgEvent: function(options) {
|
||
switch (options.type) {
|
||
case xBlufi.XBLUFI_TYPE.TYPE_STATUS_CONNECTED:
|
||
if (!options.result) {
|
||
this.ver_dataflag = 1
|
||
this.deviceid = ''
|
||
this.devicename = ''
|
||
}
|
||
break;
|
||
case xBlufi.XBLUFI_TYPE.TYPE_GET_DEVICE_LISTS:
|
||
if (options.result) {
|
||
this.devicesarr = options.data
|
||
// console.log(this.devicesarr, 'this.devicesarrthis.devicesarr');
|
||
}
|
||
break;
|
||
case xBlufi.XBLUFI_TYPE.TYPE_CONNECTED:
|
||
console.log("连接回调:" + JSON.stringify(options))
|
||
if (options.result == true) {
|
||
// 连接成功回调到达即标记已连接,避免“已连上但未推数时被误判失败”
|
||
this.ver_dataflag = 3
|
||
this.jiance = false
|
||
xBlufi.notifyInitBleEsp32({
|
||
deviceId: this.deviceid
|
||
})
|
||
this.deviceid = options.data && options.data.deviceId ? options.data.deviceId : this.deviceid
|
||
this.name = this.name
|
||
} else {
|
||
|
||
}
|
||
break;
|
||
case xBlufi.XBLUFI_TYPE.TYPE_RECIEVE_CUSTON_DATA:
|
||
console.log("1收到设备发来的自定义数据结果:", options.data)
|
||
this.ver_dataflag = 3
|
||
this.jiance = false
|
||
this.getlysj(options.data)
|
||
break;
|
||
case xBlufi.XBLUFI_TYPE.TYPE_GET_DEVICE_LISTS_START:
|
||
if (!options.result) {
|
||
console.log('蓝牙未开启')
|
||
this.jiance = true
|
||
return
|
||
} else {
|
||
this.lanyaflag = false
|
||
}
|
||
break;
|
||
}
|
||
},
|
||
getlysj(data) {
|
||
if (!data) return;
|
||
// 1. 更健壮的数据解析
|
||
const dataStr = data.toString();
|
||
// console.log('原始数据:', dataStr);
|
||
const dataObj = {};
|
||
// 判断数据格式:检查是否包含@或,分隔符
|
||
let separator = ',';
|
||
if (dataStr.includes('@')) {
|
||
separator = '@';
|
||
}
|
||
// console.log('使用分隔符:', separator);
|
||
dataStr.split(separator).forEach(part => {
|
||
if (!part) return; // 忽略空字符串
|
||
// 如果使用@分隔符,数据格式为 key-value 对,例如: status0@csq0@bat125@...
|
||
if (separator === '@') {
|
||
// 使用正则表达式分离键(字母)和值(数字)
|
||
const match = part.match(/^([a-zA-Z]+)(.*)$/);
|
||
if (!match) return;
|
||
key = match[1];
|
||
value = match[2];
|
||
} else {
|
||
// 如果使用,分隔符,数据格式为 key:value 对,例如: status:0,csq:0,bat:125,...
|
||
const [keyPart, valuePart] = part.split(':').map(item => item.trim());
|
||
if (!keyPart || valuePart === undefined) return;
|
||
key = keyPart;
|
||
value = valuePart;
|
||
}
|
||
if (key && value !== undefined) {
|
||
switch (key) {
|
||
case 'status':
|
||
dataObj.status = value;
|
||
break;
|
||
case 'bat':
|
||
dataObj.bat = parseFloat(value);
|
||
break;
|
||
case 'csq':
|
||
dataObj.csq = parseInt(value, 10);
|
||
break;
|
||
case 'lat':
|
||
dataObj.lat = parseFloat(value);
|
||
break;
|
||
case 'lon':
|
||
dataObj.lon = parseFloat(value);
|
||
break;
|
||
case 'q':
|
||
dataObj.q = parseInt(value, 10);
|
||
break;
|
||
case 's':
|
||
dataObj.s = parseInt(value, 10);
|
||
break;
|
||
}
|
||
}
|
||
});
|
||
|
||
// console.log('解析后的数据对象:', dataObj);
|
||
|
||
// 2. 获取定位
|
||
uni.getLocation({
|
||
type: 'gcj02',
|
||
isHighAccuracy: true,
|
||
success: (res) => {
|
||
this.submitData({
|
||
...dataObj,
|
||
lon: res.longitude,
|
||
lat: res.latitude
|
||
})
|
||
},
|
||
fail: () => {
|
||
this.submitData({
|
||
...dataObj,
|
||
lon: dataObj.lon || 0,
|
||
lat: dataObj.lat || 0
|
||
})
|
||
}
|
||
})
|
||
},
|
||
// 3. 单独封装数据提交
|
||
submitData(data) {
|
||
let arr = this.devicesarr.map(item => {
|
||
const name = item.name || ''
|
||
return name.slice(-12)
|
||
})
|
||
const payload = {
|
||
mac: this.mac,
|
||
sys: {
|
||
bat: data.bat !== undefined && data.bat !== null ? Number(data.bat) : 0,
|
||
csq: data.csq !== undefined && data.csq !== null ? Number(data.csq) : 0,
|
||
s: data.s !== undefined && data.s !== null ? Number(data.s) : null,
|
||
q: data.q !== undefined && data.q !== null ? Number(data.q) : null,
|
||
status: String(data.status || '0'),
|
||
lon: data.lon !== undefined && data.lon !== null ? Number(data.lon) : 0,
|
||
lat: data.lat !== undefined && data.lat !== null ? Number(data.lat) : 0
|
||
},
|
||
maclist:arr
|
||
}
|
||
this.bluetoothData = payload
|
||
this.throttledUpload()
|
||
},
|
||
// 节流上传控制
|
||
throttledUpload() {
|
||
const now = Date.now()
|
||
const throttleInterval = 10000 // 10秒
|
||
// 清除之前的定时器
|
||
clearTimeout(this.uploadTimer)
|
||
// 如果距离上次上传超过10秒且没有正在上传的请求
|
||
if (now - this.lastUploadTime >= throttleInterval && !this.isUploading) {
|
||
this.doUpload()
|
||
} else {
|
||
// 否则设置定时器,在剩余时间后执行
|
||
const remainingTime = throttleInterval - (now - this.lastUploadTime)
|
||
this.uploadTimer = setTimeout(() => {
|
||
this.doUpload()
|
||
}, remainingTime)
|
||
}
|
||
},
|
||
// 实际执行上传
|
||
doUpload() {
|
||
if (!this.bluetoothData || this.isUploading) return
|
||
this.isUploading = true
|
||
this.lastUploadTime = Date.now()
|
||
this.$u.put(`/app/device/iot/bltUpload`, this.bluetoothData).then(res => {
|
||
if(res.code == 200) {
|
||
console.log('上传蓝牙数据成功',this.bluetoothData, new Date().toLocaleTimeString())
|
||
} else {
|
||
console.log('上传蓝牙数据失败', res.msg)
|
||
}
|
||
}).catch(err => {
|
||
console.error('上传异常:', err)
|
||
}).finally(() => {
|
||
this.isUploading = false
|
||
})
|
||
},
|
||
|
||
// 静音
|
||
btnjingyin() {
|
||
this.shengyin = true
|
||
},
|
||
|
||
toTrack() {
|
||
console.log(this.deviceInfos);
|
||
uni.navigateTo({
|
||
url: '/page_shanghu/guanli/bike_track?id=' + this.deviceInfos.id + '&type=1'
|
||
})
|
||
},
|
||
/** 未绑定车型时点击「车型」一行触发绑定 */
|
||
handleModelRowClick() {
|
||
if (this.deviceInfos && this.deviceInfos.modelName) {
|
||
return
|
||
}
|
||
this.onModelBindClick()
|
||
},
|
||
/** 有可选车型则弹出选择;无可选车型则去新建车型页 */
|
||
onModelBindClick() {
|
||
const proceed = () => {
|
||
if (!this.ModelList || this.ModelList.length === 0) {
|
||
uni.navigateTo({
|
||
url: '/page_shanghu/gongzuotai/modelMt'
|
||
})
|
||
} else {
|
||
this.showModelList = true
|
||
}
|
||
}
|
||
if (this.ModelList && this.ModelList.length > 0) {
|
||
proceed()
|
||
return
|
||
}
|
||
uni.showLoading({
|
||
title: '加载中...',
|
||
mask: true
|
||
})
|
||
this.getModelList(() => {
|
||
uni.hideLoading()
|
||
proceed()
|
||
})
|
||
},
|
||
btnhb(){
|
||
this.yunyingflag = true
|
||
},
|
||
// 修改运营区
|
||
yunyingconfirm(e) {
|
||
let areaId = e[0].value
|
||
let data = {
|
||
ids: [this.sn],
|
||
areaId: areaId
|
||
}
|
||
this.$u.put('/bst/device/transfer', data).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
|
||
})
|
||
}
|
||
})
|
||
},
|
||
// 修改车型
|
||
confirm(e) {
|
||
let modelId = e[0].value
|
||
let data = {
|
||
id: this.sn,
|
||
modelId: modelId
|
||
}
|
||
this.$u.put('/bst/device', data).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(done) {
|
||
this.$u.get(`/bst/model/list?pageNum=1&pageSize=999`).then((res) => {
|
||
if (res.code == 200) {
|
||
this.ModelList = (res.rows || []).map(item => ({
|
||
value: item.id,
|
||
label: item.name
|
||
}))
|
||
} else {
|
||
uni.showToast({
|
||
title: res.msg,
|
||
icon: 'none',
|
||
duration: 2000
|
||
})
|
||
}
|
||
typeof done === 'function' && done()
|
||
}).catch(() => {
|
||
typeof done === 'function' && done()
|
||
})
|
||
},
|
||
closeQr() {
|
||
this.showqr = false
|
||
},
|
||
generateQrcode() {
|
||
uni.navigateTo({
|
||
url: '/page_shanghu/guanli/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() {
|
||
let data = {
|
||
id: this.sn,
|
||
vehicleNum: this.vehicleNum
|
||
}
|
||
this.$u.put('/bst/device', data).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
|
||
},
|
||
btn(num) {
|
||
if(this.jiance == true){
|
||
xBlufi.initXBlufi(1)
|
||
xBlufi.notifyStartDiscoverBle({
|
||
'isStart': true
|
||
})
|
||
xBlufi.listenDeviceMsgEvent(true, this.funListenDeviceMsgEvent)
|
||
}
|
||
if (this.jieliuflag == true) {
|
||
this.jieliuflag = false
|
||
this.showbtntip = false
|
||
let data = [this.sn]
|
||
if (num == 0) {
|
||
uni.showLoading({
|
||
title: '车辆开锁中...'
|
||
})
|
||
if (this.ver_dataflag == 3) {
|
||
xBlufi.notifySendCustomData({
|
||
customData: "11opensub5@"
|
||
})
|
||
let arr = this.devicesarr.map(item => {
|
||
const name = item.name || ''
|
||
return name.slice(-12)
|
||
})
|
||
let data = {
|
||
id: this.sn,
|
||
requiredIot:true,
|
||
lat: this.lat,
|
||
lon: this.lon,
|
||
macList:arr,
|
||
sendIot:false
|
||
}
|
||
this.iotRequestTwiceBeforeBle(`/bst/device/iot/unlock`, data).then((out) => {
|
||
if (out.type === 'ble') {
|
||
this._merchantUnlockBluetoothSequence()
|
||
return
|
||
}
|
||
if (out.type === 'error') {
|
||
uni.hideLoading()
|
||
uni.showToast({
|
||
title: (out.res && out.res.msg) || '操作失败',
|
||
icon: 'none',
|
||
duration: 2000
|
||
})
|
||
this.jieliuflag = true
|
||
return
|
||
}
|
||
const res = out.res
|
||
this.deviceInfo()
|
||
uni.showToast({
|
||
title: '操作成功',
|
||
icon: 'success',
|
||
duration: 3000
|
||
})
|
||
const logData = {
|
||
mac: this.mac,
|
||
reason: '商户开锁',
|
||
command: '11opensub5@',
|
||
longitude: this.lon,
|
||
latitude: this.lat,
|
||
result: '成功'
|
||
}
|
||
this.$u.post(`/app/commandLog/bluetooth`, logData).then(res => {})
|
||
this.jieliuflag = true
|
||
})
|
||
} else {
|
||
let arrs = this.devicesarr.map(item => {
|
||
const name = item.name || ''
|
||
return name.slice(-12)
|
||
})
|
||
let datas = {
|
||
id: this.sn,
|
||
requiredIot:true,
|
||
lat: this.lat,
|
||
lon: this.lon,
|
||
macList:arrs
|
||
}
|
||
this.iotRequestTwiceBeforeBle(`/bst/device/iot/unlock`, datas).then((out) => {
|
||
if (out.type === 'ble') {
|
||
this._merchantUnlockBluetoothSequence()
|
||
return
|
||
}
|
||
if (out.type === 'error') {
|
||
uni.hideLoading()
|
||
uni.showToast({
|
||
title: (out.res && out.res.msg) || '操作失败',
|
||
icon: 'none',
|
||
duration: 2000
|
||
})
|
||
this.jieliuflag = true
|
||
return
|
||
}
|
||
const res = out.res
|
||
if (res.data && res.data.db == 1 && res.data.iot == false) {
|
||
this._merchantUnlockBluetoothSequence()
|
||
} else {
|
||
this.deviceInfo()
|
||
uni.showToast({
|
||
title: '操作成功',
|
||
icon: 'success',
|
||
duration: 3000
|
||
})
|
||
}
|
||
this.jieliuflag = true
|
||
})
|
||
}
|
||
} else if (num == 1) {
|
||
uni.showLoading({
|
||
title: '锁车中...'
|
||
})
|
||
if (this.ver_dataflag == 3) {
|
||
xBlufi.notifySendCustomData({
|
||
customData: "11closesub200@"
|
||
})
|
||
// setTimeout(()=>{
|
||
// xBlufi.notifySendCustomData({
|
||
// customData: "11reboot@"
|
||
// })
|
||
// },2000)
|
||
let arrs = this.devicesarr.map(item => {
|
||
const name = item.name || ''
|
||
return name.slice(-12)
|
||
})
|
||
let datas = {
|
||
id: this.sn,
|
||
requiredIot:false,
|
||
lat: this.lat,
|
||
lon: this.lon,
|
||
macList:arrs,
|
||
sendIot:false
|
||
}
|
||
this.iotRequestTwiceBeforeBle(`/bst/device/iot/lock`, datas).then((out) => {
|
||
if (out.type === 'ble') {
|
||
this._merchantLockBluetoothSequence()
|
||
return
|
||
}
|
||
if (out.type === 'error') {
|
||
uni.hideLoading()
|
||
uni.showToast({
|
||
title: (out.res && out.res.msg) || '操作失败',
|
||
icon: 'none',
|
||
duration: 2000
|
||
})
|
||
this.jieliuflag = true
|
||
return
|
||
}
|
||
this.deviceInfo()
|
||
uni.showToast({
|
||
title: '操作成功',
|
||
icon: 'success',
|
||
duration: 3000
|
||
})
|
||
const logData = {
|
||
mac: this.mac,
|
||
reason: '商户关锁',
|
||
command: '11closesub200@',
|
||
result: '成功'
|
||
}
|
||
this.$u.post(`/app/commandLog/bluetooth`, logData).then(res => {})
|
||
this.jieliuflag = true
|
||
})
|
||
} else {
|
||
let arrs = this.devicesarr.map(item => {
|
||
const name = item.name || ''
|
||
return name.slice(-12)
|
||
})
|
||
let datas = {
|
||
id: this.sn,
|
||
requiredIot:true,
|
||
lat: this.lat,
|
||
lon: this.lon,
|
||
macList:arrs
|
||
}
|
||
this.iotRequestTwiceBeforeBle(`/bst/device/iot/lock`, datas).then((out) => {
|
||
if (out.type === 'ble') {
|
||
this._merchantLockBluetoothSequence()
|
||
return
|
||
}
|
||
if (out.type === 'error') {
|
||
uni.hideLoading()
|
||
uni.showToast({
|
||
title: (out.res && out.res.msg) || '操作失败',
|
||
icon: 'none',
|
||
duration: 2000
|
||
})
|
||
this.jieliuflag = true
|
||
return
|
||
}
|
||
this.deviceInfo()
|
||
uni.showToast({
|
||
title: '操作成功',
|
||
icon: 'success',
|
||
duration: 3000
|
||
})
|
||
this.jieliuflag = true
|
||
})
|
||
}
|
||
} else if (num == 2) {
|
||
uni.showLoading({
|
||
title: '加载中...'
|
||
})
|
||
this.$u.put('/bst/device/disable', data).then((res) => {
|
||
if (res.code == 200) {
|
||
uni.showToast({
|
||
title: '解禁成功',
|
||
icon: 'success',
|
||
duration: 2000
|
||
});
|
||
// 处理接口返回的数据,将边界数据转换为地图组件需要的折线结构
|
||
this.deviceInfo()
|
||
this.jieliuflag = true
|
||
} else {
|
||
uni.showToast({
|
||
title: res.msg,
|
||
icon: 'none',
|
||
duration: 2000
|
||
})
|
||
this.jieliuflag = true
|
||
}
|
||
})
|
||
} else if (num == 3) {
|
||
uni.showLoading({
|
||
title: '加载中...'
|
||
})
|
||
this.$u.put('/bst/device/enable', data).then((res) => {
|
||
if (res.code == 200) {
|
||
// 处理接口返回的数据,将边界数据转换为地图组件需要的折线结构
|
||
uni.showToast({
|
||
title: '解禁成功',
|
||
icon: 'success',
|
||
duration: 2000
|
||
})
|
||
this.deviceInfo()
|
||
this.jieliuflag = true
|
||
} else {
|
||
uni.showToast({
|
||
title: res.msg,
|
||
icon: 'none',
|
||
duration: 2000
|
||
})
|
||
this.jieliuflag = true
|
||
}
|
||
})
|
||
} else if (num == 4) {
|
||
if(this.ver_dataflag == 3){
|
||
xBlufi.notifySendCustomData({
|
||
customData: "11play1@"
|
||
})
|
||
this.jieliuflag = true
|
||
return
|
||
}
|
||
uni.showLoading({
|
||
title: '响铃中...'
|
||
})
|
||
let arrs = this.devicesarr.map(item => {
|
||
const name = item.name || ''
|
||
return name.slice(-12)
|
||
})
|
||
let datas = {
|
||
id: this.sn,
|
||
requiredIot:true,
|
||
lat: this.lat,
|
||
lon: this.lon,
|
||
macList:arrs
|
||
}
|
||
this.safeIotPut('/bst/device/iot/ring',datas).then((res) => {
|
||
if (res.code == 200) {
|
||
uni.hideLoading()
|
||
uni.showToast({
|
||
title: '操作成功',
|
||
icon: 'success',
|
||
duration: 2000
|
||
})
|
||
this.jieliuflag = true
|
||
} else if (res.code == 20001 || res.code == 20002 || res.code == 20003) {
|
||
uni.hideLoading()
|
||
this.runPreciseBluetoothSelfCheck().then((checkRes) => {
|
||
if (!checkRes.ok) {
|
||
return
|
||
}
|
||
this.jieliuflag = true
|
||
setTimeout(() => {
|
||
xBlufi.notifySendCustomData({
|
||
customData: "11play1@"
|
||
})
|
||
this.btProcessVisible = false
|
||
}, 1000)
|
||
}).catch(() => {
|
||
this.showBtStepError('已找到设备,但连接失败,请重试')
|
||
})
|
||
} else {
|
||
uni.hideLoading()
|
||
uni.showToast({
|
||
title: res.msg,
|
||
icon: 'none',
|
||
duration: 2000
|
||
})
|
||
this.jieliuflag = true
|
||
}
|
||
})
|
||
} else if (num == 5) {
|
||
uni.showLoading({
|
||
title: '加载中...'
|
||
})
|
||
this.$u.put('/bst/device/in', data).then((res) => {
|
||
if (res.code == 200) {
|
||
uni.showToast({
|
||
title: '回仓成功',
|
||
icon: 'success',
|
||
duration: 2000
|
||
});
|
||
this.deviceInfo()
|
||
this.jieliuflag = true
|
||
} else {
|
||
uni.showToast({
|
||
title: res.msg,
|
||
icon: 'none',
|
||
duration: 2000
|
||
})
|
||
this.jieliuflag = true
|
||
}
|
||
})
|
||
} else if (num == 6) {
|
||
uni.showLoading({
|
||
title: '加载中...'
|
||
})
|
||
this.$u.put('/bst/device/out', data).then((res) => {
|
||
if (res.code == 200) {
|
||
this.deviceInfo()
|
||
uni.showToast({
|
||
title: '出仓成功',
|
||
icon: 'success',
|
||
duration: 2000
|
||
})
|
||
this.jieliuflag = true
|
||
} else {
|
||
uni.showToast({
|
||
title: res.msg,
|
||
icon: 'none',
|
||
duration: 2000
|
||
})
|
||
this.jieliuflag = true
|
||
}
|
||
})
|
||
} else if (num == 7) {
|
||
this.showvehicle = true
|
||
} else if (num == 8) {
|
||
if(this.ver_dataflag == 3){
|
||
xBlufi.notifySendCustomData({
|
||
customData: "11reboot@"
|
||
})
|
||
this.jieliuflag = true
|
||
return
|
||
}
|
||
uni.showLoading({
|
||
title: '重启中...'
|
||
})
|
||
let arrs = this.devicesarr.map(item => {
|
||
const name = item.name || ''
|
||
return name.slice(-12)
|
||
})
|
||
let datas = {
|
||
id: this.sn,
|
||
requiredIot:true,
|
||
lat: this.lat,
|
||
lon: this.lon,
|
||
macList:arrs
|
||
}
|
||
this.safeIotPut('/bst/device/iot/reboot',datas).then((res) => {
|
||
if (res.code == 200) {
|
||
this.deviceInfo()
|
||
uni.showToast({
|
||
title: '操作成功',
|
||
icon: 'success',
|
||
duration: 2000
|
||
})
|
||
this.jieliuflag = true
|
||
}else if(res.code == 20001 || res.code == 20002 || res.code == 20003){
|
||
uni.hideLoading()
|
||
this.runPreciseBluetoothSelfCheck().then((checkRes) => {
|
||
if (!checkRes.ok) {
|
||
return
|
||
}
|
||
setTimeout(()=>{
|
||
xBlufi.notifySendCustomData({
|
||
customData: "11reboot@"
|
||
})
|
||
this.btProcessVisible = false
|
||
this.jieliuflag = true
|
||
},1000)
|
||
}).catch(() => {
|
||
this.showBtStepError('已找到设备,但连接失败,请重试')
|
||
})
|
||
} else {
|
||
uni.showToast({
|
||
title: res.msg,
|
||
icon: 'none',
|
||
duration: 3000
|
||
})
|
||
this.jieliuflag = true
|
||
}
|
||
})
|
||
} else if (num == 9) {
|
||
let that = this
|
||
uni.showModal({
|
||
title: '提示',
|
||
content: '是否需要打开坐垫锁',
|
||
showCancel: true,
|
||
success: function(res) {
|
||
if (res.confirm) {
|
||
if(that.ver_dataflag == 3){
|
||
xBlufi.notifySendCustomData({
|
||
customData: "11hpen@"
|
||
})
|
||
that.jieliuflag = true
|
||
return
|
||
}
|
||
uni.showLoading({
|
||
title: '加载中...'
|
||
})
|
||
let arrs = that.devicesarr.map(item => {
|
||
const name = item.name || ''
|
||
return name.slice(-12)
|
||
})
|
||
let datas = {
|
||
id: that.sn,
|
||
requiredIot:true,
|
||
lat: that.lat,
|
||
lon: that.lon,
|
||
macList:arrs
|
||
}
|
||
that.safeIotPut('/bst/device/iot/unlockSeat',datas).then((res) => {
|
||
if (res.code == 200) {
|
||
that.deviceInfo()
|
||
uni.showToast({
|
||
title: '操作成功',
|
||
icon: 'success',
|
||
duration: 2000
|
||
})
|
||
that.jieliuflag = true
|
||
} else if (res.code == 20001 || res.code == 20002 || res.code == 20003) {
|
||
uni.hideLoading()
|
||
that.runPreciseBluetoothSelfCheck().then((checkRes) => {
|
||
if (!checkRes.ok) {
|
||
return
|
||
}
|
||
xBlufi.notifySendCustomData({
|
||
customData: "11hpen@"
|
||
})
|
||
that.btProcessVisible = false
|
||
that.jieliuflag = true
|
||
let submitData = {
|
||
id: that.sn,
|
||
requiredIot:false,
|
||
lat: that.lat,
|
||
lon: that.lon,
|
||
macList:arrs,
|
||
sendIot:false
|
||
}
|
||
that.safeIotPut('/bst/device/iot/unlockSeat',submitData).then((submitRes) => {
|
||
if (submitRes.code == 200) {
|
||
that.deviceInfo()
|
||
uni.showToast({
|
||
title: '操作成功',
|
||
icon: 'success',
|
||
duration: 2000
|
||
})
|
||
} else {
|
||
uni.showToast({
|
||
title: submitRes.msg,
|
||
icon: 'none',
|
||
duration: 2000
|
||
})
|
||
}
|
||
})
|
||
}).catch(() => {
|
||
that.showBtStepError('已找到设备,但连接失败,请重试')
|
||
})
|
||
} else {
|
||
uni.showToast({
|
||
title: res.msg,
|
||
icon: 'none',
|
||
duration: 2000
|
||
})
|
||
that.jieliuflag = true
|
||
}
|
||
})
|
||
} else if (res.cancel) {
|
||
|
||
}
|
||
}
|
||
})
|
||
} else if (num == 10) {
|
||
uni.showLoading({
|
||
title: '加载中...'
|
||
})
|
||
this.$u.put('/bst/device/iot/refresh?id=' + this.sn).then((res) => {
|
||
if (res.code == 200) {
|
||
this.deviceInfo()
|
||
uni.showToast({
|
||
title: '操作成功',
|
||
icon: 'success',
|
||
duration: 2000
|
||
})
|
||
this.jieliuflag = true
|
||
} else {
|
||
uni.showToast({
|
||
title: res.msg,
|
||
icon: 'none',
|
||
duration: 2000
|
||
})
|
||
this.jieliuflag = true
|
||
}
|
||
})
|
||
}
|
||
}else{
|
||
this.jieliuflag = true
|
||
uni.hideLoading()
|
||
uni.showModal({
|
||
title: '提示',
|
||
content: '请不要频繁点击',
|
||
showCancel: false,
|
||
success: function(res) {
|
||
if (res.confirm) {
|
||
|
||
}
|
||
}
|
||
})
|
||
}
|
||
},
|
||
btnyc() {
|
||
this.titleflag = false
|
||
},
|
||
// 点击隐藏没有设备提示
|
||
btnhd() {
|
||
this.tishiflag = false
|
||
},
|
||
deviceInfo() {
|
||
this.markers = []
|
||
this.$u.get(`/bst/device?id=${this.sn}&refresh=true&supportLocation=true`).then((res) => {
|
||
console.log(res, 'rererer')
|
||
if (res.code === 200) {
|
||
this.latitude = res.data.latitude
|
||
this.longitude = res.data.longitude
|
||
if (res.data.music == 0) {
|
||
this.jytxt = '静音'
|
||
} else if (res.data.music == 1) {
|
||
this.jytxt = '语音'
|
||
} else if (res.data.music == 2) {
|
||
this.jytxt = '彩铃'
|
||
}
|
||
this.deviceInfos = res.data
|
||
this.checkVersion(res.data.hardwareVersion, res.data.softwareVersion)
|
||
this.mac = res.data.mac
|
||
if (this.ver_dataflag != 3) {
|
||
// this.getlanya()
|
||
}
|
||
if (this.getnum == 0) {
|
||
this.getArea()
|
||
}
|
||
this.getnum = 1
|
||
this.vehicleNum = res.data.vehicleNum
|
||
this.getModelList()
|
||
|
||
// const normalizeToTimestamp = (timeValue) => {
|
||
// if (timeValue === null || timeValue === undefined) return null
|
||
// if (typeof timeValue === 'number') return timeValue
|
||
// const normalized = (timeValue + '').replace(/-/g, '/')
|
||
// const timeStamp = new Date(normalized).getTime()
|
||
// return isNaN(timeStamp) ? null : timeStamp
|
||
// }
|
||
// const hourGap = 60 * 60 * 1000
|
||
// const nowTs = Date.now()
|
||
// const lastLocationTs = normalizeToTimestamp(this.deviceInfos.lastLocationTime)
|
||
// const mobileLocationTs = normalizeToTimestamp(this.deviceInfos.mobileLocationTime)
|
||
// const lastLocationExpired = lastLocationTs ? (nowTs - lastLocationTs) > hourGap : false
|
||
// const mobileLocationExpired = mobileLocationTs ? (nowTs - mobileLocationTs) > hourGap : false
|
||
// if (lastLocationExpired && mobileLocationExpired) {
|
||
// console.log(true)
|
||
// this.markers.push({
|
||
// id: parseFloat(this.deviceInfos.sn),
|
||
// latitude: this.deviceInfos.latitude,
|
||
// longitude: this.deviceInfos.longitude,
|
||
// width: 40,
|
||
// height: 47,
|
||
// iconPath: 'https://api.ccttiot.com/smartmeter/img/static/u9InOjshiVokOn2OVPOQ',
|
||
// callout: {
|
||
// content: this.deviceInfos.remainingPower + '%', // 修改为你想要显示的文字内容
|
||
// color: '#ffffff', // 修改为文字颜色
|
||
// fontSize: 10, // 修改为文字大小
|
||
// borderRadius: 10, // 修改为气泡圆角大小
|
||
// bgColor: '#666', // 修改为气泡背景颜色
|
||
// padding: 2, // 修改为气泡内边距
|
||
// display: 'ALWAYS', // 修改为气泡的显示策略
|
||
// }
|
||
// })
|
||
// return
|
||
// }
|
||
if (this.deviceInfos.status == 0) {
|
||
this.markers.push({
|
||
id: parseFloat(this.deviceInfos.sn),
|
||
latitude: this.deviceInfos.latitude,
|
||
longitude: this.deviceInfos.longitude,
|
||
width: 40,
|
||
height: 47,
|
||
iconPath: this.deviceInfos.onlineStatus == 0 ? 'https://lxnapi.ccttiot.com/bike/img/static/uQRng4QNKA38Amk8Wgt5' : 'https://lxnapi.ccttiot.com/bike/img/static/uocjFo8Ar2BJVpzC2G2f',
|
||
callout: {
|
||
content: this.deviceInfos.remainingPower + '%', // 修改为你想要显示的文字内容
|
||
color: '#ffffff', // 修改为文字颜色
|
||
fontSize: 10, // 修改为文字大小
|
||
borderRadius: 10, // 修改为气泡圆角大小
|
||
bgColor: '#000000', // 修改为气泡背景颜色
|
||
padding: 2, // 修改为气泡内边距
|
||
display: 'ALWAYS', // 修改为气泡的显示策略
|
||
}
|
||
})
|
||
} else if (this.deviceInfos.status == 1) {
|
||
this.markers.push({
|
||
id: parseFloat(this.deviceInfos.sn),
|
||
latitude: this.deviceInfos.latitude,
|
||
longitude: this.deviceInfos.longitude,
|
||
width: 40,
|
||
height: 47,
|
||
iconPath: this.deviceInfos.onlineStatus == 0 ? 'https://lxnapi.ccttiot.com/bike/img/static/uzhMeExOQJbMcZtrfGUV' : 'https://lxnapi.ccttiot.com/bike/img/static/uheL17wVZn24BwCwEztT',
|
||
callout: {
|
||
content: this.deviceInfos.remainingPower + '%', // 修改为你想要显示的文字内容
|
||
color: '#2679D1', // 修改为文字颜色
|
||
fontSize: 10, // 修改为文字大小
|
||
borderRadius: 10, // 修改为气泡圆角大小
|
||
bgColor: '#D4ECFF', // 修改为气泡背景颜色
|
||
padding: 2, // 修改为气泡内边距
|
||
display: 'ALWAYS', // 修改为气泡的显示策略
|
||
}
|
||
})
|
||
} else if (this.deviceInfos.status == 2) {
|
||
this.markers.push({
|
||
id: parseFloat(this.deviceInfos.sn),
|
||
latitude: this.deviceInfos.latitude,
|
||
longitude: this.deviceInfos.longitude,
|
||
width: 40,
|
||
height: 47,
|
||
iconPath: this.deviceInfos.onlineStatus == 0 ? 'https://lxnapi.ccttiot.com/bike/img/static/uR3DQEssiK62ovhh88y8' : 'https://lxnapi.ccttiot.com/bike/img/static/u460R1NKWHEpHbt0U4H7',
|
||
callout: {
|
||
content: this.deviceInfos.remainingPower + '%', // 修改为你想要显示的文字内容
|
||
color: '#2679D1', // 修改为文字颜色
|
||
fontSize: 10, // 修改为文字大小
|
||
borderRadius: 10, // 修改为气泡圆角大小
|
||
bgColor: '#D4ECFF', // 修改为气泡背景颜色
|
||
padding: 2, // 修改为气泡内边距
|
||
display: 'ALWAYS', // 修改为气泡的显示策略
|
||
}
|
||
})
|
||
} else if (this.deviceInfos.status == 3) {
|
||
this.markers.push({
|
||
id: parseFloat(this.deviceInfos.sn),
|
||
latitude: this.deviceInfos.latitude,
|
||
longitude: this.deviceInfos.longitude,
|
||
width: 40,
|
||
height: 47,
|
||
iconPath: this.deviceInfos.onlineStatus == 0 ? 'https://lxnapi.ccttiot.com/bike/img/static/uG13E7BpUFF44wVYC9no' : 'https://lxnapi.ccttiot.com/bike/img/static/uHQIdWCTmtUztl49wBKU',
|
||
callout: {
|
||
content: this.deviceInfos.remainingPower + '%', // 修改为你想要显示的文字内容
|
||
color: '#2679D1', // 修改为文字颜色
|
||
fontSize: 10, // 修改为文字大小
|
||
borderRadius: 10, // 修改为气泡圆角大小
|
||
bgColor: '#D4ECFF', // 修改为气泡背景颜色
|
||
padding: 2, // 修改为气泡内边距
|
||
display: 'ALWAYS', // 修改为气泡的显示策略
|
||
}
|
||
})
|
||
} else if (this.deviceInfos.status == 4 || this.deviceInfos.status == 9) {
|
||
this.markers.push({
|
||
id: parseFloat(this.deviceInfos.sn),
|
||
latitude: this.deviceInfos.latitude,
|
||
longitude: this.deviceInfos.longitude,
|
||
width: 40,
|
||
height: 47,
|
||
iconPath: this.deviceInfos.onlineStatus == 0 ? 'https://lxnapi.ccttiot.com/bike/img/static/uRod2zf3t9dAOYafWoWt' : 'https://lxnapi.ccttiot.com/bike/img/static/uZpXq3TBtM5gVgJJeImY',
|
||
callout: {
|
||
content: this.deviceInfos.remainingPower + '%', // 修改为你想要显示的文字内容
|
||
color: '#2679D1', // 修改为文字颜色
|
||
fontSize: 10, // 修改为文字大小
|
||
borderRadius: 10, // 修改为气泡圆角大小
|
||
bgColor: '#D4ECFF', // 修改为气泡背景颜色
|
||
padding: 2, // 修改为气泡内边距
|
||
display: 'ALWAYS', // 修改为气泡的显示策略
|
||
}
|
||
})
|
||
} else if (this.deviceInfos.status == 6) {
|
||
this.markers.push({
|
||
id: parseFloat(this.deviceInfos.sn),
|
||
latitude: this.deviceInfos.latitude,
|
||
longitude: this.deviceInfos.longitude,
|
||
width: 40,
|
||
height: 47,
|
||
iconPath: this.deviceInfos.onlineStatus == 0 ? 'https://lxnapi.ccttiot.com/bike/img/static/uhZudZM3nEKj0tYKlho2' : 'https://lxnapi.ccttiot.com/bike/img/static/ujur6TezvPf4buFAqPHo',
|
||
callout: {
|
||
content: '' + this.deviceInfos.remainingPower + '%',
|
||
color: '#2679D1', // 修改为文字颜色
|
||
fontSize: 10, // 修改为文字大小
|
||
borderRadius: 10, // 修改为气泡圆角大小
|
||
bgColor: '#D4ECFF', // 修改为气泡背景颜色
|
||
padding: 2, // 修改为气泡内边距
|
||
display: 'ALWAYS', // 修改为气泡的显示策略
|
||
}
|
||
})
|
||
} else if (this.deviceInfos.status == 8) {
|
||
this.markers.push({
|
||
id: parseFloat(this.deviceInfos.sn),
|
||
latitude: this.deviceInfos.latitude,
|
||
longitude: this.deviceInfos.longitude,
|
||
width: 40,
|
||
height: 47,
|
||
iconPath: this.deviceInfos.onlineStatus == 0 ? 'https://lxnapi.ccttiot.com/bike/img/static/ucBKG3ebYRAToVweJihu' : 'https://lxnapi.ccttiot.com/bike/img/static/uyK7Vg4Lu8xb3oNVuG2l',
|
||
callout: {
|
||
content: this.deviceInfos.remainingPower + '%', // 修改为你想要显示的文字内容
|
||
color: '#ffffff', // 修改为文字颜色
|
||
fontSize: 10, // 修改为文字大小
|
||
borderRadius: 10, // 修改为气泡圆角大小
|
||
bgColor: '#000000', // 修改为气泡背景颜色
|
||
padding: 2, // 修改为气泡内边距
|
||
display: 'ALWAYS', // 修改为气泡的显示策略
|
||
}
|
||
})
|
||
}
|
||
this.updateMobileMarker()
|
||
this.$forceUpdate()
|
||
} else {
|
||
uni.showToast({
|
||
title: res.msg,
|
||
icon: 'none',
|
||
duration: 2000
|
||
})
|
||
}
|
||
})
|
||
},
|
||
convertBoundaryToPolyline(boundary) {
|
||
if (!boundary || typeof boundary !== 'string') return null
|
||
let coords
|
||
try {
|
||
coords = JSON.parse(boundary)
|
||
} catch (error) {
|
||
console.error("Error parsing boundary JSON:", error)
|
||
return null
|
||
}
|
||
if (!Array.isArray(coords) || coords.length < 2) return null
|
||
const points = coords.map(coord => ({
|
||
latitude: Number(coord[1]),
|
||
longitude: Number(coord[0])
|
||
})).filter(p => Number.isFinite(p.latitude) && Number.isFinite(p.longitude))
|
||
if (points.length < 2) return null
|
||
const polyline = {
|
||
points: points,
|
||
fillColor: "#55888840", //填充颜色
|
||
strokeColor: "#22FF00", //描边颜色
|
||
strokeWidth: 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: "#3A7EDB40", //填充颜色
|
||
strokeColor: "#3A7EDB", //描边颜色
|
||
strokeWidth: 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
|
||
}
|
||
console.log(coords, '2222222222222');
|
||
const points = coords.map(coord => ({
|
||
latitude: coord[1],
|
||
longitude: coord[0]
|
||
}))
|
||
return {
|
||
points: points,
|
||
fillColor: "#FFF5D640", //填充颜色
|
||
strokeColor: "#FF473E", //描边颜色
|
||
strokeWidth: 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
|
||
}
|
||
console.log(coords, '333333333333');
|
||
const points = coords.map(coord => ({
|
||
latitude: coord[1],
|
||
longitude: coord[0]
|
||
}))
|
||
return {
|
||
points: points,
|
||
fillColor: "#FFD1CF40", //填充颜色
|
||
strokeColor: "#FFC107", //描边颜色
|
||
strokeWidth: 2, //描边宽度
|
||
zIndex: 1, //层级
|
||
}
|
||
}).filter(polyline => polyline !== null) // 过滤掉无效的折线数据
|
||
}
|
||
},
|
||
toggleIconAndCallout() {
|
||
this.showIconAndCallout = !this.showIconAndCallout
|
||
if (this.showIconAndCallout) {
|
||
const newMarkers = []
|
||
this.parkingList.forEach(item => {
|
||
newMarkers.push({
|
||
id: parseFloat(item.id),
|
||
latitude: parseFloat(item.latitude),
|
||
longitude: parseFloat(item.longitude),
|
||
width: 20,
|
||
height: 28.95,
|
||
iconPath: item.type == 1 ? 'https://lxnapi.ccttiot.com/bike/img/static/up2xXqAgwCX5iER600k3' : item.type == 2 ? 'https://lxnapi.ccttiot.com/bike/img/static/uDNY5Q4zOiZTCBTA2Jdq' : 'https://lxnapi.ccttiot.com/bike/img/static/u53BAQcFIX3vxsCzEZ7t',
|
||
callout: {
|
||
content: item.name,
|
||
color: '#ffffff',
|
||
fontSize: 14,
|
||
borderRadius: 10,
|
||
bgColor: item.type == 1 ? '#3A7EDB' : item.type == 2 ? '#FF473E' : '#FFC107',
|
||
padding: 6,
|
||
display: 'ALWAYS'
|
||
},
|
||
isCalloutVisible: true // 添加标记
|
||
})
|
||
})
|
||
this.$set(this, 'markers', [...this.markers, ...newMarkers])
|
||
} else {
|
||
// 过滤掉所有气泡显示的标记
|
||
this.$set(this, 'markers', this.markers.filter(marker => !marker.isCalloutVisible))
|
||
}
|
||
},
|
||
getParking() {
|
||
// 发送请求获取数据
|
||
let data = {
|
||
areaId: this.deviceInfos.areaId,
|
||
type: '',
|
||
refresh: true
|
||
}
|
||
this.$u.get(`/bst/areaSub/listByAreaId`, data).then((res) => {
|
||
if (res.code === 200) {
|
||
// 先过滤掉status为1的数据
|
||
const filteredData = res.data.filter(item => item.status != 1);
|
||
console.log(filteredData, '000000');
|
||
// 处理接口返回的数据
|
||
const type1Data = []
|
||
const type2Data = []
|
||
const type3Data = []
|
||
filteredData.forEach(row => { // 这里使用filteredData而不是res.data
|
||
if (row.type == 1) {
|
||
type1Data.push(row)
|
||
} else if (row.type == 2) {
|
||
type2Data.push(row)
|
||
} else if (row.type == 3) {
|
||
type3Data.push(row)
|
||
}
|
||
})
|
||
const validBoundaries = type1Data.map(row => row.boundaryStr).filter(boundary =>
|
||
typeof boundary === 'string' && boundary.trim() !== '')
|
||
const polylines = this.convertBoundaryToPolylines(validBoundaries, 1)
|
||
const validBoundaries1 = type2Data.map(row => row.boundaryStr).filter(boundary =>
|
||
typeof boundary === 'string' && boundary.trim() !== '')
|
||
const polylines1 = this.convertBoundaryToPolylines(validBoundaries1, 2)
|
||
const validBoundaries2 = type3Data.map(row => row.boundaryStr).filter(boundary =>
|
||
typeof boundary === 'string' && boundary.trim() !== '')
|
||
const polylines2 = this.convertBoundaryToPolylines(validBoundaries2, 3)
|
||
// 将处理后的数据添加到 this.polyline 中
|
||
this.polyline = []
|
||
this.polyline = this.polyline.concat(polylines2 || [])
|
||
this.polyline = this.polyline.concat(polylines1 || [])
|
||
this.polyline = this.polyline.concat(polylines || [])
|
||
this.polyline = this.polyline.filter(item => {
|
||
return item && Array.isArray(item.points) && item.points.length >= 2 &&
|
||
typeof item.strokeWidth === 'number'
|
||
})
|
||
// 这里也使用过滤后的数据
|
||
this.parkingList = filteredData
|
||
}
|
||
}).catch(error => {
|
||
console.error("Error fetching parking data:", error)
|
||
})
|
||
},
|
||
getArea() {
|
||
// 发送请求获取数据
|
||
let id = this.deviceInfos.areaId
|
||
this.$u.get(`/bst/area/${id}`).then((res) => {
|
||
if (res.code === 200) {
|
||
// 处理接口返回的数据,将边界数据转换为地图组件需要的折线结构
|
||
const polylines = this.convertBoundaryToPolyline(res.data.boundaryStr)
|
||
// 更新折线数据
|
||
if (polylines && Array.isArray(polylines.points) && polylines.points.length >= 2) {
|
||
this.polyline.push(polylines)
|
||
}
|
||
this.polyline = this.polyline.filter(item => {
|
||
return item && Array.isArray(item.points) && item.points.length >= 2 &&
|
||
typeof item.strokeWidth === 'number'
|
||
})
|
||
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: #F6F8FA;
|
||
}
|
||
.page {
|
||
padding-bottom: 400rpx;
|
||
width: 750rpx;
|
||
.new_infocard {
|
||
width: 750rpx;
|
||
max-height: 100vh;
|
||
background: #FFFFFF;
|
||
border-radius: 30rpx;
|
||
padding: 30rpx;
|
||
box-sizing: border-box;
|
||
position: absolute;
|
||
z-index: 99;
|
||
top: 800rpx;
|
||
.zuche {
|
||
margin-top: 26rpx;
|
||
.one {
|
||
display: flex;
|
||
align-items: center;
|
||
image {
|
||
width: 32rpx;
|
||
height: 32rpx;
|
||
margin-right: 4rpx;
|
||
}
|
||
span {
|
||
font-size: 28rpx;
|
||
color: #3D3D3D;
|
||
}
|
||
}
|
||
view {
|
||
font-size: 28rpx;
|
||
color: #808080;
|
||
// margin-bottom: 26rpx;
|
||
display: flex;
|
||
justify-content: space-between;
|
||
span {
|
||
color: #3D3D3D;
|
||
}
|
||
}
|
||
}
|
||
.bikejcxx {
|
||
margin-top: 26rpx;
|
||
border-bottom: 1rpx solid #D8D8D8;
|
||
.wai {
|
||
display: flex;
|
||
justify-content: space-between;
|
||
margin-bottom: 26rpx;
|
||
.lt {
|
||
width: 46%;
|
||
text-align: left;
|
||
font-size: 24rpx;
|
||
color: #808080;
|
||
|
||
span {
|
||
color: #3D3D3D;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
.caozuoanniu {
|
||
display: flex;
|
||
flex-wrap: wrap;
|
||
margin-top: 26rpx;
|
||
border-bottom: 1rpx solid #D8D8D8;
|
||
.dangeanniu {
|
||
width: 20%;
|
||
text-align: center;
|
||
margin-bottom: 28rpx;
|
||
.pic {
|
||
width: 88rpx;
|
||
height: 88rpx;
|
||
background: #F1F1F1;
|
||
border-radius: 6rpx 6rpx 6rpx 6rpx;
|
||
margin: auto;
|
||
margin-bottom: 14rpx;
|
||
image {
|
||
width: 42rpx;
|
||
height: 42rpx;
|
||
margin-top: 24rpx;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
.ewm {
|
||
view {
|
||
width: 140rpx;
|
||
height: 44rpx;
|
||
background: #4C97E7;
|
||
border-radius: 6rpx 6rpx 6rpx 6rpx;
|
||
font-size: 24rpx;
|
||
color: #FFFFFF;
|
||
display: flex;
|
||
align-items: center;
|
||
padding: 0 8rpx;
|
||
padding-left: 18rpx !important;
|
||
text-align: center;
|
||
box-sizing: border-box;
|
||
image {
|
||
width: 26rpx;
|
||
height: 26rpx;
|
||
margin-right: 10rpx;
|
||
}
|
||
}
|
||
}
|
||
.xuhang {
|
||
view {
|
||
width: 284rpx;
|
||
height: 102rpx;
|
||
background: #F1F1F1;
|
||
border-radius: 8rpx 8rpx 8rpx 8rpx;
|
||
display: flex;
|
||
align-items: center;
|
||
font-size: 24rpx;
|
||
color: #847f7f;
|
||
padding-left: 18rpx;
|
||
box-sizing: border-box;
|
||
image {
|
||
width: 46rpx;
|
||
height: 46rpx;
|
||
margin-right: 14rpx;
|
||
}
|
||
}
|
||
}
|
||
.bikesn {
|
||
font-size: 24rpx;
|
||
color: #7C7C7C;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: space-between;
|
||
border-bottom: 1rpx solid #D8D8D8;
|
||
padding-bottom: 26rpx;
|
||
}
|
||
.cent {
|
||
display: flex;
|
||
.lypic {
|
||
display: flex;
|
||
justify-content: center;
|
||
align-items: center;
|
||
}
|
||
image {
|
||
width: 36rpx;
|
||
height: 36rpx;
|
||
margin-right: 8rpx;
|
||
}
|
||
.glow-image {
|
||
width: 36rpx;
|
||
height: 36rpx;
|
||
margin-right: 8rpx;
|
||
transition: all 1s ease-in-out;
|
||
filter: drop-shadow(0 0 5px rgba(255, 0, 0, 0.7));
|
||
/* 青色外发光 */
|
||
}
|
||
.visible {
|
||
opacity: 1;
|
||
transform: scale(1);
|
||
filter: drop-shadow(0 0 5px rgba(255, 50, 50, 1));
|
||
/* 增强发光 */
|
||
}
|
||
.hidden {
|
||
opacity: 0.3;
|
||
transform: scale(0.95);
|
||
filter: drop-shadow(0 0 5px rgba(255, 0, 0, 0.3));
|
||
/* 减弱发光 */
|
||
}
|
||
}
|
||
.bikexx {
|
||
margin-top: 26rpx;
|
||
display: flex;
|
||
justify-content: space-between;
|
||
border-bottom: 1rpx solid #D8D8D8;
|
||
padding-bottom: 26rpx;
|
||
box-sizing: border-box;
|
||
.dianliang {
|
||
position: relative;
|
||
background: linear-gradient(to right, #c0dfff, #fff);
|
||
border-radius: 10rpx;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: space-between;
|
||
padding: 0 20rpx;
|
||
box-sizing: border-box;
|
||
.dl {
|
||
margin-top: 10rpx;
|
||
box-sizing: border-box;
|
||
color: #847f7f;
|
||
font-size: 24rpx;
|
||
}
|
||
.dy {
|
||
margin-top: 2rpx;
|
||
box-sizing: border-box;
|
||
color: #847f7f;
|
||
font-size: 24rpx;
|
||
}
|
||
view {
|
||
padding-left: 14rpx;
|
||
box-sizing: border-box;
|
||
font-size: 24rpx;
|
||
color: #3D3D3D;
|
||
span {
|
||
font-size: 28rpx;
|
||
}
|
||
}
|
||
image {
|
||
width: 22rpx;
|
||
height: 48rpx;
|
||
}
|
||
}
|
||
}
|
||
.topsn {
|
||
display: flex;
|
||
justify-content: space-between;
|
||
padding-bottom: 13rpx;
|
||
box-sizing: border-box;
|
||
.lt {
|
||
font-weight: 600;
|
||
font-size: 30rpx;
|
||
color: #3D3D3D;
|
||
display: flex;
|
||
align-items: center;
|
||
}
|
||
.rt {
|
||
display: flex;
|
||
.issuo {
|
||
width: 104rpx;
|
||
height: 42rpx;
|
||
background: #F1F1F1;
|
||
border-radius: 6rpx 6rpx 6rpx 6rpx;
|
||
text-align: center;
|
||
line-height: 42rpx;
|
||
margin-left: 10rpx;
|
||
font-size: 24rpx;
|
||
color: #3D3D3D;
|
||
}
|
||
.stutas {
|
||
span {
|
||
display: inline-block;
|
||
width: 104rpx;
|
||
height: 42rpx;
|
||
border-radius: 6rpx 6rpx 6rpx 6rpx;
|
||
text-align: center;
|
||
line-height: 42rpx;
|
||
margin-left: 28rpx;
|
||
font-size: 24rpx;
|
||
color: #fff;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
.tip_box {
|
||
position: fixed;
|
||
left: 72rpx;
|
||
top: 628rpx;
|
||
width: 610rpx;
|
||
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;
|
||
display: flex;
|
||
flex-wrap: nowrap;
|
||
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;
|
||
font-weight: 500;
|
||
font-size: 32rpx;
|
||
}
|
||
}
|
||
}
|
||
|
||
.map {
|
||
position: relative;
|
||
width: 750rpx;
|
||
height: 752rpx;
|
||
|
||
.track,
|
||
.park {
|
||
position: absolute;
|
||
width: 88rpx;
|
||
height: 88rpx;
|
||
bottom: 140rpx;
|
||
border-radius: 50%;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
transition: all 0.3s ease;
|
||
z-index: 1;
|
||
&:active {
|
||
transform: scale(0.95);
|
||
}
|
||
|
||
.img {
|
||
width: 80rpx;
|
||
height: 80rpx;
|
||
}
|
||
}
|
||
|
||
.track {
|
||
left: 30rpx;
|
||
}
|
||
|
||
.park {
|
||
right: 30rpx;
|
||
}
|
||
}
|
||
}
|
||
|
||
@keyframes slideUp {
|
||
from {
|
||
transform: translateY(100%);
|
||
opacity: 0;
|
||
}
|
||
|
||
to {
|
||
transform: translateY(0);
|
||
opacity: 1;
|
||
}
|
||
}
|
||
|
||
/* 添加声音选择组件样式 */
|
||
.sound-select {
|
||
position: fixed;
|
||
bottom: 0;
|
||
left: 0;
|
||
width: 100%;
|
||
background-color: #fff;
|
||
border-radius: 30rpx 30rpx 0 0;
|
||
z-index: 101;
|
||
padding: 30rpx;
|
||
box-sizing: border-box;
|
||
animation: slideUp 0.3s ease-out forwards;
|
||
|
||
.sound-header {
|
||
position: relative;
|
||
text-align: center;
|
||
font-size: 32rpx;
|
||
font-weight: 500;
|
||
color: #333;
|
||
padding-bottom: 30rpx;
|
||
border-bottom: 1px solid #eee;
|
||
|
||
.close-btn {
|
||
position: absolute;
|
||
right: 0;
|
||
top: -28rpx;
|
||
font-size: 60rpx;
|
||
}
|
||
}
|
||
|
||
.sound-options {
|
||
padding: 30rpx 0;
|
||
|
||
.sound-item {
|
||
display: flex;
|
||
align-items: center;
|
||
padding: 30rpx 20rpx;
|
||
margin-bottom: 20rpx;
|
||
border-radius: 12rpx;
|
||
background: #F7F7F7;
|
||
position: relative;
|
||
|
||
&.active {
|
||
background: #ECF5FF;
|
||
border: 2rpx solid #4C97E7;
|
||
|
||
&::after {
|
||
content: '';
|
||
position: absolute;
|
||
right: 30rpx;
|
||
width: 40rpx;
|
||
height: 40rpx;
|
||
background: url('https://api.ccttiot.com/smartmeter/img/static/check.png') no-repeat;
|
||
background-size: contain;
|
||
}
|
||
}
|
||
|
||
.icon {
|
||
margin-right: 20rpx;
|
||
|
||
image {
|
||
width: 48rpx;
|
||
height: 48rpx;
|
||
}
|
||
}
|
||
|
||
.label {
|
||
font-size: 32rpx;
|
||
font-weight: 500;
|
||
color: #333;
|
||
margin-right: 20rpx;
|
||
}
|
||
|
||
.desc {
|
||
font-size: 24rpx;
|
||
color: #999;
|
||
}
|
||
}
|
||
}
|
||
|
||
.confirm-btn {
|
||
width: 100%;
|
||
height: 88rpx;
|
||
background: #4C97E7;
|
||
border-radius: 44rpx;
|
||
color: #fff;
|
||
font-size: 32rpx;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
margin-top: 30rpx;
|
||
|
||
&:active {
|
||
opacity: 0.8;
|
||
}
|
||
}
|
||
}
|
||
</style> |