feat:西安应急大屏 v3 重构 + 膳食建议页 AI 升级

- 西安应急大屏:index.html 归档为 index-v2.html,新增 index-v3.html(重排布局、统计卡片/告警柱状/心脑血管预警/体检雷达图)
- 同步更新 server.js 默认入口及 emergency-app、employee-app 各页面返回/跳转引用至 index-v2.html
- 体重管理:diet-advice.html 大幅升级(偏好标签条、慢病提醒、热量/营养/钠嘌呤指标、三餐推荐),新增膳食推荐 AI 算法需求文档
This commit is contained in:
liuyunqin
2026-06-29 18:00:04 +08:00
parent 29eebdf40a
commit d525cf0eb3
37 changed files with 5636 additions and 306 deletions
@@ -268,7 +268,7 @@
</div>
<div class="nav-bar">
<!-- [交互] 点击返回至: index.html -->
<!-- [交互] 点击返回至: index-v2.html -->
<a class="nav-back" href="index.html"></a>
<span class="nav-title">我的预约</span>
</div>
@@ -571,7 +571,7 @@
});
/**
* 返回上一页:优先读取 ?from 参数,否则 history.back(),最终 fallback 到 index.html
* 返回上一页:优先读取 ?from 参数,否则 history.back(),最终 fallback 到 index-v2.html
*/
function goBack() {
var params = new URLSearchParams(window.location.search);
@@ -19,11 +19,11 @@ const root = path.resolve(__dirname, '..');
// - 'auto' : 短页面 → 最低 844;长页面 → 真实 scroll 高度
const tasks = [
// ========== 主页 / 健康现状 ==========
{ html: 'index.html', out: 'index', mode: 'auto' },
{ html: 'index-v2.html', out: 'index', mode: 'auto' },
{ html: 'health-status.html', out: 'health-status', mode: 'auto' },
// ========== 健康排查 ==========
{ html: 'health-checkup/index.html', out: 'health-checkup/index', mode: 'auto' },
{ html: 'health-checkup/index-v2.html', out: 'health-checkup/index', mode: 'auto' },
{ html: 'health-checkup/activity-detail.html', out: 'health-checkup/activity-detail', mode: 'auto', query: '?activityStatus=ongoing' },
{ html: 'health-checkup/activity-detail.html', out: 'health-checkup/activity-detail-participated', mode: 'auto', query: '?activityStatus=ongoing&participated=1&submitTime=2026-05-20%2014:32' },
{ html: 'health-checkup/activity-detail.html', out: 'health-checkup/activity-detail-ended', mode: 'auto', query: '?activityStatus=ended' },
@@ -32,7 +32,7 @@ const tasks = [
{ html: 'health-checkup/questionnaire-fill.html', out: 'health-checkup/questionnaire-fill', mode: 'auto' },
// ========== 穿戴监测 ==========
{ html: 'wearable/index.html', out: 'wearable/index', mode: 'auto' },
{ html: 'wearable/index-v2.html', out: 'wearable/index', mode: 'auto' },
{ html: 'wearable/heart-rate.html', out: 'wearable/heart-rate', mode: 'auto' },
{ html: 'wearable/heart-rate-alerts.html', out: 'wearable/heart-rate-alerts', mode: 'auto' },
{ html: 'wearable/blood-oxygen.html', out: 'wearable/blood-oxygen', mode: 'auto' },
@@ -51,17 +51,17 @@ const tasks = [
{ html: 'wearable/exercise.html', out: 'wearable/exercise-month', mode: 'auto', click: { sel: '.tab-item', text: '月' } },
// ========== 环境监测首页(4 Tab - 严格 390×844 ==========
{ html: 'environment/index.html', out: 'environment/index', mode: 'fixed', envTab: 'outdoor' },
{ html: 'environment/index.html', out: 'environment/index-outdoor', mode: 'fixed', envTab: 'outdoor' },
{ html: 'environment/index.html', out: 'environment/index-indoor', mode: 'fixed', envTab: 'indoor' },
{ html: 'environment/index.html', out: 'environment/index-water', mode: 'fixed', envTab: 'water' },
{ html: 'environment/index.html', out: 'environment/index-pollen', mode: 'fixed', envTab: 'pollen' },
{ html: 'environment/index-v2.html', out: 'environment/index', mode: 'fixed', envTab: 'outdoor' },
{ html: 'environment/index-v2.html', out: 'environment/index-outdoor', mode: 'fixed', envTab: 'outdoor' },
{ html: 'environment/index-v2.html', out: 'environment/index-indoor', mode: 'fixed', envTab: 'indoor' },
{ html: 'environment/index-v2.html', out: 'environment/index-water', mode: 'fixed', envTab: 'water' },
{ html: 'environment/index-v2.html', out: 'environment/index-pollen', mode: 'fixed', envTab: 'pollen' },
// ========== 环境监测首页 - 底部弹窗 - 严格 390×844 ==========
{ html: 'environment/index.html', out: 'environment/index-outdoor-sheet', mode: 'fixed', envTab: 'outdoor', clickMarker: true },
{ html: 'environment/index.html', out: 'environment/index-indoor-sheet', mode: 'fixed', envTab: 'indoor', clickMarker: true },
{ html: 'environment/index.html', out: 'environment/index-water-sheet', mode: 'fixed', envTab: 'water', clickMarker: true },
{ html: 'environment/index.html', out: 'environment/index-pollen-sheet', mode: 'fixed', envTab: 'pollen', clickMarker: true },
{ html: 'environment/index-v2.html', out: 'environment/index-outdoor-sheet', mode: 'fixed', envTab: 'outdoor', clickMarker: true },
{ html: 'environment/index-v2.html', out: 'environment/index-indoor-sheet', mode: 'fixed', envTab: 'indoor', clickMarker: true },
{ html: 'environment/index-v2.html', out: 'environment/index-water-sheet', mode: 'fixed', envTab: 'water', clickMarker: true },
{ html: 'environment/index-v2.html', out: 'environment/index-pollen-sheet', mode: 'fixed', envTab: 'pollen', clickMarker: true },
// ========== 环境监测设备详情 / 报警数据 ==========
{ html: 'environment/device-detail.html', out: 'environment/device-detail', mode: 'auto', query: '?tab=outdoor&id=OA001' },
+1 -1
View File
@@ -120,7 +120,7 @@ body { background: #f0f2f5; display: flex; justify-content: center; align-items:
<!-- 底部 Tab 栏 -->
<div class="tab-bar">
<!-- [交互] 点击跳转至: ../home/index.html -->
<!-- [交互] 点击跳转至: ../home/index-v2.html -->
<div class="tab-item" onclick="location.href='../home/index.html'"><span class="tab-icon">🏠</span><span class="tab-label">应用</span></div>
<div class="tab-item"><span class="tab-icon">📁</span><span class="tab-label">档案</span></div>
<div class="tab-item"><span class="tab-icon">🤖</span><span class="tab-label">AI助手</span></div>
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,307 @@
# 膳食推荐AI算法 — 需求说明
> 面向AI工程师 | 基于《高血压、高尿酸干预行动项目方案(修订版)》| 2026-06-29
---
## 一、算法架构概述
采用 **"三层规则 + AI推理"混合架构**
```
用户输入 → 第一层:基础营养层(固定公式)→ 第二层:慢病管控层(AI动态调整)→ 第三层:个性化适配层(AI推理)→ 输出食谱
```
- **第一层**:基于权威指南的固定公式(BMR、供能比),无需模型参与,确定性计算
- **第二层**:AI根据慢病组合类型动态调整营养阈值优先级,需要模型推理
- **第三层**:AI根据口味/地区/场景生成个性化食谱,需要模型推理 + 规则库
---
## 二、数据需求清单
### 2.1 系统自动获取(无需员工手动输入)
| 序号 | 数据字段 | 类型 | 数据来源 | 获取方式 | 用途(哪一层) |
|------|----------|------|----------|----------|-------------|
| 1 | 员工ID(哈希化) | string | 健康CQ平台 | 登录态自动获取,脱敏后传入 | 全链路标识 |
| 2 | 身高 | number(cm) | 员工档案 | 从 `basic-info.html` 录入的档案读取 | 第一层:计算BMR |
| 3 | 体重 | number(kg) | 体重打卡记录 | 取最近一次 `weight-checkin.html` 的测量值 | 第一层:计算BMR |
| 4 | 年龄 | number | 员工档案 | 从身份证号/档案计算 | 第一层:BMR公式参数 |
| 5 | 性别 | enum(男/女) | 员工档案 | 档案读取 | 第一层:BMR公式选择 |
| 6 | 体力活动等级 | enum | 员工档案 | 员工在 `basic-info.html` 中自行填写,5个选项之一 | 第一层:活动系数 |
| 7 | 血压-收缩压 | number(mmHg) | 体检报告/指标录入 | 从 `indicators-diseases.html` 取最近值 | 第二层:高血压分级 |
| 8 | 血压-舒张压 | number(mmHg) | 体检报告/指标录入 | 同上 | 第二层:高血压分级 |
| 9 | 血尿酸值 | number(μmol/L) | 体检报告/指标录入 | 从 `indicators-diseases.html` 取最近值 | 第二层:高尿酸分期 |
| 10 | 智能餐线消费记录 | array | 智能餐线系统 | 近6个月消费记录,脱敏后仅提供"菜品类型+消费频次",不含姓名/工号 | 第三层:提取口味偏好 |
| 11 | 肾病合并 | boolean | 体检报告 | 从年度体检报告自动获取,影响蛋白质和钠阈值 | 第二层:合并慢病调整 |
| 12 | 糖尿病合并 | boolean | 体检报告 | 从年度体检报告自动获取,影响碳水分配和GI选择 | 第二层:合并慢病调整 |
### 2.2 需问卷采集(员工主动填写)
| 序号 | 数据字段 | 类型 | 采集方式 | 问卷内容示例 | 用途(哪一层) |
|------|----------|------|----------|------------|-------------|
| 13 | 所在地区 | enum | 健康问卷 | "您常驻工作地区?" 用于匹配当地常见食材库(如西安→西北食材库) | 第三层:地区食材匹配 |
| 14 | 口味偏好 | enum(清淡/辛辣/咸鲜/酸甜) | 健康问卷 | "您偏好什么口味?" 单选 | 第三层:口味适配 |
| 15 | 规避食材 | array(string) | 健康问卷 / 膳食建议页标记 | 过敏/不喜欢食材多选(羊肉、海鲜、动物内脏、香菜、…),可自定义添加 | 第三层:排除特定食材 |
| 16 | 上班时间 | enum | 健康问卷 | "您通常的上班时间?" 正常白班 / 早班 / 晚班 / 倒班 | 第三层:场景适配 |
### 2.3 外部数据(AI团队自行整理,非实时调用)
| 序号 | 数据内容 | 来源 | 用途 |
|------|----------|------|------|
| 17 | 西北地区常见食材库 | 地方疾控《居民膳食报告》+ 本地餐饮协会 | 第三层:地区食材匹配(莜面、羊肉、土豆、菠菜…) |
| 18 | 餐品嘌呤等级标注 | AI团队预标注 | 第二层:食材嘌呤分级(高/中/低) |
| 19 | 餐品钠含量数据 | AI团队预标注 | 第二层:钠摄入计算(mg/100g) |
| 20 | 菜品-口味标签映射 | AI团队预标注 | 第三层:从菜品消费记录提取口味偏好 |
---
## 三、数据校验规则
| 字段 | 校验规则 |
|------|----------|
| 血尿酸值 | 150-1000 μmol/L,超出范围接口返回"数据异常" |
| 口味偏好 | 仅接受枚举值,传入"微辣"等非标值→自动映射为"辛辣" |
| 身高 | 100-250 cm |
| 体重 | 30-300 kg |
| 年龄 | 18-70 岁 |
| 血压 | 收缩压60-250 mmHg,舒张压30-150 mmHg |
---
## 四、第一层:基础营养计算规则(确定性公式,无需模型)
### 4.1 BMR计算
```
男性:BMR = 10 × 体重(kg) + 6.25 × 身高(cm) - 5 × 年龄 - 161 + 166
女性:BMR = 10 × 体重(kg) + 6.25 × 身高(cm) - 5 × 年龄 - 161
```
### 4.2 活动系数(员工自行填写,系统直接获取)
| 员工选项 | 活动系数 |
|----------|----------|
| 久坐不运动 | 1.2 |
| 久坐运动或久站 | 1.375 |
| 体力劳动者 | 1.55 |
| 久站+运动 | 1.725 |
| 健身+体力劳动者 | 1.9 |
### 4.3 总热量
```
总热量 = BMR × 活动系数 - 300(固定热量缺口)
```
### 4.4 三大宏量营养素供能比(固定)
| 营养素 | 供能比 | 每克热量 | 计算公式 |
|--------|--------|----------|----------|
| 蛋白质 | 15% | 4 kcal/g | 总热量×15%÷4 |
| 碳水化合物 | 55% | 4 kcal/g | 总热量×55%÷4 |
| 脂肪 | 30% | 9 kcal/g | 总热量×30%÷9 |
---
## 五、第二层:慢病管控规则(AI动态调整)
### 5.1 高血压 → 钠控制
| 高血压等级 | 判定条件 | 钠上限/日 | 相当于盐 |
|-----------|----------|----------|----------|
| 正常 | 收缩压<140 且 舒张压<90 | 无特殊限制 | — |
| 1级 | 收缩压140-159 或 舒张压90-99 | ≤2000mg | ≈5g盐 |
| 2级 | 收缩压≥160 或 舒张压≥100 | ≤1500mg | ≈3.75g盐 |
| 合并肾病 | 任意级别 + 肾病 | ≤1200mg | ≈3g盐 |
**额外约束**:每餐钠摄入不超过日总上限的40%(避免单次超标)
### 5.2 高尿酸 → 嘌呤控制
| 高尿酸分期 | 判定条件 | 嘌呤上限/日 | 高嘌呤食材 |
|-----------|----------|------------|----------|
| 无症状期 | 血尿酸420-600 μmol/L | ≤300mg | 动物内脏、沙丁鱼直接排除 |
| 急性发作期 | 血尿酸>600 或 近期发作 | ≤150mg | 海鲜类也排除 |
| 痛风石 | 已确诊痛风石 | ≤100mg | 仅保留极低嘌呤食材 |
### 5.3 合并慢病 → AI动态调整优先级
- **高血压 + 高尿酸**:优先控制钠和嘌呤,允许钾从2500→2800mg/日
- **高尿酸 + 肾病**:优先控制嘌呤和蛋白质,蛋白质从1.2g/kg→0.8g/kg体重
- **高血压 + 糖尿病**:碳水中低GI占比≥60%,钠按相应等级控制
---
## 六、第三层:个性化适配规则(AI推理 + 规则库)
### 6.1 口味适配
- 从消费记录提取高频菜品→匹配口味标签
- 例如:员工高频消费"油泼面"→口味标签=辛辣→推荐菜品时保留辛辣风味但减少钠(如"低盐油泼面",钠减少30%
- **原则**:改良而非替代,不强制推荐清淡菜品给辛辣口味员工
### 6.2 地区适配
- 食谱生成时优先从西北本地食材库选材(目标占比≥70%)
- 例如:早餐优先"杂粮粥+全麦馒头"而非"白粥+包子"
- 本地食材库包含:莜面、土豆、菠菜、羊肉、小米、全麦粉、沙棘果等
### 6.3 场景适配(根据员工填写的上班时间)
| 上班时间 | 适配策略 |
|----------|----------|
| 正常白班 | 三餐正常分配,早/午/晚餐热量比 30%/40%/30% |
| 早班 | 早餐热量适当上调至35%,凌晨餐推荐低GI主食 |
| 晚班 | 晚餐为主餐(40%热量),夜间加餐推荐低GI主食(燕麦、荞麦)+ 高蛋白菜品,避免夜间血糖波动 |
| 倒班 | 根据当日实际班次动态调整餐次分配,优先保证蛋白质摄入稳定 |
---
## 七、API接口规范
### 7.1 请求
```
POST /api/v1/diet/recommend
Content-Type: application/json
```
```json
{
"user_id": "a3f2d...", // 必填,脱敏哈希ID
"date": "2026-06-29", // 必填,推荐日期
"height": 175, // 必填 cm
"weight": 72.5, // 必填 kg
"age": 45, // 必填
"gender": "male", // 必填 male/female
"activity_level": "manual_labor", // 必填,员工自行填写的体力活动等级
// 取值:sedentary(久坐不运动) / sedentary_exercise(久坐运动或久站)
// manual_labor(体力劳动者) / standing_exercise(久站+运动)
// fitness_labor(健身+体力劳动者)
"sbp": 145, // 收缩压 mmHg,可为null
"dbp": 92, // 舒张压 mmHg,可为null
"uric_acid": 526, // 血尿酸 μmol/L,可为null
"region": "xian", // 必填,员工填写的所在地区,决定食材库匹配
"taste": "spicy", // 必填 bland/spicy/salty/sweet_sour
"avoid_foods": ["lamb", "organ_meat"], // 规避食材列表(过敏/不喜欢)
"has_kidney_disease": false, // 是否合并肾病
"has_diabetes": false, // 是否合并糖尿病
"work_schedule": "normal" // 必填 normal/early/late/rotating
// 正常白班/早班/晚班/倒班
}
```
### 7.2 响应
```json
{
"user_id": "a3f2d...",
"date": "2026-06-29",
"total_calorie": 2645,
"calorie_consumed": 1486,
"calorie_remaining": 1159,
"bmr": 1900,
"activity_factor": 1.55,
"macros": {
"protein": { "target_g": 99, "current_g": 61, "ratio": 0.15 },
"carbs": { "target_g": 364, "current_g": 186, "ratio": 0.55 },
"fat": { "target_g": 88, "current_g": 34, "ratio": 0.30 }
},
"chronic_control": {
"sodium": {
"limit_mg": 2000,
"current_mg": 1040,
"level": "ok", // ok / warn / danger
"rule": "高血压1级,≤2000mg/日"
},
"purine": {
"limit_mg": 300,
"current_mg": 204,
"level": "warn", // ok / warn / danger
"rule": "无症状高尿酸,≤300mg/日,已排除高嘌呤食材"
}
},
"personalization": {
"taste_label": "辛辣",
"region": "西安·西北",
"work_schedule": "正常白班",
"local_ratio": 0.76 // 本地食材占比
},
"meals": {
"breakfast": [
{
"dish_name": "杂粮粥",
"amount": "200g",
"ingredients": ["燕麦30g", "小米20g", "枸杞5g"],
"calorie_kcal": 185,
"nutrient": { "sodium_mg": 50, "purine_mg": 15 },
"badges": ["local", "low-purine"],
"cooking_tip": "少放糖,加少量枸杞增加风味"
}
],
"lunch": [ /* ... */ ],
"dinner": [ /* ... */ ],
"snack": [ /* ... */ ]
},
"warning": "昨日尿酸值偏高(526 μmol/L),今日已自动剔除高嘌呤食材(动物内脏、沙丁鱼)。建议增加饮水至2000ml。",
"weekly_plan": [
{ "day": "周一", "date": "08-10", "total_kcal": 2645, "meals": [ /* */ ] }
]
}
```
### 7.3 性能要求
| 指标 | 要求 |
|------|------|
| 单次响应时间 | ≤500ms |
| 1000并发响应时间 | 平均≤500ms,峰值≤1s |
| 批量查询(≤100用户) | ≤3s |
| 稳定性(72h连续) | ≥99.9%成功率 |
---
## 八、膳食建议页(diet-advice.html)展示内容映射
页面上每个展示区对应算法输出的字段:
| 页面区域 | 数据来源(响应字段) | 说明 |
|----------|---------------------|------|
| 慢病标签条 | 根据sbp/dbp/uric_acid推导的等级 | 展示"高血压1级""高尿酸无症状期" |
| AI慢病提醒 | `warning` | 红色/黄色横幅,突出显示 |
| 口味/地区/场景标签 | `personalization` | 三个pill标签 |
| 热量目标卡片 | `total_calorie` + `calorie_consumed` + `calorie_remaining` + `bmr` + `activity_factor` | 大数字+进度条 |
| 三大宏量营养素环 | `macros.protein/carbs/fat` | 环形图 |
| 钠指标卡 | `chronic_control.sodium` | 进度条+状态标识 |
| 嘌呤指标卡 | `chronic_control.purine` | 进度条+状态标识 |
| 本地食材占比 | `personalization.local_ratio` | 进度条 |
| 三餐推荐(含加餐) | `meals.breakfast/lunch/dinner/snack` | 每道菜:名称+份量+营养素+标签+烹饪建议 |
| 一周食谱 | `weekly_plan` | 7天切换 |
| 规避食材标记 | 前端交互(回传avoid_foods给接口) | 员工自行勾选 |
| 份量参考 | 静态内容(非算法输出) | 手掌/拳头等图示 |
| 分层注意事项 | `chronic_control.*.rule` + 静态内容 | 按三层分组 |
---
## 九、模型训练与交付要求
| 阶段 | 工作内容 | 验收标准 |
|------|----------|----------|
| 预训练 | 用公开膳食数据集训练基础营养计算能力 | 偏差率≤12% |
| 微调1(慢病) | 用500条员工健康数据微调慢病管控 | 符合率≥90% |
| 微调2(个性化) | 用口味/地区数据微调,加入本地食材库 | 适配率≥88% |
| 迭代优化 | 根据员工反馈调整规则库 | 满意度≥85% |
**最终精度目标:**
- 膳食建议符合《高血压/高尿酸膳食指导》率 ≥ 95%
- 口味/地区适配符合率 ≥ 92%
- 钠/嘌呤计算偏差率 ≤ 8%
**交付物:**
- 算法模型(含API接口,RESTful/HTTPS/JSON
- 规则配置文件(XML,支持非技术人员修改食材库/营养阈值/口味维度)
- 《模型使用手册》(含接口调用指南+规则配置教程+维护周期建议)
- 《数据对接规范》(含输入输出格式+校验规则)
- 《测试报告》(≥10类场景测试+性能测试)