feat: 环境监测历史数据详情页增加评定等级列及知识科普页面完善

- 四个子模块监测数据详情页末列增加评定等级(室内/室外空气质量指数、水质等级、过敏等级)
- 花粉知识科普页面从占位页改为完整列表页,含筛选、富文本编辑抽屉弹窗
- 文章内容改为富文本维护方式,弹窗改为右侧抽屉样式

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-05-15 17:34:08 +08:00
co-authored by Claude Opus 4.6
parent 53ba505739
commit afaa3baa38
43 changed files with 6745 additions and 514 deletions
@@ -3,7 +3,7 @@
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>健康监测 - 应用记录 | 健康长庆原型</title>
<title>室内空气 - 应用记录 | 健康长庆原型</title>
<style>
*{box-sizing:border-box;margin:0;padding:0;}
body{font-family:-apple-system,BlinkMacSystemFont,'PingFang SC','Microsoft YaHei',sans-serif;background:#F5F7FA;color:#333;min-width:1280px;}
@@ -40,9 +40,49 @@
.sidebar-subgroup.open>.sidebar-subgroup__body{display:block;}
.sidebar-subgroup__body .sidebar-item{padding-left:36px;font-size:12px;}
.main{margin-left:240px;margin-top:56px;padding:24px;min-height:calc(100vh - 56px);}
.page-placeholder{display:flex;flex-direction:column;align-items:center;justify-content:center;height:calc(100vh - 56px - 48px);color:var(--text-placeholder);gap:12px;}
.page-placeholder svg{opacity:.25;}
.page-placeholder p{font-size:var(--font-base);}
/* 筛选栏 */
.filter-bar{background:#fff;border-radius:var(--radius-md);padding:20px 24px;margin-bottom:16px;box-shadow:var(--shadow-sm);display:flex;align-items:center;gap:16px;flex-wrap:wrap;}
.filter-item{display:flex;align-items:center;gap:8px;}
.filter-item label{font-size:var(--font-sm);color:var(--text-secondary);white-space:nowrap;}
.filter-input{height:36px;border:1px solid var(--border);border-radius:var(--radius-sm);padding:0 12px;font-size:var(--font-sm);color:var(--text-primary);outline:none;background:#fff;min-width:180px;}
.filter-input:focus{border-color:var(--primary);}
.filter-select{height:36px;border:1px solid var(--border);border-radius:var(--radius-sm);padding:0 28px 0 12px;font-size:var(--font-sm);color:var(--text-primary);outline:none;background:#fff url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6'%3E%3Cpath d='M0 0l5 6 5-6z' fill='%23999'/%3E%3C/svg%3E") no-repeat right 10px center;appearance:none;cursor:pointer;min-width:140px;}
.btn{height:36px;padding:0 16px;border-radius:var(--radius-sm);font-size:var(--font-sm);cursor:pointer;border:none;transition:all .2s;display:inline-flex;align-items:center;gap:6px;}
.btn-primary{background:var(--primary);color:#fff;}.btn-primary:hover{background:#40a9ff;}
.btn-default{background:#fff;color:var(--text-primary);border:1px solid var(--border);}.btn-default:hover{color:var(--primary);border-color:var(--primary);}
.action-bar{display:flex;align-items:center;gap:12px;margin-bottom:16px;}
/* 表格 */
.table-card{background:#fff;border-radius:var(--radius-md);box-shadow:var(--shadow-sm);overflow:hidden;}
.table-card__content{overflow-x:auto;-webkit-overflow-scrolling:touch;}
table{width:100%;border-collapse:collapse;min-width:1200px;}
thead th{background:#FAFAFA;padding:12px 14px;text-align:center;font-size:var(--font-xs);color:var(--text-secondary);font-weight:500;border-bottom:1px solid var(--border);border-right:1px solid var(--border);white-space:nowrap;}
thead th:last-child{border-right:none;}
thead th.th-left{text-align:left;}
tbody td{padding:12px 14px;font-size:var(--font-xs);color:var(--text-primary);border-bottom:1px solid var(--border);text-align:center;white-space:nowrap;}
tbody td.td-left{text-align:left;}
tbody tr:last-child td{border-bottom:none;}
tbody tr:hover{background:#F8FBFF;}
/* 固定列 */
thead tr:first-child th:nth-child(-n+2),tbody td:nth-child(-n+2){position:sticky;z-index:2;}
thead tr:first-child th:nth-child(-n+2){z-index:3;}
thead tr:first-child th:nth-child(1),tbody td:nth-child(1){left:0;}
thead tr:first-child th:nth-child(2),tbody td:nth-child(2){left:140px;}
tbody td:nth-child(-n+2){background:#fff;}
tbody tr:hover td:nth-child(-n+2){background:#F8FBFF;}
tbody td:nth-child(2),thead tr:first-child th:nth-child(2){box-shadow:2px 0 4px rgba(0,0,0,0.06);}
/* 排序表头 */
.th-sort{cursor:pointer;user-select:none;position:relative;padding-right:22px !important;}
.th-sort:hover{color:var(--primary);}
.th-sort .sort-icon{position:absolute;right:4px;top:50%;transform:translateY(-50%);display:flex;flex-direction:column;gap:1px;}
.th-sort .sort-icon .arrow-up,.th-sort .sort-icon .arrow-down{width:0;height:0;border-left:4px solid transparent;border-right:4px solid transparent;}
.th-sort .sort-icon .arrow-up{border-bottom:5px solid #ccc;}
.th-sort .sort-icon .arrow-down{border-top:5px solid #ccc;}
.th-sort.asc .sort-icon .arrow-up{border-bottom-color:var(--primary);}
.th-sort.desc .sort-icon .arrow-down{border-top-color:var(--primary);}
.pagination{display:flex;align-items:center;justify-content:flex-end;padding:16px 24px;gap:8px;border-top:1px solid var(--border);}
.pagination span{font-size:var(--font-sm);color:var(--text-secondary);}
.page-btn{width:32px;height:32px;border:1px solid var(--border);border-radius:var(--radius-sm);background:#fff;cursor:pointer;font-size:var(--font-sm);display:inline-flex;align-items:center;justify-content:center;transition:all .2s;}
.page-btn:hover,.page-btn.active{background:var(--primary);color:#fff;border-color:var(--primary);}
</style>
</head>
<body>
@@ -57,10 +97,7 @@
<a href="../exception-dirty.html">异常事件</a>
</nav>
<div class="top-bar__right">
<a class="btn-back" href="../../../index.html">
<svg width="16" height="16" viewBox="0 0 16 16" fill="none"><path d="M10 3L5 8l5 5" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/></svg>
返回首页
</a>
<a class="btn-back" href="../../../index.html"><svg width="16" height="16" viewBox="0 0 16 16" fill="none"><path d="M10 3L5 8l5 5" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/></svg> 返回首页</a>
<div class="avatar"></div>
<span style="color:rgba(255,255,255,0.65);">系统管理员 ▾</span>
</div>
@@ -114,11 +151,112 @@
</div>
</aside>
<main class="main">
<div class="page-placeholder">
<svg width="64" height="64" viewBox="0 0 64 64" fill="none"><rect x="8" y="8" width="48" height="48" rx="8" stroke="#ccc" stroke-width="2"/><path d="M20 32h24M32 20v24" stroke="#ccc" stroke-width="2" stroke-linecap="round"/></svg>
<p>应用记录</p>
<!-- 筛选条件 -->
<div class="filter-bar">
<div class="filter-item"><label>设备名称</label><input class="filter-input" placeholder="请输入设备名称"></div>
<div class="filter-item"><label>设备编码</label><input class="filter-input" placeholder="请输入设备编码"></div>
<div class="filter-item"><label>所属单位</label>
<select class="filter-select"><option value="">全部</option><option>采油一厂</option><option>采油二厂</option><option>采油三厂</option></select>
</div>
<button class="btn btn-primary">查询</button>
<button class="btn btn-default">重置</button>
</div>
<!-- 操作按钮 -->
<div class="action-bar">
<button class="btn btn-default">导出列表数据</button>
</div>
<!-- 数据列表 -->
<div class="table-card">
<div class="table-card__content">
<table id="appTable">
<thead>
<tr>
<th rowspan="2" class="th-left" style="min-width:140px;">设备名称</th>
<th rowspan="2" style="min-width:110px;">设备编码</th>
<th rowspan="2" style="min-width:90px;">所属单位</th>
<th rowspan="2" style="min-width:130px;">设备位置</th>
<th colspan="7">移动端点击次数</th>
</tr>
<tr>
<th class="th-sort" data-col="4" onclick="sortTable(this)">温度<span class="sort-icon"><span class="arrow-up"></span><span class="arrow-down"></span></span></th>
<th class="th-sort" data-col="5" onclick="sortTable(this)">湿度<span class="sort-icon"><span class="arrow-up"></span><span class="arrow-down"></span></span></th>
<th class="th-sort" data-col="6" onclick="sortTable(this)">CO₂<span class="sort-icon"><span class="arrow-up"></span><span class="arrow-down"></span></span></th>
<th class="th-sort" data-col="7" onclick="sortTable(this)">甲醛<span class="sort-icon"><span class="arrow-up"></span><span class="arrow-down"></span></span></th>
<th class="th-sort" data-col="8" onclick="sortTable(this)">PM2.5<span class="sort-icon"><span class="arrow-up"></span><span class="arrow-down"></span></span></th>
<th class="th-sort" data-col="9" onclick="sortTable(this)">PM10<span class="sort-icon"><span class="arrow-up"></span><span class="arrow-down"></span></span></th>
<th class="th-sort" data-col="10" onclick="sortTable(this)">总点击次数<span class="sort-icon"><span class="arrow-up"></span><span class="arrow-down"></span></span></th>
</tr>
</thead>
<tbody>
<tr>
<td class="td-left">综合空气监测仪-A01</td>
<td>IA-2024-001</td>
<td>采油一厂</td>
<td>办公楼1层大厅</td>
<td>326</td><td>218</td><td>185</td><td>412</td><td>538</td><td>295</td><td>1974</td>
</tr>
<tr>
<td class="td-left">PM2.5检测仪-B03</td>
<td>IA-2024-002</td>
<td>采油一厂</td>
<td>办公楼2层会议室</td>
<td>142</td><td>98</td><td>76</td><td>203</td><td>687</td><td>345</td><td>1551</td>
</tr>
<tr>
<td class="td-left">甲醛检测仪-C02</td>
<td>IA-2024-003</td>
<td>采油二厂</td>
<td>新装修办公室3层</td>
<td>89</td><td>56</td><td>112</td><td>856</td><td>234</td><td>128</td><td>1475</td>
</tr>
<tr>
<td class="td-left">CO2检测仪-D01</td>
<td>IA-2024-004</td>
<td>采油二厂</td>
<td>地下车库B1层</td>
<td>67</td><td>45</td><td>523</td><td>38</td><td>156</td><td>89</td><td>918</td>
</tr>
<tr>
<td class="td-left">综合空气监测仪-A05</td>
<td>IA-2024-005</td>
<td>采油三厂</td>
<td>生产车间1号</td>
<td>458</td><td>312</td><td>267</td><td>189</td><td>723</td><td>456</td><td>2405</td>
</tr>
</tbody>
</table>
</div>
<div class="pagination">
<span>共 5 条</span>
<button class="page-btn active">1</button>
</div>
</div>
</main>
<script>function toggleSubgroup(h){h.parentElement.classList.toggle('open');}(function(){var a=document.querySelector('.sidebar-item.active');if(!a)return;var s=a.closest('.sidebar-subgroup');if(s)s.classList.add('open');})();</script>
<script>
function toggleSubgroup(h){h.parentElement.classList.toggle('open');}
(function(){var a=document.querySelector('.sidebar-item.active');if(!a)return;var s=a.closest('.sidebar-subgroup');if(s)s.classList.add('open');})();
/* 排序功能 */
function sortTable(th){
var table=document.getElementById('appTable');
var tbody=table.querySelector('tbody');
var rows=Array.from(tbody.querySelectorAll('tr'));
var col=parseInt(th.getAttribute('data-col'));
/* 切换排序方向 */
var allTh=table.querySelectorAll('.th-sort');
var dir='asc';
if(th.classList.contains('asc')){dir='desc';}
else if(th.classList.contains('desc')){dir='asc';}
allTh.forEach(function(t){t.classList.remove('asc','desc');});
th.classList.add(dir);
/* 排序 */
rows.sort(function(a,b){
var va=parseInt(a.cells[col].textContent);
var vb=parseInt(b.cells[col].textContent);
return dir==='asc'?(va-vb):(vb-va);
});
rows.forEach(function(r){tbody.appendChild(r);});
}
</script>
</body>
</html>
</html>
@@ -0,0 +1,345 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>室内空气 - 动态分析 | 健康长庆原型</title>
<style>
*{box-sizing:border-box;margin:0;padding:0;}
body{font-family:-apple-system,BlinkMacSystemFont,'PingFang SC','Microsoft YaHei',sans-serif;background:#F5F7FA;color:#333;min-width:1280px;}
:root{
--primary:#1890FF;--primary-light:#E6F7FF;--success:#52C41A;--warning:#FAAD14;--danger:#FF4D4F;
--text-primary:#333;--text-secondary:#666;--text-placeholder:#999;--border:#E8E8E8;--background:#F5F7FA;
--font-xs:11px;--font-sm:13px;--font-base:15px;--font-lg:17px;
--radius-sm:4px;--radius-md:8px;--radius-lg:12px;
--shadow-sm:0 1px 4px rgba(0,0,0,0.08);
}
.top-bar{display:flex;align-items:center;height:56px;background:#001529;padding:0 24px;position:fixed;top:0;left:0;right:0;z-index:100;}
.top-bar__logo{display:flex;align-items:center;gap:8px;color:#fff;font-size:var(--font-lg);font-weight:600;white-space:nowrap;width:240px;flex-shrink:0;}
.top-bar__logo svg{width:28px;height:28px;}
.top-bar__right{display:flex;align-items:center;gap:16px;color:rgba(255,255,255,0.65);font-size:var(--font-sm);}
.btn-back{color:rgba(255,255,255,0.65);cursor:pointer;display:flex;align-items:center;gap:4px;text-decoration:none;}
.btn-back:hover{color:#fff;}
.avatar{width:32px;height:32px;border-radius:50%;background:#1890FF;display:flex;align-items:center;justify-content:center;color:#fff;font-size:var(--font-sm);cursor:pointer;}
.top-bar__nav{display:flex;align-items:center;gap:4px;flex:1;}
.top-bar__nav a{color:rgba(255,255,255,0.65);text-decoration:none;padding:6px 16px;border-radius:var(--radius-sm);font-size:var(--font-sm);transition:all .2s;}
.top-bar__nav a:hover{color:#fff;background:rgba(255,255,255,0.08);}
.top-bar__nav a.active{color:#fff;background:var(--primary);}
.sidebar{position:fixed;top:56px;left:0;bottom:0;width:240px;background:#001529;overflow-y:auto;z-index:90;padding-top:8px;}
.sidebar-menu__title{color:rgba(255,255,255,0.35);font-size:var(--font-xs);padding:16px 24px 8px;letter-spacing:.5px;}
.sidebar-item{display:flex;align-items:center;gap:8px;padding:10px 24px;color:rgba(255,255,255,0.65);font-size:var(--font-sm);cursor:pointer;transition:all .15s;text-decoration:none;}
.sidebar-item:hover{color:#fff;background:rgba(255,255,255,0.06);}
.sidebar-item.active{color:#fff;background:var(--primary);}
.sidebar-subgroup__header{display:flex;align-items:center;gap:6px;padding:10px 24px;color:rgba(255,255,255,0.65);font-size:var(--font-sm);cursor:pointer;transition:all .15s;user-select:none;}
.sidebar-subgroup__header:hover{color:rgba(255,255,255,0.85);background:rgba(255,255,255,0.04);}
.sidebar-subgroup__header .arrow{width:10px;height:10px;transition:transform .2s;flex-shrink:0;}
.sidebar-subgroup__header .arrow path{stroke:rgba(255,255,255,0.45);}
.sidebar-subgroup.open>.sidebar-subgroup__header{color:rgba(255,255,255,0.85);}
.sidebar-subgroup.open>.sidebar-subgroup__header .arrow{transform:rotate(90deg);}
.sidebar-subgroup__body{display:none;padding-left:16px;}
.sidebar-subgroup.open>.sidebar-subgroup__body{display:block;}
.sidebar-subgroup__body .sidebar-item{padding-left:36px;font-size:12px;}
.main{margin-left:240px;margin-top:56px;padding:24px;min-height:calc(100vh - 56px);}
/* 页面头部 */
.page-header{display:flex;align-items:center;gap:12px;margin-bottom:20px;}
.page-header__back{width:32px;height:32px;border-radius:var(--radius-sm);border:1px solid var(--border);background:#fff;display:flex;align-items:center;justify-content:center;cursor:pointer;text-decoration:none;color:var(--text-secondary);}
.page-header__back:hover{border-color:var(--primary);color:var(--primary);}
.page-header__title{font-size:var(--font-lg);font-weight:600;color:var(--text-primary);}
/* 左右布局 */
.analysis-layout{display:flex;gap:20px;align-items:flex-start;}
/* 左侧设备信息 */
.device-card{width:320px;flex-shrink:0;background:#fff;border-radius:var(--radius-md);box-shadow:var(--shadow-sm);overflow:hidden;}
.device-card__header{padding:16px 20px;background:linear-gradient(135deg,#1890FF 0%,#096DD9 100%);color:#fff;}
.device-card__name{font-size:var(--font-base);font-weight:600;margin-bottom:4px;}
.device-card__code{font-size:var(--font-xs);opacity:.8;}
.device-card__body{padding:16px 20px;}
.device-card__item{display:flex;justify-content:space-between;align-items:center;padding:12px 0;border-bottom:1px solid #f5f5f5;}
.device-card__item:last-child{border-bottom:none;}
.device-card__label{font-size:var(--font-sm);color:var(--text-placeholder);}
.device-card__value{font-size:var(--font-sm);color:var(--text-primary);font-weight:500;text-align:right;max-width:180px;}
.aqi-tag{display:inline-block;padding:2px 10px;border-radius:10px;font-size:var(--font-xs);font-weight:500;}
.aqi-tag--clean{background:#E6FFFB;color:#13C2C2;}
.device-card__tip{margin-top:4px;padding:12px;background:#FFFBE6;border-radius:var(--radius-sm);border:1px solid #FFE58F;}
.device-card__tip-title{font-size:var(--font-xs);font-weight:600;color:var(--warning);display:block;margin-bottom:4px;}
.device-card__tip p{font-size:var(--font-xs);color:var(--text-secondary);line-height:1.6;margin:0;}
/* 监测数据实时值 */
.realtime-section{margin-top:16px;padding-top:16px;border-top:1px solid var(--border);}
.realtime-title{font-size:var(--font-xs);color:var(--text-placeholder);margin-bottom:12px;font-weight:500;}
.realtime-grid{display:grid;grid-template-columns:1fr 1fr;gap:8px;}
.realtime-item{background:#F8FBFF;border-radius:var(--radius-sm);padding:10px 12px;text-align:center;}
.realtime-item__value{font-size:var(--font-lg);font-weight:600;color:var(--primary);margin-bottom:2px;}
.realtime-item__label{font-size:var(--font-xs);color:var(--text-placeholder);}
/* 右侧图表区域 */
.chart-panel{flex:1;background:#fff;border-radius:var(--radius-md);box-shadow:var(--shadow-sm);overflow:hidden;min-width:0;}
/* 时间范围 Tab */
.time-tabs{display:flex;gap:0;border-bottom:1px solid var(--border);padding:0 24px;}
.time-tab{padding:14px 24px;font-size:var(--font-sm);color:var(--text-secondary);cursor:pointer;border-bottom:2px solid transparent;transition:all .2s;white-space:nowrap;}
.time-tab:hover{color:var(--primary);}
.time-tab.active{color:var(--primary);border-bottom-color:var(--primary);font-weight:500;}
/* 监测类型切换 */
.metric-bar{display:flex;align-items:center;gap:8px;padding:16px 24px;border-bottom:1px solid #f5f5f5;flex-wrap:wrap;}
.metric-btn{height:32px;padding:0 14px;border-radius:16px;font-size:var(--font-xs);cursor:pointer;border:1px solid var(--border);background:#fff;color:var(--text-secondary);transition:all .2s;white-space:nowrap;}
.metric-btn:hover{color:var(--primary);border-color:var(--primary);}
.metric-btn.active{background:var(--primary);color:#fff;border-color:var(--primary);}
/* 图表区域 */
.chart-area{padding:24px;min-height:400px;}
.chart-container{width:100%;height:360px;position:relative;}
.chart-container svg{width:100%;height:100%;}
/* SVG 图表样式 */
.chart-grid-line{stroke:#f0f0f0;stroke-width:1;}
.chart-axis-label{fill:#999;font-size:11px;}
.chart-line{fill:none;stroke:var(--primary);stroke-width:2;stroke-linejoin:round;stroke-linecap:round;}
.chart-area-fill{fill:url(#areaGrad);opacity:.15;}
.chart-dot{fill:var(--primary);stroke:#fff;stroke-width:2;}
.chart-title{font-size:var(--font-sm);color:var(--text-primary);font-weight:500;margin-bottom:16px;}
.chart-summary{display:flex;gap:32px;padding:0 24px 20px;}
.chart-summary__item{display:flex;align-items:center;gap:6px;}
.chart-summary__dot{width:8px;height:8px;border-radius:50%;}
.chart-summary__label{font-size:var(--font-xs);color:var(--text-placeholder);}
.chart-summary__value{font-size:var(--font-sm);color:var(--text-primary);font-weight:600;}
</style>
</head>
<body>
<div class="top-bar">
<div class="top-bar__logo"><svg viewBox="0 0 28 28" fill="none"><rect width="28" height="28" rx="6" fill="#1890FF"/><path d="M7 14h14M14 7v14" stroke="#fff" stroke-width="2.5" stroke-linecap="round"/></svg> 健康监测</div>
<nav class="top-bar__nav">
<a href="../archive-personal.html">档案</a>
<a href="../health-checkup/survey-category.html">健康排查</a>
<a href="../wearable/tool-manage.html">穿戴监测</a>
<a href="../weight/scale-device.html">体重监测</a>
<a href="../environment/indoor-device-list.html" class="active">环境监测</a>
<a href="../exception-dirty.html">异常事件</a>
</nav>
<div class="top-bar__right">
<a class="btn-back" href="../../../index.html"><svg width="16" height="16" viewBox="0 0 16 16" fill="none"><path d="M10 3L5 8l5 5" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/></svg> 返回首页</a>
<div class="avatar"></div>
<span style="color:rgba(255,255,255,0.65);">系统管理员 ▾</span>
</div>
</div>
<aside class="sidebar">
<div class="sidebar-menu__title">环境监测</div>
<div class="sidebar-subgroup open">
<div class="sidebar-subgroup__header" onclick="toggleSubgroup(this)"><svg class="arrow" viewBox="0 0 12 12"><path d="M4 2l4 4-4 4" fill="none" stroke-width="1.5" stroke-linecap="round"/></svg> 室内空气</div>
<div class="sidebar-subgroup__body">
<a href="indoor-device-list.html" class="sidebar-item">设备列表</a>
<a href="indoor-device-category.html" class="sidebar-item">设备分类</a>
<a href="indoor-data-monitor.html" class="sidebar-item active">数据监测</a>
<a href="indoor-exception-alarm.html" class="sidebar-item">异常报警</a>
<a href="indoor-app-record.html" class="sidebar-item">应用记录</a>
<a href="indoor-history-data.html" class="sidebar-item">历史数据</a>
</div>
</div>
<div class="sidebar-subgroup">
<div class="sidebar-subgroup__header" onclick="toggleSubgroup(this)"><svg class="arrow" viewBox="0 0 12 12"><path d="M4 2l4 4-4 4" fill="none" stroke-width="1.5" stroke-linecap="round"/></svg> 室外空气</div>
<div class="sidebar-subgroup__body">
<a href="outdoor-device-list.html" class="sidebar-item">设备列表</a>
<a href="outdoor-device-category.html" class="sidebar-item">设备分类</a>
<a href="outdoor-data-monitor.html" class="sidebar-item">数据监测</a>
<a href="outdoor-exception-alarm.html" class="sidebar-item">异常报警</a>
<a href="outdoor-app-record.html" class="sidebar-item">应用记录</a>
<a href="outdoor-history-data.html" class="sidebar-item">历史数据</a>
</div>
</div>
<div class="sidebar-subgroup">
<div class="sidebar-subgroup__header" onclick="toggleSubgroup(this)"><svg class="arrow" viewBox="0 0 12 12"><path d="M4 2l4 4-4 4" fill="none" stroke-width="1.5" stroke-linecap="round"/></svg> 水质监测</div>
<div class="sidebar-subgroup__body">
<a href="water-device-list.html" class="sidebar-item">设备列表</a>
<a href="water-device-category.html" class="sidebar-item">设备分类</a>
<a href="water-data-monitor.html" class="sidebar-item">数据监测</a>
<a href="water-exception-alarm.html" class="sidebar-item">异常报警</a>
<a href="water-app-record.html" class="sidebar-item">应用记录</a>
<a href="water-history-data.html" class="sidebar-item">历史数据</a>
</div>
</div>
<div class="sidebar-subgroup">
<div class="sidebar-subgroup__header" onclick="toggleSubgroup(this)"><svg class="arrow" viewBox="0 0 12 12"><path d="M4 2l4 4-4 4" fill="none" stroke-width="1.5" stroke-linecap="round"/></svg> 花粉监测</div>
<div class="sidebar-subgroup__body">
<a href="pollen-device-list.html" class="sidebar-item">设备列表</a>
<a href="pollen-device-category.html" class="sidebar-item">设备分类</a>
<a href="pollen-data-monitor.html" class="sidebar-item">数据监测</a>
<a href="pollen-exception-alarm.html" class="sidebar-item">异常报警</a>
<a href="pollen-app-record.html" class="sidebar-item">应用记录</a>
<a href="pollen-history-data.html" class="sidebar-item">历史数据</a>
<a href="pollen-knowledge.html" class="sidebar-item">知识科普</a>
</div>
</div>
</aside>
<main class="main">
<!-- 页面头部 -->
<div class="page-header">
<a class="page-header__back" href="indoor-data-monitor.html"><svg width="16" height="16" viewBox="0 0 16 16" fill="none"><path d="M10 3L5 8l5 5" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/></svg></a>
<span class="page-header__title">动态分析</span>
</div>
<!-- 左右布局 -->
<div class="analysis-layout">
<!-- 左侧 - 设备信息 -->
<div class="device-card">
<div class="device-card__header">
<div class="device-card__name">综合空气监测仪-A01</div>
<div class="device-card__code">IA-2024-001</div>
</div>
<div class="device-card__body">
<div class="device-card__item">
<span class="device-card__label">所属单位</span>
<span class="device-card__value">采油一厂</span>
</div>
<div class="device-card__item">
<span class="device-card__label">设备位置</span>
<span class="device-card__value">办公楼1层大厅</span>
</div>
<div class="device-card__item">
<span class="device-card__label">数据更新时间</span>
<span class="device-card__value">2026-05-14 14:30</span>
</div>
<div class="device-card__item">
<span class="device-card__label">空气质量指数</span>
<span class="device-card__value"><span class="aqi-tag aqi-tag--clean">清洁</span></span>
</div>
<div class="device-card__tip">
<p>至少有一个环境污染物超标。除了敏感者外,一般不会发生慢急性中毒。</p>
</div>
<!-- 实时监测数据 -->
<div class="realtime-section">
<div class="realtime-title">实时监测数据</div>
<div class="realtime-grid">
<div class="realtime-item">
<div class="realtime-item__value">24.5</div>
<div class="realtime-item__label">温度(℃)</div>
</div>
<div class="realtime-item">
<div class="realtime-item__value">52</div>
<div class="realtime-item__label">湿度(%)</div>
</div>
<div class="realtime-item">
<div class="realtime-item__value">456</div>
<div class="realtime-item__label">CO₂(ppm)</div>
</div>
<div class="realtime-item">
<div class="realtime-item__value">0.03</div>
<div class="realtime-item__label">甲醛(mg/m³)</div>
</div>
<div class="realtime-item">
<div class="realtime-item__value">35</div>
<div class="realtime-item__label">PM2.5(μg/m³)</div>
</div>
<div class="realtime-item">
<div class="realtime-item__value">68</div>
<div class="realtime-item__label">PM10(μg/m³)</div>
</div>
</div>
</div>
</div>
</div>
<!-- 右侧 - 趋势图 -->
<div class="chart-panel">
<!-- 时间范围 Tab -->
<div class="time-tabs">
<div class="time-tab active" onclick="switchTimeTab(this)">近24小时</div>
<div class="time-tab" onclick="switchTimeTab(this)">近7日</div>
<div class="time-tab" onclick="switchTimeTab(this)">近30日</div>
<div class="time-tab" onclick="switchTimeTab(this)">近3个月</div>
</div>
<!-- 监测类型切换 -->
<div class="metric-bar">
<button class="metric-btn active" onclick="switchMetric(this,'temp')">温度</button>
<button class="metric-btn" onclick="switchMetric(this,'humi')">湿度</button>
<button class="metric-btn" onclick="switchMetric(this,'co2')">二氧化碳</button>
<button class="metric-btn" onclick="switchMetric(this,'hcho')">甲醛</button>
<button class="metric-btn" onclick="switchMetric(this,'pm25')">PM2.5</button>
<button class="metric-btn" onclick="switchMetric(this,'pm10')">PM10</button>
</div>
<!-- 统计摘要 -->
<div class="chart-summary">
<div class="chart-summary__item"><span class="chart-summary__dot" style="background:#1890FF;"></span><span class="chart-summary__label">平均值</span><span class="chart-summary__value" id="avgVal">24.3 ℃</span></div>
<div class="chart-summary__item"><span class="chart-summary__dot" style="background:#52C41A;"></span><span class="chart-summary__label">最小值</span><span class="chart-summary__value" id="minVal">21.8 ℃</span></div>
<div class="chart-summary__item"><span class="chart-summary__dot" style="background:#FF4D4F;"></span><span class="chart-summary__label">最大值</span><span class="chart-summary__value" id="maxVal">26.5 ℃</span></div>
</div>
<!-- 趋势图 -->
<div class="chart-area">
<div class="chart-container" id="chartContainer">
<svg viewBox="0 0 800 320" preserveAspectRatio="xMidYMid meet">
<defs>
<linearGradient id="areaGrad" x1="0" y1="0" x2="0" y2="1">
<stop offset="0%" stop-color="#1890FF" stop-opacity="0.3"/>
<stop offset="100%" stop-color="#1890FF" stop-opacity="0"/>
</linearGradient>
</defs>
<!-- Y 轴网格线 -->
<line x1="60" y1="20" x2="780" y2="20" class="chart-grid-line"/>
<line x1="60" y1="80" x2="780" y2="80" class="chart-grid-line"/>
<line x1="60" y1="140" x2="780" y2="140" class="chart-grid-line"/>
<line x1="60" y1="200" x2="780" y2="200" class="chart-grid-line"/>
<line x1="60" y1="260" x2="780" y2="260" class="chart-grid-line"/>
<!-- Y 轴刻度 -->
<text x="50" y="24" class="chart-axis-label" text-anchor="end">28</text>
<text x="50" y="84" class="chart-axis-label" text-anchor="end">26</text>
<text x="50" y="144" class="chart-axis-label" text-anchor="end">24</text>
<text x="50" y="204" class="chart-axis-label" text-anchor="end">22</text>
<text x="50" y="264" class="chart-axis-label" text-anchor="end">20</text>
<!-- X 轴标签 -->
<text x="90" y="290" class="chart-axis-label" text-anchor="middle">00:00</text>
<text x="180" y="290" class="chart-axis-label" text-anchor="middle">04:00</text>
<text x="270" y="290" class="chart-axis-label" text-anchor="middle">06:00</text>
<text x="360" y="290" class="chart-axis-label" text-anchor="middle">08:00</text>
<text x="450" y="290" class="chart-axis-label" text-anchor="middle">10:00</text>
<text x="540" y="290" class="chart-axis-label" text-anchor="middle">12:00</text>
<text x="630" y="290" class="chart-axis-label" text-anchor="middle">14:00</text>
<text x="720" y="290" class="chart-axis-label" text-anchor="middle">16:00</text>
<!-- X 轴线 -->
<line x1="60" y1="270" x2="780" y2="270" stroke="#d9d9d9" stroke-width="1"/>
<!-- 面积填充 -->
<path class="chart-area-fill" d="M90,200 L150,220 L210,240 L270,210 L330,170 L390,140 L450,120 L510,130 L570,110 L630,100 L690,120 L750,140 L750,270 L90,270 Z"/>
<!-- 折线 -->
<polyline class="chart-line" points="90,200 150,220 210,240 270,210 330,170 390,140 450,120 510,130 570,110 630,100 690,120 750,140"/>
<!-- 数据点 -->
<circle cx="90" cy="200" r="4" class="chart-dot"/>
<circle cx="150" cy="220" r="4" class="chart-dot"/>
<circle cx="210" cy="240" r="4" class="chart-dot"/>
<circle cx="270" cy="210" r="4" class="chart-dot"/>
<circle cx="330" cy="170" r="4" class="chart-dot"/>
<circle cx="390" cy="140" r="4" class="chart-dot"/>
<circle cx="450" cy="120" r="4" class="chart-dot"/>
<circle cx="510" cy="130" r="4" class="chart-dot"/>
<circle cx="570" cy="110" r="4" class="chart-dot"/>
<circle cx="630" cy="100" r="4" class="chart-dot"/>
<circle cx="690" cy="120" r="4" class="chart-dot"/>
<circle cx="750" cy="140" r="4" class="chart-dot"/>
</svg>
</div>
</div>
</div>
</div>
</main>
<script>
function toggleSubgroup(h){h.parentElement.classList.toggle('open');}
(function(){var a=document.querySelector('.sidebar-item.active');if(!a)return;var s=a.closest('.sidebar-subgroup');if(s)s.classList.add('open');})();
/* 时间范围 Tab 切换 */
function switchTimeTab(el){
var tabs = document.querySelectorAll('.time-tab');
tabs.forEach(function(t){t.classList.remove('active');});
el.classList.add('active');
}
/* 监测类型切换 */
var metricData = {
temp: {avg:'24.3 ℃', min:'21.8 ℃', max:'26.5 ℃'},
humi: {avg:'55 %', min:'42 %', max:'68 %'},
co2: {avg:'480 ppm',min:'380 ppm',max:'620 ppm'},
hcho: {avg:'0.04 mg/m³',min:'0.02 mg/m³',max:'0.07 mg/m³'},
pm25: {avg:'38 μg/m³', min:'22 μg/m³', max:'56 μg/m³'},
pm10: {avg:'72 μg/m³', min:'45 μg/m³', max:'98 μg/m³'}
};
function switchMetric(el, key){
var btns = document.querySelectorAll('.metric-btn');
btns.forEach(function(b){b.classList.remove('active');});
el.classList.add('active');
var d = metricData[key];
document.getElementById('avgVal').textContent = d.avg;
document.getElementById('minVal').textContent = d.min;
document.getElementById('maxVal').textContent = d.max;
}
</script>
</body>
</html>
@@ -3,7 +3,7 @@
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>健康监测 - 数据监测 | 健康长庆原型</title>
<title>室内空气 - 数据监测 | 健康长庆原型</title>
<style>
*{box-sizing:border-box;margin:0;padding:0;}
body{font-family:-apple-system,BlinkMacSystemFont,'PingFang SC','Microsoft YaHei',sans-serif;background:#F5F7FA;color:#333;min-width:1280px;}
@@ -40,9 +40,51 @@
.sidebar-subgroup.open>.sidebar-subgroup__body{display:block;}
.sidebar-subgroup__body .sidebar-item{padding-left:36px;font-size:12px;}
.main{margin-left:240px;margin-top:56px;padding:24px;min-height:calc(100vh - 56px);}
.page-placeholder{display:flex;flex-direction:column;align-items:center;justify-content:center;height:calc(100vh - 56px - 48px);color:var(--text-placeholder);gap:12px;}
.page-placeholder svg{opacity:.25;}
.page-placeholder p{font-size:var(--font-base);}
/* 筛选栏 */
.filter-bar{background:#fff;border-radius:var(--radius-md);padding:20px 24px;margin-bottom:16px;box-shadow:var(--shadow-sm);display:flex;align-items:center;gap:16px;flex-wrap:wrap;}
.filter-item{display:flex;align-items:center;gap:8px;}
.filter-item label{font-size:var(--font-sm);color:var(--text-secondary);white-space:nowrap;}
.filter-input{height:36px;border:1px solid var(--border);border-radius:var(--radius-sm);padding:0 12px;font-size:var(--font-sm);color:var(--text-primary);outline:none;background:#fff;min-width:180px;}
.filter-input:focus{border-color:var(--primary);}
.filter-select{height:36px;border:1px solid var(--border);border-radius:var(--radius-sm);padding:0 28px 0 12px;font-size:var(--font-sm);color:var(--text-primary);outline:none;background:#fff url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6'%3E%3Cpath d='M0 0l5 6 5-6z' fill='%23999'/%3E%3C/svg%3E") no-repeat right 10px center;appearance:none;cursor:pointer;min-width:140px;}
.btn{height:36px;padding:0 16px;border-radius:var(--radius-sm);font-size:var(--font-sm);cursor:pointer;border:none;transition:all .2s;display:inline-flex;align-items:center;gap:6px;}
.btn-primary{background:var(--primary);color:#fff;}.btn-primary:hover{background:#40a9ff;}
.btn-default{background:#fff;color:var(--text-primary);border:1px solid var(--border);}.btn-default:hover{color:var(--primary);border-color:var(--primary);}
.action-bar{display:flex;align-items:center;gap:12px;margin-bottom:16px;}
/* 表格 */
.table-card{background:#fff;border-radius:var(--radius-md);box-shadow:var(--shadow-sm);overflow:hidden;}
.table-card__content{overflow-x:auto;-webkit-overflow-scrolling:touch;}
table{width:100%;border-collapse:collapse;min-width:1400px;}
thead th{background:#FAFAFA;padding:12px 14px;text-align:center;font-size:var(--font-xs);color:var(--text-secondary);font-weight:500;border-bottom:1px solid var(--border);border-right:1px solid var(--border);white-space:nowrap;}
thead th:last-child{border-right:none;}
thead th.th-left{text-align:left;}
tbody td{padding:12px 14px;font-size:var(--font-xs);color:var(--text-primary);border-bottom:1px solid var(--border);text-align:center;white-space:nowrap;}
tbody td.td-left{text-align:left;}
tbody tr:last-child td{border-bottom:none;}
tbody tr:hover{background:#F8FBFF;}
/* 固定列 */
thead tr:first-child th:nth-child(-n+2),tbody td:nth-child(-n+2),thead tr:first-child th:nth-last-child(-n+2),tbody td:nth-last-child(-n+2){position:sticky;z-index:2;}
thead tr:first-child th:nth-child(-n+2),thead tr:first-child th:nth-last-child(-n+2){z-index:3;}
thead tr:first-child th:nth-child(1),tbody td:nth-child(1){left:0;}
thead tr:first-child th:nth-child(2),tbody td:nth-child(2){left:130px;}
thead tr:first-child th:nth-last-child(2),tbody td:nth-last-child(2){right:70px;}
thead tr:first-child th:nth-last-child(1),tbody td:nth-last-child(1){right:0;}
tbody td:nth-child(-n+2),tbody td:nth-last-child(-n+2){background:#fff;}
tbody tr:hover td:nth-child(-n+2),tbody tr:hover td:nth-last-child(-n+2){background:#F8FBFF;}
tbody td:nth-child(2),thead tr:first-child th:nth-child(2){box-shadow:2px 0 4px rgba(0,0,0,0.06);}
tbody td:nth-last-child(2),thead tr:first-child th:nth-last-child(2){box-shadow:-2px 0 4px rgba(0,0,0,0.06);}
.link{color:var(--primary);cursor:pointer;font-size:var(--font-xs);text-decoration:none;}.link:hover{color:#40a9ff;}
/* 空气质量标签 */
.aqi-tag{display:inline-block;padding:2px 10px;border-radius:10px;font-size:var(--font-xs);font-weight:500;}
.aqi-tag--clean{background:#E6FFFB;color:#13C2C2;}
.aqi-tag--good{background:#F6FFED;color:#52C41A;}
.aqi-tag--light{background:#FFFBE6;color:#FAAD14;}
.aqi-tag--moderate{background:#FFF1F0;color:#FA541C;}
.aqi-tag--heavy{background:#FFF1F0;color:#FF4D4F;}
.pagination{display:flex;align-items:center;justify-content:flex-end;padding:16px 24px;gap:8px;border-top:1px solid var(--border);}
.pagination span{font-size:var(--font-sm);color:var(--text-secondary);}
.page-btn{width:32px;height:32px;border:1px solid var(--border);border-radius:var(--radius-sm);background:#fff;cursor:pointer;font-size:var(--font-sm);display:inline-flex;align-items:center;justify-content:center;transition:all .2s;}
.page-btn:hover,.page-btn.active{background:var(--primary);color:#fff;border-color:var(--primary);}
</style>
</head>
<body>
@@ -57,10 +99,7 @@
<a href="../exception-dirty.html">异常事件</a>
</nav>
<div class="top-bar__right">
<a class="btn-back" href="../../../index.html">
<svg width="16" height="16" viewBox="0 0 16 16" fill="none"><path d="M10 3L5 8l5 5" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/></svg>
返回首页
</a>
<a class="btn-back" href="../../../index.html"><svg width="16" height="16" viewBox="0 0 16 16" fill="none"><path d="M10 3L5 8l5 5" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/></svg> 返回首页</a>
<div class="avatar"></div>
<span style="color:rgba(255,255,255,0.65);">系统管理员 ▾</span>
</div>
@@ -114,11 +153,136 @@
</div>
</aside>
<main class="main">
<div class="page-placeholder">
<svg width="64" height="64" viewBox="0 0 64 64" fill="none"><rect x="8" y="8" width="48" height="48" rx="8" stroke="#ccc" stroke-width="2"/><path d="M20 32h24M32 20v24" stroke="#ccc" stroke-width="2" stroke-linecap="round"/></svg>
<p>数据监测</p>
<!-- 筛选条件 -->
<div class="filter-bar">
<div class="filter-item"><label>设备名称</label><input class="filter-input" placeholder="请输入设备名称"></div>
<div class="filter-item"><label>设备编码</label><input class="filter-input" placeholder="请输入设备编码"></div>
<div class="filter-item"><label>所属单位</label>
<select class="filter-select"><option value="">全部</option><option>采油一厂</option><option>采油二厂</option><option>采油三厂</option></select>
</div>
<div class="filter-item"><label>空气质量指数</label>
<select class="filter-select"><option value="">全部</option><option>清洁</option><option>未污染</option><option>轻污染</option><option>中污染</option><option>重污染</option></select>
</div>
<button class="btn btn-primary">查询</button>
<button class="btn btn-default">重置</button>
</div>
<!-- 操作按钮 -->
<div class="action-bar">
<button class="btn btn-default">导出列表数据</button>
</div>
<!-- 数据列表 -->
<div class="table-card">
<div class="table-card__content">
<table>
<thead>
<tr>
<th rowspan="2" class="th-left" style="min-width:130px;">设备名称</th>
<th rowspan="2" style="min-width:110px;">设备编码</th>
<th rowspan="2" style="min-width:90px;">所属单位</th>
<th rowspan="2" style="min-width:130px;">设备位置</th>
<th rowspan="2" style="min-width:150px;">数据更新时间</th>
<th colspan="6">监测数据</th>
<th rowspan="2" style="min-width:80px;">空气质量指数</th>
<th rowspan="2" style="min-width:70px;">操作</th>
</tr>
<tr>
<th>温度(℃)</th>
<th>湿度(%)</th>
<th>CO₂(ppm)</th>
<th>甲醛(mg/m³)</th>
<th>PM2.5(μg/m³)</th>
<th>PM10(μg/m³)</th>
</tr>
</thead>
<tbody>
<tr>
<td class="td-left">综合空气监测仪-A01</td>
<td>IA-2024-001</td>
<td>采油一厂</td>
<td>办公楼1层大厅</td>
<td>2026-05-14 14:30</td>
<td>24.5</td>
<td>52</td>
<td>456</td>
<td>0.03</td>
<td>35</td>
<td>68</td>
<td><span class="aqi-tag aqi-tag--clean">清洁</span></td>
<td><a class="link" href="indoor-data-analysis.html">动态分析</a></td>
</tr>
<tr>
<td class="td-left">PM2.5检测仪-B03</td>
<td>IA-2024-002</td>
<td>采油一厂</td>
<td>办公楼2层会议室</td>
<td>2026-05-14 14:28</td>
<td>25.1</td>
<td>58</td>
<td>512</td>
<td>0.05</td>
<td>42</td>
<td>76</td>
<td><span class="aqi-tag aqi-tag--good">未污染</span></td>
<td><a class="link" href="indoor-data-analysis.html">动态分析</a></td>
</tr>
<tr>
<td class="td-left">甲醛检测仪-C02</td>
<td>IA-2024-003</td>
<td>采油二厂</td>
<td>新装修办公室3层</td>
<td>2026-05-14 14:25</td>
<td>26.3</td>
<td>61</td>
<td>680</td>
<td>0.09</td>
<td>58</td>
<td>95</td>
<td><span class="aqi-tag aqi-tag--light">轻污染</span></td>
<td><a class="link" href="indoor-data-analysis.html">动态分析</a></td>
</tr>
<tr>
<td class="td-left">CO2检测仪-D01</td>
<td>IA-2024-004</td>
<td>采油二厂</td>
<td>地下车库B1层</td>
<td>2026-05-14 14:20</td>
<td>22.8</td>
<td>72</td>
<td>920</td>
<td>0.07</td>
<td>82</td>
<td>128</td>
<td><span class="aqi-tag aqi-tag--moderate">中污染</span></td>
<td><a class="link" href="indoor-data-analysis.html">动态分析</a></td>
</tr>
<tr>
<td class="td-left">综合空气监测仪-A05</td>
<td>IA-2024-005</td>
<td>采油三厂</td>
<td>生产车间1号</td>
<td>2026-05-14 14:15</td>
<td>28.6</td>
<td>78</td>
<td>1050</td>
<td>0.12</td>
<td>120</td>
<td>185</td>
<td><span class="aqi-tag aqi-tag--heavy">重污染</span></td>
<td><a class="link" href="indoor-data-analysis.html">动态分析</a></td>
</tr>
</tbody>
</table>
</div>
<div class="pagination">
<span>共 5 条</span>
<button class="page-btn active">1</button>
</div>
</div>
</main>
<script>function toggleSubgroup(h){h.parentElement.classList.toggle('open');}(function(){var a=document.querySelector('.sidebar-item.active');if(!a)return;var s=a.closest('.sidebar-subgroup');if(s)s.classList.add('open');})();</script>
<script>
function toggleSubgroup(h){h.parentElement.classList.toggle('open');}
(function(){var a=document.querySelector('.sidebar-item.active');if(!a)return;var s=a.closest('.sidebar-subgroup');if(s)s.classList.add('open');})();
</script>
</body>
</html>
</html>
@@ -3,7 +3,7 @@
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>健康监测 - 设备分类 | 健康长庆原型</title>
<title>室内空气 - 设备分类 | 健康长庆原型</title>
<style>
*{box-sizing:border-box;margin:0;padding:0;}
body{font-family:-apple-system,BlinkMacSystemFont,'PingFang SC','Microsoft YaHei',sans-serif;background:#F5F7FA;color:#333;min-width:1280px;}
@@ -40,9 +40,63 @@
.sidebar-subgroup.open>.sidebar-subgroup__body{display:block;}
.sidebar-subgroup__body .sidebar-item{padding-left:36px;font-size:12px;}
.main{margin-left:240px;margin-top:56px;padding:24px;min-height:calc(100vh - 56px);}
.page-placeholder{display:flex;flex-direction:column;align-items:center;justify-content:center;height:calc(100vh - 56px - 48px);color:var(--text-placeholder);gap:12px;}
.page-placeholder svg{opacity:.25;}
.page-placeholder p{font-size:var(--font-base);}
/* 筛选栏 */
.filter-bar{background:#fff;border-radius:var(--radius-md);padding:20px 24px;margin-bottom:16px;box-shadow:var(--shadow-sm);display:flex;align-items:center;gap:16px;flex-wrap:wrap;}
.filter-item{display:flex;align-items:center;gap:8px;}
.filter-item label{font-size:var(--font-sm);color:var(--text-secondary);white-space:nowrap;}
.filter-input{height:36px;border:1px solid var(--border);border-radius:var(--radius-sm);padding:0 12px;font-size:var(--font-sm);color:var(--text-primary);outline:none;background:#fff;min-width:200px;}
.filter-input:focus{border-color:var(--primary);}
.btn{height:36px;padding:0 16px;border-radius:var(--radius-sm);font-size:var(--font-sm);cursor:pointer;border:none;transition:all .2s;display:inline-flex;align-items:center;gap:6px;}
.btn-primary{background:var(--primary);color:#fff;}.btn-primary:hover{background:#40a9ff;}
.btn-default{background:#fff;color:var(--text-primary);border:1px solid var(--border);}.btn-default:hover{color:var(--primary);border-color:var(--primary);}
.action-bar{display:flex;align-items:center;gap:12px;margin-bottom:16px;}
/* 表格 */
.table-card{background:#fff;border-radius:var(--radius-md);box-shadow:var(--shadow-sm);overflow:hidden;}
.table-card__content{overflow-x:auto;-webkit-overflow-scrolling:touch;}
table{width:100%;border-collapse:collapse;min-width:900px;}
thead th{background:#FAFAFA;padding:12px 16px;text-align:center;font-size:var(--font-sm);color:var(--text-secondary);font-weight:500;border-bottom:1px solid var(--border);border-right:1px solid var(--border);white-space:nowrap;}
thead th:last-child{border-right:none;}
thead th.th-left{text-align:left;}
tbody td{padding:14px 16px;font-size:var(--font-sm);color:var(--text-primary);border-bottom:1px solid var(--border);text-align:center;white-space:nowrap;}
tbody td.td-left{text-align:left;}
tbody tr:last-child td{border-bottom:none;}
tbody tr:hover{background:#F8FBFF;}
.link{color:var(--primary);cursor:pointer;font-size:var(--font-sm);text-decoration:none;}.link:hover{color:#40a9ff;}
.link-danger{color:var(--danger);cursor:pointer;font-size:var(--font-sm);text-decoration:none;}.link-danger:hover{color:#ff7875;}
.pagination{display:flex;align-items:center;justify-content:flex-end;padding:16px 24px;gap:8px;border-top:1px solid var(--border);}
.pagination span{font-size:var(--font-sm);color:var(--text-secondary);}
.page-btn{width:32px;height:32px;border:1px solid var(--border);border-radius:var(--radius-sm);background:#fff;cursor:pointer;font-size:var(--font-sm);display:inline-flex;align-items:center;justify-content:center;transition:all .2s;}
.page-btn:hover,.page-btn.active{background:var(--primary);color:#fff;border-color:var(--primary);}
/* 抽屉弹窗 */
.drawer-mask{display:none;position:fixed;top:0;left:0;right:0;bottom:0;background:rgba(0,0,0,0.45);z-index:200;}
.drawer-mask.open{display:block;}
.drawer{position:fixed;top:0;right:-600px;width:600px;height:100%;background:#fff;z-index:201;box-shadow:-4px 0 16px rgba(0,0,0,0.12);transition:right .3s ease;display:flex;flex-direction:column;}
.drawer.open{right:0;}
.drawer__header{display:flex;align-items:center;justify-content:space-between;padding:16px 24px;border-bottom:1px solid var(--border);}
.drawer__title{font-size:var(--font-base);font-weight:600;color:var(--text-primary);}
.drawer__close{width:32px;height:32px;border:none;background:none;cursor:pointer;display:flex;align-items:center;justify-content:center;border-radius:var(--radius-sm);color:var(--text-placeholder);font-size:18px;}
.drawer__close:hover{background:#f5f5f5;color:var(--text-primary);}
.drawer__body{flex:1;overflow-y:auto;padding:24px;}
.drawer__footer{display:flex;align-items:center;justify-content:flex-end;gap:12px;padding:16px 24px;border-top:1px solid var(--border);}
/* 表单 */
.form-group{margin-bottom:20px;}
.form-label{display:block;font-size:var(--font-sm);color:var(--text-primary);margin-bottom:8px;font-weight:500;}
.form-label .required{color:var(--danger);margin-right:4px;}
.form-control{width:100%;height:36px;border:1px solid var(--border);border-radius:var(--radius-sm);padding:0 12px;font-size:var(--font-sm);color:var(--text-primary);outline:none;background:#fff;}
.form-control:focus{border-color:var(--primary);box-shadow:0 0 0 2px rgba(24,144,255,0.1);}
/* 阈值设置项(参考穿戴监测开关设置样式) */
.threshold-section-title{font-size:var(--font-sm);font-weight:600;color:var(--text-primary);margin-bottom:12px;padding-bottom:8px;border-bottom:1px solid var(--border);}
.threshold-list{display:flex;flex-direction:column;gap:12px;}
.threshold-item{border:1px solid var(--border);border-radius:var(--radius-md);overflow:hidden;}
.threshold-item__header{display:flex;align-items:center;justify-content:space-between;padding:12px 16px;background:#FAFAFA;}
.threshold-item__label{font-size:var(--font-sm);font-weight:600;color:var(--text-primary);}
.threshold-item__unit{font-size:var(--font-xs);color:var(--text-placeholder);font-weight:400;margin-left:4px;}
.threshold-item__body{padding:12px 16px;}
.threshold-row{display:grid;grid-template-columns:1fr 1fr;gap:12px;}
.threshold-field{display:flex;flex-direction:column;gap:4px;}
.threshold-field label{font-size:var(--font-xs);color:var(--text-secondary);}
.threshold-field .form-control{height:34px;border:1px solid var(--border);border-radius:var(--radius-sm);padding:0 10px;font-size:var(--font-sm);outline:none;width:100%;}
.threshold-field .form-control:focus{border-color:var(--primary);}
</style>
</head>
<body>
@@ -57,10 +111,7 @@
<a href="../exception-dirty.html">异常事件</a>
</nav>
<div class="top-bar__right">
<a class="btn-back" href="../../../index.html">
<svg width="16" height="16" viewBox="0 0 16 16" fill="none"><path d="M10 3L5 8l5 5" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/></svg>
返回首页
</a>
<a class="btn-back" href="../../../index.html"><svg width="16" height="16" viewBox="0 0 16 16" fill="none"><path d="M10 3L5 8l5 5" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/></svg> 返回首页</a>
<div class="avatar"></div>
<span style="color:rgba(255,255,255,0.65);">系统管理员 ▾</span>
</div>
@@ -114,11 +165,246 @@
</div>
</aside>
<main class="main">
<div class="page-placeholder">
<svg width="64" height="64" viewBox="0 0 64 64" fill="none"><rect x="8" y="8" width="48" height="48" rx="8" stroke="#ccc" stroke-width="2"/><path d="M20 32h24M32 20v24" stroke="#ccc" stroke-width="2" stroke-linecap="round"/></svg>
<p>设备分类</p>
<!-- 筛选条件 -->
<div class="filter-bar">
<div class="filter-item"><label>分类名称</label><input class="filter-input" placeholder="请输入分类名称"></div>
<button class="btn btn-primary">查询</button>
<button class="btn btn-default">重置</button>
</div>
<!-- 操作按钮 -->
<div class="action-bar">
<!-- [交互] 点击打开右侧抽屉弹窗(新增模式) -->
<button class="btn btn-primary" onclick="openDrawer('add')">+ 新增</button>
</div>
<!-- 数据列表 -->
<div class="table-card">
<div class="table-card__content">
<table>
<thead>
<tr>
<th rowspan="2" class="th-left" style="min-width:160px;">分类名称</th>
<th colspan="6">监测数据阈值</th>
<th rowspan="2" style="min-width:100px;">操作</th>
</tr>
<tr>
<th>温度(℃)</th>
<th>湿度(%)</th>
<th>CO₂(ppm)</th>
<th>甲醛(mg/m³)</th>
<th>PM2.5(μg/m³)</th>
<th>PM10(μg/m³)</th>
</tr>
</thead>
<tbody>
<tr>
<td class="td-left">PM2.5检测仪</td>
<td>16 ~ 28</td>
<td>30 ~ 70</td>
<td>400 ~ 1000</td>
<td>0 ~ 0.08</td>
<td>0 ~ 75</td>
<td>0 ~ 150</td>
<td><a class="link" onclick="openDrawer('edit',0)">编辑</a> <a class="link-danger">删除</a></td>
</tr>
<tr>
<td class="td-left">甲醛检测仪</td>
<td>16 ~ 28</td>
<td>30 ~ 70</td>
<td>400 ~ 1000</td>
<td>0 ~ 0.10</td>
<td>0 ~ 75</td>
<td>0 ~ 150</td>
<td><a class="link" onclick="openDrawer('edit',1)">编辑</a> <a class="link-danger">删除</a></td>
</tr>
<tr>
<td class="td-left">CO2检测仪</td>
<td>18 ~ 26</td>
<td>40 ~ 65</td>
<td>350 ~ 800</td>
<td>0 ~ 0.08</td>
<td>0 ~ 50</td>
<td>0 ~ 100</td>
<td><a class="link" onclick="openDrawer('edit',2)">编辑</a> <a class="link-danger">删除</a></td>
</tr>
<tr>
<td class="td-left">综合空气质量监测仪</td>
<td>16 ~ 30</td>
<td>30 ~ 80</td>
<td>400 ~ 1000</td>
<td>0 ~ 0.08</td>
<td>0 ~ 75</td>
<td>0 ~ 150</td>
<td><a class="link" onclick="openDrawer('edit',3)">编辑</a> <a class="link-danger">删除</a></td>
</tr>
</tbody>
</table>
</div>
<div class="pagination">
<span>共 4 条</span>
<button class="page-btn active">1</button>
</div>
</div>
</main>
<script>function toggleSubgroup(h){h.parentElement.classList.toggle('open');}(function(){var a=document.querySelector('.sidebar-item.active');if(!a)return;var s=a.closest('.sidebar-subgroup');if(s)s.classList.add('open');})();</script>
<!-- 新增分类 - 右侧抽屉弹窗 -->
<div class="drawer-mask" id="drawerMask" onclick="closeDrawer()"></div>
<div class="drawer" id="drawer">
<div class="drawer__header">
<span class="drawer__title" id="drawerTitle">新增分类</span>
<button class="drawer__close" onclick="closeDrawer()">&times;</button>
</div>
<div class="drawer__body">
<div class="form-group">
<label class="form-label"><span class="required">*</span>分类名称</label>
<input class="form-control" id="formCategoryName" placeholder="请输入分类名称">
</div>
<div class="threshold-section-title">监测数据阈值设置</div>
<div class="threshold-list">
<!-- 温度 -->
<div class="threshold-item">
<div class="threshold-item__header">
<span class="threshold-item__label">温度<span class="threshold-item__unit">(℃)</span></span>
</div>
<div class="threshold-item__body">
<div class="threshold-row">
<div class="threshold-field">
<label>阈值下限</label>
<input class="form-control" type="number" value="16" placeholder="下限">
</div>
<div class="threshold-field">
<label>阈值上限</label>
<input class="form-control" type="number" value="28" placeholder="上限">
</div>
</div>
</div>
</div>
<!-- 湿度 -->
<div class="threshold-item">
<div class="threshold-item__header">
<span class="threshold-item__label">湿度<span class="threshold-item__unit">(%)</span></span>
</div>
<div class="threshold-item__body">
<div class="threshold-row">
<div class="threshold-field">
<label>阈值下限</label>
<input class="form-control" type="number" value="30" placeholder="下限">
</div>
<div class="threshold-field">
<label>阈值上限</label>
<input class="form-control" type="number" value="70" placeholder="上限">
</div>
</div>
</div>
</div>
<!-- 二氧化碳 -->
<div class="threshold-item">
<div class="threshold-item__header">
<span class="threshold-item__label">CO₂<span class="threshold-item__unit">(ppm)</span></span>
</div>
<div class="threshold-item__body">
<div class="threshold-row">
<div class="threshold-field">
<label>阈值下限</label>
<input class="form-control" type="number" value="400" placeholder="下限">
</div>
<div class="threshold-field">
<label>阈值上限</label>
<input class="form-control" type="number" value="1000" placeholder="上限">
</div>
</div>
</div>
</div>
<!-- 甲醛 -->
<div class="threshold-item">
<div class="threshold-item__header">
<span class="threshold-item__label">甲醛<span class="threshold-item__unit">(mg/m³)</span></span>
</div>
<div class="threshold-item__body">
<div class="threshold-row">
<div class="threshold-field">
<label>阈值下限</label>
<input class="form-control" type="number" value="0" step="0.01" placeholder="下限">
</div>
<div class="threshold-field">
<label>阈值上限</label>
<input class="form-control" type="number" value="0.08" step="0.01" placeholder="上限">
</div>
</div>
</div>
</div>
<!-- PM2.5 -->
<div class="threshold-item">
<div class="threshold-item__header">
<span class="threshold-item__label">PM2.5<span class="threshold-item__unit">(μg/m³)</span></span>
</div>
<div class="threshold-item__body">
<div class="threshold-row">
<div class="threshold-field">
<label>阈值下限</label>
<input class="form-control" type="number" value="0" placeholder="下限">
</div>
<div class="threshold-field">
<label>阈值上限</label>
<input class="form-control" type="number" value="75" placeholder="上限">
</div>
</div>
</div>
</div>
<!-- PM10 -->
<div class="threshold-item">
<div class="threshold-item__header">
<span class="threshold-item__label">PM10<span class="threshold-item__unit">(μg/m³)</span></span>
</div>
<div class="threshold-item__body">
<div class="threshold-row">
<div class="threshold-field">
<label>阈值下限</label>
<input class="form-control" type="number" value="0" placeholder="下限">
</div>
<div class="threshold-field">
<label>阈值上限</label>
<input class="form-control" type="number" value="150" placeholder="上限">
</div>
</div>
</div>
</div>
</div>
</div>
<div class="drawer__footer">
<button class="btn btn-default" onclick="closeDrawer()">取消</button>
<button class="btn btn-primary" onclick="closeDrawer()">确定</button>
</div>
</div>
<script>
function toggleSubgroup(h){h.parentElement.classList.toggle('open');}
(function(){var a=document.querySelector('.sidebar-item.active');if(!a)return;var s=a.closest('.sidebar-subgroup');if(s)s.classList.add('open');})();
function openDrawer(mode, rowIdx){
var title = document.getElementById('drawerTitle');
var nameInput = document.getElementById('formCategoryName');
var fields = document.querySelectorAll('.threshold-field .form-control');
if(mode === 'edit'){
title.textContent = '编辑分类';
/* 从表格行读取数据填入表单 */
var row = document.querySelectorAll('tbody tr')[rowIdx];
var cells = row.querySelectorAll('td');
nameInput.value = cells[0].textContent.trim();
/* 解析每列的 "min ~ max" 填入对应阈值字段 */
for(var i = 0; i < 6; i++){
var parts = cells[i+1].textContent.split('~');
fields[i*2].value = parts[0].trim();
fields[i*2+1].value = parts[1].trim();
}
} else {
title.textContent = '新增分类';
nameInput.value = '';
for(var j = 0; j < fields.length; j++){ fields[j].value = ''; }
}
document.getElementById('drawerMask').classList.add('open');
document.getElementById('drawer').classList.add('open');
}
function closeDrawer(){document.getElementById('drawerMask').classList.remove('open');document.getElementById('drawer').classList.remove('open');}
</script>
</body>
</html>
@@ -3,7 +3,7 @@
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>健康监测 - 设备列表 | 健康长庆原型</title>
<title>室内空气 - 设备列表 | 健康长庆原型</title>
<style>
*{box-sizing:border-box;margin:0;padding:0;}
body{font-family:-apple-system,BlinkMacSystemFont,'PingFang SC','Microsoft YaHei',sans-serif;background:#F5F7FA;color:#333;min-width:1280px;}
@@ -40,9 +40,63 @@
.sidebar-subgroup.open>.sidebar-subgroup__body{display:block;}
.sidebar-subgroup__body .sidebar-item{padding-left:36px;font-size:12px;}
.main{margin-left:240px;margin-top:56px;padding:24px;min-height:calc(100vh - 56px);}
.page-placeholder{display:flex;flex-direction:column;align-items:center;justify-content:center;height:calc(100vh - 56px - 48px);color:var(--text-placeholder);gap:12px;}
.page-placeholder svg{opacity:.25;}
.page-placeholder p{font-size:var(--font-base);}
/* 筛选栏 */
.filter-bar{background:#fff;border-radius:var(--radius-md);padding:20px 24px;margin-bottom:16px;box-shadow:var(--shadow-sm);display:flex;align-items:center;gap:16px;flex-wrap:wrap;}
.filter-item{display:flex;align-items:center;gap:8px;}
.filter-item label{font-size:var(--font-sm);color:var(--text-secondary);white-space:nowrap;}
.filter-input{height:36px;border:1px solid var(--border);border-radius:var(--radius-sm);padding:0 12px;font-size:var(--font-sm);color:var(--text-primary);outline:none;background:#fff;min-width:160px;}
.filter-input:focus{border-color:var(--primary);}
.filter-select{height:36px;border:1px solid var(--border);border-radius:var(--radius-sm);padding:0 28px 0 12px;font-size:var(--font-sm);color:var(--text-primary);outline:none;background:#fff url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6'%3E%3Cpath d='M0 0l5 6 5-6z' fill='%23999'/%3E%3C/svg%3E") no-repeat right 10px center;appearance:none;cursor:pointer;min-width:140px;}
.btn{height:36px;padding:0 16px;border-radius:var(--radius-sm);font-size:var(--font-sm);cursor:pointer;border:none;transition:all .2s;display:inline-flex;align-items:center;gap:6px;}
.btn-primary{background:var(--primary);color:#fff;}.btn-primary:hover{background:#40a9ff;}
.btn-default{background:#fff;color:var(--text-primary);border:1px solid var(--border);}.btn-default:hover{color:var(--primary);border-color:var(--primary);}
.btn-success{background:var(--success);color:#fff;}.btn-success:hover{background:#73d13d;}
/* 操作按钮栏 */
.action-bar{display:flex;align-items:center;gap:12px;margin-bottom:16px;}
/* 表格 */
.table-card{background:#fff;border-radius:var(--radius-md);box-shadow:var(--shadow-sm);overflow:hidden;}
.table-card__content{overflow-x:auto;-webkit-overflow-scrolling:touch;}
table{width:100%;border-collapse:collapse;min-width:1000px;}
thead th{background:#FAFAFA;padding:12px 16px;text-align:left;font-size:var(--font-sm);color:var(--text-secondary);font-weight:500;border-bottom:1px solid var(--border);white-space:nowrap;}
tbody td{padding:14px 16px;font-size:var(--font-sm);color:var(--text-primary);border-bottom:1px solid var(--border);white-space:nowrap;}
tbody tr:last-child td{border-bottom:none;}
tbody tr:hover{background:#F8FBFF;}
.link{color:var(--primary);cursor:pointer;font-size:var(--font-sm);text-decoration:none;}.link:hover{color:#40a9ff;}
.link-danger{color:var(--danger);cursor:pointer;font-size:var(--font-sm);text-decoration:none;}.link-danger:hover{color:#ff7875;}
/* 分页 */
.pagination{display:flex;align-items:center;justify-content:flex-end;padding:16px 24px;gap:8px;border-top:1px solid var(--border);}
.pagination span{font-size:var(--font-sm);color:var(--text-secondary);}
.page-btn{width:32px;height:32px;border:1px solid var(--border);border-radius:var(--radius-sm);background:#fff;cursor:pointer;font-size:var(--font-sm);display:inline-flex;align-items:center;justify-content:center;transition:all .2s;}
.page-btn:hover,.page-btn.active{background:var(--primary);color:#fff;border-color:var(--primary);}
/* 抽屉弹窗 */
.drawer-mask{display:none;position:fixed;top:0;left:0;right:0;bottom:0;background:rgba(0,0,0,0.45);z-index:200;}
.drawer-mask.open{display:block;}
.drawer{position:fixed;top:0;right:-560px;width:560px;height:100%;background:#fff;z-index:201;box-shadow:-4px 0 16px rgba(0,0,0,0.12);transition:right .3s ease;display:flex;flex-direction:column;}
.drawer.open{right:0;}
.drawer__header{display:flex;align-items:center;justify-content:space-between;padding:16px 24px;border-bottom:1px solid var(--border);}
.drawer__title{font-size:var(--font-base);font-weight:600;color:var(--text-primary);}
.drawer__close{width:32px;height:32px;border:none;background:none;cursor:pointer;display:flex;align-items:center;justify-content:center;border-radius:var(--radius-sm);color:var(--text-placeholder);font-size:18px;}
.drawer__close:hover{background:#f5f5f5;color:var(--text-primary);}
.drawer__body{flex:1;overflow-y:auto;padding:24px;}
.drawer__footer{display:flex;align-items:center;justify-content:flex-end;gap:12px;padding:16px 24px;border-top:1px solid var(--border);}
/* 表单 */
.form-group{margin-bottom:20px;}
.form-label{display:block;font-size:var(--font-sm);color:var(--text-primary);margin-bottom:8px;font-weight:500;}
.form-label .required{color:var(--danger);margin-right:4px;}
.form-control{width:100%;height:36px;border:1px solid var(--border);border-radius:var(--radius-sm);padding:0 12px;font-size:var(--font-sm);color:var(--text-primary);outline:none;background:#fff;}
.form-control:focus{border-color:var(--primary);box-shadow:0 0 0 2px rgba(24,144,255,0.1);}
.form-select{width:100%;height:36px;border:1px solid var(--border);border-radius:var(--radius-sm);padding:0 28px 0 12px;font-size:var(--font-sm);color:var(--text-primary);outline:none;background:#fff url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6'%3E%3Cpath d='M0 0l5 6 5-6z' fill='%23999'/%3E%3C/svg%3E") no-repeat right 10px center;appearance:none;cursor:pointer;}
.form-select:focus{border-color:var(--primary);box-shadow:0 0 0 2px rgba(24,144,255,0.1);}
/* 地图选点区域 */
.map-picker{width:100%;height:200px;border:1px solid var(--border);border-radius:var(--radius-sm);background:#f0f2f5;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:8px;color:var(--text-placeholder);cursor:pointer;position:relative;overflow:hidden;}
.map-picker__icon{width:40px;height:40px;border-radius:50%;background:var(--primary-light);display:flex;align-items:center;justify-content:center;}
.map-picker__text{font-size:var(--font-sm);}
.map-picker__pin{position:absolute;top:50%;left:50%;transform:translate(-50%,-100%);display:none;}
.map-picker.selected{background:linear-gradient(135deg,#e6f7ff 0%,#f0f5ff 100%);border-color:var(--primary);}
.map-picker.selected .map-picker__pin{display:block;}
.map-picker.selected .map-picker__icon,.map-picker.selected .map-picker__text{display:none;}
.map-picker__hint{position:absolute;bottom:8px;left:0;right:0;text-align:center;font-size:var(--font-xs);color:var(--text-placeholder);display:none;}
.map-picker.selected .map-picker__hint{display:block;}
</style>
</head>
<body>
@@ -57,10 +111,7 @@
<a href="../exception-dirty.html">异常事件</a>
</nav>
<div class="top-bar__right">
<a class="btn-back" href="../../../index.html">
<svg width="16" height="16" viewBox="0 0 16 16" fill="none"><path d="M10 3L5 8l5 5" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/></svg>
返回首页
</a>
<a class="btn-back" href="../../../index.html"><svg width="16" height="16" viewBox="0 0 16 16" fill="none"><path d="M10 3L5 8l5 5" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/></svg> 返回首页</a>
<div class="avatar"></div>
<span style="color:rgba(255,255,255,0.65);">系统管理员 ▾</span>
</div>
@@ -114,11 +165,131 @@
</div>
</aside>
<main class="main">
<div class="page-placeholder">
<svg width="64" height="64" viewBox="0 0 64 64" fill="none"><rect x="8" y="8" width="48" height="48" rx="8" stroke="#ccc" stroke-width="2"/><path d="M20 32h24M32 20v24" stroke="#ccc" stroke-width="2" stroke-linecap="round"/></svg>
<p>设备列表</p>
<!-- 筛选条件 -->
<div class="filter-bar">
<div class="filter-item"><label>设备编码</label><input class="filter-input" placeholder="请输入设备编码"></div>
<div class="filter-item"><label>设备名称</label><input class="filter-input" placeholder="请输入设备名称"></div>
<div class="filter-item"><label>所属单位</label><select class="filter-select"><option value="">全部</option><option>采油一厂</option><option>采油二厂</option><option>采气厂</option><option>炼化公司</option></select></div>
<div class="filter-item"><label>设备分类</label><select class="filter-select"><option value="">全部</option><option>PM2.5检测仪</option><option>甲醛检测仪</option><option>CO2检测仪</option><option>综合空气质量监测仪</option></select></div>
<button class="btn btn-primary">查询</button>
<button class="btn btn-default">重置</button>
</div>
<!-- 操作按钮 -->
<div class="action-bar">
<!-- [交互] 点击打开右侧抽屉弹窗 -->
<button class="btn btn-primary" onclick="openDrawer()">+ 新增设备</button>
<button class="btn btn-success">批量入库导入</button>
<button class="btn btn-default">查看导入任务</button>
<button class="btn btn-default">导出列表数据</button>
</div>
<!-- 数据列表 -->
<div class="table-card">
<div class="table-card__content">
<table>
<thead><tr><th>设备名称</th><th>设备编码</th><th>设备分类</th><th>所属单位</th><th>设备位置</th><th>布点日期</th><th>监测时长(天)</th><th>操作</th></tr></thead>
<tbody>
<tr><td>室内空气监测仪A1</td><td>IA-2024-001</td><td>PM2.5检测仪</td><td>采油一厂</td><td>办公楼3F会议室</td><td>2024-06-15</td><td>328</td><td><a class="link" onclick="openDrawer()">编辑</a> <a class="link-danger">删除</a></td></tr>
<tr><td>室内空气监测仪A2</td><td>IA-2024-002</td><td>甲醛检测仪</td><td>采油一厂</td><td>职工活动中心2F</td><td>2024-07-20</td><td>293</td><td><a class="link" onclick="openDrawer()">编辑</a> <a class="link-danger">删除</a></td></tr>
<tr><td>综合空气检测仪B1</td><td>IA-2024-003</td><td>综合空气质量监测仪</td><td>采油二厂</td><td>员工食堂1F</td><td>2024-08-10</td><td>272</td><td><a class="link" onclick="openDrawer()">编辑</a> <a class="link-danger">删除</a></td></tr>
<tr><td>CO2监测仪C1</td><td>IA-2024-004</td><td>CO2检测仪</td><td>采气厂</td><td>综合办公楼1F大厅</td><td>2024-09-05</td><td>246</td><td><a class="link" onclick="openDrawer()">编辑</a> <a class="link-danger">删除</a></td></tr>
<tr><td>甲醛检测仪D1</td><td>IA-2025-001</td><td>甲醛检测仪</td><td>炼化公司</td><td>实验楼2F研发室</td><td>2025-01-08</td><td>121</td><td><a class="link" onclick="openDrawer()">编辑</a> <a class="link-danger">删除</a></td></tr>
</tbody>
</table>
</div>
<div class="pagination">
<span>共 42 条</span>
<button class="page-btn"></button>
<button class="page-btn active">1</button>
<button class="page-btn">2</button>
<button class="page-btn">3</button>
<button class="page-btn">4</button>
<button class="page-btn">5</button>
<button class="page-btn"></button>
</div>
</div>
</main>
<script>function toggleSubgroup(h){h.parentElement.classList.toggle('open');}(function(){var a=document.querySelector('.sidebar-item.active');if(!a)return;var s=a.closest('.sidebar-subgroup');if(s)s.classList.add('open');})();</script>
<!-- 新增设备 - 右侧抽屉弹窗 -->
<div class="drawer-mask" id="drawerMask" onclick="closeDrawer()"></div>
<div class="drawer" id="drawer">
<div class="drawer__header">
<span class="drawer__title">新增设备</span>
<button class="drawer__close" onclick="closeDrawer()">&times;</button>
</div>
<div class="drawer__body">
<div class="form-group">
<label class="form-label"><span class="required">*</span>设备名称</label>
<input class="form-control" placeholder="请输入设备名称">
</div>
<div class="form-group">
<label class="form-label"><span class="required">*</span>设备编码</label>
<input class="form-control" placeholder="请输入设备编码">
</div>
<div class="form-group">
<label class="form-label"><span class="required">*</span>设备分类</label>
<select class="form-select">
<option value="">请选择设备分类</option>
<option>PM2.5检测仪</option>
<option>甲醛检测仪</option>
<option>CO2检测仪</option>
<option>综合空气质量监测仪</option>
</select>
</div>
<div class="form-group">
<label class="form-label"><span class="required">*</span>所属单位</label>
<select class="form-select">
<option value="">请选择所属单位</option>
<option>采油一厂</option>
<option>采油二厂</option>
<option>采气厂</option>
<option>炼化公司</option>
</select>
</div>
<div class="form-group">
<label class="form-label"><span class="required">*</span>设备位置</label>
<!-- [交互] 点击地图区域可弹出地图选点组件,选点后自动填充经纬度和地址 -->
<div class="map-picker selected" onclick="this.classList.toggle('selected')">
<div class="map-picker__icon">
<svg width="20" height="20" viewBox="0 0 20 20" fill="none"><path d="M10 2C6.69 2 4 4.69 4 8c0 4.5 6 10 6 10s6-5.5 6-10c0-3.31-2.69-6-6-6zm0 8a2 2 0 110-4 2 2 0 010 4z" fill="#1890FF"/></svg>
</div>
<div class="map-picker__text">点击地图选择设备位置</div>
<!-- 选点后显示 -->
<svg class="map-picker__pin" width="160" height="120" viewBox="0 0 160 120">
<rect width="160" height="120" rx="4" fill="#e6f7ff" opacity="0.5"/>
<line x1="0" y1="30" x2="160" y2="30" stroke="#d9d9d9" stroke-width="0.5" stroke-dasharray="4"/>
<line x1="0" y1="60" x2="160" y2="60" stroke="#d9d9d9" stroke-width="0.5" stroke-dasharray="4"/>
<line x1="0" y1="90" x2="160" y2="90" stroke="#d9d9d9" stroke-width="0.5" stroke-dasharray="4"/>
<line x1="40" y1="0" x2="40" y2="120" stroke="#d9d9d9" stroke-width="0.5" stroke-dasharray="4"/>
<line x1="80" y1="0" x2="80" y2="120" stroke="#d9d9d9" stroke-width="0.5" stroke-dasharray="4"/>
<line x1="120" y1="0" x2="120" y2="120" stroke="#d9d9d9" stroke-width="0.5" stroke-dasharray="4"/>
<path d="M80 40C76.69 40 74 42.69 74 46c0 4.5 6 10 6 10s6-5.5 6-10c0-3.31-2.69-6-6-6zm0 8a2 2 0 110-4 2 2 0 010 4z" fill="#1890FF"/>
<circle cx="80" cy="46" r="12" fill="none" stroke="#1890FF" stroke-width="1" opacity="0.3"/>
<circle cx="80" cy="46" r="20" fill="none" stroke="#1890FF" stroke-width="0.5" opacity="0.15"/>
</svg>
<div class="map-picker__hint">点击重新选点</div>
</div>
</div>
<div class="form-group">
<label class="form-label"><span class="required">*</span>详细地址</label>
<!-- [交互] 地图选点后自动带入地址信息,可手动修改 -->
<input class="form-control" value="陕西省西安市长庆路采油一厂办公楼3F" placeholder="地图选点后自动带入,可手动修改">
</div>
<div class="form-group">
<label class="form-label"><span class="required">*</span>布点日期</label>
<input class="form-control" type="date" value="2025-05-14">
</div>
</div>
<div class="drawer__footer">
<button class="btn btn-default" onclick="closeDrawer()">取消</button>
<button class="btn btn-primary" onclick="closeDrawer()">确定</button>
</div>
</div>
<script>
function toggleSubgroup(h){h.parentElement.classList.toggle('open');}
(function(){var a=document.querySelector('.sidebar-item.active');if(!a)return;var s=a.closest('.sidebar-subgroup');if(s)s.classList.add('open');})();
function openDrawer(){document.getElementById('drawerMask').classList.add('open');document.getElementById('drawer').classList.add('open');}
function closeDrawer(){document.getElementById('drawerMask').classList.remove('open');document.getElementById('drawer').classList.remove('open');}
</script>
</body>
</html>
@@ -3,7 +3,7 @@
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>健康监测 - 异常报警 | 健康长庆原型</title>
<title>室内空气 - 异常报警 | 健康长庆原型</title>
<style>
*{box-sizing:border-box;margin:0;padding:0;}
body{font-family:-apple-system,BlinkMacSystemFont,'PingFang SC','Microsoft YaHei',sans-serif;background:#F5F7FA;color:#333;min-width:1280px;}
@@ -40,9 +40,36 @@
.sidebar-subgroup.open>.sidebar-subgroup__body{display:block;}
.sidebar-subgroup__body .sidebar-item{padding-left:36px;font-size:12px;}
.main{margin-left:240px;margin-top:56px;padding:24px;min-height:calc(100vh - 56px);}
.page-placeholder{display:flex;flex-direction:column;align-items:center;justify-content:center;height:calc(100vh - 56px - 48px);color:var(--text-placeholder);gap:12px;}
.page-placeholder svg{opacity:.25;}
.page-placeholder p{font-size:var(--font-base);}
/* 筛选栏 */
.filter-bar{background:#fff;border-radius:var(--radius-md);padding:20px 24px;margin-bottom:16px;box-shadow:var(--shadow-sm);display:flex;align-items:center;gap:16px;flex-wrap:wrap;}
.filter-item{display:flex;align-items:center;gap:8px;}
.filter-item label{font-size:var(--font-sm);color:var(--text-secondary);white-space:nowrap;}
.filter-input{height:36px;border:1px solid var(--border);border-radius:var(--radius-sm);padding:0 12px;font-size:var(--font-sm);color:var(--text-primary);outline:none;background:#fff;min-width:160px;}
.filter-input:focus{border-color:var(--primary);}
.filter-select{height:36px;border:1px solid var(--border);border-radius:var(--radius-sm);padding:0 28px 0 12px;font-size:var(--font-sm);color:var(--text-primary);outline:none;background:#fff url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6'%3E%3Cpath d='M0 0l5 6 5-6z' fill='%23999'/%3E%3C/svg%3E") no-repeat right 10px center;appearance:none;cursor:pointer;min-width:140px;}
.filter-date{height:36px;border:1px solid var(--border);border-radius:var(--radius-sm);padding:0 12px;font-size:var(--font-sm);color:var(--text-primary);outline:none;background:#fff;width:150px;}
.filter-date:focus{border-color:var(--primary);}
.filter-separator{color:var(--text-placeholder);font-size:var(--font-sm);}
.btn{height:36px;padding:0 16px;border-radius:var(--radius-sm);font-size:var(--font-sm);cursor:pointer;border:none;transition:all .2s;display:inline-flex;align-items:center;gap:6px;}
.btn-primary{background:var(--primary);color:#fff;}.btn-primary:hover{background:#40a9ff;}
.btn-default{background:#fff;color:var(--text-primary);border:1px solid var(--border);}.btn-default:hover{color:var(--primary);border-color:var(--primary);}
.action-bar{display:flex;align-items:center;gap:12px;margin-bottom:16px;}
/* 表格 */
.table-card{background:#fff;border-radius:var(--radius-md);box-shadow:var(--shadow-sm);overflow:hidden;}
.table-card__content{overflow-x:auto;-webkit-overflow-scrolling:touch;}
table{width:100%;border-collapse:collapse;min-width:1100px;}
thead th{background:#FAFAFA;padding:12px 14px;text-align:center;font-size:var(--font-xs);color:var(--text-secondary);font-weight:500;border-bottom:1px solid var(--border);border-right:1px solid var(--border);white-space:nowrap;}
thead th:last-child{border-right:none;}
thead th.th-left{text-align:left;}
tbody td{padding:12px 14px;font-size:var(--font-xs);color:var(--text-primary);border-bottom:1px solid var(--border);text-align:center;white-space:nowrap;}
tbody td.td-left{text-align:left;}
tbody tr:last-child td{border-bottom:none;}
tbody tr:hover{background:#F8FBFF;}
.danger-text{color:var(--danger);font-weight:500;}
.pagination{display:flex;align-items:center;justify-content:flex-end;padding:16px 24px;gap:8px;border-top:1px solid var(--border);}
.pagination span{font-size:var(--font-sm);color:var(--text-secondary);}
.page-btn{width:32px;height:32px;border:1px solid var(--border);border-radius:var(--radius-sm);background:#fff;cursor:pointer;font-size:var(--font-sm);display:inline-flex;align-items:center;justify-content:center;transition:all .2s;}
.page-btn:hover,.page-btn.active{background:var(--primary);color:#fff;border-color:var(--primary);}
</style>
</head>
<body>
@@ -57,10 +84,7 @@
<a href="../exception-dirty.html">异常事件</a>
</nav>
<div class="top-bar__right">
<a class="btn-back" href="../../../index.html">
<svg width="16" height="16" viewBox="0 0 16 16" fill="none"><path d="M10 3L5 8l5 5" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/></svg>
返回首页
</a>
<a class="btn-back" href="../../../index.html"><svg width="16" height="16" viewBox="0 0 16 16" fill="none"><path d="M10 3L5 8l5 5" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/></svg> 返回首页</a>
<div class="avatar"></div>
<span style="color:rgba(255,255,255,0.65);">系统管理员 ▾</span>
</div>
@@ -114,11 +138,110 @@
</div>
</aside>
<main class="main">
<div class="page-placeholder">
<svg width="64" height="64" viewBox="0 0 64 64" fill="none"><rect x="8" y="8" width="48" height="48" rx="8" stroke="#ccc" stroke-width="2"/><path d="M20 32h24M32 20v24" stroke="#ccc" stroke-width="2" stroke-linecap="round"/></svg>
<p>异常报警</p>
<!-- 筛选条件 -->
<div class="filter-bar">
<div class="filter-item"><label>设备名称</label><input class="filter-input" placeholder="请输入设备名称"></div>
<div class="filter-item"><label>设备编号</label><input class="filter-input" placeholder="请输入设备编号"></div>
<div class="filter-item"><label>所属单位</label>
<select class="filter-select"><option value="">全部</option><option>采油一厂</option><option>采油二厂</option><option>采油三厂</option></select>
</div>
<div class="filter-item"><label>监测类型</label>
<select class="filter-select"><option value="">全部</option><option>温度</option><option>湿度</option><option>CO₂</option><option>甲醛</option><option>PM2.5</option><option>PM10</option></select>
</div>
<div class="filter-item"><label>日期范围</label><input class="filter-date" type="date" value="2026-05-01"><span class="filter-separator"></span><input class="filter-date" type="date" value="2026-05-15"></div>
<button class="btn btn-primary">查询</button>
<button class="btn btn-default">重置</button>
</div>
<!-- 操作按钮 -->
<div class="action-bar">
<button class="btn btn-default">导出列表数据</button>
<button class="btn btn-default">查看导出任务</button>
</div>
<!-- 数据列表 -->
<div class="table-card">
<div class="table-card__content">
<table>
<thead>
<tr>
<th class="th-left" style="min-width:150px;">设备名称</th>
<th style="min-width:120px;">设备编号</th>
<th style="min-width:90px;">所属单位</th>
<th style="min-width:140px;">设备位置</th>
<th style="min-width:80px;">监测类型</th>
<th style="min-width:80px;">单位</th>
<th style="min-width:70px;">阈值</th>
<th style="min-width:80px;">异常值</th>
<th style="min-width:160px;">报警时间</th>
</tr>
</thead>
<tbody>
<tr>
<td class="td-left">综合空气监测仪-A01</td>
<td>IA-2024-001</td>
<td>采油一厂</td>
<td>办公楼1层大厅</td>
<td>甲醛</td>
<td>mg/m³</td>
<td>0.08</td>
<td class="danger-text">0.15</td>
<td>2026-05-15 09:12:36</td>
</tr>
<tr>
<td class="td-left">PM2.5检测仪-B03</td>
<td>IA-2024-002</td>
<td>采油一厂</td>
<td>办公楼2层会议室</td>
<td>PM2.5</td>
<td>μg/m³</td>
<td>75</td>
<td class="danger-text">128</td>
<td>2026-05-15 08:45:20</td>
</tr>
<tr>
<td class="td-left">CO2检测仪-D01</td>
<td>IA-2024-004</td>
<td>采油二厂</td>
<td>地下车库B1层</td>
<td>CO₂</td>
<td>ppm</td>
<td>1000</td>
<td class="danger-text">1350</td>
<td>2026-05-14 16:30:15</td>
</tr>
<tr>
<td class="td-left">综合空气监测仪-A05</td>
<td>IA-2024-005</td>
<td>采油三厂</td>
<td>生产车间1号</td>
<td>温度</td>
<td></td>
<td>35</td>
<td class="danger-text">38.6</td>
<td>2026-05-14 14:22:08</td>
</tr>
<tr>
<td class="td-left">甲醛检测仪-C02</td>
<td>IA-2024-003</td>
<td>采油二厂</td>
<td>新装修办公室3层</td>
<td>PM10</td>
<td>μg/m³</td>
<td>150</td>
<td class="danger-text">203</td>
<td>2026-05-14 11:05:42</td>
</tr>
</tbody>
</table>
</div>
<div class="pagination">
<span>共 5 条</span>
<button class="page-btn active">1</button>
</div>
</div>
</main>
<script>function toggleSubgroup(h){h.parentElement.classList.toggle('open');}(function(){var a=document.querySelector('.sidebar-item.active');if(!a)return;var s=a.closest('.sidebar-subgroup');if(s)s.classList.add('open');})();</script>
<script>
function toggleSubgroup(h){h.parentElement.classList.toggle('open');}
(function(){var a=document.querySelector('.sidebar-item.active');if(!a)return;var s=a.closest('.sidebar-subgroup');if(s)s.classList.add('open');})();
</script>
</body>
</html>
</html>
@@ -0,0 +1,260 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>室内空气 - 异常数据详情 | 健康长庆原型</title>
<style>
*{box-sizing:border-box;margin:0;padding:0;}
body{font-family:-apple-system,BlinkMacSystemFont,'PingFang SC','Microsoft YaHei',sans-serif;background:#F5F7FA;color:#333;min-width:1280px;}
:root{
--primary:#1890FF;--primary-light:#E6F7FF;--success:#52C41A;--warning:#FAAD14;--danger:#FF4D4F;
--text-primary:#333;--text-secondary:#666;--text-placeholder:#999;--border:#E8E8E8;--background:#F5F7FA;
--font-xs:11px;--font-sm:13px;--font-base:15px;--font-lg:17px;
--radius-sm:4px;--radius-md:8px;--radius-lg:12px;
--shadow-sm:0 1px 4px rgba(0,0,0,0.08);
}
.top-bar{display:flex;align-items:center;height:56px;background:#001529;padding:0 24px;position:fixed;top:0;left:0;right:0;z-index:100;}
.top-bar__logo{display:flex;align-items:center;gap:8px;color:#fff;font-size:var(--font-lg);font-weight:600;white-space:nowrap;width:240px;flex-shrink:0;}
.top-bar__logo svg{width:28px;height:28px;}
.top-bar__right{display:flex;align-items:center;gap:16px;color:rgba(255,255,255,0.65);font-size:var(--font-sm);}
.btn-back{color:rgba(255,255,255,0.65);cursor:pointer;display:flex;align-items:center;gap:4px;text-decoration:none;}.btn-back:hover{color:#fff;}
.avatar{width:32px;height:32px;border-radius:50%;background:#1890FF;display:flex;align-items:center;justify-content:center;color:#fff;font-size:var(--font-sm);cursor:pointer;}
.top-bar__nav{display:flex;align-items:center;gap:4px;flex:1;}
.top-bar__nav a{color:rgba(255,255,255,0.65);text-decoration:none;padding:6px 16px;border-radius:var(--radius-sm);font-size:var(--font-sm);transition:all .2s;}
.top-bar__nav a:hover{color:#fff;background:rgba(255,255,255,0.08);}
.top-bar__nav a.active{color:#fff;background:var(--primary);}
.sidebar{position:fixed;top:56px;left:0;bottom:0;width:240px;background:#001529;overflow-y:auto;z-index:90;padding-top:8px;}
.sidebar-menu__title{color:rgba(255,255,255,0.35);font-size:var(--font-xs);padding:16px 24px 8px;letter-spacing:.5px;}
.sidebar-item{display:flex;align-items:center;gap:8px;padding:10px 24px;color:rgba(255,255,255,0.65);font-size:var(--font-sm);cursor:pointer;transition:all .15s;text-decoration:none;}
.sidebar-item:hover{color:#fff;background:rgba(255,255,255,0.06);}
.sidebar-item.active{color:#fff;background:var(--primary);}
.sidebar-subgroup__header{display:flex;align-items:center;gap:6px;padding:10px 24px;color:rgba(255,255,255,0.65);font-size:var(--font-sm);cursor:pointer;transition:all .15s;user-select:none;}
.sidebar-subgroup__header:hover{color:rgba(255,255,255,0.85);background:rgba(255,255,255,0.04);}
.sidebar-subgroup__header .arrow{width:10px;height:10px;transition:transform .2s;flex-shrink:0;}
.sidebar-subgroup__header .arrow path{stroke:rgba(255,255,255,0.45);}
.sidebar-subgroup.open>.sidebar-subgroup__header{color:rgba(255,255,255,0.85);}
.sidebar-subgroup.open>.sidebar-subgroup__header .arrow{transform:rotate(90deg);}
.sidebar-subgroup__body{display:none;padding-left:16px;}
.sidebar-subgroup.open>.sidebar-subgroup__body{display:block;}
.sidebar-subgroup__body .sidebar-item{padding-left:36px;font-size:12px;}
.main{margin-left:240px;margin-top:56px;padding:24px;min-height:calc(100vh - 56px);}
.page-header{display:flex;align-items:center;gap:12px;margin-bottom:16px;}
.page-header__back{display:flex;align-items:center;gap:4px;color:var(--text-secondary);font-size:var(--font-sm);cursor:pointer;text-decoration:none;}.page-header__back:hover{color:var(--primary);}
.page-header__title{font-size:var(--font-lg);font-weight:600;color:var(--text-primary);}
.info-card{background:#fff;border-radius:var(--radius-md);padding:20px 24px;margin-bottom:16px;box-shadow:var(--shadow-sm);display:grid;grid-template-columns:repeat(3,1fr);gap:16px 24px;}
.info-card__item{display:flex;align-items:baseline;gap:8px;min-width:0;}
.info-card__label{font-size:var(--font-xs);color:var(--text-placeholder);white-space:nowrap;flex-shrink:0;}
.info-card__value{font-size:var(--font-sm);color:var(--text-primary);font-weight:500;word-break:break-all;}
.filter-bar{background:#fff;border-radius:var(--radius-md);padding:20px 24px;margin-bottom:16px;box-shadow:var(--shadow-sm);display:flex;align-items:center;gap:16px;flex-wrap:wrap;}
.filter-item{display:flex;align-items:center;gap:8px;}
.filter-item label{font-size:var(--font-sm);color:var(--text-secondary);white-space:nowrap;}
.filter-date{height:36px;border:1px solid var(--border);border-radius:var(--radius-sm);padding:0 12px;font-size:var(--font-sm);color:var(--text-primary);outline:none;background:#fff;width:150px;}.filter-date:focus{border-color:var(--primary);}
.filter-select{height:36px;border:1px solid var(--border);border-radius:var(--radius-sm);padding:0 28px 0 12px;font-size:var(--font-sm);color:var(--text-primary);outline:none;background:#fff url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6'%3E%3Cpath d='M0 0l5 6 5-6z' fill='%23999'/%3E%3C/svg%3E") no-repeat right 10px center;appearance:none;cursor:pointer;min-width:140px;}
.filter-separator{color:var(--text-placeholder);font-size:var(--font-sm);}
.btn{height:36px;padding:0 16px;border-radius:var(--radius-sm);font-size:var(--font-sm);cursor:pointer;border:none;transition:all .2s;display:inline-flex;align-items:center;gap:6px;}
.btn-primary{background:var(--primary);color:#fff;}.btn-primary:hover{background:#40a9ff;}
.btn-default{background:#fff;color:var(--text-primary);border:1px solid var(--border);}.btn-default:hover{color:var(--primary);border-color:var(--primary);}
.action-bar{display:flex;align-items:center;gap:12px;margin-bottom:16px;}
.table-card{background:#fff;border-radius:var(--radius-md);box-shadow:var(--shadow-sm);overflow:hidden;}
.table-card__content{overflow-x:auto;-webkit-overflow-scrolling:touch;}
table{width:100%;border-collapse:collapse;min-width:900px;}
thead th{background:#FAFAFA;padding:12px 14px;text-align:center;font-size:var(--font-xs);color:var(--text-secondary);font-weight:500;border-bottom:1px solid var(--border);border-right:1px solid var(--border);white-space:nowrap;}
thead th:last-child{border-right:none;}
thead th.th-left{text-align:left;}
tbody td{padding:12px 14px;font-size:var(--font-xs);color:var(--text-primary);border-bottom:1px solid var(--border);text-align:center;white-space:nowrap;}
tbody td.td-left{text-align:left;}
tbody tr:last-child td{border-bottom:none;}
tbody tr:hover{background:#F8FBFF;}
.danger-text{color:var(--danger);font-weight:500;}
.pagination{display:flex;align-items:center;justify-content:flex-end;padding:16px 24px;gap:8px;border-top:1px solid var(--border);}
.pagination span{font-size:var(--font-sm);color:var(--text-secondary);}
.page-btn{width:32px;height:32px;border:1px solid var(--border);border-radius:var(--radius-sm);background:#fff;cursor:pointer;font-size:var(--font-sm);display:inline-flex;align-items:center;justify-content:center;transition:all .2s;}
.page-btn:hover,.page-btn.active{background:var(--primary);color:#fff;border-color:var(--primary);}
</style>
</head>
<body>
<div class="top-bar">
<div class="top-bar__logo"><svg viewBox="0 0 28 28" fill="none"><rect width="28" height="28" rx="6" fill="#1890FF"/><path d="M7 14h14M14 7v14" stroke="#fff" stroke-width="2.5" stroke-linecap="round"/></svg> 健康监测</div>
<nav class="top-bar__nav">
<a href="../archive-personal.html">档案</a>
<a href="../health-checkup/survey-category.html">健康排查</a>
<a href="../wearable/tool-manage.html">穿戴监测</a>
<a href="../weight/scale-device.html">体重监测</a>
<a href="../environment/indoor-device-list.html" class="active">环境监测</a>
<a href="../exception-dirty.html">异常事件</a>
</nav>
<div class="top-bar__right">
<a class="btn-back" href="../../../index.html"><svg width="16" height="16" viewBox="0 0 16 16" fill="none"><path d="M10 3L5 8l5 5" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/></svg> 返回首页</a>
<div class="avatar"></div>
<span style="color:rgba(255,255,255,0.65);">系统管理员 ▾</span>
</div>
</div>
<aside class="sidebar">
<div class="sidebar-menu__title">环境监测</div>
<div class="sidebar-subgroup open">
<div class="sidebar-subgroup__header" onclick="toggleSubgroup(this)"><svg class="arrow" viewBox="0 0 12 12"><path d="M4 2l4 4-4 4" fill="none" stroke-width="1.5" stroke-linecap="round"/></svg> 室内空气</div>
<div class="sidebar-subgroup__body">
<a href="indoor-device-list.html" class="sidebar-item">设备列表</a>
<a href="indoor-device-category.html" class="sidebar-item">设备分类</a>
<a href="indoor-data-monitor.html" class="sidebar-item">数据监测</a>
<a href="indoor-exception-alarm.html" class="sidebar-item">异常报警</a>
<a href="indoor-app-record.html" class="sidebar-item">应用记录</a>
<a href="indoor-history-data.html" class="sidebar-item active">历史数据</a>
</div>
</div>
<div class="sidebar-subgroup">
<div class="sidebar-subgroup__header" onclick="toggleSubgroup(this)"><svg class="arrow" viewBox="0 0 12 12"><path d="M4 2l4 4-4 4" fill="none" stroke-width="1.5" stroke-linecap="round"/></svg> 室外空气</div>
<div class="sidebar-subgroup__body">
<a href="outdoor-device-list.html" class="sidebar-item">设备列表</a>
<a href="outdoor-device-category.html" class="sidebar-item">设备分类</a>
<a href="outdoor-data-monitor.html" class="sidebar-item">数据监测</a>
<a href="outdoor-exception-alarm.html" class="sidebar-item">异常报警</a>
<a href="outdoor-app-record.html" class="sidebar-item">应用记录</a>
<a href="outdoor-history-data.html" class="sidebar-item">历史数据</a>
</div>
</div>
<div class="sidebar-subgroup">
<div class="sidebar-subgroup__header" onclick="toggleSubgroup(this)"><svg class="arrow" viewBox="0 0 12 12"><path d="M4 2l4 4-4 4" fill="none" stroke-width="1.5" stroke-linecap="round"/></svg> 水质监测</div>
<div class="sidebar-subgroup__body">
<a href="water-device-list.html" class="sidebar-item">设备列表</a>
<a href="water-device-category.html" class="sidebar-item">设备分类</a>
<a href="water-data-monitor.html" class="sidebar-item">数据监测</a>
<a href="water-exception-alarm.html" class="sidebar-item">异常报警</a>
<a href="water-app-record.html" class="sidebar-item">应用记录</a>
<a href="water-history-data.html" class="sidebar-item">历史数据</a>
</div>
</div>
<div class="sidebar-subgroup">
<div class="sidebar-subgroup__header" onclick="toggleSubgroup(this)"><svg class="arrow" viewBox="0 0 12 12"><path d="M4 2l4 4-4 4" fill="none" stroke-width="1.5" stroke-linecap="round"/></svg> 花粉监测</div>
<div class="sidebar-subgroup__body">
<a href="pollen-device-list.html" class="sidebar-item">设备列表</a>
<a href="pollen-device-category.html" class="sidebar-item">设备分类</a>
<a href="pollen-data-monitor.html" class="sidebar-item">数据监测</a>
<a href="pollen-exception-alarm.html" class="sidebar-item">异常报警</a>
<a href="pollen-app-record.html" class="sidebar-item">应用记录</a>
<a href="pollen-history-data.html" class="sidebar-item">历史数据</a>
<a href="pollen-knowledge.html" class="sidebar-item">知识科普</a>
</div>
</div>
</aside>
<main class="main">
<!-- 页面标题与返回 -->
<div class="page-header">
<a class="page-header__back" href="indoor-history-data.html"><svg width="14" height="14" viewBox="0 0 16 16" fill="none"><path d="M10 3L5 8l5 5" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/></svg> 返回</a>
<span class="page-header__title">异常数据详情</span>
</div>
<!-- 设备信息卡片 -->
<div class="info-card">
<div class="info-card__item"><span class="info-card__label">设备名称</span><span class="info-card__value">综合空气监测仪-A01</span></div>
<div class="info-card__item"><span class="info-card__label">设备编码</span><span class="info-card__value">IA-2024-001</span></div>
<div class="info-card__item"><span class="info-card__label">所属单位</span><span class="info-card__value">采油一厂</span></div>
<div class="info-card__item"><span class="info-card__label">设备位置</span><span class="info-card__value">办公楼1层大厅</span></div>
<div class="info-card__item"><span class="info-card__label">监测日期</span><span class="info-card__value">2026-03-01 ~ 2026-05-15</span></div>
<div class="info-card__item"><span class="info-card__label">监测时长</span><span class="info-card__value">76 天</span></div>
</div>
<!-- 筛选条件 -->
<div class="filter-bar">
<div class="filter-item"><label>监测日期</label><input class="filter-date" type="date" value="2026-05-01"><span class="filter-separator"></span><input class="filter-date" type="date" value="2026-05-15"></div>
<div class="filter-item"><label>监测类型</label>
<select class="filter-select"><option value="">全部</option><option>温度</option><option>湿度</option><option>CO₂</option><option>甲醛</option><option>PM2.5</option><option>PM10</option></select>
</div>
<button class="btn btn-primary">查询</button>
<button class="btn btn-default">重置</button>
</div>
<!-- 操作按钮 -->
<div class="action-bar"><button class="btn btn-default">导出列表数据</button></div>
<!-- 数据列表 -->
<div class="table-card">
<div class="table-card__content">
<table>
<thead>
<tr>
<th style="min-width:90px;">监测类型</th>
<th style="min-width:90px;">单位</th>
<th style="min-width:80px;">阈值上限</th>
<th style="min-width:80px;">阈值下限</th>
<th style="min-width:80px;">异常值</th>
<th style="min-width:160px;">报警时间</th>
</tr>
</thead>
<tbody>
<tr>
<td>PM2.5</td>
<td>μg/m³</td>
<td>75</td>
<td></td>
<td class="danger-text">98</td>
<td>2026-05-15 07:45:12</td>
</tr>
<tr>
<td>CO₂</td>
<td>ppm</td>
<td>1000</td>
<td></td>
<td class="danger-text">1125</td>
<td>2026-05-14 14:32:08</td>
</tr>
<tr>
<td>甲醛</td>
<td>mg/m³</td>
<td>0.08</td>
<td></td>
<td class="danger-text">0.12</td>
<td>2026-05-13 16:20:45</td>
</tr>
<tr>
<td>PM10</td>
<td>μg/m³</td>
<td>150</td>
<td></td>
<td class="danger-text">178</td>
<td>2026-05-12 09:15:33</td>
</tr>
<tr>
<td>温度</td>
<td></td>
<td>28</td>
<td>16</td>
<td class="danger-text">29.3</td>
<td>2026-05-11 15:08:22</td>
</tr>
<tr>
<td>湿度</td>
<td>%</td>
<td>70</td>
<td>30</td>
<td class="danger-text">74</td>
<td>2026-05-10 11:42:56</td>
</tr>
<tr>
<td>PM2.5</td>
<td>μg/m³</td>
<td>75</td>
<td></td>
<td class="danger-text">82</td>
<td>2026-05-09 08:30:18</td>
</tr>
<tr>
<td>CO₂</td>
<td>ppm</td>
<td>1000</td>
<td></td>
<td class="danger-text">1056</td>
<td>2026-05-08 17:25:40</td>
</tr>
</tbody>
</table>
</div>
<div class="pagination">
<span>共 8 条</span>
<button class="page-btn active">1</button>
</div>
</div>
</main>
<script>
function toggleSubgroup(h){h.parentElement.classList.toggle('open');}
(function(){var a=document.querySelector('.sidebar-item.active');if(!a)return;var s=a.closest('.sidebar-subgroup');if(s)s.classList.add('open');})();
</script>
</body>
</html>
@@ -3,7 +3,7 @@
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>健康监测 - 历史数据 | 健康长庆原型</title>
<title>室内空气 - 历史数据 | 健康长庆原型</title>
<style>
*{box-sizing:border-box;margin:0;padding:0;}
body{font-family:-apple-system,BlinkMacSystemFont,'PingFang SC','Microsoft YaHei',sans-serif;background:#F5F7FA;color:#333;min-width:1280px;}
@@ -18,8 +18,7 @@
.top-bar__logo{display:flex;align-items:center;gap:8px;color:#fff;font-size:var(--font-lg);font-weight:600;white-space:nowrap;width:240px;flex-shrink:0;}
.top-bar__logo svg{width:28px;height:28px;}
.top-bar__right{display:flex;align-items:center;gap:16px;color:rgba(255,255,255,0.65);font-size:var(--font-sm);}
.btn-back{color:rgba(255,255,255,0.65);cursor:pointer;display:flex;align-items:center;gap:4px;text-decoration:none;}
.btn-back:hover{color:#fff;}
.btn-back{color:rgba(255,255,255,0.65);cursor:pointer;display:flex;align-items:center;gap:4px;text-decoration:none;}.btn-back:hover{color:#fff;}
.avatar{width:32px;height:32px;border-radius:50%;background:#1890FF;display:flex;align-items:center;justify-content:center;color:#fff;font-size:var(--font-sm);cursor:pointer;}
.top-bar__nav{display:flex;align-items:center;gap:4px;flex:1;}
.top-bar__nav a{color:rgba(255,255,255,0.65);text-decoration:none;padding:6px 16px;border-radius:var(--radius-sm);font-size:var(--font-sm);transition:all .2s;}
@@ -40,9 +39,30 @@
.sidebar-subgroup.open>.sidebar-subgroup__body{display:block;}
.sidebar-subgroup__body .sidebar-item{padding-left:36px;font-size:12px;}
.main{margin-left:240px;margin-top:56px;padding:24px;min-height:calc(100vh - 56px);}
.page-placeholder{display:flex;flex-direction:column;align-items:center;justify-content:center;height:calc(100vh - 56px - 48px);color:var(--text-placeholder);gap:12px;}
.page-placeholder svg{opacity:.25;}
.page-placeholder p{font-size:var(--font-base);}
.filter-bar{background:#fff;border-radius:var(--radius-md);padding:20px 24px;margin-bottom:16px;box-shadow:var(--shadow-sm);display:flex;align-items:center;gap:16px;flex-wrap:wrap;}
.filter-item{display:flex;align-items:center;gap:8px;}
.filter-item label{font-size:var(--font-sm);color:var(--text-secondary);white-space:nowrap;}
.filter-input{height:36px;border:1px solid var(--border);border-radius:var(--radius-sm);padding:0 12px;font-size:var(--font-sm);color:var(--text-primary);outline:none;background:#fff;min-width:180px;}.filter-input:focus{border-color:var(--primary);}
.filter-select{height:36px;border:1px solid var(--border);border-radius:var(--radius-sm);padding:0 28px 0 12px;font-size:var(--font-sm);color:var(--text-primary);outline:none;background:#fff url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6'%3E%3Cpath d='M0 0l5 6 5-6z' fill='%23999'/%3E%3C/svg%3E") no-repeat right 10px center;appearance:none;cursor:pointer;min-width:140px;}
.btn{height:36px;padding:0 16px;border-radius:var(--radius-sm);font-size:var(--font-sm);cursor:pointer;border:none;transition:all .2s;display:inline-flex;align-items:center;gap:6px;}
.btn-primary{background:var(--primary);color:#fff;}.btn-primary:hover{background:#40a9ff;}
.btn-default{background:#fff;color:var(--text-primary);border:1px solid var(--border);}.btn-default:hover{color:var(--primary);border-color:var(--primary);}
.action-bar{display:flex;align-items:center;gap:12px;margin-bottom:16px;}
.table-card{background:#fff;border-radius:var(--radius-md);box-shadow:var(--shadow-sm);overflow:hidden;}
.table-card__content{overflow-x:auto;-webkit-overflow-scrolling:touch;}
table{width:100%;border-collapse:collapse;min-width:1000px;}
thead th{background:#FAFAFA;padding:12px 14px;text-align:center;font-size:var(--font-xs);color:var(--text-secondary);font-weight:500;border-bottom:1px solid var(--border);border-right:1px solid var(--border);white-space:nowrap;}
thead th:last-child{border-right:none;}
thead th.th-left{text-align:left;}
tbody td{padding:12px 14px;font-size:var(--font-xs);color:var(--text-primary);border-bottom:1px solid var(--border);text-align:center;white-space:nowrap;}
tbody td.td-left{text-align:left;}
tbody tr:last-child td{border-bottom:none;}
tbody tr:hover{background:#F8FBFF;}
.link-btn{color:var(--primary);cursor:pointer;text-decoration:none;font-size:var(--font-xs);}.link-btn:hover{text-decoration:underline;}
.pagination{display:flex;align-items:center;justify-content:flex-end;padding:16px 24px;gap:8px;border-top:1px solid var(--border);}
.pagination span{font-size:var(--font-sm);color:var(--text-secondary);}
.page-btn{width:32px;height:32px;border:1px solid var(--border);border-radius:var(--radius-sm);background:#fff;cursor:pointer;font-size:var(--font-sm);display:inline-flex;align-items:center;justify-content:center;transition:all .2s;}
.page-btn:hover,.page-btn.active{background:var(--primary);color:#fff;border-color:var(--primary);}
</style>
</head>
<body>
@@ -57,10 +77,7 @@
<a href="../exception-dirty.html">异常事件</a>
</nav>
<div class="top-bar__right">
<a class="btn-back" href="../../../index.html">
<svg width="16" height="16" viewBox="0 0 16 16" fill="none"><path d="M10 3L5 8l5 5" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/></svg>
返回首页
</a>
<a class="btn-back" href="../../../index.html"><svg width="16" height="16" viewBox="0 0 16 16" fill="none"><path d="M10 3L5 8l5 5" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/></svg> 返回首页</a>
<div class="avatar"></div>
<span style="color:rgba(255,255,255,0.65);">系统管理员 ▾</span>
</div>
@@ -114,11 +131,91 @@
</div>
</aside>
<main class="main">
<div class="page-placeholder">
<svg width="64" height="64" viewBox="0 0 64 64" fill="none"><rect x="8" y="8" width="48" height="48" rx="8" stroke="#ccc" stroke-width="2"/><path d="M20 32h24M32 20v24" stroke="#ccc" stroke-width="2" stroke-linecap="round"/></svg>
<p>历史数据</p>
<div class="filter-bar">
<div class="filter-item"><label>设备名称</label><input class="filter-input" placeholder="请输入设备名称"></div>
<div class="filter-item"><label>设备编码</label><input class="filter-input" placeholder="请输入设备编码"></div>
<div class="filter-item"><label>所属单位</label>
<select class="filter-select"><option value="">全部</option><option>采油一厂</option><option>采油二厂</option><option>采油三厂</option></select>
</div>
<button class="btn btn-primary">查询</button>
<button class="btn btn-default">重置</button>
</div>
<div class="action-bar"><button class="btn btn-default">导出列表数据</button></div>
<div class="table-card">
<div class="table-card__content">
<table>
<thead>
<tr>
<th class="th-left" style="min-width:150px;">设备名称</th>
<th style="min-width:110px;">设备编码</th>
<th style="min-width:90px;">所属单位</th>
<th style="min-width:130px;">设备位置</th>
<th style="min-width:180px;">监测日期</th>
<th style="min-width:90px;">监测时长(天)</th>
<th style="min-width:80px;">监测数据</th>
<th style="min-width:80px;">异常数据</th>
</tr>
</thead>
<tbody>
<tr>
<td class="td-left">综合空气监测仪-A01</td>
<td>IA-2024-001</td>
<td>采油一厂</td>
<td>办公楼1层大厅</td>
<td>2026-03-01 ~ 2026-05-15</td>
<td>76</td>
<td><a class="link-btn" href="indoor-history-monitor-detail.html">查看</a></td>
<td><a class="link-btn" href="indoor-history-alarm-detail.html">查看</a></td>
</tr>
<tr>
<td class="td-left">PM2.5检测仪-B03</td>
<td>IA-2024-002</td>
<td>采油一厂</td>
<td>办公楼2层会议室</td>
<td>2026-02-15 ~ 2026-05-15</td>
<td>89</td>
<td><a class="link-btn" href="indoor-history-monitor-detail.html">查看</a></td>
<td><a class="link-btn" href="indoor-history-alarm-detail.html">查看</a></td>
</tr>
<tr>
<td class="td-left">甲醛检测仪-C02</td>
<td>IA-2024-003</td>
<td>采油二厂</td>
<td>新装修办公室3层</td>
<td>2026-04-01 ~ 2026-05-15</td>
<td>45</td>
<td><a class="link-btn" href="indoor-history-monitor-detail.html">查看</a></td>
<td><a class="link-btn" href="indoor-history-alarm-detail.html">查看</a></td>
</tr>
<tr>
<td class="td-left">CO2检测仪-D01</td>
<td>IA-2024-004</td>
<td>采油二厂</td>
<td>地下车库B1层</td>
<td>2026-01-10 ~ 2026-05-15</td>
<td>125</td>
<td><a class="link-btn" href="indoor-history-monitor-detail.html">查看</a></td>
<td><a class="link-btn" href="indoor-history-alarm-detail.html">查看</a></td>
</tr>
<tr>
<td class="td-left">综合空气监测仪-A05</td>
<td>IA-2024-005</td>
<td>采油三厂</td>
<td>生产车间1号</td>
<td>2026-03-20 ~ 2026-05-15</td>
<td>56</td>
<td><a class="link-btn" href="indoor-history-monitor-detail.html">查看</a></td>
<td><a class="link-btn" href="indoor-history-alarm-detail.html">查看</a></td>
</tr>
</tbody>
</table>
</div>
<div class="pagination"><span>共 5 条</span><button class="page-btn active">1</button></div>
</div>
</main>
<script>function toggleSubgroup(h){h.parentElement.classList.toggle('open');}(function(){var a=document.querySelector('.sidebar-item.active');if(!a)return;var s=a.closest('.sidebar-subgroup');if(s)s.classList.add('open');})();</script>
<script>
function toggleSubgroup(h){h.parentElement.classList.toggle('open');}
(function(){var a=document.querySelector('.sidebar-item.active');if(!a)return;var s=a.closest('.sidebar-subgroup');if(s)s.classList.add('open');})();
</script>
</body>
</html>
</html>
@@ -0,0 +1,213 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>室内空气 - 监测数据详情 | 健康长庆原型</title>
<style>
*{box-sizing:border-box;margin:0;padding:0;}
body{font-family:-apple-system,BlinkMacSystemFont,'PingFang SC','Microsoft YaHei',sans-serif;background:#F5F7FA;color:#333;min-width:1280px;}
:root{
--primary:#1890FF;--primary-light:#E6F7FF;--success:#52C41A;--warning:#FAAD14;--danger:#FF4D4F;
--text-primary:#333;--text-secondary:#666;--text-placeholder:#999;--border:#E8E8E8;--background:#F5F7FA;
--font-xs:11px;--font-sm:13px;--font-base:15px;--font-lg:17px;
--radius-sm:4px;--radius-md:8px;--radius-lg:12px;
--shadow-sm:0 1px 4px rgba(0,0,0,0.08);
}
.top-bar{display:flex;align-items:center;height:56px;background:#001529;padding:0 24px;position:fixed;top:0;left:0;right:0;z-index:100;}
.top-bar__logo{display:flex;align-items:center;gap:8px;color:#fff;font-size:var(--font-lg);font-weight:600;white-space:nowrap;width:240px;flex-shrink:0;}
.top-bar__logo svg{width:28px;height:28px;}
.top-bar__right{display:flex;align-items:center;gap:16px;color:rgba(255,255,255,0.65);font-size:var(--font-sm);}
.btn-back{color:rgba(255,255,255,0.65);cursor:pointer;display:flex;align-items:center;gap:4px;text-decoration:none;}.btn-back:hover{color:#fff;}
.avatar{width:32px;height:32px;border-radius:50%;background:#1890FF;display:flex;align-items:center;justify-content:center;color:#fff;font-size:var(--font-sm);cursor:pointer;}
.top-bar__nav{display:flex;align-items:center;gap:4px;flex:1;}
.top-bar__nav a{color:rgba(255,255,255,0.65);text-decoration:none;padding:6px 16px;border-radius:var(--radius-sm);font-size:var(--font-sm);transition:all .2s;}
.top-bar__nav a:hover{color:#fff;background:rgba(255,255,255,0.08);}
.top-bar__nav a.active{color:#fff;background:var(--primary);}
.sidebar{position:fixed;top:56px;left:0;bottom:0;width:240px;background:#001529;overflow-y:auto;z-index:90;padding-top:8px;}
.sidebar-menu__title{color:rgba(255,255,255,0.35);font-size:var(--font-xs);padding:16px 24px 8px;letter-spacing:.5px;}
.sidebar-item{display:flex;align-items:center;gap:8px;padding:10px 24px;color:rgba(255,255,255,0.65);font-size:var(--font-sm);cursor:pointer;transition:all .15s;text-decoration:none;}
.sidebar-item:hover{color:#fff;background:rgba(255,255,255,0.06);}
.sidebar-item.active{color:#fff;background:var(--primary);}
.sidebar-subgroup__header{display:flex;align-items:center;gap:6px;padding:10px 24px;color:rgba(255,255,255,0.65);font-size:var(--font-sm);cursor:pointer;transition:all .15s;user-select:none;}
.sidebar-subgroup__header:hover{color:rgba(255,255,255,0.85);background:rgba(255,255,255,0.04);}
.sidebar-subgroup__header .arrow{width:10px;height:10px;transition:transform .2s;flex-shrink:0;}
.sidebar-subgroup__header .arrow path{stroke:rgba(255,255,255,0.45);}
.sidebar-subgroup.open>.sidebar-subgroup__header{color:rgba(255,255,255,0.85);}
.sidebar-subgroup.open>.sidebar-subgroup__header .arrow{transform:rotate(90deg);}
.sidebar-subgroup__body{display:none;padding-left:16px;}
.sidebar-subgroup.open>.sidebar-subgroup__body{display:block;}
.sidebar-subgroup__body .sidebar-item{padding-left:36px;font-size:12px;}
.main{margin-left:240px;margin-top:56px;padding:24px;min-height:calc(100vh - 56px);}
.page-header{display:flex;align-items:center;gap:12px;margin-bottom:16px;}
.page-header__back{display:flex;align-items:center;gap:4px;color:var(--text-secondary);font-size:var(--font-sm);cursor:pointer;text-decoration:none;}.page-header__back:hover{color:var(--primary);}
.page-header__title{font-size:var(--font-lg);font-weight:600;color:var(--text-primary);}
.info-card{background:#fff;border-radius:var(--radius-md);padding:20px 24px;margin-bottom:16px;box-shadow:var(--shadow-sm);display:grid;grid-template-columns:repeat(3,1fr);gap:16px 24px;}
.info-card__item{display:flex;align-items:baseline;gap:8px;min-width:0;}
.info-card__label{font-size:var(--font-xs);color:var(--text-placeholder);white-space:nowrap;flex-shrink:0;}
.info-card__value{font-size:var(--font-sm);color:var(--text-primary);font-weight:500;word-break:break-all;}
.filter-bar{background:#fff;border-radius:var(--radius-md);padding:20px 24px;margin-bottom:16px;box-shadow:var(--shadow-sm);display:flex;align-items:center;gap:16px;flex-wrap:wrap;}
.filter-item{display:flex;align-items:center;gap:8px;}
.filter-item label{font-size:var(--font-sm);color:var(--text-secondary);white-space:nowrap;}
.filter-date{height:36px;border:1px solid var(--border);border-radius:var(--radius-sm);padding:0 12px;font-size:var(--font-sm);color:var(--text-primary);outline:none;background:#fff;width:150px;}.filter-date:focus{border-color:var(--primary);}
.filter-separator{color:var(--text-placeholder);font-size:var(--font-sm);}
.btn{height:36px;padding:0 16px;border-radius:var(--radius-sm);font-size:var(--font-sm);cursor:pointer;border:none;transition:all .2s;display:inline-flex;align-items:center;gap:6px;}
.btn-primary{background:var(--primary);color:#fff;}.btn-primary:hover{background:#40a9ff;}
.btn-default{background:#fff;color:var(--text-primary);border:1px solid var(--border);}.btn-default:hover{color:var(--primary);border-color:var(--primary);}
.action-bar{display:flex;align-items:center;gap:12px;margin-bottom:16px;}
.table-card{background:#fff;border-radius:var(--radius-md);box-shadow:var(--shadow-sm);overflow:hidden;}
.table-card__content{overflow-x:auto;-webkit-overflow-scrolling:touch;}
table{width:100%;border-collapse:collapse;min-width:900px;}
thead th{background:#FAFAFA;padding:12px 14px;text-align:center;font-size:var(--font-xs);color:var(--text-secondary);font-weight:500;border-bottom:1px solid var(--border);border-right:1px solid var(--border);white-space:nowrap;}
thead th:last-child{border-right:none;}
thead th.th-left{text-align:left;}
tbody td{padding:12px 14px;font-size:var(--font-xs);color:var(--text-primary);border-bottom:1px solid var(--border);text-align:center;white-space:nowrap;}
tbody td.td-left{text-align:left;}
tbody tr:last-child td{border-bottom:none;}
tbody tr:hover{background:#F8FBFF;}
.pagination{display:flex;align-items:center;justify-content:flex-end;padding:16px 24px;gap:8px;border-top:1px solid var(--border);}
.pagination span{font-size:var(--font-sm);color:var(--text-secondary);}
.page-btn{width:32px;height:32px;border:1px solid var(--border);border-radius:var(--radius-sm);background:#fff;cursor:pointer;font-size:var(--font-sm);display:inline-flex;align-items:center;justify-content:center;transition:all .2s;}
.page-btn:hover,.page-btn.active{background:var(--primary);color:#fff;border-color:var(--primary);}
.aqi-tag{display:inline-block;padding:2px 10px;border-radius:10px;font-size:var(--font-xs);font-weight:500;}
.aqi-tag--clean{background:#E6FFFB;color:#13C2C2;}
.aqi-tag--good{background:#F6FFED;color:#52C41A;}
.aqi-tag--light{background:#FFFBE6;color:#FAAD14;}
.aqi-tag--moderate{background:#FFF1F0;color:#FA541C;}
.aqi-tag--heavy{background:#FFF1F0;color:#FF4D4F;}
</style>
</head>
<body>
<div class="top-bar">
<div class="top-bar__logo"><svg viewBox="0 0 28 28" fill="none"><rect width="28" height="28" rx="6" fill="#1890FF"/><path d="M7 14h14M14 7v14" stroke="#fff" stroke-width="2.5" stroke-linecap="round"/></svg> 健康监测</div>
<nav class="top-bar__nav">
<a href="../archive-personal.html">档案</a>
<a href="../health-checkup/survey-category.html">健康排查</a>
<a href="../wearable/tool-manage.html">穿戴监测</a>
<a href="../weight/scale-device.html">体重监测</a>
<a href="../environment/indoor-device-list.html" class="active">环境监测</a>
<a href="../exception-dirty.html">异常事件</a>
</nav>
<div class="top-bar__right">
<a class="btn-back" href="../../../index.html"><svg width="16" height="16" viewBox="0 0 16 16" fill="none"><path d="M10 3L5 8l5 5" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/></svg> 返回首页</a>
<div class="avatar"></div>
<span style="color:rgba(255,255,255,0.65);">系统管理员 ▾</span>
</div>
</div>
<aside class="sidebar">
<div class="sidebar-menu__title">环境监测</div>
<div class="sidebar-subgroup open">
<div class="sidebar-subgroup__header" onclick="toggleSubgroup(this)"><svg class="arrow" viewBox="0 0 12 12"><path d="M4 2l4 4-4 4" fill="none" stroke-width="1.5" stroke-linecap="round"/></svg> 室内空气</div>
<div class="sidebar-subgroup__body">
<a href="indoor-device-list.html" class="sidebar-item">设备列表</a>
<a href="indoor-device-category.html" class="sidebar-item">设备分类</a>
<a href="indoor-data-monitor.html" class="sidebar-item">数据监测</a>
<a href="indoor-exception-alarm.html" class="sidebar-item">异常报警</a>
<a href="indoor-app-record.html" class="sidebar-item">应用记录</a>
<a href="indoor-history-data.html" class="sidebar-item active">历史数据</a>
</div>
</div>
<div class="sidebar-subgroup">
<div class="sidebar-subgroup__header" onclick="toggleSubgroup(this)"><svg class="arrow" viewBox="0 0 12 12"><path d="M4 2l4 4-4 4" fill="none" stroke-width="1.5" stroke-linecap="round"/></svg> 室外空气</div>
<div class="sidebar-subgroup__body">
<a href="outdoor-device-list.html" class="sidebar-item">设备列表</a>
<a href="outdoor-device-category.html" class="sidebar-item">设备分类</a>
<a href="outdoor-data-monitor.html" class="sidebar-item">数据监测</a>
<a href="outdoor-exception-alarm.html" class="sidebar-item">异常报警</a>
<a href="outdoor-app-record.html" class="sidebar-item">应用记录</a>
<a href="outdoor-history-data.html" class="sidebar-item">历史数据</a>
</div>
</div>
<div class="sidebar-subgroup">
<div class="sidebar-subgroup__header" onclick="toggleSubgroup(this)"><svg class="arrow" viewBox="0 0 12 12"><path d="M4 2l4 4-4 4" fill="none" stroke-width="1.5" stroke-linecap="round"/></svg> 水质监测</div>
<div class="sidebar-subgroup__body">
<a href="water-device-list.html" class="sidebar-item">设备列表</a>
<a href="water-device-category.html" class="sidebar-item">设备分类</a>
<a href="water-data-monitor.html" class="sidebar-item">数据监测</a>
<a href="water-exception-alarm.html" class="sidebar-item">异常报警</a>
<a href="water-app-record.html" class="sidebar-item">应用记录</a>
<a href="water-history-data.html" class="sidebar-item">历史数据</a>
</div>
</div>
<div class="sidebar-subgroup">
<div class="sidebar-subgroup__header" onclick="toggleSubgroup(this)"><svg class="arrow" viewBox="0 0 12 12"><path d="M4 2l4 4-4 4" fill="none" stroke-width="1.5" stroke-linecap="round"/></svg> 花粉监测</div>
<div class="sidebar-subgroup__body">
<a href="pollen-device-list.html" class="sidebar-item">设备列表</a>
<a href="pollen-device-category.html" class="sidebar-item">设备分类</a>
<a href="pollen-data-monitor.html" class="sidebar-item">数据监测</a>
<a href="pollen-exception-alarm.html" class="sidebar-item">异常报警</a>
<a href="pollen-app-record.html" class="sidebar-item">应用记录</a>
<a href="pollen-history-data.html" class="sidebar-item">历史数据</a>
<a href="pollen-knowledge.html" class="sidebar-item">知识科普</a>
</div>
</div>
</aside>
<main class="main">
<!-- 页面标题与返回 -->
<div class="page-header">
<a class="page-header__back" href="indoor-history-data.html"><svg width="14" height="14" viewBox="0 0 16 16" fill="none"><path d="M10 3L5 8l5 5" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/></svg> 返回</a>
<span class="page-header__title">监测数据详情</span>
</div>
<!-- 设备信息卡片 -->
<div class="info-card">
<div class="info-card__item"><span class="info-card__label">设备名称</span><span class="info-card__value">综合空气监测仪-A01</span></div>
<div class="info-card__item"><span class="info-card__label">设备编码</span><span class="info-card__value">IA-2024-001</span></div>
<div class="info-card__item"><span class="info-card__label">所属单位</span><span class="info-card__value">采油一厂</span></div>
<div class="info-card__item"><span class="info-card__label">设备位置</span><span class="info-card__value">办公楼1层大厅</span></div>
<div class="info-card__item"><span class="info-card__label">监测日期</span><span class="info-card__value">2026-03-01 ~ 2026-05-15</span></div>
<div class="info-card__item"><span class="info-card__label">监测时长</span><span class="info-card__value">76 天</span></div>
</div>
<!-- 筛选条件 -->
<div class="filter-bar">
<div class="filter-item"><label>监测日期</label><input class="filter-date" type="date" value="2026-05-01"><span class="filter-separator"></span><input class="filter-date" type="date" value="2026-05-15"></div>
<button class="btn btn-primary">查询</button>
<button class="btn btn-default">重置</button>
</div>
<!-- 操作按钮 -->
<div class="action-bar"><button class="btn btn-default">导出列表数据</button></div>
<!-- 数据列表 -->
<div class="table-card">
<div class="table-card__content">
<table>
<thead>
<tr>
<th style="min-width:160px;">监测时间</th>
<th style="min-width:90px;">温度(℃)</th>
<th style="min-width:90px;">湿度(%)</th>
<th style="min-width:100px;">CO₂(ppm)</th>
<th style="min-width:110px;">甲醛(mg/m³)</th>
<th style="min-width:110px;">PM2.5(μg/m³)</th>
<th style="min-width:110px;">PM10(μg/m³)</th>
<th style="min-width:100px;">空气质量指数</th>
</tr>
</thead>
<tbody>
<tr><td>2026-05-15 08:00:00</td><td>24.3</td><td>52</td><td>486</td><td>0.03</td><td>35</td><td>58</td><td><span class="aqi-tag aqi-tag--good">未污染</span></td></tr>
<tr><td>2026-05-15 07:00:00</td><td>23.8</td><td>54</td><td>512</td><td>0.02</td><td>32</td><td>54</td><td><span class="aqi-tag aqi-tag--good">未污染</span></td></tr>
<tr><td>2026-05-15 06:00:00</td><td>23.1</td><td>56</td><td>445</td><td>0.02</td><td>28</td><td>47</td><td><span class="aqi-tag aqi-tag--clean">清洁</span></td></tr>
<tr><td>2026-05-14 23:00:00</td><td>22.5</td><td>58</td><td>398</td><td>0.01</td><td>22</td><td>38</td><td><span class="aqi-tag aqi-tag--clean">清洁</span></td></tr>
<tr><td>2026-05-14 22:00:00</td><td>22.8</td><td>57</td><td>423</td><td>0.02</td><td>25</td><td>42</td><td><span class="aqi-tag aqi-tag--clean">清洁</span></td></tr>
<tr><td>2026-05-14 21:00:00</td><td>23.5</td><td>55</td><td>467</td><td>0.03</td><td>30</td><td>51</td><td><span class="aqi-tag aqi-tag--good">未污染</span></td></tr>
<tr><td>2026-05-14 20:00:00</td><td>24.1</td><td>53</td><td>534</td><td>0.04</td><td>38</td><td>63</td><td><span class="aqi-tag aqi-tag--light">轻污染</span></td></tr>
<tr><td>2026-05-14 19:00:00</td><td>24.6</td><td>51</td><td>578</td><td>0.05</td><td>42</td><td>68</td><td><span class="aqi-tag aqi-tag--light">轻污染</span></td></tr>
<tr><td>2026-05-14 18:00:00</td><td>25.2</td><td>49</td><td>612</td><td>0.04</td><td>45</td><td>72</td><td><span class="aqi-tag aqi-tag--moderate">中污染</span></td></tr>
<tr><td>2026-05-14 17:00:00</td><td>25.8</td><td>47</td><td>645</td><td>0.06</td><td>52</td><td>85</td><td><span class="aqi-tag aqi-tag--heavy">重污染</span></td></tr>
</tbody>
</table>
</div>
<div class="pagination">
<span>共 240 条</span>
<button class="page-btn active">1</button>
<button class="page-btn">2</button>
<button class="page-btn">3</button>
<span>...</span>
<button class="page-btn">24</button>
</div>
</div>
</main>
<script>
function toggleSubgroup(h){h.parentElement.classList.toggle('open');}
(function(){var a=document.querySelector('.sidebar-item.active');if(!a)return;var s=a.closest('.sidebar-subgroup');if(s)s.classList.add('open');})();
</script>
</body>
</html>
@@ -3,7 +3,7 @@
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>健康监测 - 应用记录 | 健康长庆原型</title>
<title>室外空气 - 应用记录 | 健康长庆原型</title>
<style>
*{box-sizing:border-box;margin:0;padding:0;}
body{font-family:-apple-system,BlinkMacSystemFont,'PingFang SC','Microsoft YaHei',sans-serif;background:#F5F7FA;color:#333;min-width:1280px;}
@@ -18,8 +18,7 @@
.top-bar__logo{display:flex;align-items:center;gap:8px;color:#fff;font-size:var(--font-lg);font-weight:600;white-space:nowrap;width:240px;flex-shrink:0;}
.top-bar__logo svg{width:28px;height:28px;}
.top-bar__right{display:flex;align-items:center;gap:16px;color:rgba(255,255,255,0.65);font-size:var(--font-sm);}
.btn-back{color:rgba(255,255,255,0.65);cursor:pointer;display:flex;align-items:center;gap:4px;text-decoration:none;}
.btn-back:hover{color:#fff;}
.btn-back{color:rgba(255,255,255,0.65);cursor:pointer;display:flex;align-items:center;gap:4px;text-decoration:none;}.btn-back:hover{color:#fff;}
.avatar{width:32px;height:32px;border-radius:50%;background:#1890FF;display:flex;align-items:center;justify-content:center;color:#fff;font-size:var(--font-sm);cursor:pointer;}
.top-bar__nav{display:flex;align-items:center;gap:4px;flex:1;}
.top-bar__nav a{color:rgba(255,255,255,0.65);text-decoration:none;padding:6px 16px;border-radius:var(--radius-sm);font-size:var(--font-sm);transition:all .2s;}
@@ -40,9 +39,44 @@
.sidebar-subgroup.open>.sidebar-subgroup__body{display:block;}
.sidebar-subgroup__body .sidebar-item{padding-left:36px;font-size:12px;}
.main{margin-left:240px;margin-top:56px;padding:24px;min-height:calc(100vh - 56px);}
.page-placeholder{display:flex;flex-direction:column;align-items:center;justify-content:center;height:calc(100vh - 56px - 48px);color:var(--text-placeholder);gap:12px;}
.page-placeholder svg{opacity:.25;}
.page-placeholder p{font-size:var(--font-base);}
.filter-bar{background:#fff;border-radius:var(--radius-md);padding:20px 24px;margin-bottom:16px;box-shadow:var(--shadow-sm);display:flex;align-items:center;gap:16px;flex-wrap:wrap;}
.filter-item{display:flex;align-items:center;gap:8px;}
.filter-item label{font-size:var(--font-sm);color:var(--text-secondary);white-space:nowrap;}
.filter-input{height:36px;border:1px solid var(--border);border-radius:var(--radius-sm);padding:0 12px;font-size:var(--font-sm);color:var(--text-primary);outline:none;background:#fff;min-width:180px;}.filter-input:focus{border-color:var(--primary);}
.filter-select{height:36px;border:1px solid var(--border);border-radius:var(--radius-sm);padding:0 28px 0 12px;font-size:var(--font-sm);color:var(--text-primary);outline:none;background:#fff url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6'%3E%3Cpath d='M0 0l5 6 5-6z' fill='%23999'/%3E%3C/svg%3E") no-repeat right 10px center;appearance:none;cursor:pointer;min-width:140px;}
.btn{height:36px;padding:0 16px;border-radius:var(--radius-sm);font-size:var(--font-sm);cursor:pointer;border:none;transition:all .2s;display:inline-flex;align-items:center;gap:6px;}
.btn-primary{background:var(--primary);color:#fff;}.btn-primary:hover{background:#40a9ff;}
.btn-default{background:#fff;color:var(--text-primary);border:1px solid var(--border);}.btn-default:hover{color:var(--primary);border-color:var(--primary);}
.action-bar{display:flex;align-items:center;gap:12px;margin-bottom:16px;}
.table-card{background:#fff;border-radius:var(--radius-md);box-shadow:var(--shadow-sm);overflow:hidden;}
.table-card__content{overflow-x:auto;-webkit-overflow-scrolling:touch;}
table{width:100%;border-collapse:collapse;min-width:1300px;}
thead th{background:#FAFAFA;padding:12px 14px;text-align:center;font-size:var(--font-xs);color:var(--text-secondary);font-weight:500;border-bottom:1px solid var(--border);border-right:1px solid var(--border);white-space:nowrap;}
thead th:last-child{border-right:none;}
thead th.th-left{text-align:left;}
tbody td{padding:12px 14px;font-size:var(--font-xs);color:var(--text-primary);border-bottom:1px solid var(--border);text-align:center;white-space:nowrap;}
tbody td.td-left{text-align:left;}
tbody tr:last-child td{border-bottom:none;}
tbody tr:hover{background:#F8FBFF;}
thead tr:first-child th:nth-child(-n+2),tbody td:nth-child(-n+2){position:sticky;z-index:2;}
thead tr:first-child th:nth-child(-n+2){z-index:3;}
thead tr:first-child th:nth-child(1),tbody td:nth-child(1){left:0;}
thead tr:first-child th:nth-child(2),tbody td:nth-child(2){left:140px;}
tbody td:nth-child(-n+2){background:#fff;}
tbody tr:hover td:nth-child(-n+2){background:#F8FBFF;}
tbody td:nth-child(2),thead tr:first-child th:nth-child(2){box-shadow:2px 0 4px rgba(0,0,0,0.06);}
.th-sort{cursor:pointer;user-select:none;position:relative;padding-right:22px !important;}
.th-sort:hover{color:var(--primary);}
.th-sort .sort-icon{position:absolute;right:4px;top:50%;transform:translateY(-50%);display:flex;flex-direction:column;gap:1px;}
.th-sort .sort-icon .arrow-up,.th-sort .sort-icon .arrow-down{width:0;height:0;border-left:4px solid transparent;border-right:4px solid transparent;}
.th-sort .sort-icon .arrow-up{border-bottom:5px solid #ccc;}
.th-sort .sort-icon .arrow-down{border-top:5px solid #ccc;}
.th-sort.asc .sort-icon .arrow-up{border-bottom-color:var(--primary);}
.th-sort.desc .sort-icon .arrow-down{border-top-color:var(--primary);}
.pagination{display:flex;align-items:center;justify-content:flex-end;padding:16px 24px;gap:8px;border-top:1px solid var(--border);}
.pagination span{font-size:var(--font-sm);color:var(--text-secondary);}
.page-btn{width:32px;height:32px;border:1px solid var(--border);border-radius:var(--radius-sm);background:#fff;cursor:pointer;font-size:var(--font-sm);display:inline-flex;align-items:center;justify-content:center;transition:all .2s;}
.page-btn:hover,.page-btn.active{background:var(--primary);color:#fff;border-color:var(--primary);}
</style>
</head>
<body>
@@ -57,10 +91,7 @@
<a href="../exception-dirty.html">异常事件</a>
</nav>
<div class="top-bar__right">
<a class="btn-back" href="../../../index.html">
<svg width="16" height="16" viewBox="0 0 16 16" fill="none"><path d="M10 3L5 8l5 5" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/></svg>
返回首页
</a>
<a class="btn-back" href="../../../index.html"><svg width="16" height="16" viewBox="0 0 16 16" fill="none"><path d="M10 3L5 8l5 5" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/></svg> 返回首页</a>
<div class="avatar"></div>
<span style="color:rgba(255,255,255,0.65);">系统管理员 ▾</span>
</div>
@@ -114,11 +145,85 @@
</div>
</aside>
<main class="main">
<div class="page-placeholder">
<svg width="64" height="64" viewBox="0 0 64 64" fill="none"><rect x="8" y="8" width="48" height="48" rx="8" stroke="#ccc" stroke-width="2"/><path d="M20 32h24M32 20v24" stroke="#ccc" stroke-width="2" stroke-linecap="round"/></svg>
<p>应用记录</p>
<div class="filter-bar">
<div class="filter-item"><label>设备名称</label><input class="filter-input" placeholder="请输入设备名称"></div>
<div class="filter-item"><label>设备编码</label><input class="filter-input" placeholder="请输入设备编码"></div>
<div class="filter-item"><label>所属单位</label>
<select class="filter-select"><option value="">全部</option><option>采油一厂</option><option>采油二厂</option><option>采油三厂</option></select>
</div>
<button class="btn btn-primary">查询</button>
<button class="btn btn-default">重置</button>
</div>
<div class="action-bar"><button class="btn btn-default">导出列表数据</button></div>
<div class="table-card">
<div class="table-card__content">
<table id="appTable">
<thead>
<tr>
<th rowspan="2" class="th-left" style="min-width:140px;">设备名称</th>
<th rowspan="2" style="min-width:110px;">设备编码</th>
<th rowspan="2" style="min-width:90px;">所属单位</th>
<th rowspan="2" style="min-width:120px;">设备位置</th>
<th colspan="8">移动端点击次数</th>
</tr>
<tr>
<th class="th-sort" data-col="4" onclick="sortTable(this)">温度<span class="sort-icon"><span class="arrow-up"></span><span class="arrow-down"></span></span></th>
<th class="th-sort" data-col="5" onclick="sortTable(this)">湿度<span class="sort-icon"><span class="arrow-up"></span><span class="arrow-down"></span></span></th>
<th class="th-sort" data-col="6" onclick="sortTable(this)">太阳辐射<span class="sort-icon"><span class="arrow-up"></span><span class="arrow-down"></span></span></th>
<th class="th-sort" data-col="7" onclick="sortTable(this)">PM2.5<span class="sort-icon"><span class="arrow-up"></span><span class="arrow-down"></span></span></th>
<th class="th-sort" data-col="8" onclick="sortTable(this)">PM10<span class="sort-icon"><span class="arrow-up"></span><span class="arrow-down"></span></span></th>
<th class="th-sort" data-col="9" onclick="sortTable(this)">照度<span class="sort-icon"><span class="arrow-up"></span><span class="arrow-down"></span></span></th>
<th class="th-sort" data-col="10" onclick="sortTable(this)">风速<span class="sort-icon"><span class="arrow-up"></span><span class="arrow-down"></span></span></th>
<th class="th-sort" data-col="11" onclick="sortTable(this)">总点击次数<span class="sort-icon"><span class="arrow-up"></span><span class="arrow-down"></span></span></th>
</tr>
</thead>
<tbody>
<tr>
<td class="td-left">空气质量监测站-A01</td><td>OA-2024-001</td><td>采油一厂</td><td>厂区大门东侧</td>
<td>285</td><td>196</td><td>78</td><td>523</td><td>412</td><td>65</td><td>134</td><td>1693</td>
</tr>
<tr>
<td class="td-left">PM10检测仪-B02</td><td>OA-2024-002</td><td>采油一厂</td><td>生产区北围栏</td>
<td>156</td><td>112</td><td>45</td><td>687</td><td>534</td><td>38</td><td>89</td><td>1661</td>
</tr>
<tr>
<td class="td-left">臭氧检测仪-C01</td><td>OA-2024-003</td><td>采油二厂</td><td>办公楼楼顶</td>
<td>98</td><td>76</td><td>123</td><td>345</td><td>267</td><td>108</td><td>56</td><td>1073</td>
</tr>
<tr>
<td class="td-left">气象参数监测仪-D01</td><td>OA-2024-004</td><td>采油三厂</td><td>气象观测场</td>
<td>412</td><td>328</td><td>256</td><td>189</td><td>145</td><td>215</td><td>367</td><td>1912</td>
</tr>
<tr>
<td class="td-left">空气质量监测站-A03</td><td>OA-2024-005</td><td>采油三厂</td><td>储油罐区南侧</td>
<td>234</td><td>178</td><td>92</td><td>456</td><td>389</td><td>87</td><td>145</td><td>1581</td>
</tr>
</tbody>
</table>
</div>
<div class="pagination"><span>共 5 条</span><button class="page-btn active">1</button></div>
</div>
</main>
<script>function toggleSubgroup(h){h.parentElement.classList.toggle('open');}(function(){var a=document.querySelector('.sidebar-item.active');if(!a)return;var s=a.closest('.sidebar-subgroup');if(s)s.classList.add('open');})();</script>
<script>
function toggleSubgroup(h){h.parentElement.classList.toggle('open');}
(function(){var a=document.querySelector('.sidebar-item.active');if(!a)return;var s=a.closest('.sidebar-subgroup');if(s)s.classList.add('open');})();
function sortTable(th){
var table=document.getElementById('appTable');
var tbody=table.querySelector('tbody');
var rows=Array.from(tbody.querySelectorAll('tr'));
var col=parseInt(th.getAttribute('data-col'));
var dir='asc';
if(th.classList.contains('asc')){dir='desc';}
else if(th.classList.contains('desc')){dir='asc';}
table.querySelectorAll('.th-sort').forEach(function(t){t.classList.remove('asc','desc');});
th.classList.add(dir);
rows.sort(function(a,b){
var va=parseInt(a.cells[col].textContent);
var vb=parseInt(b.cells[col].textContent);
return dir==='asc'?(va-vb):(vb-va);
});
rows.forEach(function(r){tbody.appendChild(r);});
}
</script>
</body>
</html>
</html>
@@ -0,0 +1,303 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>室外空气 - 动态分析 | 健康长庆原型</title>
<style>
*{box-sizing:border-box;margin:0;padding:0;}
body{font-family:-apple-system,BlinkMacSystemFont,'PingFang SC','Microsoft YaHei',sans-serif;background:#F5F7FA;color:#333;min-width:1280px;}
:root{
--primary:#1890FF;--primary-light:#E6F7FF;--success:#52C41A;--warning:#FAAD14;--danger:#FF4D4F;
--text-primary:#333;--text-secondary:#666;--text-placeholder:#999;--border:#E8E8E8;--background:#F5F7FA;
--font-xs:11px;--font-sm:13px;--font-base:15px;--font-lg:17px;
--radius-sm:4px;--radius-md:8px;--radius-lg:12px;
--shadow-sm:0 1px 4px rgba(0,0,0,0.08);
}
.top-bar{display:flex;align-items:center;height:56px;background:#001529;padding:0 24px;position:fixed;top:0;left:0;right:0;z-index:100;}
.top-bar__logo{display:flex;align-items:center;gap:8px;color:#fff;font-size:var(--font-lg);font-weight:600;white-space:nowrap;width:240px;flex-shrink:0;}
.top-bar__logo svg{width:28px;height:28px;}
.top-bar__right{display:flex;align-items:center;gap:16px;color:rgba(255,255,255,0.65);font-size:var(--font-sm);}
.btn-back{color:rgba(255,255,255,0.65);cursor:pointer;display:flex;align-items:center;gap:4px;text-decoration:none;}.btn-back:hover{color:#fff;}
.avatar{width:32px;height:32px;border-radius:50%;background:#1890FF;display:flex;align-items:center;justify-content:center;color:#fff;font-size:var(--font-sm);cursor:pointer;}
.top-bar__nav{display:flex;align-items:center;gap:4px;flex:1;}
.top-bar__nav a{color:rgba(255,255,255,0.65);text-decoration:none;padding:6px 16px;border-radius:var(--radius-sm);font-size:var(--font-sm);transition:all .2s;}
.top-bar__nav a:hover{color:#fff;background:rgba(255,255,255,0.08);}
.top-bar__nav a.active{color:#fff;background:var(--primary);}
.sidebar{position:fixed;top:56px;left:0;bottom:0;width:240px;background:#001529;overflow-y:auto;z-index:90;padding-top:8px;}
.sidebar-menu__title{color:rgba(255,255,255,0.35);font-size:var(--font-xs);padding:16px 24px 8px;letter-spacing:.5px;}
.sidebar-item{display:flex;align-items:center;gap:8px;padding:10px 24px;color:rgba(255,255,255,0.65);font-size:var(--font-sm);cursor:pointer;transition:all .15s;text-decoration:none;}
.sidebar-item:hover{color:#fff;background:rgba(255,255,255,0.06);}
.sidebar-item.active{color:#fff;background:var(--primary);}
.sidebar-subgroup__header{display:flex;align-items:center;gap:6px;padding:10px 24px;color:rgba(255,255,255,0.65);font-size:var(--font-sm);cursor:pointer;transition:all .15s;user-select:none;}
.sidebar-subgroup__header:hover{color:rgba(255,255,255,0.85);background:rgba(255,255,255,0.04);}
.sidebar-subgroup__header .arrow{width:10px;height:10px;transition:transform .2s;flex-shrink:0;}
.sidebar-subgroup__header .arrow path{stroke:rgba(255,255,255,0.45);}
.sidebar-subgroup.open>.sidebar-subgroup__header{color:rgba(255,255,255,0.85);}
.sidebar-subgroup.open>.sidebar-subgroup__header .arrow{transform:rotate(90deg);}
.sidebar-subgroup__body{display:none;padding-left:16px;}
.sidebar-subgroup.open>.sidebar-subgroup__body{display:block;}
.sidebar-subgroup__body .sidebar-item{padding-left:36px;font-size:12px;}
.main{margin-left:240px;margin-top:56px;padding:24px;min-height:calc(100vh - 56px);}
.page-header{display:flex;align-items:center;gap:12px;margin-bottom:20px;}
.page-header__back{width:32px;height:32px;border-radius:var(--radius-sm);border:1px solid var(--border);background:#fff;display:flex;align-items:center;justify-content:center;cursor:pointer;text-decoration:none;color:var(--text-secondary);}
.page-header__back:hover{border-color:var(--primary);color:var(--primary);}
.page-header__title{font-size:var(--font-lg);font-weight:600;color:var(--text-primary);}
.analysis-layout{display:flex;gap:20px;align-items:flex-start;}
.device-card{width:320px;flex-shrink:0;background:#fff;border-radius:var(--radius-md);box-shadow:var(--shadow-sm);overflow:hidden;}
.device-card__header{padding:16px 20px;background:linear-gradient(135deg,#1890FF 0%,#096DD9 100%);color:#fff;}
.device-card__name{font-size:var(--font-base);font-weight:600;margin-bottom:4px;}
.device-card__code{font-size:var(--font-xs);opacity:.8;}
.device-card__body{padding:16px 20px;}
.device-card__item{display:flex;justify-content:space-between;align-items:center;padding:12px 0;border-bottom:1px solid #f5f5f5;}
.device-card__item:last-child{border-bottom:none;}
.device-card__label{font-size:var(--font-sm);color:var(--text-placeholder);}
.device-card__value{font-size:var(--font-sm);color:var(--text-primary);font-weight:500;text-align:right;max-width:180px;}
.aqi-tag{display:inline-block;padding:2px 10px;border-radius:10px;font-size:var(--font-xs);font-weight:500;}
.aqi-tag--excellent{background:#F6FFED;color:#52C41A;}
.aqi-tag--good{background:#E6FFFB;color:#13C2C2;}
.device-card__tip{margin-top:4px;padding:12px;background:#FFFBE6;border-radius:var(--radius-sm);border:1px solid #FFE58F;}
.device-card__tip p{font-size:var(--font-xs);color:var(--text-secondary);line-height:1.6;margin:0;}
.realtime-section{margin-top:16px;padding-top:16px;border-top:1px solid var(--border);}
.realtime-title{font-size:var(--font-xs);color:var(--text-placeholder);margin-bottom:12px;font-weight:500;}
.realtime-grid{display:grid;grid-template-columns:1fr 1fr;gap:8px;}
.realtime-item{background:#F8FBFF;border-radius:var(--radius-sm);padding:10px 12px;text-align:center;}
.realtime-item__value{font-size:var(--font-lg);font-weight:600;color:var(--primary);margin-bottom:2px;}
.realtime-item__label{font-size:var(--font-xs);color:var(--text-placeholder);}
.chart-panel{flex:1;background:#fff;border-radius:var(--radius-md);box-shadow:var(--shadow-sm);overflow:hidden;min-width:0;}
.time-tabs{display:flex;gap:0;border-bottom:1px solid var(--border);padding:0 24px;}
.time-tab{padding:14px 24px;font-size:var(--font-sm);color:var(--text-secondary);cursor:pointer;border-bottom:2px solid transparent;transition:all .2s;white-space:nowrap;}
.time-tab:hover{color:var(--primary);}
.time-tab.active{color:var(--primary);border-bottom-color:var(--primary);font-weight:500;}
.metric-bar{display:flex;align-items:center;gap:8px;padding:16px 24px;border-bottom:1px solid #f5f5f5;flex-wrap:wrap;}
.metric-btn{height:32px;padding:0 14px;border-radius:16px;font-size:var(--font-xs);cursor:pointer;border:1px solid var(--border);background:#fff;color:var(--text-secondary);transition:all .2s;white-space:nowrap;}
.metric-btn:hover{color:var(--primary);border-color:var(--primary);}
.metric-btn.active{background:var(--primary);color:#fff;border-color:var(--primary);}
.chart-area{padding:24px;min-height:400px;}
.chart-container{width:100%;height:360px;position:relative;}
.chart-container svg{width:100%;height:100%;}
.chart-grid-line{stroke:#f0f0f0;stroke-width:1;}
.chart-axis-label{fill:#999;font-size:11px;}
.chart-line{fill:none;stroke:var(--primary);stroke-width:2;stroke-linejoin:round;stroke-linecap:round;}
.chart-area-fill{fill:url(#areaGrad);opacity:.15;}
.chart-dot{fill:var(--primary);stroke:#fff;stroke-width:2;}
.chart-summary{display:flex;gap:32px;padding:0 24px 20px;}
.chart-summary__item{display:flex;align-items:center;gap:6px;}
.chart-summary__dot{width:8px;height:8px;border-radius:50%;}
.chart-summary__label{font-size:var(--font-xs);color:var(--text-placeholder);}
.chart-summary__value{font-size:var(--font-sm);color:var(--text-primary);font-weight:600;}
</style>
</head>
<body>
<div class="top-bar">
<div class="top-bar__logo"><svg viewBox="0 0 28 28" fill="none"><rect width="28" height="28" rx="6" fill="#1890FF"/><path d="M7 14h14M14 7v14" stroke="#fff" stroke-width="2.5" stroke-linecap="round"/></svg> 健康监测</div>
<nav class="top-bar__nav">
<a href="../archive-personal.html">档案</a>
<a href="../health-checkup/survey-category.html">健康排查</a>
<a href="../wearable/tool-manage.html">穿戴监测</a>
<a href="../weight/scale-device.html">体重监测</a>
<a href="../environment/indoor-device-list.html" class="active">环境监测</a>
<a href="../exception-dirty.html">异常事件</a>
</nav>
<div class="top-bar__right">
<a class="btn-back" href="../../../index.html"><svg width="16" height="16" viewBox="0 0 16 16" fill="none"><path d="M10 3L5 8l5 5" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/></svg> 返回首页</a>
<div class="avatar"></div>
<span style="color:rgba(255,255,255,0.65);">系统管理员 ▾</span>
</div>
</div>
<aside class="sidebar">
<div class="sidebar-menu__title">环境监测</div>
<div class="sidebar-subgroup">
<div class="sidebar-subgroup__header" onclick="toggleSubgroup(this)"><svg class="arrow" viewBox="0 0 12 12"><path d="M4 2l4 4-4 4" fill="none" stroke-width="1.5" stroke-linecap="round"/></svg> 室内空气</div>
<div class="sidebar-subgroup__body">
<a href="indoor-device-list.html" class="sidebar-item">设备列表</a><a href="indoor-device-category.html" class="sidebar-item">设备分类</a><a href="indoor-data-monitor.html" class="sidebar-item">数据监测</a><a href="indoor-exception-alarm.html" class="sidebar-item">异常报警</a><a href="indoor-app-record.html" class="sidebar-item">应用记录</a><a href="indoor-history-data.html" class="sidebar-item">历史数据</a>
</div>
</div>
<div class="sidebar-subgroup open">
<div class="sidebar-subgroup__header" onclick="toggleSubgroup(this)"><svg class="arrow" viewBox="0 0 12 12"><path d="M4 2l4 4-4 4" fill="none" stroke-width="1.5" stroke-linecap="round"/></svg> 室外空气</div>
<div class="sidebar-subgroup__body">
<a href="outdoor-device-list.html" class="sidebar-item">设备列表</a><a href="outdoor-device-category.html" class="sidebar-item">设备分类</a><a href="outdoor-data-monitor.html" class="sidebar-item active">数据监测</a><a href="outdoor-exception-alarm.html" class="sidebar-item">异常报警</a><a href="outdoor-app-record.html" class="sidebar-item">应用记录</a><a href="outdoor-history-data.html" class="sidebar-item">历史数据</a>
</div>
</div>
<div class="sidebar-subgroup">
<div class="sidebar-subgroup__header" onclick="toggleSubgroup(this)"><svg class="arrow" viewBox="0 0 12 12"><path d="M4 2l4 4-4 4" fill="none" stroke-width="1.5" stroke-linecap="round"/></svg> 水质监测</div>
<div class="sidebar-subgroup__body">
<a href="water-device-list.html" class="sidebar-item">设备列表</a><a href="water-device-category.html" class="sidebar-item">设备分类</a><a href="water-data-monitor.html" class="sidebar-item">数据监测</a><a href="water-exception-alarm.html" class="sidebar-item">异常报警</a><a href="water-app-record.html" class="sidebar-item">应用记录</a><a href="water-history-data.html" class="sidebar-item">历史数据</a>
</div>
</div>
<div class="sidebar-subgroup">
<div class="sidebar-subgroup__header" onclick="toggleSubgroup(this)"><svg class="arrow" viewBox="0 0 12 12"><path d="M4 2l4 4-4 4" fill="none" stroke-width="1.5" stroke-linecap="round"/></svg> 花粉监测</div>
<div class="sidebar-subgroup__body">
<a href="pollen-device-list.html" class="sidebar-item">设备列表</a><a href="pollen-device-category.html" class="sidebar-item">设备分类</a><a href="pollen-data-monitor.html" class="sidebar-item">数据监测</a><a href="pollen-exception-alarm.html" class="sidebar-item">异常报警</a><a href="pollen-app-record.html" class="sidebar-item">应用记录</a><a href="pollen-history-data.html" class="sidebar-item">历史数据</a><a href="pollen-knowledge.html" class="sidebar-item">知识科普</a>
</div>
</div>
</aside>
<main class="main">
<div class="page-header">
<a class="page-header__back" href="outdoor-data-monitor.html"><svg width="16" height="16" viewBox="0 0 16 16" fill="none"><path d="M10 3L5 8l5 5" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/></svg></a>
<span class="page-header__title">动态分析</span>
</div>
<div class="analysis-layout">
<!-- 左侧 - 设备信息 -->
<div class="device-card">
<div class="device-card__header">
<div class="device-card__name">空气质量监测站-A01</div>
<div class="device-card__code">OA-2024-001</div>
</div>
<div class="device-card__body">
<div class="device-card__item">
<span class="device-card__label">所属单位</span>
<span class="device-card__value">采油一厂</span>
</div>
<div class="device-card__item">
<span class="device-card__label">设备位置</span>
<span class="device-card__value">厂区大门东侧</span>
</div>
<div class="device-card__item">
<span class="device-card__label">数据更新时间</span>
<span class="device-card__value">2026-05-14 14:30</span>
</div>
<div class="device-card__item">
<span class="device-card__label">空气质量指数</span>
<span class="device-card__value"><span class="aqi-tag aqi-tag--good"></span></span>
</div>
<div class="device-card__tip">
<p>空气质量总体良好,各项污染物指标在安全范围内,适宜室外作业。</p>
</div>
<!-- 实时监测数据 -->
<div class="realtime-section">
<div class="realtime-title">实时监测数据</div>
<div class="realtime-grid">
<div class="realtime-item">
<div class="realtime-item__value">32.5</div>
<div class="realtime-item__label">温度(℃)</div>
</div>
<div class="realtime-item">
<div class="realtime-item__value">45</div>
<div class="realtime-item__label">湿度(%)</div>
</div>
<div class="realtime-item">
<div class="realtime-item__value">680</div>
<div class="realtime-item__label">太阳辐射(W/m²)</div>
</div>
<div class="realtime-item">
<div class="realtime-item__value">28</div>
<div class="realtime-item__label">PM2.5(μg/m³)</div>
</div>
<div class="realtime-item">
<div class="realtime-item__value">52</div>
<div class="realtime-item__label">PM10(μg/m³)</div>
</div>
<div class="realtime-item">
<div class="realtime-item__value">65000</div>
<div class="realtime-item__label">照度(lm/m²)</div>
</div>
<div class="realtime-item" style="grid-column:1/-1;">
<div class="realtime-item__value">3.2</div>
<div class="realtime-item__label">风速(m/s)</div>
</div>
</div>
</div>
</div>
</div>
<!-- 右侧 - 趋势图 -->
<div class="chart-panel">
<div class="time-tabs">
<div class="time-tab active" onclick="switchTimeTab(this)">近24小时</div>
<div class="time-tab" onclick="switchTimeTab(this)">近7日</div>
<div class="time-tab" onclick="switchTimeTab(this)">近30日</div>
<div class="time-tab" onclick="switchTimeTab(this)">近3个月</div>
</div>
<div class="metric-bar">
<button class="metric-btn active" onclick="switchMetric(this,'temp')">温度</button>
<button class="metric-btn" onclick="switchMetric(this,'humi')">湿度</button>
<button class="metric-btn" onclick="switchMetric(this,'solar')">太阳辐射</button>
<button class="metric-btn" onclick="switchMetric(this,'pm25')">PM2.5</button>
<button class="metric-btn" onclick="switchMetric(this,'pm10')">PM10</button>
<button class="metric-btn" onclick="switchMetric(this,'lux')">照度</button>
<button class="metric-btn" onclick="switchMetric(this,'wind')">风速</button>
</div>
<div class="chart-summary">
<div class="chart-summary__item"><span class="chart-summary__dot" style="background:#1890FF;"></span><span class="chart-summary__label">平均值</span><span class="chart-summary__value" id="avgVal">31.5 ℃</span></div>
<div class="chart-summary__item"><span class="chart-summary__dot" style="background:#52C41A;"></span><span class="chart-summary__label">最小值</span><span class="chart-summary__value" id="minVal">26.2 ℃</span></div>
<div class="chart-summary__item"><span class="chart-summary__dot" style="background:#FF4D4F;"></span><span class="chart-summary__label">最大值</span><span class="chart-summary__value" id="maxVal">35.8 ℃</span></div>
</div>
<div class="chart-area">
<div class="chart-container" id="chartContainer">
<svg viewBox="0 0 800 320" preserveAspectRatio="xMidYMid meet">
<defs>
<linearGradient id="areaGrad" x1="0" y1="0" x2="0" y2="1">
<stop offset="0%" stop-color="#1890FF" stop-opacity="0.3"/>
<stop offset="100%" stop-color="#1890FF" stop-opacity="0"/>
</linearGradient>
</defs>
<line x1="60" y1="20" x2="780" y2="20" class="chart-grid-line"/>
<line x1="60" y1="80" x2="780" y2="80" class="chart-grid-line"/>
<line x1="60" y1="140" x2="780" y2="140" class="chart-grid-line"/>
<line x1="60" y1="200" x2="780" y2="200" class="chart-grid-line"/>
<line x1="60" y1="260" x2="780" y2="260" class="chart-grid-line"/>
<text x="50" y="24" class="chart-axis-label" text-anchor="end">38</text>
<text x="50" y="84" class="chart-axis-label" text-anchor="end">35</text>
<text x="50" y="144" class="chart-axis-label" text-anchor="end">32</text>
<text x="50" y="204" class="chart-axis-label" text-anchor="end">29</text>
<text x="50" y="264" class="chart-axis-label" text-anchor="end">26</text>
<text x="90" y="290" class="chart-axis-label" text-anchor="middle">00:00</text>
<text x="180" y="290" class="chart-axis-label" text-anchor="middle">04:00</text>
<text x="270" y="290" class="chart-axis-label" text-anchor="middle">06:00</text>
<text x="360" y="290" class="chart-axis-label" text-anchor="middle">08:00</text>
<text x="450" y="290" class="chart-axis-label" text-anchor="middle">10:00</text>
<text x="540" y="290" class="chart-axis-label" text-anchor="middle">12:00</text>
<text x="630" y="290" class="chart-axis-label" text-anchor="middle">14:00</text>
<text x="720" y="290" class="chart-axis-label" text-anchor="middle">16:00</text>
<line x1="60" y1="270" x2="780" y2="270" stroke="#d9d9d9" stroke-width="1"/>
<path class="chart-area-fill" d="M90,240 L150,230 L210,250 L270,220 L330,180 L390,140 L450,100 L510,90 L570,80 L630,100 L690,130 L750,150 L750,270 L90,270 Z"/>
<polyline class="chart-line" points="90,240 150,230 210,250 270,220 330,180 390,140 450,100 510,90 570,80 630,100 690,130 750,150"/>
<circle cx="90" cy="240" r="4" class="chart-dot"/>
<circle cx="150" cy="230" r="4" class="chart-dot"/>
<circle cx="210" cy="250" r="4" class="chart-dot"/>
<circle cx="270" cy="220" r="4" class="chart-dot"/>
<circle cx="330" cy="180" r="4" class="chart-dot"/>
<circle cx="390" cy="140" r="4" class="chart-dot"/>
<circle cx="450" cy="100" r="4" class="chart-dot"/>
<circle cx="510" cy="90" r="4" class="chart-dot"/>
<circle cx="570" cy="80" r="4" class="chart-dot"/>
<circle cx="630" cy="100" r="4" class="chart-dot"/>
<circle cx="690" cy="130" r="4" class="chart-dot"/>
<circle cx="750" cy="150" r="4" class="chart-dot"/>
</svg>
</div>
</div>
</div>
</div>
</main>
<script>
function toggleSubgroup(h){h.parentElement.classList.toggle('open');}
(function(){var a=document.querySelector('.sidebar-item.active');if(!a)return;var s=a.closest('.sidebar-subgroup');if(s)s.classList.add('open');})();
function switchTimeTab(el){
var tabs=document.querySelectorAll('.time-tab');
tabs.forEach(function(t){t.classList.remove('active');});
el.classList.add('active');
}
var metricData={
temp: {avg:'31.5 ℃', min:'26.2 ℃', max:'35.8 ℃'},
humi: {avg:'43 %', min:'32 %', max:'56 %'},
solar: {avg:'620 W/m²', min:'0 W/m²', max:'920 W/m²'},
pm25: {avg:'35 μg/m³', min:'18 μg/m³', max:'58 μg/m³'},
pm10: {avg:'68 μg/m³', min:'35 μg/m³', max:'105 μg/m³'},
lux: {avg:'52000 lm/m²',min:'0 lm/m²', max:'92000 lm/m²'},
wind: {avg:'3.8 m/s', min:'1.2 m/s', max:'6.5 m/s'}
};
function switchMetric(el,key){
var btns=document.querySelectorAll('.metric-btn');
btns.forEach(function(b){b.classList.remove('active');});
el.classList.add('active');
var d=metricData[key];
document.getElementById('avgVal').textContent=d.avg;
document.getElementById('minVal').textContent=d.min;
document.getElementById('maxVal').textContent=d.max;
}
</script>
</body>
</html>
@@ -3,7 +3,7 @@
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>健康监测 - 数据监测 | 健康长庆原型</title>
<title>室外空气 - 数据监测 | 健康长庆原型</title>
<style>
*{box-sizing:border-box;margin:0;padding:0;}
body{font-family:-apple-system,BlinkMacSystemFont,'PingFang SC','Microsoft YaHei',sans-serif;background:#F5F7FA;color:#333;min-width:1280px;}
@@ -18,8 +18,7 @@
.top-bar__logo{display:flex;align-items:center;gap:8px;color:#fff;font-size:var(--font-lg);font-weight:600;white-space:nowrap;width:240px;flex-shrink:0;}
.top-bar__logo svg{width:28px;height:28px;}
.top-bar__right{display:flex;align-items:center;gap:16px;color:rgba(255,255,255,0.65);font-size:var(--font-sm);}
.btn-back{color:rgba(255,255,255,0.65);cursor:pointer;display:flex;align-items:center;gap:4px;text-decoration:none;}
.btn-back:hover{color:#fff;}
.btn-back{color:rgba(255,255,255,0.65);cursor:pointer;display:flex;align-items:center;gap:4px;text-decoration:none;}.btn-back:hover{color:#fff;}
.avatar{width:32px;height:32px;border-radius:50%;background:#1890FF;display:flex;align-items:center;justify-content:center;color:#fff;font-size:var(--font-sm);cursor:pointer;}
.top-bar__nav{display:flex;align-items:center;gap:4px;flex:1;}
.top-bar__nav a{color:rgba(255,255,255,0.65);text-decoration:none;padding:6px 16px;border-radius:var(--radius-sm);font-size:var(--font-sm);transition:all .2s;}
@@ -40,9 +39,48 @@
.sidebar-subgroup.open>.sidebar-subgroup__body{display:block;}
.sidebar-subgroup__body .sidebar-item{padding-left:36px;font-size:12px;}
.main{margin-left:240px;margin-top:56px;padding:24px;min-height:calc(100vh - 56px);}
.page-placeholder{display:flex;flex-direction:column;align-items:center;justify-content:center;height:calc(100vh - 56px - 48px);color:var(--text-placeholder);gap:12px;}
.page-placeholder svg{opacity:.25;}
.page-placeholder p{font-size:var(--font-base);}
.filter-bar{background:#fff;border-radius:var(--radius-md);padding:20px 24px;margin-bottom:16px;box-shadow:var(--shadow-sm);display:flex;align-items:center;gap:16px;flex-wrap:wrap;}
.filter-item{display:flex;align-items:center;gap:8px;}
.filter-item label{font-size:var(--font-sm);color:var(--text-secondary);white-space:nowrap;}
.filter-input{height:36px;border:1px solid var(--border);border-radius:var(--radius-sm);padding:0 12px;font-size:var(--font-sm);color:var(--text-primary);outline:none;background:#fff;min-width:180px;}.filter-input:focus{border-color:var(--primary);}
.filter-select{height:36px;border:1px solid var(--border);border-radius:var(--radius-sm);padding:0 28px 0 12px;font-size:var(--font-sm);color:var(--text-primary);outline:none;background:#fff url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6'%3E%3Cpath d='M0 0l5 6 5-6z' fill='%23999'/%3E%3C/svg%3E") no-repeat right 10px center;appearance:none;cursor:pointer;min-width:140px;}
.btn{height:36px;padding:0 16px;border-radius:var(--radius-sm);font-size:var(--font-sm);cursor:pointer;border:none;transition:all .2s;display:inline-flex;align-items:center;gap:6px;}
.btn-primary{background:var(--primary);color:#fff;}.btn-primary:hover{background:#40a9ff;}
.btn-default{background:#fff;color:var(--text-primary);border:1px solid var(--border);}.btn-default:hover{color:var(--primary);border-color:var(--primary);}
.action-bar{display:flex;align-items:center;gap:12px;margin-bottom:16px;}
.table-card{background:#fff;border-radius:var(--radius-md);box-shadow:var(--shadow-sm);overflow:hidden;}
.table-card__content{overflow-x:auto;-webkit-overflow-scrolling:touch;}
table{width:100%;border-collapse:collapse;min-width:1500px;}
thead th{background:#FAFAFA;padding:12px 14px;text-align:center;font-size:var(--font-xs);color:var(--text-secondary);font-weight:500;border-bottom:1px solid var(--border);border-right:1px solid var(--border);white-space:nowrap;}
thead th:last-child{border-right:none;}
thead th.th-left{text-align:left;}
tbody td{padding:12px 14px;font-size:var(--font-xs);color:var(--text-primary);border-bottom:1px solid var(--border);text-align:center;white-space:nowrap;}
tbody td.td-left{text-align:left;}
tbody tr:last-child td{border-bottom:none;}
tbody tr:hover{background:#F8FBFF;}
/* 固定列 */
thead tr:first-child th:nth-child(-n+2),tbody td:nth-child(-n+2),thead tr:first-child th:nth-last-child(-n+2),tbody td:nth-last-child(-n+2){position:sticky;z-index:2;}
thead tr:first-child th:nth-child(-n+2),thead tr:first-child th:nth-last-child(-n+2){z-index:3;}
thead tr:first-child th:nth-child(1),tbody td:nth-child(1){left:0;}
thead tr:first-child th:nth-child(2),tbody td:nth-child(2){left:140px;}
thead tr:first-child th:nth-last-child(2),tbody td:nth-last-child(2){right:70px;}
thead tr:first-child th:nth-last-child(1),tbody td:nth-last-child(1){right:0;}
tbody td:nth-child(-n+2),tbody td:nth-last-child(-n+2){background:#fff;}
tbody tr:hover td:nth-child(-n+2),tbody tr:hover td:nth-last-child(-n+2){background:#F8FBFF;}
tbody td:nth-child(2),thead tr:first-child th:nth-child(2){box-shadow:2px 0 4px rgba(0,0,0,0.06);}
tbody td:nth-last-child(2),thead tr:first-child th:nth-last-child(2){box-shadow:-2px 0 4px rgba(0,0,0,0.06);}
.link{color:var(--primary);cursor:pointer;font-size:var(--font-xs);text-decoration:none;}.link:hover{color:#40a9ff;}
.aqi-tag{display:inline-block;padding:2px 10px;border-radius:10px;font-size:var(--font-xs);font-weight:500;}
.aqi-tag--excellent{background:#F6FFED;color:#52C41A;}
.aqi-tag--good{background:#E6FFFB;color:#13C2C2;}
.aqi-tag--light{background:#FFFBE6;color:#FAAD14;}
.aqi-tag--moderate{background:#FFF1F0;color:#FA541C;}
.aqi-tag--heavy{background:#FFF1F0;color:#FF4D4F;}
.aqi-tag--severe{background:#F9F0FF;color:#722ED1;}
.pagination{display:flex;align-items:center;justify-content:flex-end;padding:16px 24px;gap:8px;border-top:1px solid var(--border);}
.pagination span{font-size:var(--font-sm);color:var(--text-secondary);}
.page-btn{width:32px;height:32px;border:1px solid var(--border);border-radius:var(--radius-sm);background:#fff;cursor:pointer;font-size:var(--font-sm);display:inline-flex;align-items:center;justify-content:center;transition:all .2s;}
.page-btn:hover,.page-btn.active{background:var(--primary);color:#fff;border-color:var(--primary);}
</style>
</head>
<body>
@@ -57,10 +95,7 @@
<a href="../exception-dirty.html">异常事件</a>
</nav>
<div class="top-bar__right">
<a class="btn-back" href="../../../index.html">
<svg width="16" height="16" viewBox="0 0 16 16" fill="none"><path d="M10 3L5 8l5 5" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/></svg>
返回首页
</a>
<a class="btn-back" href="../../../index.html"><svg width="16" height="16" viewBox="0 0 16 16" fill="none"><path d="M10 3L5 8l5 5" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/></svg> 返回首页</a>
<div class="avatar"></div>
<span style="color:rgba(255,255,255,0.65);">系统管理员 ▾</span>
</div>
@@ -70,55 +105,96 @@
<div class="sidebar-subgroup">
<div class="sidebar-subgroup__header" onclick="toggleSubgroup(this)"><svg class="arrow" viewBox="0 0 12 12"><path d="M4 2l4 4-4 4" fill="none" stroke-width="1.5" stroke-linecap="round"/></svg> 室内空气</div>
<div class="sidebar-subgroup__body">
<a href="indoor-device-list.html" class="sidebar-item">设备列表</a>
<a href="indoor-device-category.html" class="sidebar-item">设备分类</a>
<a href="indoor-data-monitor.html" class="sidebar-item">数据监测</a>
<a href="indoor-exception-alarm.html" class="sidebar-item">异常报警</a>
<a href="indoor-app-record.html" class="sidebar-item">应用记录</a>
<a href="indoor-history-data.html" class="sidebar-item">历史数据</a>
<a href="indoor-device-list.html" class="sidebar-item">设备列表</a><a href="indoor-device-category.html" class="sidebar-item">设备分类</a><a href="indoor-data-monitor.html" class="sidebar-item">数据监测</a><a href="indoor-exception-alarm.html" class="sidebar-item">异常报警</a><a href="indoor-app-record.html" class="sidebar-item">应用记录</a><a href="indoor-history-data.html" class="sidebar-item">历史数据</a>
</div>
</div>
<div class="sidebar-subgroup open">
<div class="sidebar-subgroup__header" onclick="toggleSubgroup(this)"><svg class="arrow" viewBox="0 0 12 12"><path d="M4 2l4 4-4 4" fill="none" stroke-width="1.5" stroke-linecap="round"/></svg> 室外空气</div>
<div class="sidebar-subgroup__body">
<a href="outdoor-device-list.html" class="sidebar-item">设备列表</a>
<a href="outdoor-device-category.html" class="sidebar-item">设备分类</a>
<a href="outdoor-data-monitor.html" class="sidebar-item active">数据监测</a>
<a href="outdoor-exception-alarm.html" class="sidebar-item">异常报警</a>
<a href="outdoor-app-record.html" class="sidebar-item">应用记录</a>
<a href="outdoor-history-data.html" class="sidebar-item">历史数据</a>
<a href="outdoor-device-list.html" class="sidebar-item">设备列表</a><a href="outdoor-device-category.html" class="sidebar-item">设备分类</a><a href="outdoor-data-monitor.html" class="sidebar-item active">数据监测</a><a href="outdoor-exception-alarm.html" class="sidebar-item">异常报警</a><a href="outdoor-app-record.html" class="sidebar-item">应用记录</a><a href="outdoor-history-data.html" class="sidebar-item">历史数据</a>
</div>
</div>
<div class="sidebar-subgroup">
<div class="sidebar-subgroup__header" onclick="toggleSubgroup(this)"><svg class="arrow" viewBox="0 0 12 12"><path d="M4 2l4 4-4 4" fill="none" stroke-width="1.5" stroke-linecap="round"/></svg> 水质监测</div>
<div class="sidebar-subgroup__body">
<a href="water-device-list.html" class="sidebar-item">设备列表</a>
<a href="water-device-category.html" class="sidebar-item">设备分类</a>
<a href="water-data-monitor.html" class="sidebar-item">数据监测</a>
<a href="water-exception-alarm.html" class="sidebar-item">异常报警</a>
<a href="water-app-record.html" class="sidebar-item">应用记录</a>
<a href="water-history-data.html" class="sidebar-item">历史数据</a>
<a href="water-device-list.html" class="sidebar-item">设备列表</a><a href="water-device-category.html" class="sidebar-item">设备分类</a><a href="water-data-monitor.html" class="sidebar-item">数据监测</a><a href="water-exception-alarm.html" class="sidebar-item">异常报警</a><a href="water-app-record.html" class="sidebar-item">应用记录</a><a href="water-history-data.html" class="sidebar-item">历史数据</a>
</div>
</div>
<div class="sidebar-subgroup">
<div class="sidebar-subgroup__header" onclick="toggleSubgroup(this)"><svg class="arrow" viewBox="0 0 12 12"><path d="M4 2l4 4-4 4" fill="none" stroke-width="1.5" stroke-linecap="round"/></svg> 花粉监测</div>
<div class="sidebar-subgroup__body">
<a href="pollen-device-list.html" class="sidebar-item">设备列表</a>
<a href="pollen-device-category.html" class="sidebar-item">设备分类</a>
<a href="pollen-data-monitor.html" class="sidebar-item">数据监测</a>
<a href="pollen-exception-alarm.html" class="sidebar-item">异常报警</a>
<a href="pollen-app-record.html" class="sidebar-item">应用记录</a>
<a href="pollen-history-data.html" class="sidebar-item">历史数据</a>
<a href="pollen-knowledge.html" class="sidebar-item">知识科普</a>
<a href="pollen-device-list.html" class="sidebar-item">设备列表</a><a href="pollen-device-category.html" class="sidebar-item">设备分类</a><a href="pollen-data-monitor.html" class="sidebar-item">数据监测</a><a href="pollen-exception-alarm.html" class="sidebar-item">异常报警</a><a href="pollen-app-record.html" class="sidebar-item">应用记录</a><a href="pollen-history-data.html" class="sidebar-item">历史数据</a><a href="pollen-knowledge.html" class="sidebar-item">知识科普</a>
</div>
</div>
</aside>
<main class="main">
<div class="page-placeholder">
<svg width="64" height="64" viewBox="0 0 64 64" fill="none"><rect x="8" y="8" width="48" height="48" rx="8" stroke="#ccc" stroke-width="2"/><path d="M20 32h24M32 20v24" stroke="#ccc" stroke-width="2" stroke-linecap="round"/></svg>
<p>数据监测</p>
<div class="filter-bar">
<div class="filter-item"><label>设备名称</label><input class="filter-input" placeholder="请输入设备名称"></div>
<div class="filter-item"><label>设备编码</label><input class="filter-input" placeholder="请输入设备编码"></div>
<div class="filter-item"><label>所属单位</label><select class="filter-select"><option value="">全部</option><option>采油一厂</option><option>采油二厂</option><option>采油三厂</option></select></div>
<div class="filter-item"><label>空气质量指数</label><select class="filter-select"><option value="">全部</option><option></option><option></option><option>轻度污染</option><option>中度污染</option><option>重度污染</option><option>严重污染</option></select></div>
<button class="btn btn-primary">查询</button>
<button class="btn btn-default">重置</button>
</div>
<div class="action-bar"><button class="btn btn-default">导出列表数据</button></div>
<div class="table-card">
<div class="table-card__content">
<table>
<thead>
<tr>
<th rowspan="2" class="th-left" style="min-width:140px;">设备名称</th>
<th rowspan="2" style="min-width:110px;">设备编码</th>
<th rowspan="2" style="min-width:90px;">所属单位</th>
<th rowspan="2" style="min-width:120px;">设备位置</th>
<th rowspan="2" style="min-width:150px;">数据更新时间</th>
<th colspan="7">监测数据</th>
<th rowspan="2" style="min-width:80px;">空气质量指数</th>
<th rowspan="2" style="min-width:70px;">操作</th>
</tr>
<tr>
<th>温度(℃)</th><th>湿度(%)</th><th>太阳辐射(W/m²)</th><th>PM2.5(μg/m³)</th><th>PM10(μg/m³)</th><th>照度(lm/m²)</th><th>风速(m/s)</th>
</tr>
</thead>
<tbody>
<tr>
<td class="td-left">空气质量监测站-A01</td><td>OA-2024-001</td><td>采油一厂</td><td>厂区大门东侧</td><td>2026-05-14 14:30</td>
<td>32.5</td><td>45</td><td>680</td><td>28</td><td>52</td><td>65000</td><td>3.2</td>
<td><span class="aqi-tag aqi-tag--excellent"></span></td><td><a class="link" href="outdoor-data-analysis.html">动态分析</a></td>
</tr>
<tr>
<td class="td-left">PM10检测仪-B02</td><td>OA-2024-002</td><td>采油一厂</td><td>生产区北围栏</td><td>2026-05-14 14:28</td>
<td>33.1</td><td>42</td><td>720</td><td>38</td><td>68</td><td>72000</td><td>4.1</td>
<td><span class="aqi-tag aqi-tag--good"></span></td><td><a class="link" href="outdoor-data-analysis.html">动态分析</a></td>
</tr>
<tr>
<td class="td-left">臭氧检测仪-C01</td><td>OA-2024-003</td><td>采油二厂</td><td>办公楼楼顶</td><td>2026-05-14 14:25</td>
<td>31.8</td><td>50</td><td>580</td><td>55</td><td>92</td><td>58000</td><td>2.8</td>
<td><span class="aqi-tag aqi-tag--light">轻度污染</span></td><td><a class="link" href="outdoor-data-analysis.html">动态分析</a></td>
</tr>
<tr>
<td class="td-left">气象参数监测仪-D01</td><td>OA-2024-004</td><td>采油三厂</td><td>气象观测场</td><td>2026-05-14 14:20</td>
<td>34.2</td><td>38</td><td>850</td><td>82</td><td>135</td><td>85000</td><td>5.6</td>
<td><span class="aqi-tag aqi-tag--moderate">中度污染</span></td><td><a class="link" href="outdoor-data-analysis.html">动态分析</a></td>
</tr>
<tr>
<td class="td-left">空气质量监测站-A03</td><td>OA-2024-005</td><td>采油三厂</td><td>储油罐区南侧</td><td>2026-05-14 14:15</td>
<td>35.0</td><td>35</td><td>920</td><td>125</td><td>190</td><td>92000</td><td>6.3</td>
<td><span class="aqi-tag aqi-tag--heavy">重度污染</span></td><td><a class="link" href="outdoor-data-analysis.html">动态分析</a></td>
</tr>
<tr>
<td class="td-left">VOC检测仪-E01</td><td>OA-2024-006</td><td>采油三厂</td><td>化工装置区</td><td>2026-05-14 14:10</td>
<td>36.2</td><td>30</td><td>950</td><td>180</td><td>260</td><td>95000</td><td>7.1</td>
<td><span class="aqi-tag aqi-tag--severe">严重污染</span></td><td><a class="link" href="outdoor-data-analysis.html">动态分析</a></td>
</tr>
</tbody>
</table>
</div>
<div class="pagination"><span>共 6 条</span><button class="page-btn active">1</button></div>
</div>
</main>
<script>function toggleSubgroup(h){h.parentElement.classList.toggle('open');}(function(){var a=document.querySelector('.sidebar-item.active');if(!a)return;var s=a.closest('.sidebar-subgroup');if(s)s.classList.add('open');})();</script>
<script>
function toggleSubgroup(h){h.parentElement.classList.toggle('open');}
(function(){var a=document.querySelector('.sidebar-item.active');if(!a)return;var s=a.closest('.sidebar-subgroup');if(s)s.classList.add('open');})();
</script>
</body>
</html>
</html>
@@ -3,7 +3,7 @@
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>健康监测 - 设备分类 | 健康长庆原型</title>
<title>室外空气 - 设备分类 | 健康长庆原型</title>
<style>
*{box-sizing:border-box;margin:0;padding:0;}
body{font-family:-apple-system,BlinkMacSystemFont,'PingFang SC','Microsoft YaHei',sans-serif;background:#F5F7FA;color:#333;min-width:1280px;}
@@ -40,9 +40,58 @@
.sidebar-subgroup.open>.sidebar-subgroup__body{display:block;}
.sidebar-subgroup__body .sidebar-item{padding-left:36px;font-size:12px;}
.main{margin-left:240px;margin-top:56px;padding:24px;min-height:calc(100vh - 56px);}
.page-placeholder{display:flex;flex-direction:column;align-items:center;justify-content:center;height:calc(100vh - 56px - 48px);color:var(--text-placeholder);gap:12px;}
.page-placeholder svg{opacity:.25;}
.page-placeholder p{font-size:var(--font-base);}
.filter-bar{background:#fff;border-radius:var(--radius-md);padding:20px 24px;margin-bottom:16px;box-shadow:var(--shadow-sm);display:flex;align-items:center;gap:16px;flex-wrap:wrap;}
.filter-item{display:flex;align-items:center;gap:8px;}
.filter-item label{font-size:var(--font-sm);color:var(--text-secondary);white-space:nowrap;}
.filter-input{height:36px;border:1px solid var(--border);border-radius:var(--radius-sm);padding:0 12px;font-size:var(--font-sm);color:var(--text-primary);outline:none;background:#fff;min-width:200px;}
.filter-input:focus{border-color:var(--primary);}
.btn{height:36px;padding:0 16px;border-radius:var(--radius-sm);font-size:var(--font-sm);cursor:pointer;border:none;transition:all .2s;display:inline-flex;align-items:center;gap:6px;}
.btn-primary{background:var(--primary);color:#fff;}.btn-primary:hover{background:#40a9ff;}
.btn-default{background:#fff;color:var(--text-primary);border:1px solid var(--border);}.btn-default:hover{color:var(--primary);border-color:var(--primary);}
.action-bar{display:flex;align-items:center;gap:12px;margin-bottom:16px;}
.table-card{background:#fff;border-radius:var(--radius-md);box-shadow:var(--shadow-sm);overflow:hidden;}
.table-card__content{overflow-x:auto;-webkit-overflow-scrolling:touch;}
table{width:100%;border-collapse:collapse;min-width:1100px;}
thead th{background:#FAFAFA;padding:12px 16px;text-align:center;font-size:var(--font-sm);color:var(--text-secondary);font-weight:500;border-bottom:1px solid var(--border);border-right:1px solid var(--border);white-space:nowrap;}
thead th:last-child{border-right:none;}
thead th.th-left{text-align:left;}
tbody td{padding:14px 16px;font-size:var(--font-sm);color:var(--text-primary);border-bottom:1px solid var(--border);text-align:center;white-space:nowrap;}
tbody td.td-left{text-align:left;}
tbody tr:last-child td{border-bottom:none;}
tbody tr:hover{background:#F8FBFF;}
.link{color:var(--primary);cursor:pointer;font-size:var(--font-sm);text-decoration:none;}.link:hover{color:#40a9ff;}
.link-danger{color:var(--danger);cursor:pointer;font-size:var(--font-sm);text-decoration:none;}.link-danger:hover{color:#ff7875;}
.pagination{display:flex;align-items:center;justify-content:flex-end;padding:16px 24px;gap:8px;border-top:1px solid var(--border);}
.pagination span{font-size:var(--font-sm);color:var(--text-secondary);}
.page-btn{width:32px;height:32px;border:1px solid var(--border);border-radius:var(--radius-sm);background:#fff;cursor:pointer;font-size:var(--font-sm);display:inline-flex;align-items:center;justify-content:center;transition:all .2s;}
.page-btn:hover,.page-btn.active{background:var(--primary);color:#fff;border-color:var(--primary);}
.drawer-mask{display:none;position:fixed;top:0;left:0;right:0;bottom:0;background:rgba(0,0,0,0.45);z-index:200;}
.drawer-mask.open{display:block;}
.drawer{position:fixed;top:0;right:-600px;width:600px;height:100%;background:#fff;z-index:201;box-shadow:-4px 0 16px rgba(0,0,0,0.12);transition:right .3s ease;display:flex;flex-direction:column;}
.drawer.open{right:0;}
.drawer__header{display:flex;align-items:center;justify-content:space-between;padding:16px 24px;border-bottom:1px solid var(--border);}
.drawer__title{font-size:var(--font-base);font-weight:600;color:var(--text-primary);}
.drawer__close{width:32px;height:32px;border:none;background:none;cursor:pointer;display:flex;align-items:center;justify-content:center;border-radius:var(--radius-sm);color:var(--text-placeholder);font-size:18px;}
.drawer__close:hover{background:#f5f5f5;color:var(--text-primary);}
.drawer__body{flex:1;overflow-y:auto;padding:24px;}
.drawer__footer{display:flex;align-items:center;justify-content:flex-end;gap:12px;padding:16px 24px;border-top:1px solid var(--border);}
.form-group{margin-bottom:20px;}
.form-label{display:block;font-size:var(--font-sm);color:var(--text-primary);margin-bottom:8px;font-weight:500;}
.form-label .required{color:var(--danger);margin-right:4px;}
.form-control{width:100%;height:36px;border:1px solid var(--border);border-radius:var(--radius-sm);padding:0 12px;font-size:var(--font-sm);color:var(--text-primary);outline:none;background:#fff;}
.form-control:focus{border-color:var(--primary);box-shadow:0 0 0 2px rgba(24,144,255,0.1);}
.threshold-section-title{font-size:var(--font-sm);font-weight:600;color:var(--text-primary);margin-bottom:12px;padding-bottom:8px;border-bottom:1px solid var(--border);}
.threshold-list{display:flex;flex-direction:column;gap:12px;}
.threshold-item{border:1px solid var(--border);border-radius:var(--radius-md);overflow:hidden;}
.threshold-item__header{display:flex;align-items:center;justify-content:space-between;padding:12px 16px;background:#FAFAFA;}
.threshold-item__label{font-size:var(--font-sm);font-weight:600;color:var(--text-primary);}
.threshold-item__unit{font-size:var(--font-xs);color:var(--text-placeholder);font-weight:400;margin-left:4px;}
.threshold-item__body{padding:12px 16px;}
.threshold-row{display:grid;grid-template-columns:1fr 1fr;gap:12px;}
.threshold-field{display:flex;flex-direction:column;gap:4px;}
.threshold-field label{font-size:var(--font-xs);color:var(--text-secondary);}
.threshold-field .form-control{height:34px;border:1px solid var(--border);border-radius:var(--radius-sm);padding:0 10px;font-size:var(--font-sm);outline:none;width:100%;}
.threshold-field .form-control:focus{border-color:var(--primary);}
</style>
</head>
<body>
@@ -57,10 +106,7 @@
<a href="../exception-dirty.html">异常事件</a>
</nav>
<div class="top-bar__right">
<a class="btn-back" href="../../../index.html">
<svg width="16" height="16" viewBox="0 0 16 16" fill="none"><path d="M10 3L5 8l5 5" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/></svg>
返回首页
</a>
<a class="btn-back" href="../../../index.html"><svg width="16" height="16" viewBox="0 0 16 16" fill="none"><path d="M10 3L5 8l5 5" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/></svg> 返回首页</a>
<div class="avatar"></div>
<span style="color:rgba(255,255,255,0.65);">系统管理员 ▾</span>
</div>
@@ -114,11 +160,187 @@
</div>
</aside>
<main class="main">
<div class="page-placeholder">
<svg width="64" height="64" viewBox="0 0 64 64" fill="none"><rect x="8" y="8" width="48" height="48" rx="8" stroke="#ccc" stroke-width="2"/><path d="M20 32h24M32 20v24" stroke="#ccc" stroke-width="2" stroke-linecap="round"/></svg>
<p>设备分类</p>
<div class="filter-bar">
<div class="filter-item"><label>分类名称</label><input class="filter-input" placeholder="请输入分类名称"></div>
<button class="btn btn-primary">查询</button>
<button class="btn btn-default">重置</button>
</div>
<div class="action-bar">
<!-- [交互] 点击打开右侧抽屉弹窗(新增模式) -->
<button class="btn btn-primary" onclick="openDrawer('add')">+ 新增</button>
</div>
<div class="table-card">
<div class="table-card__content">
<table>
<thead>
<tr>
<th rowspan="2" class="th-left" style="min-width:160px;">分类名称</th>
<th colspan="7">监测数据阈值</th>
<th rowspan="2" style="min-width:100px;">操作</th>
</tr>
<tr>
<th>温度(℃)</th>
<th>湿度(%)</th>
<th>太阳辐射(W/m²)</th>
<th>PM2.5(μg/m³)</th>
<th>PM10(μg/m³)</th>
<th>照度(lm/m²)</th>
<th>风速(m/s)</th>
</tr>
</thead>
<tbody>
<tr>
<td class="td-left">空气质量监测站</td>
<td>-10 ~ 45</td>
<td>10 ~ 95</td>
<td>0 ~ 1200</td>
<td>0 ~ 75</td>
<td>0 ~ 150</td>
<td>0 ~ 100000</td>
<td>0 ~ 30</td>
<td><a class="link" onclick="openDrawer('edit',0)">编辑</a> <a class="link-danger">删除</a></td>
</tr>
<tr>
<td class="td-left">PM10检测仪</td>
<td>-10 ~ 45</td>
<td>10 ~ 90</td>
<td>0 ~ 1000</td>
<td>0 ~ 75</td>
<td>0 ~ 150</td>
<td>0 ~ 80000</td>
<td>0 ~ 25</td>
<td><a class="link" onclick="openDrawer('edit',1)">编辑</a> <a class="link-danger">删除</a></td>
</tr>
<tr>
<td class="td-left">臭氧检测仪</td>
<td>-5 ~ 40</td>
<td>15 ~ 85</td>
<td>0 ~ 1100</td>
<td>0 ~ 50</td>
<td>0 ~ 100</td>
<td>0 ~ 90000</td>
<td>0 ~ 20</td>
<td><a class="link" onclick="openDrawer('edit',2)">编辑</a> <a class="link-danger">删除</a></td>
</tr>
<tr>
<td class="td-left">气象参数监测仪</td>
<td>-20 ~ 50</td>
<td>5 ~ 100</td>
<td>0 ~ 1500</td>
<td>0 ~ 75</td>
<td>0 ~ 150</td>
<td>0 ~ 120000</td>
<td>0 ~ 40</td>
<td><a class="link" onclick="openDrawer('edit',3)">编辑</a> <a class="link-danger">删除</a></td>
</tr>
</tbody>
</table>
</div>
<div class="pagination">
<span>共 4 条</span>
<button class="page-btn active">1</button>
</div>
</div>
</main>
<script>function toggleSubgroup(h){h.parentElement.classList.toggle('open');}(function(){var a=document.querySelector('.sidebar-item.active');if(!a)return;var s=a.closest('.sidebar-subgroup');if(s)s.classList.add('open');})();</script>
<!-- 新增/编辑分类 - 右侧抽屉弹窗 -->
<div class="drawer-mask" id="drawerMask" onclick="closeDrawer()"></div>
<div class="drawer" id="drawer">
<div class="drawer__header">
<span class="drawer__title" id="drawerTitle">新增分类</span>
<button class="drawer__close" onclick="closeDrawer()">&times;</button>
</div>
<div class="drawer__body">
<div class="form-group">
<label class="form-label"><span class="required">*</span>分类名称</label>
<input class="form-control" id="formCategoryName" placeholder="请输入分类名称">
</div>
<div class="threshold-section-title">监测数据阈值设置</div>
<div class="threshold-list">
<div class="threshold-item">
<div class="threshold-item__header"><span class="threshold-item__label">温度<span class="threshold-item__unit">(℃)</span></span></div>
<div class="threshold-item__body"><div class="threshold-row">
<div class="threshold-field"><label>阈值下限</label><input class="form-control" type="number" placeholder="下限"></div>
<div class="threshold-field"><label>阈值上限</label><input class="form-control" type="number" placeholder="上限"></div>
</div></div>
</div>
<div class="threshold-item">
<div class="threshold-item__header"><span class="threshold-item__label">湿度<span class="threshold-item__unit">(%)</span></span></div>
<div class="threshold-item__body"><div class="threshold-row">
<div class="threshold-field"><label>阈值下限</label><input class="form-control" type="number" placeholder="下限"></div>
<div class="threshold-field"><label>阈值上限</label><input class="form-control" type="number" placeholder="上限"></div>
</div></div>
</div>
<div class="threshold-item">
<div class="threshold-item__header"><span class="threshold-item__label">太阳辐射<span class="threshold-item__unit">(W/m²)</span></span></div>
<div class="threshold-item__body"><div class="threshold-row">
<div class="threshold-field"><label>阈值下限</label><input class="form-control" type="number" placeholder="下限"></div>
<div class="threshold-field"><label>阈值上限</label><input class="form-control" type="number" placeholder="上限"></div>
</div></div>
</div>
<div class="threshold-item">
<div class="threshold-item__header"><span class="threshold-item__label">PM2.5<span class="threshold-item__unit">(μg/m³)</span></span></div>
<div class="threshold-item__body"><div class="threshold-row">
<div class="threshold-field"><label>阈值下限</label><input class="form-control" type="number" placeholder="下限"></div>
<div class="threshold-field"><label>阈值上限</label><input class="form-control" type="number" placeholder="上限"></div>
</div></div>
</div>
<div class="threshold-item">
<div class="threshold-item__header"><span class="threshold-item__label">PM10<span class="threshold-item__unit">(μg/m³)</span></span></div>
<div class="threshold-item__body"><div class="threshold-row">
<div class="threshold-field"><label>阈值下限</label><input class="form-control" type="number" placeholder="下限"></div>
<div class="threshold-field"><label>阈值上限</label><input class="form-control" type="number" placeholder="上限"></div>
</div></div>
</div>
<div class="threshold-item">
<div class="threshold-item__header"><span class="threshold-item__label">照度<span class="threshold-item__unit">(lm/m²)</span></span></div>
<div class="threshold-item__body"><div class="threshold-row">
<div class="threshold-field"><label>阈值下限</label><input class="form-control" type="number" placeholder="下限"></div>
<div class="threshold-field"><label>阈值上限</label><input class="form-control" type="number" placeholder="上限"></div>
</div></div>
</div>
<div class="threshold-item">
<div class="threshold-item__header"><span class="threshold-item__label">风速<span class="threshold-item__unit">(m/s)</span></span></div>
<div class="threshold-item__body"><div class="threshold-row">
<div class="threshold-field"><label>阈值下限</label><input class="form-control" type="number" placeholder="下限"></div>
<div class="threshold-field"><label>阈值上限</label><input class="form-control" type="number" placeholder="上限"></div>
</div></div>
</div>
</div>
</div>
<div class="drawer__footer">
<button class="btn btn-default" onclick="closeDrawer()">取消</button>
<button class="btn btn-primary" onclick="closeDrawer()">确定</button>
</div>
</div>
<script>
function toggleSubgroup(h){h.parentElement.classList.toggle('open');}
(function(){var a=document.querySelector('.sidebar-item.active');if(!a)return;var s=a.closest('.sidebar-subgroup');if(s)s.classList.add('open');})();
function openDrawer(mode, rowIdx){
var title = document.getElementById('drawerTitle');
var nameInput = document.getElementById('formCategoryName');
var fields = document.querySelectorAll('.threshold-field .form-control');
if(mode === 'edit'){
title.textContent = '编辑分类';
var row = document.querySelectorAll('tbody tr')[rowIdx];
var cells = row.querySelectorAll('td');
nameInput.value = cells[0].textContent.trim();
for(var i = 0; i < 7; i++){
var parts = cells[i+1].textContent.split('~');
fields[i*2].value = parts[0].trim();
fields[i*2+1].value = parts[1].trim();
}
} else {
title.textContent = '新增分类';
nameInput.value = '';
for(var j = 0; j < fields.length; j++){ fields[j].value = ''; }
}
document.getElementById('drawerMask').classList.add('open');
document.getElementById('drawer').classList.add('open');
}
function closeDrawer(){document.getElementById('drawerMask').classList.remove('open');document.getElementById('drawer').classList.remove('open');}
</script>
</body>
</html>
</html>
@@ -3,7 +3,7 @@
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>健康监测 - 设备列表 | 健康长庆原型</title>
<title>室外空气 - 设备列表 | 健康长庆原型</title>
<style>
*{box-sizing:border-box;margin:0;padding:0;}
body{font-family:-apple-system,BlinkMacSystemFont,'PingFang SC','Microsoft YaHei',sans-serif;background:#F5F7FA;color:#333;min-width:1280px;}
@@ -40,9 +40,56 @@
.sidebar-subgroup.open>.sidebar-subgroup__body{display:block;}
.sidebar-subgroup__body .sidebar-item{padding-left:36px;font-size:12px;}
.main{margin-left:240px;margin-top:56px;padding:24px;min-height:calc(100vh - 56px);}
.page-placeholder{display:flex;flex-direction:column;align-items:center;justify-content:center;height:calc(100vh - 56px - 48px);color:var(--text-placeholder);gap:12px;}
.page-placeholder svg{opacity:.25;}
.page-placeholder p{font-size:var(--font-base);}
.filter-bar{background:#fff;border-radius:var(--radius-md);padding:20px 24px;margin-bottom:16px;box-shadow:var(--shadow-sm);display:flex;align-items:center;gap:16px;flex-wrap:wrap;}
.filter-item{display:flex;align-items:center;gap:8px;}
.filter-item label{font-size:var(--font-sm);color:var(--text-secondary);white-space:nowrap;}
.filter-input{height:36px;border:1px solid var(--border);border-radius:var(--radius-sm);padding:0 12px;font-size:var(--font-sm);color:var(--text-primary);outline:none;background:#fff;min-width:160px;}
.filter-input:focus{border-color:var(--primary);}
.filter-select{height:36px;border:1px solid var(--border);border-radius:var(--radius-sm);padding:0 28px 0 12px;font-size:var(--font-sm);color:var(--text-primary);outline:none;background:#fff url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6'%3E%3Cpath d='M0 0l5 6 5-6z' fill='%23999'/%3E%3C/svg%3E") no-repeat right 10px center;appearance:none;cursor:pointer;min-width:140px;}
.btn{height:36px;padding:0 16px;border-radius:var(--radius-sm);font-size:var(--font-sm);cursor:pointer;border:none;transition:all .2s;display:inline-flex;align-items:center;gap:6px;}
.btn-primary{background:var(--primary);color:#fff;}.btn-primary:hover{background:#40a9ff;}
.btn-default{background:#fff;color:var(--text-primary);border:1px solid var(--border);}.btn-default:hover{color:var(--primary);border-color:var(--primary);}
.btn-success{background:var(--success);color:#fff;}.btn-success:hover{background:#73d13d;}
.action-bar{display:flex;align-items:center;gap:12px;margin-bottom:16px;}
.table-card{background:#fff;border-radius:var(--radius-md);box-shadow:var(--shadow-sm);overflow:hidden;}
.table-card__content{overflow-x:auto;-webkit-overflow-scrolling:touch;}
table{width:100%;border-collapse:collapse;min-width:1000px;}
thead th{background:#FAFAFA;padding:12px 16px;text-align:left;font-size:var(--font-sm);color:var(--text-secondary);font-weight:500;border-bottom:1px solid var(--border);white-space:nowrap;}
tbody td{padding:14px 16px;font-size:var(--font-sm);color:var(--text-primary);border-bottom:1px solid var(--border);white-space:nowrap;}
tbody tr:last-child td{border-bottom:none;}
tbody tr:hover{background:#F8FBFF;}
.link{color:var(--primary);cursor:pointer;font-size:var(--font-sm);text-decoration:none;}.link:hover{color:#40a9ff;}
.link-danger{color:var(--danger);cursor:pointer;font-size:var(--font-sm);text-decoration:none;}.link-danger:hover{color:#ff7875;}
.pagination{display:flex;align-items:center;justify-content:flex-end;padding:16px 24px;gap:8px;border-top:1px solid var(--border);}
.pagination span{font-size:var(--font-sm);color:var(--text-secondary);}
.page-btn{width:32px;height:32px;border:1px solid var(--border);border-radius:var(--radius-sm);background:#fff;cursor:pointer;font-size:var(--font-sm);display:inline-flex;align-items:center;justify-content:center;transition:all .2s;}
.page-btn:hover,.page-btn.active{background:var(--primary);color:#fff;border-color:var(--primary);}
.drawer-mask{display:none;position:fixed;top:0;left:0;right:0;bottom:0;background:rgba(0,0,0,0.45);z-index:200;}
.drawer-mask.open{display:block;}
.drawer{position:fixed;top:0;right:-560px;width:560px;height:100%;background:#fff;z-index:201;box-shadow:-4px 0 16px rgba(0,0,0,0.12);transition:right .3s ease;display:flex;flex-direction:column;}
.drawer.open{right:0;}
.drawer__header{display:flex;align-items:center;justify-content:space-between;padding:16px 24px;border-bottom:1px solid var(--border);}
.drawer__title{font-size:var(--font-base);font-weight:600;color:var(--text-primary);}
.drawer__close{width:32px;height:32px;border:none;background:none;cursor:pointer;display:flex;align-items:center;justify-content:center;border-radius:var(--radius-sm);color:var(--text-placeholder);font-size:18px;}
.drawer__close:hover{background:#f5f5f5;color:var(--text-primary);}
.drawer__body{flex:1;overflow-y:auto;padding:24px;}
.drawer__footer{display:flex;align-items:center;justify-content:flex-end;gap:12px;padding:16px 24px;border-top:1px solid var(--border);}
.form-group{margin-bottom:20px;}
.form-label{display:block;font-size:var(--font-sm);color:var(--text-primary);margin-bottom:8px;font-weight:500;}
.form-label .required{color:var(--danger);margin-right:4px;}
.form-control{width:100%;height:36px;border:1px solid var(--border);border-radius:var(--radius-sm);padding:0 12px;font-size:var(--font-sm);color:var(--text-primary);outline:none;background:#fff;}
.form-control:focus{border-color:var(--primary);box-shadow:0 0 0 2px rgba(24,144,255,0.1);}
.form-select{width:100%;height:36px;border:1px solid var(--border);border-radius:var(--radius-sm);padding:0 28px 0 12px;font-size:var(--font-sm);color:var(--text-primary);outline:none;background:#fff url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6'%3E%3Cpath d='M0 0l5 6 5-6z' fill='%23999'/%3E%3C/svg%3E") no-repeat right 10px center;appearance:none;cursor:pointer;}
.form-select:focus{border-color:var(--primary);box-shadow:0 0 0 2px rgba(24,144,255,0.1);}
.map-picker{width:100%;height:200px;border:1px solid var(--border);border-radius:var(--radius-sm);background:#f0f2f5;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:8px;color:var(--text-placeholder);cursor:pointer;position:relative;overflow:hidden;}
.map-picker__icon{width:40px;height:40px;border-radius:50%;background:var(--primary-light);display:flex;align-items:center;justify-content:center;}
.map-picker__text{font-size:var(--font-sm);}
.map-picker__pin{position:absolute;top:50%;left:50%;transform:translate(-50%,-100%);display:none;}
.map-picker.selected{background:linear-gradient(135deg,#e6f7ff 0%,#f0f5ff 100%);border-color:var(--primary);}
.map-picker.selected .map-picker__pin{display:block;}
.map-picker.selected .map-picker__icon,.map-picker.selected .map-picker__text{display:none;}
.map-picker__hint{position:absolute;bottom:8px;left:0;right:0;text-align:center;font-size:var(--font-xs);color:var(--text-placeholder);display:none;}
.map-picker.selected .map-picker__hint{display:block;}
</style>
</head>
<body>
@@ -57,10 +104,7 @@
<a href="../exception-dirty.html">异常事件</a>
</nav>
<div class="top-bar__right">
<a class="btn-back" href="../../../index.html">
<svg width="16" height="16" viewBox="0 0 16 16" fill="none"><path d="M10 3L5 8l5 5" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/></svg>
返回首页
</a>
<a class="btn-back" href="../../../index.html"><svg width="16" height="16" viewBox="0 0 16 16" fill="none"><path d="M10 3L5 8l5 5" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/></svg> 返回首页</a>
<div class="avatar"></div>
<span style="color:rgba(255,255,255,0.65);">系统管理员 ▾</span>
</div>
@@ -114,11 +158,126 @@
</div>
</aside>
<main class="main">
<div class="page-placeholder">
<svg width="64" height="64" viewBox="0 0 64 64" fill="none"><rect x="8" y="8" width="48" height="48" rx="8" stroke="#ccc" stroke-width="2"/><path d="M20 32h24M32 20v24" stroke="#ccc" stroke-width="2" stroke-linecap="round"/></svg>
<p>设备列表</p>
<!-- 筛选条件 -->
<div class="filter-bar">
<div class="filter-item"><label>设备编码</label><input class="filter-input" placeholder="请输入设备编码"></div>
<div class="filter-item"><label>设备名称</label><input class="filter-input" placeholder="请输入设备名称"></div>
<div class="filter-item"><label>所属单位</label><select class="filter-select"><option value="">全部</option><option>采油一厂</option><option>采油二厂</option><option>采气厂</option><option>炼化公司</option></select></div>
<div class="filter-item"><label>设备分类</label><select class="filter-select"><option value="">全部</option><option>空气质量监测站</option><option>PM10检测仪</option><option>臭氧检测仪</option><option>气象参数监测仪</option></select></div>
<button class="btn btn-primary">查询</button>
<button class="btn btn-default">重置</button>
</div>
<!-- 操作按钮 -->
<div class="action-bar">
<button class="btn btn-primary" onclick="openDrawer()">+ 新增设备</button>
<button class="btn btn-success">批量入库导入</button>
<button class="btn btn-default">查看导入任务</button>
<button class="btn btn-default">导出列表数据</button>
</div>
<!-- 数据列表 -->
<div class="table-card">
<div class="table-card__content">
<table>
<thead><tr><th>设备名称</th><th>设备编码</th><th>设备分类</th><th>所属单位</th><th>设备位置</th><th>布点日期</th><th>监测时长(天)</th><th>操作</th></tr></thead>
<tbody>
<tr><td>室外空气监测站A1</td><td>OA-2024-001</td><td>空气质量监测站</td><td>采油一厂</td><td>厂区东门广场</td><td>2024-05-10</td><td>364</td><td><a class="link" onclick="openDrawer()">编辑</a> <a class="link-danger">删除</a></td></tr>
<tr><td>PM10检测仪A2</td><td>OA-2024-002</td><td>PM10检测仪</td><td>采油一厂</td><td>办公楼顶层平台</td><td>2024-06-18</td><td>325</td><td><a class="link" onclick="openDrawer()">编辑</a> <a class="link-danger">删除</a></td></tr>
<tr><td>臭氧监测仪B1</td><td>OA-2024-003</td><td>臭氧检测仪</td><td>采油二厂</td><td>生产区北侧围墙</td><td>2024-07-25</td><td>288</td><td><a class="link" onclick="openDrawer()">编辑</a> <a class="link-danger">删除</a></td></tr>
<tr><td>气象参数站C1</td><td>OA-2024-004</td><td>气象参数监测仪</td><td>采气厂</td><td>厂区中心绿地</td><td>2024-08-30</td><td>252</td><td><a class="link" onclick="openDrawer()">编辑</a> <a class="link-danger">删除</a></td></tr>
<tr><td>空气质量站D1</td><td>OA-2025-001</td><td>空气质量监测站</td><td>炼化公司</td><td>南门停车场旁</td><td>2025-02-14</td><td>84</td><td><a class="link" onclick="openDrawer()">编辑</a> <a class="link-danger">删除</a></td></tr>
</tbody>
</table>
</div>
<div class="pagination">
<span>共 35 条</span>
<button class="page-btn"></button>
<button class="page-btn active">1</button>
<button class="page-btn">2</button>
<button class="page-btn">3</button>
<button class="page-btn">4</button>
<button class="page-btn"></button>
</div>
</div>
</main>
<script>function toggleSubgroup(h){h.parentElement.classList.toggle('open');}(function(){var a=document.querySelector('.sidebar-item.active');if(!a)return;var s=a.closest('.sidebar-subgroup');if(s)s.classList.add('open');})();</script>
<!-- 新增设备 - 右侧抽屉弹窗 -->
<div class="drawer-mask" id="drawerMask" onclick="closeDrawer()"></div>
<div class="drawer" id="drawer">
<div class="drawer__header">
<span class="drawer__title">新增设备</span>
<button class="drawer__close" onclick="closeDrawer()">&times;</button>
</div>
<div class="drawer__body">
<div class="form-group">
<label class="form-label"><span class="required">*</span>设备名称</label>
<input class="form-control" placeholder="请输入设备名称">
</div>
<div class="form-group">
<label class="form-label"><span class="required">*</span>设备编码</label>
<input class="form-control" placeholder="请输入设备编码">
</div>
<div class="form-group">
<label class="form-label"><span class="required">*</span>设备分类</label>
<select class="form-select">
<option value="">请选择设备分类</option>
<option>空气质量监测站</option>
<option>PM10检测仪</option>
<option>臭氧检测仪</option>
<option>气象参数监测仪</option>
</select>
</div>
<div class="form-group">
<label class="form-label"><span class="required">*</span>所属单位</label>
<select class="form-select">
<option value="">请选择所属单位</option>
<option>采油一厂</option>
<option>采油二厂</option>
<option>采气厂</option>
<option>炼化公司</option>
</select>
</div>
<div class="form-group">
<label class="form-label"><span class="required">*</span>设备位置</label>
<div class="map-picker selected" onclick="this.classList.toggle('selected')">
<div class="map-picker__icon">
<svg width="20" height="20" viewBox="0 0 20 20" fill="none"><path d="M10 2C6.69 2 4 4.69 4 8c0 4.5 6 10 6 10s6-5.5 6-10c0-3.31-2.69-6-6-6zm0 8a2 2 0 110-4 2 2 0 010 4z" fill="#1890FF"/></svg>
</div>
<div class="map-picker__text">点击地图选择设备位置</div>
<svg class="map-picker__pin" width="160" height="120" viewBox="0 0 160 120">
<rect width="160" height="120" rx="4" fill="#e6f7ff" opacity="0.5"/>
<line x1="0" y1="30" x2="160" y2="30" stroke="#d9d9d9" stroke-width="0.5" stroke-dasharray="4"/>
<line x1="0" y1="60" x2="160" y2="60" stroke="#d9d9d9" stroke-width="0.5" stroke-dasharray="4"/>
<line x1="0" y1="90" x2="160" y2="90" stroke="#d9d9d9" stroke-width="0.5" stroke-dasharray="4"/>
<line x1="40" y1="0" x2="40" y2="120" stroke="#d9d9d9" stroke-width="0.5" stroke-dasharray="4"/>
<line x1="80" y1="0" x2="80" y2="120" stroke="#d9d9d9" stroke-width="0.5" stroke-dasharray="4"/>
<line x1="120" y1="0" x2="120" y2="120" stroke="#d9d9d9" stroke-width="0.5" stroke-dasharray="4"/>
<path d="M80 40C76.69 40 74 42.69 74 46c0 4.5 6 10 6 10s6-5.5 6-10c0-3.31-2.69-6-6-6zm0 8a2 2 0 110-4 2 2 0 010 4z" fill="#1890FF"/>
<circle cx="80" cy="46" r="12" fill="none" stroke="#1890FF" stroke-width="1" opacity="0.3"/>
<circle cx="80" cy="46" r="20" fill="none" stroke="#1890FF" stroke-width="0.5" opacity="0.15"/>
</svg>
<div class="map-picker__hint">点击重新选点</div>
</div>
</div>
<div class="form-group">
<label class="form-label"><span class="required">*</span>详细地址</label>
<input class="form-control" value="陕西省西安市长庆路采油一厂东门广场" placeholder="地图选点后自动带入,可手动修改">
</div>
<div class="form-group">
<label class="form-label"><span class="required">*</span>布点日期</label>
<input class="form-control" type="date" value="2025-05-14">
</div>
</div>
<div class="drawer__footer">
<button class="btn btn-default" onclick="closeDrawer()">取消</button>
<button class="btn btn-primary" onclick="closeDrawer()">确定</button>
</div>
</div>
<script>
function toggleSubgroup(h){h.parentElement.classList.toggle('open');}
(function(){var a=document.querySelector('.sidebar-item.active');if(!a)return;var s=a.closest('.sidebar-subgroup');if(s)s.classList.add('open');})();
function openDrawer(){document.getElementById('drawerMask').classList.add('open');document.getElementById('drawer').classList.add('open');}
function closeDrawer(){document.getElementById('drawerMask').classList.remove('open');document.getElementById('drawer').classList.remove('open');}
</script>
</body>
</html>
@@ -3,7 +3,7 @@
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>健康监测 - 异常报警 | 健康长庆原型</title>
<title>室外空气 - 异常报警 | 健康长庆原型</title>
<style>
*{box-sizing:border-box;margin:0;padding:0;}
body{font-family:-apple-system,BlinkMacSystemFont,'PingFang SC','Microsoft YaHei',sans-serif;background:#F5F7FA;color:#333;min-width:1280px;}
@@ -40,9 +40,34 @@
.sidebar-subgroup.open>.sidebar-subgroup__body{display:block;}
.sidebar-subgroup__body .sidebar-item{padding-left:36px;font-size:12px;}
.main{margin-left:240px;margin-top:56px;padding:24px;min-height:calc(100vh - 56px);}
.page-placeholder{display:flex;flex-direction:column;align-items:center;justify-content:center;height:calc(100vh - 56px - 48px);color:var(--text-placeholder);gap:12px;}
.page-placeholder svg{opacity:.25;}
.page-placeholder p{font-size:var(--font-base);}
.filter-bar{background:#fff;border-radius:var(--radius-md);padding:20px 24px;margin-bottom:16px;box-shadow:var(--shadow-sm);display:flex;align-items:center;gap:16px;flex-wrap:wrap;}
.filter-item{display:flex;align-items:center;gap:8px;}
.filter-item label{font-size:var(--font-sm);color:var(--text-secondary);white-space:nowrap;}
.filter-input{height:36px;border:1px solid var(--border);border-radius:var(--radius-sm);padding:0 12px;font-size:var(--font-sm);color:var(--text-primary);outline:none;background:#fff;min-width:160px;}
.filter-input:focus{border-color:var(--primary);}
.filter-select{height:36px;border:1px solid var(--border);border-radius:var(--radius-sm);padding:0 28px 0 12px;font-size:var(--font-sm);color:var(--text-primary);outline:none;background:#fff url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6'%3E%3Cpath d='M0 0l5 6 5-6z' fill='%23999'/%3E%3C/svg%3E") no-repeat right 10px center;appearance:none;cursor:pointer;min-width:140px;}
.filter-date{height:36px;border:1px solid var(--border);border-radius:var(--radius-sm);padding:0 12px;font-size:var(--font-sm);color:var(--text-primary);outline:none;background:#fff;width:150px;}
.filter-date:focus{border-color:var(--primary);}
.filter-separator{color:var(--text-placeholder);font-size:var(--font-sm);}
.btn{height:36px;padding:0 16px;border-radius:var(--radius-sm);font-size:var(--font-sm);cursor:pointer;border:none;transition:all .2s;display:inline-flex;align-items:center;gap:6px;}
.btn-primary{background:var(--primary);color:#fff;}.btn-primary:hover{background:#40a9ff;}
.btn-default{background:#fff;color:var(--text-primary);border:1px solid var(--border);}.btn-default:hover{color:var(--primary);border-color:var(--primary);}
.action-bar{display:flex;align-items:center;gap:12px;margin-bottom:16px;}
.table-card{background:#fff;border-radius:var(--radius-md);box-shadow:var(--shadow-sm);overflow:hidden;}
.table-card__content{overflow-x:auto;-webkit-overflow-scrolling:touch;}
table{width:100%;border-collapse:collapse;min-width:1100px;}
thead th{background:#FAFAFA;padding:12px 14px;text-align:center;font-size:var(--font-xs);color:var(--text-secondary);font-weight:500;border-bottom:1px solid var(--border);border-right:1px solid var(--border);white-space:nowrap;}
thead th:last-child{border-right:none;}
thead th.th-left{text-align:left;}
tbody td{padding:12px 14px;font-size:var(--font-xs);color:var(--text-primary);border-bottom:1px solid var(--border);text-align:center;white-space:nowrap;}
tbody td.td-left{text-align:left;}
tbody tr:last-child td{border-bottom:none;}
tbody tr:hover{background:#F8FBFF;}
.danger-text{color:var(--danger);font-weight:500;}
.pagination{display:flex;align-items:center;justify-content:flex-end;padding:16px 24px;gap:8px;border-top:1px solid var(--border);}
.pagination span{font-size:var(--font-sm);color:var(--text-secondary);}
.page-btn{width:32px;height:32px;border:1px solid var(--border);border-radius:var(--radius-sm);background:#fff;cursor:pointer;font-size:var(--font-sm);display:inline-flex;align-items:center;justify-content:center;transition:all .2s;}
.page-btn:hover,.page-btn.active{background:var(--primary);color:#fff;border-color:var(--primary);}
</style>
</head>
<body>
@@ -57,10 +82,7 @@
<a href="../exception-dirty.html">异常事件</a>
</nav>
<div class="top-bar__right">
<a class="btn-back" href="../../../index.html">
<svg width="16" height="16" viewBox="0 0 16 16" fill="none"><path d="M10 3L5 8l5 5" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/></svg>
返回首页
</a>
<a class="btn-back" href="../../../index.html"><svg width="16" height="16" viewBox="0 0 16 16" fill="none"><path d="M10 3L5 8l5 5" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/></svg> 返回首页</a>
<div class="avatar"></div>
<span style="color:rgba(255,255,255,0.65);">系统管理员 ▾</span>
</div>
@@ -114,11 +136,110 @@
</div>
</aside>
<main class="main">
<div class="page-placeholder">
<svg width="64" height="64" viewBox="0 0 64 64" fill="none"><rect x="8" y="8" width="48" height="48" rx="8" stroke="#ccc" stroke-width="2"/><path d="M20 32h24M32 20v24" stroke="#ccc" stroke-width="2" stroke-linecap="round"/></svg>
<p>异常报警</p>
<!-- 筛选条件 -->
<div class="filter-bar">
<div class="filter-item"><label>设备名称</label><input class="filter-input" placeholder="请输入设备名称"></div>
<div class="filter-item"><label>设备编号</label><input class="filter-input" placeholder="请输入设备编号"></div>
<div class="filter-item"><label>所属单位</label>
<select class="filter-select"><option value="">全部</option><option>采油一厂</option><option>采油二厂</option><option>采油三厂</option></select>
</div>
<div class="filter-item"><label>监测类型</label>
<select class="filter-select"><option value="">全部</option><option>温度</option><option>湿度</option><option>太阳辐射</option><option>PM2.5</option><option>PM10</option><option>照度</option><option>风速</option></select>
</div>
<div class="filter-item"><label>日期范围</label><input class="filter-date" type="date" value="2026-05-01"><span class="filter-separator"></span><input class="filter-date" type="date" value="2026-05-15"></div>
<button class="btn btn-primary">查询</button>
<button class="btn btn-default">重置</button>
</div>
<!-- 操作按钮 -->
<div class="action-bar">
<button class="btn btn-default">导出列表数据</button>
<button class="btn btn-default">查看导出任务</button>
</div>
<!-- 数据列表 -->
<div class="table-card">
<div class="table-card__content">
<table>
<thead>
<tr>
<th class="th-left" style="min-width:150px;">设备名称</th>
<th style="min-width:120px;">设备编号</th>
<th style="min-width:90px;">所属单位</th>
<th style="min-width:140px;">设备位置</th>
<th style="min-width:80px;">监测类型</th>
<th style="min-width:80px;">单位</th>
<th style="min-width:70px;">阈值</th>
<th style="min-width:80px;">异常值</th>
<th style="min-width:160px;">报警时间</th>
</tr>
</thead>
<tbody>
<tr>
<td class="td-left">空气质量监测站-A01</td>
<td>OA-2024-001</td>
<td>采油一厂</td>
<td>厂区大门东侧</td>
<td>PM2.5</td>
<td>μg/m³</td>
<td>75</td>
<td class="danger-text">156</td>
<td>2026-05-15 10:05:22</td>
</tr>
<tr>
<td class="td-left">空气质量监测站-A01</td>
<td>OA-2024-001</td>
<td>采油一厂</td>
<td>厂区大门东侧</td>
<td>PM10</td>
<td>μg/m³</td>
<td>150</td>
<td class="danger-text">218</td>
<td>2026-05-15 10:05:22</td>
</tr>
<tr>
<td class="td-left">气象参数监测仪-D01</td>
<td>OA-2024-004</td>
<td>采油三厂</td>
<td>气象观测场</td>
<td>风速</td>
<td>m/s</td>
<td>10</td>
<td class="danger-text">13.5</td>
<td>2026-05-14 15:42:10</td>
</tr>
<tr>
<td class="td-left">空气质量监测站-A03</td>
<td>OA-2024-005</td>
<td>采油三厂</td>
<td>储油罐区南侧</td>
<td>太阳辐射</td>
<td>W/m²</td>
<td>1000</td>
<td class="danger-text">1180</td>
<td>2026-05-14 09:18:35</td>
</tr>
<tr>
<td class="td-left">PM10检测仪-B02</td>
<td>OA-2024-002</td>
<td>采油一厂</td>
<td>生产区北围栏</td>
<td>温度</td>
<td></td>
<td>40</td>
<td class="danger-text">42.3</td>
<td>2026-05-13 17:30:48</td>
</tr>
</tbody>
</table>
</div>
<div class="pagination">
<span>共 5 条</span>
<button class="page-btn active">1</button>
</div>
</div>
</main>
<script>function toggleSubgroup(h){h.parentElement.classList.toggle('open');}(function(){var a=document.querySelector('.sidebar-item.active');if(!a)return;var s=a.closest('.sidebar-subgroup');if(s)s.classList.add('open');})();</script>
<script>
function toggleSubgroup(h){h.parentElement.classList.toggle('open');}
(function(){var a=document.querySelector('.sidebar-item.active');if(!a)return;var s=a.closest('.sidebar-subgroup');if(s)s.classList.add('open');})();
</script>
</body>
</html>
</html>
@@ -0,0 +1,194 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>室外空气 - 异常数据详情 | 健康长庆原型</title>
<style>
*{box-sizing:border-box;margin:0;padding:0;}
body{font-family:-apple-system,BlinkMacSystemFont,'PingFang SC','Microsoft YaHei',sans-serif;background:#F5F7FA;color:#333;min-width:1280px;}
:root{
--primary:#1890FF;--primary-light:#E6F7FF;--success:#52C41A;--warning:#FAAD14;--danger:#FF4D4F;
--text-primary:#333;--text-secondary:#666;--text-placeholder:#999;--border:#E8E8E8;--background:#F5F7FA;
--font-xs:11px;--font-sm:13px;--font-base:15px;--font-lg:17px;
--radius-sm:4px;--radius-md:8px;--radius-lg:12px;
--shadow-sm:0 1px 4px rgba(0,0,0,0.08);
}
.top-bar{display:flex;align-items:center;height:56px;background:#001529;padding:0 24px;position:fixed;top:0;left:0;right:0;z-index:100;}
.top-bar__logo{display:flex;align-items:center;gap:8px;color:#fff;font-size:var(--font-lg);font-weight:600;white-space:nowrap;width:240px;flex-shrink:0;}
.top-bar__logo svg{width:28px;height:28px;}
.top-bar__right{display:flex;align-items:center;gap:16px;color:rgba(255,255,255,0.65);font-size:var(--font-sm);}
.btn-back{color:rgba(255,255,255,0.65);cursor:pointer;display:flex;align-items:center;gap:4px;text-decoration:none;}.btn-back:hover{color:#fff;}
.avatar{width:32px;height:32px;border-radius:50%;background:#1890FF;display:flex;align-items:center;justify-content:center;color:#fff;font-size:var(--font-sm);cursor:pointer;}
.top-bar__nav{display:flex;align-items:center;gap:4px;flex:1;}
.top-bar__nav a{color:rgba(255,255,255,0.65);text-decoration:none;padding:6px 16px;border-radius:var(--radius-sm);font-size:var(--font-sm);transition:all .2s;}
.top-bar__nav a:hover{color:#fff;background:rgba(255,255,255,0.08);}
.top-bar__nav a.active{color:#fff;background:var(--primary);}
.sidebar{position:fixed;top:56px;left:0;bottom:0;width:240px;background:#001529;overflow-y:auto;z-index:90;padding-top:8px;}
.sidebar-menu__title{color:rgba(255,255,255,0.35);font-size:var(--font-xs);padding:16px 24px 8px;letter-spacing:.5px;}
.sidebar-item{display:flex;align-items:center;gap:8px;padding:10px 24px;color:rgba(255,255,255,0.65);font-size:var(--font-sm);cursor:pointer;transition:all .15s;text-decoration:none;}
.sidebar-item:hover{color:#fff;background:rgba(255,255,255,0.06);}
.sidebar-item.active{color:#fff;background:var(--primary);}
.sidebar-subgroup__header{display:flex;align-items:center;gap:6px;padding:10px 24px;color:rgba(255,255,255,0.65);font-size:var(--font-sm);cursor:pointer;transition:all .15s;user-select:none;}
.sidebar-subgroup__header:hover{color:rgba(255,255,255,0.85);background:rgba(255,255,255,0.04);}
.sidebar-subgroup__header .arrow{width:10px;height:10px;transition:transform .2s;flex-shrink:0;}
.sidebar-subgroup__header .arrow path{stroke:rgba(255,255,255,0.45);}
.sidebar-subgroup.open>.sidebar-subgroup__header{color:rgba(255,255,255,0.85);}
.sidebar-subgroup.open>.sidebar-subgroup__header .arrow{transform:rotate(90deg);}
.sidebar-subgroup__body{display:none;padding-left:16px;}
.sidebar-subgroup.open>.sidebar-subgroup__body{display:block;}
.sidebar-subgroup__body .sidebar-item{padding-left:36px;font-size:12px;}
.main{margin-left:240px;margin-top:56px;padding:24px;min-height:calc(100vh - 56px);}
.page-header{display:flex;align-items:center;gap:12px;margin-bottom:16px;}
.page-header__back{display:flex;align-items:center;gap:4px;color:var(--text-secondary);font-size:var(--font-sm);cursor:pointer;text-decoration:none;}.page-header__back:hover{color:var(--primary);}
.page-header__title{font-size:var(--font-lg);font-weight:600;color:var(--text-primary);}
.info-card{background:#fff;border-radius:var(--radius-md);padding:20px 24px;margin-bottom:16px;box-shadow:var(--shadow-sm);display:grid;grid-template-columns:repeat(3,1fr);gap:16px 24px;}
.info-card__item{display:flex;align-items:baseline;gap:8px;min-width:0;}
.info-card__label{font-size:var(--font-xs);color:var(--text-placeholder);white-space:nowrap;flex-shrink:0;}
.info-card__value{font-size:var(--font-sm);color:var(--text-primary);font-weight:500;word-break:break-all;}
.filter-bar{background:#fff;border-radius:var(--radius-md);padding:20px 24px;margin-bottom:16px;box-shadow:var(--shadow-sm);display:flex;align-items:center;gap:16px;flex-wrap:wrap;}
.filter-item{display:flex;align-items:center;gap:8px;}
.filter-item label{font-size:var(--font-sm);color:var(--text-secondary);white-space:nowrap;}
.filter-date{height:36px;border:1px solid var(--border);border-radius:var(--radius-sm);padding:0 12px;font-size:var(--font-sm);color:var(--text-primary);outline:none;background:#fff;width:150px;}.filter-date:focus{border-color:var(--primary);}
.filter-select{height:36px;border:1px solid var(--border);border-radius:var(--radius-sm);padding:0 28px 0 12px;font-size:var(--font-sm);color:var(--text-primary);outline:none;background:#fff url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6'%3E%3Cpath d='M0 0l5 6 5-6z' fill='%23999'/%3E%3C/svg%3E") no-repeat right 10px center;appearance:none;cursor:pointer;min-width:140px;}
.filter-separator{color:var(--text-placeholder);font-size:var(--font-sm);}
.btn{height:36px;padding:0 16px;border-radius:var(--radius-sm);font-size:var(--font-sm);cursor:pointer;border:none;transition:all .2s;display:inline-flex;align-items:center;gap:6px;}
.btn-primary{background:var(--primary);color:#fff;}.btn-primary:hover{background:#40a9ff;}
.btn-default{background:#fff;color:var(--text-primary);border:1px solid var(--border);}.btn-default:hover{color:var(--primary);border-color:var(--primary);}
.action-bar{display:flex;align-items:center;gap:12px;margin-bottom:16px;}
.table-card{background:#fff;border-radius:var(--radius-md);box-shadow:var(--shadow-sm);overflow:hidden;}
.table-card__content{overflow-x:auto;-webkit-overflow-scrolling:touch;}
table{width:100%;border-collapse:collapse;min-width:900px;}
thead th{background:#FAFAFA;padding:12px 14px;text-align:center;font-size:var(--font-xs);color:var(--text-secondary);font-weight:500;border-bottom:1px solid var(--border);border-right:1px solid var(--border);white-space:nowrap;}
thead th:last-child{border-right:none;}
tbody td{padding:12px 14px;font-size:var(--font-xs);color:var(--text-primary);border-bottom:1px solid var(--border);text-align:center;white-space:nowrap;}
tbody tr:last-child td{border-bottom:none;}
tbody tr:hover{background:#F8FBFF;}
.danger-text{color:var(--danger);font-weight:500;}
.pagination{display:flex;align-items:center;justify-content:flex-end;padding:16px 24px;gap:8px;border-top:1px solid var(--border);}
.pagination span{font-size:var(--font-sm);color:var(--text-secondary);}
.page-btn{width:32px;height:32px;border:1px solid var(--border);border-radius:var(--radius-sm);background:#fff;cursor:pointer;font-size:var(--font-sm);display:inline-flex;align-items:center;justify-content:center;transition:all .2s;}
.page-btn:hover,.page-btn.active{background:var(--primary);color:#fff;border-color:var(--primary);}
</style>
</head>
<body>
<div class="top-bar">
<div class="top-bar__logo"><svg viewBox="0 0 28 28" fill="none"><rect width="28" height="28" rx="6" fill="#1890FF"/><path d="M7 14h14M14 7v14" stroke="#fff" stroke-width="2.5" stroke-linecap="round"/></svg> 健康监测</div>
<nav class="top-bar__nav">
<a href="../archive-personal.html">档案</a>
<a href="../health-checkup/survey-category.html">健康排查</a>
<a href="../wearable/tool-manage.html">穿戴监测</a>
<a href="../weight/scale-device.html">体重监测</a>
<a href="../environment/indoor-device-list.html" class="active">环境监测</a>
<a href="../exception-dirty.html">异常事件</a>
</nav>
<div class="top-bar__right">
<a class="btn-back" href="../../../index.html"><svg width="16" height="16" viewBox="0 0 16 16" fill="none"><path d="M10 3L5 8l5 5" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/></svg> 返回首页</a>
<div class="avatar"></div>
<span style="color:rgba(255,255,255,0.65);">系统管理员 ▾</span>
</div>
</div>
<aside class="sidebar">
<div class="sidebar-menu__title">环境监测</div>
<div class="sidebar-subgroup">
<div class="sidebar-subgroup__header" onclick="toggleSubgroup(this)"><svg class="arrow" viewBox="0 0 12 12"><path d="M4 2l4 4-4 4" fill="none" stroke-width="1.5" stroke-linecap="round"/></svg> 室内空气</div>
<div class="sidebar-subgroup__body">
<a href="indoor-device-list.html" class="sidebar-item">设备列表</a>
<a href="indoor-device-category.html" class="sidebar-item">设备分类</a>
<a href="indoor-data-monitor.html" class="sidebar-item">数据监测</a>
<a href="indoor-exception-alarm.html" class="sidebar-item">异常报警</a>
<a href="indoor-app-record.html" class="sidebar-item">应用记录</a>
<a href="indoor-history-data.html" class="sidebar-item">历史数据</a>
</div>
</div>
<div class="sidebar-subgroup open">
<div class="sidebar-subgroup__header" onclick="toggleSubgroup(this)"><svg class="arrow" viewBox="0 0 12 12"><path d="M4 2l4 4-4 4" fill="none" stroke-width="1.5" stroke-linecap="round"/></svg> 室外空气</div>
<div class="sidebar-subgroup__body">
<a href="outdoor-device-list.html" class="sidebar-item">设备列表</a>
<a href="outdoor-device-category.html" class="sidebar-item">设备分类</a>
<a href="outdoor-data-monitor.html" class="sidebar-item">数据监测</a>
<a href="outdoor-exception-alarm.html" class="sidebar-item">异常报警</a>
<a href="outdoor-app-record.html" class="sidebar-item">应用记录</a>
<a href="outdoor-history-data.html" class="sidebar-item active">历史数据</a>
</div>
</div>
<div class="sidebar-subgroup">
<div class="sidebar-subgroup__header" onclick="toggleSubgroup(this)"><svg class="arrow" viewBox="0 0 12 12"><path d="M4 2l4 4-4 4" fill="none" stroke-width="1.5" stroke-linecap="round"/></svg> 水质监测</div>
<div class="sidebar-subgroup__body">
<a href="water-device-list.html" class="sidebar-item">设备列表</a>
<a href="water-device-category.html" class="sidebar-item">设备分类</a>
<a href="water-data-monitor.html" class="sidebar-item">数据监测</a>
<a href="water-exception-alarm.html" class="sidebar-item">异常报警</a>
<a href="water-app-record.html" class="sidebar-item">应用记录</a>
<a href="water-history-data.html" class="sidebar-item">历史数据</a>
</div>
</div>
<div class="sidebar-subgroup">
<div class="sidebar-subgroup__header" onclick="toggleSubgroup(this)"><svg class="arrow" viewBox="0 0 12 12"><path d="M4 2l4 4-4 4" fill="none" stroke-width="1.5" stroke-linecap="round"/></svg> 花粉监测</div>
<div class="sidebar-subgroup__body">
<a href="pollen-device-list.html" class="sidebar-item">设备列表</a>
<a href="pollen-device-category.html" class="sidebar-item">设备分类</a>
<a href="pollen-data-monitor.html" class="sidebar-item">数据监测</a>
<a href="pollen-exception-alarm.html" class="sidebar-item">异常报警</a>
<a href="pollen-app-record.html" class="sidebar-item">应用记录</a>
<a href="pollen-history-data.html" class="sidebar-item">历史数据</a>
<a href="pollen-knowledge.html" class="sidebar-item">知识科普</a>
</div>
</div>
</aside>
<main class="main">
<div class="page-header">
<a class="page-header__back" href="outdoor-history-data.html"><svg width="14" height="14" viewBox="0 0 16 16" fill="none"><path d="M10 3L5 8l5 5" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/></svg> 返回</a>
<span class="page-header__title">异常数据详情</span>
</div>
<div class="info-card">
<div class="info-card__item"><span class="info-card__label">设备名称</span><span class="info-card__value">空气质量监测站-A01</span></div>
<div class="info-card__item"><span class="info-card__label">设备编码</span><span class="info-card__value">OA-2024-001</span></div>
<div class="info-card__item"><span class="info-card__label">所属单位</span><span class="info-card__value">采油一厂</span></div>
<div class="info-card__item"><span class="info-card__label">设备位置</span><span class="info-card__value">厂区东门入口</span></div>
<div class="info-card__item"><span class="info-card__label">监测日期</span><span class="info-card__value">2026-03-01 ~ 2026-05-15</span></div>
<div class="info-card__item"><span class="info-card__label">监测时长</span><span class="info-card__value">76 天</span></div>
</div>
<div class="filter-bar">
<div class="filter-item"><label>监测日期</label><input class="filter-date" type="date" value="2026-05-01"><span class="filter-separator"></span><input class="filter-date" type="date" value="2026-05-15"></div>
<div class="filter-item"><label>监测类型</label>
<select class="filter-select"><option value="">全部</option><option>温度</option><option>湿度</option><option>太阳辐射</option><option>PM2.5</option><option>PM10</option><option>照度</option><option>风速</option></select>
</div>
<button class="btn btn-primary">查询</button>
<button class="btn btn-default">重置</button>
</div>
<div class="action-bar"><button class="btn btn-default">导出列表数据</button></div>
<div class="table-card">
<div class="table-card__content">
<table>
<thead>
<tr>
<th style="min-width:90px;">监测类型</th>
<th style="min-width:90px;">单位</th>
<th style="min-width:80px;">阈值上限</th>
<th style="min-width:80px;">阈值下限</th>
<th style="min-width:80px;">异常值</th>
<th style="min-width:160px;">报警时间</th>
</tr>
</thead>
<tbody>
<tr><td>PM2.5</td><td>μg/m³</td><td>75</td><td></td><td class="danger-text">92</td><td>2026-05-15 07:30:18</td></tr>
<tr><td>PM10</td><td>μg/m³</td><td>150</td><td></td><td class="danger-text">186</td><td>2026-05-14 16:45:22</td></tr>
<tr><td>温度</td><td></td><td>40</td><td>-10</td><td class="danger-text">41.2</td><td>2026-05-13 14:20:33</td></tr>
<tr><td>风速</td><td>m/s</td><td>10</td><td></td><td class="danger-text">12.5</td><td>2026-05-12 09:15:45</td></tr>
<tr><td>太阳辐射</td><td>W/m²</td><td>1200</td><td></td><td class="danger-text">1350</td><td>2026-05-11 13:08:12</td></tr>
<tr><td>PM2.5</td><td>μg/m³</td><td>75</td><td></td><td class="danger-text">88</td><td>2026-05-10 08:42:56</td></tr>
<tr><td>照度</td><td>lm/m²</td><td>100000</td><td></td><td class="danger-text">108000</td><td>2026-05-09 12:30:40</td></tr>
<tr><td>湿度</td><td>%</td><td>90</td><td>10</td><td class="danger-text">93</td><td>2026-05-08 06:25:18</td></tr>
</tbody>
</table>
</div>
<div class="pagination"><span>共 8 条</span><button class="page-btn active">1</button></div>
</div>
</main>
<script>
function toggleSubgroup(h){h.parentElement.classList.toggle('open');}
(function(){var a=document.querySelector('.sidebar-item.active');if(!a)return;var s=a.closest('.sidebar-subgroup');if(s)s.classList.add('open');})();
</script>
</body>
</html>
@@ -3,7 +3,7 @@
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>健康监测 - 历史数据 | 健康长庆原型</title>
<title>室外空气 - 历史数据 | 健康长庆原型</title>
<style>
*{box-sizing:border-box;margin:0;padding:0;}
body{font-family:-apple-system,BlinkMacSystemFont,'PingFang SC','Microsoft YaHei',sans-serif;background:#F5F7FA;color:#333;min-width:1280px;}
@@ -18,8 +18,7 @@
.top-bar__logo{display:flex;align-items:center;gap:8px;color:#fff;font-size:var(--font-lg);font-weight:600;white-space:nowrap;width:240px;flex-shrink:0;}
.top-bar__logo svg{width:28px;height:28px;}
.top-bar__right{display:flex;align-items:center;gap:16px;color:rgba(255,255,255,0.65);font-size:var(--font-sm);}
.btn-back{color:rgba(255,255,255,0.65);cursor:pointer;display:flex;align-items:center;gap:4px;text-decoration:none;}
.btn-back:hover{color:#fff;}
.btn-back{color:rgba(255,255,255,0.65);cursor:pointer;display:flex;align-items:center;gap:4px;text-decoration:none;}.btn-back:hover{color:#fff;}
.avatar{width:32px;height:32px;border-radius:50%;background:#1890FF;display:flex;align-items:center;justify-content:center;color:#fff;font-size:var(--font-sm);cursor:pointer;}
.top-bar__nav{display:flex;align-items:center;gap:4px;flex:1;}
.top-bar__nav a{color:rgba(255,255,255,0.65);text-decoration:none;padding:6px 16px;border-radius:var(--radius-sm);font-size:var(--font-sm);transition:all .2s;}
@@ -40,9 +39,30 @@
.sidebar-subgroup.open>.sidebar-subgroup__body{display:block;}
.sidebar-subgroup__body .sidebar-item{padding-left:36px;font-size:12px;}
.main{margin-left:240px;margin-top:56px;padding:24px;min-height:calc(100vh - 56px);}
.page-placeholder{display:flex;flex-direction:column;align-items:center;justify-content:center;height:calc(100vh - 56px - 48px);color:var(--text-placeholder);gap:12px;}
.page-placeholder svg{opacity:.25;}
.page-placeholder p{font-size:var(--font-base);}
.filter-bar{background:#fff;border-radius:var(--radius-md);padding:20px 24px;margin-bottom:16px;box-shadow:var(--shadow-sm);display:flex;align-items:center;gap:16px;flex-wrap:wrap;}
.filter-item{display:flex;align-items:center;gap:8px;}
.filter-item label{font-size:var(--font-sm);color:var(--text-secondary);white-space:nowrap;}
.filter-input{height:36px;border:1px solid var(--border);border-radius:var(--radius-sm);padding:0 12px;font-size:var(--font-sm);color:var(--text-primary);outline:none;background:#fff;min-width:180px;}.filter-input:focus{border-color:var(--primary);}
.filter-select{height:36px;border:1px solid var(--border);border-radius:var(--radius-sm);padding:0 28px 0 12px;font-size:var(--font-sm);color:var(--text-primary);outline:none;background:#fff url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6'%3E%3Cpath d='M0 0l5 6 5-6z' fill='%23999'/%3E%3C/svg%3E") no-repeat right 10px center;appearance:none;cursor:pointer;min-width:140px;}
.btn{height:36px;padding:0 16px;border-radius:var(--radius-sm);font-size:var(--font-sm);cursor:pointer;border:none;transition:all .2s;display:inline-flex;align-items:center;gap:6px;}
.btn-primary{background:var(--primary);color:#fff;}.btn-primary:hover{background:#40a9ff;}
.btn-default{background:#fff;color:var(--text-primary);border:1px solid var(--border);}.btn-default:hover{color:var(--primary);border-color:var(--primary);}
.action-bar{display:flex;align-items:center;gap:12px;margin-bottom:16px;}
.table-card{background:#fff;border-radius:var(--radius-md);box-shadow:var(--shadow-sm);overflow:hidden;}
.table-card__content{overflow-x:auto;-webkit-overflow-scrolling:touch;}
table{width:100%;border-collapse:collapse;min-width:1000px;}
thead th{background:#FAFAFA;padding:12px 14px;text-align:center;font-size:var(--font-xs);color:var(--text-secondary);font-weight:500;border-bottom:1px solid var(--border);border-right:1px solid var(--border);white-space:nowrap;}
thead th:last-child{border-right:none;}
thead th.th-left{text-align:left;}
tbody td{padding:12px 14px;font-size:var(--font-xs);color:var(--text-primary);border-bottom:1px solid var(--border);text-align:center;white-space:nowrap;}
tbody td.td-left{text-align:left;}
tbody tr:last-child td{border-bottom:none;}
tbody tr:hover{background:#F8FBFF;}
.link-btn{color:var(--primary);cursor:pointer;text-decoration:none;font-size:var(--font-xs);}.link-btn:hover{text-decoration:underline;}
.pagination{display:flex;align-items:center;justify-content:flex-end;padding:16px 24px;gap:8px;border-top:1px solid var(--border);}
.pagination span{font-size:var(--font-sm);color:var(--text-secondary);}
.page-btn{width:32px;height:32px;border:1px solid var(--border);border-radius:var(--radius-sm);background:#fff;cursor:pointer;font-size:var(--font-sm);display:inline-flex;align-items:center;justify-content:center;transition:all .2s;}
.page-btn:hover,.page-btn.active{background:var(--primary);color:#fff;border-color:var(--primary);}
</style>
</head>
<body>
@@ -57,10 +77,7 @@
<a href="../exception-dirty.html">异常事件</a>
</nav>
<div class="top-bar__right">
<a class="btn-back" href="../../../index.html">
<svg width="16" height="16" viewBox="0 0 16 16" fill="none"><path d="M10 3L5 8l5 5" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/></svg>
返回首页
</a>
<a class="btn-back" href="../../../index.html"><svg width="16" height="16" viewBox="0 0 16 16" fill="none"><path d="M10 3L5 8l5 5" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/></svg> 返回首页</a>
<div class="avatar"></div>
<span style="color:rgba(255,255,255,0.65);">系统管理员 ▾</span>
</div>
@@ -114,11 +131,91 @@
</div>
</aside>
<main class="main">
<div class="page-placeholder">
<svg width="64" height="64" viewBox="0 0 64 64" fill="none"><rect x="8" y="8" width="48" height="48" rx="8" stroke="#ccc" stroke-width="2"/><path d="M20 32h24M32 20v24" stroke="#ccc" stroke-width="2" stroke-linecap="round"/></svg>
<p>历史数据</p>
<div class="filter-bar">
<div class="filter-item"><label>设备名称</label><input class="filter-input" placeholder="请输入设备名称"></div>
<div class="filter-item"><label>设备编码</label><input class="filter-input" placeholder="请输入设备编码"></div>
<div class="filter-item"><label>所属单位</label>
<select class="filter-select"><option value="">全部</option><option>采油一厂</option><option>采油二厂</option><option>采油三厂</option></select>
</div>
<button class="btn btn-primary">查询</button>
<button class="btn btn-default">重置</button>
</div>
<div class="action-bar"><button class="btn btn-default">导出列表数据</button></div>
<div class="table-card">
<div class="table-card__content">
<table>
<thead>
<tr>
<th class="th-left" style="min-width:150px;">设备名称</th>
<th style="min-width:110px;">设备编码</th>
<th style="min-width:90px;">所属单位</th>
<th style="min-width:130px;">设备位置</th>
<th style="min-width:180px;">监测日期</th>
<th style="min-width:90px;">监测时长(天)</th>
<th style="min-width:80px;">监测数据</th>
<th style="min-width:80px;">异常数据</th>
</tr>
</thead>
<tbody>
<tr>
<td class="td-left">空气质量监测站-A01</td>
<td>OA-2024-001</td>
<td>采油一厂</td>
<td>厂区东门入口</td>
<td>2026-03-01 ~ 2026-05-15</td>
<td>76</td>
<td><a class="link-btn" href="outdoor-history-monitor-detail.html">查看</a></td>
<td><a class="link-btn" href="outdoor-history-alarm-detail.html">查看</a></td>
</tr>
<tr>
<td class="td-left">PM10检测仪-B02</td>
<td>OA-2024-002</td>
<td>采油一厂</td>
<td>生产区北侧围墙</td>
<td>2026-02-10 ~ 2026-05-15</td>
<td>94</td>
<td><a class="link-btn" href="outdoor-history-monitor-detail.html">查看</a></td>
<td><a class="link-btn" href="outdoor-history-alarm-detail.html">查看</a></td>
</tr>
<tr>
<td class="td-left">风速风向仪-C03</td>
<td>OA-2024-003</td>
<td>采油二厂</td>
<td>办公楼楼顶</td>
<td>2026-04-01 ~ 2026-05-15</td>
<td>45</td>
<td><a class="link-btn" href="outdoor-history-monitor-detail.html">查看</a></td>
<td><a class="link-btn" href="outdoor-history-alarm-detail.html">查看</a></td>
</tr>
<tr>
<td class="td-left">光照辐射监测站-D01</td>
<td>OA-2024-004</td>
<td>采油二厂</td>
<td>厂区中心广场</td>
<td>2026-01-15 ~ 2026-05-15</td>
<td>120</td>
<td><a class="link-btn" href="outdoor-history-monitor-detail.html">查看</a></td>
<td><a class="link-btn" href="outdoor-history-alarm-detail.html">查看</a></td>
</tr>
<tr>
<td class="td-left">空气质量监测站-A05</td>
<td>OA-2024-005</td>
<td>采油三厂</td>
<td>厂区西门停车场</td>
<td>2026-03-20 ~ 2026-05-15</td>
<td>56</td>
<td><a class="link-btn" href="outdoor-history-monitor-detail.html">查看</a></td>
<td><a class="link-btn" href="outdoor-history-alarm-detail.html">查看</a></td>
</tr>
</tbody>
</table>
</div>
<div class="pagination"><span>共 5 条</span><button class="page-btn active">1</button></div>
</div>
</main>
<script>function toggleSubgroup(h){h.parentElement.classList.toggle('open');}(function(){var a=document.querySelector('.sidebar-item.active');if(!a)return;var s=a.closest('.sidebar-subgroup');if(s)s.classList.add('open');})();</script>
<script>
function toggleSubgroup(h){h.parentElement.classList.toggle('open');}
(function(){var a=document.querySelector('.sidebar-item.active');if(!a)return;var s=a.closest('.sidebar-subgroup');if(s)s.classList.add('open');})();
</script>
</body>
</html>
</html>
@@ -0,0 +1,208 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>室外空气 - 监测数据详情 | 健康长庆原型</title>
<style>
*{box-sizing:border-box;margin:0;padding:0;}
body{font-family:-apple-system,BlinkMacSystemFont,'PingFang SC','Microsoft YaHei',sans-serif;background:#F5F7FA;color:#333;min-width:1280px;}
:root{
--primary:#1890FF;--primary-light:#E6F7FF;--success:#52C41A;--warning:#FAAD14;--danger:#FF4D4F;
--text-primary:#333;--text-secondary:#666;--text-placeholder:#999;--border:#E8E8E8;--background:#F5F7FA;
--font-xs:11px;--font-sm:13px;--font-base:15px;--font-lg:17px;
--radius-sm:4px;--radius-md:8px;--radius-lg:12px;
--shadow-sm:0 1px 4px rgba(0,0,0,0.08);
}
.top-bar{display:flex;align-items:center;height:56px;background:#001529;padding:0 24px;position:fixed;top:0;left:0;right:0;z-index:100;}
.top-bar__logo{display:flex;align-items:center;gap:8px;color:#fff;font-size:var(--font-lg);font-weight:600;white-space:nowrap;width:240px;flex-shrink:0;}
.top-bar__logo svg{width:28px;height:28px;}
.top-bar__right{display:flex;align-items:center;gap:16px;color:rgba(255,255,255,0.65);font-size:var(--font-sm);}
.btn-back{color:rgba(255,255,255,0.65);cursor:pointer;display:flex;align-items:center;gap:4px;text-decoration:none;}.btn-back:hover{color:#fff;}
.avatar{width:32px;height:32px;border-radius:50%;background:#1890FF;display:flex;align-items:center;justify-content:center;color:#fff;font-size:var(--font-sm);cursor:pointer;}
.top-bar__nav{display:flex;align-items:center;gap:4px;flex:1;}
.top-bar__nav a{color:rgba(255,255,255,0.65);text-decoration:none;padding:6px 16px;border-radius:var(--radius-sm);font-size:var(--font-sm);transition:all .2s;}
.top-bar__nav a:hover{color:#fff;background:rgba(255,255,255,0.08);}
.top-bar__nav a.active{color:#fff;background:var(--primary);}
.sidebar{position:fixed;top:56px;left:0;bottom:0;width:240px;background:#001529;overflow-y:auto;z-index:90;padding-top:8px;}
.sidebar-menu__title{color:rgba(255,255,255,0.35);font-size:var(--font-xs);padding:16px 24px 8px;letter-spacing:.5px;}
.sidebar-item{display:flex;align-items:center;gap:8px;padding:10px 24px;color:rgba(255,255,255,0.65);font-size:var(--font-sm);cursor:pointer;transition:all .15s;text-decoration:none;}
.sidebar-item:hover{color:#fff;background:rgba(255,255,255,0.06);}
.sidebar-item.active{color:#fff;background:var(--primary);}
.sidebar-subgroup__header{display:flex;align-items:center;gap:6px;padding:10px 24px;color:rgba(255,255,255,0.65);font-size:var(--font-sm);cursor:pointer;transition:all .15s;user-select:none;}
.sidebar-subgroup__header:hover{color:rgba(255,255,255,0.85);background:rgba(255,255,255,0.04);}
.sidebar-subgroup__header .arrow{width:10px;height:10px;transition:transform .2s;flex-shrink:0;}
.sidebar-subgroup__header .arrow path{stroke:rgba(255,255,255,0.45);}
.sidebar-subgroup.open>.sidebar-subgroup__header{color:rgba(255,255,255,0.85);}
.sidebar-subgroup.open>.sidebar-subgroup__header .arrow{transform:rotate(90deg);}
.sidebar-subgroup__body{display:none;padding-left:16px;}
.sidebar-subgroup.open>.sidebar-subgroup__body{display:block;}
.sidebar-subgroup__body .sidebar-item{padding-left:36px;font-size:12px;}
.main{margin-left:240px;margin-top:56px;padding:24px;min-height:calc(100vh - 56px);}
.page-header{display:flex;align-items:center;gap:12px;margin-bottom:16px;}
.page-header__back{display:flex;align-items:center;gap:4px;color:var(--text-secondary);font-size:var(--font-sm);cursor:pointer;text-decoration:none;}.page-header__back:hover{color:var(--primary);}
.page-header__title{font-size:var(--font-lg);font-weight:600;color:var(--text-primary);}
.info-card{background:#fff;border-radius:var(--radius-md);padding:20px 24px;margin-bottom:16px;box-shadow:var(--shadow-sm);display:grid;grid-template-columns:repeat(3,1fr);gap:16px 24px;}
.info-card__item{display:flex;align-items:baseline;gap:8px;min-width:0;}
.info-card__label{font-size:var(--font-xs);color:var(--text-placeholder);white-space:nowrap;flex-shrink:0;}
.info-card__value{font-size:var(--font-sm);color:var(--text-primary);font-weight:500;word-break:break-all;}
.filter-bar{background:#fff;border-radius:var(--radius-md);padding:20px 24px;margin-bottom:16px;box-shadow:var(--shadow-sm);display:flex;align-items:center;gap:16px;flex-wrap:wrap;}
.filter-item{display:flex;align-items:center;gap:8px;}
.filter-item label{font-size:var(--font-sm);color:var(--text-secondary);white-space:nowrap;}
.filter-date{height:36px;border:1px solid var(--border);border-radius:var(--radius-sm);padding:0 12px;font-size:var(--font-sm);color:var(--text-primary);outline:none;background:#fff;width:150px;}.filter-date:focus{border-color:var(--primary);}
.filter-separator{color:var(--text-placeholder);font-size:var(--font-sm);}
.btn{height:36px;padding:0 16px;border-radius:var(--radius-sm);font-size:var(--font-sm);cursor:pointer;border:none;transition:all .2s;display:inline-flex;align-items:center;gap:6px;}
.btn-primary{background:var(--primary);color:#fff;}.btn-primary:hover{background:#40a9ff;}
.btn-default{background:#fff;color:var(--text-primary);border:1px solid var(--border);}.btn-default:hover{color:var(--primary);border-color:var(--primary);}
.action-bar{display:flex;align-items:center;gap:12px;margin-bottom:16px;}
.table-card{background:#fff;border-radius:var(--radius-md);box-shadow:var(--shadow-sm);overflow:hidden;}
.table-card__content{overflow-x:auto;-webkit-overflow-scrolling:touch;}
table{width:100%;border-collapse:collapse;min-width:1000px;}
thead th{background:#FAFAFA;padding:12px 14px;text-align:center;font-size:var(--font-xs);color:var(--text-secondary);font-weight:500;border-bottom:1px solid var(--border);border-right:1px solid var(--border);white-space:nowrap;}
thead th:last-child{border-right:none;}
tbody td{padding:12px 14px;font-size:var(--font-xs);color:var(--text-primary);border-bottom:1px solid var(--border);text-align:center;white-space:nowrap;}
tbody tr:last-child td{border-bottom:none;}
tbody tr:hover{background:#F8FBFF;}
.pagination{display:flex;align-items:center;justify-content:flex-end;padding:16px 24px;gap:8px;border-top:1px solid var(--border);}
.pagination span{font-size:var(--font-sm);color:var(--text-secondary);}
.page-btn{width:32px;height:32px;border:1px solid var(--border);border-radius:var(--radius-sm);background:#fff;cursor:pointer;font-size:var(--font-sm);display:inline-flex;align-items:center;justify-content:center;transition:all .2s;}
.page-btn:hover,.page-btn.active{background:var(--primary);color:#fff;border-color:var(--primary);}
.aqi-tag{display:inline-block;padding:2px 10px;border-radius:10px;font-size:var(--font-xs);font-weight:500;}
.aqi-tag--excellent{background:#F6FFED;color:#52C41A;}
.aqi-tag--good{background:#E6FFFB;color:#13C2C2;}
.aqi-tag--light{background:#FFFBE6;color:#FAAD14;}
.aqi-tag--moderate{background:#FFF1F0;color:#FA541C;}
.aqi-tag--heavy{background:#FFF1F0;color:#FF4D4F;}
.aqi-tag--severe{background:#F9F0FF;color:#722ED1;}
</style>
</head>
<body>
<div class="top-bar">
<div class="top-bar__logo"><svg viewBox="0 0 28 28" fill="none"><rect width="28" height="28" rx="6" fill="#1890FF"/><path d="M7 14h14M14 7v14" stroke="#fff" stroke-width="2.5" stroke-linecap="round"/></svg> 健康监测</div>
<nav class="top-bar__nav">
<a href="../archive-personal.html">档案</a>
<a href="../health-checkup/survey-category.html">健康排查</a>
<a href="../wearable/tool-manage.html">穿戴监测</a>
<a href="../weight/scale-device.html">体重监测</a>
<a href="../environment/indoor-device-list.html" class="active">环境监测</a>
<a href="../exception-dirty.html">异常事件</a>
</nav>
<div class="top-bar__right">
<a class="btn-back" href="../../../index.html"><svg width="16" height="16" viewBox="0 0 16 16" fill="none"><path d="M10 3L5 8l5 5" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/></svg> 返回首页</a>
<div class="avatar"></div>
<span style="color:rgba(255,255,255,0.65);">系统管理员 ▾</span>
</div>
</div>
<aside class="sidebar">
<div class="sidebar-menu__title">环境监测</div>
<div class="sidebar-subgroup">
<div class="sidebar-subgroup__header" onclick="toggleSubgroup(this)"><svg class="arrow" viewBox="0 0 12 12"><path d="M4 2l4 4-4 4" fill="none" stroke-width="1.5" stroke-linecap="round"/></svg> 室内空气</div>
<div class="sidebar-subgroup__body">
<a href="indoor-device-list.html" class="sidebar-item">设备列表</a>
<a href="indoor-device-category.html" class="sidebar-item">设备分类</a>
<a href="indoor-data-monitor.html" class="sidebar-item">数据监测</a>
<a href="indoor-exception-alarm.html" class="sidebar-item">异常报警</a>
<a href="indoor-app-record.html" class="sidebar-item">应用记录</a>
<a href="indoor-history-data.html" class="sidebar-item">历史数据</a>
</div>
</div>
<div class="sidebar-subgroup open">
<div class="sidebar-subgroup__header" onclick="toggleSubgroup(this)"><svg class="arrow" viewBox="0 0 12 12"><path d="M4 2l4 4-4 4" fill="none" stroke-width="1.5" stroke-linecap="round"/></svg> 室外空气</div>
<div class="sidebar-subgroup__body">
<a href="outdoor-device-list.html" class="sidebar-item">设备列表</a>
<a href="outdoor-device-category.html" class="sidebar-item">设备分类</a>
<a href="outdoor-data-monitor.html" class="sidebar-item">数据监测</a>
<a href="outdoor-exception-alarm.html" class="sidebar-item">异常报警</a>
<a href="outdoor-app-record.html" class="sidebar-item">应用记录</a>
<a href="outdoor-history-data.html" class="sidebar-item active">历史数据</a>
</div>
</div>
<div class="sidebar-subgroup">
<div class="sidebar-subgroup__header" onclick="toggleSubgroup(this)"><svg class="arrow" viewBox="0 0 12 12"><path d="M4 2l4 4-4 4" fill="none" stroke-width="1.5" stroke-linecap="round"/></svg> 水质监测</div>
<div class="sidebar-subgroup__body">
<a href="water-device-list.html" class="sidebar-item">设备列表</a>
<a href="water-device-category.html" class="sidebar-item">设备分类</a>
<a href="water-data-monitor.html" class="sidebar-item">数据监测</a>
<a href="water-exception-alarm.html" class="sidebar-item">异常报警</a>
<a href="water-app-record.html" class="sidebar-item">应用记录</a>
<a href="water-history-data.html" class="sidebar-item">历史数据</a>
</div>
</div>
<div class="sidebar-subgroup">
<div class="sidebar-subgroup__header" onclick="toggleSubgroup(this)"><svg class="arrow" viewBox="0 0 12 12"><path d="M4 2l4 4-4 4" fill="none" stroke-width="1.5" stroke-linecap="round"/></svg> 花粉监测</div>
<div class="sidebar-subgroup__body">
<a href="pollen-device-list.html" class="sidebar-item">设备列表</a>
<a href="pollen-device-category.html" class="sidebar-item">设备分类</a>
<a href="pollen-data-monitor.html" class="sidebar-item">数据监测</a>
<a href="pollen-exception-alarm.html" class="sidebar-item">异常报警</a>
<a href="pollen-app-record.html" class="sidebar-item">应用记录</a>
<a href="pollen-history-data.html" class="sidebar-item">历史数据</a>
<a href="pollen-knowledge.html" class="sidebar-item">知识科普</a>
</div>
</div>
</aside>
<main class="main">
<div class="page-header">
<a class="page-header__back" href="outdoor-history-data.html"><svg width="14" height="14" viewBox="0 0 16 16" fill="none"><path d="M10 3L5 8l5 5" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/></svg> 返回</a>
<span class="page-header__title">监测数据详情</span>
</div>
<div class="info-card">
<div class="info-card__item"><span class="info-card__label">设备名称</span><span class="info-card__value">空气质量监测站-A01</span></div>
<div class="info-card__item"><span class="info-card__label">设备编码</span><span class="info-card__value">OA-2024-001</span></div>
<div class="info-card__item"><span class="info-card__label">所属单位</span><span class="info-card__value">采油一厂</span></div>
<div class="info-card__item"><span class="info-card__label">设备位置</span><span class="info-card__value">厂区东门入口</span></div>
<div class="info-card__item"><span class="info-card__label">监测日期</span><span class="info-card__value">2026-03-01 ~ 2026-05-15</span></div>
<div class="info-card__item"><span class="info-card__label">监测时长</span><span class="info-card__value">76 天</span></div>
</div>
<div class="filter-bar">
<div class="filter-item"><label>监测日期</label><input class="filter-date" type="date" value="2026-05-01"><span class="filter-separator"></span><input class="filter-date" type="date" value="2026-05-15"></div>
<button class="btn btn-primary">查询</button>
<button class="btn btn-default">重置</button>
</div>
<div class="action-bar"><button class="btn btn-default">导出列表数据</button></div>
<div class="table-card">
<div class="table-card__content">
<table>
<thead>
<tr>
<th style="min-width:160px;">监测时间</th>
<th style="min-width:90px;">温度(℃)</th>
<th style="min-width:90px;">湿度(%)</th>
<th style="min-width:110px;">太阳辐射(W/m²)</th>
<th style="min-width:110px;">PM2.5(μg/m³)</th>
<th style="min-width:110px;">PM10(μg/m³)</th>
<th style="min-width:110px;">照度(lm/m²)</th>
<th style="min-width:100px;">风速(m/s)</th>
<th style="min-width:100px;">空气质量指数</th>
</tr>
</thead>
<tbody>
<tr><td>2026-05-15 08:00:00</td><td>26.5</td><td>45</td><td>520</td><td>42</td><td>68</td><td>35000</td><td>2.8</td><td><span class="aqi-tag aqi-tag--good"></span></td></tr>
<tr><td>2026-05-15 07:00:00</td><td>25.1</td><td>48</td><td>380</td><td>38</td><td>62</td><td>28000</td><td>3.2</td><td><span class="aqi-tag aqi-tag--excellent"></span></td></tr>
<tr><td>2026-05-15 06:00:00</td><td>23.8</td><td>52</td><td>210</td><td>35</td><td>55</td><td>18000</td><td>2.5</td><td><span class="aqi-tag aqi-tag--excellent"></span></td></tr>
<tr><td>2026-05-14 23:00:00</td><td>21.2</td><td>58</td><td>0</td><td>28</td><td>45</td><td>0</td><td>1.8</td><td><span class="aqi-tag aqi-tag--excellent"></span></td></tr>
<tr><td>2026-05-14 22:00:00</td><td>22.0</td><td>56</td><td>0</td><td>30</td><td>48</td><td>0</td><td>2.1</td><td><span class="aqi-tag aqi-tag--excellent"></span></td></tr>
<tr><td>2026-05-14 21:00:00</td><td>23.5</td><td>53</td><td>0</td><td>33</td><td>52</td><td>0</td><td>2.4</td><td><span class="aqi-tag aqi-tag--good"></span></td></tr>
<tr><td>2026-05-14 20:00:00</td><td>25.0</td><td>50</td><td>45</td><td>36</td><td>58</td><td>2500</td><td>2.6</td><td><span class="aqi-tag aqi-tag--good"></span></td></tr>
<tr><td>2026-05-14 19:00:00</td><td>26.8</td><td>47</td><td>120</td><td>40</td><td>65</td><td>8500</td><td>3.0</td><td><span class="aqi-tag aqi-tag--good"></span></td></tr>
<tr><td>2026-05-14 18:00:00</td><td>28.2</td><td>44</td><td>280</td><td>45</td><td>72</td><td>18000</td><td>3.5</td><td><span class="aqi-tag aqi-tag--light">轻度污染</span></td></tr>
<tr><td>2026-05-14 17:00:00</td><td>29.5</td><td>42</td><td>450</td><td>52</td><td>85</td><td>32000</td><td>4.1</td><td><span class="aqi-tag aqi-tag--moderate">中度污染</span></td></tr>
</tbody>
</table>
</div>
<div class="pagination">
<span>共 240 条</span>
<button class="page-btn active">1</button>
<button class="page-btn">2</button>
<button class="page-btn">3</button>
<span>...</span>
<button class="page-btn">24</button>
</div>
</div>
</main>
<script>
function toggleSubgroup(h){h.parentElement.classList.toggle('open');}
(function(){var a=document.querySelector('.sidebar-item.active');if(!a)return;var s=a.closest('.sidebar-subgroup');if(s)s.classList.add('open');})();
</script>
</body>
</html>
@@ -3,7 +3,7 @@
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>健康监测 - 应用记录 | 健康长庆原型</title>
<title>花粉监测 - 应用记录 | 健康长庆原型</title>
<style>
*{box-sizing:border-box;margin:0;padding:0;}
body{font-family:-apple-system,BlinkMacSystemFont,'PingFang SC','Microsoft YaHei',sans-serif;background:#F5F7FA;color:#333;min-width:1280px;}
@@ -18,8 +18,7 @@
.top-bar__logo{display:flex;align-items:center;gap:8px;color:#fff;font-size:var(--font-lg);font-weight:600;white-space:nowrap;width:240px;flex-shrink:0;}
.top-bar__logo svg{width:28px;height:28px;}
.top-bar__right{display:flex;align-items:center;gap:16px;color:rgba(255,255,255,0.65);font-size:var(--font-sm);}
.btn-back{color:rgba(255,255,255,0.65);cursor:pointer;display:flex;align-items:center;gap:4px;text-decoration:none;}
.btn-back:hover{color:#fff;}
.btn-back{color:rgba(255,255,255,0.65);cursor:pointer;display:flex;align-items:center;gap:4px;text-decoration:none;}.btn-back:hover{color:#fff;}
.avatar{width:32px;height:32px;border-radius:50%;background:#1890FF;display:flex;align-items:center;justify-content:center;color:#fff;font-size:var(--font-sm);cursor:pointer;}
.top-bar__nav{display:flex;align-items:center;gap:4px;flex:1;}
.top-bar__nav a{color:rgba(255,255,255,0.65);text-decoration:none;padding:6px 16px;border-radius:var(--radius-sm);font-size:var(--font-sm);transition:all .2s;}
@@ -40,9 +39,44 @@
.sidebar-subgroup.open>.sidebar-subgroup__body{display:block;}
.sidebar-subgroup__body .sidebar-item{padding-left:36px;font-size:12px;}
.main{margin-left:240px;margin-top:56px;padding:24px;min-height:calc(100vh - 56px);}
.page-placeholder{display:flex;flex-direction:column;align-items:center;justify-content:center;height:calc(100vh - 56px - 48px);color:var(--text-placeholder);gap:12px;}
.page-placeholder svg{opacity:.25;}
.page-placeholder p{font-size:var(--font-base);}
.filter-bar{background:#fff;border-radius:var(--radius-md);padding:20px 24px;margin-bottom:16px;box-shadow:var(--shadow-sm);display:flex;align-items:center;gap:16px;flex-wrap:wrap;}
.filter-item{display:flex;align-items:center;gap:8px;}
.filter-item label{font-size:var(--font-sm);color:var(--text-secondary);white-space:nowrap;}
.filter-input{height:36px;border:1px solid var(--border);border-radius:var(--radius-sm);padding:0 12px;font-size:var(--font-sm);color:var(--text-primary);outline:none;background:#fff;min-width:180px;}.filter-input:focus{border-color:var(--primary);}
.filter-select{height:36px;border:1px solid var(--border);border-radius:var(--radius-sm);padding:0 28px 0 12px;font-size:var(--font-sm);color:var(--text-primary);outline:none;background:#fff url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6'%3E%3Cpath d='M0 0l5 6 5-6z' fill='%23999'/%3E%3C/svg%3E") no-repeat right 10px center;appearance:none;cursor:pointer;min-width:140px;}
.btn{height:36px;padding:0 16px;border-radius:var(--radius-sm);font-size:var(--font-sm);cursor:pointer;border:none;transition:all .2s;display:inline-flex;align-items:center;gap:6px;}
.btn-primary{background:var(--primary);color:#fff;}.btn-primary:hover{background:#40a9ff;}
.btn-default{background:#fff;color:var(--text-primary);border:1px solid var(--border);}.btn-default:hover{color:var(--primary);border-color:var(--primary);}
.action-bar{display:flex;align-items:center;gap:12px;margin-bottom:16px;}
.table-card{background:#fff;border-radius:var(--radius-md);box-shadow:var(--shadow-sm);overflow:hidden;}
.table-card__content{overflow-x:auto;-webkit-overflow-scrolling:touch;}
table{width:100%;border-collapse:collapse;min-width:1500px;}
thead th{background:#FAFAFA;padding:12px 14px;text-align:center;font-size:var(--font-xs);color:var(--text-secondary);font-weight:500;border-bottom:1px solid var(--border);border-right:1px solid var(--border);white-space:nowrap;}
thead th:last-child{border-right:none;}
thead th.th-left{text-align:left;}
tbody td{padding:12px 14px;font-size:var(--font-xs);color:var(--text-primary);border-bottom:1px solid var(--border);text-align:center;white-space:nowrap;}
tbody td.td-left{text-align:left;}
tbody tr:last-child td{border-bottom:none;}
tbody tr:hover{background:#F8FBFF;}
thead tr:first-child th:nth-child(-n+2),tbody td:nth-child(-n+2){position:sticky;z-index:2;}
thead tr:first-child th:nth-child(-n+2){z-index:3;}
thead tr:first-child th:nth-child(1),tbody td:nth-child(1){left:0;}
thead tr:first-child th:nth-child(2),tbody td:nth-child(2){left:140px;}
tbody td:nth-child(-n+2){background:#fff;}
tbody tr:hover td:nth-child(-n+2){background:#F8FBFF;}
tbody td:nth-child(2),thead tr:first-child th:nth-child(2){box-shadow:2px 0 4px rgba(0,0,0,0.06);}
.th-sort{cursor:pointer;user-select:none;position:relative;padding-right:22px !important;}
.th-sort:hover{color:var(--primary);}
.th-sort .sort-icon{position:absolute;right:4px;top:50%;transform:translateY(-50%);display:flex;flex-direction:column;gap:1px;}
.th-sort .sort-icon .arrow-up,.th-sort .sort-icon .arrow-down{width:0;height:0;border-left:4px solid transparent;border-right:4px solid transparent;}
.th-sort .sort-icon .arrow-up{border-bottom:5px solid #ccc;}
.th-sort .sort-icon .arrow-down{border-top:5px solid #ccc;}
.th-sort.asc .sort-icon .arrow-up{border-bottom-color:var(--primary);}
.th-sort.desc .sort-icon .arrow-down{border-top-color:var(--primary);}
.pagination{display:flex;align-items:center;justify-content:flex-end;padding:16px 24px;gap:8px;border-top:1px solid var(--border);}
.pagination span{font-size:var(--font-sm);color:var(--text-secondary);}
.page-btn{width:32px;height:32px;border:1px solid var(--border);border-radius:var(--radius-sm);background:#fff;cursor:pointer;font-size:var(--font-sm);display:inline-flex;align-items:center;justify-content:center;transition:all .2s;}
.page-btn:hover,.page-btn.active{background:var(--primary);color:#fff;border-color:var(--primary);}
</style>
</head>
<body>
@@ -57,10 +91,7 @@
<a href="../exception-dirty.html">异常事件</a>
</nav>
<div class="top-bar__right">
<a class="btn-back" href="../../../index.html">
<svg width="16" height="16" viewBox="0 0 16 16" fill="none"><path d="M10 3L5 8l5 5" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/></svg>
返回首页
</a>
<a class="btn-back" href="../../../index.html"><svg width="16" height="16" viewBox="0 0 16 16" fill="none"><path d="M10 3L5 8l5 5" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/></svg> 返回首页</a>
<div class="avatar"></div>
<span style="color:rgba(255,255,255,0.65);">系统管理员 ▾</span>
</div>
@@ -114,11 +145,87 @@
</div>
</aside>
<main class="main">
<div class="page-placeholder">
<svg width="64" height="64" viewBox="0 0 64 64" fill="none"><rect x="8" y="8" width="48" height="48" rx="8" stroke="#ccc" stroke-width="2"/><path d="M20 32h24M32 20v24" stroke="#ccc" stroke-width="2" stroke-linecap="round"/></svg>
<p>应用记录</p>
<div class="filter-bar">
<div class="filter-item"><label>设备名称</label><input class="filter-input" placeholder="请输入设备名称"></div>
<div class="filter-item"><label>设备编码</label><input class="filter-input" placeholder="请输入设备编码"></div>
<div class="filter-item"><label>所属单位</label>
<select class="filter-select"><option value="">全部</option><option>采油一厂</option><option>采油二厂</option><option>采油三厂</option></select>
</div>
<button class="btn btn-primary">查询</button>
<button class="btn btn-default">重置</button>
</div>
<div class="action-bar"><button class="btn btn-default">导出列表数据</button></div>
<div class="table-card">
<div class="table-card__content">
<table id="appTable">
<thead>
<tr>
<th rowspan="2" class="th-left" style="min-width:140px;">设备名称</th>
<th rowspan="2" style="min-width:110px;">设备编码</th>
<th rowspan="2" style="min-width:90px;">所属单位</th>
<th rowspan="2" style="min-width:120px;">设备位置</th>
<th colspan="10">移动端点击次数</th>
</tr>
<tr>
<th class="th-sort" data-col="4" onclick="sortTable(this)">榆属<span class="sort-icon"><span class="arrow-up"></span><span class="arrow-down"></span></span></th>
<th class="th-sort" data-col="5" onclick="sortTable(this)">松属<span class="sort-icon"><span class="arrow-up"></span><span class="arrow-down"></span></span></th>
<th class="th-sort" data-col="6" onclick="sortTable(this)">杨属<span class="sort-icon"><span class="arrow-up"></span><span class="arrow-down"></span></span></th>
<th class="th-sort" data-col="7" onclick="sortTable(this)">柏科<span class="sort-icon"><span class="arrow-up"></span><span class="arrow-down"></span></span></th>
<th class="th-sort" data-col="8" onclick="sortTable(this)">柳属<span class="sort-icon"><span class="arrow-up"></span><span class="arrow-down"></span></span></th>
<th class="th-sort" data-col="9" onclick="sortTable(this)">蒿属<span class="sort-icon"><span class="arrow-up"></span><span class="arrow-down"></span></span></th>
<th class="th-sort" data-col="10" onclick="sortTable(this)">藜科<span class="sort-icon"><span class="arrow-up"></span><span class="arrow-down"></span></span></th>
<th class="th-sort" data-col="11" onclick="sortTable(this)">苋科<span class="sort-icon"><span class="arrow-up"></span><span class="arrow-down"></span></span></th>
<th class="th-sort" data-col="12" onclick="sortTable(this)">花粉总数<span class="sort-icon"><span class="arrow-up"></span><span class="arrow-down"></span></span></th>
<th class="th-sort" data-col="13" onclick="sortTable(this)">总点击次数<span class="sort-icon"><span class="arrow-up"></span><span class="arrow-down"></span></span></th>
</tr>
</thead>
<tbody>
<tr>
<td class="td-left">花粉采样器-A01</td><td>PL-2024-001</td><td>采油一厂</td><td>办公区绿化带</td>
<td>123</td><td>89</td><td>256</td><td>67</td><td>145</td><td>78</td><td>34</td><td>28</td><td>312</td><td>1132</td>
</tr>
<tr>
<td class="td-left">花粉浓度监测仪-B01</td><td>PL-2024-002</td><td>采油一厂</td><td>厂区东侧林带</td>
<td>198</td><td>156</td><td>423</td><td>112</td><td>234</td><td>145</td><td>56</td><td>42</td><td>478</td><td>1844</td>
</tr>
<tr>
<td class="td-left">花粉自动计数仪-C01</td><td>PL-2024-003</td><td>采油二厂</td><td>生活区花园</td>
<td>267</td><td>178</td><td>345</td><td>98</td><td>189</td><td>212</td><td>78</td><td>56</td><td>534</td><td>1957</td>
</tr>
<tr>
<td class="td-left">综合气象花粉站-D01</td><td>PL-2024-004</td><td>采油二厂</td><td>气象观测场</td>
<td>345</td><td>234</td><td>512</td><td>156</td><td>278</td><td>189</td><td>98</td><td>67</td><td>623</td><td>2502</td>
</tr>
<tr>
<td class="td-left">花粉采样器-A03</td><td>PL-2024-005</td><td>采油三厂</td><td>杨树林防护带</td>
<td>412</td><td>298</td><td>678</td><td>189</td><td>356</td><td>234</td><td>112</td><td>89</td><td>756</td><td>3124</td>
</tr>
</tbody>
</table>
</div>
<div class="pagination"><span>共 5 条</span><button class="page-btn active">1</button></div>
</div>
</main>
<script>function toggleSubgroup(h){h.parentElement.classList.toggle('open');}(function(){var a=document.querySelector('.sidebar-item.active');if(!a)return;var s=a.closest('.sidebar-subgroup');if(s)s.classList.add('open');})();</script>
<script>
function toggleSubgroup(h){h.parentElement.classList.toggle('open');}
(function(){var a=document.querySelector('.sidebar-item.active');if(!a)return;var s=a.closest('.sidebar-subgroup');if(s)s.classList.add('open');})();
function sortTable(th){
var table=document.getElementById('appTable');
var tbody=table.querySelector('tbody');
var rows=Array.from(tbody.querySelectorAll('tr'));
var col=parseInt(th.getAttribute('data-col'));
var dir='asc';
if(th.classList.contains('asc')){dir='desc';}
else if(th.classList.contains('desc')){dir='asc';}
table.querySelectorAll('.th-sort').forEach(function(t){t.classList.remove('asc','desc');});
th.classList.add(dir);
rows.sort(function(a,b){
var va=parseInt(a.cells[col].textContent);
var vb=parseInt(b.cells[col].textContent);
return dir==='asc'?(va-vb):(vb-va);
});
rows.forEach(function(r){tbody.appendChild(r);});
}
</script>
</body>
</html>
</html>
@@ -0,0 +1,314 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>花粉监测 - 动态分析 | 健康长庆原型</title>
<style>
*{box-sizing:border-box;margin:0;padding:0;}
body{font-family:-apple-system,BlinkMacSystemFont,'PingFang SC','Microsoft YaHei',sans-serif;background:#F5F7FA;color:#333;min-width:1280px;}
:root{
--primary:#1890FF;--primary-light:#E6F7FF;--success:#52C41A;--warning:#FAAD14;--danger:#FF4D4F;
--text-primary:#333;--text-secondary:#666;--text-placeholder:#999;--border:#E8E8E8;--background:#F5F7FA;
--font-xs:11px;--font-sm:13px;--font-base:15px;--font-lg:17px;
--radius-sm:4px;--radius-md:8px;--radius-lg:12px;
--shadow-sm:0 1px 4px rgba(0,0,0,0.08);
}
.top-bar{display:flex;align-items:center;height:56px;background:#001529;padding:0 24px;position:fixed;top:0;left:0;right:0;z-index:100;}
.top-bar__logo{display:flex;align-items:center;gap:8px;color:#fff;font-size:var(--font-lg);font-weight:600;white-space:nowrap;width:240px;flex-shrink:0;}
.top-bar__logo svg{width:28px;height:28px;}
.top-bar__right{display:flex;align-items:center;gap:16px;color:rgba(255,255,255,0.65);font-size:var(--font-sm);}
.btn-back{color:rgba(255,255,255,0.65);cursor:pointer;display:flex;align-items:center;gap:4px;text-decoration:none;}.btn-back:hover{color:#fff;}
.avatar{width:32px;height:32px;border-radius:50%;background:#1890FF;display:flex;align-items:center;justify-content:center;color:#fff;font-size:var(--font-sm);cursor:pointer;}
.top-bar__nav{display:flex;align-items:center;gap:4px;flex:1;}
.top-bar__nav a{color:rgba(255,255,255,0.65);text-decoration:none;padding:6px 16px;border-radius:var(--radius-sm);font-size:var(--font-sm);transition:all .2s;}
.top-bar__nav a:hover{color:#fff;background:rgba(255,255,255,0.08);}
.top-bar__nav a.active{color:#fff;background:var(--primary);}
.sidebar{position:fixed;top:56px;left:0;bottom:0;width:240px;background:#001529;overflow-y:auto;z-index:90;padding-top:8px;}
.sidebar-menu__title{color:rgba(255,255,255,0.35);font-size:var(--font-xs);padding:16px 24px 8px;letter-spacing:.5px;}
.sidebar-item{display:flex;align-items:center;gap:8px;padding:10px 24px;color:rgba(255,255,255,0.65);font-size:var(--font-sm);cursor:pointer;transition:all .15s;text-decoration:none;}
.sidebar-item:hover{color:#fff;background:rgba(255,255,255,0.06);}
.sidebar-item.active{color:#fff;background:var(--primary);}
.sidebar-subgroup__header{display:flex;align-items:center;gap:6px;padding:10px 24px;color:rgba(255,255,255,0.65);font-size:var(--font-sm);cursor:pointer;transition:all .15s;user-select:none;}
.sidebar-subgroup__header:hover{color:rgba(255,255,255,0.85);background:rgba(255,255,255,0.04);}
.sidebar-subgroup__header .arrow{width:10px;height:10px;transition:transform .2s;flex-shrink:0;}
.sidebar-subgroup__header .arrow path{stroke:rgba(255,255,255,0.45);}
.sidebar-subgroup.open>.sidebar-subgroup__header{color:rgba(255,255,255,0.85);}
.sidebar-subgroup.open>.sidebar-subgroup__header .arrow{transform:rotate(90deg);}
.sidebar-subgroup__body{display:none;padding-left:16px;}
.sidebar-subgroup.open>.sidebar-subgroup__body{display:block;}
.sidebar-subgroup__body .sidebar-item{padding-left:36px;font-size:12px;}
.main{margin-left:240px;margin-top:56px;padding:24px;min-height:calc(100vh - 56px);}
.page-header{display:flex;align-items:center;gap:12px;margin-bottom:20px;}
.page-header__back{width:32px;height:32px;border-radius:var(--radius-sm);border:1px solid var(--border);background:#fff;display:flex;align-items:center;justify-content:center;cursor:pointer;text-decoration:none;color:var(--text-secondary);}
.page-header__back:hover{border-color:var(--primary);color:var(--primary);}
.page-header__title{font-size:var(--font-lg);font-weight:600;color:var(--text-primary);}
.analysis-layout{display:flex;gap:20px;align-items:flex-start;}
.device-card{width:340px;flex-shrink:0;background:#fff;border-radius:var(--radius-md);box-shadow:var(--shadow-sm);overflow:hidden;}
.device-card__header{padding:16px 20px;background:linear-gradient(135deg,#1890FF 0%,#096DD9 100%);color:#fff;}
.device-card__name{font-size:var(--font-base);font-weight:600;margin-bottom:4px;}
.device-card__code{font-size:var(--font-xs);opacity:.8;}
.device-card__body{padding:16px 20px;}
.device-card__item{display:flex;justify-content:space-between;align-items:center;padding:12px 0;border-bottom:1px solid #f5f5f5;}
.device-card__item:last-child{border-bottom:none;}
.device-card__label{font-size:var(--font-sm);color:var(--text-placeholder);}
.device-card__value{font-size:var(--font-sm);color:var(--text-primary);font-weight:500;text-align:right;max-width:180px;}
.allergy-tag{display:inline-block;padding:2px 10px;border-radius:10px;font-size:var(--font-xs);font-weight:500;}
.allergy-tag--medium{background:#FFFBE6;color:#FAAD14;}
.device-card__tip{margin-top:4px;padding:12px;background:#FFFBE6;border-radius:var(--radius-sm);border:1px solid #FFE58F;}
.device-card__tip p{font-size:var(--font-xs);color:var(--text-secondary);line-height:1.6;margin:0;}
.realtime-section{margin-top:16px;padding-top:16px;border-top:1px solid var(--border);}
.realtime-title{font-size:var(--font-xs);color:var(--text-placeholder);margin-bottom:12px;font-weight:500;}
.realtime-grid{display:grid;grid-template-columns:1fr 1fr 1fr;gap:8px;}
.realtime-item{background:#F8FBFF;border-radius:var(--radius-sm);padding:10px 8px;text-align:center;}
.realtime-item__value{font-size:var(--font-base);font-weight:600;color:var(--primary);margin-bottom:2px;}
.realtime-item__label{font-size:10px;color:var(--text-placeholder);}
.chart-panel{flex:1;background:#fff;border-radius:var(--radius-md);box-shadow:var(--shadow-sm);overflow:hidden;min-width:0;}
.time-tabs{display:flex;gap:0;border-bottom:1px solid var(--border);padding:0 24px;}
.time-tab{padding:14px 24px;font-size:var(--font-sm);color:var(--text-secondary);cursor:pointer;border-bottom:2px solid transparent;transition:all .2s;white-space:nowrap;}
.time-tab:hover{color:var(--primary);}
.time-tab.active{color:var(--primary);border-bottom-color:var(--primary);font-weight:500;}
.metric-bar{display:flex;align-items:center;gap:8px;padding:16px 24px;border-bottom:1px solid #f5f5f5;flex-wrap:wrap;}
.metric-btn{height:32px;padding:0 14px;border-radius:16px;font-size:var(--font-xs);cursor:pointer;border:1px solid var(--border);background:#fff;color:var(--text-secondary);transition:all .2s;white-space:nowrap;}
.metric-btn:hover{color:var(--primary);border-color:var(--primary);}
.metric-btn.active{background:var(--primary);color:#fff;border-color:var(--primary);}
.chart-area{padding:24px;min-height:400px;}
.chart-container{width:100%;height:360px;position:relative;}
.chart-container svg{width:100%;height:100%;}
.chart-grid-line{stroke:#f0f0f0;stroke-width:1;}
.chart-axis-label{fill:#999;font-size:11px;}
.chart-line{fill:none;stroke:var(--primary);stroke-width:2;stroke-linejoin:round;stroke-linecap:round;}
.chart-area-fill{fill:url(#areaGrad);opacity:.15;}
.chart-dot{fill:var(--primary);stroke:#fff;stroke-width:2;}
.chart-summary{display:flex;gap:32px;padding:0 24px 20px;}
.chart-summary__item{display:flex;align-items:center;gap:6px;}
.chart-summary__dot{width:8px;height:8px;border-radius:50%;}
.chart-summary__label{font-size:var(--font-xs);color:var(--text-placeholder);}
.chart-summary__value{font-size:var(--font-sm);color:var(--text-primary);font-weight:600;}
</style>
</head>
<body>
<div class="top-bar">
<div class="top-bar__logo"><svg viewBox="0 0 28 28" fill="none"><rect width="28" height="28" rx="6" fill="#1890FF"/><path d="M7 14h14M14 7v14" stroke="#fff" stroke-width="2.5" stroke-linecap="round"/></svg> 健康监测</div>
<nav class="top-bar__nav">
<a href="../archive-personal.html">档案</a>
<a href="../health-checkup/survey-category.html">健康排查</a>
<a href="../wearable/tool-manage.html">穿戴监测</a>
<a href="../weight/scale-device.html">体重监测</a>
<a href="../environment/indoor-device-list.html" class="active">环境监测</a>
<a href="../exception-dirty.html">异常事件</a>
</nav>
<div class="top-bar__right">
<a class="btn-back" href="../../../index.html"><svg width="16" height="16" viewBox="0 0 16 16" fill="none"><path d="M10 3L5 8l5 5" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/></svg> 返回首页</a>
<div class="avatar"></div>
<span style="color:rgba(255,255,255,0.65);">系统管理员 ▾</span>
</div>
</div>
<aside class="sidebar">
<div class="sidebar-menu__title">环境监测</div>
<div class="sidebar-subgroup">
<div class="sidebar-subgroup__header" onclick="toggleSubgroup(this)"><svg class="arrow" viewBox="0 0 12 12"><path d="M4 2l4 4-4 4" fill="none" stroke-width="1.5" stroke-linecap="round"/></svg> 室内空气</div>
<div class="sidebar-subgroup__body">
<a href="indoor-device-list.html" class="sidebar-item">设备列表</a><a href="indoor-device-category.html" class="sidebar-item">设备分类</a><a href="indoor-data-monitor.html" class="sidebar-item">数据监测</a><a href="indoor-exception-alarm.html" class="sidebar-item">异常报警</a><a href="indoor-app-record.html" class="sidebar-item">应用记录</a><a href="indoor-history-data.html" class="sidebar-item">历史数据</a>
</div>
</div>
<div class="sidebar-subgroup">
<div class="sidebar-subgroup__header" onclick="toggleSubgroup(this)"><svg class="arrow" viewBox="0 0 12 12"><path d="M4 2l4 4-4 4" fill="none" stroke-width="1.5" stroke-linecap="round"/></svg> 室外空气</div>
<div class="sidebar-subgroup__body">
<a href="outdoor-device-list.html" class="sidebar-item">设备列表</a><a href="outdoor-device-category.html" class="sidebar-item">设备分类</a><a href="outdoor-data-monitor.html" class="sidebar-item">数据监测</a><a href="outdoor-exception-alarm.html" class="sidebar-item">异常报警</a><a href="outdoor-app-record.html" class="sidebar-item">应用记录</a><a href="outdoor-history-data.html" class="sidebar-item">历史数据</a>
</div>
</div>
<div class="sidebar-subgroup">
<div class="sidebar-subgroup__header" onclick="toggleSubgroup(this)"><svg class="arrow" viewBox="0 0 12 12"><path d="M4 2l4 4-4 4" fill="none" stroke-width="1.5" stroke-linecap="round"/></svg> 水质监测</div>
<div class="sidebar-subgroup__body">
<a href="water-device-list.html" class="sidebar-item">设备列表</a><a href="water-device-category.html" class="sidebar-item">设备分类</a><a href="water-data-monitor.html" class="sidebar-item">数据监测</a><a href="water-exception-alarm.html" class="sidebar-item">异常报警</a><a href="water-app-record.html" class="sidebar-item">应用记录</a><a href="water-history-data.html" class="sidebar-item">历史数据</a>
</div>
</div>
<div class="sidebar-subgroup open">
<div class="sidebar-subgroup__header" onclick="toggleSubgroup(this)"><svg class="arrow" viewBox="0 0 12 12"><path d="M4 2l4 4-4 4" fill="none" stroke-width="1.5" stroke-linecap="round"/></svg> 花粉监测</div>
<div class="sidebar-subgroup__body">
<a href="pollen-device-list.html" class="sidebar-item">设备列表</a><a href="pollen-device-category.html" class="sidebar-item">设备分类</a><a href="pollen-data-monitor.html" class="sidebar-item active">数据监测</a><a href="pollen-exception-alarm.html" class="sidebar-item">异常报警</a><a href="pollen-app-record.html" class="sidebar-item">应用记录</a><a href="pollen-history-data.html" class="sidebar-item">历史数据</a><a href="pollen-knowledge.html" class="sidebar-item">知识科普</a>
</div>
</div>
</aside>
<main class="main">
<div class="page-header">
<a class="page-header__back" href="pollen-data-monitor.html"><svg width="16" height="16" viewBox="0 0 16 16" fill="none"><path d="M10 3L5 8l5 5" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/></svg></a>
<span class="page-header__title">动态分析</span>
</div>
<div class="analysis-layout">
<!-- 左侧 - 设备信息 -->
<div class="device-card">
<div class="device-card__header">
<div class="device-card__name">花粉自动计数仪-C01</div>
<div class="device-card__code">PL-2024-003</div>
</div>
<div class="device-card__body">
<div class="device-card__item">
<span class="device-card__label">所属单位</span>
<span class="device-card__value">采油二厂</span>
</div>
<div class="device-card__item">
<span class="device-card__label">设备位置</span>
<span class="device-card__value">生活区花园</span>
</div>
<div class="device-card__item">
<span class="device-card__label">数据更新时间</span>
<span class="device-card__value">2026-05-14 14:25</span>
</div>
<div class="device-card__item">
<span class="device-card__label">过敏等级</span>
<span class="device-card__value"><span class="allergy-tag allergy-tag--medium">中等</span></span>
</div>
<div class="device-card__tip">
<p>花粉浓度中等偏高,过敏体质人群建议减少户外活动,外出时佩戴口罩。</p>
</div>
<div class="realtime-section">
<div class="realtime-title">实时监测数据(粒/千mm²)</div>
<div class="realtime-grid">
<div class="realtime-item">
<div class="realtime-item__value">68</div>
<div class="realtime-item__label">榆属</div>
</div>
<div class="realtime-item">
<div class="realtime-item__value">45</div>
<div class="realtime-item__label">松属</div>
</div>
<div class="realtime-item">
<div class="realtime-item__value">82</div>
<div class="realtime-item__label">杨属</div>
</div>
<div class="realtime-item">
<div class="realtime-item__value">35</div>
<div class="realtime-item__label">柏科</div>
</div>
<div class="realtime-item">
<div class="realtime-item__value">52</div>
<div class="realtime-item__label">柳属</div>
</div>
<div class="realtime-item">
<div class="realtime-item__value">30</div>
<div class="realtime-item__label">蒿属</div>
</div>
<div class="realtime-item">
<div class="realtime-item__value">18</div>
<div class="realtime-item__label">藜科</div>
</div>
<div class="realtime-item">
<div class="realtime-item__value">12</div>
<div class="realtime-item__label">苋科</div>
</div>
<div class="realtime-item">
<div class="realtime-item__value">342</div>
<div class="realtime-item__label">花粉总数</div>
</div>
</div>
</div>
</div>
</div>
<!-- 右侧 - 趋势图 -->
<div class="chart-panel">
<div class="time-tabs">
<div class="time-tab active" onclick="switchTimeTab(this)">近24小时</div>
<div class="time-tab" onclick="switchTimeTab(this)">近7日</div>
<div class="time-tab" onclick="switchTimeTab(this)">近30日</div>
<div class="time-tab" onclick="switchTimeTab(this)">近3个月</div>
</div>
<div class="metric-bar">
<button class="metric-btn active" onclick="switchMetric(this,'elm')">榆属</button>
<button class="metric-btn" onclick="switchMetric(this,'pine')">松属</button>
<button class="metric-btn" onclick="switchMetric(this,'poplar')">杨属</button>
<button class="metric-btn" onclick="switchMetric(this,'cypress')">柏科</button>
<button class="metric-btn" onclick="switchMetric(this,'willow')">柳属</button>
<button class="metric-btn" onclick="switchMetric(this,'mugwort')">蒿属</button>
<button class="metric-btn" onclick="switchMetric(this,'cheno')">藜科</button>
<button class="metric-btn" onclick="switchMetric(this,'amaranth')">苋科</button>
<button class="metric-btn" onclick="switchMetric(this,'total')">花粉总数</button>
</div>
<div class="chart-summary">
<div class="chart-summary__item"><span class="chart-summary__dot" style="background:#1890FF;"></span><span class="chart-summary__label">平均值</span><span class="chart-summary__value" id="avgVal">62 粒/千mm²</span></div>
<div class="chart-summary__item"><span class="chart-summary__dot" style="background:#52C41A;"></span><span class="chart-summary__label">最小值</span><span class="chart-summary__value" id="minVal">28 粒/千mm²</span></div>
<div class="chart-summary__item"><span class="chart-summary__dot" style="background:#FF4D4F;"></span><span class="chart-summary__label">最大值</span><span class="chart-summary__value" id="maxVal">95 粒/千mm²</span></div>
</div>
<div class="chart-area">
<div class="chart-container" id="chartContainer">
<svg viewBox="0 0 800 320" preserveAspectRatio="xMidYMid meet">
<defs>
<linearGradient id="areaGrad" x1="0" y1="0" x2="0" y2="1">
<stop offset="0%" stop-color="#1890FF" stop-opacity="0.3"/>
<stop offset="100%" stop-color="#1890FF" stop-opacity="0"/>
</linearGradient>
</defs>
<line x1="60" y1="20" x2="780" y2="20" class="chart-grid-line"/>
<line x1="60" y1="80" x2="780" y2="80" class="chart-grid-line"/>
<line x1="60" y1="140" x2="780" y2="140" class="chart-grid-line"/>
<line x1="60" y1="200" x2="780" y2="200" class="chart-grid-line"/>
<line x1="60" y1="260" x2="780" y2="260" class="chart-grid-line"/>
<text x="50" y="24" class="chart-axis-label" text-anchor="end">100</text>
<text x="50" y="84" class="chart-axis-label" text-anchor="end">80</text>
<text x="50" y="144" class="chart-axis-label" text-anchor="end">60</text>
<text x="50" y="204" class="chart-axis-label" text-anchor="end">40</text>
<text x="50" y="264" class="chart-axis-label" text-anchor="end">20</text>
<text x="90" y="290" class="chart-axis-label" text-anchor="middle">00:00</text>
<text x="180" y="290" class="chart-axis-label" text-anchor="middle">04:00</text>
<text x="270" y="290" class="chart-axis-label" text-anchor="middle">06:00</text>
<text x="360" y="290" class="chart-axis-label" text-anchor="middle">08:00</text>
<text x="450" y="290" class="chart-axis-label" text-anchor="middle">10:00</text>
<text x="540" y="290" class="chart-axis-label" text-anchor="middle">12:00</text>
<text x="630" y="290" class="chart-axis-label" text-anchor="middle">14:00</text>
<text x="720" y="290" class="chart-axis-label" text-anchor="middle">16:00</text>
<line x1="60" y1="270" x2="780" y2="270" stroke="#d9d9d9" stroke-width="1"/>
<path class="chart-area-fill" d="M90,220 L150,210 L210,200 L270,170 L330,140 L390,110 L450,90 L510,100 L570,80 L630,110 L690,130 L750,140 L750,270 L90,270 Z"/>
<polyline class="chart-line" points="90,220 150,210 210,200 270,170 330,140 390,110 450,90 510,100 570,80 630,110 690,130 750,140"/>
<circle cx="90" cy="220" r="4" class="chart-dot"/>
<circle cx="150" cy="210" r="4" class="chart-dot"/>
<circle cx="210" cy="200" r="4" class="chart-dot"/>
<circle cx="270" cy="170" r="4" class="chart-dot"/>
<circle cx="330" cy="140" r="4" class="chart-dot"/>
<circle cx="390" cy="110" r="4" class="chart-dot"/>
<circle cx="450" cy="90" r="4" class="chart-dot"/>
<circle cx="510" cy="100" r="4" class="chart-dot"/>
<circle cx="570" cy="80" r="4" class="chart-dot"/>
<circle cx="630" cy="110" r="4" class="chart-dot"/>
<circle cx="690" cy="130" r="4" class="chart-dot"/>
<circle cx="750" cy="140" r="4" class="chart-dot"/>
</svg>
</div>
</div>
</div>
</div>
</main>
<script>
function toggleSubgroup(h){h.parentElement.classList.toggle('open');}
(function(){var a=document.querySelector('.sidebar-item.active');if(!a)return;var s=a.closest('.sidebar-subgroup');if(s)s.classList.add('open');})();
function switchTimeTab(el){
var tabs=document.querySelectorAll('.time-tab');
tabs.forEach(function(t){t.classList.remove('active');});
el.classList.add('active');
}
var u='粒/千mm²';
var metricData={
elm: {avg:'62 '+u, min:'28 '+u, max:'95 '+u},
pine: {avg:'42 '+u, min:'18 '+u, max:'68 '+u},
poplar: {avg:'78 '+u, min:'35 '+u, max:'120 '+u},
cypress: {avg:'32 '+u, min:'12 '+u, max:'55 '+u},
willow: {avg:'48 '+u, min:'20 '+u, max:'75 '+u},
mugwort: {avg:'28 '+u, min:'10 '+u, max:'48 '+u},
cheno: {avg:'16 '+u, min:'5 '+u, max:'28 '+u},
amaranth:{avg:'10 '+u, min:'3 '+u, max:'18 '+u},
total: {avg:'316 '+u, min:'131 '+u, max:'507 '+u}
};
function switchMetric(el,key){
var btns=document.querySelectorAll('.metric-btn');
btns.forEach(function(b){b.classList.remove('active');});
el.classList.add('active');
var d=metricData[key];
document.getElementById('avgVal').textContent=d.avg;
document.getElementById('minVal').textContent=d.min;
document.getElementById('maxVal').textContent=d.max;
}
</script>
</body>
</html>
@@ -3,7 +3,7 @@
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>健康监测 - 数据监测 | 健康长庆原型</title>
<title>花粉监测 - 数据监测 | 健康长庆原型</title>
<style>
*{box-sizing:border-box;margin:0;padding:0;}
body{font-family:-apple-system,BlinkMacSystemFont,'PingFang SC','Microsoft YaHei',sans-serif;background:#F5F7FA;color:#333;min-width:1280px;}
@@ -18,8 +18,7 @@
.top-bar__logo{display:flex;align-items:center;gap:8px;color:#fff;font-size:var(--font-lg);font-weight:600;white-space:nowrap;width:240px;flex-shrink:0;}
.top-bar__logo svg{width:28px;height:28px;}
.top-bar__right{display:flex;align-items:center;gap:16px;color:rgba(255,255,255,0.65);font-size:var(--font-sm);}
.btn-back{color:rgba(255,255,255,0.65);cursor:pointer;display:flex;align-items:center;gap:4px;text-decoration:none;}
.btn-back:hover{color:#fff;}
.btn-back{color:rgba(255,255,255,0.65);cursor:pointer;display:flex;align-items:center;gap:4px;text-decoration:none;}.btn-back:hover{color:#fff;}
.avatar{width:32px;height:32px;border-radius:50%;background:#1890FF;display:flex;align-items:center;justify-content:center;color:#fff;font-size:var(--font-sm);cursor:pointer;}
.top-bar__nav{display:flex;align-items:center;gap:4px;flex:1;}
.top-bar__nav a{color:rgba(255,255,255,0.65);text-decoration:none;padding:6px 16px;border-radius:var(--radius-sm);font-size:var(--font-sm);transition:all .2s;}
@@ -40,9 +39,47 @@
.sidebar-subgroup.open>.sidebar-subgroup__body{display:block;}
.sidebar-subgroup__body .sidebar-item{padding-left:36px;font-size:12px;}
.main{margin-left:240px;margin-top:56px;padding:24px;min-height:calc(100vh - 56px);}
.page-placeholder{display:flex;flex-direction:column;align-items:center;justify-content:center;height:calc(100vh - 56px - 48px);color:var(--text-placeholder);gap:12px;}
.page-placeholder svg{opacity:.25;}
.page-placeholder p{font-size:var(--font-base);}
.filter-bar{background:#fff;border-radius:var(--radius-md);padding:20px 24px;margin-bottom:16px;box-shadow:var(--shadow-sm);display:flex;align-items:center;gap:16px;flex-wrap:wrap;}
.filter-item{display:flex;align-items:center;gap:8px;}
.filter-item label{font-size:var(--font-sm);color:var(--text-secondary);white-space:nowrap;}
.filter-input{height:36px;border:1px solid var(--border);border-radius:var(--radius-sm);padding:0 12px;font-size:var(--font-sm);color:var(--text-primary);outline:none;background:#fff;min-width:180px;}.filter-input:focus{border-color:var(--primary);}
.filter-select{height:36px;border:1px solid var(--border);border-radius:var(--radius-sm);padding:0 28px 0 12px;font-size:var(--font-sm);color:var(--text-primary);outline:none;background:#fff url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6'%3E%3Cpath d='M0 0l5 6 5-6z' fill='%23999'/%3E%3C/svg%3E") no-repeat right 10px center;appearance:none;cursor:pointer;min-width:140px;}
.btn{height:36px;padding:0 16px;border-radius:var(--radius-sm);font-size:var(--font-sm);cursor:pointer;border:none;transition:all .2s;display:inline-flex;align-items:center;gap:6px;}
.btn-primary{background:var(--primary);color:#fff;}.btn-primary:hover{background:#40a9ff;}
.btn-default{background:#fff;color:var(--text-primary);border:1px solid var(--border);}.btn-default:hover{color:var(--primary);border-color:var(--primary);}
.action-bar{display:flex;align-items:center;gap:12px;margin-bottom:16px;}
.table-card{background:#fff;border-radius:var(--radius-md);box-shadow:var(--shadow-sm);overflow:hidden;}
.table-card__content{overflow-x:auto;-webkit-overflow-scrolling:touch;}
table{width:100%;border-collapse:collapse;min-width:1800px;}
thead th{background:#FAFAFA;padding:12px 14px;text-align:center;font-size:var(--font-xs);color:var(--text-secondary);font-weight:500;border-bottom:1px solid var(--border);border-right:1px solid var(--border);white-space:nowrap;}
thead th:last-child{border-right:none;}
thead th.th-left{text-align:left;}
tbody td{padding:12px 14px;font-size:var(--font-xs);color:var(--text-primary);border-bottom:1px solid var(--border);text-align:center;white-space:nowrap;}
tbody td.td-left{text-align:left;}
tbody tr:last-child td{border-bottom:none;}
tbody tr:hover{background:#F8FBFF;}
/* 固定列 */
thead tr:first-child th:nth-child(-n+2),tbody td:nth-child(-n+2),thead tr:first-child th:nth-last-child(-n+2),tbody td:nth-last-child(-n+2){position:sticky;z-index:2;}
thead tr:first-child th:nth-child(-n+2),thead tr:first-child th:nth-last-child(-n+2){z-index:3;}
thead tr:first-child th:nth-child(1),tbody td:nth-child(1){left:0;}
thead tr:first-child th:nth-child(2),tbody td:nth-child(2){left:140px;}
thead tr:first-child th:nth-last-child(2),tbody td:nth-last-child(2){right:70px;}
thead tr:first-child th:nth-last-child(1),tbody td:nth-last-child(1){right:0;}
tbody td:nth-child(-n+2),tbody td:nth-last-child(-n+2){background:#fff;}
tbody tr:hover td:nth-child(-n+2),tbody tr:hover td:nth-last-child(-n+2){background:#F8FBFF;}
tbody td:nth-child(2),thead tr:first-child th:nth-child(2){box-shadow:2px 0 4px rgba(0,0,0,0.06);}
tbody td:nth-last-child(2),thead tr:first-child th:nth-last-child(2){box-shadow:-2px 0 4px rgba(0,0,0,0.06);}
.link{color:var(--primary);cursor:pointer;font-size:var(--font-xs);text-decoration:none;}.link:hover{color:#40a9ff;}
.allergy-tag{display:inline-block;padding:2px 10px;border-radius:10px;font-size:var(--font-xs);font-weight:500;}
.allergy-tag--vlow{background:#F6FFED;color:#52C41A;}
.allergy-tag--low{background:#E6FFFB;color:#13C2C2;}
.allergy-tag--medium{background:#FFFBE6;color:#FAAD14;}
.allergy-tag--high{background:#FFF1F0;color:#FA541C;}
.allergy-tag--vhigh{background:#FFF1F0;color:#FF4D4F;}
.pagination{display:flex;align-items:center;justify-content:flex-end;padding:16px 24px;gap:8px;border-top:1px solid var(--border);}
.pagination span{font-size:var(--font-sm);color:var(--text-secondary);}
.page-btn{width:32px;height:32px;border:1px solid var(--border);border-radius:var(--radius-sm);background:#fff;cursor:pointer;font-size:var(--font-sm);display:inline-flex;align-items:center;justify-content:center;transition:all .2s;}
.page-btn:hover,.page-btn.active{background:var(--primary);color:#fff;border-color:var(--primary);}
</style>
</head>
<body>
@@ -57,10 +94,7 @@
<a href="../exception-dirty.html">异常事件</a>
</nav>
<div class="top-bar__right">
<a class="btn-back" href="../../../index.html">
<svg width="16" height="16" viewBox="0 0 16 16" fill="none"><path d="M10 3L5 8l5 5" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/></svg>
返回首页
</a>
<a class="btn-back" href="../../../index.html"><svg width="16" height="16" viewBox="0 0 16 16" fill="none"><path d="M10 3L5 8l5 5" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/></svg> 返回首页</a>
<div class="avatar"></div>
<span style="color:rgba(255,255,255,0.65);">系统管理员 ▾</span>
</div>
@@ -70,55 +104,91 @@
<div class="sidebar-subgroup">
<div class="sidebar-subgroup__header" onclick="toggleSubgroup(this)"><svg class="arrow" viewBox="0 0 12 12"><path d="M4 2l4 4-4 4" fill="none" stroke-width="1.5" stroke-linecap="round"/></svg> 室内空气</div>
<div class="sidebar-subgroup__body">
<a href="indoor-device-list.html" class="sidebar-item">设备列表</a>
<a href="indoor-device-category.html" class="sidebar-item">设备分类</a>
<a href="indoor-data-monitor.html" class="sidebar-item">数据监测</a>
<a href="indoor-exception-alarm.html" class="sidebar-item">异常报警</a>
<a href="indoor-app-record.html" class="sidebar-item">应用记录</a>
<a href="indoor-history-data.html" class="sidebar-item">历史数据</a>
<a href="indoor-device-list.html" class="sidebar-item">设备列表</a><a href="indoor-device-category.html" class="sidebar-item">设备分类</a><a href="indoor-data-monitor.html" class="sidebar-item">数据监测</a><a href="indoor-exception-alarm.html" class="sidebar-item">异常报警</a><a href="indoor-app-record.html" class="sidebar-item">应用记录</a><a href="indoor-history-data.html" class="sidebar-item">历史数据</a>
</div>
</div>
<div class="sidebar-subgroup">
<div class="sidebar-subgroup__header" onclick="toggleSubgroup(this)"><svg class="arrow" viewBox="0 0 12 12"><path d="M4 2l4 4-4 4" fill="none" stroke-width="1.5" stroke-linecap="round"/></svg> 室外空气</div>
<div class="sidebar-subgroup__body">
<a href="outdoor-device-list.html" class="sidebar-item">设备列表</a>
<a href="outdoor-device-category.html" class="sidebar-item">设备分类</a>
<a href="outdoor-data-monitor.html" class="sidebar-item">数据监测</a>
<a href="outdoor-exception-alarm.html" class="sidebar-item">异常报警</a>
<a href="outdoor-app-record.html" class="sidebar-item">应用记录</a>
<a href="outdoor-history-data.html" class="sidebar-item">历史数据</a>
<a href="outdoor-device-list.html" class="sidebar-item">设备列表</a><a href="outdoor-device-category.html" class="sidebar-item">设备分类</a><a href="outdoor-data-monitor.html" class="sidebar-item">数据监测</a><a href="outdoor-exception-alarm.html" class="sidebar-item">异常报警</a><a href="outdoor-app-record.html" class="sidebar-item">应用记录</a><a href="outdoor-history-data.html" class="sidebar-item">历史数据</a>
</div>
</div>
<div class="sidebar-subgroup">
<div class="sidebar-subgroup__header" onclick="toggleSubgroup(this)"><svg class="arrow" viewBox="0 0 12 12"><path d="M4 2l4 4-4 4" fill="none" stroke-width="1.5" stroke-linecap="round"/></svg> 水质监测</div>
<div class="sidebar-subgroup__body">
<a href="water-device-list.html" class="sidebar-item">设备列表</a>
<a href="water-device-category.html" class="sidebar-item">设备分类</a>
<a href="water-data-monitor.html" class="sidebar-item">数据监测</a>
<a href="water-exception-alarm.html" class="sidebar-item">异常报警</a>
<a href="water-app-record.html" class="sidebar-item">应用记录</a>
<a href="water-history-data.html" class="sidebar-item">历史数据</a>
<a href="water-device-list.html" class="sidebar-item">设备列表</a><a href="water-device-category.html" class="sidebar-item">设备分类</a><a href="water-data-monitor.html" class="sidebar-item">数据监测</a><a href="water-exception-alarm.html" class="sidebar-item">异常报警</a><a href="water-app-record.html" class="sidebar-item">应用记录</a><a href="water-history-data.html" class="sidebar-item">历史数据</a>
</div>
</div>
<div class="sidebar-subgroup open">
<div class="sidebar-subgroup__header" onclick="toggleSubgroup(this)"><svg class="arrow" viewBox="0 0 12 12"><path d="M4 2l4 4-4 4" fill="none" stroke-width="1.5" stroke-linecap="round"/></svg> 花粉监测</div>
<div class="sidebar-subgroup__body">
<a href="pollen-device-list.html" class="sidebar-item">设备列表</a>
<a href="pollen-device-category.html" class="sidebar-item">设备分类</a>
<a href="pollen-data-monitor.html" class="sidebar-item active">数据监测</a>
<a href="pollen-exception-alarm.html" class="sidebar-item">异常报警</a>
<a href="pollen-app-record.html" class="sidebar-item">应用记录</a>
<a href="pollen-history-data.html" class="sidebar-item">历史数据</a>
<a href="pollen-knowledge.html" class="sidebar-item">知识科普</a>
<a href="pollen-device-list.html" class="sidebar-item">设备列表</a><a href="pollen-device-category.html" class="sidebar-item">设备分类</a><a href="pollen-data-monitor.html" class="sidebar-item active">数据监测</a><a href="pollen-exception-alarm.html" class="sidebar-item">异常报警</a><a href="pollen-app-record.html" class="sidebar-item">应用记录</a><a href="pollen-history-data.html" class="sidebar-item">历史数据</a><a href="pollen-knowledge.html" class="sidebar-item">知识科普</a>
</div>
</div>
</aside>
<main class="main">
<div class="page-placeholder">
<svg width="64" height="64" viewBox="0 0 64 64" fill="none"><rect x="8" y="8" width="48" height="48" rx="8" stroke="#ccc" stroke-width="2"/><path d="M20 32h24M32 20v24" stroke="#ccc" stroke-width="2" stroke-linecap="round"/></svg>
<p>数据监测</p>
<div class="filter-bar">
<div class="filter-item"><label>设备名称</label><input class="filter-input" placeholder="请输入设备名称"></div>
<div class="filter-item"><label>设备编码</label><input class="filter-input" placeholder="请输入设备编码"></div>
<div class="filter-item"><label>所属单位</label><select class="filter-select"><option value="">全部</option><option>采油一厂</option><option>采油二厂</option><option>采油三厂</option></select></div>
<div class="filter-item"><label>过敏等级</label><select class="filter-select"><option value="">全部</option><option>很低</option><option></option><option>中等</option><option></option><option>很高</option></select></div>
<button class="btn btn-primary">查询</button>
<button class="btn btn-default">重置</button>
</div>
<div class="action-bar"><button class="btn btn-default">导出列表数据</button></div>
<div class="table-card">
<div class="table-card__content">
<table>
<thead>
<tr>
<th rowspan="2" class="th-left" style="min-width:140px;">设备名称</th>
<th rowspan="2" style="min-width:110px;">设备编码</th>
<th rowspan="2" style="min-width:90px;">所属单位</th>
<th rowspan="2" style="min-width:120px;">设备位置</th>
<th rowspan="2" style="min-width:150px;">数据更新时间</th>
<th colspan="9">监测数据(粒/千mm²)</th>
<th rowspan="2" style="min-width:80px;">过敏等级</th>
<th rowspan="2" style="min-width:70px;">操作</th>
</tr>
<tr>
<th>榆属</th><th>松属</th><th>杨属</th><th>柏科</th><th>柳属</th><th>蒿属</th><th>藜科</th><th>苋科</th><th>花粉总数</th>
</tr>
</thead>
<tbody>
<tr>
<td class="td-left">花粉采样器-A01</td><td>PL-2024-001</td><td>采油一厂</td><td>办公区绿化带</td><td>2026-05-14 14:30</td>
<td>12</td><td>8</td><td>15</td><td>6</td><td>10</td><td>5</td><td>3</td><td>2</td><td>61</td>
<td><span class="allergy-tag allergy-tag--vlow">很低</span></td><td><a class="link" href="pollen-data-analysis.html">动态分析</a></td>
</tr>
<tr>
<td class="td-left">花粉浓度监测仪-B01</td><td>PL-2024-002</td><td>采油一厂</td><td>厂区东侧林带</td><td>2026-05-14 14:28</td>
<td>35</td><td>22</td><td>48</td><td>18</td><td>28</td><td>15</td><td>8</td><td>6</td><td>180</td>
<td><span class="allergy-tag allergy-tag--low"></span></td><td><a class="link" href="pollen-data-analysis.html">动态分析</a></td>
</tr>
<tr>
<td class="td-left">花粉自动计数仪-C01</td><td>PL-2024-003</td><td>采油二厂</td><td>生活区花园</td><td>2026-05-14 14:25</td>
<td>68</td><td>45</td><td>82</td><td>35</td><td>52</td><td>30</td><td>18</td><td>12</td><td>342</td>
<td><span class="allergy-tag allergy-tag--medium">中等</span></td><td><a class="link" href="pollen-data-analysis.html">动态分析</a></td>
</tr>
<tr>
<td class="td-left">综合气象花粉站-D01</td><td>PL-2024-004</td><td>采油二厂</td><td>气象观测场</td><td>2026-05-14 14:20</td>
<td>120</td><td>85</td><td>150</td><td>65</td><td>95</td><td>55</td><td>32</td><td>22</td><td>624</td>
<td><span class="allergy-tag allergy-tag--high"></span></td><td><a class="link" href="pollen-data-analysis.html">动态分析</a></td>
</tr>
<tr>
<td class="td-left">花粉采样器-A03</td><td>PL-2024-005</td><td>采油三厂</td><td>杨树林防护带</td><td>2026-05-14 14:15</td>
<td>210</td><td>145</td><td>280</td><td>110</td><td>168</td><td>92</td><td>55</td><td>38</td><td>1098</td>
<td><span class="allergy-tag allergy-tag--vhigh">很高</span></td><td><a class="link" href="pollen-data-analysis.html">动态分析</a></td>
</tr>
</tbody>
</table>
</div>
<div class="pagination"><span>共 5 条</span><button class="page-btn active">1</button></div>
</div>
</main>
<script>function toggleSubgroup(h){h.parentElement.classList.toggle('open');}(function(){var a=document.querySelector('.sidebar-item.active');if(!a)return;var s=a.closest('.sidebar-subgroup');if(s)s.classList.add('open');})();</script>
<script>
function toggleSubgroup(h){h.parentElement.classList.toggle('open');}
(function(){var a=document.querySelector('.sidebar-item.active');if(!a)return;var s=a.closest('.sidebar-subgroup');if(s)s.classList.add('open');})();
</script>
</body>
</html>
</html>
@@ -3,7 +3,7 @@
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>健康监测 - 设备分类 | 健康长庆原型</title>
<title>花粉监测 - 设备分类 | 健康长庆原型</title>
<style>
*{box-sizing:border-box;margin:0;padding:0;}
body{font-family:-apple-system,BlinkMacSystemFont,'PingFang SC','Microsoft YaHei',sans-serif;background:#F5F7FA;color:#333;min-width:1280px;}
@@ -40,9 +40,58 @@
.sidebar-subgroup.open>.sidebar-subgroup__body{display:block;}
.sidebar-subgroup__body .sidebar-item{padding-left:36px;font-size:12px;}
.main{margin-left:240px;margin-top:56px;padding:24px;min-height:calc(100vh - 56px);}
.page-placeholder{display:flex;flex-direction:column;align-items:center;justify-content:center;height:calc(100vh - 56px - 48px);color:var(--text-placeholder);gap:12px;}
.page-placeholder svg{opacity:.25;}
.page-placeholder p{font-size:var(--font-base);}
.filter-bar{background:#fff;border-radius:var(--radius-md);padding:20px 24px;margin-bottom:16px;box-shadow:var(--shadow-sm);display:flex;align-items:center;gap:16px;flex-wrap:wrap;}
.filter-item{display:flex;align-items:center;gap:8px;}
.filter-item label{font-size:var(--font-sm);color:var(--text-secondary);white-space:nowrap;}
.filter-input{height:36px;border:1px solid var(--border);border-radius:var(--radius-sm);padding:0 12px;font-size:var(--font-sm);color:var(--text-primary);outline:none;background:#fff;min-width:200px;}
.filter-input:focus{border-color:var(--primary);}
.btn{height:36px;padding:0 16px;border-radius:var(--radius-sm);font-size:var(--font-sm);cursor:pointer;border:none;transition:all .2s;display:inline-flex;align-items:center;gap:6px;}
.btn-primary{background:var(--primary);color:#fff;}.btn-primary:hover{background:#40a9ff;}
.btn-default{background:#fff;color:var(--text-primary);border:1px solid var(--border);}.btn-default:hover{color:var(--primary);border-color:var(--primary);}
.action-bar{display:flex;align-items:center;gap:12px;margin-bottom:16px;}
.table-card{background:#fff;border-radius:var(--radius-md);box-shadow:var(--shadow-sm);overflow:hidden;}
.table-card__content{overflow-x:auto;-webkit-overflow-scrolling:touch;}
table{width:100%;border-collapse:collapse;min-width:600px;}
thead th{background:#FAFAFA;padding:12px 16px;text-align:center;font-size:var(--font-sm);color:var(--text-secondary);font-weight:500;border-bottom:1px solid var(--border);border-right:1px solid var(--border);white-space:nowrap;}
thead th:last-child{border-right:none;}
thead th.th-left{text-align:left;}
tbody td{padding:14px 16px;font-size:var(--font-sm);color:var(--text-primary);border-bottom:1px solid var(--border);text-align:center;white-space:nowrap;}
tbody td.td-left{text-align:left;}
tbody tr:last-child td{border-bottom:none;}
tbody tr:hover{background:#F8FBFF;}
.link{color:var(--primary);cursor:pointer;font-size:var(--font-sm);text-decoration:none;}.link:hover{color:#40a9ff;}
.link-danger{color:var(--danger);cursor:pointer;font-size:var(--font-sm);text-decoration:none;}.link-danger:hover{color:#ff7875;}
.pagination{display:flex;align-items:center;justify-content:flex-end;padding:16px 24px;gap:8px;border-top:1px solid var(--border);}
.pagination span{font-size:var(--font-sm);color:var(--text-secondary);}
.page-btn{width:32px;height:32px;border:1px solid var(--border);border-radius:var(--radius-sm);background:#fff;cursor:pointer;font-size:var(--font-sm);display:inline-flex;align-items:center;justify-content:center;transition:all .2s;}
.page-btn:hover,.page-btn.active{background:var(--primary);color:#fff;border-color:var(--primary);}
.drawer-mask{display:none;position:fixed;top:0;left:0;right:0;bottom:0;background:rgba(0,0,0,0.45);z-index:200;}
.drawer-mask.open{display:block;}
.drawer{position:fixed;top:0;right:-600px;width:600px;height:100%;background:#fff;z-index:201;box-shadow:-4px 0 16px rgba(0,0,0,0.12);transition:right .3s ease;display:flex;flex-direction:column;}
.drawer.open{right:0;}
.drawer__header{display:flex;align-items:center;justify-content:space-between;padding:16px 24px;border-bottom:1px solid var(--border);}
.drawer__title{font-size:var(--font-base);font-weight:600;color:var(--text-primary);}
.drawer__close{width:32px;height:32px;border:none;background:none;cursor:pointer;display:flex;align-items:center;justify-content:center;border-radius:var(--radius-sm);color:var(--text-placeholder);font-size:18px;}
.drawer__close:hover{background:#f5f5f5;color:var(--text-primary);}
.drawer__body{flex:1;overflow-y:auto;padding:24px;}
.drawer__footer{display:flex;align-items:center;justify-content:flex-end;gap:12px;padding:16px 24px;border-top:1px solid var(--border);}
.form-group{margin-bottom:20px;}
.form-label{display:block;font-size:var(--font-sm);color:var(--text-primary);margin-bottom:8px;font-weight:500;}
.form-label .required{color:var(--danger);margin-right:4px;}
.form-control{width:100%;height:36px;border:1px solid var(--border);border-radius:var(--radius-sm);padding:0 12px;font-size:var(--font-sm);color:var(--text-primary);outline:none;background:#fff;}
.form-control:focus{border-color:var(--primary);box-shadow:0 0 0 2px rgba(24,144,255,0.1);}
.threshold-section-title{font-size:var(--font-sm);font-weight:600;color:var(--text-primary);margin-bottom:12px;padding-bottom:8px;border-bottom:1px solid var(--border);}
.threshold-list{display:flex;flex-direction:column;gap:12px;}
.threshold-item{border:1px solid var(--border);border-radius:var(--radius-md);overflow:hidden;}
.threshold-item__header{display:flex;align-items:center;justify-content:space-between;padding:12px 16px;background:#FAFAFA;}
.threshold-item__label{font-size:var(--font-sm);font-weight:600;color:var(--text-primary);}
.threshold-item__unit{font-size:var(--font-xs);color:var(--text-placeholder);font-weight:400;margin-left:4px;}
.threshold-item__body{padding:12px 16px;}
.threshold-row{display:grid;grid-template-columns:1fr 1fr;gap:12px;}
.threshold-field{display:flex;flex-direction:column;gap:4px;}
.threshold-field label{font-size:var(--font-xs);color:var(--text-secondary);}
.threshold-field .form-control{height:34px;border:1px solid var(--border);border-radius:var(--radius-sm);padding:0 10px;font-size:var(--font-sm);outline:none;width:100%;}
.threshold-field .form-control:focus{border-color:var(--primary);}
</style>
</head>
<body>
@@ -57,10 +106,7 @@
<a href="../exception-dirty.html">异常事件</a>
</nav>
<div class="top-bar__right">
<a class="btn-back" href="../../../index.html">
<svg width="16" height="16" viewBox="0 0 16 16" fill="none"><path d="M10 3L5 8l5 5" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/></svg>
返回首页
</a>
<a class="btn-back" href="../../../index.html"><svg width="16" height="16" viewBox="0 0 16 16" fill="none"><path d="M10 3L5 8l5 5" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/></svg> 返回首页</a>
<div class="avatar"></div>
<span style="color:rgba(255,255,255,0.65);">系统管理员 ▾</span>
</div>
@@ -114,11 +160,115 @@
</div>
</aside>
<main class="main">
<div class="page-placeholder">
<svg width="64" height="64" viewBox="0 0 64 64" fill="none"><rect x="8" y="8" width="48" height="48" rx="8" stroke="#ccc" stroke-width="2"/><path d="M20 32h24M32 20v24" stroke="#ccc" stroke-width="2" stroke-linecap="round"/></svg>
<p>设备分类</p>
<div class="filter-bar">
<div class="filter-item"><label>分类名称</label><input class="filter-input" placeholder="请输入分类名称"></div>
<button class="btn btn-primary">查询</button>
<button class="btn btn-default">重置</button>
</div>
<div class="action-bar">
<!-- [交互] 点击打开右侧抽屉弹窗(新增模式) -->
<button class="btn btn-primary" onclick="openDrawer('add')">+ 新增</button>
</div>
<div class="table-card">
<div class="table-card__content">
<table>
<thead>
<tr>
<th rowspan="2" class="th-left" style="min-width:160px;">分类名称</th>
<th colspan="1">监测数据阈值</th>
<th rowspan="2" style="min-width:100px;">操作</th>
</tr>
<tr>
<th>花粉浓度(粒/千mm²)</th>
</tr>
</thead>
<tbody>
<tr>
<td class="td-left">花粉采样器</td>
<td>0 ~ 500</td>
<td><a class="link" onclick="openDrawer('edit',0)">编辑</a> <a class="link-danger">删除</a></td>
</tr>
<tr>
<td class="td-left">花粉浓度监测仪</td>
<td>0 ~ 800</td>
<td><a class="link" onclick="openDrawer('edit',1)">编辑</a> <a class="link-danger">删除</a></td>
</tr>
<tr>
<td class="td-left">花粉自动计数仪</td>
<td>0 ~ 1000</td>
<td><a class="link" onclick="openDrawer('edit',2)">编辑</a> <a class="link-danger">删除</a></td>
</tr>
<tr>
<td class="td-left">综合气象花粉站</td>
<td>0 ~ 1200</td>
<td><a class="link" onclick="openDrawer('edit',3)">编辑</a> <a class="link-danger">删除</a></td>
</tr>
</tbody>
</table>
</div>
<div class="pagination">
<span>共 4 条</span>
<button class="page-btn active">1</button>
</div>
</div>
</main>
<script>function toggleSubgroup(h){h.parentElement.classList.toggle('open');}(function(){var a=document.querySelector('.sidebar-item.active');if(!a)return;var s=a.closest('.sidebar-subgroup');if(s)s.classList.add('open');})();</script>
<!-- 新增/编辑分类 - 右侧抽屉弹窗 -->
<div class="drawer-mask" id="drawerMask" onclick="closeDrawer()"></div>
<div class="drawer" id="drawer">
<div class="drawer__header">
<span class="drawer__title" id="drawerTitle">新增分类</span>
<button class="drawer__close" onclick="closeDrawer()">&times;</button>
</div>
<div class="drawer__body">
<div class="form-group">
<label class="form-label"><span class="required">*</span>分类名称</label>
<input class="form-control" id="formCategoryName" placeholder="请输入分类名称">
</div>
<div class="threshold-section-title">监测数据阈值设置</div>
<div class="threshold-list">
<div class="threshold-item">
<div class="threshold-item__header"><span class="threshold-item__label">花粉浓度<span class="threshold-item__unit">(粒/千mm²)</span></span></div>
<div class="threshold-item__body"><div class="threshold-row">
<div class="threshold-field"><label>阈值下限</label><input class="form-control" type="number" placeholder="下限"></div>
<div class="threshold-field"><label>阈值上限</label><input class="form-control" type="number" placeholder="上限"></div>
</div></div>
</div>
</div>
</div>
<div class="drawer__footer">
<button class="btn btn-default" onclick="closeDrawer()">取消</button>
<button class="btn btn-primary" onclick="closeDrawer()">确定</button>
</div>
</div>
<script>
function toggleSubgroup(h){h.parentElement.classList.toggle('open');}
(function(){var a=document.querySelector('.sidebar-item.active');if(!a)return;var s=a.closest('.sidebar-subgroup');if(s)s.classList.add('open');})();
function openDrawer(mode, rowIdx){
var title = document.getElementById('drawerTitle');
var nameInput = document.getElementById('formCategoryName');
var fields = document.querySelectorAll('.threshold-field .form-control');
if(mode === 'edit'){
title.textContent = '编辑分类';
var row = document.querySelectorAll('tbody tr')[rowIdx];
var cells = row.querySelectorAll('td');
nameInput.value = cells[0].textContent.trim();
for(var i = 0; i < 1; i++){
var parts = cells[i+1].textContent.split('~');
fields[i*2].value = parts[0].trim();
fields[i*2+1].value = parts[1].trim();
}
} else {
title.textContent = '新增分类';
nameInput.value = '';
for(var j = 0; j < fields.length; j++){ fields[j].value = ''; }
}
document.getElementById('drawerMask').classList.add('open');
document.getElementById('drawer').classList.add('open');
}
function closeDrawer(){document.getElementById('drawerMask').classList.remove('open');document.getElementById('drawer').classList.remove('open');}
</script>
</body>
</html>
</html>
@@ -3,7 +3,7 @@
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>健康监测 - 设备列表 | 健康长庆原型</title>
<title>花粉监测 - 设备列表 | 健康长庆原型</title>
<style>
*{box-sizing:border-box;margin:0;padding:0;}
body{font-family:-apple-system,BlinkMacSystemFont,'PingFang SC','Microsoft YaHei',sans-serif;background:#F5F7FA;color:#333;min-width:1280px;}
@@ -40,9 +40,56 @@
.sidebar-subgroup.open>.sidebar-subgroup__body{display:block;}
.sidebar-subgroup__body .sidebar-item{padding-left:36px;font-size:12px;}
.main{margin-left:240px;margin-top:56px;padding:24px;min-height:calc(100vh - 56px);}
.page-placeholder{display:flex;flex-direction:column;align-items:center;justify-content:center;height:calc(100vh - 56px - 48px);color:var(--text-placeholder);gap:12px;}
.page-placeholder svg{opacity:.25;}
.page-placeholder p{font-size:var(--font-base);}
.filter-bar{background:#fff;border-radius:var(--radius-md);padding:20px 24px;margin-bottom:16px;box-shadow:var(--shadow-sm);display:flex;align-items:center;gap:16px;flex-wrap:wrap;}
.filter-item{display:flex;align-items:center;gap:8px;}
.filter-item label{font-size:var(--font-sm);color:var(--text-secondary);white-space:nowrap;}
.filter-input{height:36px;border:1px solid var(--border);border-radius:var(--radius-sm);padding:0 12px;font-size:var(--font-sm);color:var(--text-primary);outline:none;background:#fff;min-width:160px;}
.filter-input:focus{border-color:var(--primary);}
.filter-select{height:36px;border:1px solid var(--border);border-radius:var(--radius-sm);padding:0 28px 0 12px;font-size:var(--font-sm);color:var(--text-primary);outline:none;background:#fff url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6'%3E%3Cpath d='M0 0l5 6 5-6z' fill='%23999'/%3E%3C/svg%3E") no-repeat right 10px center;appearance:none;cursor:pointer;min-width:140px;}
.btn{height:36px;padding:0 16px;border-radius:var(--radius-sm);font-size:var(--font-sm);cursor:pointer;border:none;transition:all .2s;display:inline-flex;align-items:center;gap:6px;}
.btn-primary{background:var(--primary);color:#fff;}.btn-primary:hover{background:#40a9ff;}
.btn-default{background:#fff;color:var(--text-primary);border:1px solid var(--border);}.btn-default:hover{color:var(--primary);border-color:var(--primary);}
.btn-success{background:var(--success);color:#fff;}.btn-success:hover{background:#73d13d;}
.action-bar{display:flex;align-items:center;gap:12px;margin-bottom:16px;}
.table-card{background:#fff;border-radius:var(--radius-md);box-shadow:var(--shadow-sm);overflow:hidden;}
.table-card__content{overflow-x:auto;-webkit-overflow-scrolling:touch;}
table{width:100%;border-collapse:collapse;min-width:1000px;}
thead th{background:#FAFAFA;padding:12px 16px;text-align:left;font-size:var(--font-sm);color:var(--text-secondary);font-weight:500;border-bottom:1px solid var(--border);white-space:nowrap;}
tbody td{padding:14px 16px;font-size:var(--font-sm);color:var(--text-primary);border-bottom:1px solid var(--border);white-space:nowrap;}
tbody tr:last-child td{border-bottom:none;}
tbody tr:hover{background:#F8FBFF;}
.link{color:var(--primary);cursor:pointer;font-size:var(--font-sm);text-decoration:none;}.link:hover{color:#40a9ff;}
.link-danger{color:var(--danger);cursor:pointer;font-size:var(--font-sm);text-decoration:none;}.link-danger:hover{color:#ff7875;}
.pagination{display:flex;align-items:center;justify-content:flex-end;padding:16px 24px;gap:8px;border-top:1px solid var(--border);}
.pagination span{font-size:var(--font-sm);color:var(--text-secondary);}
.page-btn{width:32px;height:32px;border:1px solid var(--border);border-radius:var(--radius-sm);background:#fff;cursor:pointer;font-size:var(--font-sm);display:inline-flex;align-items:center;justify-content:center;transition:all .2s;}
.page-btn:hover,.page-btn.active{background:var(--primary);color:#fff;border-color:var(--primary);}
.drawer-mask{display:none;position:fixed;top:0;left:0;right:0;bottom:0;background:rgba(0,0,0,0.45);z-index:200;}
.drawer-mask.open{display:block;}
.drawer{position:fixed;top:0;right:-560px;width:560px;height:100%;background:#fff;z-index:201;box-shadow:-4px 0 16px rgba(0,0,0,0.12);transition:right .3s ease;display:flex;flex-direction:column;}
.drawer.open{right:0;}
.drawer__header{display:flex;align-items:center;justify-content:space-between;padding:16px 24px;border-bottom:1px solid var(--border);}
.drawer__title{font-size:var(--font-base);font-weight:600;color:var(--text-primary);}
.drawer__close{width:32px;height:32px;border:none;background:none;cursor:pointer;display:flex;align-items:center;justify-content:center;border-radius:var(--radius-sm);color:var(--text-placeholder);font-size:18px;}
.drawer__close:hover{background:#f5f5f5;color:var(--text-primary);}
.drawer__body{flex:1;overflow-y:auto;padding:24px;}
.drawer__footer{display:flex;align-items:center;justify-content:flex-end;gap:12px;padding:16px 24px;border-top:1px solid var(--border);}
.form-group{margin-bottom:20px;}
.form-label{display:block;font-size:var(--font-sm);color:var(--text-primary);margin-bottom:8px;font-weight:500;}
.form-label .required{color:var(--danger);margin-right:4px;}
.form-control{width:100%;height:36px;border:1px solid var(--border);border-radius:var(--radius-sm);padding:0 12px;font-size:var(--font-sm);color:var(--text-primary);outline:none;background:#fff;}
.form-control:focus{border-color:var(--primary);box-shadow:0 0 0 2px rgba(24,144,255,0.1);}
.form-select{width:100%;height:36px;border:1px solid var(--border);border-radius:var(--radius-sm);padding:0 28px 0 12px;font-size:var(--font-sm);color:var(--text-primary);outline:none;background:#fff url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6'%3E%3Cpath d='M0 0l5 6 5-6z' fill='%23999'/%3E%3C/svg%3E") no-repeat right 10px center;appearance:none;cursor:pointer;}
.form-select:focus{border-color:var(--primary);box-shadow:0 0 0 2px rgba(24,144,255,0.1);}
.map-picker{width:100%;height:200px;border:1px solid var(--border);border-radius:var(--radius-sm);background:#f0f2f5;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:8px;color:var(--text-placeholder);cursor:pointer;position:relative;overflow:hidden;}
.map-picker__icon{width:40px;height:40px;border-radius:50%;background:var(--primary-light);display:flex;align-items:center;justify-content:center;}
.map-picker__text{font-size:var(--font-sm);}
.map-picker__pin{position:absolute;top:50%;left:50%;transform:translate(-50%,-100%);display:none;}
.map-picker.selected{background:linear-gradient(135deg,#e6f7ff 0%,#f0f5ff 100%);border-color:var(--primary);}
.map-picker.selected .map-picker__pin{display:block;}
.map-picker.selected .map-picker__icon,.map-picker.selected .map-picker__text{display:none;}
.map-picker__hint{position:absolute;bottom:8px;left:0;right:0;text-align:center;font-size:var(--font-xs);color:var(--text-placeholder);display:none;}
.map-picker.selected .map-picker__hint{display:block;}
</style>
</head>
<body>
@@ -57,10 +104,7 @@
<a href="../exception-dirty.html">异常事件</a>
</nav>
<div class="top-bar__right">
<a class="btn-back" href="../../../index.html">
<svg width="16" height="16" viewBox="0 0 16 16" fill="none"><path d="M10 3L5 8l5 5" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/></svg>
返回首页
</a>
<a class="btn-back" href="../../../index.html"><svg width="16" height="16" viewBox="0 0 16 16" fill="none"><path d="M10 3L5 8l5 5" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/></svg> 返回首页</a>
<div class="avatar"></div>
<span style="color:rgba(255,255,255,0.65);">系统管理员 ▾</span>
</div>
@@ -114,11 +158,125 @@
</div>
</aside>
<main class="main">
<div class="page-placeholder">
<svg width="64" height="64" viewBox="0 0 64 64" fill="none"><rect x="8" y="8" width="48" height="48" rx="8" stroke="#ccc" stroke-width="2"/><path d="M20 32h24M32 20v24" stroke="#ccc" stroke-width="2" stroke-linecap="round"/></svg>
<p>设备列表</p>
<!-- 筛选条件 -->
<div class="filter-bar">
<div class="filter-item"><label>设备编码</label><input class="filter-input" placeholder="请输入设备编码"></div>
<div class="filter-item"><label>设备名称</label><input class="filter-input" placeholder="请输入设备名称"></div>
<div class="filter-item"><label>所属单位</label><select class="filter-select"><option value="">全部</option><option>采油一厂</option><option>采油二厂</option><option>采气厂</option><option>炼化公司</option></select></div>
<div class="filter-item"><label>设备分类</label><select class="filter-select"><option value="">全部</option><option>花粉采样器</option><option>花粉浓度监测仪</option><option>花粉自动计数仪</option><option>综合气象花粉站</option></select></div>
<button class="btn btn-primary">查询</button>
<button class="btn btn-default">重置</button>
</div>
<!-- 操作按钮 -->
<div class="action-bar">
<button class="btn btn-primary" onclick="openDrawer()">+ 新增设备</button>
<button class="btn btn-success">批量入库导入</button>
<button class="btn btn-default">查看导入任务</button>
<button class="btn btn-default">导出列表数据</button>
</div>
<!-- 数据列表 -->
<div class="table-card">
<div class="table-card__content">
<table>
<thead><tr><th>设备名称</th><th>设备编码</th><th>设备分类</th><th>所属单位</th><th>设备位置</th><th>布点日期</th><th>监测时长(天)</th><th>操作</th></tr></thead>
<tbody>
<tr><td>花粉采样器A1</td><td>PL-2024-001</td><td>花粉采样器</td><td>采油一厂</td><td>厂区绿化带东</td><td>2024-03-01</td><td>434</td><td><a class="link" onclick="openDrawer()">编辑</a> <a class="link-danger">删除</a></td></tr>
<tr><td>花粉浓度监测仪A2</td><td>PL-2024-002</td><td>花粉浓度监测仪</td><td>采油一厂</td><td>职工宿舍区花园</td><td>2024-03-15</td><td>420</td><td><a class="link" onclick="openDrawer()">编辑</a> <a class="link-danger">删除</a></td></tr>
<tr><td>花粉计数仪B1</td><td>PL-2024-003</td><td>花粉自动计数仪</td><td>采油二厂</td><td>办公楼南侧绿地</td><td>2024-04-10</td><td>394</td><td><a class="link" onclick="openDrawer()">编辑</a> <a class="link-danger">删除</a></td></tr>
<tr><td>综合花粉站C1</td><td>PL-2024-004</td><td>综合气象花粉站</td><td>采气厂</td><td>厂区中心公园</td><td>2024-05-20</td><td>354</td><td><a class="link" onclick="openDrawer()">编辑</a> <a class="link-danger">删除</a></td></tr>
<tr><td>花粉采样器D1</td><td>PL-2025-001</td><td>花粉采样器</td><td>炼化公司</td><td>行政楼前广场</td><td>2025-03-05</td><td>65</td><td><a class="link" onclick="openDrawer()">编辑</a> <a class="link-danger">删除</a></td></tr>
</tbody>
</table>
</div>
<div class="pagination">
<span>共 26 条</span>
<button class="page-btn"></button>
<button class="page-btn active">1</button>
<button class="page-btn">2</button>
<button class="page-btn">3</button>
<button class="page-btn"></button>
</div>
</div>
</main>
<script>function toggleSubgroup(h){h.parentElement.classList.toggle('open');}(function(){var a=document.querySelector('.sidebar-item.active');if(!a)return;var s=a.closest('.sidebar-subgroup');if(s)s.classList.add('open');})();</script>
<!-- 新增设备 - 右侧抽屉弹窗 -->
<div class="drawer-mask" id="drawerMask" onclick="closeDrawer()"></div>
<div class="drawer" id="drawer">
<div class="drawer__header">
<span class="drawer__title">新增设备</span>
<button class="drawer__close" onclick="closeDrawer()">&times;</button>
</div>
<div class="drawer__body">
<div class="form-group">
<label class="form-label"><span class="required">*</span>设备名称</label>
<input class="form-control" placeholder="请输入设备名称">
</div>
<div class="form-group">
<label class="form-label"><span class="required">*</span>设备编码</label>
<input class="form-control" placeholder="请输入设备编码">
</div>
<div class="form-group">
<label class="form-label"><span class="required">*</span>设备分类</label>
<select class="form-select">
<option value="">请选择设备分类</option>
<option>花粉采样器</option>
<option>花粉浓度监测仪</option>
<option>花粉自动计数仪</option>
<option>综合气象花粉站</option>
</select>
</div>
<div class="form-group">
<label class="form-label"><span class="required">*</span>所属单位</label>
<select class="form-select">
<option value="">请选择所属单位</option>
<option>采油一厂</option>
<option>采油二厂</option>
<option>采气厂</option>
<option>炼化公司</option>
</select>
</div>
<div class="form-group">
<label class="form-label"><span class="required">*</span>设备位置</label>
<div class="map-picker selected" onclick="this.classList.toggle('selected')">
<div class="map-picker__icon">
<svg width="20" height="20" viewBox="0 0 20 20" fill="none"><path d="M10 2C6.69 2 4 4.69 4 8c0 4.5 6 10 6 10s6-5.5 6-10c0-3.31-2.69-6-6-6zm0 8a2 2 0 110-4 2 2 0 010 4z" fill="#1890FF"/></svg>
</div>
<div class="map-picker__text">点击地图选择设备位置</div>
<svg class="map-picker__pin" width="160" height="120" viewBox="0 0 160 120">
<rect width="160" height="120" rx="4" fill="#e6f7ff" opacity="0.5"/>
<line x1="0" y1="30" x2="160" y2="30" stroke="#d9d9d9" stroke-width="0.5" stroke-dasharray="4"/>
<line x1="0" y1="60" x2="160" y2="60" stroke="#d9d9d9" stroke-width="0.5" stroke-dasharray="4"/>
<line x1="0" y1="90" x2="160" y2="90" stroke="#d9d9d9" stroke-width="0.5" stroke-dasharray="4"/>
<line x1="40" y1="0" x2="40" y2="120" stroke="#d9d9d9" stroke-width="0.5" stroke-dasharray="4"/>
<line x1="80" y1="0" x2="80" y2="120" stroke="#d9d9d9" stroke-width="0.5" stroke-dasharray="4"/>
<line x1="120" y1="0" x2="120" y2="120" stroke="#d9d9d9" stroke-width="0.5" stroke-dasharray="4"/>
<path d="M80 40C76.69 40 74 42.69 74 46c0 4.5 6 10 6 10s6-5.5 6-10c0-3.31-2.69-6-6-6zm0 8a2 2 0 110-4 2 2 0 010 4z" fill="#1890FF"/>
<circle cx="80" cy="46" r="12" fill="none" stroke="#1890FF" stroke-width="1" opacity="0.3"/>
<circle cx="80" cy="46" r="20" fill="none" stroke="#1890FF" stroke-width="0.5" opacity="0.15"/>
</svg>
<div class="map-picker__hint">点击重新选点</div>
</div>
</div>
<div class="form-group">
<label class="form-label"><span class="required">*</span>详细地址</label>
<input class="form-control" value="陕西省西安市长庆路采油一厂绿化带东侧" placeholder="地图选点后自动带入,可手动修改">
</div>
<div class="form-group">
<label class="form-label"><span class="required">*</span>布点日期</label>
<input class="form-control" type="date" value="2025-05-14">
</div>
</div>
<div class="drawer__footer">
<button class="btn btn-default" onclick="closeDrawer()">取消</button>
<button class="btn btn-primary" onclick="closeDrawer()">确定</button>
</div>
</div>
<script>
function toggleSubgroup(h){h.parentElement.classList.toggle('open');}
(function(){var a=document.querySelector('.sidebar-item.active');if(!a)return;var s=a.closest('.sidebar-subgroup');if(s)s.classList.add('open');})();
function openDrawer(){document.getElementById('drawerMask').classList.add('open');document.getElementById('drawer').classList.add('open');}
function closeDrawer(){document.getElementById('drawerMask').classList.remove('open');document.getElementById('drawer').classList.remove('open');}
</script>
</body>
</html>
@@ -3,7 +3,7 @@
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>健康监测 - 异常报警 | 健康长庆原型</title>
<title>花粉监测 - 异常报警 | 健康长庆原型</title>
<style>
*{box-sizing:border-box;margin:0;padding:0;}
body{font-family:-apple-system,BlinkMacSystemFont,'PingFang SC','Microsoft YaHei',sans-serif;background:#F5F7FA;color:#333;min-width:1280px;}
@@ -40,9 +40,34 @@
.sidebar-subgroup.open>.sidebar-subgroup__body{display:block;}
.sidebar-subgroup__body .sidebar-item{padding-left:36px;font-size:12px;}
.main{margin-left:240px;margin-top:56px;padding:24px;min-height:calc(100vh - 56px);}
.page-placeholder{display:flex;flex-direction:column;align-items:center;justify-content:center;height:calc(100vh - 56px - 48px);color:var(--text-placeholder);gap:12px;}
.page-placeholder svg{opacity:.25;}
.page-placeholder p{font-size:var(--font-base);}
.filter-bar{background:#fff;border-radius:var(--radius-md);padding:20px 24px;margin-bottom:16px;box-shadow:var(--shadow-sm);display:flex;align-items:center;gap:16px;flex-wrap:wrap;}
.filter-item{display:flex;align-items:center;gap:8px;}
.filter-item label{font-size:var(--font-sm);color:var(--text-secondary);white-space:nowrap;}
.filter-input{height:36px;border:1px solid var(--border);border-radius:var(--radius-sm);padding:0 12px;font-size:var(--font-sm);color:var(--text-primary);outline:none;background:#fff;min-width:160px;}
.filter-input:focus{border-color:var(--primary);}
.filter-select{height:36px;border:1px solid var(--border);border-radius:var(--radius-sm);padding:0 28px 0 12px;font-size:var(--font-sm);color:var(--text-primary);outline:none;background:#fff url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6'%3E%3Cpath d='M0 0l5 6 5-6z' fill='%23999'/%3E%3C/svg%3E") no-repeat right 10px center;appearance:none;cursor:pointer;min-width:140px;}
.filter-date{height:36px;border:1px solid var(--border);border-radius:var(--radius-sm);padding:0 12px;font-size:var(--font-sm);color:var(--text-primary);outline:none;background:#fff;width:150px;}
.filter-date:focus{border-color:var(--primary);}
.filter-separator{color:var(--text-placeholder);font-size:var(--font-sm);}
.btn{height:36px;padding:0 16px;border-radius:var(--radius-sm);font-size:var(--font-sm);cursor:pointer;border:none;transition:all .2s;display:inline-flex;align-items:center;gap:6px;}
.btn-primary{background:var(--primary);color:#fff;}.btn-primary:hover{background:#40a9ff;}
.btn-default{background:#fff;color:var(--text-primary);border:1px solid var(--border);}.btn-default:hover{color:var(--primary);border-color:var(--primary);}
.action-bar{display:flex;align-items:center;gap:12px;margin-bottom:16px;}
.table-card{background:#fff;border-radius:var(--radius-md);box-shadow:var(--shadow-sm);overflow:hidden;}
.table-card__content{overflow-x:auto;-webkit-overflow-scrolling:touch;}
table{width:100%;border-collapse:collapse;min-width:1100px;}
thead th{background:#FAFAFA;padding:12px 14px;text-align:center;font-size:var(--font-xs);color:var(--text-secondary);font-weight:500;border-bottom:1px solid var(--border);border-right:1px solid var(--border);white-space:nowrap;}
thead th:last-child{border-right:none;}
thead th.th-left{text-align:left;}
tbody td{padding:12px 14px;font-size:var(--font-xs);color:var(--text-primary);border-bottom:1px solid var(--border);text-align:center;white-space:nowrap;}
tbody td.td-left{text-align:left;}
tbody tr:last-child td{border-bottom:none;}
tbody tr:hover{background:#F8FBFF;}
.danger-text{color:var(--danger);font-weight:500;}
.pagination{display:flex;align-items:center;justify-content:flex-end;padding:16px 24px;gap:8px;border-top:1px solid var(--border);}
.pagination span{font-size:var(--font-sm);color:var(--text-secondary);}
.page-btn{width:32px;height:32px;border:1px solid var(--border);border-radius:var(--radius-sm);background:#fff;cursor:pointer;font-size:var(--font-sm);display:inline-flex;align-items:center;justify-content:center;transition:all .2s;}
.page-btn:hover,.page-btn.active{background:var(--primary);color:#fff;border-color:var(--primary);}
</style>
</head>
<body>
@@ -57,10 +82,7 @@
<a href="../exception-dirty.html">异常事件</a>
</nav>
<div class="top-bar__right">
<a class="btn-back" href="../../../index.html">
<svg width="16" height="16" viewBox="0 0 16 16" fill="none"><path d="M10 3L5 8l5 5" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/></svg>
返回首页
</a>
<a class="btn-back" href="../../../index.html"><svg width="16" height="16" viewBox="0 0 16 16" fill="none"><path d="M10 3L5 8l5 5" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/></svg> 返回首页</a>
<div class="avatar"></div>
<span style="color:rgba(255,255,255,0.65);">系统管理员 ▾</span>
</div>
@@ -114,11 +136,108 @@
</div>
</aside>
<main class="main">
<div class="page-placeholder">
<svg width="64" height="64" viewBox="0 0 64 64" fill="none"><rect x="8" y="8" width="48" height="48" rx="8" stroke="#ccc" stroke-width="2"/><path d="M20 32h24M32 20v24" stroke="#ccc" stroke-width="2" stroke-linecap="round"/></svg>
<p>异常报警</p>
<!-- 筛选条件 -->
<div class="filter-bar">
<div class="filter-item"><label>设备名称</label><input class="filter-input" placeholder="请输入设备名称"></div>
<div class="filter-item"><label>设备编号</label><input class="filter-input" placeholder="请输入设备编号"></div>
<div class="filter-item"><label>所属单位</label>
<select class="filter-select"><option value="">全部</option><option>采油一厂</option><option>采油二厂</option><option>采油三厂</option></select>
</div>
<div class="filter-item"><label>日期范围</label><input class="filter-date" type="date" value="2026-05-01"><span class="filter-separator"></span><input class="filter-date" type="date" value="2026-05-15"></div>
<button class="btn btn-primary">查询</button>
<button class="btn btn-default">重置</button>
</div>
<!-- 操作按钮 -->
<div class="action-bar">
<button class="btn btn-default">导出列表数据</button>
<button class="btn btn-default">查看导出任务</button>
</div>
<!-- 数据列表 -->
<div class="table-card">
<div class="table-card__content">
<table>
<thead>
<tr>
<th class="th-left" style="min-width:150px;">设备名称</th>
<th style="min-width:120px;">设备编号</th>
<th style="min-width:90px;">所属单位</th>
<th style="min-width:140px;">设备位置</th>
<th style="min-width:80px;">监测类型</th>
<th style="min-width:80px;">单位</th>
<th style="min-width:70px;">阈值</th>
<th style="min-width:80px;">异常值</th>
<th style="min-width:160px;">报警时间</th>
</tr>
</thead>
<tbody>
<tr>
<td class="td-left">花粉采样器-A03</td>
<td>PL-2024-005</td>
<td>采油三厂</td>
<td>杨树林防护带</td>
<td>花粉浓度</td>
<td>粒/千mm²</td>
<td>800</td>
<td class="danger-text">1098</td>
<td>2026-05-15 08:20:15</td>
</tr>
<tr>
<td class="td-left">综合气象花粉站-D01</td>
<td>PL-2024-004</td>
<td>采油二厂</td>
<td>气象观测场</td>
<td>花粉浓度</td>
<td>粒/千mm²</td>
<td>800</td>
<td class="danger-text">924</td>
<td>2026-05-14 17:10:32</td>
</tr>
<tr>
<td class="td-left">花粉浓度监测仪-B01</td>
<td>PL-2024-002</td>
<td>采油一厂</td>
<td>厂区东侧林带</td>
<td>花粉浓度</td>
<td>粒/千mm²</td>
<td>800</td>
<td class="danger-text">860</td>
<td>2026-05-14 10:35:48</td>
</tr>
<tr>
<td class="td-left">花粉自动计数仪-C01</td>
<td>PL-2024-003</td>
<td>采油二厂</td>
<td>生活区花园</td>
<td>花粉浓度</td>
<td>粒/千mm²</td>
<td>800</td>
<td class="danger-text">1520</td>
<td>2026-05-13 15:42:10</td>
</tr>
<tr>
<td class="td-left">花粉采样器-A01</td>
<td>PL-2024-001</td>
<td>采油一厂</td>
<td>办公区绿化带</td>
<td>花粉浓度</td>
<td>粒/千mm²</td>
<td>800</td>
<td class="danger-text">835</td>
<td>2026-05-13 09:15:27</td>
</tr>
</tbody>
</table>
</div>
<div class="pagination">
<span>共 5 条</span>
<button class="page-btn active">1</button>
</div>
</div>
</main>
<script>function toggleSubgroup(h){h.parentElement.classList.toggle('open');}(function(){var a=document.querySelector('.sidebar-item.active');if(!a)return;var s=a.closest('.sidebar-subgroup');if(s)s.classList.add('open');})();</script>
<script>
function toggleSubgroup(h){h.parentElement.classList.toggle('open');}
(function(){var a=document.querySelector('.sidebar-item.active');if(!a)return;var s=a.closest('.sidebar-subgroup');if(s)s.classList.add('open');})();
</script>
</body>
</html>
</html>
@@ -0,0 +1,132 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>花粉监测 - 异常数据详情 | 健康长庆原型</title>
<style>
*{box-sizing:border-box;margin:0;padding:0;}
body{font-family:-apple-system,BlinkMacSystemFont,'PingFang SC','Microsoft YaHei',sans-serif;background:#F5F7FA;color:#333;min-width:1280px;}
:root{--primary:#1890FF;--primary-light:#E6F7FF;--success:#52C41A;--warning:#FAAD14;--danger:#FF4D4F;--text-primary:#333;--text-secondary:#666;--text-placeholder:#999;--border:#E8E8E8;--background:#F5F7FA;--font-xs:11px;--font-sm:13px;--font-base:15px;--font-lg:17px;--radius-sm:4px;--radius-md:8px;--radius-lg:12px;--shadow-sm:0 1px 4px rgba(0,0,0,0.08);}
.top-bar{display:flex;align-items:center;height:56px;background:#001529;padding:0 24px;position:fixed;top:0;left:0;right:0;z-index:100;}
.top-bar__logo{display:flex;align-items:center;gap:8px;color:#fff;font-size:var(--font-lg);font-weight:600;white-space:nowrap;width:240px;flex-shrink:0;}
.top-bar__logo svg{width:28px;height:28px;}
.top-bar__right{display:flex;align-items:center;gap:16px;color:rgba(255,255,255,0.65);font-size:var(--font-sm);}
.btn-back{color:rgba(255,255,255,0.65);cursor:pointer;display:flex;align-items:center;gap:4px;text-decoration:none;}.btn-back:hover{color:#fff;}
.avatar{width:32px;height:32px;border-radius:50%;background:#1890FF;display:flex;align-items:center;justify-content:center;color:#fff;font-size:var(--font-sm);cursor:pointer;}
.top-bar__nav{display:flex;align-items:center;gap:4px;flex:1;}
.top-bar__nav a{color:rgba(255,255,255,0.65);text-decoration:none;padding:6px 16px;border-radius:var(--radius-sm);font-size:var(--font-sm);transition:all .2s;}
.top-bar__nav a:hover{color:#fff;background:rgba(255,255,255,0.08);}
.top-bar__nav a.active{color:#fff;background:var(--primary);}
.sidebar{position:fixed;top:56px;left:0;bottom:0;width:240px;background:#001529;overflow-y:auto;z-index:90;padding-top:8px;}
.sidebar-menu__title{color:rgba(255,255,255,0.35);font-size:var(--font-xs);padding:16px 24px 8px;letter-spacing:.5px;}
.sidebar-item{display:flex;align-items:center;gap:8px;padding:10px 24px;color:rgba(255,255,255,0.65);font-size:var(--font-sm);cursor:pointer;transition:all .15s;text-decoration:none;}
.sidebar-item:hover{color:#fff;background:rgba(255,255,255,0.06);}
.sidebar-item.active{color:#fff;background:var(--primary);}
.sidebar-subgroup__header{display:flex;align-items:center;gap:6px;padding:10px 24px;color:rgba(255,255,255,0.65);font-size:var(--font-sm);cursor:pointer;transition:all .15s;user-select:none;}
.sidebar-subgroup__header:hover{color:rgba(255,255,255,0.85);background:rgba(255,255,255,0.04);}
.sidebar-subgroup__header .arrow{width:10px;height:10px;transition:transform .2s;flex-shrink:0;}
.sidebar-subgroup__header .arrow path{stroke:rgba(255,255,255,0.45);}
.sidebar-subgroup.open>.sidebar-subgroup__header{color:rgba(255,255,255,0.85);}
.sidebar-subgroup.open>.sidebar-subgroup__header .arrow{transform:rotate(90deg);}
.sidebar-subgroup__body{display:none;padding-left:16px;}
.sidebar-subgroup.open>.sidebar-subgroup__body{display:block;}
.sidebar-subgroup__body .sidebar-item{padding-left:36px;font-size:12px;}
.main{margin-left:240px;margin-top:56px;padding:24px;min-height:calc(100vh - 56px);}
.page-header{display:flex;align-items:center;gap:12px;margin-bottom:16px;}
.page-header__back{display:flex;align-items:center;gap:4px;color:var(--text-secondary);font-size:var(--font-sm);cursor:pointer;text-decoration:none;}.page-header__back:hover{color:var(--primary);}
.page-header__title{font-size:var(--font-lg);font-weight:600;color:var(--text-primary);}
.info-card{background:#fff;border-radius:var(--radius-md);padding:20px 24px;margin-bottom:16px;box-shadow:var(--shadow-sm);display:grid;grid-template-columns:repeat(3,1fr);gap:16px 24px;}
.info-card__item{display:flex;align-items:baseline;gap:8px;min-width:0;}
.info-card__label{font-size:var(--font-xs);color:var(--text-placeholder);white-space:nowrap;flex-shrink:0;}
.info-card__value{font-size:var(--font-sm);color:var(--text-primary);font-weight:500;word-break:break-all;}
.filter-bar{background:#fff;border-radius:var(--radius-md);padding:20px 24px;margin-bottom:16px;box-shadow:var(--shadow-sm);display:flex;align-items:center;gap:16px;flex-wrap:wrap;}
.filter-item{display:flex;align-items:center;gap:8px;}
.filter-item label{font-size:var(--font-sm);color:var(--text-secondary);white-space:nowrap;}
.filter-date{height:36px;border:1px solid var(--border);border-radius:var(--radius-sm);padding:0 12px;font-size:var(--font-sm);color:var(--text-primary);outline:none;background:#fff;width:150px;}.filter-date:focus{border-color:var(--primary);}
.filter-select{height:36px;border:1px solid var(--border);border-radius:var(--radius-sm);padding:0 28px 0 12px;font-size:var(--font-sm);color:var(--text-primary);outline:none;background:#fff url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6'%3E%3Cpath d='M0 0l5 6 5-6z' fill='%23999'/%3E%3C/svg%3E") no-repeat right 10px center;appearance:none;cursor:pointer;min-width:140px;}
.filter-separator{color:var(--text-placeholder);font-size:var(--font-sm);}
.btn{height:36px;padding:0 16px;border-radius:var(--radius-sm);font-size:var(--font-sm);cursor:pointer;border:none;transition:all .2s;display:inline-flex;align-items:center;gap:6px;}
.btn-primary{background:var(--primary);color:#fff;}.btn-primary:hover{background:#40a9ff;}
.btn-default{background:#fff;color:var(--text-primary);border:1px solid var(--border);}.btn-default:hover{color:var(--primary);border-color:var(--primary);}
.action-bar{display:flex;align-items:center;gap:12px;margin-bottom:16px;}
.table-card{background:#fff;border-radius:var(--radius-md);box-shadow:var(--shadow-sm);overflow:hidden;}
.table-card__content{overflow-x:auto;-webkit-overflow-scrolling:touch;}
table{width:100%;border-collapse:collapse;min-width:900px;}
thead th{background:#FAFAFA;padding:12px 14px;text-align:center;font-size:var(--font-xs);color:var(--text-secondary);font-weight:500;border-bottom:1px solid var(--border);border-right:1px solid var(--border);white-space:nowrap;}
thead th:last-child{border-right:none;}
tbody td{padding:12px 14px;font-size:var(--font-xs);color:var(--text-primary);border-bottom:1px solid var(--border);text-align:center;white-space:nowrap;}
tbody tr:last-child td{border-bottom:none;}
tbody tr:hover{background:#F8FBFF;}
.danger-text{color:var(--danger);font-weight:500;}
.pagination{display:flex;align-items:center;justify-content:flex-end;padding:16px 24px;gap:8px;border-top:1px solid var(--border);}
.pagination span{font-size:var(--font-sm);color:var(--text-secondary);}
.page-btn{width:32px;height:32px;border:1px solid var(--border);border-radius:var(--radius-sm);background:#fff;cursor:pointer;font-size:var(--font-sm);display:inline-flex;align-items:center;justify-content:center;transition:all .2s;}
.page-btn:hover,.page-btn.active{background:var(--primary);color:#fff;border-color:var(--primary);}
</style>
</head>
<body>
<div class="top-bar">
<div class="top-bar__logo"><svg viewBox="0 0 28 28" fill="none"><rect width="28" height="28" rx="6" fill="#1890FF"/><path d="M7 14h14M14 7v14" stroke="#fff" stroke-width="2.5" stroke-linecap="round"/></svg> 健康监测</div>
<nav class="top-bar__nav"><a href="../archive-personal.html">档案</a><a href="../health-checkup/survey-category.html">健康排查</a><a href="../wearable/tool-manage.html">穿戴监测</a><a href="../weight/scale-device.html">体重监测</a><a href="../environment/indoor-device-list.html" class="active">环境监测</a><a href="../exception-dirty.html">异常事件</a></nav>
<div class="top-bar__right"><a class="btn-back" href="../../../index.html"><svg width="16" height="16" viewBox="0 0 16 16" fill="none"><path d="M10 3L5 8l5 5" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/></svg> 返回首页</a><div class="avatar"></div><span style="color:rgba(255,255,255,0.65);">系统管理员 ▾</span></div>
</div>
<aside class="sidebar">
<div class="sidebar-menu__title">环境监测</div>
<div class="sidebar-subgroup"><div class="sidebar-subgroup__header" onclick="toggleSubgroup(this)"><svg class="arrow" viewBox="0 0 12 12"><path d="M4 2l4 4-4 4" fill="none" stroke-width="1.5" stroke-linecap="round"/></svg> 室内空气</div><div class="sidebar-subgroup__body"><a href="indoor-device-list.html" class="sidebar-item">设备列表</a><a href="indoor-device-category.html" class="sidebar-item">设备分类</a><a href="indoor-data-monitor.html" class="sidebar-item">数据监测</a><a href="indoor-exception-alarm.html" class="sidebar-item">异常报警</a><a href="indoor-app-record.html" class="sidebar-item">应用记录</a><a href="indoor-history-data.html" class="sidebar-item">历史数据</a></div></div>
<div class="sidebar-subgroup"><div class="sidebar-subgroup__header" onclick="toggleSubgroup(this)"><svg class="arrow" viewBox="0 0 12 12"><path d="M4 2l4 4-4 4" fill="none" stroke-width="1.5" stroke-linecap="round"/></svg> 室外空气</div><div class="sidebar-subgroup__body"><a href="outdoor-device-list.html" class="sidebar-item">设备列表</a><a href="outdoor-device-category.html" class="sidebar-item">设备分类</a><a href="outdoor-data-monitor.html" class="sidebar-item">数据监测</a><a href="outdoor-exception-alarm.html" class="sidebar-item">异常报警</a><a href="outdoor-app-record.html" class="sidebar-item">应用记录</a><a href="outdoor-history-data.html" class="sidebar-item">历史数据</a></div></div>
<div class="sidebar-subgroup"><div class="sidebar-subgroup__header" onclick="toggleSubgroup(this)"><svg class="arrow" viewBox="0 0 12 12"><path d="M4 2l4 4-4 4" fill="none" stroke-width="1.5" stroke-linecap="round"/></svg> 水质监测</div><div class="sidebar-subgroup__body"><a href="water-device-list.html" class="sidebar-item">设备列表</a><a href="water-device-category.html" class="sidebar-item">设备分类</a><a href="water-data-monitor.html" class="sidebar-item">数据监测</a><a href="water-exception-alarm.html" class="sidebar-item">异常报警</a><a href="water-app-record.html" class="sidebar-item">应用记录</a><a href="water-history-data.html" class="sidebar-item">历史数据</a></div></div>
<div class="sidebar-subgroup open"><div class="sidebar-subgroup__header" onclick="toggleSubgroup(this)"><svg class="arrow" viewBox="0 0 12 12"><path d="M4 2l4 4-4 4" fill="none" stroke-width="1.5" stroke-linecap="round"/></svg> 花粉监测</div><div class="sidebar-subgroup__body"><a href="pollen-device-list.html" class="sidebar-item">设备列表</a><a href="pollen-device-category.html" class="sidebar-item">设备分类</a><a href="pollen-data-monitor.html" class="sidebar-item">数据监测</a><a href="pollen-exception-alarm.html" class="sidebar-item">异常报警</a><a href="pollen-app-record.html" class="sidebar-item">应用记录</a><a href="pollen-history-data.html" class="sidebar-item active">历史数据</a><a href="pollen-knowledge.html" class="sidebar-item">知识科普</a></div></div>
</aside>
<main class="main">
<div class="page-header">
<a class="page-header__back" href="pollen-history-data.html"><svg width="14" height="14" viewBox="0 0 16 16" fill="none"><path d="M10 3L5 8l5 5" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/></svg> 返回</a>
<span class="page-header__title">异常数据详情</span>
</div>
<div class="info-card">
<div class="info-card__item"><span class="info-card__label">设备名称</span><span class="info-card__value">花粉自动监测仪-A01</span></div>
<div class="info-card__item"><span class="info-card__label">设备编码</span><span class="info-card__value">PL-2024-001</span></div>
<div class="info-card__item"><span class="info-card__label">所属单位</span><span class="info-card__value">采油一厂</span></div>
<div class="info-card__item"><span class="info-card__label">设备位置</span><span class="info-card__value">厂区绿化带东侧</span></div>
<div class="info-card__item"><span class="info-card__label">监测日期</span><span class="info-card__value">2026-03-01 ~ 2026-05-15</span></div>
<div class="info-card__item"><span class="info-card__label">监测时长</span><span class="info-card__value">76 天</span></div>
</div>
<div class="filter-bar">
<div class="filter-item"><label>监测日期</label><input class="filter-date" type="date" value="2026-05-01"><span class="filter-separator"></span><input class="filter-date" type="date" value="2026-05-15"></div>
<div class="filter-item"><label>监测类型</label>
<select class="filter-select"><option value="">全部</option><option>花粉浓度</option></select>
</div>
<button class="btn btn-primary">查询</button>
<button class="btn btn-default">重置</button>
</div>
<div class="action-bar"><button class="btn btn-default">导出列表数据</button></div>
<div class="table-card">
<div class="table-card__content">
<table>
<thead><tr>
<th style="min-width:90px;">监测类型</th>
<th style="min-width:90px;">单位</th>
<th style="min-width:80px;">阈值上限</th>
<th style="min-width:80px;">阈值下限</th>
<th style="min-width:80px;">异常值</th>
<th style="min-width:160px;">报警时间</th>
</tr></thead>
<tbody>
<tr><td>花粉浓度</td><td>粒/千mm²</td><td>800</td><td></td><td class="danger-text">952</td><td>2026-05-15 07:45:12</td></tr>
<tr><td>花粉浓度</td><td>粒/千mm²</td><td>800</td><td></td><td class="danger-text">1125</td><td>2026-05-14 14:32:08</td></tr>
<tr><td>花粉浓度</td><td>粒/千mm²</td><td>800</td><td></td><td class="danger-text">886</td><td>2026-05-13 16:20:45</td></tr>
<tr><td>花粉浓度</td><td>粒/千mm²</td><td>800</td><td></td><td class="danger-text">1042</td><td>2026-05-12 09:15:33</td></tr>
<tr><td>花粉浓度</td><td>粒/千mm²</td><td>800</td><td></td><td class="danger-text">918</td><td>2026-05-11 15:08:22</td></tr>
<tr><td>花粉浓度</td><td>粒/千mm²</td><td>800</td><td></td><td class="danger-text">845</td><td>2026-05-10 11:42:56</td></tr>
</tbody>
</table>
</div>
<div class="pagination"><span>共 6 条</span><button class="page-btn active">1</button></div>
</div>
</main>
<script>
function toggleSubgroup(h){h.parentElement.classList.toggle('open');}
(function(){var a=document.querySelector('.sidebar-item.active');if(!a)return;var s=a.closest('.sidebar-subgroup');if(s)s.classList.add('open');})();
</script>
</body>
</html>
@@ -3,23 +3,16 @@
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>健康监测 - 历史数据 | 健康长庆原型</title>
<title>花粉监测 - 历史数据 | 健康长庆原型</title>
<style>
*{box-sizing:border-box;margin:0;padding:0;}
body{font-family:-apple-system,BlinkMacSystemFont,'PingFang SC','Microsoft YaHei',sans-serif;background:#F5F7FA;color:#333;min-width:1280px;}
:root{
--primary:#1890FF;--primary-light:#E6F7FF;--success:#52C41A;--warning:#FAAD14;--danger:#FF4D4F;
--text-primary:#333;--text-secondary:#666;--text-placeholder:#999;--border:#E8E8E8;--background:#F5F7FA;
--font-xs:11px;--font-sm:13px;--font-base:15px;--font-lg:17px;
--radius-sm:4px;--radius-md:8px;--radius-lg:12px;
--shadow-sm:0 1px 4px rgba(0,0,0,0.08);
}
:root{--primary:#1890FF;--primary-light:#E6F7FF;--success:#52C41A;--warning:#FAAD14;--danger:#FF4D4F;--text-primary:#333;--text-secondary:#666;--text-placeholder:#999;--border:#E8E8E8;--background:#F5F7FA;--font-xs:11px;--font-sm:13px;--font-base:15px;--font-lg:17px;--radius-sm:4px;--radius-md:8px;--radius-lg:12px;--shadow-sm:0 1px 4px rgba(0,0,0,0.08);}
.top-bar{display:flex;align-items:center;height:56px;background:#001529;padding:0 24px;position:fixed;top:0;left:0;right:0;z-index:100;}
.top-bar__logo{display:flex;align-items:center;gap:8px;color:#fff;font-size:var(--font-lg);font-weight:600;white-space:nowrap;width:240px;flex-shrink:0;}
.top-bar__logo svg{width:28px;height:28px;}
.top-bar__right{display:flex;align-items:center;gap:16px;color:rgba(255,255,255,0.65);font-size:var(--font-sm);}
.btn-back{color:rgba(255,255,255,0.65);cursor:pointer;display:flex;align-items:center;gap:4px;text-decoration:none;}
.btn-back:hover{color:#fff;}
.btn-back{color:rgba(255,255,255,0.65);cursor:pointer;display:flex;align-items:center;gap:4px;text-decoration:none;}.btn-back:hover{color:#fff;}
.avatar{width:32px;height:32px;border-radius:50%;background:#1890FF;display:flex;align-items:center;justify-content:center;color:#fff;font-size:var(--font-sm);cursor:pointer;}
.top-bar__nav{display:flex;align-items:center;gap:4px;flex:1;}
.top-bar__nav a{color:rgba(255,255,255,0.65);text-decoration:none;padding:6px 16px;border-radius:var(--radius-sm);font-size:var(--font-sm);transition:all .2s;}
@@ -40,85 +33,73 @@
.sidebar-subgroup.open>.sidebar-subgroup__body{display:block;}
.sidebar-subgroup__body .sidebar-item{padding-left:36px;font-size:12px;}
.main{margin-left:240px;margin-top:56px;padding:24px;min-height:calc(100vh - 56px);}
.page-placeholder{display:flex;flex-direction:column;align-items:center;justify-content:center;height:calc(100vh - 56px - 48px);color:var(--text-placeholder);gap:12px;}
.page-placeholder svg{opacity:.25;}
.page-placeholder p{font-size:var(--font-base);}
.filter-bar{background:#fff;border-radius:var(--radius-md);padding:20px 24px;margin-bottom:16px;box-shadow:var(--shadow-sm);display:flex;align-items:center;gap:16px;flex-wrap:wrap;}
.filter-item{display:flex;align-items:center;gap:8px;}
.filter-item label{font-size:var(--font-sm);color:var(--text-secondary);white-space:nowrap;}
.filter-input{height:36px;border:1px solid var(--border);border-radius:var(--radius-sm);padding:0 12px;font-size:var(--font-sm);color:var(--text-primary);outline:none;background:#fff;min-width:180px;}.filter-input:focus{border-color:var(--primary);}
.filter-select{height:36px;border:1px solid var(--border);border-radius:var(--radius-sm);padding:0 28px 0 12px;font-size:var(--font-sm);color:var(--text-primary);outline:none;background:#fff url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6'%3E%3Cpath d='M0 0l5 6 5-6z' fill='%23999'/%3E%3C/svg%3E") no-repeat right 10px center;appearance:none;cursor:pointer;min-width:140px;}
.btn{height:36px;padding:0 16px;border-radius:var(--radius-sm);font-size:var(--font-sm);cursor:pointer;border:none;transition:all .2s;display:inline-flex;align-items:center;gap:6px;}
.btn-primary{background:var(--primary);color:#fff;}.btn-primary:hover{background:#40a9ff;}
.btn-default{background:#fff;color:var(--text-primary);border:1px solid var(--border);}.btn-default:hover{color:var(--primary);border-color:var(--primary);}
.action-bar{display:flex;align-items:center;gap:12px;margin-bottom:16px;}
.table-card{background:#fff;border-radius:var(--radius-md);box-shadow:var(--shadow-sm);overflow:hidden;}
.table-card__content{overflow-x:auto;-webkit-overflow-scrolling:touch;}
table{width:100%;border-collapse:collapse;min-width:1000px;}
thead th{background:#FAFAFA;padding:12px 14px;text-align:center;font-size:var(--font-xs);color:var(--text-secondary);font-weight:500;border-bottom:1px solid var(--border);border-right:1px solid var(--border);white-space:nowrap;}
thead th:last-child{border-right:none;}
thead th.th-left{text-align:left;}
tbody td{padding:12px 14px;font-size:var(--font-xs);color:var(--text-primary);border-bottom:1px solid var(--border);text-align:center;white-space:nowrap;}
tbody td.td-left{text-align:left;}
tbody tr:last-child td{border-bottom:none;}
tbody tr:hover{background:#F8FBFF;}
.link-btn{color:var(--primary);cursor:pointer;text-decoration:none;font-size:var(--font-xs);}.link-btn:hover{text-decoration:underline;}
.pagination{display:flex;align-items:center;justify-content:flex-end;padding:16px 24px;gap:8px;border-top:1px solid var(--border);}
.pagination span{font-size:var(--font-sm);color:var(--text-secondary);}
.page-btn{width:32px;height:32px;border:1px solid var(--border);border-radius:var(--radius-sm);background:#fff;cursor:pointer;font-size:var(--font-sm);display:inline-flex;align-items:center;justify-content:center;transition:all .2s;}
.page-btn:hover,.page-btn.active{background:var(--primary);color:#fff;border-color:var(--primary);}
</style>
</head>
<body>
<div class="top-bar">
<div class="top-bar__logo"><svg viewBox="0 0 28 28" fill="none"><rect width="28" height="28" rx="6" fill="#1890FF"/><path d="M7 14h14M14 7v14" stroke="#fff" stroke-width="2.5" stroke-linecap="round"/></svg> 健康监测</div>
<nav class="top-bar__nav">
<a href="../archive-personal.html">档案</a>
<a href="../health-checkup/survey-category.html">健康排查</a>
<a href="../wearable/tool-manage.html">穿戴监测</a>
<a href="../weight/scale-device.html">体重监测</a>
<a href="../environment/indoor-device-list.html" class="active">环境监测</a>
<a href="../exception-dirty.html">异常事件</a>
</nav>
<div class="top-bar__right">
<a class="btn-back" href="../../../index.html">
<svg width="16" height="16" viewBox="0 0 16 16" fill="none"><path d="M10 3L5 8l5 5" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/></svg>
返回首页
</a>
<div class="avatar"></div>
<span style="color:rgba(255,255,255,0.65);">系统管理员 ▾</span>
</div>
<nav class="top-bar__nav"><a href="../archive-personal.html">档案</a><a href="../health-checkup/survey-category.html">健康排查</a><a href="../wearable/tool-manage.html">穿戴监测</a><a href="../weight/scale-device.html">体重监测</a><a href="../environment/indoor-device-list.html" class="active">环境监测</a><a href="../exception-dirty.html">异常事件</a></nav>
<div class="top-bar__right"><a class="btn-back" href="../../../index.html"><svg width="16" height="16" viewBox="0 0 16 16" fill="none"><path d="M10 3L5 8l5 5" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/></svg> 返回首页</a><div class="avatar"></div><span style="color:rgba(255,255,255,0.65);">系统管理员 ▾</span></div>
</div>
<aside class="sidebar">
<div class="sidebar-menu__title">环境监测</div>
<div class="sidebar-subgroup">
<div class="sidebar-subgroup__header" onclick="toggleSubgroup(this)"><svg class="arrow" viewBox="0 0 12 12"><path d="M4 2l4 4-4 4" fill="none" stroke-width="1.5" stroke-linecap="round"/></svg>空气</div>
<div class="sidebar-subgroup__body">
<a href="indoor-device-list.html" class="sidebar-item">设备列表</a>
<a href="indoor-device-category.html" class="sidebar-item">设备分类</a>
<a href="indoor-data-monitor.html" class="sidebar-item">数据监测</a>
<a href="indoor-exception-alarm.html" class="sidebar-item">异常报警</a>
<a href="indoor-app-record.html" class="sidebar-item">应用记录</a>
<a href="indoor-history-data.html" class="sidebar-item">历史数据</a>
</div>
</div>
<div class="sidebar-subgroup">
<div class="sidebar-subgroup__header" onclick="toggleSubgroup(this)"><svg class="arrow" viewBox="0 0 12 12"><path d="M4 2l4 4-4 4" fill="none" stroke-width="1.5" stroke-linecap="round"/></svg> 室外空气</div>
<div class="sidebar-subgroup__body">
<a href="outdoor-device-list.html" class="sidebar-item">设备列表</a>
<a href="outdoor-device-category.html" class="sidebar-item">设备分类</a>
<a href="outdoor-data-monitor.html" class="sidebar-item">数据监测</a>
<a href="outdoor-exception-alarm.html" class="sidebar-item">异常报警</a>
<a href="outdoor-app-record.html" class="sidebar-item">应用记录</a>
<a href="outdoor-history-data.html" class="sidebar-item">历史数据</a>
</div>
</div>
<div class="sidebar-subgroup">
<div class="sidebar-subgroup__header" onclick="toggleSubgroup(this)"><svg class="arrow" viewBox="0 0 12 12"><path d="M4 2l4 4-4 4" fill="none" stroke-width="1.5" stroke-linecap="round"/></svg> 水质监测</div>
<div class="sidebar-subgroup__body">
<a href="water-device-list.html" class="sidebar-item">设备列表</a>
<a href="water-device-category.html" class="sidebar-item">设备分类</a>
<a href="water-data-monitor.html" class="sidebar-item">数据监测</a>
<a href="water-exception-alarm.html" class="sidebar-item">异常报警</a>
<a href="water-app-record.html" class="sidebar-item">应用记录</a>
<a href="water-history-data.html" class="sidebar-item">历史数据</a>
</div>
</div>
<div class="sidebar-subgroup open">
<div class="sidebar-subgroup__header" onclick="toggleSubgroup(this)"><svg class="arrow" viewBox="0 0 12 12"><path d="M4 2l4 4-4 4" fill="none" stroke-width="1.5" stroke-linecap="round"/></svg> 花粉监测</div>
<div class="sidebar-subgroup__body">
<a href="pollen-device-list.html" class="sidebar-item">设备列表</a>
<a href="pollen-device-category.html" class="sidebar-item">设备分类</a>
<a href="pollen-data-monitor.html" class="sidebar-item">数据监测</a>
<a href="pollen-exception-alarm.html" class="sidebar-item">异常报警</a>
<a href="pollen-app-record.html" class="sidebar-item">应用记录</a>
<a href="pollen-history-data.html" class="sidebar-item active">历史数据</a>
<a href="pollen-knowledge.html" class="sidebar-item">知识科普</a>
</div>
</div>
<div class="sidebar-subgroup"><div class="sidebar-subgroup__header" onclick="toggleSubgroup(this)"><svg class="arrow" viewBox="0 0 12 12"><path d="M4 2l4 4-4 4" fill="none" stroke-width="1.5" stroke-linecap="round"/></svg> 室内空气</div><div class="sidebar-subgroup__body"><a href="indoor-device-list.html" class="sidebar-item">设备列表</a><a href="indoor-device-category.html" class="sidebar-item">设备分类</a><a href="indoor-data-monitor.html" class="sidebar-item">数据监测</a><a href="indoor-exception-alarm.html" class="sidebar-item">异常报警</a><a href="indoor-app-record.html" class="sidebar-item">应用记录</a><a href="indoor-history-data.html" class="sidebar-item">历史数据</a></div></div>
<div class="sidebar-subgroup"><div class="sidebar-subgroup__header" onclick="toggleSubgroup(this)"><svg class="arrow" viewBox="0 0 12 12"><path d="M4 2l4 4-4 4" fill="none" stroke-width="1.5" stroke-linecap="round"/></svg>空气</div><div class="sidebar-subgroup__body"><a href="outdoor-device-list.html" class="sidebar-item">设备列表</a><a href="outdoor-device-category.html" class="sidebar-item">设备分类</a><a href="outdoor-data-monitor.html" class="sidebar-item">数据监测</a><a href="outdoor-exception-alarm.html" class="sidebar-item">异常报警</a><a href="outdoor-app-record.html" class="sidebar-item">应用记录</a><a href="outdoor-history-data.html" class="sidebar-item">历史数据</a></div></div>
<div class="sidebar-subgroup"><div class="sidebar-subgroup__header" onclick="toggleSubgroup(this)"><svg class="arrow" viewBox="0 0 12 12"><path d="M4 2l4 4-4 4" fill="none" stroke-width="1.5" stroke-linecap="round"/></svg> 水质监测</div><div class="sidebar-subgroup__body"><a href="water-device-list.html" class="sidebar-item">设备列表</a><a href="water-device-category.html" class="sidebar-item">设备分类</a><a href="water-data-monitor.html" class="sidebar-item">数据监测</a><a href="water-exception-alarm.html" class="sidebar-item">异常报警</a><a href="water-app-record.html" class="sidebar-item">应用记录</a><a href="water-history-data.html" class="sidebar-item">历史数据</a></div></div>
<div class="sidebar-subgroup open"><div class="sidebar-subgroup__header" onclick="toggleSubgroup(this)"><svg class="arrow" viewBox="0 0 12 12"><path d="M4 2l4 4-4 4" fill="none" stroke-width="1.5" stroke-linecap="round"/></svg> 花粉监测</div><div class="sidebar-subgroup__body"><a href="pollen-device-list.html" class="sidebar-item">设备列表</a><a href="pollen-device-category.html" class="sidebar-item">设备分类</a><a href="pollen-data-monitor.html" class="sidebar-item">数据监测</a><a href="pollen-exception-alarm.html" class="sidebar-item">异常报警</a><a href="pollen-app-record.html" class="sidebar-item">应用记录</a><a href="pollen-history-data.html" class="sidebar-item active">历史数据</a><a href="pollen-knowledge.html" class="sidebar-item">知识科普</a></div></div>
</aside>
<main class="main">
<div class="page-placeholder">
<svg width="64" height="64" viewBox="0 0 64 64" fill="none"><rect x="8" y="8" width="48" height="48" rx="8" stroke="#ccc" stroke-width="2"/><path d="M20 32h24M32 20v24" stroke="#ccc" stroke-width="2" stroke-linecap="round"/></svg>
<p>历史数据</p>
<div class="filter-bar">
<div class="filter-item"><label>设备名称</label><input class="filter-input" placeholder="请输入设备名称"></div>
<div class="filter-item"><label>设备编码</label><input class="filter-input" placeholder="请输入设备编码"></div>
<div class="filter-item"><label>所属单位</label><select class="filter-select"><option value="">全部</option><option>采油一厂</option><option>采油二厂</option><option>采油三厂</option></select></div>
<button class="btn btn-primary">查询</button>
<button class="btn btn-default">重置</button>
</div>
<div class="action-bar"><button class="btn btn-default">导出列表数据</button></div>
<div class="table-card">
<div class="table-card__content">
<table>
<thead><tr><th class="th-left" style="min-width:150px;">设备名称</th><th style="min-width:110px;">设备编码</th><th style="min-width:90px;">所属单位</th><th style="min-width:130px;">设备位置</th><th style="min-width:180px;">监测日期</th><th style="min-width:90px;">监测时长(天)</th><th style="min-width:80px;">监测数据</th><th style="min-width:80px;">异常数据</th></tr></thead>
<tbody>
<tr><td class="td-left">花粉自动监测仪-A01</td><td>PL-2024-001</td><td>采油一厂</td><td>厂区绿化带东侧</td><td>2026-03-01 ~ 2026-05-15</td><td>76</td><td><a class="link-btn" href="pollen-history-monitor-detail.html">查看</a></td><td><a class="link-btn" href="pollen-history-alarm-detail.html">查看</a></td></tr>
<tr><td class="td-left">花粉自动监测仪-A02</td><td>PL-2024-002</td><td>采油一厂</td><td>办公区花园</td><td>2026-02-15 ~ 2026-05-15</td><td>89</td><td><a class="link-btn" href="pollen-history-monitor-detail.html">查看</a></td><td><a class="link-btn" href="pollen-history-alarm-detail.html">查看</a></td></tr>
<tr><td class="td-left">花粉自动监测仪-B01</td><td>PL-2024-003</td><td>采油二厂</td><td>生活区公园入口</td><td>2026-04-01 ~ 2026-05-15</td><td>45</td><td><a class="link-btn" href="pollen-history-monitor-detail.html">查看</a></td><td><a class="link-btn" href="pollen-history-alarm-detail.html">查看</a></td></tr>
<tr><td class="td-left">花粉自动监测仪-B02</td><td>PL-2024-004</td><td>采油二厂</td><td>厂区西侧林带</td><td>2026-01-20 ~ 2026-05-15</td><td>115</td><td><a class="link-btn" href="pollen-history-monitor-detail.html">查看</a></td><td><a class="link-btn" href="pollen-history-alarm-detail.html">查看</a></td></tr>
<tr><td class="td-left">花粉自动监测仪-C01</td><td>PL-2024-005</td><td>采油三厂</td><td>运动场周边</td><td>2026-03-10 ~ 2026-05-15</td><td>66</td><td><a class="link-btn" href="pollen-history-monitor-detail.html">查看</a></td><td><a class="link-btn" href="pollen-history-alarm-detail.html">查看</a></td></tr>
</tbody>
</table>
</div>
<div class="pagination"><span>共 5 条</span><button class="page-btn active">1</button></div>
</div>
</main>
<script>function toggleSubgroup(h){h.parentElement.classList.toggle('open');}(function(){var a=document.querySelector('.sidebar-item.active');if(!a)return;var s=a.closest('.sidebar-subgroup');if(s)s.classList.add('open');})();</script>
<script>
function toggleSubgroup(h){h.parentElement.classList.toggle('open');}
(function(){var a=document.querySelector('.sidebar-item.active');if(!a)return;var s=a.closest('.sidebar-subgroup');if(s)s.classList.add('open');})();
</script>
</body>
</html>
</html>
@@ -0,0 +1,142 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>花粉监测 - 监测数据详情 | 健康长庆原型</title>
<style>
*{box-sizing:border-box;margin:0;padding:0;}
body{font-family:-apple-system,BlinkMacSystemFont,'PingFang SC','Microsoft YaHei',sans-serif;background:#F5F7FA;color:#333;min-width:1280px;}
:root{--primary:#1890FF;--primary-light:#E6F7FF;--success:#52C41A;--warning:#FAAD14;--danger:#FF4D4F;--text-primary:#333;--text-secondary:#666;--text-placeholder:#999;--border:#E8E8E8;--background:#F5F7FA;--font-xs:11px;--font-sm:13px;--font-base:15px;--font-lg:17px;--radius-sm:4px;--radius-md:8px;--radius-lg:12px;--shadow-sm:0 1px 4px rgba(0,0,0,0.08);}
.top-bar{display:flex;align-items:center;height:56px;background:#001529;padding:0 24px;position:fixed;top:0;left:0;right:0;z-index:100;}
.top-bar__logo{display:flex;align-items:center;gap:8px;color:#fff;font-size:var(--font-lg);font-weight:600;white-space:nowrap;width:240px;flex-shrink:0;}
.top-bar__logo svg{width:28px;height:28px;}
.top-bar__right{display:flex;align-items:center;gap:16px;color:rgba(255,255,255,0.65);font-size:var(--font-sm);}
.btn-back{color:rgba(255,255,255,0.65);cursor:pointer;display:flex;align-items:center;gap:4px;text-decoration:none;}.btn-back:hover{color:#fff;}
.avatar{width:32px;height:32px;border-radius:50%;background:#1890FF;display:flex;align-items:center;justify-content:center;color:#fff;font-size:var(--font-sm);cursor:pointer;}
.top-bar__nav{display:flex;align-items:center;gap:4px;flex:1;}
.top-bar__nav a{color:rgba(255,255,255,0.65);text-decoration:none;padding:6px 16px;border-radius:var(--radius-sm);font-size:var(--font-sm);transition:all .2s;}
.top-bar__nav a:hover{color:#fff;background:rgba(255,255,255,0.08);}
.top-bar__nav a.active{color:#fff;background:var(--primary);}
.sidebar{position:fixed;top:56px;left:0;bottom:0;width:240px;background:#001529;overflow-y:auto;z-index:90;padding-top:8px;}
.sidebar-menu__title{color:rgba(255,255,255,0.35);font-size:var(--font-xs);padding:16px 24px 8px;letter-spacing:.5px;}
.sidebar-item{display:flex;align-items:center;gap:8px;padding:10px 24px;color:rgba(255,255,255,0.65);font-size:var(--font-sm);cursor:pointer;transition:all .15s;text-decoration:none;}
.sidebar-item:hover{color:#fff;background:rgba(255,255,255,0.06);}
.sidebar-item.active{color:#fff;background:var(--primary);}
.sidebar-subgroup__header{display:flex;align-items:center;gap:6px;padding:10px 24px;color:rgba(255,255,255,0.65);font-size:var(--font-sm);cursor:pointer;transition:all .15s;user-select:none;}
.sidebar-subgroup__header:hover{color:rgba(255,255,255,0.85);background:rgba(255,255,255,0.04);}
.sidebar-subgroup__header .arrow{width:10px;height:10px;transition:transform .2s;flex-shrink:0;}
.sidebar-subgroup__header .arrow path{stroke:rgba(255,255,255,0.45);}
.sidebar-subgroup.open>.sidebar-subgroup__header{color:rgba(255,255,255,0.85);}
.sidebar-subgroup.open>.sidebar-subgroup__header .arrow{transform:rotate(90deg);}
.sidebar-subgroup__body{display:none;padding-left:16px;}
.sidebar-subgroup.open>.sidebar-subgroup__body{display:block;}
.sidebar-subgroup__body .sidebar-item{padding-left:36px;font-size:12px;}
.main{margin-left:240px;margin-top:56px;padding:24px;min-height:calc(100vh - 56px);}
.page-header{display:flex;align-items:center;gap:12px;margin-bottom:16px;}
.page-header__back{display:flex;align-items:center;gap:4px;color:var(--text-secondary);font-size:var(--font-sm);cursor:pointer;text-decoration:none;}.page-header__back:hover{color:var(--primary);}
.page-header__title{font-size:var(--font-lg);font-weight:600;color:var(--text-primary);}
.info-card{background:#fff;border-radius:var(--radius-md);padding:20px 24px;margin-bottom:16px;box-shadow:var(--shadow-sm);display:grid;grid-template-columns:repeat(3,1fr);gap:16px 24px;}
.info-card__item{display:flex;align-items:baseline;gap:8px;min-width:0;}
.info-card__label{font-size:var(--font-xs);color:var(--text-placeholder);white-space:nowrap;flex-shrink:0;}
.info-card__value{font-size:var(--font-sm);color:var(--text-primary);font-weight:500;word-break:break-all;}
.filter-bar{background:#fff;border-radius:var(--radius-md);padding:20px 24px;margin-bottom:16px;box-shadow:var(--shadow-sm);display:flex;align-items:center;gap:16px;flex-wrap:wrap;}
.filter-item{display:flex;align-items:center;gap:8px;}
.filter-item label{font-size:var(--font-sm);color:var(--text-secondary);white-space:nowrap;}
.filter-date{height:36px;border:1px solid var(--border);border-radius:var(--radius-sm);padding:0 12px;font-size:var(--font-sm);color:var(--text-primary);outline:none;background:#fff;width:150px;}.filter-date:focus{border-color:var(--primary);}
.filter-separator{color:var(--text-placeholder);font-size:var(--font-sm);}
.btn{height:36px;padding:0 16px;border-radius:var(--radius-sm);font-size:var(--font-sm);cursor:pointer;border:none;transition:all .2s;display:inline-flex;align-items:center;gap:6px;}
.btn-primary{background:var(--primary);color:#fff;}.btn-primary:hover{background:#40a9ff;}
.btn-default{background:#fff;color:var(--text-primary);border:1px solid var(--border);}.btn-default:hover{color:var(--primary);border-color:var(--primary);}
.action-bar{display:flex;align-items:center;gap:12px;margin-bottom:16px;}
.table-card{background:#fff;border-radius:var(--radius-md);box-shadow:var(--shadow-sm);overflow:hidden;}
.table-card__content{overflow-x:auto;-webkit-overflow-scrolling:touch;}
table{width:100%;border-collapse:collapse;min-width:1100px;}
thead th{background:#FAFAFA;padding:12px 14px;text-align:center;font-size:var(--font-xs);color:var(--text-secondary);font-weight:500;border-bottom:1px solid var(--border);border-right:1px solid var(--border);white-space:nowrap;}
thead th:last-child{border-right:none;}
tbody td{padding:12px 14px;font-size:var(--font-xs);color:var(--text-primary);border-bottom:1px solid var(--border);text-align:center;white-space:nowrap;}
tbody tr:last-child td{border-bottom:none;}
tbody tr:hover{background:#F8FBFF;}
.pagination{display:flex;align-items:center;justify-content:flex-end;padding:16px 24px;gap:8px;border-top:1px solid var(--border);}
.pagination span{font-size:var(--font-sm);color:var(--text-secondary);}
.page-btn{width:32px;height:32px;border:1px solid var(--border);border-radius:var(--radius-sm);background:#fff;cursor:pointer;font-size:var(--font-sm);display:inline-flex;align-items:center;justify-content:center;transition:all .2s;}
.page-btn:hover,.page-btn.active{background:var(--primary);color:#fff;border-color:var(--primary);}
.allergy-tag{display:inline-block;padding:2px 10px;border-radius:10px;font-size:var(--font-xs);font-weight:500;}
.allergy-tag--vlow{background:#F6FFED;color:#52C41A;}
.allergy-tag--low{background:#E6FFFB;color:#13C2C2;}
.allergy-tag--medium{background:#FFFBE6;color:#FAAD14;}
.allergy-tag--high{background:#FFF1F0;color:#FA541C;}
.allergy-tag--vhigh{background:#FFF1F0;color:#FF4D4F;}
</style>
</head>
<body>
<div class="top-bar">
<div class="top-bar__logo"><svg viewBox="0 0 28 28" fill="none"><rect width="28" height="28" rx="6" fill="#1890FF"/><path d="M7 14h14M14 7v14" stroke="#fff" stroke-width="2.5" stroke-linecap="round"/></svg> 健康监测</div>
<nav class="top-bar__nav"><a href="../archive-personal.html">档案</a><a href="../health-checkup/survey-category.html">健康排查</a><a href="../wearable/tool-manage.html">穿戴监测</a><a href="../weight/scale-device.html">体重监测</a><a href="../environment/indoor-device-list.html" class="active">环境监测</a><a href="../exception-dirty.html">异常事件</a></nav>
<div class="top-bar__right"><a class="btn-back" href="../../../index.html"><svg width="16" height="16" viewBox="0 0 16 16" fill="none"><path d="M10 3L5 8l5 5" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/></svg> 返回首页</a><div class="avatar"></div><span style="color:rgba(255,255,255,0.65);">系统管理员 ▾</span></div>
</div>
<aside class="sidebar">
<div class="sidebar-menu__title">环境监测</div>
<div class="sidebar-subgroup"><div class="sidebar-subgroup__header" onclick="toggleSubgroup(this)"><svg class="arrow" viewBox="0 0 12 12"><path d="M4 2l4 4-4 4" fill="none" stroke-width="1.5" stroke-linecap="round"/></svg> 室内空气</div><div class="sidebar-subgroup__body"><a href="indoor-device-list.html" class="sidebar-item">设备列表</a><a href="indoor-device-category.html" class="sidebar-item">设备分类</a><a href="indoor-data-monitor.html" class="sidebar-item">数据监测</a><a href="indoor-exception-alarm.html" class="sidebar-item">异常报警</a><a href="indoor-app-record.html" class="sidebar-item">应用记录</a><a href="indoor-history-data.html" class="sidebar-item">历史数据</a></div></div>
<div class="sidebar-subgroup"><div class="sidebar-subgroup__header" onclick="toggleSubgroup(this)"><svg class="arrow" viewBox="0 0 12 12"><path d="M4 2l4 4-4 4" fill="none" stroke-width="1.5" stroke-linecap="round"/></svg> 室外空气</div><div class="sidebar-subgroup__body"><a href="outdoor-device-list.html" class="sidebar-item">设备列表</a><a href="outdoor-device-category.html" class="sidebar-item">设备分类</a><a href="outdoor-data-monitor.html" class="sidebar-item">数据监测</a><a href="outdoor-exception-alarm.html" class="sidebar-item">异常报警</a><a href="outdoor-app-record.html" class="sidebar-item">应用记录</a><a href="outdoor-history-data.html" class="sidebar-item">历史数据</a></div></div>
<div class="sidebar-subgroup"><div class="sidebar-subgroup__header" onclick="toggleSubgroup(this)"><svg class="arrow" viewBox="0 0 12 12"><path d="M4 2l4 4-4 4" fill="none" stroke-width="1.5" stroke-linecap="round"/></svg> 水质监测</div><div class="sidebar-subgroup__body"><a href="water-device-list.html" class="sidebar-item">设备列表</a><a href="water-device-category.html" class="sidebar-item">设备分类</a><a href="water-data-monitor.html" class="sidebar-item">数据监测</a><a href="water-exception-alarm.html" class="sidebar-item">异常报警</a><a href="water-app-record.html" class="sidebar-item">应用记录</a><a href="water-history-data.html" class="sidebar-item">历史数据</a></div></div>
<div class="sidebar-subgroup open"><div class="sidebar-subgroup__header" onclick="toggleSubgroup(this)"><svg class="arrow" viewBox="0 0 12 12"><path d="M4 2l4 4-4 4" fill="none" stroke-width="1.5" stroke-linecap="round"/></svg> 花粉监测</div><div class="sidebar-subgroup__body"><a href="pollen-device-list.html" class="sidebar-item">设备列表</a><a href="pollen-device-category.html" class="sidebar-item">设备分类</a><a href="pollen-data-monitor.html" class="sidebar-item">数据监测</a><a href="pollen-exception-alarm.html" class="sidebar-item">异常报警</a><a href="pollen-app-record.html" class="sidebar-item">应用记录</a><a href="pollen-history-data.html" class="sidebar-item active">历史数据</a><a href="pollen-knowledge.html" class="sidebar-item">知识科普</a></div></div>
</aside>
<main class="main">
<div class="page-header">
<a class="page-header__back" href="pollen-history-data.html"><svg width="14" height="14" viewBox="0 0 16 16" fill="none"><path d="M10 3L5 8l5 5" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/></svg> 返回</a>
<span class="page-header__title">监测数据详情</span>
</div>
<div class="info-card">
<div class="info-card__item"><span class="info-card__label">设备名称</span><span class="info-card__value">花粉自动监测仪-A01</span></div>
<div class="info-card__item"><span class="info-card__label">设备编码</span><span class="info-card__value">PL-2024-001</span></div>
<div class="info-card__item"><span class="info-card__label">所属单位</span><span class="info-card__value">采油一厂</span></div>
<div class="info-card__item"><span class="info-card__label">设备位置</span><span class="info-card__value">厂区绿化带东侧</span></div>
<div class="info-card__item"><span class="info-card__label">监测日期</span><span class="info-card__value">2026-03-01 ~ 2026-05-15</span></div>
<div class="info-card__item"><span class="info-card__label">监测时长</span><span class="info-card__value">76 天</span></div>
</div>
<div class="filter-bar">
<div class="filter-item"><label>监测日期</label><input class="filter-date" type="date" value="2026-05-01"><span class="filter-separator"></span><input class="filter-date" type="date" value="2026-05-15"></div>
<button class="btn btn-primary">查询</button>
<button class="btn btn-default">重置</button>
</div>
<div class="action-bar"><button class="btn btn-default">导出列表数据</button></div>
<div class="table-card">
<div class="table-card__content">
<table>
<thead><tr>
<th style="min-width:160px;">监测时间</th>
<th style="min-width:90px;">榆属(粒/千mm²)</th>
<th style="min-width:90px;">松属(粒/千mm²)</th>
<th style="min-width:90px;">杨属(粒/千mm²)</th>
<th style="min-width:90px;">柏科(粒/千mm²)</th>
<th style="min-width:90px;">柳属(粒/千mm²)</th>
<th style="min-width:90px;">蒿属(粒/千mm²)</th>
<th style="min-width:90px;">藜科(粒/千mm²)</th>
<th style="min-width:90px;">苋科(粒/千mm²)</th>
<th style="min-width:100px;">花粉总数(粒/千mm²)</th>
<th style="min-width:80px;">过敏等级</th>
</tr></thead>
<tbody>
<tr><td>2026-05-15 08:00:00</td><td>120</td><td>85</td><td>95</td><td>60</td><td>45</td><td>30</td><td>25</td><td>15</td><td>475</td><td><span class="allergy-tag allergy-tag--medium">中等</span></td></tr>
<tr><td>2026-05-15 07:00:00</td><td>110</td><td>78</td><td>88</td><td>55</td><td>42</td><td>28</td><td>22</td><td>12</td><td>435</td><td><span class="allergy-tag allergy-tag--medium">中等</span></td></tr>
<tr><td>2026-05-15 06:00:00</td><td>95</td><td>65</td><td>72</td><td>48</td><td>35</td><td>22</td><td>18</td><td>10</td><td>365</td><td><span class="allergy-tag allergy-tag--low"></span></td></tr>
<tr><td>2026-05-14 23:00:00</td><td>45</td><td>30</td><td>35</td><td>22</td><td>18</td><td>12</td><td>8</td><td>5</td><td>175</td><td><span class="allergy-tag allergy-tag--vlow">很低</span></td></tr>
<tr><td>2026-05-14 22:00:00</td><td>52</td><td>35</td><td>40</td><td>25</td><td>20</td><td>15</td><td>10</td><td>6</td><td>203</td><td><span class="allergy-tag allergy-tag--vlow">很低</span></td></tr>
<tr><td>2026-05-14 21:00:00</td><td>68</td><td>45</td><td>52</td><td>32</td><td>25</td><td>18</td><td>12</td><td>8</td><td>260</td><td><span class="allergy-tag allergy-tag--low"></span></td></tr>
<tr><td>2026-05-14 20:00:00</td><td>85</td><td>58</td><td>65</td><td>40</td><td>32</td><td>22</td><td>16</td><td>10</td><td>328</td><td><span class="allergy-tag allergy-tag--low"></span></td></tr>
<tr><td>2026-05-14 19:00:00</td><td>105</td><td>72</td><td>80</td><td>50</td><td>38</td><td>26</td><td>20</td><td>12</td><td>403</td><td><span class="allergy-tag allergy-tag--medium">中等</span></td></tr>
<tr><td>2026-05-14 18:00:00</td><td>135</td><td>92</td><td>102</td><td>65</td><td>48</td><td>35</td><td>28</td><td>18</td><td>523</td><td><span class="allergy-tag allergy-tag--high"></span></td></tr>
<tr><td>2026-05-14 17:00:00</td><td>158</td><td>108</td><td>120</td><td>78</td><td>55</td><td>42</td><td>32</td><td>22</td><td>615</td><td><span class="allergy-tag allergy-tag--vhigh">很高</span></td></tr>
</tbody>
</table>
</div>
<div class="pagination"><span>共 240 条</span><button class="page-btn active">1</button><button class="page-btn">2</button><button class="page-btn">3</button><span>...</span><button class="page-btn">24</button></div>
</div>
</main>
<script>
function toggleSubgroup(h){h.parentElement.classList.toggle('open');}
(function(){var a=document.querySelector('.sidebar-item.active');if(!a)return;var s=a.closest('.sidebar-subgroup');if(s)s.classList.add('open');})();
</script>
</body>
</html>
@@ -3,7 +3,7 @@
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>健康监测 - 知识科普 | 健康长庆原型</title>
<title>花粉监测 - 知识科普 | 健康长庆原型</title>
<style>
*{box-sizing:border-box;margin:0;padding:0;}
body{font-family:-apple-system,BlinkMacSystemFont,'PingFang SC','Microsoft YaHei',sans-serif;background:#F5F7FA;color:#333;min-width:1280px;}
@@ -18,8 +18,7 @@
.top-bar__logo{display:flex;align-items:center;gap:8px;color:#fff;font-size:var(--font-lg);font-weight:600;white-space:nowrap;width:240px;flex-shrink:0;}
.top-bar__logo svg{width:28px;height:28px;}
.top-bar__right{display:flex;align-items:center;gap:16px;color:rgba(255,255,255,0.65);font-size:var(--font-sm);}
.btn-back{color:rgba(255,255,255,0.65);cursor:pointer;display:flex;align-items:center;gap:4px;text-decoration:none;}
.btn-back:hover{color:#fff;}
.btn-back{color:rgba(255,255,255,0.65);cursor:pointer;display:flex;align-items:center;gap:4px;text-decoration:none;}.btn-back:hover{color:#fff;}
.avatar{width:32px;height:32px;border-radius:50%;background:#1890FF;display:flex;align-items:center;justify-content:center;color:#fff;font-size:var(--font-sm);cursor:pointer;}
.top-bar__nav{display:flex;align-items:center;gap:4px;flex:1;}
.top-bar__nav a{color:rgba(255,255,255,0.65);text-decoration:none;padding:6px 16px;border-radius:var(--radius-sm);font-size:var(--font-sm);transition:all .2s;}
@@ -40,9 +39,59 @@
.sidebar-subgroup.open>.sidebar-subgroup__body{display:block;}
.sidebar-subgroup__body .sidebar-item{padding-left:36px;font-size:12px;}
.main{margin-left:240px;margin-top:56px;padding:24px;min-height:calc(100vh - 56px);}
.page-placeholder{display:flex;flex-direction:column;align-items:center;justify-content:center;height:calc(100vh - 56px - 48px);color:var(--text-placeholder);gap:12px;}
.page-placeholder svg{opacity:.25;}
.page-placeholder p{font-size:var(--font-base);}
.page-title{font-size:var(--font-lg);font-weight:600;color:var(--text-primary);margin-bottom:16px;}
.filter-bar{background:#fff;border-radius:var(--radius-md);padding:20px 24px;margin-bottom:16px;box-shadow:var(--shadow-sm);display:flex;align-items:center;gap:16px;flex-wrap:wrap;}
.filter-item{display:flex;align-items:center;gap:8px;}
.filter-item label{font-size:var(--font-sm);color:var(--text-secondary);white-space:nowrap;}
.filter-input{height:36px;border:1px solid var(--border);border-radius:var(--radius-sm);padding:0 12px;font-size:var(--font-sm);color:var(--text-primary);outline:none;background:#fff;width:200px;}.filter-input:focus{border-color:var(--primary);}
.btn{height:36px;padding:0 16px;border-radius:var(--radius-sm);font-size:var(--font-sm);cursor:pointer;border:none;transition:all .2s;display:inline-flex;align-items:center;gap:6px;}
.btn-primary{background:var(--primary);color:#fff;}.btn-primary:hover{background:#40a9ff;}
.btn-default{background:#fff;color:var(--text-primary);border:1px solid var(--border);}.btn-default:hover{color:var(--primary);border-color:var(--primary);}
.btn-success{background:var(--success);color:#fff;}.btn-success:hover{background:#73d13d;}
.btn-danger-text{background:none;border:none;color:var(--danger);cursor:pointer;font-size:var(--font-xs);padding:0;}.btn-danger-text:hover{opacity:.7;}
.btn-link{background:none;border:none;color:var(--primary);cursor:pointer;font-size:var(--font-xs);padding:0;}.btn-link:hover{opacity:.7;}
.action-bar{display:flex;align-items:center;gap:12px;margin-bottom:16px;}
.table-card{background:#fff;border-radius:var(--radius-md);box-shadow:var(--shadow-sm);overflow:hidden;}
.table-card__content{overflow-x:auto;-webkit-overflow-scrolling:touch;}
table{width:100%;border-collapse:collapse;min-width:1000px;}
thead th{background:#FAFAFA;padding:12px 14px;text-align:center;font-size:var(--font-xs);color:var(--text-secondary);font-weight:500;border-bottom:1px solid var(--border);border-right:1px solid var(--border);white-space:nowrap;}
thead th:last-child{border-right:none;}
thead th.th-left{text-align:left;}
tbody td{padding:12px 14px;font-size:var(--font-xs);color:var(--text-primary);border-bottom:1px solid var(--border);text-align:center;white-space:nowrap;}
tbody td.td-left{text-align:left;}
tbody tr:last-child td{border-bottom:none;}
tbody tr:hover{background:#F8FBFF;}
.cover-img{width:60px;height:40px;border-radius:var(--radius-sm);object-fit:cover;background:#f0f0f0;display:inline-block;vertical-align:middle;}
.link-text{color:var(--primary);text-decoration:none;max-width:200px;display:inline-block;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;vertical-align:middle;}.link-text:hover{text-decoration:underline;}
.content-preview{max-width:240px;display:inline-block;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;color:var(--text-secondary);font-size:var(--font-xs);}
.status-tag{display:inline-block;padding:2px 10px;border-radius:10px;font-size:var(--font-xs);font-weight:500;}
.status-tag--on{background:#F6FFED;color:#52C41A;}
.status-tag--off{background:#F5F5F5;color:var(--text-placeholder);}
.pagination{display:flex;align-items:center;justify-content:flex-end;padding:16px 24px;gap:8px;border-top:1px solid var(--border);}
.pagination span{font-size:var(--font-sm);color:var(--text-secondary);}
.page-btn{width:32px;height:32px;border:1px solid var(--border);border-radius:var(--radius-sm);background:#fff;cursor:pointer;font-size:var(--font-sm);display:inline-flex;align-items:center;justify-content:center;transition:all .2s;}
.page-btn:hover,.page-btn.active{background:var(--primary);color:#fff;border-color:var(--primary);}
.modal-mask{display:none;position:fixed;inset:0;background:rgba(0,0,0,0.45);z-index:200;}
.modal-mask.show{display:block;}
.drawer{position:fixed;top:0;right:-600px;width:600px;height:100vh;background:#fff;box-shadow:-4px 0 24px rgba(0,0,0,0.12);z-index:201;display:flex;flex-direction:column;transition:right .3s ease;}
.modal-mask.show .drawer{right:0;}
.drawer__header{display:flex;align-items:center;justify-content:space-between;padding:20px 24px;border-bottom:1px solid var(--border);flex-shrink:0;}
.drawer__title{font-size:var(--font-base);font-weight:600;color:var(--text-primary);}
.drawer__close{width:28px;height:28px;border:none;background:none;cursor:pointer;display:flex;align-items:center;justify-content:center;border-radius:var(--radius-sm);color:var(--text-placeholder);font-size:18px;}.drawer__close:hover{background:var(--background);color:var(--text-primary);}
.drawer__body{flex:1;overflow-y:auto;padding:24px;}
.drawer__footer{display:flex;justify-content:flex-end;gap:12px;padding:16px 24px;border-top:1px solid var(--border);flex-shrink:0;}
.form-group{margin-bottom:16px;}
.form-group:last-child{margin-bottom:0;}
.form-label{display:block;font-size:var(--font-sm);color:var(--text-primary);margin-bottom:6px;font-weight:500;}
.form-label .required{color:var(--danger);margin-left:2px;}
.form-input{width:100%;height:36px;border:1px solid var(--border);border-radius:var(--radius-sm);padding:0 12px;font-size:var(--font-sm);color:var(--text-primary);outline:none;}.form-input:focus{border-color:var(--primary);}
.form-upload{width:100%;height:100px;border:1px dashed var(--border);border-radius:var(--radius-sm);display:flex;flex-direction:column;align-items:center;justify-content:center;gap:6px;cursor:pointer;color:var(--text-placeholder);font-size:var(--font-xs);transition:border-color .2s;}.form-upload:hover{border-color:var(--primary);}
.form-select{width:100%;height:36px;border:1px solid var(--border);border-radius:var(--radius-sm);padding:0 12px;font-size:var(--font-sm);color:var(--text-primary);outline:none;background:#fff;appearance:auto;}.form-select:focus{border-color:var(--primary);}
.rich-editor{border:1px solid var(--border);border-radius:var(--radius-sm);overflow:hidden;}
.rich-editor__toolbar{display:flex;align-items:center;gap:2px;padding:8px 12px;background:#FAFAFA;border-bottom:1px solid var(--border);flex-wrap:wrap;}
.rich-editor__toolbar button{width:28px;height:28px;border:none;background:none;cursor:pointer;border-radius:var(--radius-sm);display:inline-flex;align-items:center;justify-content:center;color:var(--text-secondary);font-size:13px;font-weight:600;transition:all .15s;}.rich-editor__toolbar button:hover{background:#E8E8E8;color:var(--text-primary);}
.rich-editor__toolbar .sep{width:1px;height:20px;background:var(--border);margin:0 6px;}
.rich-editor__body{min-height:180px;padding:12px;font-size:var(--font-sm);color:var(--text-primary);line-height:1.6;outline:none;}
</style>
</head>
<body>
@@ -57,10 +106,7 @@
<a href="../exception-dirty.html">异常事件</a>
</nav>
<div class="top-bar__right">
<a class="btn-back" href="../../../index.html">
<svg width="16" height="16" viewBox="0 0 16 16" fill="none"><path d="M10 3L5 8l5 5" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/></svg>
返回首页
</a>
<a class="btn-back" href="../../../index.html"><svg width="16" height="16" viewBox="0 0 16 16" fill="none"><path d="M10 3L5 8l5 5" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/></svg> 返回首页</a>
<div class="avatar"></div>
<span style="color:rgba(255,255,255,0.65);">系统管理员 ▾</span>
</div>
@@ -114,11 +160,82 @@
</div>
</aside>
<main class="main">
<div class="page-placeholder">
<svg width="64" height="64" viewBox="0 0 64 64" fill="none"><rect x="8" y="8" width="48" height="48" rx="8" stroke="#ccc" stroke-width="2"/><path d="M20 32h24M32 20v24" stroke="#ccc" stroke-width="2" stroke-linecap="round"/></svg>
<p>知识科普</p>
<div class="page-title">知识科普</div>
<div class="filter-bar">
<div class="filter-item"><label>文章标题</label><input class="filter-input" type="text" placeholder="请输入文章标题"></div>
<button class="btn btn-primary">查询</button>
<button class="btn btn-default">重置</button>
</div>
<div class="action-bar"><button class="btn btn-success" onclick="openModal('add')">+ 新增</button></div>
<div class="table-card">
<div class="table-card__content">
<table>
<thead><tr>
<th class="th-left" style="min-width:200px;">文章标题</th>
<th style="min-width:80px;">封面图</th>
<th style="min-width:240px;">文章内容</th>
<th style="min-width:110px;">创建日期</th>
<th style="min-width:80px;">查看次数</th>
<th style="min-width:60px;">排序</th>
<th style="min-width:70px;">状态</th>
<th style="min-width:100px;">操作</th>
</tr></thead>
<tbody>
<tr><td class="td-left">春季花粉过敏防护指南</td><td><span class="cover-img"></span></td><td><span class="content-preview">春季是花粉过敏的高发季节,了解如何有效防护对过敏体质人群至关重要...</span></td><td>2026-04-10</td><td>1,286</td><td>1</td><td><span class="status-tag status-tag--on">开启</span></td><td><button class="btn-link" onclick="openModal('edit')">编辑</button> <button class="btn-danger-text">删除</button></td></tr>
<tr><td class="td-left">花粉浓度与过敏等级对照表</td><td><span class="cover-img"></span></td><td><span class="content-preview">花粉浓度分为五个等级:很低、低、中等、高、很高,对应不同的防护建议...</span></td><td>2026-04-08</td><td>952</td><td>2</td><td><span class="status-tag status-tag--on">开启</span></td><td><button class="btn-link" onclick="openModal('edit')">编辑</button> <button class="btn-danger-text">删除</button></td></tr>
<tr><td class="td-left">常见致敏花粉种类识别</td><td><span class="cover-img"></span></td><td><span class="content-preview">我国北方地区常见致敏花粉包括榆属、松属、杨属、柏科等乔木花粉...</span></td><td>2026-03-25</td><td>834</td><td>3</td><td><span class="status-tag status-tag--on">开启</span></td><td><button class="btn-link" onclick="openModal('edit')">编辑</button> <button class="btn-danger-text">删除</button></td></tr>
<tr><td class="td-left">花粉过敏用药须知</td><td><span class="cover-img"></span></td><td><span class="content-preview">花粉过敏常用药物包括抗组胺药、鼻用糖皮质激素、白三烯受体拮抗剂...</span></td><td>2026-03-20</td><td>721</td><td>4</td><td><span class="status-tag status-tag--on">开启</span></td><td><button class="btn-link" onclick="openModal('edit')">编辑</button> <button class="btn-danger-text">删除</button></td></tr>
<tr><td class="td-left">室内防护措施与空气净化建议</td><td><span class="cover-img"></span></td><td><span class="content-preview">花粉季节应减少开窗通风,使用带有HEPA滤网的空气净化器可有效降低...</span></td><td>2026-03-15</td><td>658</td><td>5</td><td><span class="status-tag status-tag--off">关闭</span></td><td><button class="btn-link" onclick="openModal('edit')">编辑</button> <button class="btn-danger-text">删除</button></td></tr>
</tbody>
</table>
</div>
<div class="pagination">
<span>共 5 条</span>
<button class="page-btn active">1</button>
</div>
</div>
</main>
<script>function toggleSubgroup(h){h.parentElement.classList.toggle('open');}(function(){var a=document.querySelector('.sidebar-item.active');if(!a)return;var s=a.closest('.sidebar-subgroup');if(s)s.classList.add('open');})();</script>
<!-- 新增/编辑抽屉 -->
<div class="modal-mask" id="modalMask">
<div class="drawer">
<div class="drawer__header"><span class="drawer__title" id="modalTitle">新增文章</span><button class="drawer__close" onclick="closeModal()">&times;</button></div>
<div class="drawer__body">
<div class="form-group"><label class="form-label">文章标题<span class="required">*</span></label><input class="form-input" type="text" placeholder="请输入文章标题" id="formTitle"></div>
<div class="form-group"><label class="form-label">封面图</label><div class="form-upload" id="formCover"><svg width="24" height="24" viewBox="0 0 24 24" fill="none"><path d="M12 5v14M5 12h14" stroke="#999" stroke-width="1.5" stroke-linecap="round"/></svg><span>点击上传封面图</span></div></div>
<div class="form-group"><label class="form-label">文章内容<span class="required">*</span></label>
<div class="rich-editor">
<div class="rich-editor__toolbar">
<button title="加粗"><b>B</b></button>
<button title="斜体"><i>I</i></button>
<button title="下划线"><u>U</u></button>
<span class="sep"></span>
<button title="标题">H</button>
<button title="有序列表">OL</button>
<button title="无序列表">UL</button>
<span class="sep"></span>
<button title="插入图片">&#128247;</button>
<button title="插入链接">&#128279;</button>
</div>
<div class="rich-editor__body" contenteditable="true" id="formContent">春季是花粉过敏的高发季节,了解如何有效防护对过敏体质人群至关重要。本文将从出行防护、居家措施、饮食调理三个方面为您详细介绍...</div>
</div>
</div>
<div class="form-group"><label class="form-label">排序</label><input class="form-input" type="number" placeholder="数字越小越靠前" id="formSort"></div>
<div class="form-group"><label class="form-label">状态</label><select class="form-select" id="formStatus"><option value="on">开启</option><option value="off">关闭</option></select></div>
</div>
<div class="drawer__footer"><button class="btn btn-default" onclick="closeModal()">取消</button><button class="btn btn-primary" onclick="closeModal()">确定</button></div>
</div>
</div>
<script>
function toggleSubgroup(h){h.parentElement.classList.toggle('open');}
(function(){var a=document.querySelector('.sidebar-item.active');if(!a)return;var s=a.closest('.sidebar-subgroup');if(s)s.classList.add('open');})();
function openModal(type){
document.getElementById('modalMask').classList.add('show');
document.getElementById('modalTitle').textContent=type==='add'?'新增文章':'编辑文章';
if(type==='edit'){document.getElementById('formTitle').value='春季花粉过敏防护指南';document.getElementById('formContent').innerHTML='春季是花粉过敏的高发季节,了解如何有效防护对过敏体质人群至关重要。本文将从出行防护、居家措施、饮食调理三个方面为您详细介绍...';document.getElementById('formSort').value='1';}
else{document.getElementById('formTitle').value='';document.getElementById('formContent').innerHTML='';document.getElementById('formSort').value='';}
}
function closeModal(){document.getElementById('modalMask').classList.remove('show');}
document.getElementById('modalMask').addEventListener('click',function(e){if(e.target===this)closeModal();});
</script>
</body>
</html>
</html>
@@ -3,7 +3,7 @@
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>健康监测 - 应用记录 | 健康长庆原型</title>
<title>水质监测 - 应用记录 | 健康长庆原型</title>
<style>
*{box-sizing:border-box;margin:0;padding:0;}
body{font-family:-apple-system,BlinkMacSystemFont,'PingFang SC','Microsoft YaHei',sans-serif;background:#F5F7FA;color:#333;min-width:1280px;}
@@ -18,8 +18,7 @@
.top-bar__logo{display:flex;align-items:center;gap:8px;color:#fff;font-size:var(--font-lg);font-weight:600;white-space:nowrap;width:240px;flex-shrink:0;}
.top-bar__logo svg{width:28px;height:28px;}
.top-bar__right{display:flex;align-items:center;gap:16px;color:rgba(255,255,255,0.65);font-size:var(--font-sm);}
.btn-back{color:rgba(255,255,255,0.65);cursor:pointer;display:flex;align-items:center;gap:4px;text-decoration:none;}
.btn-back:hover{color:#fff;}
.btn-back{color:rgba(255,255,255,0.65);cursor:pointer;display:flex;align-items:center;gap:4px;text-decoration:none;}.btn-back:hover{color:#fff;}
.avatar{width:32px;height:32px;border-radius:50%;background:#1890FF;display:flex;align-items:center;justify-content:center;color:#fff;font-size:var(--font-sm);cursor:pointer;}
.top-bar__nav{display:flex;align-items:center;gap:4px;flex:1;}
.top-bar__nav a{color:rgba(255,255,255,0.65);text-decoration:none;padding:6px 16px;border-radius:var(--radius-sm);font-size:var(--font-sm);transition:all .2s;}
@@ -40,9 +39,44 @@
.sidebar-subgroup.open>.sidebar-subgroup__body{display:block;}
.sidebar-subgroup__body .sidebar-item{padding-left:36px;font-size:12px;}
.main{margin-left:240px;margin-top:56px;padding:24px;min-height:calc(100vh - 56px);}
.page-placeholder{display:flex;flex-direction:column;align-items:center;justify-content:center;height:calc(100vh - 56px - 48px);color:var(--text-placeholder);gap:12px;}
.page-placeholder svg{opacity:.25;}
.page-placeholder p{font-size:var(--font-base);}
.filter-bar{background:#fff;border-radius:var(--radius-md);padding:20px 24px;margin-bottom:16px;box-shadow:var(--shadow-sm);display:flex;align-items:center;gap:16px;flex-wrap:wrap;}
.filter-item{display:flex;align-items:center;gap:8px;}
.filter-item label{font-size:var(--font-sm);color:var(--text-secondary);white-space:nowrap;}
.filter-input{height:36px;border:1px solid var(--border);border-radius:var(--radius-sm);padding:0 12px;font-size:var(--font-sm);color:var(--text-primary);outline:none;background:#fff;min-width:180px;}.filter-input:focus{border-color:var(--primary);}
.filter-select{height:36px;border:1px solid var(--border);border-radius:var(--radius-sm);padding:0 28px 0 12px;font-size:var(--font-sm);color:var(--text-primary);outline:none;background:#fff url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6'%3E%3Cpath d='M0 0l5 6 5-6z' fill='%23999'/%3E%3C/svg%3E") no-repeat right 10px center;appearance:none;cursor:pointer;min-width:140px;}
.btn{height:36px;padding:0 16px;border-radius:var(--radius-sm);font-size:var(--font-sm);cursor:pointer;border:none;transition:all .2s;display:inline-flex;align-items:center;gap:6px;}
.btn-primary{background:var(--primary);color:#fff;}.btn-primary:hover{background:#40a9ff;}
.btn-default{background:#fff;color:var(--text-primary);border:1px solid var(--border);}.btn-default:hover{color:var(--primary);border-color:var(--primary);}
.action-bar{display:flex;align-items:center;gap:12px;margin-bottom:16px;}
.table-card{background:#fff;border-radius:var(--radius-md);box-shadow:var(--shadow-sm);overflow:hidden;}
.table-card__content{overflow-x:auto;-webkit-overflow-scrolling:touch;}
table{width:100%;border-collapse:collapse;min-width:1200px;}
thead th{background:#FAFAFA;padding:12px 14px;text-align:center;font-size:var(--font-xs);color:var(--text-secondary);font-weight:500;border-bottom:1px solid var(--border);border-right:1px solid var(--border);white-space:nowrap;}
thead th:last-child{border-right:none;}
thead th.th-left{text-align:left;}
tbody td{padding:12px 14px;font-size:var(--font-xs);color:var(--text-primary);border-bottom:1px solid var(--border);text-align:center;white-space:nowrap;}
tbody td.td-left{text-align:left;}
tbody tr:last-child td{border-bottom:none;}
tbody tr:hover{background:#F8FBFF;}
thead tr:first-child th:nth-child(-n+2),tbody td:nth-child(-n+2){position:sticky;z-index:2;}
thead tr:first-child th:nth-child(-n+2){z-index:3;}
thead tr:first-child th:nth-child(1),tbody td:nth-child(1){left:0;}
thead tr:first-child th:nth-child(2),tbody td:nth-child(2){left:140px;}
tbody td:nth-child(-n+2){background:#fff;}
tbody tr:hover td:nth-child(-n+2){background:#F8FBFF;}
tbody td:nth-child(2),thead tr:first-child th:nth-child(2){box-shadow:2px 0 4px rgba(0,0,0,0.06);}
.th-sort{cursor:pointer;user-select:none;position:relative;padding-right:22px !important;}
.th-sort:hover{color:var(--primary);}
.th-sort .sort-icon{position:absolute;right:4px;top:50%;transform:translateY(-50%);display:flex;flex-direction:column;gap:1px;}
.th-sort .sort-icon .arrow-up,.th-sort .sort-icon .arrow-down{width:0;height:0;border-left:4px solid transparent;border-right:4px solid transparent;}
.th-sort .sort-icon .arrow-up{border-bottom:5px solid #ccc;}
.th-sort .sort-icon .arrow-down{border-top:5px solid #ccc;}
.th-sort.asc .sort-icon .arrow-up{border-bottom-color:var(--primary);}
.th-sort.desc .sort-icon .arrow-down{border-top-color:var(--primary);}
.pagination{display:flex;align-items:center;justify-content:flex-end;padding:16px 24px;gap:8px;border-top:1px solid var(--border);}
.pagination span{font-size:var(--font-sm);color:var(--text-secondary);}
.page-btn{width:32px;height:32px;border:1px solid var(--border);border-radius:var(--radius-sm);background:#fff;cursor:pointer;font-size:var(--font-sm);display:inline-flex;align-items:center;justify-content:center;transition:all .2s;}
.page-btn:hover,.page-btn.active{background:var(--primary);color:#fff;border-color:var(--primary);}
</style>
</head>
<body>
@@ -57,10 +91,7 @@
<a href="../exception-dirty.html">异常事件</a>
</nav>
<div class="top-bar__right">
<a class="btn-back" href="../../../index.html">
<svg width="16" height="16" viewBox="0 0 16 16" fill="none"><path d="M10 3L5 8l5 5" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/></svg>
返回首页
</a>
<a class="btn-back" href="../../../index.html"><svg width="16" height="16" viewBox="0 0 16 16" fill="none"><path d="M10 3L5 8l5 5" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/></svg> 返回首页</a>
<div class="avatar"></div>
<span style="color:rgba(255,255,255,0.65);">系统管理员 ▾</span>
</div>
@@ -114,11 +145,84 @@
</div>
</aside>
<main class="main">
<div class="page-placeholder">
<svg width="64" height="64" viewBox="0 0 64 64" fill="none"><rect x="8" y="8" width="48" height="48" rx="8" stroke="#ccc" stroke-width="2"/><path d="M20 32h24M32 20v24" stroke="#ccc" stroke-width="2" stroke-linecap="round"/></svg>
<p>应用记录</p>
<div class="filter-bar">
<div class="filter-item"><label>设备名称</label><input class="filter-input" placeholder="请输入设备名称"></div>
<div class="filter-item"><label>设备编码</label><input class="filter-input" placeholder="请输入设备编码"></div>
<div class="filter-item"><label>所属单位</label>
<select class="filter-select"><option value="">全部</option><option>采油一厂</option><option>采油二厂</option><option>采油三厂</option></select>
</div>
<button class="btn btn-primary">查询</button>
<button class="btn btn-default">重置</button>
</div>
<div class="action-bar"><button class="btn btn-default">导出列表数据</button></div>
<div class="table-card">
<div class="table-card__content">
<table id="appTable">
<thead>
<tr>
<th rowspan="2" class="th-left" style="min-width:140px;">设备名称</th>
<th rowspan="2" style="min-width:110px;">设备编码</th>
<th rowspan="2" style="min-width:90px;">所属单位</th>
<th rowspan="2" style="min-width:120px;">设备位置</th>
<th colspan="7">移动端点击次数</th>
</tr>
<tr>
<th class="th-sort" data-col="4" onclick="sortTable(this)">温度<span class="sort-icon"><span class="arrow-up"></span><span class="arrow-down"></span></span></th>
<th class="th-sort" data-col="5" onclick="sortTable(this)">电导率<span class="sort-icon"><span class="arrow-up"></span><span class="arrow-down"></span></span></th>
<th class="th-sort" data-col="6" onclick="sortTable(this)">PH<span class="sort-icon"><span class="arrow-up"></span><span class="arrow-down"></span></span></th>
<th class="th-sort" data-col="7" onclick="sortTable(this)">盐度<span class="sort-icon"><span class="arrow-up"></span><span class="arrow-down"></span></span></th>
<th class="th-sort" data-col="8" onclick="sortTable(this)">电阻率<span class="sort-icon"><span class="arrow-up"></span><span class="arrow-down"></span></span></th>
<th class="th-sort" data-col="9" onclick="sortTable(this)">TDS<span class="sort-icon"><span class="arrow-up"></span><span class="arrow-down"></span></span></th>
<th class="th-sort" data-col="10" onclick="sortTable(this)">总点击次数<span class="sort-icon"><span class="arrow-up"></span><span class="arrow-down"></span></span></th>
</tr>
</thead>
<tbody>
<tr>
<td class="td-left">多参数水质分析仪-A01</td><td>WQ-2024-001</td><td>采油一厂</td><td>生活区供水站</td>
<td>312</td><td>245</td><td>478</td><td>156</td><td>89</td><td>203</td><td>1483</td>
</tr>
<tr>
<td class="td-left">在线PH计-B02</td><td>WQ-2024-002</td><td>采油一厂</td><td>污水处理站出口</td>
<td>178</td><td>134</td><td>623</td><td>98</td><td>67</td><td>145</td><td>1245</td>
</tr>
<tr>
<td class="td-left">电导率监测仪-C01</td><td>WQ-2024-003</td><td>采油二厂</td><td>注水站入口</td>
<td>95</td><td>567</td><td>112</td><td>234</td><td>189</td><td>78</td><td>1275</td>
</tr>
<tr>
<td class="td-left">TDS检测仪-D01</td><td>WQ-2024-004</td><td>采油二厂</td><td>生产区储水池</td>
<td>145</td><td>198</td><td>267</td><td>112</td><td>76</td><td>534</td><td>1332</td>
</tr>
<tr>
<td class="td-left">多参数水质分析仪-A03</td><td>WQ-2024-005</td><td>采油三厂</td><td>排污口监测点</td>
<td>256</td><td>312</td><td>345</td><td>189</td><td>123</td><td>278</td><td>1503</td>
</tr>
</tbody>
</table>
</div>
<div class="pagination"><span>共 5 条</span><button class="page-btn active">1</button></div>
</div>
</main>
<script>function toggleSubgroup(h){h.parentElement.classList.toggle('open');}(function(){var a=document.querySelector('.sidebar-item.active');if(!a)return;var s=a.closest('.sidebar-subgroup');if(s)s.classList.add('open');})();</script>
<script>
function toggleSubgroup(h){h.parentElement.classList.toggle('open');}
(function(){var a=document.querySelector('.sidebar-item.active');if(!a)return;var s=a.closest('.sidebar-subgroup');if(s)s.classList.add('open');})();
function sortTable(th){
var table=document.getElementById('appTable');
var tbody=table.querySelector('tbody');
var rows=Array.from(tbody.querySelectorAll('tr'));
var col=parseInt(th.getAttribute('data-col'));
var dir='asc';
if(th.classList.contains('asc')){dir='desc';}
else if(th.classList.contains('desc')){dir='asc';}
table.querySelectorAll('.th-sort').forEach(function(t){t.classList.remove('asc','desc');});
th.classList.add(dir);
rows.sort(function(a,b){
var va=parseInt(a.cells[col].textContent);
var vb=parseInt(b.cells[col].textContent);
return dir==='asc'?(va-vb):(vb-va);
});
rows.forEach(function(r){tbody.appendChild(r);});
}
</script>
</body>
</html>
</html>
@@ -0,0 +1,295 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>水质监测 - 动态分析 | 健康长庆原型</title>
<style>
*{box-sizing:border-box;margin:0;padding:0;}
body{font-family:-apple-system,BlinkMacSystemFont,'PingFang SC','Microsoft YaHei',sans-serif;background:#F5F7FA;color:#333;min-width:1280px;}
:root{
--primary:#1890FF;--primary-light:#E6F7FF;--success:#52C41A;--warning:#FAAD14;--danger:#FF4D4F;
--text-primary:#333;--text-secondary:#666;--text-placeholder:#999;--border:#E8E8E8;--background:#F5F7FA;
--font-xs:11px;--font-sm:13px;--font-base:15px;--font-lg:17px;
--radius-sm:4px;--radius-md:8px;--radius-lg:12px;
--shadow-sm:0 1px 4px rgba(0,0,0,0.08);
}
.top-bar{display:flex;align-items:center;height:56px;background:#001529;padding:0 24px;position:fixed;top:0;left:0;right:0;z-index:100;}
.top-bar__logo{display:flex;align-items:center;gap:8px;color:#fff;font-size:var(--font-lg);font-weight:600;white-space:nowrap;width:240px;flex-shrink:0;}
.top-bar__logo svg{width:28px;height:28px;}
.top-bar__right{display:flex;align-items:center;gap:16px;color:rgba(255,255,255,0.65);font-size:var(--font-sm);}
.btn-back{color:rgba(255,255,255,0.65);cursor:pointer;display:flex;align-items:center;gap:4px;text-decoration:none;}.btn-back:hover{color:#fff;}
.avatar{width:32px;height:32px;border-radius:50%;background:#1890FF;display:flex;align-items:center;justify-content:center;color:#fff;font-size:var(--font-sm);cursor:pointer;}
.top-bar__nav{display:flex;align-items:center;gap:4px;flex:1;}
.top-bar__nav a{color:rgba(255,255,255,0.65);text-decoration:none;padding:6px 16px;border-radius:var(--radius-sm);font-size:var(--font-sm);transition:all .2s;}
.top-bar__nav a:hover{color:#fff;background:rgba(255,255,255,0.08);}
.top-bar__nav a.active{color:#fff;background:var(--primary);}
.sidebar{position:fixed;top:56px;left:0;bottom:0;width:240px;background:#001529;overflow-y:auto;z-index:90;padding-top:8px;}
.sidebar-menu__title{color:rgba(255,255,255,0.35);font-size:var(--font-xs);padding:16px 24px 8px;letter-spacing:.5px;}
.sidebar-item{display:flex;align-items:center;gap:8px;padding:10px 24px;color:rgba(255,255,255,0.65);font-size:var(--font-sm);cursor:pointer;transition:all .15s;text-decoration:none;}
.sidebar-item:hover{color:#fff;background:rgba(255,255,255,0.06);}
.sidebar-item.active{color:#fff;background:var(--primary);}
.sidebar-subgroup__header{display:flex;align-items:center;gap:6px;padding:10px 24px;color:rgba(255,255,255,0.65);font-size:var(--font-sm);cursor:pointer;transition:all .15s;user-select:none;}
.sidebar-subgroup__header:hover{color:rgba(255,255,255,0.85);background:rgba(255,255,255,0.04);}
.sidebar-subgroup__header .arrow{width:10px;height:10px;transition:transform .2s;flex-shrink:0;}
.sidebar-subgroup__header .arrow path{stroke:rgba(255,255,255,0.45);}
.sidebar-subgroup.open>.sidebar-subgroup__header{color:rgba(255,255,255,0.85);}
.sidebar-subgroup.open>.sidebar-subgroup__header .arrow{transform:rotate(90deg);}
.sidebar-subgroup__body{display:none;padding-left:16px;}
.sidebar-subgroup.open>.sidebar-subgroup__body{display:block;}
.sidebar-subgroup__body .sidebar-item{padding-left:36px;font-size:12px;}
.main{margin-left:240px;margin-top:56px;padding:24px;min-height:calc(100vh - 56px);}
.page-header{display:flex;align-items:center;gap:12px;margin-bottom:20px;}
.page-header__back{width:32px;height:32px;border-radius:var(--radius-sm);border:1px solid var(--border);background:#fff;display:flex;align-items:center;justify-content:center;cursor:pointer;text-decoration:none;color:var(--text-secondary);}
.page-header__back:hover{border-color:var(--primary);color:var(--primary);}
.page-header__title{font-size:var(--font-lg);font-weight:600;color:var(--text-primary);}
.analysis-layout{display:flex;gap:20px;align-items:flex-start;}
.device-card{width:320px;flex-shrink:0;background:#fff;border-radius:var(--radius-md);box-shadow:var(--shadow-sm);overflow:hidden;}
.device-card__header{padding:16px 20px;background:linear-gradient(135deg,#1890FF 0%,#096DD9 100%);color:#fff;}
.device-card__name{font-size:var(--font-base);font-weight:600;margin-bottom:4px;}
.device-card__code{font-size:var(--font-xs);opacity:.8;}
.device-card__body{padding:16px 20px;}
.device-card__item{display:flex;justify-content:space-between;align-items:center;padding:12px 0;border-bottom:1px solid #f5f5f5;}
.device-card__item:last-child{border-bottom:none;}
.device-card__label{font-size:var(--font-sm);color:var(--text-placeholder);}
.device-card__value{font-size:var(--font-sm);color:var(--text-primary);font-weight:500;text-align:right;max-width:180px;}
.wqi-tag{display:inline-block;padding:2px 10px;border-radius:10px;font-size:var(--font-xs);font-weight:500;}
.wqi-tag--pass{background:#F6FFED;color:#52C41A;}
.device-card__tip{margin-top:4px;padding:12px;background:#F6FFED;border-radius:var(--radius-sm);border:1px solid #B7EB8F;}
.device-card__tip p{font-size:var(--font-xs);color:var(--text-secondary);line-height:1.6;margin:0;}
.realtime-section{margin-top:16px;padding-top:16px;border-top:1px solid var(--border);}
.realtime-title{font-size:var(--font-xs);color:var(--text-placeholder);margin-bottom:12px;font-weight:500;}
.realtime-grid{display:grid;grid-template-columns:1fr 1fr;gap:8px;}
.realtime-item{background:#F8FBFF;border-radius:var(--radius-sm);padding:10px 12px;text-align:center;}
.realtime-item__value{font-size:var(--font-lg);font-weight:600;color:var(--primary);margin-bottom:2px;}
.realtime-item__label{font-size:var(--font-xs);color:var(--text-placeholder);}
.chart-panel{flex:1;background:#fff;border-radius:var(--radius-md);box-shadow:var(--shadow-sm);overflow:hidden;min-width:0;}
.time-tabs{display:flex;gap:0;border-bottom:1px solid var(--border);padding:0 24px;}
.time-tab{padding:14px 24px;font-size:var(--font-sm);color:var(--text-secondary);cursor:pointer;border-bottom:2px solid transparent;transition:all .2s;white-space:nowrap;}
.time-tab:hover{color:var(--primary);}
.time-tab.active{color:var(--primary);border-bottom-color:var(--primary);font-weight:500;}
.metric-bar{display:flex;align-items:center;gap:8px;padding:16px 24px;border-bottom:1px solid #f5f5f5;flex-wrap:wrap;}
.metric-btn{height:32px;padding:0 14px;border-radius:16px;font-size:var(--font-xs);cursor:pointer;border:1px solid var(--border);background:#fff;color:var(--text-secondary);transition:all .2s;white-space:nowrap;}
.metric-btn:hover{color:var(--primary);border-color:var(--primary);}
.metric-btn.active{background:var(--primary);color:#fff;border-color:var(--primary);}
.chart-area{padding:24px;min-height:400px;}
.chart-container{width:100%;height:360px;position:relative;}
.chart-container svg{width:100%;height:100%;}
.chart-grid-line{stroke:#f0f0f0;stroke-width:1;}
.chart-axis-label{fill:#999;font-size:11px;}
.chart-line{fill:none;stroke:var(--primary);stroke-width:2;stroke-linejoin:round;stroke-linecap:round;}
.chart-area-fill{fill:url(#areaGrad);opacity:.15;}
.chart-dot{fill:var(--primary);stroke:#fff;stroke-width:2;}
.chart-summary{display:flex;gap:32px;padding:0 24px 20px;}
.chart-summary__item{display:flex;align-items:center;gap:6px;}
.chart-summary__dot{width:8px;height:8px;border-radius:50%;}
.chart-summary__label{font-size:var(--font-xs);color:var(--text-placeholder);}
.chart-summary__value{font-size:var(--font-sm);color:var(--text-primary);font-weight:600;}
</style>
</head>
<body>
<div class="top-bar">
<div class="top-bar__logo"><svg viewBox="0 0 28 28" fill="none"><rect width="28" height="28" rx="6" fill="#1890FF"/><path d="M7 14h14M14 7v14" stroke="#fff" stroke-width="2.5" stroke-linecap="round"/></svg> 健康监测</div>
<nav class="top-bar__nav">
<a href="../archive-personal.html">档案</a>
<a href="../health-checkup/survey-category.html">健康排查</a>
<a href="../wearable/tool-manage.html">穿戴监测</a>
<a href="../weight/scale-device.html">体重监测</a>
<a href="../environment/indoor-device-list.html" class="active">环境监测</a>
<a href="../exception-dirty.html">异常事件</a>
</nav>
<div class="top-bar__right">
<a class="btn-back" href="../../../index.html"><svg width="16" height="16" viewBox="0 0 16 16" fill="none"><path d="M10 3L5 8l5 5" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/></svg> 返回首页</a>
<div class="avatar"></div>
<span style="color:rgba(255,255,255,0.65);">系统管理员 ▾</span>
</div>
</div>
<aside class="sidebar">
<div class="sidebar-menu__title">环境监测</div>
<div class="sidebar-subgroup">
<div class="sidebar-subgroup__header" onclick="toggleSubgroup(this)"><svg class="arrow" viewBox="0 0 12 12"><path d="M4 2l4 4-4 4" fill="none" stroke-width="1.5" stroke-linecap="round"/></svg> 室内空气</div>
<div class="sidebar-subgroup__body">
<a href="indoor-device-list.html" class="sidebar-item">设备列表</a><a href="indoor-device-category.html" class="sidebar-item">设备分类</a><a href="indoor-data-monitor.html" class="sidebar-item">数据监测</a><a href="indoor-exception-alarm.html" class="sidebar-item">异常报警</a><a href="indoor-app-record.html" class="sidebar-item">应用记录</a><a href="indoor-history-data.html" class="sidebar-item">历史数据</a>
</div>
</div>
<div class="sidebar-subgroup">
<div class="sidebar-subgroup__header" onclick="toggleSubgroup(this)"><svg class="arrow" viewBox="0 0 12 12"><path d="M4 2l4 4-4 4" fill="none" stroke-width="1.5" stroke-linecap="round"/></svg> 室外空气</div>
<div class="sidebar-subgroup__body">
<a href="outdoor-device-list.html" class="sidebar-item">设备列表</a><a href="outdoor-device-category.html" class="sidebar-item">设备分类</a><a href="outdoor-data-monitor.html" class="sidebar-item">数据监测</a><a href="outdoor-exception-alarm.html" class="sidebar-item">异常报警</a><a href="outdoor-app-record.html" class="sidebar-item">应用记录</a><a href="outdoor-history-data.html" class="sidebar-item">历史数据</a>
</div>
</div>
<div class="sidebar-subgroup open">
<div class="sidebar-subgroup__header" onclick="toggleSubgroup(this)"><svg class="arrow" viewBox="0 0 12 12"><path d="M4 2l4 4-4 4" fill="none" stroke-width="1.5" stroke-linecap="round"/></svg> 水质监测</div>
<div class="sidebar-subgroup__body">
<a href="water-device-list.html" class="sidebar-item">设备列表</a><a href="water-device-category.html" class="sidebar-item">设备分类</a><a href="water-data-monitor.html" class="sidebar-item active">数据监测</a><a href="water-exception-alarm.html" class="sidebar-item">异常报警</a><a href="water-app-record.html" class="sidebar-item">应用记录</a><a href="water-history-data.html" class="sidebar-item">历史数据</a>
</div>
</div>
<div class="sidebar-subgroup">
<div class="sidebar-subgroup__header" onclick="toggleSubgroup(this)"><svg class="arrow" viewBox="0 0 12 12"><path d="M4 2l4 4-4 4" fill="none" stroke-width="1.5" stroke-linecap="round"/></svg> 花粉监测</div>
<div class="sidebar-subgroup__body">
<a href="pollen-device-list.html" class="sidebar-item">设备列表</a><a href="pollen-device-category.html" class="sidebar-item">设备分类</a><a href="pollen-data-monitor.html" class="sidebar-item">数据监测</a><a href="pollen-exception-alarm.html" class="sidebar-item">异常报警</a><a href="pollen-app-record.html" class="sidebar-item">应用记录</a><a href="pollen-history-data.html" class="sidebar-item">历史数据</a><a href="pollen-knowledge.html" class="sidebar-item">知识科普</a>
</div>
</div>
</aside>
<main class="main">
<div class="page-header">
<a class="page-header__back" href="water-data-monitor.html"><svg width="16" height="16" viewBox="0 0 16 16" fill="none"><path d="M10 3L5 8l5 5" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/></svg></a>
<span class="page-header__title">动态分析</span>
</div>
<div class="analysis-layout">
<!-- 左侧 - 设备信息 -->
<div class="device-card">
<div class="device-card__header">
<div class="device-card__name">多参数水质分析仪-A01</div>
<div class="device-card__code">WQ-2024-001</div>
</div>
<div class="device-card__body">
<div class="device-card__item">
<span class="device-card__label">所属单位</span>
<span class="device-card__value">采油一厂</span>
</div>
<div class="device-card__item">
<span class="device-card__label">设备位置</span>
<span class="device-card__value">生活区供水站</span>
</div>
<div class="device-card__item">
<span class="device-card__label">数据更新时间</span>
<span class="device-card__value">2026-05-14 14:30</span>
</div>
<div class="device-card__item">
<span class="device-card__label">水质等级</span>
<span class="device-card__value"><span class="wqi-tag wqi-tag--pass">达标</span></span>
</div>
<div class="device-card__tip">
<p>各项水质指标均在国家饮用水安全标准范围内,水质状况良好。</p>
</div>
<div class="realtime-section">
<div class="realtime-title">实时监测数据</div>
<div class="realtime-grid">
<div class="realtime-item">
<div class="realtime-item__value">18.5</div>
<div class="realtime-item__label">温度(℃)</div>
</div>
<div class="realtime-item">
<div class="realtime-item__value">320</div>
<div class="realtime-item__label">电导率(US/cm)</div>
</div>
<div class="realtime-item">
<div class="realtime-item__value">7.2</div>
<div class="realtime-item__label">PH</div>
</div>
<div class="realtime-item">
<div class="realtime-item__value">180</div>
<div class="realtime-item__label">盐度(mg/L)</div>
</div>
<div class="realtime-item">
<div class="realtime-item__value">3125</div>
<div class="realtime-item__label">电阻率(Ω·m)</div>
</div>
<div class="realtime-item">
<div class="realtime-item__value">160</div>
<div class="realtime-item__label">TDS(mg/L)</div>
</div>
</div>
</div>
</div>
</div>
<!-- 右侧 - 趋势图 -->
<div class="chart-panel">
<div class="time-tabs">
<div class="time-tab active" onclick="switchTimeTab(this)">近24小时</div>
<div class="time-tab" onclick="switchTimeTab(this)">近7日</div>
<div class="time-tab" onclick="switchTimeTab(this)">近30日</div>
<div class="time-tab" onclick="switchTimeTab(this)">近3个月</div>
</div>
<div class="metric-bar">
<button class="metric-btn active" onclick="switchMetric(this,'temp')">温度</button>
<button class="metric-btn" onclick="switchMetric(this,'cond')">电导率</button>
<button class="metric-btn" onclick="switchMetric(this,'ph')">PH</button>
<button class="metric-btn" onclick="switchMetric(this,'salt')">盐度</button>
<button class="metric-btn" onclick="switchMetric(this,'resist')">电阻率</button>
<button class="metric-btn" onclick="switchMetric(this,'tds')">TDS</button>
</div>
<div class="chart-summary">
<div class="chart-summary__item"><span class="chart-summary__dot" style="background:#1890FF;"></span><span class="chart-summary__label">平均值</span><span class="chart-summary__value" id="avgVal">18.2 ℃</span></div>
<div class="chart-summary__item"><span class="chart-summary__dot" style="background:#52C41A;"></span><span class="chart-summary__label">最小值</span><span class="chart-summary__value" id="minVal">15.6 ℃</span></div>
<div class="chart-summary__item"><span class="chart-summary__dot" style="background:#FF4D4F;"></span><span class="chart-summary__label">最大值</span><span class="chart-summary__value" id="maxVal">21.3 ℃</span></div>
</div>
<div class="chart-area">
<div class="chart-container" id="chartContainer">
<svg viewBox="0 0 800 320" preserveAspectRatio="xMidYMid meet">
<defs>
<linearGradient id="areaGrad" x1="0" y1="0" x2="0" y2="1">
<stop offset="0%" stop-color="#1890FF" stop-opacity="0.3"/>
<stop offset="100%" stop-color="#1890FF" stop-opacity="0"/>
</linearGradient>
</defs>
<line x1="60" y1="20" x2="780" y2="20" class="chart-grid-line"/>
<line x1="60" y1="80" x2="780" y2="80" class="chart-grid-line"/>
<line x1="60" y1="140" x2="780" y2="140" class="chart-grid-line"/>
<line x1="60" y1="200" x2="780" y2="200" class="chart-grid-line"/>
<line x1="60" y1="260" x2="780" y2="260" class="chart-grid-line"/>
<text x="50" y="24" class="chart-axis-label" text-anchor="end">22</text>
<text x="50" y="84" class="chart-axis-label" text-anchor="end">20</text>
<text x="50" y="144" class="chart-axis-label" text-anchor="end">18</text>
<text x="50" y="204" class="chart-axis-label" text-anchor="end">16</text>
<text x="50" y="264" class="chart-axis-label" text-anchor="end">14</text>
<text x="90" y="290" class="chart-axis-label" text-anchor="middle">00:00</text>
<text x="180" y="290" class="chart-axis-label" text-anchor="middle">04:00</text>
<text x="270" y="290" class="chart-axis-label" text-anchor="middle">06:00</text>
<text x="360" y="290" class="chart-axis-label" text-anchor="middle">08:00</text>
<text x="450" y="290" class="chart-axis-label" text-anchor="middle">10:00</text>
<text x="540" y="290" class="chart-axis-label" text-anchor="middle">12:00</text>
<text x="630" y="290" class="chart-axis-label" text-anchor="middle">14:00</text>
<text x="720" y="290" class="chart-axis-label" text-anchor="middle">16:00</text>
<line x1="60" y1="270" x2="780" y2="270" stroke="#d9d9d9" stroke-width="1"/>
<path class="chart-area-fill" d="M90,200 L150,210 L210,220 L270,200 L330,180 L390,160 L450,140 L510,130 L570,120 L630,130 L690,140 L750,150 L750,270 L90,270 Z"/>
<polyline class="chart-line" points="90,200 150,210 210,220 270,200 330,180 390,160 450,140 510,130 570,120 630,130 690,140 750,150"/>
<circle cx="90" cy="200" r="4" class="chart-dot"/>
<circle cx="150" cy="210" r="4" class="chart-dot"/>
<circle cx="210" cy="220" r="4" class="chart-dot"/>
<circle cx="270" cy="200" r="4" class="chart-dot"/>
<circle cx="330" cy="180" r="4" class="chart-dot"/>
<circle cx="390" cy="160" r="4" class="chart-dot"/>
<circle cx="450" cy="140" r="4" class="chart-dot"/>
<circle cx="510" cy="130" r="4" class="chart-dot"/>
<circle cx="570" cy="120" r="4" class="chart-dot"/>
<circle cx="630" cy="130" r="4" class="chart-dot"/>
<circle cx="690" cy="140" r="4" class="chart-dot"/>
<circle cx="750" cy="150" r="4" class="chart-dot"/>
</svg>
</div>
</div>
</div>
</div>
</main>
<script>
function toggleSubgroup(h){h.parentElement.classList.toggle('open');}
(function(){var a=document.querySelector('.sidebar-item.active');if(!a)return;var s=a.closest('.sidebar-subgroup');if(s)s.classList.add('open');})();
function switchTimeTab(el){
var tabs=document.querySelectorAll('.time-tab');
tabs.forEach(function(t){t.classList.remove('active');});
el.classList.add('active');
}
var metricData={
temp: {avg:'18.2 ℃', min:'15.6 ℃', max:'21.3 ℃'},
cond: {avg:'335 US/cm', min:'280 US/cm', max:'420 US/cm'},
ph: {avg:'7.1', min:'6.8', max:'7.5'},
salt: {avg:'185 mg/L', min:'150 mg/L', max:'230 mg/L'},
resist: {avg:'2985 Ω·m', min:'2380 Ω·m', max:'3570 Ω·m'},
tds: {avg:'168 mg/L', min:'140 mg/L', max:'210 mg/L'}
};
function switchMetric(el,key){
var btns=document.querySelectorAll('.metric-btn');
btns.forEach(function(b){b.classList.remove('active');});
el.classList.add('active');
var d=metricData[key];
document.getElementById('avgVal').textContent=d.avg;
document.getElementById('minVal').textContent=d.min;
document.getElementById('maxVal').textContent=d.max;
}
</script>
</body>
</html>
@@ -3,7 +3,7 @@
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>健康监测 - 数据监测 | 健康长庆原型</title>
<title>水质监测 - 数据监测 | 健康长庆原型</title>
<style>
*{box-sizing:border-box;margin:0;padding:0;}
body{font-family:-apple-system,BlinkMacSystemFont,'PingFang SC','Microsoft YaHei',sans-serif;background:#F5F7FA;color:#333;min-width:1280px;}
@@ -18,8 +18,7 @@
.top-bar__logo{display:flex;align-items:center;gap:8px;color:#fff;font-size:var(--font-lg);font-weight:600;white-space:nowrap;width:240px;flex-shrink:0;}
.top-bar__logo svg{width:28px;height:28px;}
.top-bar__right{display:flex;align-items:center;gap:16px;color:rgba(255,255,255,0.65);font-size:var(--font-sm);}
.btn-back{color:rgba(255,255,255,0.65);cursor:pointer;display:flex;align-items:center;gap:4px;text-decoration:none;}
.btn-back:hover{color:#fff;}
.btn-back{color:rgba(255,255,255,0.65);cursor:pointer;display:flex;align-items:center;gap:4px;text-decoration:none;}.btn-back:hover{color:#fff;}
.avatar{width:32px;height:32px;border-radius:50%;background:#1890FF;display:flex;align-items:center;justify-content:center;color:#fff;font-size:var(--font-sm);cursor:pointer;}
.top-bar__nav{display:flex;align-items:center;gap:4px;flex:1;}
.top-bar__nav a{color:rgba(255,255,255,0.65);text-decoration:none;padding:6px 16px;border-radius:var(--radius-sm);font-size:var(--font-sm);transition:all .2s;}
@@ -40,9 +39,44 @@
.sidebar-subgroup.open>.sidebar-subgroup__body{display:block;}
.sidebar-subgroup__body .sidebar-item{padding-left:36px;font-size:12px;}
.main{margin-left:240px;margin-top:56px;padding:24px;min-height:calc(100vh - 56px);}
.page-placeholder{display:flex;flex-direction:column;align-items:center;justify-content:center;height:calc(100vh - 56px - 48px);color:var(--text-placeholder);gap:12px;}
.page-placeholder svg{opacity:.25;}
.page-placeholder p{font-size:var(--font-base);}
.filter-bar{background:#fff;border-radius:var(--radius-md);padding:20px 24px;margin-bottom:16px;box-shadow:var(--shadow-sm);display:flex;align-items:center;gap:16px;flex-wrap:wrap;}
.filter-item{display:flex;align-items:center;gap:8px;}
.filter-item label{font-size:var(--font-sm);color:var(--text-secondary);white-space:nowrap;}
.filter-input{height:36px;border:1px solid var(--border);border-radius:var(--radius-sm);padding:0 12px;font-size:var(--font-sm);color:var(--text-primary);outline:none;background:#fff;min-width:180px;}.filter-input:focus{border-color:var(--primary);}
.filter-select{height:36px;border:1px solid var(--border);border-radius:var(--radius-sm);padding:0 28px 0 12px;font-size:var(--font-sm);color:var(--text-primary);outline:none;background:#fff url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6'%3E%3Cpath d='M0 0l5 6 5-6z' fill='%23999'/%3E%3C/svg%3E") no-repeat right 10px center;appearance:none;cursor:pointer;min-width:140px;}
.btn{height:36px;padding:0 16px;border-radius:var(--radius-sm);font-size:var(--font-sm);cursor:pointer;border:none;transition:all .2s;display:inline-flex;align-items:center;gap:6px;}
.btn-primary{background:var(--primary);color:#fff;}.btn-primary:hover{background:#40a9ff;}
.btn-default{background:#fff;color:var(--text-primary);border:1px solid var(--border);}.btn-default:hover{color:var(--primary);border-color:var(--primary);}
.action-bar{display:flex;align-items:center;gap:12px;margin-bottom:16px;}
.table-card{background:#fff;border-radius:var(--radius-md);box-shadow:var(--shadow-sm);overflow:hidden;}
.table-card__content{overflow-x:auto;-webkit-overflow-scrolling:touch;}
table{width:100%;border-collapse:collapse;min-width:1400px;}
thead th{background:#FAFAFA;padding:12px 14px;text-align:center;font-size:var(--font-xs);color:var(--text-secondary);font-weight:500;border-bottom:1px solid var(--border);border-right:1px solid var(--border);white-space:nowrap;}
thead th:last-child{border-right:none;}
thead th.th-left{text-align:left;}
tbody td{padding:12px 14px;font-size:var(--font-xs);color:var(--text-primary);border-bottom:1px solid var(--border);text-align:center;white-space:nowrap;}
tbody td.td-left{text-align:left;}
tbody tr:last-child td{border-bottom:none;}
tbody tr:hover{background:#F8FBFF;}
/* 固定列 */
thead tr:first-child th:nth-child(-n+2),tbody td:nth-child(-n+2),thead tr:first-child th:nth-last-child(-n+2),tbody td:nth-last-child(-n+2){position:sticky;z-index:2;}
thead tr:first-child th:nth-child(-n+2),thead tr:first-child th:nth-last-child(-n+2){z-index:3;}
thead tr:first-child th:nth-child(1),tbody td:nth-child(1){left:0;}
thead tr:first-child th:nth-child(2),tbody td:nth-child(2){left:140px;}
thead tr:first-child th:nth-last-child(2),tbody td:nth-last-child(2){right:70px;}
thead tr:first-child th:nth-last-child(1),tbody td:nth-last-child(1){right:0;}
tbody td:nth-child(-n+2),tbody td:nth-last-child(-n+2){background:#fff;}
tbody tr:hover td:nth-child(-n+2),tbody tr:hover td:nth-last-child(-n+2){background:#F8FBFF;}
tbody td:nth-child(2),thead tr:first-child th:nth-child(2){box-shadow:2px 0 4px rgba(0,0,0,0.06);}
tbody td:nth-last-child(2),thead tr:first-child th:nth-last-child(2){box-shadow:-2px 0 4px rgba(0,0,0,0.06);}
.link{color:var(--primary);cursor:pointer;font-size:var(--font-xs);text-decoration:none;}.link:hover{color:#40a9ff;}
.wqi-tag{display:inline-block;padding:2px 10px;border-radius:10px;font-size:var(--font-xs);font-weight:500;}
.wqi-tag--pass{background:#F6FFED;color:#52C41A;}
.wqi-tag--fail{background:#FFF1F0;color:#FF4D4F;}
.pagination{display:flex;align-items:center;justify-content:flex-end;padding:16px 24px;gap:8px;border-top:1px solid var(--border);}
.pagination span{font-size:var(--font-sm);color:var(--text-secondary);}
.page-btn{width:32px;height:32px;border:1px solid var(--border);border-radius:var(--radius-sm);background:#fff;cursor:pointer;font-size:var(--font-sm);display:inline-flex;align-items:center;justify-content:center;transition:all .2s;}
.page-btn:hover,.page-btn.active{background:var(--primary);color:#fff;border-color:var(--primary);}
</style>
</head>
<body>
@@ -57,10 +91,7 @@
<a href="../exception-dirty.html">异常事件</a>
</nav>
<div class="top-bar__right">
<a class="btn-back" href="../../../index.html">
<svg width="16" height="16" viewBox="0 0 16 16" fill="none"><path d="M10 3L5 8l5 5" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/></svg>
返回首页
</a>
<a class="btn-back" href="../../../index.html"><svg width="16" height="16" viewBox="0 0 16 16" fill="none"><path d="M10 3L5 8l5 5" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/></svg> 返回首页</a>
<div class="avatar"></div>
<span style="color:rgba(255,255,255,0.65);">系统管理员 ▾</span>
</div>
@@ -70,55 +101,91 @@
<div class="sidebar-subgroup">
<div class="sidebar-subgroup__header" onclick="toggleSubgroup(this)"><svg class="arrow" viewBox="0 0 12 12"><path d="M4 2l4 4-4 4" fill="none" stroke-width="1.5" stroke-linecap="round"/></svg> 室内空气</div>
<div class="sidebar-subgroup__body">
<a href="indoor-device-list.html" class="sidebar-item">设备列表</a>
<a href="indoor-device-category.html" class="sidebar-item">设备分类</a>
<a href="indoor-data-monitor.html" class="sidebar-item">数据监测</a>
<a href="indoor-exception-alarm.html" class="sidebar-item">异常报警</a>
<a href="indoor-app-record.html" class="sidebar-item">应用记录</a>
<a href="indoor-history-data.html" class="sidebar-item">历史数据</a>
<a href="indoor-device-list.html" class="sidebar-item">设备列表</a><a href="indoor-device-category.html" class="sidebar-item">设备分类</a><a href="indoor-data-monitor.html" class="sidebar-item">数据监测</a><a href="indoor-exception-alarm.html" class="sidebar-item">异常报警</a><a href="indoor-app-record.html" class="sidebar-item">应用记录</a><a href="indoor-history-data.html" class="sidebar-item">历史数据</a>
</div>
</div>
<div class="sidebar-subgroup">
<div class="sidebar-subgroup__header" onclick="toggleSubgroup(this)"><svg class="arrow" viewBox="0 0 12 12"><path d="M4 2l4 4-4 4" fill="none" stroke-width="1.5" stroke-linecap="round"/></svg> 室外空气</div>
<div class="sidebar-subgroup__body">
<a href="outdoor-device-list.html" class="sidebar-item">设备列表</a>
<a href="outdoor-device-category.html" class="sidebar-item">设备分类</a>
<a href="outdoor-data-monitor.html" class="sidebar-item">数据监测</a>
<a href="outdoor-exception-alarm.html" class="sidebar-item">异常报警</a>
<a href="outdoor-app-record.html" class="sidebar-item">应用记录</a>
<a href="outdoor-history-data.html" class="sidebar-item">历史数据</a>
<a href="outdoor-device-list.html" class="sidebar-item">设备列表</a><a href="outdoor-device-category.html" class="sidebar-item">设备分类</a><a href="outdoor-data-monitor.html" class="sidebar-item">数据监测</a><a href="outdoor-exception-alarm.html" class="sidebar-item">异常报警</a><a href="outdoor-app-record.html" class="sidebar-item">应用记录</a><a href="outdoor-history-data.html" class="sidebar-item">历史数据</a>
</div>
</div>
<div class="sidebar-subgroup open">
<div class="sidebar-subgroup__header" onclick="toggleSubgroup(this)"><svg class="arrow" viewBox="0 0 12 12"><path d="M4 2l4 4-4 4" fill="none" stroke-width="1.5" stroke-linecap="round"/></svg> 水质监测</div>
<div class="sidebar-subgroup__body">
<a href="water-device-list.html" class="sidebar-item">设备列表</a>
<a href="water-device-category.html" class="sidebar-item">设备分类</a>
<a href="water-data-monitor.html" class="sidebar-item active">数据监测</a>
<a href="water-exception-alarm.html" class="sidebar-item">异常报警</a>
<a href="water-app-record.html" class="sidebar-item">应用记录</a>
<a href="water-history-data.html" class="sidebar-item">历史数据</a>
<a href="water-device-list.html" class="sidebar-item">设备列表</a><a href="water-device-category.html" class="sidebar-item">设备分类</a><a href="water-data-monitor.html" class="sidebar-item active">数据监测</a><a href="water-exception-alarm.html" class="sidebar-item">异常报警</a><a href="water-app-record.html" class="sidebar-item">应用记录</a><a href="water-history-data.html" class="sidebar-item">历史数据</a>
</div>
</div>
<div class="sidebar-subgroup">
<div class="sidebar-subgroup__header" onclick="toggleSubgroup(this)"><svg class="arrow" viewBox="0 0 12 12"><path d="M4 2l4 4-4 4" fill="none" stroke-width="1.5" stroke-linecap="round"/></svg> 花粉监测</div>
<div class="sidebar-subgroup__body">
<a href="pollen-device-list.html" class="sidebar-item">设备列表</a>
<a href="pollen-device-category.html" class="sidebar-item">设备分类</a>
<a href="pollen-data-monitor.html" class="sidebar-item">数据监测</a>
<a href="pollen-exception-alarm.html" class="sidebar-item">异常报警</a>
<a href="pollen-app-record.html" class="sidebar-item">应用记录</a>
<a href="pollen-history-data.html" class="sidebar-item">历史数据</a>
<a href="pollen-knowledge.html" class="sidebar-item">知识科普</a>
<a href="pollen-device-list.html" class="sidebar-item">设备列表</a><a href="pollen-device-category.html" class="sidebar-item">设备分类</a><a href="pollen-data-monitor.html" class="sidebar-item">数据监测</a><a href="pollen-exception-alarm.html" class="sidebar-item">异常报警</a><a href="pollen-app-record.html" class="sidebar-item">应用记录</a><a href="pollen-history-data.html" class="sidebar-item">历史数据</a><a href="pollen-knowledge.html" class="sidebar-item">知识科普</a>
</div>
</div>
</aside>
<main class="main">
<div class="page-placeholder">
<svg width="64" height="64" viewBox="0 0 64 64" fill="none"><rect x="8" y="8" width="48" height="48" rx="8" stroke="#ccc" stroke-width="2"/><path d="M20 32h24M32 20v24" stroke="#ccc" stroke-width="2" stroke-linecap="round"/></svg>
<p>数据监测</p>
<div class="filter-bar">
<div class="filter-item"><label>设备名称</label><input class="filter-input" placeholder="请输入设备名称"></div>
<div class="filter-item"><label>设备编码</label><input class="filter-input" placeholder="请输入设备编码"></div>
<div class="filter-item"><label>所属单位</label><select class="filter-select"><option value="">全部</option><option>采油一厂</option><option>采油二厂</option><option>采油三厂</option></select></div>
<div class="filter-item"><label>水质等级</label><select class="filter-select"><option value="">全部</option><option>达标</option><option>未达标</option></select></div>
<button class="btn btn-primary">查询</button>
<button class="btn btn-default">重置</button>
</div>
<div class="action-bar"><button class="btn btn-default">导出列表数据</button></div>
<div class="table-card">
<div class="table-card__content">
<table>
<thead>
<tr>
<th rowspan="2" class="th-left" style="min-width:140px;">设备名称</th>
<th rowspan="2" style="min-width:110px;">设备编码</th>
<th rowspan="2" style="min-width:90px;">所属单位</th>
<th rowspan="2" style="min-width:120px;">设备位置</th>
<th rowspan="2" style="min-width:150px;">数据更新时间</th>
<th colspan="6">监测数据</th>
<th rowspan="2" style="min-width:80px;">水质等级</th>
<th rowspan="2" style="min-width:70px;">操作</th>
</tr>
<tr>
<th>温度(℃)</th><th>电导率(US/cm)</th><th>PH</th><th>盐度(mg/L)</th><th>电阻率(Ω·m)</th><th>TDS(mg/L)</th>
</tr>
</thead>
<tbody>
<tr>
<td class="td-left">多参数水质分析仪-A01</td><td>WQ-2024-001</td><td>采油一厂</td><td>生活区供水站</td><td>2026-05-14 14:30</td>
<td>18.5</td><td>320</td><td>7.2</td><td>180</td><td>3125</td><td>160</td>
<td><span class="wqi-tag wqi-tag--pass">达标</span></td><td><a class="link" href="water-data-analysis.html">动态分析</a></td>
</tr>
<tr>
<td class="td-left">在线PH计-B02</td><td>WQ-2024-002</td><td>采油一厂</td><td>污水处理站出口</td><td>2026-05-14 14:28</td>
<td>20.3</td><td>580</td><td>6.8</td><td>320</td><td>1724</td><td>290</td>
<td><span class="wqi-tag wqi-tag--pass">达标</span></td><td><a class="link" href="water-data-analysis.html">动态分析</a></td>
</tr>
<tr>
<td class="td-left">电导率监测仪-C01</td><td>WQ-2024-003</td><td>采油二厂</td><td>注水站入口</td><td>2026-05-14 14:25</td>
<td>22.1</td><td>1250</td><td>8.5</td><td>680</td><td>800</td><td>625</td>
<td><span class="wqi-tag wqi-tag--fail">未达标</span></td><td><a class="link" href="water-data-analysis.html">动态分析</a></td>
</tr>
<tr>
<td class="td-left">TDS检测仪-D01</td><td>WQ-2024-004</td><td>采油二厂</td><td>生产区储水池</td><td>2026-05-14 14:20</td>
<td>19.8</td><td>450</td><td>7.0</td><td>240</td><td>2222</td><td>225</td>
<td><span class="wqi-tag wqi-tag--pass">达标</span></td><td><a class="link" href="water-data-analysis.html">动态分析</a></td>
</tr>
<tr>
<td class="td-left">多参数水质分析仪-A03</td><td>WQ-2024-005</td><td>采油三厂</td><td>排污口监测点</td><td>2026-05-14 14:15</td>
<td>23.5</td><td>1680</td><td>9.2</td><td>920</td><td>595</td><td>840</td>
<td><span class="wqi-tag wqi-tag--fail">未达标</span></td><td><a class="link" href="water-data-analysis.html">动态分析</a></td>
</tr>
</tbody>
</table>
</div>
<div class="pagination"><span>共 5 条</span><button class="page-btn active">1</button></div>
</div>
</main>
<script>function toggleSubgroup(h){h.parentElement.classList.toggle('open');}(function(){var a=document.querySelector('.sidebar-item.active');if(!a)return;var s=a.closest('.sidebar-subgroup');if(s)s.classList.add('open');})();</script>
<script>
function toggleSubgroup(h){h.parentElement.classList.toggle('open');}
(function(){var a=document.querySelector('.sidebar-item.active');if(!a)return;var s=a.closest('.sidebar-subgroup');if(s)s.classList.add('open');})();
</script>
</body>
</html>
</html>
@@ -3,7 +3,7 @@
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>健康监测 - 设备分类 | 健康长庆原型</title>
<title>水质监测 - 设备分类 | 健康长庆原型</title>
<style>
*{box-sizing:border-box;margin:0;padding:0;}
body{font-family:-apple-system,BlinkMacSystemFont,'PingFang SC','Microsoft YaHei',sans-serif;background:#F5F7FA;color:#333;min-width:1280px;}
@@ -40,9 +40,58 @@
.sidebar-subgroup.open>.sidebar-subgroup__body{display:block;}
.sidebar-subgroup__body .sidebar-item{padding-left:36px;font-size:12px;}
.main{margin-left:240px;margin-top:56px;padding:24px;min-height:calc(100vh - 56px);}
.page-placeholder{display:flex;flex-direction:column;align-items:center;justify-content:center;height:calc(100vh - 56px - 48px);color:var(--text-placeholder);gap:12px;}
.page-placeholder svg{opacity:.25;}
.page-placeholder p{font-size:var(--font-base);}
.filter-bar{background:#fff;border-radius:var(--radius-md);padding:20px 24px;margin-bottom:16px;box-shadow:var(--shadow-sm);display:flex;align-items:center;gap:16px;flex-wrap:wrap;}
.filter-item{display:flex;align-items:center;gap:8px;}
.filter-item label{font-size:var(--font-sm);color:var(--text-secondary);white-space:nowrap;}
.filter-input{height:36px;border:1px solid var(--border);border-radius:var(--radius-sm);padding:0 12px;font-size:var(--font-sm);color:var(--text-primary);outline:none;background:#fff;min-width:200px;}
.filter-input:focus{border-color:var(--primary);}
.btn{height:36px;padding:0 16px;border-radius:var(--radius-sm);font-size:var(--font-sm);cursor:pointer;border:none;transition:all .2s;display:inline-flex;align-items:center;gap:6px;}
.btn-primary{background:var(--primary);color:#fff;}.btn-primary:hover{background:#40a9ff;}
.btn-default{background:#fff;color:var(--text-primary);border:1px solid var(--border);}.btn-default:hover{color:var(--primary);border-color:var(--primary);}
.action-bar{display:flex;align-items:center;gap:12px;margin-bottom:16px;}
.table-card{background:#fff;border-radius:var(--radius-md);box-shadow:var(--shadow-sm);overflow:hidden;}
.table-card__content{overflow-x:auto;-webkit-overflow-scrolling:touch;}
table{width:100%;border-collapse:collapse;min-width:1000px;}
thead th{background:#FAFAFA;padding:12px 16px;text-align:center;font-size:var(--font-sm);color:var(--text-secondary);font-weight:500;border-bottom:1px solid var(--border);border-right:1px solid var(--border);white-space:nowrap;}
thead th:last-child{border-right:none;}
thead th.th-left{text-align:left;}
tbody td{padding:14px 16px;font-size:var(--font-sm);color:var(--text-primary);border-bottom:1px solid var(--border);text-align:center;white-space:nowrap;}
tbody td.td-left{text-align:left;}
tbody tr:last-child td{border-bottom:none;}
tbody tr:hover{background:#F8FBFF;}
.link{color:var(--primary);cursor:pointer;font-size:var(--font-sm);text-decoration:none;}.link:hover{color:#40a9ff;}
.link-danger{color:var(--danger);cursor:pointer;font-size:var(--font-sm);text-decoration:none;}.link-danger:hover{color:#ff7875;}
.pagination{display:flex;align-items:center;justify-content:flex-end;padding:16px 24px;gap:8px;border-top:1px solid var(--border);}
.pagination span{font-size:var(--font-sm);color:var(--text-secondary);}
.page-btn{width:32px;height:32px;border:1px solid var(--border);border-radius:var(--radius-sm);background:#fff;cursor:pointer;font-size:var(--font-sm);display:inline-flex;align-items:center;justify-content:center;transition:all .2s;}
.page-btn:hover,.page-btn.active{background:var(--primary);color:#fff;border-color:var(--primary);}
.drawer-mask{display:none;position:fixed;top:0;left:0;right:0;bottom:0;background:rgba(0,0,0,0.45);z-index:200;}
.drawer-mask.open{display:block;}
.drawer{position:fixed;top:0;right:-600px;width:600px;height:100%;background:#fff;z-index:201;box-shadow:-4px 0 16px rgba(0,0,0,0.12);transition:right .3s ease;display:flex;flex-direction:column;}
.drawer.open{right:0;}
.drawer__header{display:flex;align-items:center;justify-content:space-between;padding:16px 24px;border-bottom:1px solid var(--border);}
.drawer__title{font-size:var(--font-base);font-weight:600;color:var(--text-primary);}
.drawer__close{width:32px;height:32px;border:none;background:none;cursor:pointer;display:flex;align-items:center;justify-content:center;border-radius:var(--radius-sm);color:var(--text-placeholder);font-size:18px;}
.drawer__close:hover{background:#f5f5f5;color:var(--text-primary);}
.drawer__body{flex:1;overflow-y:auto;padding:24px;}
.drawer__footer{display:flex;align-items:center;justify-content:flex-end;gap:12px;padding:16px 24px;border-top:1px solid var(--border);}
.form-group{margin-bottom:20px;}
.form-label{display:block;font-size:var(--font-sm);color:var(--text-primary);margin-bottom:8px;font-weight:500;}
.form-label .required{color:var(--danger);margin-right:4px;}
.form-control{width:100%;height:36px;border:1px solid var(--border);border-radius:var(--radius-sm);padding:0 12px;font-size:var(--font-sm);color:var(--text-primary);outline:none;background:#fff;}
.form-control:focus{border-color:var(--primary);box-shadow:0 0 0 2px rgba(24,144,255,0.1);}
.threshold-section-title{font-size:var(--font-sm);font-weight:600;color:var(--text-primary);margin-bottom:12px;padding-bottom:8px;border-bottom:1px solid var(--border);}
.threshold-list{display:flex;flex-direction:column;gap:12px;}
.threshold-item{border:1px solid var(--border);border-radius:var(--radius-md);overflow:hidden;}
.threshold-item__header{display:flex;align-items:center;justify-content:space-between;padding:12px 16px;background:#FAFAFA;}
.threshold-item__label{font-size:var(--font-sm);font-weight:600;color:var(--text-primary);}
.threshold-item__unit{font-size:var(--font-xs);color:var(--text-placeholder);font-weight:400;margin-left:4px;}
.threshold-item__body{padding:12px 16px;}
.threshold-row{display:grid;grid-template-columns:1fr 1fr;gap:12px;}
.threshold-field{display:flex;flex-direction:column;gap:4px;}
.threshold-field label{font-size:var(--font-xs);color:var(--text-secondary);}
.threshold-field .form-control{height:34px;border:1px solid var(--border);border-radius:var(--radius-sm);padding:0 10px;font-size:var(--font-sm);outline:none;width:100%;}
.threshold-field .form-control:focus{border-color:var(--primary);}
</style>
</head>
<body>
@@ -57,10 +106,7 @@
<a href="../exception-dirty.html">异常事件</a>
</nav>
<div class="top-bar__right">
<a class="btn-back" href="../../../index.html">
<svg width="16" height="16" viewBox="0 0 16 16" fill="none"><path d="M10 3L5 8l5 5" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/></svg>
返回首页
</a>
<a class="btn-back" href="../../../index.html"><svg width="16" height="16" viewBox="0 0 16 16" fill="none"><path d="M10 3L5 8l5 5" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/></svg> 返回首页</a>
<div class="avatar"></div>
<span style="color:rgba(255,255,255,0.65);">系统管理员 ▾</span>
</div>
@@ -114,11 +160,175 @@
</div>
</aside>
<main class="main">
<div class="page-placeholder">
<svg width="64" height="64" viewBox="0 0 64 64" fill="none"><rect x="8" y="8" width="48" height="48" rx="8" stroke="#ccc" stroke-width="2"/><path d="M20 32h24M32 20v24" stroke="#ccc" stroke-width="2" stroke-linecap="round"/></svg>
<p>设备分类</p>
<div class="filter-bar">
<div class="filter-item"><label>分类名称</label><input class="filter-input" placeholder="请输入分类名称"></div>
<button class="btn btn-primary">查询</button>
<button class="btn btn-default">重置</button>
</div>
<div class="action-bar">
<!-- [交互] 点击打开右侧抽屉弹窗(新增模式) -->
<button class="btn btn-primary" onclick="openDrawer('add')">+ 新增</button>
</div>
<div class="table-card">
<div class="table-card__content">
<table>
<thead>
<tr>
<th rowspan="2" class="th-left" style="min-width:160px;">分类名称</th>
<th colspan="6">监测数据阈值</th>
<th rowspan="2" style="min-width:100px;">操作</th>
</tr>
<tr>
<th>温度(℃)</th>
<th>电导率(US/cm)</th>
<th>PH</th>
<th>盐度(mg/L)</th>
<th>电阻率(Ω-m)</th>
<th>TDS(mg/L)</th>
</tr>
</thead>
<tbody>
<tr>
<td class="td-left">水质多参数分析仪</td>
<td>0 ~ 40</td>
<td>0 ~ 2000</td>
<td>6.5 ~ 8.5</td>
<td>0 ~ 500</td>
<td>0 ~ 10000</td>
<td>0 ~ 1000</td>
<td><a class="link" onclick="openDrawer('edit',0)">编辑</a> <a class="link-danger">删除</a></td>
</tr>
<tr>
<td class="td-left">浊度检测仪</td>
<td>0 ~ 35</td>
<td>0 ~ 1500</td>
<td>6.0 ~ 9.0</td>
<td>0 ~ 300</td>
<td>0 ~ 8000</td>
<td>0 ~ 800</td>
<td><a class="link" onclick="openDrawer('edit',1)">编辑</a> <a class="link-danger">删除</a></td>
</tr>
<tr>
<td class="td-left">余氯检测仪</td>
<td>0 ~ 40</td>
<td>0 ~ 1800</td>
<td>6.5 ~ 8.5</td>
<td>0 ~ 400</td>
<td>0 ~ 9000</td>
<td>0 ~ 900</td>
<td><a class="link" onclick="openDrawer('edit',2)">编辑</a> <a class="link-danger">删除</a></td>
</tr>
<tr>
<td class="td-left">PH值检测仪</td>
<td>0 ~ 40</td>
<td>0 ~ 2000</td>
<td>6.0 ~ 9.0</td>
<td>0 ~ 500</td>
<td>0 ~ 10000</td>
<td>0 ~ 1000</td>
<td><a class="link" onclick="openDrawer('edit',3)">编辑</a> <a class="link-danger">删除</a></td>
</tr>
</tbody>
</table>
</div>
<div class="pagination">
<span>共 4 条</span>
<button class="page-btn active">1</button>
</div>
</div>
</main>
<script>function toggleSubgroup(h){h.parentElement.classList.toggle('open');}(function(){var a=document.querySelector('.sidebar-item.active');if(!a)return;var s=a.closest('.sidebar-subgroup');if(s)s.classList.add('open');})();</script>
<!-- 新增/编辑分类 - 右侧抽屉弹窗 -->
<div class="drawer-mask" id="drawerMask" onclick="closeDrawer()"></div>
<div class="drawer" id="drawer">
<div class="drawer__header">
<span class="drawer__title" id="drawerTitle">新增分类</span>
<button class="drawer__close" onclick="closeDrawer()">&times;</button>
</div>
<div class="drawer__body">
<div class="form-group">
<label class="form-label"><span class="required">*</span>分类名称</label>
<input class="form-control" id="formCategoryName" placeholder="请输入分类名称">
</div>
<div class="threshold-section-title">监测数据阈值设置</div>
<div class="threshold-list">
<div class="threshold-item">
<div class="threshold-item__header"><span class="threshold-item__label">温度<span class="threshold-item__unit">(℃)</span></span></div>
<div class="threshold-item__body"><div class="threshold-row">
<div class="threshold-field"><label>阈值下限</label><input class="form-control" type="number" placeholder="下限"></div>
<div class="threshold-field"><label>阈值上限</label><input class="form-control" type="number" placeholder="上限"></div>
</div></div>
</div>
<div class="threshold-item">
<div class="threshold-item__header"><span class="threshold-item__label">电导率<span class="threshold-item__unit">(US/cm)</span></span></div>
<div class="threshold-item__body"><div class="threshold-row">
<div class="threshold-field"><label>阈值下限</label><input class="form-control" type="number" placeholder="下限"></div>
<div class="threshold-field"><label>阈值上限</label><input class="form-control" type="number" placeholder="上限"></div>
</div></div>
</div>
<div class="threshold-item">
<div class="threshold-item__header"><span class="threshold-item__label">PH</span></div>
<div class="threshold-item__body"><div class="threshold-row">
<div class="threshold-field"><label>阈值下限</label><input class="form-control" type="number" step="0.1" placeholder="下限"></div>
<div class="threshold-field"><label>阈值上限</label><input class="form-control" type="number" step="0.1" placeholder="上限"></div>
</div></div>
</div>
<div class="threshold-item">
<div class="threshold-item__header"><span class="threshold-item__label">盐度<span class="threshold-item__unit">(mg/L)</span></span></div>
<div class="threshold-item__body"><div class="threshold-row">
<div class="threshold-field"><label>阈值下限</label><input class="form-control" type="number" placeholder="下限"></div>
<div class="threshold-field"><label>阈值上限</label><input class="form-control" type="number" placeholder="上限"></div>
</div></div>
</div>
<div class="threshold-item">
<div class="threshold-item__header"><span class="threshold-item__label">电阻率<span class="threshold-item__unit">(Ω-m)</span></span></div>
<div class="threshold-item__body"><div class="threshold-row">
<div class="threshold-field"><label>阈值下限</label><input class="form-control" type="number" placeholder="下限"></div>
<div class="threshold-field"><label>阈值上限</label><input class="form-control" type="number" placeholder="上限"></div>
</div></div>
</div>
<div class="threshold-item">
<div class="threshold-item__header"><span class="threshold-item__label">TDS<span class="threshold-item__unit">(mg/L)</span></span></div>
<div class="threshold-item__body"><div class="threshold-row">
<div class="threshold-field"><label>阈值下限</label><input class="form-control" type="number" placeholder="下限"></div>
<div class="threshold-field"><label>阈值上限</label><input class="form-control" type="number" placeholder="上限"></div>
</div></div>
</div>
</div>
</div>
<div class="drawer__footer">
<button class="btn btn-default" onclick="closeDrawer()">取消</button>
<button class="btn btn-primary" onclick="closeDrawer()">确定</button>
</div>
</div>
<script>
function toggleSubgroup(h){h.parentElement.classList.toggle('open');}
(function(){var a=document.querySelector('.sidebar-item.active');if(!a)return;var s=a.closest('.sidebar-subgroup');if(s)s.classList.add('open');})();
function openDrawer(mode, rowIdx){
var title = document.getElementById('drawerTitle');
var nameInput = document.getElementById('formCategoryName');
var fields = document.querySelectorAll('.threshold-field .form-control');
if(mode === 'edit'){
title.textContent = '编辑分类';
var row = document.querySelectorAll('tbody tr')[rowIdx];
var cells = row.querySelectorAll('td');
nameInput.value = cells[0].textContent.trim();
for(var i = 0; i < 6; i++){
var parts = cells[i+1].textContent.split('~');
fields[i*2].value = parts[0].trim();
fields[i*2+1].value = parts[1].trim();
}
} else {
title.textContent = '新增分类';
nameInput.value = '';
for(var j = 0; j < fields.length; j++){ fields[j].value = ''; }
}
document.getElementById('drawerMask').classList.add('open');
document.getElementById('drawer').classList.add('open');
}
function closeDrawer(){document.getElementById('drawerMask').classList.remove('open');document.getElementById('drawer').classList.remove('open');}
</script>
</body>
</html>
</html>
@@ -3,7 +3,7 @@
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>健康监测 - 设备列表 | 健康长庆原型</title>
<title>水质监测 - 设备列表 | 健康长庆原型</title>
<style>
*{box-sizing:border-box;margin:0;padding:0;}
body{font-family:-apple-system,BlinkMacSystemFont,'PingFang SC','Microsoft YaHei',sans-serif;background:#F5F7FA;color:#333;min-width:1280px;}
@@ -40,9 +40,56 @@
.sidebar-subgroup.open>.sidebar-subgroup__body{display:block;}
.sidebar-subgroup__body .sidebar-item{padding-left:36px;font-size:12px;}
.main{margin-left:240px;margin-top:56px;padding:24px;min-height:calc(100vh - 56px);}
.page-placeholder{display:flex;flex-direction:column;align-items:center;justify-content:center;height:calc(100vh - 56px - 48px);color:var(--text-placeholder);gap:12px;}
.page-placeholder svg{opacity:.25;}
.page-placeholder p{font-size:var(--font-base);}
.filter-bar{background:#fff;border-radius:var(--radius-md);padding:20px 24px;margin-bottom:16px;box-shadow:var(--shadow-sm);display:flex;align-items:center;gap:16px;flex-wrap:wrap;}
.filter-item{display:flex;align-items:center;gap:8px;}
.filter-item label{font-size:var(--font-sm);color:var(--text-secondary);white-space:nowrap;}
.filter-input{height:36px;border:1px solid var(--border);border-radius:var(--radius-sm);padding:0 12px;font-size:var(--font-sm);color:var(--text-primary);outline:none;background:#fff;min-width:160px;}
.filter-input:focus{border-color:var(--primary);}
.filter-select{height:36px;border:1px solid var(--border);border-radius:var(--radius-sm);padding:0 28px 0 12px;font-size:var(--font-sm);color:var(--text-primary);outline:none;background:#fff url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6'%3E%3Cpath d='M0 0l5 6 5-6z' fill='%23999'/%3E%3C/svg%3E") no-repeat right 10px center;appearance:none;cursor:pointer;min-width:140px;}
.btn{height:36px;padding:0 16px;border-radius:var(--radius-sm);font-size:var(--font-sm);cursor:pointer;border:none;transition:all .2s;display:inline-flex;align-items:center;gap:6px;}
.btn-primary{background:var(--primary);color:#fff;}.btn-primary:hover{background:#40a9ff;}
.btn-default{background:#fff;color:var(--text-primary);border:1px solid var(--border);}.btn-default:hover{color:var(--primary);border-color:var(--primary);}
.btn-success{background:var(--success);color:#fff;}.btn-success:hover{background:#73d13d;}
.action-bar{display:flex;align-items:center;gap:12px;margin-bottom:16px;}
.table-card{background:#fff;border-radius:var(--radius-md);box-shadow:var(--shadow-sm);overflow:hidden;}
.table-card__content{overflow-x:auto;-webkit-overflow-scrolling:touch;}
table{width:100%;border-collapse:collapse;min-width:1000px;}
thead th{background:#FAFAFA;padding:12px 16px;text-align:left;font-size:var(--font-sm);color:var(--text-secondary);font-weight:500;border-bottom:1px solid var(--border);white-space:nowrap;}
tbody td{padding:14px 16px;font-size:var(--font-sm);color:var(--text-primary);border-bottom:1px solid var(--border);white-space:nowrap;}
tbody tr:last-child td{border-bottom:none;}
tbody tr:hover{background:#F8FBFF;}
.link{color:var(--primary);cursor:pointer;font-size:var(--font-sm);text-decoration:none;}.link:hover{color:#40a9ff;}
.link-danger{color:var(--danger);cursor:pointer;font-size:var(--font-sm);text-decoration:none;}.link-danger:hover{color:#ff7875;}
.pagination{display:flex;align-items:center;justify-content:flex-end;padding:16px 24px;gap:8px;border-top:1px solid var(--border);}
.pagination span{font-size:var(--font-sm);color:var(--text-secondary);}
.page-btn{width:32px;height:32px;border:1px solid var(--border);border-radius:var(--radius-sm);background:#fff;cursor:pointer;font-size:var(--font-sm);display:inline-flex;align-items:center;justify-content:center;transition:all .2s;}
.page-btn:hover,.page-btn.active{background:var(--primary);color:#fff;border-color:var(--primary);}
.drawer-mask{display:none;position:fixed;top:0;left:0;right:0;bottom:0;background:rgba(0,0,0,0.45);z-index:200;}
.drawer-mask.open{display:block;}
.drawer{position:fixed;top:0;right:-560px;width:560px;height:100%;background:#fff;z-index:201;box-shadow:-4px 0 16px rgba(0,0,0,0.12);transition:right .3s ease;display:flex;flex-direction:column;}
.drawer.open{right:0;}
.drawer__header{display:flex;align-items:center;justify-content:space-between;padding:16px 24px;border-bottom:1px solid var(--border);}
.drawer__title{font-size:var(--font-base);font-weight:600;color:var(--text-primary);}
.drawer__close{width:32px;height:32px;border:none;background:none;cursor:pointer;display:flex;align-items:center;justify-content:center;border-radius:var(--radius-sm);color:var(--text-placeholder);font-size:18px;}
.drawer__close:hover{background:#f5f5f5;color:var(--text-primary);}
.drawer__body{flex:1;overflow-y:auto;padding:24px;}
.drawer__footer{display:flex;align-items:center;justify-content:flex-end;gap:12px;padding:16px 24px;border-top:1px solid var(--border);}
.form-group{margin-bottom:20px;}
.form-label{display:block;font-size:var(--font-sm);color:var(--text-primary);margin-bottom:8px;font-weight:500;}
.form-label .required{color:var(--danger);margin-right:4px;}
.form-control{width:100%;height:36px;border:1px solid var(--border);border-radius:var(--radius-sm);padding:0 12px;font-size:var(--font-sm);color:var(--text-primary);outline:none;background:#fff;}
.form-control:focus{border-color:var(--primary);box-shadow:0 0 0 2px rgba(24,144,255,0.1);}
.form-select{width:100%;height:36px;border:1px solid var(--border);border-radius:var(--radius-sm);padding:0 28px 0 12px;font-size:var(--font-sm);color:var(--text-primary);outline:none;background:#fff url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6'%3E%3Cpath d='M0 0l5 6 5-6z' fill='%23999'/%3E%3C/svg%3E") no-repeat right 10px center;appearance:none;cursor:pointer;}
.form-select:focus{border-color:var(--primary);box-shadow:0 0 0 2px rgba(24,144,255,0.1);}
.map-picker{width:100%;height:200px;border:1px solid var(--border);border-radius:var(--radius-sm);background:#f0f2f5;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:8px;color:var(--text-placeholder);cursor:pointer;position:relative;overflow:hidden;}
.map-picker__icon{width:40px;height:40px;border-radius:50%;background:var(--primary-light);display:flex;align-items:center;justify-content:center;}
.map-picker__text{font-size:var(--font-sm);}
.map-picker__pin{position:absolute;top:50%;left:50%;transform:translate(-50%,-100%);display:none;}
.map-picker.selected{background:linear-gradient(135deg,#e6f7ff 0%,#f0f5ff 100%);border-color:var(--primary);}
.map-picker.selected .map-picker__pin{display:block;}
.map-picker.selected .map-picker__icon,.map-picker.selected .map-picker__text{display:none;}
.map-picker__hint{position:absolute;bottom:8px;left:0;right:0;text-align:center;font-size:var(--font-xs);color:var(--text-placeholder);display:none;}
.map-picker.selected .map-picker__hint{display:block;}
</style>
</head>
<body>
@@ -57,10 +104,7 @@
<a href="../exception-dirty.html">异常事件</a>
</nav>
<div class="top-bar__right">
<a class="btn-back" href="../../../index.html">
<svg width="16" height="16" viewBox="0 0 16 16" fill="none"><path d="M10 3L5 8l5 5" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/></svg>
返回首页
</a>
<a class="btn-back" href="../../../index.html"><svg width="16" height="16" viewBox="0 0 16 16" fill="none"><path d="M10 3L5 8l5 5" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/></svg> 返回首页</a>
<div class="avatar"></div>
<span style="color:rgba(255,255,255,0.65);">系统管理员 ▾</span>
</div>
@@ -114,11 +158,126 @@
</div>
</aside>
<main class="main">
<div class="page-placeholder">
<svg width="64" height="64" viewBox="0 0 64 64" fill="none"><rect x="8" y="8" width="48" height="48" rx="8" stroke="#ccc" stroke-width="2"/><path d="M20 32h24M32 20v24" stroke="#ccc" stroke-width="2" stroke-linecap="round"/></svg>
<p>设备列表</p>
<!-- 筛选条件 -->
<div class="filter-bar">
<div class="filter-item"><label>设备编码</label><input class="filter-input" placeholder="请输入设备编码"></div>
<div class="filter-item"><label>设备名称</label><input class="filter-input" placeholder="请输入设备名称"></div>
<div class="filter-item"><label>所属单位</label><select class="filter-select"><option value="">全部</option><option>采油一厂</option><option>采油二厂</option><option>采气厂</option><option>炼化公司</option></select></div>
<div class="filter-item"><label>设备分类</label><select class="filter-select"><option value="">全部</option><option>水质多参数分析仪</option><option>浊度检测仪</option><option>余氯检测仪</option><option>PH值检测仪</option></select></div>
<button class="btn btn-primary">查询</button>
<button class="btn btn-default">重置</button>
</div>
<!-- 操作按钮 -->
<div class="action-bar">
<button class="btn btn-primary" onclick="openDrawer()">+ 新增设备</button>
<button class="btn btn-success">批量入库导入</button>
<button class="btn btn-default">查看导入任务</button>
<button class="btn btn-default">导出列表数据</button>
</div>
<!-- 数据列表 -->
<div class="table-card">
<div class="table-card__content">
<table>
<thead><tr><th>设备名称</th><th>设备编码</th><th>设备分类</th><th>所属单位</th><th>设备位置</th><th>布点日期</th><th>监测时长(天)</th><th>操作</th></tr></thead>
<tbody>
<tr><td>水质分析仪A1</td><td>WQ-2024-001</td><td>水质多参数分析仪</td><td>采油一厂</td><td>生活区供水站</td><td>2024-04-20</td><td>384</td><td><a class="link" onclick="openDrawer()">编辑</a> <a class="link-danger">删除</a></td></tr>
<tr><td>浊度检测仪A2</td><td>WQ-2024-002</td><td>浊度检测仪</td><td>采油一厂</td><td>员工食堂水房</td><td>2024-05-15</td><td>359</td><td><a class="link" onclick="openDrawer()">编辑</a> <a class="link-danger">删除</a></td></tr>
<tr><td>余氯检测仪B1</td><td>WQ-2024-003</td><td>余氯检测仪</td><td>采油二厂</td><td>宿舍区水塔</td><td>2024-06-28</td><td>315</td><td><a class="link" onclick="openDrawer()">编辑</a> <a class="link-danger">删除</a></td></tr>
<tr><td>PH检测仪C1</td><td>WQ-2024-004</td><td>PH值检测仪</td><td>采气厂</td><td>办公区直饮水机房</td><td>2024-09-12</td><td>239</td><td><a class="link" onclick="openDrawer()">编辑</a> <a class="link-danger">删除</a></td></tr>
<tr><td>水质分析仪D1</td><td>WQ-2025-001</td><td>水质多参数分析仪</td><td>炼化公司</td><td>厂区净水站出口</td><td>2025-01-20</td><td>109</td><td><a class="link" onclick="openDrawer()">编辑</a> <a class="link-danger">删除</a></td></tr>
</tbody>
</table>
</div>
<div class="pagination">
<span>共 31 条</span>
<button class="page-btn"></button>
<button class="page-btn active">1</button>
<button class="page-btn">2</button>
<button class="page-btn">3</button>
<button class="page-btn">4</button>
<button class="page-btn"></button>
</div>
</div>
</main>
<script>function toggleSubgroup(h){h.parentElement.classList.toggle('open');}(function(){var a=document.querySelector('.sidebar-item.active');if(!a)return;var s=a.closest('.sidebar-subgroup');if(s)s.classList.add('open');})();</script>
<!-- 新增设备 - 右侧抽屉弹窗 -->
<div class="drawer-mask" id="drawerMask" onclick="closeDrawer()"></div>
<div class="drawer" id="drawer">
<div class="drawer__header">
<span class="drawer__title">新增设备</span>
<button class="drawer__close" onclick="closeDrawer()">&times;</button>
</div>
<div class="drawer__body">
<div class="form-group">
<label class="form-label"><span class="required">*</span>设备名称</label>
<input class="form-control" placeholder="请输入设备名称">
</div>
<div class="form-group">
<label class="form-label"><span class="required">*</span>设备编码</label>
<input class="form-control" placeholder="请输入设备编码">
</div>
<div class="form-group">
<label class="form-label"><span class="required">*</span>设备分类</label>
<select class="form-select">
<option value="">请选择设备分类</option>
<option>水质多参数分析仪</option>
<option>浊度检测仪</option>
<option>余氯检测仪</option>
<option>PH值检测仪</option>
</select>
</div>
<div class="form-group">
<label class="form-label"><span class="required">*</span>所属单位</label>
<select class="form-select">
<option value="">请选择所属单位</option>
<option>采油一厂</option>
<option>采油二厂</option>
<option>采气厂</option>
<option>炼化公司</option>
</select>
</div>
<div class="form-group">
<label class="form-label"><span class="required">*</span>设备位置</label>
<div class="map-picker selected" onclick="this.classList.toggle('selected')">
<div class="map-picker__icon">
<svg width="20" height="20" viewBox="0 0 20 20" fill="none"><path d="M10 2C6.69 2 4 4.69 4 8c0 4.5 6 10 6 10s6-5.5 6-10c0-3.31-2.69-6-6-6zm0 8a2 2 0 110-4 2 2 0 010 4z" fill="#1890FF"/></svg>
</div>
<div class="map-picker__text">点击地图选择设备位置</div>
<svg class="map-picker__pin" width="160" height="120" viewBox="0 0 160 120">
<rect width="160" height="120" rx="4" fill="#e6f7ff" opacity="0.5"/>
<line x1="0" y1="30" x2="160" y2="30" stroke="#d9d9d9" stroke-width="0.5" stroke-dasharray="4"/>
<line x1="0" y1="60" x2="160" y2="60" stroke="#d9d9d9" stroke-width="0.5" stroke-dasharray="4"/>
<line x1="0" y1="90" x2="160" y2="90" stroke="#d9d9d9" stroke-width="0.5" stroke-dasharray="4"/>
<line x1="40" y1="0" x2="40" y2="120" stroke="#d9d9d9" stroke-width="0.5" stroke-dasharray="4"/>
<line x1="80" y1="0" x2="80" y2="120" stroke="#d9d9d9" stroke-width="0.5" stroke-dasharray="4"/>
<line x1="120" y1="0" x2="120" y2="120" stroke="#d9d9d9" stroke-width="0.5" stroke-dasharray="4"/>
<path d="M80 40C76.69 40 74 42.69 74 46c0 4.5 6 10 6 10s6-5.5 6-10c0-3.31-2.69-6-6-6zm0 8a2 2 0 110-4 2 2 0 010 4z" fill="#1890FF"/>
<circle cx="80" cy="46" r="12" fill="none" stroke="#1890FF" stroke-width="1" opacity="0.3"/>
<circle cx="80" cy="46" r="20" fill="none" stroke="#1890FF" stroke-width="0.5" opacity="0.15"/>
</svg>
<div class="map-picker__hint">点击重新选点</div>
</div>
</div>
<div class="form-group">
<label class="form-label"><span class="required">*</span>详细地址</label>
<input class="form-control" value="陕西省西安市长庆路采油一厂生活区供水站" placeholder="地图选点后自动带入,可手动修改">
</div>
<div class="form-group">
<label class="form-label"><span class="required">*</span>布点日期</label>
<input class="form-control" type="date" value="2025-05-14">
</div>
</div>
<div class="drawer__footer">
<button class="btn btn-default" onclick="closeDrawer()">取消</button>
<button class="btn btn-primary" onclick="closeDrawer()">确定</button>
</div>
</div>
<script>
function toggleSubgroup(h){h.parentElement.classList.toggle('open');}
(function(){var a=document.querySelector('.sidebar-item.active');if(!a)return;var s=a.closest('.sidebar-subgroup');if(s)s.classList.add('open');})();
function openDrawer(){document.getElementById('drawerMask').classList.add('open');document.getElementById('drawer').classList.add('open');}
function closeDrawer(){document.getElementById('drawerMask').classList.remove('open');document.getElementById('drawer').classList.remove('open');}
</script>
</body>
</html>
@@ -3,7 +3,7 @@
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>健康监测 - 异常报警 | 健康长庆原型</title>
<title>水质监测 - 异常报警 | 健康长庆原型</title>
<style>
*{box-sizing:border-box;margin:0;padding:0;}
body{font-family:-apple-system,BlinkMacSystemFont,'PingFang SC','Microsoft YaHei',sans-serif;background:#F5F7FA;color:#333;min-width:1280px;}
@@ -40,9 +40,34 @@
.sidebar-subgroup.open>.sidebar-subgroup__body{display:block;}
.sidebar-subgroup__body .sidebar-item{padding-left:36px;font-size:12px;}
.main{margin-left:240px;margin-top:56px;padding:24px;min-height:calc(100vh - 56px);}
.page-placeholder{display:flex;flex-direction:column;align-items:center;justify-content:center;height:calc(100vh - 56px - 48px);color:var(--text-placeholder);gap:12px;}
.page-placeholder svg{opacity:.25;}
.page-placeholder p{font-size:var(--font-base);}
.filter-bar{background:#fff;border-radius:var(--radius-md);padding:20px 24px;margin-bottom:16px;box-shadow:var(--shadow-sm);display:flex;align-items:center;gap:16px;flex-wrap:wrap;}
.filter-item{display:flex;align-items:center;gap:8px;}
.filter-item label{font-size:var(--font-sm);color:var(--text-secondary);white-space:nowrap;}
.filter-input{height:36px;border:1px solid var(--border);border-radius:var(--radius-sm);padding:0 12px;font-size:var(--font-sm);color:var(--text-primary);outline:none;background:#fff;min-width:160px;}
.filter-input:focus{border-color:var(--primary);}
.filter-select{height:36px;border:1px solid var(--border);border-radius:var(--radius-sm);padding:0 28px 0 12px;font-size:var(--font-sm);color:var(--text-primary);outline:none;background:#fff url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6'%3E%3Cpath d='M0 0l5 6 5-6z' fill='%23999'/%3E%3C/svg%3E") no-repeat right 10px center;appearance:none;cursor:pointer;min-width:140px;}
.filter-date{height:36px;border:1px solid var(--border);border-radius:var(--radius-sm);padding:0 12px;font-size:var(--font-sm);color:var(--text-primary);outline:none;background:#fff;width:150px;}
.filter-date:focus{border-color:var(--primary);}
.filter-separator{color:var(--text-placeholder);font-size:var(--font-sm);}
.btn{height:36px;padding:0 16px;border-radius:var(--radius-sm);font-size:var(--font-sm);cursor:pointer;border:none;transition:all .2s;display:inline-flex;align-items:center;gap:6px;}
.btn-primary{background:var(--primary);color:#fff;}.btn-primary:hover{background:#40a9ff;}
.btn-default{background:#fff;color:var(--text-primary);border:1px solid var(--border);}.btn-default:hover{color:var(--primary);border-color:var(--primary);}
.action-bar{display:flex;align-items:center;gap:12px;margin-bottom:16px;}
.table-card{background:#fff;border-radius:var(--radius-md);box-shadow:var(--shadow-sm);overflow:hidden;}
.table-card__content{overflow-x:auto;-webkit-overflow-scrolling:touch;}
table{width:100%;border-collapse:collapse;min-width:1100px;}
thead th{background:#FAFAFA;padding:12px 14px;text-align:center;font-size:var(--font-xs);color:var(--text-secondary);font-weight:500;border-bottom:1px solid var(--border);border-right:1px solid var(--border);white-space:nowrap;}
thead th:last-child{border-right:none;}
thead th.th-left{text-align:left;}
tbody td{padding:12px 14px;font-size:var(--font-xs);color:var(--text-primary);border-bottom:1px solid var(--border);text-align:center;white-space:nowrap;}
tbody td.td-left{text-align:left;}
tbody tr:last-child td{border-bottom:none;}
tbody tr:hover{background:#F8FBFF;}
.danger-text{color:var(--danger);font-weight:500;}
.pagination{display:flex;align-items:center;justify-content:flex-end;padding:16px 24px;gap:8px;border-top:1px solid var(--border);}
.pagination span{font-size:var(--font-sm);color:var(--text-secondary);}
.page-btn{width:32px;height:32px;border:1px solid var(--border);border-radius:var(--radius-sm);background:#fff;cursor:pointer;font-size:var(--font-sm);display:inline-flex;align-items:center;justify-content:center;transition:all .2s;}
.page-btn:hover,.page-btn.active{background:var(--primary);color:#fff;border-color:var(--primary);}
</style>
</head>
<body>
@@ -57,10 +82,7 @@
<a href="../exception-dirty.html">异常事件</a>
</nav>
<div class="top-bar__right">
<a class="btn-back" href="../../../index.html">
<svg width="16" height="16" viewBox="0 0 16 16" fill="none"><path d="M10 3L5 8l5 5" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/></svg>
返回首页
</a>
<a class="btn-back" href="../../../index.html"><svg width="16" height="16" viewBox="0 0 16 16" fill="none"><path d="M10 3L5 8l5 5" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/></svg> 返回首页</a>
<div class="avatar"></div>
<span style="color:rgba(255,255,255,0.65);">系统管理员 ▾</span>
</div>
@@ -114,11 +136,110 @@
</div>
</aside>
<main class="main">
<div class="page-placeholder">
<svg width="64" height="64" viewBox="0 0 64 64" fill="none"><rect x="8" y="8" width="48" height="48" rx="8" stroke="#ccc" stroke-width="2"/><path d="M20 32h24M32 20v24" stroke="#ccc" stroke-width="2" stroke-linecap="round"/></svg>
<p>异常报警</p>
<!-- 筛选条件 -->
<div class="filter-bar">
<div class="filter-item"><label>设备名称</label><input class="filter-input" placeholder="请输入设备名称"></div>
<div class="filter-item"><label>设备编号</label><input class="filter-input" placeholder="请输入设备编号"></div>
<div class="filter-item"><label>所属单位</label>
<select class="filter-select"><option value="">全部</option><option>采油一厂</option><option>采油二厂</option><option>采油三厂</option></select>
</div>
<div class="filter-item"><label>监测类型</label>
<select class="filter-select"><option value="">全部</option><option>温度</option><option>电导率</option><option>PH</option><option>盐度</option><option>电阻率</option><option>TDS</option></select>
</div>
<div class="filter-item"><label>日期范围</label><input class="filter-date" type="date" value="2026-05-01"><span class="filter-separator"></span><input class="filter-date" type="date" value="2026-05-15"></div>
<button class="btn btn-primary">查询</button>
<button class="btn btn-default">重置</button>
</div>
<!-- 操作按钮 -->
<div class="action-bar">
<button class="btn btn-default">导出列表数据</button>
<button class="btn btn-default">查看导出任务</button>
</div>
<!-- 数据列表 -->
<div class="table-card">
<div class="table-card__content">
<table>
<thead>
<tr>
<th class="th-left" style="min-width:150px;">设备名称</th>
<th style="min-width:120px;">设备编号</th>
<th style="min-width:90px;">所属单位</th>
<th style="min-width:140px;">设备位置</th>
<th style="min-width:80px;">监测类型</th>
<th style="min-width:80px;">单位</th>
<th style="min-width:70px;">阈值</th>
<th style="min-width:80px;">异常值</th>
<th style="min-width:160px;">报警时间</th>
</tr>
</thead>
<tbody>
<tr>
<td class="td-left">多参数水质分析仪-A01</td>
<td>WQ-2024-001</td>
<td>采油一厂</td>
<td>生活区供水站</td>
<td>电导率</td>
<td>US/cm</td>
<td>1000</td>
<td class="danger-text">1350</td>
<td>2026-05-15 09:30:18</td>
</tr>
<tr>
<td class="td-left">在线PH计-B02</td>
<td>WQ-2024-002</td>
<td>采油一厂</td>
<td>污水处理站出口</td>
<td>PH</td>
<td>-</td>
<td>6.5~8.5</td>
<td class="danger-text">9.2</td>
<td>2026-05-15 09:28:05</td>
</tr>
<tr>
<td class="td-left">电导率监测仪-C01</td>
<td>WQ-2024-003</td>
<td>采油二厂</td>
<td>注水站入口</td>
<td>盐度</td>
<td>mg/L</td>
<td>500</td>
<td class="danger-text">680</td>
<td>2026-05-14 16:12:40</td>
</tr>
<tr>
<td class="td-left">TDS检测仪-D01</td>
<td>WQ-2024-004</td>
<td>采油二厂</td>
<td>生产区储水池</td>
<td>TDS</td>
<td>mg/L</td>
<td>600</td>
<td class="danger-text">840</td>
<td>2026-05-14 11:48:55</td>
</tr>
<tr>
<td class="td-left">多参数水质分析仪-A03</td>
<td>WQ-2024-005</td>
<td>采油三厂</td>
<td>排污口监测点</td>
<td>电阻率</td>
<td>Ω·m</td>
<td>≥500</td>
<td class="danger-text">320</td>
<td>2026-05-13 14:25:33</td>
</tr>
</tbody>
</table>
</div>
<div class="pagination">
<span>共 5 条</span>
<button class="page-btn active">1</button>
</div>
</div>
</main>
<script>function toggleSubgroup(h){h.parentElement.classList.toggle('open');}(function(){var a=document.querySelector('.sidebar-item.active');if(!a)return;var s=a.closest('.sidebar-subgroup');if(s)s.classList.add('open');})();</script>
<script>
function toggleSubgroup(h){h.parentElement.classList.toggle('open');}
(function(){var a=document.querySelector('.sidebar-item.active');if(!a)return;var s=a.closest('.sidebar-subgroup');if(s)s.classList.add('open');})();
</script>
</body>
</html>
</html>
@@ -0,0 +1,194 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>水质监测 - 异常数据详情 | 健康长庆原型</title>
<style>
*{box-sizing:border-box;margin:0;padding:0;}
body{font-family:-apple-system,BlinkMacSystemFont,'PingFang SC','Microsoft YaHei',sans-serif;background:#F5F7FA;color:#333;min-width:1280px;}
:root{
--primary:#1890FF;--primary-light:#E6F7FF;--success:#52C41A;--warning:#FAAD14;--danger:#FF4D4F;
--text-primary:#333;--text-secondary:#666;--text-placeholder:#999;--border:#E8E8E8;--background:#F5F7FA;
--font-xs:11px;--font-sm:13px;--font-base:15px;--font-lg:17px;
--radius-sm:4px;--radius-md:8px;--radius-lg:12px;
--shadow-sm:0 1px 4px rgba(0,0,0,0.08);
}
.top-bar{display:flex;align-items:center;height:56px;background:#001529;padding:0 24px;position:fixed;top:0;left:0;right:0;z-index:100;}
.top-bar__logo{display:flex;align-items:center;gap:8px;color:#fff;font-size:var(--font-lg);font-weight:600;white-space:nowrap;width:240px;flex-shrink:0;}
.top-bar__logo svg{width:28px;height:28px;}
.top-bar__right{display:flex;align-items:center;gap:16px;color:rgba(255,255,255,0.65);font-size:var(--font-sm);}
.btn-back{color:rgba(255,255,255,0.65);cursor:pointer;display:flex;align-items:center;gap:4px;text-decoration:none;}.btn-back:hover{color:#fff;}
.avatar{width:32px;height:32px;border-radius:50%;background:#1890FF;display:flex;align-items:center;justify-content:center;color:#fff;font-size:var(--font-sm);cursor:pointer;}
.top-bar__nav{display:flex;align-items:center;gap:4px;flex:1;}
.top-bar__nav a{color:rgba(255,255,255,0.65);text-decoration:none;padding:6px 16px;border-radius:var(--radius-sm);font-size:var(--font-sm);transition:all .2s;}
.top-bar__nav a:hover{color:#fff;background:rgba(255,255,255,0.08);}
.top-bar__nav a.active{color:#fff;background:var(--primary);}
.sidebar{position:fixed;top:56px;left:0;bottom:0;width:240px;background:#001529;overflow-y:auto;z-index:90;padding-top:8px;}
.sidebar-menu__title{color:rgba(255,255,255,0.35);font-size:var(--font-xs);padding:16px 24px 8px;letter-spacing:.5px;}
.sidebar-item{display:flex;align-items:center;gap:8px;padding:10px 24px;color:rgba(255,255,255,0.65);font-size:var(--font-sm);cursor:pointer;transition:all .15s;text-decoration:none;}
.sidebar-item:hover{color:#fff;background:rgba(255,255,255,0.06);}
.sidebar-item.active{color:#fff;background:var(--primary);}
.sidebar-subgroup__header{display:flex;align-items:center;gap:6px;padding:10px 24px;color:rgba(255,255,255,0.65);font-size:var(--font-sm);cursor:pointer;transition:all .15s;user-select:none;}
.sidebar-subgroup__header:hover{color:rgba(255,255,255,0.85);background:rgba(255,255,255,0.04);}
.sidebar-subgroup__header .arrow{width:10px;height:10px;transition:transform .2s;flex-shrink:0;}
.sidebar-subgroup__header .arrow path{stroke:rgba(255,255,255,0.45);}
.sidebar-subgroup.open>.sidebar-subgroup__header{color:rgba(255,255,255,0.85);}
.sidebar-subgroup.open>.sidebar-subgroup__header .arrow{transform:rotate(90deg);}
.sidebar-subgroup__body{display:none;padding-left:16px;}
.sidebar-subgroup.open>.sidebar-subgroup__body{display:block;}
.sidebar-subgroup__body .sidebar-item{padding-left:36px;font-size:12px;}
.main{margin-left:240px;margin-top:56px;padding:24px;min-height:calc(100vh - 56px);}
.page-header{display:flex;align-items:center;gap:12px;margin-bottom:16px;}
.page-header__back{display:flex;align-items:center;gap:4px;color:var(--text-secondary);font-size:var(--font-sm);cursor:pointer;text-decoration:none;}.page-header__back:hover{color:var(--primary);}
.page-header__title{font-size:var(--font-lg);font-weight:600;color:var(--text-primary);}
.info-card{background:#fff;border-radius:var(--radius-md);padding:20px 24px;margin-bottom:16px;box-shadow:var(--shadow-sm);display:grid;grid-template-columns:repeat(3,1fr);gap:16px 24px;}
.info-card__item{display:flex;align-items:baseline;gap:8px;min-width:0;}
.info-card__label{font-size:var(--font-xs);color:var(--text-placeholder);white-space:nowrap;flex-shrink:0;}
.info-card__value{font-size:var(--font-sm);color:var(--text-primary);font-weight:500;word-break:break-all;}
.filter-bar{background:#fff;border-radius:var(--radius-md);padding:20px 24px;margin-bottom:16px;box-shadow:var(--shadow-sm);display:flex;align-items:center;gap:16px;flex-wrap:wrap;}
.filter-item{display:flex;align-items:center;gap:8px;}
.filter-item label{font-size:var(--font-sm);color:var(--text-secondary);white-space:nowrap;}
.filter-date{height:36px;border:1px solid var(--border);border-radius:var(--radius-sm);padding:0 12px;font-size:var(--font-sm);color:var(--text-primary);outline:none;background:#fff;width:150px;}.filter-date:focus{border-color:var(--primary);}
.filter-select{height:36px;border:1px solid var(--border);border-radius:var(--radius-sm);padding:0 28px 0 12px;font-size:var(--font-sm);color:var(--text-primary);outline:none;background:#fff url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6'%3E%3Cpath d='M0 0l5 6 5-6z' fill='%23999'/%3E%3C/svg%3E") no-repeat right 10px center;appearance:none;cursor:pointer;min-width:140px;}
.filter-separator{color:var(--text-placeholder);font-size:var(--font-sm);}
.btn{height:36px;padding:0 16px;border-radius:var(--radius-sm);font-size:var(--font-sm);cursor:pointer;border:none;transition:all .2s;display:inline-flex;align-items:center;gap:6px;}
.btn-primary{background:var(--primary);color:#fff;}.btn-primary:hover{background:#40a9ff;}
.btn-default{background:#fff;color:var(--text-primary);border:1px solid var(--border);}.btn-default:hover{color:var(--primary);border-color:var(--primary);}
.action-bar{display:flex;align-items:center;gap:12px;margin-bottom:16px;}
.table-card{background:#fff;border-radius:var(--radius-md);box-shadow:var(--shadow-sm);overflow:hidden;}
.table-card__content{overflow-x:auto;-webkit-overflow-scrolling:touch;}
table{width:100%;border-collapse:collapse;min-width:900px;}
thead th{background:#FAFAFA;padding:12px 14px;text-align:center;font-size:var(--font-xs);color:var(--text-secondary);font-weight:500;border-bottom:1px solid var(--border);border-right:1px solid var(--border);white-space:nowrap;}
thead th:last-child{border-right:none;}
tbody td{padding:12px 14px;font-size:var(--font-xs);color:var(--text-primary);border-bottom:1px solid var(--border);text-align:center;white-space:nowrap;}
tbody tr:last-child td{border-bottom:none;}
tbody tr:hover{background:#F8FBFF;}
.danger-text{color:var(--danger);font-weight:500;}
.pagination{display:flex;align-items:center;justify-content:flex-end;padding:16px 24px;gap:8px;border-top:1px solid var(--border);}
.pagination span{font-size:var(--font-sm);color:var(--text-secondary);}
.page-btn{width:32px;height:32px;border:1px solid var(--border);border-radius:var(--radius-sm);background:#fff;cursor:pointer;font-size:var(--font-sm);display:inline-flex;align-items:center;justify-content:center;transition:all .2s;}
.page-btn:hover,.page-btn.active{background:var(--primary);color:#fff;border-color:var(--primary);}
</style>
</head>
<body>
<div class="top-bar">
<div class="top-bar__logo"><svg viewBox="0 0 28 28" fill="none"><rect width="28" height="28" rx="6" fill="#1890FF"/><path d="M7 14h14M14 7v14" stroke="#fff" stroke-width="2.5" stroke-linecap="round"/></svg> 健康监测</div>
<nav class="top-bar__nav">
<a href="../archive-personal.html">档案</a>
<a href="../health-checkup/survey-category.html">健康排查</a>
<a href="../wearable/tool-manage.html">穿戴监测</a>
<a href="../weight/scale-device.html">体重监测</a>
<a href="../environment/indoor-device-list.html" class="active">环境监测</a>
<a href="../exception-dirty.html">异常事件</a>
</nav>
<div class="top-bar__right">
<a class="btn-back" href="../../../index.html"><svg width="16" height="16" viewBox="0 0 16 16" fill="none"><path d="M10 3L5 8l5 5" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/></svg> 返回首页</a>
<div class="avatar"></div>
<span style="color:rgba(255,255,255,0.65);">系统管理员 ▾</span>
</div>
</div>
<aside class="sidebar">
<div class="sidebar-menu__title">环境监测</div>
<div class="sidebar-subgroup">
<div class="sidebar-subgroup__header" onclick="toggleSubgroup(this)"><svg class="arrow" viewBox="0 0 12 12"><path d="M4 2l4 4-4 4" fill="none" stroke-width="1.5" stroke-linecap="round"/></svg> 室内空气</div>
<div class="sidebar-subgroup__body">
<a href="indoor-device-list.html" class="sidebar-item">设备列表</a>
<a href="indoor-device-category.html" class="sidebar-item">设备分类</a>
<a href="indoor-data-monitor.html" class="sidebar-item">数据监测</a>
<a href="indoor-exception-alarm.html" class="sidebar-item">异常报警</a>
<a href="indoor-app-record.html" class="sidebar-item">应用记录</a>
<a href="indoor-history-data.html" class="sidebar-item">历史数据</a>
</div>
</div>
<div class="sidebar-subgroup">
<div class="sidebar-subgroup__header" onclick="toggleSubgroup(this)"><svg class="arrow" viewBox="0 0 12 12"><path d="M4 2l4 4-4 4" fill="none" stroke-width="1.5" stroke-linecap="round"/></svg> 室外空气</div>
<div class="sidebar-subgroup__body">
<a href="outdoor-device-list.html" class="sidebar-item">设备列表</a>
<a href="outdoor-device-category.html" class="sidebar-item">设备分类</a>
<a href="outdoor-data-monitor.html" class="sidebar-item">数据监测</a>
<a href="outdoor-exception-alarm.html" class="sidebar-item">异常报警</a>
<a href="outdoor-app-record.html" class="sidebar-item">应用记录</a>
<a href="outdoor-history-data.html" class="sidebar-item">历史数据</a>
</div>
</div>
<div class="sidebar-subgroup open">
<div class="sidebar-subgroup__header" onclick="toggleSubgroup(this)"><svg class="arrow" viewBox="0 0 12 12"><path d="M4 2l4 4-4 4" fill="none" stroke-width="1.5" stroke-linecap="round"/></svg> 水质监测</div>
<div class="sidebar-subgroup__body">
<a href="water-device-list.html" class="sidebar-item">设备列表</a>
<a href="water-device-category.html" class="sidebar-item">设备分类</a>
<a href="water-data-monitor.html" class="sidebar-item">数据监测</a>
<a href="water-exception-alarm.html" class="sidebar-item">异常报警</a>
<a href="water-app-record.html" class="sidebar-item">应用记录</a>
<a href="water-history-data.html" class="sidebar-item active">历史数据</a>
</div>
</div>
<div class="sidebar-subgroup">
<div class="sidebar-subgroup__header" onclick="toggleSubgroup(this)"><svg class="arrow" viewBox="0 0 12 12"><path d="M4 2l4 4-4 4" fill="none" stroke-width="1.5" stroke-linecap="round"/></svg> 花粉监测</div>
<div class="sidebar-subgroup__body">
<a href="pollen-device-list.html" class="sidebar-item">设备列表</a>
<a href="pollen-device-category.html" class="sidebar-item">设备分类</a>
<a href="pollen-data-monitor.html" class="sidebar-item">数据监测</a>
<a href="pollen-exception-alarm.html" class="sidebar-item">异常报警</a>
<a href="pollen-app-record.html" class="sidebar-item">应用记录</a>
<a href="pollen-history-data.html" class="sidebar-item">历史数据</a>
<a href="pollen-knowledge.html" class="sidebar-item">知识科普</a>
</div>
</div>
</aside>
<main class="main">
<div class="page-header">
<a class="page-header__back" href="water-history-data.html"><svg width="14" height="14" viewBox="0 0 16 16" fill="none"><path d="M10 3L5 8l5 5" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/></svg> 返回</a>
<span class="page-header__title">异常数据详情</span>
</div>
<div class="info-card">
<div class="info-card__item"><span class="info-card__label">设备名称</span><span class="info-card__value">多参数水质分析仪-A01</span></div>
<div class="info-card__item"><span class="info-card__label">设备编码</span><span class="info-card__value">WQ-2024-001</span></div>
<div class="info-card__item"><span class="info-card__label">所属单位</span><span class="info-card__value">采油一厂</span></div>
<div class="info-card__item"><span class="info-card__label">设备位置</span><span class="info-card__value">生活水源取水口</span></div>
<div class="info-card__item"><span class="info-card__label">监测日期</span><span class="info-card__value">2026-03-01 ~ 2026-05-15</span></div>
<div class="info-card__item"><span class="info-card__label">监测时长</span><span class="info-card__value">76 天</span></div>
</div>
<div class="filter-bar">
<div class="filter-item"><label>监测日期</label><input class="filter-date" type="date" value="2026-05-01"><span class="filter-separator"></span><input class="filter-date" type="date" value="2026-05-15"></div>
<div class="filter-item"><label>监测类型</label>
<select class="filter-select"><option value="">全部</option><option>温度</option><option>电导率</option><option>PH</option><option>盐度</option><option>电阻率</option><option>TDS</option></select>
</div>
<button class="btn btn-primary">查询</button>
<button class="btn btn-default">重置</button>
</div>
<div class="action-bar"><button class="btn btn-default">导出列表数据</button></div>
<div class="table-card">
<div class="table-card__content">
<table>
<thead>
<tr>
<th style="min-width:90px;">监测类型</th>
<th style="min-width:90px;">单位</th>
<th style="min-width:80px;">阈值上限</th>
<th style="min-width:80px;">阈值下限</th>
<th style="min-width:80px;">异常值</th>
<th style="min-width:160px;">报警时间</th>
</tr>
</thead>
<tbody>
<tr><td>PH</td><td></td><td>8.5</td><td>6.5</td><td class="danger-text">9.1</td><td>2026-05-15 07:20:33</td></tr>
<tr><td>电导率</td><td>US/cm</td><td>500</td><td></td><td class="danger-text">538</td><td>2026-05-14 14:10:18</td></tr>
<tr><td>TDS</td><td>mg/L</td><td>300</td><td></td><td class="danger-text">325</td><td>2026-05-13 16:45:22</td></tr>
<tr><td>温度</td><td></td><td>30</td><td>4</td><td class="danger-text">31.5</td><td>2026-05-12 13:30:45</td></tr>
<tr><td>盐度</td><td>mg/L</td><td>250</td><td></td><td class="danger-text">278</td><td>2026-05-11 09:15:12</td></tr>
<tr><td>电阻率</td><td>Ω·m</td><td></td><td>1000</td><td class="danger-text">856</td><td>2026-05-10 11:42:56</td></tr>
<tr><td>PH</td><td></td><td>8.5</td><td>6.5</td><td class="danger-text">6.2</td><td>2026-05-09 08:25:40</td></tr>
<tr><td>电导率</td><td>US/cm</td><td>500</td><td></td><td class="danger-text">515</td><td>2026-05-08 17:08:33</td></tr>
</tbody>
</table>
</div>
<div class="pagination"><span>共 8 条</span><button class="page-btn active">1</button></div>
</div>
</main>
<script>
function toggleSubgroup(h){h.parentElement.classList.toggle('open');}
(function(){var a=document.querySelector('.sidebar-item.active');if(!a)return;var s=a.closest('.sidebar-subgroup');if(s)s.classList.add('open');})();
</script>
</body>
</html>
@@ -3,7 +3,7 @@
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>健康监测 - 历史数据 | 健康长庆原型</title>
<title>水质监测 - 历史数据 | 健康长庆原型</title>
<style>
*{box-sizing:border-box;margin:0;padding:0;}
body{font-family:-apple-system,BlinkMacSystemFont,'PingFang SC','Microsoft YaHei',sans-serif;background:#F5F7FA;color:#333;min-width:1280px;}
@@ -18,8 +18,7 @@
.top-bar__logo{display:flex;align-items:center;gap:8px;color:#fff;font-size:var(--font-lg);font-weight:600;white-space:nowrap;width:240px;flex-shrink:0;}
.top-bar__logo svg{width:28px;height:28px;}
.top-bar__right{display:flex;align-items:center;gap:16px;color:rgba(255,255,255,0.65);font-size:var(--font-sm);}
.btn-back{color:rgba(255,255,255,0.65);cursor:pointer;display:flex;align-items:center;gap:4px;text-decoration:none;}
.btn-back:hover{color:#fff;}
.btn-back{color:rgba(255,255,255,0.65);cursor:pointer;display:flex;align-items:center;gap:4px;text-decoration:none;}.btn-back:hover{color:#fff;}
.avatar{width:32px;height:32px;border-radius:50%;background:#1890FF;display:flex;align-items:center;justify-content:center;color:#fff;font-size:var(--font-sm);cursor:pointer;}
.top-bar__nav{display:flex;align-items:center;gap:4px;flex:1;}
.top-bar__nav a{color:rgba(255,255,255,0.65);text-decoration:none;padding:6px 16px;border-radius:var(--radius-sm);font-size:var(--font-sm);transition:all .2s;}
@@ -40,9 +39,30 @@
.sidebar-subgroup.open>.sidebar-subgroup__body{display:block;}
.sidebar-subgroup__body .sidebar-item{padding-left:36px;font-size:12px;}
.main{margin-left:240px;margin-top:56px;padding:24px;min-height:calc(100vh - 56px);}
.page-placeholder{display:flex;flex-direction:column;align-items:center;justify-content:center;height:calc(100vh - 56px - 48px);color:var(--text-placeholder);gap:12px;}
.page-placeholder svg{opacity:.25;}
.page-placeholder p{font-size:var(--font-base);}
.filter-bar{background:#fff;border-radius:var(--radius-md);padding:20px 24px;margin-bottom:16px;box-shadow:var(--shadow-sm);display:flex;align-items:center;gap:16px;flex-wrap:wrap;}
.filter-item{display:flex;align-items:center;gap:8px;}
.filter-item label{font-size:var(--font-sm);color:var(--text-secondary);white-space:nowrap;}
.filter-input{height:36px;border:1px solid var(--border);border-radius:var(--radius-sm);padding:0 12px;font-size:var(--font-sm);color:var(--text-primary);outline:none;background:#fff;min-width:180px;}.filter-input:focus{border-color:var(--primary);}
.filter-select{height:36px;border:1px solid var(--border);border-radius:var(--radius-sm);padding:0 28px 0 12px;font-size:var(--font-sm);color:var(--text-primary);outline:none;background:#fff url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6'%3E%3Cpath d='M0 0l5 6 5-6z' fill='%23999'/%3E%3C/svg%3E") no-repeat right 10px center;appearance:none;cursor:pointer;min-width:140px;}
.btn{height:36px;padding:0 16px;border-radius:var(--radius-sm);font-size:var(--font-sm);cursor:pointer;border:none;transition:all .2s;display:inline-flex;align-items:center;gap:6px;}
.btn-primary{background:var(--primary);color:#fff;}.btn-primary:hover{background:#40a9ff;}
.btn-default{background:#fff;color:var(--text-primary);border:1px solid var(--border);}.btn-default:hover{color:var(--primary);border-color:var(--primary);}
.action-bar{display:flex;align-items:center;gap:12px;margin-bottom:16px;}
.table-card{background:#fff;border-radius:var(--radius-md);box-shadow:var(--shadow-sm);overflow:hidden;}
.table-card__content{overflow-x:auto;-webkit-overflow-scrolling:touch;}
table{width:100%;border-collapse:collapse;min-width:1000px;}
thead th{background:#FAFAFA;padding:12px 14px;text-align:center;font-size:var(--font-xs);color:var(--text-secondary);font-weight:500;border-bottom:1px solid var(--border);border-right:1px solid var(--border);white-space:nowrap;}
thead th:last-child{border-right:none;}
thead th.th-left{text-align:left;}
tbody td{padding:12px 14px;font-size:var(--font-xs);color:var(--text-primary);border-bottom:1px solid var(--border);text-align:center;white-space:nowrap;}
tbody td.td-left{text-align:left;}
tbody tr:last-child td{border-bottom:none;}
tbody tr:hover{background:#F8FBFF;}
.link-btn{color:var(--primary);cursor:pointer;text-decoration:none;font-size:var(--font-xs);}.link-btn:hover{text-decoration:underline;}
.pagination{display:flex;align-items:center;justify-content:flex-end;padding:16px 24px;gap:8px;border-top:1px solid var(--border);}
.pagination span{font-size:var(--font-sm);color:var(--text-secondary);}
.page-btn{width:32px;height:32px;border:1px solid var(--border);border-radius:var(--radius-sm);background:#fff;cursor:pointer;font-size:var(--font-sm);display:inline-flex;align-items:center;justify-content:center;transition:all .2s;}
.page-btn:hover,.page-btn.active{background:var(--primary);color:#fff;border-color:var(--primary);}
</style>
</head>
<body>
@@ -57,10 +77,7 @@
<a href="../exception-dirty.html">异常事件</a>
</nav>
<div class="top-bar__right">
<a class="btn-back" href="../../../index.html">
<svg width="16" height="16" viewBox="0 0 16 16" fill="none"><path d="M10 3L5 8l5 5" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/></svg>
返回首页
</a>
<a class="btn-back" href="../../../index.html"><svg width="16" height="16" viewBox="0 0 16 16" fill="none"><path d="M10 3L5 8l5 5" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/></svg> 返回首页</a>
<div class="avatar"></div>
<span style="color:rgba(255,255,255,0.65);">系统管理员 ▾</span>
</div>
@@ -114,11 +131,91 @@
</div>
</aside>
<main class="main">
<div class="page-placeholder">
<svg width="64" height="64" viewBox="0 0 64 64" fill="none"><rect x="8" y="8" width="48" height="48" rx="8" stroke="#ccc" stroke-width="2"/><path d="M20 32h24M32 20v24" stroke="#ccc" stroke-width="2" stroke-linecap="round"/></svg>
<p>历史数据</p>
<div class="filter-bar">
<div class="filter-item"><label>设备名称</label><input class="filter-input" placeholder="请输入设备名称"></div>
<div class="filter-item"><label>设备编码</label><input class="filter-input" placeholder="请输入设备编码"></div>
<div class="filter-item"><label>所属单位</label>
<select class="filter-select"><option value="">全部</option><option>采油一厂</option><option>采油二厂</option><option>采油三厂</option></select>
</div>
<button class="btn btn-primary">查询</button>
<button class="btn btn-default">重置</button>
</div>
<div class="action-bar"><button class="btn btn-default">导出列表数据</button></div>
<div class="table-card">
<div class="table-card__content">
<table>
<thead>
<tr>
<th class="th-left" style="min-width:150px;">设备名称</th>
<th style="min-width:110px;">设备编码</th>
<th style="min-width:90px;">所属单位</th>
<th style="min-width:130px;">设备位置</th>
<th style="min-width:180px;">监测日期</th>
<th style="min-width:90px;">监测时长(天)</th>
<th style="min-width:80px;">监测数据</th>
<th style="min-width:80px;">异常数据</th>
</tr>
</thead>
<tbody>
<tr>
<td class="td-left">多参数水质分析仪-A01</td>
<td>WQ-2024-001</td>
<td>采油一厂</td>
<td>生活水源取水口</td>
<td>2026-03-01 ~ 2026-05-15</td>
<td>76</td>
<td><a class="link-btn" href="water-history-monitor-detail.html">查看</a></td>
<td><a class="link-btn" href="water-history-alarm-detail.html">查看</a></td>
</tr>
<tr>
<td class="td-left">在线PH计-B02</td>
<td>WQ-2024-002</td>
<td>采油一厂</td>
<td>净水车间出水口</td>
<td>2026-02-20 ~ 2026-05-15</td>
<td>84</td>
<td><a class="link-btn" href="water-history-monitor-detail.html">查看</a></td>
<td><a class="link-btn" href="water-history-alarm-detail.html">查看</a></td>
</tr>
<tr>
<td class="td-left">电导率仪-C03</td>
<td>WQ-2024-003</td>
<td>采油二厂</td>
<td>锅炉房供水管道</td>
<td>2026-04-01 ~ 2026-05-15</td>
<td>45</td>
<td><a class="link-btn" href="water-history-monitor-detail.html">查看</a></td>
<td><a class="link-btn" href="water-history-alarm-detail.html">查看</a></td>
</tr>
<tr>
<td class="td-left">TDS检测仪-D01</td>
<td>WQ-2024-004</td>
<td>采油二厂</td>
<td>食堂直饮水终端</td>
<td>2026-01-10 ~ 2026-05-15</td>
<td>125</td>
<td><a class="link-btn" href="water-history-monitor-detail.html">查看</a></td>
<td><a class="link-btn" href="water-history-alarm-detail.html">查看</a></td>
</tr>
<tr>
<td class="td-left">多参数水质分析仪-A05</td>
<td>WQ-2024-005</td>
<td>采油三厂</td>
<td>污水处理站排放口</td>
<td>2026-03-15 ~ 2026-05-15</td>
<td>61</td>
<td><a class="link-btn" href="water-history-monitor-detail.html">查看</a></td>
<td><a class="link-btn" href="water-history-alarm-detail.html">查看</a></td>
</tr>
</tbody>
</table>
</div>
<div class="pagination"><span>共 5 条</span><button class="page-btn active">1</button></div>
</div>
</main>
<script>function toggleSubgroup(h){h.parentElement.classList.toggle('open');}(function(){var a=document.querySelector('.sidebar-item.active');if(!a)return;var s=a.closest('.sidebar-subgroup');if(s)s.classList.add('open');})();</script>
<script>
function toggleSubgroup(h){h.parentElement.classList.toggle('open');}
(function(){var a=document.querySelector('.sidebar-item.active');if(!a)return;var s=a.closest('.sidebar-subgroup');if(s)s.classList.add('open');})();
</script>
</body>
</html>
</html>
@@ -0,0 +1,203 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>水质监测 - 监测数据详情 | 健康长庆原型</title>
<style>
*{box-sizing:border-box;margin:0;padding:0;}
body{font-family:-apple-system,BlinkMacSystemFont,'PingFang SC','Microsoft YaHei',sans-serif;background:#F5F7FA;color:#333;min-width:1280px;}
:root{
--primary:#1890FF;--primary-light:#E6F7FF;--success:#52C41A;--warning:#FAAD14;--danger:#FF4D4F;
--text-primary:#333;--text-secondary:#666;--text-placeholder:#999;--border:#E8E8E8;--background:#F5F7FA;
--font-xs:11px;--font-sm:13px;--font-base:15px;--font-lg:17px;
--radius-sm:4px;--radius-md:8px;--radius-lg:12px;
--shadow-sm:0 1px 4px rgba(0,0,0,0.08);
}
.top-bar{display:flex;align-items:center;height:56px;background:#001529;padding:0 24px;position:fixed;top:0;left:0;right:0;z-index:100;}
.top-bar__logo{display:flex;align-items:center;gap:8px;color:#fff;font-size:var(--font-lg);font-weight:600;white-space:nowrap;width:240px;flex-shrink:0;}
.top-bar__logo svg{width:28px;height:28px;}
.top-bar__right{display:flex;align-items:center;gap:16px;color:rgba(255,255,255,0.65);font-size:var(--font-sm);}
.btn-back{color:rgba(255,255,255,0.65);cursor:pointer;display:flex;align-items:center;gap:4px;text-decoration:none;}.btn-back:hover{color:#fff;}
.avatar{width:32px;height:32px;border-radius:50%;background:#1890FF;display:flex;align-items:center;justify-content:center;color:#fff;font-size:var(--font-sm);cursor:pointer;}
.top-bar__nav{display:flex;align-items:center;gap:4px;flex:1;}
.top-bar__nav a{color:rgba(255,255,255,0.65);text-decoration:none;padding:6px 16px;border-radius:var(--radius-sm);font-size:var(--font-sm);transition:all .2s;}
.top-bar__nav a:hover{color:#fff;background:rgba(255,255,255,0.08);}
.top-bar__nav a.active{color:#fff;background:var(--primary);}
.sidebar{position:fixed;top:56px;left:0;bottom:0;width:240px;background:#001529;overflow-y:auto;z-index:90;padding-top:8px;}
.sidebar-menu__title{color:rgba(255,255,255,0.35);font-size:var(--font-xs);padding:16px 24px 8px;letter-spacing:.5px;}
.sidebar-item{display:flex;align-items:center;gap:8px;padding:10px 24px;color:rgba(255,255,255,0.65);font-size:var(--font-sm);cursor:pointer;transition:all .15s;text-decoration:none;}
.sidebar-item:hover{color:#fff;background:rgba(255,255,255,0.06);}
.sidebar-item.active{color:#fff;background:var(--primary);}
.sidebar-subgroup__header{display:flex;align-items:center;gap:6px;padding:10px 24px;color:rgba(255,255,255,0.65);font-size:var(--font-sm);cursor:pointer;transition:all .15s;user-select:none;}
.sidebar-subgroup__header:hover{color:rgba(255,255,255,0.85);background:rgba(255,255,255,0.04);}
.sidebar-subgroup__header .arrow{width:10px;height:10px;transition:transform .2s;flex-shrink:0;}
.sidebar-subgroup__header .arrow path{stroke:rgba(255,255,255,0.45);}
.sidebar-subgroup.open>.sidebar-subgroup__header{color:rgba(255,255,255,0.85);}
.sidebar-subgroup.open>.sidebar-subgroup__header .arrow{transform:rotate(90deg);}
.sidebar-subgroup__body{display:none;padding-left:16px;}
.sidebar-subgroup.open>.sidebar-subgroup__body{display:block;}
.sidebar-subgroup__body .sidebar-item{padding-left:36px;font-size:12px;}
.main{margin-left:240px;margin-top:56px;padding:24px;min-height:calc(100vh - 56px);}
.page-header{display:flex;align-items:center;gap:12px;margin-bottom:16px;}
.page-header__back{display:flex;align-items:center;gap:4px;color:var(--text-secondary);font-size:var(--font-sm);cursor:pointer;text-decoration:none;}.page-header__back:hover{color:var(--primary);}
.page-header__title{font-size:var(--font-lg);font-weight:600;color:var(--text-primary);}
.info-card{background:#fff;border-radius:var(--radius-md);padding:20px 24px;margin-bottom:16px;box-shadow:var(--shadow-sm);display:grid;grid-template-columns:repeat(3,1fr);gap:16px 24px;}
.info-card__item{display:flex;align-items:baseline;gap:8px;min-width:0;}
.info-card__label{font-size:var(--font-xs);color:var(--text-placeholder);white-space:nowrap;flex-shrink:0;}
.info-card__value{font-size:var(--font-sm);color:var(--text-primary);font-weight:500;word-break:break-all;}
.filter-bar{background:#fff;border-radius:var(--radius-md);padding:20px 24px;margin-bottom:16px;box-shadow:var(--shadow-sm);display:flex;align-items:center;gap:16px;flex-wrap:wrap;}
.filter-item{display:flex;align-items:center;gap:8px;}
.filter-item label{font-size:var(--font-sm);color:var(--text-secondary);white-space:nowrap;}
.filter-date{height:36px;border:1px solid var(--border);border-radius:var(--radius-sm);padding:0 12px;font-size:var(--font-sm);color:var(--text-primary);outline:none;background:#fff;width:150px;}.filter-date:focus{border-color:var(--primary);}
.filter-separator{color:var(--text-placeholder);font-size:var(--font-sm);}
.btn{height:36px;padding:0 16px;border-radius:var(--radius-sm);font-size:var(--font-sm);cursor:pointer;border:none;transition:all .2s;display:inline-flex;align-items:center;gap:6px;}
.btn-primary{background:var(--primary);color:#fff;}.btn-primary:hover{background:#40a9ff;}
.btn-default{background:#fff;color:var(--text-primary);border:1px solid var(--border);}.btn-default:hover{color:var(--primary);border-color:var(--primary);}
.action-bar{display:flex;align-items:center;gap:12px;margin-bottom:16px;}
.table-card{background:#fff;border-radius:var(--radius-md);box-shadow:var(--shadow-sm);overflow:hidden;}
.table-card__content{overflow-x:auto;-webkit-overflow-scrolling:touch;}
table{width:100%;border-collapse:collapse;min-width:900px;}
thead th{background:#FAFAFA;padding:12px 14px;text-align:center;font-size:var(--font-xs);color:var(--text-secondary);font-weight:500;border-bottom:1px solid var(--border);border-right:1px solid var(--border);white-space:nowrap;}
thead th:last-child{border-right:none;}
tbody td{padding:12px 14px;font-size:var(--font-xs);color:var(--text-primary);border-bottom:1px solid var(--border);text-align:center;white-space:nowrap;}
tbody tr:last-child td{border-bottom:none;}
tbody tr:hover{background:#F8FBFF;}
.pagination{display:flex;align-items:center;justify-content:flex-end;padding:16px 24px;gap:8px;border-top:1px solid var(--border);}
.pagination span{font-size:var(--font-sm);color:var(--text-secondary);}
.page-btn{width:32px;height:32px;border:1px solid var(--border);border-radius:var(--radius-sm);background:#fff;cursor:pointer;font-size:var(--font-sm);display:inline-flex;align-items:center;justify-content:center;transition:all .2s;}
.page-btn:hover,.page-btn.active{background:var(--primary);color:#fff;border-color:var(--primary);}
.wqi-tag{display:inline-block;padding:2px 10px;border-radius:10px;font-size:var(--font-xs);font-weight:500;}
.wqi-tag--pass{background:#F6FFED;color:#52C41A;}
.wqi-tag--fail{background:#FFF1F0;color:#FF4D4F;}
</style>
</head>
<body>
<div class="top-bar">
<div class="top-bar__logo"><svg viewBox="0 0 28 28" fill="none"><rect width="28" height="28" rx="6" fill="#1890FF"/><path d="M7 14h14M14 7v14" stroke="#fff" stroke-width="2.5" stroke-linecap="round"/></svg> 健康监测</div>
<nav class="top-bar__nav">
<a href="../archive-personal.html">档案</a>
<a href="../health-checkup/survey-category.html">健康排查</a>
<a href="../wearable/tool-manage.html">穿戴监测</a>
<a href="../weight/scale-device.html">体重监测</a>
<a href="../environment/indoor-device-list.html" class="active">环境监测</a>
<a href="../exception-dirty.html">异常事件</a>
</nav>
<div class="top-bar__right">
<a class="btn-back" href="../../../index.html"><svg width="16" height="16" viewBox="0 0 16 16" fill="none"><path d="M10 3L5 8l5 5" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/></svg> 返回首页</a>
<div class="avatar"></div>
<span style="color:rgba(255,255,255,0.65);">系统管理员 ▾</span>
</div>
</div>
<aside class="sidebar">
<div class="sidebar-menu__title">环境监测</div>
<div class="sidebar-subgroup">
<div class="sidebar-subgroup__header" onclick="toggleSubgroup(this)"><svg class="arrow" viewBox="0 0 12 12"><path d="M4 2l4 4-4 4" fill="none" stroke-width="1.5" stroke-linecap="round"/></svg> 室内空气</div>
<div class="sidebar-subgroup__body">
<a href="indoor-device-list.html" class="sidebar-item">设备列表</a>
<a href="indoor-device-category.html" class="sidebar-item">设备分类</a>
<a href="indoor-data-monitor.html" class="sidebar-item">数据监测</a>
<a href="indoor-exception-alarm.html" class="sidebar-item">异常报警</a>
<a href="indoor-app-record.html" class="sidebar-item">应用记录</a>
<a href="indoor-history-data.html" class="sidebar-item">历史数据</a>
</div>
</div>
<div class="sidebar-subgroup">
<div class="sidebar-subgroup__header" onclick="toggleSubgroup(this)"><svg class="arrow" viewBox="0 0 12 12"><path d="M4 2l4 4-4 4" fill="none" stroke-width="1.5" stroke-linecap="round"/></svg> 室外空气</div>
<div class="sidebar-subgroup__body">
<a href="outdoor-device-list.html" class="sidebar-item">设备列表</a>
<a href="outdoor-device-category.html" class="sidebar-item">设备分类</a>
<a href="outdoor-data-monitor.html" class="sidebar-item">数据监测</a>
<a href="outdoor-exception-alarm.html" class="sidebar-item">异常报警</a>
<a href="outdoor-app-record.html" class="sidebar-item">应用记录</a>
<a href="outdoor-history-data.html" class="sidebar-item">历史数据</a>
</div>
</div>
<div class="sidebar-subgroup open">
<div class="sidebar-subgroup__header" onclick="toggleSubgroup(this)"><svg class="arrow" viewBox="0 0 12 12"><path d="M4 2l4 4-4 4" fill="none" stroke-width="1.5" stroke-linecap="round"/></svg> 水质监测</div>
<div class="sidebar-subgroup__body">
<a href="water-device-list.html" class="sidebar-item">设备列表</a>
<a href="water-device-category.html" class="sidebar-item">设备分类</a>
<a href="water-data-monitor.html" class="sidebar-item">数据监测</a>
<a href="water-exception-alarm.html" class="sidebar-item">异常报警</a>
<a href="water-app-record.html" class="sidebar-item">应用记录</a>
<a href="water-history-data.html" class="sidebar-item active">历史数据</a>
</div>
</div>
<div class="sidebar-subgroup">
<div class="sidebar-subgroup__header" onclick="toggleSubgroup(this)"><svg class="arrow" viewBox="0 0 12 12"><path d="M4 2l4 4-4 4" fill="none" stroke-width="1.5" stroke-linecap="round"/></svg> 花粉监测</div>
<div class="sidebar-subgroup__body">
<a href="pollen-device-list.html" class="sidebar-item">设备列表</a>
<a href="pollen-device-category.html" class="sidebar-item">设备分类</a>
<a href="pollen-data-monitor.html" class="sidebar-item">数据监测</a>
<a href="pollen-exception-alarm.html" class="sidebar-item">异常报警</a>
<a href="pollen-app-record.html" class="sidebar-item">应用记录</a>
<a href="pollen-history-data.html" class="sidebar-item">历史数据</a>
<a href="pollen-knowledge.html" class="sidebar-item">知识科普</a>
</div>
</div>
</aside>
<main class="main">
<div class="page-header">
<a class="page-header__back" href="water-history-data.html"><svg width="14" height="14" viewBox="0 0 16 16" fill="none"><path d="M10 3L5 8l5 5" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/></svg> 返回</a>
<span class="page-header__title">监测数据详情</span>
</div>
<div class="info-card">
<div class="info-card__item"><span class="info-card__label">设备名称</span><span class="info-card__value">多参数水质分析仪-A01</span></div>
<div class="info-card__item"><span class="info-card__label">设备编码</span><span class="info-card__value">WQ-2024-001</span></div>
<div class="info-card__item"><span class="info-card__label">所属单位</span><span class="info-card__value">采油一厂</span></div>
<div class="info-card__item"><span class="info-card__label">设备位置</span><span class="info-card__value">生活水源取水口</span></div>
<div class="info-card__item"><span class="info-card__label">监测日期</span><span class="info-card__value">2026-03-01 ~ 2026-05-15</span></div>
<div class="info-card__item"><span class="info-card__label">监测时长</span><span class="info-card__value">76 天</span></div>
</div>
<div class="filter-bar">
<div class="filter-item"><label>监测日期</label><input class="filter-date" type="date" value="2026-05-01"><span class="filter-separator"></span><input class="filter-date" type="date" value="2026-05-15"></div>
<button class="btn btn-primary">查询</button>
<button class="btn btn-default">重置</button>
</div>
<div class="action-bar"><button class="btn btn-default">导出列表数据</button></div>
<div class="table-card">
<div class="table-card__content">
<table>
<thead>
<tr>
<th style="min-width:160px;">监测时间</th>
<th style="min-width:90px;">温度(℃)</th>
<th style="min-width:110px;">电导率(US/cm)</th>
<th style="min-width:80px;">PH</th>
<th style="min-width:100px;">盐度(mg/L)</th>
<th style="min-width:100px;">电阻率(Ω·m)</th>
<th style="min-width:100px;">TDS(mg/L)</th>
<th style="min-width:80px;">水质等级</th>
</tr>
</thead>
<tbody>
<tr><td>2026-05-15 08:00:00</td><td>18.5</td><td>325</td><td>7.2</td><td>180</td><td>3080</td><td>162</td><td><span class="wqi-tag wqi-tag--pass">达标</span></td></tr>
<tr><td>2026-05-15 07:00:00</td><td>18.2</td><td>318</td><td>7.1</td><td>176</td><td>3140</td><td>159</td><td><span class="wqi-tag wqi-tag--pass">达标</span></td></tr>
<tr><td>2026-05-15 06:00:00</td><td>17.8</td><td>312</td><td>7.0</td><td>172</td><td>3210</td><td>156</td><td><span class="wqi-tag wqi-tag--pass">达标</span></td></tr>
<tr><td>2026-05-14 23:00:00</td><td>17.2</td><td>305</td><td>7.3</td><td>168</td><td>3280</td><td>152</td><td><span class="wqi-tag wqi-tag--pass">达标</span></td></tr>
<tr><td>2026-05-14 22:00:00</td><td>17.5</td><td>310</td><td>7.2</td><td>170</td><td>3230</td><td>155</td><td><span class="wqi-tag wqi-tag--pass">达标</span></td></tr>
<tr><td>2026-05-14 21:00:00</td><td>18.0</td><td>320</td><td>7.1</td><td>175</td><td>3130</td><td>160</td><td><span class="wqi-tag wqi-tag--pass">达标</span></td></tr>
<tr><td>2026-05-14 20:00:00</td><td>18.8</td><td>332</td><td>7.0</td><td>182</td><td>3010</td><td>166</td><td><span class="wqi-tag wqi-tag--pass">达标</span></td></tr>
<tr><td>2026-05-14 19:00:00</td><td>19.2</td><td>340</td><td>6.9</td><td>188</td><td>2940</td><td>170</td><td><span class="wqi-tag wqi-tag--pass">达标</span></td></tr>
<tr><td>2026-05-14 18:00:00</td><td>19.8</td><td>352</td><td>6.8</td><td>195</td><td>2840</td><td>176</td><td><span class="wqi-tag wqi-tag--fail">未达标</span></td></tr>
<tr><td>2026-05-14 17:00:00</td><td>20.3</td><td>365</td><td>6.7</td><td>202</td><td>2740</td><td>182</td><td><span class="wqi-tag wqi-tag--fail">未达标</span></td></tr>
</tbody>
</table>
</div>
<div class="pagination">
<span>共 240 条</span>
<button class="page-btn active">1</button>
<button class="page-btn">2</button>
<button class="page-btn">3</button>
<span>...</span>
<button class="page-btn">24</button>
</div>
</div>
</main>
<script>
function toggleSubgroup(h){h.parentElement.classList.toggle('open');}
(function(){var a=document.querySelector('.sidebar-item.active');if(!a)return;var s=a.closest('.sidebar-subgroup');if(s)s.classList.add('open');})();
</script>
</body>
</html>
@@ -80,6 +80,30 @@
.scope-panel .filter-row{display:flex;gap:12px;flex-wrap:wrap;align-items:center;}
.date-range{display:flex;align-items:center;gap:8px;}
.date-range input{height:36px;border:1px solid var(--border);border-radius:var(--radius-sm);padding:0 12px;font-size:var(--font-sm);outline:none;width:160px;}
/* 员工选择标签 */
.emp-tag{display:inline-flex;align-items:center;gap:4px;height:28px;padding:0 10px;background:var(--primary-light);color:var(--primary);border-radius:14px;font-size:var(--font-xs);white-space:nowrap;}
.emp-tag__remove{width:16px;height:16px;border:none;background:none;cursor:pointer;color:var(--primary);font-size:14px;line-height:1;padding:0;display:flex;align-items:center;justify-content:center;border-radius:50%;transition:background .15s;}
.emp-tag__remove:hover{background:rgba(24,144,255,0.15);}
/* 员工选择弹窗 */
.picker-modal{width:800px;}
.picker-body{display:flex;gap:0;height:420px;}
.picker-left{flex:1;border-right:1px solid var(--border);display:flex;flex-direction:column;}
.picker-left__filter{display:flex;gap:8px;padding:0 0 12px;flex-wrap:wrap;}
.picker-left__list{flex:1;overflow-y:auto;border:1px solid var(--border);border-radius:var(--radius-sm);}
.picker-emp-item{display:flex;align-items:center;gap:10px;padding:10px 14px;border-bottom:1px solid #f0f0f0;cursor:pointer;transition:background .1s;font-size:var(--font-sm);}
.picker-emp-item:last-child{border-bottom:none;}
.picker-emp-item:hover{background:#F8FBFF;}
.picker-emp-item input[type="checkbox"]{width:16px;height:16px;accent-color:var(--primary);cursor:pointer;}
.picker-emp-item .emp-info{flex:1;display:flex;flex-direction:column;gap:2px;}
.picker-emp-item .emp-name{font-weight:500;color:var(--text-primary);}
.picker-emp-item .emp-meta{font-size:var(--font-xs);color:var(--text-secondary);}
.picker-right{width:240px;display:flex;flex-direction:column;padding-left:16px;}
.picker-right__title{font-size:var(--font-sm);font-weight:500;margin-bottom:8px;color:var(--text-secondary);}
.picker-right__list{flex:1;overflow-y:auto;display:flex;flex-direction:column;gap:6px;}
.picker-right__item{display:flex;align-items:center;justify-content:space-between;padding:6px 10px;background:#FAFAFA;border-radius:var(--radius-sm);font-size:var(--font-sm);}
.picker-right__item .remove-btn{border:none;background:none;color:var(--text-placeholder);cursor:pointer;font-size:16px;line-height:1;}
.picker-right__item .remove-btn:hover{color:var(--danger);}
.picker-right__empty{font-size:var(--font-sm);color:var(--text-placeholder);text-align:center;padding-top:40px;}
</style>
</head>
<body>
@@ -257,23 +281,17 @@
<label><input type="radio" name="scope" value="all" checked onchange="toggleScopePanel(this)"> 全员通知</label>
<label><input type="radio" name="scope" value="specific" onchange="toggleScopePanel(this)"> 指定员工</label>
</div>
<!-- 指定员工选择面板 -->
<!-- 指定员工选择入口 -->
<div class="scope-panel" id="specificPanel" style="display:none;">
<div class="scope-panel .filter-row" style="display:flex;gap:12px;flex-wrap:wrap;align-items:center;margin-bottom:12px;">
<select class="filter-select" style="min-width:150px;">
<option>选择单位</option>
<option>采油一厂</option>
<option>采油二厂</option>
<option>采气一厂</option>
<option>采气二厂</option>
<option>天然气处理厂</option>
</select>
<input class="filter-input" placeholder="姓名/工号搜索" style="min-width:160px;">
<button class="btn btn-default" style="height:36px;">搜索</button>
<div style="display:flex;align-items:center;justify-content:space-between;margin-bottom:10px;">
<span style="font-size:var(--font-sm);color:var(--text-secondary);">已选员工(<span id="selectedCount">0</span>人)</span>
<button class="btn btn-primary" style="height:32px;padding:0 14px;font-size:var(--font-sm);" onclick="openPickerModal()">
<svg width="14" height="14" viewBox="0 0 14 14" fill="none"><path d="M7 2v10M2 7h10" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/></svg>
添加员工
</button>
</div>
<div style="border:1px solid var(--border);border-radius:var(--radius-sm);padding:12px;min-height:80px;background:#FAFAFA;">
<div style="font-size:var(--font-xs);color:var(--text-placeholder);margin-bottom:8px;">已选员工(0人):</div>
<div style="font-size:var(--font-sm);color:var(--text-placeholder);">请搜索并选择通知对象</div>
<div id="selectedTagsArea" style="border:1px solid var(--border);border-radius:var(--radius-sm);padding:12px;min-height:60px;background:#FAFAFA;display:flex;flex-wrap:wrap;gap:8px;align-items:flex-start;cursor:pointer;" onclick="openPickerModal()">
<span id="selectedPlaceholder" style="font-size:var(--font-sm);color:var(--text-placeholder);line-height:28px;">点击此处或上方按钮选择通知对象</span>
</div>
</div>
</div>
@@ -345,6 +363,46 @@
</div>
</div>
<!-- 选择员工弹窗 -->
<div class="modal-mask" id="pickerModal">
<div class="modal picker-modal">
<div class="modal__header">
<h3>选择员工</h3>
<button class="modal__close" onclick="closePickerModal()">×</button>
</div>
<div class="modal__body" style="padding:16px 24px 0;">
<div class="picker-body">
<div class="picker-left" style="padding-right:16px;">
<div class="picker-left__filter">
<select class="filter-select" id="pickerDeptFilter" style="min-width:140px;height:34px;" onchange="filterPickerList()">
<option value="">全部单位</option>
<option>采油一厂</option>
<option>采油二厂</option>
<option>采气一厂</option>
<option>采气二厂</option>
<option>天然气处理厂</option>
</select>
<input class="filter-input" id="pickerSearch" placeholder="姓名/工号搜索" style="min-width:140px;height:34px;" oninput="filterPickerList()">
</div>
<div class="picker-left__list" id="pickerListBody">
<!-- 由脚本渲染 -->
</div>
</div>
<div class="picker-right">
<div class="picker-right__title">已选员工(<span id="pickerSelectedCount">0</span>人)</div>
<div class="picker-right__list" id="pickerSelectedList">
<div class="picker-right__empty" id="pickerSelectedEmpty">暂未选择员工</div>
</div>
</div>
</div>
</div>
<div class="modal__footer">
<button class="btn btn-default" onclick="closePickerModal()">取消</button>
<button class="btn btn-primary" onclick="confirmPicker()">确定</button>
</div>
</div>
</div>
<script>
/* 通知示例数据 */
var NOTIFICATIONS = [
@@ -432,8 +490,135 @@ function openDetailModal(idx){
function toggleScopePanel(el){
document.getElementById('specificPanel').style.display = el.value === 'specific' ? '' : 'none';
}
/* ========== 员工选择弹窗逻辑 ========== */
/* 模拟员工数据 */
var ALL_EMPLOYEES = [
{ id:'e1', name:'张伟', code:'CQ001234', dept:'采油一厂' },
{ id:'e2', name:'李建国', code:'CQ001156', dept:'采油一厂' },
{ id:'e3', name:'陈晓燕', code:'CQ001890', dept:'采油一厂' },
{ id:'e4', name:'王磊', code:'CQ002301', dept:'采气一厂' },
{ id:'e5', name:'赵敏', code:'CQ003012', dept:'天然气处理厂' },
{ id:'e6', name:'刘洋', code:'CQ002890', dept:'采油二厂' },
{ id:'e7', name:'周强', code:'CQ002156', dept:'采气二厂' },
{ id:'e8', name:'孙丽', code:'CQ001567', dept:'采油一厂' },
{ id:'e9', name:'吴刚', code:'CQ003201', dept:'天然气处理厂' },
{ id:'e10', name:'马超', code:'CQ002450', dept:'采气一厂' },
{ id:'e11', name:'杨帆', code:'CQ001789', dept:'采油二厂' },
{ id:'e12', name:'黄涛', code:'CQ002678', dept:'采气二厂' }
];
/* 已确认的选中员工(发送通知弹窗中回显用) */
var confirmedEmployees = [];
/* 弹窗内临时选中(未确认前) */
var tempSelected = [];
/* 打开员工选择弹窗 */
function openPickerModal(){
tempSelected = confirmedEmployees.slice();
renderPickerList();
renderPickerSelected();
document.getElementById('pickerModal').classList.add('show');
}
/* 关闭员工选择弹窗(不保存) */
function closePickerModal(){
document.getElementById('pickerModal').classList.remove('show');
}
/* 确认选择 */
function confirmPicker(){
confirmedEmployees = tempSelected.slice();
renderSelectedTags();
closePickerModal();
}
/* 筛选员工列表 */
function filterPickerList(){
renderPickerList();
}
/* 渲染左侧员工列表 */
function renderPickerList(){
var dept = document.getElementById('pickerDeptFilter').value;
var keyword = document.getElementById('pickerSearch').value.trim().toLowerCase();
var list = ALL_EMPLOYEES.filter(function(emp){
if(dept && emp.dept !== dept) return false;
if(keyword && emp.name.toLowerCase().indexOf(keyword) === -1 && emp.code.toLowerCase().indexOf(keyword) === -1) return false;
return true;
});
var html = '';
list.forEach(function(emp){
var checked = tempSelected.some(function(s){ return s.id === emp.id; });
html += '<label class="picker-emp-item" onclick="event.stopPropagation()">'
+ '<input type="checkbox"' + (checked ? ' checked' : '') + ' onchange="toggleEmployee(\'' + emp.id + '\')">'
+ '<div class="emp-info"><span class="emp-name">' + emp.name + '</span>'
+ '<span class="emp-meta">' + emp.code + ' · ' + emp.dept + '</span></div></label>';
});
if(!list.length) html = '<div style="text-align:center;padding:40px 0;color:var(--text-placeholder);font-size:var(--font-sm);">未找到匹配的员工</div>';
document.getElementById('pickerListBody').innerHTML = html;
}
/* 勾选/取消员工 */
function toggleEmployee(id){
var idx = -1;
tempSelected.forEach(function(s, i){ if(s.id === id) idx = i; });
if(idx > -1){
tempSelected.splice(idx, 1);
} else {
var emp = ALL_EMPLOYEES.filter(function(e){ return e.id === id; })[0];
if(emp) tempSelected.push(emp);
}
renderPickerList();
renderPickerSelected();
}
/* 渲染右侧已选列表 */
function renderPickerSelected(){
var count = tempSelected.length;
document.getElementById('pickerSelectedCount').textContent = count;
if(!count){
document.getElementById('pickerSelectedList').innerHTML = '<div class="picker-right__empty">暂未选择员工</div>';
return;
}
var html = '';
tempSelected.forEach(function(emp){
html += '<div class="picker-right__item"><span>' + emp.name + '' + emp.dept + '</span>'
+ '<button class="remove-btn" onclick="toggleEmployee(\'' + emp.id + '\')" title="移除">×</button></div>';
});
document.getElementById('pickerSelectedList').innerHTML = html;
}
/* 渲染发送通知弹窗中的已选员工标签 */
function renderSelectedTags(){
var area = document.getElementById('selectedTagsArea');
var count = confirmedEmployees.length;
document.getElementById('selectedCount').textContent = count;
if(!count){
area.innerHTML = '<span id="selectedPlaceholder" style="font-size:var(--font-sm);color:var(--text-placeholder);line-height:28px;">点击此处或上方按钮选择通知对象</span>';
return;
}
var html = '';
confirmedEmployees.forEach(function(emp){
html += '<span class="emp-tag">' + emp.name + '' + emp.dept + ''
+ '<button class="emp-tag__remove" onclick="event.stopPropagation();removeConfirmed(\'' + emp.id + '\')" title="移除">×</button></span>';
});
area.innerHTML = html;
}
/* 从已选标签中移除员工 */
function removeConfirmed(id){
confirmedEmployees = confirmedEmployees.filter(function(e){ return e.id !== id; });
renderSelectedTags();
}
document.querySelectorAll('.modal-mask').forEach(function(m){
m.addEventListener('click', function(e){ if(e.target===m) m.classList.remove('show'); });
m.addEventListener('click', function(e){
if(e.target === m){
if(m.id === 'pickerModal') closePickerModal();
else m.classList.remove('show');
}
});
});
</script>
</body>
@@ -42,7 +42,7 @@
.btn-default{background:#fff;color:var(--text-primary);border:1px solid var(--border);}.btn-default:hover{color:var(--primary);border-color:var(--primary);}
.btn-success{background:#fff;color:var(--success);border:1px solid var(--success);}.btn-success:hover{background:#f6ffed;}
.btn-sm{height:28px;padding:0 10px;font-size:var(--font-xs);}
.table-card{background:#fff;border-radius:var(--radius-md);box-shadow:var(--shadow-sm);overflow:hidden;}
.table-card{background:#fff;border-radius:var(--radius-md);box-shadow:var(--shadow-sm);}
.table-card__header{display:flex;align-items:center;justify-content:space-between;padding:16px 24px;border-bottom:1px solid var(--border);}
.table-card__title{font-size:var(--font-base);font-weight:600;}
.table-card__actions{display:flex;gap:8px;align-items:center;}
@@ -103,8 +103,8 @@
.more-wrap{position:relative;display:inline-flex;}
.more-btn{color:var(--primary);cursor:pointer;font-size:var(--font-sm);display:inline-flex;align-items:center;gap:2px;}
.more-btn:hover{color:#40a9ff;}
.more-dropdown{position:absolute;top:100%;right:0;margin-top:4px;background:#fff;border-radius:var(--radius-md);box-shadow:var(--shadow-md);min-width:120px;padding:4px 0;z-index:200;opacity:0;pointer-events:none;transform:translateY(-4px);transition:all .15s;}
.more-dropdown.show{opacity:1;pointer-events:auto;transform:translateY(0);}
.more-dropdown{position:fixed;background:#fff;border-radius:var(--radius-md);box-shadow:var(--shadow-md);min-width:120px;padding:4px 0;z-index:999;opacity:0;pointer-events:none;transition:all .15s;}
.more-dropdown.show{opacity:1;pointer-events:auto;}
.more-dropdown-item{display:flex;align-items:center;gap:8px;padding:8px 16px;font-size:var(--font-sm);color:var(--text-primary);cursor:pointer;white-space:nowrap;transition:background .15s;}
.more-dropdown-item:hover{background:#F5F7FA;}
.more-dropdown-item.danger{color:var(--danger);}
@@ -940,15 +940,26 @@ function doUnbind() {
});
unbindTarget = null;
}
var activeDropdown = null;
function toggleMore(btn) {
var dropdown = btn.nextElementSibling;
var isOpen = dropdown.classList.contains('show');
document.querySelectorAll('.more-dropdown.show').forEach(function(d){ d.classList.remove('show'); });
if (!isOpen) dropdown.classList.add('show');
// 关闭已有的
if (activeDropdown) { document.body.removeChild(activeDropdown); activeDropdown = null; }
var src = btn.nextElementSibling;
var rect = btn.getBoundingClientRect();
// 克隆到 body 层
var clone = src.cloneNode(true);
clone.style.position = 'fixed';
clone.style.top = (rect.bottom + 4) + 'px';
clone.style.left = (rect.right - 120) + 'px';
clone.style.opacity = '1';
clone.style.pointerEvents = 'auto';
clone.classList.add('show');
document.body.appendChild(clone);
activeDropdown = clone;
}
document.addEventListener('click', function(e){
if (!e.target.closest('.more-wrap')) {
document.querySelectorAll('.more-dropdown.show').forEach(function(d){ d.classList.remove('show'); });
if (!e.target.closest('.more-wrap') && !e.target.closest('.more-dropdown')) {
if (activeDropdown) { document.body.removeChild(activeDropdown); activeDropdown = null; }
}
});
document.querySelectorAll('.modal-mask').forEach(function(m){
@@ -963,6 +974,7 @@ function openMonitorSwitch(code) {
msTargetCode = code;
document.getElementById('msDeviceCode').textContent = code;
// 关闭更多下拉
if (activeDropdown) { document.body.removeChild(activeDropdown); activeDropdown = null; }
document.querySelectorAll('.more-dropdown.show').forEach(function(d){ d.classList.remove('show'); });
// 从表格读取当前开关状态
var row = findRowByCode(code);