From 570fbeb537fc2db545820ec03e903c4dea2bddfa Mon Sep 17 00:00:00 2001 From: b2894lxlx <517289602@qq.com> Date: Thu, 8 Oct 2026 19:37:27 +0800 Subject: [PATCH] =?UTF-8?q?:bug:=20=E8=BF=90=E5=8D=95=E8=BD=A8=E8=BF=B9?= =?UTF-8?q?=E4=B8=8E=E5=AE=9E=E6=97=B6=E5=AE=9A=E4=BD=8DWGS-84=E8=BD=ACGCJ?= =?UTF-8?q?-02=E5=90=8E=E5=86=8D=E7=BB=98=E5=88=B6=E9=AB=98=E5=BE=B7?= =?UTF-8?q?=E5=9C=B0=E5=9B=BE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Cursor --- src/utils/coordinate.js | 86 +++++++++++++++++++ .../components/waybill-manage-page.vue | 23 +++-- 2 files changed, 103 insertions(+), 6 deletions(-) diff --git a/src/utils/coordinate.js b/src/utils/coordinate.js index b4654fb..01e7df3 100644 --- a/src/utils/coordinate.js +++ b/src/utils/coordinate.js @@ -13,6 +13,92 @@ const coordinateRanges = { }, }; +/** WGS-84 → GCJ-02(高德)偏移算法常量 */ +const WGS84_TO_GCJ02_PI = Math.PI; +const WGS84_TO_GCJ02_A = 6378245.0; +const WGS84_TO_GCJ02_EE = 0.00669342162296594323; + +const isOutOfChina = (longitude, latitude) => + longitude < 72.004 || longitude > 137.8347 || latitude < 0.8293 || latitude > 55.8271; + +const transformLatitude = (longitude, latitude) => { + let result = + -100.0 + + 2.0 * longitude + + 3.0 * latitude + + 0.2 * latitude * latitude + + 0.1 * longitude * latitude + + 0.2 * Math.sqrt(Math.abs(longitude)); + result += + ((20.0 * Math.sin(6.0 * longitude * WGS84_TO_GCJ02_PI) + + 20.0 * Math.sin(2.0 * longitude * WGS84_TO_GCJ02_PI)) * + 2.0) / + 3.0; + result += + ((20.0 * Math.sin(latitude * WGS84_TO_GCJ02_PI) + + 40.0 * Math.sin((latitude / 3.0) * WGS84_TO_GCJ02_PI)) * + 2.0) / + 3.0; + result += + ((160.0 * Math.sin((latitude / 12.0) * WGS84_TO_GCJ02_PI) + + 320 * Math.sin((latitude * WGS84_TO_GCJ02_PI) / 30.0)) * + 2.0) / + 3.0; + return result; +}; + +const transformLongitude = (longitude, latitude) => { + let result = + 300.0 + + longitude + + 2.0 * latitude + + 0.1 * longitude * longitude + + 0.1 * longitude * latitude + + 0.1 * Math.sqrt(Math.abs(longitude)); + result += + ((20.0 * Math.sin(6.0 * longitude * WGS84_TO_GCJ02_PI) + + 20.0 * Math.sin(2.0 * longitude * WGS84_TO_GCJ02_PI)) * + 2.0) / + 3.0; + result += + ((20.0 * Math.sin(longitude * WGS84_TO_GCJ02_PI) + + 40.0 * Math.sin((longitude / 3.0) * WGS84_TO_GCJ02_PI)) * + 2.0) / + 3.0; + result += + ((150.0 * Math.sin((longitude / 12.0) * WGS84_TO_GCJ02_PI) + + 300.0 * Math.sin((longitude / 30.0) * WGS84_TO_GCJ02_PI)) * + 2.0) / + 3.0; + return result; +}; + +/** + * WGS-84(GPS / LBS)转 GCJ-02(高德/国测局),供高德地图绘制使用。 + * 中国境外坐标不做偏移,原样返回。 + * @param {number} longitude + * @param {number} latitude + * @returns {[number, number]} [经度, 纬度] + */ +export const wgs84ToGcj02 = (longitude, latitude) => { + const lng = Number(longitude); + const lat = Number(latitude); + if (!Number.isFinite(lng) || !Number.isFinite(lat) || isOutOfChina(lng, lat)) { + return [lng, lat]; + } + let dLat = transformLatitude(lng - 105.0, lat - 35.0); + let dLng = transformLongitude(lng - 105.0, lat - 35.0); + const radLat = (lat / 180.0) * WGS84_TO_GCJ02_PI; + let magic = Math.sin(radLat); + magic = 1 - WGS84_TO_GCJ02_EE * magic * magic; + const sqrtMagic = Math.sqrt(magic); + dLat = + (dLat * 180.0) / + (((WGS84_TO_GCJ02_A * (1 - WGS84_TO_GCJ02_EE)) / (magic * sqrtMagic)) * WGS84_TO_GCJ02_PI); + dLng = (dLng * 180.0) / ((WGS84_TO_GCJ02_A / sqrtMagic) * Math.cos(radLat) * WGS84_TO_GCJ02_PI); + return [lng + dLng, lat + dLat]; +}; + export const normalizeCoordinateInput = value => { const rawValue = String(value ?? '').replace(/[^\d.-]/g, ''); const isNegative = rawValue.startsWith('-'); diff --git a/src/views/business/components/waybill-manage-page.vue b/src/views/business/components/waybill-manage-page.vue index d46a264..a565f62 100644 --- a/src/views/business/components/waybill-manage-page.vue +++ b/src/views/business/components/waybill-manage-page.vue @@ -3642,6 +3642,7 @@ import { addressTypeOptions } from '@/option/base/common-address'; import { packageOptions } from '@/option/business/common'; import { formatUpdateUserName } from '@/utils/audit'; import { getToken, isAdministrator } from '@/utils/auth'; +import { wgs84ToGcj02 } from '@/utils/coordinate'; import { openImportDialog } from '@/utils/import-excel'; import { normalizeMapSearchResults, searchAmapPlaceText } from '@/utils/map-search'; import { loadMeasurementUnitOptions } from '@/utils/measurement-unit'; @@ -6306,12 +6307,14 @@ export default { } }, async renderWaybillLocateMap(locateInfo) { - const longitude = Number(locateInfo?.longitude); - const latitude = Number(locateInfo?.latitude); - if (!Number.isFinite(longitude) || !Number.isFinite(latitude)) { + const rawLongitude = Number(locateInfo?.longitude); + const rawLatitude = Number(locateInfo?.latitude); + if (!Number.isFinite(rawLongitude) || !Number.isFinite(rawLatitude)) { this.$message.warning('定位坐标无效,无法在地图上展示'); return; } + // LBS 返回 WGS-84,高德地图使用 GCJ-02,绘制前需转换 + const [longitude, latitude] = wgs84ToGcj02(rawLongitude, rawLatitude); try { await this.loadAmap(); await this.$nextTick(); @@ -6332,7 +6335,7 @@ export default { `
${locateInfo.vehicleNo || '车辆位置'}
`, locateInfo.locateTime ? `
时间:${locateInfo.locateTime}
` : '', locateInfo.address ? `
地址:${locateInfo.address}
` : '', - `
坐标:${longitude}, ${latitude}
`, + `
坐标:${rawLongitude}, ${rawLatitude}
`, ``, ].join(''); this.waybillLocateInfoWindow = new window.AMap.InfoWindow({ @@ -6359,9 +6362,17 @@ export default { } }, async renderWaybillTrackMap(points) { + // LBS 轨迹为 WGS-84,绘制到高德前转为 GCJ-02 const path = (points || []) - .map(item => [Number(item.longitude), Number(item.latitude)]) - .filter(item => Number.isFinite(item[0]) && Number.isFinite(item[1])); + .map(item => { + const longitude = Number(item.longitude); + const latitude = Number(item.latitude); + if (!Number.isFinite(longitude) || !Number.isFinite(latitude)) { + return null; + } + return wgs84ToGcj02(longitude, latitude); + }) + .filter(Boolean); if (!path.length) { this.$message.warning('轨迹坐标无效,无法在地图上展示'); return;