chuangte_bike_newxcx/page_shanghu/guanli/order_detail.vue
2025-04-30 18:03:27 +08:00

2564 lines
70 KiB
Vue
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<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" :polyline="polyline" :polygons="polygon" :enable-zoom="true"
:enable-scroll="true">
<cover-view class="park" @click="toggleIconAndCallout">
<cover-image class="img" src="https://lxnapi.ccttiot.com/bike/img/static/uRiYQZQEb3l2LsltEsyW"
mode=""></cover-image>
</cover-view>
<cover-view class="track" @click="toTrack" v-if="orderxqobj.status != 'CANCELED'">
<cover-image class="img" src="https://lxnapi.ccttiot.com/bike/img/static/ufaAAtlirJYs1QwJF25P"
mode=""></cover-image>
</cover-view>
</map>
<view class="dingdanxx">
<view class="name" style="display: flex;justify-content: space-between;padding-right: 20rpx;box-sizing: border-box;">
订单信息
<text style="color: #3A7EDB;" v-if="orderxqobj.status == 'PROCESSING'">订单进行中</text>
<text style="color: #3A7EDB;" v-if="orderxqobj.status == 'FINISHED'">订单已完成</text>
<text style="color: #ccc;" v-if="orderxqobj.status == 'CANCELED'">订单已取消</text>
</view>
<view class="dingdanbh">
订单编号:<span>{{orderxqobj.no}}</span>
</view>
<view class="dingdanul">
<view class="dingdanli" style="width: 100%;">
套餐名称:<span v-if="orderxqobj.suitName">{{orderxqobj.suitName}}</span>
<span v-else>--</span>
</view>
</view>
<view class="dingdanul">
<view class="dingdanli">
计费方式:<span v-if="orderxqobj.suitRidingRule == 1">起步价计费</span>
<span v-if="orderxqobj.suitRidingRule == 2">区间计费</span>
</view>
</view>
<view class="dingdanul">
<view class="dingdanli">
预存费用:<span style="color: #3A7EDB;font-weight: 600;">{{orderxqobj.depositFee == undefined ? '¥0.00' : '¥' + orderxqobj.depositFee}}</span>
</view>
<view class="dingdanli">
免费时长:<span>{{orderxqobj.suitFreeRideTime}}分钟</span>
</view>
</view>
<view class="dingdanul">
<view class="dingdanli">
租赁用户:<span v-if="orderxqobj.userName">{{orderxqobj.userName}}</span>
<span v-else>--</span>
</view>
<view class="dingdanli">
手机号码:<span v-if="orderxqobj.userPhone" style="color: #4C97E7;" @click="checkbtn(1)">{{orderxqobj.userPhone}}</span>
<span v-else>--</span>
</view>
</view>
<view class="yingshouprice">
应收金额:<span style="color: #4C97E7;font-weight: 600;">{{orderxqobj.totalFee == null ? '¥0.00' : '¥' + orderxqobj.totalFee}}</span>
</view>
<view class="dingdanul">
<view class="dingdanli">
骑行费用:<span v-if="orderxqobj.ridingFee">¥{{orderxqobj.ridingFee}}</span>
<span v-else>¥0.00</span>
</view>
<view class="dingdanli" style="position: relative;" @click="btnflagxs">
调度费用:<span v-if="orderxqobj.dispatchFee">¥{{orderxqobj.dispatchFee}}</span>
<span v-if="orderxqobj.manageFee">¥{{orderxqobj.manageFee}}</span>
<span v-else>¥0.00</span>
<image v-if="orderxqobj.dispatchFee || orderxqobj.manageFee" style="width: 20rpx;height: 20rpx;margin-left: 16rpx;" src="https://api.ccttiot.com/smartmeter/img/static/ubRtJnZqaAxybajDMLSG" mode=""></image>
<view class="" v-if="flagdiaodu" style="width: 166rpx;height: 82rpx;background-color: #F3F3F3;position: absolute;top: 40rpx;right: 0;text-align: center;border-radius: 4rpx;">
<view class="" style="font-size: 20rpx;color: #808080;width: 100%;margin-top: 8rpx;">
停车区外:<span style="color: #3D3D3D;">¥{{orderxqobj.dispatchFee == null ? '0.00' : orderxqobj.dispatchFee}}</span>
</view>
<view class="" style="font-size: 20rpx;color: #808080;width: 100%;margin-top: 8rpx;">
运营区外:<span style="color: #3D3D3D;">¥{{orderxqobj.manageFee == null ? '0.00' : orderxqobj.manageFee}}</span>
</view>
</view>
</view>
</view>
<view class="yingshouprice" style="border: 0;">
退款总额:<span style="color: #4C97E7;font-weight: 600;">{{ orderxqobj.payRefunded == null ? '¥0.00' : '¥' + orderxqobj.payRefunded }}</span>
</view>
<view class="dingdanul">
<view class="dingdanli">
还车退款:<span v-if="orderxqobj.payAutoRefund">¥{{orderxqobj.payAutoRefund}}</span>
<span v-else>¥0.00</span>
</view>
<view class="dingdanli">
人工退款:<span v-if="orderxqobj.payAdminRefund">¥{{orderxqobj.payAdminRefund}}</span>
<span v-else>¥0.00</span>
</view>
</view>
<view class="yingshouprice" style="border: 0;">
实收金额:<span style="color: #4C97E7;font-weight: 600;">{{formattedPayedAmount}}</span>
</view>
</view>
<view class="xingchengxx" style="padding-bottom: 30rpx;box-sizing: border-box;">
<view class="name">
行程信息
</view>
<view class="dingdanul">
<view class="dingdanli">
订单时长:<span>{{ formattedDuration }}</span>
</view>
<view class="dingdanli">
行驶距离:<span v-if="orderxqobj.distance">
{{kmDistance}}km
</span>
<span v-else>0.00m</span>
</view>
</view>
<view class="start">
开始时间:<span v-if="orderxqobj.startTime">{{orderxqobj.startTime}}</span>
<span v-else>--</span>
</view>
<view class="start">
结束时间:<span v-if="orderxqobj.endTime">{{orderxqobj.endTime}}</span>
<span v-else>--</span>
</view>
</view>
<view class="xingchengxx" style="max-height: 9999rpx;padding-bottom: 20rpx;box-sizing: border-box;">
<view class="name">
车辆信息
</view>
<view class="card">
<view class="pic_cont" v-for="(item,index) in processedOrderDeviceList" :key="index">
<view class="jilu">
<view class="one" v-if="index == 0">
初始车辆
</view>
<view class="one" v-else>
更换车辆
</view>
<view class="two">
{{item.startTime == null ? '--' : item.startTime}}
</view>
</view>
<view class="bianhao">
<view class="">
SN<span>{{item.deviceSn == null ? '--' : item.deviceSn}}</span>
</view>
<view class="">
MAC号<span>{{item.deviceMac == null ? '--' : item.deviceMac}}</span>
</view>
</view>
<view class="bianhao">
<view class="">
车牌号:<span>{{item.deviceVehicleNum == null ? '--' : item.deviceVehicleNum}}</span>
</view>
<view class="">
车型:<span>{{item.deviceModelName == null ? '--' : item.deviceModelName}}</span>
</view>
</view>
<view class="bianhao">
<view class="" style="width: 100%;">
开锁时间:<span>{{item.startTime == null ? '--' : item.startTime}}</span>
</view>
</view>
<view class="bianhao">
<view class="" style="width: 100%;">
结束时间:<span>{{item.endTime == null ? '--' : item.endTime}}</span>
</view>
</view>
<view class="imgs">
<video v-if="item.finishPicture != null" :src="item.finishPicture"></video>
</view>
</view>
<view class="btn_cont" v-if="orderxqobj.status == 'WAIT_VERIFY'">
<view class="btn2" @click="unpass(false)">
不通过
</view>
<view class="btn1" @click="unpass(true)">
通过
</view>
</view>
</view>
</view>
<view class="info_card" style="margin-top: 20rpx;" v-if="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" v-if="orderxqobj.status != 'CANCELED'">
<view class="btn" @click="checkbtn(0)">
退款
</view>
<!-- -->
<view class="btn" @click="btnfuzhu" v-if="orderxqobj.status=='PROCESSING'">
辅助还车
</view>
</view>
<u-mask :show="false" @click="show = false" :z-index='100' />
<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=""></image>
<view class="masktxt">
{{buletxt}}
</view>
</view>
<view class="masktips" style="width: 100%;">
请确保与车辆的距离小于3米
</view>
<view class="tipsimg">
<image src="https://lxnapi.ccttiot.com/bike/img/static/ugvqmfB3QYujZ6SnfTia" mode=""></image>
</view>
</view>
<!-- 不允许停车点外还车 -->
<view class="maskpage1" v-if="maskepage==5">
<view class="top_info">
<image src="https://lxnapi.ccttiot.com/bike/img/static/uG3cbPgvPDzwlq6IHHxK" mode=""></image>
<view class="masktxt" v-if="orderinfo.sn">
蓝牙连接失败
</view>
</view>
<view class="masktips" style="width: 100%;">
请确保手机蓝牙已经打开
</view>
<view class="tipsimg">
<image src="https://lxnapi.ccttiot.com/bike/img/static/ugvqmfB3QYujZ6SnfTia" mode=""></image>
</view>
<view class="btn_box">
<view class="btn4" @click="closemask()">
返回
</view>
<view class="btn3" @click="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 class="tktc" v-if="tkflag">
<view class="name">
退款
</view>
<input type="text" v-model="amount" placeholder="请输入退款金额" />
<view class="" style="margin-top: 20rpx;">
可退款金额:{{formattedPayedAmount}}
</view>
<view class="anniu">
<view class="qx" @click="btnqx">
取消
</view>
<view class="qd" style="background-color: #3A7EDB;color: #fff;" @click="btntuikuan">
确定
</view>
</view>
</view>
<view class="mask" v-if="tkflag"></view>
</view>
</template>
<script>
const app = getApp()
var xBlufi = require("@/components/blufi/xBlufi.js")
let _this = null
export default {
data() {
return {
devicesList: [],
searching: false,
texts: '正在扫描蓝牙设备...',
btnflag: true,
tishiflag: false,
option: '',
bluthlist: [], //蓝牙数组
statusflag: false,
Bluetoothmac: '',
mac: '',
ishave: false,
ver_data: null,
deviceInfoss: {},
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: [], // 轨迹折线数组
polygon: [], // 用于存储区域多边形
cardId: '001区域',
sn: '',
deviceInfos: {},
carstause: false,
maskloading: false,
toploadtxt: "开锁中0%",
loadimg: 'https://lxnapi.ccttiot.com/bike/img/static/urJQJnOI1DEjWatFqHYh',
tiptxt: '请定点停放,规范用车',
maskepage: 0,
backgps: {},
buletxt: '',
flagdiaodu:false,
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:[],
jytxt:'开',
orid:'',
orderxqobj:{
distance: 0
},
tkflag:false,
amount:'',
orderDeviceList:[],
suitSeconds:'',
currentPolyline:[],
trackPoints: [], // 存储轨迹点数据
}
},
onLoad(e) {
this.sn = e.id
this.orid = e.orid
this.deviceInfo()
this.getorderxq()
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: {
},
computed: {
formattedDuration() {
// 获取开始时间(必须存在)
const startTime = this.orderxqobj?.startTime ? new Date(this.orderxqobj.startTime) : null;
if (!startTime || isNaN(startTime.getTime())) return '00:00:00';
// 获取结束时间若为null则用当前时间
const endTime = this.orderxqobj?.endTime
? new Date(this.orderxqobj.endTime)
: new Date();
if (isNaN(endTime.getTime())) return '00:00:00';
// 计算时间差(毫秒)
const diffMs = endTime - startTime;
if (diffMs < 0) return '00:00:00'; // 结束时间早于开始时间
// 转换为秒并格式化
const diffSeconds = Math.floor(diffMs / 1000);
return this.formatSecondsToHMS(diffSeconds);
},
// 使用计算属性来进行渲染换车
processedOrderDeviceList() {
return this.orderDeviceList.map(item => ({
...item,
pictures: item.finishPicture ? item.finishPicture.split(',') : []
}))
},
kmDistance() {
return (this.orderxqobj?.distance / 1000).toFixed(2);
},
formattedPayedAmount() {
// 默认值处理
const payedAmount = parseFloat(this.orderxqobj?.payedAmount) || 0;
const payRefunded = parseFloat(this.orderxqobj?.payRefunded) || 0;
const payRefunding = parseFloat(this.orderxqobj?.payRefunding) || 0;
// 计算实际金额
const actualAmount = payedAmount - (payRefunded + payRefunding);
// 确保是合法数字,并格式化为 ¥XX.XX
return `¥${isNaN(actualAmount) ? '0.00' : actualAmount.toFixed(2)}`;
}
},
methods: {
formatSecondsToHMS(seconds) {
const h = Math.floor(seconds / 3600).toString().padStart(2, '0');
const m = Math.floor((seconds % 3600) / 60).toString().padStart(2, '0');
const s = Math.floor(seconds % 60).toString().padStart(2, '0');
return `${h}:${m}:${s}`;
},
formatDatess(startTime, endTime) {
if (!startTime) return "0秒"; // 如果没有开始时间返回0
// 解析时间无效时间则返回0
const start = new Date(startTime);
const ends = endTime == null ? this.formatCurrentTime() : new Date(endTime);
const end = new Date(ends)
console.log(ends,end,'02220');
if (isNaN(start.getTime()) || isNaN(end.getTime())) return "0秒";
// 计算时间差(毫秒)
let diffMs = end - start;
if (diffMs < 0) return "0秒"; // 结束时间早于开始时间
// 计算各时间单位
const diffDays = Math.floor(diffMs / 86400000); // 天
diffMs %= 86400000;
const diffHours = Math.floor(diffMs / 3600000); // 小时
diffMs %= 3600000;
const diffMinutes = Math.floor(diffMs / 60000); // 分钟
diffMs %= 60000;
const diffSeconds = Math.floor(diffMs / 1000); // 秒
// 智能拼接结果忽略0值单位但至少显示"X秒"
const parts = [];
if (diffDays > 0) parts.push(`${diffDays}天`);
if (diffHours > 0) parts.push(`${diffHours}小时`);
if (diffMinutes > 0) parts.push(`${diffMinutes}分钟`);
parts.push(`${diffSeconds}秒`); // 始终显示秒
return parts.join("");
},
formatCurrentTime() {
const now = new Date();
const padZero = num => num < 10 ? `0${num}` : num;
return `${now.getFullYear()}-${padZero(now.getMonth() + 1)}-${padZero(now.getDate())} ${padZero(now.getHours())}:${padZero(now.getMinutes())}:${padZero(now.getSeconds())}`;
},
updateTrackData() {
const formattedStartTime = this.orderxqobj.startTime;
const formattedEndTime = this.orderxqobj.endTime || this.formatCurrentTime();
// this.$u.get('/bst/locationLog/listByTime?sn=' + this.sn + '&startTime=' + formattedStartTime + '&endTime=' + formattedEndTime).then((res) => {
this.$u.get('/bst/locationLog/listAll?orderId=' + this.orid).then((res) => {
if (res.code === 200) {
if (!res.data || res.data.length === 0) {
uni.showToast({
title: '该时间段内无轨迹数据',
icon: 'none',
duration: 2000
});
return
}
// 清空之前的轨迹数据
this.polyline = []
this.markers = []
// 处理轨迹点数据并按时间排序
this.trackPoints = res.data
.map(point => ({
latitude: parseFloat(point.latitude),
longitude: parseFloat(point.longitude),
time: point.at,
status: point.status,
onlineStatus: point.onlineStatus,
remainingPower: point.bat || 0
}))
.sort((a, b) => new Date(a.time) - new Date(b.time)); // 按时间排序
// 添加起点和终点标记
if (this.trackPoints.length > 0) {
const startPoint = this.trackPoints[0]
const endPoint = this.trackPoints[this.trackPoints.length - 1]
// 添加起点标记
this.markers.push({
id: 'start',
latitude: startPoint.latitude,
longitude: startPoint.longitude,
width: 22,
height: 32,
iconPath: 'https://api.ccttiot.com/smartmeter/img/static/uoORewceRbnD0jcNHhns'
})
// 添加终点标记
this.markers.push({
id: 'end',
latitude: endPoint.latitude,
longitude: endPoint.longitude,
width: 22,
height: 32,
iconPath: 'https://api.ccttiot.com/smartmeter/img/static/u5HZcdTVcyNGkHDUeT4h'
})
// 添加轨迹折线
this.polyline.push({
points: this.trackPoints.map(point => ({
latitude: point.latitude,
longitude: point.longitude
})),
color: '#00AF99',
width: 4,
dottedLine: false,
arrowLine: true,
borderWidth: 2,
borderColor: '#ffffff'
})
// 更新地图显示范围
this.$nextTick(() => {
if (this.$refs.map) {
this.$refs.map.includePoints({
points: this.trackPoints,
padding: [80, 80, 80, 80]
})
}
})
}
}
})
},
btnflagxs(){
this.flagdiaodu = !this.flagdiaodu
},
unpass(pass){
let data = {
id:this.orderxqobj.id,
pass:pass
}
this.$u.put('/bst/order/verify', data).then((res) => {
if (res.code === 200) {
uni.showToast({
title: '操作成功',
icon: 'success',
duration: 2000
})
this.deviceInfo()
this.getorderxq()
} else {
uni.showToast({
title: res.msg,
icon: 'none',
duration: 2000
})
}
})
},
parsePictures(pictureString) {
console.log(pictureString,'45454545454');
if (!pictureString || typeof pictureString !== 'string') {
return []
}
return pictureString.split(',')
},
preview(img, pic) {
uni.previewImage({
current: img,
urls: this.parsePictures(pic.finishPicture)
})
},
// 点击退款
btntuikuan(){
let data = {
orderId:this.orid,
amount:this.amount
}
this.$u.put(`/bst/order/refund`,data).then(res =>{
if(res.code == 200){
uni.showToast({
title: '退款成功',
icon: 'success',
duration: 2000
})
this.tkflag = false
this.deviceInfo()
this.getorderxq()
}else{
uni.showToast({
title: res.msg,
icon: 'none',
duration: 2000
})
}
})
},
// 点击辅助还车
btnfuzhu(){
let that = this
uni.showModal({
title: '提示',
content: '您确定要进行辅助还车吗?',
showCancel: true,
success: function (res) {
if (res.confirm) {
let data = {
orderId:that.orid
}
that.$u.put(`/bst/order/end`,data).then(res =>{
if(res.code == 200){
uni.showToast({
title: '辅助还车成功',
icon: 'success',
duration: 2000
})
that.deviceInfo()
that.getorderxq()
}else{
uni.showToast({
title: res.msg,
icon: 'none',
duration: 2000
})
}
})
} else if (res.cancel) {
}
}
})
},
// 转换成时分秒
formatSecondsToHMS(seconds) {
seconds = seconds || 0 // 处理空值
const h = Math.floor(seconds / 3600).toString().padStart(2, '0')
const m = Math.floor((seconds % 3600) / 60).toString().padStart(2, '0')
const s = Math.floor(seconds % 60).toString().padStart(2, '0')
return `${h}:${m}:${s}`
},
btnqx(){
this.tkflag = false
},
checkbtn(num) {
if(num == 1){ //1为联系客户
uni.makePhoneCall({
phoneNumber: this.orderxqobj.userPhone,
success: function(res) {
console.log('拨打电话成功', res)
},
fail: function(err) {
console.error('拨打电话失败', err)
}
})
}else{ //否则为退款
this.tkflag = true
}
},
// 请求订单详情
getorderxq(){
this.$u.get(`/bst/order/${this.orid}?assembleOrderDeviceList=true`).then(res =>{
if(res.code == 200){
this.orderxqobj = res.data
this.updateTrackData()
this.suitSeconds = res.data.suitSeconds == null ? '--' : Math.ceil(res.data.suitSeconds / 3600)
this.orderDeviceList = res.data.orderDeviceList
console.log(this.orderDeviceList,'12212121211124121')
}
})
},
// 静音
btnjingyin(){
if(this.jytxt == '开'){
let data = {
isSound:0
}
this.$u.post(`/appVerify/device/mute/${this.sn}`).then(res =>{
if(res.code == 200){
this.jytxt = '关'
uni.showToast({
title: '关闭静音成功',
icon: 'success',
duration: 2000
})
}
})
}else{
let data = {
isSound:1
}
this.$u.post(`/appVerify/device/mute/${this.sn}`).then(res =>{
if(res.code == 200){
this.jytxt = '开'
uni.showToast({
title: '开启静音成功',
icon: 'success',
duration: 2000
})
}
})
}
},
toTrack(){
let endTime = this.orderxqobj.endTime || this.formatCurrentTime()
console.log(endTime,'020202002');
uni.navigateTo({
url:'/page_shanghu/guanli/bike_track?id=' + this.deviceInfos.id + '&type=1' + '&qufen=123' + '&startTime=' + this.orderxqobj.startTime + '&endTime=' + endTime + '&orid=' + this.orid
})
},
changeShwoList(){
console.log('diaoyongle')
this.showModelList = true
},
confirm(e) {
let modelId = e[0].value
let data = {
sn: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(){
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
})
}
})
},
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
},
// 确定修改车牌号
putvehicle() {
let data = {
sn: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
},
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
let data = [this.sn]
if (num == 0) {
uni.showLoading({
title: '加载中...'
})
console.log('点击了....1');
this.$u.put('/bst/device/iot/unlock?sn=' + this.sn).then((res) => {
if (res.code == 200) {
// 处理接口返回的数据,将边界数据转换为地图组件需要的折线结构
this.deviceInfo()
uni.showToast({
title: '操作成功',
icon: 'success',
duration: 2000
})
} else {
uni.hideLoading()
this.bulebtn(2)
}
})
} else if (num == 1) {
uni.showLoading({
title: '加载中...'
})
console.log('点击了....2');
this.$u.put('/bst/device/iot/lock?sn=' + this.sn).then((res) => {
if (res.code == 200) {
// 处理接口返回的数据,将边界数据转换为地图组件需要的折线结构
this.deviceInfo()
uni.showToast({
title: '操作成功',
icon: 'success',
duration: 2000
});
} else {
uni.hideLoading()
this.bulebtn(3)
}
})
} 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()
} else {
uni.showToast({
title: res.msg,
icon: 'none',
duration: 2000
})
}
})
} 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()
} else {
uni.showToast({
title: res.msg,
icon: 'none',
duration: 2000
});
}
})
} else if (num == 4) {
uni.showLoading({
title: '加载中...'
})
this.$u.put('/bst/device/iot/ring?sn=' + this.sn).then((res) => {
if (res.code == 200) {
uni.hideLoading()
uni.showToast({
title: '操作成功',
icon: 'success',
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('/bst/device/in',data).then((res) => {
if (res.code == 200) {
uni.showToast({
title: '回仓成功',
icon: 'success',
duration: 2000
});
this.deviceInfo()
} else {
uni.showToast({
title: res.msg,
icon: 'none',
duration: 2000
})
}
})
} 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
})
} 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.put('/bst/device/iot/reboot?sn=' + this.sn).then((res) => {
if (res.code == 200) {
this.deviceInfo()
uni.showToast({
title: '操作成功',
icon: 'success',
duration: 2000
})
} else {
uni.showToast({
title: res.msg,
icon: 'none',
duration: 2000
})
// uni.hideLoading()
// this.bulebtn(4)
}
})
} else if (num == 9) {
uni.showLoading({
title: '加载中...'
})
this.$u.put('/bst/device/iot/unlockSeat?sn=' + this.sn).then((res) => {
if (res.code == 200) {
this.deviceInfo()
uni.showToast({
title: '操作成功',
icon: 'success',
duration: 2000
})
} else {
uni.showToast({
title: res.msg,
icon: 'none',
duration: 2000
})
}
})
} 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
})
} else {
uni.showToast({
title: res.msg,
icon: 'none',
duration: 2000
})
}
})
}
},
Binddevice() {
uni.getBluetoothAdapterState({
success: function(res) {
console.log('蓝牙状态:', res.available)
},
fail: function(res) {
console.log('获取蓝牙状态失败')
}
})
this.maskloading = true
this.devicesList = []
this.maskepage = 4
this.buletxt = '蓝牙连接中'
console.log("xBlufi", xBlufi.XMQTT_SYSTEM)
xBlufi.listenDeviceMsgEvent(true, this.funListenDeviceMsgEvent)
xBlufi.notifyStartDiscoverBle({
'isStart': true
})
// 两秒后停止蓝牙搜索
setTimeout(() => {
xBlufi.notifyStartDiscoverBle({
'isStart': false
})
setTimeout(() => {
if (this.devicesList.length == 0) {
this.maskepage = 5
} else {
let uniqueDevicesList = Array.from(new Set(this.devicesList))
// 将去重后的数组重新赋值给 this.devicesList
this.devicesList = uniqueDevicesList
console.log(this.devicesList, 'this.devicesListthis.devicesList')
let istrue = false
this.devicesList.forEach(device => {
// 从设备名称中提取 MAC 地址(假设 MAC 地址是设备名称的后6个字符
let macFromName = device.name.substring(device.name.length - 12)
console.log(macFromName, 'macFromNamemacFromName')
// 与 this.mac 进行比较
if (macFromName == this.mac) {
// 如果相同,则将 this.ishave 设置为 true
console.log(device)
this.deviceInfoss = device
istrue = true
this.createBLEConnection(device)
console.log('对比正确1111111111')
} else {
console.log('对比错误')
}
})
setTimeout(() => {
if (!istrue) {
this.buletxt = '蓝牙连接失败'
setTimeout(() => {
this.maskepage = 5
}, 500)
}
}, 500)
}
}, 200)
}, 5000)
},
reboot() {
let vm = this // 将外部的 this 绑定到 vm 上
uni.getNetworkType({
success(res) {
if (res.networkType !== 'none') {
uni.getConnectedBluetoothDevices({
success(res) {
console.log('已连接的蓝牙设备信息:', res)
xBlufi.notifySendCustomData({
customData: "11reboot"
})
vm.maskloading = false
},
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)
xBlufi.notifySendCustomData({
customData: "11open"
})
vm.maskloading = false
vm.deviceInfo()
},
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)
xBlufi.notifySendCustomData({
customData: "11close"
})
vm.maskloading = false
vm.deviceInfo()
},
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)
xBlufi.notifySendCustomData({
customData: "11play1@"
})
vm.maskloading = false
vm.deviceInfo()
},
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
devicesarr.forEach(device => {
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) {
xBlufi.notifyInitBleEsp32({
deviceId: options.data.deviceId
})
let systemInfo = uni.getSystemInfoSync()
if (systemInfo.platform === 'android') {
// 当前设备是 Android
} else if (systemInfo.platform === 'ios') {
// 当前设备是 iOS
}
}
if (options.result == false) {
this.carstause = false
if (this.maskepage == 4) {
this.buletxt = '设备连接失败'
setTimeout(() => {
this.maskepage = 5
}, 800)
}
}
break;
case xBlufi.XBLUFI_TYPE.TYPE_RECIEVE_CUSTON_DATA:
if (options.data) {
this.carstause = true
if (this.maskloading && this.maskepage == 4) {
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
}
this.searching = false
break
}
},
btnyc() {
this.titleflag = false
},
// 解析自定义数据
//4、建立连接
createBLEConnection(e) {
console.log('调用了')
xBlufi.notifyStartDiscoverBle({
'isStart': false
});
console.log(e, '蓝牙信息')
const deviceId = e.deviceId
let name = e.name
console.log('点击了蓝牙准备连接的deviceId:' + e.deviceId)
xBlufi.notifyConnectBle({
isStart: true,
deviceId: e.deviceId,
name
})
},
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.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:
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.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.polygon = []; // 初始化polygon数组
this.$u.get(`/bst/device?sn=${this.sn}`).then((res) => {
console.log(res, 'rererer');
if (res.code === 200) {
this.deviceInfos = res.data;
if(res.data.isSound == 0){
this.jytxt = '关';
}else{
this.jytxt = '开';
}
this.vehicleNum = res.vehicleNum;
this.mac = res.data.mac;
this.getModelList();
this.latitude = this.deviceInfos.latitude;
this.longitude = this.deviceInfos.longitude;
// 确保在获取设备信息后立即获取区域信息
if (this.deviceInfos.areaId) {
this.getArea();
}
if (this.getnum == 0) {
this.getArea()
}
this.getnum = 1
if (this.deviceInfos.status == 0) {
this.markers.push({
id: parseFloat(this.deviceInfos.sn),
latitude: this.deviceInfos.latitude,
longitude: this.deviceInfos.longitude,
// title: item.deviceName,
width: 40,
height: 47,
// iconPath: 'https://lxnapi.ccttiot.com/bike/img/static/u6jBvj7S50FPgsHaHXai',
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,
// title: item.deviceName,
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,
// title: item.deviceName,
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,
// title: item.deviceName,
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.markers.push({
id: parseFloat(this.deviceInfos.sn),
latitude: this.deviceInfos.latitude,
longitude: this.deviceInfos.longitude,
// title: item.deviceName,
width: 40,
height: 47,
// joinCluster: true,
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,
// title: item.deviceName,
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,
// title: item.deviceName,
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.$forceUpdate()
} else {
uni.showToast({
title: res.msg,
icon: 'none',
duration: 2000
})
}
})
},
convertBoundaryToPolyline(boundary) {
if (!boundary) return null;
try {
const points = JSON.parse(boundary).map(coord => ({
latitude: coord[1],
longitude: coord[0]
}));
return {
points: points,
color: "#22FF00",
width: 2,
dottedLine: false,
arrowLine: false,
borderWidth: 2,
borderColor: "#22FF00"
};
} catch (error) {
console.error("Error converting boundary to polyline:", error);
return null;
}
},
convertBoundaryToPolylines(boundaries, num) {
if (!boundaries || !Array.isArray(boundaries)) return [];
return boundaries.map(boundary => {
if (!boundary) return null;
try {
const coords = JSON.parse(boundary);
if (!Array.isArray(coords)) return null;
const points = coords.map(coord => ({
latitude: coord[1],
longitude: coord[0]
}));
let style = {};
if (num === 1) {
style = {
color: "#3A7EDB",
width: 2,
dottedLine: false,
arrowLine: false,
borderWidth: 2,
borderColor: "#3A7EDB"
};
} else if (num === 2) {
style = {
color: "#FF473E",
width: 2,
dottedLine: false,
arrowLine: false,
borderWidth: 2,
borderColor: "#FF473E"
};
} else if (num === 3) {
style = {
color: "#FFC107",
width: 2,
dottedLine: false,
arrowLine: false,
borderWidth: 2,
borderColor: "#FFC107"
};
}
return {
points: points,
...style
};
} catch (error) {
console.error("Error converting boundary to polylines:", error);
return null;
}
}).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))
}
},
convertBoundaryToPolygon(boundary) {
if (!boundary) return null;
try {
const points = JSON.parse(boundary).map(coord => ({
latitude: coord[1],
longitude: coord[0]
}));
return {
points: points,
fillColor: "#55888840",
strokeColor: "#22FF0080",
strokeWidth: 1,
zIndex: 1
};
} catch (error) {
console.error("Error converting boundary to polygon:", error);
return null;
}
},
convertBoundaryToPolygons(boundaries, num) {
if (!boundaries || !boundaries.length) return [];
const colors = {
1: { fill: "#3A7EDB40", stroke: "#3A7EDB" },
2: { fill: "#FFF5D640", stroke: "#FFC107" },
3: { fill: "#FFE0E040", stroke: "#FF473E" }
};
return boundaries.map(boundary => {
if (!boundary) return null;
try {
const coords = JSON.parse(boundary);
if (!Array.isArray(coords)) return null;
const points = coords.map(coord => ({
latitude: coord[1],
longitude: coord[0]
}));
return {
points: points,
fillColor: colors[num].fill,
strokeColor: colors[num].stroke,
strokeWidth: 1,
zIndex: 1
};
} catch (error) {
console.error("Error converting boundary to polygons:", error);
return null;
}
}).filter(Boolean);
},
getParking() {
let data = {
areaId: this.deviceInfos.areaId
};
this.$u.get('/bst/areaSub/listByAreaId', data).then((res) => {
if (res.code === 200) {
const type1Data = [];
const type2Data = [];
const type3Data = [];
res.data.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);
});
// 处理 type1 数据
const validBoundaries = type1Data.map(row => row.boundaryStr).filter(boundary =>
typeof boundary === 'string' && boundary.trim() !== '');
const polygons = this.convertBoundaryToPolygons(validBoundaries, 1);
if (polygons && polygons.length > 0) {
this.polygon = this.polygon.concat(polygons);
}
// 处理 type2 数据
const validBoundaries1 = type2Data.map(row => row.boundaryStr).filter(boundary =>
typeof boundary === 'string' && boundary.trim() !== '');
const polygons1 = this.convertBoundaryToPolygons(validBoundaries1, 2);
if (polygons1 && polygons1.length > 0) {
this.polygon = this.polygon.concat(polygons1);
}
// 处理 type3 数据
const validBoundaries2 = type3Data.map(row => row.boundaryStr).filter(boundary =>
typeof boundary === 'string' && boundary.trim() !== '');
const polygons2 = this.convertBoundaryToPolygons(validBoundaries2, 3);
if (polygons2 && polygons2.length > 0) {
this.polygon = this.polygon.concat(polygons2);
}
this.parkingList = res.data;
this.$forceUpdate();
}
}).catch(error => {
console.error("Error fetching parking data:", error);
});
},
getArea() {
let id = this.deviceInfos.areaId;
if (!id) {
console.error("Area ID is missing");
return;
}
this.$u.get(`/bst/area/${id}`).then((res) => {
if (res.code === 200 && res.data && res.data.boundaryStr) {
const polygon = this.convertBoundaryToPolygon(res.data.boundaryStr);
if (polygon) {
this.polygon = [polygon];
console.log('Area boundary added:', polygon);
this.getParking();
}
}
}).catch(error => {
console.error("Error fetching area data:", error);
});
},
}
}
</script>
<style lang="scss">
page {
overflow-x: hidden;
background-color: #F3F3F3;
}
.xingchengxx{
width: 750rpx;
max-height: 99999rpx;
background: #FFFFFF;
border-radius: 0rpx 0rpx 0rpx 0rpx;
margin-top: 20rpx;
.start{
font-size: 28rpx;
color: #808080;
padding: 0 28rpx;
box-sizing: border-box;
margin-top: 26rpx;
span{
color: #3D3D3D;
}
}
.dingdanul{
font-size: 28rpx;
color: #808080;
padding: 0 28rpx;
box-sizing: border-box;
margin-top: 26rpx;
display: flex;
justify-content: space-between;
view{
width: 50%;
}
span{
color: #3D3D3D;
}
}
.name{
font-weight: 600;
font-size: 32rpx;
color: #3D3D3D;
width: 100%;
border-bottom: 1rpx solid #F3F3F3;
padding-top: 22rpx;
padding-left: 28rpx;
padding-bottom: 22rpx;
box-sizing: border-box;
}
}
.dingdanxx{
width: 750rpx;
max-height: 858rpx;
background: #FFFFFF;
border-radius: 0rpx 0rpx 0rpx 0rpx;
padding-bottom: 20rpx;
box-sizing: border-box;
.yingshouprice{
border-top: 1px solid #F3F3F3;
margin-top: 26rpx;
padding-top: 26rpx;
padding-left: 28rpx;
box-sizing: border-box;
font-size: 28rpx;
color: #808080;
span{
color: #3D3D3D;
}
}
.dingdanul{
font-size: 28rpx;
color: #808080;
padding: 0 28rpx;
box-sizing: border-box;
margin-top: 26rpx;
display: flex;
justify-content: space-between;
view{
width: 50%;
}
span{
color: #3D3D3D;
}
}
.dingdanbh{
font-size: 28rpx;
color: #808080;
padding: 0 28rpx;
box-sizing: border-box;
margin-top: 26rpx;
span{
color: #3D3D3D;
}
}
.name{
font-weight: 600;
font-size: 32rpx;
color: #3D3D3D;
width: 100%;
border-bottom: 1rpx solid #F3F3F3;
padding-top: 22rpx;
padding-left: 28rpx;
padding-bottom: 22rpx;
box-sizing: border-box;
text{
font-weight: 400;
font-size: 28rpx;
}
}
}
.tktc{
width: 560rpx;
height: 330rpx;
background-color: #fff;
border-radius: 20rpx;
position: fixed;
top: 35%;
left: 50%;
transform: translateX(-50%);
z-index: 9;
padding: 26rpx 30rpx;
box-sizing: border-box;
.anniu{
display: flex;
justify-content: space-between;
.qd,
.qx{
width: 48%;
border: 1px solid #ccc;
border-radius: 10rpx;
color: #000;
height: 80rpx;
line-height: 80rpx;
margin-top: 30rpx;
text-align: center;
}
}
.name{
width: 100%;
text-align: center;
font-size: 32rpx;
font-weight: 600;
}
input{
width: 100%;
height: 60rpx;
line-height: 60rpx;
margin-top: 20rpx;
background-color: #F3F3F3;
border-radius: 10rpx;
padding-left: 20rpx;
box-sizing: border-box;
}
}
.mask{
width: 100%;
height: 100vh;
position: fixed;
top: 0;
left: 0;
z-index: 2;
background-color: rgba(0, 0, 0, 0.08);
}
.page {
padding-bottom: 400rpx;
width: 750rpx;
.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;
// 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;
}
}
}
}
.map {
position: relative;
width: 750rpx;
height: 752rpx;
.track {
position: absolute;
display: flex;
align-items: center;
justify-content: center;
left: 30rpx;
bottom: 40rpx;
// background-color: #fff;
border-radius: 50%;
width: 82rpx;
height: 82rpx;
// z-index: 1;
.img {
width: 82rpx;
height: 82rpx;
}
}
.park {
position: absolute;
display: flex;
align-items: center;
justify-content: center;
right: 30rpx;
bottom: 40rpx;
// background-color: #fff;
border-radius: 50%;
width: 82rpx;
height: 82rpx;
// z-index: 1;
.img {
width: 82rpx;
height: 82rpx;
}
}
}
.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: 204rpx;
height: 80rpx;
background: #4C97E7;
border-radius: 0rpx 0rpx 0rpx 0rpx;
// border: 2rpx solid #4C97E7;
border-radius: 50rpx;
font-weight: 400;
font-size: 32rpx;
color: #fff;
}
}
.card {
padding: 24rpx;
margin: 20rpx auto;
width: 720rpx;
background: #FFFFFF;
box-shadow: 0rpx 4rpx 22rpx 0rpx rgba(0, 0, 0, 0.07);
border-radius: 10rpx;
.btn_cont {
display: flex;
flex-wrap: nowrap;
justify-content: flex-end;
/* 添加此行使按钮靠右对齐 */
margin-top: 20rpx;
.btn1 {
margin-left: 30rpx;
font-weight: 400;
font-size: 32rpx;
color: #FEFFFE;
padding: 6rpx 36rpx;
background: #64B6A8;
border-radius: 8rpx 8rpx 8rpx 8rpx;
}
.btn2 {
font-weight: 400;
font-size: 32rpx;
color: #64B6A8;
padding: 6rpx 36rpx;
border-radius: 8rpx 8rpx 8rpx 8rpx;
border: 2rpx solid #64B6A8;
}
}
.tips {
margin-top: 24rpx;
width: 100%;
text-align: center;
font-weight: 400;
font-size: 28rpx;
color: #808080;
}
.info_cont {
margin-top: 22rpx;
display: flex;
align-items: center;
flex-wrap: nowrap;
justify-content: space-between;
.sn {
font-weight: 400;
font-size: 24rpx;
color: #979797;
span{
color: #000;
}
}
.time {
font-weight: 400;
font-size: 24rpx;
color: #979797;
span{
color: #000;
}
}
}
.txt {
margin-top: 24rpx;
font-weight: 400;
font-size: 32rpx;
color: #3D3D3D;
}
.pic_cont {
// display: flex;
// flex-wrap: wrap;
width: 100%;
background-color: #f6fbff;
padding: 20rpx;
box-sizing: border-box;
margin-top: 20rpx;
border-radius: 10rpx;
.bianhao{
display: flex;
view{
width: 50%;
margin-top: 10rpx;
font-size: 24rpx;
color: #979797;
span{
color: #000;
}
}
}
.jilu{
width: 100%;
display: flex;
.one{
width: 130rpx;
height: 40rpx;
text-align: center;
line-height:40rpx;
background-color: #5fc2f7;
color: #fff;
border-radius: 4rpx;
margin-right: 20rpx;
}
.two{
}
}
.imgs {
display: flex;
flex-wrap: wrap;
margin-top: 10rpx;
width: 100%;
// height:190rpx;
border-radius: 10rpx;
margin-right: 20rpx;
image{
border-radius: 10rpx;
width: 160rpx;
height:160rpx;
margin-right: 20rpx;
}
}
}
}
}
</style>