diff --git a/crates/erp-health/src/handler/critical_value_threshold_handler.rs b/crates/erp-health/src/handler/critical_value_threshold_handler.rs index 1a432d9..2d004dd 100644 --- a/crates/erp-health/src/handler/critical_value_threshold_handler.rs +++ b/crates/erp-health/src/handler/critical_value_threshold_handler.rs @@ -109,3 +109,16 @@ where .await?; Ok(Json(ApiResponse::ok(()))) } + +/// 患者端只读接口 — 返回当前租户所有活跃阈值,仅需认证。 +pub async fn list_public_thresholds( + State(state): State, + Extension(ctx): Extension, +) -> Result>>, AppError> +where + HealthState: FromRef, + S: Clone + Send + Sync + 'static, +{ + let list = critical_value_threshold_service::find_thresholds(&state.db, ctx.tenant_id).await?; + Ok(Json(ApiResponse::ok(list))) +} diff --git a/crates/erp-health/src/module.rs b/crates/erp-health/src/module.rs index 26764e1..356e840 100644 --- a/crates/erp-health/src/module.rs +++ b/crates/erp-health/src/module.rs @@ -608,6 +608,11 @@ impl HealthModule { axum::routing::put(critical_value_threshold_handler::update_threshold) .delete(critical_value_threshold_handler::delete_threshold), ) + // 患者端只读阈值(仅需认证) + .route( + "/health/critical-value-thresholds/public", + axum::routing::get(critical_value_threshold_handler::list_public_thresholds), + ) // 知情同意记录 .route( "/health/patients/{patient_id}/consents", diff --git a/crates/erp-health/src/service/critical_value_threshold_service.rs b/crates/erp-health/src/service/critical_value_threshold_service.rs index cb6ac1c..b29c929 100644 --- a/crates/erp-health/src/service/critical_value_threshold_service.rs +++ b/crates/erp-health/src/service/critical_value_threshold_service.rs @@ -186,7 +186,16 @@ fn validate_direction(direction: &str) -> HealthResult<()> { } fn validate_indicator(indicator: &str) -> HealthResult<()> { - let valid = ["systolic_bp", "diastolic_bp", "heart_rate", "blood_sugar"]; + let valid = [ + "systolic_bp", + "diastolic_bp", + "heart_rate", + "blood_sugar", + "blood_sugar_fasting", + "blood_sugar_postprandial", + "blood_oxygen", + "temperature", + ]; if valid.contains(&indicator) { Ok(()) } else { diff --git a/crates/erp-server/migration/src/lib.rs b/crates/erp-server/migration/src/lib.rs index 708009d..06e7cf5 100644 --- a/crates/erp-server/migration/src/lib.rs +++ b/crates/erp-server/migration/src/lib.rs @@ -101,6 +101,7 @@ mod m20260501_000098_create_ai_suggestion; mod m20260501_000099_create_ai_risk_threshold; mod m20260501_000100_seed_action_inbox_menu; mod m20260502_000101_seed_health_dictionaries; +mod m20260502_000102_seed_warning_thresholds; pub struct Migrator; @@ -209,6 +210,7 @@ impl MigratorTrait for Migrator { Box::new(m20260501_000099_create_ai_risk_threshold::Migration), Box::new(m20260501_000100_seed_action_inbox_menu::Migration), Box::new(m20260502_000101_seed_health_dictionaries::Migration), + Box::new(m20260502_000102_seed_warning_thresholds::Migration), ] } } diff --git a/crates/erp-server/migration/src/m20260502_000102_seed_warning_thresholds.rs b/crates/erp-server/migration/src/m20260502_000102_seed_warning_thresholds.rs new file mode 100644 index 0000000..dc6d924 --- /dev/null +++ b/crates/erp-server/migration/src/m20260502_000102_seed_warning_thresholds.rs @@ -0,0 +1,56 @@ +//! 补充 warning 级别危急值阈值种子数据 + +use sea_orm_migration::prelude::*; + +#[derive(DeriveMigrationName)] +pub struct Migration; + +#[async_trait::async_trait] +impl MigrationTrait for Migration { + async fn up(&self, manager: &SchemaManager) -> Result<(), DbErr> { + let db = manager.get_connection(); + + let result = db + .query_one(sea_orm::Statement::from_string( + sea_orm::DatabaseBackend::Postgres, + "SELECT id::text FROM tenant LIMIT 1".to_string(), + )) + .await?; + + let tid = match result { + Some(row) => row.try_get_by_index::(0).unwrap_or_default(), + None => return Ok(()), + }; + + // warning 级别阈值 — 用于小程序体征参考范围 + let sql = format!( + r#" + INSERT INTO critical_value_threshold (id, tenant_id, indicator, direction, threshold_value, level, is_active, created_at, updated_at) + VALUES + (gen_random_uuid(), '{tid}', 'systolic_bp', 'high', 140, 'warning', true, now(), now()), + (gen_random_uuid(), '{tid}', 'diastolic_bp', 'high', 90, 'warning', true, now(), now()), + (gen_random_uuid(), '{tid}', 'heart_rate', 'high', 100, 'warning', true, now(), now()), + (gen_random_uuid(), '{tid}', 'heart_rate', 'low', 60, 'warning', true, now(), now()), + (gen_random_uuid(), '{tid}', 'blood_sugar_fasting', 'high', 6.1, 'warning', true, now(), now()), + (gen_random_uuid(), '{tid}', 'blood_sugar_postprandial','high', 7.8, 'warning', true, now(), now()) + "# + ); + db.execute(sea_orm::Statement::from_string( + sea_orm::DatabaseBackend::Postgres, + sql, + )) + .await?; + + Ok(()) + } + + async fn down(&self, manager: &SchemaManager) -> Result<(), DbErr> { + let db = manager.get_connection(); + db.execute(sea_orm::Statement::from_string( + sea_orm::DatabaseBackend::Postgres, + "DELETE FROM critical_value_threshold WHERE level = 'warning'".to_string(), + )) + .await?; + Ok(()) + } +}