Files
pj_admin_cloud/src/utils/jsonp.ts
T
2025-10-21 16:44:03 +08:00

145 lines
3.2 KiB
TypeScript

/**
* JSONP 工具函数
* 用于跨域请求
*/
interface JsonpOptions {
timeout?: number
callbackName?: string
callbackParam?: string
}
/**
* JSONP 请求
* @param url 请求地址
* @param options 配置选项
* @returns Promise
*/
export function jsonp(url: string, options: JsonpOptions = {}): Promise<any> {
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<any> {
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<any> {
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<any> {
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<any> {
return this.searchLocation(keyword, boundary)
}
}
export default jsonp