Files
autoAiWorkSys/api/services/locationService.js
张成 5d7444cd65 1
2025-11-24 13:23:42 +08:00

162 lines
5.3 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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();