From b5de46bc1daa3ad56b21e1df095a611a6dd68d1f Mon Sep 17 00:00:00 2001 From: xiaosi <2652281683@qq.com> Date: Wed, 19 Aug 2026 18:44:24 +0800 Subject: [PATCH] feat: hook Monitor into Tianditu map with device markers --- .env.development | 2 +- src/layout/MainContainer.vue | 2 +- src/layout/MapLayer.vue | 2 + src/stores/modules/devicesStore.js | 4 + src/styles/prototype.css | 13 +- src/utils/commonRefs.js | 12 +- src/views/MonitorView/MonitorView.vue | 250 ++++++++++++++++++++------ 7 files changed, 214 insertions(+), 71 deletions(-) diff --git a/.env.development b/.env.development index 030631c..76cd30d 100644 --- a/.env.development +++ b/.env.development @@ -1,4 +1,4 @@ -APP_TIANDITU_TOKEN= +APP_TIANDITU_TOKEN=1e3adb7649d896631c574461b15cb9d4 APP_MAP_CENTER_LNG=106.62341584179686 APP_MAP_CENTER_LAT=26.657826154258505 APP_MAP_ZOOM=5 diff --git a/src/layout/MainContainer.vue b/src/layout/MainContainer.vue index ed26c50..fbeab99 100644 --- a/src/layout/MainContainer.vue +++ b/src/layout/MainContainer.vue @@ -91,7 +91,7 @@ function closeSidebar() { position: relative; height: 100%; overflow: hidden; - background: #eef3f7; + background: transparent; } .mask { diff --git a/src/layout/MapLayer.vue b/src/layout/MapLayer.vue index ac61273..977b602 100644 --- a/src/layout/MapLayer.vue +++ b/src/layout/MapLayer.vue @@ -12,6 +12,7 @@ function initMap() { const tk = mapConfig.token if (!tk) { console.error('[MapLayer] 缺少 APP_TIANDITU_TOKEN,跳过地图初始化') + commonRefs.setRef('map', null) return } @@ -40,6 +41,7 @@ onMounted(() => { initMap() } catch (error) { console.error('[MapLayer] 地图初始化失败:', error) + commonRefs.setRef('map', null) } }) }) diff --git a/src/stores/modules/devicesStore.js b/src/stores/modules/devicesStore.js index c0103a3..1288c02 100644 --- a/src/stores/modules/devicesStore.js +++ b/src/stores/modules/devicesStore.js @@ -286,6 +286,8 @@ export const useDeviceStore = defineStore('devices', () => { assets[dk.id] = { id: dk.id, type: 'dock', name: dk.name, location: dk.location, status: dk.status, statusClass: dk.statusClass, x: p.x, y: p.y, hasCoordinates, + longitude: hasCoordinates ? dk.longitude : null, + latitude: hasCoordinates ? dk.latitude : null, realtime: dk.realtime, environment: dk.environment, alarms: dk.alarms, online: dk.online } } @@ -299,6 +301,8 @@ export const useDeviceStore = defineStore('devices', () => { id: dr.id, type: 'drone', name: dr.name, location: dr.statusClass === 'mission' ? `${dock?.location || '--'} · 飞行中` : `停放于${dock?.name || '--'}`, status: dr.status, statusClass: dr.statusClass, x: p.x, y: p.y, hasCoordinates, + longitude: hasCoordinates ? lon : null, + latitude: hasCoordinates ? lat : null, parent: dock?.id || '', parentName: dock?.name || '--', inDock: dr.statusClass !== 'mission', altitude: dr._alt, speed: dr._speed, satellites: dr._sats, realtime: dr.realtime, alarms: dr.alarms, online: dr.online diff --git a/src/styles/prototype.css b/src/styles/prototype.css index 34c36f7..04d1204 100644 --- a/src/styles/prototype.css +++ b/src/styles/prototype.css @@ -86,14 +86,14 @@ svg { width: 18px; height: 18px; fill: none; stroke: currentColor; stroke-width: .sidebar-bottom .sidebar-profile > svg { transform: rotate(-90deg); color: #8fa0ad; } .mobile-menu { display: none; } -.monitor-layout { position: relative; flex: 1; min-height: 0; display: grid; grid-template-columns: 0 minmax(0, 1fr) 0; overflow: hidden; transition: grid-template-columns .38s cubic-bezier(.22,.8,.25,1); } +.monitor-layout { position: relative; flex: 1; min-height: 0; display: grid; grid-template-columns: 0 minmax(0, 1fr) 0; overflow: hidden; background: transparent; pointer-events: none; transition: grid-template-columns .38s cubic-bezier(.22,.8,.25,1); } .monitor-layout.focused { grid-template-columns: 276px minmax(360px, 1fr) 348px; } .monitor-layout.focused.control-expanded { grid-template-columns: 276px minmax(360px, 1fr) 560px; } -.device-panel, .detail-panel { background: #fff; min-width: 0; min-height: 0; overflow: auto; opacity: 0; visibility: hidden; z-index: 8; transition: transform .38s cubic-bezier(.22,.8,.25,1), opacity .2s ease, visibility 0s linear .38s; } +.device-panel, .detail-panel { background: #fff; min-width: 0; min-height: 0; overflow: auto; opacity: 0; visibility: hidden; z-index: 8; pointer-events: none; transition: transform .38s cubic-bezier(.22,.8,.25,1), opacity .2s ease, visibility 0s linear .38s; } .device-panel { width: 276px; border-right: 1px solid var(--line); padding: 18px 14px; transform: translateX(-100%); } .detail-panel { width: 348px; transform: translateX(100%); } .monitor-layout.control-expanded .detail-panel { width: 560px; } -.monitor-layout.focused .device-panel, .monitor-layout.focused .detail-panel { opacity: 1; visibility: visible; transform: translateX(0); transition-delay: 0s; } +.monitor-layout.focused .device-panel, .monitor-layout.focused .detail-panel { opacity: 1; visibility: visible; transform: translateX(0); pointer-events: auto; transition-delay: 0s; } .panel-heading { display: flex; justify-content: space-between; align-items: center; } .panel-heading > div { display: flex; align-items: baseline; gap: 8px; } .panel-heading h1 { margin: 0; font-size: 20px; } @@ -145,10 +145,9 @@ svg { width: 18px; height: 18px; fill: none; stroke: currentColor; stroke-width: .bound-drone.flying > i { color: var(--blue); }.bound-drone.offline > i { color: #8b969f; }.tree-line { position: absolute; left: 13px; top: -9px; width: 10px; height: 29px; border-left: 1px solid #c4ced6; border-bottom: 1px solid #c4ced6; border-radius: 0 0 0 5px; } .device-alert { margin: 0 10px 10px; padding-top: 8px; border-top: 1px solid var(--line); display: flex; align-items: center; gap: 5px; color: var(--red); font-size: 11px; }.device-alert svg { width: 12px; }.device-alert span { margin-left: auto; color: var(--muted); }.device-alert.muted { color: var(--muted); } -.map-panel { position: relative; min-width: 0; overflow: hidden; background: #71826f; isolation: isolate; } -.map-world { position: absolute; inset: 0; transform-origin: center; transition: transform .72s cubic-bezier(.2,.75,.25,1); will-change: transform; } -.map-surface { position: absolute; inset: 0; background-image: linear-gradient(rgba(16,40,38,.12), rgba(16,40,38,.22)), url("/assets/map-base-clean.png"); background-size: cover; background-position: center; filter: saturate(.42) contrast(.92); transform: scale(1.02); transition: filter .2s ease; } -.map-panel::after { content: ""; position: absolute; inset: 0; pointer-events: none; background: linear-gradient(90deg, rgba(18,28,32,.10), transparent 30%, rgba(10,20,26,.06)); z-index: 1; } +.map-panel { position: relative; min-width: 0; overflow: visible; background: transparent; isolation: isolate; pointer-events: none; } +.map-toolbar, .map-legend { pointer-events: auto; } +.map-panel::after { display: none; } .map-toolbar { position: absolute; z-index: 4; top: 14px; left: 14px; height: 34px; display: flex; background: #fff; border-radius: 5px; box-shadow: 0 4px 14px rgba(19,31,39,.17); overflow: hidden; } .map-type { padding: 0 13px; background: #fff; color: var(--muted); border-right: 1px solid var(--line); font-size: 13px; } .map-type.active { background: #263846; color: #fff; } diff --git a/src/utils/commonRefs.js b/src/utils/commonRefs.js index cbd5488..26877ab 100644 --- a/src/utils/commonRefs.js +++ b/src/utils/commonRefs.js @@ -20,7 +20,8 @@ class CommonRefs { } setRef(key, ref) { - if (key in this[refs]) return + // 允许显式 set null 唤醒 pending(无 token 等失败路径) + if (key in this[refs] && this[refs][key] != null) return this[refs][key] = ref const { [key]: resolves } = this[pendingList] @@ -33,10 +34,11 @@ class CommonRefs { getRef(key) { return new Promise((resolve) => { - const { [key]: ref } = this[refs] - if (ref) { - resolve(ref) - } else if (key in this[pendingList]) { + if (key in this[refs]) { + resolve(this[refs][key]) + return + } + if (key in this[pendingList]) { this[pendingList][key].push(resolve) } else { this[pendingList][key] = [resolve] diff --git a/src/views/MonitorView/MonitorView.vue b/src/views/MonitorView/MonitorView.vue index ed1a7aa..2dee417 100644 --- a/src/views/MonitorView/MonitorView.vue +++ b/src/views/MonitorView/MonitorView.vue @@ -67,30 +67,8 @@
-
-
- - - -
-
- 静态底图 + 天地图 @@ -244,12 +222,25 @@