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.

1557 lines
64 KiB
HTML

<!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="/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" />
<script src="/common/script/chart.min.js"></script>
<style>
/* 整个滚动条 */
::-webkit-scrollbar {
width: 8px;
height: 6px;
}
/* 滚动条轨道 */
::-webkit-scrollbar-track {
background: #0c2a49;
border-radius: 10px;
}
/* 滚动条滑块 */
::-webkit-scrollbar-thumb {
background: #107df2;
border-radius: 10px;
border: 2px solid #0c2a49;
}
/* 滚动条滑块悬停状态 */
::-webkit-scrollbar-thumb:hover {
background: #107df2;
}
/* 数据表格容器滚动条 */
.data-table-container::-webkit-scrollbar {
width: 8px;
height: 8px;
}
.data-table-container::-webkit-scrollbar-track {
background: #0c2a49;
border-radius: 4px;
}
.data-table-container::-webkit-scrollbar-thumb {
background: linear-gradient(180deg, #107df2, #107df2);
border-radius: 4px;
}
.data-table-container::-webkit-scrollbar-thumb:hover {
background: linear-gradient(180deg, #107df2, #107df2);
}
:root {
--primary-blue: #0c2a49;
--secondary-blue: #0b4c7d;
--light-blue: #6a95c9;
--accent-blue: #00ffff;
--dark-blue: #091f36;
}
body {
font-family: 'Source Han Sans CN', 'Microsoft YaHei', sans-serif;
background: url('/assets/img/bg.png') no-repeat;
background-size: 100% 100%;
color: #ffffff;
min-height: 100vh;
margin: 0;
padding: 0;
}
/* 新增顶部标题栏样式 */
.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;
/* margin-bottom: 20px; */
}
.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: 16vw;
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;
/* right: 19vw; */
color: #ffffff;
display: flex;
align-items: center;
}
.topDiv .right img:nth-child(1) {
/* width: 3vh;
margin-right: 5px; */
}
.topDiv .right span {
font-weight: bold;
font-size: 1.2vw;
}
.topDiv .icon-home {
position: absolute;
top: 1vh;
right: 8vw;
width: 4vh;
cursor: pointer;
}
/* 修改标签页样式 */
.nav-tabs {
background-color: rgba(12, 42, 73, 0.4);
border-bottom: 2px solid var(--light-blue);
padding: 0 10px;
border-radius: 0 0 8px 8px;
margin-top: 0;
}
.nav-tabs .nav-link {
color: #a0cfff;
font-weight: bold;
border: none;
padding: 12px 20px;
border-radius: 8px 8px 0 0 !important;
margin-right: 5px;
transition: all 0.3s ease;
background-color: transparent;
}
.nav-tabs .nav-link.active {
background-color: rgba(12, 42, 73, 0.8);
color: var(--accent-blue);
border: 1px solid var(--light-blue);
border-bottom: none;
box-shadow: 0 -2px 5px rgba(0, 0, 0, 0.3);
}
.nav-tabs .nav-link:hover:not(.active) {
background-color: rgba(11, 76, 125, 0.5);
color: var(--accent-blue);
}
/* 确保卡片高度一致 */
.card {
height: 100%;
border-radius: 8px;
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.3);
border: 1px solid var(--light-blue);
margin-bottom: 20px;
background-color: rgba(12, 42, 73, 0.4);
backdrop-filter: blur(5px);
}
/* 修改卡片头部样式参考siguanIndex.vue中的标题样式 */
.card-header {
height: 6vh;
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: 12px 20px;
position: relative;
}
.card-header span {
font-size: 2.4vh;
letter-spacing: 0.2vh;
font-family: YouSheBiaoTiHei;
font-weight: 400;
color: #ffffff;
}
/* 修改卡片内容区域样式参考siguanIndex.vue中的.contentDiv背景色 */
.card-body {
background-color: rgba(12, 42, 73, 0.4); /* 参考siguanIndex.vue中的.contentDiv背景色 */
backdrop-filter: blur(0px);
padding: 1vh 1vw;
box-sizing: border-box;
}
/* 左侧上部卡片(监测站点和监测指标)的特殊处理 */
.row>.col-md-6>.row>.col-md-6>.card {
height: calc(100% - 20px);
margin-bottom: 20px;
}
/* 左侧地图卡片 */
.row>.col-md-6>.card {
height: calc(100% - 235px);
margin-bottom: 0;
}
/* 右侧设备状态卡片高度调整 */
#realtime .col-md-6:last-child .card:last-child {
height: calc(100% - 20px);
}
.monitor-section {
background-color: rgba(12, 42, 73, 0.3);
padding: 20px;
border-radius: 8px;
border: 1px solid var(--light-blue);
}
.data-item {
margin-bottom: 15px;
padding-bottom: 10px;
border-bottom: 1px dashed var(--light-blue);
}
.data-label {
font-weight: bold;
color: var(--accent-blue);
}
/* 新增:设置监测指标文本颜色为白色 */
.monitoring-indicators {
color: #ffffff;
}
/* 地图容器样式调整 */
.map-container {
height: 100%;
background-color: rgba(14, 50, 87, 0.6);
border-radius: 8px;
border: 1px solid var(--light-blue);
position: relative;
}
.tab-content {
background-color: transparent;
border-radius: 0 0 8px 8px;
margin-top: 10px;
}
.warning-panel {
background-color: rgba(255, 100, 0, 0.2);
border-left: 4px solid #ff9900;
padding: 15px;
margin-bottom: 20px;
border: 1px solid var(--light-blue);
border-radius: 0 8px 8px 0;
}
.btn-action {
background: linear-gradient(to right, var(--secondary-blue), var(--light-blue));
color: white;
margin-right: 10px;
margin-bottom: 10px;
border: 1px solid var(--light-blue);
}
.btn-action:hover {
background: linear-gradient(to right, var(--light-blue), var(--secondary-blue));
color: white;
box-shadow: 0 0 10px var(--accent-blue);
}
.btn-export {
background: linear-gradient(to right, #28a745, #1e7e34);
color: white;
border: 1px solid #28a745;
}
.data-table {
font-size: 14px;
color: #ffffff;
}
.data-table td {
background-color: rgba(12, 42, 73, 0.3);
color: #ffffff; /* 设置表格数据字体为白色 */
}
.data-table th {
background-color: rgba(11, 76, 125, 0.8);
color: var(--accent-blue);
}
.data-table td {
background-color: rgba(12, 42, 73, 0.3);
}
.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: url('/assets/img/common/kva2.png') no-repeat;
background-size: 100% 100%;
border-radius: 8px;
padding: 15px 10px;
text-align: center;
border: 1px solid var(--light-blue);
}
.kpi-value {
font-size: 16px;
font-weight: bold;
color: var(--accent-blue);
margin-bottom: 5px;
}
.kpi-label {
font-size: 12px;
color: #ffffff;
}
/* 数据查询区域样式 */
.data-query-container {
display: flex;
height: calc(100vh - 160px);
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 - 330px);
}
.chart-wrapper canvas {
width: 100% !important;
height: 100% !important;
max-height: calc(100vh - 330px);
}
/* 地图工具栏按钮选中状态样式 */
.btn-map-tool {
background-color: rgba(11, 76, 125, 0.8);
border: 1px solid var(--light-blue);
color: #ffffff;
margin-bottom: 2px;
}
.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:hover {
background-color: rgba(0, 255, 255, 0.3);
color: #ffffff;
}
.btn-map-tool:focus {
box-shadow: 0 0 0 0.2rem rgba(0, 255, 255, 0.25);
}
/* 应急处理按钮布局优化 */
.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: 1px solid #ff6b6b;
padding: 12px 15px;
font-weight: bold;
transition: all 0.3s ease;
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.3);
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.4);
color: white;
border-color: #ee5a24;
}
.btn-emergency:active {
transform: translateY(0);
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.3);
}
.btn-emergency i {
margin-right: 8px;
}
/* 表单控件样式 */
.form-control, .form-select {
background-color: rgba(11, 76, 125, 0.5);
border: 1px solid var(--light-blue);
color: #ffffff;
}
.form-control:focus, .form-select:focus {
background-color: rgba(11, 76, 125, 0.8);
border-color: var(--accent-blue);
color: #ffffff;
box-shadow: 0 0 0 0.2rem rgba(0, 255, 255, 0.25);
}
.form-label {
color: var(--accent-blue);
}
/* 下拉选择框特殊样式 */
select.form-select {
background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3e%3cpath fill='none' stroke='%2300ffff' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='m2 5 6 6 6-6'/%3e%3c/svg%3e");
background-repeat: no-repeat;
background-position: right 0.75rem center;
background-size: 16px 12px;
}
/*
.main {
padding: 0 2vw 2vh;
} */
</style>
</head>
<body>
<div class="main">
<!-- 新增顶部标题栏 -->
<div class="topDiv">
<div class="left">
<span id="current-date">2025年9月17日</span>
<span id="current-time">15:18:00</span>
</div>
<div class="center">海底监测与灾害预警系统管理平台</div>
<div class="right">
<img src="/common/images/logo_gt.png" alt="" />
<!-- <span>26℃</span> -->
</div>
<!-- <img class="icon-home" src="/common/images/icon-home.png" alt="" /> -->
</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">
<span>监测站点</span>
</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>
<span class="monitoring-indicators">东营市河西仙镇</span>
</div>
</div>
</div>
</div>
<div class="col-md-6">
<div class="card">
<div class="card-header">
<span>监测指标</span>
</div>
<div class="card-body">
<div class="data-item">
<span class="data-label">水文:</span>
<span class="monitoring-indicators">波浪 温盐 海流</span>
</div>
<div class="data-item">
<span class="data-label">水质:</span>
<span class="monitoring-indicators">浊度 PH 溶解氧 叶绿素</span>
</div>
</div>
</div>
</div>
</div>
<div class="card">
<div class="card-header">
<span>地图</span>
</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="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 style="color: #fff;">正常运行</span>
</div>
<div class="card mt-3">
<div class="card-header">
<span>水文</span>
</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">
<span>水质</span>
</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">
<span>设备状态</span>
</div>
<div class="card-body">
<div class="data-item">
<span class="data-label">水文监测设备:</span> <span style="color: #fff;">正常运行</span>
</div>
<div class="data-item">
<span class="data-label">水质监测设备:</span> <span style="color: #fff;">正常运行</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">
<span>风险预报图</span>
</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">
<span>应急处理</span>
</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">
<span>数据查询</span>
</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>
</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>
// 更新时间和日期
function updateDateTime() {
const now = new Date();
const dateStr = now.getFullYear() + '年' + (now.getMonth() + 1) + '月' + now.getDate() + '日';
const timeStr = now.getHours().toString().padStart(2, '0') + ':' +
now.getMinutes().toString().padStart(2, '0') + ':' +
now.getSeconds().toString().padStart(2, '0');
document.getElementById('current-date').textContent = dateStr;
document.getElementById('current-time').textContent = timeStr;
}
// 每秒更新一次时间
setInterval(updateDateTime, 1000);
updateDateTime(); // 初始化时间
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
}),
}),
]
// 创建地图
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, 255, 255, 0.8)',
lineDash: [10, 10],
width: 2
}),
image: new ol.style.Circle({
radius: 5,
stroke: new ol.style.Stroke({
color: 'rgba(0, 255, 255, 0.8)'
}),
fill: new ol.style.Fill({
color: 'rgba(0, 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, 255, 255, 0.8)',
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(255, 255, 255, 1)'
}),
stroke: new ol.style.Stroke({
color: 'rgba(0, 0, 0, 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(0, 255, 255, 0.7)',
'rgba(255, 206, 86, 0.7)',
'rgba(0, 255, 255, 0.7)',
'rgba(255, 206, 86, 0.7)',
'rgba(0, 255, 255, 0.7)',
'rgba(0, 255, 255, 0.7)',
'rgba(0, 255, 255, 0.7)',
'rgba(255, 206, 86, 0.7)',
'rgba(255, 99, 132, 0.7)'
],
borderColor: [
'rgba(0, 255, 255, 1)',
'rgba(255, 206, 86, 1)',
'rgba(0, 255, 255, 1)',
'rgba(255, 206, 86, 1)',
'rgba(0, 255, 255, 1)',
'rgba(0, 255, 255, 1)',
'rgba(0, 255, 255, 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: '风险指数',
color: '#00ffff'
},
max: 100,
grid: {
color: 'rgba(106, 149, 201, 0.3)'
},
ticks: {
color: '#ffffff'
}
},
x: {
grid: {
color: 'rgba(106, 149, 201, 0.3)'
},
ticks: {
color: '#ffffff'
}
}
},
plugins: {
legend: {
display: true,
position: 'top',
labels: {
color: '#ffffff',
usePointStyle: true,
generateLabels: function (chart) {
return [
{
text: '无风险',
fillStyle: 'rgba(0, 255, 255, 0.7)',
strokeStyle: 'rgba(0, 255, 255, 1)',
lineWidth: 1,
pointStyle: 'rect',
fontColor: '#ffffff'
},
{
text: '一般风险',
fillStyle: 'rgba(255, 206, 86, 0.7)',
strokeStyle: 'rgba(255, 206, 86, 1)',
lineWidth: 1,
pointStyle: 'rect',
fontColor: '#ffffff'
},
{
text: '重大风险',
fillStyle: 'rgba(255, 99, 132, 0.7)',
strokeStyle: 'rgba(255, 99, 132, 1)',
lineWidth: 1,
pointStyle: 'rect',
fontColor: '#ffffff'
}
];
}
}
},
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(0, 255, 255, 1)',
backgroundColor: 'transparent',
borderWidth: 2,
tension: 0.4,
fill: false,
pointRadius: 3,
pointBackgroundColor: 'rgba(0, 255, 255, 1)',
pointBorderColor: '#fff',
pointBorderWidth: 1,
pointHoverRadius: 6,
pointHoverBackgroundColor: 'rgba(0, 255, 255, 1)',
pointHoverBorderColor: '#fff'
}]
},
options: {
responsive: true,
maintainAspectRatio: false,
plugins: {
legend: {
labels: {
color: '#ffffff',
font: {
size: 14
}
}
}
},
scales: {
y: {
beginAtZero: false,
title: {
display: true,
text: `${dataType} (${dataUnits[dataType]})`,
color: '#00ffff',
font: {
size: 14
}
},
grid: {
color: 'rgba(106, 149, 201, 0.3)'
},
ticks: {
color: '#ffffff'
}
},
x: {
title: {
display: true,
text: '时间',
color: '#00ffff',
font: {
size: 14
}
},
grid: {
color: 'rgba(106, 149, 201, 0.3)'
},
ticks: {
maxRotation: 45,
minRotation: 45,
color: '#ffffff',
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>