Skip to content

Commit 20102e4

Browse files
committed
feat(map): 搜索用 Google 数据,底图保持 CARTO/高德
移除 Google Mutant 底图升级;地点搜索与逆地理编码统一走 Google Places, 国内/国外均使用高德或 CARTO 瓦片显示,搜索与底图数据源分离。
1 parent ef3b1e4 commit 20102e4

3 files changed

Lines changed: 42 additions & 142 deletions

File tree

src/composables/useMapRegion.ts

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import { computed, ref } from 'vue'
22
import { isInChina } from '@/constants/map'
33
import {
44
type MapRegionMode,
5-
getProviderLabel,
5+
getBaseMapLabel,
66
getRegionLabel,
77
persistMapRegion,
88
readStoredMapRegion,
@@ -14,7 +14,9 @@ let regionPreferenceLocked = Boolean(readStoredMapRegion())
1414

1515
export function useMapRegion() {
1616
const regionLabel = computed(() => getRegionLabel(mapRegion.value))
17-
const providerLabel = computed(() => getProviderLabel(mapRegion.value))
17+
const baseMapLabel = computed(() => getBaseMapLabel(mapRegion.value))
18+
/** @deprecated 使用 baseMapLabel */
19+
const providerLabel = baseMapLabel
1820
const isChinaMode = computed(() => mapRegion.value === 'china')
1921

2022
function setMapRegion(mode: MapRegionMode, persist = true) {
@@ -42,6 +44,7 @@ export function useMapRegion() {
4244
mapRegion,
4345
regionMenuOpen,
4446
regionLabel,
47+
baseMapLabel,
4548
providerLabel,
4649
isChinaMode,
4750
setMapRegion,

src/utils/mapProviders.ts

Lines changed: 21 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,9 @@ import L from 'leaflet'
22
import { runtimeConfig } from '@/config/app'
33
import { DEFAULT_CENTER, DEFAULT_ZOOM } from '@/constants/map'
44
import { gcj02ToWgs84, wgs84ToGcj02 } from '@/utils/locationParser'
5-
import { loadGoogleMapsJs } from '@/utils/googleMapsLoader'
65
import {
76
getAmapTileStyleParam,
87
getCartoVariant,
9-
getGoogleMapStyle,
108
type MapThemeId,
119
} from '@/utils/mapStyles'
1210

@@ -15,8 +13,6 @@ export type MapSearchProvider = 'amap' | 'google'
1513

1614
export const MAP_REGION_STORAGE_KEY = 'workwork-map-region'
1715

18-
const LAYER_LOAD_TIMEOUT_MS = 6000
19-
2016
export const CHINA_DEFAULT_CENTER = { lat: 31.2304, lng: 121.4737 }
2117
export const GLOBAL_DEFAULT_CENTER = DEFAULT_CENTER
2218

@@ -31,8 +27,15 @@ export function persistMapRegion(mode: MapRegionMode): void {
3127
localStorage.setItem(MAP_REGION_STORAGE_KEY, mode)
3228
}
3329

34-
export function getSearchProviderForRegion(mode: MapRegionMode): MapSearchProvider {
35-
return mode === 'china' ? 'amap' : 'google'
30+
/** 地点搜索/地理编码统一走 Google(有 Key 时) */
31+
export function getMapSearchProvider(): MapSearchProvider {
32+
if (runtimeConfig.maps.googleMapsKey) return 'google'
33+
return 'amap'
34+
}
35+
36+
/** @deprecated 搜索已与区域解耦,请使用 getMapSearchProvider */
37+
export function getSearchProviderForRegion(_mode: MapRegionMode): MapSearchProvider {
38+
return getMapSearchProvider()
3639
}
3740

3841
export function getDefaultCenterForRegion(mode: MapRegionMode): { lat: number; lng: number } {
@@ -43,8 +46,18 @@ export function getRegionLabel(mode: MapRegionMode): string {
4346
return mode === 'china' ? '国内' : '国外'
4447
}
4548

49+
/** 底图瓦片来源(不含搜索数据源) */
50+
export function getBaseMapLabel(mode: MapRegionMode): string {
51+
return mode === 'china' ? '高德地图' : 'CARTO'
52+
}
53+
54+
export function getSearchProviderLabel(): string {
55+
return runtimeConfig.maps.googleMapsKey ? 'Google 搜索' : '高德搜索'
56+
}
57+
58+
/** @deprecated 使用 getBaseMapLabel */
4659
export function getProviderLabel(mode: MapRegionMode): string {
47-
return mode === 'china' ? '高德地图' : 'Google Maps'
60+
return getBaseMapLabel(mode)
4861
}
4962

5063
/** WGS84 存储坐标 → 当前底图显示坐标 */
@@ -117,58 +130,12 @@ export function createFastBaseLayerForRegion(
117130
return mode === 'china' ? createAmapBaseLayer(theme) : createCartoLayerForTheme(theme)
118131
}
119132

120-
async function withTimeout<T>(promise: Promise<T>, fallback: T, ms = LAYER_LOAD_TIMEOUT_MS): Promise<T> {
121-
return Promise.race([
122-
promise,
123-
new Promise<T>((resolve) => {
124-
window.setTimeout(() => resolve(fallback), ms)
125-
}),
126-
])
127-
}
128-
129-
async function createGoogleMutantLayer(theme: MapThemeId = 'journal'): Promise<L.Layer | null> {
130-
if (!runtimeConfig.maps.googleMapsKey) return null
131-
132-
const ready = await loadGoogleMapsJs()
133-
if (!ready) return null
134-
135-
try {
136-
const { default: GoogleMutant } = await import(
137-
'leaflet.gridlayer.googlemutant/src/Leaflet.GoogleMutant.mjs'
138-
)
139-
return new GoogleMutant({
140-
type: 'roadmap',
141-
styles: getGoogleMapStyle(theme),
142-
maxZoom: 19,
143-
}) as unknown as L.Layer
144-
} catch (error) {
145-
console.warn('Google Mutant layer failed:', error)
146-
return null
147-
}
148-
}
149-
150-
/** 国外模式尝试加载 Google 底图,超时或失败则回退 CARTO */
151-
export async function createGoogleBaseLayerWithFallback(theme: MapThemeId = 'journal'): Promise<L.Layer> {
152-
const fallback = createCartoLayerForTheme(theme)
153-
const googleLayer = await withTimeout(createGoogleMutantLayer(theme), null)
154-
return googleLayer ?? fallback
155-
}
156-
157133
export async function createBaseLayerForRegion(
158134
mode: MapRegionMode,
159135
options: { preferFast?: boolean; theme?: MapThemeId } = {}
160136
): Promise<L.Layer> {
161137
const theme = options.theme ?? 'journal'
162-
163-
if (mode === 'china') {
164-
return createAmapBaseLayer(theme)
165-
}
166-
167-
if (options.preferFast) {
168-
return createCartoLayerForTheme(theme)
169-
}
170-
171-
return createGoogleBaseLayerWithFallback(theme)
138+
return createFastBaseLayerForRegion(mode, theme)
172139
}
173140

174141
export function getInitialZoom(): number {

src/views/NomadMapView.vue

Lines changed: 16 additions & 86 deletions
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,12 @@ import { useMapRegion } from '@/composables/useMapRegion'
1515
import { useMapTheme } from '@/composables/useMapTheme'
1616
import { runtimeConfig } from '@/config/app'
1717
import {
18-
createBaseLayerForRegion,
1918
createFastBaseLayerForRegion,
2019
fromMapDisplayCoords,
2120
getDefaultCenterForRegion,
2221
getInitialZoom,
23-
getSearchProviderForRegion,
22+
getMapSearchProvider,
23+
getSearchProviderLabel,
2424
toMapDisplayCoords,
2525
type MapRegionMode,
2626
} from '@/utils/mapProviders'
@@ -49,7 +49,7 @@ const {
4949
mapRegion,
5050
regionMenuOpen,
5151
regionLabel,
52-
providerLabel,
52+
baseMapLabel,
5353
setMapRegion,
5454
toggleRegionMenu,
5555
closeRegionMenu,
@@ -91,36 +91,30 @@ const addSpotLng = ref(getDefaultCenterForRegion(mapRegion.value).lng)
9191
// 用于外部地图搜索
9292
const searchName = ref('')
9393
94-
// 搜索提供商和结果(随国内/国外模式自动切换)
95-
const searchProvider = computed(() => getSearchProviderForRegion(mapRegion.value))
94+
// 搜索统一走 Google Places(底图与搜索数据源分离)
95+
const searchProvider = computed(() => getMapSearchProvider())
96+
const searchProviderLabel = computed(() => getSearchProviderLabel())
9697
const searchResults = ref<PlaceSearchResult[]>([])
9798
const searchEmpty = ref(false)
9899
const isSearching = ref(false)
99100
const detailRegionLoading = ref(false)
100101
const showLoginReminder = ref(false)
101102
const switchingRegion = ref(false)
102-
const usingGoogleBaseMap = ref(false)
103103
104104
const hasGoogleMapsKey = computed(() => Boolean(runtimeConfig.maps.googleMapsKey))
105-
const hasAmapKey = computed(() => Boolean(runtimeConfig.maps.amapKey))
106105
107106
const searchEmptyMessage = computed(() => {
108-
if (mapRegion.value === 'china') {
109-
return hasAmapKey.value
110-
? '未找到相关地点。可尝试更简短的关键词、补充城市名,或粘贴高德/百度地图分享链接。'
111-
: '未找到相关地点。请配置高德 Key,或粘贴地图分享链接。'
107+
if (hasGoogleMapsKey.value) {
108+
return '未找到相关地点。可尝试更简短的关键词、补充城市或地区名,也可以直接粘贴 Google 地图分享链接。'
112109
}
113-
114-
return hasGoogleMapsKey.value
115-
? '未找到相关地点。可尝试更简短的关键词、补充城市或地区名,也可以直接粘贴 Google 地图分享链接。'
116-
: '未找到相关地点。请配置 Google Maps Key,或粘贴 Google 地图分享链接。'
110+
return '未找到相关地点。请配置 Google Maps Key,或粘贴地图分享链接。'
117111
})
118112
119113
const searchHintMessage = computed(() => {
120-
if (mapRegion.value === 'china') {
121-
return '当前使用高德地图搜索中国大陆地点,也可直接粘贴地图链接。'
114+
if (hasGoogleMapsKey.value) {
115+
return '地点搜索使用 Google Maps 数据,底图保持 CARTO/高德瓦片显示。也可直接粘贴地图链接。'
122116
}
123-
return '当前使用 Google Maps 搜索海外地点,也可直接粘贴 Google 地图分享链接'
117+
return '请配置 Google Maps Key 以启用地点搜索'
124118
})
125119
126120
function displayLatLng(lat: number, lng: number): [number, number] {
@@ -430,63 +424,14 @@ function applyFastBaseLayer(mode: MapRegionMode = mapRegion.value, theme: MapThe
430424
const layer = createFastBaseLayerForRegion(mode, theme)
431425
baseTileLayer = layer
432426
layer.addTo(mapInstance)
433-
usingGoogleBaseMap.value = false
434427
ensureMarkerPaneOnTop()
435428
}
436429
437-
async function swapBaseLayer(
438-
mode: MapRegionMode = mapRegion.value,
439-
options: { preferFast?: boolean; theme?: MapThemeId } = {}
440-
) {
441-
if (!mapInstance) return
442-
443-
const theme = options.theme ?? mapTheme.value
444-
445-
if (baseTileLayer) {
446-
mapInstance.removeLayer(baseTileLayer)
447-
baseTileLayer = null
448-
}
449-
450-
if (options.preferFast) {
451-
applyFastBaseLayer(mode, theme)
452-
return
453-
}
454-
455-
try {
456-
const layer = await createBaseLayerForRegion(mode, { theme })
457-
baseTileLayer = layer
458-
layer.addTo(mapInstance)
459-
usingGoogleBaseMap.value = mode === 'global' && layer.constructor.name === 'GoogleMutant'
460-
ensureMarkerPaneOnTop(true)
461-
} catch (error) {
462-
console.warn('swapBaseLayer failed, using fast fallback:', error)
463-
applyFastBaseLayer(mode, theme)
464-
}
465-
}
466-
467-
async function upgradeToGoogleBaseMap(theme: MapThemeId = mapTheme.value) {
468-
if (!mapInstance || mapRegion.value !== 'global' || usingGoogleBaseMap.value) return
469-
470-
try {
471-
await swapBaseLayer('global', { theme })
472-
void nextTick(refreshMapTiles)
473-
} catch {
474-
// 保持 CARTO 底图即可
475-
}
476-
}
477-
478430
function switchMapTheme(theme: MapThemeId) {
479431
if (theme === mapTheme.value || !mapInstance) return
480432
481433
setMapTheme(theme)
482434
applyFastBaseLayer(mapRegion.value, theme)
483-
484-
if (mapRegion.value === 'global') {
485-
scheduleIdle(() => {
486-
void upgradeToGoogleBaseMap(theme)
487-
}, 400)
488-
}
489-
490435
void nextTick(refreshMapTiles)
491436
}
492437
@@ -502,9 +447,6 @@ async function autoLocateOnIdle() {
502447
503448
if (mapRegion.value !== prevRegion) {
504449
applyFastBaseLayer(mapRegion.value)
505-
scheduleIdle(() => {
506-
void upgradeToGoogleBaseMap()
507-
}, 4000)
508450
}
509451
510452
setUserLocationMarker(userPos)
@@ -535,12 +477,6 @@ async function switchMapRegion(mode: MapRegionMode) {
535477
if (userLocation.value) setUserLocationMarker(userLocation.value)
536478
if (showAddSpot.value) updateAddPreviewMarker()
537479
void nextTick(refreshMapTiles)
538-
539-
if (mode === 'global') {
540-
scheduleIdle(() => {
541-
void upgradeToGoogleBaseMap()
542-
}, 3000)
543-
}
544480
} finally {
545481
switchingRegion.value = false
546482
mapInitializing.value = false
@@ -603,12 +539,6 @@ async function initMap() {
603539
refreshMarkers()
604540
})
605541
606-
if (mapRegion.value === 'global') {
607-
scheduleIdle(() => {
608-
void upgradeToGoogleBaseMap()
609-
}, 5000)
610-
}
611-
612542
scheduleIdle(() => {
613543
void autoLocateOnIdle()
614544
}, 2500)
@@ -1219,7 +1149,7 @@ onUnmounted(() => {
12191149
@click="switchMapRegion('china')"
12201150
>
12211151
<span class="map-region-option-name">国内</span>
1222-
<span class="map-region-option-desc">高德地图 · 中国大陆</span>
1152+
<span class="map-region-option-desc">高德底图 · 中国大陆坐标</span>
12231153
</button>
12241154
<button
12251155
type="button"
@@ -1229,7 +1159,7 @@ onUnmounted(() => {
12291159
@click="switchMapRegion('global')"
12301160
>
12311161
<span class="map-region-option-name">国外</span>
1232-
<span class="map-region-option-desc">Google Maps · 海外地区</span>
1162+
<span class="map-region-option-desc">CARTO 底图 · 海外坐标系</span>
12331163
</button>
12341164
</div>
12351165
</Transition>
@@ -1457,7 +1387,7 @@ onUnmounted(() => {
14571387
<div class="search-toolbar">
14581388
<div class="search-provider-badge">
14591389
<span class="search-provider-badge-label">当前搜索</span>
1460-
<span class="search-provider-badge-value">{{ providerLabel }}</span>
1390+
<span class="search-provider-badge-value">{{ searchProviderLabel }}</span>
14611391
</div>
14621392
<button type="button" class="search-submit-btn" @click="searchPOI" :disabled="isSearching">
14631393
<LoadingSpinner v-if="isSearching" size="sm" inline label="搜索中" />
@@ -1522,7 +1452,7 @@ onUnmounted(() => {
15221452

15231453
<!-- 底部归属信息 -->
15241454
<div v-if="mapReady" class="map-engine-badge">
1525-
{{ themeLabel }} · {{ providerLabel }}{{ mapRegion === 'global' && !usingGoogleBaseMap ? ' (加载中)' : '' }} · Leaflet
1455+
{{ themeLabel }} · {{ baseMapLabel }} · {{ searchProviderLabel }} · Leaflet
15261456
</div>
15271457
</div>
15281458
</template>

0 commit comments

Comments
 (0)