|
|
<!DOCTYPE html>
|
|
|
<html lang="zh-CN">
|
|
|
|
|
|
<head>
|
|
|
<meta charset="UTF-8">
|
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
|
<title>海洋科考船态势感知系统</title>
|
|
|
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.7.1/dist/leaflet.css" />
|
|
|
<script src="https://unpkg.com/leaflet@1.7.1/dist/leaflet.js"></script>
|
|
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/3.9.1/chart.min.js"></script>
|
|
|
<style>
|
|
|
* {
|
|
|
margin: 0;
|
|
|
padding: 0;
|
|
|
box-sizing: border-box;
|
|
|
font-family: 'Segoe UI', Arial, sans-serif;
|
|
|
}
|
|
|
|
|
|
body {
|
|
|
background: url('/assets/img/bg.png') no-repeat;
|
|
|
background-size: 100% 100%;
|
|
|
color: #e0f0ff;
|
|
|
overflow: hidden;
|
|
|
height: 100vh;
|
|
|
}
|
|
|
|
|
|
/* 新增顶部标题栏样式 */
|
|
|
.topDiv {
|
|
|
width: 100%;
|
|
|
height: 8vh;
|
|
|
background: url('/assets/img/topBg.png') top no-repeat;
|
|
|
background-size: 100% 115%;
|
|
|
display: flex;
|
|
|
justify-content: center;
|
|
|
z-index: 990;
|
|
|
position: relative;
|
|
|
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3);
|
|
|
}
|
|
|
|
|
|
.topDiv .center {
|
|
|
font-family: PangMenZhengDao, 'Source Han Sans CN';
|
|
|
font-weight: 400;
|
|
|
font-size: 4.1vh;
|
|
|
color: #ffffff;
|
|
|
align-self: center;
|
|
|
margin-top: -40px;
|
|
|
}
|
|
|
|
|
|
.topDiv .left {
|
|
|
position: absolute;
|
|
|
top: 4vh;
|
|
|
left: 3vw;
|
|
|
color: #ffffff;
|
|
|
}
|
|
|
|
|
|
.topDiv .left span:nth-child(1) {
|
|
|
font-weight: bold;
|
|
|
font-size: 0.8vw;
|
|
|
margin-right: 0.5vh;
|
|
|
}
|
|
|
|
|
|
.topDiv .left span:nth-child(2) {
|
|
|
font-weight: bold;
|
|
|
font-size: 1.2vw;
|
|
|
}
|
|
|
|
|
|
.topDiv .right {
|
|
|
position: absolute;
|
|
|
top: 3vh;
|
|
|
right: 0;
|
|
|
color: #ffffff;
|
|
|
display: flex;
|
|
|
align-items: center;
|
|
|
}
|
|
|
|
|
|
.topDiv .right img:nth-child(1) {}
|
|
|
|
|
|
.topDiv .right span {
|
|
|
font-weight: bold;
|
|
|
font-size: 1.2vw;
|
|
|
}
|
|
|
|
|
|
.topDiv .icon-home {
|
|
|
position: absolute;
|
|
|
top: 1vh;
|
|
|
right: 8vw;
|
|
|
width: 4vh;
|
|
|
cursor: pointer;
|
|
|
}
|
|
|
|
|
|
.container {
|
|
|
display: flex;
|
|
|
flex-direction: column;
|
|
|
height: calc(100vh - 8vh - 20px);
|
|
|
padding: 10px;
|
|
|
position: relative;
|
|
|
margin-bottom: 20px;
|
|
|
}
|
|
|
|
|
|
.header {
|
|
|
display: flex;
|
|
|
justify-content: space-between;
|
|
|
align-items: center;
|
|
|
padding: 10px 20px;
|
|
|
background: rgba(12, 42, 73, 0.1);
|
|
|
backdrop-filter: blur(10px);
|
|
|
border-radius: 8px;
|
|
|
margin-bottom: 10px;
|
|
|
border: 1px solid rgba(64, 156, 255, 0.3);
|
|
|
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3);
|
|
|
}
|
|
|
|
|
|
.header h1 {
|
|
|
color: #4fc3f7;
|
|
|
font-size: 24px;
|
|
|
text-shadow: 0 0 10px rgba(79, 195, 247, 0.5);
|
|
|
}
|
|
|
|
|
|
.status-bar {
|
|
|
display: flex;
|
|
|
gap: 20px;
|
|
|
}
|
|
|
|
|
|
.status-item {
|
|
|
display: flex;
|
|
|
align-items: center;
|
|
|
gap: 5px;
|
|
|
}
|
|
|
|
|
|
.status-indicator {
|
|
|
width: 10px;
|
|
|
height: 10px;
|
|
|
border-radius: 50%;
|
|
|
}
|
|
|
|
|
|
.online {
|
|
|
background-color: #4caf50;
|
|
|
box-shadow: 0 0 8px #4caf50;
|
|
|
}
|
|
|
|
|
|
.warning {
|
|
|
background-color: #ff9800;
|
|
|
box-shadow: 0 0 8px #ff9800;
|
|
|
}
|
|
|
|
|
|
.error {
|
|
|
background-color: #f44336;
|
|
|
box-shadow: 0 0 8px #f44336;
|
|
|
}
|
|
|
|
|
|
.main-content {
|
|
|
/* display: flex;
|
|
|
flex: 1;
|
|
|
gap: 10px; */
|
|
|
display: flex;
|
|
|
flex: 1;
|
|
|
gap: 10px;
|
|
|
overflow: hidden;
|
|
|
}
|
|
|
|
|
|
.left-panel,
|
|
|
.right-panel {
|
|
|
width: 300px;
|
|
|
display: flex;
|
|
|
flex-direction: column;
|
|
|
gap: 10px;
|
|
|
}
|
|
|
|
|
|
.center-panel {
|
|
|
flex: 1;
|
|
|
display: flex;
|
|
|
flex-direction: column;
|
|
|
gap: 10px;
|
|
|
}
|
|
|
|
|
|
.map-container {
|
|
|
flex: 1;
|
|
|
border-radius: 8px;
|
|
|
overflow: hidden;
|
|
|
border: 1px solid rgba(64, 156, 255, 0.3);
|
|
|
position: relative;
|
|
|
background: linear-gradient(135deg, #0a3d62, #1a5276);
|
|
|
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3);
|
|
|
min-height: 300px;
|
|
|
/* 设置最小高度 */
|
|
|
}
|
|
|
|
|
|
#map {
|
|
|
height: 100%;
|
|
|
width: 100%;
|
|
|
background: transparent;
|
|
|
z-index: 1;
|
|
|
}
|
|
|
|
|
|
.map-overlay {
|
|
|
position: absolute;
|
|
|
top: 0;
|
|
|
left: 0;
|
|
|
width: 100%;
|
|
|
height: 100%;
|
|
|
background: rgba(10, 61, 98, 0.6);
|
|
|
z-index: 0;
|
|
|
}
|
|
|
|
|
|
.panel {
|
|
|
background: rgba(12, 42, 73, 0.1);
|
|
|
backdrop-filter: blur(10px);
|
|
|
border-radius: 8px;
|
|
|
padding: 20px;
|
|
|
border: 1px solid rgba(64, 156, 255, 0.3);
|
|
|
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3);
|
|
|
}
|
|
|
|
|
|
/* 卡片头部样式 */
|
|
|
.card-header {
|
|
|
height: 40px;
|
|
|
background: url('/assets/img/common/homeTitle2.png') no-repeat;
|
|
|
background-position: center;
|
|
|
background-size: 108% 120%;
|
|
|
display: flex;
|
|
|
justify-content: center;
|
|
|
align-items: center;
|
|
|
border-radius: 8px 8px 0 0 !important;
|
|
|
border-bottom: 1px solid var(--light-blue);
|
|
|
padding: 32px 20px;
|
|
|
position: relative;
|
|
|
/* margin: -20px -20px 20px -20px; */
|
|
|
margin: -20px -20px 0px -20px;
|
|
|
}
|
|
|
|
|
|
.card-header span {
|
|
|
font-size: 1.2rem;
|
|
|
letter-spacing: 1px;
|
|
|
font-family: 'YouSheBiaoTiHei', 'Microsoft YaHei';
|
|
|
font-weight: 400;
|
|
|
color: #ffffff;
|
|
|
}
|
|
|
|
|
|
.panel-title {
|
|
|
color: #4fc3f7;
|
|
|
margin-bottom: 15px;
|
|
|
font-size: 18px;
|
|
|
border-bottom: 1px solid rgba(79, 195, 247, 0.3);
|
|
|
padding-bottom: 8px;
|
|
|
display: flex;
|
|
|
justify-content: space-between;
|
|
|
align-items: center;
|
|
|
}
|
|
|
|
|
|
.panel-title button {
|
|
|
background: rgba(25, 55, 95, 0.6);
|
|
|
color: #e3f2fd;
|
|
|
border: 1px solid rgba(79, 195, 247, 0.5);
|
|
|
border-radius: 4px;
|
|
|
padding: 4px 8px;
|
|
|
font-size: 12px;
|
|
|
cursor: pointer;
|
|
|
transition: all 0.3s;
|
|
|
}
|
|
|
|
|
|
.panel-title button:hover {
|
|
|
background: rgba(40, 80, 130, 0.7);
|
|
|
border-color: #4fc3f7;
|
|
|
}
|
|
|
|
|
|
.data-grid {
|
|
|
display: grid;
|
|
|
grid-template-columns: 1fr 1fr;
|
|
|
gap: 10px;
|
|
|
}
|
|
|
|
|
|
.data-item {
|
|
|
display: flex;
|
|
|
flex-direction: column;
|
|
|
padding: 8px;
|
|
|
background: rgba(25, 55, 95, 0.6);
|
|
|
border-radius: 4px;
|
|
|
transition: all 0.3s;
|
|
|
}
|
|
|
|
|
|
.data-item:hover {
|
|
|
background: rgba(40, 80, 130, 0.7);
|
|
|
transform: translateY(-2px);
|
|
|
}
|
|
|
|
|
|
.data-label {
|
|
|
font-size: 12px;
|
|
|
color: #a0d2ff;
|
|
|
}
|
|
|
|
|
|
.data-value {
|
|
|
font-size: 18px;
|
|
|
font-weight: bold;
|
|
|
color: #4fc3f7;
|
|
|
/* 主色调蓝色 */
|
|
|
text-shadow: 0 0 8px rgba(79, 195, 247, 0.7);
|
|
|
}
|
|
|
|
|
|
/* 为不同类型的数值添加不同颜色 */
|
|
|
.data-item:nth-child(1) .data-value,
|
|
|
/* 风速 */
|
|
|
.data-item:nth-child(3) .data-value,
|
|
|
/* 气温 */
|
|
|
.data-item:nth-child(6) .data-value {
|
|
|
/* 能见度 */
|
|
|
color: #4fc3f7;
|
|
|
/* 蓝色 */
|
|
|
text-shadow: 0 0 8px rgba(79, 195, 247, 0.7);
|
|
|
}
|
|
|
|
|
|
.data-item:nth-child(2) .data-value,
|
|
|
/* 风向 */
|
|
|
.data-item:nth-child(4) .data-value {
|
|
|
/* 气压 */
|
|
|
color: #64ffda;
|
|
|
/* 青色 */
|
|
|
text-shadow: 0 0 8px rgba(100, 255, 218, 0.7);
|
|
|
}
|
|
|
|
|
|
.data-item:nth-child(5) .data-value {
|
|
|
/* 湿度 */
|
|
|
color: #ff9800;
|
|
|
/* 橙色 */
|
|
|
text-shadow: 0 0 8px rgba(255, 152, 0, 0.7);
|
|
|
}
|
|
|
|
|
|
/* 水文要素颜色 */
|
|
|
.panel:nth-child(2) .data-item:nth-child(1) .data-value {
|
|
|
/* 水温 */
|
|
|
color: #29b6f6;
|
|
|
/* 浅蓝色 */
|
|
|
text-shadow: 0 0 8px rgba(41, 182, 246, 0.7);
|
|
|
}
|
|
|
|
|
|
.panel:nth-child(2) .data-item:nth-child(2) .data-value {
|
|
|
/* 盐度 */
|
|
|
color: #ab47bc;
|
|
|
/* 紫色 */
|
|
|
text-shadow: 0 0 8px rgba(171, 71, 188, 0.7);
|
|
|
}
|
|
|
|
|
|
.panel:nth-child(2) .data-item:nth-child(3) .data-value {
|
|
|
/* 水深 */
|
|
|
color: #5c6bc0;
|
|
|
/* 靛蓝色 */
|
|
|
text-shadow: 0 0 8px rgba(92, 107, 192, 0.7);
|
|
|
}
|
|
|
|
|
|
.panel:nth-child(2) .data-item:nth-child(4) .data-value {
|
|
|
/* 流速 */
|
|
|
color: #26c6da;
|
|
|
/* 青色 */
|
|
|
text-shadow: 0 0 8px rgba(38, 198, 218, 0.7);
|
|
|
}
|
|
|
|
|
|
.panel:nth-child(2) .data-item:nth-child(5) .data-value {
|
|
|
/* 流向 */
|
|
|
color: #66bb6a;
|
|
|
/* 绿色 */
|
|
|
text-shadow: 0 0 8px rgba(102, 187, 106, 0.7);
|
|
|
}
|
|
|
|
|
|
.panel:nth-child(2) .data-item:nth-child(6) .data-value {
|
|
|
/* 浊度 */
|
|
|
color: #ffee58;
|
|
|
/* 黄色 */
|
|
|
text-shadow: 0 0 8px rgba(255, 238, 88, 0.7);
|
|
|
}
|
|
|
|
|
|
/* 船舶状态颜色 */
|
|
|
.right-panel .data-item:nth-child(1) .data-value {
|
|
|
/* 航速 */
|
|
|
color: #ef5350;
|
|
|
/* 红色 */
|
|
|
text-shadow: 0 0 8px rgba(239, 83, 80, 0.7);
|
|
|
}
|
|
|
|
|
|
.right-panel .data-item:nth-child(2) .data-value {
|
|
|
/* 航向 */
|
|
|
color: #ec407a;
|
|
|
/* 粉色 */
|
|
|
text-shadow: 0 0 8px rgba(236, 64, 122, 0.7);
|
|
|
}
|
|
|
|
|
|
.right-panel .data-item:nth-child(3) .data-value {
|
|
|
/* 主机转速 */
|
|
|
color: #ab47bc;
|
|
|
/* 紫色 */
|
|
|
text-shadow: 0 0 8px rgba(171, 71, 188, 0.7);
|
|
|
}
|
|
|
|
|
|
.right-panel .data-item:nth-child(4) .data-value {
|
|
|
/* 燃油存量 */
|
|
|
color: #66bb6a;
|
|
|
/* 绿色 */
|
|
|
text-shadow: 0 0 8px rgba(102, 187, 106, 0.7);
|
|
|
}
|
|
|
|
|
|
/* 叶绿素浓度 */
|
|
|
.data-value:has(+ .data-unit) {
|
|
|
color: #64dd17;
|
|
|
/* 亮绿色 */
|
|
|
text-shadow: 0 0 8px rgba(100, 221, 23, 0.7);
|
|
|
}
|
|
|
|
|
|
/* 仪表数值颜色 */
|
|
|
.gauge-value {
|
|
|
font-weight: bold;
|
|
|
color: #4fc3f7;
|
|
|
text-shadow: 0 0 8px rgba(79, 195, 247, 0.7);
|
|
|
}
|
|
|
|
|
|
/* 态势图数值颜色 */
|
|
|
.wind-detail-value,
|
|
|
.wind-speed-detail-value,
|
|
|
.wave-detail-value,
|
|
|
.wave-direction-detail-value {
|
|
|
color: #4fc3f7;
|
|
|
text-shadow: 0 0 8px rgba(79, 195, 247, 0.7);
|
|
|
font-weight: bold;
|
|
|
font-size: 12px;
|
|
|
}
|
|
|
|
|
|
/* 模态框数据项颜色 */
|
|
|
.modal-data-value {
|
|
|
color: #4fc3f7;
|
|
|
text-shadow: 0 0 8px rgba(79, 195, 247, 0.7);
|
|
|
font-weight: bold;
|
|
|
}
|
|
|
|
|
|
/* 系统数据面板颜色 */
|
|
|
.system-data-value {
|
|
|
color: #4fc3f7;
|
|
|
text-shadow: 0 0 8px rgba(79, 195, 247, 0.7);
|
|
|
font-weight: bold;
|
|
|
}
|
|
|
|
|
|
.data-unit {
|
|
|
font-size: 12px;
|
|
|
color: #a0d2ff;
|
|
|
margin-left: 2px;
|
|
|
}
|
|
|
|
|
|
.gauge-container {
|
|
|
display: flex;
|
|
|
justify-content: space-around;
|
|
|
margin: 10px 0;
|
|
|
}
|
|
|
|
|
|
.gauge {
|
|
|
width: 80px;
|
|
|
height: 80px;
|
|
|
position: relative;
|
|
|
}
|
|
|
|
|
|
.gauge-bg {
|
|
|
width: 100%;
|
|
|
height: 100%;
|
|
|
border-radius: 50%;
|
|
|
background: #0d1b2a;
|
|
|
position: relative;
|
|
|
overflow: hidden;
|
|
|
border: 2px solid rgba(79, 195, 247, 0.5);
|
|
|
}
|
|
|
|
|
|
.gauge-fill {
|
|
|
position: absolute;
|
|
|
bottom: 0;
|
|
|
width: 100%;
|
|
|
background: linear-gradient(to top, #4fc3f7, #0277bd);
|
|
|
border-radius: 0 0 100px 100px;
|
|
|
transform-origin: bottom;
|
|
|
transition: height 0.5s ease;
|
|
|
}
|
|
|
|
|
|
.gauge-value {
|
|
|
position: absolute;
|
|
|
top: 50%;
|
|
|
left: 50%;
|
|
|
transform: translate(-50%, -50%);
|
|
|
font-weight: bold;
|
|
|
color: #e3f2fd;
|
|
|
}
|
|
|
|
|
|
.table-container {
|
|
|
max-height: 300px;
|
|
|
overflow-y: auto;
|
|
|
}
|
|
|
|
|
|
table {
|
|
|
width: 100%;
|
|
|
border-collapse: collapse;
|
|
|
}
|
|
|
|
|
|
th,
|
|
|
td {
|
|
|
padding: 8px 12px;
|
|
|
text-align: left;
|
|
|
border-bottom: 1px solid rgba(64, 156, 255, 0.3);
|
|
|
}
|
|
|
|
|
|
th {
|
|
|
color: #4fc3f7;
|
|
|
font-weight: normal;
|
|
|
}
|
|
|
|
|
|
.footer {
|
|
|
display: flex;
|
|
|
justify-content: space-between;
|
|
|
padding: 10px 20px;
|
|
|
background: rgba(12, 42, 73, 0.1);
|
|
|
backdrop-filter: blur(10px);
|
|
|
border-radius: 8px;
|
|
|
margin-top: 10px;
|
|
|
border: 1px solid rgba(64, 156, 255, 0.3);
|
|
|
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3);
|
|
|
flex-shrink: 0;
|
|
|
/* 防止被压缩 */
|
|
|
}
|
|
|
|
|
|
/* 时间轴样式修改 */
|
|
|
.timeline {
|
|
|
flex: 1;
|
|
|
height: 60px;
|
|
|
background: rgba(12, 42, 73, 0.3);
|
|
|
border-radius: 30px;
|
|
|
position: relative;
|
|
|
margin-right: 20px;
|
|
|
border: 1px solid rgba(64, 156, 255, 0.3);
|
|
|
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3);
|
|
|
overflow: visible;
|
|
|
/* 修改为visible以显示完整的标签 */
|
|
|
}
|
|
|
|
|
|
/* 已经过的时间轴部分 - 渐变色 */
|
|
|
.timeline-progress {
|
|
|
position: absolute;
|
|
|
top: 0;
|
|
|
left: 0;
|
|
|
height: 100%;
|
|
|
width: 75%;
|
|
|
/* 默认位置,会通过JS动态更新 */
|
|
|
background: linear-gradient(90deg, #0277bd, #4fc3f7);
|
|
|
border-radius: 30px 0 0 30px;
|
|
|
z-index: 1;
|
|
|
}
|
|
|
|
|
|
/* 时间轴轨道 */
|
|
|
.timeline-track {
|
|
|
position: absolute;
|
|
|
top: 50%;
|
|
|
left: 0;
|
|
|
width: 100%;
|
|
|
height: 6px;
|
|
|
background: rgba(25, 55, 95, 0.8);
|
|
|
border-radius: 3px;
|
|
|
transform: translateY(-50%);
|
|
|
z-index: 2;
|
|
|
}
|
|
|
|
|
|
/* 时间轴拖动按钮 */
|
|
|
.timeline-handle {
|
|
|
position: absolute;
|
|
|
top: 50%;
|
|
|
left: 75%;
|
|
|
width: 30px;
|
|
|
height: 30px;
|
|
|
transform: translate(-50%, -50%);
|
|
|
cursor: pointer;
|
|
|
z-index: 4;
|
|
|
transition: all 0.2s ease;
|
|
|
user-select: none;
|
|
|
background: url('img/进度指示.png') no-repeat center center;
|
|
|
background-size: contain;
|
|
|
}
|
|
|
|
|
|
.timeline-handle:hover {
|
|
|
transform: translate(-50%, -50%) scale(1.1);
|
|
|
}
|
|
|
|
|
|
.timeline-handle:active {
|
|
|
transform: translate(-50%, -50%) scale(1.2);
|
|
|
}
|
|
|
|
|
|
/* 时间标记 */
|
|
|
.time-marker {
|
|
|
position: absolute;
|
|
|
top: 0;
|
|
|
width: 2px;
|
|
|
height: 100%;
|
|
|
background: rgba(79, 195, 247, 0.6);
|
|
|
z-index: 3;
|
|
|
}
|
|
|
|
|
|
.time-marker::before {
|
|
|
content: '';
|
|
|
position: absolute;
|
|
|
top: 50%;
|
|
|
left: 50%;
|
|
|
transform: translate(-50%, -50%);
|
|
|
width: 10px;
|
|
|
height: 10px;
|
|
|
background: #4fc3f7;
|
|
|
border-radius: 50%;
|
|
|
box-shadow: 0 0 8px rgba(79, 195, 247, 0.8);
|
|
|
}
|
|
|
|
|
|
.time-label {
|
|
|
position: absolute;
|
|
|
top: -25px;
|
|
|
/* 修改位置以确保完全显示 */
|
|
|
transform: translateX(-50%);
|
|
|
font-size: 12px;
|
|
|
color: #a0d2ff;
|
|
|
font-weight: bold;
|
|
|
text-shadow: 0 0 5px rgba(0, 0, 0, 0.7);
|
|
|
white-space: nowrap;
|
|
|
/* 防止文本换行 */
|
|
|
}
|
|
|
|
|
|
/* 船舶图标 */
|
|
|
/* .ship-icon {
|
|
|
width: 30px;
|
|
|
height: 15px;
|
|
|
background: #4fc3f7;
|
|
|
border-radius: 30% 30% 10% 10%;
|
|
|
position: absolute;
|
|
|
top: 50%;
|
|
|
left: 75%;
|
|
|
|
|
|
transform: translate(-50%, -50%);
|
|
|
transform-origin: center;
|
|
|
box-shadow: 0 0 15px rgba(79, 195, 247, 0.9);
|
|
|
z-index: 5;
|
|
|
transition: left 0.3s ease;
|
|
|
user-select: none;
|
|
|
|
|
|
}
|
|
|
|
|
|
.ship-icon::after {
|
|
|
content: '';
|
|
|
position: absolute;
|
|
|
top: -8px;
|
|
|
left: 50%;
|
|
|
transform: translateX(-50%);
|
|
|
width: 0;
|
|
|
height: 0;
|
|
|
border-left: 5px solid transparent;
|
|
|
border-right: 5px solid transparent;
|
|
|
border-bottom: 8px solid #4fc3f7;
|
|
|
} */
|
|
|
|
|
|
/* 当前时间指示器 */
|
|
|
.current-time-indicator {
|
|
|
position: absolute;
|
|
|
top: 0;
|
|
|
left: 70%;
|
|
|
width: 2px;
|
|
|
height: 100%;
|
|
|
background: #ff9800;
|
|
|
box-shadow: 0 0 8px rgba(255, 152, 0, 0.8);
|
|
|
z-index: 3;
|
|
|
}
|
|
|
|
|
|
.current-time-indicator::after {
|
|
|
content: '现在';
|
|
|
position: absolute;
|
|
|
top: -25px;
|
|
|
left: 50%;
|
|
|
transform: translateX(-50%);
|
|
|
font-size: 12px;
|
|
|
color: #ff9800;
|
|
|
font-weight: bold;
|
|
|
text-shadow: 0 0 5px rgba(0, 0, 0, 0.7);
|
|
|
}
|
|
|
|
|
|
.controls {
|
|
|
display: flex;
|
|
|
gap: 10px;
|
|
|
}
|
|
|
|
|
|
button {
|
|
|
padding: 8px 15px;
|
|
|
background: rgba(25, 55, 95, 0.6);
|
|
|
color: #e3f2fd;
|
|
|
border: 1px solid rgba(79, 195, 247, 0.5);
|
|
|
border-radius: 4px;
|
|
|
cursor: pointer;
|
|
|
transition: background 0.3s;
|
|
|
}
|
|
|
|
|
|
button:hover {
|
|
|
background: rgba(40, 80, 130, 0.7);
|
|
|
border-color: #4fc3f7;
|
|
|
}
|
|
|
|
|
|
.alert {
|
|
|
color: #ff9800;
|
|
|
}
|
|
|
|
|
|
.critical {
|
|
|
color: #f44336;
|
|
|
}
|
|
|
|
|
|
.chart-container {
|
|
|
height: 200px;
|
|
|
margin-top: 10px;
|
|
|
display: none;
|
|
|
}
|
|
|
|
|
|
.chart-visible {
|
|
|
display: block;
|
|
|
}
|
|
|
|
|
|
/* 播放控制面板 */
|
|
|
.playback-controls {
|
|
|
position: absolute;
|
|
|
bottom: 20px;
|
|
|
right: 20px;
|
|
|
background: rgba(12, 42, 73, 0.9);
|
|
|
padding: 10px;
|
|
|
border-radius: 8px;
|
|
|
display: none;
|
|
|
z-index: 1000;
|
|
|
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3);
|
|
|
}
|
|
|
|
|
|
.playback-controls.active {
|
|
|
display: flex;
|
|
|
}
|
|
|
|
|
|
|
|
|
.playback-btn {
|
|
|
width: 30px;
|
|
|
height: 30px;
|
|
|
border-radius: 50%;
|
|
|
display: flex;
|
|
|
align-items: center;
|
|
|
justify-content: center;
|
|
|
background: rgba(25, 55, 95, 0.6);
|
|
|
border: 1px solid rgba(79, 195, 247, 0.5);
|
|
|
cursor: pointer;
|
|
|
}
|
|
|
|
|
|
.playback-slider {
|
|
|
flex: 1;
|
|
|
height: 6px;
|
|
|
background: #0d1b2a;
|
|
|
border-radius: 3px;
|
|
|
position: relative;
|
|
|
margin: 0 10px;
|
|
|
}
|
|
|
|
|
|
.playback-progress {
|
|
|
position: absolute;
|
|
|
height: 100%;
|
|
|
background: #4fc3f7;
|
|
|
border-radius: 3px;
|
|
|
width: 30%;
|
|
|
}
|
|
|
|
|
|
.modal {
|
|
|
display: none;
|
|
|
position: fixed;
|
|
|
top: 0;
|
|
|
left: 0;
|
|
|
width: 100%;
|
|
|
height: 100%;
|
|
|
background: rgba(0, 0, 0, 0.7);
|
|
|
z-index: 1000;
|
|
|
align-items: center;
|
|
|
justify-content: center;
|
|
|
}
|
|
|
|
|
|
.modal-content1 {
|
|
|
background: rgba(12, 42, 73, 0.95);
|
|
|
border-radius: 8px;
|
|
|
padding: 20px;
|
|
|
width: 90%;
|
|
|
max-width: 1200px;
|
|
|
border: 1px solid rgba(64, 156, 255, 0.3);
|
|
|
box-shadow: 0 10px 30px rgba(0, 0, 0, 0.5);
|
|
|
max-height: 90vh;
|
|
|
overflow-y: auto;
|
|
|
}
|
|
|
|
|
|
.modal-content {
|
|
|
background: rgba(12, 42, 73, 0.95);
|
|
|
border-radius: 8px;
|
|
|
padding: 20px;
|
|
|
width: 40%;
|
|
|
max-width: 1200px;
|
|
|
border: 1px solid rgba(64, 156, 255, 0.3);
|
|
|
box-shadow: 0 10px 30px rgba(0, 0, 0, 0.5);
|
|
|
max-height: 90vh;
|
|
|
overflow-y: auto;
|
|
|
}
|
|
|
|
|
|
.modal-header {
|
|
|
display: flex;
|
|
|
justify-content: space-between;
|
|
|
align-items: center;
|
|
|
margin-bottom: 20px;
|
|
|
border-bottom: 1px solid rgba(79, 195, 247, 0.3);
|
|
|
padding-bottom: 10px;
|
|
|
}
|
|
|
|
|
|
.modal-title {
|
|
|
color: #4fc3f7;
|
|
|
font-size: 20px;
|
|
|
}
|
|
|
|
|
|
.close-btn {
|
|
|
background: none;
|
|
|
border: none;
|
|
|
color: #e3f2fd;
|
|
|
font-size: 24px;
|
|
|
cursor: pointer;
|
|
|
}
|
|
|
|
|
|
.modal-chart-container {
|
|
|
height: 500px;
|
|
|
margin-bottom: 20px;
|
|
|
}
|
|
|
|
|
|
.data-export-options {
|
|
|
display: flex;
|
|
|
gap: 10px;
|
|
|
margin-top: 15px;
|
|
|
}
|
|
|
|
|
|
.data-export-options select {
|
|
|
background: rgba(25, 55, 95, 0.6);
|
|
|
color: #e3f2fd;
|
|
|
border: 1px solid rgba(79, 195, 247, 0.5);
|
|
|
border-radius: 4px;
|
|
|
padding: 8px;
|
|
|
flex: 1;
|
|
|
}
|
|
|
|
|
|
.coordinates-info {
|
|
|
position: absolute;
|
|
|
top: 20px;
|
|
|
right: 20px;
|
|
|
background: rgba(12, 42, 73, 0.9);
|
|
|
padding: 10px 15px;
|
|
|
border-radius: 8px;
|
|
|
border: 1px solid rgba(64, 156, 255, 0.3);
|
|
|
font-size: 14px;
|
|
|
display: none;
|
|
|
z-index: 1000;
|
|
|
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3);
|
|
|
display: none;
|
|
|
}
|
|
|
|
|
|
.coordinates-info.active {
|
|
|
display: block;
|
|
|
}
|
|
|
|
|
|
.coordinates-title {
|
|
|
color: #4fc3f7;
|
|
|
margin-bottom: 5px;
|
|
|
font-weight: bold;
|
|
|
}
|
|
|
|
|
|
.coordinates-value {
|
|
|
color: #e3f2fd;
|
|
|
}
|
|
|
|
|
|
.system-buttons {
|
|
|
display: flex;
|
|
|
flex-wrap: wrap;
|
|
|
gap: 10px;
|
|
|
margin-top: 10px;
|
|
|
}
|
|
|
|
|
|
.system-btn {
|
|
|
padding: 8px 12px;
|
|
|
background: rgba(25, 55, 95, 0.6);
|
|
|
border: 1px solid rgba(79, 195, 247, 0.5);
|
|
|
border-radius: 4px;
|
|
|
color: #e3f2fd;
|
|
|
cursor: pointer;
|
|
|
transition: all 0.3s;
|
|
|
flex: 1;
|
|
|
min-width: 120px;
|
|
|
text-align: center;
|
|
|
}
|
|
|
|
|
|
.system-btn:hover {
|
|
|
background: rgba(40, 80, 130, 0.7);
|
|
|
border-color: #4fc3f7;
|
|
|
transform: translateY(-2px);
|
|
|
}
|
|
|
|
|
|
.system-data-panel {
|
|
|
margin-top: 15px;
|
|
|
padding: 10px;
|
|
|
background: rgba(25, 55, 95, 0.3);
|
|
|
border-radius: 4px;
|
|
|
display: none;
|
|
|
}
|
|
|
|
|
|
.system-data-panel.active {
|
|
|
display: block;
|
|
|
}
|
|
|
|
|
|
.system-data-item {
|
|
|
display: flex;
|
|
|
justify-content: space-between;
|
|
|
margin-bottom: 8px;
|
|
|
padding-bottom: 8px;
|
|
|
border-bottom: 1px solid rgba(25, 55, 95, 0.5);
|
|
|
}
|
|
|
|
|
|
.system-data-label {
|
|
|
color: #a0d2ff;
|
|
|
}
|
|
|
|
|
|
.system-data-value {
|
|
|
color: #e3f2fd;
|
|
|
font-weight: bold;
|
|
|
}
|
|
|
|
|
|
.map-controls {
|
|
|
position: absolute;
|
|
|
bottom: 20px;
|
|
|
left: 20px;
|
|
|
display: flex;
|
|
|
flex-direction: column;
|
|
|
gap: 10px;
|
|
|
z-index: 1000;
|
|
|
}
|
|
|
|
|
|
.map-btn {
|
|
|
padding: 8px 12px;
|
|
|
background: rgba(12, 42, 73, 0.8);
|
|
|
border: 1px solid rgba(64, 156, 255, 0.3);
|
|
|
border-radius: 4px;
|
|
|
color: #e3f2fd;
|
|
|
cursor: pointer;
|
|
|
transition: all 0.3s;
|
|
|
}
|
|
|
|
|
|
.map-btn:hover {
|
|
|
background: rgba(12, 42, 73, 1);
|
|
|
border-color: #4fc3f7;
|
|
|
}
|
|
|
|
|
|
.situation-chart-container {
|
|
|
display: grid;
|
|
|
grid-template-columns: repeat(4, 1fr);
|
|
|
grid-template-rows: 1fr;
|
|
|
gap: 10px;
|
|
|
height: 300px;
|
|
|
/* 固定高度,避免占用过多空间 */
|
|
|
}
|
|
|
|
|
|
.situation-chart {
|
|
|
background: rgba(12, 42, 73, 0.1);
|
|
|
backdrop-filter: blur(1px);
|
|
|
border-radius: 8px;
|
|
|
padding: 10px;
|
|
|
border: 1px solid rgba(64, 156, 255, 0.3);
|
|
|
display: flex;
|
|
|
flex-direction: column;
|
|
|
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3);
|
|
|
}
|
|
|
|
|
|
.situation-title {
|
|
|
color: #4fc3f7;
|
|
|
margin-bottom: 10px;
|
|
|
font-size: 16px;
|
|
|
border-bottom: 1px solid rgba(79, 195, 247, 0.3);
|
|
|
padding-bottom: 5px;
|
|
|
text-align: center;
|
|
|
text-shadow: 0 0 10px rgba(79, 195, 247, 0.5);
|
|
|
}
|
|
|
|
|
|
.situation-chart canvas {
|
|
|
flex: 1;
|
|
|
width: 100% !important;
|
|
|
height: auto !important;
|
|
|
}
|
|
|
|
|
|
/* 风向态势图优化 */
|
|
|
.wind-direction-container {
|
|
|
display: flex;
|
|
|
flex-direction: column;
|
|
|
align-items: center;
|
|
|
height: 100%;
|
|
|
}
|
|
|
|
|
|
.wind-direction-indicator {
|
|
|
width: 180px;
|
|
|
height: 180px;
|
|
|
/* 减小高度以适应容器 */
|
|
|
position: relative;
|
|
|
border-radius: 50%;
|
|
|
background: linear-gradient(135deg, #0a3d62, #1a5276);
|
|
|
border: 3px solid rgba(79, 195, 247, 0.5);
|
|
|
box-shadow: 0 0 20px rgba(0, 0, 0, 0.5);
|
|
|
/* width: 280px;
|
|
|
height: 280px;
|
|
|
margin: 10px auto;
|
|
|
position: relative;
|
|
|
border-radius: 50%;
|
|
|
background: linear-gradient(135deg, #0a3d62, #1a5276);
|
|
|
border: 3px solid rgba(79, 195, 247, 0.5);
|
|
|
box-shadow: 0 0 20px rgba(0, 0, 0, 0.5); */
|
|
|
}
|
|
|
|
|
|
.wind-direction-compass {
|
|
|
position: absolute;
|
|
|
width: 100%;
|
|
|
height: 100%;
|
|
|
border-radius: 50%;
|
|
|
background: rgba(10, 25, 41, 0.3);
|
|
|
}
|
|
|
|
|
|
.wind-direction-arrow {
|
|
|
position: absolute;
|
|
|
top: 50%;
|
|
|
left: 50%;
|
|
|
width: 4px;
|
|
|
height: 70px;
|
|
|
background: linear-gradient(to top, #4fc3f7, #0277bd);
|
|
|
transform-origin: 50% 100%;
|
|
|
transform: translate(-50%, -100%) rotate(0deg);
|
|
|
border-radius: 2px;
|
|
|
z-index: 10;
|
|
|
box-shadow: 0 0 10px rgba(79, 195, 247, 0.7);
|
|
|
transition: transform 1s ease;
|
|
|
}
|
|
|
|
|
|
.wind-direction-arrow::after {
|
|
|
content: '';
|
|
|
position: absolute;
|
|
|
top: 0;
|
|
|
left: 50%;
|
|
|
transform: translateX(-50%);
|
|
|
width: 0;
|
|
|
height: 0;
|
|
|
border-left: 8px solid transparent;
|
|
|
border-right: 8px solid transparent;
|
|
|
border-bottom: 12px solid #4fc3f7;
|
|
|
}
|
|
|
|
|
|
.wind-direction-labels {
|
|
|
position: absolute;
|
|
|
width: 100%;
|
|
|
height: 100%;
|
|
|
top: 0;
|
|
|
left: 0;
|
|
|
}
|
|
|
|
|
|
.wind-direction-label {
|
|
|
position: absolute;
|
|
|
font-size: 10px;
|
|
|
/* 减小字体 */
|
|
|
color: #e3f2fd;
|
|
|
font-weight: bold;
|
|
|
}
|
|
|
|
|
|
/* 方向标签颜色 */
|
|
|
/* .wind-direction-label,
|
|
|
.wave-direction-label {
|
|
|
color: #e3f2fd;
|
|
|
font-weight: bold;
|
|
|
text-shadow: 0 0 5px rgba(255, 255, 255, 0.5);
|
|
|
} */
|
|
|
|
|
|
.north {
|
|
|
top: 2px;
|
|
|
left: 50%;
|
|
|
transform: translateX(-50%);
|
|
|
}
|
|
|
|
|
|
.east {
|
|
|
top: 50%;
|
|
|
right: 2px;
|
|
|
transform: translateY(-50%);
|
|
|
}
|
|
|
|
|
|
.south {
|
|
|
bottom: 2px;
|
|
|
left: 50%;
|
|
|
transform: translateX(-50%);
|
|
|
}
|
|
|
|
|
|
.west {
|
|
|
top: 50%;
|
|
|
left: 2px;
|
|
|
transform: translateY(-50%);
|
|
|
}
|
|
|
|
|
|
.wind-direction-details {
|
|
|
display: flex;
|
|
|
justify-content: space-around;
|
|
|
width: 100%;
|
|
|
margin-top: 5px;
|
|
|
gap: 5px;
|
|
|
/* display: flex;
|
|
|
justify-content: space-around;
|
|
|
width: 100%;
|
|
|
margin-top: 10px; */
|
|
|
}
|
|
|
|
|
|
/* .wind-detail-item {
|
|
|
display: flex;
|
|
|
flex-direction: column;
|
|
|
align-items: center;
|
|
|
padding: 8px;
|
|
|
background: rgba(25, 55, 95, 0.6);
|
|
|
border-radius: 8px;
|
|
|
min-width: 70px;
|
|
|
} */
|
|
|
|
|
|
/* .wind-detail-label {
|
|
|
color: #a0d2ff;
|
|
|
font-size: 12px;
|
|
|
} */
|
|
|
|
|
|
.wind-detail-value {
|
|
|
color: #4fc3f7;
|
|
|
|
|
|
text-shadow: 0 0 8px rgba(79, 195, 247, 0.7);
|
|
|
font-weight: bold;
|
|
|
/* font-size: 16px; */
|
|
|
}
|
|
|
|
|
|
/* 风速态势图 */
|
|
|
.wind-speed-container {
|
|
|
display: flex;
|
|
|
flex-direction: column;
|
|
|
align-items: center;
|
|
|
height: 100%;
|
|
|
}
|
|
|
|
|
|
.wind-speed-gauge {
|
|
|
width: 180px;
|
|
|
height: 180px;
|
|
|
/* 减小高度以适应容器 */
|
|
|
/* margin: 5px auto; */
|
|
|
position: relative;
|
|
|
background: linear-gradient(135deg, #0a3d62, #1a5276);
|
|
|
border-radius: 10px;
|
|
|
border: 3px solid rgba(79, 195, 247, 0.5);
|
|
|
overflow: hidden;
|
|
|
box-shadow: 0 0 20px rgba(0, 0, 0, 0.5);
|
|
|
/* width: 260px;
|
|
|
height: 280px;
|
|
|
margin: 10px auto;
|
|
|
position: relative;
|
|
|
background: linear-gradient(135deg, #0a3d62, #1a5276);
|
|
|
border-radius: 10px;
|
|
|
border: 3px solid rgba(79, 195, 247, 0.5);
|
|
|
overflow: hidden;
|
|
|
box-shadow: 0 0 20px rgba(0, 0, 0, 0.5); */
|
|
|
}
|
|
|
|
|
|
.wind-speed-fill {
|
|
|
position: absolute;
|
|
|
bottom: 0;
|
|
|
width: 100%;
|
|
|
background: linear-gradient(to top, #4fc3f7, #0277bd);
|
|
|
border-radius: 8px 8px 0 0;
|
|
|
transition: height 1s ease;
|
|
|
}
|
|
|
|
|
|
.wind-speed-value {
|
|
|
color: #64ffda;
|
|
|
/* 青色 */
|
|
|
text-shadow: 0 0 10px rgba(100, 255, 218, 0.8);
|
|
|
font-weight: bold;
|
|
|
font-size: 18px;
|
|
|
}
|
|
|
|
|
|
.wind-speed-value {
|
|
|
position: absolute;
|
|
|
top: 50%;
|
|
|
left: 50%;
|
|
|
transform: translate(-50%, -50%);
|
|
|
font-size: 22px;
|
|
|
font-weight: bold;
|
|
|
/* color: #e3f2fd;
|
|
|
text-shadow: 0 0 10px rgba(0, 0, 0, 0.7); */
|
|
|
z-index: 10;
|
|
|
}
|
|
|
|
|
|
.wind-speed-label {
|
|
|
color: #a0d2ff;
|
|
|
font-size: 10px;
|
|
|
font-weight: bold;
|
|
|
}
|
|
|
|
|
|
.wind-speed-label {
|
|
|
position: absolute;
|
|
|
bottom: 5px;
|
|
|
left: 0;
|
|
|
width: 100%;
|
|
|
text-align: center;
|
|
|
font-size: 10px;
|
|
|
color: #a0d2ff;
|
|
|
font-weight: bold;
|
|
|
}
|
|
|
|
|
|
.wind-speed-details {
|
|
|
display: flex;
|
|
|
justify-content: space-around;
|
|
|
width: 100%;
|
|
|
margin-top: 5px;
|
|
|
gap: 5px;
|
|
|
/* display: flex;
|
|
|
justify-content: space-around;
|
|
|
width: 100%;
|
|
|
margin-top: 10px; */
|
|
|
}
|
|
|
|
|
|
/* .wind-speed-detail-item {
|
|
|
display: flex;
|
|
|
flex-direction: column;
|
|
|
align-items: center;
|
|
|
padding: 8px;
|
|
|
background: rgba(25, 55, 95, 0.6);
|
|
|
border-radius: 8px;
|
|
|
min-width: 70px;
|
|
|
} */
|
|
|
|
|
|
/* .wind-speed-detail-label {
|
|
|
color: #a0d2ff;
|
|
|
font-size: 12px;
|
|
|
} */
|
|
|
|
|
|
.wind-speed-detail-value {
|
|
|
color: #64ffda;
|
|
|
/* 青色 */
|
|
|
text-shadow: 0 0 8px rgba(100, 255, 218, 0.7);
|
|
|
font-weight: bold;
|
|
|
/* font-size: 16px; */
|
|
|
}
|
|
|
|
|
|
/* 波高态势图优化 */
|
|
|
.wave-height-container {
|
|
|
display: flex;
|
|
|
flex-direction: column;
|
|
|
align-items: center;
|
|
|
height: 100%;
|
|
|
}
|
|
|
|
|
|
.wave-height-gauge {
|
|
|
width: 180px;
|
|
|
height: 180px;
|
|
|
/* 减小高度以适应容器 */
|
|
|
position: relative;
|
|
|
background: linear-gradient(135deg, #0a3d62, #1a5276);
|
|
|
border-radius: 10px;
|
|
|
border: 3px solid rgba(79, 195, 247, 0.5);
|
|
|
overflow: hidden;
|
|
|
box-shadow: 0 0 20px rgba(0, 0, 0, 0.5);
|
|
|
/* margin: 5px auto; */
|
|
|
/* width: 260px;
|
|
|
height: 280px;
|
|
|
margin: 10px auto;
|
|
|
position: relative;
|
|
|
background: linear-gradient(135deg, #0a3d62, #1a5276);
|
|
|
border-radius: 10px;
|
|
|
border: 3px solid rgba(79, 195, 247, 0.5);
|
|
|
overflow: hidden;
|
|
|
box-shadow: 0 0 20px rgba(0, 0, 0, 0.5); */
|
|
|
}
|
|
|
|
|
|
.wave-height-fill {
|
|
|
position: absolute;
|
|
|
bottom: 0;
|
|
|
width: 100%;
|
|
|
background: linear-gradient(to top, #4fc3f7, #0277bd);
|
|
|
border-radius: 8px 8px 0 0;
|
|
|
transition: height 1s ease;
|
|
|
}
|
|
|
|
|
|
.wave-height-value {
|
|
|
color: #29b6f6;
|
|
|
/* 浅蓝色 */
|
|
|
text-shadow: 0 0 10px rgba(41, 182, 246, 0.8);
|
|
|
font-weight: bold;
|
|
|
font-size: 18px;
|
|
|
}
|
|
|
|
|
|
.wave-height-value {
|
|
|
position: absolute;
|
|
|
top: 50%;
|
|
|
left: 50%;
|
|
|
transform: translate(-50%, -50%);
|
|
|
/* font-size: 22px; */
|
|
|
/* font-weight: bold; */
|
|
|
/* color: #e3f2fd;
|
|
|
text-shadow: 0 0 10px rgba(0, 0, 0, 0.7); */
|
|
|
z-index: 10;
|
|
|
}
|
|
|
|
|
|
.wave-height-label {
|
|
|
position: absolute;
|
|
|
bottom: 5px;
|
|
|
left: 0;
|
|
|
width: 100%;
|
|
|
text-align: center;
|
|
|
font-size: 10px;
|
|
|
color: #a0d2ff;
|
|
|
font-weight: bold;
|
|
|
}
|
|
|
|
|
|
.wave-height-details {
|
|
|
display: flex;
|
|
|
justify-content: space-around;
|
|
|
width: 100%;
|
|
|
margin-top: 5px;
|
|
|
gap: 5px;
|
|
|
/* display: flex;
|
|
|
justify-content: space-around;
|
|
|
width: 100%;
|
|
|
margin-top: 10px; */
|
|
|
}
|
|
|
|
|
|
/* .wave-detail-item {
|
|
|
display: flex;
|
|
|
flex-direction: column;
|
|
|
align-items: center;
|
|
|
padding: 8px;
|
|
|
background: rgba(25, 55, 95, 0.6);
|
|
|
border-radius: 8px;
|
|
|
min-width: 70px;
|
|
|
} */
|
|
|
|
|
|
/* .wave-detail-label {
|
|
|
font-size: 12px;
|
|
|
color: #a0d2ff;
|
|
|
} */
|
|
|
|
|
|
.wave-detail-value {
|
|
|
color: #29b6f6;
|
|
|
/* 浅蓝色 */
|
|
|
text-shadow: 0 0 8px rgba(41, 182, 246, 0.7);
|
|
|
font-weight: bold;
|
|
|
/* font-size: 16px; */
|
|
|
}
|
|
|
|
|
|
/* 波向态势图 */
|
|
|
.wave-direction-container {
|
|
|
display: flex;
|
|
|
flex-direction: column;
|
|
|
align-items: center;
|
|
|
height: 100%;
|
|
|
}
|
|
|
|
|
|
.wave-direction-indicator {
|
|
|
width: 180px;
|
|
|
height: 180px;
|
|
|
/* 减小高度以适应容器 */
|
|
|
position: relative;
|
|
|
border-radius: 50%;
|
|
|
background: linear-gradient(135deg, #0a3d62, #1a5276);
|
|
|
border: 3px solid rgba(79, 195, 247, 0.5);
|
|
|
box-shadow: 0 0 20px rgba(0, 0, 0, 0.5);
|
|
|
/* margin: 5px auto; */
|
|
|
/* width: 280px;
|
|
|
height: 280px;
|
|
|
margin: 10px auto;
|
|
|
position: relative;
|
|
|
border-radius: 50%;
|
|
|
background: linear-gradient(135deg, #0a3d62, #1a5276);
|
|
|
border: 3px solid rgba(79, 195, 247, 0.5);
|
|
|
box-shadow: 0 0 20px rgba(0, 0, 0, 0.5); */
|
|
|
}
|
|
|
|
|
|
.wave-direction-compass {
|
|
|
position: absolute;
|
|
|
width: 100%;
|
|
|
height: 100%;
|
|
|
border-radius: 50%;
|
|
|
background: rgba(10, 25, 41, 0.3);
|
|
|
}
|
|
|
|
|
|
.wave-direction-arrow {
|
|
|
position: absolute;
|
|
|
top: 50%;
|
|
|
left: 50%;
|
|
|
width: 4px;
|
|
|
height: 70px;
|
|
|
background: linear-gradient(to top, #4fc3f7, #0277bd);
|
|
|
transform-origin: 50% 100%;
|
|
|
transform: translate(-50%, -100%) rotate(0deg);
|
|
|
border-radius: 2px;
|
|
|
z-index: 10;
|
|
|
box-shadow: 0 0 10px rgba(79, 195, 247, 0.7);
|
|
|
transition: transform 1s ease;
|
|
|
}
|
|
|
|
|
|
.wave-direction-arrow::after {
|
|
|
content: '';
|
|
|
position: absolute;
|
|
|
top: 0;
|
|
|
left: 50%;
|
|
|
transform: translateX(-50%);
|
|
|
width: 0;
|
|
|
height: 0;
|
|
|
border-left: 8px solid transparent;
|
|
|
border-right: 8px solid transparent;
|
|
|
border-bottom: 12px solid #4fc3f7;
|
|
|
}
|
|
|
|
|
|
.wave-direction-labels {
|
|
|
position: absolute;
|
|
|
width: 100%;
|
|
|
height: 100%;
|
|
|
top: 0;
|
|
|
left: 0;
|
|
|
}
|
|
|
|
|
|
.wave-direction-label {
|
|
|
position: absolute;
|
|
|
font-size: 12px;
|
|
|
color: #e3f2fd;
|
|
|
font-weight: bold;
|
|
|
}
|
|
|
|
|
|
.wave-direction-details {
|
|
|
display: flex;
|
|
|
justify-content: space-around;
|
|
|
width: 100%;
|
|
|
margin-top: 5px;
|
|
|
gap: 5px;
|
|
|
/* display: flex;
|
|
|
justify-content: space-around;
|
|
|
width: 100%;
|
|
|
margin-top: 10px; */
|
|
|
}
|
|
|
|
|
|
/* .wave-direction-detail-item {
|
|
|
display: flex;
|
|
|
flex-direction: column;
|
|
|
align-items: center;
|
|
|
padding: 8px;
|
|
|
background: rgba(25, 55, 95, 0.6);
|
|
|
border-radius: 8px;
|
|
|
min-width: 70px;
|
|
|
} */
|
|
|
|
|
|
/* .wave-direction-detail-label {
|
|
|
color: #a0d2ff;
|
|
|
font-size: 12px;
|
|
|
} */
|
|
|
|
|
|
.wave-direction-detail-value {
|
|
|
color: #5c6bc0;
|
|
|
/* 靛蓝色 */
|
|
|
text-shadow: 0 0 8px rgba(92, 107, 192, 0.7);
|
|
|
font-weight: bold;
|
|
|
/* font-size: 16px; */
|
|
|
}
|
|
|
|
|
|
.wind-detail-item,
|
|
|
.wind-speed-detail-item,
|
|
|
.wave-detail-item,
|
|
|
.wave-direction-detail-item {
|
|
|
display: flex;
|
|
|
flex-direction: column;
|
|
|
align-items: center;
|
|
|
padding: 4px;
|
|
|
background: rgba(25, 55, 95, 0.6);
|
|
|
border-radius: 4px;
|
|
|
min-width: 50px;
|
|
|
}
|
|
|
|
|
|
.wind-detail-label,
|
|
|
.wind-speed-detail-label,
|
|
|
.wave-detail-label,
|
|
|
.wave-direction-detail-label {
|
|
|
font-size: 10px;
|
|
|
color: #a0d2ff;
|
|
|
margin-bottom: 2px;
|
|
|
}
|
|
|
|
|
|
/* 预警颜色 */
|
|
|
.normal {
|
|
|
background: linear-gradient(to top, #4fc3f7, #0277bd) !important;
|
|
|
}
|
|
|
|
|
|
.warning {
|
|
|
background: linear-gradient(to top, #ff9800, #f57c00) !important;
|
|
|
}
|
|
|
|
|
|
.danger {
|
|
|
background: linear-gradient(to top, #f44336, #d32f2f) !important;
|
|
|
}
|
|
|
|
|
|
/* 海洋波纹效果 */
|
|
|
.wave-pattern {
|
|
|
position: absolute;
|
|
|
bottom: 0;
|
|
|
width: 100%;
|
|
|
height: 15px;
|
|
|
background: linear-gradient(90deg, transparent, rgba(79, 195, 247, 0.3), transparent);
|
|
|
animation: wave-animation 3s infinite linear;
|
|
|
}
|
|
|
|
|
|
@keyframes wave-animation {
|
|
|
0% {
|
|
|
transform: translateX(-100%);
|
|
|
}
|
|
|
|
|
|
100% {
|
|
|
transform: translateX(100%);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
/* 图表模态框样式 */
|
|
|
.chart-modal-container {
|
|
|
display: grid;
|
|
|
grid-template-columns: 1fr 1fr;
|
|
|
gap: 20px;
|
|
|
margin-bottom: 20px;
|
|
|
}
|
|
|
|
|
|
.chart-modal-item {
|
|
|
background: rgba(12, 42, 73, 0.1);
|
|
|
backdrop-filter: blur(10px);
|
|
|
border-radius: 8px;
|
|
|
padding: 15px;
|
|
|
border: 1px solid rgba(64, 156, 255, 0.3);
|
|
|
}
|
|
|
|
|
|
.chart-modal-title {
|
|
|
color: #4fc3f7;
|
|
|
margin-bottom: 15px;
|
|
|
font-size: 18px;
|
|
|
border-bottom: 1px solid rgba(79, 195, 247, 0.3);
|
|
|
padding-bottom: 8px;
|
|
|
text-align: center;
|
|
|
}
|
|
|
|
|
|
.chart-modal-canvas {
|
|
|
height: 300px;
|
|
|
width: 100%;
|
|
|
}
|
|
|
|
|
|
.modal-data-grid {
|
|
|
display: grid;
|
|
|
grid-template-columns: repeat(3, 1fr);
|
|
|
gap: 10px;
|
|
|
margin-top: 20px;
|
|
|
}
|
|
|
|
|
|
.modal-data-item {
|
|
|
display: flex;
|
|
|
flex-direction: column;
|
|
|
padding: 10px;
|
|
|
background: rgba(25, 55, 95, 0.6);
|
|
|
border-radius: 4px;
|
|
|
text-align: center;
|
|
|
}
|
|
|
|
|
|
.modal-data-label {
|
|
|
font-size: 12px;
|
|
|
color: #a0d2ff;
|
|
|
margin-bottom: 5px;
|
|
|
}
|
|
|
|
|
|
.modal-data-value {
|
|
|
font-size: 18px;
|
|
|
font-weight: bold;
|
|
|
color: #e3f2fd;
|
|
|
}
|
|
|
|
|
|
.modal-data-unit {
|
|
|
font-size: 12px;
|
|
|
color: #a0d2ff;
|
|
|
}
|
|
|
|
|
|
/* 滚动条样式 */
|
|
|
::-webkit-scrollbar {
|
|
|
width: 4px;
|
|
|
height: 4px;
|
|
|
}
|
|
|
|
|
|
::-webkit-scrollbar-track {
|
|
|
background: rgba(12, 42, 73, 0.3);
|
|
|
border-radius: 4px;
|
|
|
}
|
|
|
|
|
|
::-webkit-scrollbar-thumb {
|
|
|
background: rgba(106, 149, 201, 0.5);
|
|
|
border-radius: 4px;
|
|
|
}
|
|
|
|
|
|
::-webkit-scrollbar-thumb:hover {
|
|
|
background: rgba(106, 149, 201, 0.7);
|
|
|
}
|
|
|
</style>
|
|
|
</head>
|
|
|
|
|
|
<body>
|
|
|
<!-- 顶部标题栏 -->
|
|
|
<div class="topDiv">
|
|
|
<div class="left">
|
|
|
<span id="current-date">2023年11月5日</span>
|
|
|
<span id="current-time">14:30:25</span>
|
|
|
</div>
|
|
|
<div class="center">海洋调查科考任务系统</div>
|
|
|
<div class="right">
|
|
|
<img src="/common/images/logo_gt.png" alt="" />
|
|
|
</div>
|
|
|
</div>
|
|
|
|
|
|
<div class="container">
|
|
|
<div class="header">
|
|
|
<h1>海洋调查科考任务系统 - 探索者号</h1>
|
|
|
<div class="status-bar">
|
|
|
<div class="status-item">
|
|
|
<div class="status-indicator online"></div>
|
|
|
<span>GPS: 在线</span>
|
|
|
</div>
|
|
|
<div class="status-item">
|
|
|
<div class="status-indicator online"></div>
|
|
|
<span>气象站: 在线</span>
|
|
|
</div>
|
|
|
<div class="status-item">
|
|
|
<div class="status-indicator warning"></div>
|
|
|
<span>声纳: 警告</span>
|
|
|
</div>
|
|
|
<div class="status-item">
|
|
|
<span>位置: 18.5°N, 115.5°E</span>
|
|
|
</div>
|
|
|
<div class="status-item">
|
|
|
<span>时间: 2025-10-18 20:47:02</span>
|
|
|
</div>
|
|
|
<div class="controls">
|
|
|
<button id="dataDownloadBtn">数据下载</button>
|
|
|
<button id="dataPlaybackBtn">数据回放</button>
|
|
|
<button id="weatherChartBtn">气象要素图表</button>
|
|
|
<button id="hydroChartBtn">水文要素图表</button>
|
|
|
</div>
|
|
|
</div>
|
|
|
</div>
|
|
|
|
|
|
<div class="main-content">
|
|
|
<div class="left-panel">
|
|
|
<div class="panel">
|
|
|
<div class="card-header">
|
|
|
<span>气象要素</span>
|
|
|
</div>
|
|
|
<div class="panel-title">
|
|
|
<span>气象要素</span>
|
|
|
<button id="showWeatherChart">显示图表</button>
|
|
|
</div>
|
|
|
<div class="data-grid">
|
|
|
<div class="data-item">
|
|
|
<span class="data-label">风速</span>
|
|
|
<div>
|
|
|
<span class="data-value">12.5</span>
|
|
|
<span class="data-unit">m/s</span>
|
|
|
</div>
|
|
|
</div>
|
|
|
<div class="data-item">
|
|
|
<span class="data-label">风向</span>
|
|
|
<div>
|
|
|
<span class="data-value">NE</span>
|
|
|
<span class="data-unit">45°</span>
|
|
|
</div>
|
|
|
</div>
|
|
|
<div class="data-item">
|
|
|
<span class="data-label">气温</span>
|
|
|
<div>
|
|
|
<span class="data-value">29.6</span>
|
|
|
<span class="data-unit">°C</span>
|
|
|
</div>
|
|
|
</div>
|
|
|
<div class="data-item">
|
|
|
<span class="data-label">气压</span>
|
|
|
<div>
|
|
|
<span class="data-value">1012.5</span>
|
|
|
<span class="data-unit">hPa</span>
|
|
|
</div>
|
|
|
</div>
|
|
|
<div class="data-item">
|
|
|
<span class="data-label">湿度</span>
|
|
|
<div>
|
|
|
<span class="data-value">78</span>
|
|
|
<span class="data-unit">%</span>
|
|
|
</div>
|
|
|
</div>
|
|
|
<div class="data-item">
|
|
|
<span class="data-label">能见度</span>
|
|
|
<div>
|
|
|
<span class="data-value">15.2</span>
|
|
|
<span class="data-unit">km</span>
|
|
|
</div>
|
|
|
</div>
|
|
|
</div>
|
|
|
<div class="chart-container" id="weatherChartContainer">
|
|
|
<canvas id="weatherChart"></canvas>
|
|
|
</div>
|
|
|
<div class="gauge-container">
|
|
|
<div class="gauge">
|
|
|
<div class="gauge-bg">
|
|
|
<div class="gauge-fill" style="height: 65%"></div>
|
|
|
</div>
|
|
|
<div class="gauge-value">65%</div>
|
|
|
<div style="text-align: center; margin-top: 5px; font-size: 12px; color: #a0d2ff;">云量</div>
|
|
|
</div>
|
|
|
<div class="gauge">
|
|
|
<div class="gauge-bg">
|
|
|
<div class="gauge-fill" style="height: 30%"></div>
|
|
|
</div>
|
|
|
<div class="gauge-value">30%</div>
|
|
|
<div style="text-align: center; margin-top: 5px; font-size: 12px; color: #a0d2ff;">降水概率
|
|
|
</div>
|
|
|
</div>
|
|
|
</div>
|
|
|
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<div class="panel">
|
|
|
<div class="card-header">
|
|
|
<span>水文要素</span>
|
|
|
</div>
|
|
|
<div class="panel-title">
|
|
|
<span>水文要素</span>
|
|
|
<button id="showHydroChart">显示图表</button>
|
|
|
</div>
|
|
|
<div class="data-grid">
|
|
|
<div class="data-item">
|
|
|
<span class="data-label">水温</span>
|
|
|
<div>
|
|
|
<span class="data-value">23.9</span>
|
|
|
<span class="data-unit">°C</span>
|
|
|
</div>
|
|
|
</div>
|
|
|
<div class="data-item">
|
|
|
<span class="data-label">盐度</span>
|
|
|
<div>
|
|
|
<span class="data-value">34.2</span>
|
|
|
<span class="data-unit">PSU</span>
|
|
|
</div>
|
|
|
</div>
|
|
|
<div class="data-item">
|
|
|
<span class="data-label">水深</span>
|
|
|
<div>
|
|
|
<span class="data-value">1250</span>
|
|
|
<span class="data-unit">m</span>
|
|
|
</div>
|
|
|
</div>
|
|
|
<div class="data-item">
|
|
|
<span class="data-label">流速</span>
|
|
|
<div>
|
|
|
<span class="data-value">1.2</span>
|
|
|
<span class="data-unit">m/s</span>
|
|
|
</div>
|
|
|
</div>
|
|
|
<div class="data-item">
|
|
|
<span class="data-label">流向</span>
|
|
|
<div>
|
|
|
<span class="data-value">SE</span>
|
|
|
<span class="data-unit">135°</span>
|
|
|
</div>
|
|
|
</div>
|
|
|
<div class="data-item">
|
|
|
<span class="data-label">浊度</span>
|
|
|
<div>
|
|
|
<span class="data-value">0.08</span>
|
|
|
<span class="data-unit">NTU</span>
|
|
|
</div>
|
|
|
</div>
|
|
|
</div>
|
|
|
<div class="chart-container" id="hydroChartContainer">
|
|
|
<canvas id="hydroChart"></canvas>
|
|
|
</div>
|
|
|
<div style="margin-top: 15px;">
|
|
|
<div style="display: flex; justify-content: space-between; margin-bottom: 5px;">
|
|
|
<span class="data-label">叶绿素浓度</span>
|
|
|
<span class="data-value">2.8 µg/L</span>
|
|
|
</div>
|
|
|
<div style="height: 10px; background: #0d1b2a; border-radius: 5px; overflow: hidden;">
|
|
|
<div
|
|
|
style="height: 100%; width: 45%; background: linear-gradient(to right, #4caf50, #8bc34a);">
|
|
|
</div>
|
|
|
</div>
|
|
|
</div>
|
|
|
|
|
|
|
|
|
</div>
|
|
|
</div>
|
|
|
|
|
|
<div class="center-panel">
|
|
|
<div class="situation-chart-container">
|
|
|
<div class="situation-chart">
|
|
|
<div class="situation-title">风向态势图</div>
|
|
|
<div class="wind-direction-container">
|
|
|
<div class="wind-direction-indicator">
|
|
|
<div class="wind-direction-compass"></div>
|
|
|
<div class="wind-direction-arrow" id="windArrow"></div>
|
|
|
<div class="wind-direction-labels">
|
|
|
<div class="wind-direction-label north">N</div>
|
|
|
<div class="wind-direction-label east">E</div>
|
|
|
<div class="wind-direction-label south">S</div>
|
|
|
<div class="wind-direction-label west">W</div>
|
|
|
</div>
|
|
|
</div>
|
|
|
<div class="wind-direction-details">
|
|
|
<div class="wind-detail-item">
|
|
|
<div class="wind-detail-label">当前风向</div>
|
|
|
<div class="wind-detail-value" id="windDirectionValue">NE 45°</div>
|
|
|
</div>
|
|
|
<div class="wind-detail-item">
|
|
|
<div class="wind-detail-label">平均风速</div>
|
|
|
<div class="wind-detail-value">12.5 m/s</div>
|
|
|
</div>
|
|
|
</div>
|
|
|
</div>
|
|
|
</div>
|
|
|
|
|
|
<div class="situation-chart">
|
|
|
<div class="situation-title">风速态势图</div>
|
|
|
<div class="wind-speed-container">
|
|
|
<div class="wind-speed-gauge">
|
|
|
<div class="wind-speed-fill" id="windSpeedFill" style="height: 60%"></div>
|
|
|
<div class="wind-speed-value" id="windSpeedValue">12.5m/s</div>
|
|
|
<div class="wind-speed-label">风速 (m/s)</div>
|
|
|
</div>
|
|
|
<div class="wind-speed-details">
|
|
|
<div class="wind-speed-detail-item">
|
|
|
<div class="wind-speed-detail-label">平均风速</div>
|
|
|
<div class="wind-speed-detail-value">12.5 m/s</div>
|
|
|
</div>
|
|
|
<div class="wind-speed-detail-item">
|
|
|
<div class="wind-speed-detail-label">阵风风速</div>
|
|
|
<div class="wind-speed-detail-value">15.2 m/s</div>
|
|
|
</div>
|
|
|
</div>
|
|
|
</div>
|
|
|
</div>
|
|
|
|
|
|
<div class="situation-chart">
|
|
|
<div class="situation-title">波高态势图</div>
|
|
|
<div class="wave-height-container">
|
|
|
<div class="wave-height-gauge">
|
|
|
<div class="wave-height-fill" id="waveHeightFill" style="height: 60%"></div>
|
|
|
<div class="wave-height-value" id="waveHeightValue">2.5m</div>
|
|
|
<div class="wave-height-label">波高 (m)</div>
|
|
|
<div class="wave-pattern"></div>
|
|
|
</div>
|
|
|
<div class="wave-height-details">
|
|
|
<div class="wave-detail-item">
|
|
|
<div class="wave-detail-label">平均波高</div>
|
|
|
<div class="wave-detail-value">2.5 m</div>
|
|
|
</div>
|
|
|
<div class="wave-detail-item">
|
|
|
<div class="wave-detail-label">最大波高</div>
|
|
|
<div class="wave-detail-value">3.8 m</div>
|
|
|
</div>
|
|
|
</div>
|
|
|
</div>
|
|
|
</div>
|
|
|
|
|
|
<div class="situation-chart">
|
|
|
<div class="situation-title">波向态势图</div>
|
|
|
<div class="wave-direction-container">
|
|
|
<div class="wave-direction-indicator">
|
|
|
<div class="wave-direction-compass"></div>
|
|
|
<div class="wave-direction-arrow" id="waveDirectionArrow"></div>
|
|
|
<div class="wave-direction-labels">
|
|
|
<div class="wave-direction-label north">N</div>
|
|
|
<div class="wave-direction-label east">E</div>
|
|
|
<div class="wave-direction-label south">S</div>
|
|
|
<div class="wave-direction-label west">W</div>
|
|
|
</div>
|
|
|
</div>
|
|
|
<div class="wave-direction-details">
|
|
|
<div class="wave-direction-detail-item">
|
|
|
<div class="wave-direction-detail-label">当前波向</div>
|
|
|
<div class="wave-direction-detail-value" id="waveDirectionValue">SE 135°</div>
|
|
|
</div>
|
|
|
<div class="wave-direction-detail-item">
|
|
|
<div class="wave-direction-detail-label">波周期</div>
|
|
|
<div class="wave-direction-detail-value">8.2 s</div>
|
|
|
</div>
|
|
|
</div>
|
|
|
</div>
|
|
|
</div>
|
|
|
</div>
|
|
|
|
|
|
<div class="map-container">
|
|
|
<div class="map-overlay"></div>
|
|
|
<div id="map"></div>
|
|
|
<div class="coordinates-info" id="coordinatesInfo">
|
|
|
<div class="coordinates-title">船舶位置信息</div>
|
|
|
<div class="coordinates-value">纬度: <span id="latValue">18.5°N</span></div>
|
|
|
<div class="coordinates-value">经度: <span id="lngValue">115.5°E</span></div>
|
|
|
</div>
|
|
|
|
|
|
<div class="map-controls">
|
|
|
<button class="map-btn" id="toggleSatellite">切换卫星图</button>
|
|
|
<button class="map-btn" id="toggleTerrain">切换地形图</button>
|
|
|
<button class="map-btn" id="resetView">重置视图</button>
|
|
|
</div>
|
|
|
|
|
|
<div class="playback-controls"
|
|
|
style="position: absolute; bottom: 20px; right: 20px; background: rgba(12, 42, 73, 0.9); padding: 10px; border-radius: 8px; display: none;"
|
|
|
id="playbackPanel">
|
|
|
<div class="playback-btn" id="playPauseBtn">▶</div>
|
|
|
<div class="playback-slider">
|
|
|
<div class="playback-progress"></div>
|
|
|
</div>
|
|
|
<span id="playbackTime">10:30:00</span>
|
|
|
<button id="closePlayback">关闭</button>
|
|
|
</div>
|
|
|
</div>
|
|
|
</div>
|
|
|
|
|
|
<div class="right-panel">
|
|
|
<div class="panel">
|
|
|
<div class="card-header">
|
|
|
<span>船舶状态</span>
|
|
|
</div>
|
|
|
<div class="panel-title">船舶状态</div>
|
|
|
<div class="data-grid">
|
|
|
<div class="data-item">
|
|
|
<span class="data-label">航速</span>
|
|
|
<div>
|
|
|
<span class="data-value">8.0</span>
|
|
|
<span class="data-unit">节</span>
|
|
|
</div>
|
|
|
</div>
|
|
|
<div class="data-item">
|
|
|
<span class="data-label">航向</span>
|
|
|
<div>
|
|
|
<span class="data-value">245</span>
|
|
|
<span class="data-unit">°</span>
|
|
|
</div>
|
|
|
</div>
|
|
|
<div class="data-item">
|
|
|
<span class="data-label">主机转速</span>
|
|
|
<div>
|
|
|
<span class="data-value">1250</span>
|
|
|
<span class="data-unit">RPM</span>
|
|
|
</div>
|
|
|
</div>
|
|
|
<div class="data-item">
|
|
|
<span class="data-label">燃油存量</span>
|
|
|
<div>
|
|
|
<span class="data-value">78</span>
|
|
|
<span class="data-unit">%</span>
|
|
|
</div>
|
|
|
</div>
|
|
|
</div>
|
|
|
|
|
|
<div style="margin-top: 15px;">
|
|
|
<div class="data-label">系统状态</div>
|
|
|
<div class="system-buttons">
|
|
|
<button class="system-btn" data-system="navigation">导航系统</button>
|
|
|
<button class="system-btn" data-system="communication">通信系统</button>
|
|
|
<button class="system-btn" data-system="sonar">声纳系统</button>
|
|
|
<button class="system-btn" data-system="sampling">采样系统</button>
|
|
|
</div>
|
|
|
</div>
|
|
|
</div>
|
|
|
|
|
|
<div class="panel">
|
|
|
<div class="card-header">
|
|
|
<span>数据记录</span>
|
|
|
</div>
|
|
|
<div class="panel-title">数据记录</div>
|
|
|
<div class="table-container">
|
|
|
<table>
|
|
|
<thead>
|
|
|
<tr>
|
|
|
<th>时间</th>
|
|
|
<th>参数</th>
|
|
|
<th>数值</th>
|
|
|
</tr>
|
|
|
</thead>
|
|
|
<tbody>
|
|
|
<tr>
|
|
|
<td>14:25:10</td>
|
|
|
<td>CTD采样</td>
|
|
|
<td>完成</td>
|
|
|
</tr>
|
|
|
<tr>
|
|
|
<td>14:20:35</td>
|
|
|
<td>浮游生物网</td>
|
|
|
<td>部署</td>
|
|
|
</tr>
|
|
|
<tr>
|
|
|
<td>14:15:42</td>
|
|
|
<td>水温异常</td>
|
|
|
<td class="alert">+1.2°C</td>
|
|
|
</tr>
|
|
|
<tr>
|
|
|
<td>14:10:18</td>
|
|
|
<td>ADCP数据</td>
|
|
|
<td>接收</td>
|
|
|
</tr>
|
|
|
<tr>
|
|
|
<td>14:05:55</td>
|
|
|
<td>气象数据</td>
|
|
|
<td>更新</td>
|
|
|
</tr>
|
|
|
<tr>
|
|
|
<td>14:00:30</td>
|
|
|
<td>GPS定位</td>
|
|
|
<td>正常</td>
|
|
|
</tr>
|
|
|
</tbody>
|
|
|
</table>
|
|
|
</div>
|
|
|
</div>
|
|
|
</div>
|
|
|
</div>
|
|
|
|
|
|
<div class="footer">
|
|
|
<div class="timeline">
|
|
|
<!-- <div class="timeline-progress"></div>
|
|
|
<div class="timeline-track"></div>
|
|
|
<div class="time-marker" style="left: 10%;">
|
|
|
<div class="time-label">14:00</div>
|
|
|
</div>
|
|
|
<div class="time-marker" style="left: 30%;">
|
|
|
<div class="time-label">14:10</div>
|
|
|
</div>
|
|
|
<div class="time-marker" style="left: 50%;">
|
|
|
<div class="time-label">14:20</div>
|
|
|
</div>
|
|
|
<div class="current-time-indicator"></div>
|
|
|
<div class="time-marker" style="left: 90%;">
|
|
|
<div class="time-label">14:40</div>
|
|
|
</div>
|
|
|
<div class="timeline-handle"></div>
|
|
|
<div class="ship-icon"></div> -->
|
|
|
</div>
|
|
|
|
|
|
<div class="controls">
|
|
|
<button>数据导出</button>
|
|
|
<button>警报设置</button>
|
|
|
<button>系统设置</button>
|
|
|
</div>
|
|
|
</div>
|
|
|
</div>
|
|
|
|
|
|
<!-- 数据下载模态框 -->
|
|
|
<div class="modal" id="downloadModal">
|
|
|
<div class="modal-content">
|
|
|
<div class="modal-header">
|
|
|
<h2 class="modal-title">数据下载</h2>
|
|
|
<button class="close-btn">×</button>
|
|
|
</div>
|
|
|
<div class="data-export-options">
|
|
|
<select>
|
|
|
<option>气象数据</option>
|
|
|
<option>水文数据</option>
|
|
|
<option>航行数据</option>
|
|
|
<option>全部数据</option>
|
|
|
</select>
|
|
|
<select>
|
|
|
<option>CSV格式</option>
|
|
|
<option>JSON格式</option>
|
|
|
<option>Excel格式</option>
|
|
|
</select>
|
|
|
<select>
|
|
|
<option>最近1小时</option>
|
|
|
<option>最近6小时</option>
|
|
|
<option>最近24小时</option>
|
|
|
<option>自定义时间段</option>
|
|
|
</select>
|
|
|
<button>下载</button>
|
|
|
</div>
|
|
|
</div>
|
|
|
</div>
|
|
|
|
|
|
<!-- 系统详情模态框 -->
|
|
|
<div class="modal" id="systemModal">
|
|
|
<div class="modal-content">
|
|
|
<div class="modal-header">
|
|
|
<h2 class="modal-title" id="systemModalTitle">系统详情</h2>
|
|
|
<button class="close-btn">×</button>
|
|
|
</div>
|
|
|
<div id="systemModalContent">
|
|
|
<!-- 内容将通过JavaScript动态填充 -->
|
|
|
</div>
|
|
|
</div>
|
|
|
</div>
|
|
|
|
|
|
<!-- 气象要素图表模态框 -->
|
|
|
<div class="modal" id="weatherChartModal">
|
|
|
<div class="modal-content1">
|
|
|
<div class="modal-header">
|
|
|
<h2 class="modal-title">气象要素详细图表</h2>
|
|
|
<button class="close-btn">×</button>
|
|
|
</div>
|
|
|
<div class="chart-modal-container">
|
|
|
<div class="chart-modal-item">
|
|
|
<div class="chart-modal-title">风速变化趋势</div>
|
|
|
<div class="chart-modal-canvas">
|
|
|
<canvas id="weatherWindChart"></canvas>
|
|
|
</div>
|
|
|
</div>
|
|
|
<div class="chart-modal-item">
|
|
|
<div class="chart-modal-title">气温变化趋势</div>
|
|
|
<div class="chart-modal-canvas">
|
|
|
<canvas id="weatherTempChart"></canvas>
|
|
|
</div>
|
|
|
</div>
|
|
|
<div class="chart-modal-item">
|
|
|
<div class="chart-modal-title">气压变化趋势</div>
|
|
|
<div class="chart-modal-canvas">
|
|
|
<canvas id="weatherPressureChart"></canvas>
|
|
|
</div>
|
|
|
</div>
|
|
|
<div class="chart-modal-item">
|
|
|
<div class="chart-modal-title">湿度变化趋势</div>
|
|
|
<div class="chart-modal-canvas">
|
|
|
<canvas id="weatherHumidityChart"></canvas>
|
|
|
</div>
|
|
|
</div>
|
|
|
</div>
|
|
|
<div class="modal-data-grid">
|
|
|
<div class="modal-data-item">
|
|
|
<div class="modal-data-label">平均风速</div>
|
|
|
<div class="modal-data-value">12.5</div>
|
|
|
<div class="modal-data-unit">m/s</div>
|
|
|
</div>
|
|
|
<div class="modal-data-item">
|
|
|
<div class="modal-data-label">最高气温</div>
|
|
|
<div class="modal-data-value">24.2</div>
|
|
|
<div class="modal-data-unit">°C</div>
|
|
|
</div>
|
|
|
<div class="modal-data-item">
|
|
|
<div class="modal-data-label">最低气温</div>
|
|
|
<div class="modal-data-value">20.5</div>
|
|
|
<div class="modal-data-unit">°C</div>
|
|
|
</div>
|
|
|
<div class="modal-data-item">
|
|
|
<div class="modal-data-label">平均气压</div>
|
|
|
<div class="modal-data-value">1012.5</div>
|
|
|
<div class="modal-data-unit">hPa</div>
|
|
|
</div>
|
|
|
<div class="modal-data-item">
|
|
|
<div class="modal-data-label">平均湿度</div>
|
|
|
<div class="modal-data-value">78</div>
|
|
|
<div class="modal-data-unit">%</div>
|
|
|
</div>
|
|
|
<div class="modal-data-item">
|
|
|
<div class="modal-data-label">能见度</div>
|
|
|
<div class="modal-data-value">15.2</div>
|
|
|
<div class="modal-data-unit">km</div>
|
|
|
</div>
|
|
|
</div>
|
|
|
</div>
|
|
|
</div>
|
|
|
|
|
|
<!-- 水文要素图表模态框 -->
|
|
|
<div class="modal" id="hydroChartModal">
|
|
|
<div class="modal-content1">
|
|
|
<div class="modal-header">
|
|
|
<h2 class="modal-title">水文要素详细图表</h2>
|
|
|
<button class="close-btn">×</button>
|
|
|
</div>
|
|
|
<div class="chart-modal-container">
|
|
|
<div class="chart-modal-item">
|
|
|
<div class="chart-modal-title">水温变化趋势</div>
|
|
|
<div class="chart-modal-canvas">
|
|
|
<canvas id="hydroTempChart"></canvas>
|
|
|
</div>
|
|
|
</div>
|
|
|
<div class="chart-modal-item">
|
|
|
<div class="chart-modal-title">盐度变化趋势</div>
|
|
|
<div class="chart-modal-canvas">
|
|
|
<canvas id="hydroSalinityChart"></canvas>
|
|
|
</div>
|
|
|
</div>
|
|
|
<div class="chart-modal-item">
|
|
|
<div class="chart-modal-title">流速变化趋势</div>
|
|
|
<div class="chart-modal-canvas">
|
|
|
<canvas id="hydroFlowChart"></canvas>
|
|
|
</div>
|
|
|
</div>
|
|
|
<div class="chart-modal-item">
|
|
|
<div class="chart-modal-title">浊度变化趋势</div>
|
|
|
<div class="chart-modal-canvas">
|
|
|
<canvas id="hydroTurbidityChart"></canvas>
|
|
|
</div>
|
|
|
</div>
|
|
|
</div>
|
|
|
<div class="modal-data-grid">
|
|
|
<div class="modal-data-item">
|
|
|
<div class="modal-data-label">平均水温</div>
|
|
|
<div class="modal-data-value">18.5</div>
|
|
|
<div class="modal-data-unit">°C</div>
|
|
|
</div>
|
|
|
<div class="modal-data-item">
|
|
|
<div class="modal-data-label">平均盐度</div>
|
|
|
<div class="modal-data-value">34.2</div>
|
|
|
<div class="modal-data-unit">PSU</div>
|
|
|
</div>
|
|
|
<div class="modal-data-item">
|
|
|
<div class="modal-data-label">平均流速</div>
|
|
|
<div class="modal-data-value">1.2</div>
|
|
|
<div class="modal-data-unit">m/s</div>
|
|
|
</div>
|
|
|
<div class="modal-data-item">
|
|
|
<div class="modal-data-label">平均浊度</div>
|
|
|
<div class="modal-data-value">4.5</div>
|
|
|
<div class="modal-data-unit">NTU</div>
|
|
|
</div>
|
|
|
<div class="modal-data-item">
|
|
|
<div class="modal-data-label">叶绿素浓度</div>
|
|
|
<div class="modal-data-value">2.8</div>
|
|
|
<div class="modal-data-unit">µg/L</div>
|
|
|
</div>
|
|
|
<div class="modal-data-item">
|
|
|
<div class="modal-data-label">水深</div>
|
|
|
<div class="modal-data-value">1250</div>
|
|
|
<div class="modal-data-unit">m</div>
|
|
|
</div>
|
|
|
</div>
|
|
|
</div>
|
|
|
</div>
|
|
|
|
|
|
<script>
|
|
|
// 在全局作用域声明变量
|
|
|
var map;
|
|
|
var shipMarker;
|
|
|
var seaMapLayer;
|
|
|
var satelliteLayer;
|
|
|
var terrainLayer;
|
|
|
|
|
|
// 确保地图正确初始化
|
|
|
document.addEventListener('DOMContentLoaded', function () {
|
|
|
// 检查地图容器是否存在
|
|
|
var mapContainer = document.getElementById('map');
|
|
|
if (mapContainer) {
|
|
|
console.log('地图容器已找到');
|
|
|
|
|
|
// 初始化地图 - 设置为南海区域
|
|
|
try {
|
|
|
map = L.map('map', {
|
|
|
minZoom: 5,
|
|
|
maxZoom: 18,
|
|
|
attributionControl: false,
|
|
|
}).setView([18.0, 115.0], 5);
|
|
|
|
|
|
// 使用OpenSeaMap海图瓦片 - 海洋区域呈现蓝色
|
|
|
seaMapLayer = L.tileLayer('https://server.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x}', {
|
|
|
attribution: '© <a href="https://www.esri.com/">Esri</a>'
|
|
|
}).addTo(map);
|
|
|
|
|
|
// 添加卫星图层
|
|
|
satelliteLayer = L.tileLayer('https://server.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x}', {
|
|
|
attribution: '© <a href="https://www.esri.com/">Esri</a>'
|
|
|
}).addTo(map);
|
|
|
|
|
|
// 添加地形图层
|
|
|
// terrainLayer = L.tileLayer('https://{s}.tile.opentopomap.org/{z}/{x}/{y}.png', {
|
|
|
// attribution: '© <a href="https://www.opentopomap.org/">OpenTopoMap</a> contributors'
|
|
|
// });
|
|
|
terrainLayer = L.tileLayer(
|
|
|
'http://t{s}.tianditu.com/DataServer?T=ter_w&x={x}&y={y}&l={z}&tk=489fa3b53cd351877dcf69e9ed899a04',
|
|
|
//'http://t{s}.tianditu.gov.cn/DataServer?T=ter_w&x={x}&y={y}&l={z}&tk=cd7516c53e2e5bee9bad989b63db6ce4',
|
|
|
{ attribution: '天地图地形', subdomains: [0, 1, 2, 3, 4, 5, 6, 7] },
|
|
|
)
|
|
|
|
|
|
// // 创建自定义船形图标
|
|
|
// var shipIcon = L.divIcon({
|
|
|
// html: '<div class="ship-icon"></div>',
|
|
|
// iconSize: [30, 15],
|
|
|
// className: 'ship-marker'
|
|
|
// });
|
|
|
|
|
|
// // 添加船舶位置标记 - 设置在南海区域
|
|
|
// shipMarker = L.marker([18.5, 115.5], { icon: shipIcon }).addTo(map);
|
|
|
// 创建自定义船形图标
|
|
|
var shipIcon = L.icon({
|
|
|
iconUrl: 'img/科考船.png',
|
|
|
// iconSize: [30, 15],
|
|
|
// iconAnchor: [15, 7.5],
|
|
|
// popupAnchor: [0, -10]
|
|
|
});
|
|
|
|
|
|
// 添加船舶位置标记 - 设置在南海区域
|
|
|
shipMarker = L.marker([18.5, 115.5], { icon: shipIcon }).addTo(map);
|
|
|
|
|
|
// 添加采样点标记
|
|
|
var samplePoints = [
|
|
|
{ lat: 18.0, lng: 114.8, type: 'CTD' },
|
|
|
{ lat: 19.0, lng: 116.2, type: 'Plankton' },
|
|
|
{ lat: 17.5, lng: 115.0, type: 'CTD' },
|
|
|
{ lat: 18.3, lng: 114.5, type: 'Plankton' },
|
|
|
{ lat: 18.7, lng: 116.0, type: 'CTD' },
|
|
|
{ lat: 19.2, lng: 115.3, type: 'Plankton' },
|
|
|
{ lat: 17.8, lng: 115.8, type: 'CTD' },
|
|
|
{ lat: 18.9, lng: 114.2, type: 'Plankton' }
|
|
|
];
|
|
|
|
|
|
samplePoints.forEach(function (point) {
|
|
|
var color = point.type === 'CTD' ? '#4caf50' : '#ff9800';
|
|
|
L.circleMarker([point.lat, point.lng], {
|
|
|
color: color,
|
|
|
fillColor: color,
|
|
|
fillOpacity: 0.7,
|
|
|
radius: 6
|
|
|
}).addTo(map).bindPopup(point.type + ' 采样点');
|
|
|
});
|
|
|
|
|
|
// 添加船舶点击事件(在 shipMarker 创建之后)
|
|
|
if (shipMarker) {
|
|
|
shipMarker.on('click', function (e) {
|
|
|
var lat = e.latlng.lat;
|
|
|
var lng = e.latlng.lng;
|
|
|
|
|
|
// 更新坐标信息显示
|
|
|
document.getElementById('latValue').textContent = lat.toFixed(4) + '°N';
|
|
|
document.getElementById('lngValue').textContent = lng.toFixed(4) + '°E';
|
|
|
|
|
|
// 显示坐标信息框
|
|
|
var coordsInfo = document.getElementById('coordinatesInfo');
|
|
|
coordsInfo.classList.add('active');
|
|
|
|
|
|
// 3秒后自动隐藏
|
|
|
setTimeout(function () {
|
|
|
coordsInfo.classList.remove('active');
|
|
|
}, 3000);
|
|
|
});
|
|
|
}
|
|
|
|
|
|
console.log('地图初始化成功');
|
|
|
} catch (error) {
|
|
|
console.error('地图初始化失败:', error);
|
|
|
}
|
|
|
} else {
|
|
|
console.error('地图容器未找到');
|
|
|
}
|
|
|
initDateTime();
|
|
|
});
|
|
|
|
|
|
// 更新船舶位置函数
|
|
|
function updateShipPosition() {
|
|
|
// 确保 shipMarker 已定义且地图已初始化
|
|
|
if (typeof shipMarker === 'undefined' || !shipMarker) {
|
|
|
console.warn('shipMarker 未定义或未初始化');
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
// 模拟船舶移动
|
|
|
var currentLat = shipMarker.getLatLng().lat;
|
|
|
var currentLng = shipMarker.getLatLng().lng;
|
|
|
|
|
|
// 在南海区域内随机移动
|
|
|
var newLat = currentLat + (Math.random() - 0.5) * 0.05;
|
|
|
var newLng = currentLng + (Math.random() - 0.5) * 0.05;
|
|
|
|
|
|
// 确保船舶在南海区域内
|
|
|
newLat = Math.min(Math.max(newLat, 10), 23);
|
|
|
newLng = Math.min(Math.max(newLng, 105), 120);
|
|
|
|
|
|
shipMarker.setLatLng([newLat, newLng]);
|
|
|
|
|
|
// 更新位置显示
|
|
|
var positionElement = document.querySelector('.status-item:nth-child(4) span:last-child');
|
|
|
if (positionElement) {
|
|
|
positionElement.textContent = newLat.toFixed(2) + '°N, ' + newLng.toFixed(2) + '°E';
|
|
|
}
|
|
|
}
|
|
|
|
|
|
// 地图控制按钮事件处理
|
|
|
document.addEventListener('DOMContentLoaded', function () {
|
|
|
// 等待DOM加载完成后添加事件监听器
|
|
|
setTimeout(function () {
|
|
|
// 切换卫星图
|
|
|
var toggleSatelliteBtn = document.getElementById('toggleSatellite');
|
|
|
if (toggleSatelliteBtn) {
|
|
|
toggleSatelliteBtn.addEventListener('click', function () {
|
|
|
if (map && seaMapLayer && satelliteLayer) {
|
|
|
if (map.hasLayer(seaMapLayer)) {
|
|
|
map.removeLayer(seaMapLayer);
|
|
|
satelliteLayer.addTo(map);
|
|
|
} else if (map.hasLayer(terrainLayer)) {
|
|
|
map.removeLayer(terrainLayer);
|
|
|
satelliteLayer.addTo(map);
|
|
|
}
|
|
|
}
|
|
|
});
|
|
|
}
|
|
|
|
|
|
// 切换地形图
|
|
|
var toggleTerrainBtn = document.getElementById('toggleTerrain');
|
|
|
if (toggleTerrainBtn) {
|
|
|
toggleTerrainBtn.addEventListener('click', function () {
|
|
|
if (map && seaMapLayer && terrainLayer) {
|
|
|
if (map.hasLayer(seaMapLayer)) {
|
|
|
map.removeLayer(seaMapLayer);
|
|
|
terrainLayer.addTo(map);
|
|
|
} else if (map.hasLayer(satelliteLayer)) {
|
|
|
map.removeLayer(satelliteLayer);
|
|
|
terrainLayer.addTo(map);
|
|
|
}
|
|
|
}
|
|
|
});
|
|
|
}
|
|
|
|
|
|
// 重置视图
|
|
|
var resetViewBtn = document.getElementById('resetView');
|
|
|
if (resetViewBtn) {
|
|
|
resetViewBtn.addEventListener('click', function () {
|
|
|
if (map && satelliteLayer && terrainLayer && seaMapLayer) {
|
|
|
if (map.hasLayer(satelliteLayer)) {
|
|
|
map.removeLayer(satelliteLayer);
|
|
|
}
|
|
|
if (map.hasLayer(terrainLayer)) {
|
|
|
map.removeLayer(terrainLayer);
|
|
|
}
|
|
|
seaMapLayer.addTo(map);
|
|
|
map.setView([18.0, 115.0], 5);
|
|
|
}
|
|
|
});
|
|
|
}
|
|
|
}, 500); // 延迟执行确保地图已初始化
|
|
|
});
|
|
|
|
|
|
// 创建气象图表
|
|
|
var weatherChart = new Chart(document.getElementById('weatherChart'), {
|
|
|
type: 'line',
|
|
|
data: {
|
|
|
labels: ['13:00', '13:15', '13:30', '13:45', '14:00', '14:15', '14:30'],
|
|
|
datasets: [{
|
|
|
label: '风速 (m/s)',
|
|
|
data: [10.2, 11.5, 12.1, 12.8, 12.5, 11.9, 12.3],
|
|
|
borderColor: '#4fc3f7',
|
|
|
backgroundColor: 'rgba(79, 195, 247, 0.1)',
|
|
|
tension: 0.4,
|
|
|
fill: true,
|
|
|
yAxisID: 'y'
|
|
|
}, {
|
|
|
label: '气压 (hPa)',
|
|
|
data: [1010.5, 1011.2, 1011.8, 1012.3, 1012.5, 1012.2, 1012.4],
|
|
|
borderColor: '#4caf50',
|
|
|
backgroundColor: 'rgba(76, 175, 80, 0.1)',
|
|
|
tension: 0.4,
|
|
|
fill: true,
|
|
|
yAxisID: 'y1'
|
|
|
}, {
|
|
|
label: '气温 (°C)',
|
|
|
data: [21.2, 21.5, 21.8, 22.1, 22.3, 22.1, 22.4],
|
|
|
borderColor: '#ff9800',
|
|
|
backgroundColor: 'rgba(255, 152, 0, 0.1)',
|
|
|
tension: 0.4,
|
|
|
fill: true,
|
|
|
yAxisID: 'y'
|
|
|
}]
|
|
|
},
|
|
|
options: {
|
|
|
responsive: true,
|
|
|
maintainAspectRatio: false,
|
|
|
scales: {
|
|
|
y: {
|
|
|
type: 'linear',
|
|
|
display: true,
|
|
|
position: 'left',
|
|
|
grid: {
|
|
|
color: 'rgba(255, 255, 255, 0.1)'
|
|
|
},
|
|
|
ticks: {
|
|
|
color: '#e0e0e0'
|
|
|
}
|
|
|
},
|
|
|
y1: {
|
|
|
type: 'linear',
|
|
|
display: true,
|
|
|
position: 'right',
|
|
|
grid: {
|
|
|
drawOnChartArea: false,
|
|
|
},
|
|
|
ticks: {
|
|
|
color: '#e0e0e0'
|
|
|
}
|
|
|
},
|
|
|
x: {
|
|
|
grid: {
|
|
|
color: 'rgba(255, 255, 255, 0.1)'
|
|
|
},
|
|
|
ticks: {
|
|
|
color: '#e0e0e0'
|
|
|
}
|
|
|
}
|
|
|
},
|
|
|
plugins: {
|
|
|
legend: {
|
|
|
labels: {
|
|
|
color: '#e0e0e0'
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
});
|
|
|
|
|
|
// 创建水文图表
|
|
|
var hydroChart = new Chart(document.getElementById('hydroChart'), {
|
|
|
type: 'line',
|
|
|
data: {
|
|
|
labels: ['13:00', '13:15', '13:30', '13:45', '14:00', '14:15', '14:30'],
|
|
|
datasets: [{
|
|
|
label: '水温 (°C)',
|
|
|
data: [17.8, 18.0, 18.2, 18.3, 18.5, 18.4, 18.6],
|
|
|
borderColor: '#4fc3f7',
|
|
|
backgroundColor: 'rgba(79, 195, 247, 0.1)',
|
|
|
tension: 0.4,
|
|
|
fill: true,
|
|
|
yAxisID: 'y'
|
|
|
}, {
|
|
|
label: '盐度 (PSU)',
|
|
|
data: [33.8, 33.9, 34.0, 34.1, 34.2, 34.1, 34.3],
|
|
|
borderColor: '#4caf50',
|
|
|
backgroundColor: 'rgba(76, 175, 80, 0.1)',
|
|
|
tension: 0.4,
|
|
|
fill: true,
|
|
|
yAxisID: 'y1'
|
|
|
}, {
|
|
|
label: '浊度 (NTU)',
|
|
|
data: [3.8, 4.0, 4.2, 4.3, 4.5, 4.4, 4.6],
|
|
|
borderColor: '#ff9800',
|
|
|
backgroundColor: 'rgba(255, 152, 0, 0.1)',
|
|
|
tension: 0.4,
|
|
|
fill: true,
|
|
|
yAxisID: 'y'
|
|
|
}]
|
|
|
},
|
|
|
options: {
|
|
|
responsive: true,
|
|
|
maintainAspectRatio: false,
|
|
|
scales: {
|
|
|
y: {
|
|
|
type: 'linear',
|
|
|
display: true,
|
|
|
position: 'left',
|
|
|
grid: {
|
|
|
color: 'rgba(255, 255, 255, 0.1)'
|
|
|
},
|
|
|
ticks: {
|
|
|
color: '#e0e0e0'
|
|
|
}
|
|
|
},
|
|
|
y1: {
|
|
|
type: 'linear',
|
|
|
display: true,
|
|
|
position: 'right',
|
|
|
grid: {
|
|
|
drawOnChartArea: false,
|
|
|
},
|
|
|
ticks: {
|
|
|
color: '#e0e0e0'
|
|
|
}
|
|
|
},
|
|
|
x: {
|
|
|
grid: {
|
|
|
color: 'rgba(255, 255, 255, 0.1)'
|
|
|
},
|
|
|
ticks: {
|
|
|
color: '#e0e0e0'
|
|
|
}
|
|
|
}
|
|
|
},
|
|
|
plugins: {
|
|
|
legend: {
|
|
|
labels: {
|
|
|
color: '#e0e0e0'
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
});
|
|
|
|
|
|
// 创建气象要素详细图表
|
|
|
var weatherWindChart = new Chart(document.getElementById('weatherWindChart'), {
|
|
|
type: 'line',
|
|
|
data: {
|
|
|
labels: ['12:00', '12:30', '13:00', '13:30', '14:00', '14:30', '15:00'],
|
|
|
datasets: [{
|
|
|
label: '风速 (m/s)',
|
|
|
data: [9.5, 10.2, 11.5, 12.1, 12.8, 12.5, 11.9],
|
|
|
borderColor: '#4fc3f7',
|
|
|
backgroundColor: 'rgba(79, 195, 247, 0.1)',
|
|
|
tension: 0.4,
|
|
|
fill: true
|
|
|
}, {
|
|
|
label: '阵风风速 (m/s)',
|
|
|
data: [11.2, 12.0, 13.5, 14.2, 15.0, 14.5, 13.8],
|
|
|
borderColor: '#ff9800',
|
|
|
backgroundColor: 'rgba(255, 152, 0, 0.1)',
|
|
|
tension: 0.4,
|
|
|
fill: true
|
|
|
}]
|
|
|
},
|
|
|
options: {
|
|
|
responsive: true,
|
|
|
maintainAspectRatio: false,
|
|
|
scales: {
|
|
|
y: {
|
|
|
beginAtZero: true,
|
|
|
grid: {
|
|
|
color: 'rgba(255, 255, 255, 0.1)'
|
|
|
},
|
|
|
ticks: {
|
|
|
color: '#e0e0e0'
|
|
|
}
|
|
|
},
|
|
|
x: {
|
|
|
grid: {
|
|
|
color: 'rgba(255, 255, 255, 0.1)'
|
|
|
},
|
|
|
ticks: {
|
|
|
color: '#e0e0e0'
|
|
|
}
|
|
|
}
|
|
|
},
|
|
|
plugins: {
|
|
|
legend: {
|
|
|
labels: {
|
|
|
color: '#e0e0e0'
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
});
|
|
|
|
|
|
var weatherTempChart = new Chart(document.getElementById('weatherTempChart'), {
|
|
|
type: 'line',
|
|
|
data: {
|
|
|
labels: ['12:00', '12:30', '13:00', '13:30', '14:00', '14:30', '15:00'],
|
|
|
datasets: [{
|
|
|
label: '气温 (°C)',
|
|
|
data: [20.5, 21.0, 21.5, 22.0, 22.3, 22.1, 21.8],
|
|
|
borderColor: '#4fc3f7',
|
|
|
backgroundColor: 'rgba(79, 195, 247, 0.1)',
|
|
|
tension: 0.4,
|
|
|
fill: true
|
|
|
}]
|
|
|
},
|
|
|
options: {
|
|
|
responsive: true,
|
|
|
maintainAspectRatio: false,
|
|
|
scales: {
|
|
|
y: {
|
|
|
beginAtZero: false,
|
|
|
grid: {
|
|
|
color: 'rgba(255, 255, 255, 0.1)'
|
|
|
},
|
|
|
ticks: {
|
|
|
color: '#e0e0e0'
|
|
|
}
|
|
|
},
|
|
|
x: {
|
|
|
grid: {
|
|
|
color: 'rgba(255, 255, 255, 0.1)'
|
|
|
},
|
|
|
ticks: {
|
|
|
color: '#e0e0e0'
|
|
|
}
|
|
|
}
|
|
|
},
|
|
|
plugins: {
|
|
|
legend: {
|
|
|
labels: {
|
|
|
color: '#e0e0e0'
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
});
|
|
|
|
|
|
var weatherPressureChart = new Chart(document.getElementById('weatherPressureChart'), {
|
|
|
type: 'line',
|
|
|
data: {
|
|
|
labels: ['12:00', '12:30', '13:00', '13:30', '14:00', '14:30', '15:00'],
|
|
|
datasets: [{
|
|
|
label: '气压 (hPa)',
|
|
|
data: [1010.0, 1010.5, 1011.2, 1011.8, 1012.3, 1012.5, 1012.2],
|
|
|
borderColor: '#4fc3f7',
|
|
|
backgroundColor: 'rgba(79, 195, 247, 0.1)',
|
|
|
tension: 0.4,
|
|
|
fill: true
|
|
|
}]
|
|
|
},
|
|
|
options: {
|
|
|
responsive: true,
|
|
|
maintainAspectRatio: false,
|
|
|
scales: {
|
|
|
y: {
|
|
|
beginAtZero: false,
|
|
|
grid: {
|
|
|
color: 'rgba(255, 255, 255, 0.1)'
|
|
|
},
|
|
|
ticks: {
|
|
|
color: '#e0e0e0'
|
|
|
}
|
|
|
},
|
|
|
x: {
|
|
|
grid: {
|
|
|
color: 'rgba(255, 255, 255, 0.1)'
|
|
|
},
|
|
|
ticks: {
|
|
|
color: '#e0e0e0'
|
|
|
}
|
|
|
}
|
|
|
},
|
|
|
plugins: {
|
|
|
legend: {
|
|
|
labels: {
|
|
|
color: '#e0e0e0'
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
});
|
|
|
|
|
|
var weatherHumidityChart = new Chart(document.getElementById('weatherHumidityChart'), {
|
|
|
type: 'line',
|
|
|
data: {
|
|
|
labels: ['12:00', '12:30', '13:00', '13:30', '14:00', '14:30', '15:00'],
|
|
|
datasets: [{
|
|
|
label: '湿度 (%)',
|
|
|
data: [75, 76, 77, 78, 78, 77, 76],
|
|
|
borderColor: '#4fc3f7',
|
|
|
backgroundColor: 'rgba(79, 195, 247, 0.1)',
|
|
|
tension: 0.4,
|
|
|
fill: true
|
|
|
}]
|
|
|
},
|
|
|
options: {
|
|
|
responsive: true,
|
|
|
maintainAspectRatio: false,
|
|
|
scales: {
|
|
|
y: {
|
|
|
beginAtZero: false,
|
|
|
grid: {
|
|
|
color: 'rgba(255, 255, 255, 0.1)'
|
|
|
},
|
|
|
ticks: {
|
|
|
color: '#e0e0e0'
|
|
|
}
|
|
|
},
|
|
|
x: {
|
|
|
grid: {
|
|
|
color: 'rgba(255, 255, 255, 0.1)'
|
|
|
},
|
|
|
ticks: {
|
|
|
color: '#e0e0e0'
|
|
|
}
|
|
|
}
|
|
|
},
|
|
|
plugins: {
|
|
|
legend: {
|
|
|
labels: {
|
|
|
color: '#e0e0e0'
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
});
|
|
|
|
|
|
// 创建水文要素详细图表
|
|
|
var hydroTempChart = new Chart(document.getElementById('hydroTempChart'), {
|
|
|
type: 'line',
|
|
|
data: {
|
|
|
labels: ['12:00', '12:30', '13:00', '13:30', '14:00', '14:30', '15:00'],
|
|
|
datasets: [{
|
|
|
label: '水温 (°C)',
|
|
|
data: [17.5, 17.8, 18.0, 18.2, 18.3, 18.5, 18.4],
|
|
|
borderColor: '#4fc3f7',
|
|
|
backgroundColor: 'rgba(79, 195, 247, 0.1)',
|
|
|
tension: 0.4,
|
|
|
fill: true
|
|
|
}]
|
|
|
},
|
|
|
options: {
|
|
|
responsive: true,
|
|
|
maintainAspectRatio: false,
|
|
|
scales: {
|
|
|
y: {
|
|
|
beginAtZero: false,
|
|
|
grid: {
|
|
|
color: 'rgba(255, 255, 255, 0.1)'
|
|
|
},
|
|
|
ticks: {
|
|
|
color: '#e0e0e0'
|
|
|
}
|
|
|
},
|
|
|
x: {
|
|
|
grid: {
|
|
|
color: 'rgba(255, 255, 255, 0.1)'
|
|
|
},
|
|
|
ticks: {
|
|
|
color: '#e0e0e0'
|
|
|
}
|
|
|
}
|
|
|
},
|
|
|
plugins: {
|
|
|
legend: {
|
|
|
labels: {
|
|
|
color: '#e0e0e0'
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
});
|
|
|
|
|
|
var hydroSalinityChart = new Chart(document.getElementById('hydroSalinityChart'), {
|
|
|
type: 'line',
|
|
|
data: {
|
|
|
labels: ['12:00', '12:30', '13:00', '13:30', '14:00', '14:30', '15:00'],
|
|
|
datasets: [{
|
|
|
label: '盐度 (PSU)',
|
|
|
data: [33.5, 33.7, 33.9, 34.0, 34.1, 34.2, 34.1],
|
|
|
borderColor: '#4fc3f7',
|
|
|
backgroundColor: 'rgba(79, 195, 247, 0.1)',
|
|
|
tension: 0.4,
|
|
|
fill: true
|
|
|
}]
|
|
|
},
|
|
|
options: {
|
|
|
responsive: true,
|
|
|
maintainAspectRatio: false,
|
|
|
scales: {
|
|
|
y: {
|
|
|
beginAtZero: false,
|
|
|
grid: {
|
|
|
color: 'rgba(255, 255, 255, 0.1)'
|
|
|
},
|
|
|
ticks: {
|
|
|
color: '#e0e0e0'
|
|
|
}
|
|
|
},
|
|
|
x: {
|
|
|
grid: {
|
|
|
color: 'rgba(255, 255, 255, 0.1)'
|
|
|
},
|
|
|
ticks: {
|
|
|
color: '#e0e0e0'
|
|
|
}
|
|
|
}
|
|
|
},
|
|
|
plugins: {
|
|
|
legend: {
|
|
|
labels: {
|
|
|
color: '#e0e0e0'
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
});
|
|
|
|
|
|
var hydroFlowChart = new Chart(document.getElementById('hydroFlowChart'), {
|
|
|
type: 'line',
|
|
|
data: {
|
|
|
labels: ['12:00', '12:30', '13:00', '13:30', '14:00', '14:30', '15:00'],
|
|
|
datasets: [{
|
|
|
label: '流速 (m/s)',
|
|
|
data: [1.0, 1.1, 1.2, 1.2, 1.1, 1.2, 1.1],
|
|
|
borderColor: '#4fc3f7',
|
|
|
backgroundColor: 'rgba(79, 195, 247, 0.1)',
|
|
|
tension: 0.4,
|
|
|
fill: true
|
|
|
}]
|
|
|
},
|
|
|
options: {
|
|
|
responsive: true,
|
|
|
maintainAspectRatio: false,
|
|
|
scales: {
|
|
|
y: {
|
|
|
beginAtZero: false,
|
|
|
grid: {
|
|
|
color: 'rgba(255, 255, 255, 0.1)'
|
|
|
},
|
|
|
ticks: {
|
|
|
color: '#e0e0e0'
|
|
|
}
|
|
|
},
|
|
|
x: {
|
|
|
grid: {
|
|
|
color: 'rgba(255, 255, 255, 0.1)'
|
|
|
},
|
|
|
ticks: {
|
|
|
color: '#e0e0e0'
|
|
|
}
|
|
|
}
|
|
|
},
|
|
|
plugins: {
|
|
|
legend: {
|
|
|
labels: {
|
|
|
color: '#e0e0e0'
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
});
|
|
|
|
|
|
var hydroTurbidityChart = new Chart(document.getElementById('hydroTurbidityChart'), {
|
|
|
type: 'line',
|
|
|
data: {
|
|
|
labels: ['12:00', '12:30', '13:00', '13:30', '14:00', '14:30', '15:00'],
|
|
|
datasets: [{
|
|
|
label: '浊度 (NTU)',
|
|
|
data: [3.5, 3.8, 4.0, 4.2, 4.3, 4.5, 4.4],
|
|
|
borderColor: '#4fc3f7',
|
|
|
backgroundColor: 'rgba(79, 195, 247, 0.1)',
|
|
|
tension: 0.4,
|
|
|
fill: true
|
|
|
}]
|
|
|
},
|
|
|
options: {
|
|
|
responsive: true,
|
|
|
maintainAspectRatio: false,
|
|
|
scales: {
|
|
|
y: {
|
|
|
beginAtZero: false,
|
|
|
grid: {
|
|
|
color: 'rgba(255, 255, 255, 0.1)'
|
|
|
},
|
|
|
ticks: {
|
|
|
color: '#e0e0e0'
|
|
|
}
|
|
|
},
|
|
|
x: {
|
|
|
grid: {
|
|
|
color: 'rgba(255, 255, 255, 0.1)'
|
|
|
},
|
|
|
ticks: {
|
|
|
color: '#e0e0e0'
|
|
|
}
|
|
|
}
|
|
|
},
|
|
|
plugins: {
|
|
|
legend: {
|
|
|
labels: {
|
|
|
color: '#e0e0e0'
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
});
|
|
|
|
|
|
// 风向和波高态势图更新函数
|
|
|
function updateSituationCharts() {
|
|
|
// 随机更新风向(0-360度)
|
|
|
var windDirection = Math.floor(Math.random() * 360);
|
|
|
var windArrow = document.getElementById('windArrow');
|
|
|
windArrow.style.transform = 'translate(-50%, -100%) rotate(' + windDirection + 'deg)';
|
|
|
|
|
|
// 更新风向显示
|
|
|
var directions = ['N', 'NNE', 'NE', 'ENE', 'E', 'ESE', 'SE', 'SSE', 'S', 'SSW', 'SW', 'WSW', 'W', 'WNW', 'NW', 'NNW'];
|
|
|
var index = Math.round(windDirection / 22.5) % 16;
|
|
|
document.getElementById('windDirectionValue').textContent = directions[index] + ' ' + windDirection + '°';
|
|
|
|
|
|
// 随机更新风速(5-20 m/s)
|
|
|
var windSpeed = 5 + Math.random() * 15;
|
|
|
var windSpeedFill = document.getElementById('windSpeedFill');
|
|
|
var windSpeedValue = document.getElementById('windSpeedValue');
|
|
|
|
|
|
// 风速填充高度(最大20 m/s对应100%)
|
|
|
var windFillHeight = (windSpeed / 20) * 100;
|
|
|
windSpeedFill.style.height = windFillHeight + '%';
|
|
|
windSpeedValue.textContent = windSpeed.toFixed(1) + 'm/s';
|
|
|
|
|
|
// 根据风速设置预警颜色
|
|
|
if (windSpeed < 10) {
|
|
|
windSpeedFill.className = 'wind-speed-fill normal';
|
|
|
} else if (windSpeed < 15) {
|
|
|
windSpeedFill.className = 'wind-speed-fill warning';
|
|
|
} else {
|
|
|
windSpeedFill.className = 'wind-speed-fill danger';
|
|
|
}
|
|
|
|
|
|
// 随机更新波高(0.5-5米)
|
|
|
var waveHeight = 0.5 + Math.random() * 4.5;
|
|
|
var waveHeightFill = document.getElementById('waveHeightFill');
|
|
|
var waveHeightValue = document.getElementById('waveHeightValue');
|
|
|
|
|
|
// 波高填充高度(最大5米对应100%)
|
|
|
var waveFillHeight = (waveHeight / 5) * 100;
|
|
|
waveHeightFill.style.height = waveFillHeight + '%';
|
|
|
waveHeightValue.textContent = waveHeight.toFixed(1) + 'm';
|
|
|
|
|
|
// 根据波高设置预警颜色
|
|
|
if (waveHeight < 2) {
|
|
|
waveHeightFill.className = 'wave-height-fill normal';
|
|
|
} else if (waveHeight < 3) {
|
|
|
waveHeightFill.className = 'wave-height-fill warning';
|
|
|
} else {
|
|
|
waveHeightFill.className = 'wave-height-fill danger';
|
|
|
}
|
|
|
|
|
|
// 随机更新波向(0-360度)
|
|
|
var waveDirection = Math.floor(Math.random() * 360);
|
|
|
var waveDirectionArrow = document.getElementById('waveDirectionArrow');
|
|
|
waveDirectionArrow.style.transform = 'translate(-50%, -100%) rotate(' + waveDirection + 'deg)';
|
|
|
|
|
|
// 更新波向显示
|
|
|
var waveIndex = Math.round(waveDirection / 22.5) % 16;
|
|
|
document.getElementById('waveDirectionValue').textContent = directions[waveIndex] + ' ' + waveDirection + '°';
|
|
|
}
|
|
|
|
|
|
// 模拟实时数据更新
|
|
|
function updateData() {
|
|
|
// // 更新气象数据
|
|
|
// document.querySelectorAll('.data-value')[0].textContent = (12 + Math.random()).toFixed(1);
|
|
|
// document.querySelectorAll('.data-value')[2].textContent = (22 + Math.random()).toFixed(1);
|
|
|
// document.querySelectorAll('.data-value')[3].textContent = (1012 + Math.random() * 2).toFixed(1);
|
|
|
|
|
|
// // 更新水文数据
|
|
|
// //document.querySelectorAll('.data-value')[6].textContent = (18 + Math.random()).toFixed(1);
|
|
|
// document.querySelectorAll('.data-value')[8].textContent = Math.floor(1240 + Math.random() * 20);
|
|
|
// document.querySelectorAll('.data-value')[9].textContent = (1.1 + Math.random() * 0.2).toFixed(1);
|
|
|
|
|
|
// // 更新船舶状态
|
|
|
// document.querySelectorAll('.data-value')[12].textContent = (8 + Math.random()).toFixed(1);
|
|
|
// document.querySelectorAll('.data-value')[13].textContent = Math.floor(240 + Math.random() * 10);
|
|
|
|
|
|
// 更新仪表
|
|
|
document.querySelectorAll('.gauge-fill')[0].style.height = (60 + Math.random() * 10) + '%';
|
|
|
document.querySelectorAll('.gauge-value')[0].textContent = Math.round(parseFloat(document.querySelectorAll('.gauge-fill')[0].style.height)) + '%';
|
|
|
|
|
|
document.querySelectorAll('.gauge-fill')[1].style.height = (25 + Math.random() * 10) + '%';
|
|
|
document.querySelectorAll('.gauge-value')[1].textContent = Math.round(parseFloat(document.querySelectorAll('.gauge-fill')[1].style.height)) + '%';
|
|
|
|
|
|
// 更新图表数据
|
|
|
updateChartData();
|
|
|
|
|
|
// 更新船舶位置
|
|
|
updateShipPosition();
|
|
|
|
|
|
// 更新态势图
|
|
|
updateSituationCharts();
|
|
|
}
|
|
|
|
|
|
function updateChartData() {
|
|
|
// 更新气象图表数据
|
|
|
var newTime = getCurrentTime();
|
|
|
|
|
|
weatherChart.data.labels.push(newTime);
|
|
|
weatherChart.data.datasets[0].data.push(12 + Math.random());
|
|
|
weatherChart.data.datasets[1].data.push(1012 + Math.random() * 2);
|
|
|
weatherChart.data.datasets[2].data.push(22 + Math.random());
|
|
|
|
|
|
if (weatherChart.data.datasets[0].data.length > 10) {
|
|
|
weatherChart.data.labels.shift();
|
|
|
weatherChart.data.datasets[0].data.shift();
|
|
|
weatherChart.data.datasets[1].data.shift();
|
|
|
weatherChart.data.datasets[2].data.shift();
|
|
|
}
|
|
|
|
|
|
weatherChart.update();
|
|
|
|
|
|
// 更新水文图表数据
|
|
|
hydroChart.data.labels.push(newTime);
|
|
|
hydroChart.data.datasets[0].data.push(18 + Math.random());
|
|
|
hydroChart.data.datasets[1].data.push(34 + Math.random() * 0.5);
|
|
|
hydroChart.data.datasets[2].data.push(4 + Math.random() * 1);
|
|
|
|
|
|
if (hydroChart.data.datasets[0].data.length > 10) {
|
|
|
hydroChart.data.labels.shift();
|
|
|
hydroChart.data.datasets[0].data.shift();
|
|
|
hydroChart.data.datasets[1].data.shift();
|
|
|
hydroChart.data.datasets[2].data.shift();
|
|
|
}
|
|
|
|
|
|
hydroChart.update();
|
|
|
}
|
|
|
|
|
|
// function updateShipPosition() {
|
|
|
// // 模拟船舶移动
|
|
|
// var currentLat = shipMarker.getLatLng().lat;
|
|
|
// var currentLng = shipMarker.getLatLng().lng;
|
|
|
|
|
|
// // 在南海区域内随机移动
|
|
|
// var newLat = currentLat + (Math.random() - 0.5) * 0.05;
|
|
|
// var newLng = currentLng + (Math.random() - 0.5) * 0.05;
|
|
|
|
|
|
// // 确保船舶在南海区域内
|
|
|
// newLat = Math.min(Math.max(newLat, 10), 23);
|
|
|
// newLng = Math.min(Math.max(newLng, 105), 120);
|
|
|
|
|
|
// shipMarker.setLatLng([newLat, newLng]);
|
|
|
|
|
|
// // 更新位置显示
|
|
|
// document.querySelector('.status-item:nth-child(4) span:last-child').textContent =
|
|
|
// newLat.toFixed(2) + '°N, ' + newLng.toFixed(2) + '°E';
|
|
|
// }
|
|
|
|
|
|
function getCurrentTime() {
|
|
|
const now = new Date();
|
|
|
return `${now.getHours()}:${now.getMinutes().toString().padStart(2, '0')}`;
|
|
|
}
|
|
|
|
|
|
// // 添加船舶点击事件
|
|
|
// shipMarker.on('click', function (e) {
|
|
|
// var lat = e.latlng.lat;
|
|
|
// var lng = e.latlng.lng;
|
|
|
|
|
|
// // 更新坐标信息显示
|
|
|
// document.getElementById('latValue').textContent = lat.toFixed(4) + '°N';
|
|
|
// document.getElementById('lngValue').textContent = lng.toFixed(4) + '°E';
|
|
|
|
|
|
// // 显示坐标信息框
|
|
|
// var coordsInfo = document.getElementById('coordinatesInfo');
|
|
|
// coordsInfo.classList.add('active');
|
|
|
|
|
|
// // 3秒后自动隐藏
|
|
|
// setTimeout(function () {
|
|
|
// coordsInfo.classList.remove('active');
|
|
|
// }, 3000);
|
|
|
// });
|
|
|
|
|
|
// 系统按钮事件处理 - 改为弹出模态框
|
|
|
document.querySelectorAll('.system-btn').forEach(function (btn) {
|
|
|
btn.addEventListener('click', function () {
|
|
|
var system = this.getAttribute('data-system');
|
|
|
var systemModal = document.getElementById('systemModal');
|
|
|
var systemModalTitle = document.getElementById('systemModalTitle');
|
|
|
var systemModalContent = document.getElementById('systemModalContent');
|
|
|
|
|
|
// 设置模态框标题
|
|
|
systemModalTitle.textContent = this.textContent + '详情';
|
|
|
|
|
|
// 根据系统类型设置内容
|
|
|
var content = '';
|
|
|
if (system === 'navigation') {
|
|
|
content = `
|
|
|
<div class="system-data-panel active">
|
|
|
<div class="system-data-item">
|
|
|
<span class="system-data-label">GPS定位精度</span>
|
|
|
<span class="system-data-value">2.1 m</span>
|
|
|
</div>
|
|
|
<div class="system-data-item">
|
|
|
<span class="system-data-label">陀螺仪状态</span>
|
|
|
<span class="system-data-value">正常</span>
|
|
|
</div>
|
|
|
<div class="system-data-item">
|
|
|
<span class="system-data-label">罗经航向</span>
|
|
|
<span class="system-data-value">245.2°</span>
|
|
|
</div>
|
|
|
<div class="system-data-item">
|
|
|
<span class="system-data-label">AIS连接</span>
|
|
|
<span class="system-data-value">在线</span>
|
|
|
</div>
|
|
|
<div class="system-data-item">
|
|
|
<span class="system-data-label">GPS卫星数量</span>
|
|
|
<span class="system-data-value">12</span>
|
|
|
</div>
|
|
|
<div class="system-data-item">
|
|
|
<span class="system-data-label">最后定位时间</span>
|
|
|
<span class="system-data-value">14:29:45</span>
|
|
|
</div>
|
|
|
</div>
|
|
|
`;
|
|
|
} else if (system === 'communication') {
|
|
|
content = `
|
|
|
<div class="system-data-panel active">
|
|
|
<div class="system-data-item">
|
|
|
<span class="system-data-label">卫星通信</span>
|
|
|
<span class="system-data-value">正常</span>
|
|
|
</div>
|
|
|
<div class="system-data-item">
|
|
|
<span class="system-data-label">信号强度</span>
|
|
|
<span class="system-data-value">85%</span>
|
|
|
</div>
|
|
|
<div class="system-data-item">
|
|
|
<span class="system-data-label">数据传输率</span>
|
|
|
<span class="system-data-value">512 kbps</span>
|
|
|
</div>
|
|
|
<div class="system-data-item">
|
|
|
<span class="system-data-label">最后通信</span>
|
|
|
<span class="system-data-value">14:28:15</span>
|
|
|
</div>
|
|
|
<div class="system-data-item">
|
|
|
<span class="system-data-label">通信延迟</span>
|
|
|
<span class="system-data-value">320 ms</span>
|
|
|
</div>
|
|
|
<div class="system-data-item">
|
|
|
<span class="system-data-label">数据包丢失率</span>
|
|
|
<span class="system-data-value">0.2%</span>
|
|
|
</div>
|
|
|
</div>
|
|
|
`;
|
|
|
} else if (system === 'sonar') {
|
|
|
content = `
|
|
|
<div class="system-data-panel active">
|
|
|
<div class="system-data-item">
|
|
|
<span class="system-data-label">多波束状态</span>
|
|
|
<span class="system-data-value">运行中</span>
|
|
|
</div>
|
|
|
<div class="system-data-item">
|
|
|
<span class="system-data-label">最大探测深度</span>
|
|
|
<span class="system-data-value">4500 m</span>
|
|
|
</div>
|
|
|
<div class="system-data-item">
|
|
|
<span class="system-data-label">声波频率</span>
|
|
|
<span class="system-data-value">12 kHz</span>
|
|
|
</div>
|
|
|
<div class="system-data-item">
|
|
|
<span class="system-data-label">数据质量</span>
|
|
|
<span class="system-data-value">良好</span>
|
|
|
</div>
|
|
|
<div class="system-data-item">
|
|
|
<span class="system-data-label">声波发射功率</span>
|
|
|
<span class="system-data-value">85%</span>
|
|
|
</div>
|
|
|
<div class="system-data-item">
|
|
|
<span class="system-data-label">最后扫描时间</span>
|
|
|
<span class="system-data-value">14:27:30</span>
|
|
|
</div>
|
|
|
</div>
|
|
|
`;
|
|
|
} else if (system === 'sampling') {
|
|
|
content = `
|
|
|
<div class="system-data-panel active">
|
|
|
<div class="system-data-item">
|
|
|
<span class="system-data-label">CTD采水器</span>
|
|
|
<span class="system-data-value">就绪</span>
|
|
|
</div>
|
|
|
<div class="system-data-item">
|
|
|
<span class="system-data-label">浮游生物网</span>
|
|
|
<span class="system-data-value">部署中</span>
|
|
|
</div>
|
|
|
<div class="system-data-item">
|
|
|
<span class="system-data-label">沉积物采样</span>
|
|
|
<span class="system-data-value">待命</span>
|
|
|
</div>
|
|
|
<div class="system-data-item">
|
|
|
<span class="system-data-label">样本数量</span>
|
|
|
<span class="system-data-value">24</span>
|
|
|
</div>
|
|
|
<div class="system-data-item">
|
|
|
<span class="system-data-label">最后采样时间</span>
|
|
|
<span class="system-data-value">14:25:10</span>
|
|
|
</div>
|
|
|
<div class="system-data-item">
|
|
|
<span class="system-data-label">样本存储温度</span>
|
|
|
<span class="system-data-value">4.2°C</span>
|
|
|
</div>
|
|
|
</div>
|
|
|
`;
|
|
|
}
|
|
|
|
|
|
systemModalContent.innerHTML = content;
|
|
|
systemModal.style.display = 'flex';
|
|
|
});
|
|
|
});
|
|
|
|
|
|
// 地图控制按钮事件处理
|
|
|
document.getElementById('toggleSatellite').addEventListener('click', function () {
|
|
|
if (map.hasLayer(seaMapLayer)) {
|
|
|
map.removeLayer(seaMapLayer);
|
|
|
satelliteLayer.addTo(map);
|
|
|
} else if (map.hasLayer(terrainLayer)) {
|
|
|
map.removeLayer(terrainLayer);
|
|
|
satelliteLayer.addTo(map);
|
|
|
}
|
|
|
});
|
|
|
|
|
|
document.getElementById('toggleTerrain').addEventListener('click', function () {
|
|
|
if (map.hasLayer(seaMapLayer)) {
|
|
|
map.removeLayer(seaMapLayer);
|
|
|
terrainLayer.addTo(map);
|
|
|
} else if (map.hasLayer(satelliteLayer)) {
|
|
|
map.removeLayer(satelliteLayer);
|
|
|
terrainLayer.addTo(map);
|
|
|
}
|
|
|
});
|
|
|
|
|
|
document.getElementById('resetView').addEventListener('click', function () {
|
|
|
if (map.hasLayer(satelliteLayer)) {
|
|
|
map.removeLayer(satelliteLayer);
|
|
|
}
|
|
|
if (map.hasLayer(terrainLayer)) {
|
|
|
map.removeLayer(terrainLayer);
|
|
|
}
|
|
|
seaMapLayer.addTo(map);
|
|
|
map.setView([18.0, 115.0], 5);
|
|
|
});
|
|
|
|
|
|
// 按钮事件处理
|
|
|
document.getElementById('showWeatherChart').addEventListener('click', function () {
|
|
|
var container = document.getElementById('weatherChartContainer');
|
|
|
var dataGrid = this.closest('.panel').querySelector('.data-grid');
|
|
|
container.classList.toggle('chart-visible');
|
|
|
if (container.classList.contains('chart-visible')) {
|
|
|
dataGrid.style.display = 'none';
|
|
|
this.textContent = '隐藏图表';
|
|
|
} else {
|
|
|
dataGrid.style.display = 'grid';
|
|
|
this.textContent = '显示图表';
|
|
|
}
|
|
|
});
|
|
|
|
|
|
document.getElementById('showHydroChart').addEventListener('click', function () {
|
|
|
var container = document.getElementById('hydroChartContainer');
|
|
|
var dataGrid = this.closest('.panel').querySelector('.data-grid');
|
|
|
container.classList.toggle('chart-visible');
|
|
|
if (container.classList.contains('chart-visible')) {
|
|
|
dataGrid.style.display = 'none';
|
|
|
this.textContent = '隐藏图表';
|
|
|
} else {
|
|
|
dataGrid.style.display = 'grid';
|
|
|
this.textContent = '显示图表';
|
|
|
}
|
|
|
});
|
|
|
|
|
|
document.getElementById('dataDownloadBtn').addEventListener('click', function () {
|
|
|
document.getElementById('downloadModal').style.display = 'flex';
|
|
|
});
|
|
|
|
|
|
document.getElementById('dataPlaybackBtn').addEventListener('click', function () {
|
|
|
document.getElementById('playbackPanel').style.display = 'flex';
|
|
|
});
|
|
|
|
|
|
document.getElementById('weatherChartBtn').addEventListener('click', function () {
|
|
|
document.getElementById('weatherChartModal').style.display = 'flex';
|
|
|
});
|
|
|
|
|
|
document.getElementById('hydroChartBtn').addEventListener('click', function () {
|
|
|
document.getElementById('hydroChartModal').style.display = 'flex';
|
|
|
});
|
|
|
|
|
|
document.getElementById('closePlayback').addEventListener('click', function () {
|
|
|
document.getElementById('playbackPanel').style.display = 'none';
|
|
|
});
|
|
|
|
|
|
// 关闭模态框
|
|
|
document.querySelectorAll('.close-btn').forEach(function (btn) {
|
|
|
btn.addEventListener('click', function () {
|
|
|
document.querySelectorAll('.modal').forEach(function (modal) {
|
|
|
modal.style.display = 'none';
|
|
|
});
|
|
|
});
|
|
|
});
|
|
|
|
|
|
// 点击模态框外部关闭
|
|
|
window.addEventListener('click', function (event) {
|
|
|
document.querySelectorAll('.modal').forEach(function (modal) {
|
|
|
if (event.target === modal) {
|
|
|
modal.style.display = 'none';
|
|
|
}
|
|
|
});
|
|
|
});
|
|
|
|
|
|
// 每5秒更新一次数据
|
|
|
setInterval(updateData, 5000);
|
|
|
|
|
|
// 初始数据更新
|
|
|
updateData();
|
|
|
|
|
|
// 时间轴拖动功能
|
|
|
function initTimeline() {
|
|
|
// 确保DOM已加载完成
|
|
|
if (document.readyState === 'loading') {
|
|
|
document.addEventListener('DOMContentLoaded', createTimeline);
|
|
|
} else {
|
|
|
createTimeline();
|
|
|
}
|
|
|
}
|
|
|
|
|
|
// 修改时间轴创建函数
|
|
|
function createTimeline() {
|
|
|
const timeline = document.querySelector('.timeline');
|
|
|
if (!timeline) {
|
|
|
console.error('时间轴容器未找到');
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
// 清空时间轴容器
|
|
|
timeline.innerHTML = '';
|
|
|
|
|
|
// 获取当前时间并设置时间轴默认位置
|
|
|
const now = new Date();
|
|
|
const hours = now.getHours();
|
|
|
const minutes = now.getMinutes();
|
|
|
const currentTimePercent = ((hours * 60 + minutes) / (24 * 60)) * 100;
|
|
|
|
|
|
// 创建时间轴基础元素
|
|
|
const progress = document.createElement('div');
|
|
|
progress.className = 'timeline-progress';
|
|
|
progress.style.width = currentTimePercent + '%';
|
|
|
|
|
|
const track = document.createElement('div');
|
|
|
track.className = 'timeline-track';
|
|
|
|
|
|
// 添加基础元素到时间轴
|
|
|
timeline.appendChild(progress);
|
|
|
timeline.appendChild(track);
|
|
|
|
|
|
// 生成24小时时间标记 (每3小时一个标记)
|
|
|
for (let i = 0; i < 24; i += 3) {
|
|
|
const marker = document.createElement('div');
|
|
|
marker.className = 'time-marker';
|
|
|
marker.style.left = (i / 24) * 100 + '%';
|
|
|
|
|
|
const label = document.createElement('div');
|
|
|
label.className = 'time-label';
|
|
|
label.textContent = i.toString().padStart(2, '0') + ':00';
|
|
|
label.style.left = '50%';
|
|
|
|
|
|
marker.appendChild(label);
|
|
|
timeline.appendChild(marker);
|
|
|
}
|
|
|
|
|
|
// 添加当前时间指示器
|
|
|
const currentTimeMarker = document.createElement('div');
|
|
|
currentTimeMarker.className = 'current-time-indicator';
|
|
|
currentTimeMarker.style.left = currentTimePercent + '%';
|
|
|
timeline.appendChild(currentTimeMarker);
|
|
|
|
|
|
// 创建拖动按钮(使用图片)
|
|
|
const handle = document.createElement('div');
|
|
|
handle.className = 'timeline-handle';
|
|
|
handle.style.left = currentTimePercent + '%';
|
|
|
timeline.appendChild(handle);
|
|
|
|
|
|
// 创建船舶图标
|
|
|
const shipIcon = document.createElement('div');
|
|
|
shipIcon.className = 'ship-icon';
|
|
|
shipIcon.style.left = currentTimePercent + '%';
|
|
|
timeline.appendChild(shipIcon);
|
|
|
|
|
|
// 添加拖动事件
|
|
|
addDragEvents(handle, progress, shipIcon);
|
|
|
}
|
|
|
|
|
|
|
|
|
function addDragEvents(handle, progress, shipIcon) {
|
|
|
let isDragging = false;
|
|
|
|
|
|
// 鼠标按下事件
|
|
|
handle.addEventListener('mousedown', function (e) {
|
|
|
isDragging = true;
|
|
|
e.preventDefault();
|
|
|
});
|
|
|
|
|
|
// 鼠标移动事件
|
|
|
document.addEventListener('mousemove', function (e) {
|
|
|
if (!isDragging) return;
|
|
|
|
|
|
const timeline = document.querySelector('.timeline');
|
|
|
const timelineRect = timeline.getBoundingClientRect();
|
|
|
let posX = e.clientX - timelineRect.left;
|
|
|
|
|
|
// 限制拖动范围
|
|
|
posX = Math.max(0, Math.min(posX, timelineRect.width));
|
|
|
|
|
|
// 计算百分比位置
|
|
|
const percent = (posX / timelineRect.width) * 100;
|
|
|
|
|
|
// 更新拖动按钮位置
|
|
|
handle.style.left = percent + '%';
|
|
|
|
|
|
// 更新进度条
|
|
|
progress.style.width = percent + '%';
|
|
|
|
|
|
// 更新船舶图标位置
|
|
|
shipIcon.style.left = percent + '%';
|
|
|
});
|
|
|
|
|
|
// 鼠标释放事件
|
|
|
document.addEventListener('mouseup', function () {
|
|
|
isDragging = false;
|
|
|
});
|
|
|
|
|
|
// 触摸事件支持(移动端)
|
|
|
handle.addEventListener('touchstart', function (e) {
|
|
|
isDragging = true;
|
|
|
e.preventDefault();
|
|
|
});
|
|
|
|
|
|
document.addEventListener('touchmove', function (e) {
|
|
|
if (!isDragging) return;
|
|
|
|
|
|
const timeline = document.querySelector('.timeline');
|
|
|
const timelineRect = timeline.getBoundingClientRect();
|
|
|
let posX = e.touches[0].clientX - timelineRect.left;
|
|
|
|
|
|
// 限制拖动范围
|
|
|
posX = Math.max(0, Math.min(posX, timelineRect.width));
|
|
|
|
|
|
// 计算百分比位置
|
|
|
const percent = (posX / timelineRect.width) * 100;
|
|
|
|
|
|
// 更新拖动按钮位置
|
|
|
handle.style.left = percent + '%';
|
|
|
|
|
|
// 更新进度条
|
|
|
progress.style.width = percent + '%';
|
|
|
|
|
|
// 更新船舶图标位置
|
|
|
shipIcon.style.left = percent + '%';
|
|
|
});
|
|
|
|
|
|
document.addEventListener('touchend', function () {
|
|
|
isDragging = false;
|
|
|
});
|
|
|
}
|
|
|
|
|
|
// 页面加载完成后初始化时间轴
|
|
|
initTimeline();
|
|
|
|
|
|
// 窗口大小改变时重新初始化时间轴
|
|
|
window.addEventListener('resize', function () {
|
|
|
setTimeout(initTimeline, 100); // 延迟执行以确保DOM已更新
|
|
|
});
|
|
|
|
|
|
// 初始化日期时间
|
|
|
function initDateTime() {
|
|
|
function updateDateTime() {
|
|
|
const now = new Date();
|
|
|
const dateStr = now.getFullYear() + '年' +
|
|
|
(now.getMonth() + 1) + '月' +
|
|
|
now.getDate() + '日';
|
|
|
const timeStr = now.toTimeString().substr(0, 8);
|
|
|
|
|
|
document.getElementById('current-date').textContent = dateStr;
|
|
|
document.getElementById('current-time').textContent = timeStr;
|
|
|
}
|
|
|
|
|
|
updateDateTime();
|
|
|
setInterval(updateDateTime, 1000);
|
|
|
}
|
|
|
</script>
|
|
|
</body>
|
|
|
|
|
|
</html> |