Showing
4 changed files
with
121 additions
and
4 deletions
| ... | @@ -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() | ... | ... |
-
Please register or login to post a comment