This commit is contained in:
张成
2025-11-24 13:23:42 +08:00
commit 5d7444cd65
156 changed files with 50653 additions and 0 deletions

View File

@@ -0,0 +1,161 @@
const axios = require('axios');
const config = require('../../config/config');
/**
* 地理位置服务
*/
class LocationService {
/**
* 根据经纬度获取地址信息
* @param {number} latitude 纬度
* @param {number} longitude 经度
* @returns {Promise<Object>} 地址信息
*/
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<Object>} 经纬度信息
*/
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();