flinfo/dc-App/pages/busNavigation/busNavigation.nvue
2025-03-10 15:39:19 +08:00

816 lines
28 KiB
Plaintext

<template>
<view class="container">
<map id="map" :show-compass="true" :include-points="points" :polyline="polyline" lang="en"
:longitude="center.longitude" :latitude="center.latitude"
:markers="markers" bindmarkertap="handleMarkerTap" show-location
:style="'width:' + windowWidth + 'px;' + 'height:'+ '540rpx;' ">
</map>
<image src="/static/chatImg/fy.png" @click="changeLan" mode="" class="fy_icon"></image>
<view class="contenr_" v-if="lang=='en'">
<view class="contenr_top">
<!-- 顶部 全程 时间-->
<view class="c_t_box">
<view>
<text class="text_1">{{ Number.parseInt(allData.duration / 60) || 0 }}min</text>
</view>
<view class="ds_">
<text class="text_2">walk distance</text>
<text class="text_1">
{{ allData.walkingDistance ? Number.parseFloat(allData.walkingDistance / 1000).toFixed(2) : 0 }}km
</text>
</view>
</view>
<!-- -->
<view class="c_c_box">
<view class="ds_" style="flex-wrap: wrap;">
<view v-for="(item,index) in allData.segments" :key="index">
<view class="segment-item" :style="{ flexDirection: 'row', alignItems: 'center' }">
<image src="/static/imgs/icon2.png" style="height: 48rpx; width: 48rpx; flex-shrink: 0;"
v-if="item.walking"></image>
<view class="c_c_title" :style="'background-color:' + colorList[index] "
v-for="(it,idx) in item.bus" :key="idx">
<text class="text_line">{{ it.enName.split('(')[0] || '' }}</text>
</view>
</view>
</view>
</view>
</view>
<!-- 下方注释 -->
<view class="ds_">
<text class="text_4">all cost</text>
<text class="text_4">¥{{ allData.cost == '[]' ? 0 : allData.cost }}</text>
</view>
</view>
<scroll-view scroll-y :show-scrollbar="false" @scrolltoupper="upper" @scrolltolower="lower"
:refresher-enabled="true" style="height: 620rpx;" lower-threshold="50">
<view class="contenr_bottom">
<view class="c_b_title">
<image src="/static/imgs/icon3.png"
style="height: 40rpx;width: 40rpx;margin-right: 20rpx;"></image>
<text class="text_1">My Location</text>
</view>
</view>
<!-- -- 我需要把循环包在这 这两块一起循环 下面的循环不需要 -->
<view class="c_box" v-for="(item,index) in allData.segments" :key="index">
<view class="c_b_box" v-if="item.walking">
<view class="ds_">
<view class="qiu_"></view>
<text class="text_4">Walk {{ item.walking.distance }} meters
({{ Number.parseInt(item.walking.duration / 60) }} minutes)
</text>
</view>
<view class="b_walk">
<text class="text_3" @click="walkLine(item.walking)">Walk</text>
</view>
</view>
<view class="contenr_bottom_d" v-if="item.bus&&item.bus.length>0" v-for="(it) in item.bus">
<view class="bz_left">
<view class="l_t_i" :style="'background-color:' + colorList[index] ">
<image src="/static/imgs/icon4.png" style="height: 32rpx;width: 32rpx;"></image>
</view>
<view class="l_t_z" :style="'background-color:' + colorList[index] "></view>
<view class="l_t_i" :style="'background-color:' + colorList[index] "></view>
</view>
<view class="bz_right">
<text class="text_1" style="margin-bottom: 32rpx;">{{ it.departureStop.enName }} station
</text>
<view class="ds_">
<view class="bz_icon bz_width" :style="'background-color:' + colorList[index] ">
<text class="text_3">{{ it.enName }}</text>
</view>
</view>
<view class="botton_size">
<text class="text_4">{{ it.viaStops.length }} station
({{ Number.parseInt(it.duration / 60) }} min)
</text>
</view>
<text class="text_1" style="margin-top: 39rpx;">{{ it.arrivalStop.enName }} station</text>
</view>
</view>
</view>
<view class="contenr_bottom">
<view class="c_b_title">
<image src="/static/imgs/end.png"
style="height: 50rpx;width: 45rpx;margin-right: 20rpx;"></image>
<text class="text_1">destination</text>
</view>
</view>
</scroll-view>
</view>
<view class="contenr_" v-else>
<view class="contenr_top">
<!-- 顶部 全程 时间-->
<view class="c_t_box">
<view>
<text class="text_1">{{ Number.parseInt(allData.duration / 60) || 0 }}分钟</text>
</view>
<view class="ds_">
<text class="text_2">步行距离</text>
<text class="text_1">
{{ allData.walkingDistance ? Number.parseFloat(allData.walkingDistance / 1000).toFixed(2) : 0 }}km
</text>
</view>
</view>
<!-- -->
<view class="c_c_box">
<view class="ds_" style="flex-wrap: wrap;">
<view v-for="(item,index) in allData.segments">
<view class="segment-item" :style="{ flexDirection: 'row', alignItems: 'center' }">
<image src="/static/imgs/icon2.png" style="height: 48rpx;width: 48rpx; flex-shrink: 0"
v-if="item.walking"></image>
<view class="c_c_title" :style="'background-color:' + colorList[index] "
v-for="(it,idx) in item.bus" :key="idx">
<text class="text_line">{{ it.name.split('(')[0] || '' }}</text>
</view>
</view>
</view>
</view>
</view>
<!-- 下方注释 -->
<view class="ds_">
<text class="text_4">总花费</text>
<text class="text_4">¥{{ allData.cost }}</text>
</view>
</view>
<scroll-view scroll-y :show-scrollbar="false" @scrolltoupper="upper" @scrolltolower="lower"
:refresher-enabled="true" style="height: 620rpx;" lower-threshold="50">
<view class="contenr_bottom">
<view class="c_b_title">
<image src="/static/imgs/icon3.png"
style="height: 40rpx;width: 40rpx;margin-right: 20rpx;"></image>
<text class="text_1">我的位置</text>
</view>
</view>
<!-- -- 我需要把循环包在这 这两块一起循环 下面的循环不需要 -->
<view class="c_box" v-for="(item,index) in allData.segments" :key="index">
<view class="c_b_box" v-if="item.walking">
<view class="ds_">
<view class="qiu_"></view>
<text class="text_4">步行 {{ item.walking.distance }} 米
({{ Number.parseInt(item.walking.duration / 60) }} 分钟)
</text>
</view>
<view class="b_walk">
<text class="text_3" @click="walkLine(item.walking)">导航</text>
</view>
</view>
<view class="contenr_bottom_d" v-if="item.bus&&item.bus.length>0" v-for="(it) in item.bus">
<view class="bz_left">
<view class="l_t_i" :style="'background-color:' + colorList[index] ">
<image src="/static/imgs/icon4.png" style="height: 32rpx;width: 32rpx;"></image>
</view>
<view class="l_t_z" :style="'background-color:' + colorList[index] "></view>
<view class="l_t_i" :style="'background-color:' + colorList[index] "></view>
</view>
<view class="bz_right">
<text class="text_1" style="margin-bottom: 32rpx;">{{ it.departureStop.name }} 站点</text>
<view class="ds_">
<view class="bz_icon bz_width" :style="'background-color:' + colorList[index]">
<text class="text_3">{{ it.name }}</text>
</view>
</view>
<view class="botton_size">
<text class="text_4">{{ it.viaStops.length }} 站
({{ Number.parseInt(it.duration / 60) }} 分钟)
</text>
</view>
<text class="text_1" style="margin-top: 39rpx;">{{ it.arrivalStop.name }} 站点</text>
</view>
</view>
</view>
<view class="contenr_bottom">
<view class="c_b_title">
<image src="/static/imgs/end.png"
style="height: 50rpx;width: 45rpx;margin-right: 20rpx;"></image>
<text class="text_1">终点</text>
</view>
</view>
</scroll-view>
</view>
</view>
</template>
<script>
import request from '../../utils/request'
import config from '@/config'
export default {
data() {
return {
lang: 'en',
translateY: 0,
longPressTimer: null, // 长按定时器
isDragging: false, // 是否正在拖动
colorList: [
"#f9d402",
"#009bc2",
"#000000",
"#c34100",
"#006a00",
],
//打车预估路线
polyline: [],
center: {
latitude: null,
longitude: null
},
mapContext: null,
controls: [],
markers: [],
startPoint: [],
endPoint: [],
// 接口返回
container: {},
routeTitle: '',
distance: 0,
duration: 0,
cost: 0,
points: [],
allData: {}
}
},
onLoad(option) {
this.startPoint = option.startPoint.split(',')
this.endPoint = option.endPoint.split(',')
this.startExecution()
this.getLatLon()
},
mounted() {
// 设置初始的触摸起始点坐标,用于计算移动距离
this.startY = 0;
},
computed: {
windowHeight() {
return uni.getSystemInfoSync().windowHeight / 3;
},
windowWidth() {
return uni.getSystemInfoSync().windowWidth;
}
},
methods: {
changeLan() {
if (this.lang == 'en') {
this.lang = 'zh'
} else {
this.lang = 'en'
}
},
getLatLon() {
let _this = this;
uni.getLocation({
// 谷歌使用wgs84 其他使用gcj02
type: 'gcj02', // 使用国测局坐标系
geocode: true,
success: function (res) {
_this.center.longitude = res.longitude
_this.center.latitude = res.latitude
},
fail: function (err) {
console.log('获取位置信息失败: ' + err.errMsg);
uni.setStorageSync("isGetAddress", false)
}
});
},
walkLine(data) {
let endInfo = {}
endInfo.location = [data.endLocationLng, data.endLocationLat]
uni.getLocation({
// 谷歌使用wgs84 其他使用gcj02
type: 'gcj02', // 使用国测局坐标系
geocode: true,
success: function (res) {
let staInfo = {}
staInfo.location = [res.longitude, res.latitude]
uni.navigateTo({
url: '/pages/index/PedestrianNavigation?startPoint=' + staInfo
.location +
'&endPoint=' + endInfo.location
})
},
fail: function (err) {
uni.showToast({
title: 'Failed to get location',
icon: 'none'
})
}
});
},
upper(e) {
console.log('Scroll to top');
},
lower(e) {
setTimeout(() => {
this.items.push(...Array.from({length: 10}, (_, i) =>
'New Item ' + (this.items.length + i + 1)
));
if (this.items.length >= 50) this.hasMore = false;
}, 1000);
},
startExecution() {
let that = this
uni.showLoading({
title: 'Loading...'
});
request({
url: 'walkApi/getIntegratedRouteInfo',
method: 'post',
data: {
startLocationLng: this.startPoint[0],
startLocationLat: this.startPoint[1],
endLocationLng: this.endPoint[0],
endLocationLat: this.endPoint[1],
}
}).then(res => {
that.allData = res.data
that.duration = res.data.duration / 60
that.distance = res.data.walkingDistance / 1000
that.cost = res.data.cost
let segments = res.data.segments
that.points = []
//先进行步行的线路展示
that.polyline = []
for (var item of segments) {
let walking = item.walking
if (walking && walking.polyline) {
let item = {}
item.color = '#787878'
item.points = walking.polyline
item.width = 11
item.dottedLine = true
that.polyline.push(item)
//that.points=that.points.concat(item.points)
}
}
//再进行公交的线路展示
for (var item of segments) {
let bus = item.bus
if (bus && bus.length > 0) {
for (var busIt of bus) {
let item = {}
item.color = '#5500ff'
item.points = busIt.polyline
item.width = 18
item.arrowLine = true
that.polyline.push(item)
//that.points=that.points.concat(item.points)
}
}
}
//进行标记点处理
that.markers = []
//起点和终点处理
that.markers.push({
id: 1,
label: {
content: 'Start Point',
fontSize: 8,
color: '#145e07'
},
iconPath: config.startStopIcon,
latitude: this.startPoint[1],
longitude: this.startPoint[0],
width: 20,
height: 20,
})
that.markers.push({
id: 2,
label: {
content: 'End Point',
fontSize: 8,
color: '#145e07'
},
iconPath: config.endStopIcon,
latitude: this.endPoint[1],
longitude: this.endPoint[0],
width: 20,
height: 20,
})
let i = 1;
for (var item of segments) {
let bus = item.bus
if (bus && bus.length > 0) {
for (var busIt of bus) {
//途径上车点
that.markers.push({
id: busIt.departureStop.id,
label: {
content: busIt.enName,
fontSize: 8,
color: '#145e07'
},
iconPath: config.varStop,
latitude: busIt.departureStop.locationLat,
longitude: busIt.departureStop.locationLng,
width: 20,
height: 20,
})
that.points.push({
latitude: that.offsetLatitude1(busIt.departureStop.locationLat, 30000),
longitude: busIt.departureStop.locationLng
})
that.points.push({
latitude: that.offsetLatitude2(busIt.departureStop.locationLat, 30000),
longitude: busIt.departureStop.locationLng
})
that.points.push({
latitude: busIt.departureStop.locationLat,
longitude: that.offsetLongitude1(busIt.departureStop.locationLng, 30000)
})
that.points.push({
latitude: busIt.departureStop.locationLat,
longitude: that.offsetLongitude2(busIt.departureStop.locationLng, 30000)
})
that.points.push({
latitude: that.offsetLatitude1(busIt.arrivalStop.locationLat, 30000),
longitude: busIt.arrivalStop.locationLng
})
that.points.push({
latitude: that.offsetLatitude2(busIt.arrivalStop.locationLat, 30000),
longitude: busIt.arrivalStop.locationLng
})
that.points.push({
latitude: busIt.arrivalStop.locationLat,
longitude: that.offsetLongitude1(busIt.arrivalStop.locationLng, 30000)
})
that.points.push({
latitude: busIt.arrivalStop.locationLat,
longitude: that.offsetLongitude2(busIt.arrivalStop.locationLng, 30000)
})
}
}
}
console.log(that.points);
}).finally(() => {
uni.hideLoading()
})
},
offsetLongitude1(oldValue, num) {
oldValue = Number.parseFloat(oldValue)
const R = 6371000; // 地球半径,单位为米
const latRad = oldValue * Math.PI / 180;
const deltaLon = num / (R * Math.cos(latRad));
return oldValue + deltaLon;
},
offsetLongitude2(oldValue, num) {
oldValue = Number.parseFloat(oldValue)
const R = 6371000; // 地球半径,单位为米
const latRad = oldValue * Math.PI / 180;
const deltaLon = num / (R * Math.cos(latRad));
return oldValue - deltaLon;
},
offsetLatitude1(oldValue, num) {
oldValue = Number.parseFloat(oldValue)
const R = 6371000; // 地球半径,单位为米
const deltaLat = num / R;
return oldValue + deltaLat;
},
offsetLatitude2(oldValue, num) {
oldValue = Number.parseFloat(oldValue)
const R = 6371000; // 地球半径,单位为米
const deltaLat = num / R;
return oldValue - deltaLat;
},
goback() {
uni.navigateBack()
},
beforeDestroy() {
if (this.timer) {
clearInterval(this.timer);
this.timer = null;
}
},
// 对于 TabBar 类型页面还需要额外关注 onHide 钩子
onHide() {
if (this.timer) {
clearInterval(this.timer);
this.timer = null;
}
}
}
}
</script>
<style scoped lang="scss">
.container {
width: 750rpx;
flex: 1;
}
.ds_ {
flex-direction: row;
align-items: center;
}
.bottom_pr {
min-height: 160rpx;
position: fixed;
bottom: 0rpx;
width: 750rpx;
background: #fff;
box-shadow: 0rpx -2rpx 3rpx 0rpx rgba(50, 113, 79, 0.3);
overflow: hidden;
box-sizing: border-box;
padding: 30rpx;
flex-direction: row;
align-items: center;
justify-content: space-between;
}
.draggable {
width: 100px;
height: 100px;
background-color: blue;
color: white;
display: flex;
justify-content: center;
align-items: center;
z-index: 99999;
}
.bz_icon {
box-sizing: border-box;
padding: 18rpx 18rpx;
border-radius: 8rpx;
display: flex;
justify-content: center;
align-items: center;
margin-right: 20rpx;
}
.b_walk {
width: 80rpx;
height: 40rpx;
background: #32714F;
border-radius: 32rpx 32rpx 32rpx 32rpx;
display: flex;
justify-content: center;
align-items: center;
}
.button_ {
width: 686rpx;
height: 96rpx;
background: #32714F;
border-radius: 12rpx 12rpx 12rpx 12rpx;
display: flex;
justify-content: center;
align-items: center;
z-index: 99999;
}
.qiu_ {
width: 16rpx;
height: 16rpx;
border-radius: 50%;
background: #e8e8e8;
margin-right: 32rpx;
}
.c_b_box {
margin: 10rpx 0rpx;
flex-direction: row;
align-items: center;
justify-content: space-between;
}
.c_b_title {
flex-direction: row;
align-items: center;
}
.button_text {
color: #FFFFFF;
font-size: 38rpx;
}
.contenr_ {
min-height: 160rpx;
position: fixed;
bottom: 0rpx;
width: 750rpx;
background: #fff;
}
.contenr_top {
width: 686rpx;
background: #FFFFFF;
box-shadow: 0rpx 8rpx 20rpx 0rpx rgba(0, 0, 0, 0.1);
border-radius: 32rpx 32rpx 32rpx 32rpx;
margin-left: 32rpx;
box-sizing: border-box;
padding: 32rpx 24rpx;
}
.c_t_box {
box-sizing: border-box;
padding-bottom: 16rpx;
border-bottom: 2rpx solid #F2F2F2;;
flex-direction: row;
align-items: center;
justify-content: space-between;
margin-bottom: 16rpx;
}
.c_c_box {
margin-bottom: 16rpx;
}
.c_box {
box-sizing: border-box;
padding: 0px 32rpx;
}
.text_1 {
font-size: 30rpx;
color: #333333;
font-weight: 600;
lines: 2;
}
.text_2 {
font-size: 32rpx;
color: #999999;
margin-right: 5px;
}
.text_3 {
font-weight: 500;
font-size: 28rpx;
color: #FFFFFF;
white-space: normal;
word-wrap: break-word;
/* 如果需要强制换行可以添加 */
word-break: break-all;
/* 如果父容器需要限制宽度 */
display: block;
max-width: 100%;
}
.text_line {
font-weight: 500;
font-size: 23rpx;
color: #FFFFFF;
}
.text_4 {
font-weight: 400;
font-size: 24rpx;
color: #999999;
margin-right: 10rpx;
}
.text_5 {
font-size: 24rpx;
color: #333333;
margin-right: 10rpx;
}
.c_c_title {
//width: 260rpx;
width: 100%;
height: 48rpx;
border-radius: 8rpx 8rpx 8rpx 8rpx;
background: #fcd702;
flex-direction: row;
align-items: center;
justify-content: center;
//margin: 5px 5rpx;
margin-left: 2rpx;
}
.contenr_bottom {
// margin-top: 40rpx;
box-sizing: border-box;
padding: 32rpx;
padding-bottom: 0px;
}
.contenr_bottom_d {
box-sizing: border-box;
padding: 11rpx;
padding-top: 0px;
flex-direction: row;
}
.bz_left {
position: relative;
margin-right: 20rpx;
}
.bz_right {
}
.l_t_i {
width: 40rpx;
height: 40rpx;
border-radius: 50%;
flex-direction: row;
align-items: center;
justify-content: center;
border: 1rpx solid #fff;
}
.l_t_z {
width: 24rpx;
height: 240rpx;
margin: 4rpx 0rpx;
margin-left: 8rpx;
border-radius: 16rpx;
}
.po_box {
height: 360rpx;
overflow: auto;
}
.botton_size {
margin-top: 100rpx;
}
.fy_icon {
position: fixed;
right: 15px;
top: 15px;
width: 80rpx;
height: 80rpx;
}
::v-deep .amap-logo {
opacity: 0 !important;
}
::v-deep .amap-copyright {
opacity: 0 !important;
}
::v-deep .BMap_cpyCtrl {
display: none !important;
}
::v-deep .anchorBL {
display: none !important;
}
.bz_width {
width: 50%;
}
.segment-item{
width: 290rpx;
margin: 5rpx 2rpx;
}
</style>