|
|
<!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://cdn.bootcdn.net/ajax/libs/bootstrap/5.3.0/css/bootstrap.min.css">
|
|
|
<link href="https://demo.axureux.com/fontawesome/5.7.2/pro/css/all.min.css" type="text/css" rel="stylesheet" />
|
|
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/3.9.1/chart.min.js"></script> -->
|
|
|
<link rel="stylesheet" href="/common/css/bootstrap.min.css">
|
|
|
<link href="https://demo.axureux.com/fontawesome/5.7.2/pro/css/all.min.css" type="text/css" rel="stylesheet" />
|
|
|
<!-- <link href="/common/css/all.min.css" type="text/css" rel="stylesheet" /> -->
|
|
|
<script src="/common/script/chart.min.js"></script>
|
|
|
<style>
|
|
|
/* 整个滚动条 */
|
|
|
::-webkit-scrollbar {
|
|
|
width: 8px;
|
|
|
height: 6px;
|
|
|
}
|
|
|
|
|
|
/* 滚动条轨道 */
|
|
|
::-webkit-scrollbar-track {
|
|
|
background: #f1f3f5;
|
|
|
border-radius: 10px;
|
|
|
}
|
|
|
|
|
|
/* 滚动条滑块 */
|
|
|
::-webkit-scrollbar-thumb {
|
|
|
background: #a5b4fc;
|
|
|
border-radius: 10px;
|
|
|
border: 2px solid #f1f3f5;
|
|
|
}
|
|
|
|
|
|
/* 滚动条滑块悬停状态 */
|
|
|
::-webkit-scrollbar-thumb:hover {
|
|
|
background: #7c3aed;
|
|
|
}
|
|
|
|
|
|
/* 滚动条角落 */
|
|
|
::-webkit-scrollbar-corner {
|
|
|
background: #f1f3f5;
|
|
|
}
|
|
|
|
|
|
|
|
|
/* 数据表格容器滚动条 */
|
|
|
.data-table-container::-webkit-scrollbar {
|
|
|
width: 8px;
|
|
|
height: 8px;
|
|
|
}
|
|
|
|
|
|
.data-table-container::-webkit-scrollbar-track {
|
|
|
background: #f8f9fa;
|
|
|
border-radius: 4px;
|
|
|
}
|
|
|
|
|
|
.data-table-container::-webkit-scrollbar-thumb {
|
|
|
background: linear-gradient(180deg, #4da6ff, #1a6bc9);
|
|
|
border-radius: 4px;
|
|
|
}
|
|
|
|
|
|
.data-table-container::-webkit-scrollbar-thumb:hover {
|
|
|
background: linear-gradient(180deg, #1a6bc9, #0d4a8a);
|
|
|
}
|
|
|
|
|
|
:root {
|
|
|
--primary-blue: #1a6bc9;
|
|
|
--secondary-blue: #2c8ce0;
|
|
|
--light-blue: #e6f2ff;
|
|
|
--dark-blue: #0d4a8a;
|
|
|
--accent-blue: #4da6ff;
|
|
|
}
|
|
|
|
|
|
body {
|
|
|
font-family: 'Microsoft YaHei', sans-serif;
|
|
|
background-color: #f5f9ff;
|
|
|
color: #333;
|
|
|
}
|
|
|
|
|
|
.header {
|
|
|
background: linear-gradient(135deg, var(--primary-blue), var(--dark-blue));
|
|
|
color: white;
|
|
|
padding: 15px 20px;
|
|
|
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.2);
|
|
|
text-align: center;
|
|
|
}
|
|
|
|
|
|
/* 修改标签页样式,使用浅灰色背景 */
|
|
|
.nav-tabs {
|
|
|
background-color: #f8f9fa;
|
|
|
/* 浅灰色背景 */
|
|
|
border-bottom: 2px solid #dee2e6;
|
|
|
/* 浅灰色边框 */
|
|
|
padding: 0 10px;
|
|
|
/* 添加内边距 */
|
|
|
border-radius: 0 0 8px 8px;
|
|
|
/* 添加圆角 */
|
|
|
}
|
|
|
|
|
|
.nav-tabs .nav-link {
|
|
|
color: #495057;
|
|
|
/* 深灰色文字 */
|
|
|
font-weight: bold;
|
|
|
border: none;
|
|
|
padding: 12px 20px;
|
|
|
border-radius: 8px 8px 0 0 !important;
|
|
|
margin-right: 5px;
|
|
|
/* 添加右侧间距 */
|
|
|
transition: all 0.3s ease;
|
|
|
/* 添加过渡效果 */
|
|
|
}
|
|
|
|
|
|
.nav-tabs .nav-link.active {
|
|
|
background-color: #ffffff;
|
|
|
/* 白色背景 */
|
|
|
color: #1a6bc9;
|
|
|
/* 蓝色文字 */
|
|
|
border: none;
|
|
|
box-shadow: 0 -2px 5px rgba(0, 0, 0, 0.1);
|
|
|
/* 添加阴影效果 */
|
|
|
}
|
|
|
|
|
|
.nav-tabs .nav-link:hover:not(.active) {
|
|
|
background-color: #e9ecef;
|
|
|
/* 悬停时的浅灰色 */
|
|
|
color: #1a6bc9;
|
|
|
/* 蓝色文字 */
|
|
|
}
|
|
|
|
|
|
/* 确保卡片高度一致 */
|
|
|
.card {
|
|
|
height: 100%;
|
|
|
border-radius: 8px;
|
|
|
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
|
|
|
border: 1px solid #dee2e6;
|
|
|
/* 添加边框 */
|
|
|
margin-bottom: 20px;
|
|
|
/* 恢复margin-bottom */
|
|
|
}
|
|
|
|
|
|
/* 左侧上部卡片(监测站点和监测指标)的特殊处理 */
|
|
|
.row>.col-md-6>.row>.col-md-6>.card {
|
|
|
height: calc(100% - 20px);
|
|
|
/* 调整高度以适应margin */
|
|
|
margin-bottom: 20px;
|
|
|
}
|
|
|
|
|
|
/* 左侧地图卡片 */
|
|
|
.row>.col-md-6>.card {
|
|
|
height: calc(100% - 215px);
|
|
|
/* 与其他卡片保持一致的高度计算 */
|
|
|
margin-bottom: 0;
|
|
|
}
|
|
|
|
|
|
/* 右侧设备状态卡片高度调整 */
|
|
|
#realtime .col-md-6:last-child .card:last-child {
|
|
|
height: calc(100% - 20px);
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* 右侧设备状态卡片高度调整 */
|
|
|
#realtime .col-md-6:last-child .card:last-child {
|
|
|
height: calc(100% - 20px);
|
|
|
/* 与地图卡片高度一致 */
|
|
|
}
|
|
|
|
|
|
.card-header {
|
|
|
background: linear-gradient(to right, var(--secondary-blue), var(--accent-blue));
|
|
|
color: white;
|
|
|
font-weight: bold;
|
|
|
border-radius: 8px 8px 0 0 !important;
|
|
|
border-bottom: 1px solid #dee2e6;
|
|
|
}
|
|
|
|
|
|
.monitor-section {
|
|
|
background-color: white;
|
|
|
padding: 20px;
|
|
|
border-radius: 8px;
|
|
|
}
|
|
|
|
|
|
.data-item {
|
|
|
margin-bottom: 15px;
|
|
|
padding-bottom: 10px;
|
|
|
border-bottom: 1px dashed #ddd;
|
|
|
}
|
|
|
|
|
|
.data-label {
|
|
|
font-weight: bold;
|
|
|
color: var(--dark-blue);
|
|
|
}
|
|
|
|
|
|
/* 地图容器样式调整 */
|
|
|
.map-container {
|
|
|
height: 100%;
|
|
|
/* 减去card-header的高度 */
|
|
|
background-color: #eef7ff;
|
|
|
border-radius: 8px;
|
|
|
border: 1px solid #cce5ff;
|
|
|
position: relative;
|
|
|
}
|
|
|
|
|
|
.tab-content {
|
|
|
/* padding: 20px; */
|
|
|
background-color: white;
|
|
|
border-radius: 0 0 8px 8px;
|
|
|
}
|
|
|
|
|
|
.warning-panel {
|
|
|
background-color: #fff4e6;
|
|
|
border-left: 4px solid #ff9900;
|
|
|
padding: 15px;
|
|
|
margin-bottom: 20px;
|
|
|
}
|
|
|
|
|
|
.btn-action {
|
|
|
background-color: var(--secondary-blue);
|
|
|
color: white;
|
|
|
margin-right: 10px;
|
|
|
margin-bottom: 10px;
|
|
|
}
|
|
|
|
|
|
.btn-action:hover {
|
|
|
background-color: var(--primary-blue);
|
|
|
color: white;
|
|
|
}
|
|
|
|
|
|
.btn-export {
|
|
|
background-color: #28a745;
|
|
|
color: white;
|
|
|
}
|
|
|
|
|
|
.data-table {
|
|
|
font-size: 14px;
|
|
|
}
|
|
|
|
|
|
.data-table th {
|
|
|
background-color: var(--light-blue);
|
|
|
}
|
|
|
|
|
|
.chart-container {
|
|
|
position: relative;
|
|
|
height: 300px;
|
|
|
width: 100%;
|
|
|
}
|
|
|
|
|
|
.risk-chart {
|
|
|
height: calc(100vh - 615px);
|
|
|
overflow: hidden;
|
|
|
/* 防止出现滚动条 */
|
|
|
}
|
|
|
|
|
|
.kpi-grid {
|
|
|
display: grid;
|
|
|
grid-template-columns: repeat(4, 1fr);
|
|
|
gap: 15px;
|
|
|
}
|
|
|
|
|
|
.kpi-item {
|
|
|
background: #f8f9fa;
|
|
|
border-radius: 8px;
|
|
|
padding: 20px 10px;
|
|
|
text-align: center;
|
|
|
border: 1px solid #dee2e6;
|
|
|
}
|
|
|
|
|
|
.kpi-value {
|
|
|
font-size: 16px;
|
|
|
font-weight: bold;
|
|
|
color: #0d6efd;
|
|
|
margin-bottom: 5px;
|
|
|
}
|
|
|
|
|
|
.kpi-label {
|
|
|
font-size: 12px;
|
|
|
color: #6c757d;
|
|
|
}
|
|
|
|
|
|
/* 数据查询区域样式 */
|
|
|
.data-query-container {
|
|
|
display: flex;
|
|
|
height: calc(100vh - 150px);
|
|
|
gap: 20px;
|
|
|
}
|
|
|
|
|
|
.data-chart-section {
|
|
|
flex: 3;
|
|
|
display: flex;
|
|
|
flex-direction: column;
|
|
|
}
|
|
|
|
|
|
.data-table-section {
|
|
|
flex: 1;
|
|
|
display: flex;
|
|
|
flex-direction: column;
|
|
|
}
|
|
|
|
|
|
.data-table-container {
|
|
|
flex: 1;
|
|
|
overflow-y: auto;
|
|
|
max-height: calc(100vh - 208px);
|
|
|
}
|
|
|
|
|
|
.chart-wrapper {
|
|
|
height: calc(100vh - 320px);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
.chart-wrapper canvas {
|
|
|
width: 100% !important;
|
|
|
height: 100% !important;
|
|
|
max-height: calc(100vh - 320px);
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* 地图工具栏按钮选中状态样式 - 改进版本 */
|
|
|
.btn-map-tool.active {
|
|
|
background-color: #ff6b35 !important;
|
|
|
/* 使用更醒目的橙色 */
|
|
|
border-color: #e55a2b !important;
|
|
|
box-shadow: 0 0 0 0.2rem rgba(255, 107, 53, 0.35);
|
|
|
color: white !important;
|
|
|
}
|
|
|
|
|
|
/* 悬停状态也保持一致性 */
|
|
|
.btn-map-tool.active:hover {
|
|
|
background-color: #e55a2b !important;
|
|
|
border-color: #cc481f !important;
|
|
|
}
|
|
|
|
|
|
.btn-map-tool:focus {
|
|
|
box-shadow: 0 0 0 0.2rem rgba(26, 107, 201, 0.25);
|
|
|
}
|
|
|
|
|
|
/* 确保工具栏按钮有一致的样式 */
|
|
|
.btn-map-tool {
|
|
|
margin-bottom: 2px;
|
|
|
}
|
|
|
|
|
|
/* 应急处理按钮布局优化 */
|
|
|
.emergency-actions {
|
|
|
display: grid;
|
|
|
grid-template-columns: repeat(2, 1fr);
|
|
|
gap: 15px;
|
|
|
}
|
|
|
|
|
|
/* 在小屏幕上使用单列布局 */
|
|
|
@media (max-width: 768px) {
|
|
|
.emergency-actions {
|
|
|
grid-template-columns: 1fr;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
/* 应急处理按钮样式优化 */
|
|
|
.btn-emergency {
|
|
|
background: linear-gradient(135deg, #ff6b6b, #ee5a24);
|
|
|
color: white;
|
|
|
border: none;
|
|
|
padding: 12px 15px;
|
|
|
font-weight: bold;
|
|
|
transition: all 0.3s ease;
|
|
|
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
|
|
|
text-align: center;
|
|
|
width: 100%;
|
|
|
}
|
|
|
|
|
|
.btn-emergency:hover {
|
|
|
background: linear-gradient(135deg, #ee5a24, #ff6b6b);
|
|
|
transform: translateY(-2px);
|
|
|
box-shadow: 0 6px 8px rgba(0, 0, 0, 0.15);
|
|
|
color: white;
|
|
|
}
|
|
|
|
|
|
.btn-emergency:active {
|
|
|
transform: translateY(0);
|
|
|
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
|
|
|
}
|
|
|
|
|
|
.btn-emergency i {
|
|
|
margin-right: 8px;
|
|
|
}
|
|
|
</style>
|
|
|
</head>
|
|
|
|
|
|
<body>
|
|
|
<div class="header d-flex justify-content-between align-items-center">
|
|
|
<h2 class="mb-0">海底监测与灾害预警系统管理平台</h2>
|
|
|
<img src="/common/images/logo_gt.png" alt="Logo" style="height: 50px; width: auto;">
|
|
|
</div>
|
|
|
|
|
|
<ul class="nav nav-tabs" id="mainTabs" role="tablist">
|
|
|
<li class="nav-item" role="presentation">
|
|
|
<button class="nav-link active" id="realtime-tab" data-bs-toggle="tab" data-bs-target="#realtime"
|
|
|
type="button" role="tab">实时监控</button>
|
|
|
</li>
|
|
|
<li class="nav-item" role="presentation">
|
|
|
<button class="nav-link" id="data-tab" data-bs-toggle="tab" data-bs-target="#data" type="button"
|
|
|
role="tab">数据管理</button>
|
|
|
</li>
|
|
|
</ul>
|
|
|
|
|
|
<div class="tab-content container-fluid mt-3" id="mainTabContent">
|
|
|
<!-- 实时监控面板 -->
|
|
|
<div class="tab-pane fade show active" id="realtime" role="tabpanel">
|
|
|
<div class="row">
|
|
|
<!-- 左侧内容 -->
|
|
|
<div class="col-md-6">
|
|
|
<div class="row">
|
|
|
<div class="col-md-6">
|
|
|
<div class="card">
|
|
|
<div class="card-header">监测站点</div>
|
|
|
<div class="card-body">
|
|
|
<div class="data-item">
|
|
|
<span class="data-label">站点名称:</span>
|
|
|
<select class="form-select form-select-sm"
|
|
|
style="display: inline-block; width: auto;">
|
|
|
<option selected>东营监测站</option>
|
|
|
<option>青岛监测站</option>
|
|
|
<option>烟台监测站</option>
|
|
|
<option>日照监测站</option>
|
|
|
<option>潍坊监测站</option>
|
|
|
</select>
|
|
|
</div>
|
|
|
<div class="data-item">
|
|
|
<span class="data-label">分布区域:</span> 东营市河西仙镇
|
|
|
</div>
|
|
|
</div>
|
|
|
</div>
|
|
|
</div>
|
|
|
|
|
|
<div class="col-md-6">
|
|
|
<div class="card">
|
|
|
<div class="card-header">监测指标</div>
|
|
|
<div class="card-body">
|
|
|
<div class="data-item">
|
|
|
<span class="data-label">水文:</span> 波浪 温盐 海流
|
|
|
</div>
|
|
|
<div class="data-item">
|
|
|
<span class="data-label">水质:</span> 浊度 PH 溶解氧 叶绿素
|
|
|
</div>
|
|
|
</div>
|
|
|
</div>
|
|
|
</div>
|
|
|
</div>
|
|
|
|
|
|
<div class="card">
|
|
|
<div class="card-header">地图</div>
|
|
|
<div class="card-body p-0">
|
|
|
<div class="map-container">
|
|
|
<div id="map" style="width: 100%; height: 100%; position: relative;"></div>
|
|
|
|
|
|
<!-- 地图工具栏 -->
|
|
|
<div id="map-toolbar"
|
|
|
style="position: absolute; top: 10px; right: 10px; z-index: 1000;">
|
|
|
<div class="btn-group-vertical" role="group">
|
|
|
<button id="btn-locate" class="btn btn-primary btn-sm btn-map-tool" title="定位">
|
|
|
<i class="fas fa-location-arrow"></i>
|
|
|
</button>
|
|
|
<button id="btn-draw-point" class="btn btn-primary btn-sm btn-map-tool"
|
|
|
title="绘制点">
|
|
|
<i class="fas fa-map-marker-alt"></i>
|
|
|
</button>
|
|
|
<button id="btn-draw-line" class="btn btn-primary btn-sm btn-map-tool"
|
|
|
title="绘制线">
|
|
|
<i class="fas fa-minus"></i>
|
|
|
</button>
|
|
|
<button id="btn-draw-polygon" class="btn btn-primary btn-sm btn-map-tool"
|
|
|
title="绘制多边形">
|
|
|
<i class="fas fa-draw-polygon"></i>
|
|
|
</button>
|
|
|
<button id="btn-draw-circle" class="btn btn-primary btn-sm btn-map-tool"
|
|
|
title="绘制圆形">
|
|
|
<i class="fas fa-circle"></i>
|
|
|
</button>
|
|
|
<button id="btn-measure" class="btn btn-primary btn-sm btn-map-tool"
|
|
|
title="测量距离">
|
|
|
<i class="fas fa-ruler"></i>
|
|
|
</button>
|
|
|
<button id="btn-delete" class="btn btn-danger btn-sm btn-map-tool" title="删除">
|
|
|
<i class="fas fa-trash"></i>
|
|
|
</button>
|
|
|
</div>
|
|
|
</div>
|
|
|
<!-- 经纬度显示 - 移动到左上角 -->
|
|
|
<!-- <div id="mouse-position"
|
|
|
style="position: absolute; top: 70px; left: 20px; background: rgba(255,255,255,0.8); padding: 5px 10px; border-radius: 4px; font-size: 12px; z-index: 1000; box-shadow: 0 0 5px rgba(0,0,0,0.3);">
|
|
|
经纬度: 0.000000, 0.000000
|
|
|
</div> -->
|
|
|
|
|
|
<!-- 比例尺 -->
|
|
|
<div id="scale-line" style="position: absolute; bottom: 10px; left: 15px;"></div>
|
|
|
</div>
|
|
|
</div>
|
|
|
</div>
|
|
|
</div>
|
|
|
|
|
|
<!-- 右侧内容 -->
|
|
|
<div class="col-md-6">
|
|
|
<ul class="nav nav-tabs" id="realtimeSubTabs" role="tablist">
|
|
|
<li class="nav-item" role="presentation">
|
|
|
<button class="nav-link active" id="monitor-data-tab" data-bs-toggle="tab"
|
|
|
data-bs-target="#monitor-data" type="button" role="tab">监测数据</button>
|
|
|
</li>
|
|
|
<li class="nav-item" role="presentation">
|
|
|
<button class="nav-link" id="warning-info-tab" data-bs-toggle="tab"
|
|
|
data-bs-target="#warning-info" type="button" role="tab">告警信息</button>
|
|
|
</li>
|
|
|
</ul>
|
|
|
|
|
|
<div class="tab-content" id="realtimeSubTabContent">
|
|
|
<!-- 监测数据子面板 -->
|
|
|
<div class="tab-pane fade show active" id="monitor-data" role="tabpanel">
|
|
|
<div class="data-item" style="padding-top: 15px;">
|
|
|
<span class="data-label">数据更新时间:</span> 2025-09-17 15:18:00
|
|
|
</div>
|
|
|
<div class="data-item">
|
|
|
<span class="data-label">运行状态:</span> <span class="text-success">正常运行</span>
|
|
|
</div>
|
|
|
<div class="card mt-3">
|
|
|
<div class="card-header bg-info text-white">水文</div>
|
|
|
<div class="card-body">
|
|
|
<div class="kpi-grid">
|
|
|
<div class="kpi-item">
|
|
|
<div class="kpi-value">15 cm</div>
|
|
|
<div class="kpi-label">平均波高</div>
|
|
|
</div>
|
|
|
<div class="kpi-item">
|
|
|
<div class="kpi-value">9.9 s</div>
|
|
|
<div class="kpi-label">平均波周期</div>
|
|
|
</div>
|
|
|
<div class="kpi-item">
|
|
|
<div class="kpi-value">25.2 cm</div>
|
|
|
<div class="kpi-label">1/3波高</div>
|
|
|
</div>
|
|
|
<div class="kpi-item">
|
|
|
<div class="kpi-value">9.9 s</div>
|
|
|
<div class="kpi-label">1/3波周期</div>
|
|
|
</div>
|
|
|
<div class="kpi-item">
|
|
|
<div class="kpi-value">20.1 cm</div>
|
|
|
<div class="kpi-label">1/10波高</div>
|
|
|
</div>
|
|
|
<div class="kpi-item">
|
|
|
<div class="kpi-value">9.1 s</div>
|
|
|
<div class="kpi-label">1/10波周期</div>
|
|
|
</div>
|
|
|
<div class="kpi-item">
|
|
|
<div class="kpi-value">26.4 cm</div>
|
|
|
<div class="kpi-label">最大波高</div>
|
|
|
</div>
|
|
|
<div class="kpi-item">
|
|
|
<div class="kpi-value">10 s</div>
|
|
|
<div class="kpi-label">最大波周期</div>
|
|
|
</div>
|
|
|
|
|
|
<div class="kpi-item">
|
|
|
<div class="kpi-value">135 °</div>
|
|
|
<div class="kpi-label">主波向</div>
|
|
|
</div>
|
|
|
<div class="kpi-item">
|
|
|
<div class="kpi-value">28.13 ℃</div>
|
|
|
<div class="kpi-label">水温</div>
|
|
|
</div>
|
|
|
<div class="kpi-item">
|
|
|
<div class="kpi-value">23 mS/cm</div>
|
|
|
<div class="kpi-label">电导率</div>
|
|
|
</div>
|
|
|
<div class="kpi-item">
|
|
|
<div class="kpi-value">23 m</div>
|
|
|
<div class="kpi-label">潮位</div>
|
|
|
</div>
|
|
|
<div class="kpi-item">
|
|
|
<div class="kpi-value">38 mm/s</div>
|
|
|
<div class="kpi-label">流速</div>
|
|
|
</div>
|
|
|
<div class="kpi-item">
|
|
|
<div class="kpi-value">156 °</div>
|
|
|
<div class="kpi-label">流向</div>
|
|
|
</div>
|
|
|
</div>
|
|
|
</div>
|
|
|
</div>
|
|
|
|
|
|
<div class="card mt-3">
|
|
|
<div class="card-header bg-info text-white">水质</div>
|
|
|
<div class="card-body">
|
|
|
<div class="kpi-grid">
|
|
|
<div class="kpi-item">
|
|
|
<div class="kpi-value">15 NTU</div>
|
|
|
<div class="kpi-label">浊度</div>
|
|
|
</div>
|
|
|
<div class="kpi-item">
|
|
|
<div class="kpi-value">7.9</div>
|
|
|
<div class="kpi-label">PH</div>
|
|
|
</div>
|
|
|
<div class="kpi-item">
|
|
|
<div class="kpi-value">6 mg/L</div>
|
|
|
<div class="kpi-label">溶解氧</div>
|
|
|
</div>
|
|
|
<div class="kpi-item">
|
|
|
<div class="kpi-value">0.8 μg/L</div>
|
|
|
<div class="kpi-label">叶绿素</div>
|
|
|
</div>
|
|
|
</div>
|
|
|
</div>
|
|
|
</div>
|
|
|
|
|
|
<!-- 修改设备状态卡片部分 -->
|
|
|
<div class="card mt-3" style="height: calc(100% - 20px);">
|
|
|
<div class="card-header bg-info text-white">设备状态</div>
|
|
|
<div class="card-body">
|
|
|
<div class="data-item">
|
|
|
<span class="data-label">水文监测设备:</span> <span class="text-success">正常运行</span>
|
|
|
</div>
|
|
|
<div class="data-item">
|
|
|
<span class="data-label">水质监测设备:</span> <span class="text-success">正常运行</span>
|
|
|
</div>
|
|
|
</div>
|
|
|
</div>
|
|
|
</div>
|
|
|
|
|
|
<!-- 告警信息子面板 -->
|
|
|
<div class="tab-pane fade" id="warning-info" role="tabpanel">
|
|
|
<div class="warning-panel">
|
|
|
<h5>警告信息</h5>
|
|
|
<p>当前系统检测到异常波动,请注意查看风险预报图。</p>
|
|
|
</div>
|
|
|
|
|
|
<div class="card">
|
|
|
<div class="card-header">风险预报图</div>
|
|
|
<div class="card-body">
|
|
|
<div class="risk-chart">
|
|
|
<canvas id="riskChart"></canvas>
|
|
|
</div>
|
|
|
</div>
|
|
|
</div>
|
|
|
|
|
|
<div class="card mt-3">
|
|
|
<div class="card-header">应急处理</div>
|
|
|
<div class="card-body">
|
|
|
<div class="emergency-actions">
|
|
|
<button class="btn btn-emergency">
|
|
|
<i class="fas fa-plug"></i>断开波浪设备电源
|
|
|
</button>
|
|
|
<button class="btn btn-emergency">
|
|
|
<i class="fas fa-plug"></i>断开海流设备电源
|
|
|
</button>
|
|
|
<button class="btn btn-emergency">
|
|
|
<i class="fas fa-plug"></i>断开水质设备电源
|
|
|
</button>
|
|
|
<button class="btn btn-emergency">
|
|
|
<i class="fas fa-redo"></i>补发当天数据
|
|
|
</button>
|
|
|
</div>
|
|
|
</div>
|
|
|
</div>
|
|
|
</div>
|
|
|
</div>
|
|
|
</div>
|
|
|
</div>
|
|
|
</div>
|
|
|
|
|
|
<!-- 数据管理面板 -->
|
|
|
<div class="tab-pane fade" id="data" role="tabpanel">
|
|
|
<div class="data-query-container">
|
|
|
<!-- 左侧图表 -->
|
|
|
<div class="data-chart-section">
|
|
|
<div class="card h-100">
|
|
|
<div class="card-header">数据查询</div>
|
|
|
<div class="card-body">
|
|
|
<div class="row mb-3">
|
|
|
<div class="col-md-5">
|
|
|
<label class="form-label">开始时间:</label>
|
|
|
<input type="date" class="form-control" id="startDate" value="2025-09-16">
|
|
|
</div>
|
|
|
<div class="col-md-5">
|
|
|
<label class="form-label">结束时间:</label>
|
|
|
<input type="date" class="form-control" id="endDate" value="2025-09-22">
|
|
|
</div>
|
|
|
<div class="col-md-2">
|
|
|
<label class="form-label">数据类型:</label>
|
|
|
<select class="form-select" id="dataTypeSelect">
|
|
|
<option value="流速" selected>流速</option>
|
|
|
<option value="波浪">波浪</option>
|
|
|
<option value="温盐">温盐</option>
|
|
|
<option value="海流">海流</option>
|
|
|
<option value="浊度">浊度</option>
|
|
|
<option value="PH">PH</option>
|
|
|
<option value="溶解氧">溶解氧</option>
|
|
|
<option value="叶绿素">叶绿素</option>
|
|
|
<option value="电导率">电导率</option>
|
|
|
<option value="潮位">潮位</option>
|
|
|
<option value="流向">流向</option>
|
|
|
</select>
|
|
|
</div>
|
|
|
</div>
|
|
|
|
|
|
<div class="chart-wrapper">
|
|
|
<canvas id="dataChart"></canvas>
|
|
|
</div>
|
|
|
</div>
|
|
|
</div>
|
|
|
</div>
|
|
|
|
|
|
<!-- 右侧数据表格 -->
|
|
|
<div class="data-table-section">
|
|
|
<div class="card h-100">
|
|
|
<div class="card-header d-flex justify-content-between align-items-center">
|
|
|
<span>数据列表</span>
|
|
|
<button class="btn btn-sm btn-export">数据导出</button>
|
|
|
</div>
|
|
|
<div class="data-table-container">
|
|
|
<div class="card-body p-0">
|
|
|
<div class="table-responsive">
|
|
|
<table class="table table-striped table-hover data-table mb-0">
|
|
|
<thead>
|
|
|
<tr>
|
|
|
<th>时间</th>
|
|
|
<th id="dataColumnType">流速(m/s)</th>
|
|
|
</tr>
|
|
|
</thead>
|
|
|
<tbody id="dataTableBody">
|
|
|
<!-- 数据将通过JavaScript动态生成 -->
|
|
|
</tbody>
|
|
|
</table>
|
|
|
</div>
|
|
|
</div>
|
|
|
</div>
|
|
|
</div>
|
|
|
</div>
|
|
|
</div>
|
|
|
</div>
|
|
|
</div>
|
|
|
<link rel="stylesheet" href="/common/plugin/map/ol/v6.12.0/css/ol.css" type="text/css" />
|
|
|
<script src="/common/plugin/map/ol/v6.12.0/build/ol.js"></script>
|
|
|
<link rel="stylesheet" href="/common/plugin/map/ol/ol-ext-master/ol-ext.css" />
|
|
|
<script type="text/javascript" src="/common/plugin/map/ol/ol-ext-master/ol-ext.js"></script>
|
|
|
<script src="/common/script/bootstrap.bundle.min.js"></script>
|
|
|
<!-- <script src="https://cdnjs.cloudflare.com/ajax/libs/bootstrap/5.3.0/js/bootstrap.bundle.min.js"></script> -->
|
|
|
<script>
|
|
|
var TDT_API_KEY = "a4f4b6000cb9d1bf148bb77452000f30";
|
|
|
// 地图初始化
|
|
|
document.addEventListener('DOMContentLoaded', function () {
|
|
|
// 存储图表实例的全局变量
|
|
|
window.charts = {
|
|
|
riskChart: null,
|
|
|
dataChart: null
|
|
|
};
|
|
|
|
|
|
// 存储地图实例的全局变量
|
|
|
window.mapInstance = null;
|
|
|
|
|
|
// 节流函数,防止频繁触发
|
|
|
function throttle(func, limit) {
|
|
|
let inThrottle;
|
|
|
return function () {
|
|
|
const args = arguments;
|
|
|
const context = this;
|
|
|
if (!inThrottle) {
|
|
|
func.apply(context, args);
|
|
|
inThrottle = true;
|
|
|
setTimeout(() => inThrottle = false, limit);
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
// 处理窗口大小改变事件
|
|
|
const handleResize = throttle(function () {
|
|
|
// 重绘风险预报图
|
|
|
if (window.charts.riskChart) {
|
|
|
window.charts.riskChart.resize();
|
|
|
}
|
|
|
|
|
|
// 重绘数据图表
|
|
|
if (window.dataChartInstance) {
|
|
|
window.dataChartInstance.resize();
|
|
|
}
|
|
|
|
|
|
// 调整地图大小
|
|
|
if (window.mapInstance) {
|
|
|
setTimeout(() => {
|
|
|
window.mapInstance.updateSize();
|
|
|
}, 100);
|
|
|
}
|
|
|
}, 200);
|
|
|
|
|
|
// 监听窗口大小改变事件
|
|
|
window.addEventListener('resize', handleResize);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
var osm = [
|
|
|
new ol.layer.Tile({
|
|
|
source: new ol.source.XYZ({
|
|
|
url: "http://t{0-7}.tianditu.com/DataServer?T=img_w&x={x}&y={y}&l={z}&tk=" + TDT_API_KEY
|
|
|
})
|
|
|
}),
|
|
|
new ol.layer.Tile({
|
|
|
source: new ol.source.XYZ({
|
|
|
url: "http://t{0-7}.tianditu.com/DataServer?T=cva_w&x={x}&y={y}&l={z}&tk=" + TDT_API_KEY
|
|
|
}),
|
|
|
// visible: false
|
|
|
}),
|
|
|
]
|
|
|
// 创建地图
|
|
|
const map = new ol.Map({
|
|
|
target: 'map',
|
|
|
layers: osm,
|
|
|
view: new ol.View({
|
|
|
center: ol.proj.fromLonLat([118.6, 37.5]), // 东营坐标
|
|
|
zoom: 9
|
|
|
})
|
|
|
});
|
|
|
|
|
|
// 添加比例尺控件
|
|
|
const scaleLine = new ol.control.ScaleLine({
|
|
|
target: 'scale-line',
|
|
|
units: 'metric'
|
|
|
});
|
|
|
map.addControl(scaleLine);
|
|
|
|
|
|
// 当前选中的工具按钮
|
|
|
let activeToolButton = null;
|
|
|
// 当前的绘制交互
|
|
|
let currentDraw = null;
|
|
|
// 矢量图层源
|
|
|
const source = new ol.source.Vector();
|
|
|
const vector = new ol.layer.Vector({
|
|
|
source: source
|
|
|
});
|
|
|
map.addLayer(vector);
|
|
|
|
|
|
// 格式化距离显示
|
|
|
function formatLength(line) {
|
|
|
const length = ol.sphere.getLength(line);
|
|
|
let output;
|
|
|
if (length > 1000) {
|
|
|
output = (Math.round(length / 1000 * 100) / 100) + ' km';
|
|
|
} else {
|
|
|
output = (Math.round(length * 100) / 100) + ' m';
|
|
|
}
|
|
|
return output;
|
|
|
}
|
|
|
|
|
|
// 更新工具按钮的选中状态
|
|
|
function updateToolButtonState(button) {
|
|
|
// 如果之前有选中的按钮,取消选中状态
|
|
|
if (activeToolButton) {
|
|
|
activeToolButton.classList.remove('active');
|
|
|
}
|
|
|
|
|
|
// 如果点击的是同一个按钮,则取消选中(相当于关闭工具)
|
|
|
if (activeToolButton === button) {
|
|
|
// 移除当前的绘制交互
|
|
|
if (currentDraw) {
|
|
|
map.removeInteraction(currentDraw);
|
|
|
currentDraw = null;
|
|
|
}
|
|
|
activeToolButton = null;
|
|
|
return false; // 表示工具已关闭
|
|
|
} else {
|
|
|
// 设置新的选中按钮
|
|
|
button.classList.add('active');
|
|
|
activeToolButton = button;
|
|
|
return true; // 表示工具已激活
|
|
|
}
|
|
|
}
|
|
|
|
|
|
// 定位按钮功能
|
|
|
document.getElementById('btn-locate').addEventListener('click', function () {
|
|
|
const isActivated = updateToolButtonState(this);
|
|
|
|
|
|
if (isActivated) {
|
|
|
// 这里可以添加实际的定位功能
|
|
|
const view = map.getView();
|
|
|
view.setCenter(ol.proj.fromLonLat([118.6, 37.5]));
|
|
|
view.setZoom(12);
|
|
|
|
|
|
// 定位功能执行后自动取消激活状态
|
|
|
setTimeout(() => {
|
|
|
if (activeToolButton === this) {
|
|
|
this.classList.remove('active');
|
|
|
activeToolButton = null;
|
|
|
}
|
|
|
}, 300);
|
|
|
}
|
|
|
});
|
|
|
|
|
|
// 绘制点
|
|
|
document.getElementById('btn-draw-point').addEventListener('click', function () {
|
|
|
const isActivated = updateToolButtonState(this);
|
|
|
|
|
|
// 移除之前的绘制交互
|
|
|
if (currentDraw) {
|
|
|
map.removeInteraction(currentDraw);
|
|
|
currentDraw = null;
|
|
|
}
|
|
|
|
|
|
if (isActivated) {
|
|
|
currentDraw = new ol.interaction.Draw({
|
|
|
source: source,
|
|
|
type: 'Point'
|
|
|
});
|
|
|
map.addInteraction(currentDraw);
|
|
|
}
|
|
|
});
|
|
|
|
|
|
// 绘制线
|
|
|
document.getElementById('btn-draw-line').addEventListener('click', function () {
|
|
|
const isActivated = updateToolButtonState(this);
|
|
|
|
|
|
// 移除之前的绘制交互
|
|
|
if (currentDraw) {
|
|
|
map.removeInteraction(currentDraw);
|
|
|
currentDraw = null;
|
|
|
}
|
|
|
|
|
|
if (isActivated) {
|
|
|
currentDraw = new ol.interaction.Draw({
|
|
|
source: source,
|
|
|
type: 'LineString'
|
|
|
});
|
|
|
map.addInteraction(currentDraw);
|
|
|
}
|
|
|
});
|
|
|
|
|
|
// 绘制多边形
|
|
|
document.getElementById('btn-draw-polygon').addEventListener('click', function () {
|
|
|
const isActivated = updateToolButtonState(this);
|
|
|
|
|
|
// 移除之前的绘制交互
|
|
|
if (currentDraw) {
|
|
|
map.removeInteraction(currentDraw);
|
|
|
currentDraw = null;
|
|
|
}
|
|
|
|
|
|
if (isActivated) {
|
|
|
currentDraw = new ol.interaction.Draw({
|
|
|
source: source,
|
|
|
type: 'Polygon'
|
|
|
});
|
|
|
map.addInteraction(currentDraw);
|
|
|
}
|
|
|
});
|
|
|
|
|
|
// 绘制圆形
|
|
|
document.getElementById('btn-draw-circle').addEventListener('click', function () {
|
|
|
const isActivated = updateToolButtonState(this);
|
|
|
|
|
|
// 移除之前的绘制交互
|
|
|
if (currentDraw) {
|
|
|
map.removeInteraction(currentDraw);
|
|
|
currentDraw = null;
|
|
|
}
|
|
|
|
|
|
if (isActivated) {
|
|
|
currentDraw = new ol.interaction.Draw({
|
|
|
source: source,
|
|
|
type: 'Circle'
|
|
|
});
|
|
|
map.addInteraction(currentDraw);
|
|
|
}
|
|
|
});
|
|
|
|
|
|
// 测量功能
|
|
|
document.getElementById('btn-measure').addEventListener('click', function () {
|
|
|
const isActivated = updateToolButtonState(this);
|
|
|
|
|
|
// 移除之前的绘制交互
|
|
|
if (currentDraw) {
|
|
|
map.removeInteraction(currentDraw);
|
|
|
currentDraw = null;
|
|
|
}
|
|
|
|
|
|
if (isActivated) {
|
|
|
currentDraw = new ol.interaction.Draw({
|
|
|
source: source,
|
|
|
type: 'LineString',
|
|
|
style: new ol.style.Style({
|
|
|
stroke: new ol.style.Stroke({
|
|
|
color: 'rgba(0, 0, 255, 0.5)',
|
|
|
lineDash: [10, 10],
|
|
|
width: 2
|
|
|
}),
|
|
|
image: new ol.style.Circle({
|
|
|
radius: 5,
|
|
|
stroke: new ol.style.Stroke({
|
|
|
color: 'rgba(0, 0, 255, 0.5)'
|
|
|
}),
|
|
|
fill: new ol.style.Fill({
|
|
|
color: 'rgba(255, 255, 255, 0.2)'
|
|
|
})
|
|
|
})
|
|
|
})
|
|
|
});
|
|
|
|
|
|
// 监听绘制结束事件
|
|
|
currentDraw.on('drawend', function (evt) {
|
|
|
// 获取绘制的要素
|
|
|
const feature = evt.feature;
|
|
|
const line = feature.getGeometry();
|
|
|
|
|
|
// 计算距离
|
|
|
const distance = formatLength(line);
|
|
|
|
|
|
// 创建包含线条和文本的样式数组
|
|
|
const styles = [
|
|
|
// 保留原有的线条样式
|
|
|
new ol.style.Style({
|
|
|
stroke: new ol.style.Stroke({
|
|
|
color: 'rgba(0, 0, 255, 0.5)',
|
|
|
lineDash: [10, 10],
|
|
|
width: 2
|
|
|
})
|
|
|
}),
|
|
|
// 添加文本标注样式
|
|
|
new ol.style.Style({
|
|
|
text: new ol.style.Text({
|
|
|
font: '14px sans-serif',
|
|
|
text: distance,
|
|
|
fill: new ol.style.Fill({
|
|
|
color: 'rgba(0, 0, 0, 1)'
|
|
|
}),
|
|
|
stroke: new ol.style.Stroke({
|
|
|
color: 'rgba(255, 255, 255, 1)',
|
|
|
width: 3
|
|
|
}),
|
|
|
// 将文本放置在线条的中点位置
|
|
|
placement: 'line',
|
|
|
textAlign: 'center'
|
|
|
})
|
|
|
})
|
|
|
];
|
|
|
|
|
|
// 应用样式数组到要素
|
|
|
feature.setStyle(styles);
|
|
|
});
|
|
|
|
|
|
map.addInteraction(currentDraw);
|
|
|
}
|
|
|
});
|
|
|
|
|
|
// 删除功能
|
|
|
document.getElementById('btn-delete').addEventListener('click', function () {
|
|
|
const isActivated = updateToolButtonState(this);
|
|
|
|
|
|
if (isActivated) {
|
|
|
// 清除所有绘制内容
|
|
|
source.clear();
|
|
|
|
|
|
// 移除当前的绘制交互
|
|
|
if (currentDraw) {
|
|
|
map.removeInteraction(currentDraw);
|
|
|
currentDraw = null;
|
|
|
}
|
|
|
|
|
|
// 删除功能执行后自动取消激活状态
|
|
|
setTimeout(() => {
|
|
|
if (activeToolButton === this) {
|
|
|
this.classList.remove('active');
|
|
|
activeToolButton = null;
|
|
|
}
|
|
|
}, 300);
|
|
|
}
|
|
|
});
|
|
|
|
|
|
// 点击地图其他区域时取消绘制
|
|
|
map.on('click', function (e) {
|
|
|
// 可以在这里添加点击事件处理
|
|
|
});
|
|
|
|
|
|
|
|
|
// 修改风险预报图初始化代码,存储实例
|
|
|
const riskCtx = document.getElementById('riskChart').getContext('2d');
|
|
|
window.charts.riskChart = new Chart(riskCtx, {
|
|
|
type: 'bar',
|
|
|
data: {
|
|
|
labels: ['波浪', '海流', '电导率', '潮位', '水温', '溶解氧', '叶绿素', '浊度', 'PH值'],
|
|
|
datasets: [{
|
|
|
label: '风险指数',
|
|
|
data: [15, 65, 20, 60, 25, 18, 22, 55, 85],
|
|
|
backgroundColor: [
|
|
|
'rgba(75, 192, 192, 0.7)',
|
|
|
'rgba(255, 206, 86, 0.7)',
|
|
|
'rgba(75, 192, 192, 0.7)',
|
|
|
'rgba(255, 206, 86, 0.7)',
|
|
|
'rgba(75, 192, 192, 0.7)',
|
|
|
'rgba(75, 192, 192, 0.7)',
|
|
|
'rgba(75, 192, 192, 0.7)',
|
|
|
'rgba(255, 206, 86, 0.7)',
|
|
|
'rgba(255, 99, 132, 0.7)'
|
|
|
],
|
|
|
borderColor: [
|
|
|
'rgba(75, 192, 192, 1)',
|
|
|
'rgba(255, 206, 86, 1)',
|
|
|
'rgba(75, 192, 192, 1)',
|
|
|
'rgba(255, 206, 86, 1)',
|
|
|
'rgba(75, 192, 192, 1)',
|
|
|
'rgba(75, 192, 192, 1)',
|
|
|
'rgba(75, 192, 192, 1)',
|
|
|
'rgba(255, 206, 86, 1)',
|
|
|
'rgba(255, 99, 132, 1)'
|
|
|
],
|
|
|
borderWidth: 1,
|
|
|
barPercentage: 0.5,
|
|
|
categoryPercentage: 0.8
|
|
|
}]
|
|
|
},
|
|
|
options: {
|
|
|
responsive: true,
|
|
|
maintainAspectRatio: false,
|
|
|
scales: {
|
|
|
y: {
|
|
|
beginAtZero: true,
|
|
|
title: {
|
|
|
display: true,
|
|
|
text: '风险指数'
|
|
|
},
|
|
|
max: 100
|
|
|
}
|
|
|
},
|
|
|
plugins: {
|
|
|
legend: {
|
|
|
display: true,
|
|
|
position: 'top',
|
|
|
labels: {
|
|
|
usePointStyle: true,
|
|
|
generateLabels: function (chart) {
|
|
|
return [
|
|
|
{
|
|
|
text: '无风险',
|
|
|
fillStyle: 'rgba(75, 192, 192, 0.7)',
|
|
|
strokeStyle: 'rgba(75, 192, 192, 1)',
|
|
|
lineWidth: 1,
|
|
|
pointStyle: 'rect',
|
|
|
fontColor: '#666'
|
|
|
},
|
|
|
{
|
|
|
text: '一般风险',
|
|
|
fillStyle: 'rgba(255, 206, 86, 0.7)',
|
|
|
strokeStyle: 'rgba(255, 206, 86, 1)',
|
|
|
lineWidth: 1,
|
|
|
pointStyle: 'rect',
|
|
|
fontColor: '#666'
|
|
|
},
|
|
|
{
|
|
|
text: '重大风险',
|
|
|
fillStyle: 'rgba(255, 99, 132, 0.7)',
|
|
|
strokeStyle: 'rgba(255, 99, 132, 1)',
|
|
|
lineWidth: 1,
|
|
|
pointStyle: 'rect',
|
|
|
fontColor: '#666'
|
|
|
}
|
|
|
];
|
|
|
}
|
|
|
}
|
|
|
},
|
|
|
tooltip: {
|
|
|
callbacks: {
|
|
|
label: function (context) {
|
|
|
let label = context.dataset.label || '';
|
|
|
if (label) {
|
|
|
label += ': ';
|
|
|
}
|
|
|
if (context.parsed.y !== null) {
|
|
|
label += context.parsed.y + '分';
|
|
|
}
|
|
|
return label;
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
});
|
|
|
|
|
|
// 数据类型对应的单位
|
|
|
const dataUnits = {
|
|
|
'流速': 'm/s',
|
|
|
'波浪': 'cm',
|
|
|
'温盐': '‰',
|
|
|
'海流': 'cm/s',
|
|
|
'浊度': 'NTU',
|
|
|
'PH': '',
|
|
|
'溶解氧': 'mg/L',
|
|
|
'叶绿素': 'μg/L',
|
|
|
'电导率': 'mS/cm',
|
|
|
'潮位': 'm',
|
|
|
'流向': '°'
|
|
|
};
|
|
|
|
|
|
// 全局变量存储图表实例
|
|
|
window.dataChartInstance = null;
|
|
|
|
|
|
// 模拟数据
|
|
|
function generateMockData(dataType, startDate, endDate) {
|
|
|
const start = new Date(startDate);
|
|
|
const end = new Date(endDate);
|
|
|
const data = [];
|
|
|
|
|
|
// 计算时间间隔(10分钟)
|
|
|
const interval = 10 * 60 * 1000; // 10分钟毫秒数
|
|
|
const points = Math.min(100, Math.floor((end - start) / interval)); // 最多100个点
|
|
|
|
|
|
for (let i = 0; i <= points; i++) {
|
|
|
const time = new Date(start.getTime() + i * interval);
|
|
|
const timeStr = time.toISOString().slice(0, 16).replace('T', ' ');
|
|
|
|
|
|
// 根据数据类型生成不同的模拟数据
|
|
|
let value;
|
|
|
switch (dataType) {
|
|
|
case '流速':
|
|
|
value = (0.4 + Math.random() * 0.3).toFixed(3);
|
|
|
break;
|
|
|
case '波浪':
|
|
|
value = (10 + Math.random() * 20).toFixed(1);
|
|
|
break;
|
|
|
case '温盐':
|
|
|
value = (30 + Math.random() * 5).toFixed(1);
|
|
|
break;
|
|
|
case '海流':
|
|
|
value = (20 + Math.random() * 30).toFixed(1);
|
|
|
break;
|
|
|
case '浊度':
|
|
|
value = (10 + Math.random() * 10).toFixed(1);
|
|
|
break;
|
|
|
case 'PH':
|
|
|
value = (7.5 + Math.random() * 0.8).toFixed(1);
|
|
|
break;
|
|
|
case '溶解氧':
|
|
|
value = (5 + Math.random() * 3).toFixed(1);
|
|
|
break;
|
|
|
case '叶绿素':
|
|
|
value = (0.5 + Math.random() * 0.5).toFixed(2);
|
|
|
break;
|
|
|
case '电导率':
|
|
|
value = (20 + Math.random() * 10).toFixed(1);
|
|
|
break;
|
|
|
case '潮位':
|
|
|
value = (2 + Math.random() * 2).toFixed(1);
|
|
|
break;
|
|
|
case '流向':
|
|
|
value = Math.floor(Math.random() * 360);
|
|
|
break;
|
|
|
default:
|
|
|
value = (Math.random() * 100).toFixed(2);
|
|
|
}
|
|
|
|
|
|
data.push({
|
|
|
time: timeStr,
|
|
|
value: value
|
|
|
});
|
|
|
}
|
|
|
|
|
|
return data;
|
|
|
}
|
|
|
|
|
|
// 修改数据图表更新函数,确保存储实例
|
|
|
function updateChartData() {
|
|
|
const dataType = document.getElementById('dataTypeSelect').value;
|
|
|
const startDate = document.getElementById('startDate').value;
|
|
|
const endDate = document.getElementById('endDate').value;
|
|
|
|
|
|
document.getElementById('dataColumnType').textContent = `${dataType}(${dataUnits[dataType]})`;
|
|
|
|
|
|
const data = generateMockData(dataType, startDate, endDate);
|
|
|
|
|
|
const tableBody = document.getElementById('dataTableBody');
|
|
|
tableBody.innerHTML = '';
|
|
|
data.forEach(item => {
|
|
|
const row = document.createElement('tr');
|
|
|
row.innerHTML = `
|
|
|
<td>${item.time}</td>
|
|
|
<td>${item.value}</td>
|
|
|
`;
|
|
|
tableBody.appendChild(row);
|
|
|
});
|
|
|
|
|
|
const labels = data.map(item => item.time);
|
|
|
const values = data.map(item => parseFloat(item.value));
|
|
|
|
|
|
if (window.dataChartInstance) {
|
|
|
window.dataChartInstance.destroy();
|
|
|
}
|
|
|
|
|
|
const chartContainer = document.querySelector('.chart-wrapper');
|
|
|
const canvas = document.getElementById('dataChart');
|
|
|
|
|
|
canvas.style.height = '100%';
|
|
|
canvas.style.width = '100%';
|
|
|
|
|
|
const dataCtx = canvas.getContext('2d');
|
|
|
window.dataChartInstance = new Chart(dataCtx, {
|
|
|
type: 'line',
|
|
|
data: {
|
|
|
labels: labels,
|
|
|
datasets: [{
|
|
|
label: `${dataType} (${dataUnits[dataType]})`,
|
|
|
data: values,
|
|
|
borderColor: 'rgba(26, 107, 201, 1)',
|
|
|
backgroundColor: 'transparent',
|
|
|
borderWidth: 2,
|
|
|
tension: 0.4,
|
|
|
fill: false,
|
|
|
pointRadius: 3,
|
|
|
pointBackgroundColor: 'rgba(26, 107, 201, 1)',
|
|
|
pointBorderColor: '#fff',
|
|
|
pointBorderWidth: 1,
|
|
|
pointHoverRadius: 6,
|
|
|
pointHoverBackgroundColor: 'rgba(26, 107, 201, 1)',
|
|
|
pointHoverBorderColor: '#fff'
|
|
|
}]
|
|
|
},
|
|
|
options: {
|
|
|
responsive: true,
|
|
|
maintainAspectRatio: false,
|
|
|
plugins: {
|
|
|
legend: {
|
|
|
labels: {
|
|
|
color: '#333',
|
|
|
font: {
|
|
|
size: 14
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
},
|
|
|
scales: {
|
|
|
y: {
|
|
|
beginAtZero: false,
|
|
|
title: {
|
|
|
display: true,
|
|
|
text: `${dataType} (${dataUnits[dataType]})`,
|
|
|
color: '#333',
|
|
|
font: {
|
|
|
size: 14
|
|
|
}
|
|
|
},
|
|
|
grid: {
|
|
|
color: 'rgba(0, 0, 0, 0.1)'
|
|
|
},
|
|
|
ticks: {
|
|
|
color: '#666'
|
|
|
}
|
|
|
},
|
|
|
x: {
|
|
|
title: {
|
|
|
display: true,
|
|
|
text: '时间',
|
|
|
color: '#333',
|
|
|
font: {
|
|
|
size: 14
|
|
|
}
|
|
|
},
|
|
|
grid: {
|
|
|
color: 'rgba(0, 0, 0, 0.1)'
|
|
|
},
|
|
|
ticks: {
|
|
|
maxRotation: 45,
|
|
|
minRotation: 45,
|
|
|
color: '#666',
|
|
|
callback: function (value, index) {
|
|
|
const step = Math.ceil(labels.length / 9);
|
|
|
if (index % step === 0 || index === labels.length - 1) {
|
|
|
return labels[index].slice(11);
|
|
|
}
|
|
|
return '';
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
});
|
|
|
|
|
|
setTimeout(() => {
|
|
|
if (window.dataChartInstance) {
|
|
|
window.dataChartInstance.resize();
|
|
|
}
|
|
|
}, 100);
|
|
|
}
|
|
|
|
|
|
// 初始化图表和数据
|
|
|
updateChartData();
|
|
|
|
|
|
// 监听选择变化
|
|
|
document.getElementById('dataTypeSelect').addEventListener('change', updateChartData);
|
|
|
document.getElementById('startDate').addEventListener('change', updateChartData);
|
|
|
document.getElementById('endDate').addEventListener('change', updateChartData);
|
|
|
});
|
|
|
|
|
|
</script>
|
|
|
</body>
|
|
|
|
|
|
</html> |