From 23cd62a70faadc9747bc2fca5fd212650681cf60 Mon Sep 17 00:00:00 2001 From: iven Date: Sat, 2 May 2026 11:34:35 +0800 Subject: [PATCH] =?UTF-8?q?feat(db):=20=E5=81=A5=E5=BA=B7=E6=A8=A1?= =?UTF-8?q?=E5=9D=97=E5=AD=97=E5=85=B8=E7=A7=8D=E5=AD=90=E6=95=B0=E6=8D=AE?= =?UTF-8?q?=20=E2=80=94=206=20=E4=B8=AA=E5=AD=97=E5=85=B8=20+=2043=20?= =?UTF-8?q?=E4=B8=AA=E6=9D=A1=E7=9B=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - health_department (11 科室) - health_title (9 职称) - health_device_type (8 设备类型) - health_follow_up_type (5 随访类型) - health_consultation_type (3 咨询类型) - health_relationship (5 关系类型) --- crates/erp-server/migration/src/lib.rs | 2 + ...0260502_000101_seed_health_dictionaries.rs | 213 ++++++++++++++++++ 2 files changed, 215 insertions(+) create mode 100644 crates/erp-server/migration/src/m20260502_000101_seed_health_dictionaries.rs diff --git a/crates/erp-server/migration/src/lib.rs b/crates/erp-server/migration/src/lib.rs index 0b8a479..708009d 100644 --- a/crates/erp-server/migration/src/lib.rs +++ b/crates/erp-server/migration/src/lib.rs @@ -100,6 +100,7 @@ mod m20260501_000097_seed_menu_permissions; 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; pub struct Migrator; @@ -207,6 +208,7 @@ impl MigratorTrait for Migrator { Box::new(m20260501_000098_create_ai_suggestion::Migration), 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), ] } } diff --git a/crates/erp-server/migration/src/m20260502_000101_seed_health_dictionaries.rs b/crates/erp-server/migration/src/m20260502_000101_seed_health_dictionaries.rs new file mode 100644 index 0000000..3e29568 --- /dev/null +++ b/crates/erp-server/migration/src/m20260502_000101_seed_health_dictionaries.rs @@ -0,0 +1,213 @@ +//! 健康模块字典种子数据 — 6 个字典 + 对应条目 + +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(()), + }; + + let sys = "00000000-0000-0000-0000-000000000000"; + + // ── 1. 科室 health_department ── + let dict_dept = "d1000001-0000-0000-0000-000000000001"; + insert_dict(db, &tid, dict_dept, "科室", "health_department", "医护科室分类", sys).await?; + let dept_items = [ + ("全科", "全科", 1), + ("内科", "内科", 2), + ("外科", "外科", 3), + ("儿科", "儿科", 4), + ("妇产科", "妇产科", 5), + ("骨科", "骨科", 6), + ("眼科", "眼科", 7), + ("口腔科", "口腔科", 8), + ("皮肤科", "皮肤科", 9), + ("中医科", "中医科", 10), + ("体检中心", "体检中心", 11), + ]; + for (i, (label, value, sort)) in dept_items.iter().enumerate() { + insert_item(db, &tid, dict_dept, label, value, *sort, None, &(i + 1), sys).await?; + } + + // ── 2. 职称 health_title ── + let dict_title = "d1000001-0000-0000-0000-000000000002"; + insert_dict(db, &tid, dict_title, "职称", "health_title", "医护职称分类", sys).await?; + let title_items = [ + ("住院医师", "住院医师", 1), + ("主治医师", "主治医师", 2), + ("副主任医师", "副主任医师", 3), + ("主任医师", "主任医师", 4), + ("护士", "护士", 5), + ("护师", "护师", 6), + ("主管护师", "主管护师", 7), + ("副主任护师", "副主任护师", 8), + ("主任护师", "主任护师", 9), + ]; + for (i, (label, value, sort)) in title_items.iter().enumerate() { + insert_item(db, &tid, dict_title, label, value, *sort, None, &(i + 1), sys).await?; + } + + // ── 3. 设备类型 health_device_type ── + let dict_dev = "d1000001-0000-0000-0000-000000000003"; + insert_dict(db, &tid, dict_dev, "设备类型", "health_device_type", "健康监测设备类型", sys).await?; + let dev_items = [ + ("血压计", "blood_pressure", 1), + ("血糖仪", "blood_glucose", 2), + ("心率监测", "heart_rate", 3), + ("血氧仪", "blood_oxygen", 4), + ("计步器", "steps", 5), + ("体温计", "temperature", 6), + ("睡眠监测", "sleep", 7), + ("压力监测", "stress", 8), + ]; + for (i, (label, value, sort)) in dev_items.iter().enumerate() { + insert_item(db, &tid, dict_dev, label, value, *sort, None, &(i + 1), sys).await?; + } + + // ── 4. 随访类型 health_follow_up_type ── + let dict_fu = "d1000001-0000-0000-0000-000000000004"; + insert_dict(db, &tid, dict_fu, "随访类型", "health_follow_up_type", "随访方式分类", sys).await?; + let fu_items = [ + ("电话", "phone", 1), + ("门诊", "outpatient", 2), + ("家访", "home_visit", 3), + ("线上", "online", 4), + ("微信", "wechat", 5), + ]; + for (i, (label, value, sort)) in fu_items.iter().enumerate() { + insert_item(db, &tid, dict_fu, label, value, *sort, None, &(i + 1), sys).await?; + } + + // ── 5. 咨询类型 health_consultation_type ── + let dict_consult = "d1000001-0000-0000-0000-000000000005"; + insert_dict( + db, &tid, dict_consult, "咨询类型", "health_consultation_type", "咨询会话类型", sys, + ) + .await?; + let consult_items = [ + ("客服咨询", "customer_service", 1), + ("医疗咨询", "medical", 2), + ("健康咨询", "health_consultation", 3), + ]; + for (i, (label, value, sort)) in consult_items.iter().enumerate() { + insert_item(db, &tid, dict_consult, label, value, *sort, None, &(i + 1), sys).await?; + } + + // ── 6. 关系 health_relationship ── + let dict_rel = "d1000001-0000-0000-0000-000000000006"; + insert_dict(db, &tid, dict_rel, "关系", "health_relationship", "家属与患者关系", sys).await?; + let rel_items = [ + ("父母", "parent", 1), + ("配偶", "spouse", 2), + ("子女", "child", 3), + ("兄弟姐妹", "sibling", 4), + ("其他", "other", 5), + ]; + for (i, (label, value, sort)) in rel_items.iter().enumerate() { + insert_item(db, &tid, dict_rel, label, value, *sort, None, &(i + 1), sys).await?; + } + + Ok(()) + } + + async fn down(&self, manager: &SchemaManager) -> Result<(), DbErr> { + let db = manager.get_connection(); + + let dict_ids = [ + "d1000001-0000-0000-0000-000000000001", + "d1000001-0000-0000-0000-000000000002", + "d1000001-0000-0000-0000-000000000003", + "d1000001-0000-0000-0000-000000000004", + "d1000001-0000-0000-0000-000000000005", + "d1000001-0000-0000-0000-000000000006", + ]; + + // 先删条目(级联应该也会处理,但显式清理更安全) + for dict_id in &dict_ids { + db.execute(sea_orm::Statement::from_string( + sea_orm::DatabaseBackend::Postgres, + format!("DELETE FROM dictionary_items WHERE dictionary_id = '{dict_id}'"), + )) + .await + .ok(); + } + + // 再删字典 + for dict_id in &dict_ids { + db.execute(sea_orm::Statement::from_string( + sea_orm::DatabaseBackend::Postgres, + format!("DELETE FROM dictionaries WHERE id = '{dict_id}'"), + )) + .await + .ok(); + } + + Ok(()) + } +} + +async fn insert_dict( + db: &sea_orm_migration::SchemaManagerConnection<'_>, + tenant_id: &str, + id: &str, + name: &str, + code: &str, + description: &str, + sys: &str, +) -> Result<(), DbErr> { + db.execute(sea_orm::Statement::from_string( + sea_orm::DatabaseBackend::Postgres, + format!( + "INSERT INTO dictionaries (id, tenant_id, name, code, description, created_at, updated_at, created_by, updated_by, deleted_at, version) \ + VALUES ('{id}', '{tenant_id}', '{name}', '{code}', '{description}', NOW(), NOW(), '{sys}', '{sys}', NULL, 1) \ + ON CONFLICT (id) DO NOTHING" + ), + )) + .await?; + Ok(()) +} + +async fn insert_item( + db: &sea_orm_migration::SchemaManagerConnection<'_>, + tenant_id: &str, + dict_id: &str, + label: &str, + value: &str, + sort_order: i32, + color: Option<&str>, + idx: &usize, + sys: &str, +) -> Result<(), DbErr> { + // 生成条目 ID:基于字典 ID 后缀 + 序号 + let suffix = &dict_id[24..]; + let item_id = format!("d200{idx:04x}-0000-0000-{suffix}"); + let color_sql = match color { + Some(c) => format!("'{c}'"), + None => "NULL".to_string(), + }; + db.execute(sea_orm::Statement::from_string( + sea_orm::DatabaseBackend::Postgres, + format!( + "INSERT INTO dictionary_items (id, tenant_id, dictionary_id, label, value, sort_order, color, created_at, updated_at, created_by, updated_by, deleted_at, version) \ + VALUES ('{item_id}', '{tenant_id}', '{dict_id}', '{label}', '{value}', {sort_order}, {color_sql}, NOW(), NOW(), '{sys}', '{sys}', NULL, 1) \ + ON CONFLICT (id) DO NOTHING" + ), + )) + .await?; + Ok(()) +}