feat: 优化页面效果
This commit is contained in:
parent
d694ea8835
commit
0d88e161d9
@ -570,6 +570,17 @@
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-bottom: 12px;
|
||||
cursor: move;
|
||||
padding: 10px 20px;
|
||||
border-bottom: 1px solid rgba(0, 0, 0, 0.05);
|
||||
border-radius: 8px 8px 0 0;
|
||||
transition: background-color 0.2s ease;
|
||||
margin: -16px -16px 12px -16px;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.weather-card-header:hover {
|
||||
background-color: rgba(26, 160, 148, 0.05);
|
||||
}
|
||||
|
||||
.weather-card-title {
|
||||
@ -773,6 +784,12 @@
|
||||
.weather-param-value {
|
||||
font-size: 8px;
|
||||
}
|
||||
|
||||
#measureStatus{
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
padding: 6px 0px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@ -830,9 +847,11 @@
|
||||
<div class="map-card">
|
||||
|
||||
<div id="map-container">
|
||||
<div id="weatherForecastCard" class="weather-forecast-card" style="display: none;">
|
||||
<div id="weatherForecastCard" class="weather-forecast-card" style="display: none;" th:if="${role=='SUPER_ADMIN'}">
|
||||
<div class="weather-card-header">
|
||||
<h3 class="weather-card-title">Windy 天气预测 :) </h3>
|
||||
<h3 class="weather-card-title">
|
||||
Windy 天气预测 :)
|
||||
</h3>
|
||||
<button class="weather-close-btn" onclick="closeWeatherCard()">×</button>
|
||||
</div>
|
||||
<div id="weatherDeviceInfo" class="weather-device-info">
|
||||
@ -924,7 +943,7 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="dropdown-divider"></div>
|
||||
<div class="dropdown-group">
|
||||
<div class="dropdown-group" th:if="${role=='SUPER_ADMIN'}">
|
||||
<div class="dropdown-group-title">Windy 天气预测</div>
|
||||
<div class="dropdown-item">
|
||||
<label class="switch-label">
|
||||
@ -1577,7 +1596,7 @@
|
||||
function onMapTypeChange() {
|
||||
var mapType = document.getElementById('mapTypeSelectNew').value;
|
||||
|
||||
if(mapType.startsWith('google_') && [[${role}]] != "SUPER_ADMIN") {
|
||||
if(mapType.startsWith('google_') && /*[[${role}]]*/ 'USER' != "SUPER_ADMIN") {
|
||||
layer.msg('拒绝使用');
|
||||
document.getElementById('mapTypeSelectNew').value = 'tianditu_terrain_hybrid';
|
||||
mapType = 'tianditu_terrain_hybrid';
|
||||
@ -1912,6 +1931,9 @@
|
||||
// 默认显示所有设备
|
||||
document.getElementById('warningFilter').value = 'all';
|
||||
showAll();
|
||||
|
||||
// 初始化天气卡片拖动功能
|
||||
initWeatherCardDrag();
|
||||
});
|
||||
|
||||
function queryDevices(status_type) {
|
||||
@ -2180,7 +2202,6 @@
|
||||
|
||||
function deactivateMeasure() {
|
||||
measureActive = false;
|
||||
|
||||
// 隐藏测量状态指示器
|
||||
document.getElementById('measureStatus').style.display = 'none';
|
||||
|
||||
@ -2250,6 +2271,12 @@
|
||||
document.getElementById('mapFunctionsMenu').classList.remove('show');
|
||||
}
|
||||
function toggleWeatherForecast() {
|
||||
var role = /*[[${role}]]*/ 'USER';
|
||||
if (role !== 'SUPER_ADMIN') {
|
||||
layer.msg('您没有权限使用此功能');
|
||||
return;
|
||||
}
|
||||
|
||||
weatherEnabled = document.getElementById('enableWeatherSwitch').checked;
|
||||
if (weatherEnabled) {
|
||||
layer.msg(
|
||||
@ -2290,15 +2317,18 @@
|
||||
anim: 2
|
||||
});
|
||||
}
|
||||
|
||||
// 显示天气预测卡片
|
||||
|
||||
function showWeatherForecast(deviceInfo) {
|
||||
currentWeatherDevice = deviceInfo;
|
||||
currentForecastIndex = 0;
|
||||
weatherData = null;
|
||||
|
||||
var role = /*[[${role}]]*/ 'USER';
|
||||
if (role !== 'SUPER_ADMIN') {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!weatherEnabled) {
|
||||
// 如果天气预测未启用,显示提示信息
|
||||
layer.msg(
|
||||
'天气预测功能未启用,请在地图功能菜单中开启',
|
||||
{time: 2000}
|
||||
@ -2311,6 +2341,8 @@
|
||||
'坐标: ' + deviceInfo.latitude.toFixed(4) + ', ' + deviceInfo.longitude.toFixed(4);
|
||||
|
||||
document.getElementById('weatherForecastCard').style.display = 'block';
|
||||
|
||||
initWeatherCardDrag();
|
||||
|
||||
document.getElementById('weatherForecastContent').innerHTML =
|
||||
'<div class="weather-loading">' +
|
||||
@ -2363,8 +2395,7 @@
|
||||
var date = new Date(timestamp);
|
||||
timeDisplay.textContent = formatDateTime(date);
|
||||
}
|
||||
|
||||
// 获取天气数据
|
||||
|
||||
function fetchWeatherData(lat, lon) {
|
||||
var requestBody = {
|
||||
"lat": parseFloat(lat.toFixed(2)),
|
||||
@ -2412,7 +2443,7 @@
|
||||
|
||||
if (weatherData['temp-surface'] && weatherData['temp-surface'][i] !== null) {
|
||||
var temp = (weatherData['temp-surface'][i] - 273.15).toFixed(1); // 转换为摄氏度
|
||||
forecastHtml += createWeatherParam('🌡️', '温度', temp + '°C');
|
||||
forecastHtml += createWeatherParam('温度', temp + '°C');
|
||||
}
|
||||
|
||||
if (weatherData['wind_u-surface'] && weatherData['wind_v-surface'] &&
|
||||
@ -2421,30 +2452,30 @@
|
||||
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);
|
||||
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');
|
||||
forecastHtml += createWeatherParam('降水', precip + ' mm');
|
||||
}
|
||||
|
||||
if (weatherData['rh-surface'] && weatherData['rh-surface'][i] !== null) {
|
||||
var humidity = weatherData['rh-surface'][i].toFixed(0);
|
||||
forecastHtml += createWeatherParam('💧', '湿度', humidity + '%');
|
||||
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');
|
||||
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 += createWeatherParam('阵风', gust + ' m/s');
|
||||
}
|
||||
|
||||
forecastHtml += '</div></div>';
|
||||
@ -2459,9 +2490,8 @@
|
||||
'</div>';
|
||||
}
|
||||
|
||||
function createWeatherParam(icon, label, value) {
|
||||
function createWeatherParam(label, value) {
|
||||
return '<div class="weather-param">' +
|
||||
'<span class="weather-param-icon">' + icon + '</span>' +
|
||||
'<span class="weather-param-label">' + label + '</span>' +
|
||||
'<span class="weather-param-value">' + value + '</span>' +
|
||||
'</div>';
|
||||
@ -2484,6 +2514,179 @@
|
||||
var index = Math.round(angle / 45) % 8;
|
||||
return directions[index];
|
||||
}
|
||||
|
||||
function initWeatherCardDrag() {
|
||||
var weatherCard = document.getElementById('weatherForecastCard');
|
||||
if (!weatherCard) return;
|
||||
|
||||
var isDragging = false;
|
||||
var startX, startY;
|
||||
var startLeft, startTop;
|
||||
|
||||
var originalStyles = {
|
||||
top: '55%',
|
||||
right: '20px',
|
||||
left: 'auto',
|
||||
transform: 'translateY(-50%)'
|
||||
};
|
||||
|
||||
var cardHeader = weatherCard.querySelector('.weather-card-header');
|
||||
cardHeader.addEventListener('dblclick', function() {
|
||||
// 重置
|
||||
weatherCard.style.top = originalStyles.top;
|
||||
weatherCard.style.right = originalStyles.right;
|
||||
weatherCard.style.left = originalStyles.left;
|
||||
weatherCard.style.transform = originalStyles.transform;
|
||||
});
|
||||
|
||||
var cardHeader = weatherCard.querySelector('.weather-card-header');
|
||||
cardHeader.addEventListener('mousedown', function(e) {
|
||||
if (e.target.tagName === 'BUTTON' ||
|
||||
e.target.classList.contains('weather-nav-btn') ||
|
||||
e.target.classList.contains('weather-close-btn')) {
|
||||
return;
|
||||
}
|
||||
|
||||
e.preventDefault();
|
||||
|
||||
startX = e.clientX;
|
||||
startY = e.clientY;
|
||||
|
||||
var rect = weatherCard.getBoundingClientRect();
|
||||
startLeft = rect.left;
|
||||
startTop = rect.top;
|
||||
|
||||
// 准备拖动
|
||||
isDragging = true;
|
||||
|
||||
// 设置为绝对定位(如果还不是)
|
||||
if (getComputedStyle(weatherCard).position !== 'absolute') {
|
||||
weatherCard.style.position = 'absolute';
|
||||
weatherCard.style.top = rect.top + 'px';
|
||||
weatherCard.style.left = rect.left + 'px';
|
||||
weatherCard.style.right = 'auto';
|
||||
weatherCard.style.transform = 'none';
|
||||
}
|
||||
|
||||
weatherCard.style.opacity = '0.9';
|
||||
weatherCard.style.boxShadow = '0 12px 48px rgba(0, 0, 0, 0.25)';
|
||||
weatherCard.style.zIndex = '1200';
|
||||
|
||||
document.body.style.userSelect = 'none';
|
||||
});
|
||||
|
||||
// 鼠标移动事件
|
||||
document.addEventListener('mousemove', function(e) {
|
||||
if (!isDragging) return;
|
||||
|
||||
// 计算移动距离
|
||||
var dx = e.clientX - startX;
|
||||
var dy = e.clientY - startY;
|
||||
|
||||
// 计算新位置
|
||||
var newLeft = startLeft + dx;
|
||||
var newTop = startTop + dy;
|
||||
|
||||
// 限制在视口内
|
||||
var maxX = window.innerWidth - weatherCard.offsetWidth;
|
||||
var maxY = window.innerHeight - weatherCard.offsetHeight;
|
||||
|
||||
newLeft = Math.max(0, Math.min(newLeft, maxX));
|
||||
newTop = Math.max(0, Math.min(newTop, maxY));
|
||||
|
||||
// 应用新位置
|
||||
weatherCard.style.left = newLeft + 'px';
|
||||
weatherCard.style.top = newTop + 'px';
|
||||
});
|
||||
|
||||
// 鼠标释放事件
|
||||
document.addEventListener('mouseup', function() {
|
||||
if (!isDragging) return;
|
||||
|
||||
isDragging = false;
|
||||
weatherCard.style.opacity = '1';
|
||||
weatherCard.style.boxShadow = '0 8px 32px rgba(0, 0, 0, 0.15)';
|
||||
|
||||
document.body.style.userSelect = '';
|
||||
});
|
||||
|
||||
cardHeader.addEventListener('touchstart', function(e) {
|
||||
if (e.target.tagName === 'BUTTON' ||
|
||||
e.target.classList.contains('weather-nav-btn') ||
|
||||
e.target.classList.contains('weather-close-btn')) {
|
||||
return;
|
||||
}
|
||||
|
||||
e.preventDefault();
|
||||
|
||||
var touch = e.touches[0];
|
||||
|
||||
startX = touch.clientX;
|
||||
startY = touch.clientY;
|
||||
|
||||
// 获取当前卡片位置
|
||||
var rect = weatherCard.getBoundingClientRect();
|
||||
startLeft = rect.left;
|
||||
startTop = rect.top;
|
||||
|
||||
// 准备拖动
|
||||
isDragging = true;
|
||||
|
||||
// 设置为绝对定位(如果还不是)
|
||||
if (getComputedStyle(weatherCard).position !== 'absolute') {
|
||||
weatherCard.style.position = 'absolute';
|
||||
weatherCard.style.top = rect.top + 'px';
|
||||
weatherCard.style.left = rect.left + 'px';
|
||||
weatherCard.style.right = 'auto';
|
||||
weatherCard.style.transform = 'none';
|
||||
}
|
||||
|
||||
// 添加活动样式
|
||||
weatherCard.style.opacity = '0.9';
|
||||
weatherCard.style.boxShadow = '0 12px 48px rgba(0, 0, 0, 0.25)';
|
||||
|
||||
// 在拖动过程中临时禁用文本选择
|
||||
document.body.style.userSelect = 'none';
|
||||
});
|
||||
|
||||
document.addEventListener('touchmove', function(e) {
|
||||
if (!isDragging) return;
|
||||
|
||||
e.preventDefault(); // 防止页面滚动
|
||||
|
||||
var touch = e.touches[0];
|
||||
|
||||
// 计算移动距离
|
||||
var dx = touch.clientX - startX;
|
||||
var dy = touch.clientY - startY;
|
||||
|
||||
// 计算新位置
|
||||
var newLeft = startLeft + dx;
|
||||
var newTop = startTop + dy;
|
||||
|
||||
// 限制在视口内
|
||||
var maxX = window.innerWidth - weatherCard.offsetWidth;
|
||||
var maxY = window.innerHeight - weatherCard.offsetHeight;
|
||||
|
||||
newLeft = Math.max(0, Math.min(newLeft, maxX));
|
||||
newTop = Math.max(0, Math.min(newTop, maxY));
|
||||
|
||||
// 应用新位置
|
||||
weatherCard.style.left = newLeft + 'px';
|
||||
weatherCard.style.top = newTop + 'px';
|
||||
});
|
||||
|
||||
document.addEventListener('touchend', function() {
|
||||
if (!isDragging) return;
|
||||
|
||||
isDragging = false;
|
||||
weatherCard.style.opacity = '1';
|
||||
weatherCard.style.boxShadow = '0 8px 32px rgba(0, 0, 0, 0.15)';
|
||||
|
||||
// 恢复文本选择功能
|
||||
document.body.style.userSelect = '';
|
||||
});
|
||||
}
|
||||
</script>
|
||||
|
||||
</body>
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user