Compare commits

...

4 Commits

Author SHA1 Message Date
702c6a87f4 feat: 优化页面效果 2025-07-04 22:00:01 +08:00
3e99132ad7 feat: 优化页面效果 2025-07-04 21:56:54 +08:00
efaf5fe8f4 feat: 优化页面效果 2025-07-04 21:48:26 +08:00
6ecc833a2c feat: 优化页面效果 2025-07-04 21:09:34 +08:00
10 changed files with 2045 additions and 2489 deletions

View File

@ -0,0 +1,83 @@
/**
* 坐标转换工具模块
* 提供WGS84和GCJ-02坐标系之间的转换功能
*/
var CoordinateUtils = (function() {
'use strict';
var pi = 3.14159265358979324;
var a = 6378245.0;
var ee = 0.00669342162296594323;
/**
* 判断是否在国内不在国内则不做偏移
*/
function outOfChina(lon, lat) {
if ((lon < 72.004 || lon > 137.8347) && (lat < 0.8293 || lat > 55.8271)) {
return true;
} else {
return false;
}
}
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;
}
function getMapCoordinates(lat, lon, mapType) {
var coordinates;
if (mapType === 'amap' || mapType === 'amap_satellite') {
// 高德地图 WGS84 转换为 GCJ-02
var gcjCoord = transform(lat, lon);
coordinates = ol.proj.fromLonLat([gcjCoord.lon, gcjCoord.lat]);
} else if (mapType.startsWith('google_')) {
// Google地图使用WGS84坐标系
coordinates = ol.proj.fromLonLat([lon, lat]);
} else {
// 天地图 CGCS2000与WGS84实质一样
coordinates = ol.proj.fromLonLat([lon, lat]);
}
return coordinates;
}
return {
transform: transform,
getMapCoordinates: getMapCoordinates,
outOfChina: outOfChina
};
})();

View File

