// deno run -A https://kevisual.xiongxiao.me/root/test-map-distance/index.ts?a=1 import path from 'node:path'; import fs from 'node:fs'; /** * 手动读取 .env 文件 */ function loadEnv() { const envPath = path.resolve(process.cwd(), '.env'); if (!fs.existsSync(envPath)) { return {}; } const content = fs.readFileSync(envPath, 'utf-8'); const env: Record = {}; for (const line of content.split('\n')) { const trimmed = line.trim(); if (!trimmed || trimmed.startsWith('#')) continue; const [key, ...valueParts] = trimmed.split('='); if (key && valueParts.length > 0) { env[key.trim()] = valueParts.join('=').trim(); } } return env; } const env = loadEnv(); const AMAP_KEY = env.AMAP_KEY || ''; if (!AMAP_KEY) { throw new Error('请在环境变量中设置 AMAP_KEY'); } /** * 地理编码:将地址转换为经纬度 */ async function geocode(address: string): Promise<{ lng: number; lat: number } | null> { const url = `https://restapi.amap.com/v3/geocode/geo?address=${encodeURIComponent(address)}&key=${AMAP_KEY}`; const res = await fetch(url).then(r => r.json()); if (res.status === '1' && res.geocodes?.length > 0) { const [lng, lat] = res.geocodes[0].location.split(',').map(Number); return { lng, lat }; } return null; } /** * 计算两点间的直线距离(米) */ function calculateDistance( from: { lng: number; lat: number }, to: { lng: number; lat: number } ): number { const R = 6371000; // 地球半径(米) const dLat = (to.lat - from.lat) * Math.PI / 180; const dLng = (to.lng - from.lng) * Math.PI / 180; const a = Math.sin(dLat / 2) ** 2 + Math.cos(from.lat * Math.PI / 180) * Math.cos(to.lat * Math.PI / 180) * Math.sin(dLng / 2) ** 2; const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a)); return R * c; } /** * 主函数:计算两个地址间的距离 */ async function getDistance(fromAddress: string, toAddress: string) { const [from, to] = await Promise.all([ geocode(fromAddress), geocode(toAddress) ]); if (!from || !to) { throw new Error('地址解析失败'); } const distance = calculateDistance(from, to); return { from, to, distanceMeters: distance, distanceKm: (distance / 1000).toFixed(2) }; } // 使用示例 // getDistance('北京市', '上海市').then(console.log); // const fromAddress = '北京市朝阳区望京SOHO'; // const toAddress = '杭州市西湖区雅仕苑'; const addressPath = path.resolve(process.cwd(), 'address.json'); type Address = { from: string; to: string; } let addressJson: Address[]; // 读取 address.json 文件 const addressData = fs.readFileSync(addressPath, 'utf-8'); try { addressJson = JSON.parse(addressData) as Address[]; } catch (error) { console.error('无法解析 address.json 文件,请确保其为有效的 JSON 格式'); process.exit(1); } if (!Array.isArray(addressJson)) { console.error('address.json 文件格式错误,应为地址对象数组'); process.exit(1); } const results: any[] = []; for (const addr of addressJson) { try { // 计算距离 const result = await getDistance(addr.from, addr.to); results.push({ from: addr.from, to: addr.to, distanceMeters: result.distanceMeters, distanceKm: result.distanceKm, }); console.log(`地址对 (${addr.from} -> ${addr.to}) 的距离为: ${result.distanceKm} 公里`); } catch (error) { console.error(`计算地址对 (${addr.from} -> ${addr.to}) 距离时出错:`, error); } } // 将结果写入 distance-results.json 文件 const resultPath = path.resolve(process.cwd(), 'distance-results.json'); fs.writeFileSync(resultPath, JSON.stringify(results, null, 2), 'utf-8'); console.log(`距离结果已保存到 ${resultPath}`);