You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

2647 lines
80 KiB
HTML

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" issue="width=device-width, initial-scale=1.0">
<title>科考任务综合管理系统 - 系统主页</title>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
<script src="/js/echarts5.4.3/echarts.min.js"></script>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
font-family: 'Microsoft YaHei', Arial, sans-serif;
}
body {
background: url('/assets/img/bg.png') no-repeat;
background-size: 100% 100%;
color: #e0f0ff;
background-color: #0a1a2a;
overflow-x: hidden;
overflow-y: auto;
}
.container {
/* max-width: 1400px; */
margin: 0 auto;
padding: 20px;
}
/* 顶部标题栏 */
.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: fixed;
top: 0;
left: 0;
}
.top-header {
display: flex;
align-items: center;
justify-content: space-between;
width: 100%;
padding: 0 20px;
}
.logo-container {
display: flex;
align-items: center;
space-x: 3;
}
.logo-container img {
height: 40px;
}
.system-title {
text-align: center;
font-size: 2rem;
font-weight: bold;
color: white;
margin-top: -30px;
}
.header-right {
display: flex;
align-items: center;
space-x: 5;
}
.notification-button {
position: relative;
margin-right: 20px;
}
.notification-button::after {
content: '';
position: absolute;
top: 5px;
right: 5px;
width: 8px;
height: 8px;
background: #f44336;
border-radius: 50%;
box-shadow: 0 0 8px rgba(244, 67, 54, 0.7);
}
.user-info-container {
display: flex;
align-items: center;
space-x: 3;
}
.user-info-text {
color: white;
}
header {
display: flex;
justify-content: space-between;
align-items: center;
padding: 15px 0;
border-bottom: 1px solid rgba(64, 156, 255, 0.3);
margin-bottom: 30px;
background: rgba(12, 42, 73, 0.1);
backdrop-filter: blur(10px);
border-radius: 8px;
padding: 15px 20px;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3);
margin-top: 8vh;
/* 为顶部标题栏留出空间 */
}
.logo {
display: flex;
align-items: center;
}
.logo i {
font-size: 32px;
margin-right: 10px;
color: #40a9ff;
}
.logo h1 {
font-size: 24px;
font-weight: 600;
color: #e0f0ff;
}
.user-info {
display: flex;
align-items: center;
}
.user-info img {
width: 40px;
height: 40px;
border-radius: 50%;
margin-right: 10px;
border: 2px solid #40a9ff;
}
/* 侧边栏样式 */
.sidebar {
position: fixed;
left: 0;
top: 0;
width: 50px;
height: 100%;
background: rgba(12, 42, 73, 0.1);
backdrop-filter: blur(10px);
padding-top: 80px;
z-index: 100;
transition: all 0.3s ease;
border-right: 1px solid rgba(64, 156, 255, 0.3);
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3);
margin-top: 8vh;
/* 为顶部标题栏留出空间 */
}
.sidebar ul {
list-style: none;
padding: 0;
}
.sidebar li {
padding: 0;
}
.sidebar a {
display: block;
padding: 15px 20px;
color: #a0d2ff;
text-decoration: none;
transition: all 0.3s;
border-left: 4px solid transparent;
}
.sidebar a:hover,
.sidebar a.active {
background: rgba(59, 130, 246, 0.1);
border-left: 4px solid #3B82F6;
color: #e0f0ff;
}
.sidebar a i {
margin-right: 10px;
width: 20px;
text-align: center;
}
/* 主内容区域 */
.main-content {
margin-left: 50px;
padding: 20px;
margin-top: 3vh;
/* 为顶部标题栏留出空间 */
}
.section-title {
font-size: 24px;
margin-bottom: 20px;
padding-bottom: 10px;
border-bottom: 1px solid rgba(64, 156, 255, 0.3);
color: #e0f0ff;
}
.module-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
gap: 20px;
margin-bottom: 30px;
}
.module-card {
background: rgba(12, 42, 73, 0.1);
backdrop-filter: blur(10px);
border-radius: 10px;
padding: 20px;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3);
border: 1px solid rgba(64, 156, 255, 0.3);
color: #e0f0ff;
}
.module-title {
height: 40px;
background: url('/assets/img/common/homeTitle2.png') no-repeat;
background-position: center;
background-size: 100% 100%;
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 0px -20px;
}
.module-title span {
font-size: 1.2rem;
letter-spacing: 1px;
font-family: 'YouSheBiaoTiHei', 'Microsoft YaHei';
font-weight: 400;
color: #ffffff;
}
.module-title i {
margin-right: 10px;
color: #40a9ff;
}
.chart-container {
height: 200px;
position: relative;
}
.data-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
gap: 15px;
}
.data-item {
background: rgba(25, 55, 95, 0.6);
border-radius: 5px;
padding: 10px;
text-align: center;
}
.data-label {
font-size: 12px;
color: #a0d2ff;
margin-bottom: 5px;
}
.data-value {
font-size: 16px;
font-weight: bold;
color: #e0f0ff;
}
table {
width: 100%;
border-collapse: collapse;
margin-top: 10px;
}
th,
td {
padding: 8px 12px;
text-align: left;
border-bottom: 1px solid rgba(64, 156, 255, 0.3);
}
th {
background: rgba(25, 55, 95, 0.6);
font-weight: normal;
color: #4fc3f7;
}
.hidden {
display: none;
}
.video-container {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
gap: 20px;
}
.video-item {
background: rgba(25, 55, 95, 0.6);
border-radius: 10px;
padding: 15px;
text-align: center;
}
.video-placeholder {
height: 100%;
background-image: url("/img_kekao/6.png");
background-size: 100% 100%;
/* background: rgba(40, 80, 130, 0.7); */
border-radius: 5px;
display: flex;
align-items: center;
justify-content: center;
margin-bottom: 10px;
}
.video-placeholder i {
color: #4fc3f7;
}
.status-item {
background: rgba(12, 42, 73, 0.1);
backdrop-filter: blur(10px);
border-radius: 8px;
padding: 15px;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3);
border: 1px solid rgba(64, 156, 255, 0.3);
flex: 1;
margin: 0 10px;
display: flex;
flex-direction: column;
align-items: center;
}
.status-item:first-child {
margin-left: 0;
}
.status-item:last-child {
margin-right: 0;
}
.status-item i {
font-size: 32px;
margin-bottom: 10px;
color: #40a9ff;
}
.status-value {
font-size: 24px;
font-weight: bold;
margin: 5px 0;
color: #e0f0ff;
}
.status-label {
font-size: 14px;
color: #a0d2ff;
}
.status {
display: flex;
justify-content: space-between;
margin-top: 30px;
}
footer {
margin-top: 40px;
text-align: center;
padding: 20px;
border-top: 1px solid rgba(64, 156, 255, 0.3);
color: #a0d2ff;
font-size: 14px;
}
/* 三行布局 */
.row {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
gap: 20px;
margin-bottom: 20px;
}
/* 第二行特殊布局:激光测风雷达、风廓线雷达、测波雷达、水质测量仪 */
.row-second {
display: grid;
grid-template-columns: repeat(4, 1fr);
gap: 20px;
margin-bottom: 20px;
}
/* 测波雷达和水质测量仪容器 */
.combined-modules {
grid-column: span 2;
display: grid;
grid-template-columns: 1fr 1fr;
gap: 20px;
}
/* 测波雷达和水质测量仪内部三列布局 */
.wave-data-grid,
.water-data-grid {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 10px;
}
.wave-data-item,
.water-data-item {
/* background: rgba(25, 55, 95, 0.6);
border-radius: 5px; */
background: url('/img_kekao/kuang-wz-150_90.png') no-repeat;
background-position: center;
background-size: 100% 100%;
padding: 8px;
text-align: center;
position: relative;
}
.wave-data-label,
.water-data-label {
font-size: 11px;
color: #a0d2ff;
margin-bottom: 3px;
}
.wave-data-value,
.water-data-value {
font-size: 13px;
font-weight: bold;
color: #e0f0ff;
}
@media (max-width: 768px) {
.sidebar {
width: 70px;
}
.sidebar a span {
display: none;
}
.sidebar a i {
margin-right: 0;
font-size: 20px;
}
.main-content {
margin-left: 70px;
}
.data-grid {
grid-template-columns: 1fr 1fr;
}
.status {
flex-direction: column;
}
.status-item {
margin: 10px 0;
}
/* 响应式调整第二行布局 */
.row-second {
grid-template-columns: 1fr;
}
.combined-modules {
grid-column: span 1;
grid-template-columns: 1fr;
}
/* 响应式调整测波雷达和水质测量仪内部布局 */
.wave-data-grid,
.water-data-grid {
grid-template-columns: repeat(2, 1fr);
}
}
/* 态势图容器样式 */
.situation-chart-container {
display: grid;
grid-template-columns: repeat(2, 1fr);
gap: 15px;
margin-bottom: 15px;
}
.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: #40a9ff;
margin-bottom: 10px;
font-size: 14px;
border-bottom: 1px solid rgba(64, 169, 255, 0.3);
padding-bottom: 5px;
text-align: center;
}
/* 风向态势图 */
.wind-direction-container {
display: flex;
flex-direction: column;
align-items: center;
height: 100%;
}
.wind-direction-indicator {
width: 120px;
height: 120px;
position: relative;
border-radius: 50%;
background: linear-gradient(135deg, #0a3d62, #1a5276);
border: 2px solid rgba(64, 169, 255, 0.5);
box-shadow: 0 0 10px rgba(0, 0, 0, 0.3);
}
.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: 3px;
height: 45px;
background: linear-gradient(to top, #40a9ff, #0277bd);
transform-origin: 50% 100%;
transform: translate(-50%, -100%) rotate(0deg);
border-radius: 2px;
z-index: 10;
box-shadow: 0 0 5px rgba(64, 169, 255, 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: 6px solid transparent;
border-right: 6px solid transparent;
border-bottom: 8px solid #40a9ff;
}
.wind-direction-labels {
position: absolute;
width: 100%;
height: 100%;
top: 0;
left: 0;
}
.wind-direction-label {
position: absolute;
font-size: 10px;
color: #e0f0ff;
font-weight: bold;
}
.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: 8px;
gap: 5px;
}
.wind-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 {
font-size: 10px;
color: #a0d2ff;
margin-bottom: 2px;
}
.wind-detail-value {
color: #40a9ff;
text-shadow: 0 0 8px rgba(64, 169, 255, 0.7);
font-weight: bold;
font-size: 10px;
}
/* 风速态势图 */
.wind-speed-container {
display: flex;
flex-direction: column;
align-items: center;
height: 100%;
}
.wind-speed-gauge {
width: 60px;
height: 120px;
position: relative;
/* background: linear-gradient(135deg, #0a3d62, #1a5276); */
overflow: hidden;
box-shadow: 0 0 10px rgba(0, 0, 0, 0.3);
background-image: url(/img_kekao/wendu.png);
background-size: 100% 100%;
}
.wind-speed-fill {
position: absolute;
bottom: 0;
width: 100%;
background: linear-gradient(to top, #40a9ff, #0277bd);
border-radius: 8px 8px 0 0;
transition: height 1s ease;
}
.wind-speed-value {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
font-size: 16px;
font-weight: bold;
color: #e0f0ff;
text-shadow: 0 0 10px rgba(0, 0, 0, 0.7);
z-index: 10;
}
.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: 8px;
gap: 5px;
}
.wind-speed-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-speed-detail-label {
font-size: 10px;
color: #a0d2ff;
margin-bottom: 2px;
}
.wind-speed-detail-value {
color: #64ffda;
text-shadow: 0 0 8px rgba(100, 255, 218, 0.7);
font-weight: bold;
font-size: 10px;
}
/* 波高态势图 */
.wave-height-container {
display: flex;
flex-direction: column;
align-items: center;
height: 100%;
}
.wave-height-gauge {
width: 60px;
height: 120px;
position: relative;
/* background: linear-gradient(135deg, #0a3d62, #1a5276); */
overflow: hidden;
box-shadow: 0 0 10px rgba(0, 0, 0, 0.3);
background-image: url(/img_kekao/shidu.png);
background-size: 100% 100%;
}
.wave-height-fill {
position: absolute;
bottom: 0;
width: 100%;
background: linear-gradient(to top, #40a9ff, #0277bd);
border-radius: 8px 8px 0 0;
transition: height 1s ease;
}
.wave-height-value {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
font-size: 16px;
font-weight: bold;
color: #e0f0ff;
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: 8px;
gap: 5px;
}
.wave-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;
}
.wave-detail-label {
font-size: 10px;
color: #a0d2ff;
margin-bottom: 2px;
}
.wave-detail-value {
color: #29b6f6;
text-shadow: 0 0 8px rgba(41, 182, 246, 0.7);
font-weight: bold;
font-size: 10px;
}
/* 波向态势图 */
.wave-direction-container {
display: flex;
flex-direction: column;
align-items: center;
height: 100%;
}
.wave-direction-indicator {
width: 120px;
height: 120px;
position: relative;
/* border-radius: 50%;
background: linear-gradient(135deg, #0a3d62, #1a5276);
border: 2px solid rgba(64, 169, 255, 0.5); */
/* box-shadow: 0 0 10px rgba(0, 0, 0, 0.3); */
}
.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: 3px;
height: 45px;
background: linear-gradient(to top, #40a9ff, #0277bd);
transform-origin: 50% 100%;
transform: translate(-50%, -100%) rotate(0deg);
border-radius: 2px;
z-index: 10;
box-shadow: 0 0 5px rgba(64, 169, 255, 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: 6px solid transparent;
border-right: 6px solid transparent;
border-bottom: 8px solid #40a9ff;
}
.wave-direction-labels {
position: absolute;
width: 100%;
height: 100%;
top: 0;
left: 0;
}
.wave-direction-label {
position: absolute;
font-size: 10px;
color: #e0f0ff;
font-weight: bold;
}
.wave-direction-details {
display: flex;
justify-content: space-around;
width: 100%;
margin-top: 8px;
gap: 5px;
}
.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;
}
.wave-direction-detail-label {
font-size: 10px;
color: #a0d2ff;
margin-bottom: 2px;
}
.wave-direction-detail-value {
color: #5c6bc0;
text-shadow: 0 0 8px rgba(92, 107, 192, 0.7);
font-weight: bold;
font-size: 10px;
}
/* 海洋波纹效果 */
.wave-pattern {
position: absolute;
bottom: 0;
width: 100%;
height: 10px;
background: linear-gradient(90deg, transparent, rgba(64, 169, 255, 0.3), transparent);
animation: wave-animation 3s infinite linear;
}
@keyframes wave-animation {
0% {
transform: translateX(-100%);
}
100% {
transform: translateX(100%);
}
}
.moule-img {
background-image: url("/img_kekao/海图.png");
background-size: 100% 100%;
}
/*四个角*/
.topL {
width: 10px;
height: 10px;
border-top-width: 2px;
border-top-color: #26c6f0;
border-top-style: solid;
border-left-width: 2px;
border-left-color: #26c6f0;
border-left-style: solid;
position: absolute;
top: -2px;
left: -2px
}
.topR {
width: 10px;
height: 10px;
border-top-width: 2px;
border-top-color: #26c6f0;
border-top-style: solid;
border-right-width: 2px;
border-right-color: #26c6f0;
border-right-style: solid;
position: absolute;
top: -2px;
right: -2px
}
.bottomL {
width: 10px;
height: 10px;
border-bottom-width: 2px;
border-bottom-color: #26c6f0;
border-bottom-style: solid;
border-left-width: 2px;
border-left-color: #26c6f0;
border-left-style: solid;
position: absolute;
bottom: -2px;
left: -2px
}
.bottomR {
width: 10px;
height: 10px;
border-bottom-width: 2px;
border-bottom-color: #26c6f0;
border-bottom-style: solid;
border-right-width: 2px;
border-right-color: #26c6f0;
border-right-style: solid;
position: absolute;
bottom: -2px;
right: -2px
}
/* 卡片头部样式 */
/* .card-header {
height: 40px;
background: url('/assets/img/common/homeTitle2.png') no-repeat;
background-position: center;
background-size: 100% 100%;
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 0px -20px;
}
.card-header span {
font-size: 1.2rem;
letter-spacing: 1px;
font-family: 'YouSheBiaoTiHei', 'Microsoft YaHei';
font-weight: 400;
color: #ffffff;
} */
</style>
</head>
<body>
<div class="topDiv">
<div class="top-header">
<div class="logo-container">
<!-- 这里应该放置实际的logo图片 -->
<img src="/common/images/logo_gt.png" alt="Logo">
</div>
<div class="system-title">科考任务综合管理系统</div>
<div class="header-right"> <i class="fa fa-ship"></i>
科考任务天数24
<!-- <div class="notification-button">
<button class="text-white hover:text-blue-300 transition-colors relative">
<i class="fa fa-bell text-xl"></i>
<span
class="absolute -top-1 -right-1 bg-danger text-white text-xs rounded-full w-4 h-4 flex items-center justify-center">2</span>
</button>
</div> -->
<!-- <div class="user-info-container">
<div class="user-info-text">
<div class="text-sm"> <i class="fa fa-ship"></i>
科考任务天数</div>
<div class="text-sm">24</div>
</div>
</div> -->
</div>
</div>
</div>
<!-- 侧边栏 -->
<aside class="sidebar">
<ul>
<li><a href="#" class="active" data-page="home"><i class="fa fa-home"></i> <span>主页</span></a></li>
<li><a href="#" data-page="history"><i class="fa fa-history"></i> <span>历史查询</span></a></li>
<li><a href="#" data-page="voice"><i class="fa fa-microphone"></i> <span>语音通信</span></a></li>
<li><a href="#" data-page="video"><i class="fa fa-video-camera"></i> <span>视频监控</span></a></li>
<li><a href="#" data-page="settings"><i class="fa fa-cog"></i> <span>设置</span></a></li>
</ul>
</aside>
<!-- 主内容区域 -->
<div class="main-content">
<div class="container">
<!-- 主页内容 -->
<div id="home-page">
<!-- 第一行:天气现象及能见度仪曲线图 与 自动气象仪 -->
<div class="row" style="grid-template-columns: 1fr 3fr;">
<!-- 天气现象及能见度仪曲线图 -->
<div class="module-card">
<h3 class="module-title"><i class="fa fa-cloud"></i> 天气现象及能见度仪曲线图</h3>
<div class="chart-container">
<canvas id="weatherChart"></canvas>
</div>
</div>
<!-- 自动气象仪 -->
<div class="module-card" style="display: flex; flex-direction: column;">
<h3 class="module-title"><i class="fa fa-thermometer-half"></i> 自动气象仪</h3>
<div class="row" style="flex: 1;grid-template-columns: 2fr 1fr;margin: 0;">
<div class="situation-chart-container" style="grid-template-columns: repeat(4, 1fr);">
<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">25.79 ℃</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">60 %</div>
</div>
</div>
</div>
</div>
<div class="situation-chart">
<div class="situation-title">气压</div>
<div class="wave-direction-container">
<div class="wave-direction-indicator" id="humChart">
</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">1013 hPa</div>
</div>
</div>
</div>
</div>
</div>
<div class="data-grid" style="grid-template-columns: repeat(4, 1fr);">
<div class="data-item" style="position: relative;">
<i class="topL"></i>
<i class="topR"></i>
<i class="bottomL"></i>
<i class="bottomR"></i>
<div class="data-label">平均航速</div>
<div class="data-value">15.2 节</div>
</div>
<div class="data-item" style="position: relative;">
<i class="topL"></i>
<i class="topR"></i>
<i class="bottomL"></i>
<i class="bottomR"></i>
<div class="data-label">积累雨量</div>
<div class="data-value">63.35 mm</div>
</div>
<div class="data-item" style="position: relative;">
<i class="topL"></i>
<i class="topR"></i>
<i class="bottomL"></i>
<i class="bottomR"></i>
<div class="data-label">可见光云量</div>
<div class="data-value">14.9%</div>
</div>
<div class="data-item" style="position: relative;">
<i class="topL"></i>
<i class="topR"></i>
<i class="bottomL"></i>
<i class="bottomR"></i>
<div class="data-label">第一层云高</div>
<div class="data-value">257 m</div>
</div>
<div class="data-item" style="position: relative;">
<i class="topL"></i>
<i class="topR"></i>
<i class="bottomL"></i>
<i class="bottomR"></i>
<div class="data-label">第一层云厚</div>
<div class="data-value">33 m</div>
</div>
<div class="data-item" style="position: relative;">
<i class="topL"></i>
<i class="topR"></i>
<i class="bottomL"></i>
<i class="bottomR"></i>
<div class="data-label">雨强</div>
<div class="data-value">20.718 mm</div>
</div>
<div class="data-item" style="position: relative;">
<i class="topL"></i>
<i class="topR"></i>
<i class="bottomL"></i>
<i class="bottomR"></i>
<div class="data-label">红外云量</div>
<div class="data-value">9.1%</div>
</div>
<div class="data-item" style="position: relative;">
<i class="topL"></i>
<i class="topR"></i>
<i class="bottomL"></i>
<i class="bottomR"></i>
<div class="data-label">第二层云高</div>
<div class="data-value">1286 m</div>
</div>
<div class="data-item" style="position: relative;">
<i class="topL"></i>
<i class="topR"></i>
<i class="bottomL"></i>
<i class="bottomR"></i>
<div class="data-label">第二层云厚</div>
<div class="data-value">16 m</div>
</div>
<div class="data-item" style="position: relative;">
<i class="topL"></i>
<i class="topR"></i>
<i class="bottomL"></i>
<i class="bottomR"></i>
<div class="data-label">1分钟能见度</div>
<div class="data-value">5293 m</div>
</div>
<div class="data-item" style="position: relative;">
<i class="topL"></i>
<i class="topR"></i>
<i class="bottomL"></i>
<i class="bottomR"></i>
<div class="data-label">综合云量</div>
<div class="data-value">17.3 %</div>
</div>
<div class="data-item" style="position: relative;">
<i class="topL"></i>
<i class="topR"></i>
<i class="bottomL"></i>
<i class="bottomR"></i>
<div class="data-label">云底高</div>
<div class="data-value">257 m</div>
</div>
</div>
</div>
</div>
</div>
<!-- 第二行:激光测风雷达、风廓线雷达、测波雷达、水质测量仪 -->
<div class="row-second">
<!-- 修改激光测风雷达模块 -->
<div class="module-card">
<h3 class="module-title"><i class="fa fa-dot-circle-o"></i> 激光测风雷达</h3>
<div class="chart-container">
<div id="windRadarChart" style="width: 100%; height: 100%;">
<div class="loading"
style="display: flex; flex-direction: column; align-items: center; justify-content: center; height: 100%;">
<div class="spinner"
style="border: 4px solid #f3f3f3; border-top: 4px solid #3498db; border-radius: 50%; width: 40px; height: 40px; animation: spin 2s linear infinite; margin-bottom: 15px;">
</div>
<div>风向杆图表加载中...</div>
</div>
</div>
</div>
</div>
<!-- 风廓线雷达 -->
<div class="module-card">
<h3 class="module-title"><i class="fa fa-circle-o"></i> 风廓线雷达</h3>
<div class="chart-container">
<canvas id="fanLineChart"></canvas>
</div>
</div>
<!-- 测波雷达和水质测量仪容器 -->
<div class="combined-modules">
<!-- 测波雷达 -->
<div class="module-card">
<h3 class="module-title"><i class="fa fa-tint"></i> 测波雷达</h3>
<div class="wave-data-grid" style="gap: 20px;">
<div class="wave-data-item">
<div class="wave-data-label">最大波高</div>
<div class="wave-data-value">0.26 m</div>
</div>
<div class="wave-data-item">
<div class="wave-data-label">最大波高周期</div>
<div class="wave-data-value">2.75 s</div>
</div>
<div class="wave-data-item">
<div class="wave-data-label">1/10波高</div>
<div class="wave-data-value">0.2 m</div>
</div>
<div class="wave-data-item">
<div class="wave-data-label">1/10波高周期</div>
<div class="wave-data-value">3.81 s</div>
</div>
<div class="wave-data-item">
<div class="wave-data-label">有效波高</div>
<div class="wave-data-value">0.16 m</div>
</div>
<div class="wave-data-item">
<div class="wave-data-label">有效波高周期</div>
<div class="wave-data-value">3.15 s</div>
</div>
<div class="wave-data-item">
<div class="wave-data-label">平均波高</div>
<div class="wave-data-value">0.1 m</div>
</div>
<div class="wave-data-item">
<div class="wave-data-label">平均波高周期</div>
<div class="wave-data-value">2.18 s</div>
</div>
<div class="wave-data-item">
<div class="wave-data-label">皮向</div>
<div class="wave-data-value">82 Deg</div>
</div>
</div>
</div>
<!-- 水质测量仪 -->
<div class="module-card" style="display: flex; flex-direction: column;">
<h3 class="module-title"><i class="fa fa-flask"></i> 水质测量仪</h3>
<div class="water-data-grid" style="flex: 1;">
<div class="water-data-item">
<div class="water-data-label">温度</div>
<div class="water-data-value">23.65 °C</div>
</div>
<div class="water-data-item">
<div class="water-data-label">浊度</div>
<div class="water-data-value">335.43 NTU</div>
</div>
<div class="water-data-item">
<div class="water-data-label">盐度</div>
<div class="water-data-value">0.2 ppt</div>
</div>
<div class="water-data-item">
<div class="water-data-label">电导率</div>
<div class="water-data-value">0.5094 mS/cm</div>
</div>
<div class="water-data-item">
<div class="water-data-label">溶解氧</div>
<div class="water-data-value">6.72 mg</div>
</div>
<div class="water-data-item">
<div class="water-data-label">PH</div>
<div class="water-data-value">7.53</div>
</div>
<div class="water-data-item">
<div class="water-data-label">蓝绿藻</div>
<div class="water-data-value">297.33 ug/L</div>
</div>
<div class="water-data-item">
<div class="water-data-label">叶绿素-a</div>
<div class="water-data-value">2.68 ug/L</div>
</div>
</div>
</div>
</div>
</div>
<!-- 第三行:海图显示、激光光阵雨滴谱仪/大气相干长度测量仪组合、ADCP、视频监控 -->
<div class="row">
<!-- 海图显示 -->
<div class="module-card" style="display: flex; flex-direction: column; height: 100%">
<h3 class="module-title"><i class="fa fa-map"></i> 海图显示</h3>
<div class="moule-img"
style="flex: 1; height: 100%; border-radius: 5px; display: flex; align-items: center; justify-content: center;">
<!-- <p>海图显示区域</p> -->
</div>
</div>
<!-- 激光光阵雨滴谱仪和大气相干长度测量仪组合 -->
<div class="module-card" style="display: flex; flex-direction: column; gap: 15px;">
<!-- 激光光阵雨滴谱仪 -->
<div style="flex: 1;">
<h3 class="module-title"><i class="fa fa-cloud-download"></i> 激光光阵雨滴谱仪</h3>
<div class="data-grid" style="grid-template-columns: repeat(2, 1fr);">
<div class="data-item" style="position: relative;">
<i class="topL"></i>
<i class="topR"></i>
<i class="bottomL"></i>
<i class="bottomR"></i>
<div class="data-label">天气</div>
<div class="data-value">小雨</div>
</div>
<div class="data-item" style="position: relative;">
<i class="topL"></i>
<i class="topR"></i>
<i class="bottomL"></i>
<i class="bottomR"></i>
<div class="data-label">更新时间</div>
<div class="data-value">2023-08-15 14:30:25</div>
</div>
</div>
</div>
<!-- 大气相干长度测量仪 -->
<div style="flex: 1; margin-top: 10px; padding-top: 10px; border-top: 1px solid rgba(64, 156, 255, 0.3);">
<h3 class="module-title"><i class="fa fa-eye"></i> 大气相干长度测量仪</h3>
<div class="data-grid">
<div class="data-item" style="position: relative;">
<i class="topL"></i>
<i class="topR"></i>
<i class="bottomL"></i>
<i class="bottomR"></i>
<div class="data-label">大气相干长度</div>
<div class="data-value">0.020323 cm</div>
</div>
</div>
</div>
</div>
<!-- ADCP -->
<div class="module-card">
<h3 class="module-title"><i class="fa fa-table"></i> ADCP</h3>
<table>
<thead>
<tr>
<th>深度(m)</th>
<th>大小(m/s)</th>
<th>方向(Deg)</th>
<th>流速E(m/s)</th>
<th>流速N(m/s)</th>
<th>流速U(m/s)</th>
</tr>
</thead>
<tbody>
<tr>
<td>10</td>
<td>0.25</td>
<td>180</td>
<td>-0.25</td>
<td>0.00</td>
<td>0.05</td>
</tr>
<tr>
<td>20</td>
<td>0.30</td>
<td>190</td>
<td>-0.29</td>
<td>-0.05</td>
<td>0.08</td>
</tr>
<tr>
<td>30</td>
<td>0.35</td>
<td>200</td>
<td>-0.33</td>
<td>-0.12</td>
<td>0.12</td>
</tr>
<tr>
<td>40</td>
<td>0.40</td>
<td>210</td>
<td>-0.35</td>
<td>-0.20</td>
<td>0.15</td>
</tr>
<tr>
<td>50</td>
<td>0.45</td>
<td>220</td>
<td>-0.34</td>
<td>-0.29</td>
<td>0.18</td>
</tr>
</tbody>
</table>
</div>
<!-- 视频监控模块 -->
<div class="module-card" style="display: flex; flex-direction: column; height: 100%">
<h3 class="module-title"><i class="fa fa-video-camera"></i> 视频监控</h3>
<div class="video-item" style="flex: 1;">
<div class="video-placeholder">
<!-- <i class="fa fa-video-camera fa-3x"></i> -->
</div>
<p>主甲板摄像头</p>
</div>
</div>
</div>
<!--
<div class="status">
<div class="status-item">
<i class="fa fa-signal"></i>
<div class="status-value">98%</div>
<div class="status-label">系统运行正常</div>
</div>
<div class="status-item">
<i class="fa fa-ship"></i>
<div class="status-value">24</div>
<div class="status-label">科考任务天数</div>
</div>
<div class="status-item">
<i class="fa fa-tachometer"></i>
<div class="status-value">15.2节</div>
<div class="status-label">平均航速</div>
</div>
<div class="status-item">
<i class="fa fa-thermometer-half"></i>
<div class="status-value">18.5°C</div>
<div class="status-label">海水表面温度</div>
</div>
</div> -->
<!--
<footer>
<p>科考任务综合管理系统 © 2023 国家海洋科学考察中心 | 当前版本: v2.5.1</p>
</footer> -->
</div>
<!-- 历史查询页面 -->
<div id="history-page" class="hidden">
<h2 class="section-title">历史查询</h2>
<div class="module-card">
<h3 class="module-title"><i class="fa fa-history"></i> 历史数据查询</h3>
<div class="data-grid">
<div class="data-item">
<div class="data-label">查询时间范围</div>
<div class="data-value">2023-08-01 至 2023-08-15</div>
</div>
<div class="data-item">
<div class="data-label">数据类型</div>
<div class="data-value">气象数据</div>
</div>
<div class="data-item">
<div class="data-label">查询结果</div>
<div class="data-value">1,250 条记录</div>
</div>
</div>
<div
style="margin-top: 20px; height: 300px; background: rgba(25, 55, 95, 0.6); border-radius: 5px; display: flex; align-items: center; justify-content: center;">
<p>历史数据图表展示区域</p>
</div>
</div>
</div>
<!-- 语音通信页面 -->
<div id="voice-page" class="hidden">
<h2 class="section-title">语音通信</h2>
<div class="module-card">
<h3 class="module-title"><i class="fa fa-microphone"></i> 语音通信系统</h3>
<div class="data-grid">
<div class="data-item">
<div class="data-label">通信状态</div>
<div class="data-value">正常</div>
</div>
<div class="data-item">
<div class="data-label">当前频道</div>
<div class="data-value">CH-08</div>
</div>
<div class="data-item">
<div class="data-label">信号强度</div>
<div class="data-value">-75 dBm</div>
</div>
</div>
<div style="margin-top: 20px; padding: 20px; background: rgba(25, 55, 95, 0.6); border-radius: 5px;">
<h4>通信记录</h4>
<ul style="margin-top: 10px; list-style: none;">
<li style="padding: 5px 0; border-bottom: 1px solid rgba(64, 156, 255, 0.3);">[14:25] 船长: 报告当前航向和速度</li>
<li style="padding: 5px 0; border-bottom: 1px solid rgba(64, 156, 255, 0.3);">[14:26] 大副: 航向185度速度12.5节
</li>
<li style="padding: 5px 0; border-bottom: 1px solid rgba(64, 156, 255, 0.3);">[14:30] 科考队长: 请求调整航向至目标站点
</li>
</ul>
</div>
</div>
</div>
<!-- 视频监控页面 -->
<div id="video-page" class="hidden">
<h2 class="section-title">视频监控</h2>
<div class="video-container">
<div class="video-item">
<div class="video-placeholder">
<i class="fa fa-video-camera fa-3x"></i>
</div>
<p>主甲板摄像头 - 实时</p>
</div>
<div class="video-item">
<div class="video-placeholder">
<i class="fa fa-video-camera fa-3x"></i>
</div>
<p>实验室监控 - 实时</p>
</div>
<div class="video-item">
<div class="video-placeholder">
<i class="fa fa-video-camera fa-3x"></i>
</div>
<p>驾驶台监控 - 实时</p>
</div>
<div class="video-item">
<div class="video-placeholder">
<i class="fa fa-video-camera fa-3x"></i>
</div>
<p>水下摄像头 - 实时</p>
</div>
</div>
<div class="module-card" style="margin-top: 20px;">
<h3 class="module-title"><i class="fa fa-history"></i> 视频回放</h3>
<div class="data-grid">
<div class="data-item">
<div class="data-label">回放时间</div>
<div class="data-value">2023-08-14 10:00</div>
</div>
<div class="data-item">
<div class="data-label">摄像头</div>
<div class="data-value">主甲板</div>
</div>
<div class="data-item">
<div class="data-label">时长</div>
<div class="data-value">2小时35分钟</div>
</div>
</div>
</div>
</div>
<!-- 设置页面 -->
<div id="settings-page" class="hidden">
<h2 class="section-title">系统设置</h2>
<div class="module-grid">
<div class="module-card">
<h3 class="module-title"><i class="fa fa-user-circle"></i> 用户设置</h3>
<div class="data-grid">
<div class="data-item">
<div class="data-label">用户名</div>
<div class="data-value">张海洋</div>
</div>
<div class="data-item">
<div class="data-label">角色</div>
<div class="data-value">科考队长</div>
</div>
</div>
</div>
<div class="module-card">
<h3 class="module-title"><i class="fa fa-sliders"></i> 系统参数</h3>
<div class="data-grid">
<div class="data-item">
<div class="data-label">数据刷新频率</div>
<div class="data-value">5 秒</div>
</div>
<div class="data-item">
<div class="data-label">报警阈值</div>
<div class="data-value">可配置</div>
</div>
</div>
</div>
</div>
<div class="module-card">
<h3 class="module-title"><i class="fa fa-cog"></i> 设备配置</h3>
<div class="data-grid">
<div class="data-item">
<div class="data-label">气象站</div>
<div class="data-value">已连接</div>
</div>
<div class="data-item">
<div class="data-label">ADCP</div>
<div class="data-value">已连接</div>
</div>
<div class="data-item">
<div class="data-label">水质仪</div>
<div class="data-value">已连接</div>
</div>
<div class="data-item">
<div class="data-label">测波雷达</div>
<div class="data-value">已连接</div>
</div>
</div>
</div>
</div>
</div>
</div>
<script>
// 设置当前日期和时间
function updateDateTime() {
const now = new Date();
const dateStr = now.toLocaleDateString('zh-CN', {
year: 'numeric',
month: 'long',
day: 'numeric',
weekday: 'long'
});
const timeStr = now.toLocaleTimeString('zh-CN', {
hour: '2-digit',
minute: '2-digit',
second: '2-digit'
});
document.getElementById('current-date').textContent = dateStr;
document.getElementById('current-time').textContent = timeStr;
}
// updateDateTime();
// setInterval(updateDateTime, 1000);
// 页面切换功能
document.querySelectorAll('.sidebar a').forEach(link => {
link.addEventListener('click', function (e) {
e.preventDefault();
// 移除所有活动状态
document.querySelectorAll('.sidebar a').forEach(item => {
item.classList.remove('active');
});
// 添加当前活动状态
this.classList.add('active');
// 隐藏所有页面
document.querySelectorAll('#home-page, #history-page, #voice-page, #video-page, #settings-page').forEach(page => {
page.classList.add('hidden');
});
// 显示对应页面
const page = this.getAttribute('data-page');
document.getElementById(`${page}-page`).classList.remove('hidden');
});
});
// 天气现象及能见度仪曲线图
const weatherCtx = document.getElementById('weatherChart').getContext('2d');
const weatherChart = new Chart(weatherCtx, {
type: 'line',
data: {
labels: ['00:00', '04:00', '08:00', '12:00', '16:00', '20:00'],
datasets: [{
label: '能见度 (m)',
data: [5000, 4800, 5200, 4900, 5100, 5300],
borderColor: '#40a9ff',
backgroundColor: 'rgba(64, 169, 255, 0.1)',
tension: 0.4,
fill: true
}]
},
options: {
responsive: true,
maintainAspectRatio: false,
plugins: {
legend: {
labels: {
color: '#e0f0ff'
}
}
},
scales: {
y: {
ticks: {
color: '#a0d2ff'
},
grid: {
color: 'rgba(64, 156, 255, 0.2)'
}
},
x: {
ticks: {
color: '#a0d2ff'
},
grid: {
color: 'rgba(64, 156, 255, 0.2)'
}
}
}
}
});
// 风廓线雷达
const fanLineCtx = document.getElementById('fanLineChart').getContext('2d');
const fanLineChart = new Chart(fanLineCtx, {
type: 'line',
data: {
labels: ['0m', '50m', '100m', '150m', '200m', '250m'],
datasets: [{
label: '风速剖面 (m/s)',
data: [3, 4.5, 6, 7.2, 8, 8.5],
borderColor: '#40a9ff',
backgroundColor: 'rgba(64, 169, 255, 0.1)',
tension: 0.4,
fill: true
}]
},
options: {
responsive: true,
maintainAspectRatio: false,
plugins: {
legend: {
labels: {
color: '#e0f0ff'
}
}
},
scales: {
y: {
ticks: {
color: '#a0d2ff'
},
grid: {
color: 'rgba(64, 156, 255, 0.2)'
}
},
x: {
ticks: {
color: '#a0d2ff'
},
grid: {
color: 'rgba(64, 156, 255, 0.2)'
}
}
}
}
});
// 风向和波高态势图更新函数
function updateSituationCharts() {
// 随机更新风向0-360度
var windDirection = Math.floor(Math.random() * 360);
var windArrow = document.getElementById('windArrow');
if (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;
var windDirectionValue = document.getElementById('windDirectionValue');
if (windDirectionValue) {
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');
// if (windSpeedFill && 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';
// } else if (windSpeed < 15) {
// windSpeedFill.className = 'wind-speed-fill';
// } else {
// windSpeedFill.className = 'wind-speed-fill';
// }
// }
// // 随机更新波高0.5-5 m
// var waveHeight = 0.5 + Math.random() * 4.5;
// var waveHeightFill = document.getElementById('waveHeightFill');
// var waveHeightValue = document.getElementById('waveHeightValue');
// if (waveHeightFill && waveHeightValue) {
// // 波高填充高度最大5 m对应100%
// var waveFillHeight = (waveHeight / 5) * 100;
// waveHeightFill.style.height = waveFillHeight + '%';
// waveHeightValue.textContent = waveHeight.toFixed(1) + 'm';
// }
// // 随机更新波向0-360度
// var waveDirection = Math.floor(Math.random() * 360);
// var waveDirectionArrow = document.getElementById('waveDirectionArrow');
// var waveDirectionValue = document.getElementById('waveDirectionValue');
// if (waveDirectionArrow) {
// waveDirectionArrow.style.transform = 'translate(-50%, -100%) rotate(' + waveDirection + 'deg)';
// }
// if (waveDirectionValue) {
// var waveDirectionText = directions[Math.round(waveDirection / 22.5) % 16];
// waveDirectionValue.textContent = waveDirectionText + ' ' + waveDirection + '°';
// }
}
// 气压图表初始化函数
function initPressureChart() {
const humChartCtx = document.getElementById('humChart');
if (!humChartCtx) return;
const humChart = echarts.init(humChartCtx);
const humOptions = {
// 仪表盘系列配置(多个同心圆组成复合仪表盘)
series: [
// 第1个系列最内层红色圆环装饰用
{
type: 'gauge', // 类型为仪表盘
center: ['50%', '60%'], // 中心位置水平50%垂直60%
radius: '30%', // 半径占容器30%
min: 950, // 最小值
max: 1050, // 最大值
startAngle: 270, // 起始角度12点钟方向为0度
endAngle: -89.99999, // 结束角度形成270度的圆弧
splitNumber: 5, // 减少分割段数从10减少到5
axisLine: {
lineStyle: {
color: [[1, '#ff4500']], // 轴线颜色(红色)
width: 0, // 轴线宽度0表示不显示
shadowColor: '#fff', // 阴影颜色
shadowBlur: 10 // 阴影模糊大小
}
},
axisLabel: { show: false }, // 不显示刻度标签
axisTick: {
length: 4, // 刻度线长度
lineStyle: { color: 'rgba(176,204,53,.5)' } // 刻度线颜色(半透明绿色)
},
splitLine: { show: false }, // 不显示分割线
pointer: {
width: 0, // 指针宽度0表示不显示
shadowColor: '#fff', // 指针阴影颜色
shadowBlur: 5 // 指针阴影模糊大小
},
detail: { show: false } // 不显示详情
},
// 第2个系列中层灰色圆环装饰用
{
name: '气压', // 系列名称
type: 'gauge',
center: ['50%', '60%'],
radius: '60%', // 半径比内层大
min: 950,
max: 1050,
splitNumber: 5, // 减少分割段数从10减少到5
axisLine: {
lineStyle: {
color: [[1, '#037592']], // 轴线颜色(深灰色)
width: 8, // 轴线宽度
shadowBlur: 10 // 阴影模糊
}
},
axisLabel: {
textStyle: {
fontWeight: '',
color: 'rgba(30,144,255,0.3)', // 调整刻度数字颜色,降低透明度使其更清晰可见
shadowColor: '#fff',
shadowBlur: 10,
fontSize: 8 // 调整字体大小
},
distance: 0 // 调整标签距离
},
axisTick: {
length: 2, // 刻度线长度
lineStyle: { color: 'auto' } // 自动颜色
},
splitLine: {
length: 0, // 分割线长度0表示不显示
lineStyle: {
width: 0,
color: '#fff',
shadowColor: '#fff',
shadowBlur: 10
}
},
pointer: {
width: 0, // 不显示指针
shadowColor: '#fff',
shadowBlur: 5
},
detail: { show: false } // 不显示详情
},
// 第3个系列最外层主仪表盘显示红色指针
{
type: 'gauge',
center: ['50%', '60%'],
radius: '100%', // 最大半径(占满容器)
min: 950,
max: 2000,
name: '气压', // 系列名称(用于提示框显示)
splitNumber: 5, // 减少分割段数从10减少到5
axisLine: {
lineStyle: {
color: [[1, '#55D0D4']], // 轴线颜色(浅灰色)
width: 1 // 轴线宽度
}
},
itemStyle: {
normal: {
color: '#55D0D4' // 数据项颜色
}
},
axisTick: { length: 3 }, // 刻度线长度
axisLabel: {
textStyle: {
fontWeight: 'bolder', // 加粗字体
fontSize: 8, // 调整字体大小从10减小到8
fontFamily: 'Arial', // 字体
color: 'rgba(224, 240, 255, 0.8)' // 调整刻度数字颜色,使用半透明的浅色
},
distance: 2 // 调整标签距离
},
splitLine: {
length: 5, // 分割线长度
lineStyle: { width: 1 } // 分割线宽度
},
pointer: {
width: 3, // 指针宽度
length: '90%', // 指针长度(相对半径)
itemStyle: {
color: '#FF0000' // 指针颜色(红色)
}
},
detail: {
show: false,
formatter: '{value} hPa',
offsetCenter: [0, '80%'],
textStyle: {
fontSize: 14, // 稍微减小字体大小
color: '#e0f0ff'
}
}, // 显示详情
data: [{ value: 1013.2 }] // 绑定气压数据
}
]
};
humChart.setOption(humOptions);
// 添加窗口大小调整事件监听
window.addEventListener('resize', function () {
humChart.resize();
});
}
// 页面加载完成后初始化态势图
document.addEventListener('DOMContentLoaded', function () {
updateSituationCharts();
initPressureChart();
// 每5秒更新一次态势图数据
setInterval(updateSituationCharts, 5000);
});
</script>
<style>
.loading {
text-align: center;
padding: 50px;
font-size: 18px;
color: #666;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
height: 100%;
}
.spinner {
border: 4px solid #f3f3f3;
border-top: 4px solid #3498db;
border-radius: 50%;
width: 40px;
height: 40px;
animation: spin 2s linear infinite;
margin-bottom: 15px;
}
@keyframes spin {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
}
.wind-barb-legend {
display: flex;
justify-content: center;
flex-wrap: wrap;
gap: 15px;
margin: 10px 0;
font-size: 11px;
}
.legend-item {
text-align: center;
}
.legend-barb {
display: inline-block;
margin-bottom: 3px;
}
</style>
<script>
// 在页面加载完成后初始化风向杆图表
document.addEventListener('DOMContentLoaded', function () {
// 等待一段时间确保echarts加载完成
setTimeout(initWindBarbChart, 500);
});
function initWindBarbChart() {
const chartDom = document.getElementById('windRadarChart');
// 检查echarts是否已加载
if (typeof echarts === 'undefined') {
chartDom.innerHTML = `
<div class="loading">
<div style="color: #e74c3c; font-size: 24px;">⚠️</div>
<div>ECharts库加载失败</div>
<div style="font-size: 12px; margin-top: 10px;">请检查网络连接或刷新页面重试</div>
</div>
`;
return;
}
// 显示加载状态
chartDom.innerHTML = `
<div class="loading">
<div class="spinner"></div>
<div>正在生成风向杆数据...</div>
</div>
`;
// 延迟一小段时间后渲染图表,模拟数据加载
setTimeout(() => {
const myChart = echarts.init(chartDom);
// 风速颜色映射(与"风向杆.html"保持一致)
const windSpeedColors = [
{ min: 0, max: 2, color: '#98FB98', label: '0-2 m/s' }, // 浅绿色 - 微风
{ min: 2, max: 5, color: '#7EC8E3', label: '2-5 m/s' }, // 浅蓝色 - 轻风
{ min: 5, max: 10, color: '#FFD700', label: '5-10 m/s' }, // 黄色 - 和风
{ min: 10, max: 15, color: '#FFA500', label: '10-15 m/s' }, // 橙色 - 清风
{ min: 15, max: 20, color: '#FF6347', label: '15-20 m/s' }, // 番茄红 - 强风
{ min: 20, max: 25, color: '#DC143C', label: '20-25 m/s' }, // 深红 - 大风
{ min: 25, max: 50, color: '#8B0000', label: '25-50 m/s' } // 暗红 - 狂风
];
// 根据风速获取颜色
function getColorForWindSpeed(speed) {
for (const range of windSpeedColors) {
if (speed >= range.min && speed < range.max) {
return range.color;
}
}
return windSpeedColors[windSpeedColors.length - 1].color; // 默认返回最高风速颜色
}
// 绘制风矢杆
function drawWindBarb(ctx, direction, speed, barbLength, isExample = false) {
const radian = (direction - 180) * Math.PI / 180; // 指向风的来向
// 根据风速获取颜色
const color = getColorForWindSpeed(speed);
ctx.strokeStyle = color;
ctx.fillStyle = color;
ctx.lineWidth = 1.5;
ctx.lineCap = 'round';
if (speed === 0) {
// 静风 - 画圆圈
ctx.beginPath();
ctx.arc(0, 0, 4, 0, 2 * Math.PI);
ctx.stroke();
return;
}
// 绘制主杆
ctx.beginPath();
ctx.moveTo(0, 0);
const endX = Math.cos(radian) * barbLength;
const endY = Math.sin(radian) * barbLength;
ctx.lineTo(endX, endY);
ctx.stroke();
// 绘制风羽
let remainingSpeed = speed;
let position = 0;
const spacing = isExample ? 6 : 4;
// 绘制三角旗 (20 m/s)
const triangles = Math.floor(remainingSpeed / 20);
remainingSpeed %= 20;
for (let i = 0; i < triangles; i++) {
const posX = Math.cos(radian) * (position * spacing);
const posY = Math.sin(radian) * (position * spacing);
const perpendicular = radian + Math.PI / 2;
const triangleSize = isExample ? 8 : 6;
ctx.beginPath();
ctx.moveTo(posX, posY);
ctx.lineTo(
posX + Math.cos(perpendicular) * triangleSize,
posY + Math.sin(perpendicular) * triangleSize
);
ctx.lineTo(
posX + Math.cos(radian) * triangleSize + Math.cos(perpendicular) * triangleSize,
posY + Math.sin(radian) * triangleSize + Math.sin(perpendicular) * triangleSize
);
ctx.closePath();
ctx.fill();
position += 2;
}
// 绘制长羽 (4 m/s)
const longFeathers = Math.floor(remainingSpeed / 4);
remainingSpeed %= 4;
for (let i = 0; i < longFeathers; i++) {
const posX = Math.cos(radian) * (position * spacing);
const posY = Math.sin(radian) * (position * spacing);
const perpendicular = radian + Math.PI / 2;
const featherLength = isExample ? 10 : 8;
ctx.beginPath();
ctx.moveTo(posX, posY);
ctx.lineTo(
posX + Math.cos(perpendicular) * featherLength,
posY + Math.sin(perpendicular) * featherLength
);
ctx.stroke();
position += 1;
}
// 绘制短羽 (2 m/s)
const shortFeathers = Math.floor(remainingSpeed / 2);
for (let i = 0; i < shortFeathers; i++) {
const posX = Math.cos(radian) * (position * spacing);
const posY = Math.sin(radian) * (position * spacing);
const perpendicular = radian + Math.PI / 2;
const featherLength = isExample ? 6 : 5;
ctx.beginPath();
ctx.moveTo(posX, posY);
ctx.lineTo(
posX + Math.cos(perpendicular) * featherLength,
posY + Math.sin(perpendicular) * featherLength
);
ctx.stroke();
position += 1;
}
}
// 生成精确数据
function generateData() {
const times = [];
const heights = [];
const data = [];
// 生成时间序列12个时间点
const now = new Date();
for (let i = 11; i >= 0; i--) {
const time = new Date(now.getTime() - i * 2 * 60 * 60 * 1000);
times.push(time.toLocaleTimeString('zh-CN', { hour: '2-digit', minute: '2-digit' }));
}
// 生成高度序列从250m到3850m每240m一个点
for (let h = 250; h <= 3850; h += 240) {
heights.push(h);
}
// 根据要求生成精确的风向风速数据
for (let i = 0; i < times.length; i++) {
for (let j = 0; j < heights.length; j++) {
const height = heights[j];
let direction, speed;
// 根据高度设置风向风速
if (height === 250) {
// 250m: 东南风135°, 14m/s (3个长羽1个短羽)
direction = 135;
speed = 14;
} else if (height === 490) {
// 490m: 西北风315°, 16m/s (1个长羽)
direction = 315;
speed = 16;
} else if (height >= 730 && height <= 2170) {
// 730m至2170m: 东北风45°, 8m/s (1个长羽1个短羽)
direction = 45;
speed = 8;
} else if (height >= 2410 && height <= 3850) {
// 2410m至3850m: 东风90°, 45m/s (2个三角旗1个长羽1个短羽)
direction = 90;
speed = 45;
} else {
// 其他高度使用默认数据
const directions = [0, 45, 90, 135, 180, 225, 270, 315];
direction = directions[Math.floor(Math.random() * directions.length)];
speed = Math.floor(Math.random() * 20) + 5;
}
data.push([i, j, direction, speed]);
}
}
return { times, heights, data };
}
// 渲染风矢杆项目
function renderWindBarb(params, api) {
const xIndex = api.value(0);
const yIndex = api.value(1);
const direction = api.value(2);
const speed = api.value(3);
const point = api.coord([xIndex, yIndex]);
const barbLength = 25; // 风矢杆长度
const group = {
type: 'group',
children: [],
silent: false
};
// 创建canvas绘制风矢杆
const canvas = document.createElement('canvas');
canvas.width = 60;
canvas.height = 60;
const ctx = canvas.getContext('2d');
ctx.translate(30, 30);
drawWindBarb(ctx, direction, speed, barbLength);
group.children.push({
type: 'image',
style: {
image: canvas,
x: point[0] - 30,
y: point[1] - 30,
width: 60,
height: 60
}
});
return group;
}
// 获取风向文本描述
function getDirectionText(direction) {
const directions = ['北', '东北', '东', '东南', '南', '西南', '西', '西北'];
const index = Math.round(direction / 45) % 8;
return directions[index];
}
// 获取风羽描述
function getWindBarbDescription(speed) {
if (speed === 0) return '静风';
let description = '风羽: ';
let remaining = speed;
const triangles = Math.floor(remaining / 20);
remaining %= 20;
if (triangles > 0) description += `${triangles}个三角旗 `;
const longFeathers = Math.floor(remaining / 4);
remaining %= 4;
if (longFeathers > 0) description += `${longFeathers}个长羽 `;
const shortFeathers = Math.floor(remaining / 2);
if (shortFeathers > 0) description += `${shortFeathers}个短羽`;
return description.trim();
}
const { times, heights, data } = generateData();
const option = {
title: {
text: '激光测风雷达风向杆图',
left: 'center',
textStyle: {
fontSize: 14,
fontWeight: 'bold',
color: '#e0f0ff'
}
},
tooltip: {
trigger: 'item',
backgroundColor: 'rgba(0, 0, 0, 0.8)',
borderColor: '#40a9ff',
borderWidth: 1,
textStyle: {
color: '#e0f0ff'
},
formatter: function (params) {
const time = times[params.value[0]];
const height = heights[params.value[1]];
const direction = params.value[2];
const speed = params.value[3];
const directionText = getDirectionText(direction);
const barbDescription = getWindBarbDescription(speed);
const colorLabel = windSpeedColors.find(range => speed >= range.min && speed < range.max)?.label || '未知';
return `
<div style="font-weight: bold; margin-bottom: 5px;">${time}</div>
<div>高度: <b>${height}m</b></div>
<div>风向: <b>${Math.round(direction)}° ${directionText}</b></div>
<div>风速: <b>${speed} m/s</b></div>
<div style="margin-top: 5px; font-size: 12px; color: #ccc;">
${barbDescription}
</div>
<div style="font-size: 12px; color: #ccc;">
风速范围: ${colorLabel}
</div>
`;
}
},
grid: {
left: '70px',
right: '100px',
bottom: '70px',
top: '50px',
containLabel: false
},
xAxis: {
type: 'category',
data: times,
name: '时间',
nameLocation: 'middle',
nameGap: 30,
axisLabel: {
color: '#a0d2ff',
fontSize: 10,
interval: 1,
rotate: 45
},
axisLine: {
lineStyle: {
color: '#40a9ff'
}
}
},
yAxis: {
type: 'category',
data: heights.map(h => h + 'm'),
name: '高度 (m)',
nameLocation: 'middle',
nameGap: 50,
axisLabel: {
color: '#a0d2ff',
fontSize: 10
},
axisLine: {
lineStyle: {
color: '#40a9ff'
}
},
inverse: false // 从下往上递增
},
visualMap: {
type: 'piecewise',
min: 0,
max: 50,
orient: 'vertical',
right: 10,
top: 'center',
textStyle: {
color: '#a0d2ff',
fontSize: 9
},
pieces: windSpeedColors,
name: '风速\n(m/s)',
nameTextStyle: {
fontSize: 10,
fontWeight: 'bold',
color: '#e0f0ff'
},
formatter: function (value) {
// 自定义格式化显示
const range = windSpeedColors.find(range =>
value.min === range.min && value.max === range.max
);
return range ? range.label : '';
}
},
series: [{
name: '风矢杆',
type: 'custom',
renderItem: renderWindBarb,
data: data,
encode: {
x: [0],
y: [1]
},
animation: true,
animationDuration: 800
}],
// dataZoom: [ // 这里添加了dataZoom组件实现了横纵坐标轴的收缩功能
// {
// type: 'slider', // 这个 dataZoom 组件是滑动条类型
// start: 10, // 数据窗口的起始百分比默认为0即最左边
// end: 50 // 数据窗口的结束百分比默认为100即最右边
// },
// {
// type: 'inside', // 这个 dataZoom 组件是内置类型,即图表内部的一个滑动条
// }
// ]
};
myChart.setOption(option);
// 添加窗口大小调整事件监听
window.addEventListener('resize', function () {
myChart.resize();
});
// 创建图例示例
setTimeout(() => {
createLegendExamples();
}, 100);
// 创建图例示例
function createLegendExamples() {
// 创建图例容器
const legendContainer = document.createElement('div');
legendContainer.className = 'wind-barb-legend';
legendContainer.style.cssText = `
display: flex;
justify-content: center;
flex-wrap: wrap;
gap: 15px;
margin: 10px 0;
font-size: 11px;
`;
// 图例项
const legendItems = [
{ id: 'legend-short-feather', text: '短羽 = 2 m/s' },
{ id: 'legend-long-feather', text: '长羽 = 4 m/s' },
{ id: 'legend-triangle', text: '三角旗 = 20 m/s' },
{ id: 'legend-calm', text: '圆圈 = 静风' }
];
legendItems.forEach(item => {
const legendItem = document.createElement('div');
legendItem.className = 'legend-item';
legendItem.style.cssText = 'text-align: center;';
const legendBarb = document.createElement('div');
legendBarb.className = 'legend-barb';
legendBarb.id = item.id;
legendBarb.style.cssText = 'display: inline-block; margin-bottom: 3px;';
const legendText = document.createElement('div');
legendText.textContent = item.text;
legendItem.appendChild(legendBarb);
legendItem.appendChild(legendText);
legendContainer.appendChild(legendItem);
});
//chartDom.parentNode.appendChild(legendContainer);
// 创建风矢杆示例
createWindBarbExample('legend-short-feather', 0, 2, 0); // 短羽
createWindBarbExample('legend-long-feather', 0, 4, 0); // 长羽
createWindBarbExample('legend-triangle', 0, 20, 0); // 三角旗
createWindBarbExample('legend-calm', 0, 0, 0); // 静风
}
// 创建风矢杆示例
function createWindBarbExample(elementId, direction, speed, exampleDirection) {
const container = document.getElementById(elementId);
if (!container) return;
const canvas = document.createElement('canvas');
canvas.width = 50;
canvas.height = 50;
canvas.style.width = '50px';
canvas.style.height = '50px';
const ctx = canvas.getContext('2d');
ctx.translate(25, 25);
if (speed === 0) {
// 静风 - 画圆圈
ctx.beginPath();
ctx.arc(0, 0, 8, 0, 2 * Math.PI);
ctx.strokeStyle = '#000';
ctx.lineWidth = 1.5;
ctx.stroke();
} else {
// 风矢杆
drawWindBarb(ctx, exampleDirection, speed, 20, true);
}
container.appendChild(canvas);
}
}, 800); // 模拟数据加载时间
}
</script>
</body>
</html>