feat(health): 体征增加体温/SpO2/血糖类型字段
- 迁移 079: vital_signs 表新增 body_temperature/spo2/blood_sugar_type 列 - Entity/DTO/Service 全链路支持新字段 - blood_sugar_type: fasting/postprandial/random/ogtt - daily_monitoring 兼容层补全新字段为 None
This commit is contained in:
@@ -20,6 +20,10 @@ pub struct CreateVitalSignsReq {
|
|||||||
pub heart_rate: Option<i32>,
|
pub heart_rate: Option<i32>,
|
||||||
pub weight: Option<Decimal>,
|
pub weight: Option<Decimal>,
|
||||||
pub blood_sugar: Option<Decimal>,
|
pub blood_sugar: Option<Decimal>,
|
||||||
|
pub body_temperature: Option<Decimal>,
|
||||||
|
pub spo2: Option<i32>,
|
||||||
|
/// fasting / postprandial / random / ogtt
|
||||||
|
pub blood_sugar_type: Option<String>,
|
||||||
pub water_intake_ml: Option<i32>,
|
pub water_intake_ml: Option<i32>,
|
||||||
pub urine_output_ml: Option<i32>,
|
pub urine_output_ml: Option<i32>,
|
||||||
pub notes: Option<String>,
|
pub notes: Option<String>,
|
||||||
@@ -42,6 +46,9 @@ pub struct UpdateVitalSignsReq {
|
|||||||
pub heart_rate: Option<i32>,
|
pub heart_rate: Option<i32>,
|
||||||
pub weight: Option<Decimal>,
|
pub weight: Option<Decimal>,
|
||||||
pub blood_sugar: Option<Decimal>,
|
pub blood_sugar: Option<Decimal>,
|
||||||
|
pub body_temperature: Option<Decimal>,
|
||||||
|
pub spo2: Option<i32>,
|
||||||
|
pub blood_sugar_type: Option<String>,
|
||||||
pub water_intake_ml: Option<i32>,
|
pub water_intake_ml: Option<i32>,
|
||||||
pub urine_output_ml: Option<i32>,
|
pub urine_output_ml: Option<i32>,
|
||||||
pub notes: Option<String>,
|
pub notes: Option<String>,
|
||||||
@@ -66,6 +73,9 @@ pub struct VitalSignsResp {
|
|||||||
pub heart_rate: Option<i32>,
|
pub heart_rate: Option<i32>,
|
||||||
pub weight: Option<Decimal>,
|
pub weight: Option<Decimal>,
|
||||||
pub blood_sugar: Option<Decimal>,
|
pub blood_sugar: Option<Decimal>,
|
||||||
|
pub body_temperature: Option<Decimal>,
|
||||||
|
pub spo2: Option<i32>,
|
||||||
|
pub blood_sugar_type: Option<String>,
|
||||||
pub water_intake_ml: Option<i32>,
|
pub water_intake_ml: Option<i32>,
|
||||||
pub urine_output_ml: Option<i32>,
|
pub urine_output_ml: Option<i32>,
|
||||||
pub notes: Option<String>,
|
pub notes: Option<String>,
|
||||||
|
|||||||
@@ -24,6 +24,12 @@ pub struct Model {
|
|||||||
#[sea_orm(skip_serializing_if = "Option::is_none")]
|
#[sea_orm(skip_serializing_if = "Option::is_none")]
|
||||||
pub blood_sugar: Option<Decimal>,
|
pub blood_sugar: Option<Decimal>,
|
||||||
#[sea_orm(skip_serializing_if = "Option::is_none")]
|
#[sea_orm(skip_serializing_if = "Option::is_none")]
|
||||||
|
pub body_temperature: Option<Decimal>,
|
||||||
|
#[sea_orm(skip_serializing_if = "Option::is_none")]
|
||||||
|
pub spo2: Option<i32>,
|
||||||
|
#[sea_orm(skip_serializing_if = "Option::is_none")]
|
||||||
|
pub blood_sugar_type: Option<String>,
|
||||||
|
#[sea_orm(skip_serializing_if = "Option::is_none")]
|
||||||
pub water_intake_ml: Option<i32>,
|
pub water_intake_ml: Option<i32>,
|
||||||
#[sea_orm(skip_serializing_if = "Option::is_none")]
|
#[sea_orm(skip_serializing_if = "Option::is_none")]
|
||||||
pub urine_output_ml: Option<i32>,
|
pub urine_output_ml: Option<i32>,
|
||||||
|
|||||||
@@ -83,6 +83,9 @@ pub async fn create_daily_monitoring(
|
|||||||
heart_rate: None,
|
heart_rate: None,
|
||||||
weight: req.weight,
|
weight: req.weight,
|
||||||
blood_sugar: req.blood_sugar,
|
blood_sugar: req.blood_sugar,
|
||||||
|
body_temperature: None,
|
||||||
|
spo2: None,
|
||||||
|
blood_sugar_type: None,
|
||||||
water_intake_ml: req.fluid_intake,
|
water_intake_ml: req.fluid_intake,
|
||||||
urine_output_ml: req.urine_output,
|
urine_output_ml: req.urine_output,
|
||||||
notes: req.notes,
|
notes: req.notes,
|
||||||
@@ -121,6 +124,9 @@ pub async fn update_daily_monitoring(
|
|||||||
heart_rate: None,
|
heart_rate: None,
|
||||||
weight: req.weight,
|
weight: req.weight,
|
||||||
blood_sugar: req.blood_sugar,
|
blood_sugar: req.blood_sugar,
|
||||||
|
body_temperature: None,
|
||||||
|
spo2: None,
|
||||||
|
blood_sugar_type: None,
|
||||||
water_intake_ml: req.fluid_intake,
|
water_intake_ml: req.fluid_intake,
|
||||||
urine_output_ml: req.urine_output,
|
urine_output_ml: req.urine_output,
|
||||||
notes: req.notes,
|
notes: req.notes,
|
||||||
|
|||||||
@@ -59,6 +59,9 @@ pub async fn list_vital_signs(
|
|||||||
heart_rate: m.heart_rate,
|
heart_rate: m.heart_rate,
|
||||||
weight: m.weight.map(|d| d.to_f64().unwrap_or(0.0)),
|
weight: m.weight.map(|d| d.to_f64().unwrap_or(0.0)),
|
||||||
blood_sugar: m.blood_sugar.map(|d| d.to_f64().unwrap_or(0.0)),
|
blood_sugar: m.blood_sugar.map(|d| d.to_f64().unwrap_or(0.0)),
|
||||||
|
body_temperature: m.body_temperature.map(|d| d.to_f64().unwrap_or(0.0)),
|
||||||
|
spo2: m.spo2,
|
||||||
|
blood_sugar_type: m.blood_sugar_type,
|
||||||
water_intake_ml: m.water_intake_ml,
|
water_intake_ml: m.water_intake_ml,
|
||||||
urine_output_ml: m.urine_output_ml,
|
urine_output_ml: m.urine_output_ml,
|
||||||
notes: m.notes,
|
notes: m.notes,
|
||||||
@@ -100,6 +103,9 @@ pub async fn create_vital_signs(
|
|||||||
heart_rate: Set(req.heart_rate),
|
heart_rate: Set(req.heart_rate),
|
||||||
weight: Set(req.weight.map(|v| sea_orm::prelude::Decimal::from_f64_retain(v).unwrap_or_default())),
|
weight: Set(req.weight.map(|v| sea_orm::prelude::Decimal::from_f64_retain(v).unwrap_or_default())),
|
||||||
blood_sugar: Set(req.blood_sugar.map(|v| sea_orm::prelude::Decimal::from_f64_retain(v).unwrap_or_default())),
|
blood_sugar: Set(req.blood_sugar.map(|v| sea_orm::prelude::Decimal::from_f64_retain(v).unwrap_or_default())),
|
||||||
|
body_temperature: Set(req.body_temperature.map(|v| sea_orm::prelude::Decimal::from_f64_retain(v).unwrap_or_default())),
|
||||||
|
spo2: Set(req.spo2),
|
||||||
|
blood_sugar_type: Set(req.blood_sugar_type),
|
||||||
water_intake_ml: Set(req.water_intake_ml),
|
water_intake_ml: Set(req.water_intake_ml),
|
||||||
urine_output_ml: Set(req.urine_output_ml),
|
urine_output_ml: Set(req.urine_output_ml),
|
||||||
notes: Set(req.notes),
|
notes: Set(req.notes),
|
||||||
@@ -131,6 +137,9 @@ pub async fn create_vital_signs(
|
|||||||
heart_rate: m.heart_rate,
|
heart_rate: m.heart_rate,
|
||||||
weight: m.weight.map(|d| d.to_f64().unwrap_or(0.0)),
|
weight: m.weight.map(|d| d.to_f64().unwrap_or(0.0)),
|
||||||
blood_sugar: m.blood_sugar.map(|d| d.to_f64().unwrap_or(0.0)),
|
blood_sugar: m.blood_sugar.map(|d| d.to_f64().unwrap_or(0.0)),
|
||||||
|
body_temperature: m.body_temperature.map(|d| d.to_f64().unwrap_or(0.0)),
|
||||||
|
spo2: m.spo2,
|
||||||
|
blood_sugar_type: m.blood_sugar_type,
|
||||||
water_intake_ml: m.water_intake_ml, urine_output_ml: m.urine_output_ml,
|
water_intake_ml: m.water_intake_ml, urine_output_ml: m.urine_output_ml,
|
||||||
notes: m.notes, created_at: m.created_at, updated_at: m.updated_at, version: m.version,
|
notes: m.notes, created_at: m.created_at, updated_at: m.updated_at, version: m.version,
|
||||||
})
|
})
|
||||||
@@ -178,6 +187,9 @@ pub async fn update_vital_signs(
|
|||||||
if let Some(v) = req.heart_rate { active.heart_rate = Set(Some(v)); }
|
if let Some(v) = req.heart_rate { active.heart_rate = Set(Some(v)); }
|
||||||
if let Some(v) = req.weight { active.weight = Set(Some(sea_orm::prelude::Decimal::from_f64_retain(v).unwrap_or_default())); }
|
if let Some(v) = req.weight { active.weight = Set(Some(sea_orm::prelude::Decimal::from_f64_retain(v).unwrap_or_default())); }
|
||||||
if let Some(v) = req.blood_sugar { active.blood_sugar = Set(Some(sea_orm::prelude::Decimal::from_f64_retain(v).unwrap_or_default())); }
|
if let Some(v) = req.blood_sugar { active.blood_sugar = Set(Some(sea_orm::prelude::Decimal::from_f64_retain(v).unwrap_or_default())); }
|
||||||
|
if let Some(v) = req.body_temperature { active.body_temperature = Set(Some(sea_orm::prelude::Decimal::from_f64_retain(v).unwrap_or_default())); }
|
||||||
|
if let Some(v) = req.spo2 { active.spo2 = Set(Some(v)); }
|
||||||
|
if let Some(v) = req.blood_sugar_type { active.blood_sugar_type = Set(Some(v)); }
|
||||||
if let Some(v) = req.water_intake_ml { active.water_intake_ml = Set(Some(v)); }
|
if let Some(v) = req.water_intake_ml { active.water_intake_ml = Set(Some(v)); }
|
||||||
if let Some(v) = req.urine_output_ml { active.urine_output_ml = Set(Some(v)); }
|
if let Some(v) = req.urine_output_ml { active.urine_output_ml = Set(Some(v)); }
|
||||||
if let Some(v) = req.notes { active.notes = Set(Some(v)); }
|
if let Some(v) = req.notes { active.notes = Set(Some(v)); }
|
||||||
@@ -210,6 +222,9 @@ pub async fn update_vital_signs(
|
|||||||
heart_rate: m.heart_rate,
|
heart_rate: m.heart_rate,
|
||||||
weight: m.weight.map(|d| d.to_f64().unwrap_or(0.0)),
|
weight: m.weight.map(|d| d.to_f64().unwrap_or(0.0)),
|
||||||
blood_sugar: m.blood_sugar.map(|d| d.to_f64().unwrap_or(0.0)),
|
blood_sugar: m.blood_sugar.map(|d| d.to_f64().unwrap_or(0.0)),
|
||||||
|
body_temperature: m.body_temperature.map(|d| d.to_f64().unwrap_or(0.0)),
|
||||||
|
spo2: m.spo2,
|
||||||
|
blood_sugar_type: m.blood_sugar_type.clone(),
|
||||||
water_intake_ml: m.water_intake_ml,
|
water_intake_ml: m.water_intake_ml,
|
||||||
urine_output_ml: m.urine_output_ml,
|
urine_output_ml: m.urine_output_ml,
|
||||||
notes: m.notes.clone(),
|
notes: m.notes.clone(),
|
||||||
@@ -232,6 +247,9 @@ pub async fn update_vital_signs(
|
|||||||
heart_rate: m.heart_rate,
|
heart_rate: m.heart_rate,
|
||||||
weight: m.weight.map(|d| d.to_f64().unwrap_or(0.0)),
|
weight: m.weight.map(|d| d.to_f64().unwrap_or(0.0)),
|
||||||
blood_sugar: m.blood_sugar.map(|d| d.to_f64().unwrap_or(0.0)),
|
blood_sugar: m.blood_sugar.map(|d| d.to_f64().unwrap_or(0.0)),
|
||||||
|
body_temperature: m.body_temperature.map(|d| d.to_f64().unwrap_or(0.0)),
|
||||||
|
spo2: m.spo2,
|
||||||
|
blood_sugar_type: m.blood_sugar_type,
|
||||||
water_intake_ml: m.water_intake_ml, urine_output_ml: m.urine_output_ml,
|
water_intake_ml: m.water_intake_ml, urine_output_ml: m.urine_output_ml,
|
||||||
notes: m.notes, created_at: m.created_at, updated_at: m.updated_at, version: m.version,
|
notes: m.notes, created_at: m.created_at, updated_at: m.updated_at, version: m.version,
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -78,6 +78,7 @@ mod m20260426_000075_create_patient_devices;
|
|||||||
mod m20260426_000076_create_alert_rules;
|
mod m20260426_000076_create_alert_rules;
|
||||||
mod m20260426_000077_create_alerts;
|
mod m20260426_000077_create_alerts;
|
||||||
mod m20260427_000078_normalize_follow_up_types;
|
mod m20260427_000078_normalize_follow_up_types;
|
||||||
|
mod m20260427_000079_add_vital_signs_fields;
|
||||||
|
|
||||||
pub struct Migrator;
|
pub struct Migrator;
|
||||||
|
|
||||||
@@ -163,6 +164,7 @@ impl MigratorTrait for Migrator {
|
|||||||
Box::new(m20260426_000076_create_alert_rules::Migration),
|
Box::new(m20260426_000076_create_alert_rules::Migration),
|
||||||
Box::new(m20260426_000077_create_alerts::Migration),
|
Box::new(m20260426_000077_create_alerts::Migration),
|
||||||
Box::new(m20260427_000078_normalize_follow_up_types::Migration),
|
Box::new(m20260427_000078_normalize_follow_up_types::Migration),
|
||||||
|
Box::new(m20260427_000079_add_vital_signs_fields::Migration),
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,54 @@
|
|||||||
|
use sea_orm_migration::prelude::*;
|
||||||
|
|
||||||
|
pub struct Migration;
|
||||||
|
|
||||||
|
impl MigrationName for Migration {
|
||||||
|
fn name(&self) -> &str {
|
||||||
|
"m20260427_000079_add_vital_signs_fields"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[async_trait::async_trait]
|
||||||
|
impl MigrationTrait for Migration {
|
||||||
|
async fn up(&self, manager: &SchemaManager) -> Result<(), DbErr> {
|
||||||
|
let conn = manager.get_connection();
|
||||||
|
|
||||||
|
conn.execute_unprepared(
|
||||||
|
"ALTER TABLE vital_signs ADD COLUMN IF NOT EXISTS body_temperature DECIMAL(4,1)",
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
conn.execute_unprepared(
|
||||||
|
"ALTER TABLE vital_signs ADD COLUMN IF NOT EXISTS spo2 INTEGER",
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
conn.execute_unprepared(
|
||||||
|
"ALTER TABLE vital_signs ADD COLUMN IF NOT EXISTS blood_sugar_type VARCHAR(20) DEFAULT 'fasting'",
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn down(&self, manager: &SchemaManager) -> Result<(), DbErr> {
|
||||||
|
let conn = manager.get_connection();
|
||||||
|
|
||||||
|
conn.execute_unprepared(
|
||||||
|
"ALTER TABLE vital_signs DROP COLUMN IF EXISTS blood_sugar_type",
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
conn.execute_unprepared(
|
||||||
|
"ALTER TABLE vital_signs DROP COLUMN IF EXISTS spo2",
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
conn.execute_unprepared(
|
||||||
|
"ALTER TABLE vital_signs DROP COLUMN IF EXISTS body_temperature",
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user