From cc107a19b742acc306d9ab00b0a1cd0ce7081101 Mon Sep 17 00:00:00 2001 From: hx <190679152@qq.com> Date: Fri, 20 Mar 2026 16:31:56 +0800 Subject: [PATCH] =?UTF-8?q?b=E7=AB=AF=E5=9B=BD=E9=99=85=E5=8C=96=20?= =?UTF-8?q?=E5=9C=B0=E5=9B=BE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/device/TrajectoryDialog.vue | 71 +++++++++++++++++++--- 1 file changed, 62 insertions(+), 9 deletions(-) diff --git a/src/components/device/TrajectoryDialog.vue b/src/components/device/TrajectoryDialog.vue index be57b63..fe16e38 100644 --- a/src/components/device/TrajectoryDialog.vue +++ b/src/components/device/TrajectoryDialog.vue @@ -122,6 +122,8 @@ const LEAFLET_DEFAULT_CENTER = [31.2304, 121.4737]; const AMAP_FALLBACK_MAX_ZOOM = 20; const GOOGLE_DETAIL_ZOOM = 21; const LEAFLET_MAX_ZOOM = 22; +const LEAFLET_GOOGLE_MAX_ZOOM = 20; +const LEAFLET_GOOGLE_TILE_URL = "https://mt1.google.com/vt/lyrs=m&x={x}&y={y}&z={z}"; const LEAFLET_LINE_ARROW_MAX = 36; const LEAFLET_SHOW_LINE_ARROWS = false; const LEAFLET_TRAJECTORY_LINE_COLOR = "#1a73e8"; @@ -179,7 +181,7 @@ export default { return !!(this.mapConfig && this.mapConfig.gaodeKey); }, hasGoogleKey() { - return !!(this.mapConfig && this.mapConfig.googleKey); + return true; }, hasMaptilerKey() { return !!(this.mapConfig && this.mapConfig.maptilerKey); @@ -286,14 +288,10 @@ export default { try { const response = await getDeviceTrajectoryMapConfig(); const data = response && response.data ? response.data : {}; - if (!data.gaodeKey && !data.googleKey && !data.maptilerKey) { - this.loadError = this.$t("device.trajectory.message.missingMapKey"); - return; - } this.mapConfig = data; } catch (error) { - this.mapConfig = null; - this.loadError = error && error.message ? error.message : this.$t("device.trajectory.message.mapConfigLoadFailed"); + // Google tiles mode does not depend on map config, keep dialog usable. + this.mapConfig = {}; } }, async fetchTrajectory() { @@ -340,9 +338,9 @@ export default { return; } if (this.mapProvider === "google") { - await this.ensureGoogleMap(); + await this.ensureLeafletGoogleMap(); if (!this.loadError) { - this.renderGoogleTrajectory(); + this.renderLeafletTrajectory(); } return; } @@ -386,6 +384,21 @@ export default { this.mapVendor = "leaflet"; } else { this.mapsApi = mapsApi; + if (this.tileLayer && typeof this.map.removeLayer === "function") { + this.map.removeLayer(this.tileLayer); + } + this.tileLayer = mapsApi.tileLayer( + "https://api.maptiler.com/maps/streets/{z}/{x}/{y}{r}.png?key=" + + encodeURIComponent(this.mapConfig.maptilerKey), + { + attribution: + '© MapTiler © OpenStreetMap', + maxZoom: LEAFLET_MAX_ZOOM, + maxNativeZoom: LEAFLET_MAX_ZOOM, + detectRetina: true, + } + ); + this.tileLayer.addTo(this.map); if (typeof this.map.invalidateSize === "function") { this.map.invalidateSize(); } @@ -396,6 +409,46 @@ export default { this.mapLoading = false; } }, + async ensureLeafletGoogleMap() { + this.mapLoading = true; + try { + const mapsApi = await loadLeaflet(); + if (!this.$refs.map) { + return; + } + if (!this.map || this.mapVendor !== "leaflet") { + this.destroyMap(); + this.mapsApi = mapsApi; + this.map = mapsApi.map(this.$refs.map, { + center: LEAFLET_DEFAULT_CENTER, + zoom: LEAFLET_GOOGLE_MAX_ZOOM, + zoomControl: true, + }); + this.tileLayer = mapsApi.tileLayer(LEAFLET_GOOGLE_TILE_URL, { + maxZoom: LEAFLET_GOOGLE_MAX_ZOOM, + }); + this.tileLayer.addTo(this.map); + this.mapVendor = "leaflet"; + return; + } + + this.mapsApi = mapsApi; + if (this.tileLayer && typeof this.map.removeLayer === "function") { + this.map.removeLayer(this.tileLayer); + } + this.tileLayer = mapsApi.tileLayer(LEAFLET_GOOGLE_TILE_URL, { + maxZoom: LEAFLET_GOOGLE_MAX_ZOOM, + }); + this.tileLayer.addTo(this.map); + if (typeof this.map.invalidateSize === "function") { + this.map.invalidateSize(); + } + } catch (error) { + this.loadError = error && error.message ? error.message : this.$t("device.trajectory.message.googleLoadFailed"); + } finally { + this.mapLoading = false; + } + }, renderLeafletTrajectory() { if (!this.map || !this.mapsApi || !this.trajectoryPoints.length) { return;