@ -0,0 +1,369 @@
/**
* 设备标记管理模块
* 负责设备标记的创建分类和显示管理
*/
var DeviceMarkers = (function() {
'use strict';
var greenFeatures = [];
var orangeFeatures = [];
var redFeatures = [];
var allFeatures = [];
var myLocationFeature = null;
var myLocationInterval = null;
var showDeviceId = true;
var minZoomForLabels = 4;
var map = null;
var vectorSource = null;
var vectorLayer = null;
function init(mapInstance, vectorSourceInstance, vectorLayerInstance) {
map = mapInstance;
vectorSource = vectorSourceInstance;
vectorLayer = vectorLayerInstance;
}
function createDeviceStyle(feature) {
if (feature.get('isMyLocation')) {
return new ol.style.Style({
image: new ol.style.Icon({
anchor: [0.5, 1],
src: '../images/loc_blue.png',
scale: 0.7
})
});
}
var deviceInfo = feature.get('deviceInfo');
if (!deviceInfo) return null;
var iconSrc;
var color = '#000';
var isHovered = feature.get('hovered') === true;
var scale = isHovered ? 0.85 : 0.7;
// 根据告警级别选择图标
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: scale
})
});
// 根据缩放级别和设置决定是否显示设备ID
if (showDeviceId && map && map.getView().getZoom() >= minZoomForLabels) {
style.setText(new ol.style.Text({
text: deviceInfo.deviceid,
offsetY: -30,
fill: new ol.style.Fill({
color: isHovered ? '#1aa094' : color
}),
stroke: new ol.style.Stroke({
color: '#fff',
width: isHovered ? 3 : 2
}),
font: isHovered ? 'bold 12px Arial' : '12px Arial'
}));
}
return style;
}
function addDeviceMarkers(deviceList) {
if (!vectorSource || !deviceList) return;
var savedMyLocationFeature = myLocationFeature;
vectorSource.clear();
greenFeatures = [];
orangeFeatures = [];
redFeatures = [];
allFeatures = [];
for (var i = 0; i < deviceList.length; i++) {
var device = deviceList[i];
var currentMapType = getCurrentMapType();
var mapCoordinates = CoordinateUtils.getMapCoordinates(
device.latitude,
device.longitude,
currentMapType
);
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 (vectorLayer) {
vectorLayer.changed();
}
}
function getCurrentMapType() {
var mapTypeSelect = document.getElementById('mapTypeSelectNew');
return mapTypeSelect ? mapTypeSelect.value : 'tianditu_satellite';
}
function showAllDevices() {
if (!vectorSource) return;
var savedMyLocationFeature = myLocationFeature;
vectorSource.clear();
if (savedMyLocationFeature) {
vectorSource.addFeature(savedMyLocationFeature);
}
for (var i = 0; i < allFeatures.length; i++) {
vectorSource.addFeature(allFeatures[i]);
}
}
function showWarning1Devices() {
if (!vectorSource) return;
var savedMyLocationFeature = myLocationFeature;
vectorSource.clear();
if (savedMyLocationFeature) {
vectorSource.addFeature(savedMyLocationFeature);
}
for (var i = 0; i < allFeatures.length; i++) {
vectorSource.addFeature(allFeatures[i]);
}
hideGreenFeatures();
hideRedFeatures();
}
function showWarning2Devices() {
if (!vectorSource) return;
var savedMyLocationFeature = myLocationFeature;
vectorSource.clear();
if (savedMyLocationFeature) {
vectorSource.addFeature(savedMyLocationFeature);
}
for (var i = 0; i < allFeatures.length; i++) {
vectorSource.addFeature(allFeatures[i]);
}
hideGreenFeatures();
hideOrangeFeatures();
}
function hideGreenFeatures() {
for (var i = 0; i < greenFeatures.length; i++) {
vectorSource.removeFeature(greenFeatures[i]);
}
}
function hideOrangeFeatures() {
for (var i = 0; i < orangeFeatures.length; i++) {
vectorSource.removeFeature(orangeFeatures[i]);
}
}
function hideRedFeatures() {
for (var i = 0; i < redFeatures.length; i++) {
vectorSource.removeFeature(redFeatures[i]);
}
}
function findDeviceById(deviceId) {
// console.log('搜索设备:', deviceId, '(类型:', typeof deviceId, ')');
// console.log('当前设备总数:', allFeatures.length);
var searchTerm = String(deviceId).trim();
for (var i = 0; i < allFeatures.length; i++) {
var feature = allFeatures[i];
var deviceInfo = feature.get('deviceInfo');
if (deviceInfo) {
var currentDeviceId = String(deviceInfo.deviceid);
// console.log('检查设备:', currentDeviceId, '(类型:', typeof deviceInfo.deviceid, ')');
if (currentDeviceId === searchTerm) {
// console.log('精确匹配找到设备:', currentDeviceId);
return feature;
}
if (currentDeviceId.indexOf(searchTerm) !== -1) {
// console.log('部分匹配找到设备:', currentDeviceId);
return feature;
}
if (currentDeviceId.replace(/\s+/g, '') === searchTerm.replace(/\s+/g, '')) {
// console.log('去除空格后匹配找到设备:', currentDeviceId);
return feature;
}
}
}
console.log('未找到设备:', deviceId);
return null;
}
function locateDevice(deviceId) {
var feature = findDeviceById(deviceId);
if (feature && map) {
var geometry = feature.getGeometry();
var coordinates = geometry.getCoordinates();
map.getView().animate({
center: coordinates,
zoom: Math.max(map.getView().getZoom(), 15),
duration: 1000
});
return true;
}
return false;
}
/**
* 获取我的位置
*/
function getMyLocation() {
if (navigator.geolocation) {
navigator.geolocation.getCurrentPosition(
function(position) {
var lat = position.coords.latitude;
var lon = position.coords.longitude;
var currentMapType = getCurrentMapType();
var coordinates = CoordinateUtils.getMapCoordinates(lat, lon, currentMapType);
if (myLocationFeature) {
vectorSource.removeFeature(myLocationFeature);
}
myLocationFeature = new ol.Feature({
geometry: new ol.geom.Point(coordinates),
isMyLocation: true
});
vectorSource.addFeature(myLocationFeature);
map.getView().animate({
center: coordinates,
zoom: 15,
duration: 1000
});
},
function(error) {
console.error('获取位置失败:', error);
}
);
}
}
function startLocationUpdates() {
if (navigator.geolocation) {
myLocationInterval = setInterval(function() {
getMyLocation();
}, 30000);
}
}
function stopLocationUpdates() {
if (myLocationInterval) {
clearInterval(myLocationInterval);
myLocationInterval = null;
}
}
function updateMyLocationForMapType(mapType) {
if (myLocationFeature) {
var geometry = myLocationFeature.getGeometry();
var coordinates = geometry.getCoordinates();
var lonLat = ol.proj.toLonLat(coordinates);
var newCoordinates = CoordinateUtils.getMapCoordinates(lonLat[1], lonLat[0], mapType);
myLocationFeature.setGeometry(new ol.geom.Point(newCoordinates));
}
}
function setShowDeviceId(show) {
showDeviceId = show;
if (vectorLayer) {
vectorLayer.changed();
}
}
function getDeviceStats() {
return {
total: allFeatures.length,
green: greenFeatures.length,
orange: orangeFeatures.length,
red: redFeatures.length
};
}
return {
init: init,
createDeviceStyle: createDeviceStyle,
addDeviceMarkers: addDeviceMarkers,
showAllDevices: showAllDevices,
showWarning1Devices: showWarning1Devices,
showWarning2Devices: showWarning2Devices,
hideGreenFeatures: hideGreenFeatures,
hideOrangeFeatures: hideOrangeFeatures,
hideRedFeatures: hideRedFeatures,
findDeviceById: findDeviceById,
locateDevice: locateDevice,
getMyLocation: getMyLocation,
startLocationUpdates: startLocationUpdates,
stopLocationUpdates: stopLocationUpdates,
updateMyLocationForMapType: updateMyLocationForMapType,
setShowDeviceId: setShowDeviceId,
getDeviceStats: getDeviceStats,
getAllFeatures: function() { return allFeatures; },
getGreenFeatures: function() { return greenFeatures; },
getOrangeFeatures: function() { return orangeFeatures; },
getRedFeatures: function() { return redFeatures; },
getMyLocationFeature: function() { return myLocationFeature; }
};
})();

View File

