feat(map): 添加地图加载状态管理和错误处理功能
重构地图组件,增加加载状态管理和错误处理机制: 1. 添加加载中和错误状态UI展示 2. 实现带指数退避的重试机制 3. 优化错误信息提示 4. 清理未使用的组件导入
Showing
4 changed files
with
272 additions
and
116 deletions
| ... | @@ -13,10 +13,6 @@ declare module '@vue/runtime-core' { | ... | @@ -13,10 +13,6 @@ declare module '@vue/runtime-core' { |
| 13 | AudioBackground1: typeof import('./src/components/audioBackground1.vue')['default'] | 13 | AudioBackground1: typeof import('./src/components/audioBackground1.vue')['default'] |
| 14 | AudioList: typeof import('./src/components/audioList.vue')['default'] | 14 | AudioList: typeof import('./src/components/audioList.vue')['default'] |
| 15 | BottomNav: typeof import('./src/components/BottomNav.vue')['default'] | 15 | BottomNav: typeof import('./src/components/BottomNav.vue')['default'] |
| 16 | - ElButton: typeof import('element-plus/es')['ElButton'] | ||
| 17 | - ElInput: typeof import('element-plus/es')['ElInput'] | ||
| 18 | - ElOption: typeof import('element-plus/es')['ElOption'] | ||
| 19 | - ElSelect: typeof import('element-plus/es')['ElSelect'] | ||
| 20 | Floor: typeof import('./src/components/Floor/index.vue')['default'] | 16 | Floor: typeof import('./src/components/Floor/index.vue')['default'] |
| 21 | InfoPopup: typeof import('./src/components/InfoPopup.vue')['default'] | 17 | InfoPopup: typeof import('./src/components/InfoPopup.vue')['default'] |
| 22 | InfoPopupLite: typeof import('./src/components/InfoPopupLite.vue')['default'] | 18 | InfoPopupLite: typeof import('./src/components/InfoPopupLite.vue')['default'] |
| ... | @@ -28,25 +24,9 @@ declare module '@vue/runtime-core' { | ... | @@ -28,25 +24,9 @@ declare module '@vue/runtime-core' { |
| 28 | RouterLink: typeof import('vue-router')['RouterLink'] | 24 | RouterLink: typeof import('vue-router')['RouterLink'] |
| 29 | RouterView: typeof import('vue-router')['RouterView'] | 25 | RouterView: typeof import('vue-router')['RouterView'] |
| 30 | SvgIcon: typeof import('./src/components/Floor/svgIcon.vue')['default'] | 26 | SvgIcon: typeof import('./src/components/Floor/svgIcon.vue')['default'] |
| 31 | - VanBackTop: typeof import('vant/es')['BackTop'] | ||
| 32 | - VanButton: typeof import('vant/es')['Button'] | ||
| 33 | - VanCol: typeof import('vant/es')['Col'] | ||
| 34 | - VanConfigProvider: typeof import('vant/es')['ConfigProvider'] | ||
| 35 | VanDialog: typeof import('vant/es')['Dialog'] | 27 | VanDialog: typeof import('vant/es')['Dialog'] |
| 36 | - VanField: typeof import('vant/es')['Field'] | ||
| 37 | - VanFloatingPanel: typeof import('vant/es')['FloatingPanel'] | ||
| 38 | VanIcon: typeof import('vant/es')['Icon'] | 28 | VanIcon: typeof import('vant/es')['Icon'] |
| 39 | - VanImage: typeof import('vant/es')['Image'] | ||
| 40 | - VanImagePreview: typeof import('vant/es')['ImagePreview'] | ||
| 41 | - VanOverlay: typeof import('vant/es')['Overlay'] | ||
| 42 | VanPopup: typeof import('vant/es')['Popup'] | 29 | VanPopup: typeof import('vant/es')['Popup'] |
| 43 | - VanRow: typeof import('vant/es')['Row'] | ||
| 44 | - VanSlider: typeof import('vant/es')['Slider'] | ||
| 45 | - VanSwipe: typeof import('vant/es')['Swipe'] | ||
| 46 | - VanSwipeItem: typeof import('vant/es')['SwipeItem'] | ||
| 47 | - VanTab: typeof import('vant/es')['Tab'] | ||
| 48 | - VanTabs: typeof import('vant/es')['Tabs'] | ||
| 49 | - VanToast: typeof import('vant/es')['Toast'] | ||
| 50 | VRViewer: typeof import('./src/components/VRViewer/index.vue')['default'] | 30 | VRViewer: typeof import('./src/components/VRViewer/index.vue')['default'] |
| 51 | } | 31 | } |
| 52 | } | 32 | } | ... | ... |
| ... | @@ -2,7 +2,6 @@ | ... | @@ -2,7 +2,6 @@ |
| 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'] | ||
| 6 | const computed: typeof import('vue')['computed'] | 5 | const computed: typeof import('vue')['computed'] |
| 7 | const createApp: typeof import('vue')['createApp'] | 6 | const createApp: typeof import('vue')['createApp'] |
| 8 | const customRef: typeof import('vue')['customRef'] | 7 | const customRef: typeof import('vue')['customRef'] | ... | ... |
| 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-09-21 19:03:12 | 4 | + * @LastEditTime: 2025-09-25 21:54:49 |
| 5 | * @FilePath: /map-demo/src/views/checkin/map.vue | 5 | * @FilePath: /map-demo/src/views/checkin/map.vue |
| 6 | * @Description: 公众地图主体页面 | 6 | * @Description: 公众地图主体页面 |
| 7 | --> | 7 | --> |
| 8 | <template> | 8 | <template> |
| 9 | <div ref="root" :style="{ height: mapHeight, position: 'relative', overflow: 'hidden' }"> | 9 | <div ref="root" :style="{ height: mapHeight, position: 'relative', overflow: 'hidden' }"> |
| 10 | + <!-- 地图加载状态提示 --> | ||
| 11 | + <div v-if="mapLoadingState.isLoading" class="map-loading-overlay"> | ||
| 12 | + <div class="loading-content"> | ||
| 13 | + <van-loading size="24px" color="#DD7850">地图加载中...</van-loading> | ||
| 14 | + <p class="loading-text">正在初始化地图,请稍候</p> | ||
| 15 | + </div> | ||
| 16 | + </div> | ||
| 17 | + | ||
| 18 | + <!-- 地图加载错误提示 --> | ||
| 19 | + <div v-if="mapLoadingState.isError" class="map-error-overlay"> | ||
| 20 | + <div class="error-content"> | ||
| 21 | + <van-icon name="warning-o" size="48px" color="#ff4444" /> | ||
| 22 | + <p class="error-title">地图加载失败</p> | ||
| 23 | + <p class="error-message">{{ mapLoadingState.errorMessage }}</p> | ||
| 24 | + <van-button | ||
| 25 | + type="primary" | ||
| 26 | + color="#DD7850" | ||
| 27 | + @click="retryLoadMap" | ||
| 28 | + :loading="mapLoadingState.isLoading" | ||
| 29 | + > | ||
| 30 | + 重新加载 | ||
| 31 | + </van-button> | ||
| 32 | + </div> | ||
| 33 | + </div> | ||
| 34 | + | ||
| 10 | <div id="container"></div> | 35 | <div id="container"></div> |
| 11 | <!-- 添加导航面板容器 --> | 36 | <!-- 添加导航面板容器 --> |
| 12 | <div id="walking-panel" style="position: absolute; bottom: 1rem; left: 1rem; padding: 1rem;"></div> | 37 | <div id="walking-panel" style="position: absolute; bottom: 1rem; left: 1rem; padding: 1rem;"></div> |
| ... | @@ -304,6 +329,14 @@ export default { | ... | @@ -304,6 +329,14 @@ export default { |
| 304 | floatingPanelBorderRadius: '1.25rem' | 329 | floatingPanelBorderRadius: '1.25rem' |
| 305 | }, | 330 | }, |
| 306 | showClose: false, | 331 | showClose: false, |
| 332 | + // 地图加载状态管理 | ||
| 333 | + mapLoadingState: { | ||
| 334 | + isLoading: true, | ||
| 335 | + isError: false, | ||
| 336 | + errorMessage: '', | ||
| 337 | + retryCount: 0, | ||
| 338 | + maxRetries: 3 | ||
| 339 | + }, | ||
| 307 | markerStyle2: { // 选中 | 340 | markerStyle2: { // 选中 |
| 308 | //设置文本样式,Object 同 css 样式表 | 341 | //设置文本样式,Object 同 css 样式表 |
| 309 | "padding": ".5rem .2rem .5rem .2rem", | 342 | "padding": ".5rem .2rem .5rem .2rem", |
| ... | @@ -405,102 +438,44 @@ export default { | ... | @@ -405,102 +438,44 @@ export default { |
| 405 | store.keepPages.push('CheckinMap'); | 438 | store.keepPages.push('CheckinMap'); |
| 406 | } | 439 | } |
| 407 | 440 | ||
| 408 | - const AMap = await AMapLoader.load({ | 441 | + // 开始加载地图 |
| 409 | - key: '17b8fc386104b89db88b60b049a6dbce', // 控制台获取 | 442 | + this.mapLoadingState.isLoading = true; |
| 410 | - version: '2.0', // 指定API版本 | 443 | + this.mapLoadingState.isError = false; |
| 411 | - plugins: ['AMap.ElasticMarker','AMap.ImageLayer','AMap.ToolBar','AMap.IndoorMap','AMap.Walking','AMap.Geolocation'] // 必须加载步行导航插件 | 444 | + |
| 412 | - }) | 445 | + try { |
| 413 | - const code = this.$route.query.id; | 446 | + await this.initializeMapWithRetry(); |
| 414 | - const { data } = await mapAPI({ i: code }); | 447 | + } catch (error) { |
| 415 | - this.navBarList = data.list; // 底部导航条 | 448 | + console.error('地图初始化失败:', error); |
| 416 | - this.mapTiles = data.level; // 获取图层 | 449 | + this.handleMapLoadError(error); |
| 417 | - this.navKey = data.list.length ? data.list[0]['id'] : 0; // 默认选中 第一个 id | ||
| 418 | - this.navList = data.list.length ? data.list.filter(item => item.id === this.navKey)[0]['list'] : []; // 返回默认选中项的实体信息 | ||
| 419 | - this.data_center = data.map.center.map(item => Number(item)); // 地图中心点 | ||
| 420 | - this.data_zoom = data.map.zoom; // 地图默认缩放 | ||
| 421 | - this.data_rotation = data.map.rotation; // 地图旋转角度 | ||
| 422 | - this.data_zooms = data.map.zooms.map(item => Number(item)); // 地图默认缩放范围 | ||
| 423 | - this.data_paths = data.map.path ? data.map.path : {}; // 地图默认导航路径 | ||
| 424 | - this.data_logo = data.map.map_logo ? data.map.map_logo : ''; // 地图logo | ||
| 425 | - this.point_range = data.map.map_range ? data.map.map_range : []; // 地图定位范围 | ||
| 426 | - if (data.map.map_layers) { // 地图默认图层 | ||
| 427 | - if (data.map.map_layers === 'satellite') { // 卫星和路网 | ||
| 428 | - this.data_layers = [new AMap.TileLayer.Satellite(), new AMap.TileLayer.RoadNet()] | ||
| 429 | - } else { // 平面图 | ||
| 430 | - this.data_layers = []; | ||
| 431 | - } | ||
| 432 | - } | ||
| 433 | - if (data.map.path) { | ||
| 434 | - for (const key in data.map.path) { | ||
| 435 | - const element = data.map.path[key]; | ||
| 436 | - this.data_path_list.push({ | ||
| 437 | - name: key, | ||
| 438 | - path: element, | ||
| 439 | - status: true | ||
| 440 | - }) | ||
| 441 | - } | ||
| 442 | - } | ||
| 443 | - // 地图标题 | ||
| 444 | - document.title = data.map.map_title; | ||
| 445 | - // 微信分享 | ||
| 446 | - const shareData = { | ||
| 447 | - title: data.map.map_title, // 分享标题 | ||
| 448 | - desc: '别院地图', // 分享描述 | ||
| 449 | - link: location.origin + location.pathname + location.hash, // 分享链接,该链接域名或路径必须与当前页面对应的公众号 JS 安全域名一致 | ||
| 450 | - imgUrl: '', // 分享图标 | ||
| 451 | - success: function () { | ||
| 452 | - // console.warn('设置成功'); | ||
| 453 | - } | ||
| 454 | } | 450 | } |
| 455 | - // 分享好友(微信好友或qq好友) | ||
| 456 | - wx.updateAppMessageShareData(shareData); | ||
| 457 | - // 分享到朋友圈或qq空间 | ||
| 458 | - wx.updateTimelineShareData(shareData); | ||
| 459 | - // 分享到腾讯微博 | ||
| 460 | - wx.onMenuShareWeibo(shareData); | ||
| 461 | - // 初始化地图 | ||
| 462 | - this.initMap(); | ||
| 463 | - // this.setMapBoundary(); | ||
| 464 | - // 使用之前获取当前地址,判断当前是否能够获取经纬度 | ||
| 465 | - // wx.getLocation({ | ||
| 466 | - // type: 'wgs84', // 默认为wgs84的gps坐标,如果要返回直接给openLocation用的火星坐标,可传入'gcj02' | ||
| 467 | - // success: (res) => { | ||
| 468 | - // var latitude = res.latitude; // 纬度,浮点数,范围为90 ~ -90 | ||
| 469 | - // var longitude = res.longitude; // 经度,浮点数,范围为180 ~ -180。 | ||
| 470 | - // var speed = res.speed; // 速度,以米/每秒计 | ||
| 471 | - // var accuracy = res.accuracy; // 位置精度 | ||
| 472 | - // this.current_lng = GPS.gcj_encrypt(latitude, longitude).lon; | ||
| 473 | - // this.current_lat = GPS.gcj_encrypt(latitude, longitude).lat; | ||
| 474 | - // }, | ||
| 475 | - // }); | ||
| 476 | - // 设置贴片地图 | ||
| 477 | - this.setTitleLayer(); | ||
| 478 | - // 地图标题 | ||
| 479 | - document.title = data.map.map_title; | ||
| 480 | - // | ||
| 481 | - // setTimeout(() => { | ||
| 482 | - // this.info_height = (0.5 * window.innerHeight); | ||
| 483 | - // // 浮动面板样式 | ||
| 484 | - // $('.van-floating-panel__content').css('borderRadius', '1.5rem'); | ||
| 485 | - // }, 2000); | ||
| 486 | - // 初始化步行导航插件时指定面板容器 | ||
| 487 | - this.walking = new AMap.Walking({ | ||
| 488 | - map: this.map, | ||
| 489 | - // panel: 'walking-panel', // 必须指定存在的DOM元素ID | ||
| 490 | - hideMarkers: false, // 设置隐藏路径规划的起始点图标 | ||
| 491 | - isOutline: true, // 使用map属性时,绘制的规划线路是否显示描边 | ||
| 492 | - autoFitView: true, // 是否自动调整地图视野到显示的路线 | ||
| 493 | - }); | ||
| 494 | }, | 451 | }, |
| 495 | // keep-alive 组件激活时调用 | 452 | // keep-alive 组件激活时调用 |
| 496 | activated() { | 453 | activated() { |
| 497 | - // 组件被激活时,不需要重新初始化地图,保持之前的状态 | 454 | + // 组件被激活时,检查地图是否已经初始化 |
| 498 | - console.log('地图组件已激活,保持之前状态'); | 455 | + console.log('地图组件已激活'); |
| 456 | + | ||
| 499 | // 确保当前页面在缓存列表中 | 457 | // 确保当前页面在缓存列表中 |
| 500 | const store = mainStore(); | 458 | const store = mainStore(); |
| 501 | if (!store.keepPages.includes('CheckinMap')) { | 459 | if (!store.keepPages.includes('CheckinMap')) { |
| 502 | store.keepPages.push('CheckinMap'); | 460 | store.keepPages.push('CheckinMap'); |
| 503 | } | 461 | } |
| 462 | + | ||
| 463 | + // 如果地图还未初始化或加载失败,重新尝试加载 | ||
| 464 | + if (!this.map || this.mapLoadingState.isError) { | ||
| 465 | + console.log('地图未初始化或加载失败,重新加载'); | ||
| 466 | + this.mapLoadingState.isLoading = true; | ||
| 467 | + this.mapLoadingState.isError = false; | ||
| 468 | + this.initializeMapWithRetry().catch(error => { | ||
| 469 | + console.error('重新激活时地图加载失败:', error); | ||
| 470 | + this.handleMapLoadError(error); | ||
| 471 | + }); | ||
| 472 | + } else { | ||
| 473 | + // 地图已经初始化,重新设置地图大小以适应容器 | ||
| 474 | + this.$nextTick(() => { | ||
| 475 | + this.map.getSize(); | ||
| 476 | + }); | ||
| 477 | + } | ||
| 478 | + | ||
| 504 | // 重置page-info组件状态,关闭浮动面板 | 479 | // 重置page-info组件状态,关闭浮动面板 |
| 505 | this.info_height = 0; | 480 | this.info_height = 0; |
| 506 | this.itemInfo = {}; | 481 | this.itemInfo = {}; |
| ... | @@ -511,12 +486,6 @@ export default { | ... | @@ -511,12 +486,6 @@ export default { |
| 511 | // 还原标记点样式 | 486 | // 还原标记点样式 |
| 512 | this.resetMarkStyle(); | 487 | this.resetMarkStyle(); |
| 513 | }); | 488 | }); |
| 514 | - // 如果地图已经初始化,重新设置地图大小以适应容器 | ||
| 515 | - if (this.map) { | ||
| 516 | - this.$nextTick(() => { | ||
| 517 | - this.map.getSize(); | ||
| 518 | - }); | ||
| 519 | - } | ||
| 520 | }, | 489 | }, |
| 521 | // keep-alive 组件停用时调用 | 490 | // keep-alive 组件停用时调用 |
| 522 | deactivated() { | 491 | deactivated() { |
| ... | @@ -539,6 +508,151 @@ export default { | ... | @@ -539,6 +508,151 @@ export default { |
| 539 | methods: { | 508 | methods: { |
| 540 | ...mapActions(mainStore, ['changeAudio', 'changeAudioSrc', 'changeAudioStatus']), | 509 | ...mapActions(mainStore, ['changeAudio', 'changeAudioSrc', 'changeAudioStatus']), |
| 541 | /** | 510 | /** |
| 511 | + * 计算重试延迟时间(指数退避算法) | ||
| 512 | + * @param {number} retryCount - 当前重试次数 | ||
| 513 | + * @returns {number} 延迟时间(毫秒) | ||
| 514 | + */ | ||
| 515 | + calculateRetryDelay(retryCount) { | ||
| 516 | + // 基础延迟时间:1秒,每次重试翻倍,最大不超过10秒 | ||
| 517 | + const baseDelay = 1000; | ||
| 518 | + const maxDelay = 10000; | ||
| 519 | + const delay = Math.min(baseDelay * Math.pow(2, retryCount), maxDelay); | ||
| 520 | + // 添加随机抖动,避免所有用户同时重试 | ||
| 521 | + const jitter = Math.random() * 0.3 * delay; | ||
| 522 | + return delay + jitter; | ||
| 523 | + }, | ||
| 524 | + | ||
| 525 | + /** | ||
| 526 | + * 重试加载地图 | ||
| 527 | + */ | ||
| 528 | + async retryLoadMap() { | ||
| 529 | + if (this.mapLoadingState.retryCount >= this.mapLoadingState.maxRetries) { | ||
| 530 | + this.mapLoadingState.errorMessage = '已达到最大重试次数,请稍后再试'; | ||
| 531 | + return; | ||
| 532 | + } | ||
| 533 | + | ||
| 534 | + this.mapLoadingState.isLoading = true; | ||
| 535 | + this.mapLoadingState.isError = false; | ||
| 536 | + this.mapLoadingState.retryCount++; | ||
| 537 | + | ||
| 538 | + // 计算延迟时间 | ||
| 539 | + const delay = this.calculateRetryDelay(this.mapLoadingState.retryCount - 1); | ||
| 540 | + | ||
| 541 | + try { | ||
| 542 | + // 等待延迟时间 | ||
| 543 | + await new Promise(resolve => setTimeout(resolve, delay)); | ||
| 544 | + | ||
| 545 | + // 重新初始化地图 | ||
| 546 | + await this.initializeMapWithRetry(); | ||
| 547 | + } catch (error) { | ||
| 548 | + console.error('重试加载地图失败:', error); | ||
| 549 | + this.handleMapLoadError(error); | ||
| 550 | + } | ||
| 551 | + }, | ||
| 552 | + | ||
| 553 | + /** | ||
| 554 | + * 处理地图加载错误 | ||
| 555 | + * @param {Error} error - 错误对象 | ||
| 556 | + */ | ||
| 557 | + handleMapLoadError(error) { | ||
| 558 | + this.mapLoadingState.isLoading = false; | ||
| 559 | + this.mapLoadingState.isError = true; | ||
| 560 | + | ||
| 561 | + // 根据错误类型设置不同的错误信息 | ||
| 562 | + if (error.message && error.message.includes('quota')) { | ||
| 563 | + this.mapLoadingState.errorMessage = '地图服务繁忙,请稍后重试'; | ||
| 564 | + } else if (error.message && error.message.includes('network')) { | ||
| 565 | + this.mapLoadingState.errorMessage = '网络连接异常,请检查网络后重试'; | ||
| 566 | + } else { | ||
| 567 | + this.mapLoadingState.errorMessage = '地图加载失败,请重试'; | ||
| 568 | + } | ||
| 569 | + }, | ||
| 570 | + | ||
| 571 | + /** | ||
| 572 | + * 带重试机制的地图初始化 | ||
| 573 | + */ | ||
| 574 | + async initializeMapWithRetry() { | ||
| 575 | + try { | ||
| 576 | + const AMap = await AMapLoader.load({ | ||
| 577 | + key: '17b8fc386104b89db88b60b049a6dbce', | ||
| 578 | + version: '2.0', | ||
| 579 | + plugins: ['AMap.ElasticMarker','AMap.ImageLayer','AMap.ToolBar','AMap.IndoorMap','AMap.Walking','AMap.Geolocation'] | ||
| 580 | + }); | ||
| 581 | + | ||
| 582 | + // 获取地图数据 | ||
| 583 | + const code = this.$route.query.id; | ||
| 584 | + const { data } = await mapAPI({ i: code }); | ||
| 585 | + | ||
| 586 | + // 设置地图数据 | ||
| 587 | + this.navBarList = data.list; | ||
| 588 | + this.mapTiles = data.level; | ||
| 589 | + this.navKey = data.list.length ? data.list[0]['id'] : 0; | ||
| 590 | + this.navList = data.list.length ? data.list.filter(item => item.id === this.navKey)[0]['list'] : []; | ||
| 591 | + this.data_center = data.map.center.map(item => Number(item)); | ||
| 592 | + this.data_zoom = data.map.zoom; | ||
| 593 | + this.data_rotation = data.map.rotation; | ||
| 594 | + this.data_zooms = data.map.zooms.map(item => Number(item)); | ||
| 595 | + this.data_paths = data.map.path ? data.map.path : {}; | ||
| 596 | + this.data_logo = data.map.map_logo ? data.map.map_logo : ''; | ||
| 597 | + this.point_range = data.map.map_range ? data.map.map_range : []; | ||
| 598 | + | ||
| 599 | + if (data.map.map_layers) { | ||
| 600 | + if (data.map.map_layers === 'satellite') { | ||
| 601 | + this.data_layers = [new AMap.TileLayer.Satellite(), new AMap.TileLayer.RoadNet()]; | ||
| 602 | + } else { | ||
| 603 | + this.data_layers = []; | ||
| 604 | + } | ||
| 605 | + } | ||
| 606 | + | ||
| 607 | + if (data.map.path) { | ||
| 608 | + for (const key in data.map.path) { | ||
| 609 | + const element = data.map.path[key]; | ||
| 610 | + this.data_path_list.push({ | ||
| 611 | + name: key, | ||
| 612 | + path: element, | ||
| 613 | + status: true | ||
| 614 | + }); | ||
| 615 | + } | ||
| 616 | + } | ||
| 617 | + | ||
| 618 | + // 设置页面标题 | ||
| 619 | + document.title = data.map.map_title; | ||
| 620 | + | ||
| 621 | + // 微信分享配置 | ||
| 622 | + const shareData = { | ||
| 623 | + title: data.map.map_title, | ||
| 624 | + desc: '别院地图', | ||
| 625 | + link: location.origin + location.pathname + location.hash, | ||
| 626 | + imgUrl: '', | ||
| 627 | + success: function () {} | ||
| 628 | + }; | ||
| 629 | + wx.updateAppMessageShareData(shareData); | ||
| 630 | + wx.updateTimelineShareData(shareData); | ||
| 631 | + wx.onMenuShareWeibo(shareData); | ||
| 632 | + | ||
| 633 | + // 初始化地图 | ||
| 634 | + this.initMap(); | ||
| 635 | + this.setTitleLayer(); | ||
| 636 | + | ||
| 637 | + // 初始化步行导航 | ||
| 638 | + this.walking = new AMap.Walking({ | ||
| 639 | + map: this.map, | ||
| 640 | + hideMarkers: false, | ||
| 641 | + isOutline: true, | ||
| 642 | + autoFitView: true, | ||
| 643 | + }); | ||
| 644 | + | ||
| 645 | + // 地图加载成功 | ||
| 646 | + this.mapLoadingState.isLoading = false; | ||
| 647 | + this.mapLoadingState.isError = false; | ||
| 648 | + this.mapLoadingState.retryCount = 0; | ||
| 649 | + | ||
| 650 | + } catch (error) { | ||
| 651 | + console.error('地图初始化失败:', error); | ||
| 652 | + throw error; // 重新抛出错误,让调用方处理 | ||
| 653 | + } | ||
| 654 | + }, | ||
| 655 | + /** | ||
| 542 | * 创建标记点的HTML内容,包含图标和文字 | 656 | * 创建标记点的HTML内容,包含图标和文字 |
| 543 | * @param {Object} entityInfo - 实体信息 | 657 | * @param {Object} entityInfo - 实体信息 |
| 544 | * @param {String} textDirection - 文字方向 ('vertical' 或 'horizontal') | 658 | * @param {String} textDirection - 文字方向 ('vertical' 或 'horizontal') |
| ... | @@ -1510,4 +1624,68 @@ export default { | ... | @@ -1510,4 +1624,68 @@ export default { |
| 1510 | .van-floating-panel__header-bar { | 1624 | .van-floating-panel__header-bar { |
| 1511 | background: none; | 1625 | background: none; |
| 1512 | } | 1626 | } |
| 1627 | + | ||
| 1628 | +/* 地图加载状态样式 */ | ||
| 1629 | +.map-loading-overlay { | ||
| 1630 | + position: fixed; | ||
| 1631 | + top: 0; | ||
| 1632 | + left: 0; | ||
| 1633 | + width: 100%; | ||
| 1634 | + height: 100%; | ||
| 1635 | + background-color: rgba(255, 255, 255, 0.9); | ||
| 1636 | + display: flex; | ||
| 1637 | + justify-content: center; | ||
| 1638 | + align-items: center; | ||
| 1639 | + z-index: 9999; | ||
| 1640 | +} | ||
| 1641 | + | ||
| 1642 | +.loading-content { | ||
| 1643 | + display: flex; | ||
| 1644 | + flex-direction: column; | ||
| 1645 | + align-items: center; | ||
| 1646 | + text-align: center; | ||
| 1647 | +} | ||
| 1648 | + | ||
| 1649 | +.loading-text { | ||
| 1650 | + margin-top: 1rem; | ||
| 1651 | + color: #666; | ||
| 1652 | + font-size: 0.9rem; | ||
| 1653 | +} | ||
| 1654 | + | ||
| 1655 | +/* 地图加载错误状态样式 */ | ||
| 1656 | +.map-error-overlay { | ||
| 1657 | + position: fixed; | ||
| 1658 | + top: 0; | ||
| 1659 | + left: 0; | ||
| 1660 | + width: 100%; | ||
| 1661 | + height: 100%; | ||
| 1662 | + background-color: rgba(255, 255, 255, 0.95); | ||
| 1663 | + display: flex; | ||
| 1664 | + justify-content: center; | ||
| 1665 | + align-items: center; | ||
| 1666 | + z-index: 9999; | ||
| 1667 | +} | ||
| 1668 | + | ||
| 1669 | +.error-content { | ||
| 1670 | + display: flex; | ||
| 1671 | + flex-direction: column; | ||
| 1672 | + align-items: center; | ||
| 1673 | + text-align: center; | ||
| 1674 | + padding: 2rem; | ||
| 1675 | + max-width: 300px; | ||
| 1676 | +} | ||
| 1677 | + | ||
| 1678 | +.error-title { | ||
| 1679 | + margin: 1rem 0 0.5rem 0; | ||
| 1680 | + font-size: 1.1rem; | ||
| 1681 | + font-weight: 600; | ||
| 1682 | + color: #333; | ||
| 1683 | +} | ||
| 1684 | + | ||
| 1685 | +.error-message { | ||
| 1686 | + margin: 0.5rem 0 1.5rem 0; | ||
| 1687 | + color: #666; | ||
| 1688 | + font-size: 0.9rem; | ||
| 1689 | + line-height: 1.4; | ||
| 1690 | +} | ||
| 1513 | </style> | 1691 | </style> | ... | ... |
-
Please register or login to post a comment