日期:2026-08-13(v2 更新:2026-08-18) 分支:cfclub 状态:v2 待评审(疾病史/用药输入重设计)
| 版本 | 日期 | 变更 |
|---|---|---|
| v1 | 2026-08-13 | 初版设计(疾病史:10 预置标签 + 自由输入;用药:每药 药名+服药时间) |
| v2 | 2026-08-18 | 疾病史重设计:预置清单扩为「菌群报告病症风险 + 互联网统计常见病」两源合并去重(约 50 项,分类折叠多选),每条疾病新增确诊时间(年月);用药重设计:每药一行保留,新增开始服药日期 → 自动计算已服时长,记不清时可用时长文本兜底 |
当前出方案流程(health-plan-summary.vue:选报告 → 提需求 → AI 生成方案)只接收健康报告 + 用户自由文本需求,没有结构化的"当前健康现状"输入。AI 出方案时不知道用户身高体重、血压血糖血脂、疾病史、用药情况、过敏源等关键信息,方案精度受限。
用户需求(已确认):
设计目标:
| # | 问题 | 决策 |
|---|---|---|
| 1 | 调研触发形式 | 两者都要:出方案流程内提示填写 + 独立档案页随时维护;填过一次后出方案自动读取,可更新 |
| 2 | 数据归属对象 | 按账号(user_id)存一份 |
| 3 | 过敏/食物喜好与现有表关系 | 复用现有 diet_preferences(按 family_member_id 存),新表不重复存;出方案时一并读取传入 |
| 4 | 指标值形态 | 结构化数值 + 可选备注(血压 120/80、血糖 5.6 + 备注补充诊断信息) |
| 5 | 疾病史形态(v2) | 预置清单多选:菌群报告病症风险(20 项)+ 互联网统计常见病(约 40 项)合并去重后按类别分组折叠多选(约 50 项);未列出的保留自定义输入兜底;每条疾病含 diagnosedAt(确诊时间,年月) |
| 6 | 用药形态(v2) | 每药一条:{name, startDate, durationText, time};startDate(开始服药年月)自动计算已服时长,记不清时填 durationText(约 X 个月/年) |
| 7 | 不填的提醒方式 | 弹窗确认:「未填写健康现状,方案可能不精准」→「去填写」/「直接生成」 |
| 8 | AI 接入方式 | 前端随请求传参:前端把健康现状+饮食偏好随 aiSendMessage 请求传给 AI(Dify inputs) |
独立档案页 (pages/health/health-status-form.vue) 出方案流程 (health-plan-summary.vue)
│ 读/写 │ 读取
▼ ▼
health_status 表 (新, user_id 唯一) diet_preferences (现有, family_member_id)
│ │
└──────────────────┬──────────────────────────────────┘
▼ 前端组装 healthStatus + dietPrefs
aiSendMessage({query, reportId, healthStatus, dietPrefs})
▼
AIChatController.sendMessage
▼
inputs.put("health_status", ...) / inputs.put("diet_preferences", ...)
▼
Dify 生成方案
diet_preferences(无则空)。uni.showModal 弹窗 →「去填写」跳档案页 /「直接生成」继续。health_statusCREATE TABLE IF NOT EXISTS health_status (
id BIGINT AUTO_INCREMENT PRIMARY KEY,
user_id BIGINT NOT NULL COMMENT '所属账号(一个账号一份)',
height_cm DECIMAL(5,1) DEFAULT NULL COMMENT '身高(cm)',
weight_kg DECIMAL(5,1) DEFAULT NULL COMMENT '体重(kg)',
blood_pressure VARCHAR(20) DEFAULT NULL COMMENT '血压,如 120/80',
blood_glucose DECIMAL(4,1) DEFAULT NULL COMMENT '空腹血糖(mmol/L)',
blood_lipids JSON DEFAULT NULL COMMENT '血脂 [{name,value,unit,note}]',
disease_history JSON DEFAULT NULL COMMENT '疾病史 [{name,diagnosedAt,note}]',
medications JSON DEFAULT NULL COMMENT '在服药物/治疗 [{name,startDate,durationText,time}]',
notes VARCHAR(500) DEFAULT NULL COMMENT '其他补充说明',
filled_at DATETIME DEFAULT NULL COMMENT '首次填写时间',
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
UNIQUE KEY uk_user (user_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='当前状态调研-健康现状档案';
diet_preferences。DatabaseInitializer.runMigrations() 新增迁移(CREATE TABLE IF NOT EXISTS),同步 schema.sql。迁移编号按现有最大编号递增。disease_history/medications 为 JSON 字符串列,字段结构变化发生在 JSON 内部,表结构、实体、Controller、Service 均不变。blood_lipids:
[
{"name": "总胆固醇", "value": 4.5, "unit": "mmol/L", "note": ""},
{"name": "甘油三酯", "value": 1.8, "unit": "mmol/L", "note": "偏高,医生建议控制"}
]
disease_history(v2):
[
{"name": "高血压", "diagnosedAt": "2021-03"},
{"name": "胃病", "diagnosedAt": ""},
{"name": "自定义补充病", "diagnosedAt": "2019-08"}
]
diagnosedAt:确诊时间(年月,yyyy-MM),可空。note:保留字段,仅用于兼容 v1 旧数据回显({name, note} 无 diagnosedAt 时 diagnosedAt 置空);v2 新数据不产生 note。medications(v2):
[
{"name": "立普妥", "startDate": "2024-05", "durationText": "已服 15 个月", "time": "早饭后一次"},
{"name": "二甲双胍", "startDate": "", "durationText": "约 3 个月", "time": "随餐"}
]
startDate:开始服药年月(yyyy-MM),可空;保存时前端据此自动计算 durationText。durationText:已服时长文本,自动计算值("已服 X 个月/年")或手动兜底("约 X 个月/年")。time:服药时间点(如"早饭后一次"),保留 v1 字段。预置清单的"互联网统计源"疾病排序与文案依据,数据来自国家卫健委、国家疾控中心、国家癌症中心、中华医学会及《柳叶刀》等权威来源;大型流行病学调查周期为 5-10 年,以下为最新权威口径。
| 疾病 | 患病率 / 人数 | 数据出处 | 数据年份 |
|---|---|---|---|
| 高血压 | 现患约 2.45 亿;成人患病率 25.2%(另一口径 27.5%) | 《中国心血管健康与疾病报告2023》;《健康中国行动2019—2030年》;《中国居民营养与慢性病状况报告2020》 | 2023 / 2019 / 2020 |
| 血脂异常 | 18 岁及以上成人患病率 40.4% | 《健康中国行动2019—2030年》 | 2019 |
| 糖尿病 | 成人患病率约 11.9%;糖尿病前期 35.2%;患病人数或超 1.8 亿 | 国家卫健委《高血糖症营养和运动指导原则(2024年版)》;2024-11 全国糖尿病学术会议 | 2024 |
| 冠心病 | 现患约 1139 万 | 《中国心血管健康与疾病报告2023》 | 2023 |
| 脑卒中 | 现患约 1300 万 | 《中国心血管健康与疾病报告2023》 | 2023 |
| 心力衰竭 | 现患约 890 万 | 《中国心血管健康与疾病报告2023》 | 2023 |
| 心房颤动 | 现患约 487 万 | 《中国心血管健康与疾病报告2023》 | 2023 |
| 慢阻肺 | 20 岁+ 8.6%、40 岁+ 13.7%;患者近 1 亿 | 王辰院士"中国成人肺部健康研究"(Lancet) | 2018 |
| 哮喘 | 20 岁+ 4.2%,患者约 4570 万 | 王辰院士团队(Lancet) | 2019 |
| 慢性肾病 | 8.2%(超 8000 万,知晓率仅 10%);另一口径 10.8% | 2018 年中国居民慢性病监测(JAMA Intern Med 2024);2012 年调查(NEJM) | 2024 / 2012 |
| 幽门螺杆菌感染 | 自然人群感染率约 40%-50% | 多项流行病学调查及 2022 年 meta | 2022 |
| 脂肪肝 | 患病率接近 30% | 流行病学综述 | 近年 |
| 胃食管反流病 | 总体患病率约 8.7% | 2022 年 meta 分析 | 2022 |
| 肠易激综合征 | 普通人群约 1.4%-11.5%(各调查差异大) | 中国流行病学调查汇总 | 多项 |
| 慢性便秘 | 总患病率约 8.5%,60 岁+约 32.6% | 2022 年 meta 分析 | 2022 |
| 胆结石 | 患病率约 7%-10% | 流行病学资料 | 2024 综述 |
| 过敏性鼻炎 | 中国成人患者约 1.5 亿;患病率约 17.6% | 张罗等全国调查估算;2011 年调查 | 2017 / 2011 |
| 超重/肥胖 | 成人超重肥胖率超 50%(BMI≥24 口径);6-17 岁约 19% | 《中国居民营养与慢性病状况报告2020》;2024 肥胖防控大会 | 2020 / 2024 |
| 高尿酸血症 | 成人总体约 13.3%;18-29 岁青年男性 32.3% | 《中国高尿酸血症与痛风诊疗指南(2019)》;《痛风诊疗规范(2023)》 | 2019 / 2023 |
| 骨质疏松 | 50 岁+ 19.2%(女性 32.1%,65 岁+女性 51.6%) | 首次中国骨质疏松症流行病学调查(国家卫健委) | 2018 |
| 缺铁性贫血 | 全国居民贫血 9.7%(女性 12.6%、孕妇 17.2%) | 中国居民营养与健康状况监测 | 2010-2013 |
| 肺癌 | 新发 106.06 万例,居第 1 位 | 国家癌症中心+IARC(JNCC) | 2022 数据 / 2024 发布 |
| 结直肠癌 | 51.71 万例,第 2 位 | 同上 | 同上 |
| 甲状腺癌 | 46.61 万例,第 3 位 | 同上 | 同上 |
| 肝癌 | 36.77 万例,第 4 位 | 同上 | 同上 |
| 胃癌 | 35.87 万例,第 5 位 | 同上 | 同上 |
| 乳腺癌 | 女性第 2 位 | 同上 | 同上 |
| 食管癌 | 男性第 5 位 | 同上 | 同上 |
| 近视 | 儿童青少年总体 52.7%(小学 35.6%/初中 71.1%/高中 80.5%) | 国家疾控局监测 | 2023 |
| 龋齿 | 12 岁儿童约 34.5%、5 岁约 70.9% | 第四次全国口腔健康流行病学调查 | 2015-2017 |
| 注意缺陷多动障碍 | 患病率约 6%(meta 口径,待核实) | 流行病学 meta 分析 | 近年 |
| 焦虑障碍 | 成人终生 7.6%,12 个月 4.98% | 中国精神卫生调查(CMHS,Lancet Psychiatry) | 2019 |
| 抑郁障碍 | 成人 12 个月约 3.6% | 中国精神卫生调查(CMHS) | 2019 |
| 偏头痛 | 年患病率 9.3%(女性 12.8%);约 2 亿患者 | 中国头痛流行病学调查 | 2021 |
口径差异说明:高血压(25.2% vs 27.5%)、CKD(8.2% vs 10.8%)存在不同调查口径,科普文案取最新发布口径并注明调查年份。 待核实项:湿疹/特应性皮炎、食物过敏、ADHD、失眠、IBD 具体患病率未获权威一手来源,预置清单保留条目但文案引用前需补充核实。
entity/HealthStatus.java — @TableName("health_status"),字段对应上表(diseaseHistory/medications 保持 String,JSON 字符串透传,v2 无字段变更)。mapper/HealthStatusMapper.java — MyBatis-Plus BaseMapper。service/HealthStatusService.java(接口)+ impl/HealthStatusServiceImpl.java:
HealthStatus getByUserId(Long userId)HealthStatus save(Long userId, HealthStatus status)(upsert:有则更新,无则插入;filledAt 仅首次填写时赋值)HealthStatusController路由前缀 /api/health-status,统一 @PostMapping:
| 接口 | 说明 | 参数 | 返回 |
|---|---|---|---|
POST /api/health-status/get |
查询当前账号健康现状 | {}(从 JWT 取 userId) |
HealthStatus 或 null |
POST /api/health-status/save |
保存/更新(upsert) | HealthStatus 字段(JSON body,diseaseHistory/medications 为 JSON 字符串) | 保存后的 HealthStatus |
成员饮食偏好复用现有接口:
POST /api/diet/preferences/current-member(已有DietPreferencesService.getCurrentMemberPreferences,前端已有getDietPreferences),不新增重复端点。
AIChatController.sendMessage当前方法 @RequestBody Map<String, String> params 已解析 reportId/surveyId。新增:
String healthStatusStr = params.get("healthStatus"); // JSON 字符串(可空)
String dietPrefsStr = params.get("dietPrefs"); // JSON 字符串(可空)
...
if (healthStatusStr != null && !healthStatusStr.trim().isEmpty()) {
try {
inputs.put("health_status", objectMapper.readValue(healthStatusStr, Map.class));
} catch (Exception e) { log.warn("healthStatus解析失败: {}", e.getMessage()); }
}
if (dietPrefsStr != null && !dietPrefsStr.trim().isEmpty()) {
try {
inputs.put("diet_preferences", objectMapper.readValue(dietPrefsStr, Map.class));
} catch (Exception e) { log.warn("dietPrefs解析失败: {}", e.getMessage()); }
}
pages/health/health-status-form.vue(修改,非新增)pages.json(health 分包,v1 已实现)。POST /api/health-status/get 回显;保存 POST /api/health-status/save。\d{2,3}/\d{2,3}、血糖 1–30;前端校验 + 后端兜底。health-main/index.vue)「方案制定」旁加「健康档案」按钮(v1 已实现)。预置疾病清单(两源合并去重,约 50 项):
| 分类 | 疾病(★ = 菌群报告病症风险源) |
|---|---|
| 🫀 心血管代谢 | 高血压、糖尿病、血脂异常、冠心病、脑卒中、心力衰竭、心房颤动、慢阻肺、心脑血管疾病★、II型糖尿病★、肥胖★、超重、高尿酸血症、骨质疏松 |
| 🍽️ 消化系统 | 幽门螺杆菌感染、脂肪肝、慢性胃炎、胃食管反流、肠易激综合征★、炎症性肠炎★、慢性便秘★、感染性腹泻★、胆结石、炎症性肠病、肝病★、胃病★、胆病★、肾病★、腹胀★ |
| 🤧 过敏免疫 | 过敏性鼻炎★、哮喘、湿疹、食物过敏、自体免疫病★ |
| 🧠 精神神经 | 抑郁症★、失眠★、焦虑障碍、偏头痛、自闭症★ |
| 🫁 呼吸系统 | 肺部感染或疾病★、肺部疾病★ |
| 🎗️ 肿瘤 | 结直肠癌★、肺癌、甲状腺癌、肝癌、胃癌、乳腺癌、食管癌 |
| 🧒 儿童青少年 | 近视、龋齿、注意缺陷多动障碍、甲状腺疾病★ |
| 其他 | 缺铁性贫血、贫血 |
菌群源说明:★ 标注的疾病来自
PdfParseService.KNOWN_DISEASE_RISKS白名单(20 项)+ 报告指标知识库,与肠道菌群报告"疾病风险评估"板块一一对应(如炎症性肠炎、肠易激综合征、II型糖尿病、心脑血管疾病等),勾选后可关联菌群报告风险值。互联网统计源数据(患病率/出处/年份)见 4.3 节,供科普文案使用。
分类折叠交互:
uni-collapse 或自实现折叠),默认展开前 3 组;已选中的疾病自动展开所在组。tag-active 高亮),点选=选中/取消。showModal 说明该病与菌群报告的关系(如"菌群报告可评估炎症性肠炎风险")。已选疾病区:
picker mode="date" 前端限制到年月,或自实现年月滚动选择器)→ 回填 diagnosedAt。yyyy-MM(如 2021-03)。自定义补充(兜底):
tag-active 样式呈现于已选区,可删除。durationText。当前年月 - startDate → "已服 X 个月"(<12 个月)/"已服 X 年"(≥12 个月,取整)。health-plan-summary.vue(修改)onLoad 并行读取:getHealthStatus() + 目标成员 getDietPreferences()(现有接口,后端按所选成员返回)。点「生成方案」时若健康现状未填(get 返回 null)→ uni.showModal:
标题:填写健康现状
内容:尚未填写健康现状,方案可能不够精准。是否先填写?
[去填写] [直接生成]
uni.navigateTo 档案页,返回后重新读取;「直接生成」→ 继续。生成时传参:aiSendMessage({ query, reportId, healthStatus, dietPrefs })。
目标成员选择:现有 subjectId 或所选报告归属成员;dietPrefs 按该成员读取。
utils/api.js(修改)getHealthStatus、saveHealthStatus。getDietPreferences(/api/diet/preferences/current-member)。aiSendMessage 支持透传 healthStatus/dietPrefs(langgraph body 与 dify fallback data 均携带)。| 场景 | 处理 |
|---|---|
| 未填任何调研数据点生成方案 | 弹窗提醒,可「直接生成」继续 |
| 调研数据读取失败(网络/接口) | 静默降级,不阻塞出方案 |
| healthStatus/dietPrefs JSON 解析失败 | 后端记 warn 日志,跳过该 inputs,不抛 500 |
| JSON 字段损坏(DB 中) | 读取时按空处理 |
| 数值非法(身高 999、血压 abc) | 前端校验拦截 + 后端返回 Result.error |
| 空提交 | 至少填 1 项,否则返回 Result.error("请至少填写一项") |
| 超过 6 个月未更新 | 出方案弹窗提示「上次填写时间较早,建议更新」(可跳过) |
| v1 旧数据回显 | {name, note} 无 diagnosedAt/startDate/durationText → 前端置空默认值,不报错 |
| 确诊时间晚于当前 | 年月选择器 end 限制为当前年月,防未来日期 |
| 服药开始日期晚于当前 | 同上限制 |
mvn clean compile 通过;新增 Service 单测(可选,现有测试较少):
node --check 语法校验(不打包,HBuilderX 打包)。{name,note} / {name,time})回显兼容,不报错survey_templates 机制管理题目)——字段固定,本期仅按本设计固化。diet_preferences。