常见疾病查询:科目树 → 关键字 → 明细 三步入诊全链路设计
# 常见疾病查询:科目树 → 关键字 → 明细 三步入诊全链路设计
> 接口:常见疾病查询(apiCode=546)· 免费 · 请求方式 POST/GET · 返回格式 JSON · 适用人群:全栈工程师、医疗产品 · 阅读时间:约 8 分钟
## 核心要点
- 三个接入点天然构成「**科目树(546-1) → 关键字检索(546-2) → 疾病明细(546-3)**」链路,`id` 是串联它们的主键。
- 数据表只需存三把键:`typeId`/`subTypeId`(科室)、`diseaseId`(来自 546-2),即可还原导诊与病种展示。
- 链路是**同步**的,但每一步可独立缓存:科目树几乎静态,明细按 `id` 缓存,检索结果可按 query 短缓存。
## Why:单个接口解决不了"导诊"
真实导诊场景是:「用户说'我头晕、血压高' → 系统推荐'心血管内科' → 再展示'高血压'的症状/治疗」。这恰好对应:
1. 科目树(546-1)给出"有哪些科"——地图。
2. 关键字检索(546-2)把"高血压"映射到科室 `typeId=3`、子科室 `subTypeId=0304`,并给出疾病 `id`。
3. 明细(546-3)用 `id` 取出症状/诊断/治疗/预防,给用户看"这个病怎么回事"。
把三步串起来,才是产品能用的能力,而不是三个孤立接口。
## What:链路与依赖
```
用户症状/病名
│
▼
[546-2 关键字查询疾病] ← 可选 typeId/subTypeId 限定科室、key 关键词、page 分页
│ 返回 contentlist[],每项含 id / name / typeId / subTypeId
▼
取某项 id ──► [546-3 取得疾病明细] 返回 item[],含 tagList(症状/诊断/治疗/预防)、alias
▲
│ (科目树用于"按科室浏览"入口)
[546-1 查询疾病科目] ── 返回 list[],typeId/subId 父子结构
```
依赖关系:546-3 的 `id` **必须**来自 546-2 的返回,不能自造。
## How:实现一个最小导诊服务
### 数据表设计(关系示意)
```sql
-- 科室字典(来自 546-1,几乎静态,可一次性落库)
CREATE TABLE dept (
type_id VARCHAR(8) PRIMARY KEY, -- 一级科目 id
type_name VARCHAR(32),
sub_id VARCHAR(8), -- 二级子科目 id
sub_name VARCHAR(32)
);
-- 用户检索/收藏的疾病(id 来自 546-2)
CREATE TABLE user_disease (
disease_id VARCHAR(32) PRIMARY KEY, -- 546-2 返回的 id
name VARCHAR(64),
type_id VARCHAR(8), -- 推荐科室(一级)
sub_type_id VARCHAR(8) -- 推荐科室(二级)
);
```
### Python:封装三步入诊
```python
def triage(keyword, type_id=None, sub_type_id=None):
"""输入症状/病名,返回推荐科室 + 首个匹配疾病的明细。"""
hits = call("546-2", key=keyword, typeId=type_id or "", subTypeId=sub_type_id or "", page="1")
if not hits.get("contentlist"):
return None # 没搜到,建议人工/兜底科室
top = hits["contentlist"][0]
detail = call("546-3", id=top["id"])
item = (detail.get("item") or [{}])[0]
tags = {t["name"]: t["content"] for t in item.get("tagList", [])}
return {
"recommend_dept": f"{top.get('typeName')}/{top.get('subTypeName')}",
"disease": top["name"],
"alias": item.get("alias", ""),
"symptom": tags.get("症状", ""),
"treatment": tags.get("治疗", ""),
}
print(triage("高血压", type_id="3"))
```
### cURL(分步)
```bash
# 步骤2:检索
curl -X POST "https://route.showapi.com/546-2?appKey=YOUR_APPKEY" \
-H "content-type: application/x-www-form-urlencoded" \
--data-urlencode "key=高血压" --data-urlencode "page=1"
# 步骤3:明细(用上一步的 id)
curl -X POST "https://route.showapi.com/546-3?appKey=YOUR_APPKEY" \
-H "content-type: application/x-www-form-urlencoded" \
--data-urlencode "id=<疾病id>"
```
### Node.js(fetch)
```javascript
async function triage(keyword, typeId) {
const hits = await call("546-2", { key: keyword, typeId: typeId || "", page: "1" });
const top = (hits.contentlist || [])[0];
if (!top) return null;
const detail = await call("546-3", { id: top.id });
const it = (detail.item || [])[0];
const tags = Object.fromEntries((it?.tagList || []).map(t => [t.name, t.content]));
return { recommendDept: `${top.typeName}/${top.subTypeName}`, disease: top.name, symptom: tags["症状"] };
}
```
## 返回示例与解析
`546-2` 返回 `contentlist[]` 中每项含 `typeId`/`subTypeId`/`typeName`/`subTypeName`,可直接作为"推荐科室"展示;`546-3` 的 `tagList` 取出后按 `name`(症状/诊断/治疗/预防)分组渲染即可。
## 进阶 / 边界
- **科目树静态化**:546-1 返回的是医院科室标准分类,变化极少,建议首次拉取后落库/缓存(见[缓存策略](https://www.showapi.com/guides/disease-query-cache-546)),别每次实时调。
- **检索可限定科室**:`typeId`/`subTypeId` 能缩小范围,适合"在某科室下找病"的浏览式交互。
- **无结果兜底**:546-2 可能空返回,UI 上要给出"未匹配到,请描述更具体的症状"之类的兜底,而非报错。
- **非诊疗免责**:明细仅供参考,UI 必须标注"不能替代医生诊断"。
## FAQ
**Q1:546-3 的 id 可以自己生成吗?**
A:不可以。`id` 必须由 546-2 关键字查询返回,自造的 id 查不到明细。
**Q2:科目树需要每次都调吗?**
A:不需要。546-1 几乎静态,落库或缓存一次即可,后续用本地数据。
**Q3:检索没结果怎么办?**
A:先确认关键词是否过细,可去掉 `key` 只用 `typeId` 浏览;仍无果则提示用户补充症状描述。
**Q4:三步能合成一次请求吗?**
A:不能。接口是三个独立接入点,需按顺序调用,且 546-3 依赖 546-2 的 `id`。
## 相关能力 / 下一步阅读
- [常见疾病查询:关键字检索疾病(546-2 的 typeId/subTypeId/key/page 用法)](https://www.showapi.com/guides/disease-query-keyword-search-546)
- [常见疾病查询:取得疾病明细并解析症状/诊断/治疗/预防(546-3 的 tagList)](https://www.showapi.com/guides/disease-query-detail-546)
- [医院导诊/挂号系统如何集成常见疾病查询?从症状到科室推荐](https://www.showapi.com/guides/disease-query-triage-546)
- **本系列共 12 篇**:查看[常见疾病查询指南总目录](https://www.showapi.com/guides/disease-query-guides-546)