@ -0,0 +1,218 @@
/**
* 设备总览主入口文件
* 负责整个设备总览模块的初始化和全局函数暴露
*/
var DeviceOverview = (function() {
'use strict';
// 全局变量从原HTML中提取
var deviceList = [];
/**
* 初始化设备总览模块
* @param {Array} devices - 设备列表数据
* @param {Object} options - 配置选项
*/
function init(devices, options) {
deviceList = devices || [];
// 设置全局变量供其他模块使用
window.deviceList = deviceList;
window.userRole = options && options.role ? options.role : 'USER';
// 等待layui加载完成后初始化
layui.use(['form'], function(){
var form = layui.form;
// 绑定表单事件
form.on('select(mapTypeNew)', function(data){
MapCore.switchMapType(data.value);
});
// 初始化地图核心
MapCore.initialize(deviceList);
// 默认显示所有设备
document.getElementById('warningFilter').value = 'all';
SearchFilter.showAllDevices();
});
}
// 暴露给HTML使用的全局函数
/**
* 地图类型变化处理
*/
function onMapTypeChange() {
return MapCore.onMapTypeChange();
}
/**
* 搜索设备
*/
function searchDeviceNew() {
return MapCore.searchDeviceNew();
}
/**
* 告警过滤变化处理
*/
function onWarningFilterChange() {
return MapCore.onWarningFilterChange();
}
/**
* 切换地图功能菜单
*/
function toggleMapFunctionsMenu() {
return MapCore.toggleMapFunctionsMenu();
}
/**
* 切换设备ID显示
*/
function toggleDeviceId() {
return MapCore.toggleDeviceId();
}
/**
* 切换集群显示
*/
function toggleCluster() {
return MapCore.toggleCluster();
}
/**
* 切换测距功能
*/
function toggleMeasureDistance() {
return MeasureTools.toggleMeasureDistance();
}
/**
* 完成测量
*/
function finishMeasuring() {
return MeasureTools.finishMeasuring();
}
/**
* 清除测距
*/
function clearMeasure() {
return MeasureTools.clearMeasure();
}
/**
* 切换天气预报功能
*/
function toggleWeatherForecast() {
return WeatherForecast.toggleWeatherForecast();
}
/**
* 关闭天气卡片
*/
function closeWeatherCard() {
return WeatherForecast.closeWeatherCard();
}
/**
* 显示上一个天气预报
*/
function showPrevForecast() {
return WeatherForecast.showPrevForecast();
}
/**
* 显示下一个天气预报
*/
function showNextForecast() {
return WeatherForecast.showNextForecast();
}
/**
* 查询设备
* @param {string} statusType - 状态类型
*/
function queryDevices(statusType) {
return SearchFilter.queryDevices(statusType);
}
/**
* 定位设备到地图
* @param {string} deviceId - 设备ID
* @param {number} latitude - 纬度
* @param {number} longitude - 经度
*/
function locateDeviceOnMap(deviceId, latitude, longitude) {
return SearchFilter.locateDeviceOnMap(deviceId, latitude, longitude);
}
/**
* 直接定位设备
* @param {string} deviceId - 设备ID
*/
function locateDeviceDirectly(deviceId) {
return SearchFilter.locateDeviceDirectly(deviceId);
}
/**
* 切换地图类型
* @param {string} mapType - 地图类型
*/
function switchMapType(mapType) {
return MapCore.switchMapType(mapType);
}
// 公开API
return {
init: init,
// 地图相关
onMapTypeChange: onMapTypeChange,
switchMapType: switchMapType,
// 搜索和过滤
searchDeviceNew: searchDeviceNew,
onWarningFilterChange: onWarningFilterChange,
queryDevices: queryDevices,
locateDeviceOnMap: locateDeviceOnMap,
locateDeviceDirectly: locateDeviceDirectly,
// 地图功能
toggleMapFunctionsMenu: toggleMapFunctionsMenu,
toggleDeviceId: toggleDeviceId,
toggleCluster: toggleCluster,
// 测距工具
toggleMeasureDistance: toggleMeasureDistance,
finishMeasuring: finishMeasuring,
clearMeasure: clearMeasure,
// 天气预报
toggleWeatherForecast: toggleWeatherForecast,
closeWeatherCard: closeWeatherCard,
showPrevForecast: showPrevForecast,
showNextForecast: showNextForecast
};
})();
// 将主要函数暴露到全局作用域供HTML中的onclick等使用
window.DeviceOverview = DeviceOverview;
window.onMapTypeChange = DeviceOverview.onMapTypeChange;
window.searchDeviceNew = DeviceOverview.searchDeviceNew;
window.onWarningFilterChange = DeviceOverview.onWarningFilterChange;
window.toggleMapFunctionsMenu = DeviceOverview.toggleMapFunctionsMenu;
window.toggleDeviceId = DeviceOverview.toggleDeviceId;
window.toggleCluster = DeviceOverview.toggleCluster;
window.toggleMeasureDistance = DeviceOverview.toggleMeasureDistance;
window.finishMeasuring = DeviceOverview.finishMeasuring;
window.clearMeasure = DeviceOverview.clearMeasure;
window.toggleWeatherForecast = DeviceOverview.toggleWeatherForecast;
window.closeWeatherCard = DeviceOverview.closeWeatherCard;
window.showPrevForecast = DeviceOverview.showPrevForecast;
window.showNextForecast = DeviceOverview.showNextForecast;
window.queryDevices = DeviceOverview.queryDevices;
window.locateDeviceOnMap = DeviceOverview.locateDeviceOnMap;
window.locateDeviceDirectly = DeviceOverview.locateDeviceDirectly;

View File

