diff --git a/src/components/TiandituPickMap.vue b/src/components/TiandituPickMap.vue index 38c53fd..00dc772 100644 --- a/src/components/TiandituPickMap.vue +++ b/src/components/TiandituPickMap.vue @@ -5,6 +5,7 @@ import { getTiandituKey, invalidateMapSize, loadTianditu, + normalizeTiandituPois, parseTiandituPoiLonlat, SUZHOU_MAP_CENTER, SUZHOU_MAP_ZOOM, @@ -99,15 +100,18 @@ function initLocalSearch(T: NonNullable) { pageCapacity: 10, onSearchComplete: (result) => { searchLoading.value = false - if (result.getResultType() !== 1) { + const resultType = Number(result.getResultType()) + if (resultType !== 1) { searchResults.value = [] ElMessage.warning('未找到相关地点,请换个关键词试试') return } - const pois = result.getPois() || [] + const pois = normalizeTiandituPois(result.getPois()).filter((poi) => + Boolean(parseTiandituPoiLonlat(poi)), + ) searchResults.value = pois if (!pois.length) { - ElMessage.warning('未找到相关地点,请换个关键词试试') + ElMessage.warning('未找到有效坐标的地点,请换个关键词试试') } }, }) @@ -129,7 +133,7 @@ function runSearch() { } function selectPoi(poi: TiandituSearchPoi) { - const coord = parseTiandituPoiLonlat(poi.lonlat) + const coord = parseTiandituPoiLonlat(poi) if (!coord) { ElMessage.warning('该地点坐标无效,请换一条结果') return diff --git a/src/utils/tiandituMap.ts b/src/utils/tiandituMap.ts index 1fc33ef..8f29af8 100644 --- a/src/utils/tiandituMap.ts +++ b/src/utils/tiandituMap.ts @@ -32,12 +32,15 @@ declare global { export interface TiandituSearchPoi { name: string address?: string - lonlat: string + lonlat?: string + lon?: number | string + lng?: number | string + lat?: number | string } export interface TiandituLocalSearchResult { - getResultType(): number - getPois(): TiandituSearchPoi[] + getResultType(): number | string + getPois(): TiandituSearchPoi[] | Record | false | null } export interface TiandituLocalSearchConfig { @@ -276,16 +279,53 @@ export function shortenSchoolMapLabel(name: string, max = 12): string { return t.length > max ? `${t.slice(0, max)}…` : t } -/** 解析天地图 POI 的 lonlat 字段(格式:"经度 纬度") */ -export function parseTiandituPoiLonlat(lonlat: string): { lng: number; lat: number } | null { - const parts = lonlat.trim().split(/\s+/) - if (parts.length < 2) return null - const lng = Number(parts[0]) - const lat = Number(parts[1]) +function parseLonlatPair(first: unknown, second: unknown): { lng: number; lat: number } | null { + let lng = Number(first) + let lat = Number(second) if (!Number.isFinite(lng) || !Number.isFinite(lat)) return null + // 部分结果可能为 "纬度,经度",按中国范围自动纠正 + if (lng <= 60 && lat >= 70) { + ;[lng, lat] = [lat, lng] + } return { lng, lat } } +/** 解析天地图 POI 坐标(支持 "经度 纬度"、"经度,纬度" 及 lon/lat 字段) */ +export function parseTiandituPoiLonlat( + poi: TiandituSearchPoi | string, +): { lng: number; lat: number } | null { + if (typeof poi === 'string') { + const text = poi.trim() + if (!text) return null + const parts = text.split(/[\s,;,]+/).filter(Boolean) + if (parts.length < 2) return null + return parseLonlatPair(parts[0], parts[1]) + } + + const extra = poi as unknown as Record + const rawLonlat = poi.lonlat ?? extra.LonLat ?? extra.lonLat + if (typeof rawLonlat === 'string' && rawLonlat.trim()) { + const fromLonlat = parseTiandituPoiLonlat(rawLonlat) + if (fromLonlat) return fromLonlat + } + + const lng = poi.lng ?? poi.lon ?? extra.Lon + const lat = poi.lat ?? extra.Lat + if (lng != null && lat != null) { + return parseLonlatPair(lng, lat) + } + + return null +} + +/** 规范化 LocalSearch 返回的 POI 列表 */ +export function normalizeTiandituPois(pois: unknown): TiandituSearchPoi[] { + if (!pois) return [] + if (Array.isArray(pois)) return pois + if (typeof pois === 'object') return Object.values(pois) + return [] +} + /** 高校雷达网地图:固定以苏州市为中心展示 */ export function centerMapOnSuzhou( map: TiandituMap,