/** 地点搜索 v5/place/text 使用的「Web 服务」类型 Key */ export const AMAP_WEB_SERVICE_KEY = 'b43016a0d1f5b0c32211560392059708'; /** * 高德地点关键词搜索(Web 服务 v5)。 * @see https://restapi.amap.com/v5/place/text * @param {string} keyword 地点关键字 * @param {{ key?: string, pageSize?: number, pageNum?: number, region?: string, cityLimit?: boolean }} options * @returns {Promise} */ export function searchAmapPlaceText(keyword, options = {}) { const key = options.key || AMAP_WEB_SERVICE_KEY; const pageSize = options.pageSize || 20; const pageNum = options.pageNum || 1; if (!key) { return Promise.reject(new Error('高德地图 Key 未配置')); } const trimmed = String(keyword || '').trim(); if (!trimmed) { return Promise.reject(new Error('请输入地址关键词')); } const params = new URLSearchParams({ key, keywords: trimmed, page_size: String(pageSize), page_num: String(pageNum), show_fields: 'photos', }); if (options.region) { params.set('region', options.region); } if (options.cityLimit != null) { params.set('city_limit', options.cityLimit ? 'true' : 'false'); } return fetch(`https://restapi.amap.com/v5/place/text?${params.toString()}`) .then(response => { if (!response.ok) { throw new Error('高德地点搜索请求失败'); } return response.json(); }) .then(data => { if (String(data?.status) === '1') { return Array.isArray(data.pois) ? data.pois : []; } const error = new Error(data?.info || '高德地点搜索失败'); error.code = data?.infocode; throw error; }); } /** * 将高德 Geocoder / place/text 结果规范化为地图选址浮层列表数据。 * @param {Array|Object} geocodesOrResult geocodes/pois 数组,或含 geocodes/pois/location 的结果对象 * @param {string} keyword 搜索关键词兜底文案 * @returns {Array<{id: string|number, name: string, address: string, location: any, photo: string}>} */ export function normalizeMapSearchResults(geocodesOrResult, keyword = '') { const fallback = String(keyword || '').trim(); let list = []; if (Array.isArray(geocodesOrResult)) { list = geocodesOrResult; } else if (geocodesOrResult && typeof geocodesOrResult === 'object') { if (Array.isArray(geocodesOrResult.pois)) { list = geocodesOrResult.pois; } else if (Array.isArray(geocodesOrResult.geocodes)) { list = geocodesOrResult.geocodes; } else if (geocodesOrResult.location) { list = [geocodesOrResult]; } } return list .map((item, index) => { if (!item) return null; if (isPlacePoi(item)) { const address = buildPoiAddress(item) || fallback || '-'; return { id: item.id || index, name: String(item.name || '').trim() || address, address, location: parseMapLocation(item.location), photo: pickPoiPhoto(item), }; } const buildingName = pickNamedField(item?.building); const neighborhoodName = pickNamedField(item?.neighborhood); const address = item?.formattedAddress || item?.address || fallback || '-'; return { id: item?.id || index, name: buildingName || neighborhoodName || address, address, location: parseMapLocation(item?.location), photo: item?.photo || item?.image || '', }; }) .filter(item => item && item.location); } export function parseMapLocation(location) { if (!location) return null; if (typeof location.getLng === 'function' && typeof location.getLat === 'function') { return location; } if (typeof location === 'string') { const parts = location.split(','); const lng = Number(parts[0]); const lat = Number(parts[1]); if (!Number.isFinite(lng) || !Number.isFinite(lat)) return null; return { lng, lat }; } if (Number.isFinite(Number(location.lng)) && Number.isFinite(Number(location.lat))) { return { lng: Number(location.lng), lat: Number(location.lat) }; } if ( Number.isFinite(Number(location.longitude)) && Number.isFinite(Number(location.latitude)) ) { return { lng: Number(location.longitude), lat: Number(location.latitude) }; } return null; } function isPlacePoi(item) { return Boolean(item && item.name && item.location && (item.id || item.typecode || item.adname)); } function buildPoiAddress(item) { const detail = String(item.address || '').trim(); const region = [item.pname, item.cityname, item.adname] .map(value => String(value || '').trim()) .filter(Boolean); // 直辖市等场景省市名可能重复 const uniqueRegion = region.filter((value, index) => region.indexOf(value) === index); const prefix = uniqueRegion.join(''); if (prefix && detail) { if (detail.startsWith(prefix)) return detail; return `${prefix}${detail}`; } return detail || prefix || String(item.name || '').trim(); } function pickPoiPhoto(item) { const photos = item?.photos; if (Array.isArray(photos) && photos.length) { return photos[0]?.url || ''; } if (photos && typeof photos === 'object') { return photos.url || ''; } return item?.photo || item?.image || ''; } function pickNamedField(value) { if (!value) return ''; if (typeof value === 'string') return value.trim(); if (typeof value === 'object' && value.name) return String(value.name).trim(); return ''; }