diff --git a/sec-beidou/src/main/resources/static/js/device-overview.js b/sec-beidou/src/main/resources/static/js/device-overview.js new file mode 100644 index 00000000..c6447ab7 --- /dev/null +++ b/sec-beidou/src/main/resources/static/js/device-overview.js @@ -0,0 +1,755 @@ +(function() { + var map, vectorSource, vectorLayer, currentBaseLayer; + var greenFeatures = [], orangeFeatures = [], redFeatures = [], allFeatures = []; + var marker_state = 3, currentSearchedDevice = null, myLocationFeature = null, myLocationInterval; + var clusterSource, clusterLayer, showDeviceId = true, showCluster = true; + var minZoomForLabels = 4, maxZoomForClustering = 8; + var measureDraw, measureLayer, measureSource, measureTooltipElement, measureTooltip, sketch; + + // 天地图的Key + var TIANDITU_KEY = '0c260b8a094a4e0bc507808812cefdac'; + // 设备列表 + var deviceList = window.deviceList || []; + var pi = 3.14159265358979324, a = 6378245.0, ee = 0.00669342162296594323; + + // 判断是否超出中国,如果超出那么就不用转换坐标了 + function outOfChina(lon, lat) { + return (lon < 72.004 || lon > 137.8347) && (lat < 0.8293 || lat > 55.8271); + } + + function transformLat(x, y) { + var 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 * Math.sin(y * pi / 30.0)) * 2.0 / 3.0; + return ret; + } + + function transformLon(x, y) { + var 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; + } + + function transform(wgLat, wgLon) { + var mars_point = { lon: 0, lat: 0 }; + if (outOfChina(wgLon, wgLat)) { + mars_point.lat = wgLat; + mars_point.lon = wgLon; + return mars_point; + } + var dLat = transformLat(wgLon - 105.0, wgLat - 35.0); + var dLon = transformLon(wgLon - 105.0, wgLat - 35.0); + var radLat = wgLat / 180.0 * pi; + var magic = Math.sin(radLat); + magic = 1 - ee * magic * magic; + var sqrtMagic = Math.sqrt(magic); + dLat = (dLat * 180.0) / ((a * (1 - ee)) / (magic * sqrtMagic) * pi); + dLon = (dLon * 180.0) / (a / sqrtMagic * Math.cos(radLat) * pi); + mars_point.lat = wgLat + dLat; + mars_point.lon = wgLon + dLon; + return mars_point; + } + + var mapLayers = { + amap: new ol.layer.Tile({ + source: new ol.source.XYZ({ + url: 'https://webrd0{1-4}.is.autonavi.com/appmaptile?lang=zh_cn&size=1&scale=1&style=8&x={x}&y={y}&z={z}' + }) + }), + amap_satellite: new ol.layer.Group({ + layers: [ + new ol.layer.Tile({ + source: new ol.source.XYZ({ + url: 'https://webst0{1-4}.is.autonavi.com/appmaptile?style=6&x={x}&y={y}&z={z}' + }) + }), + new ol.layer.Tile({ + source: new ol.source.XYZ({ + url: 'https://webst0{1-4}.is.autonavi.com/appmaptile?style=8&x={x}&y={y}&z={z}' + }) + }) + ] + }), + tianditu_satellite: new ol.layer.Group({ + 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, + tileLoadFunction: tileLoadErrorHandler + }) + }), + 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, + tileLoadFunction: tileLoadErrorHandler + }) + }) + ] + }), + tianditu_normal: new ol.layer.Group({ + 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, + tileLoadFunction: tileLoadErrorHandler + }) + }), + 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, + tileLoadFunction: tileLoadErrorHandler + }) + }) + ] + }), + tianditu_terrain: new ol.layer.Group({ + 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, + tileLoadFunction: tileLoadErrorHandler + }) + }) + ] + }), + tianditu_terrain_hybrid: new ol.layer.Group({ + 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, + tileLoadFunction: tileLoadErrorHandler + }) + }), + 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, + tileLoadFunction: tileLoadErrorHandler + }) + }) + ] + }) + }; + + function tileLoadErrorHandler(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'); + } + }; + } + + function initialize() { + vectorSource = new ol.source.Vector(); + vectorLayer = new ol.layer.Vector({ + source: vectorSource, + style: function(feature) { + if (!feature.get('isMyLocation')) { + var deviceInfo = feature.get('deviceInfo'); + var iconSrc, color = '#000'; + + if (deviceInfo.warning == 2) iconSrc = '../images/loc1_red.png'; + else if (deviceInfo.warning == 1) iconSrc = '../images/loc1_orange.png'; + else iconSrc = '../images/loc1_green.png'; + + var style = new ol.style.Style({ + image: new ol.style.Icon({ anchor: [0.5, 1], src: iconSrc, scale: 0.7 }) + }); + + if (showDeviceId && map.getView().getZoom() >= minZoomForLabels) { + style.setText(new ol.style.Text({ + text: deviceInfo.deviceid, + offsetY: -30, + fill: new ol.style.Fill({ color: color }), + stroke: new ol.style.Stroke({ color: '#fff', width: 2 }), + font: '12px Arial' + })); + } + return style; + } + return null; + } + }); + + 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.Circle({ radius: 7, fill: new ol.style.Fill({ color: '#ffcc33' }) }) + }) + }); + + clusterSource = new ol.source.Cluster({ distance: 40, source: vectorSource }); + clusterLayer = new ol.layer.Vector({ + source: clusterSource, + style: function(feature) { + var size = feature.get('features').length; + return new ol.style.Style({ + image: new ol.style.Circle({ radius: 15, fill: new ol.style.Fill({ color: '#3399CC' }) }), + text: new ol.style.Text({ text: size.toString(), fill: new ol.style.Fill({ color: '#fff' }) }) + }); + } + }); + + var initialMapType = document.getElementById('mapTypeSelect').value; + currentBaseLayer = mapLayers[initialMapType]; + + map = new ol.Map({ + target: 'map-container', + layers: [currentBaseLayer, measureLayer, clusterLayer, vectorLayer], + view: new ol.View({ center: ol.proj.fromLonLat([116.404, 39.915]), zoom: 7 }) + }); + + var scaleLineControl = new ol.control.ScaleLine({ units: 'metric', bar: true, steps: 4, text: true, minWidth: 140 }); + map.addControl(scaleLineControl); + + function updateMapSize() { + map.updateSize(); + } + + setTimeout(updateMapSize, 200); + window.addEventListener('resize', function() { + setTimeout(updateMapSize, 200); + }); + window.addEventListener('load', function() { + setTimeout(updateMapSize, 500); + }); + + var measureDistanceBtn = document.getElementById('measure-distance'); + var clearMeasureBtn = document.getElementById('clear-measure'); + + measureDistanceBtn.addEventListener('click', function() { + this.classList.toggle('active'); + if (this.classList.contains('active')) { + addMeasureInteraction(); + document.getElementById('clear-measure').classList.remove('active'); + layer.msg('双击以结束测量'); + } else { + map.removeInteraction(measureDraw); + measureSource.clear(); + if (measureTooltipElement) measureTooltipElement.parentNode.removeChild(measureTooltipElement); + } + }); + + clearMeasureBtn.addEventListener('click', function() { + measureSource.clear(); + if (measureTooltipElement) measureTooltipElement.parentNode.removeChild(measureTooltipElement); + var overlays = map.getOverlays().getArray(); + var measureOverlays = overlays.filter(function(overlay) { + return overlay.getElement() && overlay.getElement().className && overlay.getElement().className.indexOf('ol-tooltip') !== -1; + }); + measureOverlays.forEach(function(overlay) { + map.removeOverlay(overlay); + }); + measureTooltipElement = null; + measureDistanceBtn.classList.remove('active'); + this.classList.add('active'); + setTimeout(function() { + document.getElementById('clear-measure').classList.remove('active'); + }, 300); + map.removeInteraction(measureDraw); + }); + + var initialZoom = map.getView().getZoom(); + if (showCluster && initialZoom < maxZoomForClustering) { + clusterLayer.setVisible(true); + vectorLayer.setVisible(false); + } else { + clusterLayer.setVisible(false); + vectorLayer.setVisible(true); + } + + map.getView().on('change:resolution', function() { + var zoom = map.getView().getZoom(); + if (showCluster) { + if (zoom >= maxZoomForClustering) { + clusterLayer.setVisible(false); + vectorLayer.setVisible(true); + } else { + clusterLayer.setVisible(true); + vectorLayer.setVisible(false); + } + } + vectorLayer.changed(); + }); + + map.on('click', function(evt) { + var feature = map.forEachFeatureAtPixel(evt.pixel, function(feature) { + return feature; + }); + if (feature) { + var features = feature.get('features'); + if (features && features.length > 1) { + var extent = vectorSource.getExtent(); + map.getView().fit(extent, { padding: [50, 50, 50, 50], duration: 1000 }); + } + } + }); + + if (deviceList.length > 0) { + var centerLat = 0, centerLon = 0; + for (var i = 0; i < deviceList.length; i++) { + centerLat += deviceList[i].latitude; + centerLon += deviceList[i].longitude; + } + centerLat = centerLat / deviceList.length; + centerLon = centerLon / deviceList.length; + map.getView().setCenter(ol.proj.fromLonLat([centerLon, centerLat])); + } + + addDeviceMarkers(); + myLocation(); + startLocationUpdates(); + } + + function switchMapType(mapType) { + map.removeLayer(currentBaseLayer); + currentBaseLayer = mapLayers[mapType]; + map.getLayers().insertAt(0, currentBaseLayer); + updateMyLocationForMapType(mapType); + addDeviceMarkers(); + } + + function updateMyLocationForMapType(mapType) { + if (myLocationFeature) { + var originalCoords = myLocationFeature.get('originalCoords'); + if (originalCoords) { + var lat = originalCoords.lat, lon = originalCoords.lon, coordinates; + if (mapType === 'amap' || mapType === 'amap_satellite') { + var gcjCoord = transform(lat, lon); + coordinates = ol.proj.fromLonLat([gcjCoord.lon, gcjCoord.lat]); + } else { + coordinates = ol.proj.fromLonLat([lon, lat]); + } + myLocationFeature.getGeometry().setCoordinates(coordinates); + } + } + } + + function addDeviceMarkers() { + var savedMyLocationFeature = myLocationFeature; + vectorSource.clear(); + greenFeatures = []; + orangeFeatures = []; + redFeatures = []; + allFeatures = []; + + for (var i = 0; i < deviceList.length; i++) { + var device = deviceList[i]; + var mapCoordinates; + var currentMapType = document.getElementById('mapTypeSelect').value; + if (currentMapType === 'amap' || currentMapType === 'amap_satellite') { + var gcjCoord = transform(device.latitude, device.longitude); + mapCoordinates = ol.proj.fromLonLat([gcjCoord.lon, gcjCoord.lat]); + } else { + mapCoordinates = ol.proj.fromLonLat([device.longitude, device.latitude]); + } + + var feature = new ol.Feature({ + geometry: new ol.geom.Point(mapCoordinates), + deviceInfo: device + }); + + if (device.warning == 2) redFeatures.push(feature); + else if (device.warning == 1) orangeFeatures.push(feature); + else greenFeatures.push(feature); + + allFeatures.push(feature); + vectorSource.addFeature(feature); + } + + if (savedMyLocationFeature) vectorSource.addFeature(savedMyLocationFeature); + + if (currentSearchedDevice) { + filterByDeviceId(currentSearchedDevice); + } else { + if (marker_state === 2) { + hideGreen(); + hideRed(); + } else if (marker_state === 3) { + hideGreen(); + hideOrange(); + } + } + vectorLayer.changed(); + } + + function myLocation() { + if (navigator.geolocation) { + navigator.geolocation.getCurrentPosition(function(position) { + var lon = position.coords.longitude; + var lat = position.coords.latitude; + var currentMapType = document.getElementById('mapTypeSelect').value; + var coordinates; + + if (currentMapType === 'amap' || currentMapType === 'amap_satellite') { + var gcjCoord = transform(lat, lon); + coordinates = ol.proj.fromLonLat([gcjCoord.lon, gcjCoord.lat]); + } else { + coordinates = ol.proj.fromLonLat([lon, lat]); + } + + if (myLocationFeature) { + vectorSource.removeFeature(myLocationFeature); + } + + myLocationFeature = new ol.Feature({ + geometry: new ol.geom.Point(coordinates), + isMyLocation: true, + originalCoords: { lat: lat, lon: lon } + }); + + var style = new ol.style.Style({ + image: new ol.style.Icon({ + anchor: [0.5, 1], + src: '../images/loc_blue.png', + scale: 0.7 + }) + }); + + myLocationFeature.setStyle(style); + vectorSource.addFeature(myLocationFeature); + map.getView().setCenter(coordinates); + }); + } + } + + function startLocationUpdates() { + if (myLocationInterval) { + clearInterval(myLocationInterval); + } + myLocationInterval = setInterval(function() { + myLocation(); + }, 10 * 60 * 1000); + } + + function showAll() { + document.getElementById('btn-all').classList.add('active'); + document.getElementById('btn-warning1').classList.remove('active'); + document.getElementById('btn-warning2').classList.remove('active'); + document.getElementById('btn-device-locate').classList.remove('active'); + document.getElementById('btn-device-locate').style.display = 'none'; + + currentSearchedDevice = null; + document.getElementById('deviceSearch').value = ''; + var savedMyLocationFeature = myLocationFeature; + vectorSource.clear(); + + if (savedMyLocationFeature) { + vectorSource.addFeature(savedMyLocationFeature); + } + for (var i = 0; i < allFeatures.length; i++) { + vectorSource.addFeature(allFeatures[i]); + } + marker_state = 1; + } + + function showWarning1() { + document.getElementById('btn-all').classList.remove('active'); + document.getElementById('btn-warning1').classList.add('active'); + document.getElementById('btn-warning2').classList.remove('active'); + document.getElementById('btn-device-locate').classList.remove('active'); + document.getElementById('btn-device-locate').style.display = 'none'; + + currentSearchedDevice = null; + document.getElementById('deviceSearch').value = ''; + var savedMyLocationFeature = myLocationFeature; + vectorSource.clear(); + + if (savedMyLocationFeature) { + vectorSource.addFeature(savedMyLocationFeature); + } + for (var i = 0; i < allFeatures.length; i++) { + vectorSource.addFeature(allFeatures[i]); + } + hideGreen(); + hideRed(); + marker_state = 2; + } + + function showWarning2() { + document.getElementById('btn-all').classList.remove('active'); + document.getElementById('btn-warning1').classList.remove('active'); + document.getElementById('btn-warning2').classList.add('active'); + document.getElementById('btn-device-locate').classList.remove('active'); + document.getElementById('btn-device-locate').style.display = 'none'; + + currentSearchedDevice = null; + document.getElementById('deviceSearch').value = ''; + var savedMyLocationFeature = myLocationFeature; + vectorSource.clear(); + + if (savedMyLocationFeature) { + vectorSource.addFeature(savedMyLocationFeature); + } + for (var i = 0; i < allFeatures.length; i++) { + vectorSource.addFeature(allFeatures[i]); + } + hideGreen(); + hideOrange(); + marker_state = 3; + } + + function showGreen() { + for (var i = 0; i < greenFeatures.length; i++) { + if (!vectorSource.hasFeature(greenFeatures[i])) { + vectorSource.addFeature(greenFeatures[i]); + } + } + } + + function showOrange() { + for (var i = 0; i < orangeFeatures.length; i++) { + if (!vectorSource.hasFeature(orangeFeatures[i])) { + vectorSource.addFeature(orangeFeatures[i]); + } + } + } + + function showRed() { + for (var i = 0; i < redFeatures.length; i++) { + if (!vectorSource.hasFeature(redFeatures[i])) { + vectorSource.addFeature(redFeatures[i]); + } + } + } + + function hideGreen() { + for (var i = 0; i < greenFeatures.length; i++) { + vectorSource.removeFeature(greenFeatures[i]); + } + } + + function hideOrange() { + for (var i = 0; i < orangeFeatures.length; i++) { + vectorSource.removeFeature(orangeFeatures[i]); + } + } + + function hideRed() { + for (var i = 0; i < redFeatures.length; i++) { + vectorSource.removeFeature(redFeatures[i]); + } + } + + function searchDevice() { + var deviceId = document.getElementById('deviceSearch').value.trim(); + if (!deviceId) { + currentSearchedDevice = null; + vectorSource.clear(); + for (var i = 0; i < allFeatures.length; i++) { + vectorSource.addFeature(allFeatures[i]); + } + if (marker_state === 2) { + hideGreen(); + hideRed(); + } else if (marker_state === 3) { + hideGreen(); + hideOrange(); + } + document.getElementById('btn-device-locate').style.display = 'none'; + updateFilterButtonsState(marker_state); + return; + } + currentSearchedDevice = deviceId; + filterByDeviceId(deviceId); + } + + function locateDeviceOnMap(deviceId, latitude, longitude) { + currentSearchedDevice = deviceId; + filterByDeviceId(deviceId); + 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) { + document.getElementById('btn-all').classList.remove('active'); + document.getElementById('btn-warning1').classList.remove('active'); + document.getElementById('btn-warning2').classList.remove('active'); + if (state === 1) { + document.getElementById('btn-all').classList.add('active'); + } else if (state === 2) { + document.getElementById('btn-warning1').classList.add('active'); + } else if (state === 3) { + document.getElementById('btn-warning2').classList.add('active'); + } + } + + function filterByDeviceId(deviceId) { + var savedMyLocationFeature = myLocationFeature; + vectorSource.clear(); + if (savedMyLocationFeature) { + vectorSource.addFeature(savedMyLocationFeature); + } + var found = false; + for (var i = 0; i < allFeatures.length; i++) { + var feature = allFeatures[i]; + var deviceInfo = feature.get('deviceInfo'); + if (deviceInfo && deviceInfo.deviceid.includes(deviceId)) { + vectorSource.addFeature(feature); + found = true; + var geometry = feature.getGeometry(); + var deviceCoord = geometry.getCoordinates(); + map.getView().setCenter(deviceCoord); + map.getView().setZoom(15); + } + } + if (!found) { + layer.msg('未找到设备: ' + deviceId); + if (marker_state === 1) { + showAll(); + } else if (marker_state === 2) { + showWarning1(); + } else if (marker_state === 3) { + showWarning2(); + } + } + document.getElementById('current-device-id').textContent = deviceId; + document.getElementById('btn-device-locate').style.display = 'block'; + document.getElementById('btn-device-locate').classList.add('active'); + document.getElementById('btn-all').classList.remove('active'); + document.getElementById('btn-warning1').classList.remove('active'); + document.getElementById('btn-warning2').classList.remove('active'); + } + + function addMeasureInteraction() { + var type = 'LineString'; + measureDraw = new ol.interaction.Draw({ + source: measureSource, + type: type, + 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(measureDraw); + createMeasureTooltip(); + var listener; + measureDraw.on('drawstart', function(evt) { + sketch = evt.feature; + listener = sketch.getGeometry().on('change', function(evt) { + var geom = evt.target; + var output = formatLength(geom); + measureTooltipElement.innerHTML = output; + measureTooltip.setPosition(geom.getLastCoordinate()); + }); + }); + measureDraw.on('drawend', function() { + measureTooltipElement.className = 'ol-tooltip ol-tooltip-static'; + measureTooltip.setOffset([0, -7]); + sketch = null; + measureTooltipElement = null; + createMeasureTooltip(); + ol.Observable.unByKey(listener); + }); + } + + function createMeasureTooltip() { + if (measureTooltipElement) { + measureTooltipElement.parentNode.removeChild(measureTooltipElement); + } + measureTooltipElement = document.createElement('div'); + measureTooltipElement.className = 'ol-tooltip ol-tooltip-measure'; + measureTooltip = new ol.Overlay({ + element: measureTooltipElement, + offset: [0, -15], + positioning: 'bottom-center', + stopEvent: false + }); + map.addOverlay(measureTooltip); + } + + function formatLength(line) { + var coordinates = line.getCoordinates(); + var length = 0; + for (var i = 0, ii = coordinates.length - 1; i < ii; ++i) { + var c1 = ol.proj.transform(coordinates[i], 'EPSG:3857', 'EPSG:4326'); + var c2 = ol.proj.transform(coordinates[i + 1], 'EPSG:3857', 'EPSG:4326'); + length += haversineDistance(c1, c2); + } + return length > 1000 ? Math.round((length / 1000) * 100) / 100 + ' 公里' : Math.round(length * 100) / 100 + ' 米'; + } + + function haversineDistance(coord1, coord2) { + var R = 6371000; + var dLat = (coord2[1] - coord1[1]) * Math.PI / 180; + var dLon = (coord2[0] - coord1[0]) * Math.PI / 180; + var a = Math.sin(dLat / 2) * Math.sin(dLat / 2) + + Math.cos(coord1[1] * Math.PI / 180) * Math.cos(coord2[1] * Math.PI / 180) * + Math.sin(dLon / 2) * Math.sin(dLon / 2); + var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a)); + return R * c; + } + + layui.use(['form'], function() { + var form = layui.form; + form.on('select(mapType)', function(data) { + switchMapType(data.value); + }); + form.on('switch(showDeviceId)', function(data) { + showDeviceId = data.elem.checked; + vectorLayer.changed(); + }); + form.on('switch(showCluster)', function(data) { + showCluster = data.elem.checked; + var zoom = map.getView().getZoom(); + if (showCluster) { + if (zoom < maxZoomForClustering) { + clusterLayer.setVisible(true); + vectorLayer.setVisible(false); + } else { + clusterLayer.setVisible(false); + vectorLayer.setVisible(true); + } + } else { + clusterLayer.setVisible(false); + vectorLayer.setVisible(true); + } + }); + initialize(); + showAll(); + }); + + window.searchDevice = searchDevice; + window.showAll = showAll; + window.showWarning1 = showWarning1; + window.showWarning2 = showWarning2; + window.locateDeviceOnMap = locateDeviceOnMap; + window.queryDevices = function(status_type) { + 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=' + status_type + }); + }; + +})(); 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 e7965680..29ac597a 100644 --- a/sec-beidou/src/main/resources/templates/page/device_overview.html +++ b/sec-beidou/src/main/resources/templates/page/device_overview.html @@ -69,18 +69,22 @@ } .btn-wrap { z-index: 999; - position: fixed; - bottom: 2rem; - margin-left: 1rem; - padding: .5rem .5rem; - border-radius: .25rem; - background-color: #fff; - box-shadow: 0 2px 6px 0 rgba(27, 142, 236, 0.5); + position: absolute; + bottom: 20px; + right: 20px; + padding: 10px; + border-radius: 4px; + background-color: white; + box-shadow: 0 2px 4px rgba(0,0,0,0.2); + display: flex; + flex-direction: row; + flex-wrap: wrap; + width: auto; } .btn { - width: 75px; + width: auto; + min-width: 75px; height: 30px; - float: left; background-color: #fff; color: rgba(27, 142, 236, 1); font-size: 14px; @@ -91,16 +95,19 @@ line-height: 30px; cursor: pointer; transition: all 0.3s ease; + float: none; + display: inline-block; } .btn:hover, .btn.active { background-color: rgba(27, 142, 236, 0.8); color: #fff; } #map-container { - height: 85vh; + height: 75vh; width: 100%; padding:0px; position: relative; + overflow: hidden; } .map-control-card { position: absolute; @@ -167,7 +174,117 @@ position: static; display: block; margin-bottom: 1em; + width: 100%; + box-sizing: border-box; } + + #map-container { + height: 75vh!important; + min-height: 300px; + overflow: hidden; + position: relative; + } + + .ol-viewport, + .ol-layers, + .ol-layer { + height: 100% !important; + } + + .btn-wrap { + position: static; + margin: 10px auto; + width: 100%; + justify-content: center; + box-sizing: border-box; + } + + .btn { + margin-bottom: 5px; + font-size: 12px; + padding: 0 5px; + } + + .measure-buttons { + display: flex; + justify-content: space-between; + } + + .search-box input { + height: 36px; + } + + .search-box button { + height: 36px; + width: 60px; + } + } + + .measure-buttons { + margin-top: 10px; + display: flex; + gap: 5px; + } + + .ol-scale-line { + position: absolute; + bottom: 8px; + left: 8px; + background: rgba(255, 255, 255, 0.8); + padding: 5px; + border-radius: 4px; + } + + .ol-scale-line-inner { + border: 1px solid #000; + border-top: none; + color: #000; + font-size: 12px; + text-align: center; + margin: 1px; + padding: 0px 2px; + } + + .ol-scale-container { + display: none; + } + + .ol-tooltip { + position: relative; + background: rgba(0, 0, 0, 0.7); + border-radius: 4px; + color: white; + padding: 6px 10px; + opacity: 0.9; + white-space: nowrap; + font-size: 14px; + pointer-events: none; + font-weight: bold; + box-shadow: 0 1px 3px rgba(0,0,0,0.3); + } + .ol-tooltip-measure { + opacity: 1; + font-weight: bold; + } + .ol-tooltip-static { + background-color: #ffcc33; + color: black; + border: 1px solid white; + box-shadow: 0 2px 5px rgba(0,0,0,0.2); + } + .ol-tooltip-measure:before, + .ol-tooltip-static:before { + border-top: 6px solid rgba(0, 0, 0, 0.7); + border-right: 6px solid transparent; + border-left: 6px solid transparent; + content: ""; + position: absolute; + bottom: -6px; + margin-left: -7px; + left: 50%; + } + .ol-tooltip-static:before { + border-top-color: #ffcc33; } @@ -177,7 +294,7 @@