<template> <view class="page" v-if="loading"> <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="polygons" :polyline="polyline" :enable-building="true"> <cover-view class="park" @click="toggleIconAndCallout" v-if="showpark"> <cover-image class="img" src="https://lxnapi.ccttiot.com/bike/img/static/uRiYQZQEb3l2LsltEsyW" mode=""></cover-image> </cover-view> </map> <view class="info_card"> <view class="info_tit"> 基本信息 </view> <view class="lines"></view> <view class="cont"> <view class="info_li"> 订单编号:<span>{{orderInfo.orderNo}}</span> </view> <!-- <view class="info_li"> </view> --> <view class="info_li"> <view class="half_infoli " @click="callPhone"> 租赁用户:<span style="color:#4C97E7 ;">{{orderInfo.phonenumber}}</span> </view> <view class="half_infoli"> 用户姓名:<span v-if="orderInfo.realName">{{orderInfo.realName}}</span> <span v-else>--</span> </view> </view> <view class="info_li"> 订单状态:<span>{{status()}}</span> </view> <view class="info_li"> <view class="half_infoli"> 租赁时长:<span>{{ computedList(orderInfo)}}</span> </view> <view class="half_infoli"> 行驶距离:<span>{{orderInfo.distance/1000}}Km</span> </view> </view> </view> </view> <view class="info_card" style="margin-top: 20rpx;"> <view class="info_tit"> 设备信息 </view> <view class="lines"></view> <view class="cont"> <view class="info_li"> <view class="half_infoli" v-if="deviceInfos.onlineStatus==0"> 网络状态:<span style="color: #FF4444;">离线</span> </view> <view class="half_infoli" v-if="deviceInfos.onlineStatus==1"> 网络状态:<span>在线</span> </view> <view class="half_infoli" v-if="deviceInfos.lockStatus==0"> 锁状态:<span>关锁</span> </view> <view class="half_infoli" v-if="deviceInfos.lockStatus==1"> 锁状态:<span>开锁</span> </view> </view> <view class="info_li"> <view class="half_infoli"> 车牌号: <span v-if="orderInfo.device.vehicleNum">{{orderInfo.device.vehicleNum}}</span> <span v-else>--</span> </view> <view class="half_infoli"> SN: <span v-if="orderInfo.device.sn">{{orderInfo.device.sn}}</span> <span v-else>--</span> </view> </view> <!-- <view class="info_li"> <view class="half_infoli"> 运营区域: <span v-if="orderInfo.area">{{orderInfo.area}}</span> <span v-else>--</span> </view> </view> --> <view class="info_li"> </view> </view> </view> <view class="info_card" style="margin-top: 20rpx;"> <view class="info_tit"> 费用明细 <view class="money"> 结算总费用:¥{{orderInfo.settlementFee}} </view> </view> <view class="lines"></view> <view class="cont"> <view class="info_li"> <view class="half_infoli"> 预约费用:<span>{{orderInfo.appointmentFee}}</span> </view> <view class="half_infoli"> 运营区外调度费:<span>{{orderInfo.dispatchFee}}</span> </view> </view> <view class="info_li"> <view class="half_infoli"> 停车点外调度费:<span>{{orderInfo.manageFee}}</span> </view> <view class="half_infoli"> 骑行费用:<span>{{orderInfo.ridingFee}}</span> </view> </view> <view class="info_li"> <view class="half_infoli"> 停车点外调度费:<span>{{orderInfo.manageFee}}</span> </view> <view class="half_infoli"> 骑行费用:<span>{{orderInfo.ridingFee}}</span> </view> </view> <view class="info_li"> 实收:<span>{{orderInfo.totalFee}}</span> </view> <view class="info_li"> 支付方式:<span v-if="orderInfo.payType=='yj'">押金抵扣</span><span v-if="orderInfo.payType=='wx'">微信支付</span> </view> <view class="info_li" v-if="orderInfo.rule" style="display: inline-block;"> 计费模板:<span>{{orderInfo.rule.name}}</span> </view> <view class="info_li" v-if="orderInfo.payTime"> 支付时间:<span>{{orderInfo.payTime}}</span> </view> </view> <view class="lines"></view> <view class="info_tit" v-if="orderInfo.videoUrl!=null"> 视频审核 <view class="vadio_type" v-if="orderInfo.status==5"> 待审核 </view> <view class="vadio_type" style="color: #FF4444 ;background: #FFEEEE;" v-if="orderInfo.status==6"> 设备损坏 </view> <view class="vadio_type" style="color: #64B6A8;background: #E2FFFA;" v-if="orderInfo.status==4"> 审核通过 </view> <view class="vadio_type" style="color: #64B6A8;background: #E2FFFA;" v-if="orderInfo.status==7"> 待官方审核 </view> </view> <view class="vadio_box" v-if="orderInfo.videoUrl!=null"> <video :src="orderInfo.videoUrl" controls="controls" style="width: 100%;" @fullscreenchange="handleFullscreenChange"></video> <view class="vadio_li"> <view class="" style="width: 10rpx;"> </view> <view class="vadio_info"> 提交时间:{{orderInfo.returnTime}} </view> </view> <view class="vadio_li"> <view class="" style="width: 10rpx;"> </view> <view class="btn_box" v-if="false"> <view class="vadio_btn" @click="pass()" v-if="orderInfo.status==5"> 通过 </view> <view class="vadio_btn" style="background: #FF4444;" @click="unpass" v-if="orderInfo.status==5"> 有损坏 </view> <view class="vadio_btn" style="background: #64B6A8 ;" @click="showck=true" v-if="orderInfo.status==6"> 押金扣款 </view> <view class="vadio_btn" style="background: #64B6A8 ;" @click="callPhone"> 电话沟通 </view> </view> </view> </view> <view class="lines"></view> <view class="cont" v-if="orderInfo.etRefund"> <view class="info_li"> <view class="half_infoli"> 预约费退款:<span>{{orderInfo.etRefund.appointmentFee}}</span> </view> <view class="half_infoli"> 调度费退款:<span>{{orderInfo.etRefund.dispatchFee}}</span> </view> </view> <view class="info_li"> <view class="half_infoli"> 骑行费退款:<span>{{orderInfo.etRefund.ridingFee}}</span> </view> <view class="half_infoli"> 管理费退款:<span>{{orderInfo.etRefund.manageFee}}</span> </view> </view> <view class="info_li"> 退款原因:<span v-if="orderInfo.etRefund.reason">{{orderInfo.etRefund.reason}}</span> <span v-else>--</span> </view> <view class="info_li"> 退款时间:<span>{{orderInfo.etRefund.createTime}}</span> </view> </view> </view> <view class="info_card" style="margin-top: 20rpx;"> <view class="info_tit"> 行程记录 </view> <view class="lines"></view> <view class="cont"> <view v-for="(item,index) in orderInfo.tripLogs" :key="index"> <view class="info_lis" v-if="item.type==1"> 开锁时间:<view class="text">{{ displayAmount(item.createTime)}}</view> </view> <!-- <view class="info_lis" v-if="item.type==1"> 开锁地点:<view class="text"> {{ displayAmount(item.address)}}</view> </view> --> <view class="info_lis" v-if="item.type==2"> 临时锁车时间:<view class="text">{{ displayAmount(item.createTime)}}</view> </view> <!-- <view class="info_lis" v-if="item.type==2"> 临时锁车地点:<view class="text">{{ displayAmount(item.address)}}</view> </view> --> <view class="info_lis" v-if="item.type==3"> 解除时间:<view class="text">{{ displayAmount(item.createTime)}}</view> </view> <view class="info_lis" v-if="item.type==4"> 关锁时间:<view class="text">{{ displayAmount(item.createTime)}}</view> </view> <!-- <view class="info_lis" v-if="item.type==4"> 关锁地点:<view class="text">{{displayAmount(item.address)}}</view> </view> --> </view> <!-- <view class="info_li"> 锁车时间:<span>120.56189,27.12379</span> </view> <view class="info_li"> 锁车地点:<span>120.56189,27.12379</span> </view> --> <!-- <view class="info_li"> 解除时间:<span>120.56189,27.12379</span> </view> --> </view> </view> <!-- <view class="bot" v-if='orderInfo.paid==1'> <view class="btn" @click="backfee"> 退款 </view> </view> --> <view class="bot_btn"> <view class="btn" @click="backfee()" v-if='orderInfo.paid==1'> 退款 </view> <view class="btn" @click="showfzhc=true" v-if=' orderInfo.status==0||orderInfo.status==2'> 辅助还车 </view> <view class="btn" @click="showgj=true" v-if=' orderInfo.status==1||orderInfo.status==3'> 改价 </view> <view class="btn" @click="pass()" v-if="orderInfo.status==5"> 审核通过 </view> <view class="btn" @click="yjdkBtn()" v-if="orderInfo.status==3"> 押金抵扣 </view> <view class="btn" @click="openBtn()" v-if="orderInfo.status==2"> 开锁 </view> <view class="btn" @click="closeBtn()" v-if="orderInfo.status==2"> 关锁 </view> <view class="btn" @click="unpass" v-if="orderInfo.status==5"> 有损坏 </view> <view class="btn" @click="showck=true" v-if="orderInfo.status==6"> 押金扣款 </view> <view class="btn" @click="backpass()" v-if="orderInfo.status==6"> 撤销损坏 </view> <view class="btn" @click="callPhone"> 联系客户 </view> </view> <u-mask :show="showload" :z-index='100' /> <u-mask :show="show" :z-index='100' /> <u-mask :show="showfzhc" @click="show = false" :z-index='100' /> <u-mask :show="showgj" :z-index='100' /> <view class="tip_box1" v-if="showgj"> <view class="top1"> <view class="tip"> 改价 </view> <view class="ipt_box"> <view class="text"> 运营区外调度费 </view> <view class="ipt"> <input type="text" v-model="orderInfo.dispatchFee" placeholder="0.00" class="input" placeholder-style="color:#C7CDD3"> 元 </view> </view> <view class="ipt_box"> <view class="text"> 停车点外调度费 </view> <view class="ipt"> <input type="text" v-model="orderInfo.manageFee" placeholder="0.00" class="input" placeholder-style="color:#C7CDD3"> 元 </view> </view> <view class="ipt_box"> <view class="text"> 骑行费 </view> <view class="ipt"> <input type="text" v-model="orderInfo.ridingFee" placeholder="0.00" class="input" placeholder-style="color:#C7CDD3"> 元 </view> </view> <view class="ipt_box"> <view class="text"> 预约费 </view> <view class="ipt"> <input type="text" v-model="orderInfo.appointmentFee" placeholder="0.00" class="input" placeholder-style="color:#C7CDD3"> 元 </view> </view> </view> <view class="bot1"> <view class="bot_left" @click="showgj=false"> 取消 </view> <view class="bot_right" @click="changeMoney()"> 确定 </view> </view> </view> <view class="tip_box1" v-if="showfzhc"> <view class="top1"> <view class="tip"> 提示 </view> <view class="txt"> 确定要辅助还车吗? </view> </view> <view class="bot1"> <view class="bot_left" @click="closefz()"> 取消 </view> <view class="bot_right" @click="backDevice()"> 确定 </view> </view> </view> <view class="tip_box" v-if="showtk"> <view class="top" v-if="showtk"> <view class="tip"> 退款 </view> <view class="ipt_box"> <view class="text"> 运营区外调度费 </view> <view class="ipt"> <input type="text" v-model="dispatchFee" placeholder="0.00" class="input" placeholder-style="color:#C7CDD3" @input="checkAndUpdate('dispatchFee')"> 元 </view> </view> <view class="ipt_box" style="width:100%;margin-top: 6rpx;"> <view class="width:10% ;"> </view> <view style="color: #ccc;margin-left: auto; font-size: 24rpx;"> 最大可退款金额:{{orderInfo.dispatchFee}}元 </view> </view> <view class="ipt_box"> <view class="text"> 停车点外调度费 </view> <view class="ipt"> <input type="text" v-model="manageFee" placeholder="0.00" class="input" placeholder-style="color:#C7CDD3" @input="checkAndUpdate('manageFee')"> 元 </view> </view> <view class="ipt_box" style="width:100%;margin-top: 6rpx;"> <view class="width:10% ;"> </view> <view style="color: #ccc;margin-left: auto; font-size: 24rpx;"> 最大可退款金额:{{orderInfo.manageFee}}元 </view> </view> <view class="ipt_box"> <view class="text"> 骑行费 </view> <view class="ipt"> <input type="text" v-model="ridingFee" placeholder="0.00" class="input" placeholder-style="color:#C7CDD3" @input="checkAndUpdate('ridingFee')"> 元 </view> </view> <view class="ipt_box" style="width:100%;margin-top: 6rpx;"> <view class="width:10% ;"> </view> <view style="color: #ccc;margin-left: auto; font-size: 24rpx;"> 最大可退款金额:{{orderInfo.ridingFee}}元 </view> </view> <view class="ipt_box"> <view class="text"> 预约费 </view> <view class="ipt"> <input type="text" v-model="appointmentFee" placeholder="0.00" class="input" placeholder-style="color:#C7CDD3" @input="checkAndUpdate('appointmentFee')"> 元 </view> </view> <view class="ipt_box" style="width:100%;margin-top: 6rpx;"> <view class="width:10% ;"> </view> <view style="color: #ccc;margin-left: auto; font-size: 24rpx;"> 最大可退款金额:{{orderInfo.appointmentFee}}元 </view> </view> <view class="ipt_box"> <view class="text"> 原因 </view> <view class="ipt"> <input type="text" v-model="orderInfo.reason" placeholder="选填" class="input" placeholder-style="color:#C7CDD3" @input="checkAndUpdate('reason')"> </view> </view> </view> <view class="bots"> <view class="bot_left" @click="closetk()"> 取消 </view> <view class="bot_right" @click="backMoney()"> 确定 </view> </view> </view> <u-mask :show="showck" @click="showck = false" :z-index='100' /> <view class="tip_box" v-if="showck"> <view class="top" v-if="showck"> <view class="tip"> 押金扣款 </view> <view class="ipt_box"> <view class="text"> 扣款金额 </view> <view class="ipt"> <input type="text" v-model="money" placeholder=" " class="input" placeholder-style="color:#C7CDD3">元 </view> </view> </view> <view class="bots"> <view class="bot_left" @click="showck=false"> 取消 </view> <view class="bot_right" @click="ckmoney()"> 确定 </view> </view> </view> </view> </template> <script> export default { data() { return { bgc: { backgroundColor: "#F7FAFE", }, latitude: 0, longitude: 0, isMap: false, zoomSize: 15, markers: [], polyline: [{ points: [], width: 8, arrowLine: true, color: '#00AF99' // strokeWidth: 2, // strokeColor: '#00AF99', // fillColor: '#00AF99' }, ], polygons: [], cardId: '001区域', orderId: '', orderInfo: {}, loading: false, showtk: false, show: false, _mapContext: null, showpark: true, showck: false, money: '', areaNum: 1, showload: false, showfzhc: false, showgj: false, deviceInfos: {}, dispatchFee: 0, manageFee: 0, ridingFee: 0, appointmentFee: 0, } }, created() { this._mapContext = uni.createMapContext("map", this); //map为map组件id }, mounted() { // this.onRegionChange(); }, onLoad(e) { this.orderId = e.id this.getOrderDetail() // this.getParking() }, // onReady() { // // 确保地图组件已加载完成 // console.log(this._mapContext, 'this._mapContext'); // this._mapContext.addGroundOverlay({ // id: 11, // src: `https://lxnapi.ccttiot.com/bike/img/static/uXRz2sbToNsqckQQjnLo`, // 手绘地图素材路径 // bounds: { // southwest: { // 左下角 GPS // longitude: 116.392133, // latitude: 39.912931, // }, // northeast: { // 右上角 GPS // longitude: 116.402022, // latitude: 39.923246, // }, // }, // // visible: true, // zIndex: 1000, // success: (res) => { // console.log("显示成功", res); // }, // fail: (e) => { // console.log("显示失败", e); // }, // }); // // this.getParking(); // }, components: { }, methods: { backpass() { this.showload = true uni.showLoading({ title: '加载中...' }) let data = { orderNo: this.orderId, "status": "5" } this.$u.put("/appVerify/order/damaged", data).then((res) => { this.showload = false if (res.code === 200) { uni.hideLoading() // 处理接口返回的数据,将边界数据转换为地图组件需要的折线结构 this.getOrderDetail() uni.showToast({ title: '操作成功', icon: 'none', duration: 2000 }); } else { uni.showToast({ title: res.msg, icon: 'none', duration: 2000 }); } }).catch(error => { console.error("Error fetching area data:", error); }); }, status() { // if (this.deviceInfos.onlineStatus == 0) { // return '离线' // } else { // } if (this.deviceInfos.status == 0) { return '仓库中' } else if (this.deviceInfos.status == 1) { return '待租' } else if (this.deviceInfos.status == 2) { return '预约中' } else if (this.deviceInfos.status == 3) { return '骑行中' } else if (this.deviceInfos.status == 4) { return '临时锁车中' } else if (this.deviceInfos.status == 6) { return '调度中' } else if (this.deviceInfos.status == 8) { return '下线' } }, deviceInfo() { this.$u.get('/app/device/info?sn=' + this.orderInfo.sn).then((res) => { console.log(res, 'rererer'); if (res.code === 200) { this.deviceInfos = res.data this.$forceUpdate() } else { uni.showToast({ title: res.msg, icon: 'none', duration: 2000 }); } }) }, // 开锁 openBtn() { uni.showLoading({ title: '加载中...' }) this.$u.post('/appVerify/admin/unlocking?sn=' + this.orderInfo.sn).then((res) => { if (res.code == 200) { // 处理接口返回的数据,将边界数据转换为地图组件需要的折线结构 uni.showToast({ title: '操作成功', icon: 'none', duration: 2000 }); } else { uni.showToast({ title: res.msg, icon: 'none', duration: 2000 }); } }).catch(error => { console.error("Error fetching area data:", error); }); }, // 关锁 closeBtn() { uni.showLoading({ title: '加载中...' }) this.$u.post('/appVerify/admin/lock?sn=' + this.orderInfo.sn).then((res) => { if (res.code == 200) { // 处理接口返回的数据,将边界数据转换为地图组件需要的折线结构 uni.showToast({ title: '操作成功', icon: 'none', duration: 2000 }); } else { uni.showToast({ title: res.msg, icon: 'none', duration: 2000 }); } }).catch(error => { console.error("Error fetching area data:", error); }); }, // 押金抵扣 yjdkBtn() { uni.showLoading({ title: '加载中' }) let data = { orderNo: this.orderInfo.orderNo, } this.$u.post('/appVerify/order/deduction', data).then((res) => { if (res.code === 200) { // 处理接口返回的数据,将边界数据转换为地图组件需要的折线结构 uni.showToast({ title: '操作成功', icon: 'none', duration: 2000 }); this.getOrderDetail() } else { uni.showToast({ title: res.msg, icon: 'none', duration: 2000 }); } }).catch(error => { console.error("Error fetching area data:", error); }); }, // 改价 changeMoney() { uni.showLoading({ title: '加载中' }) let data = { orderNo: this.orderInfo.orderNo, dispatchFee: this.orderInfo.dispatchFee, manageFee: this.orderInfo.manageFee, ridingFee: this.orderInfo.ridingFee, appointmentFee: this.orderInfo.appointmentFee, } this.$u.put('/appVerify/order/editPrice', data).then((res) => { if (res.code === 200) { // 处理接口返回的数据,将边界数据转换为地图组件需要的折线结构 this.showgj = false this.getOrderDetail() uni.showToast({ title: '操作成功', icon: 'none', duration: 2000 }); } else { uni.showToast({ title: res.msg, icon: 'none', duration: 2000 }); } }).catch(error => { console.error("Error fetching area data:", error); }); }, closefz() { // this.show = false this.showfzhc = false // this.orderInfo = {} }, backDevice() { uni.showLoading({ title: '加载中' }) this.$u.post('/appVerify/device/return?orderNo=' + this.orderInfo.orderNo + '&returnType=2').then(( res) => { if (res.code === 200) { // 处理接口返回的数据,将边界数据转换为地图组件需要的折线结构 // this.show = false this.showfzhc = false this.getOrderDetail() uni.showToast({ title: '操作成功', icon: 'none', duration: 2000 }); } else { uni.showToast({ title: res.msg, icon: 'none', duration: 2000 }); } }).catch(error => { console.error("Error fetching area data:", error); }); }, ckmoney() { uni.showLoading({ title: '加载中...' }) this.showload = true if (this.money != '') { let data = { orderNo: this.orderId, status: "7", deductionAmount: this.money, audioFiles: '' } this.$u.put("/appVerify/order/submitAudit", data).then((res) => { this.showload = false uni.hideLoading() if (res.code === 200) { // 处理接口返回的数据,将边界数据转换为地图组件需要的折线结构 this.getOrderDetail() this.showck = false uni.showToast({ title: '操作成功', icon: 'none', duration: 2000 }); } else { uni.showToast({ title: res.msg, icon: 'none', duration: 2000 }); } }).catch(error => { this.showck = false console.error("Error fetching area data:", error); }); } else { uni.showToast({ title: '扣款金额不能为空', icon: 'none', duration: 2000 }); } }, unpass() { this.showload = true uni.showLoading({ title: '加载中...' }) let data = { orderNo: this.orderId, "status": "6" } this.$u.put("/appVerify/order/damaged", data).then((res) => { this.showload = false if (res.code === 200) { uni.hideLoading() // 处理接口返回的数据,将边界数据转换为地图组件需要的折线结构 this.getOrderDetail() uni.showToast({ title: '操作成功', icon: 'none', duration: 2000 }); } else { uni.showToast({ title: res.msg, icon: 'none', duration: 2000 }); } }).catch(error => { console.error("Error fetching area data:", error); }); }, pass() { this.showload = true uni.showLoading({ title: '加载中...' }) this.$u.post("/appVerify/passAudit/" + this.orderId).then((res) => { uni.hideLoading() this.showload = false if (res.code === 200) { // 处理接口返回的数据,将边界数据转换为地图组件需要的折线结构 this.getOrderDetail() uni.showToast({ title: '操作成功', icon: 'none', duration: 2000 }); } else { uni.showToast({ title: res.msg, icon: 'none', duration: 2000 }); } }).catch(error => { console.error("Error fetching area data:", error); }); }, handleFullscreenChange(e) { // 这里可以通过 e.detail 来获取全屏状态的信息(如果有的话) // 但请注意,不同平台和浏览器可能返回的信息不同 console.log('全屏状态变化', e.detail); if (e.detail.fullScreen) { this.showpark = false } else { this.showpark = true } }, displayAmount(amount) { return amount ? amount : '--'; }, backfee() { this.show = true this.showtk = true }, closetk() { this.show = false this.showtk = false // this.orderInfo = {} }, toggleIconAndCallout() { this.showIconAndCallout = !this.showIconAndCallout; if (this.showIconAndCallout) { const newMarkers = []; this.parkingList.forEach(item => { newMarkers.push({ id: parseFloat(item.parkingId), 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/u53BAQcFIX3vxsCzEZ7t' : ' https://lxnapi.ccttiot.com/bike/img/static/uDNY5Q4zOiZTCBTA2Jdq', callout: { content: item.parkingName, color: '#ffffff', fontSize: 14, borderRadius: 10, bgColor: item.type == 1 ? '#3A7EDB' : item.type == 2 ? '#FFC107' : '#FF473E', padding: 6, display: 'ALWAYS' }, isCalloutVisible: true // 添加标记 }); }); this.$set(this, 'markers', [...this.markers, ...newMarkers]); } else { // 过滤掉所有气泡显示的标记 this.$set(this, 'markers', this.markers.filter(marker => !marker.isCalloutVisible)); } }, callPhone() { uni.makePhoneCall({ phoneNumber: this.orderInfo.phonenumber }) }, computedList(item) { if (item.status == 0 || item.status == 2) { const createTime = new Date(item.createTime); const payTime = Date.now(); const timeDifference = Math.abs(createTime - payTime); const hours = Math.floor(timeDifference / (1000 * 60 * 60)); const minutes = Math.floor((timeDifference % (1000 * 60 * 60)) / (1000 * 60)); const seconds = Math.floor((timeDifference % (1000 * 60)) / 1000); let result = ''; if (hours > 0) { result += `${hours}小时`; } if (minutes > 0 || hours > 0) { // 显示分钟条件:有小时或者有分钟 result += `${minutes}分`; } // result += `${seconds}秒`; // 始终显示秒 return result; } else { const createTime = new Date(item.createTime); const payTime = new Date(item.returnTime); const timeDifference = Math.abs(createTime - payTime); const hours = Math.floor(timeDifference / (1000 * 60 * 60)); const minutes = Math.floor((timeDifference % (1000 * 60 * 60)) / (1000 * 60)); const seconds = Math.floor((timeDifference % (1000 * 60)) / 1000); let result = ''; if (hours > 0) { result += `${hours}小时`; } if (minutes > 0 || hours > 0) { // 显示分钟条件:有小时或者有分钟 result += `${minutes}分`; } // result += `${seconds}秒`; // 始终显示秒 return result; } }, convertBoundaryToPolyline(boundary) { if (!boundary) return null; const points = JSON.parse(boundary).map(coord => ({ latitude: coord[1], longitude: coord[0] })); 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; } const points = coords.map(coord => ({ latitude: coord[1], longitude: coord[0] })); return { points: points, fillColor: "#FFF5D640", //填充颜色 strokeColor: "#FFC107", //描边颜色 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; } const points = coords.map(coord => ({ latitude: coord[1], longitude: coord[0] })); return { points: points, fillColor: "#FFD1CF40", //填充颜色 strokeColor: "#FF473E", //描边颜色 strokeWidth: 2, //描边宽度 zIndex: 1, //层级 }; }).filter(polyline => polyline !== null); // 过滤掉无效的折线数据 } }, getParking() { // 发送请求获取数据 let data = { areaId: this.orderInfo.areaId } this.$u.get('/app/parking/list?', data).then((res) => { if (res.code === 200) { // 处理接口返回的数据 const type1Data = []; const type2Data = []; const type3Data = []; res.rows.forEach(row => { if (row.type == 1) { type1Data.push(row); } else if (row.type == 2) { type2Data.push(row); } else if (row.type == 3) { type3Data.push(row); } }); 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.polygons = this.polygons.concat(polylines2); this.polygons = this.polygons.concat(polylines1); this.polygons = this.polygons.concat(polylines); // console.log(this.polyline); this.parkingList = res.rows } }).catch(error => { console.error("Error fetching parking data:", error); }); }, getArea() { // 发送请求获取数据 let id = this.orderInfo.areaId this.$u.get("/app/area/" + id).then((res) => { if (res.code === 200) { // 处理接口返回的数据,将边界数据转换为地图组件需要的折线结构 const polylines = this.convertBoundaryToPolyline(res.data.boundaryStr) // 更新折线数据 this.polygons.push(polylines) this.getParking() // console.log(this.polyline); } }).catch(error => { console.error("Error fetching area data:", error); }); }, status() { if (this.orderInfo != '') { if (this.orderInfo.status == 0) { return '预约中' } else if (this.orderInfo.status == 1) { return '取消预约' } else if (this.orderInfo.status == 2) { return '骑行中' } else if (this.orderInfo.status == 3) { return '骑行结束' } else if (this.orderInfo.status == 4) { return '订单完成' } } }, backMoney() { let data = { orderNo: this.orderInfo.orderNo, dispatchFee: this.dispatchFee, manageFee: this.manageFee, ridingFee: this.ridingFee, appointmentFee: this.appointmentFee, // reason: this.reason } if ( data.dispatchFee > this.orderInfo.dispatchFee || data.manageFee > this.orderInfo.manageFee || data.ridingFee > this.orderInfo.ridingFee || data.appointmentFee > this.orderInfo.appointmentFee ) { uni.showToast({ title: '退款金额不能大于实际支付金额', icon: 'none', duration: 2000 }); return; // 阻止请求的发送 } this.$u.put('/appVerify/order/refund', data).then((res) => { if (res.code === 200) { // 处理接口返回的数据,将边界数据转换为地图组件需要的折线结构 this.show = false this.showtk = false this.getOrderDetail() } else { uni.showToast({ title: res.msg, icon: 'none', duration: 2000 }); } }).catch(error => { console.error("Error fetching area data:", error); }); }, getOrderDetail() { this.$u.get('/appVerify/order/' + this.orderId).then((res) => { if (res.code === 200) { // 处理接口返回的数据,将边界数据转换为地图组件需要的折线结构 this.orderInfo = res.data this.areaNum = this.areaNum + 1 if (this.areaNum != 0) { this.getArea() } this.deviceInfo() this.loading = true this.latitude = parseFloat(this.orderInfo.latitude) this.longitude = parseFloat(this.orderInfo.longitude) this.getpolyline() // this.polyline[0].points = JSON.parse(res.data.tripRouteStr).map(coord => ({ // latitude: coord[1], // longitude: coord[0] // })); // let abb; // try { // abb = JSON.parse(res.data.tripRouteStr); // } catch (error) { // console.error("Error parsing tripRouteStr:", error); // return; // } // if (abb.length > 2) { // this.latitude = parseFloat(abb[0][1]); // this.longitude = parseFloat(abb[0][0]); // this.polyline[0].points = abb.map(coord => ({ // latitude: coord[1], // longitude: coord[0] // })); // this.markers.push({ // id: 0, // latitude: abb[0][1], // longitude: abb[0][0], // width: 25, // height: 38, // iconPath: 'https://lxnapi.ccttiot.com/bike/img/static/u06paUGiHLvL08Pw7BGr' // }, { // id: 1, // latitude: abb[abb.length - 1][1], // longitude: abb[abb.length - 1][0], // width: 25, // height: 38, // iconPath: 'https://lxnapi.ccttiot.com/bike/img/static/uwpAj9vYtPRmhtTOtflx' // }); // } } // console.log(points,''); // this.polyline[0].points=points }).catch(error => { console.error("Error fetching area data:", error); }); }, getpolyline() { this.$u.post("/system/device/trajectoryByOrderNo?orderNo=" + this.orderId).then((res) => { if (res.code === 200) { this.polyline[0].points = JSON.parse(res.data).map(coord => ({ latitude: coord[1], longitude: coord[0] })); let abb; try { abb = JSON.parse(res.data); console.log(abb,'abbbb'); } catch (error) { console.error("Error parsing tripRouteStr:", error); return; } if (abb.length > 2) { this.latitude = parseFloat(abb[0][1]); this.longitude = parseFloat(abb[0][0]); this.polyline[0].points = abb.map(coord => ({ latitude: coord[1], longitude: coord[0] })); this.markers.push({ id: 0, latitude: abb[0][1], longitude: abb[0][0], width: 25, height: 38, iconPath: 'https://lxnapi.ccttiot.com/bike/img/static/u06paUGiHLvL08Pw7BGr' }, { id: 1, latitude: abb[abb.length - 1][1], longitude: abb[abb.length - 1][0], width: 25, height: 38, iconPath: 'https://lxnapi.ccttiot.com/bike/img/static/uwpAj9vYtPRmhtTOtflx' }); } } }).catch(error => { console.error("Error fetching area data:", error); }); } } } </script> <style lang="scss"> page { overflow-x: hidden; background-color: #F3F3F3; } .page { padding-bottom: 200rpx; width: 750rpx; .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; // padding-bottom: 40rpx; .btn:nth-child(4n) { margin-right: 0; } .btn { margin-top: 10rpx; margin-right: 18rpx; margin-bottom: 30rpx; display: flex; align-items: center; justify-content: center; width: 164rpx; height: 66rpx; background: #E2F2FF; border-radius: 0rpx 0rpx 0rpx 0rpx; border: 2rpx solid #4C97E7; font-weight: 400; font-size: 28rpx; color: #3D3D3D; } } .tip_box1 { position: fixed; left: 72rpx; top: 628rpx; width: 610rpx; // height: 282rpx; background: #FFFFFF; border-radius: 30rpx 30rpx 30rpx 30rpx; z-index: 110; padding-bottom: 100rpx; .top1 { 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; } } .bot1 { 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; } } } .tip_box { position: fixed; left: 72rpx; top: 628rpx; width: 610rpx; // height: 282rpx; background: #FFFFFF; border-radius: 30rpx 30rpx 30rpx 30rpx; z-index: 110; padding-bottom: 100rpx; .top { padding: 52rpx 38rpx 42rpx 36rpx; .ipt_box { margin-top: 22rpx; display: flex; flex-wrap: nowrap; align-items: center; .text { width: 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; } } } .map { position: relative; width: 750rpx; height: 752rpx; .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: 0; .img { width: 82rpx; height: 82rpx; } } } .info_card { background: #FFFFFF; .info_tit { display: flex; flex-wrap: nowrap; padding: 22rpx 28rpx; font-weight: 600; font-size: 32rpx; color: #3D3D3D; .money { margin-left: auto; font-weight: 500; font-size: 32rpx; color: #4C97E7; } .vadio_type { margin-left: auto; padding: 5rpx 34rpx; background: #FFFAE6; border-radius: 8rpx 8rpx 8rpx 8rpx; font-weight: 400; font-size: 28rpx; color: #FFCC00; } } .lines { width: 750rpx; // height: 2rpx; border-bottom: 2rpx solid #E7E7E7; } .vadio_box { padding: 26rpx 28rpx; .vadio_li { display: flex; flex-wrap: nowrap; // justify-content: space-between; .vadio_info { margin-left: auto; font-weight: 400; font-size: 24rpx; color: #979797; } .btn_box { display: flex; flex-wrap: nowrap; align-items: center; margin-left: auto; .vadio_btn { margin-left: 10rpx; padding: 6rpx 44rpx; background: #4C97E7; border-radius: 8rpx 8rpx 8rpx 8rpx; font-weight: 400; font-size: 32rpx; color: #FEFFFE; } } } } .cont { padding: 26rpx 28rpx; .info_li { display: flex; flex-wrap: nowrap; font-weight: 400; font-size: 28rpx; color: #808080; .text { width: 70%; white-space: nowrap; /* 禁止换行 */ overflow: hidden; /* 超出部分隐藏 */ text-overflow: ellipsis; } span { color: #3D3D3D; } line-height: 48rpx; .half_infoli { width: 50%; font-weight: 400; font-size: 28rpx; color: #808080; span { color: #3D3D3D; } } } .info_lis { width: 90%; display: inline-block; // flex-wrap: nowrap; font-weight: 400; font-size: 28rpx; color: #808080; white-space: nowrap; /* 禁止换行 */ overflow: hidden; /* 超出部分隐藏 */ text-overflow: ellipsis; .text { display: inline; // width: 70%; // white-space: nowrap; // /* 禁止换行 */ // overflow: hidden; // /* 超出部分隐藏 */ // text-overflow: ellipsis; } span { color: #3D3D3D; } line-height: 48rpx; .half_infoli { width: 50%; font-weight: 400; font-size: 28rpx; color: #808080; span { color: #3D3D3D; } } } } } .bot { position: fixed; bottom: 0; width: 750rpx; height: 184rpx; background: #FFFFFF; box-shadow: 0rpx 10rpx 64rpx 0rpx rgba(0, 0, 0, 0.08), 0rpx 10rpx 64rpx 0rpx rgba(0, 0, 0, 0.08); border-radius: 0rpx 0rpx 0rpx 0rpx; .btn { margin: 46rpx auto; display: flex; align-items: center; justify-content: center; width: 680rpx; height: 90rpx; background: #4C97E7; border-radius: 54rpx 54rpx 54rpx 54rpx; font-weight: 500; font-size: 40rpx; color: #FFFFFF; } } } </style>