fix: 更新健康监测文档和页面,删除活动统计页
|
After Width: | Height: | Size: 38 KiB |
@@ -33,7 +33,7 @@
|
||||
│ ├── 水质监测(达标/未达标 · 6项指标)
|
||||
│ └── 花粉监测(5级评价 · 8种花粉+总数)
|
||||
├── 设备详情(依 Tab 切换指标下拉、阈值线与等级文案)
|
||||
└── 报警数据(依 Tab 切换可选报警类型与阈值范围)
|
||||
└── 报警数据(依 Tab 切换展示不同类型报警,支持按年月筛选)
|
||||
```
|
||||
|
||||
## 页面清单
|
||||
@@ -225,17 +225,17 @@
|
||||
**功能说明:** 穿戴设备监测数据的主页,展示设备连接状态和各项健康指标的最新数据卡片网格。
|
||||
|
||||
**主要UI元素:**
|
||||
- 设备连接状态栏(设备图标、设备名称如"华为 WATCH GT5 Pro"、设备序列号、连接状态)
|
||||
- 设备连接状态栏(手表图标、设备名称如"华为 WATCH GT5 Pro"、设备序列号如"SF55996622586")
|
||||
- 监测卡片网格(2列布局,共9张卡片):
|
||||
- 步数卡片(当前步数、距离换算、同步时间)
|
||||
- 睡眠卡片(睡眠时长、平均睡眠参考、同步时间)
|
||||
- 心率卡片(当前心率、范围值、同步时间)
|
||||
- 体温卡片(当前体温、范围值、同步时间)
|
||||
- 血氧卡片(当前血氧、范围值、同步时间)
|
||||
- 压力卡片(当前压力值、范围值、同步时间)
|
||||
- 血压卡片(收缩压/舒张压、状态标签、同步时间。手表不支持时,隐藏该模块)
|
||||
- 心电图卡片(心率值、分类结果标签、同步时间。手表不支持时,隐藏该模块)
|
||||
- 锻炼卡片(锻炼次数/时长/消耗统计、同步时间)
|
||||
- 步数卡片(当前步数 8,562、距离换算"相当于步行5.2公里"、同步时间)
|
||||
- 睡眠卡片(睡眠时长 7h 32min、平均睡眠参考"平均睡眠8小时57分"、同步时间)
|
||||
- 心率卡片(当前心率 72 bpm、范围值 89~120、同步时间)
|
||||
- 体温卡片(当前体温 36.5℃、范围值 36.2~37.1℃、同步时间)
|
||||
- 血氧卡片(当前血氧 98%、范围值 95~99%、同步时间)
|
||||
- 压力卡片(当前压力值 42、范围值 18~82、同步时间)
|
||||
- 血压卡片(收缩压/舒张压 120/78 mmHg、状态标签"正常"、同步时间)
|
||||
- 心电图卡片(心率 75 次/分钟、分类结果标签"窦性心律"、同步时间)
|
||||
- 锻炼卡片(消耗 680 千卡、锻炼时长 52 分钟、同步时间)
|
||||
|
||||
**交互说明:**
|
||||
- 点击各卡片进入对应详情页面
|
||||
@@ -269,18 +269,17 @@
|
||||
**功能说明:** 展示心率预警记录列表,支持按年份和月份筛选。
|
||||
|
||||
**主要UI元素:**
|
||||
- 预警记录列表标题(含总条数)
|
||||
- 筛选按钮
|
||||
- 预警记录卡片(时间、等级、数值、持续时长、触发原因、右侧阈值范围显示)
|
||||
- 时间筛选弹窗(年份/月份下拉)
|
||||
- 预警记录列表标题(含总条数,如"预警记录(共 3 条)")
|
||||
- 筛选按钮(显示当前筛选年月,如"2026-4")
|
||||
- 预警记录卡片:
|
||||
- 预警时间(如"2026-04-28 16:32")
|
||||
- 预警数值(如"142 bpm")
|
||||
- 时间筛选弹窗(年份/月份下拉选择,取消/确定按钮)
|
||||
|
||||
**业务规则:**
|
||||
- 预警等级:严重(红色)、警告(橙色)
|
||||
- 每条预警卡片右侧显示正常阈值范围参考
|
||||
|
||||
**交互说明:**
|
||||
- 点击筛选按钮打开时间筛选弹窗
|
||||
- 选择年份和月份后点击"确定"应用筛选
|
||||
- 选择年份和月份后点击"确定"应用筛选,卡片列表按所选年月过滤
|
||||
|
||||
---
|
||||
|
||||
@@ -288,7 +287,7 @@
|
||||
|
||||
**血氧详情(wearable/blood-oxygen.html):** 展示血氧监测数据,图表采用柱状图形式,支持日/周/月/年多时间维度查看,底部时间轴滑块可交互选择具体时间点。
|
||||
|
||||
**血氧预警历史(wearable/blood-oxygen-alerts.html):** 页面结构与心率预警历史一致,展示血氧预警记录列表,每条卡片右侧显示正常阈值范围。
|
||||
**血氧预警历史(wearable/blood-oxygen-alerts.html):** 展示血氧预警记录列表,支持按年月筛选。页面结构与心率预警历史一致,区别在于确定按钮为绿色主题。示例数据:1条记录(2026年3月),93%(严重)。
|
||||
|
||||

|
||||

|
||||
@@ -302,13 +301,13 @@
|
||||
|
||||
**血压详情(wearable/blood-pressure.html):** 展示收缩压/舒张压双线图表,统计卡片分别显示收缩压和舒张压的最高/最低值。
|
||||
|
||||
**血压预警历史(wearable/blood-pressure-alerts.html):** 预警记录卡片同时显示收缩压和舒张压数值,右侧显示正常阈值范围。
|
||||
**血压预警历史(wearable/blood-pressure-alerts.html):** 预警记录以"收缩压/舒张压"格式显示(如"158/98 mmHg"),支持按年月筛选。示例数据:4条记录(2026年5月)
|
||||
|
||||
---
|
||||
|
||||
### 14-15. 体温详情与预警历史
|
||||
|
||||
**体温详情(wearable/temperature.html)** 和 **体温预警历史(wearable/temperature-alerts.html)** 的页面结构与心率一致,预警历史页面每条卡片右侧显示正常阈值范围。
|
||||
**体温详情(wearable/temperature.html)** 和 **体温预警历史(wearable/temperature-alerts.html)** 的页面结构与心率一致。
|
||||
|
||||

|
||||

|
||||
@@ -317,7 +316,7 @@
|
||||
|
||||
### 16-17. 压力详情与预警历史
|
||||
|
||||
**压力详情(wearable/stress.html)** 和 **压力预警历史(wearable/stress-alerts.html)** 的页面结构与心率一致,额外显示压力等级评估徽章,预警历史页面每条卡片右侧显示正常阈值范围。
|
||||
**压力详情(wearable/stress.html)** 和 **压力预警历史(wearable/stress-alerts.html)** 的页面结构与心率一致。压力详情额外显示压力等级评估徽章。
|
||||
|
||||

|
||||

|
||||
@@ -452,9 +451,6 @@
|
||||
|
||||
**典型设备:** 空气质量监测站、PM10检测仪、臭氧检测仪、气象参数监测仪、VOC检测仪(共6台示例)
|
||||
|
||||
**等级描述(示例):**
|
||||
- 优:空气质量令人满意,基本无污染
|
||||
- 严重污染:健康人群运动耐受力降低,有明显强烈症状,提前出现某些疾病
|
||||
|
||||
##### 23.1.1 设备底部弹窗
|
||||
|
||||
@@ -609,47 +605,47 @@
|
||||
|
||||

|
||||
|
||||
**功能说明:** 展示环境监测设备的报警记录,支持按日期范围和报警类型筛选。页面根据 URL 参数 `tab` 决定可选报警类型与展示的报警列表。
|
||||
**功能说明:** 展示环境监测设备的报警记录,支持按时间筛选。页面根据 URL 参数 `tab`(outdoor/indoor/water/pollen)决定展示的报警类型与数据列表。
|
||||
|
||||
**通用 UI 元素:**
|
||||
- 筛选区:日期范围(起始/结束日期选择器)、类型下拉、重置按钮、查询按钮
|
||||
- 统计条:报警总条数(红色突出)
|
||||
- 报警卡片列表:左侧红色边条,顶部"{指标} 超标报警" + 时间,中部报警值(红底)→ 阈值范围(灰底),底部设备名称/位置
|
||||
- 筛选按钮(显示当前年月,如"2026-5")
|
||||
- 报警卡片列表:左侧红色边条,顶部"{指标} 超标报警" + 时间,中部"报警值(数值+单位)› 阈值范围(min~max+单位)"
|
||||
- 数据通过 JavaScript 动态渲染
|
||||
|
||||
**通用交互说明:**
|
||||
- 设置日期范围和类型后点击"查询"筛选
|
||||
- 点击"重置"恢复默认日期与类型筛选条件
|
||||
- 点击筛选按钮打开时间筛选弹窗,选择年月后确定
|
||||
- 列表为空时显示"暂无报警数据"占位
|
||||
|
||||
**业务规则:**
|
||||
- 报警值高于阈值上限或低于阈值下限时进入报警列表
|
||||
- 报警卡片同时呈现实际值与允许阈值范围(min~max),便于直观判断超标幅度
|
||||
- 报警卡片同时呈现实际值与允许阈值范围(min~max),直观判断超标幅度
|
||||
|
||||
#### 25.1 室外空气
|
||||
|
||||

|
||||
|
||||
**可选报警类型:** PM2.5、PM10、温度、湿度、风速、太阳辐射、照度
|
||||
**示例数据(8条,2026年5月):** PM2.5(156 μg/m³,阈值 0~75)、PM10(218 μg/m³,阈值 0~150)、风速(13.5 m/s,阈值 0~10)、太阳辐射(1180 W/m²,阈值 0~1000)、温度(42.3℃,阈值 -10~40)、PM2.5(195 μg/m³)、PM10(285 μg/m³)、照度(98500 lm/m²,阈值 0~95000)
|
||||
|
||||
|
||||
#### 25.2 室内空气
|
||||
|
||||

|
||||
|
||||
**可选报警类型:** PM2.5、PM10、CO₂、甲醛、温度、湿度
|
||||
**示例数据(6条,2026年5月):** CO₂(1250 ppm,阈值 400~1000)、甲醛(0.15 mg/m³,阈值 0~0.10)、PM2.5(135 μg/m³,阈值 0~75)、CO₂(980 ppm,敏感场所阈值 400~800)、湿度(85%,阈值 30~80)、甲醛(0.12 mg/m³)
|
||||
|
||||
|
||||
#### 25.3 水质监测
|
||||
|
||||

|
||||
|
||||
**可选报警类型:** PH、电导率、盐度、TDS、电阻率、温度
|
||||
**示例数据(6条,2026年5月):** 电导率(1250 μS/cm,阈值 50~1000)、PH(8.5,阈值 6.5~8.0)、TDS(840 mg/L,阈值 0~500)、盐度(920 mg/L,阈值 0~500)、电导率(1680 μS/cm)、PH(9.2)
|
||||
|
||||
|
||||
#### 25.4 花粉监测
|
||||
|
||||

|
||||
|
||||
**可选报警类型:** 花粉总数
|
||||
**示例数据(3条,2026年5月):** 花粉总数(1098、924、860 粒/千mm²,阈值 0~800)
|
||||
|
||||
> 备注:花粉监测仅对"花粉总数"设置统一报警阈值,各属/科单一指标暂不单独报警。
|
||||
|
||||
|
Before Width: | Height: | Size: 46 KiB After Width: | Height: | Size: 40 KiB |
|
Before Width: | Height: | Size: 59 KiB After Width: | Height: | Size: 52 KiB |
|
Before Width: | Height: | Size: 31 KiB After Width: | Height: | Size: 26 KiB |
|
Before Width: | Height: | Size: 45 KiB After Width: | Height: | Size: 39 KiB |
|
Before Width: | Height: | Size: 59 KiB After Width: | Height: | Size: 52 KiB |
|
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 10 KiB |
|
Before Width: | Height: | Size: 26 KiB After Width: | Height: | Size: 21 KiB |
|
Before Width: | Height: | Size: 22 KiB After Width: | Height: | Size: 16 KiB |
|
Before Width: | Height: | Size: 44 KiB After Width: | Height: | Size: 41 KiB |
|
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 13 KiB |
|
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 10 KiB |
@@ -15,17 +15,159 @@ body { background: #f0f2f5; display: flex; justify-content: center; align-items:
|
||||
.nav-back { width: 28px; height: 28px; display: flex; align-items: center; justify-content: center; cursor: pointer; }
|
||||
.nav-title { flex: 1; text-align: center; font-size: 17px; font-weight: 600; color: #1a1a1a; margin-right: 28px; }
|
||||
|
||||
/* 筛选区 */
|
||||
.filter-bar { background: #fff; padding: 12px 16px; border-bottom: 1px solid #f0f0f0; flex-shrink: 0; display: flex; flex-direction: column; gap: 8px; }
|
||||
.filter-row { display: flex; align-items: center; gap: 8px; }
|
||||
.filter-label { font-size: 12px; color: #999; flex-shrink: 0; }
|
||||
.filter-date-input { height: 32px; border: 1px solid #e8e8e8; border-radius: 8px; padding: 0 8px; font-size: 12px; color: #333; outline: none; background: #fff; flex: 1; min-width: 0; }
|
||||
.filter-date-input:focus { border-color: #1aad8d; }
|
||||
.filter-sep { font-size: 12px; color: #bbb; flex-shrink: 0; }
|
||||
.filter-select { height: 32px; border: 1px solid #e8e8e8; border-radius: 8px; padding: 0 24px 0 10px; font-size: 12px; color: #333; background: #fff url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='8' height='5'%3E%3Cpath d='M0 0l4 5 4-5z' fill='%23999'/%3E%3C/svg%3E") no-repeat right 8px center; appearance: none; outline: none; cursor: pointer; flex: 1; }
|
||||
.filter-btn { height: 32px; padding: 0 16px; border-radius: 8px; border: none; font-size: 12px; font-weight: 600; cursor: pointer; flex-shrink: 0; }
|
||||
.filter-btn--primary { background: #1aad8d; color: #fff; }
|
||||
.filter-btn--reset { background: #f5f5f5; color: #666; }
|
||||
/* 筛选按钮 */
|
||||
.filter-btn {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 4px;
|
||||
padding: 4px 2px;
|
||||
border: none;
|
||||
background: transparent;
|
||||
font-size: 13px;
|
||||
color: #333;
|
||||
font-weight: 600;
|
||||
cursor: pointer;
|
||||
}
|
||||
.filter-btn__arrow {
|
||||
font-size: 9px;
|
||||
color: #999;
|
||||
}
|
||||
|
||||
/* 时间筛选弹窗 */
|
||||
.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;
|
||||
}
|
||||
|
||||
/* 统计条 */
|
||||
.stat-bar { padding: 10px 16px; display: flex; align-items: center; justify-content: space-between; }
|
||||
@@ -70,42 +212,67 @@ body { background: #f0f2f5; display: flex; justify-content: center; align-items:
|
||||
<div class="nav-title">报警数据</div>
|
||||
</div>
|
||||
|
||||
<!-- 筛选区 -->
|
||||
<div class="filter-bar">
|
||||
<div class="filter-row">
|
||||
<span class="filter-label">日期</span>
|
||||
<input class="filter-date-input" type="date" id="dateFrom" value="2026-05-01">
|
||||
<span class="filter-sep">至</span>
|
||||
<input class="filter-date-input" type="date" id="dateTo" value="2026-05-25">
|
||||
</div>
|
||||
<div class="filter-row">
|
||||
<span class="filter-label">类型</span>
|
||||
<select class="filter-select" id="typeFilter">
|
||||
<option value="">全部类型</option>
|
||||
</select>
|
||||
<button class="filter-btn filter-btn--reset" onclick="resetFilter()">重置</button>
|
||||
<button class="filter-btn filter-btn--primary" onclick="applyFilter()">查询</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 统计 -->
|
||||
<!-- 统计与筛选 -->
|
||||
<div class="stat-bar">
|
||||
<span class="stat-bar__count">共 <strong id="totalCount">0</strong> 条报警</span>
|
||||
<button class="filter-btn" id="filterBtn" onclick="openTimeFilter()">
|
||||
<span id="filterLabel">2026-5</span>
|
||||
<span class="filter-btn__arrow">▼</span>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<!-- 列表 -->
|
||||
<div class="list-wrap" id="listWrap"></div>
|
||||
|
||||
<!-- 时间筛选弹窗 -->
|
||||
<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">
|
||||
<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="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>
|
||||
|
||||
<script>
|
||||
// 各 Tab 报警类型选项
|
||||
const TYPE_OPTIONS = {
|
||||
outdoor: ['PM2.5','PM10','温度','湿度','风速','太阳辐射','照度'],
|
||||
indoor: ['PM2.5','PM10','CO₂','甲醛','温度','湿度'],
|
||||
water: ['PH','电导率','盐度','TDS','电阻率','温度'],
|
||||
pollen: ['花粉总数']
|
||||
};
|
||||
|
||||
// 报警数据
|
||||
const ALARM_DATA = {
|
||||
outdoor: [
|
||||
@@ -143,33 +310,34 @@ const ALARM_DATA = {
|
||||
|
||||
const params = new URLSearchParams(location.search);
|
||||
const tab = params.get('tab') || 'outdoor';
|
||||
const devId = params.get('id') || '';
|
||||
|
||||
// 初始化类型下拉
|
||||
const typeOpts = TYPE_OPTIONS[tab] || [];
|
||||
const typeSelect = document.getElementById('typeFilter');
|
||||
typeOpts.forEach(t => {
|
||||
const o = document.createElement('option');
|
||||
o.value = t; o.textContent = t;
|
||||
typeSelect.appendChild(o);
|
||||
});
|
||||
let currentYear = '2026';
|
||||
let currentMonth = '05';
|
||||
|
||||
function applyFilter() {
|
||||
const from = document.getElementById('dateFrom').value;
|
||||
const to = document.getElementById('dateTo').value;
|
||||
const type = typeSelect.value;
|
||||
let list = ALARM_DATA[tab] || [];
|
||||
if (from) list = list.filter(r => r.time.slice(0,10) >= from);
|
||||
if (to) list = list.filter(r => r.time.slice(0,10) <= to);
|
||||
if (type) list = list.filter(r => r.type === type);
|
||||
renderList(list);
|
||||
function openTimeFilter() {
|
||||
document.getElementById('yearSelect').value = currentYear;
|
||||
document.getElementById('monthSelect').value = currentMonth;
|
||||
document.getElementById('timeFilterModal').classList.add('active');
|
||||
}
|
||||
|
||||
function resetFilter() {
|
||||
document.getElementById('dateFrom').value = '2026-05-01';
|
||||
document.getElementById('dateTo').value = '2026-05-25';
|
||||
typeSelect.value = '';
|
||||
applyFilter();
|
||||
function closeTimeFilter() {
|
||||
document.getElementById('timeFilterModal').classList.remove('active');
|
||||
}
|
||||
|
||||
function applyTimeFilter() {
|
||||
currentYear = document.getElementById('yearSelect').value;
|
||||
currentMonth = document.getElementById('monthSelect').value;
|
||||
|
||||
let list = ALARM_DATA[tab] || [];
|
||||
if (currentYear) list = list.filter(r => r.time.slice(0,4) === currentYear);
|
||||
if (currentMonth) list = list.filter(r => r.time.slice(5,7) === currentMonth);
|
||||
renderList(list);
|
||||
updateFilterLabel();
|
||||
closeTimeFilter();
|
||||
}
|
||||
|
||||
function updateFilterLabel() {
|
||||
document.getElementById('filterLabel').textContent = currentYear + '-' + parseInt(currentMonth);
|
||||
}
|
||||
|
||||
function renderList(list) {
|
||||
@@ -202,8 +370,24 @@ function renderList(list) {
|
||||
`).join('');
|
||||
}
|
||||
|
||||
// 初始渲染
|
||||
applyFilter();
|
||||
// 初始渲染:按默认月份筛选
|
||||
let list = ALARM_DATA[tab] || [];
|
||||
if (currentYear) list = list.filter(r => r.time.slice(0,4) === currentYear);
|
||||
if (currentMonth) list = list.filter(r => r.time.slice(5,7) === currentMonth);
|
||||
renderList(list);
|
||||
updateFilterLabel();
|
||||
|
||||
// 点击弹窗外部关闭
|
||||
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>
|
||||
|
||||
|
After Width: | Height: | Size: 113 KiB |
|
After Width: | Height: | Size: 114 KiB |
|
After Width: | Height: | Size: 91 KiB |
|
After Width: | Height: | Size: 115 KiB |
|
After Width: | Height: | Size: 114 KiB |
|
After Width: | Height: | Size: 40 KiB |
|
After Width: | Height: | Size: 73 KiB |
|
After Width: | Height: | Size: 58 KiB |
|
After Width: | Height: | Size: 115 KiB |
|
After Width: | Height: | Size: 49 KiB |
|
After Width: | Height: | Size: 40 KiB |
@@ -205,41 +205,22 @@ body {
|
||||
/* 底部安全区 */
|
||||
.bottom-safe { height: 20px; flex-shrink: 0; }
|
||||
|
||||
/* 右侧阈值范围 */
|
||||
.alert-card__threshold {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: flex-end;
|
||||
gap: 4px;
|
||||
flex-shrink: 0;
|
||||
padding-top: 4px;
|
||||
}
|
||||
.alert-card__threshold-item {
|
||||
font-size: 11px;
|
||||
color: #bbb;
|
||||
}
|
||||
.alert-card__threshold-item span {
|
||||
font-weight: 600;
|
||||
color: #666;
|
||||
}
|
||||
|
||||
/* 筛选按钮 */
|
||||
.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;
|
||||
padding: 4px 2px;
|
||||
border: none;
|
||||
background: transparent;
|
||||
font-size: 13px;
|
||||
color: #333;
|
||||
font-weight: 600;
|
||||
cursor: pointer;
|
||||
transition: all 0.2s;
|
||||
}
|
||||
.filter-btn:active {
|
||||
background: #f5f5f5;
|
||||
border-color: #bbb;
|
||||
.filter-btn__arrow {
|
||||
font-size: 9px;
|
||||
color: #999;
|
||||
}
|
||||
|
||||
/* 时间筛选弹窗 */
|
||||
@@ -422,12 +403,9 @@ body {
|
||||
<!-- 预警记录列表标题 + 筛选按钮 -->
|
||||
<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 class="filter-btn" id="filterBtn" onclick="openTimeFilter()">
|
||||
<span id="filterLabel">2026-3</span>
|
||||
<span class="filter-btn__arrow">▼</span>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
@@ -448,11 +426,6 @@ body {
|
||||
<span class="alert-card__value-unit">%</span>
|
||||
</div>
|
||||
</div>
|
||||
<!-- 右侧阈值范围 -->
|
||||
<div class="alert-card__threshold">
|
||||
<div class="alert-card__threshold-item">上限 <span>100%</span></div>
|
||||
<div class="alert-card__threshold-item">下限 <span>95%</span></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 底部安全区 -->
|
||||
@@ -483,7 +456,6 @@ body {
|
||||
<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>
|
||||
@@ -511,7 +483,12 @@ body {
|
||||
|
||||
<script>
|
||||
// 时间筛选功能
|
||||
let currentYear = '2026';
|
||||
let currentMonth = '03';
|
||||
|
||||
function openTimeFilter() {
|
||||
document.getElementById('yearSelect').value = currentYear;
|
||||
document.getElementById('monthSelect').value = currentMonth;
|
||||
document.getElementById('timeFilterModal').classList.add('active');
|
||||
}
|
||||
|
||||
@@ -524,29 +501,38 @@ function updateMonths() {
|
||||
}
|
||||
|
||||
function applyTimeFilter() {
|
||||
const year = document.getElementById('yearSelect').value;
|
||||
const month = document.getElementById('monthSelect').value;
|
||||
currentYear = document.getElementById('yearSelect').value;
|
||||
currentMonth = document.getElementById('monthSelect').value;
|
||||
|
||||
// 获取所有预警记录卡片
|
||||
const alertCards = document.querySelectorAll('.alert-card');
|
||||
filterCards();
|
||||
updateFilterLabel();
|
||||
closeTimeFilter();
|
||||
}
|
||||
|
||||
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('-');
|
||||
function filterCards() {
|
||||
var alertCards = document.querySelectorAll('.alert-card');
|
||||
alertCards.forEach(function(card) {
|
||||
var timeText = card.querySelector('.alert-card__time').textContent;
|
||||
var dateStr = timeText.split(' ')[0];
|
||||
var parts = dateStr.split('-');
|
||||
var cardYear = parts[0];
|
||||
var cardMonth = parts[1];
|
||||
|
||||
// 根据筛选条件显示/隐藏
|
||||
let show = true;
|
||||
if (year && cardYear !== year) show = false;
|
||||
if (month && cardMonth !== month) show = false;
|
||||
var show = true;
|
||||
if (currentYear && cardYear !== currentYear) show = false;
|
||||
if (currentMonth && cardMonth !== currentMonth) show = false;
|
||||
|
||||
card.style.display = show ? 'flex' : 'none';
|
||||
});
|
||||
|
||||
closeTimeFilter();
|
||||
}
|
||||
|
||||
function updateFilterLabel() {
|
||||
document.getElementById('filterLabel').textContent = currentYear + '-' + parseInt(currentMonth);
|
||||
}
|
||||
|
||||
// 初始默认筛选
|
||||
filterCards();
|
||||
|
||||
// 点击弹窗外部关闭
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
const modal = document.getElementById('timeFilterModal');
|
||||
|
||||
@@ -188,37 +188,158 @@ body {
|
||||
|
||||
.bottom-safe { height: 20px; flex-shrink: 0; }
|
||||
|
||||
/* 右侧阈值范围 */
|
||||
.alert-card__threshold {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: flex-end;
|
||||
gap: 4px;
|
||||
flex-shrink: 0;
|
||||
padding-top: 4px;
|
||||
}
|
||||
.alert-card__threshold-item {
|
||||
font-size: 11px;
|
||||
color: #bbb;
|
||||
}
|
||||
.alert-card__threshold-item span {
|
||||
font-weight: 600;
|
||||
color: #666;
|
||||
}
|
||||
|
||||
.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;
|
||||
padding: 4px 2px;
|
||||
border: none;
|
||||
background: transparent;
|
||||
font-size: 13px;
|
||||
color: #333;
|
||||
font-weight: 600;
|
||||
cursor: pointer;
|
||||
}
|
||||
.filter-btn:active { background: #f5f5f5; border-color: #bbb; }
|
||||
.filter-btn__arrow {
|
||||
font-size: 9px;
|
||||
color: #999;
|
||||
}
|
||||
|
||||
/* 时间筛选弹窗 */
|
||||
.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;
|
||||
}
|
||||
|
||||
</style>
|
||||
</head>
|
||||
@@ -255,12 +376,9 @@ body {
|
||||
|
||||
<div style="display: flex; align-items: center; justify-content: space-between; padding: 14px 16px 8px;">
|
||||
<div class="section-title" style="margin: 0; padding: 0;">预警记录(共 4 条)</div>
|
||||
<button class="filter-btn">
|
||||
<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 class="filter-btn" id="filterBtn" onclick="openTimeFilter()">
|
||||
<span id="filterLabel">2026-5</span>
|
||||
<span class="filter-btn__arrow">▼</span>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
@@ -278,10 +396,6 @@ body {
|
||||
<span class="alert-card__value-unit">mmHg</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="alert-card__threshold">
|
||||
<div class="alert-card__threshold-item">上限 <span>140/90</span></div>
|
||||
<div class="alert-card__threshold-item">下限 <span>90/60</span></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 预警记录 2:警告 -->
|
||||
@@ -298,10 +412,6 @@ body {
|
||||
<span class="alert-card__value-unit">mmHg</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="alert-card__threshold">
|
||||
<div class="alert-card__threshold-item">上限 <span>140/90</span></div>
|
||||
<div class="alert-card__threshold-item">下限 <span>90/60</span></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 预警记录 3:警告 -->
|
||||
@@ -318,10 +428,6 @@ body {
|
||||
<span class="alert-card__value-unit">mmHg</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="alert-card__threshold">
|
||||
<div class="alert-card__threshold-item">上限 <span>140/90</span></div>
|
||||
<div class="alert-card__threshold-item">下限 <span>90/60</span></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 预警记录 4:警告 -->
|
||||
@@ -338,15 +444,117 @@ body {
|
||||
<span class="alert-card__value-unit">mmHg</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="alert-card__threshold">
|
||||
<div class="alert-card__threshold-item">上限 <span>140/90</span></div>
|
||||
<div class="alert-card__threshold-item">下限 <span>90/60</span></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="bottom-safe"></div>
|
||||
</div>
|
||||
|
||||
<!-- 时间筛选弹窗 -->
|
||||
<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">
|
||||
<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="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>
|
||||
|
||||
<script>
|
||||
// 时间筛选功能
|
||||
let currentYear = '2026';
|
||||
let currentMonth = '05';
|
||||
|
||||
function openTimeFilter() {
|
||||
document.getElementById('yearSelect').value = currentYear;
|
||||
document.getElementById('monthSelect').value = currentMonth;
|
||||
document.getElementById('timeFilterModal').classList.add('active');
|
||||
}
|
||||
|
||||
function closeTimeFilter() {
|
||||
document.getElementById('timeFilterModal').classList.remove('active');
|
||||
}
|
||||
|
||||
function applyTimeFilter() {
|
||||
currentYear = document.getElementById('yearSelect').value;
|
||||
currentMonth = document.getElementById('monthSelect').value;
|
||||
|
||||
filterCards();
|
||||
updateFilterLabel();
|
||||
closeTimeFilter();
|
||||
}
|
||||
|
||||
function filterCards() {
|
||||
var alertCards = document.querySelectorAll('.alert-card');
|
||||
alertCards.forEach(function(card) {
|
||||
var timeText = card.querySelector('.alert-card__time').textContent;
|
||||
var dateStr = timeText.split(' ')[0];
|
||||
var parts = dateStr.split('-');
|
||||
var cardYear = parts[0];
|
||||
var cardMonth = parts[1];
|
||||
|
||||
var show = true;
|
||||
if (currentYear && cardYear !== currentYear) show = false;
|
||||
if (currentMonth && cardMonth !== currentMonth) show = false;
|
||||
|
||||
card.style.display = show ? 'flex' : 'none';
|
||||
});
|
||||
}
|
||||
|
||||
function updateFilterLabel() {
|
||||
document.getElementById('filterLabel').textContent = currentYear + '-' + parseInt(currentMonth);
|
||||
}
|
||||
|
||||
// 初始默认筛选
|
||||
filterCards();
|
||||
|
||||
// 点击弹窗外部关闭
|
||||
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>
|
||||
|
||||
@@ -204,41 +204,22 @@ body {
|
||||
/* 底部安全区 */
|
||||
.bottom-safe { height: 20px; flex-shrink: 0; }
|
||||
|
||||
/* 右侧阈值范围 */
|
||||
.alert-card__threshold {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: flex-end;
|
||||
gap: 4px;
|
||||
flex-shrink: 0;
|
||||
padding-top: 4px;
|
||||
}
|
||||
.alert-card__threshold-item {
|
||||
font-size: 11px;
|
||||
color: #bbb;
|
||||
}
|
||||
.alert-card__threshold-item span {
|
||||
font-weight: 600;
|
||||
color: #666;
|
||||
}
|
||||
|
||||
/* 筛选按钮 */
|
||||
.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;
|
||||
padding: 4px 2px;
|
||||
border: none;
|
||||
background: transparent;
|
||||
font-size: 13px;
|
||||
color: #333;
|
||||
font-weight: 600;
|
||||
cursor: pointer;
|
||||
transition: all 0.2s;
|
||||
}
|
||||
.filter-btn:active {
|
||||
background: #f5f5f5;
|
||||
border-color: #bbb;
|
||||
.filter-btn__arrow {
|
||||
font-size: 9px;
|
||||
color: #999;
|
||||
}
|
||||
|
||||
/* 时间筛选弹窗 */
|
||||
@@ -421,12 +402,9 @@ body {
|
||||
<!-- 预警记录列表标题 + 筛选按钮 -->
|
||||
<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 class="filter-btn" id="filterBtn" onclick="openTimeFilter()">
|
||||
<span id="filterLabel">2026-4</span>
|
||||
<span class="filter-btn__arrow">▼</span>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
@@ -447,11 +425,6 @@ body {
|
||||
<span class="alert-card__value-unit">次/分钟</span>
|
||||
</div>
|
||||
</div>
|
||||
<!-- 右侧阈值范围 -->
|
||||
<div class="alert-card__threshold">
|
||||
<div class="alert-card__threshold-item">上限 <span>140 次/分钟</span></div>
|
||||
<div class="alert-card__threshold-item">下限 <span>50 次/分钟</span></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 预警记录 2:警告 - 2026-04-25 -->
|
||||
@@ -471,11 +444,6 @@ body {
|
||||
<span class="alert-card__value-unit">次/分钟</span>
|
||||
</div>
|
||||
</div>
|
||||
<!-- 右侧阈值范围 -->
|
||||
<div class="alert-card__threshold">
|
||||
<div class="alert-card__threshold-item">上限 <span>120 次/分钟</span></div>
|
||||
<div class="alert-card__threshold-item">下限 <span>50 次/分钟</span></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 预警记录 3:警告 - 2026-04-20 -->
|
||||
@@ -495,11 +463,6 @@ body {
|
||||
<span class="alert-card__value-unit">次/分钟</span>
|
||||
</div>
|
||||
</div>
|
||||
<!-- 右侧阈值范围 -->
|
||||
<div class="alert-card__threshold">
|
||||
<div class="alert-card__threshold-item">上限 <span>120 次/分钟</span></div>
|
||||
<div class="alert-card__threshold-item">下限 <span>50 次/分钟</span></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 底部安全区 -->
|
||||
@@ -530,7 +493,6 @@ body {
|
||||
<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>
|
||||
@@ -558,7 +520,12 @@ body {
|
||||
|
||||
<script>
|
||||
// 时间筛选功能
|
||||
let currentYear = '2026';
|
||||
let currentMonth = '04';
|
||||
|
||||
function openTimeFilter() {
|
||||
document.getElementById('yearSelect').value = currentYear;
|
||||
document.getElementById('monthSelect').value = currentMonth;
|
||||
document.getElementById('timeFilterModal').classList.add('active');
|
||||
}
|
||||
|
||||
@@ -571,29 +538,38 @@ function updateMonths() {
|
||||
}
|
||||
|
||||
function applyTimeFilter() {
|
||||
const year = document.getElementById('yearSelect').value;
|
||||
const month = document.getElementById('monthSelect').value;
|
||||
currentYear = document.getElementById('yearSelect').value;
|
||||
currentMonth = document.getElementById('monthSelect').value;
|
||||
|
||||
// 获取所有预警记录卡片
|
||||
const alertCards = document.querySelectorAll('.alert-card');
|
||||
filterCards();
|
||||
updateFilterLabel();
|
||||
closeTimeFilter();
|
||||
}
|
||||
|
||||
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('-');
|
||||
function filterCards() {
|
||||
var alertCards = document.querySelectorAll('.alert-card');
|
||||
alertCards.forEach(function(card) {
|
||||
var timeText = card.querySelector('.alert-card__time').textContent;
|
||||
var dateStr = timeText.split(' ')[0];
|
||||
var parts = dateStr.split('-');
|
||||
var cardYear = parts[0];
|
||||
var cardMonth = parts[1];
|
||||
|
||||
// 根据筛选条件显示/隐藏
|
||||
let show = true;
|
||||
if (year && cardYear !== year) show = false;
|
||||
if (month && cardMonth !== month) show = false;
|
||||
var show = true;
|
||||
if (currentYear && cardYear !== currentYear) show = false;
|
||||
if (currentMonth && cardMonth !== currentMonth) show = false;
|
||||
|
||||
card.style.display = show ? 'flex' : 'none';
|
||||
});
|
||||
|
||||
closeTimeFilter();
|
||||
}
|
||||
|
||||
function updateFilterLabel() {
|
||||
document.getElementById('filterLabel').textContent = currentYear + '-' + parseInt(currentMonth);
|
||||
}
|
||||
|
||||
// 初始默认筛选
|
||||
filterCards();
|
||||
|
||||
// 点击弹窗外部关闭
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
const modal = document.getElementById('timeFilterModal');
|
||||
|
||||
@@ -95,7 +95,7 @@ body { background: #f0f2f5; display: flex; justify-content: center; align-items:
|
||||
<div class="device-icon">⌚</div>
|
||||
<div class="device-info">
|
||||
<div class="device-name">华为 WATCH GT5 Pro</div>
|
||||
<div class="device-meta">SF55996622586 · 已连接</div>
|
||||
<div class="device-meta">SF55996622586</div>
|
||||
</div>
|
||||
<!-- <div class="device-battery">-->
|
||||
<!-- <div class="battery-icon"><div class="battery-fill" style="width:72%"></div></div>-->
|
||||
|
||||
@@ -209,41 +209,22 @@ body {
|
||||
/* 底部安全区 */
|
||||
.bottom-safe { height: 20px; flex-shrink: 0; }
|
||||
|
||||
/* 右侧阈值范围 */
|
||||
.alert-card__threshold {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: flex-end;
|
||||
gap: 4px;
|
||||
flex-shrink: 0;
|
||||
padding-top: 4px;
|
||||
}
|
||||
.alert-card__threshold-item {
|
||||
font-size: 11px;
|
||||
color: #bbb;
|
||||
}
|
||||
.alert-card__threshold-item span {
|
||||
font-weight: 600;
|
||||
color: #666;
|
||||
}
|
||||
|
||||
/* 筛选按钮 */
|
||||
.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;
|
||||
padding: 4px 2px;
|
||||
border: none;
|
||||
background: transparent;
|
||||
font-size: 13px;
|
||||
color: #333;
|
||||
font-weight: 600;
|
||||
cursor: pointer;
|
||||
transition: all 0.2s;
|
||||
}
|
||||
.filter-btn:active {
|
||||
background: #f5f5f5;
|
||||
border-color: #bbb;
|
||||
.filter-btn__arrow {
|
||||
font-size: 9px;
|
||||
color: #999;
|
||||
}
|
||||
|
||||
/* 时间筛选弹窗 */
|
||||
@@ -426,12 +407,9 @@ body {
|
||||
<!-- 预警记录列表标题 + 筛选按钮 -->
|
||||
<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 class="filter-btn" id="filterBtn" onclick="openTimeFilter()">
|
||||
<span id="filterLabel">2026-4</span>
|
||||
<span class="filter-btn__arrow">▼</span>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
@@ -452,11 +430,6 @@ body {
|
||||
<span class="alert-card__value-unit">压力值</span>
|
||||
</div>
|
||||
</div>
|
||||
<!-- 右侧阈值范围 -->
|
||||
<div class="alert-card__threshold">
|
||||
<div class="alert-card__threshold-item">上限 <span>80</span></div>
|
||||
<div class="alert-card__threshold-item">下限 <span>0</span></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 预警记录 2:严重 - 2026-04-22 15:10,压力值 88 -->
|
||||
@@ -476,11 +449,6 @@ body {
|
||||
<span class="alert-card__value-unit">压力值</span>
|
||||
</div>
|
||||
</div>
|
||||
<!-- 右侧阈值范围 -->
|
||||
<div class="alert-card__threshold">
|
||||
<div class="alert-card__threshold-item">上限 <span>85</span></div>
|
||||
<div class="alert-card__threshold-item">下限 <span>0</span></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 底部安全区 -->
|
||||
@@ -511,7 +479,6 @@ body {
|
||||
<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>
|
||||
@@ -539,7 +506,12 @@ body {
|
||||
|
||||
<script>
|
||||
// 时间筛选功能
|
||||
let currentYear = '2026';
|
||||
let currentMonth = '04';
|
||||
|
||||
function openTimeFilter() {
|
||||
document.getElementById('yearSelect').value = currentYear;
|
||||
document.getElementById('monthSelect').value = currentMonth;
|
||||
document.getElementById('timeFilterModal').classList.add('active');
|
||||
}
|
||||
|
||||
@@ -552,29 +524,38 @@ function updateMonths() {
|
||||
}
|
||||
|
||||
function applyTimeFilter() {
|
||||
const year = document.getElementById('yearSelect').value;
|
||||
const month = document.getElementById('monthSelect').value;
|
||||
currentYear = document.getElementById('yearSelect').value;
|
||||
currentMonth = document.getElementById('monthSelect').value;
|
||||
|
||||
// 获取所有预警记录卡片
|
||||
const alertCards = document.querySelectorAll('.alert-card');
|
||||
filterCards();
|
||||
updateFilterLabel();
|
||||
closeTimeFilter();
|
||||
}
|
||||
|
||||
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('-');
|
||||
function filterCards() {
|
||||
var alertCards = document.querySelectorAll('.alert-card');
|
||||
alertCards.forEach(function(card) {
|
||||
var timeText = card.querySelector('.alert-card__time').textContent;
|
||||
var dateStr = timeText.split(' ')[0];
|
||||
var parts = dateStr.split('-');
|
||||
var cardYear = parts[0];
|
||||
var cardMonth = parts[1];
|
||||
|
||||
// 根据筛选条件显示/隐藏
|
||||
let show = true;
|
||||
if (year && cardYear !== year) show = false;
|
||||
if (month && cardMonth !== month) show = false;
|
||||
var show = true;
|
||||
if (currentYear && cardYear !== currentYear) show = false;
|
||||
if (currentMonth && cardMonth !== currentMonth) show = false;
|
||||
|
||||
card.style.display = show ? 'flex' : 'none';
|
||||
});
|
||||
|
||||
closeTimeFilter();
|
||||
}
|
||||
|
||||
function updateFilterLabel() {
|
||||
document.getElementById('filterLabel').textContent = currentYear + '-' + parseInt(currentMonth);
|
||||
}
|
||||
|
||||
// 初始默认筛选
|
||||
filterCards();
|
||||
|
||||
// 点击弹窗外部关闭
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
const modal = document.getElementById('timeFilterModal');
|
||||
|
||||
@@ -204,41 +204,22 @@ body {
|
||||
/* 底部安全区 */
|
||||
.bottom-safe { height: 20px; flex-shrink: 0; }
|
||||
|
||||
/* 右侧阈值范围 */
|
||||
.alert-card__threshold {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: flex-end;
|
||||
gap: 4px;
|
||||
flex-shrink: 0;
|
||||
padding-top: 4px;
|
||||
}
|
||||
.alert-card__threshold-item {
|
||||
font-size: 11px;
|
||||
color: #bbb;
|
||||
}
|
||||
.alert-card__threshold-item span {
|
||||
font-weight: 600;
|
||||
color: #666;
|
||||
}
|
||||
|
||||
/* 筛选按钮 */
|
||||
.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;
|
||||
padding: 4px 2px;
|
||||
border: none;
|
||||
background: transparent;
|
||||
font-size: 13px;
|
||||
color: #333;
|
||||
font-weight: 600;
|
||||
cursor: pointer;
|
||||
transition: all 0.2s;
|
||||
}
|
||||
.filter-btn:active {
|
||||
background: #f5f5f5;
|
||||
border-color: #bbb;
|
||||
.filter-btn__arrow {
|
||||
font-size: 9px;
|
||||
color: #999;
|
||||
}
|
||||
|
||||
/* 时间筛选弹窗 */
|
||||
@@ -421,12 +402,9 @@ body {
|
||||
<!-- 预警记录列表标题 + 筛选按钮 -->
|
||||
<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 class="filter-btn" id="filterBtn" onclick="openTimeFilter()">
|
||||
<span id="filterLabel">2026-4</span>
|
||||
<span class="filter-btn__arrow">▼</span>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
@@ -447,11 +425,6 @@ body {
|
||||
<span class="alert-card__value-unit">°C</span>
|
||||
</div>
|
||||
</div>
|
||||
<!-- 右侧阈值范围 -->
|
||||
<div class="alert-card__threshold">
|
||||
<div class="alert-card__threshold-item">上限 <span>37.3°C</span></div>
|
||||
<div class="alert-card__threshold-item">下限 <span>35.0°C</span></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 底部安全区 -->
|
||||
@@ -482,7 +455,6 @@ body {
|
||||
<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>
|
||||
@@ -510,7 +482,12 @@ body {
|
||||
|
||||
<script>
|
||||
// 时间筛选功能
|
||||
let currentYear = '2026';
|
||||
let currentMonth = '04';
|
||||
|
||||
function openTimeFilter() {
|
||||
document.getElementById('yearSelect').value = currentYear;
|
||||
document.getElementById('monthSelect').value = currentMonth;
|
||||
document.getElementById('timeFilterModal').classList.add('active');
|
||||
}
|
||||
|
||||
@@ -523,29 +500,38 @@ function updateMonths() {
|
||||
}
|
||||
|
||||
function applyTimeFilter() {
|
||||
const year = document.getElementById('yearSelect').value;
|
||||
const month = document.getElementById('monthSelect').value;
|
||||
currentYear = document.getElementById('yearSelect').value;
|
||||
currentMonth = document.getElementById('monthSelect').value;
|
||||
|
||||
// 获取所有预警记录卡片
|
||||
const alertCards = document.querySelectorAll('.alert-card');
|
||||
filterCards();
|
||||
updateFilterLabel();
|
||||
closeTimeFilter();
|
||||
}
|
||||
|
||||
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('-');
|
||||
function filterCards() {
|
||||
var alertCards = document.querySelectorAll('.alert-card');
|
||||
alertCards.forEach(function(card) {
|
||||
var timeText = card.querySelector('.alert-card__time').textContent;
|
||||
var dateStr = timeText.split(' ')[0];
|
||||
var parts = dateStr.split('-');
|
||||
var cardYear = parts[0];
|
||||
var cardMonth = parts[1];
|
||||
|
||||
// 根据筛选条件显示/隐藏
|
||||
let show = true;
|
||||
if (year && cardYear !== year) show = false;
|
||||
if (month && cardMonth !== month) show = false;
|
||||
var show = true;
|
||||
if (currentYear && cardYear !== currentYear) show = false;
|
||||
if (currentMonth && cardMonth !== currentMonth) show = false;
|
||||
|
||||
card.style.display = show ? 'flex' : 'none';
|
||||
});
|
||||
|
||||
closeTimeFilter();
|
||||
}
|
||||
|
||||
function updateFilterLabel() {
|
||||
document.getElementById('filterLabel').textContent = currentYear + '-' + parseInt(currentMonth);
|
||||
}
|
||||
|
||||
// 初始默认筛选
|
||||
filterCards();
|
||||
|
||||
// 点击弹窗外部关闭
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
const modal = document.getElementById('timeFilterModal');
|
||||
|
||||
@@ -709,10 +709,10 @@ body {
|
||||
</div>
|
||||
|
||||
|
||||
<!-- 今日三餐推荐 -->
|
||||
<div class="meal-card" id="mealCard">
|
||||
<div class="meal-card__header-row">
|
||||
<div class="meal-card__title">今日三餐推荐</div>
|
||||
<!-- 今日食谱推荐 -->
|
||||
<div class="meal-card" id="mealCard">
|
||||
<div class="meal-card__header-row">
|
||||
<div class="meal-card__title">今日食谱推荐</div>
|
||||
<span class="meal-card__ai-reason" id="mealReason">根据你的偏好与健康目标推荐</span>
|
||||
</div>
|
||||
<div class="meal-card__tabs">
|
||||
|
||||
@@ -353,7 +353,6 @@ const SITE_MAP = [
|
||||
{ file:'health-checkup/survey-manage.html', label:'问卷管理' },
|
||||
{ file:'health-checkup/survey-edit.html', label:'新增/编辑问卷', dialog:true },
|
||||
{ file:'health-checkup/activity-manage.html', label:'活动管理' },
|
||||
{ file:'health-checkup/activity-stat.html', label:'活动统计' },
|
||||
{ file:'health-checkup/activity-edit.html', label:'新增/编辑活动', dialog:true },
|
||||
{ file:'health-checkup/activity-detail.html', label:'活动详情', dialog:true },
|
||||
{ file:'wearable/tool-manage.html', label:'穿戴监测-工具管理' },
|
||||
|
||||
@@ -39,8 +39,10 @@
|
||||
.info-meta__item{padding:0 12px;border-right:1px solid var(--border);}
|
||||
.info-meta__item:first-child{padding-left:0;}
|
||||
.info-meta__item:last-child{border-right:none;}
|
||||
.info-card__right{display:flex;align-items:center;gap:40px;padding-left:32px;border-left:1px solid var(--border);flex-shrink:0;}
|
||||
.stat-item{text-align:center;}
|
||||
.info-card__right{display:flex;align-items:center;gap:40px;padding-left:32px;border-left:1px solid var(--border);flex-shrink:0;}
|
||||
.info-card__date-filter{display:flex;align-items:center;gap:8px;}
|
||||
.info-card__date-filter label{font-size:var(--font-xs);color:var(--text-secondary);white-space:nowrap;}
|
||||
.stat-item{text-align:center;}
|
||||
.stat-num{font-size:28px;font-weight:700;line-height:1.2;}
|
||||
.stat-num--blue{color:var(--primary);}
|
||||
.stat-num--green{color:var(--success);}
|
||||
@@ -182,6 +184,16 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="info-card__right">
|
||||
<div class="info-card__date-filter">
|
||||
<label>年份</label>
|
||||
<select class="filter-select" id="filterYear" onchange="onYearChange()">
|
||||
<option value="2026">2026年</option>
|
||||
<option value="2025">2025年</option>
|
||||
<option value="2024">2024年</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- ③ Tab 切换区 + 筛选栏 + 表格 -->
|
||||
@@ -479,6 +491,12 @@
|
||||
</div>
|
||||
|
||||
<script>
|
||||
/* ===== 年份切换 ===== */
|
||||
var currentYear = '2026';
|
||||
function onYearChange(){
|
||||
currentYear = document.getElementById('filterYear').value;
|
||||
// 可根据年份刷新页面数据
|
||||
}
|
||||
// [交互] Tab 切换
|
||||
function switchTab(tab) {
|
||||
document.querySelectorAll('.tab-item').forEach(function(el, i) {
|
||||
|
||||
@@ -42,6 +42,13 @@ body{font-family:-apple-system,BlinkMacSystemFont,'PingFang SC','Microsoft YaHei
|
||||
.info-card__detail{display:flex;flex-direction:column;gap:6px;}
|
||||
.info-card__name{font-size:var(--font-lg);font-weight:600;color:var(--text-primary);}
|
||||
.info-card__meta{display:flex;gap:24px;font-size:var(--font-sm);color:var(--text-secondary);}
|
||||
.info-card__right{flex-shrink:0;margin-left:auto;}
|
||||
.info-card__date-filter{display:flex;align-items:center;gap:8px;}
|
||||
.info-card__date-filter label{font-size:var(--font-xs);color:var(--text-secondary);white-space:nowrap;}
|
||||
|
||||
/* 年份选择 */
|
||||
.filter-select{height:32px;min-width:110px;border:1px solid var(--border);border-radius:var(--radius-sm);padding:0 28px 0 10px;font-size:var(--font-xs);color:var(--text-primary);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 8px center;cursor:pointer;outline:none;appearance:none;-webkit-appearance:none;}
|
||||
|
||||
/* Tab栏 */
|
||||
.tab-bar{display:flex;gap:0;border-bottom:2px solid var(--border);margin-bottom:20px;background:#fff;padding:0 24px;border-radius:var(--radius-md) var(--radius-md) 0 0;box-shadow:var(--shadow-sm);}
|
||||
.tab-item{padding:14px 24px;font-size:var(--font-sm);color:var(--text-secondary);cursor:pointer;border-bottom:2px solid transparent;margin-bottom:-2px;transition:all .2s;white-space:nowrap;}
|
||||
@@ -206,6 +213,16 @@ tbody tr:hover{background:#F8FBFF;}
|
||||
<span id="empDept">研发部</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="info-card__right">
|
||||
<div class="info-card__date-filter">
|
||||
<label>年份</label>
|
||||
<select class="filter-select" id="filterYear" onchange="onYearChange()">
|
||||
<option value="2026">2026年</option>
|
||||
<option value="2025">2025年</option>
|
||||
<option value="2024">2024年</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- [交互] 四个Tab -->
|
||||
<div class="tab-bar">
|
||||
@@ -364,6 +381,12 @@ tbody tr:hover{background:#F8FBFF;}
|
||||
</div>
|
||||
</div>
|
||||
<script>
|
||||
/* ===== 年份切换 ===== */
|
||||
var currentYear = '2026';
|
||||
function onYearChange(){
|
||||
currentYear = document.getElementById('filterYear').value;
|
||||
// 可根据年份刷新页面数据
|
||||
}
|
||||
// 主Tab切换
|
||||
function switchMainPanel(name, el) {
|
||||
document.querySelectorAll('.tab-bar .tab-item').forEach(function(t){t.classList.remove('active');});
|
||||
|
||||
@@ -43,7 +43,6 @@
|
||||
│ │ └── 新增/编辑活动
|
||||
│ │ └── 活动详情
|
||||
│ │ └── 内Tab:已参加人员 / 未参加人员
|
||||
│ └── 活动统计
|
||||
│
|
||||
├── 穿戴监测(侧边栏)
|
||||
│ ├── 设备管理
|
||||
@@ -140,7 +139,6 @@
|
||||
| 7 | 活动管理 | 活动列表 | health-checkup/activity-manage.html | 页面 |
|
||||
| | | 新增/编辑活动 | health-checkup/activity-edit.html | 页面 |
|
||||
| | | 活动详情 | health-checkup/activity-detail.html | 页面 |
|
||||
| 8 | 活动统计 | 活动统计列表 | health-checkup/activity-stat.html | 页面 |
|
||||
|
||||
### 穿戴监测(侧边栏组:穿戴监测 / 运维中心)
|
||||
|
||||
@@ -242,13 +240,13 @@
|
||||
**功能说明:** 展示单个员工的全维度健康数据详情,涵盖健康现状、健康排查、穿戴监测三大板块。
|
||||
|
||||
**页面布局:**
|
||||
- 顶部员工信息卡片:头像(首字母)、姓名、工号、单位、部门
|
||||
- 顶部员工信息卡片:头像(首字母)、姓名、工号、单位、部门、年份筛选(下拉,默认当年)
|
||||
- 主Tab切换:健康现状 / 健康排查 / 穿戴监测
|
||||
|
||||
**健康现状Tab:**
|
||||
- 健康分类标签(如B类)
|
||||
- 医院信息网格:状态、医院、日期、联系方式
|
||||
- 慢性病表格:病名、确诊年份、医院、治疗情况
|
||||
- 住院信息网格:住院状态、所在医院、住院时间、住院次数、联系人、联系电话
|
||||
- 分类信息(如"B类慢病信息")+ 慢性病表格:慢病名称、确诊年份、确诊医院、治疗情况
|
||||
|
||||
**健康排查Tab:**
|
||||
- 按参与状态筛选
|
||||
@@ -468,7 +466,7 @@
|
||||
|
||||
## 三、健康排查(含问卷管理、活动管理)
|
||||
|
||||
> **说明**:健康排查模块侧边栏包含三个菜单项:问卷管理、活动管理、活动统计。
|
||||
> **说明**:健康排查模块侧边栏包含两个菜单项:问卷管理、活动管理。
|
||||
|
||||
### 103. 问卷管理(health-checkup/survey-manage.html)
|
||||
|
||||
@@ -476,16 +474,20 @@
|
||||
|
||||
**功能说明:** 管理健康排查问卷,支持问卷的创建、编辑、预览和删除。
|
||||
|
||||
**筛选条件:** 问卷名称(输入框)、目标人群(多选:A~E类)
|
||||
**筛选条件:** 问卷名称(输入框)、适应人群(多选:A~E类)
|
||||
|
||||
**表格列:** 问卷名称、人群标签(彩色)、状态(开关:开启/关闭)、操作
|
||||
**表格列:** 问卷名称、适应人群(彩色标签:A类蓝色/B类绿色/C类橙色/D类紫色/E类青色)、问卷状态(开关:开启/关闭)、操作
|
||||
|
||||
**交互说明:**
|
||||
- 点击"新增问卷"打开新增弹窗
|
||||
- 点击"预览"打开预览弹窗(展示问卷基本信息+所有题目,含题型图标、选项和跳转逻辑提示)
|
||||
- 点击"编辑"打开编辑弹窗(问卷名称、人群多选、描述)
|
||||
- 操作列:预览、编辑、删除
|
||||
- 支持导出列表数据
|
||||
- 点击"编辑"跳转到编辑页面
|
||||
- 操作列:问卷预览、编辑、删除
|
||||
- 支持导出列表数据、导出问卷详情、查看导出任务
|
||||
|
||||
**新增/编辑弹窗字段:**
|
||||
- 问卷名称 *(输入框)
|
||||
- 适应人群 *(多选:A~E类)
|
||||
|
||||
---
|
||||
|
||||
@@ -496,7 +498,7 @@
|
||||
**功能说明:** 完整的问卷编辑器,支持创建和编辑健康排查问卷。
|
||||
|
||||
**页面布局:** 左右分栏布局
|
||||
- **左侧面板(吸顶):** 问卷名称输入、目标人群多选(A~E类)、描述文本域
|
||||
- **左侧面板(吸顶):** 问卷名称输入、适应人群多选(A~E类)、描述文本域
|
||||
- **右侧面板:** 题目列表区域,题目卡片
|
||||
- **底部保存栏:** 显示问卷名称或"未填写",取消和保存按钮
|
||||
|
||||
@@ -519,15 +521,15 @@
|
||||
|
||||
**功能说明:** 健康排查活动的增删改查管理。
|
||||
|
||||
**筛选条件:** 活动名称(输入框)、所属单位(下拉)、活动状态(下拉:待开始/进行中/已完成)、日期范围
|
||||
**筛选条件:** 活动名称(输入框)、组织单位(下拉)、活动状态(下拉:待开始/进行中/已完成)、日期范围
|
||||
|
||||
**表格列:** 活动名称、所属单位、所属部门、日期范围、人员范围(点击可查看参与人员)、状态标签、负责人、联系电话、操作
|
||||
**表格列:** 活动名称、组织单位、组织部门、起止日期、人员筛选(点击可查看参与人员弹窗)、应参加人数、已参加人数(绿色)、未参加人数(红色)、活动状态(标签)、负责人、负责人电话、操作
|
||||
|
||||
**交互说明:**
|
||||
- 点击"新增活动"跳转到新增活动页面
|
||||
- 点击"人员范围"打开参与人员弹窗(含筛选、汇总统计、内嵌员工表格)
|
||||
- 操作列:详情、编辑、删除(带确认提示)
|
||||
- 支持导出列表数据
|
||||
- 点击"人员筛选"列打开参与人员弹窗(含筛选:单位/部门、员工姓名、员工编号、是否参加 + 汇总统计:应参加/已参加/未参加人数 + 内嵌员工表格)
|
||||
- 操作列:活动详情、编辑、删除(带确认提示)
|
||||
- 支持导出列表数据、查看导出任务
|
||||
|
||||
---
|
||||
|
||||
@@ -538,16 +540,20 @@
|
||||
**功能说明:** 创建或编辑健康排查活动。
|
||||
|
||||
**表单字段:**
|
||||
- 活动名称、所属单位(下拉)、所属部门(下拉)
|
||||
- 活动名称
|
||||
- 组织机构(树形联动选择器:展开单位后选择部门,支持多厂/多部门)
|
||||
- 问卷多选(显示每个问卷对应的人群标签)
|
||||
- 人员筛选:单选切换(全员/指定)。选择"指定"时:部门多选+员工选择器
|
||||
- 员工选择器弹窗:按部门、姓名、工号、人群类型筛选;复选选择,支持全选;显示单位/部门/姓名/工号/性别/年龄/人群
|
||||
- 日期范围、负责人(可搜索下拉,带手机号)、活动说明(文本域)
|
||||
- 文件上传区域(拖拽上传,10MB限制,支持PDF/Word/Excel/图片)
|
||||
- 员工选择器弹窗:按部门、姓名、工号、所属人群筛选;复选选择,支持全选;显示单位/部门/姓名/工号/性别/年龄/所属人群
|
||||
- 起止日期
|
||||
- 负责部门(下拉)
|
||||
- 负责人(可搜索下拉,带头像,含手机号自动填充)
|
||||
- 活动说明(文本域)
|
||||
- 活动文件上传区域(拖拽上传,10MB限制,支持PDF/Word/Excel/图片,单文件)
|
||||
- 底部保存栏:取消和保存按钮
|
||||
|
||||
**交互说明:**
|
||||
- 选择单位后启用部门和员工选择器
|
||||
- 选择组织机构后启用部门和员工选择器
|
||||
- 已选员工以可移除标签形式展示
|
||||
- 负责人搜索带头像样式选项
|
||||
|
||||
@@ -560,8 +566,8 @@
|
||||
**功能说明:** 查看活动详情和参与人员数据。
|
||||
|
||||
**页面布局:**
|
||||
- 面包屑导航:根据来源动态变化(来自activity-manage或activity-stat)
|
||||
- 信息卡片:4列网格展示所有活动字段,含问卷及人群标签
|
||||
- 面包屑导航:活动管理 / 活动详情
|
||||
- 信息卡片:4列网格展示所有活动字段(活动名称、组织单位、组织部门、起止日期、人员筛选、活动状态、负责人、负责人电话、活动说明、选择问卷(含人群标签)、活动文件)
|
||||
- Tab切换:已参加人员 / 未参加人员(带数量角标)
|
||||
|
||||
**已参加人员Tab:** 筛选(部门、姓名、工号)、导出按钮、表格列:单位、部门、姓名、工号、性别、年龄、已填问卷、填写时间、操作(问卷详情)
|
||||
@@ -572,22 +578,6 @@
|
||||
|
||||
---
|
||||
|
||||
### 108. 活动统计(health-checkup/activity-stat.html)
|
||||
|
||||

|
||||
|
||||
**功能说明:** 查看各活动的参与统计情况。
|
||||
|
||||
**筛选条件:** 活动名称(输入框)、所属单位(多选)
|
||||
|
||||
**表格列:** 活动名称、所属单位、所属部门、日期范围、应参加人数、已参加人数(绿色)、未参加人数(红色)、状态标签、操作(详情)
|
||||
|
||||
**交互说明:**
|
||||
- 点击"详情"跳转到活动详情页
|
||||
- 支持导出列表数据
|
||||
|
||||
---
|
||||
|
||||
### 109. 心率异常(watch5)(wearable/ops/alarm-heartrate.html)
|
||||
|
||||

|
||||
@@ -704,11 +694,12 @@
|
||||
|
||||
**交互说明:**
|
||||
- 点击"新增设备"打开新增设备表单弹窗
|
||||
- 点击"批量入库导入"打开文件上传弹窗(Excel导入)
|
||||
- 点击"批量入库导入"打开文件上传弹窗(Excel导入,含所属单位选择)
|
||||
- 点击"批量绑定导入"打开批量绑定弹窗
|
||||
- 点击"查看导入任务"查看导入任务状态
|
||||
- 点击"导出列表数据"导出数据
|
||||
- 点击"查看导出任务"查看导出任务状态
|
||||
- 点击"绑定员工"打开绑定弹窗(搜索选择员工)
|
||||
- 点击"绑定员工"打开绑定弹窗(搜索选择员工,含绑定日期)
|
||||
- 点击"解除绑定"打开确认弹窗
|
||||
- 点击"绑定记录"打开该设备的绑定历史弹窗
|
||||
- 点击更多菜单→"设备配置"打开设备配置弹窗
|
||||
@@ -1500,7 +1491,7 @@ Tab标签:总览、心率、血氧、压力、睡眠、体温、锻炼、步
|
||||
|
||||
**表格列:** 设备名称、设备编码、所属单位、设备位置、设备详情、温度、湿度、CO₂、甲醛、PM2.5、PM10、总点击次数↕
|
||||
|
||||
> 注:实际页面各监测指标列未带"点击次数"后缀(与截图一致),多出"设备详情"列。
|
||||
> 注:表头一级分组为"移动端点击次数",各监测指标列名直接使用指标名称(不带"点击次数"后缀)。各类型均包含"设备详情"列,位于指标列最前。
|
||||
|
||||
**交互说明:**
|
||||
- 表头支持排序
|
||||
@@ -1604,10 +1595,11 @@ Tab标签:总览、心率、血氧、压力、睡眠、体温、锻炼、步
|
||||
|
||||
#### APP记录页面差异
|
||||
|
||||
各类型的点击次数列对应各自监测指标:
|
||||
- 室外:温度/湿度/太阳辐射/PM2.5/PM10/照度/风速点击次数 + 总点击次数
|
||||
- 水质:温度/电导率/pH/盐度/电阻率/TDS点击次数 + 总点击次数
|
||||
- 花粉:榆属/松属/杨属/柏科/柳属/蒿属/藜科/苋科/花粉总数点击次数 + 总点击次数
|
||||
各类型的点击次数列对应各自监测指标(一级表头为"移动端点击次数",二级列名直接使用指标名称,均含"设备详情"列):
|
||||
- 室内:设备详情 + 温度/湿度/CO₂/甲醛/PM2.5/PM10 + 总点击次数(8列)
|
||||
- 室外:设备详情 + 温度/湿度/太阳辐射/PM2.5/PM10/照度/风速 + 总点击次数(9列)
|
||||
- 水质:设备详情 + 温度/电导率/PH/盐度/电阻率/TDS + 总点击次数(8列)
|
||||
- 花粉:设备详情 + 榆属/松属/杨属/柏科/柳属/蒿属/藜科/苋科/花粉总数 + 总点击次数(11列)
|
||||
|
||||
#### 历史监测详情页面差异
|
||||
|
||||
|
||||
|
Before Width: | Height: | Size: 61 KiB After Width: | Height: | Size: 59 KiB |
|
Before Width: | Height: | Size: 80 KiB After Width: | Height: | Size: 68 KiB |
|
Before Width: | Height: | Size: 76 KiB After Width: | Height: | Size: 64 KiB |
|
Before Width: | Height: | Size: 76 KiB After Width: | Height: | Size: 63 KiB |
|
Before Width: | Height: | Size: 77 KiB After Width: | Height: | Size: 66 KiB |
|
Before Width: | Height: | Size: 47 KiB After Width: | Height: | Size: 156 KiB |
|
Before Width: | Height: | Size: 67 KiB After Width: | Height: | Size: 62 KiB |
|
Before Width: | Height: | Size: 104 KiB After Width: | Height: | Size: 108 KiB |
|
Before Width: | Height: | Size: 87 KiB |
|
Before Width: | Height: | Size: 46 KiB After Width: | Height: | Size: 41 KiB |
|
Before Width: | Height: | Size: 73 KiB After Width: | Height: | Size: 67 KiB |
|
Before Width: | Height: | Size: 107 KiB After Width: | Height: | Size: 97 KiB |
|
Before Width: | Height: | Size: 81 KiB After Width: | Height: | Size: 56 KiB |
|
Before Width: | Height: | Size: 83 KiB After Width: | Height: | Size: 76 KiB |
|
Before Width: | Height: | Size: 77 KiB After Width: | Height: | Size: 52 KiB |
|
Before Width: | Height: | Size: 92 KiB After Width: | Height: | Size: 88 KiB |
|
Before Width: | Height: | Size: 86 KiB After Width: | Height: | Size: 68 KiB |
|
Before Width: | Height: | Size: 99 KiB After Width: | Height: | Size: 64 KiB |
|
Before Width: | Height: | Size: 95 KiB After Width: | Height: | Size: 86 KiB |
@@ -193,7 +193,7 @@
|
||||
<td>IA-2024-001</td>
|
||||
<td>采油一厂</td>
|
||||
<td>办公楼1层大厅</td>
|
||||
<td><a href="indoor-device-list.html" class="link">设备详情</a></td>
|
||||
<td>245</td>
|
||||
<td>326</td><td>218</td><td>185</td><td>412</td><td>538</td><td>295</td><td>1974</td>
|
||||
</tr>
|
||||
<tr>
|
||||
@@ -201,7 +201,7 @@
|
||||
<td>IA-2024-002</td>
|
||||
<td>采油一厂</td>
|
||||
<td>办公楼2层会议室</td>
|
||||
<td><a href="indoor-device-list.html" class="link">设备详情</a></td>
|
||||
<td>178</td>
|
||||
<td>142</td><td>98</td><td>76</td><td>203</td><td>687</td><td>345</td><td>1551</td>
|
||||
</tr>
|
||||
<tr>
|
||||
@@ -209,7 +209,7 @@
|
||||
<td>IA-2024-003</td>
|
||||
<td>采油二厂</td>
|
||||
<td>新装修办公室3层</td>
|
||||
<td><a href="indoor-device-list.html" class="link">设备详情</a></td>
|
||||
<td>203</td>
|
||||
<td>89</td><td>56</td><td>112</td><td>856</td><td>234</td><td>128</td><td>1475</td>
|
||||
</tr>
|
||||
<tr>
|
||||
@@ -217,7 +217,7 @@
|
||||
<td>IA-2024-004</td>
|
||||
<td>采油二厂</td>
|
||||
<td>地下车库B1层</td>
|
||||
<td><a href="indoor-device-list.html" class="link">设备详情</a></td>
|
||||
<td>156</td>
|
||||
<td>67</td><td>45</td><td>523</td><td>38</td><td>156</td><td>89</td><td>918</td>
|
||||
</tr>
|
||||
<tr>
|
||||
@@ -225,7 +225,7 @@
|
||||
<td>IA-2024-005</td>
|
||||
<td>采油三厂</td>
|
||||
<td>生产车间1号</td>
|
||||
<td><a href="indoor-device-list.html" class="link">设备详情</a></td>
|
||||
<td>289</td>
|
||||
<td>458</td><td>312</td><td>267</td><td>189</td><td>723</td><td>456</td><td>2405</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
|
||||
@@ -180,27 +180,27 @@
|
||||
<tbody>
|
||||
<tr>
|
||||
<td class="td-left">空气质量监测站-A01</td><td>OA-2024-001</td><td>采油一厂</td><td>厂区大门东侧</td>
|
||||
<td><a href="outdoor-device-list.html" class="link">设备详情</a></td>
|
||||
<td>245</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><a href="outdoor-device-list.html" class="link">设备详情</a></td>
|
||||
<td>189</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><a href="outdoor-device-list.html" class="link">设备详情</a></td>
|
||||
<td>134</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><a href="outdoor-device-list.html" class="link">设备详情</a></td>
|
||||
<td>278</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><a href="outdoor-device-list.html" class="link">设备详情</a></td>
|
||||
<td>198</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>
|
||||
|
||||
@@ -182,27 +182,27 @@
|
||||
<tbody>
|
||||
<tr>
|
||||
<td class="td-left">花粉采样器-A01</td><td>PL-2024-001</td><td>采油一厂</td><td>办公区绿化带</td>
|
||||
<td><a href="pollen-device-list.html" class="link">设备详情</a></td>
|
||||
<td>198</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><a href="pollen-device-list.html" class="link">设备详情</a></td>
|
||||
<td>245</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><a href="pollen-device-list.html" class="link">设备详情</a></td>
|
||||
<td>267</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><a href="pollen-device-list.html" class="link">设备详情</a></td>
|
||||
<td>312</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><a href="pollen-device-list.html" class="link">设备详情</a></td>
|
||||
<td>356</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>
|
||||
|
||||
@@ -179,27 +179,27 @@
|
||||
<tbody>
|
||||
<tr>
|
||||
<td class="td-left">多参数水质分析仪-A01</td><td>WQ-2024-001</td><td>采油一厂</td><td>生活区供水站</td>
|
||||
<td><a href="water-device-list.html" class="link">设备详情</a></td>
|
||||
<td>223</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><a href="water-device-list.html" class="link">设备详情</a></td>
|
||||
<td>167</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><a href="water-device-list.html" class="link">设备详情</a></td>
|
||||
<td>145</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><a href="water-device-list.html" class="link">设备详情</a></td>
|
||||
<td>189</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><a href="water-device-list.html" class="link">设备详情</a></td>
|
||||
<td>234</td>
|
||||
<td>256</td><td>312</td><td>345</td><td>189</td><td>123</td><td>278</td><td>1503</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
|
||||
@@ -158,7 +158,6 @@
|
||||
<div class="sidebar-menu__title">健康排查</div>
|
||||
<a href="survey-manage.html" class="sidebar-item">问卷管理</a>
|
||||
<a href="activity-manage.html" class="sidebar-item active">活动管理</a>
|
||||
<a href="activity-stat.html" class="sidebar-item">活动统计</a>
|
||||
</aside>
|
||||
<main class="main">
|
||||
<!-- 面包屑 -->
|
||||
@@ -322,11 +321,6 @@ function toggleSubgroup(h){h.parentElement.classList.toggle('open');}
|
||||
/* 根据来源页面切换侧边栏选中和面包屑 */
|
||||
(function(){
|
||||
var ref = document.referrer || '';
|
||||
if(ref.indexOf('activity-stat.html') > -1){
|
||||
document.getElementById('sidebarActManage').classList.remove('active');
|
||||
document.getElementById('sidebarActStat').classList.add('active');
|
||||
document.getElementById('breadcrumb').innerHTML = '<a href="activity-stat.html">活动统计</a><span>/</span><span>活动详情</span>';
|
||||
}
|
||||
})();
|
||||
|
||||
/* ===== 数据 ===== */
|
||||
@@ -343,11 +337,11 @@ var surveyCrowdMap = {
|
||||
var surveyCrowdColors = {'A类':'tag-blue','B类':'tag-green','C类':'tag-orange','D类':'tag-purple','E类':'tag-cyan'};
|
||||
|
||||
var activities = [
|
||||
{id:1, name:'2026年上半年员工健康排查', org:'能源集团', dept:'人力资源部', dateFrom:'2026-01-01', dateTo:'2026-03-31', personType:'全体人员', personCount:1280, status:'已完成', leader:'张明', phone:'13800001234', surveys:['健康记录问卷','职业健康排查问卷'], desc:'年度例行员工健康排查活动,覆盖全体员工。'},
|
||||
{id:2, name:'2026年Q2心理健康专项排查', org:'能源集团', dept:'安全环保部', dateFrom:'2026-04-01', dateTo:'2026-06-30', personType:'指定人员', personCount:356, status:'进行中', leader:'李华', phone:'13800005678', surveys:['心理健康评估问卷'], desc:'针对C类和D类人群的心理健康专项排查。'},
|
||||
{id:3, name:'2026年Q3职业健康排查', org:'能源集团', dept:'安全环保部', dateFrom:'2026-07-01', dateTo:'2026-09-30', personType:'指定人员', personCount:520, status:'待开始', leader:'王强', phone:'13800009012', surveys:['职业健康排查问卷','健康记录问卷'], desc:'第三季度职业健康专项排查,针对A类和B类人群。'},
|
||||
{id:4, name:'新员工入职健康基线调查', org:'能源集团', dept:'人力资源部', dateFrom:'2026-06-01', dateTo:'2026-12-31', personType:'指定人员', personCount:85, status:'进行中', leader:'赵芳', phone:'13800003456', surveys:['新员工健康基线问卷'], desc:'2026年度新入职员工健康基线数据采集。'},
|
||||
{id:5, name:'慢病患者季度随访', org:'能源集团', dept:'工会', dateFrom:'2026-04-01', dateTo:'2026-06-30', personType:'指定人员', personCount:128, status:'进行中', leader:'孙丽', phone:'13800007890', surveys:['慢病管理随访问卷'], desc:'E类慢病患者第二季度定期随访。'}
|
||||
{id:1, name:'2026年上半年员工健康排查', org:'能源集团', dept:'人力资源部', dateFrom:'2026-01-01', dateTo:'2026-03-31', personType:'全体人员', personCount:1280, status:'已完成', leader:'张明', phone:'13800001234', surveys:['健康记录问卷','职业健康排查问卷'], desc:'年度例行员工健康排查活动,覆盖全体员工。', file:'2026上半年健康排查通知.pdf'},
|
||||
{id:2, name:'2026年Q2心理健康专项排查', org:'能源集团', dept:'安全环保部', dateFrom:'2026-04-01', dateTo:'2026-06-30', personType:'指定人员', personCount:356, status:'进行中', leader:'李华', phone:'13800005678', surveys:['心理健康评估问卷'], desc:'针对C类和D类人群的心理健康专项排查。', file:'心理健康排查实施方案.pdf'},
|
||||
{id:3, name:'2026年Q3职业健康排查', org:'能源集团', dept:'安全环保部', dateFrom:'2026-07-01', dateTo:'2026-09-30', personType:'指定人员', personCount:520, status:'待开始', leader:'王强', phone:'13800009012', surveys:['职业健康排查问卷','健康记录问卷'], desc:'第三季度职业健康专项排查,针对A类和B类人群。', file:''},
|
||||
{id:4, name:'新员工入职健康基线调查', org:'能源集团', dept:'人力资源部', dateFrom:'2026-06-01', dateTo:'2026-12-31', personType:'指定人员', personCount:85, status:'进行中', leader:'赵芳', phone:'13800003456', surveys:['新员工健康基线问卷'], desc:'2026年度新入职员工健康基线数据采集。', file:'新员工健康基线调查通知.pdf'},
|
||||
{id:5, name:'慢病患者季度随访', org:'能源集团', dept:'工会', dateFrom:'2026-04-01', dateTo:'2026-06-30', personType:'指定人员', personCount:128, status:'进行中', leader:'孙丽', phone:'13800007890', surveys:['慢病管理随访问卷'], desc:'E类慢病患者第二季度定期随访。', file:'慢病随访安排表.xlsx'}
|
||||
];
|
||||
|
||||
/* 参与人员模拟数据 */
|
||||
@@ -551,6 +545,12 @@ var currentTab = 'done';
|
||||
html += '<div class="info-item"><span class="info-item__label">负责人电话</span><span class="info-item__value">'+currentAct.phone+'</span></div>';
|
||||
html += '<div class="info-item"><span class="info-item__label">活动说明</span><span class="info-item__value">'+esc(currentAct.desc||'—')+'</span></div>';
|
||||
html += '<div class="info-item"><span class="info-item__label">选择问卷</span><span class="info-item__value">'+surveyNames+'</span></div>';
|
||||
// 活动文件
|
||||
var file = currentAct.file || '';
|
||||
var fileHtml = file ? '<a class="link" href="javascript:void(0)" onclick="viewFile(\''+esc(file)+'\')" style="display:inline-flex;align-items:center;gap:4px;">'+
|
||||
'<svg width="14" height="14" viewBox="0 0 14 14" fill="none"><path d="M3 1h5l4 4v8H3V1z" stroke="currentColor" stroke-width="1.3"/><path d="M8 1v4h4" stroke="currentColor" stroke-width="1.3"/></svg>'+
|
||||
esc(file)+'</a>' : '—';
|
||||
html += '<div class="info-item info-item__half"><span class="info-item__label">活动文件</span><span class="info-item__value">'+fileHtml+'</span></div>';
|
||||
document.getElementById('infoGrid').innerHTML = html;
|
||||
|
||||
/* 计算已参加/未参加 */
|
||||
@@ -710,6 +710,11 @@ function closeModal(id){document.getElementById(id).classList.remove('show');}
|
||||
|
||||
function esc(s){return (s||'').replace(/&/g,'&').replace(/"/g,'"').replace(/</g,'<').replace(/>/g,'>');}
|
||||
|
||||
/* ===== 查看活动文件 ===== */
|
||||
function viewFile(fileName){
|
||||
alert('查看文件:' + fileName + '\n(原型示意,实际项目中跳转至文件预览或下载)');
|
||||
}
|
||||
|
||||
/* 点击遮罩关闭弹窗 */
|
||||
document.querySelectorAll('.modal-mask').forEach(function(m){
|
||||
m.addEventListener('click',function(e){if(e.target === m) closeModal(m.id);});
|
||||
|
||||
@@ -159,7 +159,28 @@
|
||||
.emp-table__info{font-size:var(--font-xs);color:var(--text-secondary);}
|
||||
.emp-table__info strong{color:var(--primary);}
|
||||
|
||||
/* 文件上传 */
|
||||
/* 树形选择器(组织机构) */
|
||||
.tree-select{position:relative;width:100%;}
|
||||
.tree-select__trigger{width:100%;height:36px;border:1px solid var(--border);border-radius:var(--radius-sm);padding:0 32px 0 12px;font-size:var(--font-sm);background:#fff;cursor:pointer;display:flex;align-items:center;user-select:none;transition:border-color .2s;box-sizing:border-box;position:relative;}
|
||||
.tree-select__trigger:hover{border-color:var(--primary);}
|
||||
.tree-select__trigger::after{content:'';position:absolute;right:12px;top:50%;transform:translateY(-50%);border:4px solid transparent;border-top:5px solid #999;pointer-events:none;}
|
||||
.tree-select__text{color:var(--text-placeholder);overflow:hidden;text-overflow:ellipsis;white-space:nowrap;}
|
||||
.tree-select__text.has-value{color:var(--text-primary);}
|
||||
.tree-select__panel{position:absolute;top:100%;left:0;right:0;margin-top:4px;background:#fff;border:1px solid var(--border);border-radius:var(--radius-md);box-shadow:var(--shadow-md);z-index:500;display:none;max-height:320px;overflow-y:auto;}
|
||||
.tree-select__panel.show{display:block;}
|
||||
.tree-select__group{border-bottom:1px solid #F5F5F5;}
|
||||
.tree-select__group:last-child{border-bottom:none;}
|
||||
.tree-select__group-header{display:flex;align-items:center;gap:6px;padding:9px 16px;font-size:var(--font-sm);font-weight:500;color:var(--text-primary);cursor:pointer;transition:background .1s;user-select:none;}
|
||||
.tree-select__group-header:hover{background:#F5F7FA;}
|
||||
.tree-select__group-arrow{width:16px;height:16px;display:flex;align-items:center;justify-content:center;transition:transform .2s;flex-shrink:0;color:var(--text-placeholder);}
|
||||
.tree-select__group-arrow.expanded{transform:rotate(90deg);}
|
||||
.tree-select__group-label{flex:1;}
|
||||
.tree-select__option{padding:8px 16px 8px 38px;font-size:var(--font-sm);cursor:pointer;transition:background .1s;display:none;color:var(--text-secondary);}
|
||||
.tree-select__option.show{display:block;}
|
||||
.tree-select__option:hover{background:#F5F7FA;}
|
||||
.tree-select__option.selected{color:var(--primary);background:var(--primary-light);}
|
||||
|
||||
/* 文件上传 */
|
||||
.upload-area{border:2px dashed var(--border);border-radius:var(--radius-md);padding:32px;text-align:center;cursor:pointer;transition:all .2s;background:#FAFAFA;}
|
||||
.upload-area:hover{border-color:var(--primary);background:var(--primary-light);}
|
||||
.upload-area svg{width:40px;height:40px;color:var(--text-placeholder);margin-bottom:8px;}
|
||||
@@ -208,7 +229,6 @@
|
||||
<div class="sidebar-menu__title">健康排查</div>
|
||||
<a href="survey-manage.html" class="sidebar-item">问卷管理</a>
|
||||
<a href="activity-manage.html" class="sidebar-item active">活动管理</a>
|
||||
<a href="activity-stat.html" class="sidebar-item">活动统计</a>
|
||||
</aside>
|
||||
<main class="main">
|
||||
<div class="form-card">
|
||||
@@ -223,34 +243,96 @@
|
||||
<input class="form-input" id="actName" placeholder="请输入活动名称">
|
||||
</div>
|
||||
|
||||
<!-- 组织单位 & 组织部门 -->
|
||||
<div class="form-row">
|
||||
<div class="form-group">
|
||||
<label>组织单位 <span class="req">*</span></label>
|
||||
<select class="form-input" id="actOrg">
|
||||
<option value="">请选择组织单位</option>
|
||||
<option>第一采油厂</option>
|
||||
<option>第二采油厂</option>
|
||||
<option>第三采油厂</option>
|
||||
<option>第四采油厂</option>
|
||||
<option>第五采油厂</option>
|
||||
<option>第六采油厂</option>
|
||||
<option>第七采油厂</option>
|
||||
<option>第八采油厂</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>组织部门 <span class="req">*</span></label>
|
||||
<select class="form-input" id="actDept">
|
||||
<option value="">请选择组织部门</option>
|
||||
<option>人力资源部</option>
|
||||
<option>安全环保部</option>
|
||||
<option>工会</option>
|
||||
<option>生产技术部</option>
|
||||
<option>财务部</option>
|
||||
<option>信息中心</option>
|
||||
<option>综合办公室</option>
|
||||
</select>
|
||||
<!-- 组织机构(树形联动选择器) -->
|
||||
<div class="form-group">
|
||||
<label>组织机构 <span class="req">*</span></label>
|
||||
<div class="tree-select" id="orgTreeSelect">
|
||||
<input type="hidden" id="actOrgValue" value="">
|
||||
<div class="tree-select__trigger" onclick="toggleOrgTree()">
|
||||
<span class="tree-select__text" id="orgTreeText">请选择组织机构</span>
|
||||
</div>
|
||||
<div class="tree-select__panel" id="orgTreePanel">
|
||||
<div class="tree-select__group" data-unit="第一采油厂">
|
||||
<div class="tree-select__group-header" onclick="toggleOrgGroup(this, event)">
|
||||
<span class="tree-select__group-arrow">▶</span>
|
||||
<span class="tree-select__group-label">第一采油厂</span>
|
||||
</div>
|
||||
<div class="tree-select__option" data-val="第一采油厂|人力资源部" onclick="selectOrgOption(this,'第一采油厂 / 人力资源部')">人力资源部</div>
|
||||
<div class="tree-select__option" data-val="第一采油厂|安全环保部" onclick="selectOrgOption(this,'第一采油厂 / 安全环保部')">安全环保部</div>
|
||||
<div class="tree-select__option" data-val="第一采油厂|生产技术部" onclick="selectOrgOption(this,'第一采油厂 / 生产技术部')">生产技术部</div>
|
||||
<div class="tree-select__option" data-val="第一采油厂|综合办公室" onclick="selectOrgOption(this,'第一采油厂 / 综合办公室')">综合办公室</div>
|
||||
</div>
|
||||
<div class="tree-select__group" data-unit="第二采油厂">
|
||||
<div class="tree-select__group-header" onclick="toggleOrgGroup(this, event)">
|
||||
<span class="tree-select__group-arrow">▶</span>
|
||||
<span class="tree-select__group-label">第二采油厂</span>
|
||||
</div>
|
||||
<div class="tree-select__option" data-val="第二采油厂|工会" onclick="selectOrgOption(this,'第二采油厂 / 工会')">工会</div>
|
||||
<div class="tree-select__option" data-val="第二采油厂|生产技术部" onclick="selectOrgOption(this,'第二采油厂 / 生产技术部')">生产技术部</div>
|
||||
<div class="tree-select__option" data-val="第二采油厂|财务部" onclick="selectOrgOption(this,'第二采油厂 / 财务部')">财务部</div>
|
||||
<div class="tree-select__option" data-val="第二采油厂|信息中心" onclick="selectOrgOption(this,'第二采油厂 / 信息中心')">信息中心</div>
|
||||
</div>
|
||||
<div class="tree-select__group" data-unit="第三采油厂">
|
||||
<div class="tree-select__group-header" onclick="toggleOrgGroup(this, event)">
|
||||
<span class="tree-select__group-arrow">▶</span>
|
||||
<span class="tree-select__group-label">第三采油厂</span>
|
||||
</div>
|
||||
<div class="tree-select__option" data-val="第三采油厂|信息中心" onclick="selectOrgOption(this,'第三采油厂 / 信息中心')">信息中心</div>
|
||||
<div class="tree-select__option" data-val="第三采油厂|综合办公室" onclick="selectOrgOption(this,'第三采油厂 / 综合办公室')">综合办公室</div>
|
||||
<div class="tree-select__option" data-val="第三采油厂|人力资源部" onclick="selectOrgOption(this,'第三采油厂 / 人力资源部')">人力资源部</div>
|
||||
<div class="tree-select__option" data-val="第三采油厂|安全环保部" onclick="selectOrgOption(this,'第三采油厂 / 安全环保部')">安全环保部</div>
|
||||
</div>
|
||||
<div class="tree-select__group" data-unit="第四采油厂">
|
||||
<div class="tree-select__group-header" onclick="toggleOrgGroup(this, event)">
|
||||
<span class="tree-select__group-arrow">▶</span>
|
||||
<span class="tree-select__group-label">第四采油厂</span>
|
||||
</div>
|
||||
<div class="tree-select__option" data-val="第四采油厂|安全环保部" onclick="selectOrgOption(this,'第四采油厂 / 安全环保部')">安全环保部</div>
|
||||
<div class="tree-select__option" data-val="第四采油厂|生产技术部" onclick="selectOrgOption(this,'第四采油厂 / 生产技术部')">生产技术部</div>
|
||||
<div class="tree-select__option" data-val="第四采油厂|工会" onclick="selectOrgOption(this,'第四采油厂 / 工会')">工会</div>
|
||||
<div class="tree-select__option" data-val="第四采油厂|财务部" onclick="selectOrgOption(this,'第四采油厂 / 财务部')">财务部</div>
|
||||
</div>
|
||||
<div class="tree-select__group" data-unit="第五采油厂">
|
||||
<div class="tree-select__group-header" onclick="toggleOrgGroup(this, event)">
|
||||
<span class="tree-select__group-arrow">▶</span>
|
||||
<span class="tree-select__group-label">第五采油厂</span>
|
||||
</div>
|
||||
<div class="tree-select__option" data-val="第五采油厂|工会" onclick="selectOrgOption(this,'第五采油厂 / 工会')">工会</div>
|
||||
<div class="tree-select__option" data-val="第五采油厂|财务部" onclick="selectOrgOption(this,'第五采油厂 / 财务部')">财务部</div>
|
||||
<div class="tree-select__option" data-val="第五采油厂|人力资源部" onclick="selectOrgOption(this,'第五采油厂 / 人力资源部')">人力资源部</div>
|
||||
<div class="tree-select__option" data-val="第五采油厂|生产技术部" onclick="selectOrgOption(this,'第五采油厂 / 生产技术部')">生产技术部</div>
|
||||
</div>
|
||||
<div class="tree-select__group" data-unit="第六采油厂">
|
||||
<div class="tree-select__group-header" onclick="toggleOrgGroup(this, event)">
|
||||
<span class="tree-select__group-arrow">▶</span>
|
||||
<span class="tree-select__group-label">第六采油厂</span>
|
||||
</div>
|
||||
<div class="tree-select__option" data-val="第六采油厂|信息中心" onclick="selectOrgOption(this,'第六采油厂 / 信息中心')">信息中心</div>
|
||||
<div class="tree-select__option" data-val="第六采油厂|综合办公室" onclick="selectOrgOption(this,'第六采油厂 / 综合办公室')">综合办公室</div>
|
||||
<div class="tree-select__option" data-val="第六采油厂|安全环保部" onclick="selectOrgOption(this,'第六采油厂 / 安全环保部')">安全环保部</div>
|
||||
<div class="tree-select__option" data-val="第六采油厂|生产技术部" onclick="selectOrgOption(this,'第六采油厂 / 生产技术部')">生产技术部</div>
|
||||
</div>
|
||||
<div class="tree-select__group" data-unit="第七采油厂">
|
||||
<div class="tree-select__group-header" onclick="toggleOrgGroup(this, event)">
|
||||
<span class="tree-select__group-arrow">▶</span>
|
||||
<span class="tree-select__group-label">第七采油厂</span>
|
||||
</div>
|
||||
<div class="tree-select__option" data-val="第七采油厂|人力资源部" onclick="selectOrgOption(this,'第七采油厂 / 人力资源部')">人力资源部</div>
|
||||
<div class="tree-select__option" data-val="第七采油厂|安全环保部" onclick="selectOrgOption(this,'第七采油厂 / 安全环保部')">安全环保部</div>
|
||||
<div class="tree-select__option" data-val="第七采油厂|工会" onclick="selectOrgOption(this,'第七采油厂 / 工会')">工会</div>
|
||||
<div class="tree-select__option" data-val="第七采油厂|信息中心" onclick="selectOrgOption(this,'第七采油厂 / 信息中心')">信息中心</div>
|
||||
</div>
|
||||
<div class="tree-select__group" data-unit="第八采油厂">
|
||||
<div class="tree-select__group-header" onclick="toggleOrgGroup(this, event)">
|
||||
<span class="tree-select__group-arrow">▶</span>
|
||||
<span class="tree-select__group-label">第八采油厂</span>
|
||||
</div>
|
||||
<div class="tree-select__option" data-val="第八采油厂|生产技术部" onclick="selectOrgOption(this,'第八采油厂 / 生产技术部')">生产技术部</div>
|
||||
<div class="tree-select__option" data-val="第八采油厂|工会" onclick="selectOrgOption(this,'第八采油厂 / 工会')">工会</div>
|
||||
<div class="tree-select__option" data-val="第八采油厂|财务部" onclick="selectOrgOption(this,'第八采油厂 / 财务部')">财务部</div>
|
||||
<div class="tree-select__option" data-val="第八采油厂|综合办公室" onclick="selectOrgOption(this,'第八采油厂 / 综合办公室')">综合办公室</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -322,6 +404,21 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 负责部门 -->
|
||||
<div class="form-group">
|
||||
<label>负责部门 <span class="req">*</span></label>
|
||||
<select class="form-input" id="responsibleDept">
|
||||
<option value="">请选择负责部门</option>
|
||||
<option>人力资源部</option>
|
||||
<option>安全环保部</option>
|
||||
<option>工会</option>
|
||||
<option>生产技术部</option>
|
||||
<option>财务部</option>
|
||||
<option>信息中心</option>
|
||||
<option>综合办公室</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<!-- 负责人 -->
|
||||
<div class="form-group">
|
||||
<label>负责人 <span class="req">*</span></label>
|
||||
@@ -350,9 +447,9 @@
|
||||
<div class="upload-area" id="uploadArea" onclick="document.getElementById('fileInput').click()">
|
||||
<svg viewBox="0 0 40 40" fill="none"><path d="M20 8v24M12 16l8-8 8 8" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/><path d="M8 28v4a2 2 0 002 2h20a2 2 0 002-2v-4" stroke="currentColor" stroke-width="2" stroke-linecap="round"/></svg>
|
||||
<div class="upload-area__text">点击或拖拽文件到此区域上传</div>
|
||||
<div class="upload-area__hint">支持 PDF、Word、Excel、图片等格式,单个文件不超过 10MB</div>
|
||||
<div class="upload-area__hint">支持 PDF、Word、Excel、图片等格式,文件不超过 10MB</div>
|
||||
</div>
|
||||
<input type="file" id="fileInput" style="display:none" multiple onchange="handleFiles(this.files)">
|
||||
<input type="file" id="fileInput" style="display:none" onchange="handleFile(this.files)">
|
||||
<div class="file-list" id="fileList"></div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -450,6 +547,114 @@
|
||||
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 getOrgUnit(val){
|
||||
var idx = val.indexOf('|');
|
||||
return idx > -1 ? val.substring(0, idx) : val;
|
||||
}
|
||||
|
||||
// 从组织机构值中提取部门名称(兼容"单位|部门"格式)
|
||||
function getOrgDept(val){
|
||||
var idx = val.indexOf('|');
|
||||
return idx > -1 ? val.substring(idx + 1) : '';
|
||||
}
|
||||
|
||||
// 点击触发器展开/收起下拉面板
|
||||
function toggleOrgTree(){
|
||||
var panel = document.getElementById('orgTreePanel');
|
||||
var isShow = panel.classList.contains('show');
|
||||
closeAllPanels();
|
||||
if(!isShow) panel.classList.add('show');
|
||||
}
|
||||
|
||||
// 点击单位标题展开/收起部门列表,或选中该单位
|
||||
function toggleOrgGroup(headerEl, event){
|
||||
event.stopPropagation();
|
||||
var arrow = headerEl.querySelector('.tree-select__group-arrow');
|
||||
var group = headerEl.parentElement;
|
||||
var options = group.querySelectorAll('.tree-select__option');
|
||||
var isExpanded = arrow.classList.contains('expanded');
|
||||
if(isExpanded){
|
||||
// 收起:隐藏部门选项,并选中该单位
|
||||
arrow.classList.remove('expanded');
|
||||
options.forEach(function(opt){ opt.classList.remove('show'); });
|
||||
var unitName = group.getAttribute('data-unit');
|
||||
selectOrgOptionInner(unitName, unitName);
|
||||
} else {
|
||||
// 收起其他已展开的分组
|
||||
document.querySelectorAll('.tree-select__group-arrow.expanded').forEach(function(a){
|
||||
a.classList.remove('expanded');
|
||||
});
|
||||
document.querySelectorAll('.tree-select__option.show').forEach(function(o){
|
||||
o.classList.remove('show');
|
||||
});
|
||||
// 展开当前分组
|
||||
arrow.classList.add('expanded');
|
||||
options.forEach(function(opt){ opt.classList.add('show'); });
|
||||
}
|
||||
}
|
||||
|
||||
// 点击部门选项选中
|
||||
function selectOrgOption(el, displayText){
|
||||
var val = el.getAttribute('data-val');
|
||||
selectOrgOptionInner(val, displayText);
|
||||
}
|
||||
|
||||
// 内部选中逻辑
|
||||
function selectOrgOptionInner(val, displayText){
|
||||
var hidden = document.getElementById('actOrgValue');
|
||||
var oldVal = hidden.value;
|
||||
hidden.value = val;
|
||||
// 更新触发器显示
|
||||
var textEl = document.getElementById('orgTreeText');
|
||||
textEl.textContent = displayText;
|
||||
textEl.className = 'tree-select__text has-value';
|
||||
// 更新面板选中态
|
||||
document.querySelectorAll('#orgTreePanel .tree-select__option.selected').forEach(function(o){
|
||||
o.classList.remove('selected');
|
||||
});
|
||||
var targetOpt = document.querySelector('#orgTreePanel .tree-select__option[data-val="' + val + '"]');
|
||||
if(targetOpt){ targetOpt.classList.add('selected'); }
|
||||
// 关闭面板
|
||||
document.getElementById('orgTreePanel').classList.remove('show');
|
||||
// 触发change事件
|
||||
if(oldVal !== val){
|
||||
updateOrgDependent();
|
||||
}
|
||||
}
|
||||
|
||||
// 监听组织机构变化,同步更新部门和员工选择器状态
|
||||
function updateOrgDependent(){
|
||||
var orgVal = document.getElementById('actOrgValue').value;
|
||||
var orgUnit = getOrgUnit(orgVal);
|
||||
var deptTrigger = document.getElementById('deptTrigger');
|
||||
if(orgUnit){
|
||||
deptTrigger.classList.remove('disabled');
|
||||
if(selectedDepts.length===0){
|
||||
deptTrigger.textContent = '请选择部门(可多选)';
|
||||
}
|
||||
} else {
|
||||
deptTrigger.classList.add('disabled');
|
||||
deptTrigger.textContent = '请先选择组织机构';
|
||||
selectedDepts = [];
|
||||
updateDeptTrigger();
|
||||
}
|
||||
var empTrigger = document.getElementById('empTrigger');
|
||||
var text = document.getElementById('empTriggerText');
|
||||
if(orgUnit){
|
||||
empTrigger.classList.remove('disabled');
|
||||
text.className = 'emp-trigger__text';
|
||||
text.textContent = '点击选择员工';
|
||||
} else {
|
||||
empTrigger.classList.add('disabled');
|
||||
text.className = 'emp-trigger__text';
|
||||
text.textContent = '请先选择组织机构';
|
||||
selectedEmployees = [];
|
||||
renderSelectedPersons();
|
||||
}
|
||||
}
|
||||
|
||||
/* ===== 问卷多选 ===== */
|
||||
var selectedSurveys = [];
|
||||
|
||||
@@ -498,9 +703,9 @@ function removeSurveyTag(val){
|
||||
var selectedDepts = [];
|
||||
|
||||
function toggleDeptPanel(){
|
||||
var org = document.getElementById('actOrg').value;
|
||||
var org = document.getElementById('actOrgValue').value;
|
||||
if(!org){
|
||||
showToast('请先选择组织单位');
|
||||
showToast('请先选择组织机构');
|
||||
return;
|
||||
}
|
||||
var panel = document.getElementById('deptPanel');
|
||||
@@ -579,71 +784,20 @@ var mockEmployees = [
|
||||
{org:'第八采油厂',dept:'工会',name:'罗琳',id:'015123',gender:'女',age:32,crowd:'B类'},
|
||||
];
|
||||
|
||||
// 监听组织单位变化,同步更新部门和员工选择器状态
|
||||
document.getElementById('actOrg').addEventListener('change', updateOrgDependent);
|
||||
|
||||
function updateOrgDependent(){
|
||||
var org = document.getElementById('actOrg').value;
|
||||
// 更新部门选择器状态
|
||||
var deptTrigger = document.getElementById('deptTrigger');
|
||||
if(org){
|
||||
deptTrigger.classList.remove('disabled');
|
||||
if(selectedDepts.length === 0){
|
||||
deptTrigger.textContent = '请选择部门(可多选)';
|
||||
}
|
||||
} else {
|
||||
deptTrigger.classList.add('disabled');
|
||||
deptTrigger.textContent = '请先选择组织单位';
|
||||
// 清空已选部门
|
||||
selectedDepts = [];
|
||||
updateDeptTrigger();
|
||||
}
|
||||
// 更新员工选择器状态
|
||||
var empTrigger = document.getElementById('empTrigger');
|
||||
var text = document.getElementById('empTriggerText');
|
||||
if(org){
|
||||
empTrigger.classList.remove('disabled');
|
||||
text.className = 'emp-trigger__text';
|
||||
text.textContent = '点击选择员工';
|
||||
} else {
|
||||
empTrigger.classList.add('disabled');
|
||||
text.className = 'emp-trigger__text';
|
||||
text.textContent = '请先选择组织单位';
|
||||
// 清空已选员工
|
||||
selectedEmployees = [];
|
||||
renderSelectedPersons();
|
||||
}
|
||||
}
|
||||
|
||||
// 打开员工弹窗
|
||||
function openEmpModal(){
|
||||
var org = document.getElementById('actOrg').value;
|
||||
if(!org){
|
||||
showToast('请先选择组织单位');
|
||||
return;
|
||||
}
|
||||
// 初始化临时选中列表为当前已选
|
||||
tempSelectedEmps = selectedEmployees.slice();
|
||||
renderEmpTable();
|
||||
document.getElementById('empModal').classList.add('show');
|
||||
}
|
||||
|
||||
// 关闭员工弹窗
|
||||
function closeEmpModal(){
|
||||
document.getElementById('empModal').classList.remove('show');
|
||||
}
|
||||
|
||||
// 渲染员工表格
|
||||
function renderEmpTable(){
|
||||
var org = document.getElementById('actOrg').value;
|
||||
var orgVal = document.getElementById('actOrgValue').value;
|
||||
var orgUnit = getOrgUnit(orgVal);
|
||||
var orgDept = getOrgDept(orgVal);
|
||||
var filterDept = document.getElementById('empFilterDept').value;
|
||||
var filterName = document.getElementById('empFilterName').value.trim().toLowerCase();
|
||||
var filterId = document.getElementById('empFilterId').value.trim().toLowerCase();
|
||||
var filterCrowd = document.getElementById('empFilterCrowd').value;
|
||||
|
||||
// 根据组织单位筛选
|
||||
// 根据组织机构筛选
|
||||
var filtered = mockEmployees.filter(function(e){
|
||||
if(e.org !== org) return false;
|
||||
if(e.org !== orgUnit) return false;
|
||||
if(orgDept && e.dept !== orgDept) return false;
|
||||
if(filterDept && e.dept !== filterDept) return false;
|
||||
if(filterName && e.name.indexOf(filterName) === -1) return false;
|
||||
if(filterId && e.id.toLowerCase().indexOf(filterId) === -1) return false;
|
||||
@@ -814,36 +968,37 @@ function removeEmp(empId){
|
||||
renderSelectedPersons();
|
||||
}
|
||||
|
||||
/* ===== 文件上传 ===== */
|
||||
var uploadedFiles = [];
|
||||
/* ===== 文件上传(仅支持单个文件) ===== */
|
||||
var uploadedFile = null;
|
||||
|
||||
function handleFiles(files){
|
||||
for(var i=0;i<files.length;i++){
|
||||
var f = files[i];
|
||||
if(f.size > 10*1024*1024){alert('文件「'+f.name+'」超过10MB限制');continue;}
|
||||
uploadedFiles.push({name:f.name, size:f.size});
|
||||
}
|
||||
function handleFile(files){
|
||||
if(!files || files.length === 0) return;
|
||||
var f = files[0];
|
||||
if(f.size > 10*1024*1024){alert('文件「'+f.name+'」超过10MB限制');return;}
|
||||
uploadedFile = {name:f.name, size:f.size};
|
||||
renderFileList();
|
||||
document.getElementById('fileInput').value = '';
|
||||
}
|
||||
|
||||
function renderFileList(){
|
||||
var container = document.getElementById('fileList');
|
||||
var html = '';
|
||||
uploadedFiles.forEach(function(f,i){
|
||||
var sizeStr = f.size > 1024*1024 ? (f.size/(1024*1024)).toFixed(1)+' MB' : (f.size/1024).toFixed(0)+' KB';
|
||||
html += '<div class="file-item">';
|
||||
html += '<div class="file-item__icon"><svg width="16" height="16" viewBox="0 0 16 16" fill="none"><path d="M3 1h6l4 4v10H3V1z" stroke="#1890FF" stroke-width="1.3"/><path d="M9 1v4h4" stroke="#1890FF" stroke-width="1.3"/></svg></div>';
|
||||
html += '<span class="file-item__name">'+esc(f.name)+'</span>';
|
||||
html += '<span class="file-item__size">'+sizeStr+'</span>';
|
||||
html += '<button class="file-item__del" onclick="removeFile('+i+')" title="删除"><svg width="12" height="12" viewBox="0 0 12 12" fill="none"><path d="M3 3l6 6M9 3l-6 6" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/></svg></button>';
|
||||
html += '</div>';
|
||||
});
|
||||
if(!uploadedFile){
|
||||
container.innerHTML = '';
|
||||
return;
|
||||
}
|
||||
var f = uploadedFile;
|
||||
var sizeStr = f.size > 1024*1024 ? (f.size/(1024*1024)).toFixed(1)+' MB' : (f.size/1024).toFixed(0)+' KB';
|
||||
var html = '<div class="file-item">';
|
||||
html += '<div class="file-item__icon"><svg width="16" height="16" viewBox="0 0 16 16" fill="none"><path d="M3 1h6l4 4v10H3V1z" stroke="#1890FF" stroke-width="1.3"/><path d="M9 1v4h4" stroke="#1890FF" stroke-width="1.3"/></svg></div>';
|
||||
html += '<span class="file-item__name">'+esc(f.name)+'</span>';
|
||||
html += '<span class="file-item__size">'+sizeStr+'</span>';
|
||||
html += '<button class="file-item__del" onclick="removeFile()" title="删除"><svg width="12" height="12" viewBox="0 0 12 12" fill="none"><path d="M3 3l6 6M9 3l-6 6" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/></svg></button>';
|
||||
html += '</div>';
|
||||
container.innerHTML = html;
|
||||
}
|
||||
|
||||
function removeFile(idx){
|
||||
uploadedFiles.splice(idx, 1);
|
||||
function removeFile(){
|
||||
uploadedFile = null;
|
||||
renderFileList();
|
||||
}
|
||||
|
||||
@@ -854,7 +1009,7 @@ function removeFile(idx){
|
||||
area.addEventListener('dragleave', function(){area.style.borderColor='';area.style.background='';});
|
||||
area.addEventListener('drop', function(e){
|
||||
e.preventDefault();area.style.borderColor='';area.style.background='';
|
||||
handleFiles(e.dataTransfer.files);
|
||||
handleFile(e.dataTransfer.files);
|
||||
});
|
||||
})();
|
||||
|
||||
@@ -863,6 +1018,7 @@ function closeAllPanels(){
|
||||
document.getElementById('surveyPanel').classList.remove('show');
|
||||
document.getElementById('deptPanel').classList.remove('show');
|
||||
document.getElementById('leaderPanel').classList.remove('show');
|
||||
document.getElementById('orgTreePanel').classList.remove('show');
|
||||
}
|
||||
|
||||
/* ===== 保存 ===== */
|
||||
@@ -877,9 +1033,10 @@ function saveActivity(){
|
||||
var dateFrom = document.getElementById('dateFrom').value;
|
||||
var dateTo = document.getElementById('dateTo').value;
|
||||
if(!dateFrom||!dateTo){alert('请选择起止日期');return;}
|
||||
var org = document.getElementById('actOrg').value.trim();
|
||||
var dept = document.getElementById('actDept').value.trim();
|
||||
if(!org||!dept){alert('请输入组织单位和组织部门');return;}
|
||||
var org = document.getElementById('actOrgValue').value;
|
||||
var responsibleDept = document.getElementById('responsibleDept').value;
|
||||
if(!org){alert('请选择组织机构');return;}
|
||||
if(!responsibleDept){alert('请选择负责部门');return;}
|
||||
if(!selectedLeader){alert('请选择负责人');return;}
|
||||
showToast('保存成功!');
|
||||
setTimeout(function(){window.location.href='activity-manage.html';},1000);
|
||||
@@ -899,6 +1056,7 @@ document.addEventListener('click',function(e){
|
||||
if(!e.target.closest('#surveySelect')) document.getElementById('surveyPanel').classList.remove('show');
|
||||
if(!e.target.closest('#deptSelect')) document.getElementById('deptPanel').classList.remove('show');
|
||||
if(!e.target.closest('#leaderSelect')) document.getElementById('leaderPanel').classList.remove('show');
|
||||
if(!e.target.closest('#orgTreeSelect')) document.getElementById('orgTreePanel').classList.remove('show');
|
||||
});
|
||||
|
||||
// 点击弹窗遮罩关闭
|
||||
|
||||
@@ -133,7 +133,6 @@
|
||||
<div class="sidebar-menu__title">健康排查</div>
|
||||
<a href="survey-manage.html" class="sidebar-item">问卷管理</a>
|
||||
<a href="activity-manage.html" class="sidebar-item active">活动管理</a>
|
||||
<a href="activity-stat.html" class="sidebar-item">活动统计</a>
|
||||
</aside>
|
||||
<main class="main">
|
||||
<!-- 筛选栏 -->
|
||||
@@ -193,17 +192,20 @@
|
||||
</div>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th style="width:18%;">活动名称</th>
|
||||
<th style="width:10%;">组织单位</th>
|
||||
<th style="width:10%;">组织部门</th>
|
||||
<th style="width:12%;">起止日期</th>
|
||||
<th style="width:10%;">人员筛选</th>
|
||||
<th style="width:8%;">活动状态</th>
|
||||
<th style="width:8%;">负责人</th>
|
||||
<th style="width:10%;">负责人电话</th>
|
||||
<th style="width:14%;">操作</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<th style="width:14%;">活动名称</th>
|
||||
<th style="width:8%;">组织单位</th>
|
||||
<th style="width:8%;">组织部门</th>
|
||||
<th style="width:10%;">起止日期</th>
|
||||
<th style="width:8%;">人员筛选</th>
|
||||
<th style="width:8%;">应参加人数</th>
|
||||
<th style="width:8%;">已参加人数</th>
|
||||
<th style="width:8%;">未参加人数</th>
|
||||
<th style="width:6%;">活动状态</th>
|
||||
<th style="width:6%;">负责人</th>
|
||||
<th style="width:8%;">负责人电话</th>
|
||||
<th style="width:8%;">操作</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="tbody"></tbody>
|
||||
</table>
|
||||
@@ -298,13 +300,13 @@ function toggleSubgroup(h){h.parentElement.classList.toggle('open');}
|
||||
/* ===== 数据 ===== */
|
||||
var statusMap = {'待开始':'tag-blue','进行中':'tag-orange','已完成':'tag-green'};
|
||||
|
||||
var activities = [
|
||||
{id:1, name:'2026年上半年员工健康排查', org:'能源集团', dept:'人力资源部', dateFrom:'2026-01-01', dateTo:'2026-03-31', personType:'全体人员', personCount:1280, status:'已完成', leader:'张明', phone:'13800001234', surveys:['健康记录问卷','职业健康排查问卷'], desc:'年度例行员工健康排查活动,覆盖全体员工。'},
|
||||
{id:2, name:'2026年Q2心理健康专项排查', org:'能源集团', dept:'安全环保部', dateFrom:'2026-04-01', dateTo:'2026-06-30', personType:'指定人员', personCount:356, status:'进行中', leader:'李华', phone:'13800005678', surveys:['心理健康评估问卷'], desc:'针对C类和D类人群的心理健康专项排查。'},
|
||||
{id:3, name:'2026年Q3职业健康排查', org:'能源集团', dept:'安全环保部', dateFrom:'2026-07-01', dateTo:'2026-09-30', personType:'指定人员', personCount:520, status:'待开始', leader:'王强', phone:'13800009012', surveys:['职业健康排查问卷','健康记录问卷'], desc:'第三季度职业健康专项排查,针对A类和B类人群。'},
|
||||
{id:4, name:'新员工入职健康基线调查', org:'能源集团', dept:'人力资源部', dateFrom:'2026-06-01', dateTo:'2026-12-31', personType:'指定人员', personCount:85, status:'进行中', leader:'赵芳', phone:'13800003456', surveys:['新员工健康基线问卷'], desc:'2026年度新入职员工健康基线数据采集。'},
|
||||
{id:5, name:'慢病患者季度随访', org:'能源集团', dept:'工会', dateFrom:'2026-04-01', dateTo:'2026-06-30', personType:'指定人员', personCount:128, status:'进行中', leader:'孙丽', phone:'13800007890', surveys:['慢病管理随访问卷'], desc:'E类慢病患者第二季度定期随访。'}
|
||||
];
|
||||
var activities = [
|
||||
{id:1, name:'2026年上半年员工健康排查', org:'能源集团', dept:'人力资源部', dateFrom:'2026-01-01', dateTo:'2026-03-31', personType:'全体人员', personCount:1280, doneCount:1150, status:'已完成', leader:'张明', phone:'13800001234', surveys:['健康记录问卷','职业健康排查问卷'], desc:'年度例行员工健康排查活动,覆盖全体员工。'},
|
||||
{id:2, name:'2026年Q2心理健康专项排查', org:'能源集团', dept:'安全环保部', dateFrom:'2026-04-01', dateTo:'2026-06-30', personType:'指定人员', personCount:356, doneCount:280, status:'进行中', leader:'李华', phone:'13800005678', surveys:['心理健康评估问卷'], desc:'针对C类和D类人群的心理健康专项排查。'},
|
||||
{id:3, name:'2026年Q3职业健康排查', org:'能源集团', dept:'安全环保部', dateFrom:'2026-07-01', dateTo:'2026-09-30', personType:'指定人员', personCount:520, doneCount:0, status:'待开始', leader:'王强', phone:'13800009012', surveys:['职业健康排查问卷','健康记录问卷'], desc:'第三季度职业健康专项排查,针对A类和B类人群。'},
|
||||
{id:4, name:'新员工入职健康基线调查', org:'能源集团', dept:'人力资源部', dateFrom:'2026-06-01', dateTo:'2026-12-31', personType:'指定人员', personCount:85, doneCount:60, status:'进行中', leader:'赵芳', phone:'13800003456', surveys:['新员工健康基线问卷'], desc:'2026年度新入职员工健康基线数据采集。'},
|
||||
{id:5, name:'慢病患者季度随访', org:'能源集团', dept:'工会', dateFrom:'2026-04-01', dateTo:'2026-06-30', personType:'指定人员', personCount:128, doneCount:98, status:'进行中', leader:'孙丽', phone:'13800007890', surveys:['慢病管理随访问卷'], desc:'E类慢病患者第二季度定期随访。'}
|
||||
];
|
||||
|
||||
/* 参与人员模拟数据 */
|
||||
var allPersons = [
|
||||
@@ -331,30 +333,34 @@ var allPersons = [
|
||||
];
|
||||
|
||||
/* ===== 渲染表格 ===== */
|
||||
function renderTable(data){
|
||||
var html = '';
|
||||
data.forEach(function(a){
|
||||
html += '<tr>';
|
||||
html += '<td>'+esc(a.name)+'</td>';
|
||||
html += '<td>'+esc(a.org)+'</td>';
|
||||
html += '<td>'+esc(a.dept)+'</td>';
|
||||
html += '<td>'+a.dateFrom+' ~ '+a.dateTo+'</td>';
|
||||
html += '<td><span class="link link-clickable" onclick="openPersonModal('+a.id+')">'+a.personCount+'人</span></td>';
|
||||
html += '<td><span class="tag '+statusMap[a.status]+'">'+a.status+'</span></td>';
|
||||
html += '<td>'+esc(a.leader)+'</td>';
|
||||
html += '<td>'+a.phone+'</td>';
|
||||
html += '<td>';
|
||||
html += '<button class="link" onclick="openDetail('+a.id+')">活动详情</button>';
|
||||
html += '<span class="link-separator">|</span>';
|
||||
html += '<button class="link" onclick="openEdit('+a.id+')">编辑</button>';
|
||||
html += '<span class="link-separator">|</span>';
|
||||
html += '<button class="link link-danger" onclick="deleteActivity('+a.id+')">删除</button>';
|
||||
html += '</td></tr>';
|
||||
});
|
||||
document.getElementById('tbody').innerHTML = html || '<tr><td colspan="9" style="text-align:center;padding:40px;color:var(--text-placeholder);">暂无数据</td></tr>';
|
||||
document.getElementById('totalCount').textContent = '共 '+data.length+' 条数据';
|
||||
document.getElementById('pageTotal').textContent = '共 '+data.length+' 条数据';
|
||||
}
|
||||
function renderTable(data){
|
||||
var html = '';
|
||||
data.forEach(function(a){
|
||||
var pending = a.personCount - (a.doneCount||0);
|
||||
html += '<tr>';
|
||||
html += '<td>'+esc(a.name)+'</td>';
|
||||
html += '<td>'+esc(a.org)+'</td>';
|
||||
html += '<td>'+esc(a.dept)+'</td>';
|
||||
html += '<td>'+a.dateFrom+' ~ '+a.dateTo+'</td>';
|
||||
html += '<td><span class="link link-clickable" onclick="openPersonModal('+a.id+')">'+esc(a.personType)+'</span></td>';
|
||||
html += '<td>'+a.personCount+'</td>';
|
||||
html += '<td style="color:var(--success);">'+(a.doneCount||0)+'</td>';
|
||||
html += '<td style="color:var(--danger);">'+pending+'</td>';
|
||||
html += '<td><span class="tag '+statusMap[a.status]+'">'+a.status+'</span></td>';
|
||||
html += '<td>'+esc(a.leader)+'</td>';
|
||||
html += '<td>'+a.phone+'</td>';
|
||||
html += '<td>';
|
||||
html += '<button class="link" onclick="openDetail('+a.id+')">活动详情</button>';
|
||||
html += '<span class="link-separator">|</span>';
|
||||
html += '<button class="link" onclick="openEdit('+a.id+')">编辑</button>';
|
||||
html += '<span class="link-separator">|</span>';
|
||||
html += '<button class="link link-danger" onclick="deleteActivity('+a.id+')">删除</button>';
|
||||
html += '</td></tr>';
|
||||
});
|
||||
document.getElementById('tbody').innerHTML = html || '<tr><td colspan="12" style="text-align:center;padding:40px;color:var(--text-placeholder);">暂无数据</td></tr>';
|
||||
document.getElementById('totalCount').textContent = '共 '+data.length+' 条数据';
|
||||
document.getElementById('pageTotal').textContent = '共 '+data.length+' 条数据';
|
||||
}
|
||||
|
||||
/* ===== 筛选 ===== */
|
||||
function filterTable(){
|
||||
|
||||
@@ -1,317 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="zh-CN">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>健康监测 - 活动统计 | 健康CQ原型</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);}
|
||||
/* 筛选栏 */
|
||||
.filter-bar{display:flex;align-items:center;gap:16px;margin-bottom:16px;flex-wrap:wrap;background:#fff;padding:16px 24px;border-radius:var(--radius-md);box-shadow:var(--shadow-sm);}
|
||||
.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);outline:none;min-width:180px;}
|
||||
.filter-input:focus{border-color:var(--primary);}
|
||||
/* 多选下拉 */
|
||||
.multi-select{position:relative;display:inline-block;min-width:200px;}
|
||||
.multi-select__trigger{min-height:36px;border:1px solid var(--border);border-radius:var(--radius-sm);padding:4px 32px 4px 8px;font-size:var(--font-sm);background:#fff;cursor:pointer;display:flex;align-items:center;gap:4px;flex-wrap:wrap;user-select:none;position:relative;}
|
||||
.multi-select__trigger::after{content:'';position:absolute;right:12px;top:50%;transform:translateY(-50%);border:4px solid transparent;border-top:5px solid #999;pointer-events:none;}
|
||||
.multi-select__trigger.placeholder{padding:0 32px 0 12px;color:var(--text-placeholder);align-items:center;}
|
||||
.multi-select__trigger .sel-tag{display:inline-flex;align-items:center;gap:2px;background:var(--primary-light);color:var(--primary);padding:1px 6px;border-radius:var(--radius-sm);font-size:var(--font-xs);line-height:1.6;}
|
||||
.multi-select__trigger .sel-tag .tag-x{cursor:pointer;font-size:12px;line-height:1;margin-left:2px;}
|
||||
.multi-select__trigger .sel-tag .tag-x:hover{color:var(--danger);}
|
||||
.multi-select__panel{position:absolute;top:100%;left:0;margin-top:4px;background:#fff;border:1px solid var(--border);border-radius:var(--radius-md);box-shadow:0 4px 12px rgba(0,0,0,0.12);z-index:300;display:none;min-width:200px;padding:8px 0;}
|
||||
.multi-select__panel.show{display:block;}
|
||||
.multi-select__opt{display:flex;align-items:center;gap:8px;padding:8px 16px;font-size:var(--font-sm);cursor:pointer;transition:background .1s;}
|
||||
.multi-select__opt:hover{background:#F5F7FA;}
|
||||
.multi-select__opt.checked{color:var(--primary);background:var(--primary-light);}
|
||||
.multi-select__cb{width:14px;height:14px;border:1px solid var(--border);border-radius:3px;display:flex;align-items:center;justify-content:center;flex-shrink:0;transition:all .15s;}
|
||||
.multi-select__cb.checked{background:var(--primary);border-color:var(--primary);}
|
||||
.multi-select__cb.checked::after{content:'';width:4px;height:8px;border:solid #fff;border-width:0 1.5px 1.5px 0;transform:rotate(45deg);margin-top:-2px;}
|
||||
/* 工具栏 */
|
||||
.toolbar{display:flex;align-items:center;gap:12px;margin-bottom:16px;flex-wrap:wrap;}
|
||||
.toolbar .spacer{flex:1;}
|
||||
.btn{height:36px;padding:0 16px;border-radius:var(--radius-sm);font-size:var(--font-sm);cursor:pointer;border:1px solid var(--border);background:#fff;color:var(--text-primary);transition:all .15s;display:inline-flex;align-items:center;gap:6px;}
|
||||
.btn:hover{color:var(--primary);border-color:var(--primary);}
|
||||
.btn-primary{background:var(--primary);color:#fff;border-color:var(--primary);}
|
||||
.btn-primary:hover{background:#40a9ff;border-color:#40a9ff;color:#fff;}
|
||||
/* 表格 */
|
||||
.table-card{background:#fff;border-radius:var(--radius-md);box-shadow:var(--shadow-sm);overflow:hidden;}
|
||||
.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{width:100%;border-collapse:collapse;}
|
||||
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);}
|
||||
tbody td{padding:14px 16px;font-size:var(--font-sm);color:var(--text-primary);border-bottom:1px solid var(--border);}
|
||||
tbody tr:last-child td{border-bottom:none;}
|
||||
tbody tr:hover{background:#F8FBFF;}
|
||||
.tag{display:inline-flex;align-items:center;padding:2px 8px;border-radius:10px;font-size:var(--font-xs);}
|
||||
.tag-blue{background:var(--primary-light);color:var(--primary);}
|
||||
.tag-green{background:#F6FFED;color:var(--success);}
|
||||
.tag-orange{background:#FFF7E6;color:#FA8C16;}
|
||||
.link{color:var(--primary);cursor:pointer;font-size:var(--font-sm);text-decoration:none;background:none;border:none;}
|
||||
.link:hover{color:#40a9ff;}
|
||||
.link-separator{color:var(--border);margin:0 6px;user-select:none;}
|
||||
/* 分页 */
|
||||
.pagination{display:flex;align-items:center;justify-content:flex-end;gap:16px;padding:16px 24px;font-size:var(--font-sm);color:var(--text-secondary);}
|
||||
.pagination__pages{display:flex;align-items:center;gap:4px;}
|
||||
.page-item{width:32px;height:32px;display:flex;align-items:center;justify-content:center;border-radius:var(--radius-sm);cursor:pointer;transition:all .15s;}
|
||||
.page-item:hover{color:var(--primary);}
|
||||
.page-item.active{background:var(--primary);color:#fff;}
|
||||
</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="../crowd-status-employee.html">健康现状</a>
|
||||
<a href="survey-manage.html" class="active">健康排查</a>
|
||||
<a href="../wearable/tool-manage.html">穿戴监测</a>
|
||||
<a href="../environment/indoor-device-list.html">健康环境</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>
|
||||
<a href="survey-manage.html" class="sidebar-item">问卷管理</a>
|
||||
<a href="activity-manage.html" class="sidebar-item">活动管理</a>
|
||||
<a href="activity-stat.html" class="sidebar-item active">活动统计</a>
|
||||
</aside>
|
||||
<main class="main">
|
||||
<!-- 筛选栏 -->
|
||||
<div class="filter-bar">
|
||||
<div class="filter-item">
|
||||
<span class="filter-item__label">活动名称</span>
|
||||
<input class="filter-input" id="filterName" placeholder="请输入活动名称">
|
||||
</div>
|
||||
<div class="filter-item">
|
||||
<span class="filter-item__label">组织单位</span>
|
||||
<div class="multi-select" id="orgSelect">
|
||||
<div class="multi-select__trigger placeholder" onclick="toggleOrgSelect()">全部</div>
|
||||
<div class="multi-select__panel" id="orgPanel">
|
||||
<div class="multi-select__opt" data-val="全部" onclick="toggleOrgOpt(this,'全部')"><span class="multi-select__cb"></span>全部</div>
|
||||
<div class="multi-select__opt" data-val="能源集团" onclick="toggleOrgOpt(this,'能源集团')"><span class="multi-select__cb"></span>能源集团</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<button class="btn btn-primary" onclick="filterTable()">
|
||||
<svg width="14" height="14" viewBox="0 0 14 14" fill="none"><circle cx="6" cy="6" r="4.5" stroke="currentColor" stroke-width="1.5"/><path d="M10.5 10.5l2 2" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/></svg>
|
||||
查询
|
||||
</button>
|
||||
<button class="btn" onclick="resetFilter()">重置</button>
|
||||
</div>
|
||||
<!-- 操作栏 -->
|
||||
<div class="toolbar">
|
||||
<button class="btn" onclick="alert('导出列表数据')">
|
||||
<svg width="14" height="14" viewBox="0 0 14 14" fill="none"><path d="M7 1v8M4 6l3 3 3-3M2 11h10" stroke="currentColor" stroke-width="1.3" stroke-linecap="round" stroke-linejoin="round"/></svg>
|
||||
导出列表数据
|
||||
</button>
|
||||
<button class="btn" onclick="alert('查看导出任务')">
|
||||
<svg width="14" height="14" viewBox="0 0 14 14" fill="none"><circle cx="7" cy="7" r="5.5" stroke="currentColor" stroke-width="1.3"/><path d="M7 4v3.5l2.5 1.5" stroke="currentColor" stroke-width="1.3" stroke-linecap="round"/></svg>
|
||||
查看导出任务
|
||||
</button>
|
||||
</div>
|
||||
<!-- 表格 -->
|
||||
<div class="table-card">
|
||||
<div class="table-card__header">
|
||||
<span class="table-card__title">活动统计</span>
|
||||
<span style="font-size:var(--font-sm);color:var(--text-secondary);" id="totalCount">共 0 条数据</span>
|
||||
</div>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th style="width:18%;">活动名称</th>
|
||||
<th style="width:10%;">组织单位</th>
|
||||
<th style="width:10%;">组织部门</th>
|
||||
<th style="width:12%;">起止日期</th>
|
||||
<th style="width:8%;">应参加人数</th>
|
||||
<th style="width:8%;">已参加人数</th>
|
||||
<th style="width:8%;">未参加人数</th>
|
||||
<th style="width:8%;">活动状态</th>
|
||||
<th style="width:18%;">操作</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="tbody"></tbody>
|
||||
</table>
|
||||
<!-- 分页 -->
|
||||
<div class="pagination">
|
||||
<span class="pagination__total" id="pageTotal"></span>
|
||||
<div class="pagination__pages">
|
||||
<span class="page-item active">1</span>
|
||||
</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');})();
|
||||
|
||||
/* ===== 数据 ===== */
|
||||
var statusMap = {'待开始':'tag-blue','进行中':'tag-orange','已完成':'tag-green'};
|
||||
|
||||
var activities = [
|
||||
{id:1, name:'2026年上半年员工健康排查', org:'能源集团', dept:'人力资源部', dateFrom:'2026-01-01', dateTo:'2026-03-31', personCount:1280, doneCount:1150, status:'已完成', leader:'张明', surveys:['健康记录问卷','职业健康排查问卷'], desc:'年度例行员工健康排查活动,覆盖全体员工。'},
|
||||
{id:2, name:'2026年Q2心理健康专项排查', org:'能源集团', dept:'安全环保部', dateFrom:'2026-04-01', dateTo:'2026-06-30', personCount:356, doneCount:280, status:'进行中', leader:'李华', surveys:['心理健康评估问卷'], desc:'针对C类和D类人群的心理健康专项排查。'},
|
||||
{id:3, name:'2026年Q3职业健康排查', org:'能源集团', dept:'安全环保部', dateFrom:'2026-07-01', dateTo:'2026-09-30', personCount:520, doneCount:0, status:'待开始', leader:'王强', surveys:['职业健康排查问卷','健康记录问卷'], desc:'第三季度职业健康专项排查,针对A类和B类人群。'},
|
||||
{id:4, name:'新员工入职健康基线调查', org:'能源集团', dept:'人力资源部', dateFrom:'2026-06-01', dateTo:'2026-12-31', personCount:85, doneCount:60, status:'进行中', leader:'赵芳', surveys:['新员工健康基线问卷'], desc:'2026年度新入职员工健康基线数据采集。'},
|
||||
{id:5, name:'慢病患者季度随访', org:'能源集团', dept:'工会', dateFrom:'2026-04-01', dateTo:'2026-06-30', personCount:128, doneCount:98, status:'进行中', leader:'孙丽', surveys:['慢病管理随访问卷'], desc:'E类慢病患者第二季度定期随访。'}
|
||||
];
|
||||
|
||||
/* 组织单位多选 */
|
||||
var filterOrgs = [];
|
||||
|
||||
function toggleOrgSelect(){
|
||||
var panel = document.getElementById('orgPanel');
|
||||
var isShow = panel.classList.contains('show');
|
||||
closeAllPanels();
|
||||
if(!isShow) panel.classList.add('show');
|
||||
}
|
||||
|
||||
function toggleOrgOpt(el, val){
|
||||
var cb = el.querySelector('.multi-select__cb');
|
||||
if(val === '全部'){
|
||||
filterOrgs = [];
|
||||
document.querySelectorAll('#orgPanel .multi-select__opt').forEach(function(opt){
|
||||
opt.classList.remove('checked');opt.querySelector('.multi-select__cb').classList.remove('checked');
|
||||
});
|
||||
el.classList.add('checked');cb.classList.add('checked');
|
||||
} else {
|
||||
document.querySelector('#orgPanel .multi-select__opt[data-val="全部"]').classList.remove('checked');
|
||||
document.querySelector('#orgPanel .multi-select__opt[data-val="全部"]').querySelector('.multi-select__cb').classList.remove('checked');
|
||||
if(cb.classList.contains('checked')){
|
||||
el.classList.remove('checked');cb.classList.remove('checked');
|
||||
filterOrgs = filterOrgs.filter(function(c){return c!==val;});
|
||||
} else {
|
||||
el.classList.add('checked');cb.classList.add('checked');
|
||||
filterOrgs.push(val);
|
||||
}
|
||||
}
|
||||
updateOrgTrigger();
|
||||
}
|
||||
|
||||
function updateOrgTrigger(){
|
||||
var trigger = document.querySelector('#orgSelect .multi-select__trigger');
|
||||
if(filterOrgs.length===0){
|
||||
trigger.textContent = '全部';
|
||||
trigger.className = 'multi-select__trigger placeholder';
|
||||
} else {
|
||||
trigger.className = 'multi-select__trigger';
|
||||
var html = '';
|
||||
filterOrgs.forEach(function(c){
|
||||
html += '<span class="sel-tag">'+esc(c)+'<span class="tag-x" onclick="removeOrgTag(\''+c+'\')">×</span></span>';
|
||||
});
|
||||
trigger.innerHTML = html;
|
||||
}
|
||||
}
|
||||
|
||||
function removeOrgTag(val){
|
||||
filterOrgs = filterOrgs.filter(function(c){return c!==val;});
|
||||
var opt = document.querySelector('#orgPanel .multi-select__opt[data-val="'+val+'"]');
|
||||
opt.classList.remove('checked');opt.querySelector('.multi-select__cb').classList.remove('checked');
|
||||
updateOrgTrigger();
|
||||
}
|
||||
|
||||
function closeAllPanels(){
|
||||
document.querySelectorAll('.multi-select__panel').forEach(function(p){p.classList.remove('show');});
|
||||
}
|
||||
|
||||
/* ===== 渲染表格 ===== */
|
||||
function renderTable(data){
|
||||
var html = '';
|
||||
data.forEach(function(a){
|
||||
var pending = a.personCount - a.doneCount;
|
||||
html += '<tr>';
|
||||
html += '<td>'+esc(a.name)+'</td>';
|
||||
html += '<td>'+esc(a.org)+'</td>';
|
||||
html += '<td>'+esc(a.dept)+'</td>';
|
||||
html += '<td>'+a.dateFrom+' ~ '+a.dateTo+'</td>';
|
||||
html += '<td>'+a.personCount+'</td>';
|
||||
html += '<td style="color:var(--success);">'+a.doneCount+'</td>';
|
||||
html += '<td style="color:var(--danger);">'+pending+'</td>';
|
||||
html += '<td><span class="tag '+statusMap[a.status]+'">'+a.status+'</span></td>';
|
||||
html += '<td>';
|
||||
html += '<button class="link" onclick="window.location.href=\'activity-detail.html?id='+a.id+'\'">活动详情</button>';
|
||||
html += '</td></tr>';
|
||||
});
|
||||
document.getElementById('tbody').innerHTML = html || '<tr><td colspan="9" style="text-align:center;padding:40px;color:var(--text-placeholder);">暂无数据</td></tr>';
|
||||
document.getElementById('totalCount').textContent = '共 '+data.length+' 条数据';
|
||||
document.getElementById('pageTotal').textContent = '共 '+data.length+' 条数据';
|
||||
}
|
||||
|
||||
/* ===== 筛选 ===== */
|
||||
function filterTable(){
|
||||
var name = document.getElementById('filterName').value.trim().toLowerCase();
|
||||
var filtered = activities.filter(function(a){
|
||||
if(name && a.name.toLowerCase().indexOf(name) === -1) return false;
|
||||
if(filterOrgs.length > 0 && filterOrgs.indexOf(a.org) === -1) return false;
|
||||
return true;
|
||||
});
|
||||
renderTable(filtered);
|
||||
}
|
||||
|
||||
function resetFilter(){
|
||||
document.getElementById('filterName').value = '';
|
||||
filterOrgs = [];
|
||||
document.querySelectorAll('#orgPanel .multi-select__opt').forEach(function(opt){
|
||||
opt.classList.remove('checked');opt.querySelector('.multi-select__cb').classList.remove('checked');
|
||||
});
|
||||
var allOpt = document.querySelector('#orgPanel .multi-select__opt[data-val="全部"]');
|
||||
allOpt.classList.add('checked');allOpt.querySelector('.multi-select__cb').classList.add('checked');
|
||||
updateOrgTrigger();
|
||||
renderTable(activities);
|
||||
}
|
||||
|
||||
function esc(s){return (s||'').replace(/&/g,'&').replace(/"/g,'"').replace(/</g,'<').replace(/>/g,'>');}
|
||||
|
||||
/* ===== 初始化 ===== */
|
||||
renderTable(activities);
|
||||
|
||||
document.addEventListener('click',function(e){
|
||||
if(!e.target.closest('.multi-select')) closeAllPanels();
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -251,7 +251,6 @@
|
||||
<div class="sidebar-menu__title">健康排查</div>
|
||||
<a href="survey-manage.html" class="sidebar-item">问卷管理</a>
|
||||
<a href="activity-manage.html" class="sidebar-item">活动管理</a>
|
||||
<a href="activity-stat.html" class="sidebar-item">活动统计</a>
|
||||
</aside>
|
||||
<main class="main">
|
||||
<div class="editor-layout">
|
||||
|
||||
@@ -161,7 +161,6 @@
|
||||
<div class="sidebar-menu__title">健康排查</div>
|
||||
<a href="survey-manage.html" class="sidebar-item active">问卷管理</a>
|
||||
<a href="activity-manage.html" class="sidebar-item">活动管理</a>
|
||||
<a href="activity-stat.html" class="sidebar-item">活动统计</a>
|
||||
</aside>
|
||||
<main class="main">
|
||||
<!-- 筛选栏 -->
|
||||
|
||||
@@ -318,6 +318,9 @@
|
||||
<button class="btn btn-default" onclick="openImportModal()">
|
||||
批量入库导入
|
||||
</button>
|
||||
<button class="btn btn-default" onclick="void(0)">
|
||||
批量绑定导入
|
||||
</button>
|
||||
<button class="btn btn-default" onclick="void(0)">
|
||||
查看导入任务
|
||||
</button>
|
||||
@@ -570,7 +573,7 @@
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>绑定日期 <span style="color:var(--danger)">*</span></label>
|
||||
<input class="form-control" type="date" value="2026-05-11" id="bindDate">
|
||||
<input class="form-control" type="datetime-local" id="bindDate">
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal__footer">
|
||||
@@ -646,6 +649,17 @@
|
||||
下载导入模板
|
||||
</button>
|
||||
</div>
|
||||
<div class="form-group" style="margin-bottom:16px;">
|
||||
<label>所属单位 <span style="color:var(--danger)">*</span></label>
|
||||
<select class="form-control filter-select" style="width:100%;">
|
||||
<option value="">请选择所属单位</option>
|
||||
<option value="采油一厂">采油一厂</option>
|
||||
<option value="采油二厂">采油二厂</option>
|
||||
<option value="采气一厂">采气一厂</option>
|
||||
<option value="采气二厂">采气二厂</option>
|
||||
<option value="天然气处理厂">天然气处理厂</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="upload-area">
|
||||
<svg width="48" height="48" viewBox="0 0 48 48" fill="none"><rect x="4" y="4" width="40" height="40" rx="6" stroke="#999" stroke-width="2"/><path d="M24 14v20M16 22l8-8 8 8" stroke="#999" stroke-width="2" stroke-linecap="round"/></svg>
|
||||
<p>点击或拖拽文件到此区域上传</p>
|
||||
@@ -693,10 +707,6 @@
|
||||
<div style="background:#F0F7FF;border:1px solid #BAE0FF;border-radius:var(--radius-md);padding:10px 16px;flex-shrink:0;">
|
||||
<span style="font-size:var(--font-sm);color:#0958D9;">设备编码:<strong id="msDeviceCode">WD-2024-001</strong></span>
|
||||
</div>
|
||||
<button class="btn btn-default btn-sm" onclick="showAddTypeForm()">
|
||||
<svg width="12" height="12" viewBox="0 0 12 12" fill="none"><path d="M6 1v10M1 6h10" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/></svg>
|
||||
新增类型配置
|
||||
</button>
|
||||
</div>
|
||||
<div class="monitor-setting-list" id="monitorSettingList">
|
||||
<!-- 心率 -->
|
||||
@@ -877,6 +887,10 @@ function openBindModal(code, name) {
|
||||
document.getElementById('bindEmpSearch').value = '';
|
||||
document.getElementById('empDropdown').classList.remove('show');
|
||||
document.getElementById('empCard').style.display = 'none';
|
||||
// 绑定日期默认当前时间
|
||||
var now = new Date();
|
||||
var pad = function(n){ return n < 10 ? '0' + n : n; };
|
||||
document.getElementById('bindDate').value = now.getFullYear() + '-' + pad(now.getMonth()+1) + '-' + pad(now.getDate()) + 'T' + pad(now.getHours()) + ':' + pad(now.getMinutes());
|
||||
document.getElementById('bindModal').classList.add('show');
|
||||
}
|
||||
var selectedEmp = null;
|
||||
|
||||
@@ -632,6 +632,65 @@
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<!-- 血压面板(独立:双线图 + 收缩压/舒张压分开) -->
|
||||
<div class="tab-panel" id="panel-bp" style="display:none;">
|
||||
<div class="metric-toolbar">
|
||||
<div class="metric-toolbar__left">
|
||||
<div class="time-granularity">
|
||||
<button class="time-btn active" onclick="switchGranularityBp(this)">日</button>
|
||||
<button class="time-btn" onclick="switchGranularityBp(this)">周</button>
|
||||
<button class="time-btn" onclick="switchGranularityBp(this)">月</button>
|
||||
<button class="time-btn" onclick="switchGranularityBp(this)">年</button>
|
||||
</div>
|
||||
</div>
|
||||
<button class="btn btn-default" id="btnToggleBpList" onclick="toggleBpView()">
|
||||
<svg width="14" height="14" viewBox="0 0 14 14" fill="none"><path d="M2 3h10M2 7h10M2 11h10" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/></svg>
|
||||
列表展示
|
||||
</button>
|
||||
</div>
|
||||
<!-- 趋势图视图 -->
|
||||
<div id="bp-chart-view">
|
||||
<div class="date-nav">
|
||||
<button class="date-nav__btn" onclick="void(0)">‹</button>
|
||||
<span class="date-nav__text">2026-05-12</span>
|
||||
<button class="date-nav__btn" onclick="void(0)">›</button>
|
||||
</div>
|
||||
<div class="metric-summary" id="bpSummary">
|
||||
<div class="metric-summary__item"><span class="metric-summary__value" style="color:#EB2F96;">135</span><span class="metric-summary__unit">mmHg</span><span class="metric-summary__label">收缩压最高</span></div>
|
||||
<div class="metric-summary__item"><span class="metric-summary__value" style="color:#EB2F96;">112</span><span class="metric-summary__unit">mmHg</span><span class="metric-summary__label">收缩压最低</span></div>
|
||||
<div class="metric-summary__item"><span class="metric-summary__value" style="color:#1890FF;">88</span><span class="metric-summary__unit">mmHg</span><span class="metric-summary__label">舒张压最高</span></div>
|
||||
<div class="metric-summary__item"><span class="metric-summary__value" style="color:#1890FF;">72</span><span class="metric-summary__unit">mmHg</span><span class="metric-summary__label">舒张压最低</span></div>
|
||||
</div>
|
||||
<div class="chart-area" id="bpTrendChart"></div>
|
||||
</div>
|
||||
<!-- 列表视图 -->
|
||||
<div id="bp-table-view" style="display:none;">
|
||||
<div style="display:flex;gap:16px;margin-bottom:16px;align-items:center;">
|
||||
<div class="filter-item">
|
||||
<label style="font-size:var(--font-sm);color:var(--text-secondary);">日期</label>
|
||||
<input type="date" value="2026-05-12" style="height:36px;border:1px solid var(--border);border-radius:var(--radius-sm);padding:0 12px;font-size:var(--font-sm);outline:none;">
|
||||
</div>
|
||||
<button class="btn btn-default">导出</button>
|
||||
</div>
|
||||
<table class="data-history-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>上报时间</th>
|
||||
<th>收缩压 (mmHg)</th>
|
||||
<th>舒张压 (mmHg)</th>
|
||||
<th>状态</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="bpTableBody">
|
||||
<tr><td>14:32:05</td><td>120</td><td>78</td><td><span class="tag tag-green">正常</span></td></tr>
|
||||
<tr><td>14:02:05</td><td>124</td><td>80</td><td><span class="tag tag-green">正常</span></td></tr>
|
||||
<tr><td>13:32:05</td><td>118</td><td>75</td><td><span class="tag tag-green">正常</span></td></tr>
|
||||
<tr><td>13:02:05</td><td>131</td><td>85</td><td><span class="tag tag-green">正常</span></td></tr>
|
||||
<tr><td>12:32:05</td><td>142</td><td>92</td><td><span class="tag tag-red">异常</span></td></tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -675,12 +734,20 @@ function switchMainTab(el, tab) {
|
||||
document.getElementById('panel-metric').style.display = 'none';
|
||||
document.getElementById('panel-exercise').style.display = 'none';
|
||||
document.getElementById('panel-ecg').style.display = 'none';
|
||||
document.getElementById('panel-bp').style.display = 'none';
|
||||
if (tab === 'overview') {
|
||||
document.getElementById('panel-overview').style.display = '';
|
||||
} else if (tab === 'exercise') {
|
||||
document.getElementById('panel-exercise').style.display = '';
|
||||
} else if (tab === 'ecg') {
|
||||
document.getElementById('panel-ecg').style.display = '';
|
||||
} else if (tab === 'bp') {
|
||||
document.getElementById('panel-bp').style.display = '';
|
||||
bpListView = false;
|
||||
document.getElementById('btnToggleBpList').innerHTML = '<svg width="14" height="14" viewBox="0 0 14 14" fill="none"><path d="M2 3h10M2 7h10M2 11h10" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/></svg> 列表展示';
|
||||
document.getElementById('bp-chart-view').style.display = '';
|
||||
document.getElementById('bp-table-view').style.display = 'none';
|
||||
renderBpTrendChart();
|
||||
} else {
|
||||
document.getElementById('panel-metric').style.display = '';
|
||||
isListView = false;
|
||||
@@ -760,8 +827,71 @@ function renderTrendChart() {
|
||||
+ '<polyline points="'+pts+'" fill="none" stroke="#1890FF" stroke-width="2"/>'
|
||||
+ xLabels
|
||||
+ '</svg>';
|
||||
}
|
||||
function openEcgDetail(time, result, value) {
|
||||
}
|
||||
/* ===== 血压面板专用 ===== */
|
||||
var bpListView = false;
|
||||
function toggleBpView() {
|
||||
bpListView = !bpListView;
|
||||
var btn = document.getElementById('btnToggleBpList');
|
||||
if (bpListView) {
|
||||
document.getElementById('bp-chart-view').style.display = 'none';
|
||||
document.getElementById('bp-table-view').style.display = '';
|
||||
btn.innerHTML = '<svg width="14" height="14" viewBox="0 0 14 14" fill="none"><path d="M3 3h8v8H3z" stroke="currentColor" stroke-width="1.5" fill="none"/><path d="M3 7h8" stroke="currentColor" stroke-width="1"/></svg> 趋势图展示';
|
||||
} else {
|
||||
document.getElementById('bp-chart-view').style.display = '';
|
||||
document.getElementById('bp-table-view').style.display = 'none';
|
||||
btn.innerHTML = '<svg width="14" height="14" viewBox="0 0 14 14" fill="none"><path d="M2 3h10M2 7h10M2 11h10" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/></svg> 列表展示';
|
||||
renderBpTrendChart();
|
||||
}
|
||||
}
|
||||
function switchGranularityBp(el) {
|
||||
document.querySelectorAll('#panel-bp .time-granularity .time-btn').forEach(function(b){ b.classList.remove('active'); });
|
||||
el.classList.add('active');
|
||||
renderBpTrendChart();
|
||||
}
|
||||
function renderBpTrendChart() {
|
||||
var c = document.getElementById('bpTrendChart');
|
||||
if (!c) return;
|
||||
var W = c.offsetWidth || 880, H = 280;
|
||||
var pad = {t:20,r:20,b:40,l:50};
|
||||
var cw = W - pad.l - pad.r, ch = H - pad.t - pad.b;
|
||||
// 24小时数据点
|
||||
var n = 25;
|
||||
// 收缩压数据 (systolic)
|
||||
var sysData = [118,116,114,112,115,118,120,122,125,128,130,128,124,122,120,124,128,132,135,130,126,122,120,118,116];
|
||||
// 舒张压数据 (diastolic)
|
||||
var diaData = [75,74,72,73,74,76,78,78,80,82,84,82,80,78,76,78,80,84,86,82,80,78,76,74,72];
|
||||
var minV = 60, maxV = 150;
|
||||
function px(i){ return pad.l + i/(n-1)*cw; }
|
||||
function py(v){ return pad.t + ch - (v-minV)/(maxV-minV)*ch; }
|
||||
// 网格线
|
||||
var yLines = [60,80,100,120,140];
|
||||
var gridLines = yLines.map(function(v){
|
||||
return '<line x1="'+pad.l+'" y1="'+py(v)+'" x2="'+(pad.l+cw)+'" y2="'+py(v)+'" stroke="#f0f0f0" stroke-width="1"/>'
|
||||
+ '<text x="'+(pad.l-8)+'" y="'+(py(v)+4)+'" text-anchor="end" font-size="11" fill="#999">'+v+'</text>';
|
||||
}).join('');
|
||||
// X轴标签
|
||||
var xTicks = [0,4,8,12,16,20,24];
|
||||
var xLabels = xTicks.map(function(h){
|
||||
var label = (h<10?'0':'')+h+':00';
|
||||
return '<text x="'+px(h)+'" y="'+(H-10)+'" text-anchor="middle" font-size="10" fill="#aaa">'+label+'</text>';
|
||||
}).join('');
|
||||
// 收缩压折线
|
||||
var sysPts = sysData.map(function(v,i){ return px(i)+','+py(v); }).join(' ');
|
||||
// 舒张压折线
|
||||
var diaPts = diaData.map(function(v,i){ return px(i)+','+py(v); }).join(' ');
|
||||
c.innerHTML = '<svg width="'+W+'" height="'+H+'" viewBox="0 0 '+W+' '+H+'">'
|
||||
+ gridLines + xLabels
|
||||
// 舒张压(蓝色)
|
||||
+ '<polyline points="'+diaPts+'" fill="none" stroke="#1890FF" stroke-width="2" stroke-dasharray="6,3"/>'
|
||||
// 收缩压(粉色)
|
||||
+ '<polyline points="'+sysPts+'" fill="none" stroke="#EB2F96" stroke-width="2"/>'
|
||||
// 图例
|
||||
+ '<circle cx="'+(W-130)+'" cy="22" r="4" fill="#EB2F96"/><text x="'+(W-120)+'" y="26" font-size="11" fill="#666">收缩压</text>'
|
||||
+ '<circle cx="'+(W-60)+'" cy="22" r="4" fill="#1890FF"/><text x="'+(W-50)+'" y="26" font-size="11" fill="#666">舒张压</text>'
|
||||
+ '</svg>';
|
||||
}
|
||||
function openEcgDetail(time, result, value) {
|
||||
document.getElementById('ecgTime').textContent = time;
|
||||
document.getElementById('ecgResult').textContent = result;
|
||||
document.getElementById('ecgValue').textContent = value;
|
||||
|
||||