You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

430 lines
12 KiB

6 months ago
<template>
<div class="container">
<div class="main-map">
<div class="left-map">
<div id="container">
<div class="map-btn">
<div class="Driving" @click.stop="Driving">驾车方案</div>
<div class="Ride" @click.stop="Ride">骑行方案</div>
</div>
</div>
<div id="panel"></div>
</div>
<div class="right-info">
<div class="top">
<div class="icon" @click.stop="close">
<el-icon><Close /></el-icon>
</div>
</div>
<div class="price">
<div class="label">订单金额:</div>
<div class="money">{{goodsInfo.otPrice}}</div>
</div>
<div class="address">
<el-icon><LocationFilled /></el-icon>{{ goodsInfo.province }} {{ goodsInfo.city }} {{ goodsInfo.detail
}}{{ goodsInfo.street }}{{ goodsInfo.detail }}
</div>
<div class="receipt-time">
<div class="label">收货时间变化:</div>
<div class="time">{{ goodsInfo.createTime }}</div>
</div>
<div class="receipt-time">
<div class="label">商品类型:</div>
<div class="time">{{ goodsInfo.productType }}</div>
</div>
<div class="receipt-time">
<div class="label">商品总数:</div>
<div class="time">1</div>
</div>
<div class="line"></div>
<div class="address-ipt-box">
<div style="width: 80%; display: flex; flex-direction: column; justify-content: space-between">
<el-input v-model="startingPoint" placeholder="Please input" @keydown="startingPointEvent">
<template #prepend>起点:</template>
</el-input>
<el-input v-model="terminal" placeholder="Please input" @keydown="startingPointEvent">
<template #prepend>终点:</template>
</el-input>
</div>
<div class="btn" @click.stop="viewMap">查看</div>
</div>
<div class="tisp" v-if="TravelOptions">{{ TravelOptions }}{{ routes.time }} {{ routes.distance }}公里</div>
<div class="submit">
<placerBtn :goodsinfo="goodsInfo" />
</div>
</div>
</div>
</div>
</template>
<script lang="ts" setup>
// @ts-ignore
// 这是要被忽略类型检查的代码
window._AMapSecurityConfig = {
securityJsCode: '0c4dce68b8380eb47ad26dbea2cff570',
}
// 地图map
import feedback from '~/utils/feedback'
import AMapLoader from '@amap/amap-jsapi-loader'
import { onMounted, reactive, ref, toRefs, watch, defineEmits, defineProps } from 'vue'
import { Close, LocationFilled } from '@element-plus/icons-vue'
const emits = defineEmits(['closeChange'])
const props = defineProps(['goodsinfo'])
const close = () => {
emits('closeChange', false)
}
const goodsInfo = <any>ref({})
goodsInfo.value = props.goodsinfo
console.log(goodsInfo.value)
const startingPoint = <any>ref('')
startingPoint.value = goodsInfo.value.sendAddressObj.detailAddress
const terminal = <any>ref('')
terminal.value =
goodsInfo.value.province +
goodsInfo.value.city +
goodsInfo.value.detail +
goodsInfo.value.street +
goodsInfo.value.detail
// 37b09e9ef9458d8e987b9351420563ab
let map: any = null
let amap: any = null
let marker: any = null
let driving: any = null
let Riding: any = null
const routes = <any>ref({
time: '',
distance: '',
})
//进行地图初始化
function initMap() {
AMapLoader.load({
key: '37b09e9ef9458d8e987b9351420563ab', // 申请好的Web端开发者Key,首次调用 load 时必填
plugins: ['AMap.AutoComplete', 'AMap.PlaceSearch', 'AMap.Driving', 'AMap.DragRoute', 'AMap.Riding'],
version: '2.0', // 指定要加载的 JSAPI 的版本,缺省时默认为 1.4.15
Loca: {
version: '2.0.0',
},
})
.then((AMap) => {
amap = AMap
map = new AMap.Map('container', {
//设置地图容器id
plugins: ['AMap.AutoComplete', 'AMap.PlaceSearch', 'AMap.Driving', 'AMap.DragRoute', 'AMap.Riding'],
center: [goodsInfo.value.longitude, goodsInfo.value.latitude], //地图中心点
zoom: 10, //地图显示的缩放级别
})
//点标记显示内容
const markerContent = `<div class="custom-content-marker">
<img src="https://a.amap.com/jsapi/static/image/plugin/marker/end.png">
<div class="close-btn" onclick="clearMarker()"></div>
</div>`
const position = new AMap.LngLat(goodsInfo.value.longitude, goodsInfo.value.latitude) //Marker 经纬度
marker = new AMap.Marker({
position: position,
content: markerContent, //将 html 传给 content
offset: new AMap.Pixel(-13, -30), //以 icon 的 [center bottom] 为原点
})
map.add(marker)
// goView() // 获取线路规划
})
.catch((e) => {
console.log(e)
})
}
initMap()
const TravelOptions = <any>ref('')
const goView = () => {
map.remove(marker)
// eslint-disable-next-line no-undef
driving = new amap.Driving({
map: map,
// 驾车路线规划策略,AMap.DrivingPolicy.LEAST_TIME是最快捷模式
policy: amap.DrivingPolicy.LEAST_TIME,
// // panel 指定将结构化的路线详情数据显示的对应的DOM上,传入值需是DOM的ID
// panel: 'panel',
})
// 根据起终点经纬度规划驾车导航路线
driving.search(
// [
// { keyword: goodsInfo.value.sendAddressObj.detailAddress, city: goodsInfo.value.city },
// { keyword: goodsInfo.value.province, city: goodsInfo.value.city },
// ],
// 起点经纬度
[goodsInfo.value.sendAddressObj.longitude, goodsInfo.value.sendAddressObj.latitude],
// 终点经纬度
[goodsInfo.value.longitude, goodsInfo.value.latitude],
function (status: any, result: any) {
// result 即是对应的驾车导航信息,相关数据结构文档请参考 https://lbs.amap.com/api/javascript-api/reference/route-search#m_DrivingResult
if (status === 'complete') {
routes.value.distance = metersToKilometers(result.routes[0].distance)
routes.value.time = formatTime(result.routes[0].time)
console.log('绘制驾车路线完成', result)
TravelOptions.value = '驾车'
routes.value.time = formatTime(result.routes[0].time)
} else {
console.log('获取驾车数据失败:' + result)
}
},
)
}
const viewMap = () => {
goView()
}
const Driving = () => {
TravelOptions.value = '驾车'
if (Riding) {
Riding.clear()
}
if (driving) {
driving.clear()
}
goView()
}
const Ride = () => {
TravelOptions.value = '骑行'
if (driving) {
driving.clear()
}
if (Riding) {
Riding.clear()
}
map.clearMap()
// eslint-disable-next-line no-undef
Riding = new amap.Riding({
map: map,
// 驾车路线规划策略,AMap.DrivingPolicy.LEAST_TIME是最快捷模式
policy: 0,
// // panel 指定将结构化的路线详情数据显示的对应的DOM上,传入值需是DOM的ID
// panel: 'panel',
})
// 根据起终点经纬度规划驾车导航路线
Riding.search(
// 起点经纬度
[goodsInfo.value.sendAddressObj.longitude, goodsInfo.value.sendAddressObj.latitude],
// 终点经纬度
[goodsInfo.value.longitude, goodsInfo.value.latitude],
function (status: any, result: any) {
// result 即是对应的驾车导航信息,相关数据结构文档请参考 https://lbs.amap.com/api/javascript-api/reference/route-search#m_DrivingResult
if (status === 'complete') {
routes.value.distance = metersToKilometers(result.routes[0].distance)
routes.value.time = formatTime(result.routes[0].time)
console.log('绘制骑行路线完成', result)
} else {
feedback.msgError('获取骑行数据失败')
console.log('获取骑行数据失败:' + result)
}
},
)
}
const dialogTableVisible = ref(false)
const changeDialog = () => {
dialogTableVisible.value = !dialogTableVisible.value
}
//暴露方法
defineExpose({
changeDialog,
initMap,
})
function formatTime(seconds: any) {
console.log(seconds)
let hours = Math.floor(seconds / 3600)
let minutes = Math.floor((seconds % 3600) / 60)
let remainingSeconds = seconds % 60
return `${hours}${minutes}${remainingSeconds}`
}
function metersToKilometers(meters: any) {
let kilometers = meters / 1000
return kilometers
}
const startingPointEvent = (event:any) => {
if (event.keyCode !== 37 && event.keyCode !== 39) {
event.preventDefault();
}
}
</script>
<style lang="scss" scoped>
.custom-content-marker {
position: relative;
width: 25px;
height: 34px;
}
.custom-content-marker img {
width: 100%;
height: 100%;
}
.custom-content-marker .close-btn {
position: absolute;
top: -6px;
right: -8px;
width: 15px;
height: 15px;
font-size: 12px;
background: #ccc;
border-radius: 50%;
color: #fff;
text-align: center;
line-height: 15px;
box-shadow: -1px 1px 1px rgba(10, 10, 10, 0.2);
}
.custom-content-marker .close-btn:hover {
background: #666;
}
.container {
position: fixed;
left: 10%;
top: 0;
z-index: 1010;
width: 100%;
height: 100%;
#container {
width: 100%;
height: 100%;
}
.main-map {
position: absolute;
top: 50%;
left: 50%;
width: 4.5833rem;
height: 2.6042rem;
background-color: #fff;
z-index: 1;
transform: translate(-50%, -50%);
display: flex;
box-shadow: 0px 0px 58px rgba(0, 0, 0, 0.1);
.left-map {
width: 2.7083rem;
height: 100%;
background-color: skyblue;
#container {
position: relative;
}
.map-btn {
position: absolute;
bottom: 0.1563rem;
left: 0.1042rem;
z-index: 1;
display: flex;
.Driving {
margin-right: 0.1042rem;
width: 0.4167rem;
height: 0.1563rem;
text-align: center;
line-height: 0.1563rem;
color: #fff;
border-radius: 0.026rem;
background-color: #ff4e8d;
cursor: pointer;
}
.Ride {
margin-right: 0.1042rem;
width: 0.4167rem;
height: 0.1563rem;
text-align: center;
line-height: 0.1563rem;
color: #fff;
border-radius: 0.026rem;
background-color: #ff4e8d;
cursor: pointer;
}
}
}
.right-info {
flex: 1;
padding: 0.0781rem;
.top {
width: 100%;
display: flex;
justify-content: end;
align-items: center;
i {
font-size: 0.125rem;
cursor: pointer;
}
}
.label {
font-size: 0.1042rem;
font-weight: 600;
margin-right: 0.0521rem;
}
.price {
display: flex;
align-items: center;
.money {
color: #ff4e8d;
font-size: 0.1042rem;
font-weight: 600;
}
}
.address {
margin-top: 0.1042rem;
font-size: 0.0833rem;
color: #575d6c;
margin-bottom: 0.1042rem;
}
.receipt-time {
display: flex;
align-items: center;
color: #2d3646;
margin: 0.0521rem 0;
.label {
font-size: 0.0833rem;
font-weight: 400;
}
.time {
font-size: 0.0833rem;
}
}
.line {
margin-top: 0.1042rem;
width: 100%;
height: 1px;
background-color: #c2c5cc;
}
.address-ipt-box {
display: flex;
margin-top: 0.1042rem;
height: 0.4063rem;
.btn {
padding: 0.0521rem 0.026rem;
width: 0.1875rem;
height: 0.4063rem;
background-color: #ff4e8d;
margin-left: 0.0521rem;
color: #fff;
font-size: 20px;
text-align: center;
line-height: 0.151rem;
cursor: pointer;
}
}
.tisp {
margin-top: 0.0521rem;
font-size: 0.0625rem;
color: #575d6c;
}
.submit {
margin-top: 0.1563rem;
display: flex;
}
}
}
}
</style>