141 lines
3.4 KiB
TypeScript
141 lines
3.4 KiB
TypeScript
import { toast } from './toast'
|
|
|
|
let tdtLoaded = false
|
|
let tdtLoadCallbacks: ((T: typeof window.T) => void)[] = []
|
|
|
|
const mapKey = import.meta.env.VITE_TIANDITU_MAP_KEY
|
|
|
|
export function loadTianDiTu(onLoadedCallback?: (T: typeof window.T) => void) {
|
|
if (tdtLoaded && window.T) {
|
|
onLoadedCallback?.(window.T)
|
|
return
|
|
}
|
|
|
|
if (onLoadedCallback)
|
|
tdtLoadCallbacks.push(onLoadedCallback)
|
|
|
|
if (document.querySelector(`script[src*="tianditu.gov.cn/api"]`))
|
|
return
|
|
|
|
const script = document.createElement('script')
|
|
script.src = `https://api.tianditu.gov.cn/api?v=4.0&tk=${mapKey}`
|
|
script.onload = () => {
|
|
if (!window.T) {
|
|
console.error('天地图脚本加载成功,但 T 不存在')
|
|
return
|
|
}
|
|
|
|
tdtLoaded = true
|
|
tdtLoadCallbacks.forEach(cb => cb(window.T!))
|
|
tdtLoadCallbacks = []
|
|
}
|
|
script.onerror = () => {
|
|
console.error('天地图脚本加载失败')
|
|
tdtLoadCallbacks = []
|
|
}
|
|
|
|
document.head.appendChild(script)
|
|
}
|
|
|
|
export async function getAddressByPoint(lon: number, lat: number): Promise<string> {
|
|
return new Promise((resolve, reject) => {
|
|
loadTianDiTu((T) => {
|
|
try {
|
|
const geocoder = new T.Geocoder()
|
|
|
|
geocoder.getLocation(new T.LngLat(lon, lat), (res: any) => {
|
|
try {
|
|
const addr = res.formatted_address
|
|
const comp = res.addressComponent || {}
|
|
|
|
if (!addr) {
|
|
const parts = [
|
|
comp.nation,
|
|
comp.province,
|
|
comp.city,
|
|
comp.county,
|
|
comp.road,
|
|
comp.poi || comp.address,
|
|
].filter(Boolean)
|
|
|
|
resolve(parts.join(' '))
|
|
}
|
|
else {
|
|
resolve(addr)
|
|
}
|
|
}
|
|
catch (err) {
|
|
reject(err)
|
|
}
|
|
})
|
|
}
|
|
catch (err) {
|
|
reject(err)
|
|
}
|
|
})
|
|
})
|
|
}
|
|
|
|
export async function getPoint(): Promise<{ lon: number, lat: number } | null> {
|
|
return new Promise((resolve, reject) => {
|
|
uni.getLocation({
|
|
type: 'wgs84',
|
|
success(res) {
|
|
console.log(res)
|
|
|
|
const lon = res.longitude
|
|
const lat = res.latitude
|
|
|
|
if (!lon || !lat || (lon === 0 && lat === 0)) {
|
|
resolve(null) // 无效坐标返回 null
|
|
}
|
|
else {
|
|
resolve({ lon, lat })
|
|
}
|
|
},
|
|
fail(err) {
|
|
console.error('获取定位失败', err)
|
|
resolve(null) // 定位失败也返回 null,调用方可以判断
|
|
},
|
|
})
|
|
})
|
|
}
|
|
|
|
export interface CurrentLocation {
|
|
lon: number
|
|
lat: number
|
|
address: string
|
|
}
|
|
|
|
/**
|
|
* 获取当前位置及对应地址(自动处理错误和提示)
|
|
* @returns 如果成功返回位置信息,否则返回 null(已自动 toast 提示)
|
|
*/
|
|
export function getCurrentLocation(): Promise<CurrentLocation | null> {
|
|
return getPoint()
|
|
.then((point) => {
|
|
if (!point) {
|
|
return null
|
|
}
|
|
|
|
return getAddressByPoint(point.lon, point.lat).then(address => ({
|
|
lon: point.lon,
|
|
lat: point.lat,
|
|
address,
|
|
}))
|
|
})
|
|
.catch((err) => {
|
|
console.error('[getCurrentLocation] 获取位置失败:', err)
|
|
return null
|
|
})
|
|
.finally(() => {
|
|
console.log('[getCurrentLocation] 操作完成')
|
|
})
|
|
}
|
|
|
|
export async function getDrive(points: number[][], style: string = '0') {
|
|
loadTianDiTu((T) => {
|
|
const drivingRoute = new T.DrivingRoute(null)
|
|
})
|
|
}
|