@ -0,0 +1,360 @@
/**
* 地图核心模块
* 负责地图初始化事件处理和核心功能管理
*/
var MapCore = (function() {
'use strict';
var map = null;
var vectorSource = null;
var vectorLayer = null;
var clusterSource = null;
var clusterLayer = null;
var currentBaseLayer = null;
var showDeviceId = true;
var showCluster = true;
var minZoomForLabels = 4;
var maxZoomForClustering = 8;
var hoveredFeature = null;
function initialize(deviceList) {
// 创建矢量数据源和图层
vectorSource = new ol.source.Vector();
vectorLayer = new ol.layer.Vector({
source: vectorSource,
style: function(feature) {
return DeviceMarkers.createDeviceStyle(feature);
}
});
// 创建集群数据源和图层
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;
var style = 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'
})
})
});
return style;
}
});
var initialMapType = document.getElementById('mapTypeSelectNew').value || 'tianditu_satellite';
currentBaseLayer = MapLayers.getLayer(initialMapType);
map = new ol.Map({
target: 'map-container',
layers: [
currentBaseLayer,
clusterLayer,
vectorLayer
],
view: new ol.View({
center: ol.proj.fromLonLat([116.404, 39.915]),
zoom: 7
})
});
DeviceMarkers.init(map, vectorSource, vectorLayer);
MeasureTools.init(map);
WeatherForecast.init();
var scaleLineControl = new ol.control.ScaleLine();
map.addControl(scaleLineControl);
var initialZoom = map.getView().getZoom();
updateLayerVisibility(initialZoom);
map.getView().on('change:resolution', function() {
var zoom = map.getView().getZoom();
updateLayerVisibility(zoom);
vectorLayer.changed();
});
bindMouseEvents();
if (deviceList && deviceList.length > 0) {
setCenterFromDevices(deviceList);
}
DeviceMarkers.addDeviceMarkers(deviceList);
DeviceMarkers.getMyLocation();
DeviceMarkers.startLocationUpdates();
document.getElementById('showDeviceIdSwitch').checked = showDeviceId;
document.getElementById('showClusterSwitch').checked = showCluster;
}
function updateLayerVisibility(zoom) {
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);
}
}
function bindMouseEvents() {
map.on('pointermove', function(evt) {
if (evt.dragging) {
return;
}
var pixel = map.getEventPixel(evt.originalEvent);
var hit = map.hasFeatureAtPixel(pixel);
map.getTargetElement().style.cursor = hit ? 'pointer' : '';
var feature = map.forEachFeatureAtPixel(pixel, function(feature) {
return feature;
});
if (hoveredFeature && hoveredFeature !== feature) {
hoveredFeature.set('hovered', false);
}
if (feature) {
// 处理集群
var features = feature.get('features');
if (features && features.length === 1) {
features[0].set('hovered', true);
hoveredFeature = features[0];
} else if (!features && feature.get('deviceInfo')) {
feature.set('hovered', true);
hoveredFeature = feature;
}
}
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
});
} else if (features && features.length === 1) {
// 单个设备点击
var deviceInfo = features[0].get('deviceInfo');
if (deviceInfo) {
showDeviceInfo(deviceInfo);
// 如果天气预测开启,显示天气卡片
if (WeatherForecast.isEnabled()) {
WeatherForecast.showWeatherForecast(deviceInfo);
}
}
} else if (feature.get('deviceInfo')) {
var deviceInfo = feature.get('deviceInfo');
showDeviceInfo(deviceInfo);
// 如果天气预测开启,显示天气卡片
if (WeatherForecast.isEnabled()) {
WeatherForecast.showWeatherForecast(deviceInfo);
}
}
}
});
}
function showDeviceInfo(deviceInfo) {
var statusText = '';
if (deviceInfo.warning === 2) {
statusText = '严重告警';
} else if (deviceInfo.warning === 1) {
statusText = '一般告警';
} else {
statusText = '正常';
}
var infoMsg = ' 设备: ' + deviceInfo.deviceid +
' | 状态: ' + statusText +
' | 坐标: ' + deviceInfo.latitude.toFixed(4) + ', ' + deviceInfo.longitude.toFixed(4);
if (window.layer && typeof window.layer.msg === 'function') {
window.layer.msg(infoMsg, {
time: 3000,
area: ['auto', 'auto'],
offset: 'auto'
});
}
}
function setCenterFromDevices(deviceList) {
if (!deviceList || deviceList.length === 0) return;
var minLat = deviceList[0].latitude;
var maxLat = deviceList[0].latitude;
var minLon = deviceList[0].longitude;
var maxLon = deviceList[0].longitude;
for (var i = 1; i < deviceList.length; i++) {
var device = deviceList[i];
minLat = Math.min(minLat, device.latitude);
maxLat = Math.max(maxLat, device.latitude);
minLon = Math.min(minLon, device.longitude);
maxLon = Math.max(maxLon, device.longitude);
}
var centerLat = (minLat + maxLat) / 2;
var centerLon = (minLon + maxLon) / 2;
map.getView().setCenter(ol.proj.fromLonLat([centerLon, centerLat]));
}
function switchMapType(mapType) {
if (!MapLayers.hasLayer(mapType)) {
console.error('未知的地图类型:', mapType);
return;
}
map.removeLayer(currentBaseLayer);
currentBaseLayer = MapLayers.getLayer(mapType);
map.getLayers().insertAt(0, currentBaseLayer);
DeviceMarkers.updateMyLocationForMapType(mapType);
// 重新获取设备列表并添加标记
var deviceList = window.deviceList || [];
DeviceMarkers.addDeviceMarkers(deviceList);
}
function toggleDeviceId() {
showDeviceId = document.getElementById('showDeviceIdSwitch').checked;
DeviceMarkers.setShowDeviceId(showDeviceId);
if (window.layer && typeof window.layer.msg === 'function') {
window.layer.msg(showDeviceId ? '已显示设备信息' : '已隐藏设备信息');
}
}
function toggleCluster() {
showCluster = document.getElementById('showClusterSwitch').checked;
var zoom = map.getView().getZoom();
updateLayerVisibility(zoom);
if (window.layer && typeof window.layer.msg === 'function') {
window.layer.msg(showCluster ? '已启用集群显示' : '已禁用集群显示');
}
}
function toggleMapFunctionsMenu() {
var menu = document.getElementById('mapFunctionsMenu');
if (menu) {
menu.classList.toggle('show');
if (menu.classList.contains('show')) {
document.addEventListener('click', closeMapFunctionsMenu);
}
}
}
/**
* 关闭地图功能菜单
* @param {Event} event - 点击事件
*/
function closeMapFunctionsMenu(event) {
var dropdown = document.getElementById('mapFunctionsMenu');
var toggleBtn = document.querySelector('.dropdown-toggle');
if (dropdown && !dropdown.contains(event.target) && !toggleBtn.contains(event.target)) {
dropdown.classList.remove('show');
document.removeEventListener('click', closeMapFunctionsMenu);
}
}
/**
* 地图类型变化处理
*/
function onMapTypeChange() {
var mapType = document.getElementById('mapTypeSelectNew').value;
switchMapType(mapType);
}
function onWarningFilterChange() {
var filterValue = document.getElementById('warningFilter').value;
switch(filterValue) {
case 'all':
SearchFilter.showAllDevices();
break;
case 'warning1':
SearchFilter.showWarning1Devices();
break;
case 'warning2':
SearchFilter.showWarning2Devices();
break;
}
}
function searchDeviceNew() {
var searchInput = document.getElementById('deviceSearchNew');
if (searchInput) {
var deviceId = searchInput.value.trim();
if (deviceId) {
SearchFilter.searchDevice(deviceId);
} else {
if (window.layer && typeof window.layer.msg === 'function') {
window.layer.msg('请输入设备编号');
}
}
}
}
function getMap() {
return map;
}
function getVectorSource() {
return vectorSource;
}
function getVectorLayer() {
return vectorLayer;
}
return {
initialize: initialize,
switchMapType: switchMapType,
toggleDeviceId: toggleDeviceId,
toggleCluster: toggleCluster,
toggleMapFunctionsMenu: toggleMapFunctionsMenu,
onMapTypeChange: onMapTypeChange,
onWarningFilterChange: onWarningFilterChange,
searchDeviceNew: searchDeviceNew,
getMap: getMap,
getVectorSource: getVectorSource,
getVectorLayer: getVectorLayer
};
})();

