|
@@ -718,7 +718,6 @@ const loadAmapApi = (): Promise<void> => {
|
|
|
});
|
|
});
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
-// 初始化高德地图
|
|
|
|
|
// 初始化高德地图
|
|
// 初始化高德地图
|
|
|
const initMap = async () => {
|
|
const initMap = async () => {
|
|
|
try {
|
|
try {
|
|
@@ -784,7 +783,8 @@ const initMap = async () => {
|
|
|
|
|
|
|
|
mapInstance.add(markerInstance);
|
|
mapInstance.add(markerInstance);
|
|
|
|
|
|
|
|
- mapInstance.on('click', (e: any) => {
|
|
|
|
|
|
|
+ // 点击地图事件 - 更新坐标并获取地址
|
|
|
|
|
+ mapInstance.on('click', async (e: any) => {
|
|
|
const lng = e.lnglat.getLng();
|
|
const lng = e.lnglat.getLng();
|
|
|
const lat = e.lnglat.getLat();
|
|
const lat = e.lnglat.getLat();
|
|
|
|
|
|
|
@@ -793,18 +793,144 @@ const initMap = async () => {
|
|
|
selectedCoordinate.value = `纬度: ${lat.toFixed(6)}, 经度: ${lng.toFixed(6)} (GCJ-02)`;
|
|
selectedCoordinate.value = `纬度: ${lat.toFixed(6)}, 经度: ${lng.toFixed(6)} (GCJ-02)`;
|
|
|
form.value.latitude = lat;
|
|
form.value.latitude = lat;
|
|
|
form.value.longitude = lng;
|
|
form.value.longitude = lng;
|
|
|
|
|
+
|
|
|
|
|
+ // 使用 OpenCageData API 获取中文地址(需要将 GCJ-02 转换为 WGS-84)
|
|
|
|
|
+ await setSelectedLocationWithConversion(lat, lng);
|
|
|
});
|
|
});
|
|
|
|
|
|
|
|
if (hasCoordinates) {
|
|
if (hasCoordinates) {
|
|
|
const lat = Number(form.value.latitude || markerPos[1]);
|
|
const lat = Number(form.value.latitude || markerPos[1]);
|
|
|
const lng = Number(form.value.longitude || markerPos[0]);
|
|
const lng = Number(form.value.longitude || markerPos[0]);
|
|
|
selectedCoordinate.value = `纬度: ${lat.toFixed(6)}, 经度: ${lng.toFixed(6)} (GCJ-02)`;
|
|
selectedCoordinate.value = `纬度: ${lat.toFixed(6)}, 经度: ${lng.toFixed(6)} (GCJ-02)`;
|
|
|
|
|
+
|
|
|
|
|
+ // 如果编辑模式且已有地址,不需要重新获取
|
|
|
|
|
+ if (!form.value.address) {
|
|
|
|
|
+ // 如果是新增模式或地址为空,尝试获取地址
|
|
|
|
|
+ await setSelectedLocationWithConversion(lat, lng);
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|
|
|
} catch (error) {
|
|
} catch (error) {
|
|
|
console.error('地图初始化失败:', error);
|
|
console.error('地图初始化失败:', error);
|
|
|
proxy?.$modal.msgError('地图加载失败');
|
|
proxy?.$modal.msgError('地图加载失败');
|
|
|
}
|
|
}
|
|
|
};
|
|
};
|
|
|
|
|
+
|
|
|
|
|
+/**
|
|
|
|
|
+ * 使用 OpenCageData API 获取地址(GCJ-02 → WGS-84 转换)
|
|
|
|
|
+ */
|
|
|
|
|
+const setSelectedLocationWithConversion = async (gcjLat: number, gcjLon: number) => {
|
|
|
|
|
+ const coordsText = `纬度:${gcjLat.toFixed(6)}, 经度:${gcjLon.toFixed(6)}`;
|
|
|
|
|
+
|
|
|
|
|
+ try {
|
|
|
|
|
+ // 关键步骤:将 GCJ-02 转换为 WGS-84
|
|
|
|
|
+ const wgs84Coords = convertGcj02ToWgs84(gcjLat, gcjLon);
|
|
|
|
|
+
|
|
|
|
|
+ console.log('坐标转换:', {
|
|
|
|
|
+ '原始GCJ-02': `${gcjLat}, ${gcjLon}`,
|
|
|
|
|
+ '转换WGS-84': `${wgs84Coords.lat}, ${wgs84Coords.lng}`
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ // 使用 WGS-84 坐标调用 OpenCageData API
|
|
|
|
|
+ const response = await fetch(
|
|
|
|
|
+ `https://api.opencagedata.com/geocode/v1/json?q=${wgs84Coords.lat}+${wgs84Coords.lng}&key=82827937f9614a6eb17c772efa63d75d&language=zh&no_annotations=1`
|
|
|
|
|
+ );
|
|
|
|
|
+
|
|
|
|
|
+ if (response.ok) {
|
|
|
|
|
+ const data = await response.json();
|
|
|
|
|
+ if (data && data.results && data.results.length > 0) {
|
|
|
|
|
+ const address = data.results[0].formatted;
|
|
|
|
|
+ // 清理地址格式:移除开头的邮编和逗号
|
|
|
|
|
+ const cleanedAddress = cleanChineseAddress(address);
|
|
|
|
|
+
|
|
|
|
|
+ // 将地址填充到表单中(注意:数据库中仍然存储 GCJ-02 坐标)
|
|
|
|
|
+ form.value.address = cleanedAddress;
|
|
|
|
|
+
|
|
|
|
|
+ console.log('详细地址:', cleanedAddress);
|
|
|
|
|
+ proxy?.$modal.msgSuccess(`已获取地址:${cleanedAddress}`);
|
|
|
|
|
+ } else {
|
|
|
|
|
+ form.value.address = coordsText;
|
|
|
|
|
+ proxy?.$modal.msgWarning('未能获取详细地址,请手动输入');
|
|
|
|
|
+ }
|
|
|
|
|
+ } else {
|
|
|
|
|
+ form.value.address = coordsText;
|
|
|
|
|
+ proxy?.$modal.msgWarning('地址解析服务异常,请手动输入');
|
|
|
|
|
+ }
|
|
|
|
|
+ } catch (error) {
|
|
|
|
|
+ console.error('地址解析失败:', error);
|
|
|
|
|
+ form.value.address = coordsText;
|
|
|
|
|
+ proxy?.$modal.msgWarning('地址解析失败,请手动输入');
|
|
|
|
|
+ }
|
|
|
|
|
+};
|
|
|
|
|
+
|
|
|
|
|
+/**
|
|
|
|
|
+ * GCJ-02 → WGS-84(前端简易版)
|
|
|
|
|
+ */
|
|
|
|
|
+const convertGcj02ToWgs84 = (gcjLat: number, gcjLon: number): { lat: number; lng: number } => {
|
|
|
|
|
+ const PI = 3.1415926535897932384626;
|
|
|
|
|
+ const A = 6378245.0;
|
|
|
|
|
+ const EE = 0.00669342162296594323;
|
|
|
|
|
+
|
|
|
|
|
+ const outOfChina = (lat: number, lon: number): boolean => {
|
|
|
|
|
+ return lon < 72.004 || lon > 137.8347 || lat < 0.8293 || lat > 55.8271;
|
|
|
|
|
+ };
|
|
|
|
|
+
|
|
|
|
|
+ const transformLat = (x: number, y: number): number => {
|
|
|
|
|
+ let ret = -100.0 + 2.0 * x + 3.0 * y + 0.2 * y * y + 0.1 * x * y + 0.2 * Math.sqrt(Math.abs(x));
|
|
|
|
|
+ ret += ((20.0 * Math.sin(6.0 * x * PI) + 20.0 * Math.sin(2.0 * x * PI)) * 2.0) / 3.0;
|
|
|
|
|
+ ret += ((20.0 * Math.sin(y * PI) + 40.0 * Math.sin((y / 3.0) * PI)) * 2.0) / 3.0;
|
|
|
|
|
+ ret += ((160.0 * Math.sin((y / 12.0) * PI) + 320.0 * Math.sin((y * PI) / 30.0)) * 2.0) / 3.0;
|
|
|
|
|
+ return ret;
|
|
|
|
|
+ };
|
|
|
|
|
+
|
|
|
|
|
+ const transformLon = (x: number, y: number): number => {
|
|
|
|
|
+ let ret = 300.0 + x + 2.0 * y + 0.1 * x * x + 0.1 * x * y + 0.1 * Math.sqrt(Math.abs(x));
|
|
|
|
|
+ ret += ((20.0 * Math.sin(6.0 * x * PI) + 20.0 * Math.sin(2.0 * x * PI)) * 2.0) / 3.0;
|
|
|
|
|
+ ret += ((20.0 * Math.sin(x * PI) + 40.0 * Math.sin((x / 3.0) * PI)) * 2.0) / 3.0;
|
|
|
|
|
+ ret += ((150.0 * Math.sin((x / 12.0) * PI) + 300.0 * Math.sin((x / 30.0) * PI)) * 2.0) / 3.0;
|
|
|
|
|
+ return ret;
|
|
|
|
|
+ };
|
|
|
|
|
+
|
|
|
|
|
+ if (outOfChina(gcjLat, gcjLon)) {
|
|
|
|
|
+ return { lat: gcjLat, lng: gcjLon };
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ let dLat = transformLat(gcjLon - 105.0, gcjLat - 35.0);
|
|
|
|
|
+ let dLon = transformLon(gcjLon - 105.0, gcjLat - 35.0);
|
|
|
|
|
+ const radLat = (gcjLat / 180.0) * PI;
|
|
|
|
|
+ let magic = Math.sin(radLat);
|
|
|
|
|
+ magic = 1 - EE * magic * magic;
|
|
|
|
|
+ const sqrtMagic = Math.sqrt(magic);
|
|
|
|
|
+ dLat = (dLat * 180.0) / (((A * (1 - EE)) / (magic * sqrtMagic)) * PI);
|
|
|
|
|
+ dLon = (dLon * 180.0) / ((A / sqrtMagic) * Math.cos(radLat) * PI);
|
|
|
|
|
+
|
|
|
|
|
+ return {
|
|
|
|
|
+ lat: gcjLat - dLat, // 注意:这里是减法,与 WGS→GCJ 相反
|
|
|
|
|
+ lng: gcjLon - dLon
|
|
|
|
|
+ };
|
|
|
|
|
+};
|
|
|
|
|
+
|
|
|
|
|
+/**
|
|
|
|
|
+ * 清理中文地址格式
|
|
|
|
|
+ */
|
|
|
|
|
+const cleanChineseAddress = (address: string): string => {
|
|
|
|
|
+ if (!address) return address;
|
|
|
|
|
+
|
|
|
|
|
+ // 移除开头的邮编(如 "410000 湖南省..." → "湖南省...")
|
|
|
|
|
+ let cleaned = address.replace(/^\d{5,}\s*/, '');
|
|
|
|
|
+
|
|
|
|
|
+ // 处理重复的省市名称(如:湖南省长沙市长沙市 → 湖南省长沙市)
|
|
|
|
|
+ cleaned = cleaned.replace(/([\u4e00-\u9fa5]+市)\1/g, '$1');
|
|
|
|
|
+
|
|
|
|
|
+ // 移除多余的逗号、空格
|
|
|
|
|
+ cleaned = cleaned.replace(/[,,\s]+/g, '').replace(/\s+/g, '');
|
|
|
|
|
+
|
|
|
|
|
+ // 移除 "中国" 前缀(OpenCageData 通常会包含)
|
|
|
|
|
+ cleaned = cleaned.replace(/^中国/, '');
|
|
|
|
|
+
|
|
|
|
|
+ return cleaned;
|
|
|
|
|
+};
|
|
|
|
|
+
|
|
|
|
|
+// ... existing code ...
|
|
|
// WGS-84转GCJ-02(前端简易版)
|
|
// WGS-84转GCJ-02(前端简易版)
|
|
|
const convertWgs84ToGcj02 = (wgsLat: number, wgsLon: number): { lat: number; lng: number } => {
|
|
const convertWgs84ToGcj02 = (wgsLat: number, wgsLon: number): { lat: number; lng: number } => {
|
|
|
const PI = 3.1415926535897932384626;
|
|
const PI = 3.1415926535897932384626;
|