hookehuyr

✨ feat(简约模版): 详情页新增步行导航功能

1 { 1 {
2 "globals": { 2 "globals": {
3 "EffectScope": true, 3 "EffectScope": true,
4 + "ElMessage": true,
4 "computed": true, 5 "computed": true,
5 "createApp": true, 6 "createApp": true,
6 "customRef": true, 7 "customRef": true,
......
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
2 export {} 2 export {}
3 declare global { 3 declare global {
4 const EffectScope: typeof import('vue')['EffectScope'] 4 const EffectScope: typeof import('vue')['EffectScope']
5 + const ElMessage: typeof import('element-plus/es')['ElMessage']
5 const computed: typeof import('vue')['computed'] 6 const computed: typeof import('vue')['computed']
6 const createApp: typeof import('vue')['createApp'] 7 const createApp: typeof import('vue')['createApp']
7 const customRef: typeof import('vue')['customRef'] 8 const customRef: typeof import('vue')['customRef']
......
1 <!-- 1 <!--
2 * @Date: 2024-09-15 22:08:49 2 * @Date: 2024-09-15 22:08:49
3 * @LastEditors: hookehuyr hookehuyr@gmail.com 3 * @LastEditors: hookehuyr hookehuyr@gmail.com
4 - * @LastEditTime: 2025-02-10 16:11:47 4 + * @LastEditTime: 2025-03-06 09:50:03
5 * @FilePath: /map-demo/src/views/by/info.vue 5 * @FilePath: /map-demo/src/views/by/info.vue
6 * @Description: 文件描述 6 * @Description: 文件描述
7 --> 7 -->
...@@ -31,6 +31,7 @@ ...@@ -31,6 +31,7 @@
31 <van-icon v-else name="https://cdn.ipadbiz.cn/bieyuan/map/icon/%E8%AF%AD%E9%9F%B32@3x.png" size="1.65rem" /> 31 <van-icon v-else name="https://cdn.ipadbiz.cn/bieyuan/map/icon/%E8%AF%AD%E9%9F%B32@3x.png" size="1.65rem" />
32 </div> 32 </div>
33 <div v-if="page_details.path?.length > 1" @click="goTo()" class="info-btn">前往</div> 33 <div v-if="page_details.path?.length > 1" @click="goTo()" class="info-btn">前往</div>
34 + <div @click="goToWalk()" class="info-btn">前往</div>
34 </div> 35 </div>
35 </div> 36 </div>
36 <div class="info-sub-title">{{ page_details.note }}</div> 37 <div class="info-sub-title">{{ page_details.note }}</div>
...@@ -283,7 +284,7 @@ const outerStopAudio = () => { ...@@ -283,7 +284,7 @@ const outerStopAudio = () => {
283 audio.value.pause(); 284 audio.value.pause();
284 } 285 }
285 286
286 -const emit = defineEmits(["closeFloat", 'route']); 287 +const emit = defineEmits(["closeFloat", 'route', 'walkRoute']);
287 288
288 const show_toast = ref(false); 289 const show_toast = ref(false);
289 const toast_text = ref(''); 290 const toast_text = ref('');
...@@ -312,6 +313,41 @@ const goTo = () => { // 打开标记地图显示 ...@@ -312,6 +313,41 @@ const goTo = () => { // 打开标记地图显示
312 } 313 }
313 } 314 }
314 315
316 +const goToWalk = async () => { // 打开步行导航地图显示
317 + // 没有关联导航提示
318 + try {
319 + const isLocationEnabled = await checkWxLocation();
320 + if (!isLocationEnabled) {
321 + // 提示用户开启定位
322 + show_toast.value = true;
323 + toast_text.value = '请开启手机定位功能';
324 + return;
325 + }
326 + } catch (err) {
327 + console.error('获取定位状态失败:', err);
328 + }
329 + //
330 + if ($router.currentRoute.value.path === '/by/info') { // 详情页
331 + $router.push({
332 + path: '/by',
333 + query: {
334 + id: $route.query.id,
335 + marker_id: $route.query.marker_id
336 + }
337 + })
338 + } else { // 地图页
339 + //
340 + emit("closeFloat", false);
341 + //
342 + if (page_details.value?.position.length) {
343 + emit("walkRoute", {name: '步行导航', point: [+page_details.value?.position[0], +page_details.value?.position[1]]});
344 + } else {
345 + show_toast.value = true;
346 + toast_text.value = '该标记点没有关联导航';
347 + }
348 + }
349 +}
350 +
315 const goBack = () => { // 返回首页 351 const goBack = () => { // 返回首页
316 $router.push({ 352 $router.push({
317 path: '/by', 353 path: '/by',
...@@ -447,6 +483,24 @@ const onStatusAudioList = (status) => { // 音频列表组件,状态改变 ...@@ -447,6 +483,24 @@ const onStatusAudioList = (status) => { // 音频列表组件,状态改变
447 // show_audio.value = false; 483 // show_audio.value = false;
448 // } 484 // }
449 } 485 }
486 +
487 +const checkWxLocation = () => {
488 + return new Promise((resolve, reject) => {
489 + wx.getLocation({
490 + type: 'gcj02', // 默认为 wgs84 返回 gps 坐标,gcj02 返回可用于 wx.openLocation 的坐标
491 + success: (res) => {
492 + resolve(true); // 已开启定位
493 + },
494 + fail: (err) => {
495 + if (err.errMsg.indexOf('deny') > -1) {
496 + resolve(false); // 未开启定位
497 + } else {
498 + reject(err); // 其他错误
499 + }
500 + }
501 + });
502 + });
503 +}
450 </script> 504 </script>
451 505
452 <style lang="less"> 506 <style lang="less">
......
1 <!-- 1 <!--
2 * @Date: 2023-05-19 14:54:27 2 * @Date: 2023-05-19 14:54:27
3 * @LastEditors: hookehuyr hookehuyr@gmail.com 3 * @LastEditors: hookehuyr hookehuyr@gmail.com
4 - * @LastEditTime: 2025-03-05 17:52:15 4 + * @LastEditTime: 2025-03-06 10:31:16
5 * @FilePath: /map-demo/src/views/by/map.vue 5 * @FilePath: /map-demo/src/views/by/map.vue
6 * @Description: 公众地图主体页面 6 * @Description: 公众地图主体页面
7 --> 7 -->
8 <template> 8 <template>
9 <div ref="root" style="height: 100vh; position: relative; overflow: hidden;"> 9 <div ref="root" style="height: 100vh; position: relative; overflow: hidden;">
10 <div id="container"></div> 10 <div id="container"></div>
11 + <!-- 添加导航面板容器 -->
12 + <div id="walking-panel" style="position: absolute; bottom: 1rem; left: 1rem; padding: 1rem;"></div>
11 <div style="position: absolute; top: 2rem; right: 1rem; display: flex; flex-direction: column;"> 13 <div style="position: absolute; top: 2rem; right: 1rem; display: flex; flex-direction: column;">
12 <!-- <van-icon size="2rem" name="search" color="#DD7850" style="margin-bottom: 1rem;" /> --> 14 <!-- <van-icon size="2rem" name="search" color="#DD7850" style="margin-bottom: 1rem;" /> -->
13 <van-image 15 <van-image
...@@ -42,7 +44,7 @@ ...@@ -42,7 +44,7 @@
42 <button @click="show = false">关闭</button> 44 <button @click="show = false">关闭</button>
43 </div> 45 </div>
44 </template> --> 46 </template> -->
45 - <page-info ref="pageInfo" :info="itemInfo" :height="info_height" @close-float="onCloseFloat" @route="onRoute"></page-info> 47 + <page-info ref="pageInfo" :info="itemInfo" :height="info_height" @close-float="onCloseFloat" @route="onRoute" @walk-route="onWalkRoute"></page-info>
46 <!-- <div v-if="showClose" @click="closeFloatPanel" class="close-float-panel"> 48 <!-- <div v-if="showClose" @click="closeFloatPanel" class="close-float-panel">
47 <van-icon name="arrow-left" color="#FFF" size="1.5rem" /> 49 <van-icon name="arrow-left" color="#FFF" size="1.5rem" />
48 </div> --> 50 </div> -->
...@@ -96,6 +98,7 @@ import audioBackground1 from '@/components/audioBackground1.vue' ...@@ -96,6 +98,7 @@ import audioBackground1 from '@/components/audioBackground1.vue'
96 import { mapState, mapActions } from 'pinia' 98 import { mapState, mapActions } from 'pinia'
97 import { mainStore } from '@/store' 99 import { mainStore } from '@/store'
98 import { parseQueryString } from '@/utils/tools' 100 import { parseQueryString } from '@/utils/tools'
101 +import AMapLoader from '@amap/amap-jsapi-loader'
99 102
100 const GPS = { 103 const GPS = {
101 PI: 3.14159265358979324, 104 PI: 3.14159265358979324,
...@@ -153,6 +156,11 @@ const GPS = { ...@@ -153,6 +156,11 @@ const GPS = {
153 } 156 }
154 }; 157 };
155 158
159 +// 关键安全配置
160 +window._AMapSecurityConfig = {
161 + securityJsCode: '8602057c4c8dae5bed9a240c0582c46f', // 替换为你的密钥
162 +}
163 +
156 export default { 164 export default {
157 components: { pageInfo, audioBackground1 }, 165 components: { pageInfo, audioBackground1 },
158 data() { 166 data() {
...@@ -267,9 +275,15 @@ export default { ...@@ -267,9 +275,15 @@ export default {
267 toast_text: '', 275 toast_text: '',
268 data_logo: '', 276 data_logo: '',
269 data_layers: [], 277 data_layers: [],
278 + walking: '',
270 } 279 }
271 }, 280 },
272 async mounted() { 281 async mounted() {
282 + const AMap = await AMapLoader.load({
283 + key: '381c6763e1fefd810fbab697f470149c', // 控制台获取
284 + version: '2.0', // 指定API版本
285 + plugins: ['AMap.ElasticMarker','AMap.ImageLayer','AMap.ToolBar','AMap.IndoorMap','AMap.Walking','AMap.Geolocation'] // 必须加载步行导航插件
286 + })
273 const code = this.$route.query.id; 287 const code = this.$route.query.id;
274 const { data } = await mapAPI({ i: code }); 288 const { data } = await mapAPI({ i: code });
275 this.navBarList = data.list; // 底部导航条 289 this.navBarList = data.list; // 底部导航条
...@@ -342,6 +356,14 @@ export default { ...@@ -342,6 +356,14 @@ export default {
342 // // 浮动面板样式 356 // // 浮动面板样式
343 // $('.van-floating-panel__content').css('borderRadius', '1.5rem'); 357 // $('.van-floating-panel__content').css('borderRadius', '1.5rem');
344 // }, 2000); 358 // }, 2000);
359 + // 初始化步行导航插件时指定面板容器
360 + this.walking = new AMap.Walking({
361 + map: this.map,
362 + // panel: 'walking-panel', // 必须指定存在的DOM元素ID
363 + hideMarkers: false, // 设置隐藏路径规划的起始点图标
364 + isOutline: true, // 使用map属性时,绘制的规划线路是否显示描边
365 + autoFitView: true, // 是否自动调整地图视野到显示的路线
366 + });
345 }, 367 },
346 watch: { 368 watch: {
347 // // 监听 $route 对象的 query 属性 369 // // 监听 $route 对象的 query 属性
...@@ -941,6 +963,45 @@ export default { ...@@ -941,6 +963,45 @@ export default {
941 // 定位到当前位置中心 963 // 定位到当前位置中心
942 this.map.setZoomAndCenter(this.zoom, this.data_center); 964 this.map.setZoomAndCenter(this.zoom, this.data_center);
943 }, 965 },
966 + async onWalkRoute (position) {
967 + await this.$nextTick(); // 等待DOM更新
968 + // 步行导航
969 + // let walking = new AMap.Walking({
970 + // map: this.map,
971 + // panel: "panel"
972 + // });
973 +
974 + // 确保参数格式正确
975 + const startPoint = [this.current_lng, this.current_lat]; // 起点
976 + const endPoint = position.point; // 终点
977 +
978 + // 参数检查
979 + if (!startPoint[0] || !startPoint[1]) {
980 + this.show_toast = true;
981 + this.toast_text = '无法获取当前位置,请确保已开启定位功能';
982 + return;
983 + }
984 +
985 + if (!endPoint[0] || !endPoint[1]) {
986 + this.show_toast = true;
987 + this.toast_text = '目的地坐标不完整';
988 + return;
989 + }
990 +
991 + // 转换为 LngLat 对象
992 + const start = new AMap.LngLat(startPoint[0], startPoint[1]);
993 + const end = new AMap.LngLat(endPoint[0], endPoint[1]);
994 +
995 + // 规划步行路线
996 + this.walking.search(start, end, (status, result) => {
997 + if (status === 'complete') {
998 + console.log('步行路线规划成功');
999 + } else {
1000 + console.error('步行路线规划失败:', status, result);
1001 + ElMessage.error('步行路线规划失败,请稍后重试');
1002 + }
1003 + });
1004 + },
944 handleLocation(status) { // 打开/关闭 当前定位 1005 handleLocation(status) { // 打开/关闭 当前定位
945 if (status) { 1006 if (status) {
946 this.setLocation() 1007 this.setLocation()
......