const axios = require('axios'); const config = require('../../config/config'); /** * 地理位置服务 */ class LocationService { /** * 根据经纬度获取地址信息 * @param {number} latitude 纬度 * @param {number} longitude 经度 * @returns {Promise} 地址信息 */ async getAddressByLocation(latitude, longitude) { try { const url = `https://apis.map.qq.com/ws/geocoder/v1/?location=${latitude},${longitude}&key=${config.qq_map_key}`; const response = await axios.get(url); if (response.data.status !== 0) { throw new Error('地理位置解析失败, ' + response.data.message); } let addressComponent = response.data.result.address_component let formatAddress = this.formatAddressInfo(addressComponent) return formatAddress; } catch (error) { throw error; } } /** * 根据地址获取经纬度 * @param {string} address 地址 * @returns {Promise} 经纬度信息 */ async getLocationByAddress(address) { const url = `https://apis.map.qq.com/ws/geocoder/v1/?address=${encodeURIComponent(address)}&key=${config.qq_map_key}`; const response = await axios.get(url); if (response.data.status !== 0) { throw new Error('地址解析失败, ' + response.data.message); } let addressComponent = response.data.result.location return addressComponent; } /** * 计算两点之间的距离(公里) * @param {number} lat1 第一个点的纬度 * @param {number} lng1 第一个点的经度 * @param {number} lat2 第二个点的纬度 * @param {number} lng2 第二个点的经度 * @returns {number} 距离(公里) */ calculateDistance(lat1, lng1, lat2, lng2) { const R = 6371; // 地球半径(公里) const dLat = this.toRadians(lat2 - lat1); const dLng = this.toRadians(lng2 - lng1); const a = Math.sin(dLat / 2) * Math.sin(dLat / 2) + Math.cos(this.toRadians(lat1)) * Math.cos(this.toRadians(lat2)) * Math.sin(dLng / 2) * Math.sin(dLng / 2); const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a)); const distance = R * c; return Math.round(distance * 100) / 100; // 保留两位小数 } /** * 角度转弧度 * @param {number} degrees 角度 * @returns {number} 弧度 */ toRadians(degrees) { return degrees * (Math.PI / 180); } /** * 格式化地址信息 * @param {Object} addressComponent 地址组件 * @returns {Object} 格式化后的地址信息 */ formatAddressInfo(addressComponent) { // 处理省份名称,去掉"省"、"市"、"自治区"等后缀 let province = addressComponent.province || ''; province = province.replace(/省|市|自治区|特别行政区/g, ''); // 处理城市名称,去掉"市"后缀 let city = addressComponent.city || ''; city = city.replace(/市/g, ''); // 处理区县名称 let district = addressComponent.district || ''; // 检查是否为直辖市(北京、上海、天津、重庆) const municipalities = ['北京', '上海', '天津', '重庆']; const isMunicipality = municipalities.includes(province) || municipalities.some(m => addressComponent.province && addressComponent.province.includes(m)); // 如果是直辖市,调整省份和城市字段 if (isMunicipality) { // 直辖市:province 保持为直辖市名称,city 设置为区名 const municipalityName = municipalities.find(m => province.includes(m) || (addressComponent.province && addressComponent.province.includes(m)) ) || province; province = municipalityName; // 特殊处理:浦东新区、滨海新区等特殊区名,保持完整名称 if (district.includes('新区') || district.includes('开发区') || district.includes('高新区')) { city = district; // 保持完整的区名作为城市(不去掉后缀) district = ''; // 清空区字段 } else { // 普通区名去掉后缀后作为城市 city = district.replace(/区|县/g, ''); district = ''; // 清空区字段 } } else { // 非直辖市,按正常逻辑处理 district = district.replace(/区|县/g, ''); } // 构建简化的地址格式:城市 区县 let formatted_address = ''; if (city && district) { formatted_address = `${city} ${district}`; } else if (city) { formatted_address = city; } else if (district) { formatted_address = district; } else if (province) { formatted_address = province; } return { province: province, city: city, district: district, street: addressComponent.street || '', street_number: addressComponent.street_number || '', formatted_address: formatted_address }; } } module.exports = new LocationService();