feat: 管理员端个人中心模块补全,新增我的页面及子页面

- 新增 profile/index.html 个人中心主页(蓝色渐变头部 + 菜单卡片 + 退出登录弹窗 + Tab栏)
- 新增 profile/edit-profile.html 修改个人信息(头像更换 ActionSheet + 姓名编辑 + Toast反馈)
- 新增 profile/change-pwd.html 修改密码(三字段表单 + 成功弹窗)
- 页面交互参考驻场人员端 onsite/profile/,适配管理员身份
- index.html SITE_MAP admin「我的」模块补全 3 页面条目
- ai-assistant/message 共享页面 roleBaseMap 新增 admin 角色路由
- 管理员端 CHANGELOG 初始化

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
liuyunqin
2026-06-23 11:10:08 +08:00
co-authored by Claude Opus 4.8
parent 7d7488737b
commit 04b34c106e
27 changed files with 4523 additions and 63 deletions
+1 -1
View File
@@ -1,4 +1,4 @@
_Last synced: 2026-06-18 | Base commit: `14a80cb`_
_Last synced: 2026-06-18 | Base commit: `06587d2`_
# 记忆索引
+34 -18
View File
@@ -3,32 +3,54 @@ name: 记忆健康检查报告
description: memory-lint 最新一次执行的检查结果与待处理项
type: lint
last_updated: 2026-06-18
commit: 14a80cb
---
# 记忆健康检查报告
> _执行时间: 2026-06-18 | Base commit: `14a80cb` | Last synced: 2026-06-18_
> _执行时间: 2026-06-18 | Base commit: `06587d2` | Last synced: 2026-06-18_
## 健康概览
| 检查项 | 状态 | AUTO-FIX | NEED-HUMAN |
|--------|------|----------|------------|
| 孤儿检测 | ✅ | | — |
| 幽灵检测 | ✅ | | — |
| 引用存在性检测(3A) | ✅ | | |
| 双链对称性检测(3B) | ✅ | | |
| 内容矛盾检测 | ✅ | — | |
| 孤儿检测 | ✅ | 0 | — |
| 幽灵检测 | ✅ | 0 | — |
| 引用存在性检测(3A) | ✅ | 0 | 0 |
| 双链对称性检测(3B) | ✅ | 0 | 0 |
| 内容矛盾检测 | ✅ | — | 0 |
| 过期检测 | ⚠ | — | 1 待处理 |
| 可推断内容污染 | ✅ | — | |
| 可推断内容污染 | ✅ | — | 0 |
**AUTO-FIX 已执行 0 项 | NEED-HUMAN 待处理 1 项**
---
## 摘要
## 检查详情
(无)
### 孤儿检测
- 索引文件(5 个):project_overview.md, project_progress.md, decisions.md, feedback.md, user_profile.md
- 磁盘文件(7 个,排除 MEMORY.md/ lint_report.md):与索引一致
- 结果:无孤儿引用
### 幽灵检测
- 磁盘上所有记忆文件均已在 MEMORY.md 索引中注册
- 结果:无幽灵文件
### 交叉引用完整性
- `feedback.md``[[decisions.md#餐厅终端设备 PAD 居中外壳设计模式]]` ✅ 目标存在
- `decisions.md``[[feedback.md#PAD 终端页面内禁止可见滚动条]]` ✅ 目标存在
- 两个引用形成双向对称链接 ✅
### 内容矛盾检测
- 未发现 decisions vs feedback / 架构文件之间的内容矛盾
- 未发现 synthesis vs decisions 之间的抵触
### 过期检测
- user_profile.md (last_updated: 2026-04-21) — 距今 58 天,在 90 天 ERROR 阈值内但在 30 天 WARN 阈值外
### 可推断内容污染
- project_progress.md 列出具体 HTML 文件名为模块进度记录所需,非代码污染
- 未发现方法签名、SQL 语句、依赖版本号等可推断代码细节
---
@@ -36,11 +58,5 @@ commit: 14a80cb
### [WARN] 过期记忆
- **文件**`user_profile.md`last_updated: 2026-04-21已过期 58 天)
- **建议**:核对用户角色与偏好是否仍准确;本次会话未涉及用户画像变化,可在下次会话有相关线索时更新
---
## 本次执行新增的双链
- `decisions.md#餐厅终端设备 PAD 居中外壳设计模式``feedback.md#PAD 终端页面内禁止可见滚动条`(已闭环)
- **文件**`user_profile.md`last_updated: 2026-04-21距今 58 天)
- **建议**:核对用户角色与偏好是否仍准确;本次会话未涉及用户画像变化,可在有相关线索时更新
+14 -4
View File
@@ -3,7 +3,7 @@ name: 项目进度
description: 各模块原型开发进度与近期里程碑
type: project
last_updated: 2026-06-18
commit: 14a80cb
commit: 06587d2
---
# 项目进度
@@ -16,6 +16,7 @@ commit: 14a80cb
- `operator/` — 操作人员端(22 页:工作台15 + 知识库2 + 个人中心5)✅
- `professional/` — 专业人员端(13 页:工作台7 + 知识库2 + 个人中心4)✅
- `onsite/` — 驻场人员端(12 页:工作台6 + 知识库2 + 个人中心4)✅
- `admin/` — 管理员端(18 页:工作台13 + 知识库2 + 个人中心3)🔨 设计中
- `message/` — 消息/即时通讯(3 页,共享模块)✅
- `ai-assistant/` — AI 助手(1 页,共享模块)✅
@@ -58,9 +59,17 @@ commit: 14a80cb
- `health-checkup/` — 健康体检管理 ✅
- `nutrition/` — 营养管理(70+ 页:溯源双菜单、档案、种采、供应、生产、用餐、异常、食堂、数据、模型、终端、字典)🔨 设计中
- 溯源模块重构:食材溯源/餐品溯源双菜单分离(trace-timeline 双维度搜索区独立)
- `health-monitor/`健康监测管理(83 页)🔨 设计中
- `weight-management/`体重管理(39 页)🔨 设计中
- 档案:`archive-personal-weight-data.html``archive-personal-weight-detail.html``archive-unit-report.html``archive-algorithm-model.html`
- 计划管理:`plan-list.html``plan-edit.html``registration-tracking.html``target-weight-review.html`
- 过程管理:`action-record.html``action-overview.html``action-overview-detail.html``activity-statistics.html`
- 历史干预:`history-plan-list.html``history-plan-detail.html`
- 个人体重管理:`personal-target-data.html``personal-target-detail.html`
- 设备管理:体重秤(`scale-*.html`×4)、蓝牙秤(`bluetooth-*.html`×4)、体脂仪(`fat-*.html`×4)、运动器械(`sport-*.html`×4)
- 数据统计:`employee-data.html`/`employee-data-record.html``dept-stat.html``employee-stat.html``detail-data.html``weight-ranking.html`
- 异常事件:`exception-system-dirty.html``exception-result-abnormal.html`
- `health-monitor/` — 健康监测管理(40+ 页)🔨 设计中
- `wearable/` — 穿戴监测(8 页:设备管理/绑定记录/用户数据/部门报告/部门统计/个人统计/异常事件/通知配置)
- `weight/` — 体重监测(20 页:体重秤/蓝牙秤/体脂仪/运动器械各含设备管理+监测+明细+新增,员工数据/部门统计/员工统计)
- `environment/` — 环境监测(25 页:室内/室外/花粉/水质各含设备类型+设备列表+数据监测+历史数据+APP记录+异常告警,花粉知识)
- `health-checkup/` — 健康排查(7 页:问卷分类/模板/题目/评分/格言/部门记录/用户记录)
- 根级页面(5 页:档案管理个人/单位/算法、异常事件脏数据/结果)
@@ -86,7 +95,8 @@ Web 管理端和员工端 APP 的其余模块(系统管理、运动管理、
- 覆盖模块:18 个(含三端+其他终端)
## 近期里程碑
- 2026-06-18营养模块净菜联动与小程序登录优化——小程序新增 `me-login.html` 微信授权登录页,并将“我”入口统一先跳转登录页;Web 管理端营养模块补强餐品/食材、净菜订单、净菜内供/外售、净菜入库、净菜包装等页面的“食材名称 + 净菜类型”联动与包装规格整数输入,对应模块 CHANGELOG 已补充记录。
- 2026-06-18体重管理 Web管理端异常事件页面补全 + 历史干预模块 + 个人目标详情——补全 `exception-system-dirty.html`(系统脏数据:筛选栏/操作栏/9列表格/分页/10条Mock数据)和 `exception-result-abnormal.html`(结果异常:员工维度筛选含单位部门联动/9列表格/分页/10条Mock数据),参考健康监测模块对应页面字段设计;新增 `history-plan-list.html`(历史干预计划列表)、`history-plan-detail.html`(计划详情)、`personal-target-detail.html`(个人目标详情);`activity-statistics.html``weight-ranking.html``detail-data.html``personal-target-data.html` 等页面大幅重构;全部 39 个页面顶部导航新增「历史干预」菜单;`index.html` SITE_MAP 同步更新;`health-monitor/exception-result.html` 移除异常等级筛选及列
- 2026-06-18:营养模块净菜联动与小程序登录优化——小程序新增 `me-login.html` 微信授权登录页,并将"我"入口统一先跳转登录页;Web 管理端营养模块补强餐品/食材、净菜订单、净菜内供/外售、净菜入库、净菜包装等页面的"食材名称 + 净菜类型"联动与包装规格整数输入,对应模块 CHANGELOG 已补充记录。
- 2026-06-17:餐厅终端设备净菜加工与配比秤流程迭代——净菜加工秤从验收语义调整为净菜加工,新增任务获取/自动轮询、未完成净菜卡片、累计加工、重量确认弹窗、任务截止/到达时间展示;配比秤详情增加订单类型标签并统一年月日时间格式。
- 2026-06-16:体重管理 Web 管理端活动计划重构——活动计划列表、计划编辑、报名追踪、行动记录、行动总览/详情、目标体重审核等页面完成大幅重构,补充单位部门双列联动筛选并更新 `web-admin/weight-management/doc/CHANGELOG.md`
- 2026-06-15:卫生供应仓储管理联动增强——`sup-warehouse.html``sup-in-raw.html``sup-in-cleanin.html` 新增存储方式列;搜索区新增存储方式筛选,所在区域按柜子/仓区级别联动;新增弹窗在柜类场景下下钻到格口级别,仓库场景下选择仓区;对应 `web-admin/nutrition/doc/CHANGELOG.md` 已补充记录
+6 -34
View File
@@ -1,21 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ClaudeCodeTabState">
<option name="tabNames">
<map>
<entry key="1" value="RR" />
</map>
</option>
<option name="tabSessions">
<map>
<entry key="0">
<value>
<TabSessionState>
<option name="provider" value="claude" />
<option name="sessionId" value="eafa762f-e1c9-43d9-bcb0-bdcbaf8a558e" />
<option name="cwd" value="$PROJECT_DIR$" />
<option name="model" value="claude-sonnet-4-6" />
<option name="permissionMode" value="bypassPermissions" />
<option name="reasoningEffort" value="medium" />
<option name="reasoningEffort" value="high" />
</TabSessionState>
</value>
</entry>
@@ -23,40 +19,16 @@
<value>
<TabSessionState>
<option name="provider" value="claude" />
<option name="sessionId" value="138df05e-0994-43f4-815e-ae3e2bce9d58" />
<option name="sessionId" value="c093ac97-b314-4135-8140-d28789bec779" />
<option name="cwd" value="$PROJECT_DIR$" />
<option name="model" value="claude-opus-4-6" />
<option name="model" value="claude-sonnet-4-6" />
<option name="permissionMode" value="bypassPermissions" />
<option name="reasoningEffort" value="medium" />
</TabSessionState>
</value>
</entry>
<entry key="2">
<value>
<TabSessionState>
<option name="provider" value="claude" />
<option name="sessionId" value="147fc6bc-9ed3-4b0d-970d-0087ec03558c" />
<option name="cwd" value="$PROJECT_DIR$" />
<option name="model" value="claude-opus-4-6" />
<option name="permissionMode" value="bypassPermissions" />
<option name="reasoningEffort" value="medium" />
</TabSessionState>
</value>
</entry>
<entry key="3">
<value>
<TabSessionState>
<option name="provider" value="claude" />
<option name="sessionId" value="56449601-4de2-4e73-b2ca-6b3ad0b2c6e0" />
<option name="cwd" value="$PROJECT_DIR$" />
<option name="model" value="claude-opus-4-6" />
<option name="permissionMode" value="bypassPermissions" />
<option name="reasoningEffort" value="medium" />
<option name="reasoningEffort" value="high" />
</TabSessionState>
</value>
</entry>
</map>
</option>
<option name="tabCount" value="4" />
<option name="tabCount" value="2" />
</component>
</project>
+1 -1
View File
@@ -1,4 +1,4 @@
<!-- Last updated: 2026-06-12 | Commit: 2373704 -->
<!-- Last updated: 2026-06-18 | Commit: 06587d2 -->
# 项目约束
+18
View File
@@ -0,0 +1,18 @@
# 管理员端 - 变更日志
## [2026-06-23]
### 新增
- **个人中心模块** — 新建管理员「我的」页面及子页面
- `profile/index.html` — 个人中心主页,含蓝色渐变头部(姓名/角色/部门)、菜单卡片(修改个人信息/修改密码/关于我们)、退出登录弹窗、底部Tab导航栏
- `profile/edit-profile.html` — 修改个人信息,支持头像更换(拍照/相册ActionSheet)、姓名编辑、保存Toast反馈
- `profile/change-pwd.html` — 修改密码,含当前密码/新密码/确认新密码三段式表单,修改成功弹窗
- 页面布局与交互参考驻场人员端(`onsite/profile/`),适配管理员身份(王建国/健康管理员/安全环保部·健康管理科)
### 修改的文件
- `profile/index.html` - 个人中心主页
- `profile/edit-profile.html` - 修改个人信息
- `profile/change-pwd.html` - 修改密码
- `index.html`(导航页) - SITE_MAP 中 admin「我的」模块补全 3 个页面条目
- `../../ai-assistant/index.html` - roleBaseMap 新增 admin 角色路由
- `../../message/index.html` - roleBaseMap 新增 admin 角色路由
+187
View File
@@ -0,0 +1,187 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>知识详情</title>
<style>
/* ========== 公共基础样式 ========== */
* { margin: 0; padding: 0; box-sizing: border-box; }
body { background: #f0f2f5; display: flex; justify-content: center; align-items: flex-start; min-height: 100vh; padding: 20px; font-family: -apple-system, BlinkMacSystemFont, 'PingFang SC', 'Helvetica Neue', sans-serif; }
.phone-shell { width: 390px; height: 844px; background: #fff; border-radius: 44px; box-shadow: 0 20px 60px rgba(0,0,0,0.25), inset 0 0 0 2px #e0e0e0; overflow: hidden; position: relative; display: flex; flex-direction: column; flex-shrink: 0; }
.status-bar { height: 44px; background: #fff; display: flex; align-items: center; justify-content: space-between; padding: 0 24px; flex-shrink: 0; z-index: 10; }
.status-bar .time { font-size: 15px; font-weight: 700; color: #1a1a1a; }
.status-bar .icons { display: flex; gap: 6px; align-items: center; font-size: 12px; color: #1a1a1a; }
.nav-bar { height: 44px; display: flex; align-items: center; padding: 0 16px; background: #fff; border-bottom: 1px solid #f0f0f0; flex-shrink: 0; position: relative; }
.back-btn { display: flex; align-items: center; gap: 4px; color: #1677ff; font-size: 15px; cursor: pointer; background: none; border: none; padding: 4px 0; }
.nav-title { position: absolute; left: 50%; transform: translateX(-50%); font-size: 17px; font-weight: 600; color: #1a1a1a; white-space: nowrap; }
.scroll-content { flex: 1; overflow-y: auto; background: #f7f8fa; }
.scroll-content::-webkit-scrollbar { display: none; }
</style>
</head>
<body>
<div class="phone-shell">
<!-- 状态栏 -->
<div class="status-bar">
<span class="time">9:41</span>
<div class="icons"><span>●●●</span><span>WiFi</span><span>🔋</span></div>
</div>
<!-- 导航栏 -->
<div class="nav-bar">
<button class="back-btn" onclick="window.location.href='./index.html'">
<svg width="10" height="16" viewBox="0 0 10 16" fill="none" stroke="currentColor" stroke-width="2"><path d="M8 1L2 8l6 7"/></svg>返回
</button>
<span class="nav-title" id="kd-nav-title">知识详情</span>
</div>
<!-- 内容区 -->
<div class="scroll-content" style="padding:16px;">
<div id="kd-content" style="background:#fff;border-radius:16px;padding:20px;box-shadow:0 1px 6px rgba(0,0,0,0.06);">
<!-- 由JS动态填充内容 -->
</div>
<div style="height:16px;"></div>
</div>
</div>
<script>
/**
* 知识库数据集合
* 每个key对应一个知识条目的完整内容
*/
var KB_DATA = {
'blood-routine': {
icon: '🩺', bg: '#e6f4ff', title: '血常规检查解读指南', cat: '体检知识', date: '2026-03-15',
summary: '血常规是最基本的血液检验,通过检测血液中各种细胞成分的数量和形态,帮助医生了解患者的基本健康状况,是临床诊断的重要依据之一。',
items: [
{ color: '#1677ff', name: '白细胞计数(WBC', desc: '正常范围:4.010.0 × 10⁹/L。升高提示感染、炎症或白血病;降低见于病毒感染、药物影响或免疫抑制。' },
{ color: '#52c41a', name: '红细胞计数(RBC', desc: '男性正常范围:4.55.5 × 10¹²/L;女性:3.8–5.1 × 10¹²/L。降低提示贫血,升高见于脱水或红细胞增多症。' },
{ color: '#fa8c16', name: '血小板计数(PLT', desc: '正常范围:100–300 × 10⁹/L。降低有出血风险,升高见于炎症或血小板增多症。' }
]
},
'ecg': {
icon: '❤️', bg: '#f6ffed', title: '心电图异常结果说明', cat: '体检知识', date: '2026-03-10',
summary: '心电图(ECG)是记录心脏电活动的无创检查,常见异常结果需结合临床症状综合判断,不可单凭报告结论下诊断。',
items: [
{ color: '#ff4d4f', name: 'ST段改变', desc: 'ST段压低≥0.1mV提示心肌缺血;ST段抬高需警惕急性心肌梗死,需立即就医。' },
{ color: '#fa8c16', name: '心律失常', desc: '包括窦性心动过速(>100次/分)、窦性心动过缓(<60次/分)、房颤等,需结合症状评估。' },
{ color: '#1677ff', name: '束支传导阻滞', desc: '完全性左束支传导阻滞常提示器质性心脏病;右束支传导阻滞可见于正常人,需随访观察。' }
]
},
'liver': {
icon: '🔬', bg: '#fff7e6', title: '肝功能指标详解', cat: '体检知识', date: '2026-03-12',
summary: '肝功能检查通过检测血液中多种酶和蛋白质水平,评估肝脏的合成、代谢和排泄功能,是发现肝脏疾病的重要手段。',
items: [
{ color: '#fa8c16', name: '谷丙转氨酶(ALT', desc: '正常值:男≤50 U/L,女≤40 U/L。升高提示肝细胞损伤,见于病毒性肝炎、脂肪肝、药物性肝损伤等。' },
{ color: '#52c41a', name: '谷草转氨酶(AST', desc: '正常值:≤40 U/L。AST/ALT比值>2提示酒精性肝病;单纯升高也见于心肌损伤。' },
{ color: '#1677ff', name: '总胆红素(TBIL', desc: '正常值:3.417.1 μmol/L。升高引起黄疸,需区分溶血性、肝细胞性和梗阻性黄疸。' }
]
},
'glucose': {
icon: '💉', bg: '#fff1f0', title: '血糖检测与糖尿病筛查', cat: '体检知识', date: '2026-03-08',
summary: '血糖检测是糖尿病筛查和管理的核心手段,包括空腹血糖、餐后2小时血糖和糖化血红蛋白三项主要指标。',
items: [
{ color: '#ff4d4f', name: '空腹血糖(FPG', desc: '正常:<6.1 mmol/L;糖尿病前期:6.17.0 mmol/L;糖尿病诊断标准:≥7.0 mmol/L(需两次确认)。' },
{ color: '#fa8c16', name: '餐后2小时血糖', desc: '正常:<7.8 mmol/L;糖耐量受损:7.811.1 mmol/L;≥11.1 mmol/L结合症状可诊断糖尿病。' },
{ color: '#722ed1', name: '糖化血红蛋白(HbA1c', desc: '反映近2–3个月平均血糖水平。正常<5.7%;5.7–6.4%为糖尿病前期;≥6.5%可诊断糖尿病。' }
]
},
'antihypertensive': {
icon: '💊', bg: '#e6f4ff', title: '常用降压药物对比', cat: '药品知识', date: '2026-02-20',
summary: '降压药物分为五大类,各有适应症和禁忌症,临床选药需结合患者合并症、年龄、肾功能等综合考量。',
items: [
{ color: '#1677ff', name: 'ACEI/ARB类', desc: '代表药:依那普利、缬沙坦。适用于合并糖尿病、蛋白尿、心衰患者。禁用于妊娠、双侧肾动脉狭窄。' },
{ color: '#52c41a', name: '钙通道阻滞剂(CCB', desc: '代表药:氨氯地平、硝苯地平。适用于老年、单纯收缩期高血压。不良反应:踝部水肿、头痛。' },
{ color: '#fa8c16', name: '利尿剂', desc: '代表药:氢氯噻嗪、螺内酯。适用于容量负荷过重、心衰患者。注意监测血钾、血糖、血尿酸。' }
]
},
'statin': {
icon: '🧪', bg: '#f6ffed', title: '他汀类药物使用指南', cat: '药品知识', date: '2026-02-15',
summary: '他汀类药物是目前最有效的调脂药物,通过抑制HMG-CoA还原酶降低LDL-C,同时具有抗炎、稳定斑块等多效性作用。',
items: [
{ color: '#52c41a', name: '适应症与目标值', desc: '适用于LDL-C升高、动脉粥样硬化性心血管病(ASCVD)患者。高危患者LDL-C目标<1.8 mmol/L。' },
{ color: '#fa8c16', name: '常用药物与剂量', desc: '阿托伐他汀1080mg/日;瑞舒伐他汀5–40mg/日;辛伐他汀20–40mg/日(晚间服用效果更佳)。' },
{ color: '#ff4d4f', name: '副作用监测', desc: '肌肉疼痛(肌病):监测CK;肝功能损害:用药前及用药后4–8周复查ALT/AST;血糖轻度升高。' }
]
},
'hypertension': {
icon: '🫀', bg: '#fff7e6', title: '高血压诊断与管理', cat: '疾病知识', date: '2026-03-01',
summary: '高血压是最常见的慢性病之一,长期控制不佳可导致心、脑、肾等靶器官损害。规范管理可显著降低心脑血管事件风险。',
items: [
{ color: '#ff4d4f', name: '诊断标准与分级', desc: '1级:140159/9099 mmHg2级:160179/100109 mmHg3级:≥180/110 mmHg。非同日3次测量均达标方可诊断。' },
{ color: '#fa8c16', name: '生活方式干预', desc: '减重(BMI<24)、低盐饮食(<6g/日)、戒烟限酒、规律有氧运动(每周≥150分钟)、减少精神压力。' },
{ color: '#1677ff', name: '药物治疗原则', desc: '小剂量起始,优先选用长效制剂,联合用药,个体化治疗。血压目标:一般患者<140/90 mmHg,高危患者<130/80 mmHg。' }
]
},
'migraine': {
icon: '🧠', bg: '#fff1f0', title: '偏头痛的诊断与治疗', cat: '疾病知识', date: '2026-03-05',
summary: '偏头痛是一种反复发作的神经血管性头痛,以单侧搏动性头痛为主要特征,常伴恶心、畏光、畏声,严重影响生活质量。',
items: [
{ color: '#ff4d4f', name: '诊断要点', desc: '发作5次以上;持续4–72小时;单侧、搏动性、中重度;活动加重;伴恶心/呕吐或畏光/畏声。需排除继发性头痛。' },
{ color: '#fa8c16', name: '急性期治疗', desc: '轻中度:NSAIDs(布洛芬600mg)或对乙酰氨基酚。中重度:曲普坦类(舒马曲坦50–100mg)为首选,发作早期使用效果最佳。' },
{ color: '#722ed1', name: '预防性治疗', desc: '每月发作≥4次或严重影响生活时考虑预防用药。常用药物:普萘洛尔、托吡酯、阿米替林、丙戊酸钠。' }
]
},
'nutrition': {
icon: '🥗', bg: '#f6ffed', title: '职场人群营养膳食指南', cat: '保健知识', date: '2026-02-28',
summary: '久坐办公人群因活动量少、饮食不规律,易出现超重、血脂异常、颈椎病等问题。科学膳食是维护健康的基础。',
items: [
{ color: '#52c41a', name: '能量与三大营养素', desc: '每日能量摄入:轻体力劳动男性2250kcal,女性1800kcal。碳水化合物5065%,蛋白质1520%,脂肪2030%。' },
{ color: '#1677ff', name: '重点营养建议', desc: '增加蔬菜水果(每日500g以上);减少精制碳水和加工食品;优选全谷物;每周鱼类2次以上;控制红肉摄入。' },
{ color: '#fa8c16', name: '饮食行为干预', desc: '规律三餐,避免不吃早餐;控制外卖频率;减少含糖饮料;每日饮水1500–1700ml;避免久坐后立即进食。' }
]
},
'exercise': {
icon: '🏃', bg: '#e6f4ff', title: '运动与心血管健康', cat: '保健知识', date: '2026-02-25',
summary: '规律有氧运动是预防和改善心血管疾病的重要非药物手段,可降低血压、改善血脂、控制体重、减少心血管事件风险。',
items: [
{ color: '#1677ff', name: '运动推荐量', desc: '每周≥150分钟中等强度有氧运动(如快走、游泳、骑车),或≥75分钟高强度运动。每次至少10分钟,分散进行亦有效。' },
{ color: '#52c41a', name: '运动强度判断', desc: '中等强度:运动时心率达最大心率(220-年龄)的50–70%,可说话但不能唱歌。高强度:心率达70–85%,说话困难。' },
{ color: '#ff4d4f', name: '特殊人群注意事项', desc: '高血压患者避免憋气用力动作;冠心病患者运动前需评估;运动前热身5–10分钟,运动后拉伸放松,避免突然停止。' }
]
}
};
/**
* 页面加载时根据URL参数渲染知识详情
* 从URL的key参数获取知识条目标识,查找数据并填充页面
*/
function renderDetail() {
// 解析URL参数获取知识条目key
var params = new URLSearchParams(window.location.search);
var key = params.get('key') || 'blood-routine'; // 默认显示血常规
var d = KB_DATA[key];
if (!d) {
// 未找到对应数据时使用默认值
d = KB_DATA['blood-routine'];
}
// 设置导航栏标题
document.getElementById('kd-nav-title').textContent = d.title;
// 生成主要内容条目的HTML
var itemsHtml = d.items.map(function(it) {
return '<div style="background:#f7f8fa;border-radius:10px;padding:14px;margin-bottom:12px;">' +
'<div style="font-size:13px;font-weight:600;color:' + it.color + ';margin-bottom:6px;">' + it.name + '</div>' +
'<div style="font-size:13px;color:#444;line-height:1.7;">' + it.desc + '</div>' +
'</div>';
}).join('');
// 填充内容区域
document.getElementById('kd-content').innerHTML =
'<div style="display:flex;align-items:center;gap:12px;margin-bottom:16px;padding-bottom:16px;border-bottom:1px solid #f5f5f5;">' +
'<div style="width:48px;height:48px;border-radius:12px;background:' + d.bg + ';display:flex;align-items:center;justify-content:center;font-size:24px;">' + d.icon + '</div>' +
'<div><div style="font-size:17px;font-weight:700;color:#1a1a1a;">' + d.title + '</div><div style="font-size:12px;color:#999;margin-top:3px;">' + d.cat + ' · 更新于 ' + d.date + '</div></div>' +
'</div>' +
'<div style="font-size:15px;font-weight:700;color:#1a1a1a;margin-bottom:8px;">概述</div>' +
'<div style="font-size:14px;color:#444;line-height:1.8;margin-bottom:16px;">' + d.summary + '</div>' +
'<div style="font-size:15px;font-weight:700;color:#1a1a1a;margin-bottom:8px;">主要内容</div>' +
itemsHtml;
}
// 页面加载完成后渲染详情
renderDetail();
</script>
</body>
</html>
+298
View File
@@ -0,0 +1,298 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>知识库</title>
<style>
/* ========== 公共基础样式 ========== */
* { margin: 0; padding: 0; box-sizing: border-box; }
body { background: #f0f2f5; display: flex; justify-content: center; align-items: flex-start; min-height: 100vh; padding: 20px; font-family: -apple-system, BlinkMacSystemFont, 'PingFang SC', 'Helvetica Neue', sans-serif; }
.phone-shell { width: 390px; height: 844px; background: #fff; border-radius: 44px; box-shadow: 0 20px 60px rgba(0,0,0,0.25), inset 0 0 0 2px #e0e0e0; overflow: hidden; position: relative; display: flex; flex-direction: column; flex-shrink: 0; }
.status-bar { height: 44px; background: #fff; display: flex; align-items: center; justify-content: space-between; padding: 0 24px; flex-shrink: 0; z-index: 10; }
.status-bar .time { font-size: 15px; font-weight: 700; color: #1a1a1a; }
.status-bar .icons { display: flex; gap: 6px; align-items: center; font-size: 12px; color: #1a1a1a; }
.scroll-content { flex: 1; overflow-y: auto; background: #f7f8fa; }
.scroll-content::-webkit-scrollbar { display: none; }
/* ========== 分段Tab样式 ========== */
.seg-tabs { display: flex; background: #fff; border-bottom: 1px solid #f0f0f0; flex-shrink: 0; }
.seg-tab {
flex: 1; text-align: center; padding: 12px 0;
font-size: 14px; color: #666; cursor: pointer;
border-bottom: 2px solid transparent; transition: all 0.2s;
}
.seg-tab.active { color: #1677ff; border-bottom-color: #1677ff; font-weight: 600; }
/* ========== 底部Tab栏样式 ========== */
.tab-bar { height: 83px; background: #fff; border-top: 1px solid #e8e8e8; display: flex; align-items: flex-start; padding-top: 8px; flex-shrink: 0; }
.tab-item { flex: 1; display: flex; flex-direction: column; align-items: center; gap: 4px; cursor: pointer; padding: 4px 0; position: relative; text-decoration: none; }
.tab-item .tab-icon { font-size: 22px; line-height: 1; }
.tab-item .tab-label { font-size: 10px; color: #999; font-weight: 500; }
.tab-item.active .tab-label { color: #1677ff; }
.tab-badge { position: absolute; top: 2px; right: 18px; background: #ff4d4f; color: #fff; font-size: 10px; font-weight: 700; min-width: 16px; height: 16px; border-radius: 8px; display: flex; align-items: center; justify-content: center; padding: 0 4px; }
/* ========== 子分类Tab ========== */
.sub-tabs { display: flex; gap: 8px; padding: 10px 16px; background: #fff; flex-shrink: 0; }
.sub-tab {
font-size: 12px; padding: 4px 14px; border-radius: 16px;
background: #f5f5f5; color: #666; cursor: pointer; transition: all 0.2s;
}
.sub-tab.active { background: #e6f4ff; color: #1677ff; font-weight: 600; }
/* ========== PDF文档条目 ========== */
.pdf-item {
background: #fff; border-radius: 10px; padding: 12px 14px;
display: flex; align-items: center; gap: 10px;
box-shadow: 0 1px 4px rgba(0,0,0,0.06); margin-bottom: 10px; cursor: pointer;
}
.pdf-item__icon {
width: 44px; height: 44px; border-radius: 10px; background: #fff1f0;
display: flex; align-items: center; justify-content: center; flex-shrink: 0;
}
.pdf-item__info { flex: 1; }
.pdf-item__name { font-size: 14px; font-weight: 600; color: #1a1a1a; }
.pdf-item__meta { font-size: 12px; color: #999; margin-top: 3px; display: flex; gap: 8px; }
</style>
</head>
<body>
<div class="phone-shell">
<!-- 状态栏 -->
<div class="status-bar">
<span class="time">9:41</span>
<div class="icons"><span>●●●</span><span>WiFi</span><span>🔋</span></div>
</div>
<!-- 蓝色渐变头部 -->
<div style="background:linear-gradient(135deg,#1677ff,#0958d9);padding:16px 20px 20px;flex-shrink:0;">
<div style="color:rgba(255,255,255,0.75);font-size:12px;margin-bottom:2px;">专业参考</div>
<div style="color:#fff;font-size:20px;font-weight:700;">知识库</div>
</div>
<!-- 一级分类Tab -->
<div class="seg-tabs">
<div class="seg-tab active" onclick="switchTopTab(this,'panel-article')">知识文章</div>
<div class="seg-tab" onclick="switchTopTab(this,'panel-rule')">规章制度</div>
</div>
<!-- 知识文章面板 -->
<div id="panel-article" style="flex:1;display:flex;flex-direction:column;overflow:hidden;">
<!-- 子分类Tab -->
<div class="sub-tabs">
<div class="sub-tab active" onclick="switchKbTab(this,'kb-exam')">体检知识</div>
<div class="sub-tab" onclick="switchKbTab(this,'kb-drug')">药品知识</div>
<div class="sub-tab" onclick="switchKbTab(this,'kb-disease')">疾病知识</div>
<div class="sub-tab" onclick="switchKbTab(this,'kb-health')">保健知识</div>
</div>
<!-- 知识条目列表 -->
<div class="scroll-content">
<!-- 体检知识 -->
<div id="kb-exam">
<div style="padding:12px 16px 0;">
<!-- 血常规检查解读指南 -->
<div style="background:#fff;border-radius:10px;padding:12px 14px;display:flex;align-items:center;gap:10px;box-shadow:0 1px 4px rgba(0,0,0,0.06);margin-bottom:10px;cursor:pointer;" onclick="goDetail('blood-routine')">
<div style="width:44px;height:44px;border-radius:10px;background:#e6f4ff;display:flex;align-items:center;justify-content:center;font-size:22px;flex-shrink:0;">🩺</div>
<div style="flex:1;"><div style="font-size:14px;font-weight:600;color:#1a1a1a;">血常规检查解读指南</div><div style="font-size:12px;color:#999;margin-top:3px;">了解各项血常规指标的正常范围与临床意义</div></div>
<svg width="7" height="12" viewBox="0 0 7 12" fill="none" stroke="#ccc" stroke-width="1.5"><path d="M1 1l5 5-5 5"/></svg>
</div>
<!-- 心电图异常结果说明 -->
<div style="background:#fff;border-radius:10px;padding:12px 14px;display:flex;align-items:center;gap:10px;box-shadow:0 1px 4px rgba(0,0,0,0.06);margin-bottom:10px;cursor:pointer;" onclick="goDetail('ecg')">
<div style="width:44px;height:44px;border-radius:10px;background:#f6ffed;display:flex;align-items:center;justify-content:center;font-size:22px;flex-shrink:0;">❤️</div>
<div style="flex:1;"><div style="font-size:14px;font-weight:600;color:#1a1a1a;">心电图异常结果说明</div><div style="font-size:12px;color:#999;margin-top:3px;">常见心电图异常表现及处理建议</div></div>
<svg width="7" height="12" viewBox="0 0 7 12" fill="none" stroke="#ccc" stroke-width="1.5"><path d="M1 1l5 5-5 5"/></svg>
</div>
<!-- 肝功能指标详解 -->
<div style="background:#fff;border-radius:10px;padding:12px 14px;display:flex;align-items:center;gap:10px;box-shadow:0 1px 4px rgba(0,0,0,0.06);margin-bottom:10px;cursor:pointer;" onclick="goDetail('liver')">
<div style="width:44px;height:44px;border-radius:10px;background:#fff7e6;display:flex;align-items:center;justify-content:center;font-size:22px;flex-shrink:0;">🔬</div>
<div style="flex:1;"><div style="font-size:14px;font-weight:600;color:#1a1a1a;">肝功能指标详解</div><div style="font-size:12px;color:#999;margin-top:3px;">ALT、AST等肝功能指标的临床意义</div></div>
<svg width="7" height="12" viewBox="0 0 7 12" fill="none" stroke="#ccc" stroke-width="1.5"><path d="M1 1l5 5-5 5"/></svg>
</div>
<!-- 血糖检测与糖尿病筛查 -->
<div style="background:#fff;border-radius:10px;padding:12px 14px;display:flex;align-items:center;gap:10px;box-shadow:0 1px 4px rgba(0,0,0,0.06);margin-bottom:10px;cursor:pointer;" onclick="goDetail('glucose')">
<div style="width:44px;height:44px;border-radius:10px;background:#fff1f0;display:flex;align-items:center;justify-content:center;font-size:22px;flex-shrink:0;">💉</div>
<div style="flex:1;"><div style="font-size:14px;font-weight:600;color:#1a1a1a;">血糖检测与糖尿病筛查</div><div style="font-size:12px;color:#999;margin-top:3px;">空腹血糖、糖化血红蛋白的判读标准</div></div>
<svg width="7" height="12" viewBox="0 0 7 12" fill="none" stroke="#ccc" stroke-width="1.5"><path d="M1 1l5 5-5 5"/></svg>
</div>
</div>
<div style="height:16px;"></div>
</div>
<!-- 药品知识 -->
<div id="kb-drug" style="display:none;">
<div style="padding:12px 16px 0;">
<!-- 常用降压药物对比 -->
<div style="background:#fff;border-radius:10px;padding:12px 14px;display:flex;align-items:center;gap:10px;box-shadow:0 1px 4px rgba(0,0,0,0.06);margin-bottom:10px;cursor:pointer;" onclick="goDetail('antihypertensive')">
<div style="width:44px;height:44px;border-radius:10px;background:#e6f4ff;display:flex;align-items:center;justify-content:center;font-size:22px;flex-shrink:0;">💊</div>
<div style="flex:1;"><div style="font-size:14px;font-weight:600;color:#1a1a1a;">常用降压药物对比</div><div style="font-size:12px;color:#999;margin-top:3px;">各类降压药的适应症与注意事项</div></div>
<svg width="7" height="12" viewBox="0 0 7 12" fill="none" stroke="#ccc" stroke-width="1.5"><path d="M1 1l5 5-5 5"/></svg>
</div>
<!-- 他汀类药物使用指南 -->
<div style="background:#fff;border-radius:10px;padding:12px 14px;display:flex;align-items:center;gap:10px;box-shadow:0 1px 4px rgba(0,0,0,0.06);margin-bottom:10px;cursor:pointer;" onclick="goDetail('statin')">
<div style="width:44px;height:44px;border-radius:10px;background:#f6ffed;display:flex;align-items:center;justify-content:center;font-size:22px;flex-shrink:0;">🧪</div>
<div style="flex:1;"><div style="font-size:14px;font-weight:600;color:#1a1a1a;">他汀类药物使用指南</div><div style="font-size:12px;color:#999;margin-top:3px;">调脂药物的用法用量与副作用监测</div></div>
<svg width="7" height="12" viewBox="0 0 7 12" fill="none" stroke="#ccc" stroke-width="1.5"><path d="M1 1l5 5-5 5"/></svg>
</div>
</div>
<div style="height:16px;"></div>
</div>
<!-- 疾病知识 -->
<div id="kb-disease" style="display:none;">
<div style="padding:12px 16px 0;">
<!-- 高血压诊断与管理 -->
<div style="background:#fff;border-radius:10px;padding:12px 14px;display:flex;align-items:center;gap:10px;box-shadow:0 1px 4px rgba(0,0,0,0.06);margin-bottom:10px;cursor:pointer;" onclick="goDetail('hypertension')">
<div style="width:44px;height:44px;border-radius:10px;background:#fff7e6;display:flex;align-items:center;justify-content:center;font-size:22px;flex-shrink:0;">🫀</div>
<div style="flex:1;"><div style="font-size:14px;font-weight:600;color:#1a1a1a;">高血压诊断与管理</div><div style="font-size:12px;color:#999;margin-top:3px;">高血压分级标准及生活方式干预</div></div>
<svg width="7" height="12" viewBox="0 0 7 12" fill="none" stroke="#ccc" stroke-width="1.5"><path d="M1 1l5 5-5 5"/></svg>
</div>
<!-- 偏头痛的诊断与治疗 -->
<div style="background:#fff;border-radius:10px;padding:12px 14px;display:flex;align-items:center;gap:10px;box-shadow:0 1px 4px rgba(0,0,0,0.06);margin-bottom:10px;cursor:pointer;" onclick="goDetail('migraine')">
<div style="width:44px;height:44px;border-radius:10px;background:#fff1f0;display:flex;align-items:center;justify-content:center;font-size:22px;flex-shrink:0;">🧠</div>
<div style="flex:1;"><div style="font-size:14px;font-weight:600;color:#1a1a1a;">偏头痛的诊断与治疗</div><div style="font-size:12px;color:#999;margin-top:3px;">偏头痛的临床特征、诱因及处理方案</div></div>
<svg width="7" height="12" viewBox="0 0 7 12" fill="none" stroke="#ccc" stroke-width="1.5"><path d="M1 1l5 5-5 5"/></svg>
</div>
</div>
<div style="height:16px;"></div>
</div>
<!-- 保健知识 -->
<div id="kb-health" style="display:none;">
<div style="padding:12px 16px 0;">
<!-- 职场人群营养膳食指南 -->
<div style="background:#fff;border-radius:10px;padding:12px 14px;display:flex;align-items:center;gap:10px;box-shadow:0 1px 4px rgba(0,0,0,0.06);margin-bottom:10px;cursor:pointer;" onclick="goDetail('nutrition')">
<div style="width:44px;height:44px;border-radius:10px;background:#f6ffed;display:flex;align-items:center;justify-content:center;font-size:22px;flex-shrink:0;">🥗</div>
<div style="flex:1;"><div style="font-size:14px;font-weight:600;color:#1a1a1a;">职场人群营养膳食指南</div><div style="font-size:12px;color:#999;margin-top:3px;">针对久坐办公人群的饮食建议</div></div>
<svg width="7" height="12" viewBox="0 0 7 12" fill="none" stroke="#ccc" stroke-width="1.5"><path d="M1 1l5 5-5 5"/></svg>
</div>
<!-- 运动与心血管健康 -->
<div style="background:#fff;border-radius:10px;padding:12px 14px;display:flex;align-items:center;gap:10px;box-shadow:0 1px 4px rgba(0,0,0,0.06);margin-bottom:10px;cursor:pointer;" onclick="goDetail('exercise')">
<div style="width:44px;height:44px;border-radius:10px;background:#e6f4ff;display:flex;align-items:center;justify-content:center;font-size:22px;flex-shrink:0;">🏃</div>
<div style="flex:1;"><div style="font-size:14px;font-weight:600;color:#1a1a1a;">运动与心血管健康</div><div style="font-size:12px;color:#999;margin-top:3px;">有氧运动对心血管的保护作用</div></div>
<svg width="7" height="12" viewBox="0 0 7 12" fill="none" stroke="#ccc" stroke-width="1.5"><path d="M1 1l5 5-5 5"/></svg>
</div>
</div>
<div style="height:16px;"></div>
</div>
</div>
</div><!-- /panel-article -->
<!-- 规章制度面板 -->
<div id="panel-rule" style="display:none;flex:1;overflow-y:auto;background:#f7f8fa;">
<div style="padding:12px 16px 0;">
<div class="pdf-item">
<div class="pdf-item__icon"><svg width="24" height="24" viewBox="0 0 24 24" fill="none"><path d="M6 2h9l5 5v15H6a2 2 0 01-2-2V4a2 2 0 012-2z" fill="#ff4d4f" opacity="0.15" stroke="#ff4d4f" stroke-width="1.5"/><path d="M15 2v5h5" stroke="#ff4d4f" stroke-width="1.5"/><text x="8" y="17" font-size="7" font-weight="700" fill="#ff4d4f">PDF</text></svg></div>
<div class="pdf-item__info">
<div class="pdf-item__name">员工健康管理办法(2026版)</div>
<div class="pdf-item__meta"><span>PDF · 2.3MB</span><span>2026-01-15</span></div>
</div>
<svg width="7" height="12" viewBox="0 0 7 12" fill="none" stroke="#ccc" stroke-width="1.5"><path d="M1 1l5 5-5 5"/></svg>
</div>
<div class="pdf-item">
<div class="pdf-item__icon"><svg width="24" height="24" viewBox="0 0 24 24" fill="none"><path d="M6 2h9l5 5v15H6a2 2 0 01-2-2V4a2 2 0 012-2z" fill="#ff4d4f" opacity="0.15" stroke="#ff4d4f" stroke-width="1.5"/><path d="M15 2v5h5" stroke="#ff4d4f" stroke-width="1.5"/><text x="8" y="17" font-size="7" font-weight="700" fill="#ff4d4f">PDF</text></svg></div>
<div class="pdf-item__info">
<div class="pdf-item__name">职业病防治管理规定</div>
<div class="pdf-item__meta"><span>PDF · 1.8MB</span><span>2025-12-20</span></div>
</div>
<svg width="7" height="12" viewBox="0 0 7 12" fill="none" stroke="#ccc" stroke-width="1.5"><path d="M1 1l5 5-5 5"/></svg>
</div>
<div class="pdf-item">
<div class="pdf-item__icon"><svg width="24" height="24" viewBox="0 0 24 24" fill="none"><path d="M6 2h9l5 5v15H6a2 2 0 01-2-2V4a2 2 0 012-2z" fill="#ff4d4f" opacity="0.15" stroke="#ff4d4f" stroke-width="1.5"/><path d="M15 2v5h5" stroke="#ff4d4f" stroke-width="1.5"/><text x="8" y="17" font-size="7" font-weight="700" fill="#ff4d4f">PDF</text></svg></div>
<div class="pdf-item__info">
<div class="pdf-item__name">体检异常结果处置流程</div>
<div class="pdf-item__meta"><span>PDF · 0.9MB</span><span>2025-11-08</span></div>
</div>
<svg width="7" height="12" viewBox="0 0 7 12" fill="none" stroke="#ccc" stroke-width="1.5"><path d="M1 1l5 5-5 5"/></svg>
</div>
<div class="pdf-item">
<div class="pdf-item__icon"><svg width="24" height="24" viewBox="0 0 24 24" fill="none"><path d="M6 2h9l5 5v15H6a2 2 0 01-2-2V4a2 2 0 012-2z" fill="#ff4d4f" opacity="0.15" stroke="#ff4d4f" stroke-width="1.5"/><path d="M15 2v5h5" stroke="#ff4d4f" stroke-width="1.5"/><text x="8" y="17" font-size="7" font-weight="700" fill="#ff4d4f">PDF</text></svg></div>
<div class="pdf-item__info">
<div class="pdf-item__name">健康咨询服务管理细则</div>
<div class="pdf-item__meta"><span>PDF · 1.5MB</span><span>2025-10-22</span></div>
</div>
<svg width="7" height="12" viewBox="0 0 7 12" fill="none" stroke="#ccc" stroke-width="1.5"><path d="M1 1l5 5-5 5"/></svg>
</div>
<div class="pdf-item">
<div class="pdf-item__icon"><svg width="24" height="24" viewBox="0 0 24 24" fill="none"><path d="M6 2h9l5 5v15H6a2 2 0 01-2-2V4a2 2 0 012-2z" fill="#ff4d4f" opacity="0.15" stroke="#ff4d4f" stroke-width="1.5"/><path d="M15 2v5h5" stroke="#ff4d4f" stroke-width="1.5"/><text x="8" y="17" font-size="7" font-weight="700" fill="#ff4d4f">PDF</text></svg></div>
<div class="pdf-item__info">
<div class="pdf-item__name">应急救护操作规范</div>
<div class="pdf-item__meta"><span>PDF · 3.1MB</span><span>2025-09-15</span></div>
</div>
<svg width="7" height="12" viewBox="0 0 7 12" fill="none" stroke="#ccc" stroke-width="1.5"><path d="M1 1l5 5-5 5"/></svg>
</div>
</div>
<div style="height:16px;"></div>
</div>
<!-- 底部Tab栏 -->
<div class="tab-bar">
<a class="tab-item" href="../workbench/index.html">
<span class="tab-icon">🏥</span>
<span class="tab-label">工作台</span>
<span class="tab-badge">3</span>
</a>
<a class="tab-item active" href="./index.html">
<span class="tab-icon">📚</span>
<span class="tab-label">知识库</span>
</a>
<a class="tab-item" href="../../ai-assistant/index.html">
<span class="tab-icon">🤖</span>
<span class="tab-label">AI助手</span>
</a>
<a class="tab-item" href="../../message/index.html">
<span class="tab-icon">💬</span>
<span class="tab-label">消息</span>
<span class="tab-badge">2</span>
</a>
<a class="tab-item" href="../profile/index.html">
<span class="tab-icon">👤</span>
<span class="tab-label">我的</span>
</a>
</div>
</div>
<script>
/* 标记当前角色为管理员 */
sessionStorage.setItem('appRole', 'admin');
/**
* 切换一级Tab(知识文章 / 规章制度)
*/
function switchTopTab(el, panelId) {
el.closest('.seg-tabs').querySelectorAll('.seg-tab').forEach(function(t) {
t.classList.remove('active');
});
el.classList.add('active');
var displayMap = { 'panel-article': 'flex', 'panel-rule': 'block' };
['panel-article', 'panel-rule'].forEach(function(id) {
var p = document.getElementById(id);
if (p) p.style.display = id === panelId ? displayMap[id] : 'none';
});
}
/**
* 切换知识库子分类Tab
* @param {HTMLElement} el - 被点击的Tab元素
* @param {string} panelId - 对应面板的ID
*/
function switchKbTab(el, panelId) {
el.closest('.sub-tabs').querySelectorAll('.sub-tab').forEach(function(t) {
t.classList.remove('active');
});
el.classList.add('active');
['kb-exam', 'kb-drug', 'kb-disease', 'kb-health'].forEach(function(id) {
var p = document.getElementById(id);
if (p) p.style.display = id === panelId ? 'block' : 'none';
});
}
/**
* 跳转到知识详情页
* @param {string} key - 知识条目的标识key
*/
function goDetail(key) {
window.location.href = './detail.html?key=' + key;
}
</script>
</body>
</html>
@@ -0,0 +1,70 @@
<!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>
* { margin: 0; padding: 0; box-sizing: border-box; }
body { background: #f0f2f5; display: flex; justify-content: center; align-items: flex-start; min-height: 100vh; padding: 20px; font-family: -apple-system, BlinkMacSystemFont, 'PingFang SC', 'Helvetica Neue', sans-serif; }
.phone-shell { width: 390px; height: 844px; background: #fff; border-radius: 44px; box-shadow: 0 20px 60px rgba(0,0,0,0.25), inset 0 0 0 2px #e0e0e0; overflow: hidden; position: relative; display: flex; flex-direction: column; flex-shrink: 0; }
.status-bar { height: 44px; background: #fff; display: flex; align-items: center; justify-content: space-between; padding: 0 24px; flex-shrink: 0; z-index: 10; }
.status-bar .time { font-size: 15px; font-weight: 700; color: #1a1a1a; }
.status-bar .icons { display: flex; gap: 6px; align-items: center; font-size: 12px; color: #1a1a1a; }
.nav-bar { height: 44px; display: flex; align-items: center; padding: 0 16px; background: #fff; border-bottom: 1px solid #f0f0f0; flex-shrink: 0; position: relative; }
.back-btn { display: flex; align-items: center; gap: 4px; color: #1677ff; font-size: 15px; cursor: pointer; background: none; border: none; padding: 4px 0; }
.nav-title { position: absolute; left: 50%; transform: translateX(-50%); font-size: 17px; font-weight: 600; color: #1a1a1a; white-space: nowrap; }
.scroll-content { flex: 1; overflow-y: auto; background: #f7f8fa; }
.scroll-content::-webkit-scrollbar { display: none; }
.btn-primary { background: #1677ff; color: #fff; border: none; border-radius: 10px; padding: 12px 24px; font-size: 15px; font-weight: 600; cursor: pointer; width: 100%; }
.modal-center { display: none; position: absolute; inset: 0; background: rgba(0,0,0,0.5); z-index: 200; align-items: center; justify-content: center; }
.modal-center.active { display: flex; }
.modal-box { width: 280px; background: #fff; border-radius: 16px; overflow: hidden; }
</style>
</head>
<body>
<div class="phone-shell">
<div class="status-bar">
<span class="time">9:41</span>
<div class="icons"><span>●●●</span><span>WiFi</span><span>🔋</span></div>
</div>
<div class="nav-bar">
<button class="back-btn" onclick="location.href='./index.html'">
<svg width="10" height="16" viewBox="0 0 10 16" fill="none" stroke="currentColor" stroke-width="2"><path d="M8 1L2 8l6 7"/></svg>返回
</button>
<span class="nav-title">修改密码</span>
</div>
<div class="scroll-content" style="padding:16px;">
<div style="background:#fff;border-radius:12px;overflow:hidden;box-shadow:0 1px 6px rgba(0,0,0,0.06);margin-bottom:20px;">
<div style="display:flex;align-items:center;padding:14px 16px;border-bottom:1px solid #f5f5f5;">
<span style="font-size:14px;color:#999;width:80px;flex-shrink:0;">当前密码</span>
<input type="password" placeholder="请输入当前密码" style="flex:1;border:none;font-size:14px;color:#1a1a1a;outline:none;text-align:right;" />
</div>
<div style="display:flex;align-items:center;padding:14px 16px;border-bottom:1px solid #f5f5f5;">
<span style="font-size:14px;color:#999;width:80px;flex-shrink:0;">新密码</span>
<input type="password" placeholder="请输入新密码" style="flex:1;border:none;font-size:14px;color:#1a1a1a;outline:none;text-align:right;" />
</div>
<div style="display:flex;align-items:center;padding:14px 16px;">
<span style="font-size:14px;color:#999;width:80px;flex-shrink:0;">确认新密码</span>
<input type="password" placeholder="再次输入新密码" style="flex:1;border:none;font-size:14px;color:#1a1a1a;outline:none;text-align:right;" />
</div>
</div>
<button onclick="openModal('modal-pwd-saved')" class="btn-primary">保存修改</button>
</div>
<div id="modal-pwd-saved" class="modal-center">
<div class="modal-box">
<div style="padding:20px 20px 8px;font-size:17px;font-weight:700;text-align:center;color:#1a1a1a;">修改成功</div>
<div style="padding:8px 20px 20px;font-size:14px;color:#666;text-align:center;line-height:1.6;">密码已更新,下次登录请使用新密码。</div>
<div style="display:flex;border-top:1px solid #f0f0f0;">
<button onclick="closeModal('modal-pwd-saved');location.href='./index.html'" style="flex:1;padding:14px;font-size:16px;cursor:pointer;background:none;border:none;color:#1677ff;font-weight:600;">确定</button>
</div>
</div>
</div>
</div>
<script>
function openModal(id) { var m = document.getElementById(id); if (m) m.classList.add('active'); }
function closeModal(id) { var m = document.getElementById(id); if (m) m.classList.remove('active'); }
sessionStorage.setItem('appRole', 'admin');
</script>
</body>
</html>
@@ -0,0 +1,111 @@
<!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>
* { margin: 0; padding: 0; box-sizing: border-box; }
body { background: #f0f2f5; display: flex; justify-content: center; align-items: flex-start; min-height: 100vh; padding: 20px; font-family: -apple-system, BlinkMacSystemFont, 'PingFang SC', 'Helvetica Neue', sans-serif; }
.phone-shell { width: 390px; height: 844px; background: #fff; border-radius: 44px; box-shadow: 0 20px 60px rgba(0,0,0,0.25), inset 0 0 0 2px #e0e0e0; overflow: hidden; position: relative; display: flex; flex-direction: column; flex-shrink: 0; }
.status-bar { height: 44px; background: #fff; display: flex; align-items: center; justify-content: space-between; padding: 0 24px; flex-shrink: 0; z-index: 10; }
.status-bar .time { font-size: 15px; font-weight: 700; color: #1a1a1a; }
.status-bar .icons { display: flex; gap: 6px; align-items: center; font-size: 12px; color: #1a1a1a; }
.nav-bar { height: 44px; display: flex; align-items: center; padding: 0 16px; background: #fff; border-bottom: 1px solid #f0f0f0; flex-shrink: 0; position: relative; }
.back-btn { display: flex; align-items: center; gap: 4px; color: #1677ff; font-size: 15px; cursor: pointer; background: none; border: none; padding: 4px 0; text-decoration: none; }
.nav-title { position: absolute; left: 50%; transform: translateX(-50%); font-size: 17px; font-weight: 600; color: #1a1a1a; white-space: nowrap; }
.scroll-content { flex: 1; overflow-y: auto; background: #f7f8fa; }
.scroll-content::-webkit-scrollbar { display: none; }
.avatar-section { display: flex; flex-direction: column; align-items: center; padding: 32px 0 24px; background: #fff; }
.avatar-wrap { position: relative; cursor: pointer; }
.avatar-img { width: 80px; height: 80px; border-radius: 50%; background: linear-gradient(135deg, #e6f4ff, #91caff); display: flex; align-items: center; justify-content: center; font-size: 40px; border: 3px solid #f0f0f0; }
.avatar-badge { position: absolute; bottom: 0; right: 0; width: 26px; height: 26px; background: #1677ff; border-radius: 50%; border: 2px solid #fff; display: flex; align-items: center; justify-content: center; }
.avatar-hint { font-size: 13px; color: #999; margin-top: 10px; }
.form-group { background: #fff; margin: 12px 16px; border-radius: 12px; overflow: hidden; box-shadow: 0 1px 6px rgba(0,0,0,0.06); }
.form-row { display: flex; align-items: center; padding: 16px; border-bottom: 1px solid #f5f5f5; }
.form-row:last-child { border-bottom: none; }
.form-label { font-size: 15px; color: #1a1a1a; width: 72px; flex-shrink: 0; }
.form-input { flex: 1; font-size: 15px; color: #1a1a1a; border: none; outline: none; background: transparent; text-align: right; }
.form-input::placeholder { color: #ccc; }
.bottom-action { padding: 16px; flex-shrink: 0; background: #f7f8fa; }
.btn-save { width: 100%; padding: 14px; background: linear-gradient(135deg, #1677ff, #0958d9); color: #fff; border: none; border-radius: 12px; font-size: 16px; font-weight: 600; cursor: pointer; }
.action-sheet-mask { display: none; position: absolute; inset: 0; background: rgba(0,0,0,0.5); z-index: 200; }
.action-sheet-mask.active { display: block; }
.action-sheet { position: absolute; bottom: 0; left: 0; right: 0; background: #fff; border-radius: 16px 16px 0 0; padding-bottom: 20px; z-index: 201; transform: translateY(100%); transition: transform 0.3s ease; }
.action-sheet-mask.active .action-sheet { transform: translateY(0); }
.action-sheet-item { padding: 16px; text-align: center; font-size: 16px; color: #1a1a1a; cursor: pointer; border-bottom: 1px solid #f5f5f5; }
.action-sheet-item:active { background: #f5f5f5; }
.action-sheet-cancel { padding: 16px; text-align: center; font-size: 16px; color: #999; cursor: pointer; margin-top: 8px; background: #f7f8fa; }
.toast { display: none; position: absolute; top: 50%; left: 50%; transform: translate(-50%,-50%); background: rgba(0,0,0,0.75); color: #fff; padding: 12px 24px; border-radius: 8px; font-size: 14px; z-index: 300; }
.toast.active { display: block; }
</style>
</head>
<body>
<div class="phone-shell">
<div class="status-bar">
<span class="time">9:41</span>
<div class="icons"><span>●●●</span><span>WiFi</span><span>🔋</span></div>
</div>
<div class="nav-bar">
<a href="./index.html" class="back-btn">
<svg width="10" height="16" viewBox="0 0 10 16" fill="none" stroke="currentColor" stroke-width="2"><path d="M8 1L2 8l6 7"/></svg>返回
</a>
<span class="nav-title">修改个人信息</span>
</div>
<div class="scroll-content">
<div class="avatar-section">
<div class="avatar-wrap" onclick="openSheet()">
<div class="avatar-img" id="avatarDisplay">👤</div>
<div class="avatar-badge">
<svg width="14" height="14" viewBox="0 0 14 14" fill="none" stroke="#fff" stroke-width="1.5"><path d="M7 3v8M3 7h8"/></svg>
</div>
</div>
<div class="avatar-hint">点击更换头像</div>
</div>
<div class="form-group">
<div class="form-row">
<span class="form-label">姓名</span>
<input class="form-input" id="inputName" type="text" value="王建国" placeholder="请输入姓名" />
</div>
</div>
</div>
<div class="bottom-action">
<button class="btn-save" onclick="handleSave()">保存</button>
</div>
<div id="avatarSheet" class="action-sheet-mask" onclick="closeSheet(event)">
<div class="action-sheet">
<div class="action-sheet-item" onclick="pickAvatar('camera')">拍照</div>
<div class="action-sheet-item" onclick="pickAvatar('album')">从相册选择</div>
<div class="action-sheet-cancel" onclick="closeSheet()">取消</div>
</div>
</div>
<div id="toast" class="toast">保存成功</div>
</div>
<script>
function openSheet() {
document.getElementById('avatarSheet').classList.add('active');
}
function closeSheet(e) {
if (!e || e.target.id === 'avatarSheet' || e.target.closest('.action-sheet-cancel')) {
document.getElementById('avatarSheet').classList.remove('active');
}
}
function pickAvatar(source) {
document.getElementById('avatarSheet').classList.remove('active');
showToast('已选择:' + (source === 'camera' ? '拍照' : '从相册选择'));
}
function handleSave() {
var name = document.getElementById('inputName').value.trim();
if (!name) { showToast('请输入姓名'); return; }
showToast('保存成功');
}
function showToast(msg) {
var t = document.getElementById('toast');
t.textContent = msg;
t.classList.add('active');
setTimeout(function() { t.classList.remove('active'); }, 1500);
}
sessionStorage.setItem('appRole', 'admin');
</script>
</body>
</html>
+85
View File
@@ -0,0 +1,85 @@
<!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>
* { margin: 0; padding: 0; box-sizing: border-box; }
body { background: #f0f2f5; display: flex; justify-content: center; align-items: flex-start; min-height: 100vh; padding: 20px; font-family: -apple-system, BlinkMacSystemFont, 'PingFang SC', 'Helvetica Neue', sans-serif; }
.phone-shell { width: 390px; height: 844px; background: #fff; border-radius: 44px; box-shadow: 0 20px 60px rgba(0,0,0,0.25), inset 0 0 0 2px #e0e0e0; overflow: hidden; position: relative; display: flex; flex-direction: column; flex-shrink: 0; }
.status-bar { height: 44px; background: transparent; display: flex; align-items: center; justify-content: space-between; padding: 0 24px; flex-shrink: 0; position: absolute; top: 0; left: 0; right: 0; z-index: 10; }
.status-bar .time { font-size: 15px; font-weight: 700; color: #fff; }
.status-bar .icons { display: flex; gap: 6px; align-items: center; font-size: 12px; color: #fff; }
.scroll-content { flex: 1; overflow-y: auto; background: #f7f8fa; }
.scroll-content::-webkit-scrollbar { display: none; }
.tab-bar { height: 83px; background: #fff; border-top: 1px solid #e8e8e8; display: flex; align-items: flex-start; padding-top: 8px; flex-shrink: 0; }
.tab-item { flex: 1; display: flex; flex-direction: column; align-items: center; gap: 4px; cursor: pointer; padding: 4px 0; position: relative; }
.tab-item .tab-icon { font-size: 22px; line-height: 1; }
.tab-item .tab-label { font-size: 10px; color: #999; font-weight: 500; }
.tab-item.active .tab-label { color: #1677ff; }
.tab-badge { position: absolute; top: 2px; right: 18px; background: #ff4d4f; color: #fff; font-size: 10px; font-weight: 700; min-width: 16px; height: 16px; border-radius: 8px; display: flex; align-items: center; justify-content: center; padding: 0 4px; }
.menu-card { background: #fff; border-radius: 12px; overflow: hidden; box-shadow: 0 1px 6px rgba(0,0,0,0.06); }
.menu-item { display: flex; align-items: center; padding: 16px; cursor: pointer; border-bottom: 1px solid #f5f5f5; }
.menu-item:last-child { border-bottom: none; }
.logout-btn { width: 100%; height: 48px; border: none; border-radius: 12px; background: #fff1f0; color: #ff4d4f; font-size: 15px; font-weight: 600; cursor: pointer; display: flex; align-items: center; justify-content: center; gap: 8px; box-shadow: 0 1px 6px rgba(0,0,0,0.06); }
.modal-center { display: none; position: absolute; inset: 0; background: rgba(0,0,0,0.5); z-index: 200; align-items: center; justify-content: center; }
.modal-center.active { display: flex; }
.modal-box { width: 280px; background: #fff; border-radius: 16px; overflow: hidden; }
</style>
</head>
<body>
<div class="phone-shell">
<div class="status-bar">
<span class="time">9:41</span>
<div class="icons"><span>●●●</span><span>WiFi</span><span>🔋</span></div>
</div>
<div style="background:linear-gradient(135deg,#1677ff,#0958d9);padding:60px 20px 24px;flex-shrink:0;">
<div style="display:flex;align-items:center;gap:16px;">
<div style="width:68px;height:68px;border-radius:50%;background:linear-gradient(135deg,#e6f4ff,#91caff);display:flex;align-items:center;justify-content:center;font-size:34px;border:3px solid rgba(255,255,255,0.5);">👤</div>
<div>
<div style="color:#fff;font-size:20px;font-weight:700;">王建国</div>
<div style="color:rgba(255,255,255,0.8);font-size:13px;margin-top:3px;">健康管理员</div>
<div style="color:rgba(255,255,255,0.78);font-size:12px;margin-top:4px;">安全环保部 · 健康管理科</div>
</div>
</div>
</div>
<div class="scroll-content" style="padding:12px 16px;">
<div class="menu-card">
<div class="menu-item" onclick="location.href='./edit-profile.html'"><span style="font-size:18px;margin-right:12px;">📝</span><span style="font-size:15px;color:#1a1a1a;flex:1;">修改个人信息</span><svg width="7" height="12" viewBox="0 0 7 12" fill="none" stroke="#ccc" stroke-width="1.5"><path d="M1 1l5 5-5 5"/></svg></div>
<div class="menu-item" onclick="location.href='./change-pwd.html'"><span style="font-size:18px;margin-right:12px;">🔒</span><span style="font-size:15px;color:#1a1a1a;flex:1;">修改密码</span><svg width="7" height="12" viewBox="0 0 7 12" fill="none" stroke="#ccc" stroke-width="1.5"><path d="M1 1l5 5-5 5"/></svg></div>
<div style="display:flex;align-items:center;padding:16px;cursor:pointer;">
<span style="font-size:18px;margin-right:12px;"></span><span style="font-size:15px;color:#1a1a1a;flex:1;">关于我们</span>
<svg width="7" height="12" viewBox="0 0 7 12" fill="none" stroke="#ccc" stroke-width="1.5"><path d="M1 1l5 5-5 5"/></svg>
</div>
</div>
<div style="margin-top:16px;">
<button class="logout-btn" onclick="openModal('modal-logout')">退出登录</button>
</div>
<div style="height:16px;"></div>
</div>
<div id="modal-logout" class="modal-center">
<div class="modal-box">
<div style="padding:20px 20px 8px;font-size:17px;font-weight:700;text-align:center;color:#1a1a1a;">退出登录</div>
<div style="padding:8px 20px 20px;font-size:14px;color:#666;text-align:center;line-height:1.6;">确认退出当前账号?</div>
<div style="display:flex;border-top:1px solid #f0f0f0;">
<button onclick="closeModal('modal-logout')" style="flex:1;padding:14px;font-size:16px;cursor:pointer;background:none;border:none;color:#666;border-right:1px solid #f0f0f0;">取消</button>
<button onclick="closeModal('modal-logout')" style="flex:1;padding:14px;font-size:16px;cursor:pointer;background:none;border:none;color:#ff4d4f;font-weight:600;">确认退出</button>
</div>
</div>
</div>
<div class="tab-bar">
<div class="tab-item" onclick="location.href='../workbench/index.html'"><span class="tab-icon">🏥</span><span class="tab-label">工作台</span><span class="tab-badge">3</span></div>
<div class="tab-item" onclick="location.href='../knowledge/index.html'"><span class="tab-icon">📚</span><span class="tab-label">知识库</span></div>
<div class="tab-item" onclick="location.href='../../ai-assistant/index.html'"><span class="tab-icon">🤖</span><span class="tab-label">AI助手</span></div>
<div class="tab-item" onclick="location.href='../../message/index.html'"><span class="tab-icon">💬</span><span class="tab-label">消息</span><span class="tab-badge">2</span></div>
<div class="tab-item active" onclick="location.href='./index.html'"><span class="tab-icon">👤</span><span class="tab-label">我的</span></div>
</div>
</div>
<script>
sessionStorage.setItem('appRole', 'admin');
function openModal(id) { var m = document.getElementById(id); if (m) m.classList.add('active'); }
function closeModal(id) { var m = document.getElementById(id); if (m) m.classList.remove('active'); }
</script>
</body>
</html>
@@ -0,0 +1,289 @@
<!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>
* { margin: 0; padding: 0; box-sizing: border-box; }
body { background: #f0f2f5; display: flex; justify-content: center; align-items: flex-start; min-height: 100vh; padding: 20px; font-family: -apple-system, BlinkMacSystemFont, 'PingFang SC', 'Helvetica Neue', sans-serif; }
.phone-shell { width: 390px; height: 844px; background: #fff; border-radius: 44px; box-shadow: 0 20px 60px rgba(0,0,0,0.25), inset 0 0 0 2px #e0e0e0; overflow: hidden; position: relative; display: flex; flex-direction: column; flex-shrink: 0; }
.status-bar { height: 44px; background: #fff; display: flex; align-items: center; justify-content: space-between; padding: 0 24px; flex-shrink: 0; z-index: 10; }
.status-bar .time { font-size: 15px; font-weight: 700; color: #1a1a1a; }
.status-bar .icons { display: flex; gap: 6px; align-items: center; font-size: 12px; color: #1a1a1a; }
.nav-bar { height: 44px; background: #fff; display: flex; align-items: center; padding: 0 16px; flex-shrink: 0; border-bottom: 1px solid #f0f0f0; position: relative; }
.nav-back { display: flex; align-items: center; gap: 4px; color: #1677ff; font-size: 15px; cursor: pointer; background: none; border: none; padding: 4px 0; }
.nav-title { position: absolute; left: 50%; transform: translateX(-50%); font-size: 17px; font-weight: 600; color: #1a1a1a; white-space: nowrap; }
.scroll-content { flex: 1; overflow-y: auto; background: #f7f8fa; }
.scroll-content::-webkit-scrollbar { display: none; }
/* 计划信息区 */
.plan-info { background: #fff; padding: 12px 16px; margin: 0; border-bottom: 1px solid #f0f0f0; }
.plan-title-row { display: flex; align-items: center; justify-content: space-between; margin-bottom: 8px; }
.plan-title-row__title { font-size: 14px; font-weight: 700; color: #1a1a1a; }
.plan-title-row__date { font-size: 12px; color: #666; }
.plan-select { display: flex; align-items: center; gap: 8px; padding: 8px 12px; background: #f7f8fa; border-radius: 8px; cursor: pointer; position: relative; border: 1px solid #e8e8e8; }
.plan-select__text { flex: 1; font-size: 14px; font-weight: 600; color: #1a1a1a; }
.plan-select__arrow { font-size: 12px; color: #bbb; transition: transform 0.2s; }
.plan-select__arrow.open { transform: rotate(180deg); }
.plan-meta { display: flex; gap: 0; margin-top: 10px; }
.plan-meta__item { flex: 1; text-align: center; padding: 0 4px; }
.plan-meta__item + .plan-meta__item { border-left: 1px solid #f0f0f0; }
.plan-meta__val { font-size: 15px; font-weight: 700; color: #1a1a1a; }
.plan-meta__label { font-size: 10px; color: #999; margin-top: 2px; }
/* 计划下拉面板 */
.plan-dropdown { display: none; position: absolute; top: 100%; left: 0; right: 0; background: #fff; border-radius: 8px; box-shadow: 0 4px 16px rgba(0,0,0,0.12); z-index: 50; margin-top: 4px; max-height: 200px; overflow-y: auto; }
.plan-dropdown.active { display: block; }
.plan-dropdown__item { padding: 10px 12px; font-size: 13px; color: #333; cursor: pointer; border-bottom: 1px solid #f5f5f5; }
.plan-dropdown__item:hover { background: #f7f8fa; }
.plan-dropdown__item.selected { background: #e6f4ff; color: #1677ff; font-weight: 600; }
/* Tab */
.seg-tabs { display: flex; background: #fff; border-bottom: 1px solid #f0f0f0; flex-shrink: 0; }
.seg-tab { flex: 1; text-align: center; padding: 12px 0; font-size: 13px; color: #666; cursor: pointer; border-bottom: 2px solid transparent; transition: all 0.2s; }
.seg-tab.active { color: #1677ff; border-bottom-color: #1677ff; font-weight: 600; }
.seg-tab .badge { display: inline-block; background: #e8e8e8; color: #666; font-size: 10px; font-weight: 700; min-width: 16px; height: 16px; border-radius: 8px; padding: 0 4px; margin-left: 4px; vertical-align: middle; line-height: 16px; }
.seg-tab.active .badge { background: #e6f4ff; color: #1677ff; }
/* 员工卡片 */
.employee-card { background: #fff; border-radius: 12px; margin: 10px 12px 0; padding: 14px; box-shadow: 0 1px 4px rgba(0,0,0,0.06); display: flex; align-items: center; gap: 10px; }
.employee-card__avatar { width: 44px; height: 44px; border-radius: 50%; background: linear-gradient(135deg, #e6f4ff, #b7d8ff); display: flex; align-items: center; justify-content: center; font-size: 20px; color: #1677ff; flex-shrink: 0; font-weight: 700; }
.employee-card__info { flex: 1; min-width: 0; }
.employee-card__name { font-size: 15px; font-weight: 600; color: #1a1a1a; }
.employee-card__meta { font-size: 12px; color: #999; margin-top: 3px; display: flex; gap: 8px; flex-wrap: wrap; }
.employee-card__meta span { white-space: nowrap; }
.employee-card__phone { font-size: 12px; color: #1677ff; flex-shrink: 0; white-space: nowrap; }
</style>
</head>
<body>
<div class="phone-shell">
<!-- 状态栏 -->
<div class="status-bar">
<span class="time">9:41</span>
<div class="icons"><span>●●●</span><span>WiFi</span><span>🔋</span></div>
</div>
<!-- 导航栏 -->
<!-- [交互] 点击返回工作台 -->
<div class="nav-bar">
<button class="nav-back" onclick="location.href='./index.html'">
<svg width="10" height="16" viewBox="0 0 10 16" fill="none" stroke="currentColor" stroke-width="2"><path d="M8 1L2 8l6 7"/></svg>返回
</button>
<span class="nav-title">体检进度跟踪</span>
</div>
<!-- 体检计划信息 -->
<div class="plan-info">
<!-- 标题行:当前计划 + 起止日期 -->
<div class="plan-title-row">
<span class="plan-title-row__title">体检计划</span>
<span class="plan-title-row__date" id="planDateRange">2026-04-01 至 2026-06-30</span>
</div>
<!-- [交互] 点击展开计划选择下拉 -->
<div class="plan-select" onclick="togglePlanDropdown()" style="position:relative;">
<span class="plan-select__text" id="planSelectText">2026年度员工健康体检</span>
<span class="plan-select__arrow" id="planSelectArrow"></span>
<div class="plan-dropdown" id="planDropdown">
<div class="plan-dropdown__item selected" onclick="selectPlan(event, '2026年度员工健康体检', '2026-04-01', '2026-06-30', '91', '120', '86', '78', '34', '42')">2026年度员工健康体检</div>
<div class="plan-dropdown__item" onclick="selectPlan(event, '2025年度员工健康体检', '2025-04-01', '2025-06-30', '91', '115', '115', '110', '0', '5')">2025年度员工健康体检</div>
<div class="plan-dropdown__item" onclick="selectPlan(event, '2025年职业病专项体检', '2025-09-01', '2025-10-31', '61', '45', '45', '45', '0', '0')">2025年职业病专项体检</div>
</div>
</div>
<!-- 统计指标:第一行 -->
<div class="plan-meta">
<div class="plan-meta__item">
<div class="plan-meta__val" id="planDays">91</div>
<div class="plan-meta__label">进行天数</div>
</div>
<div class="plan-meta__item">
<div class="plan-meta__val" id="planExpected">120</div>
<div class="plan-meta__label">应参检人数</div>
</div>
<div class="plan-meta__item">
<div class="plan-meta__val" id="planBooked" style="color:#1677ff;">86</div>
<div class="plan-meta__label">已预约人数</div>
</div>
</div>
<!-- 统计指标:第二行 -->
<div class="plan-meta" style="margin-top:6px;">
<div class="plan-meta__item">
<div class="plan-meta__val" id="planChecked" style="color:#52c41a;">78</div>
<div class="plan-meta__label">已参检人数</div>
</div>
<div class="plan-meta__item">
<div class="plan-meta__val" id="planUnbooked" style="color:#fa8c16;">34</div>
<div class="plan-meta__label">未预约人数</div>
</div>
<div class="plan-meta__item">
<div class="plan-meta__val" id="planUnchecked" style="color:#ff4d4f;">42</div>
<div class="plan-meta__label">未参检人数</div>
</div>
</div>
</div>
<!-- Tab:已预约 / 已参检 / 未预约 / 未参检 -->
<div class="seg-tabs">
<div class="seg-tab active" onclick="switchTab(this,'panel-booked')">已预约<span class="badge" id="badgeBooked">86</span></div>
<div class="seg-tab" onclick="switchTab(this,'panel-checked')">已参检<span class="badge" id="badgeChecked">78</span></div>
<div class="seg-tab" onclick="switchTab(this,'panel-unbooked')">未预约<span class="badge" id="badgeUnbooked">34</span></div>
<div class="seg-tab" onclick="switchTab(this,'panel-unchecked')">未参检<span class="badge" id="badgeUnchecked">42</span></div>
</div>
<div class="scroll-content">
<!-- 已预约列表 -->
<div id="panel-booked">
<!-- JS动态渲染 -->
</div>
<!-- 已参检列表 -->
<div id="panel-checked" style="display:none;">
<!-- JS动态渲染 -->
</div>
<!-- 未预约列表 -->
<div id="panel-unbooked" style="display:none;">
<!-- JS动态渲染 -->
</div>
<!-- 未参检列表 -->
<div id="panel-unchecked" style="display:none;">
<!-- JS动态渲染 -->
</div>
<div style="height:16px;"></div>
</div>
</div>
<script>
/* ===== Mock数据 ===== */
var bookedList = [
{ name:'张小红', empNo:'CQ001256', unit:'公司机关', dept:'办公室', phone:'13812346789' },
{ name:'李建国', empNo:'CQ000832', unit:'采油一厂', dept:'技术部', phone:'13923458901' },
{ name:'王芳', empNo:'CQ001103', unit:'信息技术中心', dept:'数据部', phone:'13634564567' },
{ name:'陈伟', empNo:'CQ000567', unit:'安全环保部', dept:'安环部', phone:'13545677890' },
{ name:'赵志强', empNo:'CQ000089', unit:'公司机关', dept:'后勤部', phone:'13756782345' },
{ name:'孙丽', empNo:'CQ001340', unit:'采油一厂', dept:'作业区', phone:'15867890123' },
{ name:'周明', empNo:'CQ000921', unit:'信息技术中心', dept:'技术部', phone:'18678903456' },
{ name:'刘海波', empNo:'CQ000234', unit:'公司机关', dept:'行政部', phone:'13389015678' }
];
var checkedList = [
{ name:'孙丽', empNo:'CQ001340', unit:'采油一厂', dept:'作业区', phone:'15867890123' },
{ name:'周明', empNo:'CQ000921', unit:'信息技术中心', dept:'技术部', phone:'18678903456' },
{ name:'吴静', empNo:'CQ001412', unit:'公司机关', dept:'人力部', phone:'15289016789' },
{ name:'黄晓明', empNo:'CQ000789', unit:'采油一厂', dept:'工程部', phone:'18990120123' },
{ name:'杨丽华', empNo:'CQ001098', unit:'安全环保部', dept:'安环部', phone:'13101234567' },
{ name:'郑国强', empNo:'CQ000456', unit:'公司机关', dept:'财务部', phone:'17712347890' },
{ name:'马燕', empNo:'CQ001521', unit:'信息技术中心', dept:'运维部', phone:'15023452345' },
{ name:'林伟东', empNo:'CQ000678', unit:'采油一厂', dept:'设备部', phone:'19934563456' }
];
var unbookedList = [
{ name:'何秀兰', empNo:'CQ001623', unit:'公司机关', dept:'后勤部', phone:'15545676789' },
{ name:'许建军', empNo:'CQ000345', unit:'安全环保部', dept:'监察部', phone:'13256788901' },
{ name:'蒋文博', empNo:'CQ001734', unit:'采油一厂', dept:'作业区', phone:'18867894567' },
{ name:'沈晓燕', empNo:'CQ000890', unit:'信息技术中心', dept:'开发部', phone:'13678905678' },
{ name:'韩磊', empNo:'CQ001845', unit:'公司机关', dept:'财务部', phone:'15789012345' },
{ name:'曹敏', empNo:'CQ000456', unit:'采油一厂', dept:'设备部', phone:'18590125678' },
{ name:'邓国栋', empNo:'CQ001956', unit:'安全环保部', dept:'安环部', phone:'17301233456' },
{ name:'彭丽娟', empNo:'CQ000567', unit:'公司机关', dept:'办公室', phone:'15912345678' }
];
var uncheckedList = [
{ name:'张小红', empNo:'CQ001256', unit:'公司机关', dept:'办公室', phone:'13812346789' },
{ name:'何秀兰', empNo:'CQ001623', unit:'公司机关', dept:'后勤部', phone:'15545676789' },
{ name:'许建军', empNo:'CQ000345', unit:'安全环保部', dept:'监察部', phone:'13256788901' },
{ name:'蒋文博', empNo:'CQ001734', unit:'采油一厂', dept:'作业区', phone:'18867894567' },
{ name:'曹敏', empNo:'CQ000456', unit:'采油一厂', dept:'设备部', phone:'18590125678' },
{ name:'邓国栋', empNo:'CQ001956', unit:'安全环保部', dept:'安环部', phone:'17301233456' },
{ name:'彭丽娟', empNo:'CQ000567', unit:'公司机关', dept:'办公室', phone:'15912345678' },
{ name:'冯志远', empNo:'CQ002067', unit:'信息技术中心', dept:'运维部', phone:'13423459012' }
];
/* ===== 头像取姓氏 ===== */
function getAvatarChar(name) {
return name.charAt(0);
}
/* ===== 渲染员工卡片 ===== */
function renderEmployeeCard(item) {
var html = '<div class="employee-card">';
html += ' <div class="employee-card__avatar">' + getAvatarChar(item.name) + '</div>';
html += ' <div class="employee-card__info">';
html += ' <div class="employee-card__name">' + item.name + ' <span style="font-weight:400;font-size:12px;color:#999;">' + item.empNo + '</span></div>';
html += ' <div class="employee-card__meta"><span>' + item.unit + '</span><span>' + item.dept + '</span></div>';
html += ' </div>';
html += ' <span class="employee-card__phone">' + item.phone + '</span>';
html += '</div>';
return html;
}
function renderList(listId, data) {
var html = '';
data.forEach(function(item) {
html += renderEmployeeCard(item);
});
document.getElementById(listId).innerHTML = html;
}
/* ===== Tab切换 ===== */
function switchTab(el, panelId) {
el.closest('.seg-tabs').querySelectorAll('.seg-tab').forEach(function(t) { t.classList.remove('active'); });
el.classList.add('active');
['panel-booked','panel-checked','panel-unbooked','panel-unchecked'].forEach(function(id) {
document.getElementById(id).style.display = id === panelId ? 'block' : 'none';
});
}
/* ===== 计划选择 ===== */
function togglePlanDropdown() {
var dd = document.getElementById('planDropdown');
var arrow = document.getElementById('planSelectArrow');
var isOpen = dd.classList.contains('active');
dd.classList.toggle('active');
if (isOpen) { arrow.classList.remove('open'); } else { arrow.classList.add('open'); }
}
function selectPlan(e, name, startDate, endDate, days, expected, booked, checked, unbooked, unchecked) {
e.stopPropagation();
document.getElementById('planSelectText').textContent = name;
document.getElementById('planDateRange').textContent = startDate + ' 至 ' + endDate;
document.getElementById('planDays').textContent = days;
document.getElementById('planExpected').textContent = expected;
document.getElementById('planBooked').textContent = booked;
document.getElementById('planChecked').textContent = checked;
document.getElementById('planUnbooked').textContent = unbooked;
document.getElementById('planUnchecked').textContent = unchecked;
// 更新Tab角标
document.getElementById('badgeBooked').textContent = booked;
document.getElementById('badgeChecked').textContent = checked;
document.getElementById('badgeUnbooked').textContent = unbooked;
document.getElementById('badgeUnchecked').textContent = unchecked;
// 更新下拉选中态
document.querySelectorAll('.plan-dropdown__item').forEach(function(item) {
item.classList.toggle('selected', item.textContent === name);
});
document.getElementById('planDropdown').classList.remove('active');
document.getElementById('planSelectArrow').classList.remove('open');
}
// 点击外部关闭下拉
document.addEventListener('click', function(e) {
if (!e.target.closest('.plan-select')) {
document.getElementById('planDropdown').classList.remove('active');
document.getElementById('planSelectArrow').classList.remove('open');
}
});
/* ===== 初始化 ===== */
renderList('panel-booked', bookedList);
renderList('panel-checked', checkedList);
renderList('panel-unbooked', unbookedList);
renderList('panel-unchecked', uncheckedList);
</script>
</body>
</html>
@@ -0,0 +1,198 @@
<!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>
* { margin: 0; padding: 0; box-sizing: border-box; }
body { background: #f0f2f5; display: flex; justify-content: center; align-items: flex-start; min-height: 100vh; padding: 20px; font-family: -apple-system, BlinkMacSystemFont, 'PingFang SC', 'Helvetica Neue', sans-serif; }
.phone-shell { width: 390px; height: 844px; background: #f7f8fa; border-radius: 44px; box-shadow: 0 20px 60px rgba(0,0,0,0.25), inset 0 0 0 2px #e0e0e0; overflow: hidden; position: relative; display: flex; flex-direction: column; flex-shrink: 0; }
.status-bar { height: 44px; background: #fff; display: flex; align-items: center; justify-content: space-between; padding: 0 24px; flex-shrink: 0; z-index: 10; }
.status-bar .time { font-size: 15px; font-weight: 700; color: #1a1a1a; }
.status-bar .icons { display: flex; gap: 6px; align-items: center; font-size: 12px; color: #1a1a1a; }
.nav-bar { height: 44px; background: #fff; display: flex; align-items: center; padding: 0 16px; flex-shrink: 0; border-bottom: 1px solid #f0f0f0; position: relative; }
.nav-back { display: flex; align-items: center; gap: 4px; color: #1677ff; font-size: 15px; cursor: pointer; background: none; border: none; padding: 4px 0; }
.nav-title { position: absolute; left: 50%; transform: translateX(-50%); font-size: 17px; font-weight: 600; color: #1a1a1a; white-space: nowrap; }
.scroll-content { flex: 1; overflow-y: auto; background: #f7f8fa; }
.scroll-content::-webkit-scrollbar { display: none; }
/* 员工信息 */
.emp-info { background: #fff; padding: 14px 16px; margin: 0; border-bottom: 1px solid #f0f0f0; }
.emp-info__name { font-size: 17px; font-weight: 700; color: #1a1a1a; }
.emp-info__meta { font-size: 12px; color: #999; margin-top: 4px; display: flex; gap: 8px; }
/* 数据对比卡片 */
.data-compare { background: #fff; border-radius: 12px; margin: 10px 12px 0; padding: 14px; box-shadow: 0 1px 4px rgba(0,0,0,0.06); }
.data-compare__title { font-size: 14px; font-weight: 700; color: #1a1a1a; margin-bottom: 10px; }
.data-compare__table { display: flex; gap: 0; }
.data-compare__col { flex: 1; text-align: center; }
.data-compare__col-label { font-size: 11px; color: #999; margin-bottom: 6px; font-weight: 600; }
.data-compare__row { font-size: 12px; color: #666; padding: 4px 0; border-bottom: 1px solid #f8f8f8; }
.data-compare__row:last-child { border-bottom: none; }
.data-compare__row .val { font-weight: 600; }
.data-compare__col--initial .val { color: #666; }
.data-compare__col--target .val { color: #52c41a; }
.data-compare__col--current .val { color: #1677ff; }
/* 变化指标 */
.change-row { display: flex; gap: 0; background: #fff; border-radius: 12px; margin: 10px 12px 0; padding: 10px 0; box-shadow: 0 1px 4px rgba(0,0,0,0.06); }
.change-item { flex: 1; text-align: center; }
.change-item + .change-item { border-left: 1px solid #f0f0f0; }
.change-item__val { font-size: 16px; font-weight: 700; }
.change-item__val--down { color: #52c41a; }
.change-item__val--up { color: #ff4d4f; }
.change-item__label { font-size: 10px; color: #999; margin-top: 2px; }
/* 饮食明细标题 */
.section-title { font-size: 14px; font-weight: 700; color: #1a1a1a; margin: 14px 12px 6px; }
/* 饮食明细卡片 */
.diet-card { background: #fff; border-radius: 12px; margin: 8px 12px 0; padding: 14px; box-shadow: 0 1px 4px rgba(0,0,0,0.06); }
.diet-card__head { display: flex; align-items: center; justify-content: space-between; margin-bottom: 8px; }
.diet-card__meal { font-size: 14px; font-weight: 600; color: #1a1a1a; }
.diet-card__time { font-size: 12px; color: #999; }
.diet-card__row { display: flex; justify-content: space-between; align-items: center; }
.diet-card__kcal { font-size: 16px; font-weight: 700; color: #fa8c16; }
.diet-card__kcal span { font-size: 12px; font-weight: 400; color: #999; }
.diet-card__source { font-size: 11px; }
.tag { display: inline-block; padding: 2px 8px; border-radius: 4px; font-size: 10px; font-weight: 600; }
.tag-blue { background: #e6f4ff; color: #1677ff; }
.tag-purple { background: #f9f0ff; color: #722ed1; }
</style>
</head>
<body>
<div class="phone-shell">
<div class="status-bar">
<span class="time">9:41</span>
<div class="icons"><span>●●●</span><span>WiFi</span><span>🔋</span></div>
</div>
<!-- 导航栏 -->
<!-- [交互] 点击返回饮食记录列表 -->
<div class="nav-bar">
<button class="nav-back" onclick="location.href='./eat-detail.html'">
<svg width="10" height="16" viewBox="0 0 10 16" fill="none" stroke="currentColor" stroke-width="2"><path d="M8 1L2 8l6 7"/></svg>返回
</button>
<span class="nav-title">饮食明细</span>
</div>
<div class="scroll-content">
<!-- 日期 -->
<div style="padding:10px 16px;background:#fff;border-bottom:1px solid #f0f0f0;font-size:14px;color:#333;font-weight:600;">2026-06-22</div>
<!-- 员工基本信息 -->
<div class="emp-info">
<div class="emp-info__name">张小红</div>
<div class="emp-info__meta">
<span></span><span>32岁</span><span>公司机关 · 办公室</span><span>身高 162cm</span>
</div>
</div>
<!-- 初始 / 目标 / 当前 -->
<div class="data-compare">
<div class="data-compare__title">数据对比</div>
<div class="data-compare__table">
<div class="data-compare__col data-compare__col--initial">
<div class="data-compare__col-label">初始</div>
<div class="data-compare__row">体重 <span class="val">72.5kg</span></div>
<div class="data-compare__row">BMI <span class="val">27.6</span></div>
<div class="data-compare__row">体脂 <span class="val">32.1%</span></div>
<div class="data-compare__row">腰围 <span class="val">86cm</span></div>
</div>
<div class="data-compare__col data-compare__col--target">
<div class="data-compare__col-label">目标</div>
<div class="data-compare__row">体重 <span class="val">62kg</span></div>
<div class="data-compare__row">BMI <span class="val">23.6</span></div>
<div class="data-compare__row">体脂 <span class="val">26%</span></div>
<div class="data-compare__row">腰围 <span class="val">76cm</span></div>
</div>
<div class="data-compare__col data-compare__col--current">
<div class="data-compare__col-label">当前</div>
<div class="data-compare__row">体重 <span class="val">67.2kg</span></div>
<div class="data-compare__row">BMI <span class="val">25.6</span></div>
<div class="data-compare__row">体脂 <span class="val">29.5%</span></div>
<div class="data-compare__row">腰围 <span class="val">81cm</span></div>
</div>
</div>
</div>
<!-- 变化指标 -->
<div class="change-row">
<div class="change-item">
<div class="change-item__val change-item__val--down">-5.3kg</div>
<div class="change-item__label">体重变化</div>
</div>
<div class="change-item">
<div class="change-item__val change-item__val--down">-2.0</div>
<div class="change-item__label">BMI变化</div>
</div>
<div class="change-item">
<div class="change-item__val change-item__val--down">-2.6%</div>
<div class="change-item__label">体脂变化</div>
</div>
<div class="change-item">
<div class="change-item__val change-item__val--down">-5cm</div>
<div class="change-item__label">腰围变化</div>
</div>
</div>
<!-- 当日饮食明细 -->
<div class="section-title">当日饮食明细</div>
<!-- 早餐 -->
<div class="diet-card">
<div class="diet-card__head">
<span class="diet-card__meal">🥣 早餐</span>
<span class="diet-card__time">摄入时间:2026-06-22 07:30:00</span>
</div>
<div class="diet-card__row">
<div class="diet-card__kcal">486 <span>kcal</span></div>
<span class="tag tag-blue">智记</span>
</div>
</div>
<!-- 午餐 -->
<div class="diet-card">
<div class="diet-card__head">
<span class="diet-card__meal">🍱 午餐</span>
<span class="diet-card__time">摄入时间:2026-06-22 12:15:00</span>
</div>
<div class="diet-card__row">
<div class="diet-card__kcal">720 <span>kcal</span></div>
<span class="tag tag-blue">智记</span>
</div>
</div>
<!-- 下午加餐 -->
<div class="diet-card">
<div class="diet-card__head">
<span class="diet-card__meal">🍎 加餐</span>
<span class="diet-card__time">摄入时间:2026-06-22 15:40:00</span>
</div>
<div class="diet-card__row">
<div class="diet-card__kcal">185 <span>kcal</span></div>
<span class="tag tag-purple">自记</span>
</div>
</div>
<!-- 晚餐 -->
<div class="diet-card">
<div class="diet-card__head">
<span class="diet-card__meal">🍽️ 晚餐</span>
<span class="diet-card__time">摄入时间:2026-06-22 18:30:00</span>
</div>
<div class="diet-card__row">
<div class="diet-card__kcal">560 <span>kcal</span></div>
<span class="tag tag-blue">智记</span>
</div>
</div>
<div style="height:20px;"></div>
</div>
</div>
</body>
</html>
@@ -0,0 +1,253 @@
<!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>
* { margin: 0; padding: 0; box-sizing: border-box; }
body { background: #f0f2f5; display: flex; justify-content: center; align-items: flex-start; min-height: 100vh; padding: 20px; font-family: -apple-system, BlinkMacSystemFont, 'PingFang SC', 'Helvetica Neue', sans-serif; }
.phone-shell { width: 390px; height: 844px; background: #fff; border-radius: 44px; box-shadow: 0 20px 60px rgba(0,0,0,0.25), inset 0 0 0 2px #e0e0e0; overflow: hidden; position: relative; display: flex; flex-direction: column; flex-shrink: 0; }
.status-bar { height: 44px; background: #fff; display: flex; align-items: center; justify-content: space-between; padding: 0 24px; flex-shrink: 0; z-index: 10; }
.status-bar .time { font-size: 15px; font-weight: 700; color: #1a1a1a; }
.status-bar .icons { display: flex; gap: 6px; align-items: center; font-size: 12px; color: #1a1a1a; }
.nav-bar { height: 44px; background: #fff; display: flex; align-items: center; padding: 0 16px; flex-shrink: 0; border-bottom: 1px solid #f0f0f0; position: relative; }
.nav-back { display: flex; align-items: center; gap: 4px; color: #1677ff; font-size: 15px; cursor: pointer; background: none; border: none; padding: 4px 0; }
.nav-title { position: absolute; left: 50%; transform: translateX(-50%); font-size: 17px; font-weight: 600; color: #1a1a1a; white-space: nowrap; }
.scroll-content { flex: 1; overflow-y: auto; background: #f7f8fa; }
.scroll-content::-webkit-scrollbar { display: none; }
/* 日期导航 */
.date-nav { display: flex; align-items: center; justify-content: center; gap: 8px; padding: 10px 16px; background: #fff; border-bottom: 1px solid #f0f0f0; position: relative; }
.date-nav__arrow { width: 32px; height: 32px; border-radius: 50%; background: #f5f5f5; display: flex; align-items: center; justify-content: center; cursor: pointer; border: none; color: #666; font-size: 16px; flex-shrink: 0; }
.date-nav__arrow:active { background: #e6f4ff; }
.date-nav__text { font-size: 15px; font-weight: 600; color: #1a1a1a; min-width: 110px; text-align: center; }
.date-nav__cal { width: 28px; height: 28px; border-radius: 6px; background: none; display: flex; align-items: center; justify-content: center; cursor: pointer; border: none; font-size: 16px; flex-shrink: 0; color: #1677ff; }
.date-nav__cal:active { background: #e6f4ff; }
/* 日历面板 */
.cal-panel { display: none; position: absolute; top: 42px; left: 16px; right: 16px; background: #fff; border-radius: 14px; box-shadow: 0 8px 30px rgba(0,0,0,0.15); z-index: 100; padding: 16px; }
.cal-panel.active { display: block; }
.cal-panel__head { display: flex; align-items: center; justify-content: space-between; margin-bottom: 12px; }
.cal-panel__month { font-size: 15px; font-weight: 700; color: #1a1a1a; }
.cal-panel__nav { width: 28px; height: 28px; border-radius: 50%; border: none; background: #f5f5f5; cursor: pointer; font-size: 14px; color: #666; display: flex; align-items: center; justify-content: center; }
.cal-panel__nav:active { background: #e6f4ff; }
.cal-panel__weekdays { display: flex; margin-bottom: 6px; }
.cal-panel__weekday { flex: 1; text-align: center; font-size: 11px; color: #999; padding: 4px 0; }
.cal-panel__grid { display: flex; flex-wrap: wrap; }
.cal-panel__day { width: calc(100% / 7); text-align: center; padding: 8px 0; font-size: 13px; color: #333; cursor: pointer; border-radius: 8px; }
.cal-panel__day--other { color: #ddd; }
.cal-panel__day:hover { background: #f5f5f5; }
.cal-panel__day--today { font-weight: 700; color: #1677ff; }
.cal-panel__day--selected { background: #1677ff; color: #fff; font-weight: 700; }
.cal-panel__day--selected:hover { background: #1677ff; }
/* Tab */
.seg-tabs { display: flex; background: #fff; border-bottom: 1px solid #f0f0f0; flex-shrink: 0; }
.seg-tab { flex: 1; text-align: center; padding: 12px 0; font-size: 14px; color: #666; cursor: pointer; border-bottom: 2px solid transparent; transition: all 0.2s; }
.seg-tab.active { color: #1677ff; border-bottom-color: #1677ff; font-weight: 600; }
.seg-tab .badge { display: inline-block; background: #e8e8e8; color: #666; font-size: 10px; font-weight: 700; min-width: 16px; height: 16px; border-radius: 8px; padding: 0 4px; margin-left: 4px; vertical-align: middle; line-height: 16px; }
.seg-tab.active .badge { background: #e6f4ff; color: #1677ff; }
/* 员工卡片 */
.employee-card { background: #fff; border-radius: 12px; margin: 10px 12px 0; padding: 14px; box-shadow: 0 1px 4px rgba(0,0,0,0.06); display: flex; align-items: center; gap: 10px; cursor: pointer; }
.employee-card:active { transform: scale(0.98); }
.employee-card__info { flex: 1; min-width: 0; }
.employee-card__name { font-size: 15px; font-weight: 600; color: #1a1a1a; }
.employee-card__meta { font-size: 12px; color: #999; margin-top: 3px; display: flex; gap: 8px; flex-wrap: wrap; }
.employee-card__arrow { font-size: 12px; color: #1677ff; flex-shrink: 0; white-space: nowrap; }
</style>
</head>
<body>
<div class="phone-shell">
<!-- 状态栏 -->
<div class="status-bar">
<span class="time">9:41</span>
<div class="icons"><span>●●●</span><span>WiFi</span><span>🔋</span></div>
</div>
<!-- 导航栏 -->
<!-- [交互] 点击返回体重管理详情 -->
<div class="nav-bar">
<button class="nav-back" onclick="location.href='./weight-detail.html'">
<svg width="10" height="16" viewBox="0 0 10 16" fill="none" stroke="currentColor" stroke-width="2"><path d="M8 1L2 8l6 7"/></svg>返回
</button>
<span class="nav-title">饮食记录</span>
</div>
<!-- 日期导航 -->
<div class="date-nav">
<button class="date-nav__arrow" onclick="changeDate(-1)"></button>
<!-- [交互] 点击日历图标打开日期选择面板 -->
<button class="date-nav__cal" onclick="toggleCalPanel()">📅</button>
<span class="date-nav__text" id="dateText">2026-06-22</span>
<button class="date-nav__arrow" onclick="changeDate(1)"></button>
<!-- 日历选择面板 -->
<div class="cal-panel" id="calPanel">
<div class="cal-panel__head">
<button class="cal-panel__nav" onclick="calPrevMonth(event)"></button>
<span class="cal-panel__month" id="calMonthLabel">2026年6月</span>
<button class="cal-panel__nav" onclick="calNextMonth(event)"></button>
</div>
<div class="cal-panel__weekdays">
<div class="cal-panel__weekday"></div><div class="cal-panel__weekday"></div><div class="cal-panel__weekday"></div><div class="cal-panel__weekday"></div><div class="cal-panel__weekday"></div><div class="cal-panel__weekday"></div><div class="cal-panel__weekday"></div>
</div>
<div class="cal-panel__grid" id="calGrid"></div>
</div>
</div>
<!-- Tab:已记录 / 未记录 -->
<div class="seg-tabs">
<div class="seg-tab active" onclick="switchTab(this,'panel-recorded')">已记录<span class="badge" id="badgeRecorded">78</span></div>
<div class="seg-tab" onclick="switchTab(this,'panel-unrecorded')">未记录<span class="badge" id="badgeUnrecorded">8</span></div>
</div>
<div class="scroll-content">
<!-- 已记录列表 -->
<div id="panel-recorded">
<!-- JS动态渲染 -->
</div>
<!-- 未记录列表 -->
<div id="panel-unrecorded" style="display:none;">
<!-- JS动态渲染 -->
</div>
<div style="height:16px;"></div>
</div>
</div>
<script>
/* ===== Mock数据 ===== */
var recordedList = [
{ name:'张小红', gender:'女', age:32, dept:'公司机关 · 办公室', height:162 },
{ name:'李建国', gender:'男', age:45, dept:'采油一厂 · 技术部', height:175 },
{ name:'王芳', gender:'女', age:28, dept:'信息技术中心 · 数据部', height:160 },
{ name:'陈伟', gender:'男', age:36, dept:'安全环保部 · 安环部', height:178 },
{ name:'赵志强', gender:'男', age:61, dept:'公司机关 · 后勤部', height:170 },
{ name:'孙丽', gender:'女', age:41, dept:'采油一厂 · 作业区', height:158 },
{ name:'周明', gender:'男', age:33, dept:'信息技术中心 · 技术部', height:182 },
{ name:'刘海波', gender:'男', age:55, dept:'公司机关 · 行政部', height:168 }
];
var unrecordedList = [
{ name:'吴静', gender:'女', age:26, dept:'公司机关 · 人力部', height:165 },
{ name:'黄晓明', gender:'男', age:42, dept:'采油一厂 · 工程部', height:176 },
{ name:'杨丽华', gender:'女', age:39, dept:'安全环保部 · 安环部', height:163 },
{ name:'郑国强', gender:'男', age:50, dept:'公司机关 · 财务部', height:172 },
{ name:'马燕', gender:'女', age:35, dept:'信息技术中心 · 运维部', height:159 },
{ name:'林伟东', gender:'男', age:44, dept:'采油一厂 · 设备部', height:180 },
{ name:'何秀兰', gender:'女', age:47, dept:'公司机关 · 后勤部', height:161 },
{ name:'许建军', gender:'男', age:31, dept:'安全环保部 · 监察部', height:174 }
];
/* ===== Tab切换 ===== */
function switchTab(el, panelId) {
el.closest('.seg-tabs').querySelectorAll('.seg-tab').forEach(function(t) { t.classList.remove('active'); });
el.classList.add('active');
['panel-recorded','panel-unrecorded'].forEach(function(id) {
document.getElementById(id).style.display = id === panelId ? 'block' : 'none';
});
}
/* ===== 渲染列表 ===== */
function renderRecordedList() {
var html = '';
recordedList.forEach(function(item) {
html += '<div class="employee-card" onclick="location.href=\'./diet-employee-detail.html\'">';
html += ' <div class="employee-card__info">';
html += ' <div class="employee-card__name">' + item.name + '</div>';
html += ' <div class="employee-card__meta"><span>' + item.gender + '</span><span>' + item.age + '岁</span><span>' + item.dept + '</span><span>身高 ' + item.height + 'cm</span></div>';
html += ' </div>';
html += ' <span class="employee-card__arrow">记录明细 </span>';
html += '</div>';
});
document.getElementById('panel-recorded').innerHTML = html;
}
function renderUnrecordedList() {
var html = '';
unrecordedList.forEach(function(item) {
html += '<div class="employee-card">';
html += ' <div class="employee-card__info">';
html += ' <div class="employee-card__name">' + item.name + '</div>';
html += ' <div class="employee-card__meta"><span>' + item.gender + '</span><span>' + item.age + '岁</span><span>' + item.dept + '</span><span>身高 ' + item.height + 'cm</span></div>';
html += ' </div>';
html += '</div>';
});
document.getElementById('panel-unrecorded').innerHTML = html;
}
/* ===== 日期导航 ===== */
var currentDate = new Date(2026, 5, 22);
var calViewYear = currentDate.getFullYear();
var calViewMonth = currentDate.getMonth();
function changeDate(delta) {
currentDate.setDate(currentDate.getDate() + delta);
calViewYear = currentDate.getFullYear();
calViewMonth = currentDate.getMonth();
renderDate();
}
function renderDate() {
var y = currentDate.getFullYear();
var m = String(currentDate.getMonth() + 1).padStart(2, '0');
var d = String(currentDate.getDate()).padStart(2, '0');
document.getElementById('dateText').textContent = y + '-' + m + '-' + d;
}
/* ===== 日历面板 ===== */
function toggleCalPanel() {
var panel = document.getElementById('calPanel');
if (panel.classList.contains('active')) { panel.classList.remove('active'); return; }
calViewYear = currentDate.getFullYear();
calViewMonth = currentDate.getMonth();
renderCal();
panel.classList.add('active');
}
function calPrevMonth(e) { e.stopPropagation(); calViewMonth--; if (calViewMonth < 0) { calViewMonth = 11; calViewYear--; } renderCal(); }
function calNextMonth(e) { e.stopPropagation(); calViewMonth++; if (calViewMonth > 11) { calViewMonth = 0; calViewYear++; } renderCal(); }
function renderCal() {
document.getElementById('calMonthLabel').textContent = calViewYear + '年' + (calViewMonth + 1) + '月';
var firstDay = new Date(calViewYear, calViewMonth, 1).getDay();
var daysInMonth = new Date(calViewYear, calViewMonth + 1, 0).getDate();
var today = new Date();
var html = '';
for (var i = 0; i < firstDay; i++) { html += '<div class="cal-panel__day cal-panel__day--other"></div>'; }
for (var d = 1; d <= daysInMonth; d++) {
var cls = 'cal-panel__day';
if (calViewYear === today.getFullYear() && calViewMonth === today.getMonth() && d === today.getDate()) cls += ' cal-panel__day--today';
if (calViewYear === currentDate.getFullYear() && calViewMonth === currentDate.getMonth() && d === currentDate.getDate()) cls += ' cal-panel__day--selected';
html += '<div class="' + cls + '" onclick="selectCalDay(event,' + d + ')">' + d + '</div>';
}
document.getElementById('calGrid').innerHTML = html;
}
function selectCalDay(e, day) {
e.stopPropagation();
currentDate = new Date(calViewYear, calViewMonth, day);
calViewYear = currentDate.getFullYear();
calViewMonth = currentDate.getMonth();
renderDate();
renderCal();
document.getElementById('calPanel').classList.remove('active');
}
document.addEventListener('click', function(e) {
if (!e.target.closest('.date-nav') && !e.target.closest('.cal-panel')) {
document.getElementById('calPanel').classList.remove('active');
}
});
/* 初始化 */
renderRecordedList();
renderUnrecordedList();
</script>
</body>
</html>
@@ -0,0 +1,263 @@
<!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>
* { margin: 0; padding: 0; box-sizing: border-box; }
body { background: #f0f2f5; display: flex; justify-content: center; align-items: flex-start; min-height: 100vh; padding: 20px; font-family: -apple-system, BlinkMacSystemFont, 'PingFang SC', 'Helvetica Neue', sans-serif; }
.phone-shell { width: 390px; height: 844px; background: #fff; border-radius: 44px; box-shadow: 0 20px 60px rgba(0,0,0,0.25), inset 0 0 0 2px #e0e0e0; overflow: hidden; position: relative; display: flex; flex-direction: column; flex-shrink: 0; }
.status-bar { height: 44px; background: #fff; display: flex; align-items: center; justify-content: space-between; padding: 0 24px; flex-shrink: 0; }
.status-bar .time { font-size: 15px; font-weight: 700; color: #1a1a1a; }
.status-bar .icons { display: flex; gap: 6px; align-items: center; font-size: 12px; color: #1a1a1a; }
.nav-bar { height: 44px; display: flex; align-items: center; padding: 0 16px; background: #fff; border-bottom: 1px solid #f0f0f0; flex-shrink: 0; position: relative; }
.back-btn { display: flex; align-items: center; gap: 4px; color: #1677ff; font-size: 15px; cursor: pointer; background: none; border: none; padding: 4px 0; }
.nav-title { position: absolute; left: 50%; transform: translateX(-50%); font-size: 17px; font-weight: 600; color: #1a1a1a; white-space: nowrap; }
.scroll-content { flex: 1; overflow-y: auto; background: #f7f8fa; }
.scroll-content::-webkit-scrollbar { display: none; }
.card { background: #fff; border-radius: 12px; margin: 12px 16px 0; box-shadow: 0 1px 4px rgba(0,0,0,0.06); overflow: hidden; }
.card__header { display: flex; align-items: center; justify-content: space-between; gap: 12px; padding: 16px; border-bottom: 1px solid #f0f0f0; cursor: pointer; }
.card__title { font-size: 15px; font-weight: 700; color: #1a1a1a; }
.card__toggle { display: inline-flex; align-items: center; gap: 4px; color: #1677ff; font-size: 12px; font-weight: 600; }
.card__arrow { width: 14px; height: 14px; transition: transform .2s ease; }
.card__body { padding: 0 16px 16px; }
.card--collapsed .card__body { display: none; }
.card--collapsed .card__arrow { transform: rotate(-90deg); }
.card--collapsed .card__header { border-bottom: none; }
.card__tag { display: inline-flex; align-items: center; gap: 4px; padding: 3px 10px; border-radius: 999px; font-size: 11px; font-weight: 600; color: #1677ff; background: #e6f4ff; }
.info-item { display: flex; font-size: 13px; line-height: 1.6; padding: 5px 0; }
.info-item__label { color: #999; min-width: 72px; flex-shrink: 0; }
.info-item__value { color: #333; flex: 1; word-break: break-all; }
.tag { display: inline-block; padding: 2px 8px; border-radius: 4px; font-size: 11px; font-weight: 600; }
.tag-green { background: #f6ffed; color: #52c41a; }
.location-link { color: #1677ff; display: inline-flex; align-items: center; gap: 3px; }
.desc-block { padding: 6px 0; }
.desc-block__label { font-size: 13px; color: #999; margin-bottom: 6px; }
.desc-block__text { font-size: 13px; color: #333; line-height: 1.8; }
.form-textarea, .form-input { width: 100%; border: 1px solid #d9d9d9; border-radius: 10px; padding: 10px 12px; font-size: 13px; color: #333; background: #fff; outline: none; }
.form-textarea:focus, .form-input:focus { border-color: #1677ff; box-shadow: 0 0 0 2px rgba(22,119,255,0.12); }
.form-textarea { min-height: 82px; resize: none; line-height: 1.7; }
.form-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; }
.photo-list { display: flex; gap: 8px; flex-wrap: wrap; margin-top: 2px; }
.photo-item { width: 90px; height: 68px; border-radius: 8px; background: linear-gradient(135deg, #e6f7ff, #bae7ff); border: 1px solid #d9d9d9; position: relative; overflow: hidden; display: flex; align-items: center; justify-content: center; font-size: 10px; color: #1677ff; }
.photo-item__mask { position: absolute; inset: auto 0 0 0; background: rgba(0,0,0,0.42); color: #fff; font-size: 10px; text-align: center; padding: 3px 0; }
.photo-item__delete { position: absolute; top: -1px; right: -1px; width: 18px; height: 18px; border-radius: 50%; background: #ff4d4f; color: #fff; font-size: 12px; line-height: 18px; text-align: center; cursor: pointer; z-index: 2; box-shadow: 0 1px 3px rgba(0,0,0,0.2); }
.photo-add { width: 90px; height: 68px; border-radius: 8px; border: 1px dashed #91caff; background: #f7fbff; color: #1677ff; font-size: 12px; cursor: pointer; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 4px; }
.photo-add span:first-child { font-size: 18px; line-height: 1; }
.result-toolbar, .summary-toolbar { display: flex; justify-content: space-between; align-items: center; margin-bottom: 8px; }
.result-action-btn { height: 30px; padding: 0 12px; border: none; border-radius: 8px; background: #e6f4ff; color: #1677ff; font-size: 12px; font-weight: 600; cursor: pointer; }
.result-empty { border: 1px dashed #d9d9d9; border-radius: 10px; background: #fafafa; color: #999; font-size: 13px; line-height: 1.7; padding: 12px; }
.result-filled { border: 1px solid #e8e8e8; border-radius: 10px; background: #fafafa; color: #333; font-size: 13px; line-height: 1.7; padding: 12px; white-space: pre-line; }
.summary-toolbar { display: flex; justify-content: space-between; align-items: center; margin-bottom: 8px; }
.summary-add-btn, .summary-edit-btn { border: none; border-radius: 8px; font-size: 12px; cursor: pointer; }
.summary-add-btn { height: 30px; padding: 0 12px; background: #e6f4ff; color: #1677ff; font-weight: 600; }
.summary-list { display: flex; flex-direction: column; gap: 8px; }
.summary-item { border: 1px solid #e8e8e8; border-radius: 10px; background: #fafafa; padding: 10px 12px; }
.summary-item__top { display: flex; justify-content: space-between; align-items: center; gap: 8px; margin-bottom: 6px; }
.summary-item__idx { font-size: 12px; font-weight: 600; color: #1677ff; }
.summary-edit-btn { height: 26px; padding: 0 10px; background: #fff; color: #666; border: 1px solid #d9d9d9; }
.summary-delete-btn { height: 26px; padding: 0 10px; background: #fff; color: #ff4d4f; border: 1px solid #ffa39e; border-radius: 8px; font-size: 12px; cursor: pointer; }
.summary-item__text { font-size: 13px; color: #333; line-height: 1.7; white-space: pre-line; }
.action-row { display: flex; justify-content: flex-end; margin-top: 12px; }
.save-btn { height: 36px; border: none; border-radius: 8px; background: #1677ff; color: #fff; font-size: 13px; font-weight: 600; padding: 0 18px; cursor: pointer; }
.tip-text { margin-top: 8px; font-size: 12px; color: #999; line-height: 1.6; }
.dialog-mask { position: absolute; inset: 0; background: rgba(0,0,0,0.45); display: none; align-items: center; justify-content: center; padding: 20px; z-index: 30; }
.dialog-mask.show { display: flex; }
.dialog { width: 100%; background: #fff; border-radius: 16px; overflow: hidden; box-shadow: 0 16px 40px rgba(0,0,0,0.18); }
.dialog__header { padding: 16px 18px 10px; font-size: 16px; font-weight: 700; color: #1a1a1a; }
.dialog__body { padding: 0 18px 18px; }
.dialog__hint { font-size: 12px; color: #999; line-height: 1.6; margin-bottom: 10px; }
.dialog__footer { display: flex; border-top: 1px solid #f0f0f0; }
.dialog__btn { flex: 1; height: 46px; border: none; background: #fff; font-size: 14px; cursor: pointer; }
.dialog__btn + .dialog__btn { border-left: 1px solid #f0f0f0; }
.dialog__btn--primary { color: #1677ff; font-weight: 600; }
.ambulance-toolbar { display: flex; justify-content: space-between; align-items: center; margin-bottom: 8px; }
.ambulance-action-btn { height: 30px; padding: 0 12px; border: none; border-radius: 8px; background: #e6f4ff; color: #1677ff; font-size: 12px; font-weight: 600; cursor: pointer; }
.ambulance-display { border: 1px solid #e8e8e8; border-radius: 10px; background: #fafafa; padding: 12px; }
.ambulance-display__row { display: flex; gap: 8px; margin-bottom: 6px; font-size: 13px; line-height: 1.7; }
.ambulance-display__row:last-child { margin-bottom: 0; }
.ambulance-display__label { width: 72px; flex-shrink: 0; color: #999; }
.ambulance-display__value { flex: 1; color: #333; }
.option-list { display: flex; flex-direction: column; gap: 8px; margin-bottom: 12px; }
.option-item { display: flex; align-items: center; gap: 10px; padding: 10px 12px; border: 1px solid #e8e8e8; border-radius: 10px; background: #fff; cursor: pointer; }
.option-item.selected { border-color: #1677ff; background: #f0f7ff; }
.option-item.is-hidden { display: none; }
.option-item__check { width: 18px; height: 18px; border-radius: 50%; border: 2px solid #d9d9d9; flex-shrink: 0; display: flex; align-items: center; justify-content: center; }
.option-item.selected .option-item__check { border-color: #1677ff; background: #1677ff; }
.option-item.selected .option-item__check::after { content: '✓'; color: #fff; font-size: 11px; font-weight: 700; }
.option-item__main { flex: 1; min-width: 0; }
.option-item__title { font-size: 13px; font-weight: 600; color: #1a1a1a; }
.option-item__meta { margin-top: 2px; font-size: 12px; color: #999; }
.option-item__dist { font-size: 12px; color: #1677ff; font-weight: 600; flex-shrink: 0; }
.search-box { margin-bottom: 10px; }
.search-input { width: 100%; height: 36px; border: 1px solid #d9d9d9; border-radius: 8px; padding: 0 12px 0 36px; font-size: 13px; color: #333; background: #fff url('data:image/svg+xml,%3Csvg xmlns=%22http://www.w3.org/2000/svg%22 width=%2214%22 height=%2214%22 fill=%22none%22%3E%3Ccircle cx=%226%22 cy=%226%22 r=%224%22 stroke=%22%23999%22 stroke-width=%221.4%22/%3E%3Cpath d=%22M10 10l2.5 2.5%22 stroke=%22%23999%22 stroke-width=%221.4%22 stroke-linecap=%22round%22/%3E%3C/svg%3E') no-repeat 12px center; outline: none; }
.search-input:focus { border-color: #1677ff; }
.dialog-field { margin-bottom: 12px; }
.dialog-field:last-child { margin-bottom: 0; }
.dialog-field__label { font-size: 12px; color: #666; margin-bottom: 4px; }
.dialog-field__input { width: 100%; height: 36px; border: 1px solid #d9d9d9; border-radius: 8px; padding: 0 12px; font-size: 13px; color: #333; outline: none; }
.dialog-field__input:focus { border-color: #1677ff; }
.dialog-field__textarea { width: 100%; min-height: 60px; border: 1px solid #d9d9d9; border-radius: 8px; padding: 8px 12px; font-size: 13px; color: #333; outline: none; resize: none; font-family: inherit; line-height: 1.6; }
.dialog-field__textarea:focus { border-color: #1677ff; }
</style>
</head>
<body>
<div class="phone-shell">
<div class="status-bar">
<span class="time">9:41</span>
<div class="icons"><span>●●●</span><span>WiFi</span><span>🔋</span></div>
</div>
<div class="nav-bar">
<!-- [交互] 点击返回应急求助工单列表 -->
<button class="back-btn" onclick="location.href='./emergency-orders.html'">
<svg width="10" height="16" viewBox="0 0 10 16" fill="none" stroke="currentColor" stroke-width="2"><path d="M8 1L2 8l6 7"/></svg>返回
</button>
<span class="nav-title">应急工单详情</span>
</div>
<div class="scroll-content">
<div class="card" id="basic-info-card">
<div class="card__header" onclick="toggleCard('basic-info-card', this)">
<div class="card__title">基本信息</div>
<div class="card__toggle"><span>收起</span><svg class="card__arrow" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="2"><path d="M3 6l5 5 5-5"/></svg></div>
</div>
<div class="card__body">
<div class="info-item"><span class="info-item__label">工单编号</span><span class="info-item__value">YJ5633256</span></div>
<div class="info-item"><span class="info-item__label">应急中心</span><span class="info-item__value">西安应急中心</span></div>
<div class="info-item"><span class="info-item__label">求助员工</span><span class="info-item__value">王旭(EMP-56985</span></div>
<div class="info-item"><span class="info-item__label">所属单位</span><span class="info-item__value">公司机关</span></div>
<div class="info-item"><span class="info-item__label">所属部门</span><span class="info-item__value">健康科</span></div>
<div class="info-item"><span class="info-item__label">求助方式</span><span class="info-item__value">应急视频</span></div>
<div class="info-item"><span class="info-item__label">求助时间</span><span class="info-item__value">2026-03-21 15:12:21</span></div>
<div class="info-item"><span class="info-item__label">位置信息</span><span class="info-item__value"><span class="location-link"><svg width="14" height="14" viewBox="0 0 16 16" fill="none"><path d="M8 1C5.24 1 3 3.24 3 6c0 3.75 5 7 5 7s5-3.25 5-7c0-2.76-2.24-5-5-5z" stroke="currentColor" stroke-width="1.4"/><circle cx="8" cy="6" r="1.5" stroke="currentColor" stroke-width="1.2"/></svg>陕西省西安市雁塔区电子一路56号</span></span></div>
<div class="info-item"><span class="info-item__label">操作人员</span><span class="info-item__value">刘旭</span></div>
<div class="info-item"><span class="info-item__label">专业人员</span><span class="info-item__value">刘旭</span></div>
<div class="info-item"><span class="info-item__label">工单状态</span><span class="info-item__value"><span class="tag tag-green">已完成</span></span></div>
<div class="info-item"><span class="info-item__label">完成时间</span><span class="info-item__value">2026-03-21 16:45:00</span></div>
</div>
</div>
<div class="card" id="rescue-info-card">
<div class="card__header" onclick="toggleCard('rescue-info-card', this)">
<div class="card__title">救助信息</div>
<div class="card__toggle"><span>收起</span><svg class="card__arrow" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="2"><path d="M3 6l5 5 5-5"/></svg></div>
</div>
<div class="card__body">
<div class="desc-block">
<div class="desc-block__label">救助意见:</div>
<div class="desc-block__text">建议立即送往最近医院急诊科进行头颅CT检查,排除脑血管意外可能。</div>
</div>
<div class="desc-block">
<div class="desc-block__label">救助结果:</div>
<div id="result-display" class="result-filled"></div>
</div>
<div class="desc-block">
<div class="desc-block__label">相关照片:</div>
<div class="photo-list" id="photo-list-done">
<div class="photo-item">现场照片 1</div>
<div class="photo-item">现场照片 2</div>
<div class="photo-item">现场照片 3</div>
</div>
</div>
<div class="desc-block">
<div class="desc-block__label">补充小结:</div>
<div id="summary-list-done" class="summary-list"></div>
</div>
<!-- <div class="action-row">-->
<!-- <button class="save-btn" onclick="saveSection('救助信息')">保存救助信息</button>-->
<!-- </div>-->
</div>
</div>
<div class="card" id="dispatch-info-card">
<div class="card__header" onclick="toggleCard('dispatch-info-card', this)">
<div class="card__title">派单信息</div>
<div class="card__toggle"><span>收起</span><svg class="card__arrow" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="2"><path d="M3 6l5 5 5-5"/></svg></div>
</div>
<div class="card__body">
<div class="info-item"><span class="info-item__label">派单时间</span><span class="info-item__value">2026-03-21 15:18:00</span></div>
<div class="info-item"><span class="info-item__label">驻场人员</span><span class="info-item__value">王希(138-9201-3001</span></div>
<div class="info-item"><span class="info-item__label">派单状态</span><span class="info-item__value"><span class="tag tag-green">已完成</span></span></div>
<div class="info-item"><span class="info-item__label">结束时间</span><span class="info-item__value">2026-03-21 16:40:00</span></div>
<div class="desc-block">
<div class="desc-block__label">派单说明:</div>
<div class="desc-block__text">给这个员工紧急挂号就诊,需要拍头颅CT</div>
</div>
<div class="desc-block">
<div class="desc-block__label">驻场说明:</div>
<div class="desc-block__text">已经挂号并且开了头颅CT检查单,已陪同就诊完毕,员工状态稳定</div>
</div>
</div>
</div>
<div class="card" id="ambulance-card">
<div class="card__header" onclick="toggleCard('ambulance-card', this)">
<div class="card__title">救护车支援</div>
<div class="card__toggle"><span>收起</span><svg class="card__arrow" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="2"><path d="M3 6l5 5 5-5"/></svg></div>
</div>
<div class="card__body">
<div class="ambulance-toolbar">
<div class="desc-block__label" style="margin-bottom:0;">支援详情</div>
</div>
<div id="ambulance-display" class="ambulance-display">
<div class="ambulance-display__row"><span class="ambulance-display__label">车牌号</span><span id="amb-d-plate" class="ambulance-display__value">陕A·120-01</span></div>
<div class="ambulance-display__row"><span class="ambulance-display__label">所属机构</span><span id="amb-d-hospital" class="ambulance-display__value">CQ能源职工医院</span></div>
<div class="ambulance-display__row"><span class="ambulance-display__label">驾驶人</span><span id="amb-d-driver" class="ambulance-display__value">李强</span></div>
<div class="ambulance-display__row"><span class="ambulance-display__label">驾驶人电话</span><span id="amb-d-driverphone" class="ambulance-display__value">138-9101-2001</span></div>
<div class="ambulance-display__row"><span class="ambulance-display__label">随行人</span><span id="amb-d-escort" class="ambulance-display__value">张伟</span></div>
<div class="ambulance-display__row"><span class="ambulance-display__label">随行人电话</span><span id="amb-d-escortphone" class="ambulance-display__value">138-9201-5001</span></div>
<div class="ambulance-display__row"><span class="ambulance-display__label">目的地</span><span id="amb-d-dest" class="ambulance-display__value">CQ能源职工医院急诊科</span></div>
<div class="ambulance-display__row"><span class="ambulance-display__label">备注</span><span id="amb-d-remark" class="ambulance-display__value">患者疑似脑血管意外,请携带心电监护设备</span></div>
</div>
</div>
</div>
<div style="height:16px;"></div>
</div>
</div>
<script>
sessionStorage.setItem('appRole', 'admin');
function toggleCard(cardId, headerEl) {
var card = document.getElementById(cardId);
card.classList.toggle('card--collapsed');
var label = headerEl.querySelector('.card__toggle span');
label.textContent = card.classList.contains('card--collapsed') ? '展开' : '收起';
}
var summaryItems = [
'接到应急求助后立即抵达现场,员工突发头晕伴恶心呕吐。',
'现场监测体征异常,初步处置无效,联系驻场人员陪同就医。',
'已完成头颅CT检测,员工由同事留守陪护,已告知家属及部门负责人。'
];
var resultText = '员工已送达CQ能源职工医院急诊科,完成头颅CT检查,排除脑出血,诊断为高血压引起的眩晕,已开具降压药物并留观。';
function renderResult() {
var el = document.getElementById('result-display');
el.className = resultText ? 'result-filled' : 'result-empty';
el.innerHTML = resultText ? escapeHtml(resultText).replace(/\n/g, '<br>') : '暂未填写救助结果';
}
function renderSummaryList() {
var container = document.getElementById('summary-list-done');
container.innerHTML = '';
for (var i = 0; i < summaryItems.length; i++) {
var item = document.createElement('div');
item.className = 'summary-item';
item.innerHTML = '<div class="summary-item__top"><span class="summary-item__idx">小结 ' + (i + 1) + '</span></div><div class="summary-item__text">' + escapeHtml(summaryItems[i]).replace(/\n/g, '<br>') + '</div>';
container.appendChild(item);
}
}
function escapeHtml(text) {
return text.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/"/g, '&quot;').replace(/'/g, '&#39;');
}
renderResult();
renderSummaryList();
</script>
</body>
</html>
@@ -0,0 +1,310 @@
<!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>
* { margin: 0; padding: 0; box-sizing: border-box; }
body { background: #f0f2f5; display: flex; justify-content: center; align-items: flex-start; min-height: 100vh; padding: 20px; font-family: -apple-system, BlinkMacSystemFont, 'PingFang SC', 'Helvetica Neue', sans-serif; }
.phone-shell { width: 390px; height: 844px; background: #fff; border-radius: 44px; box-shadow: 0 20px 60px rgba(0,0,0,0.25), inset 0 0 0 2px #e0e0e0; overflow: hidden; position: relative; display: flex; flex-direction: column; flex-shrink: 0; }
.status-bar { height: 44px; background: #fff; display: flex; align-items: center; justify-content: space-between; padding: 0 24px; flex-shrink: 0; z-index: 10; }
.status-bar .time { font-size: 15px; font-weight: 700; color: #1a1a1a; }
.status-bar .icons { display: flex; gap: 6px; align-items: center; font-size: 12px; color: #1a1a1a; }
.nav-bar { height: 44px; background: #fff; display: flex; align-items: center; padding: 0 16px; flex-shrink: 0; border-bottom: 1px solid #f0f0f0; position: relative; }
.nav-back { display: flex; align-items: center; gap: 4px; color: #1677ff; font-size: 15px; cursor: pointer; background: none; border: none; padding: 4px 0; }
.nav-title { position: absolute; left: 50%; transform: translateX(-50%); font-size: 17px; font-weight: 600; color: #1a1a1a; white-space: nowrap; }
.scroll-content { flex: 1; overflow-y: auto; background: #f7f8fa; }
.scroll-content::-webkit-scrollbar { display: none; }
/* 主Tab */
.main-tabs { display: flex; background: #fff; border-bottom: 1px solid #f0f0f0; flex-shrink: 0; }
.main-tab { flex: 1; text-align: center; padding: 12px 0; font-size: 14px; color: #666; cursor: pointer; border-bottom: 2px solid transparent; transition: all 0.2s; }
.main-tab.active { color: #1677ff; border-bottom-color: #1677ff; font-weight: 600; }
.main-tab .badge { display: inline-block; background: #e8e8e8; color: #666; font-size: 10px; font-weight: 700; min-width: 16px; height: 16px; border-radius: 8px; padding: 0 4px; margin-left: 4px; vertical-align: middle; line-height: 16px; }
.main-tab.active .badge { background: #e6f4ff; color: #1677ff; }
/* 筛选区 */
.filter-bar { display: flex; align-items: center; gap: 8px; padding: 10px 12px; background: #fff; border-bottom: 1px solid #f0f0f0; flex-shrink: 0; }
.filter-bar__select { display: flex; align-items: center; gap: 4px; padding: 6px 10px; background: #f7f8fa; border-radius: 6px; border: 1px solid #e8e8e8; cursor: pointer; font-size: 13px; color: #333; flex-shrink: 0; position: relative; }
.filter-bar__select--month { flex-shrink: 0; }
.filter-bar__select--method { flex-shrink: 0; }
.filter-bar__select-arrow { font-size: 10px; color: #bbb; transition: transform 0.2s; }
.filter-bar__select-arrow.open { transform: rotate(180deg); }
/* 月份下拉 */
.month-dropdown { display: none; position: absolute; top: 100%; left: 0; background: #fff; border-radius: 8px; box-shadow: 0 4px 16px rgba(0,0,0,0.12); z-index: 50; margin-top: 4px; width: 140px; max-height: 180px; overflow-y: auto; }
.month-dropdown.active { display: block; }
.month-dropdown__item { padding: 10px 12px; font-size: 13px; color: #333; cursor: pointer; border-bottom: 1px solid #f5f5f5; }
.month-dropdown__item:hover { background: #f7f8fa; }
.month-dropdown__item.selected { background: #e6f4ff; color: #1677ff; font-weight: 600; }
/* 工单卡片 */
.order-card { background: #fff; border-radius: 12px; margin: 10px 12px 0; padding: 14px; box-shadow: 0 1px 4px rgba(0,0,0,0.06); cursor: pointer; }
.order-card:active { transform: scale(0.98); }
.order-card__header { display: flex; align-items: center; justify-content: space-between; margin-bottom: 10px; }
.order-card__time { font-size: 12px; color: #999; }
/* 求助方式标签 */
.method-tag { display: inline-flex; align-items: center; gap: 4px; padding: 4px 10px; border-radius: 12px; font-size: 12px; font-weight: 600; }
.method-tag--video { background: #fff0f6; color: #eb2f96; }
.method-tag--phone { background: #fff7e6; color: #fa8c16; }
.method-tag--120 { background: #fff1f0; color: #ff4d4f; }
/* 员工信息行 */
.order-card__emp { display: flex; align-items: center; gap: 8px; padding: 10px; background: #f9fafb; border-radius: 8px; margin-bottom: 8px; }
.order-card__emp-avatar { width: 36px; height: 36px; border-radius: 50%; background: linear-gradient(135deg, #e6f4ff, #b7d8ff); display: flex; align-items: center; justify-content: center; font-size: 16px; color: #1677ff; flex-shrink: 0; font-weight: 700; }
.order-card__emp-info { flex: 1; min-width: 0; }
.order-card__emp-name { font-size: 14px; font-weight: 600; color: #1a1a1a; }
.order-card__emp-meta { font-size: 11px; color: #999; margin-top: 2px; display: flex; gap: 6px; flex-wrap: wrap; }
.order-card__emp-phone { font-size: 12px; color: #1677ff; flex-shrink: 0; }
/* 处理信息行 */
.order-card__detail { display: flex; gap: 0; }
.order-card__detail-item { flex: 1; }
.order-card__detail-item + .order-card__detail-item { border-left: 1px solid #f0f0f0; padding-left: 10px; margin-left: 10px; }
.order-card__detail-label { font-size: 10px; color: #999; margin-bottom: 2px; }
.order-card__detail-val { font-size: 13px; color: #333; font-weight: 600; }
/* 已完成态 */
.order-card--done .order-card__header { opacity: 0.8; }
</style>
</head>
<body>
<div class="phone-shell">
<!-- 状态栏 -->
<div class="status-bar">
<span class="time">9:41</span>
<div class="icons"><span>●●●</span><span>WiFi</span><span>🔋</span></div>
</div>
<!-- 导航栏 -->
<!-- [交互] 点击返回工作台 -->
<div class="nav-bar">
<button class="nav-back" onclick="location.href='./index.html'">
<svg width="10" height="16" viewBox="0 0 10 16" fill="none" stroke="currentColor" stroke-width="2"><path d="M8 1L2 8l6 7"/></svg>返回
</button>
<span class="nav-title">应急求助工单</span>
</div>
<!-- Tab:进行中 / 已完成 -->
<div class="main-tabs">
<div class="main-tab active" onclick="switchMainTab(this,'panel-active')">进行中<span class="badge" id="badgeActive">3</span></div>
<div class="main-tab" onclick="switchMainTab(this,'panel-done')">已完成<span class="badge" id="badgeDone">12</span></div>
</div>
<!-- 筛选区 -->
<div class="filter-bar">
<!-- [交互] 点击展开月份下拉 -->
<div class="filter-bar__select filter-bar__select--month" onclick="toggleMonthDropdown()" style="position:relative;">
<span id="monthText">月份筛选</span>
<span class="filter-bar__select-arrow" id="monthArrow"></span>
<div class="month-dropdown" id="monthDropdown">
<div class="month-dropdown__item selected" onclick="selectMonth(event, '全部', '')">全部</div>
<div class="month-dropdown__item" onclick="selectMonth(event, '2026年6月', '2026-06')">2026年6月</div>
<div class="month-dropdown__item" onclick="selectMonth(event, '2026年5月', '2026-05')">2026年5月</div>
<div class="month-dropdown__item" onclick="selectMonth(event, '2026年4月', '2026-04')">2026年4月</div>
</div>
</div>
<!-- [交互] 点击展开求助方式下拉 -->
<div class="filter-bar__select filter-bar__select--method" onclick="toggleMethodDropdown()" style="position:relative;">
<span id="methodText">求助方式</span>
<span class="filter-bar__select-arrow" id="methodArrow"></span>
<div class="month-dropdown" id="methodDropdown">
<div class="month-dropdown__item selected" onclick="selectMethod(event, '全部', 'all')">全部</div>
<div class="month-dropdown__item" onclick="selectMethod(event, '应急视频', 'video')">应急视频</div>
<div class="month-dropdown__item" onclick="selectMethod(event, '应急电话', 'phone')">应急电话</div>
<div class="month-dropdown__item" onclick="selectMethod(event, '拨打120', '120')">拨打120</div>
</div>
</div>
</div>
<div class="scroll-content">
<!-- 进行中列表 -->
<div id="panel-active">
<!-- JS动态渲染 -->
</div>
<!-- 已完成列表 -->
<div id="panel-done" style="display:none;">
<!-- JS动态渲染 -->
</div>
<div style="height:16px;"></div>
</div>
</div>
<script>
/* ===== Mock数据 ===== */
var activeOrders = [
{ id:'EM202606001', method:'video', methodLabel:'应急视频', time:'2026-06-22 14:35', empName:'张小红', empGender:'女', empAge:32, empNo:'CQ001256', empUnit:'公司机关', empDept:'办公室', empPhone:'13812346789', center:'第一应急中心', operator:'王建国', professional:'刘志明' },
{ id:'EM202606002', method:'phone', methodLabel:'应急电话', time:'2026-06-22 10:12', empName:'李建国', empGender:'男', empAge:45, empNo:'CQ000832', empUnit:'采油一厂', empDept:'技术部', empPhone:'13923458901', center:'第二应急中心', operator:'赵海龙', professional:'陈晓东' },
{ id:'EM202606003', method:'120', methodLabel:'拨打120', time:'2026-06-21 08:20', empName:'赵志强', empGender:'男', empAge:61, empNo:'CQ000089', empUnit:'公司机关', empDept:'后勤部', empPhone:'13756782345', center:'第一应急中心', operator:'王建国', professional:'周伟' }
];
var doneOrders = [
{ id:'EM202606004', method:'video', methodLabel:'应急视频', time:'2026-06-20 16:05', empName:'王芳', empGender:'女', empAge:28, empNo:'CQ001103', empUnit:'信息技术中心', empDept:'数据部', empPhone:'13634564567', center:'第一应急中心', operator:'王建国', professional:'刘志明' },
{ id:'EM202606005', method:'phone', methodLabel:'应急电话', time:'2026-06-18 09:45', empName:'陈伟', empGender:'男', empAge:36, empNo:'CQ000567', empUnit:'安全环保部', empDept:'安环部', empPhone:'13545677890', center:'第三应急中心', operator:'孙海涛', professional:'黄志强' },
{ id:'EM202606006', method:'120', methodLabel:'拨打120', time:'2026-06-15 22:10', empName:'孙丽', empGender:'女', empAge:41, empNo:'CQ001340', empUnit:'采油一厂', empDept:'作业区', empPhone:'15867890123', center:'第二应急中心', operator:'赵海龙', professional:'马云飞' },
{ id:'EM202606007', method:'video', methodLabel:'应急视频', time:'2026-06-12 11:30', empName:'周明', empGender:'男', empAge:33, empNo:'CQ000921', empUnit:'信息技术中心', empDept:'技术部', empPhone:'18678903456', center:'第一应急中心', operator:'王建国', professional:'刘志明' },
{ id:'EM202606008', method:'phone', methodLabel:'应急电话', time:'2026-06-10 15:20', empName:'刘海波', empGender:'男', empAge:55, empNo:'CQ000234', empUnit:'公司机关', empDept:'行政部', empPhone:'13389015678', center:'第三应急中心', operator:'孙海涛', professional:'周伟' },
{ id:'EM202606009', method:'120', methodLabel:'拨打120', time:'2026-06-08 07:55', empName:'吴静', empGender:'女', empAge:26, empNo:'CQ001412', empUnit:'公司机关', empDept:'人力部', empPhone:'15289016789', center:'第二应急中心', operator:'赵海龙', professional:'陈晓东' },
{ id:'EM202606010', method:'video', methodLabel:'应急视频', time:'2026-06-05 13:40', empName:'黄晓明', empGender:'男', empAge:42, empNo:'CQ000789', empUnit:'采油一厂', empDept:'工程部', empPhone:'18990120123', center:'第一应急中心', operator:'王建国', professional:'黄志强' },
{ id:'EM202606011', method:'phone', methodLabel:'应急电话', time:'2026-06-03 18:15', empName:'杨丽华', empGender:'女', empAge:39, empNo:'CQ001098', empUnit:'安全环保部', empDept:'安环部', empPhone:'13101234567', center:'第三应急中心', operator:'孙海涛', professional:'马云飞' },
{ id:'EM202605001', method:'video', methodLabel:'应急视频', time:'2026-05-28 10:00', empName:'郑国强', empGender:'男', empAge:50, empNo:'CQ000456', empUnit:'公司机关', empDept:'财务部', empPhone:'17712347890', center:'第二应急中心', operator:'赵海龙', professional:'刘志明' },
{ id:'EM202605002', method:'120', methodLabel:'拨打120', time:'2026-05-25 20:30', empName:'马燕', empGender:'女', empAge:35, empNo:'CQ001521', empUnit:'信息技术中心', empDept:'运维部', empPhone:'15023452345', center:'第一应急中心', operator:'王建国', professional:'周伟' },
{ id:'EM202605003', method:'phone', methodLabel:'应急电话', time:'2026-05-20 14:50', empName:'林伟东', empGender:'男', empAge:44, empNo:'CQ000678', empUnit:'采油一厂', empDept:'设备部', empPhone:'19934563456', center:'第三应急中心', operator:'孙海涛', professional:'陈晓东' },
{ id:'EM202604001', method:'video', methodLabel:'应急视频', time:'2026-04-15 09:10', empName:'何秀兰', empGender:'女', empAge:47, empNo:'CQ001623', empUnit:'公司机关', empDept:'后勤部', empPhone:'15545676789', center:'第一应急中心', operator:'王建国', professional:'黄志强' }
];
/* ===== 当前筛选状态 ===== */
var currentMonth = '';
var currentMethod = 'all';
/* ===== 渲染工具函数 ===== */
function getAvatarChar(name) { return name.charAt(0); }
function getMethodTagClass(method) {
if (method === 'video') return 'method-tag--video';
if (method === 'phone') return 'method-tag--phone';
return 'method-tag--120';
}
function filterByMonth(list) {
if (!currentMonth) return list;
return list.filter(function(item) {
return item.time.indexOf(currentMonth) === 0;
});
}
function filterByMethod(list) {
if (currentMethod === 'all') return list;
return list.filter(function(item) {
return item.method === currentMethod;
});
}
function getFilteredList(list) {
return filterByMethod(filterByMonth(list));
}
function renderOrderCard(item) {
var html = '<div class="order-card" onclick="location.href=\'./emergency-order-detail.html\'">';
html += ' <div class="order-card__header">';
html += ' <span class="method-tag ' + getMethodTagClass(item.method) + '">' + (item.method === 'video' ? '📹 ' : item.method === 'phone' ? '📞 ' : '🚑 ') + item.methodLabel + '</span>';
html += ' <span class="order-card__time">' + item.time + '</span>';
html += ' </div>';
html += ' <div class="order-card__emp">';
html += ' <div class="order-card__emp-avatar">' + getAvatarChar(item.empName) + '</div>';
html += ' <div class="order-card__emp-info">';
html += ' <div class="order-card__emp-name">' + item.empName + ' <span style="font-weight:400;font-size:11px;color:#999;">' + item.empNo + '</span></div>';
html += ' <div class="order-card__emp-meta"><span>' + item.empGender + '</span><span>' + item.empAge + '岁</span><span>' + item.empUnit + '</span><span>' + item.empDept + '</span></div>';
html += ' </div>';
html += ' <span class="order-card__emp-phone">' + item.empPhone + '</span>';
html += ' </div>';
html += ' <div class="order-card__detail">';
html += ' <div class="order-card__detail-item">';
html += ' <div class="order-card__detail-label">应急中心</div>';
html += ' <div class="order-card__detail-val">' + item.center + '</div>';
html += ' </div>';
html += ' <div class="order-card__detail-item">';
html += ' <div class="order-card__detail-label">操作人员</div>';
html += ' <div class="order-card__detail-val">' + item.operator + '</div>';
html += ' </div>';
html += ' <div class="order-card__detail-item">';
html += ' <div class="order-card__detail-label">专业人员</div>';
html += ' <div class="order-card__detail-val">' + item.professional + '</div>';
html += ' </div>';
html += ' </div>';
html += '</div>';
return html;
}
function renderList(listId, data) {
var filtered = getFilteredList(data);
var html = '';
if (filtered.length === 0) {
html = '<div style="text-align:center;padding:40px 16px;color:#999;font-size:14px;">暂无数据</div>';
} else {
filtered.forEach(function(item) {
html += renderOrderCard(item);
});
}
document.getElementById(listId).innerHTML = html;
}
/* ===== 主Tab切换 ===== */
function switchMainTab(el, panelId) {
el.closest('.main-tabs').querySelectorAll('.main-tab').forEach(function(t) { t.classList.remove('active'); });
el.classList.add('active');
document.getElementById('panel-active').style.display = panelId === 'panel-active' ? 'block' : 'none';
document.getElementById('panel-done').style.display = panelId === 'panel-done' ? 'block' : 'none';
}
/* ===== 月份筛选 ===== */
function toggleMonthDropdown() {
var dd = document.getElementById('monthDropdown');
var arrow = document.getElementById('monthArrow');
var isOpen = dd.classList.contains('active');
dd.classList.toggle('active');
if (isOpen) { arrow.classList.remove('open'); } else { arrow.classList.add('open'); }
}
function selectMonth(e, label, value) {
e.stopPropagation();
currentMonth = value;
document.getElementById('monthText').textContent = label;
document.querySelectorAll('.month-dropdown__item').forEach(function(item) {
item.classList.toggle('selected', item.textContent === label);
});
document.getElementById('monthDropdown').classList.remove('active');
document.getElementById('monthArrow').classList.remove('open');
// 重新渲染两个列表
renderList('panel-active', activeOrders);
renderList('panel-done', doneOrders);
}
// 点击外部关闭下拉
document.addEventListener('click', function(e) {
if (!e.target.closest('.filter-bar__select--month')) {
document.getElementById('monthDropdown').classList.remove('active');
document.getElementById('monthArrow').classList.remove('open');
}
if (!e.target.closest('.filter-bar__select--method')) {
document.getElementById('methodDropdown').classList.remove('active');
document.getElementById('methodArrow').classList.remove('open');
}
});
/* ===== 求助方式筛选 ===== */
function toggleMethodDropdown() {
var dd = document.getElementById('methodDropdown');
var arrow = document.getElementById('methodArrow');
var isOpen = dd.classList.contains('active');
dd.classList.toggle('active');
if (isOpen) { arrow.classList.remove('open'); } else { arrow.classList.add('open'); }
}
function selectMethod(e, label, value) {
e.stopPropagation();
currentMethod = value;
document.getElementById('methodText').textContent = label;
document.querySelectorAll('#methodDropdown .month-dropdown__item').forEach(function(item) {
item.classList.toggle('selected', item.textContent === label);
});
document.getElementById('methodDropdown').classList.remove('active');
document.getElementById('methodArrow').classList.remove('open');
// 重新渲染两个列表
renderList('panel-active', activeOrders);
renderList('panel-done', doneOrders);
}
/* ===== 初始化 ===== */
renderList('panel-active', activeOrders);
renderList('panel-done', doneOrders);
</script>
</body>
</html>
@@ -0,0 +1,214 @@
<!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>
* { margin: 0; padding: 0; box-sizing: border-box; }
body { background: #f0f2f5; display: flex; justify-content: center; align-items: flex-start; min-height: 100vh; padding: 20px; font-family: -apple-system, BlinkMacSystemFont, 'PingFang SC', 'Helvetica Neue', sans-serif; }
.phone-shell { width: 390px; height: 844px; background: #fff; border-radius: 44px; box-shadow: 0 20px 60px rgba(0,0,0,0.25), inset 0 0 0 2px #e0e0e0; overflow: hidden; position: relative; display: flex; flex-direction: column; flex-shrink: 0; }
.status-bar { height: 44px; background: #fff; display: flex; align-items: center; justify-content: space-between; padding: 0 24px; flex-shrink: 0; z-index: 10; }
.status-bar .time { font-size: 15px; font-weight: 700; color: #1a1a1a; }
.status-bar .icons { display: flex; gap: 6px; align-items: center; font-size: 12px; color: #1a1a1a; }
.nav-bar { height: 44px; background: #fff; display: flex; align-items: center; padding: 0 16px; flex-shrink: 0; border-bottom: 1px solid #f0f0f0; position: relative; }
.nav-back { display: flex; align-items: center; gap: 4px; color: #1677ff; font-size: 15px; cursor: pointer; background: none; border: none; padding: 4px 0; }
.nav-title { position: absolute; left: 50%; transform: translateX(-50%); font-size: 17px; font-weight: 600; color: #1a1a1a; white-space: nowrap; }
.scroll-content { flex: 1; overflow-y: auto; background: #f7f8fa; }
.scroll-content::-webkit-scrollbar { display: none; }
.date-nav { display: flex; align-items: center; justify-content: center; gap: 8px; padding: 10px 16px; background: #fff; border-bottom: 1px solid #f0f0f0; position: relative; }
.date-nav__arrow { width: 32px; height: 32px; border-radius: 50%; background: #f5f5f5; display: flex; align-items: center; justify-content: center; cursor: pointer; border: none; color: #666; font-size: 16px; flex-shrink: 0; }
.date-nav__arrow:active { background: #e6f4ff; }
.date-nav__text { font-size: 15px; font-weight: 600; color: #1a1a1a; min-width: 110px; text-align: center; }
.date-nav__cal { width: 28px; height: 28px; border-radius: 6px; background: none; display: flex; align-items: center; justify-content: center; cursor: pointer; border: none; font-size: 16px; flex-shrink: 0; color: #1677ff; }
.date-nav__cal:active { background: #e6f4ff; }
.cal-panel { display: none; position: absolute; top: 42px; left: 16px; right: 16px; background: #fff; border-radius: 14px; box-shadow: 0 8px 30px rgba(0,0,0,0.15); z-index: 100; padding: 16px; }
.cal-panel.active { display: block; }
.cal-panel__head { display: flex; align-items: center; justify-content: space-between; margin-bottom: 12px; }
.cal-panel__month { font-size: 15px; font-weight: 700; color: #1a1a1a; }
.cal-panel__nav { width: 28px; height: 28px; border-radius: 50%; border: none; background: #f5f5f5; cursor: pointer; font-size: 14px; color: #666; display: flex; align-items: center; justify-content: center; }
.cal-panel__nav:active { background: #e6f4ff; }
.cal-panel__weekdays { display: flex; margin-bottom: 6px; }
.cal-panel__weekday { flex: 1; text-align: center; font-size: 11px; color: #999; padding: 4px 0; }
.cal-panel__grid { display: flex; flex-wrap: wrap; }
.cal-panel__day { width: calc(100% / 7); text-align: center; padding: 8px 0; font-size: 13px; color: #333; cursor: pointer; border-radius: 8px; }
.cal-panel__day--other { color: #ddd; }
.cal-panel__day:hover { background: #f5f5f5; }
.cal-panel__day--today { font-weight: 700; color: #1677ff; }
.cal-panel__day--selected { background: #1677ff; color: #fff; font-weight: 700; }
.cal-panel__day--selected:hover { background: #1677ff; }
.seg-tabs { display: flex; background: #fff; border-bottom: 1px solid #f0f0f0; flex-shrink: 0; }
.seg-tab { flex: 1; text-align: center; padding: 12px 0; font-size: 14px; color: #666; cursor: pointer; border-bottom: 2px solid transparent; transition: all 0.2s; }
.seg-tab.active { color: #1677ff; border-bottom-color: #1677ff; font-weight: 600; }
.seg-tab .badge { display: inline-block; background: #e8e8e8; color: #666; font-size: 10px; font-weight: 700; min-width: 16px; height: 16px; border-radius: 8px; padding: 0 4px; margin-left: 4px; vertical-align: middle; line-height: 16px; }
.seg-tab.active .badge { background: #e6f4ff; color: #1677ff; }
.employee-card { background: #fff; border-radius: 12px; margin: 10px 12px 0; padding: 14px; box-shadow: 0 1px 4px rgba(0,0,0,0.06); display: flex; align-items: center; gap: 10px; cursor: pointer; }
.employee-card:active { transform: scale(0.98); }
.employee-card__info { flex: 1; min-width: 0; }
.employee-card__name { font-size: 15px; font-weight: 600; color: #1a1a1a; }
.employee-card__meta { font-size: 12px; color: #999; margin-top: 3px; display: flex; gap: 8px; flex-wrap: wrap; }
.employee-card__arrow { font-size: 12px; color: #1677ff; flex-shrink: 0; white-space: nowrap; }
</style>
</head>
<body>
<div class="phone-shell">
<div class="status-bar">
<span class="time">9:41</span>
<div class="icons"><span>●●●</span><span>WiFi</span><span>🔋</span></div>
</div>
<!-- [交互] 点击返回体重管理详情 -->
<div class="nav-bar">
<button class="nav-back" onclick="location.href='./weight-detail.html'">
<svg width="10" height="16" viewBox="0 0 10 16" fill="none" stroke="currentColor" stroke-width="2"><path d="M8 1L2 8l6 7"/></svg>返回
</button>
<span class="nav-title">运动记录</span>
</div>
<div class="date-nav">
<button class="date-nav__arrow" onclick="changeDate(-1)"></button>
<button class="date-nav__cal" onclick="toggleCalPanel()">📅</button>
<span class="date-nav__text" id="dateText">2026-06-22</span>
<button class="date-nav__arrow" onclick="changeDate(1)"></button>
<div class="cal-panel" id="calPanel">
<div class="cal-panel__head">
<button class="cal-panel__nav" onclick="calPrevMonth(event)"></button>
<span class="cal-panel__month" id="calMonthLabel">2026年6月</span>
<button class="cal-panel__nav" onclick="calNextMonth(event)"></button>
</div>
<div class="cal-panel__weekdays">
<div class="cal-panel__weekday"></div><div class="cal-panel__weekday"></div><div class="cal-panel__weekday"></div><div class="cal-panel__weekday"></div><div class="cal-panel__weekday"></div><div class="cal-panel__weekday"></div><div class="cal-panel__weekday"></div>
</div>
<div class="cal-panel__grid" id="calGrid"></div>
</div>
</div>
<div class="seg-tabs">
<div class="seg-tab active" onclick="switchTab(this,'panel-recorded')">已记录<span class="badge" id="badgeRecorded">65</span></div>
<div class="seg-tab" onclick="switchTab(this,'panel-unrecorded')">未记录<span class="badge" id="badgeUnrecorded">21</span></div>
</div>
<div class="scroll-content">
<div id="panel-recorded"><!-- JS动态渲染 --></div>
<div id="panel-unrecorded" style="display:none;"><!-- JS动态渲染 --></div>
<div style="height:16px;"></div>
</div>
</div>
<script>
var recordedList = [
{ name:'陈伟', gender:'男', age:36, dept:'安全环保部 · 安环部', height:178 },
{ name:'王芳', gender:'女', age:28, dept:'信息技术中心 · 数据部', height:160 },
{ name:'赵志强', gender:'男', age:61, dept:'公司机关 · 后勤部', height:170 },
{ name:'张小红', gender:'女', age:32, dept:'公司机关 · 办公室', height:162 },
{ name:'周明', gender:'男', age:33, dept:'信息技术中心 · 技术部', height:182 },
{ name:'李建国', gender:'男', age:45, dept:'采油一厂 · 技术部', height:175 },
{ name:'孙丽', gender:'女', age:41, dept:'采油一厂 · 作业区', height:158 },
{ name:'刘海波', gender:'男', age:55, dept:'公司机关 · 行政部', height:168 }
];
var unrecordedList = [
{ name:'吴静', gender:'女', age:26, dept:'公司机关 · 人力部', height:165 },
{ name:'黄晓明', gender:'男', age:42, dept:'采油一厂 · 工程部', height:176 },
{ name:'马燕', gender:'女', age:35, dept:'信息技术中心 · 运维部', height:159 },
{ name:'林伟东', gender:'男', age:44, dept:'采油一厂 · 设备部', height:180 }
];
function switchTab(el, panelId) {
el.closest('.seg-tabs').querySelectorAll('.seg-tab').forEach(function(t) { t.classList.remove('active'); });
el.classList.add('active');
['panel-recorded','panel-unrecorded'].forEach(function(id) {
document.getElementById(id).style.display = id === panelId ? 'block' : 'none';
});
}
function renderRecordedList() {
var html = '';
recordedList.forEach(function(item) {
html += '<div class="employee-card" onclick="location.href=\'./exercise-employee-detail.html\'">';
html += ' <div class="employee-card__info">';
html += ' <div class="employee-card__name">' + item.name + '</div>';
html += ' <div class="employee-card__meta"><span>' + item.gender + '</span><span>' + item.age + '岁</span><span>' + item.dept + '</span><span>身高 ' + item.height + 'cm</span></div>';
html += ' </div>';
html += ' <span class="employee-card__arrow">记录明细 </span>';
html += '</div>';
});
document.getElementById('panel-recorded').innerHTML = html;
}
function renderUnrecordedList() {
var html = '';
unrecordedList.forEach(function(item) {
html += '<div class="employee-card">';
html += ' <div class="employee-card__info">';
html += ' <div class="employee-card__name">' + item.name + '</div>';
html += ' <div class="employee-card__meta"><span>' + item.gender + '</span><span>' + item.age + '岁</span><span>' + item.dept + '</span><span>身高 ' + item.height + 'cm</span></div>';
html += ' </div>';
html += '</div>';
});
document.getElementById('panel-unrecorded').innerHTML = html;
}
var currentDate = new Date(2026, 5, 22);
var calViewYear = currentDate.getFullYear();
var calViewMonth = currentDate.getMonth();
function changeDate(delta) {
currentDate.setDate(currentDate.getDate() + delta);
calViewYear = currentDate.getFullYear(); calViewMonth = currentDate.getMonth();
renderDate();
}
function renderDate() {
var y = currentDate.getFullYear();
var m = String(currentDate.getMonth() + 1).padStart(2, '0');
var d = String(currentDate.getDate()).padStart(2, '0');
document.getElementById('dateText').textContent = y + '-' + m + '-' + d;
}
function toggleCalPanel() {
var panel = document.getElementById('calPanel');
if (panel.classList.contains('active')) { panel.classList.remove('active'); return; }
calViewYear = currentDate.getFullYear(); calViewMonth = currentDate.getMonth();
renderCal(); panel.classList.add('active');
}
function calPrevMonth(e) { e.stopPropagation(); calViewMonth--; if (calViewMonth < 0) { calViewMonth = 11; calViewYear--; } renderCal(); }
function calNextMonth(e) { e.stopPropagation(); calViewMonth++; if (calViewMonth > 11) { calViewMonth = 0; calViewYear++; } renderCal(); }
function renderCal() {
document.getElementById('calMonthLabel').textContent = calViewYear + '年' + (calViewMonth + 1) + '月';
var firstDay = new Date(calViewYear, calViewMonth, 1).getDay();
var daysInMonth = new Date(calViewYear, calViewMonth + 1, 0).getDate();
var today = new Date();
var html = '';
for (var i = 0; i < firstDay; i++) { html += '<div class="cal-panel__day cal-panel__day--other"></div>'; }
for (var d = 1; d <= daysInMonth; d++) {
var cls = 'cal-panel__day';
if (calViewYear === today.getFullYear() && calViewMonth === today.getMonth() && d === today.getDate()) cls += ' cal-panel__day--today';
if (calViewYear === currentDate.getFullYear() && calViewMonth === currentDate.getMonth() && d === currentDate.getDate()) cls += ' cal-panel__day--selected';
html += '<div class="' + cls + '" onclick="selectCalDay(event,' + d + ')">' + d + '</div>';
}
document.getElementById('calGrid').innerHTML = html;
}
function selectCalDay(e, day) {
e.stopPropagation();
currentDate = new Date(calViewYear, calViewMonth, day);
calViewYear = currentDate.getFullYear(); calViewMonth = currentDate.getMonth();
renderDate(); renderCal();
document.getElementById('calPanel').classList.remove('active');
}
document.addEventListener('click', function(e) {
if (!e.target.closest('.date-nav') && !e.target.closest('.cal-panel')) {
document.getElementById('calPanel').classList.remove('active');
}
});
renderRecordedList();
renderUnrecordedList();
</script>
</body>
</html>
@@ -0,0 +1,191 @@
<!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>
* { margin: 0; padding: 0; box-sizing: border-box; }
body { background: #f0f2f5; display: flex; justify-content: center; align-items: flex-start; min-height: 100vh; padding: 20px; font-family: -apple-system, BlinkMacSystemFont, 'PingFang SC', 'Helvetica Neue', sans-serif; }
.phone-shell { width: 390px; height: 844px; background: #f7f8fa; border-radius: 44px; box-shadow: 0 20px 60px rgba(0,0,0,0.25), inset 0 0 0 2px #e0e0e0; overflow: hidden; position: relative; display: flex; flex-direction: column; flex-shrink: 0; }
.status-bar { height: 44px; background: #fff; display: flex; align-items: center; justify-content: space-between; padding: 0 24px; flex-shrink: 0; z-index: 10; }
.status-bar .time { font-size: 15px; font-weight: 700; color: #1a1a1a; }
.status-bar .icons { display: flex; gap: 6px; align-items: center; font-size: 12px; color: #1a1a1a; }
.nav-bar { height: 44px; background: #fff; display: flex; align-items: center; padding: 0 16px; flex-shrink: 0; border-bottom: 1px solid #f0f0f0; position: relative; }
.nav-back { display: flex; align-items: center; gap: 4px; color: #1677ff; font-size: 15px; cursor: pointer; background: none; border: none; padding: 4px 0; }
.nav-title { position: absolute; left: 50%; transform: translateX(-50%); font-size: 17px; font-weight: 600; color: #1a1a1a; white-space: nowrap; }
.scroll-content { flex: 1; overflow-y: auto; background: #f7f8fa; }
.scroll-content::-webkit-scrollbar { display: none; }
.emp-info { background: #fff; padding: 14px 16px; margin: 0; border-bottom: 1px solid #f0f0f0; }
.emp-info__name { font-size: 17px; font-weight: 700; color: #1a1a1a; }
.emp-info__meta { font-size: 12px; color: #999; margin-top: 4px; display: flex; gap: 8px; }
.data-compare { background: #fff; border-radius: 12px; margin: 10px 12px 0; padding: 14px; box-shadow: 0 1px 4px rgba(0,0,0,0.06); }
.data-compare__title { font-size: 14px; font-weight: 700; color: #1a1a1a; margin-bottom: 10px; }
.data-compare__table { display: flex; gap: 0; }
.data-compare__col { flex: 1; text-align: center; }
.data-compare__col-label { font-size: 11px; color: #999; margin-bottom: 6px; font-weight: 600; }
.data-compare__row { font-size: 12px; color: #666; padding: 4px 0; border-bottom: 1px solid #f8f8f8; }
.data-compare__row:last-child { border-bottom: none; }
.data-compare__row .val { font-weight: 600; }
.data-compare__col--initial .val { color: #666; }
.data-compare__col--target .val { color: #52c41a; }
.data-compare__col--current .val { color: #1677ff; }
.change-row { display: flex; gap: 0; background: #fff; border-radius: 12px; margin: 10px 12px 0; padding: 10px 0; box-shadow: 0 1px 4px rgba(0,0,0,0.06); }
.change-item { flex: 1; text-align: center; }
.change-item + .change-item { border-left: 1px solid #f0f0f0; }
.change-item__val { font-size: 16px; font-weight: 700; }
.change-item__val--down { color: #52c41a; }
.change-item__val--up { color: #ff4d4f; }
.change-item__label { font-size: 10px; color: #999; margin-top: 2px; }
.section-title { font-size: 14px; font-weight: 700; color: #1a1a1a; margin: 14px 12px 6px; }
.exercise-card { background: #fff; border-radius: 12px; margin: 8px 12px 0; padding: 14px; box-shadow: 0 1px 4px rgba(0,0,0,0.06); }
.exercise-card__head { display: flex; align-items: center; justify-content: space-between; margin-bottom: 8px; }
.exercise-card__type { font-size: 14px; font-weight: 600; color: #1a1a1a; }
.exercise-card__time { font-size: 12px; color: #999; }
.exercise-card__row { display: flex; align-items: center; gap: 16px; }
.exercise-card__duration { font-size: 15px; font-weight: 700; color: #1677ff; }
.exercise-card__duration span { font-size: 11px; font-weight: 400; color: #999; }
.exercise-card__kcal { font-size: 15px; font-weight: 700; color: #fa8c16; }
.exercise-card__kcal span { font-size: 11px; font-weight: 400; color: #999; }
.exercise-card__source { margin-left: auto; }
.tag { display: inline-block; padding: 2px 8px; border-radius: 4px; font-size: 10px; font-weight: 600; }
.tag-blue { background: #e6f4ff; color: #1677ff; }
.tag-purple { background: #f9f0ff; color: #722ed1; }
.tag-orange { background: #fff7e6; color: #fa8c16; }
.tag-cyan { background: #e6fffb; color: #13c2c2; }
</style>
</head>
<body>
<div class="phone-shell">
<div class="status-bar">
<span class="time">9:41</span>
<div class="icons"><span>●●●</span><span>WiFi</span><span>🔋</span></div>
</div>
<!-- [交互] 点击返回运动记录列表 -->
<div class="nav-bar">
<button class="nav-back" onclick="location.href='./exercise-detail.html'">
<svg width="10" height="16" viewBox="0 0 10 16" fill="none" stroke="currentColor" stroke-width="2"><path d="M8 1L2 8l6 7"/></svg>返回
</button>
<span class="nav-title">运动明细</span>
</div>
<div class="scroll-content">
<div style="padding:10px 16px;background:#fff;border-bottom:1px solid #f0f0f0;font-size:14px;color:#333;font-weight:600;">2026-06-22</div>
<div class="emp-info">
<div class="emp-info__name">陈伟</div>
<div class="emp-info__meta">
<span></span><span>36岁</span><span>安全环保部 · 安环部</span><span>身高 178cm</span>
</div>
</div>
<div class="data-compare">
<div class="data-compare__title">数据对比</div>
<div class="data-compare__table">
<div class="data-compare__col data-compare__col--initial">
<div class="data-compare__col-label">初始</div>
<div class="data-compare__row">体重 <span class="val">92kg</span></div>
<div class="data-compare__row">BMI <span class="val">29.0</span></div>
<div class="data-compare__row">体脂 <span class="val">30.2%</span></div>
<div class="data-compare__row">腰围 <span class="val">102cm</span></div>
</div>
<div class="data-compare__col data-compare__col--target">
<div class="data-compare__col-label">目标</div>
<div class="data-compare__row">体重 <span class="val">80kg</span></div>
<div class="data-compare__row">BMI <span class="val">25.2</span></div>
<div class="data-compare__row">体脂 <span class="val">22%</span></div>
<div class="data-compare__row">腰围 <span class="val">90cm</span></div>
</div>
<div class="data-compare__col data-compare__col--current">
<div class="data-compare__col-label">当前</div>
<div class="data-compare__row">体重 <span class="val">86.5kg</span></div>
<div class="data-compare__row">BMI <span class="val">27.3</span></div>
<div class="data-compare__row">体脂 <span class="val">27.8%</span></div>
<div class="data-compare__row">腰围 <span class="val">96cm</span></div>
</div>
</div>
</div>
<div class="change-row">
<div class="change-item">
<div class="change-item__val change-item__val--down">-5.5kg</div>
<div class="change-item__label">体重变化</div>
</div>
<div class="change-item">
<div class="change-item__val change-item__val--down">-1.7</div>
<div class="change-item__label">BMI变化</div>
</div>
<div class="change-item">
<div class="change-item__val change-item__val--down">-2.4%</div>
<div class="change-item__label">体脂变化</div>
</div>
<div class="change-item">
<div class="change-item__val change-item__val--down">-6cm</div>
<div class="change-item__label">腰围变化</div>
</div>
</div>
<div class="section-title">当日运动明细</div>
<div class="exercise-card">
<div class="exercise-card__head">
<span class="exercise-card__type">🏃 跑步</span>
<span class="exercise-card__time">2026-06-22 06:30:00</span>
</div>
<div class="exercise-card__row">
<div class="exercise-card__duration">45 <span>分钟</span></div>
<div class="exercise-card__kcal">320 <span>千卡</span></div>
<span class="exercise-card__source tag tag-cyan">穿戴</span>
</div>
</div>
<div class="exercise-card">
<div class="exercise-card__head">
<span class="exercise-card__type">🚴 骑行</span>
<span class="exercise-card__time">2026-06-22 12:40:00</span>
</div>
<div class="exercise-card__row">
<div class="exercise-card__duration">30 <span>分钟</span></div>
<div class="exercise-card__kcal">180 <span>千卡</span></div>
<span class="exercise-card__source tag tag-purple">自记</span>
</div>
</div>
<div class="exercise-card">
<div class="exercise-card__head">
<span class="exercise-card__type">🏊 游泳</span>
<span class="exercise-card__time">2026-06-22 18:00:00</span>
</div>
<div class="exercise-card__row">
<div class="exercise-card__duration">60 <span>分钟</span></div>
<div class="exercise-card__kcal">480 <span>千卡</span></div>
<span class="exercise-card__source tag tag-orange">器械</span>
</div>
</div>
<div class="exercise-card">
<div class="exercise-card__head">
<span class="exercise-card__type">🚶 步行</span>
<span class="exercise-card__time">2026-06-22 20:00:00</span>
</div>
<div class="exercise-card__row">
<div class="exercise-card__duration">8,520 <span></span></div>
<div class="exercise-card__kcal">150 <span>千卡</span></div>
<span class="exercise-card__source tag tag-blue">微信</span>
</div>
</div>
<div style="height:20px;"></div>
</div>
</div>
</body>
</html>
@@ -0,0 +1,460 @@
<!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>
* { margin: 0; padding: 0; box-sizing: border-box; }
body { background: #f0f2f5; display: flex; justify-content: center; align-items: flex-start; min-height: 100vh; padding: 20px; font-family: -apple-system, BlinkMacSystemFont, 'PingFang SC', 'Helvetica Neue', sans-serif; }
.phone-shell { width: 390px; height: 844px; background: #fff; border-radius: 44px; box-shadow: 0 20px 60px rgba(0,0,0,0.25), inset 0 0 0 2px #e0e0e0; overflow: hidden; position: relative; display: flex; flex-direction: column; flex-shrink: 0; }
.status-bar { height: 44px; background: #fff; display: flex; align-items: center; justify-content: space-between; padding: 0 24px; flex-shrink: 0; z-index: 10; }
.status-bar .time { font-size: 15px; font-weight: 700; color: #1a1a1a; }
.status-bar .icons { display: flex; gap: 6px; align-items: center; font-size: 12px; color: #1a1a1a; }
.nav-bar { height: 44px; background: #fff; display: flex; align-items: center; padding: 0 16px; flex-shrink: 0; border-bottom: 1px solid #f0f0f0; position: relative; }
.nav-back { display: flex; align-items: center; gap: 4px; color: #1677ff; font-size: 15px; cursor: pointer; background: none; border: none; padding: 4px 0; }
.nav-title { position: absolute; left: 50%; transform: translateX(-50%); font-size: 17px; font-weight: 600; color: #1a1a1a; white-space: nowrap; }
.scroll-content { flex: 1; overflow-y: auto; background: #f7f8fa; padding-bottom: 20px; }
.scroll-content::-webkit-scrollbar { display: none; }
/* 标签 */
.tag { display: inline-block; padding: 2px 8px; border-radius: 4px; font-size: 11px; font-weight: 600; }
.tag-green { background: #f6ffed; color: #52c41a; }
.tag-orange { background: #fff7e6; color: #fa8c16; }
.tag-red { background: #fff1f0; color: #ff4d4f; }
/* 申请时间顶栏 */
.time-bar { background: #fff; padding: 10px 16px; border-bottom: 1px solid #f0f0f0; font-size: 12px; color: #666; display: flex; align-items: center; justify-content: space-between; }
.time-bar__label { color: #999; }
/* 信息卡片 */
.info-card { background: #fff; border-radius: 12px; margin: 10px 12px 0; padding: 14px; box-shadow: 0 1px 4px rgba(0,0,0,0.06); }
.info-card__title { font-size: 13px; font-weight: 600; color: #999; margin-bottom: 10px; padding-bottom: 8px; border-bottom: 1px solid #f0f0f0; }
/* 基本信息 */
.info-card__name { font-size: 17px; font-weight: 700; color: #1a1a1a; }
.info-card__meta { display: flex; gap: 12px; font-size: 12px; color: #666; margin-top: 6px; }
/* 数据行 */
.data-section { margin-bottom: 12px; }
.data-section:last-child { margin-bottom: 0; }
.data-section__label { font-size: 11px; color: #999; margin-bottom: 4px; }
.data-section__vals { display: flex; gap: 10px; flex-wrap: wrap; }
.data-section__val { font-size: 13px; font-weight: 600; color: #333; }
.data-section__val--target { color: #52c41a; }
/* 分隔线 */
.section-divider { height: 1px; background: #f0f0f0; margin: 10px 0; }
/* 推荐范围 */
.range-row { display: flex; gap: 0; }
.range-col { flex: 1; text-align: center; padding: 8px 4px; background: #f9fafb; border-radius: 8px; margin: 0 3px; }
.range-col__label { font-size: 11px; color: #999; margin-bottom: 4px; }
.range-col__range { font-size: 13px; font-weight: 600; color: #1677ff; }
/* 日期区间 */
.date-range-row { display: flex; align-items: center; justify-content: center; gap: 12px; font-size: 14px; color: #333; }
.date-range-row .arrow { color: #bbb; font-size: 16px; }
/* 审核结果信息 */
.result-info { display: none; background: #fff; border-radius: 12px; margin: 10px 12px 0; padding: 14px; box-shadow: 0 1px 4px rgba(0,0,0,0.06); }
.result-info.active { display: block; }
.result-info__row { display: flex; align-items: center; gap: 8px; margin-bottom: 6px; font-size: 13px; color: #666; }
.result-info__row:last-child { margin-bottom: 0; }
.result-info__label { color: #999; font-size: 12px; }
/* 操作区 - 单选按钮组 */
.action-area { display: block; }
.action-area.hidden { display: none; }
.action-bar { display: flex; gap: 24px; padding: 16px 12px 0; }
.radio-item { display: flex; align-items: center; gap: 8px; cursor: pointer; font-size: 14px; font-weight: 600; color: #333; }
.radio-dot { width: 20px; height: 20px; border-radius: 50%; border: 2px solid #d9d9d9; display: flex; align-items: center; justify-content: center; flex-shrink: 0; transition: all 0.2s; }
.radio-dot::after { content: ''; width: 10px; height: 10px; border-radius: 50%; background: transparent; transition: all 0.2s; }
.radio-item--approve.selected .radio-dot { border-color: #1677ff; }
.radio-item--approve.selected .radio-dot::after { background: #1677ff; }
.radio-item--reject.selected .radio-dot { border-color: #ff4d4f; }
.radio-item--reject.selected .radio-dot::after { background: #ff4d4f; }
/* 驳回原因 */
.reject-reason { display: none; background: #fff; border-radius: 12px; margin: 10px 12px 0; padding: 14px; box-shadow: 0 1px 4px rgba(0,0,0,0.06); }
.reject-reason.active { display: block; }
.reject-reason__label { font-size: 13px; font-weight: 600; color: #333; margin-bottom: 8px; }
.reject-reason__textarea { width: 100%; height: 80px; border: 1px solid #d9d9d9; border-radius: 8px; padding: 10px; font-size: 13px; color: #333; resize: none; font-family: inherit; outline: none; }
.reject-reason__textarea:focus { border-color: #1677ff; }
.reject-reason__textarea::placeholder { color: #ccc; }
/* 提交按钮 */
.submit-bar { padding: 12px; }
.submit-btn { width: 100%; padding: 12px 0; border-radius: 8px; font-size: 15px; font-weight: 600; text-align: center; cursor: pointer; border: none; background: #1677ff; color: #fff; }
.submit-btn:active { background: #0958d9; }
.submit-btn:disabled { background: #d9d9d9; color: #999; cursor: not-allowed; }
/* 确认弹窗 */
.overlay { display: none; position: fixed; top: 0; left: 0; right: 0; bottom: 0; background: rgba(0,0,0,0.45); z-index: 200; justify-content: center; align-items: center; }
.overlay.active { display: flex; }
.dialog { width: 300px; background: #fff; border-radius: 16px; padding: 24px 20px 16px; text-align: center; }
.dialog__title { font-size: 17px; font-weight: 700; color: #1a1a1a; margin-bottom: 8px; }
.dialog__msg { font-size: 14px; color: #666; margin-bottom: 20px; line-height: 1.6; }
.dialog__actions { display: flex; gap: 10px; }
.dialog__btn { flex: 1; padding: 10px 0; border-radius: 8px; font-size: 14px; font-weight: 600; cursor: pointer; border: 1px solid #d9d9d9; background: #fff; color: #333; }
.dialog__btn--primary { background: #1677ff; color: #fff; border-color: #1677ff; }
.dialog__btn--danger { background: #ff4d4f; color: #fff; border-color: #ff4d4f; }
.dialog__btn:active { opacity: 0.8; }
</style>
</head>
<body>
<div class="phone-shell">
<!-- 状态栏 -->
<div class="status-bar">
<span class="time">9:41</span>
<div class="icons"><span>●●●</span><span>WiFi</span><span>🔋</span></div>
</div>
<!-- 导航栏 -->
<!-- [交互] 点击返回体重管理详情 -->
<div class="nav-bar">
<button class="nav-back" onclick="location.href='./weight-detail.html'">
<svg width="10" height="16" viewBox="0 0 10 16" fill="none" stroke="currentColor" stroke-width="2"><path d="M8 1L2 8l6 7"/></svg>返回
</button>
<span class="nav-title">目标审核</span>
</div>
<!-- 申请时间顶栏 -->
<div class="time-bar">
<span class="time-bar__label">申请时间</span>
<span id="applyTime">2026-06-20 14:30</span>
</div>
<div class="scroll-content">
<!-- 基本信息卡片 -->
<div class="info-card">
<div class="info-card__name" id="personName">张小红</div>
<div class="info-card__meta" id="personMeta">
<span></span><span>32岁</span><span>身高 162cm</span>
</div>
</div>
<!-- 初始 / 目标 / 推荐范围 合并在一个卡片 -->
<div class="info-card">
<!-- 初始数据 -->
<div class="data-section">
<div class="data-section__label">初始数据</div>
<div class="data-section__vals" id="initialVals">
<span class="data-section__val">体重 72.5kg</span>
<span class="data-section__val">BMI 27.6</span>
<span class="data-section__val">体脂 32.1%</span>
<span class="data-section__val">腰围 86cm</span>
</div>
</div>
<div class="section-divider"></div>
<!-- 目标数据 -->
<div class="data-section">
<div class="data-section__label">目标数据</div>
<div class="data-section__vals" id="targetVals">
<span class="data-section__val data-section__val--target">体重 62kg</span>
<span class="data-section__val data-section__val--target">BMI 23.6</span>
<span class="data-section__val data-section__val--target">体脂 26%</span>
<span class="data-section__val data-section__val--target">腰围 76cm</span>
</div>
</div>
<div class="section-divider"></div>
<!-- 推荐范围 -->
<div class="data-section">
<div class="data-section__label">推荐数据范围</div>
<div class="range-row" id="rangeVals">
<div class="range-col">
<div class="range-col__label">体重</div>
<div class="range-col__range">58 ~ 65kg</div>
</div>
<div class="range-col">
<div class="range-col__label">体脂</div>
<div class="range-col__range">24% ~ 28%</div>
</div>
<div class="range-col">
<div class="range-col__label">腰围</div>
<div class="range-col__range">72 ~ 80cm</div>
</div>
</div>
</div>
</div>
<!-- 目标起止日期 -->
<div class="info-card">
<div class="info-card__title">目标起止日期</div>
<div class="date-range-row" id="dateRange">
<span>2026-06-20</span>
<span class="arrow"></span>
<span>2026-09-20</span>
</div>
</div>
<!-- 审核操作(待审核时显示) -->
<div class="action-area" id="actionArea">
<!-- [交互] 点击选择审核结果 -->
<div class="action-bar">
<div class="radio-item radio-item--approve selected" id="btnApprove" onclick="selectApprove()">
<span class="radio-dot"></span><span>审核通过</span>
</div>
<div class="radio-item radio-item--reject" id="btnReject" onclick="selectReject()">
<span class="radio-dot"></span><span>审核驳回</span>
</div>
</div>
<!-- 驳回原因 -->
<div class="reject-reason" id="rejectReason">
<div class="reject-reason__label">驳回原因</div>
<textarea class="reject-reason__textarea" id="rejectTextarea" placeholder="请输入驳回原因…"></textarea>
</div>
<!-- 提交按钮 -->
<!-- [交互] 点击提交确认审核结果 -->
<div class="submit-bar">
<button class="submit-btn" id="submitBtn" onclick="submitReview()">提交审核</button>
</div>
</div>
<!-- 审核结果信息(已审核状态时显示) -->
<div class="result-info" id="resultInfo">
<div class="result-info__row" id="resultStatus"></div>
<div class="result-info__row">
<span class="result-info__label">审核人</span>
<span id="resultReviewer">刘主管</span>
</div>
<div class="result-info__row">
<span class="result-info__label">审核时间</span>
<span id="resultTime">2026-06-16</span>
</div>
<div class="result-info__row" id="resultReasonRow" style="display:none;">
<span class="result-info__label">驳回原因</span>
<span id="resultReason">目标设定偏低,建议调整</span>
</div>
</div>
</div>
<!-- 确认弹窗 -->
<div class="overlay" id="confirmOverlay">
<div class="dialog">
<div class="dialog__title" id="dialogTitle">确认审核</div>
<div class="dialog__msg" id="dialogMsg"></div>
<div class="dialog__actions">
<button class="dialog__btn" onclick="closeDialog()">取消</button>
<button class="dialog__btn dialog__btn--primary" id="dialogConfirmBtn" onclick="confirmAction()">确认</button>
</div>
</div>
</div>
<!-- 成功弹窗 -->
<div class="overlay" id="successOverlay">
<div class="dialog">
<div class="dialog__title">审核完成</div>
<div class="dialog__msg" id="successMsg"></div>
<div class="dialog__actions" style="justify-content:center;">
<button class="dialog__btn dialog__btn--primary" style="flex:0 0 auto;padding:10px 40px;" onclick="goBack()">返回列表</button>
</div>
</div>
</div>
</div>
<script>
/* ===== 人员数据 ===== */
var personData = {
pending: {
name: '张小红', meta: '<span>女</span><span>32岁</span><span>身高 162cm</span>',
applyTime: '2026-06-20 14:30',
initial: '体重 72.5kg | BMI 27.6 | 体脂 32.1% | 腰围 86cm',
target: '体重 62kg | BMI 23.6 | 体脂 26% | 腰围 76cm',
range: [
{ label:'体重', val:'58 ~ 65kg' },
{ label:'体脂', val:'24% ~ 28%' },
{ label:'腰围', val:'72 ~ 80cm' }
],
dateStart: '2026-06-20', dateEnd: '2026-09-20'
},
approved: {
name: '王芳', meta: '<span>女</span><span>28岁</span><span>身高 160cm</span>',
applyTime: '2026-06-15 09:00',
initial: '体重 65kg | BMI 25.4 | 体脂 30% | 腰围 78cm',
target: '体重 56kg | BMI 21.9 | 体脂 24% | 腰围 70cm',
range: [
{ label:'体重', val:'53 ~ 60kg' },
{ label:'体脂', val:'22% ~ 26%' },
{ label:'腰围', val:'66 ~ 74cm' }
],
dateStart: '2026-06-15', dateEnd: '2026-09-15',
result: {
status: 'approved', reviewer: '刘主管', time: '2026-06-16'
}
},
signed: {
name: '陈伟', meta: '<span>男</span><span>36岁</span><span>身高 178cm</span>',
applyTime: '2026-06-12 16:20',
initial: '体重 92kg | BMI 29.0 | 体脂 30.2% | 腰围 102cm',
target: '体重 80kg | BMI 25.2 | 体脂 22% | 腰围 90cm',
range: [
{ label:'体重', val:'78 ~ 85kg' },
{ label:'体脂', val:'20% ~ 24%' },
{ label:'腰围', val:'86 ~ 94cm' }
],
dateStart: '2026-06-12', dateEnd: '2026-09-12',
result: {
status: 'signed', reviewer: '刘主管', time: '2026-06-14'
}
},
rejected: {
name: '刘海波', meta: '<span>男</span><span>52岁</span><span>身高 170cm</span>',
applyTime: '2026-06-10 11:00',
initial: '体重 85kg | BMI 29.4 | 体脂 33% | 腰围 100cm',
target: '体重 70kg | BMI 24.2 | 体脂 24% | 腰围 88cm',
range: [
{ label:'体重', val:'68 ~ 75kg' },
{ label:'体脂', val:'22% ~ 26%' },
{ label:'腰围', val:'84 ~ 92cm' }
],
dateStart: '2026-06-10', dateEnd: '2026-09-10',
result: {
status: 'rejected', reviewer: '刘主管', time: '2026-06-17', reason: '目标设定偏低,建议调整'
}
}
};
/* ===== 解析 URL 参数 ===== */
function getQueryParam(name) {
var match = location.search.match(new RegExp('[?&]' + name + '=([^&]*)'));
return match ? decodeURIComponent(match[1]) : null;
}
/* ===== 初始化页面 ===== */
function initPage() {
var status = getQueryParam('status') || 'pending';
var data = personData[status] || personData.pending;
// 基本信息
document.getElementById('personName').textContent = data.name;
document.getElementById('personMeta').innerHTML = data.meta;
document.getElementById('applyTime').textContent = data.applyTime;
// 初始数据
document.getElementById('initialVals').innerHTML = data.initial.split('|').map(function(s) {
return '<span class="data-section__val">' + s.trim() + '</span>';
}).join('');
// 目标数据
document.getElementById('targetVals').innerHTML = data.target.split('|').map(function(s) {
return '<span class="data-section__val data-section__val--target">' + s.trim() + '</span>';
}).join('');
// 推荐范围
document.getElementById('rangeVals').innerHTML = data.range.map(function(r) {
return '<div class="range-col"><div class="range-col__label">' + r.label + '</div><div class="range-col__range">' + r.val + '</div></div>';
}).join('');
// 日期
document.getElementById('dateRange').innerHTML = '<span>' + data.dateStart + '</span><span class="arrow">→</span><span>' + data.dateEnd + '</span>';
// 审核结果 / 操作区
if (status === 'pending') {
document.getElementById('actionArea').classList.remove('hidden');
document.getElementById('resultInfo').classList.remove('active');
selectApprove();
} else {
document.getElementById('actionArea').classList.add('hidden');
document.getElementById('resultInfo').classList.add('active');
var r = data.result;
// 状态标签
var tagHtml = '';
if (r.status === 'approved') tagHtml = '<span class="tag tag-green">已通过</span>';
else if (r.status === 'signed') tagHtml = '<span class="tag tag-orange">待签署</span>';
else if (r.status === 'rejected') tagHtml = '<span class="tag tag-red">已驳回</span>';
document.getElementById('resultStatus').innerHTML = tagHtml;
// 审核人 & 时间
document.getElementById('resultReviewer').textContent = r.reviewer;
document.getElementById('resultTime').textContent = r.time;
// 驳回原因
if (r.reason) {
document.getElementById('resultReasonRow').style.display = 'flex';
document.getElementById('resultReason').textContent = r.reason;
} else {
document.getElementById('resultReasonRow').style.display = 'none';
}
}
}
var selectedAction = null;
function selectApprove() {
selectedAction = 'approve';
document.getElementById('btnApprove').classList.add('selected');
document.getElementById('btnReject').classList.remove('selected');
document.getElementById('rejectReason').classList.remove('active');
}
function selectReject() {
selectedAction = 'reject';
document.getElementById('btnReject').classList.add('selected');
document.getElementById('btnApprove').classList.remove('selected');
document.getElementById('rejectReason').classList.add('active');
document.getElementById('rejectTextarea').focus();
}
function submitReview() {
if (!selectedAction) {
alert('请选择审核结果(通过或驳回)');
return;
}
if (selectedAction === 'reject') {
var reason = document.getElementById('rejectTextarea').value.trim();
if (!reason) { alert('请输入驳回原因'); return; }
showConfirmDialog('驳回', '确认驳回该目标申请?<br>驳回原因:' + reason, 'reject');
} else {
showConfirmDialog('通过', '确认通过该目标申请?', 'approve');
}
}
function showConfirmDialog(title, msg, action) {
document.getElementById('dialogTitle').textContent = title;
document.getElementById('dialogMsg').innerHTML = msg;
var confirmBtn = document.getElementById('dialogConfirmBtn');
if (action === 'reject') {
confirmBtn.className = 'dialog__btn dialog__btn--danger';
confirmBtn.textContent = '确认驳回';
} else {
confirmBtn.className = 'dialog__btn dialog__btn--primary';
confirmBtn.textContent = '确认通过';
}
confirmBtn.setAttribute('data-action', action);
document.getElementById('confirmOverlay').classList.add('active');
}
function closeDialog() {
document.getElementById('confirmOverlay').classList.remove('active');
}
function confirmAction() {
var action = document.getElementById('dialogConfirmBtn').getAttribute('data-action');
document.getElementById('confirmOverlay').classList.remove('active');
var msg = action === 'approve' ? '该目标申请已审核通过' : '该目标申请已驳回';
document.getElementById('successMsg').textContent = msg;
document.getElementById('successOverlay').classList.add('active');
}
function goBack() {
location.href = './weight-detail.html';
}
/* 启动 */
initPage();
</script>
</body>
</html>
+131
View File
@@ -0,0 +1,131 @@
<!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>
* { margin: 0; padding: 0; box-sizing: border-box; }
body { background: #f0f2f5; display: flex; justify-content: center; align-items: flex-start; min-height: 100vh; padding: 20px; font-family: -apple-system, BlinkMacSystemFont, 'PingFang SC', 'Helvetica Neue', sans-serif; }
.phone-shell { width: 390px; height: 844px; background: #fff; border-radius: 44px; box-shadow: 0 20px 60px rgba(0,0,0,0.25), inset 0 0 0 2px #e0e0e0; overflow: hidden; position: relative; display: flex; flex-direction: column; flex-shrink: 0; }
.status-bar { height: 44px; background: #fff; display: flex; align-items: center; justify-content: space-between; padding: 0 24px; flex-shrink: 0; z-index: 10; }
.status-bar .time { font-size: 15px; font-weight: 700; color: #1a1a1a; }
.status-bar .icons { display: flex; gap: 6px; align-items: center; font-size: 12px; color: #1a1a1a; }
.scroll-content { flex: 1; overflow-y: auto; background: #f7f8fa; }
.scroll-content::-webkit-scrollbar { display: none; }
/* 底部Tab栏 */
.tab-bar { height: 83px; background: #fff; border-top: 1px solid #e8e8e8; display: flex; align-items: flex-start; padding-top: 8px; flex-shrink: 0; }
.tab-item { flex: 1; display: flex; flex-direction: column; align-items: center; gap: 4px; cursor: pointer; padding: 4px 0; position: relative; }
.tab-item .tab-icon { font-size: 22px; line-height: 1; }
.tab-item .tab-label { font-size: 10px; color: #999; font-weight: 500; }
.tab-item.active .tab-label { color: #1677ff; }
.tab-badge { position: absolute; top: 2px; right: 18px; background: #ff4d4f; color: #fff; font-size: 10px; font-weight: 700; min-width: 16px; height: 16px; border-radius: 8px; display: flex; align-items: center; justify-content: center; padding: 0 4px; }
/* 功能入口卡片 */
.func-card { background: #fff; border-radius: 12px; margin: 10px 16px 0; padding: 16px; cursor: pointer; box-shadow: 0 1px 4px rgba(0,0,0,0.06); transition: transform 0.15s; }
.func-card:active { transform: scale(0.98); }
.func-card__header { display: flex; align-items: center; gap: 12px; }
.func-card__icon { width: 44px; height: 44px; border-radius: 12px; display: flex; align-items: center; justify-content: center; font-size: 22px; flex-shrink: 0; }
.func-card__icon--blue { background: linear-gradient(135deg, #e6f4ff, #b7d8ff); }
.func-card__icon--green { background: linear-gradient(135deg, #f6ffed, #b7eb8f); }
.func-card__icon--orange { background: linear-gradient(135deg, #fff7e6, #ffd591); }
.func-card__icon--red { background: linear-gradient(135deg, #fff1f0, #ffccc7); }
.func-card__info { flex: 1; min-width: 0; }
.func-card__title { font-size: 16px; font-weight: 600; color: #1a1a1a; }
.func-card__desc { font-size: 12px; color: #999; margin-top: 2px; }
.func-card__arrow { font-size: 14px; color: #bbb; flex-shrink: 0; }
</style>
</head>
<body>
<div class="phone-shell">
<!-- 状态栏 -->
<div class="status-bar">
<span class="time">9:41</span>
<div class="icons"><span>●●●</span><span>WiFi</span><span>🔋</span></div>
</div>
<!-- 蓝色渐变头部:个人信息 -->
<div style="background:linear-gradient(135deg,#1677ff,#0958d9);padding:16px 20px 20px;flex-shrink:0;">
<!-- 个人信息行 -->
<div style="display:flex;align-items:center;gap:12px;">
<!-- [交互] 点击头像可跳转至个人中心 -->
<div style="width:48px;height:48px;border-radius:50%;background:rgba(255,255,255,0.25);display:flex;align-items:center;justify-content:center;font-size:24px;flex-shrink:0;border:2px solid rgba(255,255,255,0.4);cursor:pointer;" onclick="location.href='../profile/index.html'">👤</div>
<div style="flex:1;min-width:0;">
<div style="color:#fff;font-size:18px;font-weight:700;">王建国</div>
<div style="color:rgba(255,255,255,0.85);font-size:13px;margin-top:2px;">健康管理员</div>
<div style="color:rgba(255,255,255,0.65);font-size:11px;margin-top:2px;">安全环保部 · 健康管理科</div>
</div>
</div>
</div>
<!-- 功能入口卡片列表 -->
<div class="scroll-content">
<!-- [交互] 点击跳转至: ./weight-detail.html -->
<div class="func-card" onclick="location.href='./weight-detail.html'">
<div class="func-card__header">
<div class="func-card__icon func-card__icon--blue">🏋️</div>
<div class="func-card__info">
<div class="func-card__title">体重管理详情</div>
<div class="func-card__desc">查看员工每日记录数据、减重排名及目标审核</div>
</div>
<span class="func-card__arrow"></span>
</div>
</div>
<!-- [交互] 点击跳转至: ./checkup-progress.html -->
<div class="func-card" onclick="location.href='./checkup-progress.html'">
<div class="func-card__header">
<div class="func-card__icon func-card__icon--green">🏥</div>
<div class="func-card__info">
<div class="func-card__title">体检进度跟踪</div>
<div class="func-card__desc">查看体检计划下员工预约、体检具体进度</div>
</div>
<span class="func-card__arrow"></span>
</div>
</div>
<!-- [交互] 点击跳转至: ./emergency-orders.html -->
<div class="func-card" onclick="location.href='./emergency-orders.html'">
<div class="func-card__header">
<div class="func-card__icon func-card__icon--orange">🚑</div>
<div class="func-card__info">
<div class="func-card__title">应急求助工单</div>
<div class="func-card__desc">查看员工发起应急求助记录及跟踪过程</div>
</div>
<span class="func-card__arrow"></span>
</div>
</div>
<!-- [交互] 点击跳转至: ./wearable-alerts.html -->
<div class="func-card" onclick="location.href='./wearable-alerts.html'">
<div class="func-card__header">
<div class="func-card__icon func-card__icon--red"></div>
<div class="func-card__info">
<div class="func-card__title">穿戴预警记录</div>
<div class="func-card__desc">查看佩戴穿戴设备的员工预警记录</div>
</div>
<span class="func-card__arrow"></span>
</div>
</div>
<div style="height:16px;"></div>
</div>
<!-- 底部5Tab导航栏 -->
<div class="tab-bar">
<div class="tab-item active" onclick="location.href='./index.html'"><span class="tab-icon">🏥</span><span class="tab-label">工作台</span><span class="tab-badge">3</span></div>
<div class="tab-item" onclick="location.href='../knowledge/index.html'"><span class="tab-icon">📚</span><span class="tab-label">知识库</span></div>
<div class="tab-item" onclick="location.href='../../ai-assistant/index.html'"><span class="tab-icon">🤖</span><span class="tab-label">AI助手</span></div>
<div class="tab-item" onclick="location.href='../../message/index.html'"><span class="tab-icon">💬</span><span class="tab-label">消息</span><span class="tab-badge">2</span></div>
<div class="tab-item" onclick="location.href='../profile/index.html'"><span class="tab-icon">👤</span><span class="tab-label">我的</span></div>
</div>
</div>
<script>
/* 标记当前角色为管理员,供共用页面(消息、AI助手)判断返回目标 */
sessionStorage.setItem('appRole', 'admin');
</script>
</body>
</html>
@@ -0,0 +1,268 @@
<!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>
* { margin: 0; padding: 0; box-sizing: border-box; }
body { background: #f0f2f5; display: flex; justify-content: center; align-items: flex-start; min-height: 100vh; padding: 20px; font-family: -apple-system, BlinkMacSystemFont, 'PingFang SC', 'Helvetica Neue', sans-serif; }
.phone-shell { width: 390px; height: 844px; background: #fff; border-radius: 44px; box-shadow: 0 20px 60px rgba(0,0,0,0.25), inset 0 0 0 2px #e0e0e0; overflow: hidden; position: relative; display: flex; flex-direction: column; flex-shrink: 0; }
.status-bar { height: 44px; background: #fff; display: flex; align-items: center; justify-content: space-between; padding: 0 24px; flex-shrink: 0; z-index: 10; }
.status-bar .time { font-size: 15px; font-weight: 700; color: #1a1a1a; }
.status-bar .icons { display: flex; gap: 6px; align-items: center; font-size: 12px; color: #1a1a1a; }
.nav-bar { height: 44px; background: #fff; display: flex; align-items: center; padding: 0 16px; flex-shrink: 0; border-bottom: 1px solid #f0f0f0; position: relative; }
.nav-back { display: flex; align-items: center; gap: 4px; color: #1677ff; font-size: 15px; cursor: pointer; background: none; border: none; padding: 4px 0; }
.nav-title { position: absolute; left: 50%; transform: translateX(-50%); font-size: 17px; font-weight: 600; color: #1a1a1a; white-space: nowrap; }
.scroll-content { flex: 1; overflow-y: auto; background: #f7f8fa; }
.scroll-content::-webkit-scrollbar { display: none; }
/* 筛选区 */
.filter-bar { display: flex; align-items: center; gap: 8px; padding: 10px 12px; background: #fff; border-bottom: 1px solid #f0f0f0; flex-shrink: 0; }
.filter-bar__select { display: flex; align-items: center; gap: 4px; padding: 6px 10px; background: #f7f8fa; border-radius: 6px; border: 1px solid #e8e8e8; cursor: pointer; font-size: 13px; color: #333; flex-shrink: 0; position: relative; }
.filter-bar__select-arrow { font-size: 10px; color: #bbb; transition: transform 0.2s; }
.filter-bar__select-arrow.open { transform: rotate(180deg); }
/* 下拉面板 */
.type-dropdown { display: none; position: absolute; top: 100%; left: 0; background: #fff; border-radius: 8px; box-shadow: 0 4px 16px rgba(0,0,0,0.12); z-index: 50; margin-top: 4px; width: 140px; max-height: 220px; overflow-y: auto; }
.type-dropdown.active { display: block; }
.type-dropdown__item { padding: 10px 12px; font-size: 13px; color: #333; cursor: pointer; border-bottom: 1px solid #f5f5f5; }
.type-dropdown__item:hover { background: #f7f8fa; }
.type-dropdown__item.selected { background: #e6f4ff; color: #1677ff; font-weight: 600; }
/* 预警标签 */
.alert-tag { display: inline-flex; align-items: center; gap: 4px; padding: 3px 10px; border-radius: 12px; font-size: 11px; font-weight: 600; }
.alert-tag--sos { background: #fff1f0; color: #ff4d4f; }
.alert-tag--temp { background: #fff7e6; color: #fa8c16; }
.alert-tag--heart { background: #fff0f6; color: #eb2f96; }
.alert-tag--spo2 { background: #f6ffed; color: #52c41a; }
.alert-tag--stress { background: #f9f0ff; color: #722ed1; }
.alert-tag--fall { background: #fffbe6; color: #d4b106; }
/* 预警卡片 */
.alert-card { background: #fff; border-radius: 12px; margin: 10px 12px 0; padding: 14px; box-shadow: 0 1px 4px rgba(0,0,0,0.06); }
.alert-card__header { display: flex; align-items: center; justify-content: space-between; margin-bottom: 10px; }
.alert-card__time { font-size: 12px; color: #999; }
.alert-card__abnormal { padding: 8px 10px; background: #f9fafb; border-radius: 8px; margin-bottom: 8px; display: flex; align-items: center; gap: 6px; }
.alert-card__abnormal-label { font-size: 12px; color: #999; flex-shrink: 0; }
.alert-card__abnormal-val { font-size: 14px; font-weight: 700; color: #ff4d4f; }
.alert-card__abnormal-unit { font-size: 11px; color: #999; font-weight: 400; margin-left: 2px; }
/* 员工信息行 */
.alert-card__emp { display: flex; align-items: center; gap: 8px; padding: 10px; background: #f9fafb; border-radius: 8px; margin-bottom: 8px; }
.alert-card__emp-avatar { width: 36px; height: 36px; border-radius: 50%; background: linear-gradient(135deg, #e6f4ff, #b7d8ff); display: flex; align-items: center; justify-content: center; font-size: 16px; color: #1677ff; flex-shrink: 0; font-weight: 700; }
.alert-card__emp-info { flex: 1; min-width: 0; }
.alert-card__emp-name { font-size: 14px; font-weight: 600; color: #1a1a1a; }
.alert-card__emp-meta { font-size: 11px; color: #999; margin-top: 2px; display: flex; gap: 6px; flex-wrap: wrap; }
.alert-card__address { font-size: 12px; color: #666; padding: 6px 0 0; display: flex; align-items: flex-start; gap: 4px; }
.alert-card__address-label { color: #999; flex-shrink: 0; font-size: 12px; }
.alert-card__address-text { color: #666; font-size: 12px; }
</style>
</head>
<body>
<div class="phone-shell">
<!-- 状态栏 -->
<div class="status-bar">
<span class="time">9:41</span>
<div class="icons"><span>●●●</span><span>WiFi</span><span>🔋</span></div>
</div>
<!-- 导航栏 -->
<!-- [交互] 点击返回工作台 -->
<div class="nav-bar">
<button class="nav-back" onclick="location.href='./index.html'">
<svg width="10" height="16" viewBox="0 0 10 16" fill="none" stroke="currentColor" stroke-width="2"><path d="M8 1L2 8l6 7"/></svg>返回
</button>
<span class="nav-title">穿戴预警记录</span>
</div>
<!-- 筛选区 -->
<div class="filter-bar">
<!-- [交互] 点击展开月份下拉 -->
<div class="filter-bar__select" onclick="toggleMonthDropdown()" style="position:relative;">
<span id="monthText">月份筛选</span>
<span class="filter-bar__select-arrow" id="monthArrow"></span>
<div class="type-dropdown" id="monthDropdown">
<div class="type-dropdown__item" onclick="selectMonth(event, '全部', '')">全部</div>
<div class="type-dropdown__item" onclick="selectMonth(event, '2026年6月', '2026-06')">2026年6月</div>
<div class="type-dropdown__item" onclick="selectMonth(event, '2026年5月', '2026-05')">2026年5月</div>
<div class="type-dropdown__item" onclick="selectMonth(event, '2026年4月', '2026-04')">2026年4月</div>
</div>
</div>
<!-- [交互] 点击展开预警类型下拉 -->
<div class="filter-bar__select" onclick="toggleTypeDropdown()" style="position:relative;">
<span id="typeText">预警类型</span>
<span class="filter-bar__select-arrow" id="typeArrow"></span>
<div class="type-dropdown" id="typeDropdown">
<div class="type-dropdown__item" onclick="selectType(event, '全部', 'all')">全部</div>
<div class="type-dropdown__item" onclick="selectType(event, '一键告警', 'sos')">一键告警</div>
<div class="type-dropdown__item" onclick="selectType(event, '体温异常', 'temp')">体温异常</div>
<div class="type-dropdown__item" onclick="selectType(event, '心率异常', 'heart')">心率异常</div>
<div class="type-dropdown__item" onclick="selectType(event, '血氧异常', 'spo2')">血氧异常</div>
<div class="type-dropdown__item" onclick="selectType(event, '压力异常', 'stress')">压力异常</div>
<div class="type-dropdown__item" onclick="selectType(event, '摔倒', 'fall')">摔倒</div>
</div>
</div>
</div>
<div class="scroll-content">
<!-- 统计条 -->
<div style="padding:10px 16px;font-size:12px;color:#999;" id="alertCount">共 12 条预警</div>
<div id="alert-list">
<!-- JS动态渲染 -->
</div>
<div style="height:16px;"></div>
</div>
</div>
<script>
/* ===== Mock数据 ===== */
var alertRecords = [
{ type:'sos', typeLabel:'一键告警', time:'2026-06-22 14:35:00', abnormal:'一键告警', abnormalUnit:'', empName:'张小红', empGender:'女', empAge:32, empNo:'CQ001256', empUnit:'公司机关', empDept:'办公室', address:'陕西省西安市雁塔区电子一路56号办公楼3层' },
{ type:'temp', typeLabel:'体温异常', time:'2026-06-22 10:12:00', abnormal:'38.7', abnormalUnit:'℃', empName:'李建国', empGender:'男', empAge:45, empNo:'CQ000832', empUnit:'采油一厂', empDept:'技术部', address:'陕西省西安市未央区凤城八路108号采油一厂A区' },
{ type:'heart', typeLabel:'心率异常', time:'2026-06-21 08:20:00', abnormal:'128', abnormalUnit:'次/分', empName:'赵志强', empGender:'男', empAge:61, empNo:'CQ000089', empUnit:'公司机关', empDept:'后勤部', address:'陕西省西安市雁塔区电子一路56号' },
{ type:'spo2', typeLabel:'血氧异常', time:'2026-06-20 16:05:00', abnormal:'91', abnormalUnit:'%', empName:'王芳', empGender:'女', empAge:28, empNo:'CQ001103', empUnit:'信息技术中心', empDept:'数据部', address:'陕西省西安市高新区高新路88号信息大厦12层' },
{ type:'stress', typeLabel:'压力异常', time:'2026-06-19 11:30:00', abnormal:'高', abnormalUnit:'', empName:'陈伟', empGender:'男', empAge:36, empNo:'CQ000567', empUnit:'安全环保部', empDept:'安环部', address:'陕西省西安市碑林区友谊西路127号' },
{ type:'fall', typeLabel:'摔倒', time:'2026-06-18 15:45:00', abnormal:'检测到摔倒', abnormalUnit:'', empName:'孙丽', empGender:'女', empAge:41, empNo:'CQ001340', empUnit:'采油一厂', empDept:'作业区', address:'陕西省西安市未央区凤城八路108号采油一厂B区2层' },
{ type:'temp', typeLabel:'体温异常', time:'2026-06-17 09:10:00', abnormal:'39.1', abnormalUnit:'℃', empName:'周明', empGender:'男', empAge:33, empNo:'CQ000921', empUnit:'信息技术中心', empDept:'技术部', address:'陕西省西安市高新区高新路88号信息大厦15层' },
{ type:'heart', typeLabel:'心率异常', time:'2026-06-16 22:30:00', abnormal:'135', abnormalUnit:'次/分', empName:'刘海波', empGender:'男', empAge:55, empNo:'CQ000234', empUnit:'公司机关', empDept:'行政部', address:'陕西省西安市雁塔区电子一路56号办公楼5层' },
{ type:'sos', typeLabel:'一键告警', time:'2026-06-15 07:55:00', abnormal:'一键告警', abnormalUnit:'', empName:'吴静', empGender:'女', empAge:26, empNo:'CQ001412', empUnit:'公司机关', empDept:'人力部', address:'陕西省西安市雁塔区电子一路56号办公楼2层' },
{ type:'spo2', typeLabel:'血氧异常', time:'2026-06-14 13:20:00', abnormal:'89', abnormalUnit:'%', empName:'黄晓明', empGender:'男', empAge:42, empNo:'CQ000789', empUnit:'采油一厂', empDept:'工程部', address:'陕西省西安市未央区凤城八路108号采油一厂C区' },
{ type:'fall', typeLabel:'摔倒', time:'2026-06-13 18:15:00', abnormal:'检测到摔倒', abnormalUnit:'', empName:'杨丽华', empGender:'女', empAge:39, empNo:'CQ001098', empUnit:'安全环保部', empDept:'安环部', address:'陕西省西安市碑林区友谊西路127号' },
{ type:'stress', typeLabel:'压力异常', time:'2026-06-12 10:40:00', abnormal:'极高', abnormalUnit:'', empName:'郑国强', empGender:'男', empAge:50, empNo:'CQ000456', empUnit:'公司机关', empDept:'财务部', address:'陕西省西安市雁塔区电子一路56号办公楼6层' }
];
/* ===== 工具函数 ===== */
function getAvatarChar(name) { return name.charAt(0); }
function getTypeTagClass(type) {
var map = {
sos: 'alert-tag--sos', temp: 'alert-tag--temp', heart: 'alert-tag--heart',
spo2: 'alert-tag--spo2', stress: 'alert-tag--stress', fall: 'alert-tag--fall'
};
return map[type] || '';
}
function getTypeIcon(type) {
var map = { sos:'🆘', temp:'🌡️', heart:'💓', spo2:'🫁', stress:'😰', fall:'🚨' };
return map[type] || '';
}
/* ===== 筛选状态 ===== */
var currentMonth = '';
var currentType = 'all';
function filterByMonth(list) {
if (!currentMonth) return list;
return list.filter(function(item) { return item.time.indexOf(currentMonth) === 0; });
}
function filterByType(list) {
if (currentType === 'all') return list;
return list.filter(function(item) { return item.type === currentType; });
}
/* ===== 渲染 ===== */
function renderAlertCard(item) {
var html = '<div class="alert-card">';
html += ' <div class="alert-card__header">';
html += ' <span style="font-size:14px;font-weight:700;color:#1a1a1a;">' + item.typeLabel + '</span>';
html += ' <span class="alert-card__time">' + item.time + '</span>';
html += ' </div>';
html += ' <div class="alert-card__abnormal">';
html += ' <span class="alert-card__abnormal-label">异常值</span>';
html += ' <span class="alert-card__abnormal-val">' + item.abnormal + '</span>';
if (item.abnormalUnit) {
html += ' <span class="alert-card__abnormal-unit">' + item.abnormalUnit + '</span>';
}
html += ' </div>';
html += ' <div class="alert-card__emp">';
html += ' <div class="alert-card__emp-avatar">' + getAvatarChar(item.empName) + '</div>';
html += ' <div class="alert-card__emp-info">';
html += ' <div class="alert-card__emp-name">' + item.empName + ' <span style="font-weight:400;font-size:11px;color:#999;">' + item.empNo + '</span></div>';
html += ' <div class="alert-card__emp-meta"><span>' + item.empGender + '</span><span>' + item.empAge + '岁</span><span>' + item.empUnit + '</span><span>' + item.empDept + '</span></div>';
html += ' </div>';
html += ' </div>';
html += ' <div class="alert-card__address">';
html += ' <span class="alert-card__address-label">📍</span>';
html += ' <span class="alert-card__address-text">' + item.address + '</span>';
html += ' </div>';
html += '</div>';
return html;
}
function renderList() {
var filtered = filterByType(filterByMonth(alertRecords));
document.getElementById('alertCount').textContent = '共 ' + filtered.length + ' 条预警';
var html = '';
if (filtered.length === 0) {
html = '<div style="text-align:center;padding:40px 16px;color:#999;font-size:14px;">暂无预警记录</div>';
} else {
filtered.forEach(function(item) {
html += renderAlertCard(item);
});
}
document.getElementById('alert-list').innerHTML = html;
}
/* ===== 月份筛选 ===== */
function toggleMonthDropdown() {
var dd = document.getElementById('monthDropdown');
var arrow = document.getElementById('monthArrow');
var isOpen = dd.classList.contains('active');
dd.classList.toggle('active');
if (isOpen) { arrow.classList.remove('open'); } else { arrow.classList.add('open'); }
}
function selectMonth(e, label, value) {
e.stopPropagation();
currentMonth = value;
document.getElementById('monthText').textContent = value ? label : '月份筛选';
document.querySelectorAll('#monthDropdown .type-dropdown__item').forEach(function(item) {
item.classList.toggle('selected', item.textContent === label);
});
document.getElementById('monthDropdown').classList.remove('active');
document.getElementById('monthArrow').classList.remove('open');
renderList();
}
/* ===== 预警类型筛选 ===== */
function toggleTypeDropdown() {
var dd = document.getElementById('typeDropdown');
var arrow = document.getElementById('typeArrow');
var isOpen = dd.classList.contains('active');
dd.classList.toggle('active');
if (isOpen) { arrow.classList.remove('open'); } else { arrow.classList.add('open'); }
}
function selectType(e, label, value) {
e.stopPropagation();
currentType = value;
document.getElementById('typeText').textContent = value === 'all' ? '预警类型' : label;
document.querySelectorAll('#typeDropdown .type-dropdown__item').forEach(function(item) {
item.classList.toggle('selected', item.textContent === label);
});
document.getElementById('typeDropdown').classList.remove('active');
document.getElementById('typeArrow').classList.remove('open');
renderList();
}
// 点击外部关闭下拉
document.addEventListener('click', function(e) {
if (!e.target.closest('.filter-bar__select')) {
document.getElementById('monthDropdown').classList.remove('active');
document.getElementById('monthArrow').classList.remove('open');
document.getElementById('typeDropdown').classList.remove('active');
document.getElementById('typeArrow').classList.remove('open');
}
});
/* ===== 初始化 ===== */
renderList();
</script>
</body>
</html>
@@ -0,0 +1,684 @@
<!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>
* { margin: 0; padding: 0; box-sizing: border-box; }
body { background: #f0f2f5; display: flex; justify-content: center; align-items: flex-start; min-height: 100vh; padding: 20px; font-family: -apple-system, BlinkMacSystemFont, 'PingFang SC', 'Helvetica Neue', sans-serif; }
.phone-shell { width: 390px; height: 844px; background: #fff; border-radius: 44px; box-shadow: 0 20px 60px rgba(0,0,0,0.25), inset 0 0 0 2px #e0e0e0; overflow: hidden; position: relative; display: flex; flex-direction: column; flex-shrink: 0; }
.status-bar { height: 44px; background: #fff; display: flex; align-items: center; justify-content: space-between; padding: 0 24px; flex-shrink: 0; z-index: 10; }
.status-bar .time { font-size: 15px; font-weight: 700; color: #1a1a1a; }
.status-bar .icons { display: flex; gap: 6px; align-items: center; font-size: 12px; color: #1a1a1a; }
.nav-bar { height: 44px; background: #fff; display: flex; align-items: center; padding: 0 16px; flex-shrink: 0; border-bottom: 1px solid #f0f0f0; position: relative; }
.nav-back { display: flex; align-items: center; gap: 4px; color: #1677ff; font-size: 15px; cursor: pointer; background: none; border: none; padding: 4px 0; }
.nav-title { position: absolute; left: 50%; transform: translateX(-50%); font-size: 17px; font-weight: 600; color: #1a1a1a; white-space: nowrap; }
.scroll-content { flex: 1; overflow-y: auto; background: #f7f8fa; }
.scroll-content::-webkit-scrollbar { display: none; }
/* 主Tab */
.main-tabs { display: flex; background: #fff; border-bottom: 1px solid #f0f0f0; flex-shrink: 0; }
.main-tab { flex: 1; text-align: center; padding: 12px 0; font-size: 14px; color: #666; cursor: pointer; border-bottom: 2px solid transparent; transition: all 0.2s; }
.main-tab.active { color: #1677ff; border-bottom-color: #1677ff; font-weight: 600; }
/* 子Tab */
.sub-tabs { display: flex; gap: 8px; padding: 10px 12px; background: #fff; flex-shrink: 0; flex-wrap: wrap; }
.sub-tab { font-size: 12px; padding: 4px 14px; border-radius: 16px; background: #f5f5f5; color: #666; cursor: pointer; transition: all 0.2s; white-space: nowrap; }
.sub-tab.active { background: #e6f4ff; color: #1677ff; font-weight: 600; }
.sub-tab .badge { display: inline-block; background: #ff4d4f; color: #fff; font-size: 10px; font-weight: 700; min-width: 16px; height: 16px; border-radius: 8px; padding: 0 4px; margin-left: 4px; vertical-align: middle; line-height: 16px; }
/* 标签 */
.tag { display: inline-block; padding: 2px 8px; border-radius: 4px; font-size: 11px; font-weight: 600; }
.tag-blue { background: #e6f4ff; color: #1677ff; }
.tag-green { background: #f6ffed; color: #52c41a; }
.tag-orange { background: #fff7e6; color: #fa8c16; }
.tag-red { background: #fff1f0; color: #ff4d4f; }
.tag-gray { background: #f5f5f5; color: #999; }
/* 计划信息区 */
.plan-info { background: #fff; padding: 12px 16px; margin: 0; border-bottom: 1px solid #f0f0f0; }
.plan-title-row { display: flex; align-items: center; justify-content: space-between; margin-bottom: 8px; }
.plan-title-row__title { font-size: 14px; font-weight: 700; color: #1a1a1a; }
.plan-title-row__date { font-size: 12px; color: #666; }
.plan-select { display: flex; align-items: center; gap: 8px; padding: 8px 12px; background: #f7f8fa; border-radius: 8px; cursor: pointer; position: relative; border: 1px solid #e8e8e8; }
.plan-select__text { flex: 1; font-size: 14px; font-weight: 600; color: #1a1a1a; }
.plan-select__arrow { font-size: 12px; color: #bbb; transition: transform 0.2s; }
.plan-select__arrow.open { transform: rotate(180deg); }
.plan-meta { display: flex; gap: 0; margin-top: 10px; }
.plan-meta__item { flex: 1; text-align: center; padding: 0 6px; }
.plan-meta__item + .plan-meta__item { border-left: 1px solid #f0f0f0; }
.plan-meta__val { font-size: 15px; font-weight: 700; color: #1a1a1a; }
.plan-meta__label { font-size: 10px; color: #999; margin-top: 2px; }
/* 计划下拉面板 */
.plan-dropdown { display: none; position: absolute; top: 100%; left: 0; right: 0; background: #fff; border-radius: 8px; box-shadow: 0 4px 16px rgba(0,0,0,0.12); z-index: 50; margin-top: 4px; max-height: 200px; overflow-y: auto; }
.plan-dropdown.active { display: block; }
.plan-dropdown__item { padding: 10px 12px; font-size: 13px; color: #333; cursor: pointer; border-bottom: 1px solid #f5f5f5; }
.plan-dropdown__item:hover { background: #f7f8fa; }
.plan-dropdown__item.selected { background: #e6f4ff; color: #1677ff; font-weight: 600; }
/* 日期导航 */
.date-nav { display: flex; align-items: center; justify-content: center; gap: 8px; padding: 10px 16px; background: #fff; border-bottom: 1px solid #f0f0f0; position: relative; }
.date-nav__arrow { width: 32px; height: 32px; border-radius: 50%; background: #f5f5f5; display: flex; align-items: center; justify-content: center; cursor: pointer; border: none; color: #666; font-size: 16px; flex-shrink: 0; }
.date-nav__arrow:active { background: #e6f4ff; }
.date-nav__text { font-size: 15px; font-weight: 600; color: #1a1a1a; min-width: 110px; text-align: center; }
.date-nav__cal { width: 28px; height: 28px; border-radius: 6px; background: none; display: flex; align-items: center; justify-content: center; cursor: pointer; border: none; font-size: 16px; flex-shrink: 0; color: #1677ff; }
.date-nav__cal:active { background: #e6f4ff; }
/* 日历面板 */
.cal-panel { display: none; position: absolute; top: 42px; left: 16px; right: 16px; background: #fff; border-radius: 14px; box-shadow: 0 8px 30px rgba(0,0,0,0.15); z-index: 100; padding: 16px; }
.cal-panel.active { display: block; }
.cal-panel__head { display: flex; align-items: center; justify-content: space-between; margin-bottom: 12px; }
.cal-panel__month { font-size: 15px; font-weight: 700; color: #1a1a1a; }
.cal-panel__nav { width: 28px; height: 28px; border-radius: 50%; border: none; background: #f5f5f5; cursor: pointer; font-size: 14px; color: #666; display: flex; align-items: center; justify-content: center; }
.cal-panel__nav:active { background: #e6f4ff; }
.cal-panel__weekdays { display: flex; margin-bottom: 6px; }
.cal-panel__weekday { flex: 1; text-align: center; font-size: 11px; color: #999; padding: 4px 0; }
.cal-panel__grid { display: flex; flex-wrap: wrap; }
.cal-panel__day { width: calc(100% / 7); text-align: center; padding: 8px 0; font-size: 13px; color: #333; cursor: pointer; border-radius: 8px; }
.cal-panel__day--other { color: #ddd; }
.cal-panel__day:hover { background: #f5f5f5; }
.cal-panel__day--today { font-weight: 700; color: #1677ff; }
.cal-panel__day--selected { background: #1677ff; color: #fff; font-weight: 700; }
.cal-panel__day--selected:hover { background: #1677ff; }
/* 每日记录卡片 */
.day-card { background: #fff; border-radius: 12px; margin: 10px 12px 0; padding: 14px; box-shadow: 0 1px 4px rgba(0,0,0,0.06); }
.day-card__header { display: flex; align-items: center; gap: 8px; margin-bottom: 10px; }
.day-card__icon { width: 36px; height: 36px; border-radius: 10px; display: flex; align-items: center; justify-content: center; font-size: 18px; flex-shrink: 0; }
.day-card__icon--blue { background: #e6f4ff; }
.day-card__icon--green { background: #f6ffed; }
.day-card__icon--orange { background: #fff7e6; }
.day-card__title { font-size: 15px; font-weight: 600; color: #1a1a1a; flex: 1; }
.day-card__link { font-size: 12px; color: #1677ff; cursor: pointer; flex-shrink: 0; white-space: nowrap; background: none; border: none; }
.day-card__body { display: flex; gap: 0; background: #f9fafb; border-radius: 8px; padding: 10px 0; margin-bottom: 10px; }
.day-card__stat { flex: 1; text-align: center; }
.day-card__stat-num { font-size: 20px; font-weight: 700; }
.day-card__stat-num--green { color: #52c41a; }
.day-card__stat-num--red { color: #ff4d4f; }
.day-card__stat-label { font-size: 11px; color: #999; margin-top: 2px; }
.day-card__stat-divider { width: 1px; background: #e8e8e8; align-self: stretch; }
/* 排名Tab(参考 employee weight-ranking */
.rank-tabs { display: flex; border-bottom: 1px solid #f0f0f0; background: #fff; }
.rank-tab { flex: 1; text-align: center; padding: 12px 0 10px; font-size: 13px; font-weight: 600; color: #bbb; cursor: pointer; position: relative; white-space: nowrap; }
.rank-tab.active { color: #1677ff; }
.rank-tab.active::after { content: ''; position: absolute; bottom: -1px; left: 50%; transform: translateX(-50%); width: 36px; height: 3px; background: #1677ff; border-radius: 2px; }
.rank-list-header { display: flex; align-items: center; padding: 8px 12px; border-bottom: 1px solid #f0f0f0; background: #fff; }
.rank-list-header span { font-size: 11px; color: #999; }
.rank-list-header__rank { width: 36px; text-align: center; flex-shrink: 0; }
.rank-list-header__user { flex: 1; padding-left: 4px; }
.rank-list-header__score { width: 56px; text-align: right; flex-shrink: 0; }
.rank-list { background: #fff; padding: 4px 12px 12px; }
.rank-item { display: flex; align-items: center; padding: 10px 4px; border-bottom: 1px solid #f8f8f8; gap: 4px; }
.rank-item:last-child { border-bottom: none; }
.rank-item__num { width: 36px; height: 30px; flex-shrink: 0; display: flex; align-items: center; justify-content: center; }
.rank-item__num-text { font-size: 14px; font-weight: 700; color: #666; }
.rank-item__num--gold { width: 28px; height: 28px; border-radius: 50%; background: linear-gradient(135deg, #ffd700, #ffb300); margin: 0 auto; }
.rank-item__num--silver { width: 28px; height: 28px; border-radius: 50%; background: linear-gradient(135deg, #b0bec5, #90a4ae); margin: 0 auto; }
.rank-item__num--bronze { width: 28px; height: 28px; border-radius: 50%; background: linear-gradient(135deg, #cd7f32, #a0522d); margin: 0 auto; }
.rank-item__user { flex: 1; min-width: 0; padding-left: 2px; }
.rank-item__name { font-size: 14px; font-weight: 600; color: #1a1a1a; }
.rank-item__dept { font-size: 11px; color: #999; margin-top: 1px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.rank-item__score { width: 56px; text-align: right; flex-shrink: 0; }
.rank-item__score-val { font-size: 14px; font-weight: 700; color: #1a1a1a; }
.rank-item__score-unit { font-size: 10px; color: #999; margin-left: 1px; }
/* 目标审核卡片 */
.review-card { background: #fff; border-radius: 12px; margin: 10px 12px 0; padding: 14px; box-shadow: 0 1px 4px rgba(0,0,0,0.06); }
.review-card__head { display: flex; align-items: center; justify-content: space-between; margin-bottom: 8px; }
.review-card__name { font-size: 15px; font-weight: 600; color: #1a1a1a; }
.review-card__time { font-size: 11px; color: #bbb; }
.review-card__basic { display: flex; gap: 12px; font-size: 12px; color: #666; margin-bottom: 10px; }
.review-card__row { display: flex; gap: 0; margin-bottom: 8px; }
.review-card__col { flex: 1; }
.review-card__col-title { font-size: 11px; color: #999; margin-bottom: 4px; }
.review-card__col-vals { display: flex; gap: 8px; }
.review-card__col-val { font-size: 13px; font-weight: 600; color: #333; }
.review-card__actions { display: flex; gap: 8px; margin-top: 10px; }
.review-card__btn { flex: 1; padding: 8px 0; border-radius: 6px; font-size: 13px; font-weight: 600; text-align: center; cursor: pointer; border: 1px solid #d9d9d9; background: #fff; color: #666; }
.review-card__btn:active { opacity: 0.8; }
.review-card__btn--primary { background: #1677ff; color: #fff; border-color: #1677ff; }
.review-card__btn--danger { background: #fff; color: #ff4d4f; border-color: #ff4d4f; }
</style>
</head>
<body>
<div class="phone-shell">
<!-- 状态栏 -->
<div class="status-bar">
<span class="time">9:41</span>
<div class="icons"><span>●●●</span><span>WiFi</span><span>🔋</span></div>
</div>
<!-- 导航栏 -->
<!-- [交互] 点击返回工作台 -->
<div class="nav-bar">
<button class="nav-back" onclick="location.href='./index.html'">
<svg width="10" height="16" viewBox="0 0 10 16" fill="none" stroke="currentColor" stroke-width="2"><path d="M8 1L2 8l6 7"/></svg>返回
</button>
<span class="nav-title">体重管理详情</span>
</div>
<!-- 干预计划信息 -->
<div class="plan-info">
<!-- 标题行:当前活动 + 起止日期 -->
<div class="plan-title-row">
<span class="plan-title-row__title">当前活动</span>
<span class="plan-title-row__date" id="planDateRange">2026-04-01 至 2026-06-29</span>
</div>
<!-- [交互] 点击展开计划选择下拉 -->
<div class="plan-select" onclick="togglePlanDropdown()" style="position:relative;">
<span class="plan-select__text" id="planSelectText">2026年二季度体重管理活动</span>
<span class="plan-select__arrow" id="planSelectArrow"></span>
<div class="plan-dropdown" id="planDropdown">
<div class="plan-dropdown__item selected" onclick="selectPlan(event, '2026年二季度体重管理活动', '2026-04-01', '90', '120', '86')">2026年二季度体重管理活动</div>
<div class="plan-dropdown__item" onclick="selectPlan(event, '2026年一季度体重管理活动', '2026-01-01', '90', '100', '100')">2026年一季度体重管理活动</div>
<div class="plan-dropdown__item" onclick="selectPlan(event, '2025年四季度减重挑战', '2025-10-01', '92', '80', '80')">2025年四季度减重挑战</div>
</div>
</div>
<div class="plan-meta">
<div class="plan-meta__item">
<div class="plan-meta__val" id="planDays">90/90</div>
<div class="plan-meta__label">活动进行天数</div>
</div>
<div class="plan-meta__item">
<div class="plan-meta__val" id="planExpected">120</div>
<div class="plan-meta__label">应参加人数</div>
</div>
<div class="plan-meta__item">
<div class="plan-meta__val" id="planActual">86</div>
<div class="plan-meta__label">已参加人数</div>
</div>
</div>
</div>
<!-- 主Tab:每日记录 / 减重排名 / 目标审核 -->
<div class="main-tabs">
<div class="main-tab active" onclick="switchMainTab(this,'panel-record')">每日记录</div>
<div class="main-tab" onclick="switchMainTab(this,'panel-ranking')">减重排名</div>
<div class="main-tab" onclick="switchMainTab(this,'panel-review')">目标审核</div>
</div>
<div class="scroll-content">
<!-- ==================== 每日记录面板 ==================== -->
<div id="panel-record">
<!-- 日期导航 -->
<div class="date-nav">
<button class="date-nav__arrow" onclick="changeDate(-1)"></button>
<!-- [交互] 点击日历图标打开日期选择面板 -->
<button class="date-nav__cal" onclick="toggleCalPanel()">📅</button>
<span class="date-nav__text" id="dateText">2026-06-22(今日)</span>
<button class="date-nav__arrow" onclick="changeDate(1)"></button>
<!-- 日历选择面板 -->
<div class="cal-panel" id="calPanel">
<div class="cal-panel__head">
<button class="cal-panel__nav" onclick="calPrevMonth(event)"></button>
<span class="cal-panel__month" id="calMonthLabel">2026年6月</span>
<button class="cal-panel__nav" onclick="calNextMonth(event)"></button>
</div>
<div class="cal-panel__weekdays">
<div class="cal-panel__weekday"></div><div class="cal-panel__weekday"></div><div class="cal-panel__weekday"></div><div class="cal-panel__weekday"></div><div class="cal-panel__weekday"></div><div class="cal-panel__weekday"></div><div class="cal-panel__weekday"></div>
</div>
<div class="cal-panel__grid" id="calGrid"></div>
</div>
</div>
<!-- 当日饮食卡片 -->
<!-- [交互] 点击查看跳转至饮食记录详情 -->
<div class="day-card">
<div class="day-card__header">
<div class="day-card__icon day-card__icon--blue">🍽️</div>
<div class="day-card__title">当日饮食</div>
<span class="day-card__link" onclick="location.href='./eat-detail.html'">查看详情 </span>
</div>
<div class="day-card__body">
<div class="day-card__stat">
<div class="day-card__stat-num day-card__stat-num--green">78</div>
<div class="day-card__stat-label">已打卡人数</div>
</div>
<div class="day-card__stat-divider"></div>
<div class="day-card__stat">
<div class="day-card__stat-num day-card__stat-num--red">8</div>
<div class="day-card__stat-label">未打卡人数</div>
</div>
</div>
</div>
<!-- 当日运动卡片 -->
<!-- [交互] 点击查看跳转至运动记录详情 -->
<div class="day-card">
<div class="day-card__header">
<div class="day-card__icon day-card__icon--green">🏃</div>
<div class="day-card__title">当日运动</div>
<span class="day-card__link" onclick="location.href='./exercise-detail.html'">查看详情 </span>
</div>
<div class="day-card__body">
<div class="day-card__stat">
<div class="day-card__stat-num day-card__stat-num--green">65</div>
<div class="day-card__stat-label">已打卡人数</div>
</div>
<div class="day-card__stat-divider"></div>
<div class="day-card__stat">
<div class="day-card__stat-num day-card__stat-num--red">21</div>
<div class="day-card__stat-label">未打卡人数</div>
</div>
</div>
</div>
<!-- 当日体重卡片 -->
<!-- [交互] 点击查看跳转至体重记录详情 -->
<div class="day-card">
<div class="day-card__header">
<div class="day-card__icon day-card__icon--orange">⚖️</div>
<div class="day-card__title">当日体重</div>
<span class="day-card__link" onclick="location.href='./weight-record.html'">查看详情 </span>
</div>
<div class="day-card__body">
<div class="day-card__stat">
<div class="day-card__stat-num day-card__stat-num--green">72</div>
<div class="day-card__stat-label">已打卡人数</div>
</div>
<div class="day-card__stat-divider"></div>
<div class="day-card__stat">
<div class="day-card__stat-num day-card__stat-num--red">14</div>
<div class="day-card__stat-label">未打卡人数</div>
</div>
</div>
</div>
<div style="height:16px;"></div>
</div>
<!-- ==================== 减重排名面板 ==================== -->
<div id="panel-ranking" style="display:none;">
<!-- 排名子Tab -->
<div class="rank-tabs" id="rankTabs">
<div class="rank-tab active" data-tab="weight" onclick="switchRankTab('weight')">减重量</div>
<div class="rank-tab" data-tab="rate" onclick="switchRankTab('rate')">减重率</div>
<div class="rank-tab" data-tab="score" onclick="switchRankTab('score')">综合分</div>
<div class="rank-tab" data-tab="action" onclick="switchRankTab('action')">行动分</div>
</div>
<!-- 排行榜列表头 -->
<div class="rank-list-header">
<span class="rank-list-header__rank">排名</span>
<span class="rank-list-header__user">员工</span>
<span class="rank-list-header__score" id="rankListHeader">减重量</span>
</div>
<!-- 排行榜列表 -->
<div class="rank-list" id="rankList">
<!-- JS动态渲染 -->
</div>
<div style="height:16px;"></div>
</div>
<!-- ==================== 目标审核面板 ==================== -->
<div id="panel-review" style="display:none;">
<!-- 审核子Tab -->
<div class="sub-tabs" id="reviewTabs">
<div class="sub-tab active" onclick="switchReviewTab(this,'rv-pending')">待审核<span class="badge">2</span></div>
<div class="sub-tab" onclick="switchReviewTab(this,'rv-approved')">已通过</div>
<div class="sub-tab" onclick="switchReviewTab(this,'rv-signed')">已通过待签署</div>
<div class="sub-tab" onclick="switchReviewTab(this,'rv-rejected')">已驳回</div>
</div>
<!-- 待审核列表 -->
<div id="rv-pending">
<!-- 审核卡片1 -->
<div class="review-card">
<div class="review-card__head">
<span class="review-card__name">张小红</span>
<span class="review-card__time">申请时间:2026-06-20 14:30</span>
</div>
<div class="review-card__basic">
<span></span><span>32岁</span><span>身高 162cm</span>
</div>
<div class="review-card__row">
<div class="review-card__col">
<div class="review-card__col-title">初始</div>
<div class="review-card__col-vals">
<span class="review-card__col-val">体重 72.5kg</span>
<span class="review-card__col-val">BMI 27.6</span>
<span class="review-card__col-val">体脂 32.1%</span>
<span class="review-card__col-val">腰围 86cm</span>
</div>
</div>
</div>
<div class="review-card__row">
<div class="review-card__col">
<div class="review-card__col-title">目标</div>
<div class="review-card__col-vals">
<span class="review-card__col-val" style="color:#52c41a;">体重 62kg</span>
<span class="review-card__col-val" style="color:#52c41a;">BMI 23.6</span>
<span class="review-card__col-val" style="color:#52c41a;">体脂 26%</span>
<span class="review-card__col-val" style="color:#52c41a;">腰围 76cm</span>
</div>
</div>
</div>
<!-- [交互] 点击审核跳转至审核页面 -->
<div class="review-card__actions">
<button class="review-card__btn review-card__btn--primary" onclick="location.href='./goal-review.html'">审核</button>
</div>
</div>
<!-- 审核卡片2 -->
<div class="review-card">
<div class="review-card__head">
<span class="review-card__name">李建国</span>
<span class="review-card__time">申请时间:2026-06-19 10:15</span>
</div>
<div class="review-card__basic">
<span></span><span>45岁</span><span>身高 175cm</span>
</div>
<div class="review-card__row">
<div class="review-card__col">
<div class="review-card__col-title">初始</div>
<div class="review-card__col-vals">
<span class="review-card__col-val">体重 88.2kg</span>
<span class="review-card__col-val">BMI 28.8</span>
<span class="review-card__col-val">体脂 28.5%</span>
<span class="review-card__col-val">腰围 98cm</span>
</div>
</div>
</div>
<div class="review-card__row">
<div class="review-card__col">
<div class="review-card__col-title">目标</div>
<div class="review-card__col-vals">
<span class="review-card__col-val" style="color:#52c41a;">体重 78kg</span>
<span class="review-card__col-val" style="color:#52c41a;">BMI 25.5</span>
<span class="review-card__col-val" style="color:#52c41a;">体脂 22%</span>
<span class="review-card__col-val" style="color:#52c41a;">腰围 88cm</span>
</div>
</div>
</div>
<!-- [交互] 点击审核跳转至审核页面 -->
<div class="review-card__actions">
<button class="review-card__btn review-card__btn--primary" onclick="location.href='./goal-review.html'">审核</button>
</div>
</div>
<div style="height:16px;"></div>
</div>
<!-- 已通过列表 -->
<div id="rv-approved" style="display:none;">
<!-- [交互] 点击卡片跳转至审核详情页面 -->
<div class="review-card" onclick="location.href='./goal-review.html?status=approved'" style="cursor:pointer;">
<div class="review-card__head">
<span class="review-card__name">王芳</span>
<span class="review-card__time">申请时间:2026-06-15 09:00</span>
</div>
<div class="review-card__basic"><span></span><span>28岁</span><span>身高 160cm</span></div>
<div class="review-card__row"><div class="review-card__col"><div class="review-card__col-title">初始</div><div class="review-card__col-vals"><span class="review-card__col-val">体重 65kg</span><span class="review-card__col-val">BMI 25.4</span><span class="review-card__col-val">体脂 30%</span><span class="review-card__col-val">腰围 78cm</span></div></div></div>
<div class="review-card__row"><div class="review-card__col"><div class="review-card__col-title">目标</div><div class="review-card__col-vals"><span class="review-card__col-val" style="color:#52c41a;">体重 56kg</span><span class="review-card__col-val" style="color:#52c41a;">BMI 21.9</span><span class="review-card__col-val" style="color:#52c41a;">体脂 24%</span><span class="review-card__col-val" style="color:#52c41a;">腰围 70cm</span></div></div></div>
<div style="text-align:right;margin-top:8px;"><span class="tag tag-green">已通过</span><span style="font-size:11px;color:#999;margin-left:6px;">审核人:刘主管</span><span style="font-size:11px;color:#999;margin-left:6px;">审核时间:2026-06-16</span></div>
</div>
<div style="height:16px;"></div>
</div>
<!-- 已通过待签署列表 -->
<div id="rv-signed" style="display:none;">
<!-- [交互] 点击卡片跳转至审核详情页面 -->
<div class="review-card" onclick="location.href='./goal-review.html?status=signed'" style="cursor:pointer;">
<div class="review-card__head">
<span class="review-card__name">陈伟</span>
<span class="review-card__time">申请时间:2026-06-12 16:20</span>
</div>
<div class="review-card__basic"><span></span><span>36岁</span><span>身高 178cm</span></div>
<div class="review-card__row"><div class="review-card__col"><div class="review-card__col-title">初始</div><div class="review-card__col-vals"><span class="review-card__col-val">体重 92kg</span><span class="review-card__col-val">BMI 29.0</span><span class="review-card__col-val">体脂 30.2%</span><span class="review-card__col-val">腰围 102cm</span></div></div></div>
<div class="review-card__row"><div class="review-card__col"><div class="review-card__col-title">目标</div><div class="review-card__col-vals"><span class="review-card__col-val" style="color:#52c41a;">体重 80kg</span><span class="review-card__col-val" style="color:#52c41a;">BMI 25.2</span><span class="review-card__col-val" style="color:#52c41a;">体脂 22%</span><span class="review-card__col-val" style="color:#52c41a;">腰围 90cm</span></div></div></div>
<div style="text-align:right;margin-top:8px;"><span class="tag tag-orange">待签署</span><span style="font-size:11px;color:#999;margin-left:6px;">审核人:刘主管</span><span style="font-size:11px;color:#999;margin-left:6px;">审核时间:2026-06-14</span></div>
</div>
<div style="height:16px;"></div>
</div>
<!-- 已驳回列表 -->
<div id="rv-rejected" style="display:none;">
<!-- [交互] 点击卡片跳转至审核详情页面 -->
<div class="review-card" onclick="location.href='./goal-review.html?status=rejected'" style="cursor:pointer;">
<div class="review-card__head">
<span class="review-card__name">刘海波</span>
<span class="review-card__time">申请时间:2026-06-10 11:00</span>
</div>
<div class="review-card__basic"><span></span><span>52岁</span><span>身高 170cm</span></div>
<div class="review-card__row"><div class="review-card__col"><div class="review-card__col-title">初始</div><div class="review-card__col-vals"><span class="review-card__col-val">体重 85kg</span><span class="review-card__col-val">BMI 29.4</span><span class="review-card__col-val">体脂 33%</span><span class="review-card__col-val">腰围 100cm</span></div></div></div>
<div class="review-card__row"><div class="review-card__col"><div class="review-card__col-title">目标</div><div class="review-card__col-vals"><span class="review-card__col-val" style="color:#52c41a;">体重 70kg</span><span class="review-card__col-val" style="color:#52c41a;">BMI 24.2</span><span class="review-card__col-val" style="color:#52c41a;">体脂 24%</span><span class="review-card__col-val" style="color:#52c41a;">腰围 88cm</span></div></div></div>
<div style="text-align:right;margin-top:8px;"><span class="tag tag-red">已驳回</span><span style="font-size:11px;color:#999;margin-left:6px;">审核人:刘主管</span><span style="font-size:11px;color:#999;margin-left:6px;">审核时间:2026-06-17</span></div>
<div style="text-align:right;margin-top:4px;"><span style="font-size:11px;color:#999;">驳回原因:目标设定偏低,建议调整</span></div>
</div>
<div style="height:16px;"></div>
</div>
</div>
</div>
</div>
<script>
/* ===== 计划选择 ===== */
function togglePlanDropdown() {
var dd = document.getElementById('planDropdown');
var arrow = document.getElementById('planSelectArrow');
var isOpen = dd.classList.contains('active');
dd.classList.toggle('active');
if (isOpen) { arrow.classList.remove('open'); } else { arrow.classList.add('open'); }
}
function calcEndDate(startStr, totalDays) {
var d = new Date(startStr);
d.setDate(d.getDate() + totalDays - 1);
return d.getFullYear() + '-' + String(d.getMonth() + 1).padStart(2, '0') + '-' + String(d.getDate()).padStart(2, '0');
}
function selectPlan(e, name, startDate, days, expected, actual) {
e.stopPropagation();
document.getElementById('planSelectText').textContent = name;
// 计算结束日期并更新标题行
var endDate = calcEndDate(startDate, parseInt(days));
document.getElementById('planDateRange').textContent = startDate + ' 至 ' + endDate;
document.getElementById('planDays').textContent = days + '/' + days;
document.getElementById('planExpected').textContent = expected;
document.getElementById('planActual').textContent = actual;
// 更新下拉选中态
document.querySelectorAll('.plan-dropdown__item').forEach(function(item) {
item.classList.toggle('selected', item.textContent === name);
});
document.getElementById('planDropdown').classList.remove('active');
document.getElementById('planSelectArrow').classList.remove('open');
}
// 点击外部关闭下拉
document.addEventListener('click', function(e) {
if (!e.target.closest('.plan-select')) {
document.getElementById('planDropdown').classList.remove('active');
document.getElementById('planSelectArrow').classList.remove('open');
}
});
/* ===== 主Tab切换 ===== */
function switchMainTab(el, panelId) {
el.closest('.main-tabs').querySelectorAll('.main-tab').forEach(function(t) { t.classList.remove('active'); });
el.classList.add('active');
['panel-record','panel-ranking','panel-review'].forEach(function(id) {
document.getElementById(id).style.display = id === panelId ? 'block' : 'none';
});
}
/* ===== 日期导航 ===== */
var currentDate = new Date(2026, 5, 22); // 6月=5
var calViewYear = currentDate.getFullYear();
var calViewMonth = currentDate.getMonth();
function changeDate(delta) {
currentDate.setDate(currentDate.getDate() + delta);
calViewYear = currentDate.getFullYear();
calViewMonth = currentDate.getMonth();
renderDate();
}
function renderDate() {
var now = new Date();
var y = currentDate.getFullYear();
var m = String(currentDate.getMonth() + 1).padStart(2, '0');
var d = String(currentDate.getDate()).padStart(2, '0');
var dateStr = y + '-' + m + '-' + d;
var isToday = currentDate.toDateString() === now.toDateString();
document.getElementById('dateText').textContent = dateStr;
}
/* ===== 日历面板 ===== */
function toggleCalPanel() {
var panel = document.getElementById('calPanel');
var isOpen = panel.classList.contains('active');
if (isOpen) {
panel.classList.remove('active');
} else {
calViewYear = currentDate.getFullYear();
calViewMonth = currentDate.getMonth();
renderCal();
panel.classList.add('active');
}
}
function calPrevMonth(e) { e.stopPropagation(); calViewMonth--; if (calViewMonth < 0) { calViewMonth = 11; calViewYear--; } renderCal(); }
function calNextMonth(e) { e.stopPropagation(); calViewMonth++; if (calViewMonth > 11) { calViewMonth = 0; calViewYear++; } renderCal(); }
function renderCal() {
document.getElementById('calMonthLabel').textContent = calViewYear + '年' + (calViewMonth + 1) + '月';
var firstDay = new Date(calViewYear, calViewMonth, 1).getDay();
var daysInMonth = new Date(calViewYear, calViewMonth + 1, 0).getDate();
var today = new Date();
var grid = document.getElementById('calGrid');
var html = '';
// 前置空白
for (var i = 0; i < firstDay; i++) { html += '<div class="cal-panel__day cal-panel__day--other"></div>'; }
for (var d = 1; d <= daysInMonth; d++) {
var cls = 'cal-panel__day';
var isToday = (calViewYear === today.getFullYear() && calViewMonth === today.getMonth() && d === today.getDate());
var isSel = (calViewYear === currentDate.getFullYear() && calViewMonth === currentDate.getMonth() && d === currentDate.getDate());
if (isToday) cls += ' cal-panel__day--today';
if (isSel) cls += ' cal-panel__day--selected';
html += '<div class="' + cls + '" onclick="selectCalDay(event,' + d + ')">' + d + '</div>';
}
grid.innerHTML = html;
}
function selectCalDay(e, day) {
e.stopPropagation();
currentDate = new Date(calViewYear, calViewMonth, day);
calViewYear = currentDate.getFullYear();
calViewMonth = currentDate.getMonth();
renderDate();
renderCal();
document.getElementById('calPanel').classList.remove('active');
}
// 点击外部关闭日历
document.addEventListener('click', function(e) {
if (!e.target.closest('.date-nav') && !e.target.closest('.cal-panel')) {
document.getElementById('calPanel').classList.remove('active');
}
});
/* ===== 排名Tab切换 ===== */
var rankHeaderLabels = { weight: '减重量', rate: '减重率', score: '综合分', action: '行动积分' };
var rankDataMap = {
weight: [
{ rank:1, name:'张**', dept:'公司机关 · 办公室', val:'15.2', unit:'kg' },
{ rank:2, name:'刘**', dept:'信息技术中心 · 技术部', val:'14.8', unit:'kg' },
{ rank:3, name:'王**', dept:'公司机关 · 人力部', val:'13.5', unit:'kg' },
{ rank:4, name:'赵**', dept:'安全环保部 · 安环部', val:'12.9', unit:'kg' },
{ rank:5, name:'陈**', dept:'公司机关 · 财务部', val:'12.1', unit:'kg' },
{ rank:6, name:'孙**', dept:'信息技术中心 · 技术部', val:'11.6', unit:'kg' },
{ rank:7, name:'周**', dept:'公司机关 · 办公室', val:'11.2', unit:'kg' },
{ rank:8, name:'李**', dept:'公司机关 · 办公室', val:'10.9', unit:'kg' },
{ rank:9, name:'吴**', dept:'信息技术中心 · 技术部', val:'10.3', unit:'kg' },
{ rank:10, name:'郑**', dept:'公司机关 · 人力部', val:'9.8', unit:'kg' }
],
rate: [
{ rank:1, name:'刘**', dept:'信息技术中心 · 技术部', val:'18.6', unit:'%' },
{ rank:2, name:'张**', dept:'公司机关 · 办公室', val:'17.9', unit:'%' },
{ rank:3, name:'赵**', dept:'安全环保部 · 安环部', val:'17.2', unit:'%' },
{ rank:4, name:'王**', dept:'公司机关 · 人力部', val:'16.5', unit:'%' },
{ rank:5, name:'陈**', dept:'公司机关 · 财务部', val:'16.0', unit:'%' },
{ rank:6, name:'孙**', dept:'信息技术中心 · 技术部', val:'15.3', unit:'%' },
{ rank:7, name:'周**', dept:'公司机关 · 办公室', val:'15.1', unit:'%' },
{ rank:8, name:'吴**', dept:'信息技术中心 · 技术部', val:'14.8', unit:'%' },
{ rank:9, name:'黄**', dept:'安全环保部 · 安环部', val:'14.2', unit:'%' },
{ rank:10, name:'郑**', dept:'公司机关 · 人力部', val:'13.6', unit:'%' }
],
score: [
{ rank:1, name:'张**', dept:'公司机关 · 办公室', val:'96.6', unit:'分' },
{ rank:2, name:'刘**', dept:'信息技术中心 · 技术部', val:'95.3', unit:'分' },
{ rank:3, name:'王**', dept:'公司机关 · 人力部', val:'92.9', unit:'分' },
{ rank:4, name:'赵**', dept:'安全环保部 · 安环部', val:'90.2', unit:'分' },
{ rank:5, name:'陈**', dept:'公司机关 · 财务部', val:'88.5', unit:'分' },
{ rank:6, name:'孙**', dept:'信息技术中心 · 技术部', val:'87.3', unit:'分' },
{ rank:7, name:'周**', dept:'公司机关 · 办公室', val:'87.0', unit:'分' },
{ rank:8, name:'李**', dept:'公司机关 · 办公室', val:'86.6', unit:'分' },
{ rank:9, name:'吴**', dept:'信息技术中心 · 技术部', val:'84.1', unit:'分' },
{ rank:10, name:'郑**', dept:'公司机关 · 人力部', val:'82.8', unit:'分' }
],
action: [
{ rank:1, name:'陈**', dept:'公司机关 · 财务部', val:'1580', unit:'分' },
{ rank:2, name:'周**', dept:'公司机关 · 办公室', val:'1520', unit:'分' },
{ rank:3, name:'吴**', dept:'信息技术中心 · 技术部', val:'1460', unit:'分' },
{ rank:4, name:'孙**', dept:'信息技术中心 · 技术部', val:'1380', unit:'分' },
{ rank:5, name:'李**', dept:'公司机关 · 办公室', val:'1250', unit:'分' },
{ rank:6, name:'张**', dept:'公司机关 · 办公室', val:'1180', unit:'分' },
{ rank:7, name:'黄**', dept:'安全环保部 · 安环部', val:'1100', unit:'分' },
{ rank:8, name:'刘**', dept:'信息技术中心 · 技术部', val:'1060', unit:'分' },
{ rank:9, name:'杨**', dept:'公司机关 · 办公室', val:'1020', unit:'分' },
{ rank:10, name:'王**', dept:'公司机关 · 人力部', val:'980', unit:'分' }
]
};
function switchRankTab(tab) {
document.querySelectorAll('#rankTabs .rank-tab').forEach(function(t) { t.classList.toggle('active', t.dataset.tab === tab); });
document.getElementById('rankListHeader').textContent = rankHeaderLabels[tab];
renderRankList(rankDataMap[tab]);
}
function renderRankList(data) {
var html = '';
data.forEach(function(item) {
var numHtml = '';
if (item.rank === 1) {
numHtml = '<div class="rank-item__num rank-item__num--gold"></div>';
} else if (item.rank === 2) {
numHtml = '<div class="rank-item__num rank-item__num--silver"></div>';
} else if (item.rank === 3) {
numHtml = '<div class="rank-item__num rank-item__num--bronze"></div>';
} else {
numHtml = '<span class="rank-item__num-text">' + item.rank + '</span>';
}
html += '<div class="rank-item">';
html += ' <div class="rank-item__num">' + numHtml + '</div>';
html += ' <div class="rank-item__user"><div class="rank-item__name">' + item.name + '</div><div class="rank-item__dept">' + item.dept + '</div></div>';
html += ' <div class="rank-item__score"><div class="rank-item__score-val">' + item.val + '<span class="rank-item__score-unit">' + item.unit + '</span></div></div>';
html += '</div>';
});
document.getElementById('rankList').innerHTML = html;
}
/* ===== 审核Tab切换 ===== */
function switchReviewTab(el, panelId) {
el.closest('.sub-tabs').querySelectorAll('.sub-tab').forEach(function(t) { t.classList.remove('active'); });
el.classList.add('active');
['rv-pending','rv-approved','rv-signed','rv-rejected'].forEach(function(id) {
document.getElementById(id).style.display = id === panelId ? 'block' : 'none';
});
}
/* 初始化 */
switchRankTab('weight');
</script>
</body>
</html>
@@ -0,0 +1,207 @@
<!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>
* { margin: 0; padding: 0; box-sizing: border-box; }
body { background: #f0f2f5; display: flex; justify-content: center; align-items: flex-start; min-height: 100vh; padding: 20px; font-family: -apple-system, BlinkMacSystemFont, 'PingFang SC', 'Helvetica Neue', sans-serif; }
.phone-shell { width: 390px; height: 844px; background: #f7f8fa; border-radius: 44px; box-shadow: 0 20px 60px rgba(0,0,0,0.25), inset 0 0 0 2px #e0e0e0; overflow: hidden; position: relative; display: flex; flex-direction: column; flex-shrink: 0; }
.status-bar { height: 44px; background: #fff; display: flex; align-items: center; justify-content: space-between; padding: 0 24px; flex-shrink: 0; z-index: 10; }
.status-bar .time { font-size: 15px; font-weight: 700; color: #1a1a1a; }
.status-bar .icons { display: flex; gap: 6px; align-items: center; font-size: 12px; color: #1a1a1a; }
.nav-bar { height: 44px; background: #fff; display: flex; align-items: center; padding: 0 16px; flex-shrink: 0; border-bottom: 1px solid #f0f0f0; position: relative; }
.nav-back { display: flex; align-items: center; gap: 4px; color: #1677ff; font-size: 15px; cursor: pointer; background: none; border: none; padding: 4px 0; }
.nav-title { position: absolute; left: 50%; transform: translateX(-50%); font-size: 17px; font-weight: 600; color: #1a1a1a; white-space: nowrap; }
.scroll-content { flex: 1; overflow-y: auto; background: #f7f8fa; }
.scroll-content::-webkit-scrollbar { display: none; }
.emp-info { background: #fff; padding: 14px 16px; margin: 0; border-bottom: 1px solid #f0f0f0; }
.emp-info__name { font-size: 17px; font-weight: 700; color: #1a1a1a; }
.emp-info__meta { font-size: 12px; color: #999; margin-top: 4px; display: flex; gap: 8px; }
.data-compare { background: #fff; border-radius: 12px; margin: 10px 12px 0; padding: 14px; box-shadow: 0 1px 4px rgba(0,0,0,0.06); }
.data-compare__title { font-size: 14px; font-weight: 700; color: #1a1a1a; margin-bottom: 10px; }
.data-compare__table { display: flex; gap: 0; }
.data-compare__col { flex: 1; text-align: center; }
.data-compare__col-label { font-size: 11px; color: #999; margin-bottom: 6px; font-weight: 600; }
.data-compare__row { font-size: 12px; color: #666; padding: 4px 0; border-bottom: 1px solid #f8f8f8; }
.data-compare__row:last-child { border-bottom: none; }
.data-compare__row .val { font-weight: 600; }
.data-compare__col--initial .val { color: #666; }
.data-compare__col--target .val { color: #52c41a; }
.data-compare__col--current .val { color: #1677ff; }
.change-row { display: flex; gap: 0; background: #fff; border-radius: 12px; margin: 10px 12px 0; padding: 10px 0; box-shadow: 0 1px 4px rgba(0,0,0,0.06); }
.change-item { flex: 1; text-align: center; }
.change-item + .change-item { border-left: 1px solid #f0f0f0; }
.change-item__val { font-size: 16px; font-weight: 700; }
.change-item__val--down { color: #52c41a; }
.change-item__val--up { color: #ff4d4f; }
.change-item__label { font-size: 10px; color: #999; margin-top: 2px; }
.section-title { font-size: 14px; font-weight: 700; color: #1a1a1a; margin: 14px 12px 6px; }
/* 记录列表 */
.record-list { padding: 8px 12px 16px; display: flex; flex-direction: column; gap: 8px; }
.record-item { background: #fff; border-radius: 14px; padding: 14px; box-shadow: 0 2px 8px rgba(0,0,0,0.03); }
.record-item__header { display: flex; align-items: center; justify-content: space-between; margin-bottom: 10px; }
.record-item__time { font-size: 11px; color: #bbb; }
.record-item__body { display: flex; align-items: center; gap: 16px; }
.record-item__metric { text-align: center; min-width: 48px; }
.record-item__metric-label { font-size: 10px; color: #999; margin-bottom: 2px; }
.record-item__metric-val { font-size: 16px; font-weight: 700; color: #1a1a1a; }
.record-item__metric-unit { font-size: 10px; color: #999; font-weight: 400; margin-left: 1px; }
.record-item__source { margin-left: auto; }
.source-badge { display: inline-block; padding: 4px 10px; border-radius: 12px; font-size: 11px; font-weight: 600; }
.source-badge--scale { background: #e8effa; color: #5470c6; }
.source-badge--bt { background: #f3efff; color: #8b5cf6; }
.source-badge--self { background: #f5f0ff; color: #a78bfa; }
.source-badge--fat { background: #e6edf5; color: #1e3a5f; }
.source-badge--wear { background: #e6fffb; color: #13c2c2; }
</style>
</head>
<body>
<div class="phone-shell">
<div class="status-bar">
<span class="time">9:41</span>
<div class="icons"><span>●●●</span><span>WiFi</span><span>🔋</span></div>
</div>
<!-- [交互] 点击返回体重记录列表 -->
<div class="nav-bar">
<button class="nav-back" onclick="location.href='./weight-record.html'">
<svg width="10" height="16" viewBox="0 0 10 16" fill="none" stroke="currentColor" stroke-width="2"><path d="M8 1L2 8l6 7"/></svg>返回
</button>
<span class="nav-title">体重明细</span>
</div>
<div class="scroll-content">
<div style="padding:10px 16px;background:#fff;border-bottom:1px solid #f0f0f0;font-size:14px;color:#333;font-weight:600;">2026-06-22</div>
<div class="emp-info">
<div class="emp-info__name">张小红</div>
<div class="emp-info__meta">
<span></span><span>32岁</span><span>公司机关 · 办公室</span><span>身高 162cm</span>
</div>
</div>
<div class="data-compare">
<div class="data-compare__title">数据对比</div>
<div class="data-compare__table">
<div class="data-compare__col data-compare__col--initial">
<div class="data-compare__col-label">初始</div>
<div class="data-compare__row">体重 <span class="val">72.5kg</span></div>
<div class="data-compare__row">BMI <span class="val">27.6</span></div>
<div class="data-compare__row">体脂 <span class="val">32.1%</span></div>
<div class="data-compare__row">腰围 <span class="val">86cm</span></div>
</div>
<div class="data-compare__col data-compare__col--target">
<div class="data-compare__col-label">目标</div>
<div class="data-compare__row">体重 <span class="val">62kg</span></div>
<div class="data-compare__row">BMI <span class="val">23.6</span></div>
<div class="data-compare__row">体脂 <span class="val">26%</span></div>
<div class="data-compare__row">腰围 <span class="val">76cm</span></div>
</div>
<div class="data-compare__col data-compare__col--current">
<div class="data-compare__col-label">当前</div>
<div class="data-compare__row">体重 <span class="val">67.2kg</span></div>
<div class="data-compare__row">BMI <span class="val">25.6</span></div>
<div class="data-compare__row">体脂 <span class="val">29.5%</span></div>
<div class="data-compare__row">腰围 <span class="val">81cm</span></div>
</div>
</div>
</div>
<div class="change-row">
<div class="change-item">
<div class="change-item__val change-item__val--down">-5.3kg</div>
<div class="change-item__label">体重变化</div>
</div>
<div class="change-item">
<div class="change-item__val change-item__val--down">-2.0</div>
<div class="change-item__label">BMI变化</div>
</div>
<div class="change-item">
<div class="change-item__val change-item__val--down">-2.6%</div>
<div class="change-item__label">体脂变化</div>
</div>
<div class="change-item">
<div class="change-item__val change-item__val--down">-5cm</div>
<div class="change-item__label">腰围变化</div>
</div>
</div>
<div class="section-title">体重记录列表</div>
<div class="record-list">
<div class="record-item">
<div class="record-item__header">
<span class="record-item__time">2026-06-22 07:30</span>
</div>
<div class="record-item__body">
<div class="record-item__metric"><div class="record-item__metric-label">体重</div><div class="record-item__metric-val">67.2<span class="record-item__metric-unit">kg</span></div></div>
<div class="record-item__metric"><div class="record-item__metric-label">体脂率</div><div class="record-item__metric-val">29.5<span class="record-item__metric-unit">%</span></div></div>
<div class="record-item__metric"><div class="record-item__metric-label">腰围</div><div class="record-item__metric-val">81.0<span class="record-item__metric-unit">cm</span></div></div>
<div class="record-item__source"><span class="source-badge source-badge--bt">蓝牙秤</span></div>
</div>
</div>
<div class="record-item">
<div class="record-item__header">
<span class="record-item__time">2026-06-21 18:30</span>
</div>
<div class="record-item__body">
<div class="record-item__metric"><div class="record-item__metric-label">体重</div><div class="record-item__metric-val">66.8<span class="record-item__metric-unit">kg</span></div></div>
<div class="record-item__metric"><div class="record-item__metric-label">体脂率</div><div class="record-item__metric-val">29.1<span class="record-item__metric-unit">%</span></div></div>
<div class="record-item__metric"><div class="record-item__metric-label">腰围</div><div class="record-item__metric-val">80.5<span class="record-item__metric-unit">cm</span></div></div>
<div class="record-item__source"><span class="source-badge source-badge--scale">身高秤</span></div>
</div>
</div>
<div class="record-item">
<div class="record-item__header">
<span class="record-item__time">2026-06-20 07:15</span>
</div>
<div class="record-item__body">
<div class="record-item__metric"><div class="record-item__metric-label">体重</div><div class="record-item__metric-val">67.0<span class="record-item__metric-unit">kg</span></div></div>
<div class="record-item__metric"><div class="record-item__metric-label">体脂率</div><div class="record-item__metric-val">29.3<span class="record-item__metric-unit">%</span></div></div>
<div class="record-item__metric"><div class="record-item__metric-label">腰围</div><div class="record-item__metric-val">81.0<span class="record-item__metric-unit">cm</span></div></div>
<div class="record-item__source"><span class="source-badge source-badge--fat">体脂仪</span></div>
</div>
</div>
<div class="record-item">
<div class="record-item__header">
<span class="record-item__time">2026-06-18 09:00</span>
</div>
<div class="record-item__body">
<div class="record-item__metric"><div class="record-item__metric-label">体重</div><div class="record-item__metric-val">67.5<span class="record-item__metric-unit">kg</span></div></div>
<div class="record-item__metric"><div class="record-item__metric-label">体脂率</div><div class="record-item__metric-val">--</div></div>
<div class="record-item__metric"><div class="record-item__metric-label">腰围</div><div class="record-item__metric-val">--</div></div>
<div class="record-item__source"><span class="source-badge source-badge--self">自记</span></div>
</div>
</div>
<div class="record-item">
<div class="record-item__header">
<span class="record-item__time">2026-06-15 07:20</span>
</div>
<div class="record-item__body">
<div class="record-item__metric"><div class="record-item__metric-label">体重</div><div class="record-item__metric-val">68.2<span class="record-item__metric-unit">kg</span></div></div>
<div class="record-item__metric"><div class="record-item__metric-label">体脂率</div><div class="record-item__metric-val">29.8<span class="record-item__metric-unit">%</span></div></div>
<div class="record-item__metric"><div class="record-item__metric-label">腰围</div><div class="record-item__metric-val">81.5<span class="record-item__metric-unit">cm</span></div></div>
<div class="record-item__source"><span class="source-badge source-badge--wear">穿戴</span></div>
</div>
</div>
</div>
<div style="height:20px;"></div>
</div>
</div>
</body>
</html>
@@ -0,0 +1,216 @@
<!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>
* { margin: 0; padding: 0; box-sizing: border-box; }
body { background: #f0f2f5; display: flex; justify-content: center; align-items: flex-start; min-height: 100vh; padding: 20px; font-family: -apple-system, BlinkMacSystemFont, 'PingFang SC', 'Helvetica Neue', sans-serif; }
.phone-shell { width: 390px; height: 844px; background: #fff; border-radius: 44px; box-shadow: 0 20px 60px rgba(0,0,0,0.25), inset 0 0 0 2px #e0e0e0; overflow: hidden; position: relative; display: flex; flex-direction: column; flex-shrink: 0; }
.status-bar { height: 44px; background: #fff; display: flex; align-items: center; justify-content: space-between; padding: 0 24px; flex-shrink: 0; z-index: 10; }
.status-bar .time { font-size: 15px; font-weight: 700; color: #1a1a1a; }
.status-bar .icons { display: flex; gap: 6px; align-items: center; font-size: 12px; color: #1a1a1a; }
.nav-bar { height: 44px; background: #fff; display: flex; align-items: center; padding: 0 16px; flex-shrink: 0; border-bottom: 1px solid #f0f0f0; position: relative; }
.nav-back { display: flex; align-items: center; gap: 4px; color: #1677ff; font-size: 15px; cursor: pointer; background: none; border: none; padding: 4px 0; }
.nav-title { position: absolute; left: 50%; transform: translateX(-50%); font-size: 17px; font-weight: 600; color: #1a1a1a; white-space: nowrap; }
.scroll-content { flex: 1; overflow-y: auto; background: #f7f8fa; }
.scroll-content::-webkit-scrollbar { display: none; }
.date-nav { display: flex; align-items: center; justify-content: center; gap: 8px; padding: 10px 16px; background: #fff; border-bottom: 1px solid #f0f0f0; position: relative; }
.date-nav__arrow { width: 32px; height: 32px; border-radius: 50%; background: #f5f5f5; display: flex; align-items: center; justify-content: center; cursor: pointer; border: none; color: #666; font-size: 16px; flex-shrink: 0; }
.date-nav__arrow:active { background: #e6f4ff; }
.date-nav__text { font-size: 15px; font-weight: 600; color: #1a1a1a; min-width: 110px; text-align: center; }
.date-nav__cal { width: 28px; height: 28px; border-radius: 6px; background: none; display: flex; align-items: center; justify-content: center; cursor: pointer; border: none; font-size: 16px; flex-shrink: 0; color: #1677ff; }
.date-nav__cal:active { background: #e6f4ff; }
.cal-panel { display: none; position: absolute; top: 42px; left: 16px; right: 16px; background: #fff; border-radius: 14px; box-shadow: 0 8px 30px rgba(0,0,0,0.15); z-index: 100; padding: 16px; }
.cal-panel.active { display: block; }
.cal-panel__head { display: flex; align-items: center; justify-content: space-between; margin-bottom: 12px; }
.cal-panel__month { font-size: 15px; font-weight: 700; color: #1a1a1a; }
.cal-panel__nav { width: 28px; height: 28px; border-radius: 50%; border: none; background: #f5f5f5; cursor: pointer; font-size: 14px; color: #666; display: flex; align-items: center; justify-content: center; }
.cal-panel__nav:active { background: #e6f4ff; }
.cal-panel__weekdays { display: flex; margin-bottom: 6px; }
.cal-panel__weekday { flex: 1; text-align: center; font-size: 11px; color: #999; padding: 4px 0; }
.cal-panel__grid { display: flex; flex-wrap: wrap; }
.cal-panel__day { width: calc(100% / 7); text-align: center; padding: 8px 0; font-size: 13px; color: #333; cursor: pointer; border-radius: 8px; }
.cal-panel__day--other { color: #ddd; }
.cal-panel__day:hover { background: #f5f5f5; }
.cal-panel__day--today { font-weight: 700; color: #1677ff; }
.cal-panel__day--selected { background: #1677ff; color: #fff; font-weight: 700; }
.cal-panel__day--selected:hover { background: #1677ff; }
.seg-tabs { display: flex; background: #fff; border-bottom: 1px solid #f0f0f0; flex-shrink: 0; }
.seg-tab { flex: 1; text-align: center; padding: 12px 0; font-size: 14px; color: #666; cursor: pointer; border-bottom: 2px solid transparent; transition: all 0.2s; }
.seg-tab.active { color: #1677ff; border-bottom-color: #1677ff; font-weight: 600; }
.seg-tab .badge { display: inline-block; background: #e8e8e8; color: #666; font-size: 10px; font-weight: 700; min-width: 16px; height: 16px; border-radius: 8px; padding: 0 4px; margin-left: 4px; vertical-align: middle; line-height: 16px; }
.seg-tab.active .badge { background: #e6f4ff; color: #1677ff; }
.employee-card { background: #fff; border-radius: 12px; margin: 10px 12px 0; padding: 14px; box-shadow: 0 1px 4px rgba(0,0,0,0.06); display: flex; align-items: center; gap: 10px; cursor: pointer; }
.employee-card:active { transform: scale(0.98); }
.employee-card__info { flex: 1; min-width: 0; }
.employee-card__name { font-size: 15px; font-weight: 600; color: #1a1a1a; }
.employee-card__meta { font-size: 12px; color: #999; margin-top: 3px; display: flex; gap: 8px; flex-wrap: wrap; }
.employee-card__arrow { font-size: 12px; color: #1677ff; flex-shrink: 0; white-space: nowrap; }
</style>
</head>
<body>
<div class="phone-shell">
<div class="status-bar">
<span class="time">9:41</span>
<div class="icons"><span>●●●</span><span>WiFi</span><span>🔋</span></div>
</div>
<!-- [交互] 点击返回体重管理详情 -->
<div class="nav-bar">
<button class="nav-back" onclick="location.href='./weight-detail.html'">
<svg width="10" height="16" viewBox="0 0 10 16" fill="none" stroke="currentColor" stroke-width="2"><path d="M8 1L2 8l6 7"/></svg>返回
</button>
<span class="nav-title">体重记录</span>
</div>
<div class="date-nav">
<button class="date-nav__arrow" onclick="changeDate(-1)"></button>
<button class="date-nav__cal" onclick="toggleCalPanel()">📅</button>
<span class="date-nav__text" id="dateText">2026-06-22</span>
<button class="date-nav__arrow" onclick="changeDate(1)"></button>
<div class="cal-panel" id="calPanel">
<div class="cal-panel__head">
<button class="cal-panel__nav" onclick="calPrevMonth(event)"></button>
<span class="cal-panel__month" id="calMonthLabel">2026年6月</span>
<button class="cal-panel__nav" onclick="calNextMonth(event)"></button>
</div>
<div class="cal-panel__weekdays">
<div class="cal-panel__weekday"></div><div class="cal-panel__weekday"></div><div class="cal-panel__weekday"></div><div class="cal-panel__weekday"></div><div class="cal-panel__weekday"></div><div class="cal-panel__weekday"></div><div class="cal-panel__weekday"></div>
</div>
<div class="cal-panel__grid" id="calGrid"></div>
</div>
</div>
<div class="seg-tabs">
<div class="seg-tab active" onclick="switchTab(this,'panel-recorded')">已记录<span class="badge" id="badgeRecorded">72</span></div>
<div class="seg-tab" onclick="switchTab(this,'panel-unrecorded')">未记录<span class="badge" id="badgeUnrecorded">14</span></div>
</div>
<div class="scroll-content">
<div id="panel-recorded"><!-- JS动态渲染 --></div>
<div id="panel-unrecorded" style="display:none;"><!-- JS动态渲染 --></div>
<div style="height:16px;"></div>
</div>
</div>
<script>
var recordedList = [
{ name:'张小红', gender:'女', age:32, dept:'公司机关 · 办公室', height:162 },
{ name:'李建国', gender:'男', age:45, dept:'采油一厂 · 技术部', height:175 },
{ name:'陈伟', gender:'男', age:36, dept:'安全环保部 · 安环部', height:178 },
{ name:'周明', gender:'男', age:33, dept:'信息技术中心 · 技术部', height:182 },
{ name:'王芳', gender:'女', age:28, dept:'信息技术中心 · 数据部', height:160 },
{ name:'赵志强', gender:'男', age:61, dept:'公司机关 · 后勤部', height:170 },
{ name:'孙丽', gender:'女', age:41, dept:'采油一厂 · 作业区', height:158 },
{ name:'刘海波', gender:'男', age:55, dept:'公司机关 · 行政部', height:168 }
];
var unrecordedList = [
{ name:'吴静', gender:'女', age:26, dept:'公司机关 · 人力部', height:165 },
{ name:'黄晓明', gender:'男', age:42, dept:'采油一厂 · 工程部', height:176 },
{ name:'马燕', gender:'女', age:35, dept:'信息技术中心 · 运维部', height:159 },
{ name:'林伟东', gender:'男', age:44, dept:'采油一厂 · 设备部', height:180 },
{ name:'郑国强', gender:'男', age:50, dept:'公司机关 · 财务部', height:172 },
{ name:'杨丽华', gender:'女', age:39, dept:'安全环保部 · 安环部', height:163 }
];
function switchTab(el, panelId) {
el.closest('.seg-tabs').querySelectorAll('.seg-tab').forEach(function(t) { t.classList.remove('active'); });
el.classList.add('active');
['panel-recorded','panel-unrecorded'].forEach(function(id) {
document.getElementById(id).style.display = id === panelId ? 'block' : 'none';
});
}
function renderRecordedList() {
var html = '';
recordedList.forEach(function(item) {
html += '<div class="employee-card" onclick="location.href=\'./weight-employee-detail.html\'">';
html += ' <div class="employee-card__info">';
html += ' <div class="employee-card__name">' + item.name + '</div>';
html += ' <div class="employee-card__meta"><span>' + item.gender + '</span><span>' + item.age + '岁</span><span>' + item.dept + '</span><span>身高 ' + item.height + 'cm</span></div>';
html += ' </div>';
html += ' <span class="employee-card__arrow">记录明细 </span>';
html += '</div>';
});
document.getElementById('panel-recorded').innerHTML = html;
}
function renderUnrecordedList() {
var html = '';
unrecordedList.forEach(function(item) {
html += '<div class="employee-card">';
html += ' <div class="employee-card__info">';
html += ' <div class="employee-card__name">' + item.name + '</div>';
html += ' <div class="employee-card__meta"><span>' + item.gender + '</span><span>' + item.age + '岁</span><span>' + item.dept + '</span><span>身高 ' + item.height + 'cm</span></div>';
html += ' </div>';
html += '</div>';
});
document.getElementById('panel-unrecorded').innerHTML = html;
}
var currentDate = new Date(2026, 5, 22);
var calViewYear = currentDate.getFullYear();
var calViewMonth = currentDate.getMonth();
function changeDate(delta) {
currentDate.setDate(currentDate.getDate() + delta);
calViewYear = currentDate.getFullYear(); calViewMonth = currentDate.getMonth();
renderDate();
}
function renderDate() {
var y = currentDate.getFullYear();
var m = String(currentDate.getMonth() + 1).padStart(2, '0');
var d = String(currentDate.getDate()).padStart(2, '0');
document.getElementById('dateText').textContent = y + '-' + m + '-' + d;
}
function toggleCalPanel() {
var panel = document.getElementById('calPanel');
if (panel.classList.contains('active')) { panel.classList.remove('active'); return; }
calViewYear = currentDate.getFullYear(); calViewMonth = currentDate.getMonth();
renderCal(); panel.classList.add('active');
}
function calPrevMonth(e) { e.stopPropagation(); calViewMonth--; if (calViewMonth < 0) { calViewMonth = 11; calViewYear--; } renderCal(); }
function calNextMonth(e) { e.stopPropagation(); calViewMonth++; if (calViewMonth > 11) { calViewMonth = 0; calViewYear++; } renderCal(); }
function renderCal() {
document.getElementById('calMonthLabel').textContent = calViewYear + '年' + (calViewMonth + 1) + '月';
var firstDay = new Date(calViewYear, calViewMonth, 1).getDay();
var daysInMonth = new Date(calViewYear, calViewMonth + 1, 0).getDate();
var today = new Date();
var html = '';
for (var i = 0; i < firstDay; i++) { html += '<div class="cal-panel__day cal-panel__day--other"></div>'; }
for (var d = 1; d <= daysInMonth; d++) {
var cls = 'cal-panel__day';
if (calViewYear === today.getFullYear() && calViewMonth === today.getMonth() && d === today.getDate()) cls += ' cal-panel__day--today';
if (calViewYear === currentDate.getFullYear() && calViewMonth === currentDate.getMonth() && d === currentDate.getDate()) cls += ' cal-panel__day--selected';
html += '<div class="' + cls + '" onclick="selectCalDay(event,' + d + ')">' + d + '</div>';
}
document.getElementById('calGrid').innerHTML = html;
}
function selectCalDay(e, day) {
e.stopPropagation();
currentDate = new Date(calViewYear, calViewMonth, day);
calViewYear = currentDate.getFullYear(); calViewMonth = currentDate.getMonth();
renderDate(); renderCal();
document.getElementById('calPanel').classList.remove('active');
}
document.addEventListener('click', function(e) {
if (!e.target.closest('.date-nav') && !e.target.closest('.cal-panel')) {
document.getElementById('calPanel').classList.remove('active');
}
});
renderRecordedList();
renderUnrecordedList();
</script>
</body>
</html>
+2 -1
View File
@@ -128,7 +128,8 @@ function initTabLinks() {
assistant: '../assistant',
professional: '../professional',
operator: '../operator',
onsite: '../onsite'
onsite: '../onsite',
admin: '../admin'
};
var base = roleBaseMap[role] || '../expert';
document.getElementById('link-workbench').href = base + '/workbench/index.html';
+2 -1
View File
@@ -264,7 +264,8 @@ function initTabLinks() {
assistant: '../assistant',
professional: '../professional',
operator: '../operator',
onsite: '../onsite'
onsite: '../onsite',
admin: '../admin'
};
var base = roleBaseMap[role] || '../expert';
document.getElementById('link-workbench').href = base + '/workbench/index.html';
+10 -3
View File
@@ -800,9 +800,16 @@ const SITE_MAP = [
]}
]},
{ role:'管理员', id:'admin', modules:[
{name:'工作台',dir:'emergency-app/admin/workbench',pages:[]},
{name:'知识库',dir:'emergency-app/admin/knowledge',pages:[]},
{name:'我的',dir:'emergency-app/admin/profile',pages:[]}
{name:'工作台',dir:'emergency-app/admin/workbench',pages:[
{file:'index.html',label:'工作台首页'},{file:'checkup-progress.html',label:'体检进度跟踪'},{file:'emergency-orders.html',label:'应急求助工单'},{file:'emergency-order-detail.html',label:'应急工单详情'},{file:'wearable-alerts.html',label:'穿戴预警记录'},{file:'weight-detail.html',label:'体重管理详情'},{file:'goal-review.html',label:'目标审核'},{file:'eat-detail.html',label:'饮食记录详情'},{file:'diet-employee-detail.html',label:'饮食明细'},{file:'exercise-detail.html',label:'运动记录详情'},{file:'exercise-employee-detail.html',label:'运动明细'},{file:'weight-record.html',label:'体重记录详情'},{file:'weight-employee-detail.html',label:'体重明细'}
]},
{name:'知识库',dir:'emergency-app/admin/knowledge',pages:[
{file:'index.html',label:'知识库首页'},{file:'detail.html',label:'知识详情'}
]},
{name:'我的',dir:'emergency-app/admin/profile',pages:[
{file:'index.html',label:'个人中心'},
{file:'edit-profile.html',label:'修改个人信息'},{file:'change-pwd.html',label:'修改密码'}
]}
]}
],
shared:[