# 菌群报告页面重构设计规范
> 基于参考 JSON 完整数据,重构「肠道菌群报告详情页」,覆盖查看+编辑混合场景。
> 页面只展示个性化数据(个人测定值),标准说明通过弹出框从知识库获取。
**版本:** v1.1(v1.0 修正:仅展示个性化数据 + 知识库弹出框 + 异常值颜色箭头)
**日期:** 2026-07-17
**状态:** Draft
**作者:** Sisyphus
---
## 1. 背景与目标
### 1.1 现状问题
- 现有 `pages/health/gut-flora-detail.vue` 只展示 5 个评分圆环 + 3 组菌属分类 + 食物推荐
- 后端 `/api/health/report/detail` 已返回完整数据:`report` + `indicators` + `gutFlora` + `diseaseRisks`
- Reference JSON 显示完整报告含 200+ 菌属条目、50+ 评估指标、224 种食物推荐
- 现有页面覆盖率不足 5%,大量有价值数据丢失
### 1.2 设计目标
1. **完整展示**:将所有报告板块(评分/指标/菌群/疾病风险/食物)全部呈现
2. **仅展示个性化值**:页面只显示该人的测定数值,标准说明不内嵌
3. **知识库弹出框**:每个菌、营养素、指标的名称可点击 → 弹出详细说明(来自独立知识库表)
4. **异常值颜色+箭头**:超出正常范围的数值用颜色区分,名称上标 ↑(过高)↓(过低)
5. **可编辑**:用户可在查看页面转向编辑模式,调整解析错误的数据
### 1.3 不在本文档范围
- 报告上传 / 解析流程(已稳定)
- 后端 PDF 解析逻辑(已由 `PdfParseService` 完成)
- 报告列表页(`/pages/health/report-list`,未变动)
---
## 2. 设计决策
| 决策项 | 选择 | 理由 |
|--------|------|------|
| 页面拆分 | 主页 + 3 个详情页 | 食物 224 条 + 菌群 200 条过长,必须分页;指标用手风琴折叠到主页 |
| 模式 | 混合(默认查看 + 编辑切换) | 满足「全字段可编辑」同时保留查看优先体验 |
| 编辑范围 | 仅修改现有条目(不增删) | 当前需求是修正 AI 解析错误,不是新增数据 |
| 保存路径 | 新增 `POST /api/health/report/edit` | 编辑已发布报告(不用 draftId) |
| 说明展示 | 不内嵌,点击名称弹出知识库 | 页面干净,知识库可独立维护 |
---
## 3. 页面架构
```
pages/health/
├── gut-flora-detail.vue # 主页 (本文件重写)
├── gut-flora-species-detail.vue # 菌群详情 (新增)
├── gut-flora-foods-detail.vue # 食物推荐 (新增)
└── gut-flora-risks-detail.vue # 疾病风险 (新增)
```
page.json 中需新增 3 个路径:
| Path | Title |
|------|-------|
| `pages/health/gut-flora-species-detail` | 菌群详情 |
| `pages/health/gut-flora-foods-detail` | 饮食推荐 |
| `pages/health/gut-flora-risks-detail` | 疾病风险 |
---
## 4. 异常值颜色与箭头规则(通用)
所有页面(主页手风琴、菌群卡片、营养指标列表)统一使用以下规则:
| 状态 | 颜色 | 箭头 | 示例 |
|------|------|------|------|
| `正常` / `低风险` | 默认文本 #333 | 无 | 维生素A 84 |
| `偏高` / `过多` / `高` | 红色 #C62828 | ↑ | **双歧杆菌属↑** 12.8% |
| `偏低` / `缺乏` / `不足` / `低` | 琥珀色 #E65100 | ↓ | **维生素B1↓** 2 |
| `异常` | 红色 #C62828 | ⚠ | **炎症水平⚠** 16 |
| `注意` | 黄色 #F59E0B | ⚠ | **甲状腺疾病⚠** |
实现方式(Vue 2 inline 表达式):
```html
{{ item.name }}{{ arrowMap[item.status] }}
{{ item.name }}
```
不可用方法调用(`statusClass(item.status)`),必须内联 `:class="'status-' + item.status"`。
---
## 5. 知识库弹出框(通用组件)
### 组件:`components/health-knowledge-popup.vue`
每个菌属名/营养素名/指标名都是可点击的,点击后打开一个弹出框显示该项目的知识库说明。
```html
{{ item.name }}
:item-name="knowledgeName"
@close="closeKnowledge" />
```
### 弹出框内容结构
```
┌────────────────────────────────┐
│ 双歧杆菌属 Bifidobacterium [×]│
│ ────────────────────────────── │
│ 【分类】有益菌 │
│ 【正常范围】0.19-14.59% │
│ 【功能说明】 │
│ 最重要的益生菌,参与肠道免疫屏障│
│ 维护,抑制有害菌生长,促进营养 │
│ 物质吸收...(完整说明文字) │
│ │
│ 【相关建议】 │
│ 补充来源:酸奶、开菲尔等发酵食品│
└────────────────────────────────┘
```
### 数据来源
知识库数据存储在独立数据库表 `health_knowledge_base` 中。
后端接口:
```
POST /api/health/knowledge/query
body: { itemType: "bacteria", itemName: "双歧杆菌属 Bifidobacterium" }
返回: { code: 200, data: { itemType, itemName, category, normalRange, description, suggestion } }
```
---
## 6. 主页:gut-flora-detail.vue
### 6.1 板块布局(由上至下)
1. **报告头部**(hero 渐变背景)
- 姓名、年龄、性别、报告编号、报告日期
- 肠道预测年龄 / 肠型(徽章)
2. **健康评分总览**(圆形进度环,5-11 个)
- 健康总分(综合)/ 菌群健康 / 慢病控制 / 营养均衡 / 平衡 / 多样性 / 有益菌 / 有害菌 / 核心菌属
3. **快速跳转入口**(4 个图标卡,进入详情页)
- 🦠 菌群详情(X 种)
- ⚠️ 疾病风险(X 项)
- 🍽️ 饮食推荐(X 项)
- 📋 全部指标(X 项)
4. **肠道功能面板**(手风琴 Accordion)
- 肠道屏障与代谢物 → 指标列表,名称可点击弹知识库,异常值带颜色+箭头
- 短链脂肪酸
- 神经递质与激素
- 抗生素风险评估
5. **营养指标面板**(手风琴 Accordion)
- 主要营养(碳水/蛋白/脂肪/纤维素/乳制品)
- 氨基酸(10 项)
- 维生素(9 项)
- 微量元素
### 6.2 两种模式
| 模式 | 显示 | 操作 |
|------|------|------|
| 查看模式 | 只展示数值 + 状态颜色+箭头 | 点击名称弹知识库 |
| 编辑模式 | 数值改为 input / 状态改为 picker | 点击「取消」「保存」 |
查看模式下,名称仍然可点击弹知识库。编辑模式下知识库弹框仍然可用。
### 6.3 顶部 FAB
- 查看模式:右下显示「✏️ 编辑」浮动按钮
- 编辑模式:底部显示「取消」「保存(草稿)」双按钮固定栏
### 6.4 手风琴中指标卡结构
```
┌───────────────────────────────────┐
│ 维生素B1 ↓ 数值: 2 │
│ 正常范围: 4-20 │
└───────────────────────────────────┘
```
- 名称 `维生素B1` → 可点击,弹出知识库
- `↓` 箭头 + 红色字体(偏低)
- 正常范围的用默认色,无箭头
---
## 7. 菌群详情:gut-flora-species-detail.vue
### 7.1 顶部导航(12 分类 Tab)
| Tab | 数据源 |
|-----|--------|
| 核心菌属 | payload.gutFlora → category="core" |
| 益生菌(菌门) | payload.probioticSpecies → category="probiotic" |
| 有害菌 | category="harmful" |
| 其它菌属 | category="other" |
| 病原菌 | category="pathogen" |
| 肥胖相关 | category="obesity" |
| 便秘相关 | category="constipation" |
| 抑郁相关 | category="depression" |
| 过敏相关 | category="allergy" |
| 腹胀相关 | category="bloating" |
| 失眠相关 | category="insomnia" |
| 全部 | 不过滤 |
### 7.2 卡片结构
**无内嵌说明**,标准说明通过点击名称弹出知识库获取。
```
┌─────────────────────────────────────────┐
│ 双歧杆菌属 Bifidobacterium ↑ │ ← 名称可点(弹出知识库), ↑红色(偏高)
│ 丰度 0.2973% | 正常范围 0.19-12.59 │
│ 人群水平 53% | 检出率 97.12% │
└─────────────────────────────────────────┘
```
- 菌名:可点击 → 弹出知识库(`itemType="bacteria"`)
- 丰度值:显示数值 + 正常范围
- 状态:通过菌名颜色+箭头体现,不在卡片上单独显示状态文字
- 人群水平/检出率:灰色小字辅助信息
### 7.3 编辑模式
可编辑字段:`丰度值(bacteriaValue)`、`状态(status)`
不可编辑:菌属名称、正常范围、人群水平、检出率
---
## 8. 食物推荐:gut-flora-foods-detail.vue
### 8.1 顶部筛选
- 分类筛选条(主食 / 蔬菜 / 水果 / 肉类 / 其它),滑动横向
- 排序:推荐指数降序(-X 高优 → +X 高优);用户可切换「仅看推荐」(score ≥ 5)
### 8.2 卡片结构
```
┌────────────────────────────────────┐
│ 大麦 推荐指数: +10 [主食] │
│ 蛋白12 | 脂肪2 | 碳水73 | 纤维17 │
│ 能量 1481KJ │
└────────────────────────────────────┘
```
食物无知识库需求(数据自包含),但名称可点击 → 视需求可未来接入。
### 8.3 编辑模式
可编辑字段:`推荐指数(score)`
---
## 9. 疾病风险:gut-flora-risks-detail.vue
### 9.1 布局
重要风险(注意/异常)置顶,其余按风险等级排序。
### 9.2 卡片结构
```
┌────────────────────────────────────┐
│ 甲状腺疾病 ⚠ │ ← 名称可点弹出知识库
│ 风险值: 0.33 风险等级: [注意] │
└────────────────────────────────────┘
```
风险等级颜色:低风险→绿、注意→黄/⚠、异常→红
疾病名称可点击 → 弹出知识库(`itemType="disease"`)
### 9.3 编辑模式
可编辑字段:`风险值(riskValue)`、`风险等级(riskLevel picker)`
---
## 10. 知识库架构
### 10.1 数据库表
```sql
CREATE TABLE IF NOT EXISTS health_knowledge_base (
id BIGINT AUTO_INCREMENT PRIMARY KEY,
item_type VARCHAR(50) NOT NULL COMMENT '类型: bacteria/nutrient/indicator/vitamin/amino_acid/disease',
item_name VARCHAR(200) NOT NULL COMMENT '项目名称(精确匹配)',
category VARCHAR(100) COMMENT '分类(如 有益菌/有害菌)',
normal_range VARCHAR(200) COMMENT '正常范围参考',
description TEXT COMMENT '详细说明',
suggestion TEXT COMMENT '相关建议(如补充来源)',
source VARCHAR(100) COMMENT '数据来源',
created_at DATETIME,
updated_at DATETIME,
UNIQUE KEY uk_type_name (item_type, item_name),
INDEX idx_type (item_type)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='健康知识库 - 菌属/营养素/指标说明';
```
### 10.2 初次数据填充
参考 JSON 文件中所有菌属的 `说明` 字段、指标的 `健康状况`/参考范围等,一次性导入 `health_knowledge_base`。
### 10.3 API
```
POST /api/health/knowledge/query
body: { itemType: "bacteria", itemName: "双歧杆菌属 Bifidobacterium" }
→ { code: 200, data: { id, itemType, itemName, category, normalRange, description, suggestion } }
POST /api/health/knowledge/batch-query
body: { queries: [{ itemType, itemName }, ...] }
→ { code: 200, data: { "bacteria:双歧杆菌属 Bifidobacterium": {...}, ... } }
```
批查询用于首次加载时预取当前页面所有项目的知识库。单查询用于点击时按需加载。
---
## 11. 公共交互规范
### 11.1 编辑状态机
```
查看模式 ─[点击编辑]→ 编辑模式 ─[点击取消]→ 查看模式 (丢弃改动)
─[点击保存]→ POST /api/health/report/edit → toast → 重新加载 → 查看模式
```
### 11.2 编辑按钮触发位置
- 主页:右下 FAB(查看模式)
- 详情页:顶部导航栏右侧文字按钮「编辑」
### 11.3 数据流
```
进入页面 → onLoad({ reportId }) → loadReportDetail()
GET /api/health/report/detail → 缓存于 this.reportData
点击编辑 → 深拷贝 this.reportData → this.editData → 进入编辑模式
点击取消 → 丢弃 this.editData → 回查看模式
点击保存 →
POST /api/health/report/edit { reportId, payload: { indicators, gutFlora, diseaseRisks, foods }, subjectId }
→ 200 → toast "已保存" → loadReportDetail() 重新拉 → 查看模式
```
### 11.4 知识库弹出框数据流
```
首次加载 → 遍历报告的 indicators/gutFlora,
收集所有不重复的 (itemType, itemName) 对
→ POST /api/health/knowledge/batch-query → 缓存入 this.knowledgeMap
→ 前端 直接从缓存取
点击名称 → if (cache[type+name]) → 直接显示
else → POST /api/health/knowledge/query → 显示并加入缓存
```
### 11.5 mini-program 限制
- 禁可选链 `?.`,全部用 `&&` 短路
- 禁 CSS Grid,全部 flex
- Vue 2 Options API
- 状态类徽章用 `:class="'status-' + item.status"` 内联
---
## 12. 数据契约
### 12.1 GET /api/health/report/detail — 后端已有(不变)
```json
{
"code": 200,
"data": {
"report": { "id":..., "personName":"某人", "overallScore":57, "gutHealthScore":76, ... },
"indicators": [
{ "category":"营养", "indicatorName":"碳水化合物", "indicatorValue":"96", "status":"正常", "refRange":"..." },
{ "category":"氨基酸", "indicatorName":"胱氨酸", "indicatorValue":"86", "status":"正常", "refRange":"..." },
{ "category":"维生素", "indicatorName":"维生素B1", "indicatorValue":"2", "status":"缺乏", "refRange":"..." },
...
],
"gutFlora": [
{ "bacteriaName":"双歧杆菌属 Bifidobacterium", "bacteriaValue":"0.2973", "category":"core", "status":"偏低", "normalRange":"0.19-12.59", "populationLevel":"53%", "detectionRate":"97.12%" },
...
],
"diseaseRisks": [
{ "diseaseName":"甲状腺疾病", "riskValue":"0.33", "riskLevel":"注意" }
]
}
}
```
### 12.2 POST /api/health/report/edit — 新增
```json
{
"reportId": 123,
"payload": {
"indicators": [...], // 编辑后的完整 list
"gutFlora": [...], // 编辑后的完整 list
"probioticSpecies": [...], // 编辑后的菌门 list
"foods": [...], // 编辑后的食物 list
"diseaseRisks": [...] // 编辑后的疾病风险 list
},
"subjectId": 456
}
```
### 12.3 POST /api/health/knowledge/query — 新增
```json
// 请求
{ "itemType": "bacteria", "itemName": "双歧杆菌属 Bifidobacterium" }
// 响应
{ "code":200, "data": {
"id":1, "itemType":"bacteria", "itemName":"双歧杆菌属 Bifidobacterium",
"category":"有益菌",
"normalRange":"0.19-14.59",
"description":"最重要的益生菌,参与肠道免疫屏障维护...",
"suggestion":"补充来源:酸奶、开菲尔等发酵食品"
}}
```
### 12.4 POST /api/health/knowledge/batch-query — 新增
```json
// 请求
{ "queries": [
{"itemType":"bacteria","itemName":"双歧杆菌属 Bifidobacterium"},
{"itemType":"vitamin","itemName":"维生素B1"}
]}
// 响应
{ "code":200, "data": {
"bacteria:双歧杆菌属 Bifidobacterium": { ... },
"vitamin:维生素B1": { ... }
}}
```
---
## 13. 后端需补充
| 改动 | 位置 | 方法 | 说明 |
|------|------|------|------|
| 新建 Entity | `entity/HealthKnowledgeBase.java` | — | @TableName("health_knowledge_base") |
| 新建 Mapper | `mapper/HealthKnowledgeBaseMapper.java` | — | MyBatis-Plus BaseMapper |
| 新建 Service | `service/HealthKnowledgeBaseService.java` | `query(itemType, itemName)`, `batchQuery(List)` | 查知识库 |
| 新建 Controller | `controller/HealthKnowledgeBaseController.java` | `POST /api/health/knowledge/query`, `POST /api/health/knowledge/batch-query` | 知识库 API |
| 编辑 API | `controller/HealthReportController.java` | `POST /api/health/report/edit` | 编辑已发布报告 |
| 编辑 Service | `service/HealthReportService.java` | `updateReportFromPayload(reportId, payload, subjectId)` | 抹写并刷新 7 维 |
| 数据库迁移 | `config/DatabaseInitializer.java` | 创建 `health_knowledge_base` 表 + 导入参考 JSON 的说明数据 | 迁移 N+1 |
| schema.sql | `resources/schema.sql` | 追加新表 DDL | 同步 |
### 13.1 KnowledgeBaseService 方法签名
```java
public HealthKnowledgeBase query(String itemType, String itemName) {
return mapper.selectOne(
new LambdaQueryWrapper()
.eq(HealthKnowledgeBase::getItemType, itemType)
.eq(HealthKnowledgeBase::getItemName, itemName)
);
}
public Map batchQuery(List queries) {
// 按 (type, name) 批量查询
}
```
---
## 14. 验收标准
### 14.1 主页(gut-flora-detail.vue)
- [ ] 长 scroll 顺畅渲染 >= 1000rpx 高度
- [ ] 报告头部显示姓名/年龄/性别/编号/日期
- [ ] 健康评分圆环绘制(11 项可滚动横向)
- [ ] 4 个快速跳转入口可见,且能跳到对应详情页
- [ ] 肠道功能 / 营养指标 双手风琴,能折叠/展开
- [ ] 每个指标名称可点击 → 弹出知识库弹出框
- [ ] 异常值:偏高/过多 → 红色 + ↑;偏低/缺乏/不足 → 琥珀色 + ↓
- [ ] 正常值:默认色无箭头
- [ ] 右下 FAB「编辑」按钮可见
- [ ] 点击「编辑」后 input/picker 可用,「保存」固定底部出现
- [ ] 保存成功后正确返回查看模式 + toast 提示
### 14.2 菌群详情(gut-flora-species-detail.vue)
- [ ] 12 分类 Tab 正常切换
- [ ] 每个 Tab 显示对应菌属列表
- [ ] 卡片显示菌名(可点弹知识库)、丰度、正常范围、人群水平、检出率
- [ ] 无内嵌说明文字
- [ ] 菌名带颜色+箭头指示偏高/偏低
- [ ] 编辑模式可改丰度/状态,保存后写入
### 14.3 食物推荐(gut-flora-foods-detail.vue)
- [ ] 分类筛选条切换生效
- [ ] 列表按推荐指数降序
- [ ] 卡片显示名称/分类/推荐指数/营养数据
- [ ] 编辑模式可改推荐指数
### 14.4 疾病风险(gut-flora-risks-detail.vue)
- [ ] 重要风险(注意/异常)置顶
- [ ] 风险等级用颜色徽章:低风险=绿/注意=黄+⚠/异常=红
- [ ] 疾病名称可点击弹知识库
- [ ] 编辑模式可改风险值/风险等级
### 14.5 知识库
- [ ] 后端 `batch-query` 支持一次预取全部知识库条目
- [ ] 弹出框正确显示类型/说明/建议
- [ ] 数据库迁移幂等可重复运行
- [ ] 参考 JSON 说明数据正确导入
### 14.6 E2E 测试
- [ ] `tests/e2e/flora-microbiome-flow.spec.js` 现有场景通过
- [ ] 新增 `.kb-link`、`.knowledge-popup` 选择器覆盖知识库交互
---
## 15. 文件变更清单
| 文件 | 操作 | 内容 |
|------|------|------|
| `cfc-frontend/pages/health/gut-flora-detail.vue` | 重写 | 长 scroll + 手风琴 + 知识库弹框 + 颜色箭头 + 双模式 |
| `cfc-frontend/pages/health/gut-flora-species-detail.vue` | 新建 | 12 Tab + 卡片(无说明) + 颜色箭头 + 知识库弹框 |
| `cfc-frontend/pages/health/gut-flora-foods-detail.vue` | 新建 | 分类筛选 + 卡片 + 编辑 |
| `cfc-frontend/pages/health/gut-flora-risks-detail.vue` | 新建 | 重要置顶 + 卡片 + 知识库弹框 |
| `cfc-frontend/components/health-knowledge-popup.vue` | 新建 | 通用知识库弹出框组件 |
| `cfc-frontend/pages.json` | 改 | 注册 3 个新页面路径 |
| `cfc-frontend/utils/api.js` | 改 | 新增 `editHealthReport`、`queryKnowledge`、`batchQueryKnowledge` |
| `cfc-backend/.../entity/HealthKnowledgeBase.java` | 新建 | 知识库实体 |
| `cfc-backend/.../mapper/HealthKnowledgeBaseMapper.java` | 新建 | 知识库 Mapper |
| `cfc-backend/.../service/HealthKnowledgeBaseService.java` | 新建 | 知识库 Service |
| `cfc-backend/.../controller/HealthKnowledgeBaseController.java` | 新建 | 知识库 API |
| `cfc-backend/.../controller/HealthReportController.java` | 改 | 新增 `POST /api/health/report/edit` |
| `cfc-backend/.../service/HealthReportService.java` | 改 | 新增 `updateReportFromPayload` |
| `cfc-backend/.../config/DatabaseInitializer.java` | 改 | 创建 health_knowledge_base 表 + 导入数据 |
| `cfc-backend/.../resources/schema.sql` | 改 | 追加 health_knowledge_base DDL |
| `tests/e2e/flora-microbiome-flow.spec.js` | 检查/更新 | 适配新选择器 |
---
## 16. 风险与权衡
| 风险 | 缓解 |
|------|------|
| 200+ 菌属首次加载时 batch-query 知识库可能慢 | 并行请求;知识库表小(<500 行),加索引后毫秒级 |
| 知识库数据导入工作量 | 参考 JSON 已有完整的 `说明` 字段,可用脚本批量入库 |
| 编辑时大批量数据上传慢 | 前端只提交被改过的索引列表 |
| 编辑后是否破坏 7 维评分 | 编辑路径同样调用 `refreshFromGutReport` 刷新 |
| mini-program 真机性能(200+ 卡片) | `v-if` 分组懒加载 |
---
## 17. 实现顺序
1. 后端:`HealthKnowledgeBase` 表迁移 + 实体/Mapper/Service/Controller → `mvn clean compile`
2. 后端:`POST /api/health/report/edit` + `updateReportFromPayload` → `mvn clean compile`
3. 导入参考 JSON 的说明数据到 `health_knowledge_base`
4. 前端:`components/health-knowledge-popup.vue` 通用弹框组件
5. 前端:新建 `gut-flora-foods-detail.vue`(最简单)→ 验证编辑流
6. 前端:新建 `gut-flora-risks-detail.vue` + 知识库弹框
7. 前端:新建 `gut-flora-species-detail.vue` + 12 Tab + 颜色箭头 + 知识库弹框
8. 前端:重写 `gut-flora-detail.vue`(手风琴 + 指标知识库 + 颜色箭头 + 双模式)
9. 更新 `pages.json` + `utils/api.js`
10. 跑 `tests/e2e/flora-microbiome-flow.spec.js` 验证
11. 微信开发者工具手动验证关键操作