View File

@ -0,0 +1,179 @@
/**
* 地图图层管理模块
* 管理不同类型的地图图层天地图高德谷歌等
*/
var MapLayers = (function() {
'use strict';
// 天地图 API 密钥 fengyarnom@gmail.com
var TIANDITU_KEY = '0c260b8a094a4e0bc507808812cefdac';
function createTiandituTileLoadFunction() {
return function(imageTile, src) {
imageTile.getImage().src = src;
imageTile.getImage().onerror = function() {
// 天地图加载失败时切换到高德地图
var mapTypeSelect = document.getElementById('mapTypeSelectNew');
if(mapTypeSelect && mapTypeSelect.value.startsWith('tianditu_')) {
mapTypeSelect.value = 'amap';
if (window.DeviceOverview && typeof window.DeviceOverview.switchMapType === 'function') {
window.DeviceOverview.switchMapType('amap');
}
if (window.layer && typeof window.layer.msg === 'function') {
window.layer.msg('天地图加载失败,已自动切换到高德地图');
}
if (window.layui && window.layui.form) {
window.layui.form.render('select');
}
}
};
};
}
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}'
})
})
]
}),
// 谷歌卫星图
google_satellite: new ol.layer.Tile({
source: new ol.source.XYZ({
url: 'https://mt{0-3}.google.com/vt/lyrs=s&x={x}&y={y}&z={z}',
crossOrigin: 'anonymous'
})
}),
// 谷歌地形图
google_terrain: new ol.layer.Tile({
source: new ol.source.XYZ({
url: 'https://mt{0-3}.google.com/vt/lyrs=p&x={x}&y={y}&z={z}',
crossOrigin: 'anonymous'
})
}),
// 谷歌道路图
google_roadmap: new ol.layer.Tile({
source: new ol.source.XYZ({
url: 'https://mt{0-3}.google.com/vt/lyrs=m&x={x}&y={y}&z={z}',
crossOrigin: 'anonymous'
})
}),
// 谷歌混合图
google_hybrid: new ol.layer.Tile({
source: new ol.source.XYZ({
url: 'https://mt{0-3}.google.com/vt/lyrs=y&x={x}&y={y}&z={z}',
crossOrigin: 'anonymous'
})
}),
// 天地图卫星影像
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: createTiandituTileLoadFunction()
})
}),
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: createTiandituTileLoadFunction()
})
})
]
}),
// 天地图矢量图
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: createTiandituTileLoadFunction()
})
}),
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: createTiandituTileLoadFunction()
})
})
]
}),
// 天地图地形图
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: createTiandituTileLoadFunction()
})
})
]
}),
// 天地图地形混合图
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: createTiandituTileLoadFunction()
})
}),
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: createTiandituTileLoadFunction()
})
})
]
})
};
function getLayer(mapType) {
return mapLayers[mapType];
}
function getAllLayers() {
return mapLayers;
}
function hasLayer(mapType) {
return mapLayers.hasOwnProperty(mapType);
}
return {
getLayer: getLayer,
getAllLayers: getAllLayers,
hasLayer: hasLayer
};
})();

View File

