|
@@ -97,7 +97,7 @@
|
|
|
</div>
|
|
|
</div>
|
|
|
</div>
|
|
|
- <div v-show="!!routeData && routeData.length > 0" class="route-box">
|
|
|
+ <div v-show="showAddress && !!routeData && routeData.length > 0" class="route-box">
|
|
|
<div class="route-item1">
|
|
|
<i class="icon-position3" />
|
|
|
<div class="text1">路线始点:</div>
|
|
@@ -108,14 +108,14 @@
|
|
|
<div v-for="(item, index) in routeData" :key="index" class="route-item2" @click="drawRoute(item)">
|
|
|
<div class="text-box1">
|
|
|
<div :class="'tag' + index">{{ getTag(index) }}</div>
|
|
|
- <div class="text1">{{ item.policy }}</div>
|
|
|
+ <div class="text1">{{ item.strategy }}</div>
|
|
|
</div>
|
|
|
<div class="route-info">
|
|
|
<div class="text-box2">
|
|
|
<i class="icon1" />
|
|
|
- <div class="gradient-text2">{{ item.date[0] }}</div>
|
|
|
+ <div class="gradient-text2">{{ item.duration[0] }}</div>
|
|
|
<div class="text2">小时</div>
|
|
|
- <div class="gradient-text2">{{ item.date[1] }}</div>
|
|
|
+ <div class="gradient-text2">{{ item.duration[1] }}</div>
|
|
|
<div class="text2">分钟</div>
|
|
|
</div>
|
|
|
<div class="line"></div>
|
|
@@ -167,10 +167,14 @@ import {
|
|
|
getYardSitesDetails
|
|
|
} from '@/api/globalMap/spatialAnalysis';
|
|
|
import BigNumber from 'bignumber.js';
|
|
|
+import gcoord from 'gcoord';
|
|
|
+import startImg from '@/assets/images/map/start.png';
|
|
|
+import endImg from '@/assets/images/map/end.png';
|
|
|
|
|
|
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
|
|
|
const { emergency_resource, disaster_relief_material } = toRefs<any>(proxy?.useDict('emergency_resource', 'disaster_relief_material'));
|
|
|
// 应急物资
|
|
|
+const amapKey = 'e45d4caa2bef3c84714a2ed9b1e27d98';
|
|
|
let expand = ref(true);
|
|
|
let AMap, map, driving, geocoder;
|
|
|
let routeData = ref([]);
|
|
@@ -281,15 +285,22 @@ const toSelect = () => {
|
|
|
};
|
|
|
const handleClickMap = (e) => {
|
|
|
map.off('click', handleClickMap);
|
|
|
- tempState.longitude = e.lnglat.getLng();
|
|
|
- tempState.latitude = e.lnglat.getLat();
|
|
|
- geocoder.getAddress([tempState.longitude, tempState.latitude], (status, result) => {
|
|
|
- if (status === 'complete' && result.info === 'OK') {
|
|
|
- tempState.address = result.regeocode.formattedAddress;
|
|
|
- }
|
|
|
- });
|
|
|
+ getAddress([e.lnglat.getLng(), e.lnglat.getLat()]);
|
|
|
showRight.value = true;
|
|
|
};
|
|
|
+const getAddress = async (location) => {
|
|
|
+ const gcj02Coord = gcoord.transform(location, gcoord.WGS84, gcoord.GCJ02);
|
|
|
+ tempState.longitude = location[0];
|
|
|
+ tempState.latitude = location[1];
|
|
|
+ // 调用高德逆向地理编码 API
|
|
|
+ const response = await fetch(`https://restapi.amap.com/v3/geocode/regeo?key=${amapKey}&location=${gcj02Coord[0]},${gcj02Coord[1]}`);
|
|
|
+ const result = await response.json();
|
|
|
+
|
|
|
+ // 解析地址信息
|
|
|
+ if (result.status === '1' && result.regeocode) {
|
|
|
+ tempState.address = result.regeocode.formatted_address;
|
|
|
+ }
|
|
|
+};
|
|
|
const confirmSelect = () => {
|
|
|
selectEvent(
|
|
|
{
|
|
@@ -335,61 +346,51 @@ const selectEvent = (item, unFitView) => {
|
|
|
getList();
|
|
|
};
|
|
|
|
|
|
-const handleRoutes = (item) => {
|
|
|
- const start = [item.longitude, item.latitude];
|
|
|
- const end = [selectData.value.longitude, selectData.value.latitude];
|
|
|
+const handleRoutes = async (item) => {
|
|
|
+ const lnglat = gcoord.transform([item.longitude, item.latitude], gcoord.WGS84, gcoord.GCJ02);
|
|
|
+ const lnglat2 = gcoord.transform([selectData.value.longitude, selectData.value.latitude], gcoord.WGS84, gcoord.GCJ02);
|
|
|
+ const start = [lnglat[0], lnglat[1]];
|
|
|
+ const end = lnglat2;
|
|
|
showAddress.value = true;
|
|
|
routesAddress.value = item.address;
|
|
|
- calculateRoutes(start, end, 0);
|
|
|
-};
|
|
|
-// 计算并展示三条路线
|
|
|
-const calculateRoutes = (start, end, index) => {
|
|
|
- if (index >= 3) {
|
|
|
- return;
|
|
|
- }
|
|
|
- // 不同的策略或参数来生成不同的路线
|
|
|
- const policyMap = [
|
|
|
- AMap.DrivingPolicy.LEAST_TIME, // 最短时间
|
|
|
- AMap.DrivingPolicy.LEAST_DISTANCE, // 最短距离
|
|
|
- AMap.DrivingPolicy.LEAST_FEE // 最少费用
|
|
|
- ];
|
|
|
- driving.setPolicy(policyMap[index]);
|
|
|
+ // 10速度最快 返回结果会躲避拥堵,路程较短,尽量缩短时间,与高德地图的默认策略也就是不进行任何勾选一致
|
|
|
+ // 16费用最低 返回的结果尽量不走高速,并且尽量规划收费较低甚至免费的路径结果,与高德地图的“避免收费&不走高速”策略一致
|
|
|
+ const url = `https://restapi.amap.com/v3/direction/driving?origin=${start}&destination=${end}&key=${amapKey}`;
|
|
|
+ const response = await fetch(url + '&strategy=10');
|
|
|
|
|
|
- driving.search(new AMap.LngLat(start[0], start[1]), new AMap.LngLat(end[0], end[1]), function (status, result) {
|
|
|
- if (status === 'complete' && result.info === 'OK') {
|
|
|
- const route = result.routes[0];
|
|
|
- if (index === 0) {
|
|
|
- routeData.value = [];
|
|
|
- }
|
|
|
- route.date = formatDate(route.time);
|
|
|
- routeData.value.push(route);
|
|
|
+ if (!!response.ok) {
|
|
|
+ const data = await response.json();
|
|
|
+ if (data.route && data.route.paths) {
|
|
|
+ data.route.paths.forEach((item) => {
|
|
|
+ item.duration = formatDate(item.duration);
|
|
|
+ });
|
|
|
+ routeData.value = data.route.paths;
|
|
|
+ } else {
|
|
|
+ routeData.value = [];
|
|
|
}
|
|
|
-
|
|
|
- // 计算下一条路线
|
|
|
- calculateRoutes(start, end, index + 1);
|
|
|
- });
|
|
|
+ }
|
|
|
+ const response2 = await fetch(url + '&strategy=16');
|
|
|
+ if (!!response2.ok) {
|
|
|
+ const data2 = await response2.json();
|
|
|
+ if (data2.route && data2.route.paths) {
|
|
|
+ data2.route.paths.forEach((item) => {
|
|
|
+ item.duration = formatDate(item.duration);
|
|
|
+ });
|
|
|
+ routeData.value = routeData.value.concat(data2.route.paths);
|
|
|
+ }
|
|
|
+ }
|
|
|
};
|
|
|
+
|
|
|
const drawRoute = (route) => {
|
|
|
const path = parseRouteToPath(route);
|
|
|
- if (!!startMarker) {
|
|
|
- map.remove(startMarker);
|
|
|
- startMarker = null;
|
|
|
- }
|
|
|
- if (!!endMarker) {
|
|
|
- map.remove(endMarker);
|
|
|
- endMarker = null;
|
|
|
- }
|
|
|
- if (!!routeLine) {
|
|
|
- routeLine.setMap(null);
|
|
|
- routeLine = null;
|
|
|
- }
|
|
|
+ clearLine();
|
|
|
const icon1 = new AMap.Icon({
|
|
|
size: new AMap.Size(19, 31),
|
|
|
- image: 'https://webapi.amap.com/theme/v1.3/markers/n/start.png'
|
|
|
+ image: startImg
|
|
|
});
|
|
|
const icon2 = new AMap.Icon({
|
|
|
size: new AMap.Size(19, 31),
|
|
|
- image: 'https://webapi.amap.com/theme/v1.3/markers/n/end.png'
|
|
|
+ image: endImg
|
|
|
});
|
|
|
startMarker = new AMap.Marker({
|
|
|
position: path[0],
|
|
@@ -427,11 +428,14 @@ const parseRouteToPath = (route) => {
|
|
|
for (var i = 0, l = route.steps.length; i < l; i++) {
|
|
|
var step = route.steps[i];
|
|
|
|
|
|
- for (var j = 0, n = step.path.length; j < n; j++) {
|
|
|
- path.push(step.path[j]);
|
|
|
- }
|
|
|
+ // 按分号分割字符串,得到一个包含经纬度对的数组
|
|
|
+ const coordinatesPairs = step.polyline.split(';');
|
|
|
+ // 将每个经纬度对进一步分割成经度和纬度,并转换为一个对象
|
|
|
+ path = coordinatesPairs.map((pair) => {
|
|
|
+ const [longitude, latitude] = pair.split(',');
|
|
|
+ return gcoord.transform([longitude, latitude], gcoord.GCJ02, gcoord.WGS84);
|
|
|
+ });
|
|
|
}
|
|
|
-
|
|
|
return path;
|
|
|
};
|
|
|
function formatDate(seconds: number) {
|
|
@@ -453,15 +457,27 @@ function formatDate(seconds: number) {
|
|
|
return [hours, minutes];
|
|
|
}
|
|
|
const getTag = (index) => {
|
|
|
- let tag = '路线' + index;
|
|
|
- if (index === 0) {
|
|
|
- tag = '路线A';
|
|
|
- } else if (index === 1) {
|
|
|
- tag = '路线B';
|
|
|
- } else if (index === 2) {
|
|
|
- tag = '路线C';
|
|
|
+ const arr = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'];
|
|
|
+ return '路线' + (arr[index] ? arr[index] : index);
|
|
|
+};
|
|
|
+const clearMarker2 = () => {
|
|
|
+ if (!selectMarker) return;
|
|
|
+ selectMarker.remove();
|
|
|
+ selectMarker = null;
|
|
|
+};
|
|
|
+const clearLine = () => {
|
|
|
+ if (!!startMarker) {
|
|
|
+ startMarker.remove();
|
|
|
+ startMarker = null;
|
|
|
+ }
|
|
|
+ if (!!endMarker) {
|
|
|
+ endMarker.remove();
|
|
|
+ endMarker = null;
|
|
|
+ }
|
|
|
+ if (!!routeLine) {
|
|
|
+ routeLine.remove();
|
|
|
+ routeLine = null;
|
|
|
}
|
|
|
- return tag;
|
|
|
};
|
|
|
const handlePointDetails = (data) => {
|
|
|
let methodList = {
|
|
@@ -1016,6 +1032,7 @@ onUnmounted(() => {
|
|
|
background: url('@/assets/images/electronicDisasterMapManage/close.png') no-repeat;
|
|
|
background-size: 100% 100%;
|
|
|
margin-left: 5px;
|
|
|
+ cursor: pointer;
|
|
|
}
|
|
|
}
|
|
|
.route-item2 {
|
|
@@ -1026,26 +1043,21 @@ onUnmounted(() => {
|
|
|
cursor: pointer;
|
|
|
.text-box1 {
|
|
|
display: flex;
|
|
|
- .tag0 {
|
|
|
+ .tag {
|
|
|
color: #fff;
|
|
|
- background-color: #e65d63;
|
|
|
+ background-color: #2c81ff;
|
|
|
border-radius: 10px;
|
|
|
padding: 2px 6px;
|
|
|
font-size: 12px;
|
|
|
}
|
|
|
+ .tag0 {
|
|
|
+ background-color: #e65d63;
|
|
|
+ }
|
|
|
.tag1 {
|
|
|
- color: #fff;
|
|
|
background-color: #f0b13c;
|
|
|
- border-radius: 10px;
|
|
|
- padding: 2px 6px;
|
|
|
- font-size: 12px;
|
|
|
}
|
|
|
.tag2 {
|
|
|
- color: #fff;
|
|
|
background-color: #6bc26b;
|
|
|
- border-radius: 10px;
|
|
|
- padding: 2px 6px;
|
|
|
- font-size: 12px;
|
|
|
}
|
|
|
.text1 {
|
|
|
font-size: 14px;
|