* 调用 OpenStreetMap Nominatim API 获取真实地址(免费,无需 Key)
(lat, lon)
| 142 | * 调用 OpenStreetMap Nominatim API 获取真实地址(免费,无需 Key) |
| 143 | */ |
| 144 | async function fetchAddressFromOSM(lat, lon) { |
| 145 | // 在城市中心附近小范围偏移 (约 300-500m) |
| 146 | const offsetLat = lat + (Math.random() - 0.5) * 0.005; |
| 147 | const offsetLon = lon + (Math.random() - 0.5) * 0.005; |
| 148 | |
| 149 | const url = `https://nominatim.openstreetmap.org/reverse?format=json&lat=${offsetLat}&lon=${offsetLon}&addressdetails=1&accept-language=en`; |
| 150 | |
| 151 | try { |
| 152 | const response = await fetch(url, { |
| 153 | headers: { |
| 154 | 'User-Agent': 'GeoFill-Extension/1.7.1' |
| 155 | } |
| 156 | }); |
| 157 | |
| 158 | if (!response.ok) { |
| 159 | console.log('[GeoFill] OSM Nominatim API 请求失败:', response.status); |
| 160 | return null; |
| 161 | } |
| 162 | |
| 163 | const data = await response.json(); |
| 164 | |
| 165 | if (data && data.address) { |
| 166 | const addr = data.address; |
| 167 | // 构建街道地址 |
| 168 | let streetAddress = ''; |
| 169 | if (addr.house_number && addr.road) { |
| 170 | streetAddress = `${addr.house_number} ${addr.road}`; |
| 171 | } else if (addr.road) { |
| 172 | streetAddress = `${Math.floor(Math.random() * 999) + 1} ${addr.road}`; |
| 173 | } else if (addr.neighbourhood) { |
| 174 | streetAddress = addr.neighbourhood; |
| 175 | } else if (addr.suburb) { |
| 176 | streetAddress = addr.suburb; |
| 177 | } |
| 178 | |
| 179 | // 对于城市国家(新加坡、香港等),state 可能为空,使用 suburb 等代替 |
| 180 | const stateValue = addr.state || addr.province || addr.region || |
| 181 | addr.suburb || addr.neighbourhood || addr.county || ''; |
| 182 | |
| 183 | return { |
| 184 | address: streetAddress || data.display_name?.split(',')[0] || '', |
| 185 | city: addr.city || addr.town || addr.village || addr.municipality || addr.county || '', |
| 186 | state: stateValue, |
| 187 | zipCode: addr.postcode || '', |
| 188 | country: addr.country || '', |
| 189 | source: 'openstreetmap' |
| 190 | }; |
| 191 | } |
| 192 | } catch (e) { |
| 193 | console.log('[GeoFill] OSM Nominatim API 调用失败:', e); |
| 194 | } |
| 195 | |
| 196 | return null; |
| 197 | } |
| 198 | |
| 199 | /** |
| 200 | * 智能获取真实地址:优先 Geoapify,备用 OSM |
no outgoing calls
no test coverage detected