要了解 **FHIR Patient data** 並設計輸入網頁,我建議分兩個層次來看:
---
## 一、FHIR Patient Resource 基礎
FHIR (**Fast Healthcare Interoperability Resources**) 是 HL7 制定的標準,用於醫療資料交換。
其中 **Patient resource** 用來描述病患的基本資料。
### 1. Patient 主要欄位(常用)
以下是最常會用到的欄位(FHIR JSON 格式):
```json
{
"resourceType": "Patient",
"id": "example",
"identifier": [
{
"system": "http://hospital.org/patient-id",
"value": "1234567890"
}
],
"name": [
{
"use": "official",
"family": "Wang",
"given": ["Chieh-An"]
}
],
"gender": "male",
"birthDate": "1995-08-19",
"telecom": [
{
"system": "phone",
"value": "0912345678",
"use": "mobile"
},
{
"system": "email",
"value": "test@example.com"
}
],
"address": [
{
"use": "home",
"line": ["台北市中正區某某路 100 號"],
"city": "Taipei",
"postalCode": "100"
}
]
}
```
👉 常見對應:
* **identifier** → 身分證號或病歷號
* **name** → 姓名(可有多個版本,例如官方/暱稱)
* **gender** → 性別
* **birthDate** → 生日
* **telecom** → 聯絡方式(電話、Email)
* **address** → 地址
FHIR 的結構有點「JSON 文件式」,所以資料可擴展、支援多值。
---
## 二、設計輸入網頁 (表單)
假設你要做一個簡單的輸入網頁,可以對應上述欄位,讓使用者輸入病患基本資料,最後轉換成 FHIR JSON。
### 1. 前端欄位設計
表單欄位建議如下:
* **身分證號 / 病歷號 (identifier)**
* **姓名 (name.family, name.given)**
* **性別 (gender: male/female/other/unknown)**
* **生日 (birthDate, date picker)**
* **電話 (telecom\[phone])**
* **Email (telecom\[email])**
* **住址 (address.line, address.city, postalCode)**
### 2. HTML 表單範例
這裡示範簡單 HTML + JavaScript:
```html
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<title>FHIR Patient 輸入表單</title>
</head>
<body>
<h2>病患資料輸入</h2>
<form id="patientForm">
<label>病歷號/身分證號: <input type="text" id="identifier"></label><br><br>
<label>姓氏: <input type="text" id="family"></label><br>
<label>名字: <input type="text" id="given"></label><br><br>
<label>性別:
<select id="gender">
<option value="male">男</option>
<option value="female">女</option>
<option value="other">其他</option>
<option value="unknown">未知</option>
</select>
</label><br><br>
<label>生日: <input type="date" id="birthDate"></label><br><br>
<label>電話: <input type="text" id="phone"></label><br>
<label>Email: <input type="email" id="email"></label><br><br>
<label>住址: <input type="text" id="address"></label><br>
<label>城市: <input type="text" id="city"></label><br>
<label>郵遞區號: <input type="text" id="postalCode"></label><br><br>
<button type="button" onclick="generateFHIR()">轉換為FHIR JSON</button>
</form>
<h3>FHIR JSON 結果</h3>
<pre id="output"></pre>
<script>
function generateFHIR() {
const patient = {
resourceType: "Patient",
identifier: [
{
system: "http://hospital.org/patient-id",
value: document.getElementById("identifier").value
}
],
name: [
{
use: "official",
family: document.getElementById("family").value,
given: [document.getElementById("given").value]
}
],
gender: document.getElementById("gender").value,
birthDate: document.getElementById("birthDate").value,
telecom: [
{
system: "phone",
value: document.getElementById("phone").value,
use: "mobile"
},
{
system: "email",
value: document.getElementById("email").value
}
],
address: [
{
use: "home",
line: [document.getElementById("address").value],
city: document.getElementById("city").value,
postalCode: document.getElementById("postalCode").value
}
]
};
document.getElementById("output").textContent = JSON.stringify(patient, null, 2);
}
</script>
</body>
</html>
```
輸入資料後,點「轉換為FHIR JSON」就會生成一個符合 FHIR Patient resource 的 JSON。
---
✅ 建議流程:
1. 先理解 FHIR Patient 的資料模型
2. 設計表單 → 欄位與 FHIR 對應
3. 產生 JSON → 後端可直接存 DB 或透過 FHIR API 發送
---
要不要我幫你設計一個 **進階版本**(有驗證、防呆,例如必填檢查、格式檢查,並可直接送到 FHIR Server)?
太好了 👍
我們來做一個 **進階版 FHIR Patient 輸入網頁**,除了輸入 → 轉換成 JSON 外,還會加上 **必填欄位檢查**、**格式驗證**,並提供一個按鈕把資料送到 **FHIR Server**(例如 HAPI FHIR 測試伺服器)。
---
## 一、必填/防呆設計
* **identifier (病歷號/身分證號)** → 必填
* **family / given (姓名)** → 必填
* **gender** → 必填(預設 male/female)
* **birthDate** → 必填,且必須符合 `YYYY-MM-DD`
* **phone** → 格式檢查(只允許數字與 `+` 開頭)
* **email** → 格式檢查(用 HTML5 的 email type)
---
## 二、進階表單程式碼
這個網頁會:
1. 先檢查輸入格式
2. 若正確 → 產生 JSON
3. 可選擇送出到 HAPI FHIR Public Server
```html
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<title>FHIR Patient 輸入表單</title>
<style>
body { font-family: Arial, sans-serif; margin: 20px; }
label { display: block; margin-top: 10px; }
input, select { padding: 5px; width: 300px; }
button { margin-top: 15px; padding: 8px 12px; border: none; border-radius: 6px; background: #4CAF50; color: white; cursor: pointer; }
button:hover { background: #45a049; }
pre { background: #f4f4f4; padding: 10px; border-radius: 8px; }
.error { color: red; font-size: 0.9em; }
</style>
</head>
<body>
<h2>FHIR Patient 輸入表單</h2>
<form id="patientForm">
<label>病歷號/身分證號*:
<input type="text" id="identifier" required>
<span class="error" id="idError"></span>
</label>
<label>姓氏*:
<input type="text" id="family" required>
</label>
<label>名字*:
<input type="text" id="given" required>
</label>
<label>性別*:
<select id="gender" required>
<option value="">請選擇</option>
<option value="male">男</option>
<option value="female">女</option>
<option value="other">其他</option>
<option value="unknown">未知</option>
</select>
</label>
<label>生日*:
<input type="date" id="birthDate" required>
<span class="error" id="birthError"></span>
</label>
<label>電話:
<input type="text" id="phone" pattern="^\\+?[0-9]+$" placeholder="+886912345678">
<span class="error" id="phoneError"></span>
</label>
<label>Email:
<input type="email" id="email" placeholder="example@test.com">
</label>
<label>住址:
<input type="text" id="address">
</label>
<label>城市:
<input type="text" id="city">
</label>
<label>郵遞區號:
<input type="text" id="postalCode" pattern="^[0-9]{3,6}$">
</label>
<button type="button" onclick="generateFHIR()">產生 FHIR JSON</button>
<button type="button" onclick="sendFHIR()">送到 FHIR Server</button>
</form>
<h3>FHIR JSON 結果</h3>
<pre id="output"></pre>
<script>
let patientFHIR = null;
function validateForm() {
let valid = true;
// 驗證生日
const birthDate = document.getElementById("birthDate").value;
if (!/^\d{4}-\d{2}-\d{2}$/.test(birthDate)) {
document.getElementById("birthError").textContent = "生日格式必須是 YYYY-MM-DD";
valid = false;
} else {
document.getElementById("birthError").textContent = "";
}
// 驗證電話
const phone = document.getElementById("phone").value;
if (phone && !/^\+?[0-9]+$/.test(phone)) {
document.getElementById("phoneError").textContent = "電話只能包含數字或 +";
valid = false;
} else {
document.getElementById("phoneError").textContent = "";
}
return valid;
}
function generateFHIR() {
if (!validateForm()) return;
patientFHIR = {
resourceType: "Patient",
identifier: [
{
system: "http://hospital.org/patient-id",
value: document.getElementById("identifier").value
}
],
name: [
{
use: "official",
family: document.getElementById("family").value,
given: [document.getElementById("given").value]
}
],
gender: document.getElementById("gender").value,
birthDate: document.getElementById("birthDate").value,
telecom: [],
address: [
{
use: "home",
line: [document.getElementById("address").value],
city: document.getElementById("city").value,
postalCode: document.getElementById("postalCode").value
}
]
};
// 電話 & Email
const phone = document.getElementById("phone").value;
if (phone) patientFHIR.telecom.push({ system: "phone", value: phone, use: "mobile" });
const email = document.getElementById("email").value;
if (email) patientFHIR.telecom.push({ system: "email", value: email });
document.getElementById("output").textContent = JSON.stringify(patientFHIR, null, 2);
}
async function sendFHIR() {
if (!patientFHIR) {
alert("請先產生 FHIR JSON");
return;
}
try {
const response = await fetch("https://hapi.fhir.org/baseR4/Patient", {
method: "POST",
headers: {
"Content-Type": "application/fhir+json"
},
body: JSON.stringify(patientFHIR)
});
if (response.ok) {
const data = await response.json();
alert("已成功送出到 FHIR Server!\n新建 ID: " + data.id);
} else {
alert("送出失敗,HTTP 狀態: " + response.status);
}
} catch (err) {
alert("錯誤: " + err.message);
}
}
</script>
</body>
</html>
```
---
### 三、功能說明
1. **表單輸入**
* 必填 & 格式驗證
* 錯誤訊息會即時顯示
2. **產生 JSON**
* 按下 `產生 FHIR JSON` → 輸出 FHIR 標準的 Patient 資料
3. **送到 FHIR Server**
* 使用 `fetch()` 送 POST 到 [HAPI FHIR public server](https://hapi.fhir.org/baseR4/)
* 成功後會回傳一個新的 Patient ID
---