@ -0,0 +1,303 @@
/**
* 测距工具模块
* 提供地图测距功能
*/
var MeasureTools = (function() {
'use strict';
var measureActive = false;
var measureDraw = null;
var measureSource = null;
var measureLayer = null;
var measureTooltips = [];
var measureFeatures = [];
var currentMeasureTooltips = [];
var currentSketch = null;
var currentListener = null;
var segmentTooltips = [];
var map = null;
function init(mapInstance) {
map = mapInstance;
// 测距专用图层
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 })
})
})
});
if (map) {
map.addLayer(measureLayer);
}
}
function toggleMeasureDistance() {
if (measureActive) {
deactivateMeasure();
if (window.layer && typeof window.layer.msg === 'function') {
window.layer.msg('测距功能已关闭');
}
} else {
activateMeasure();
if (window.layer && typeof window.layer.msg === 'function') {
window.layer.msg('点击左键添加距离节点,点击右键结束测量 :)');
}
}
var menu = document.getElementById('mapFunctionsMenu');
if (menu) {
menu.classList.remove('show');
}
}
function finishMeasuring() {
if (measureActive && currentSketch && measureDraw) {
measureDraw.finishDrawing();
}
}
function activateMeasure() {
if (!map || !measureSource) return;
measureActive = true;
// 显示测量状态指示器
var measureStatus = document.getElementById('measureStatus');
if (measureStatus) {
measureStatus.style.display = 'flex';
}
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);
map.getViewport().addEventListener('contextmenu', function(e) {
if (measureActive && currentSketch) {
e.preventDefault();
measureDraw.finishDrawing();
}
});
measureDraw.on('drawstart', function(evt) {
currentSketch = evt.feature;
currentMeasureTooltips = [];
segmentTooltips = [];
currentListener = currentSketch.getGeometry().on('change', function(e) {
var geom = e.target;
var coords = geom.getCoordinates();
clearTemporaryTooltips();
clearSegmentTooltips();
// 计算并显示每个节点的距离
var total = 0;
for (var i = 0; i < coords.length; i++) {
if (i === 0) {
// 起点
var startTooltip = createMeasureTooltip(coords[0], '起点');
currentMeasureTooltips.push(startTooltip);
} else {
// 计算段距离
var seg = new ol.geom.LineString([coords[i-1], coords[i]]);
var segmentLength = ol.sphere.getLength(seg);
total += segmentLength;
// 显示每个节点的累计距离
var output = formatLength(total);
var tooltip = createMeasureTooltip(coords[i], output);
segmentTooltips.push(tooltip);
if (i === coords.length - 1) {
currentMeasureTooltips.push(tooltip);
}
}
}
});
});
// 绘制结束
measureDraw.on('drawend', function(evt) {
var coords = evt.feature.getGeometry().getCoordinates();
clearTemporaryTooltips();
clearSegmentTooltips();
var total = 0;
for (var i = 0; i < coords.length; i++) {
if (i === 0) {
var startTooltip = createMeasureTooltip(coords[0], '起点', true);
measureTooltips.push(startTooltip);
} else {
var seg = new ol.geom.LineString([coords[i-1], coords[i]]);
total += ol.sphere.getLength(seg);
var output = formatLength(total);
var tooltip = createMeasureTooltip(coords[i], output, true);
measureTooltips.push(tooltip);
}
}
measureFeatures.push(evt.feature);
if (currentListener) {
ol.Observable.unByKey(currentListener);
}
currentSketch = null;
currentListener = null;
var measureStatus = document.getElementById('measureStatus');
if (measureStatus) {
measureStatus.style.display = 'none';
}
map.removeInteraction(measureDraw);
measureActive = false;
if (window.layer && typeof window.layer.msg === 'function') {
window.layer.msg('测量完成');
}
});
}
function deactivateMeasure() {
measureActive = false;
var measureStatus = document.getElementById('measureStatus');
if (measureStatus) {
measureStatus.style.display = 'none';
}
if (measureDraw && map) {
map.removeInteraction(measureDraw);
measureDraw = null;
}
if (currentListener) {
ol.Observable.unByKey(currentListener);
currentListener = null;
}
currentSketch = null;
clearTemporaryTooltips();
clearSegmentTooltips();
}
function createMeasureTooltip(coord, text, isStatic) {
var elem = document.createElement('div');
elem.className = isStatic ? '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);
if (map) {
map.addOverlay(overlay);
}
return overlay;
}
function formatLength(length) {
if (length > 1000) {
return (Math.round(length / 100) / 10) + ' km';
} else {
return (Math.round(length * 10) / 10) + ' m';
}
}
function clearAllMeasureTooltips() {
if (!map) return;
for (var i = 0; i < measureTooltips.length; i++) {
map.removeOverlay(measureTooltips[i]);
}
measureTooltips = [];
clearTemporaryTooltips();
}
function clearTemporaryTooltips() {
if (!map) return;
for (var i = 0; i < currentMeasureTooltips.length; i++) {
map.removeOverlay(currentMeasureTooltips[i]);
}
currentMeasureTooltips = [];
}
function clearSegmentTooltips() {
if (!map) return;
for (var i = 0; i < segmentTooltips.length; i++) {
map.removeOverlay(segmentTooltips[i]);
}
segmentTooltips = [];
}
function clearMeasure() {
if (measureSource) {
measureSource.clear();
}
clearAllMeasureTooltips();
measureFeatures = [];
if (window.layer && typeof window.layer.msg === 'function') {
window.layer.msg('测距标记已清除');
}
// 关闭地图功能菜单
var menu = document.getElementById('mapFunctionsMenu');
if (menu) {
menu.classList.remove('show');
}
}
function isActive() {
return measureActive;
}
function getMeasureCount() {
return measureFeatures.length;
}
return {
init: init,
toggleMeasureDistance: toggleMeasureDistance,
finishMeasuring: finishMeasuring,
clearMeasure: clearMeasure,
isActive: isActive,
getMeasureCount: getMeasureCount
};
})();

View File

