/** * JSONP 工具函数 * 用于跨域请求 */ interface JsonpOptions { timeout?: number callbackName?: string callbackParam?: string } /** * JSONP 请求 * @param url 请求地址 * @param options 配置选项 * @returns Promise */ export function jsonp(url: string, options: JsonpOptions = {}): Promise { const { timeout = 10000, callbackName = `jsonp_callback_${Date.now()}_${Math.random().toString(36).substr(2)}`, callbackParam = "callback", } = options return new Promise((resolve, reject) => { // 创建 script 标签 const script = document.createElement("script") // 设置超时 const timer = setTimeout(() => { cleanup() reject(new Error("JSONP request timeout")) }, timeout) // 清理函数 const cleanup = () => { if (script.parentNode) { script.parentNode.removeChild(script) } if ((window as any)[callbackName]) { delete (window as any)[callbackName] } clearTimeout(timer) } // 设置全局回调函数 ;(window as any)[callbackName] = (data: any) => { cleanup() resolve(data) } // 处理错误 script.onerror = () => { cleanup() reject(new Error("JSONP request failed")) } // 构建请求 URL const separator = url.includes("?") ? "&" : "?" const requestUrl = `${url}${separator}${callbackParam}=${callbackName}` // 发起请求 script.src = requestUrl document.head.appendChild(script) }) } /** * 腾讯地图 API JSONP 请求封装 */ export class TencentMapAPI { private apiKey: string constructor(apiKey: string) { this.apiKey = apiKey } /** * 逆地址解析 * @param lat 纬度 * @param lng 经度 * @returns Promise */ async reverseGeocode(lat: number, lng: number): Promise { const url = `https://apis.map.qq.com/ws/geocoder/v1/?location=${lat},${lng}&key=${this.apiKey}&get_poi=1&output=jsonp` try { const data = await jsonp(url) return data } catch (error) { console.error("逆地址解析失败:", error) throw error } } /** * 地址搜索 * @param keyword 搜索关键词 * @param boundary 搜索范围 * @returns Promise */ async searchLocation(keyword: string, boundary: string = "region(全国,0)"): Promise { const url = `https://apis.map.qq.com/ws/place/v1/search?boundary=${encodeURIComponent(boundary)}&keyword=${encodeURIComponent( keyword, )}&page_size=10&page_index=1&key=${this.apiKey}&output=jsonp` try { const data = await jsonp(url) return data } catch (error) { console.error("地址搜索失败:", error) throw error } } /** * 地址解析(正向地理编码) * @param address 地址 * @returns Promise */ async geocode(address: string): Promise { const url = `https://apis.map.qq.com/ws/geocoder/v1/?address=${encodeURIComponent(address)}&key=${this.apiKey}&output=jsonp` try { const data = await jsonp(url) return data } catch (error) { console.error("地址解析失败:", error) throw error } } /** * POI 搜索 * @param keyword 搜索关键词 * @param boundary 搜索范围 * @returns Promise */ async searchPOI(keyword: string, boundary: string = "region(全国,0)"): Promise { return this.searchLocation(keyword, boundary) } } export default jsonp