# 如何将实验室结果导入 FHIR 记录

> 教程：将实验室报告以 CSV 和 HL7 v2 ORU^R01 格式导入 FHIR R4 Observations，包含 LOINC 代码和参考范围，处理未映射的标记和重新发送的报告，并追溯每项结果的来源实验室。

Source: https://developers.anpheros.com/zh/guides/import-lab-results-fhir

**本教程将以 CSV 文件和 HL7 v2 ORU^R01 消息形式处理实验室报告，分别通过一个请求将其导入患者的 HL7 FHIR R4 记录，并展示您获得的结果：包含 LOINC 代码、参考范围和出处的实验室 `Observation` 资源。** 它还涵盖了每个实验室集成都会遇到的两个问题：无法自动映射的标记和重复发送的报告。所有操作均在免费沙盒上使用合成患者进行。

## 为什么实验室结果难以存储

实验室报告看起来很简单：一个标记、一个值、一个单位、一个参考范围、一个日期。实际上，每个实验室都有自己的标记命名方式（“Hemoglobina glicozilata”、“HbA1c”、“Glycated haemoglobin”），使用逗号或点作为小数点，将范围写成 `4,0-5,6`、`<5` 或 `>3.5`，并在出现问题时重新发送同一份报告。如果将这些结果存储为自由文本，就无法随时间进行比较、绘制图表、与其他应用程序共享，也无法自信地提供给 AI 模型。

