| | |
| | | let marker: AnyMap; |
| | | let rangeCircle: AnyMap; |
| | | let geocoder: AnyMap; |
| | | /** |
| | | * 组件是否已卸载。 |
| | | * |
| | | * 百度地图 SDK 是异步加载的(loadBaiduMapSdk 内部创建 script 标签)。 |
| | | * 用户打开定位后如果很快点「确认」或「取消」,弹窗关闭 → 本组件卸载 → 地图容器从 DOM 移除, |
| | | * 但加载流程仍在 await 中继续,等 SDK 就绪后会执行 new BMapGL.Map(mapContainer.value), |
| | | * 此时 mapContainer 已是 null,百度地图内部会抛 |
| | | * "Cannot read properties of null (reading 'Map')"。 |
| | | * 用这个标志位让异步流程在卸载后立即退出。 |
| | | */ |
| | | let disposed = false; |
| | | |
| | | const baiduMapKey = String(import.meta.env.VITE_BAIDU_MAP_KEY ?? '').trim(); |
| | | const hasMapConfig = computed(() => Boolean(baiduMapKey)); |
| | |
| | | loading.value = true; |
| | | try { |
| | | await loadBaiduMapSdk(15_000); |
| | | // 卸载后立即退出:此时地图容器已从 DOM 移除,继续初始化会抛 null.Map |
| | | if (disposed || !mapContainer.value) { |
| | | return; |
| | | } |
| | | await nextTick(); |
| | | if (disposed || !mapContainer.value) { |
| | | return; |
| | | } |
| | | // SDK 回调触发但 BMapGL 未挂载(常见于 ak 无效 / 域名未授权 / 被网络拦截) |
| | | if (!window.BMapGL) { |
| | | message.error('百度地图加载失败,请检查地图 Key 配置或网络'); |
| | | return; |
| | | } |
| | | const hasCoordinates = |
| | | Number.isFinite(props.longitude) && Number.isFinite(props.latitude); |
| | | const center = hasCoordinates |
| | | ? wgs84ToBd09(Number(props.longitude), Number(props.latitude)) |
| | | : DEFAULT_CENTER; |
| | | map = new window.BMapGL.Map(mapContainer.value); |
| | | if (disposed) { |
| | | // 初始化过程中被卸载,直接销毁,避免残留实例 |
| | | map?.destroy?.(); |
| | | map = undefined; |
| | | return; |
| | | } |
| | | map.centerAndZoom( |
| | | new window.BMapGL.Point(center[0], center[1]), |
| | | hasCoordinates ? 19 : 12, |
| | |
| | | onMounted(initializeMap); |
| | | |
| | | onBeforeUnmount(() => { |
| | | map?.clearOverlays?.(); |
| | | map?.destroy?.(); |
| | | // 先置标志位,让还在 await 中的 initializeMap 立即退出 |
| | | disposed = true; |
| | | try { |
| | | map?.clearOverlays?.(); |
| | | map?.destroy?.(); |
| | | } catch (error) { |
| | | // 地图实例若处于半初始化状态,destroy 内部可能报错,这里吞掉避免影响弹窗关闭 |
| | | console.warn('[LocationMapPicker] 销毁地图实例失败', error); |
| | | } |
| | | map = undefined; |
| | | marker = undefined; |
| | | rangeCircle = undefined; |