- 新增 alert_noise_reducer:患者级升级(30min/3次阈值) + 系统级聚合(5min窗口) - 补全 FHIR R4 handler stubs(Plan 2 路由注册但 handler 缺失导致编译失败)
229 lines
9.0 KiB
Rust
229 lines
9.0 KiB
Rust
use axum::extract::{FromRef, Path, Query, State};
|
|
use axum::response::IntoResponse;
|
|
use axum::Json;
|
|
use serde::Deserialize;
|
|
use uuid::Uuid;
|
|
|
|
use crate::state::HealthState;
|
|
|
|
/// GET /fhir/R4/metadata — FHIR CapabilityStatement
|
|
pub async fn capability_statement<S>() -> Result<impl IntoResponse, erp_core::error::AppError>
|
|
where
|
|
HealthState: FromRef<S>,
|
|
S: Clone + Send + Sync + 'static,
|
|
{
|
|
let stmt = serde_json::json!({
|
|
"resourceType": "CapabilityStatement",
|
|
"status": "active",
|
|
"date": chrono::Utc::now().format("%Y-%m-%d").to_string(),
|
|
"kind": "instance",
|
|
"fhirVersion": "4.0.1",
|
|
"format": ["application/fhir+json"],
|
|
"rest": [{
|
|
"mode": "server",
|
|
"resource": [
|
|
{ "type": "Patient", "interaction": [{"code": "read"}, {"code": "search-type"}], "operation": [{"name": "everything"}] },
|
|
{ "type": "Observation", "interaction": [{"code": "read"}, {"code": "search-type"}], "operation": [{"name": "lastn"}] },
|
|
{ "type": "Device", "interaction": [{"code": "read"}, {"code": "search-type"}] },
|
|
{ "type": "DiagnosticReport", "interaction": [{"code": "read"}, {"code": "search-type"}] },
|
|
{ "type": "Encounter", "interaction": [{"code": "read"}, {"code": "search-type"}] },
|
|
{ "type": "Practitioner", "interaction": [{"code": "read"}, {"code": "search-type"}] },
|
|
{ "type": "Appointment", "interaction": [{"code": "read"}, {"code": "search-type"}] },
|
|
{ "type": "Task", "interaction": [{"code": "read"}, {"code": "search-type"}] },
|
|
],
|
|
"operation": [
|
|
{ "name": "everything", "definition": "/fhir/R4/Patient/{id}/$everything" },
|
|
{ "name": "lastn", "definition": "/fhir/R4/Observation/$lastn" },
|
|
]
|
|
}]
|
|
});
|
|
|
|
Ok(Json(stmt))
|
|
}
|
|
|
|
#[derive(Debug, Deserialize)]
|
|
pub struct SearchParams {
|
|
pub patient: Option<String>,
|
|
pub category: Option<String>,
|
|
#[serde(rename = "_count")]
|
|
pub count: Option<u32>,
|
|
#[serde(rename = "_offset")]
|
|
pub offset: Option<u32>,
|
|
}
|
|
|
|
// ── Patient ────────────────────────────────────────────────────────────
|
|
|
|
pub async fn search_patients(
|
|
State(_state): State<HealthState>,
|
|
Query(_params): Query<SearchParams>,
|
|
) -> Result<impl IntoResponse, erp_core::error::AppError> {
|
|
Ok(Json(serde_json::json!({
|
|
"resourceType": "Bundle", "type": "searchset", "total": 0, "entry": []
|
|
})))
|
|
}
|
|
|
|
pub async fn get_patient(
|
|
State(_state): State<HealthState>,
|
|
Path(_id): Path<Uuid>,
|
|
) -> Result<impl IntoResponse, erp_core::error::AppError> {
|
|
Ok(Json(serde_json::json!({
|
|
"resourceType": "OperationOutcome",
|
|
"issue": [{"severity": "information", "code": "not-found", "diagnostics": "Patient not implemented yet"}]
|
|
})))
|
|
}
|
|
|
|
pub async fn patient_everything(
|
|
State(_state): State<HealthState>,
|
|
Path(_id): Path<Uuid>,
|
|
) -> Result<impl IntoResponse, erp_core::error::AppError> {
|
|
Ok(Json(serde_json::json!({
|
|
"resourceType": "Bundle", "type": "searchset", "total": 0, "entry": []
|
|
})))
|
|
}
|
|
|
|
// ── Observation ────────────────────────────────────────────────────────
|
|
|
|
pub async fn search_observations(
|
|
State(_state): State<HealthState>,
|
|
Query(_params): Query<SearchParams>,
|
|
) -> Result<impl IntoResponse, erp_core::error::AppError> {
|
|
Ok(Json(serde_json::json!({
|
|
"resourceType": "Bundle", "type": "searchset", "total": 0, "entry": []
|
|
})))
|
|
}
|
|
|
|
pub async fn observation_lastn(
|
|
State(_state): State<HealthState>,
|
|
Query(_params): Query<SearchParams>,
|
|
) -> Result<impl IntoResponse, erp_core::error::AppError> {
|
|
Ok(Json(serde_json::json!({
|
|
"resourceType": "Bundle", "type": "searchset", "total": 0, "entry": []
|
|
})))
|
|
}
|
|
|
|
// ── Device ─────────────────────────────────────────────────────────────
|
|
|
|
pub async fn search_devices(
|
|
State(_state): State<HealthState>,
|
|
Query(_params): Query<SearchParams>,
|
|
) -> Result<impl IntoResponse, erp_core::error::AppError> {
|
|
Ok(Json(serde_json::json!({
|
|
"resourceType": "Bundle", "type": "searchset", "total": 0, "entry": []
|
|
})))
|
|
}
|
|
|
|
pub async fn get_device(
|
|
State(_state): State<HealthState>,
|
|
Path(_id): Path<Uuid>,
|
|
) -> Result<impl IntoResponse, erp_core::error::AppError> {
|
|
Ok(Json(serde_json::json!({
|
|
"resourceType": "OperationOutcome",
|
|
"issue": [{"severity": "information", "code": "not-found", "diagnostics": "Device not implemented yet"}]
|
|
})))
|
|
}
|
|
|
|
// ── Practitioner ───────────────────────────────────────────────────────
|
|
|
|
pub async fn search_practitioners(
|
|
State(_state): State<HealthState>,
|
|
Query(_params): Query<SearchParams>,
|
|
) -> Result<impl IntoResponse, erp_core::error::AppError> {
|
|
Ok(Json(serde_json::json!({
|
|
"resourceType": "Bundle", "type": "searchset", "total": 0, "entry": []
|
|
})))
|
|
}
|
|
|
|
pub async fn get_practitioner(
|
|
State(_state): State<HealthState>,
|
|
Path(_id): Path<Uuid>,
|
|
) -> Result<impl IntoResponse, erp_core::error::AppError> {
|
|
Ok(Json(serde_json::json!({
|
|
"resourceType": "OperationOutcome",
|
|
"issue": [{"severity": "information", "code": "not-found", "diagnostics": "Practitioner not implemented yet"}]
|
|
})))
|
|
}
|
|
|
|
// ── Appointment ────────────────────────────────────────────────────────
|
|
|
|
pub async fn search_appointments(
|
|
State(_state): State<HealthState>,
|
|
Query(_params): Query<SearchParams>,
|
|
) -> Result<impl IntoResponse, erp_core::error::AppError> {
|
|
Ok(Json(serde_json::json!({
|
|
"resourceType": "Bundle", "type": "searchset", "total": 0, "entry": []
|
|
})))
|
|
}
|
|
|
|
pub async fn get_appointment(
|
|
State(_state): State<HealthState>,
|
|
Path(_id): Path<Uuid>,
|
|
) -> Result<impl IntoResponse, erp_core::error::AppError> {
|
|
Ok(Json(serde_json::json!({
|
|
"resourceType": "OperationOutcome",
|
|
"issue": [{"severity": "information", "code": "not-found", "diagnostics": "Appointment not implemented yet"}]
|
|
})))
|
|
}
|
|
|
|
// ── DiagnosticReport ───────────────────────────────────────────────────
|
|
|
|
pub async fn search_diagnostic_reports(
|
|
State(_state): State<HealthState>,
|
|
Query(_params): Query<SearchParams>,
|
|
) -> Result<impl IntoResponse, erp_core::error::AppError> {
|
|
Ok(Json(serde_json::json!({
|
|
"resourceType": "Bundle", "type": "searchset", "total": 0, "entry": []
|
|
})))
|
|
}
|
|
|
|
pub async fn get_diagnostic_report(
|
|
State(_state): State<HealthState>,
|
|
Path(_id): Path<Uuid>,
|
|
) -> Result<impl IntoResponse, erp_core::error::AppError> {
|
|
Ok(Json(serde_json::json!({
|
|
"resourceType": "OperationOutcome",
|
|
"issue": [{"severity": "information", "code": "not-found", "diagnostics": "DiagnosticReport not implemented yet"}]
|
|
})))
|
|
}
|
|
|
|
// ── Encounter ──────────────────────────────────────────────────────────
|
|
|
|
pub async fn search_encounters(
|
|
State(_state): State<HealthState>,
|
|
Query(_params): Query<SearchParams>,
|
|
) -> Result<impl IntoResponse, erp_core::error::AppError> {
|
|
Ok(Json(serde_json::json!({
|
|
"resourceType": "Bundle", "type": "searchset", "total": 0, "entry": []
|
|
})))
|
|
}
|
|
|
|
pub async fn get_encounter(
|
|
State(_state): State<HealthState>,
|
|
Path(_id): Path<Uuid>,
|
|
) -> Result<impl IntoResponse, erp_core::error::AppError> {
|
|
Ok(Json(serde_json::json!({
|
|
"resourceType": "OperationOutcome",
|
|
"issue": [{"severity": "information", "code": "not-found", "diagnostics": "Encounter not implemented yet"}]
|
|
})))
|
|
}
|
|
|
|
// ── Task ───────────────────────────────────────────────────────────────
|
|
|
|
pub async fn search_tasks(
|
|
State(_state): State<HealthState>,
|
|
Query(_params): Query<SearchParams>,
|
|
) -> Result<impl IntoResponse, erp_core::error::AppError> {
|
|
Ok(Json(serde_json::json!({
|
|
"resourceType": "Bundle", "type": "searchset", "total": 0, "entry": []
|
|
})))
|
|
}
|
|
|
|
pub async fn get_task(
|
|
State(_state): State<HealthState>,
|
|
Path(_id): Path<Uuid>,
|
|
) -> Result<impl IntoResponse, erp_core::error::AppError> {
|
|
Ok(Json(serde_json::json!({
|
|
"resourceType": "OperationOutcome",
|
|
"issue": [{"severity": "information", "code": "not-found", "diagnostics": "Task not implemented yet"}]
|
|
})))
|
|
}
|