From 1336bb16e63ab4f715b44e34e319b66f7a149379 Mon Sep 17 00:00:00 2001 From: yarnom Date: Fri, 4 Jul 2025 11:11:35 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=96=B0=E5=A2=9E=E6=B5=8B=E8=B7=9D?= =?UTF-8?q?=E5=92=8C=E6=AF=94=E4=BE=8B=E5=B0=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../templates/page/device_overview.html | 742 +++++++++--------- 1 file changed, 383 insertions(+), 359 deletions(-) diff --git a/sec-beidou/src/main/resources/templates/page/device_overview.html b/sec-beidou/src/main/resources/templates/page/device_overview.html index c3d8a838..127fd788 100644 --- a/sec-beidou/src/main/resources/templates/page/device_overview.html +++ b/sec-beidou/src/main/resources/templates/page/device_overview.html @@ -67,20 +67,20 @@ ul li { list-style: none; } - + .layuimini-main { height: 96vh; display: flex; flex-direction: column; } - + .map-wrapper { flex: 1; display: flex; flex-direction: column; position: relative; } - + .map-card { flex: 1; background: white; @@ -91,7 +91,7 @@ flex-direction: column; overflow: hidden; } - + #map-container { flex: 1; width: 100%; @@ -111,7 +111,7 @@ margin-bottom: 10px; color: #333; } - + /* 地图顶部功能条样式 */ .map-toolbar { position: absolute; @@ -132,21 +132,21 @@ width:auto; max-width: 95vw; } - + .toolbar-item { display: flex; align-items: center; gap: 6px; white-space: nowrap; } - + .toolbar-label { font-size: 12px; color: #666; white-space: nowrap; font-weight: 500; } - + .toolbar-select { border: 1px solid rgba(230, 230, 230, 0.8); border-radius: 6px; @@ -156,7 +156,7 @@ min-width: 120px; height: 28px; } - + .toolbar-input { border: 1px solid rgba(230, 230, 230, 0.8); border-radius: 6px; @@ -166,7 +166,7 @@ width: 140px; height: 28px; } - + .toolbar-btn { background: rgba(26, 160, 148, 0.9); color: white; @@ -178,75 +178,27 @@ height: 28px; transition: all 0.2s ease; } - + .toolbar-btn:hover { background: rgba(26, 160, 148, 1); transform: translateY(-1px); } - + .toolbar-divider { width: 1px; height: 20px; background: rgba(230, 230, 230, 0.6); } - - /* 比例尺样式 */ - .map-scale { - position: absolute; - bottom: 20px; - left: 20px; - z-index: 1000; - background: rgba(255, 255, 255, 0.9); - padding: 8px 12px; - border-radius: 6px; - box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1); - font-size: 12px; - color: #333; - font-weight: bold; - border: 1px solid rgba(0, 0, 0, 0.1); - } - - /* 测距工具样式 */ - .measure-tooltip { - position: relative; - background: rgba(0, 0, 0, 0.8); - border-radius: 4px; - color: white; - padding: 4px 8px; - opacity: 0.8; - white-space: nowrap; - font-size: 12px; - } - - .measure-tooltip-measure { - opacity: 1; - font-weight: bold; - } - - .measure-tooltip-static { - background-color: #ffcc33; - color: black; - border: 1px solid white; - } - - .help-tooltip { - background: rgba(0, 0, 0, 0.8); - color: white; - padding: 4px 8px; - border-radius: 4px; - font-size: 12px; - white-space: nowrap; - } - - + + .overview-stats { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; } - + .stat-item { display: flex; align-items: center; @@ -259,19 +211,19 @@ cursor: pointer; height: 28px; } - + .stat-item:hover { background: #e9ecef; } - + .stat-item.non-clickable { cursor: default; } - + .stat-item.non-clickable:hover { background: #f8f9fa; } - + .stat-dot { width: 6px; height: 6px; @@ -279,21 +231,21 @@ margin-right: 6px; flex-shrink: 0; } - + .dot-green { background-color: #48bb78; } .dot-blue { background-color: #4299e1; } .dot-gray { background-color: #a0aec0; } .dot-orange { background-color: #ed8936; } .dot-red { background-color: #f56565; } .dot-yellow { background-color: #ecc94b; } - + .stat-item span:nth-child(2) { font-size: 12px; color: #666; margin-right: 4px; white-space: nowrap; } - + .stat-number { font-size: 13px; font-weight: bold; @@ -306,36 +258,36 @@ height: calc(100dvh - 20px); /* 动态视口高度,支持移动端 */ overflow: hidden; } - + .map-wrapper { flex: 1; overflow: hidden; } - + .map-card { margin: 8px; height: calc(100% - 16px); overflow: hidden; } - + #map-container { height: 100%; overflow: hidden; } - - + + .device-overview-bar { padding: 8px 12px; margin-bottom: 8px; flex-shrink: 0; } - + .overview-stats { gap: 4px; flex-wrap: wrap; } - + .stat-item { flex: 0 0 auto; min-width: auto; @@ -348,25 +300,25 @@ overflow: hidden; text-overflow: ellipsis; } - + .stat-item span:not(.stat-dot):not(.stat-number) { display: none; } - + .stat-dot { width: 4px; height: 4px; margin-right: 3px; flex-shrink: 0; } - + .stat-number { font-size: 11px; font-weight: bold; } - - + + /* 移动端工具栏适配 */ .map-toolbar { position: static; @@ -380,19 +332,19 @@ gap: 6px; padding: 6px 10px; } - + .toolbar-item { gap: 4px; flex: 0 0 auto; } - + .toolbar-label { font-size: 10px; display: none; /* 隐藏标签节省空间 */ } - - + + .toolbar-select, .toolbar-input { font-size: 11px; @@ -400,22 +352,40 @@ min-width: 80px; width: auto; } - + .toolbar-btn { font-size: 11px; height: 24px; padding: 2px 8px; } - + .toolbar-divider { display: none; /* 隐藏分隔线 */ } - + #toolbar-device-locate span:not(.toolbar-label) { font-size: 10px; padding: 2px 4px; } } + + .ol-tooltip { + position: absolute; + background: rgba(255,255,255,0.8); + border-radius: 4px; + padding: 4px 8px; + border: 1px solid #d9d9d9; + color: #333; + font-size: 12px; + white-space: nowrap; + pointer-events: none; + z-index: 1001; + } + .ol-tooltip-static { + background: #ffcc33; + color: #222; + border: 1px solid #ffcc33; + } @@ -486,44 +456,48 @@ - +
- +
- +
- +
- +
- +
- + + + +
- + + +
+
+ + + +
- - -
比例尺 1:1000
+ @@ -541,7 +515,7 @@ var greenFeatures = []; var orangeFeatures = []; var redFeatures = []; - var marker_state = 1; // 1:all; 2:orange; 3:red + var marker_state = 3; // 1:all; 2:orange; 3:red var allFeatures = []; // 存储所有设备标记,用于搜索功能 var currentSearchedDevice = null; // 当前搜索的设备ID var myLocationFeature = null; // 存储"我的位置"标记 @@ -552,16 +526,9 @@ var showCluster = true; var minZoomForLabels = 4; var maxZoomForClustering = 8; - - // 测距相关变量 + // 测距专用source和layer var measureSource; - var measureVector; - var measureTooltipElement; - var measureTooltip; - var helpTooltipElement; - var helpTooltip; - var draw; - var measuring = false; + var measureLayer; // 天地图 API 密钥(fengyarnom@gmail.com) var TIANDITU_KEY = '0c260b8a094a4e0bc507808812cefdac'; @@ -650,12 +617,38 @@ layers: [ new ol.layer.Tile({ source: new ol.source.XYZ({ - url: 'https://t{0-7}.tianditu.gov.cn/img_w/wmts?SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&LAYER=img&STYLE=default&TILEMATRIXSET=w&FORMAT=tiles&TILEMATRIX={z}&TILEROW={y}&TILECOL={x}&tk=' + TIANDITU_KEY + url: 'https://t{0-7}.tianditu.gov.cn/img_w/wmts?SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&LAYER=img&STYLE=default&TILEMATRIXSET=w&FORMAT=tiles&TILEMATRIX={z}&TILEROW={y}&TILECOL={x}&tk=' + TIANDITU_KEY, + tileLoadFunction: function(imageTile, src) { + imageTile.getImage().src = src; + imageTile.getImage().onerror = function() { + // 天地图加载失败时切换到高德地图 + var mapTypeSelect = document.getElementById('mapTypeSelect'); + if(mapTypeSelect.value.startsWith('tianditu_')) { + mapTypeSelect.value = 'amap'; + switchMapType('amap'); + layer.msg('天地图加载失败,已自动切换到高德地图'); + layui.form.render('select'); + } + }; + } }) }), new ol.layer.Tile({ source: new ol.source.XYZ({ - url: 'https://t{0-7}.tianditu.gov.cn/cia_w/wmts?SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&LAYER=cia&STYLE=default&TILEMATRIXSET=w&FORMAT=tiles&TILEMATRIX={z}&TILEROW={y}&TILECOL={x}&tk=' + TIANDITU_KEY + url: 'https://t{0-7}.tianditu.gov.cn/cia_w/wmts?SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&LAYER=cia&STYLE=default&TILEMATRIXSET=w&FORMAT=tiles&TILEMATRIX={z}&TILEROW={y}&TILECOL={x}&tk=' + TIANDITU_KEY, + tileLoadFunction: function(imageTile, src) { + imageTile.getImage().src = src; + imageTile.getImage().onerror = function() { + // 天地图加载失败时切换到高德地图 + var mapTypeSelect = document.getElementById('mapTypeSelect'); + if(mapTypeSelect.value.startsWith('tianditu_')) { + mapTypeSelect.value = 'amap'; + switchMapType('amap'); + layer.msg('天地图加载失败,已自动切换到高德地图'); + layui.form.render('select'); + } + }; + } }) }) ] @@ -664,12 +657,38 @@ layers: [ new ol.layer.Tile({ source: new ol.source.XYZ({ - url: 'https://t{0-7}.tianditu.gov.cn/vec_w/wmts?SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&LAYER=vec&STYLE=default&TILEMATRIXSET=w&FORMAT=tiles&TILEMATRIX={z}&TILEROW={y}&TILECOL={x}&tk=' + TIANDITU_KEY + url: 'https://t{0-7}.tianditu.gov.cn/vec_w/wmts?SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&LAYER=vec&STYLE=default&TILEMATRIXSET=w&FORMAT=tiles&TILEMATRIX={z}&TILEROW={y}&TILECOL={x}&tk=' + TIANDITU_KEY, + tileLoadFunction: function(imageTile, src) { + imageTile.getImage().src = src; + imageTile.getImage().onerror = function() { + // 天地图加载失败时切换到高德地图 + var mapTypeSelect = document.getElementById('mapTypeSelect'); + if(mapTypeSelect.value.startsWith('tianditu_')) { + mapTypeSelect.value = 'amap'; + switchMapType('amap'); + layer.msg('天地图加载失败,已自动切换到高德地图'); + layui.form.render('select'); + } + }; + } }) }), new ol.layer.Tile({ source: new ol.source.XYZ({ - url: 'https://t{0-7}.tianditu.gov.cn/cva_w/wmts?SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&LAYER=cva&STYLE=default&TILEMATRIXSET=w&FORMAT=tiles&TILEMATRIX={z}&TILEROW={y}&TILECOL={x}&tk=' + TIANDITU_KEY + url: 'https://t{0-7}.tianditu.gov.cn/cva_w/wmts?SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&LAYER=cva&STYLE=default&TILEMATRIXSET=w&FORMAT=tiles&TILEMATRIX={z}&TILEROW={y}&TILECOL={x}&tk=' + TIANDITU_KEY, + tileLoadFunction: function(imageTile, src) { + imageTile.getImage().src = src; + imageTile.getImage().onerror = function() { + // 天地图加载失败时切换到高德地图 + var mapTypeSelect = document.getElementById('mapTypeSelect'); + if(mapTypeSelect.value.startsWith('tianditu_')) { + mapTypeSelect.value = 'amap'; + switchMapType('amap'); + layer.msg('天地图加载失败,已自动切换到高德地图'); + layui.form.render('select'); + } + }; + } }) }) ] @@ -678,7 +697,20 @@ layers: [ new ol.layer.Tile({ source: new ol.source.XYZ({ - url: 'https://t{0-7}.tianditu.gov.cn/ter_w/wmts?SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&LAYER=ter&STYLE=default&TILEMATRIXSET=w&FORMAT=tiles&TILEMATRIX={z}&TILEROW={y}&TILECOL={x}&tk=' + TIANDITU_KEY + url: 'https://t{0-7}.tianditu.gov.cn/ter_w/wmts?SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&LAYER=ter&STYLE=default&TILEMATRIXSET=w&FORMAT=tiles&TILEMATRIX={z}&TILEROW={y}&TILECOL={x}&tk=' + TIANDITU_KEY, + tileLoadFunction: function(imageTile, src) { + imageTile.getImage().src = src; + imageTile.getImage().onerror = function() { + // 天地图加载失败时切换到高德地图 + var mapTypeSelect = document.getElementById('mapTypeSelect'); + if(mapTypeSelect.value.startsWith('tianditu_')) { + mapTypeSelect.value = 'amap'; + switchMapType('amap'); + layer.msg('天地图矢量图加载失败,已自动切换到高德矢量图'); + layui.form.render('select'); + } + }; + } }) }) ] @@ -687,12 +719,38 @@ layers: [ new ol.layer.Tile({ source: new ol.source.XYZ({ - url: 'https://t{0-7}.tianditu.gov.cn/ter_w/wmts?SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&LAYER=ter&STYLE=default&TILEMATRIXSET=w&FORMAT=tiles&TILEMATRIX={z}&TILEROW={y}&TILECOL={x}&tk=' + TIANDITU_KEY + url: 'https://t{0-7}.tianditu.gov.cn/ter_w/wmts?SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&LAYER=ter&STYLE=default&TILEMATRIXSET=w&FORMAT=tiles&TILEMATRIX={z}&TILEROW={y}&TILECOL={x}&tk=' + TIANDITU_KEY, + tileLoadFunction: function(imageTile, src) { + imageTile.getImage().src = src; + imageTile.getImage().onerror = function() { + // 天地图加载失败时切换到高德地图 + var mapTypeSelect = document.getElementById('mapTypeSelect'); + if(mapTypeSelect.value.startsWith('tianditu_')) { + mapTypeSelect.value = 'amap'; + switchMapType('amap'); + layer.msg('天地图加载失败,已自动切换到高德地图'); + layui.form.render('select'); + } + }; + } }) }), new ol.layer.Tile({ source: new ol.source.XYZ({ - url: 'https://t{0-7}.tianditu.gov.cn/cta_w/wmts?SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&LAYER=cta&STYLE=default&TILEMATRIXSET=w&FORMAT=tiles&TILEMATRIX={z}&TILEROW={y}&TILECOL={x}&tk=' + TIANDITU_KEY + url: 'https://t{0-7}.tianditu.gov.cn/cta_w/wmts?SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&LAYER=cta&STYLE=default&TILEMATRIXSET=w&FORMAT=tiles&TILEMATRIX={z}&TILEROW={y}&TILECOL={x}&tk=' + TIANDITU_KEY, + tileLoadFunction: function(imageTile, src) { + imageTile.getImage().src = src; + imageTile.getImage().onerror = function() { + // 天地图加载失败时切换到高德地图 + var mapTypeSelect = document.getElementById('mapTypeSelect'); + if(mapTypeSelect.value.startsWith('tianditu_')) { + mapTypeSelect.value = 'amap'; + switchMapType('amap'); + layer.msg('天地图加载失败,已自动切换到高德地图'); + layui.form.render('select'); + } + }; + } }) }) ] @@ -785,6 +843,28 @@ }) }); + // 创建测距专用图层 + measureSource = new ol.source.Vector(); + measureLayer = new ol.layer.Vector({ + source: measureSource, + style: new ol.style.Style({ + fill: new ol.style.Fill({ color: 'rgba(255,255,255,0.2)' }), + stroke: new ol.style.Stroke({ color: '#ffcc33', width: 2 }), + image: new ol.style.RegularShape({ + points: 4, + radius: 8, + radius2: 0, + angle: Math.PI / 4, + stroke: new ol.style.Stroke({ color: '#ed8936', width: 2 }) + }) + }) + }); + map.addLayer(measureLayer); + + // 添加比例尺控件 + var scaleLineControl = new ol.control.ScaleLine(); + map.addControl(scaleLineControl); + // 设置初始可见性状态 var initialZoom = map.getView().getZoom(); if (showCluster && initialZoom < maxZoomForClustering) { @@ -807,7 +887,6 @@ } } vectorLayer.changed(); - updateScale(); // 更新比例尺 }); map.on('click', function(evt) { @@ -845,7 +924,6 @@ addDeviceMarkers(); myLocation(); startLocationUpdates(); - updateScale(); // 初始化比例尺 } function switchMapType(mapType) { @@ -942,229 +1020,6 @@ - // 新的地图功能事件处理 - function onMapFeaturesChange() { - var selectElement = document.getElementById('mapFeatures'); - var value = selectElement.value; - - switch(value) { - case 'toggle_labels': - showDeviceId = !showDeviceId; - vectorLayer.changed(); - break; - case 'toggle_cluster': - showCluster = !showCluster; - var zoom = map.getView().getZoom(); - if (showCluster) { - if (zoom >= maxZoomForClustering) { - clusterLayer.setVisible(false); - vectorLayer.setVisible(true); - } else { - clusterLayer.setVisible(true); - vectorLayer.setVisible(false); - } - } else { - clusterLayer.setVisible(false); - vectorLayer.setVisible(true); - } - break; - case 'measure_distance': - startMeasuring(); - break; - case 'clear_measure': - clearMeasurements(); - break; - } - - // 重置下拉框到默认状态 - selectElement.value = ''; - } - - // 测距功能 - function startMeasuring() { - if (measuring) return; - - measuring = true; - - // 创建测距图层 - if (!measureSource) { - measureSource = new ol.source.Vector(); - measureVector = new ol.layer.Vector({ - source: measureSource, - style: new ol.style.Style({ - fill: new ol.style.Fill({ - color: 'rgba(255, 255, 255, 0.2)' - }), - stroke: new ol.style.Stroke({ - color: '#ffcc33', - width: 2 - }), - image: new ol.style.Circle({ - radius: 7, - fill: new ol.style.Fill({ - color: '#ffcc33' - }) - }) - }) - }); - map.addLayer(measureVector); - } - - // 创建绘制交互 - draw = new ol.interaction.Draw({ - source: measureSource, - type: 'LineString', - style: new ol.style.Style({ - fill: new ol.style.Fill({ - color: 'rgba(255, 255, 255, 0.2)' - }), - stroke: new ol.style.Stroke({ - color: 'rgba(0, 0, 0, 0.5)', - lineDash: [10, 10], - width: 2 - }), - image: new ol.style.Circle({ - radius: 5, - stroke: new ol.style.Stroke({ - color: 'rgba(0, 0, 0, 0.7)' - }), - fill: new ol.style.Fill({ - color: 'rgba(255, 255, 255, 0.2)' - }) - }) - }) - }); - - map.addInteraction(draw); - - createMeasureTooltip(); - createHelpTooltip(); - - var listener; - draw.on('drawstart', function(evt) { - var sketch = evt.feature; - var tooltipCoord = evt.coordinate; - - listener = sketch.getGeometry().on('change', function(evt) { - var geom = evt.target; - var output; - if (geom instanceof ol.geom.LineString) { - output = formatLength(geom); - tooltipCoord = geom.getLastCoordinate(); - } - measureTooltipElement.innerHTML = output; - measureTooltip.setPosition(tooltipCoord); - }); - }); - - draw.on('drawend', function() { - measureTooltipElement.className = 'measure-tooltip measure-tooltip-static'; - measureTooltip.setOffset([0, -7]); - measureTooltipElement = null; - createMeasureTooltip(); - ol.Observable.unByKey(listener); - - // 结束测距 - map.removeInteraction(draw); - measuring = false; - - // 移除帮助提示 - if (helpTooltip) { - map.removeOverlay(helpTooltip); - helpTooltip = null; - helpTooltipElement = null; - } - }); - } - - function clearMeasurements() { - if (measureSource) { - measureSource.clear(); - } - - if (draw) { - map.removeInteraction(draw); - draw = null; - } - - measuring = false; - - // 清除所有测距相关的覆盖物 - var overlays = map.getOverlays().getArray().slice(); - overlays.forEach(function(overlay) { - if (overlay.getElement() && - (overlay.getElement().classList.contains('measure-tooltip') || - overlay.getElement().classList.contains('help-tooltip'))) { - map.removeOverlay(overlay); - } - }); - - measureTooltip = null; - measureTooltipElement = null; - helpTooltip = null; - helpTooltipElement = null; - } - - function createMeasureTooltip() { - if (measureTooltipElement) { - measureTooltipElement.parentNode.removeChild(measureTooltipElement); - } - measureTooltipElement = document.createElement('div'); - measureTooltipElement.className = 'measure-tooltip measure-tooltip-measure'; - measureTooltip = new ol.Overlay({ - element: measureTooltipElement, - offset: [0, -15], - positioning: 'bottom-center' - }); - map.addOverlay(measureTooltip); - } - - function createHelpTooltip() { - if (helpTooltipElement) { - helpTooltipElement.parentNode.removeChild(helpTooltipElement); - } - helpTooltipElement = document.createElement('div'); - helpTooltipElement.className = 'measure-tooltip help-tooltip'; - helpTooltipElement.innerHTML = '点击开始测距,双击结束'; - helpTooltip = new ol.Overlay({ - element: helpTooltipElement, - offset: [15, 0], - positioning: 'center-left' - }); - map.addOverlay(helpTooltip); - } - - function formatLength(line) { - var length = ol.Sphere.getLength(line); - var output; - if (length > 100) { - output = (Math.round(length / 1000 * 100) / 100) + ' km'; - } else { - output = (Math.round(length * 100) / 100) + ' m'; - } - return output; - } - - // 比例尺更新功能 - function updateScale() { - var view = map.getView(); - var resolution = view.getResolution(); - var units = view.getProjection().getUnits(); - var dpi = 25.4 / 0.28; - var mpu = ol.proj.METERS_PER_UNIT[units]; - var scale = resolution * mpu * 39.37 * dpi; - - if (scale >= 9500 && scale <= 950000) { - scale = Math.round(scale / 1000) * 1000; - } else if (scale >= 950000) { - scale = Math.round(scale / 100000) * 100000; - } else { - scale = Math.round(scale); - } - - document.getElementById('map-scale').textContent = '比例尺 1:' + scale.toLocaleString(); - } - function onMapTypeChange() { var mapType = document.getElementById('mapTypeSelectNew').value; switchMapType(mapType); @@ -1196,10 +1051,10 @@ currentSearchedDevice = deviceId; filterByDeviceId(deviceId); - + // 更新过滤器为显示所有设备,因为搜索时需要显示匹配的设备 document.getElementById('warningFilter').value = 'all'; - + // 显示设备定位信息 document.getElementById('current-device-id-new').textContent = deviceId; document.getElementById('toolbar-device-locate').style.display = 'flex'; @@ -1210,7 +1065,7 @@ // document.getElementById('deviceSearch').value = ''; document.getElementById('deviceSearchNew').value = ''; document.getElementById('toolbar-device-locate').style.display = 'none'; - + // 根据当前过滤器状态重新显示设备 var filterValue = document.getElementById('warningFilter').value; if (filterValue === 'all') { @@ -1227,7 +1082,7 @@ navigator.geolocation.getCurrentPosition(function(position) { var lon = position.coords.longitude; var lat = position.coords.latitude; - var currentMapType = document.getElementById('mapTypeSelectNew').value; + var currentMapType = document.getElementById('mapTypeSelect').value; var coordinates; if (currentMapType === 'amap' || currentMapType === 'amap_satellite') { @@ -1435,10 +1290,17 @@ currentSearchedDevice = deviceId; filterByDeviceId(deviceId); - var layerIndex = layer.index; - layer.close(layerIndex); - - layer.msg('已定位到设备: ' + deviceId); + var layerIndex = layer.open({ + title: '', + type: 2, + shade: 0.2, + maxmin: true, + shadeClose: true, + anim: 2, + offset: 'rb', + area: ['100%', '50%'], + content: '../page/gnss_q_status?query=' + deviceId, + }); } function updateFilterButtonsState(state) { @@ -1502,7 +1364,7 @@ // document.getElementById('btn-all').classList.remove('active'); // document.getElementById('btn-warning1').classList.remove('active'); // document.getElementById('btn-warning2').classList.remove('active'); - + // 更新新工具栏中的设备定位信息 document.getElementById('current-device-id-new').textContent = deviceId; document.getElementById('toolbar-device-locate').style.display = 'flex'; @@ -1563,7 +1425,7 @@ // 新工具栏的事件处理函数 function onWarningFilterChange() { var filterValue = document.getElementById('warningFilter').value; - + // 重置按钮状态 (注释掉原有按钮操作) // document.getElementById('btn-all').classList.remove('active'); // document.getElementById('btn-warning1').classList.remove('active'); @@ -1585,6 +1447,168 @@ showWarning2(); } } + + function onDisplayOptionsChange() { + var optionValue = document.getElementById('displayOptions').value; + + switch(optionValue) { + case 'both': + showDeviceId = true; + showCluster = true; + break; + case 'device': + showDeviceId = true; + showCluster = false; + break; + case 'cluster': + showDeviceId = false; + showCluster = true; + break; + case 'none': + showDeviceId = false; + showCluster = false; + break; + } + + // 更新图层可见性 + var zoom = map.getView().getZoom(); + if (showCluster) { + if (zoom >= maxZoomForClustering) { + clusterLayer.setVisible(false); + vectorLayer.setVisible(true); + } else { + clusterLayer.setVisible(true); + vectorLayer.setVisible(false); + } + } else { + clusterLayer.setVisible(false); + vectorLayer.setVisible(true); + } + + // 强制更新样式 + vectorLayer.changed(); + } + + // --- 测距相关变量 --- + var measureActive = false; + var measureDraw; // 当前测距交互 + var measureTooltipElement; + var measureTooltip; + var measureTooltips = []; // 存储所有测距点的overlay + + function toggleMeasureDistance() { + if (measureActive) { + deactivateMeasure(); + } else { + activateMeasure(); + } + } + + function activateMeasure() { + measureSource.clear(); + clearAllMeasureTooltips(); + measureActive = true; + document.getElementById('measure-distance-btn').style.background = '#ed8936'; + // 创建测距交互 + measureDraw = new ol.interaction.Draw({ + source: measureSource, + type: 'LineString', + style: new ol.style.Style({ + fill: new ol.style.Fill({ color: 'rgba(255,255,255,0.2)' }), + stroke: new ol.style.Stroke({ color: '#ffcc33', width: 2 }), + image: new ol.style.RegularShape({ + points: 4, + radius: 8, + radius2: 0, + angle: Math.PI / 4, + stroke: new ol.style.Stroke({ color: '#ed8936', width: 2 }) + }) + }) + }); + map.addInteraction(measureDraw); + + var sketch; + var listener; + measureDraw.on('drawstart', function(evt) { + sketch = evt.feature; + var coords = sketch.getGeometry().getCoordinates(); + // 第一个点 + addMeasureTooltip(coords[0], '0 m'); + listener = sketch.getGeometry().on('change', function(e) { + var geom = e.target; + var coords = geom.getCoordinates(); + clearAllMeasureTooltips(); + var total = 0; + for (var i = 0; i < coords.length; i++) { + if (i === 0) { + addMeasureTooltip(coords[0], '0 m'); + } else { + var seg = new ol.geom.LineString([coords[i-1], coords[i]]); + total += ol.sphere.getLength(seg); + var output = (total > 100 ? (Math.round(total / 100) / 10) + ' km' : (Math.round(total * 10) / 10) + ' m'); + addMeasureTooltip(coords[i], output, i === coords.length-1); + } + } + }); + }); + measureDraw.on('drawend', function(evt) { + // 终点的tooltip样式特殊 + if (measureTooltips.length > 0) { + var last = measureTooltips[measureTooltips.length-1]; + last.getElement().className = 'ol-tooltip ol-tooltip-static'; + } + ol.Observable.unByKey(listener); + measureDraw = null; + measureActive = false; + document.getElementById('measure-distance-btn').style.background = ''; + }); + } + + function deactivateMeasure() { + measureActive = false; + document.getElementById('measure-distance-btn').style.background = ''; + if (measureDraw) { + map.removeInteraction(measureDraw); + measureDraw = null; + } + if (measureTooltipElement) { + measureTooltipElement.parentNode.removeChild(measureTooltipElement); + measureTooltipElement = null; + } + document.getElementById('measure-result').innerHTML = ''; + measureSource.clear(); + clearAllMeasureTooltips(); + } + + // 添加测距tooltip + function addMeasureTooltip(coord, text, isLast) { + var elem = document.createElement('div'); + elem.className = isLast ? 'ol-tooltip ol-tooltip-static' : 'ol-tooltip ol-tooltip-measure'; + elem.innerHTML = text; + var overlay = new ol.Overlay({ + element: elem, + offset: [0, -15], + positioning: 'bottom-center' + }); + overlay.setPosition(coord); + map.addOverlay(overlay); + measureTooltips.push(overlay); + } + + // 清除所有测距tooltip + function clearAllMeasureTooltips() { + for (var i = 0; i < measureTooltips.length; i++) { + map.removeOverlay(measureTooltips[i]); + } + measureTooltips = []; + } + + // 清除测距按钮 + function clearMeasure() { + measureSource.clear(); + clearAllMeasureTooltips(); + document.getElementById('measure-result').innerHTML = ''; + }