feat: 四个预警历史页面新增时间筛选功能

- 预警记录标题右侧添加筛选按钮(日历图标)
- 点击弹出底部弹窗,支持年份和月份的级联选择
- 月份支持"全部"选项,可同时筛选多个条件
- 选择后点击"确定"按钮过滤预警记录显示
- 弹窗采用底部滑出动画,确定按钮颜色与各页面主题色一致
- 涉及文件:heart-rate-alerts.html、blood-oxygen-alerts.html、temperature-alerts.html、stress-alerts.html

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
This commit is contained in:
2026-05-07 11:46:23 +08:00
co-authored by Claude Haiku 4.5
parent 852fe14dab
commit 6c9f2cf147
5 changed files with 1175 additions and 11 deletions
@@ -204,6 +204,165 @@ body {
/* 底部安全区 */
.bottom-safe { height: 20px; flex-shrink: 0; }
/* 筛选按钮 */
.filter-btn {
display: flex;
align-items: center;
gap: 4px;
padding: 6px 12px;
border: 1px solid #ddd;
border-radius: 6px;
background: #fff;
font-size: 12px;
color: #666;
cursor: pointer;
transition: all 0.2s;
}
.filter-btn:active {
background: #f5f5f5;
border-color: #bbb;
}
/* 时间筛选弹窗 */
.time-filter-modal {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
display: none;
z-index: 1000;
}
.time-filter-modal.active {
display: flex;
flex-direction: column;
align-items: center;
justify-content: flex-end;
}
.time-filter-overlay {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: rgba(0, 0, 0, 0.4);
}
.time-filter-panel {
position: relative;
width: 100%;
max-width: 390px;
background: #fff;
border-radius: 16px 16px 0 0;
box-shadow: 0 -2px 10px rgba(0, 0, 0, 0.1);
animation: slideUp 0.3s ease-out;
}
@keyframes slideUp {
from {
transform: translateY(100%);
}
to {
transform: translateY(0);
}
}
.time-filter-header {
display: flex;
align-items: center;
justify-content: space-between;
padding: 16px;
border-bottom: 1px solid #f0f0f0;
font-size: 16px;
font-weight: 600;
color: #1a1a1a;
}
.time-filter-close {
width: 28px;
height: 28px;
display: flex;
align-items: center;
justify-content: center;
border: none;
background: none;
font-size: 20px;
color: #999;
cursor: pointer;
}
.time-filter-content {
padding: 16px;
display: flex;
flex-direction: column;
gap: 16px;
}
.filter-section {
display: flex;
flex-direction: column;
gap: 8px;
}
.filter-label {
font-size: 13px;
font-weight: 600;
color: #333;
}
.filter-select {
padding: 10px 12px;
border: 1px solid #ddd;
border-radius: 8px;
font-size: 14px;
color: #333;
background: #fff;
cursor: pointer;
appearance: none;
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8'%3E%3Cpath fill='%23666' d='M1 1l5 5 5-5'/%3E%3C/svg%3E");
background-repeat: no-repeat;
background-position: right 10px center;
padding-right: 32px;
}
.time-filter-footer {
display: flex;
gap: 12px;
padding: 16px;
border-top: 1px solid #f0f0f0;
}
.filter-btn-cancel,
.filter-btn-confirm {
flex: 1;
padding: 12px;
border: none;
border-radius: 8px;
font-size: 14px;
font-weight: 600;
cursor: pointer;
transition: all 0.2s;
}
.filter-btn-cancel {
background: #f5f5f5;
color: #666;
}
.filter-btn-cancel:active {
background: #e8e8e8;
}
.filter-btn-confirm {
background: #52c41a;
color: #fff;
}
.filter-btn-confirm:active {
background: #3a9013;
}
</style>
</head>
<body>
@@ -259,8 +418,8 @@ body {
<path d="M9 13.5a3 3 0 0 0 3 3" stroke="#fff" stroke-width="1.5" stroke-linecap="round" opacity="0.7"/>
</svg>
</div>
<div class="stats-card__recent-label">最近预警时间</div>
<div class="stats-card__recent-time">暂无</div>
<!-- <div class="stats-card__recent-label">最近预警时间</div>-->
<div class="stats-card__unit">无预警,请继续保持</div>
</div>
</div>
@@ -277,8 +436,17 @@ body {
<!-- <div class="empty-state__text">暂无预警记录,请继续保持</div>-->
<!-- </div>-->
<!-- 预警记录列表标题 -->
<div class="section-title">预警记录(共 1 条)</div>
<!-- 预警记录列表标题 + 筛选按钮 -->
<div style="display: flex; align-items: center; justify-content: space-between; padding: 14px 16px 8px;">
<div class="section-title" style="margin: 0; padding: 0;">预警记录(共 1 条)</div>
<button class="filter-btn" onclick="openTimeFilter()">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<rect x="3" y="4" width="18" height="18" rx="2"/>
<path d="M16 2v4M8 2v4M3 10h18"/>
</svg>
筛选
</button>
</div>
<!-- 历史预警记录:2026-03-08 严重 -->
<div class="alert-card">
@@ -324,6 +492,105 @@ body {
<div class="bottom-safe"></div>
</div><!-- /scroll-content -->
<!-- 时间筛选弹窗 -->
<div class="time-filter-modal" id="timeFilterModal">
<div class="time-filter-overlay" onclick="closeTimeFilter()"></div>
<div class="time-filter-panel">
<div class="time-filter-header">
<span>选择时间</span>
<button class="time-filter-close" onclick="closeTimeFilter()"></button>
</div>
<div class="time-filter-content">
<!-- 年份选择 -->
<div class="filter-section">
<label class="filter-label">年份</label>
<select id="yearSelect" class="filter-select" onchange="updateMonths()">
<option value="2026">2026</option>
<option value="2025">2025</option>
<option value="2024">2024</option>
</select>
</div>
<!-- 月份选择 -->
<div class="filter-section">
<label class="filter-label">月份</label>
<select id="monthSelect" class="filter-select">
<option value="">全部</option>
<option value="01">1月</option>
<option value="02">2月</option>
<option value="03">3月</option>
<option value="04">4月</option>
<option value="05">5月</option>
<option value="06">6月</option>
<option value="07">7月</option>
<option value="08">8月</option>
<option value="09">9月</option>
<option value="10">10月</option>
<option value="11">11月</option>
<option value="12">12月</option>
</select>
</div>
</div>
<div class="time-filter-footer">
<button class="filter-btn-cancel" onclick="closeTimeFilter()">取消</button>
<button class="filter-btn-confirm" onclick="applyTimeFilter()">确定</button>
</div>
</div>
</div>
</div><!-- /phone-shell -->
<script>
// 时间筛选功能
function openTimeFilter() {
document.getElementById('timeFilterModal').classList.add('active');
}
function closeTimeFilter() {
document.getElementById('timeFilterModal').classList.remove('active');
}
function updateMonths() {
// 可根据选中年份动态更新月份(当前所有年份月份相同)
}
function applyTimeFilter() {
const year = document.getElementById('yearSelect').value;
const month = document.getElementById('monthSelect').value;
// 获取所有预警记录卡片
const alertCards = document.querySelectorAll('.alert-card');
alertCards.forEach(card => {
const timeText = card.querySelector('.alert-card__time').textContent;
// 格式:2026-03-08 03:22
const [dateStr] = timeText.split(' ');
const [cardYear, cardMonth] = dateStr.split('-');
// 根据筛选条件显示/隐藏
let show = true;
if (year && cardYear !== year) show = false;
if (month && cardMonth !== month) show = false;
card.style.display = show ? 'flex' : 'none';
});
closeTimeFilter();
}
// 点击弹窗外部关闭
document.addEventListener('DOMContentLoaded', function() {
const modal = document.getElementById('timeFilterModal');
if (modal) {
modal.addEventListener('click', function(e) {
if (e.target === modal || e.target.classList.contains('time-filter-overlay')) {
closeTimeFilter();
}
});
}
});
</script>
</body>
</html>
@@ -4,6 +4,23 @@
---
## [2026-05-07] feat: 四个预警历史页面新增时间筛选功能
**涉及文件(4个修改):**
- `heart-rate-alerts.html` — 预警记录标题右侧添加筛选按钮,点击弹出年月级联选择弹窗,支持按年份和月份筛选预警记录
- `blood-oxygen-alerts.html` — 同步添加时间筛选功能
- `temperature-alerts.html` — 同步添加时间筛选功能
- `stress-alerts.html` — 同步添加时间筛选功能
**变更说明:**
- 预警记录标题区域新增"筛选"按钮(日历图标 + 文字),点击后弹出底部弹窗
- 弹窗支持年份选择(2024-2026)和月份选择(1-12月),月份支持"全部"选项
- 选择年月后点击"确定"按钮,预警列表根据选中时间过滤显示
- 点击"取消"或弹窗外部可关闭弹窗
- 弹窗采用底部滑出动画,确定按钮颜色与各页面主题色保持一致
---
## [2026-05-07] refactor: 统一四个预警历史页面布局结构
**涉及文件(4个修改):**
@@ -85,3 +102,83 @@
- 每个指标支持多时间维度数据展示(日/周/月/年)
- 前 4 个指标配备预警历史页面,展示预警统计和详细记录
- 所有页面采用统一的设计规范和交互模式
**涉及文件(4个修改):**
- `blood-oxygen-alerts.html` — 更新 stats-card 结构,添加 stats-card__recent-label 和 stats-card__recent-time,删除 stats-card__sub-label;更新 section-title 文本为"预警记录(共 1 条)"
- `temperature-alerts.html` — 完全重构为标准格式,采用与 heart-rate-alerts.html 相同的 stats-card 和 alert-card 结构,颜色主题使用黄色(#faad14
- `stress-alerts.html` — 已符合标准格式(无需修改)
- `heart-rate-alerts.html` — 参考标准(无需修改)
**变更说明:**
- 四个预警历史页面现采用统一的布局结构:stats-card(左侧统计数据 + 右侧图标和最近预警时间)+ alert-card(左侧等级圆点 + 右侧卡片内容)
- 各页面保持各自的颜色主题:心率红色(#ff7a8a)、血氧绿色(#52c41a)、体温黄色(#faad14)、压力橙色(#fa8c16
- 统一的 CSS 类名和 DOM 结构便于后续维护和扩展
---
## [2026-04-30] refactor: 压缩四个详情页面整体布局高度
**涉及文件(4个修改):**
- `heart-rate.html` — 减少主值字体大小(58px → 48px)、图表高度(258px → 160px)、卡片内边距(18px 12px → 14px 12px
- `temperature.html` — 同步应用布局压缩
- `blood-oxygen.html` — 同步应用布局压缩
- `stress.html` — 同步应用布局压缩
**变更说明:**
- 所有详情页面现可在 844px 手机屏幕内完整显示,无需垂直滚动
- 减少了 150+ 像素的垂直空间占用
---
## [2026-04-30] refactor: 详情页面最高/最低/平均改为一行三列显示
**涉及文件(4个修改):**
- `heart-rate.html` — 将三个指标从垂直堆叠改为水平三列布局,使用 flex: 1 实现等宽分布
- `temperature.html` — 同步应用三列布局
- `blood-oxygen.html` — 同步应用三列布局
- `stress.html` — 同步应用三列布局
**变更说明:**
- 指标卡片从竖向排列改为横向三列,每列包含标签、数值、单位和时间提示
- 使用垂直分隔线(1px 灰色)分隔三列
- 提高了空间利用效率
---
## [2026-04-27] refactor: 血氧和压力详情页现代化设计
**涉及文件(2个修改):**
- `blood-oxygen.html` — 从旧的 hero-card 布局改为现代 top-panel 结构,新增 CSS 变量(--theme: #52c41a)、Tab 导航、图表、时间模式切换
- `stress.html` — 从旧的 hero-card 布局改为现代 top-panel 结构,新增 CSS 变量(--theme: #faad14)、Tab 导航、图表、时间模式切换
**变更说明:**
- 采用与 temperature.html 相同的现代设计风格
- 新增日/周/月/年四种时间维度的数据展示
- 图表使用 SVG 绘制,支持动态数据切换
- 保留各指标的特定说明文案(血氧正常范围、压力等级说明)
---
## [2026-04-21] init: 健康监测模块初始化
**新增文件(10个):**
| 文件 | 说明 |
|------|------|
| `index.html` | 模块首页:四个监测指标入口 |
| `heart-rate.html` | 心率详情:日/周/月/年数据展示 + 预警历史入口 |
| `heart-rate-alerts.html` | 心率预警历史:预警统计 + 预警记录列表 |
| `blood-oxygen.html` | 血氧详情:日/周/月/年数据展示 + 预警历史入口 |
| `blood-oxygen-alerts.html` | 血氧预警历史:预警统计 + 预警记录列表 |
| `temperature.html` | 体温详情:日/周/月/年数据展示 + 预警历史入口 |
| `temperature-alerts.html` | 体温预警历史:预警统计 + 预警记录列表 |
| `stress.html` | 压力详情:日/周/月/年数据展示 + 预警历史入口 |
| `stress-alerts.html` | 压力预警历史:预警统计 + 预警记录列表 |
| `exercise.html` | 运动详情:日/周/月/年数据展示 |
| `sleep.html` | 睡眠详情:日/周/月/年数据展示 |
**变更说明:**
- 健康监测模块包含 6 个主要监测指标(心率、血氧、体温、压力、运动、睡眠)
- 每个指标支持多时间维度数据展示(日/周/月/年)
- 前 4 个指标配备预警历史页面,展示预警统计和详细记录
- 所有页面采用统一的设计规范和交互模式
@@ -203,7 +203,165 @@ body {
/* 底部安全区 */
.bottom-safe { height: 20px; flex-shrink: 0; }
</style>
/* 筛选按钮 */
.filter-btn {
display: flex;
align-items: center;
gap: 4px;
padding: 6px 12px;
border: 1px solid #ddd;
border-radius: 6px;
background: #fff;
font-size: 12px;
color: #666;
cursor: pointer;
transition: all 0.2s;
}
.filter-btn:active {
background: #f5f5f5;
border-color: #bbb;
}
/* 时间筛选弹窗 */
.time-filter-modal {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
display: none;
z-index: 1000;
}
.time-filter-modal.active {
display: flex;
flex-direction: column;
align-items: center;
justify-content: flex-end;
}
.time-filter-overlay {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: rgba(0, 0, 0, 0.4);
}
.time-filter-panel {
position: relative;
width: 100%;
max-width: 390px;
background: #fff;
border-radius: 16px 16px 0 0;
box-shadow: 0 -2px 10px rgba(0, 0, 0, 0.1);
animation: slideUp 0.3s ease-out;
}
@keyframes slideUp {
from {
transform: translateY(100%);
}
to {
transform: translateY(0);
}
}
.time-filter-header {
display: flex;
align-items: center;
justify-content: space-between;
padding: 16px;
border-bottom: 1px solid #f0f0f0;
font-size: 16px;
font-weight: 600;
color: #1a1a1a;
}
.time-filter-close {
width: 28px;
height: 28px;
display: flex;
align-items: center;
justify-content: center;
border: none;
background: none;
font-size: 20px;
color: #999;
cursor: pointer;
}
.time-filter-content {
padding: 16px;
display: flex;
flex-direction: column;
gap: 16px;
}
.filter-section {
display: flex;
flex-direction: column;
gap: 8px;
}
.filter-label {
font-size: 13px;
font-weight: 600;
color: #333;
}
.filter-select {
padding: 10px 12px;
border: 1px solid #ddd;
border-radius: 8px;
font-size: 14px;
color: #333;
background: #fff;
cursor: pointer;
appearance: none;
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8'%3E%3Cpath fill='%23666' d='M1 1l5 5 5-5'/%3E%3C/svg%3E");
background-repeat: no-repeat;
background-position: right 10px center;
padding-right: 32px;
}
.time-filter-footer {
display: flex;
gap: 12px;
padding: 16px;
border-top: 1px solid #f0f0f0;
}
.filter-btn-cancel,
.filter-btn-confirm {
flex: 1;
padding: 12px;
border: none;
border-radius: 8px;
font-size: 14px;
font-weight: 600;
cursor: pointer;
transition: all 0.2s;
}
.filter-btn-cancel {
background: #f5f5f5;
color: #666;
}
.filter-btn-cancel:active {
background: #e8e8e8;
}
.filter-btn-confirm {
background: #ff7a8a;
color: #fff;
}
.filter-btn-confirm:active {
background: #ff5a7a;
}
</head>
<body>
<div class="phone-shell">
@@ -262,8 +420,17 @@ body {
</div>
</div>
<!-- 预警记录列表标题 -->
<div class="section-title">预警记录(共 3 条)</div>
<!-- 预警记录列表标题 + 筛选按钮 -->
<div style="display: flex; align-items: center; justify-content: space-between; padding: 14px 16px 8px;">
<div class="section-title" style="margin: 0; padding: 0;">预警记录(共 3 条)</div>
<button class="filter-btn" onclick="openTimeFilter()">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<rect x="3" y="4" width="18" height="18" rx="2"/>
<path d="M16 2v4M8 2v4M3 10h18"/>
</svg>
筛选
</button>
</div>
<!-- 预警记录 1:严重 - 2026-04-28 -->
<div class="alert-card">
@@ -385,6 +552,105 @@ body {
<div class="bottom-safe"></div>
</div><!-- /scroll-content -->
<!-- 时间筛选弹窗 -->
<div class="time-filter-modal" id="timeFilterModal">
<div class="time-filter-overlay" onclick="closeTimeFilter()"></div>
<div class="time-filter-panel">
<div class="time-filter-header">
<span>选择时间</span>
<button class="time-filter-close" onclick="closeTimeFilter()"></button>
</div>
<div class="time-filter-content">
<!-- 年份选择 -->
<div class="filter-section">
<label class="filter-label">年份</label>
<select id="yearSelect" class="filter-select" onchange="updateMonths()">
<option value="2026">2026</option>
<option value="2025">2025</option>
<option value="2024">2024</option>
</select>
</div>
<!-- 月份选择 -->
<div class="filter-section">
<label class="filter-label">月份</label>
<select id="monthSelect" class="filter-select">
<option value="">全部</option>
<option value="01">1月</option>
<option value="02">2月</option>
<option value="03">3月</option>
<option value="04">4月</option>
<option value="05">5月</option>
<option value="06">6月</option>
<option value="07">7月</option>
<option value="08">8月</option>
<option value="09">9月</option>
<option value="10">10月</option>
<option value="11">11月</option>
<option value="12">12月</option>
</select>
</div>
</div>
<div class="time-filter-footer">
<button class="filter-btn-cancel" onclick="closeTimeFilter()">取消</button>
<button class="filter-btn-confirm" onclick="applyTimeFilter()">确定</button>
</div>
</div>
</div>
</div><!-- /phone-shell -->
<script>
// 时间筛选功能
function openTimeFilter() {
document.getElementById('timeFilterModal').classList.add('active');
}
function closeTimeFilter() {
document.getElementById('timeFilterModal').classList.remove('active');
}
function updateMonths() {
// 可根据选中年份动态更新月份(当前所有年份月份相同)
}
function applyTimeFilter() {
const year = document.getElementById('yearSelect').value;
const month = document.getElementById('monthSelect').value;
// 获取所有预警记录卡片
const alertCards = document.querySelectorAll('.alert-card');
alertCards.forEach(card => {
const timeText = card.querySelector('.alert-card__time').textContent;
// 格式:2026-04-28 16:32
const [dateStr] = timeText.split(' ');
const [cardYear, cardMonth] = dateStr.split('-');
// 根据筛选条件显示/隐藏
let show = true;
if (year && cardYear !== year) show = false;
if (month && cardMonth !== month) show = false;
card.style.display = show ? 'flex' : 'none';
});
closeTimeFilter();
}
// 点击弹窗外部关闭
document.addEventListener('DOMContentLoaded', function() {
const modal = document.getElementById('timeFilterModal');
if (modal) {
modal.addEventListener('click', function(e) {
if (e.target === modal || e.target.classList.contains('time-filter-overlay')) {
closeTimeFilter();
}
});
}
});
</script>
</body>
</html>
+269 -2
View File
@@ -208,6 +208,165 @@ body {
/* 底部安全区 */
.bottom-safe { height: 20px; flex-shrink: 0; }
/* 筛选按钮 */
.filter-btn {
display: flex;
align-items: center;
gap: 4px;
padding: 6px 12px;
border: 1px solid #ddd;
border-radius: 6px;
background: #fff;
font-size: 12px;
color: #666;
cursor: pointer;
transition: all 0.2s;
}
.filter-btn:active {
background: #f5f5f5;
border-color: #bbb;
}
/* 时间筛选弹窗 */
.time-filter-modal {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
display: none;
z-index: 1000;
}
.time-filter-modal.active {
display: flex;
flex-direction: column;
align-items: center;
justify-content: flex-end;
}
.time-filter-overlay {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: rgba(0, 0, 0, 0.4);
}
.time-filter-panel {
position: relative;
width: 100%;
max-width: 390px;
background: #fff;
border-radius: 16px 16px 0 0;
box-shadow: 0 -2px 10px rgba(0, 0, 0, 0.1);
animation: slideUp 0.3s ease-out;
}
@keyframes slideUp {
from {
transform: translateY(100%);
}
to {
transform: translateY(0);
}
}
.time-filter-header {
display: flex;
align-items: center;
justify-content: space-between;
padding: 16px;
border-bottom: 1px solid #f0f0f0;
font-size: 16px;
font-weight: 600;
color: #1a1a1a;
}
.time-filter-close {
width: 28px;
height: 28px;
display: flex;
align-items: center;
justify-content: center;
border: none;
background: none;
font-size: 20px;
color: #999;
cursor: pointer;
}
.time-filter-content {
padding: 16px;
display: flex;
flex-direction: column;
gap: 16px;
}
.filter-section {
display: flex;
flex-direction: column;
gap: 8px;
}
.filter-label {
font-size: 13px;
font-weight: 600;
color: #333;
}
.filter-select {
padding: 10px 12px;
border: 1px solid #ddd;
border-radius: 8px;
font-size: 14px;
color: #333;
background: #fff;
cursor: pointer;
appearance: none;
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8'%3E%3Cpath fill='%23666' d='M1 1l5 5 5-5'/%3E%3C/svg%3E");
background-repeat: no-repeat;
background-position: right 10px center;
padding-right: 32px;
}
.time-filter-footer {
display: flex;
gap: 12px;
padding: 16px;
border-top: 1px solid #f0f0f0;
}
.filter-btn-cancel,
.filter-btn-confirm {
flex: 1;
padding: 12px;
border: none;
border-radius: 8px;
font-size: 14px;
font-weight: 600;
cursor: pointer;
transition: all 0.2s;
}
.filter-btn-cancel {
background: #f5f5f5;
color: #666;
}
.filter-btn-cancel:active {
background: #e8e8e8;
}
.filter-btn-confirm {
background: #fa8c16;
color: #fff;
}
.filter-btn-confirm:active {
background: #d46b08;
}
</style>
</head>
<body>
@@ -270,8 +429,17 @@ body {
</div>
</div>
<!-- 预警记录列表标题 -->
<div class="section-title">预警记录(共 2 条)</div>
<!-- 预警记录列表标题 + 筛选按钮 -->
<div style="display: flex; align-items: center; justify-content: space-between; padding: 14px 16px 8px;">
<div class="section-title" style="margin: 0; padding: 0;">预警记录(共 2 条)</div>
<button class="filter-btn" onclick="openTimeFilter()">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<rect x="3" y="4" width="18" height="18" rx="2"/>
<path d="M16 2v4M8 2v4M3 10h18"/>
</svg>
筛选
</button>
</div>
<!-- 预警记录 1:警告 - 2026-04-30 16:30,压力值 82 -->
<div class="alert-card">
@@ -357,6 +525,105 @@ body {
<div class="bottom-safe"></div>
</div><!-- /scroll-content -->
<!-- 时间筛选弹窗 -->
<div class="time-filter-modal" id="timeFilterModal">
<div class="time-filter-overlay" onclick="closeTimeFilter()"></div>
<div class="time-filter-panel">
<div class="time-filter-header">
<span>选择时间</span>
<button class="time-filter-close" onclick="closeTimeFilter()"></button>
</div>
<div class="time-filter-content">
<!-- 年份选择 -->
<div class="filter-section">
<label class="filter-label">年份</label>
<select id="yearSelect" class="filter-select" onchange="updateMonths()">
<option value="2026">2026</option>
<option value="2025">2025</option>
<option value="2024">2024</option>
</select>
</div>
<!-- 月份选择 -->
<div class="filter-section">
<label class="filter-label">月份</label>
<select id="monthSelect" class="filter-select">
<option value="">全部</option>
<option value="01">1月</option>
<option value="02">2月</option>
<option value="03">3月</option>
<option value="04">4月</option>
<option value="05">5月</option>
<option value="06">6月</option>
<option value="07">7月</option>
<option value="08">8月</option>
<option value="09">9月</option>
<option value="10">10月</option>
<option value="11">11月</option>
<option value="12">12月</option>
</select>
</div>
</div>
<div class="time-filter-footer">
<button class="filter-btn-cancel" onclick="closeTimeFilter()">取消</button>
<button class="filter-btn-confirm" onclick="applyTimeFilter()">确定</button>
</div>
</div>
</div>
</div><!-- /phone-shell -->
<script>
// 时间筛选功能
function openTimeFilter() {
document.getElementById('timeFilterModal').classList.add('active');
}
function closeTimeFilter() {
document.getElementById('timeFilterModal').classList.remove('active');
}
function updateMonths() {
// 可根据选中年份动态更新月份(当前所有年份月份相同)
}
function applyTimeFilter() {
const year = document.getElementById('yearSelect').value;
const month = document.getElementById('monthSelect').value;
// 获取所有预警记录卡片
const alertCards = document.querySelectorAll('.alert-card');
alertCards.forEach(card => {
const timeText = card.querySelector('.alert-card__time').textContent;
// 格式:2026-04-30 16:30
const [dateStr] = timeText.split(' ');
const [cardYear, cardMonth] = dateStr.split('-');
// 根据筛选条件显示/隐藏
let show = true;
if (year && cardYear !== year) show = false;
if (month && cardMonth !== month) show = false;
card.style.display = show ? 'flex' : 'none';
});
closeTimeFilter();
}
// 点击弹窗外部关闭
document.addEventListener('DOMContentLoaded', function() {
const modal = document.getElementById('timeFilterModal');
if (modal) {
modal.addEventListener('click', function(e) {
if (e.target === modal || e.target.classList.contains('time-filter-overlay')) {
closeTimeFilter();
}
});
}
});
</script>
</body>
</html>
@@ -203,6 +203,165 @@ body {
/* 底部安全区 */
.bottom-safe { height: 20px; flex-shrink: 0; }
/* 筛选按钮 */
.filter-btn {
display: flex;
align-items: center;
gap: 4px;
padding: 6px 12px;
border: 1px solid #ddd;
border-radius: 6px;
background: #fff;
font-size: 12px;
color: #666;
cursor: pointer;
transition: all 0.2s;
}
.filter-btn:active {
background: #f5f5f5;
border-color: #bbb;
}
/* 时间筛选弹窗 */
.time-filter-modal {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
display: none;
z-index: 1000;
}
.time-filter-modal.active {
display: flex;
flex-direction: column;
align-items: center;
justify-content: flex-end;
}
.time-filter-overlay {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: rgba(0, 0, 0, 0.4);
}
.time-filter-panel {
position: relative;
width: 100%;
max-width: 390px;
background: #fff;
border-radius: 16px 16px 0 0;
box-shadow: 0 -2px 10px rgba(0, 0, 0, 0.1);
animation: slideUp 0.3s ease-out;
}
@keyframes slideUp {
from {
transform: translateY(100%);
}
to {
transform: translateY(0);
}
}
.time-filter-header {
display: flex;
align-items: center;
justify-content: space-between;
padding: 16px;
border-bottom: 1px solid #f0f0f0;
font-size: 16px;
font-weight: 600;
color: #1a1a1a;
}
.time-filter-close {
width: 28px;
height: 28px;
display: flex;
align-items: center;
justify-content: center;
border: none;
background: none;
font-size: 20px;
color: #999;
cursor: pointer;
}
.time-filter-content {
padding: 16px;
display: flex;
flex-direction: column;
gap: 16px;
}
.filter-section {
display: flex;
flex-direction: column;
gap: 8px;
}
.filter-label {
font-size: 13px;
font-weight: 600;
color: #333;
}
.filter-select {
padding: 10px 12px;
border: 1px solid #ddd;
border-radius: 8px;
font-size: 14px;
color: #333;
background: #fff;
cursor: pointer;
appearance: none;
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8'%3E%3Cpath fill='%23666' d='M1 1l5 5 5-5'/%3E%3C/svg%3E");
background-repeat: no-repeat;
background-position: right 10px center;
padding-right: 32px;
}
.time-filter-footer {
display: flex;
gap: 12px;
padding: 16px;
border-top: 1px solid #f0f0f0;
}
.filter-btn-cancel,
.filter-btn-confirm {
flex: 1;
padding: 12px;
border: none;
border-radius: 8px;
font-size: 14px;
font-weight: 600;
cursor: pointer;
transition: all 0.2s;
}
.filter-btn-cancel {
background: #f5f5f5;
color: #666;
}
.filter-btn-cancel:active {
background: #e8e8e8;
}
.filter-btn-confirm {
background: #faad14;
color: #fff;
}
.filter-btn-confirm:active {
background: #d48806;
}
</style>
</head>
<body>
@@ -262,8 +421,17 @@ body {
</div>
</div>
<!-- 预警记录列表标题 -->
<div class="section-title">预警记录(共 1 条)</div>
<!-- 预警记录列表标题 + 筛选按钮 -->
<div style="display: flex; align-items: center; justify-content: space-between; padding: 14px 16px 8px;">
<div class="section-title" style="margin: 0; padding: 0;">预警记录(共 1 条)</div>
<button class="filter-btn" onclick="openTimeFilter()">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<rect x="3" y="4" width="18" height="18" rx="2"/>
<path d="M16 2v4M8 2v4M3 10h18"/>
</svg>
筛选
</button>
</div>
<!-- 预警记录:警告 - 2026-04-15 -->
<div class="alert-card">
@@ -309,6 +477,105 @@ body {
<div class="bottom-safe"></div>
</div><!-- /scroll-content -->
<!-- 时间筛选弹窗 -->
<div class="time-filter-modal" id="timeFilterModal">
<div class="time-filter-overlay" onclick="closeTimeFilter()"></div>
<div class="time-filter-panel">
<div class="time-filter-header">
<span>选择时间</span>
<button class="time-filter-close" onclick="closeTimeFilter()"></button>
</div>
<div class="time-filter-content">
<!-- 年份选择 -->
<div class="filter-section">
<label class="filter-label">年份</label>
<select id="yearSelect" class="filter-select" onchange="updateMonths()">
<option value="2026">2026</option>
<option value="2025">2025</option>
<option value="2024">2024</option>
</select>
</div>
<!-- 月份选择 -->
<div class="filter-section">
<label class="filter-label">月份</label>
<select id="monthSelect" class="filter-select">
<option value="">全部</option>
<option value="01">1月</option>
<option value="02">2月</option>
<option value="03">3月</option>
<option value="04">4月</option>
<option value="05">5月</option>
<option value="06">6月</option>
<option value="07">7月</option>
<option value="08">8月</option>
<option value="09">9月</option>
<option value="10">10月</option>
<option value="11">11月</option>
<option value="12">12月</option>
</select>
</div>
</div>
<div class="time-filter-footer">
<button class="filter-btn-cancel" onclick="closeTimeFilter()">取消</button>
<button class="filter-btn-confirm" onclick="applyTimeFilter()">确定</button>
</div>
</div>
</div>
</div><!-- /phone-shell -->
<script>
// 时间筛选功能
function openTimeFilter() {
document.getElementById('timeFilterModal').classList.add('active');
}
function closeTimeFilter() {
document.getElementById('timeFilterModal').classList.remove('active');
}
function updateMonths() {
// 可根据选中年份动态更新月份(当前所有年份月份相同)
}
function applyTimeFilter() {
const year = document.getElementById('yearSelect').value;
const month = document.getElementById('monthSelect').value;
// 获取所有预警记录卡片
const alertCards = document.querySelectorAll('.alert-card');
alertCards.forEach(card => {
const timeText = card.querySelector('.alert-card__time').textContent;
// 格式:2026-04-15 13:28
const [dateStr] = timeText.split(' ');
const [cardYear, cardMonth] = dateStr.split('-');
// 根据筛选条件显示/隐藏
let show = true;
if (year && cardYear !== year) show = false;
if (month && cardMonth !== month) show = false;
card.style.display = show ? 'flex' : 'none';
});
closeTimeFilter();
}
// 点击弹窗外部关闭
document.addEventListener('DOMContentLoaded', function() {
const modal = document.getElementById('timeFilterModal');
if (modal) {
modal.addEventListener('click', function(e) {
if (e.target === modal || e.target.classList.contains('time-filter-overlay')) {
closeTimeFilter();
}
});
}
});
</script>
</body>
</html>