FHIR 记录将每个结果存储为一个 `Observation`，包含 LOINC 代码、UCUM 单位、值、参考范围和日期，并在 `Provenance` 资源中保留发送者信息。 [实验室连接器](https://developers.anpheros.com/zh/guides/lab-connector) 会为您完成此转换。

```
 lab report (CSV, HL7 v2, JSON)
        │  POST /v1/patients/{id}/labs/import
        ▼
 ┌──────────────────────────────────────────────┐
 │ parse rows → map marker to LOINC → parse     │
 │ value, unit, range → stable id per row       │
 └──────────────────────────────────────────────┘
        │
        ▼
 Observation (category laboratory) + Provenance (author_type import, source system, report id)
        │
        ├─► the patient's app and every app they consented to
        └─► webhooks: resource.created per Observation
```

## 开始之前

您需要从 [platform.anpheros.com/dashboard](https://platform.anpheros.com/dashboard/) 获取一个沙盒密钥 (`sk_test_…`)（**获取沙盒密钥**）。示例使用了 `curl`；[SDK](https://developers.anpheros.com/zh/guides/sdks) 提供了相同的调用 (`labs.importCsv`, `labs.importHl7`, `labs.importItems`)。

```bash
export BASE=https://platform.anpheros.com
export KEY=sk_test_…
# Elena Ionescu, a synthetic patient with type 2 diabetes
export PID=$(curl -s "$BASE/fhir/R4/Patient?identifier=https://anpheros.com/fhir/sid/sandbox-persona|p02" \
  -H "Authorization: Bearer $KEY" | jq -r '.entry[0].resource.id')
```

## 步骤 1：导入 CSV 报告

罗马尼亚实验室可能会这样导出报告：分号、小数点逗号、罗马尼亚语列名和日期，如 `DD.MM.YYYY`。连接器可识别罗马尼亚语和英语列名。

```bash
cat > report.csv <<'EOF'
Analiza;Rezultat;UM;Interval de referinta;Data
Hemoglobina glicozilata (HbA1c);6,9;%;4,0-5,6;01.10.2026
Glicemie;131;mg/dL;70-100;01.10.2026
TSH;2,1;mUI/L;0,4-4,0;01.10.2026
Marker foarte rar;12;U/L;0-20;01.10.2026
EOF

curl -X POST "$BASE/v1/patients/$PID/labs/import" -H "Authorization: Bearer $KEY" \
     -H "Content-Type: text/csv" -H "X-Anpheros-Source-System: labx" \
     -H "Idempotency-Key: report-2026-10-01-elena" --data-binary @report.csv
```

响应 (`201`)：

```json
{"created": 4, "skipped": 0, "unmapped": ["Marker foarte rar"], "warnings": [],
 "observations": [
  {"id": "ff0bbb44-…", "marker": "Hemoglobina glicozilata (HbA1c)", "code": "4548-4", "system": "http://loinc.org", "value": 6.9, "unit": "%", "date": "2026-10-01"},
  {"id": "ebe5522f-…", "marker": "Glicemie", "code": "2345-7", "system": "http://loinc.org", "value": 131.0, "unit": "mg/dL", "date": "2026-10-01"},
  {"id": "bace44a8-…", "marker": "TSH", "code": "3016-3", "system": "http://loinc.org", "value": 2.1, "unit": "mUI/L", "date": "2026-10-01"},
  {"id": "26fd2270-…", "marker": "Marker foarte rar", "code": "marker_foarte_rar", "system": "urn:anpheros:lab-code", "value": 12.0, "unit": "U/L", "date": "2026-10-01"}]}
```

HbA1c、葡萄糖和 TSH 已根据其名称映射到 LOINC。小数点逗号已转换为数字，范围已转换为 `referenceRange`。一行数据返回到 `unmapped`。它仍然存储在实验室自己的代码 (`urn:anpheros:lab-code`) 下，并包含报告中的确切文本，因此不会丢失任何内容。

## 步骤 2：处理未映射的标记

有些名称需要做出决定。“Glicemie”（血糖）是一个很好的例子：LOINC 有一个代码用于血清或血浆中的葡萄糖（`2345-7`，在实验室采集的静脉样本），另一个代码用于全血中的葡萄糖（`2339-0`，例如指尖采血）。在实验室报告中，单独的“Glicemie”被映射到血清或血浆。名称中包含“capilar”、“capillary”或“sânge integral”的，则映射到全血：

```json
{"created": 1, "skipped": 0, "unmapped": [], "warnings": [],
 "observations": [{"id": "00480a6d-…", "marker": "Glicemie capilara", "code": "2339-0", "system": "http://loinc.org", "value": 140.0, "unit": "mg/dL", "date": "2026-10-02"}]}
```

对于连接器无法识别的标记，请查找代码：

```bash
curl "$BASE/v1/terminology/loinc?q=glucose" -H "Authorization: Bearer $KEY"
```

```json
{"data": [
  {"system": "http://loinc.org", "code": "2339-0", "display": "Glucose [Mass/volume] in Blood", "display_ro": "Glicemie (sânge)", "category": "laboratory", "unit": "mg/dL"},
  {"system": "http://loinc.org", "code": "2345-7", "display": "Glucose [Mass/volume] in Serum or Plasma", "display_ro": "Glicemie (ser)", "category": "laboratory", "unit": "mg/dL"}],
 "total": 2}
```

然后将代码发送到 `LOINC` 列。报告中的代码始终优先于名称。请在您这边为每个实验室保留该映射，并将其添加到该实验室的每份报告中：

```
Analiza;Rezultat;UM;Interval de referinta;Data;LOINC
Glicemie;99;mg/dL;70-100;04.10.2026;2339-0
```

LOINC 完全不涵盖的标记，例如虚构的“Marker foarte rar”，可以保留在实验室代码下。它们会显示给患者并包含在记录中。它们不能与其他实验室的结果进行比较。

## 步骤 3：发送相同的报告两次

实验室会重新发送报告。每一行都会生成一个稳定的标识符，该标识符由报告 ID、代码、日期和值构成，因此第二次导入相同的报告不会产生任何新内容：

```json
{"created": 0, "skipped": 4, "unmapped": ["Marker foarte rar"], "warnings": [], "observations": []}
```

已更改的行（例如，修正后的值）将作为新结果导入。`Idempotency-Key` 标头提供了第二个保证：使用相同密钥的网络重试将返回不变的第一个响应。

## 步骤 4：导入 HL7 v2 ORU^R01 消息

大多数实验室信息系统都使用 HL7 v2。直接发送消息（ER7 文本，段落以 CR 或 LF 分隔）：

```
MSH|^~\&|LABX|LAB1|ANPHEROS|EHR|202610010930||ORU^R01|MSG00077|P|2.5.1
PID|1||12345||Ionescu^Elena||19850903|F
OBR|1||R-77|24331-1^Lipid panel^LN|||202610010800
OBX|1|NM|2093-3^Cholesterol [Mass/volume] in Serum or Plasma^LN||212|mg/dL|<200|H|||F|||202610010800
OBX|2|NM|2085-9^HDL Cholesterol^LN||52|mg/dL|>40|N|||F|||202610010800
```

```bash
curl -X POST "$BASE/v1/patients/$PID/labs/import" -H "Authorization: Bearer $KEY" \
     -H "Content-Type: x-application/hl7-v2+er7" --data-binary @oru.hl7
```

```json
{"created": 2, "skipped": 0, "unmapped": [], "warnings": [],
 "observations": [
  {"id": "b562045b-…", "marker": "Cholesterol [Mass/volume] in Serum or Plasma", "code": "2093-3", "system": "http://loinc.org", "value": 212.0, "unit": "mg/dL", "date": "2026-10-01T08:00:00Z"},
  {"id": "9b3274e4-…", "marker": "HDL Cholesterol", "code": "2085-9", "system": "http://loinc.org", "value": 52.0, "unit": "mg/dL", "date": "2026-10-01T08:00:00Z"}]}
```

`OBX-3` 使用 `LN` 编码系统，直接作为 LOINC 使用。`OBX-7` 成为参考范围，而 `OBX-8`（`H`、`N`）则作为解释。`OBR-3`（`R-77`）将作为 provenance 中的报告 ID 保留。患者是 URL 中的那位：`PID` 段不用于查找患者，因此错误的 `PID` 无法将结果附加给其他人。

已持有解析后的结果？发送 JSON：`{"date": "2026-10-01", "origin": "report-77", "items": [{"marker": "Ferritin", "value": 38, "unit": "ng/mL", "ref_low": 15, "ref_high": 150}]}`。铁蛋白映射到 LOINC `2276-4`。

## 第 5 步：以 FHIR 格式读取结果

```bash
curl "$BASE/fhir/R4/Observation?patient=$PID&code=http://loinc.org|4548-4&_sort=-date&_count=1" \
     -H "Authorization: Bearer $KEY"
```

导入的 HbA1c 存储格式如下：

```json
{
  "resourceType": "Observation",
  "id": "62b1b0c0-…",
  "meta": {"versionId": "1", "lastUpdated": "2026-10-12T20:05:57.011Z"},
  "identifier": [{"system": "urn:anpheros:lab-import", "value": "c52d3cd6449291d34f6bef1516d0ac05"}],
  "status": "final",
  "category": [{"coding": [{"system": "http://terminology.hl7.org/CodeSystem/observation-category", "code": "laboratory"}]}],
  "code": {"coding": [{"system": "http://loinc.org", "code": "4548-4", "display": "Hemoglobin A1c/Hemoglobin.total in Blood"}],
           "text": "Hemoglobina glicozilata (HbA1c)"},
  "subject": {"reference": "Patient/…"},
  "effectiveDateTime": "2026-10-01",
  "valueQuantity": {"value": 6.9, "unit": "%"},
  "referenceRange": [{"low": {"value": 4.0, "unit": "%"}, "high": {"value": 5.6, "unit": "%"}}]
}
```

LOINC 显示是标准的英文名称。`code.text` 保留了实验室自己的措辞，因此患者仍然可以看到纸质报告上的内容。有关资源和搜索的更多信息，请参阅 [FHIR 平台](https://developers.anpheros.com/zh/guides/fhir) 指南和 [FHIR 代码系统](https://developers.anpheros.com/zh/guides/fhir-code-systems)。

## 步骤 6：检查发送者

```bash
curl "$BASE/v1/patients/$PID/provenance/Observation/62b1b0c0-…" -H "Authorization: Bearer $KEY"
```

```json
{"data": [{"version": 1, "activity": "CREATE", "recorded": "2026-10-12T20:05:57.011000Z",
           "author_type": "import", "author": "proj_…", "source_system": "labx", "origin_id": null,
           "fhir": "Provenance/f15c4fee-…"}], "total": 1}
```

`author_type: import` 和 `source_system: labx` 保持原值。当 AI 应用程序稍后通过 [context API](https://developers.anpheros.com/zh/guides/llm-healthcare-data) 读取此结果时，它会被标记为 `[import/labx]`，以便模型能够区分实验室结果和患者输入的数值。

## 后续操作

- 患者将在其应用程序中看到结果。任何他们已授权的应用程序都可以读取这些结果，但受限于其权限范围（[同意与访问模型](https://developers.anpheros.com/zh/guides/consent)）。
- 每次生成 Observation 时会触发一个 `resource.created` [Webhook](https://developers.anpheros.com/zh/guides/webhooks)，以便诊所仪表板或 AI 摘要无需轮询即可更新。
- `POST /fhir/R4/Observation/$validate?profile=eu-lab` 报告了结果如何符合 HL7 Europe 实验室报告配置文件的要求。
- 每请求最多 500 行；限制请参见 [限制与速率限制](https://developers.anpheros.com/zh/guides/limits)。

## 常见问题解答

### 哪些实验室报告格式可以导入 FHIR？
CSV（带标题行，接受逗号、分号或制表符分隔，接受逗号作为小数点），HL7 v2 ORU^R01 消息和 JSON。PDF 报告可以存储为文档；从中提取的值会指向该文档。

### 没有 LOINC 代码的标记会怎样？
它们将存储在实验室自己的代码下，并带有报告中的确切文本，列在 `unmapped` 中。为该实验室添加 LOINC 列，它们将被映射。报告中的代码始终优先于名称。

### 重新发送报告安全吗？
是的。每一行都有一个由报告、代码、日期和值构建的稳定标识符，因此已导入的行将被跳过；已更改的行将被导入为新结果。

### 实验室可以导入任何患者的结果吗？
不可以。实验室只能导入其项目创建的患者，或者其记录已通过 OAuth 与其共享的患者。其他患者对它来说不存在（`404`）。

## 相关

- [Laboratory results API](https://developers.anpheros.com/zh/guides/lab-results-api)：HL7 v2 和 FHIR 并列，以及一个结果必须包含的内容
- [Lab connector](https://developers.anpheros.com/zh/guides/lab-connector)：每个列名、HL7 字段和响应字段
- [Healthcare data interoperability](https://developers.anpheros.com/zh/guides/interoperability)：为什么代码和来源使交换的数据可用
- [Healthcare integrations](https://developers.anpheros.com/zh/guides/healthcare-integrations)：诊所、实验室、设备和第三方应用程序
- [Medical data API](https://developers.anpheros.com/zh/guides/medical-data-api)：编写单个观察结果、病症和药物
- [How to build an AI healthcare app with a FHIR backend](https://developers.anpheros.com/zh/guides/build-ai-healthcare-app)：在 AI 回答中使用这些结果