@ -0,0 +1,187 @@
/**
* 搜索和过滤功能模块
* 负责设备搜索过滤和查询功能
*/
var SearchFilter = (function() {
'use strict';
var currentSearchedDevice = null;
var markerState = 3; // 1:all; 2:orange; 3:red
function searchDevice(deviceId) {
if (!deviceId || !deviceId.trim()) {
clearSearch();
return false;
}
deviceId = deviceId.trim();
currentSearchedDevice = deviceId;
var success = DeviceMarkers.locateDevice(deviceId);
if (success) {
if (window.layer && typeof window.layer.msg === 'function') {
window.layer.msg('已定位到设备: ' + deviceId);
}
// 获取设备信息并显示天气预测(如果启用)
var targetFeature = DeviceMarkers.findDeviceById(deviceId);
if (targetFeature && window.WeatherForecast && window.WeatherForecast.isEnabled()) {
var deviceInfo = targetFeature.get('deviceInfo');
if (deviceInfo) {
window.WeatherForecast.showWeatherForecast(deviceInfo);
}
}
} else {
if (window.layer && typeof window.layer.msg === 'function') {
window.layer.msg('未找到设备: ' + deviceId);
}
}
return success;
}
function clearSearch() {
currentSearchedDevice = null;
var searchInput = document.getElementById('deviceSearchNew');
if (searchInput) {
searchInput.value = '';
}
// 恢复到当前的过滤状态
applyCurrentFilter();
}
function applyCurrentFilter() {
switch(markerState) {
case 1:
showAllDevices();
break;
case 2:
showWarning1Devices();
break;
case 3:
showWarning2Devices();
break;
}
}
function showAllDevices() {
currentSearchedDevice = null;
clearSearchInput();
DeviceMarkers.showAllDevices();
markerState = 1;
updateFilterSelect('all');
}
function showWarning1Devices() {
currentSearchedDevice = null;
clearSearchInput();
DeviceMarkers.showWarning1Devices();
markerState = 2;
updateFilterSelect('warning1');
}
function showWarning2Devices() {
currentSearchedDevice = null;
clearSearchInput();
DeviceMarkers.showWarning2Devices();
markerState = 3;
updateFilterSelect('warning2');
}
function clearSearchInput() {
var searchInput = document.getElementById('deviceSearchNew');
if (searchInput) {
searchInput.value = '';
}
}
function updateFilterSelect(filterValue) {
var filterSelect = document.getElementById('warningFilter');
if (filterSelect) {
filterSelect.value = filterValue;
}
}
function filterDevicesByStatus(statusType) {
switch(statusType) {
case 'warning1':
showWarning1Devices();
break;
case 'warning2':
showWarning2Devices();
break;
case 'offline':
case 'no_fwd':
case 'nofixed':
case 'nogga':
// 对于这些状态,显示所有设备,让用户在弹窗中选择
showAllDevices();
break;
default:
showAllDevices();
break;
}
}
function queryDevices(statusType) {
filterDevicesByStatus(statusType);
// 打开设备列表弹窗
if (window.layer && typeof window.layer.open === 'function') {
var index = window.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=' + statusType,
});
}
}
function locateDeviceOnMap(deviceId, latitude, longitude) {
currentSearchedDevice = deviceId;
var success = DeviceMarkers.locateDevice(deviceId);
if (success && window.layer && typeof window.layer.closeAll === 'function') {
window.layer.closeAll();
}
return success;
}
function locateDeviceDirectly(deviceId) {
currentSearchedDevice = deviceId;
return DeviceMarkers.locateDevice(deviceId);
}
function getCurrentSearchedDevice() {
return currentSearchedDevice;
}
function getMarkerState() {
return markerState;
}
function setMarkerState(state) {
markerState = state;
}
return {
searchDevice: searchDevice,
clearSearch: clearSearch,
showAllDevices: showAllDevices,
showWarning1Devices: showWarning1Devices,
showWarning2Devices: showWarning2Devices,
filterDevicesByStatus: filterDevicesByStatus,
queryDevices: queryDevices,
locateDeviceOnMap: locateDeviceOnMap,
locateDeviceDirectly: locateDeviceDirectly,
getCurrentSearchedDevice: getCurrentSearchedDevice,
getMarkerState: getMarkerState,
setMarkerState: setMarkerState
};
})();

View File

@ -0,0 +1,307 @@
var WeatherForecast = (function() {
'use strict';
var weatherApiKey = 'Uxh4IdMuAvhSiBnsf4UUDVGF4e3YAp2B';
var weatherEnabled = false;
var weatherData = null;
var currentForecastIndex = 0;
var currentWeatherDevice = null;
function init() {
// 天气预报模块初始化完成
}
function toggleWeatherForecast() {
var role = window.userRole || 'USER';
if (role !== 'SUPER_ADMIN') {
if (window.layer && typeof window.layer.msg === 'function') {
window.layer.msg('您没有权限使用此功能');
}
return;
}
var enableSwitch = document.getElementById('enableWeatherSwitch');
weatherEnabled = enableSwitch ? enableSwitch.checked : false;
if (weatherEnabled) {
if (window.layer && typeof window.layer.msg === 'function') {
window.layer.msg(
'搜索设备或点击地图设备图标即可自动查询天气预测',
{time: 3000, area: ['300px', '80px']}
);
}
} else {
if (window.layer && typeof window.layer.msg === 'function') {
window.layer.msg('天气预测功能已关闭');
}
closeWeatherCard();
}
var menu = document.getElementById('mapFunctionsMenu');
if (menu) {
menu.classList.remove('show');
}
}
function showWeatherForecast(deviceInfo) {
currentWeatherDevice = deviceInfo;
weatherData = null;
var role = window.userRole || 'USER';
if (role !== 'SUPER_ADMIN') {
return;
}
if (!weatherEnabled) {
if (window.layer && typeof window.layer.msg === 'function') {
window.layer.msg('天气预测功能未启用', {time: 2000});
}
return;
}
var deviceIdElement = document.getElementById('weatherDeviceId');
var deviceCoordsElement = document.getElementById('weatherDeviceCoords');
if (deviceIdElement) {
deviceIdElement.textContent = '设备: ' + deviceInfo.deviceid;
}
if (deviceCoordsElement) {
deviceCoordsElement.textContent =
'坐标: ' + deviceInfo.latitude.toFixed(4) + ', ' + deviceInfo.longitude.toFixed(4);
}
var weatherCard = document.getElementById('weatherForecastCard');
if (weatherCard) {
weatherCard.style.display = 'block';
}
var contentElement = document.getElementById('weatherForecastContent');
if (contentElement) {
contentElement.innerHTML =
'<div class="weather-loading">' +
'<i class="layui-icon layui-icon-loading layui-icon-anim-rotate"></i>' +
'<p>请确保网络可访问 Windy API 服务</p>' +
'<p>正在获取天气预测数据...</p>' +
'</div>';
}
var prevBtn = document.getElementById('prevForecast');
var nextBtn = document.getElementById('nextForecast');
var timeDisplay = document.getElementById('forecastTimeDisplay');
if (prevBtn) prevBtn.disabled = true;
if (nextBtn) nextBtn.disabled = true;
if (timeDisplay) timeDisplay.textContent = '--:--';
fetchWeatherData(deviceInfo.latitude, deviceInfo.longitude);
}
function closeWeatherCard() {
var weatherCard = document.getElementById('weatherForecastCard');
if (weatherCard) {
weatherCard.style.display = 'none';
}
currentWeatherDevice = null;
weatherData = null;
}
function showPrevForecast() {
if (!weatherData || currentForecastIndex <= 0) return;
currentForecastIndex--;
displayCurrentForecast();
updateForecastNavigation();
}
function showNextForecast() {
if (!weatherData || !weatherData.ts || currentForecastIndex >= weatherData.ts.length - 1) return;
currentForecastIndex++;
displayCurrentForecast();
updateForecastNavigation();
}
function updateForecastNavigation() {
if (!weatherData || !weatherData.ts) return;
var prevBtn = document.getElementById('prevForecast');
var nextBtn = document.getElementById('nextForecast');
var timeDisplay = document.getElementById('forecastTimeDisplay');
if (prevBtn) prevBtn.disabled = (currentForecastIndex <= 0);
if (nextBtn) nextBtn.disabled = (currentForecastIndex >= weatherData.ts.length - 1);
if (timeDisplay) {
var timestamp = weatherData.ts[currentForecastIndex];
var date = new Date(timestamp);
timeDisplay.textContent = formatDateTime(date);
}
}
function fetchWeatherData(lat, lon) {
var requestBody = {
"lat": parseFloat(lat.toFixed(2)),
"lon": parseFloat(lon.toFixed(2)),
"model": "gfs",
"parameters": ["temp", "wind", "precip", "pressure", "rh", "windGust"],
"levels": ["surface"],
"key": weatherApiKey,
"hours": 72
};
fetch('https://api.windy.com/api/point-forecast/v2', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Accept': 'application/json'
},
body: JSON.stringify(requestBody)
})
.then(function(response) {
if (!response.ok) {
throw new Error('网络响应状态: ' + response.status);
}
return response.json();
})
.then(function(data) {
weatherData = data;
var currentTime = new Date().getTime();
var closestIndex = 0;
var futureIndex = -1;
if (weatherData.ts && weatherData.ts.length > 0) {
for (var i = 0; i < weatherData.ts.length; i++) {
if (weatherData.ts[i] > currentTime) {
futureIndex = i;
break;
}
}
if (futureIndex >= 0) {
closestIndex = futureIndex;
} else {
var smallestDiff = Number.MAX_VALUE;
for (var i = 0; i < weatherData.ts.length; i++) {
var diff = Math.abs(weatherData.ts[i] - currentTime);
if (diff < smallestDiff) {
smallestDiff = diff;
closestIndex = i;
}
}
}
}
currentForecastIndex = closestIndex;
displayCurrentForecast();
updateForecastNavigation();
})
.catch(function(error) {
console.error('天气数据获取失败:', error);
displayWeatherError('获取天气数据失败: ' + error.message);
});
}
function displayCurrentForecast() {
if (!weatherData || !weatherData.ts || weatherData.ts.length === 0) {
displayWeatherError('无可用的天气预测数据');
return;
}
var i = currentForecastIndex;
var forecastHtml = '<div class="weather-forecast-item"><div class="weather-param-grid">';
if (weatherData['temp-surface'] && weatherData['temp-surface'][i] !== null) {
var temp = (weatherData['temp-surface'][i] - 273.15).toFixed(1);
forecastHtml += createWeatherParam('温度', temp + '°C');
}
if (weatherData['wind_u-surface'] && weatherData['wind_v-surface'] &&
weatherData['wind_u-surface'][i] !== null && weatherData['wind_v-surface'][i] !== null) {
var windU = weatherData['wind_u-surface'][i];
var windV = weatherData['wind_v-surface'][i];
var windSpeed = Math.sqrt(windU * windU + windV * windV).toFixed(1);
var windDir = getWindDirection(windU, windV);
forecastHtml += createWeatherParam('风速', windSpeed + ' m/s');
forecastHtml += createWeatherParam('风向', windDir);
}
if (weatherData['past3hprecip-surface'] && weatherData['past3hprecip-surface'][i] !== null) {
var precip = weatherData['past3hprecip-surface'][i].toFixed(1);
forecastHtml += createWeatherParam('降水', precip + ' mm');
}
if (weatherData['rh-surface'] && weatherData['rh-surface'][i] !== null) {
var humidity = weatherData['rh-surface'][i].toFixed(0);
forecastHtml += createWeatherParam('湿度', humidity + '%');
}
if (weatherData['pressure-surface'] && weatherData['pressure-surface'][i] !== null) {
var pressure = (weatherData['pressure-surface'][i] / 100).toFixed(0);
forecastHtml += createWeatherParam('气压', pressure + ' hPa');
}
if (weatherData['gust-surface'] && weatherData['gust-surface'][i] !== null) {
var gust = weatherData['gust-surface'][i].toFixed(1);
forecastHtml += createWeatherParam('阵风', gust + ' m/s');
}
forecastHtml += '</div></div>';
var contentElement = document.getElementById('weatherForecastContent');
if (contentElement) {
contentElement.innerHTML = forecastHtml;
}
}
function displayWeatherError(message) {
var contentElement = document.getElementById('weatherForecastContent');
if (contentElement) {
contentElement.innerHTML =
'<div class="weather-error">' +
'<i class="layui-icon layui-icon-close"></i>' +
'<p>' + message + '</p>' +
'</div>';
}
}
function createWeatherParam(label, value) {
return '<div class="weather-param">' +
'<span class="weather-param-label">' + label + '</span>' +
'<span class="weather-param-value">' + value + '</span>' +
'</div>';
}
function formatDateTime(date) {
var month = (date.getMonth() + 1).toString().padStart(2, '0');
var day = date.getDate().toString().padStart(2, '0');
var hours = date.getHours().toString().padStart(2, '0');
var minutes = date.getMinutes().toString().padStart(2, '0');
return month + '-' + day + ' ' + hours + ':' + minutes;
}
function getWindDirection(u, v) {
var angle = Math.atan2(-u, -v) * 180 / Math.PI;
angle = (angle + 360) % 360;
var directions = ['北', '东北', '东', '东南', '南', '西南', '西', '西北'];
var index = Math.round(angle / 45) % 8;
return directions[index];
}
function isEnabled() {
return weatherEnabled;
}
return {
init: init,
toggleWeatherForecast: toggleWeatherForecast,
showWeatherForecast: showWeatherForecast,
closeWeatherCard: closeWeatherCard,
showPrevForecast: showPrevForecast,
showNextForecast: showNextForecast,
isEnabled: isEnabled
};
})();

View File

@ -1,755 +0,0 @@
(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
});
};
})();