feat(db): 健康模块字典种子数据 — 6 个字典 + 43 个条目
Some checks failed
CI / rust-check (push) Has been cancelled
CI / rust-test (push) Has been cancelled
CI / frontend-build (push) Has been cancelled
CI / security-audit (push) Has been cancelled

- health_department (11 科室)
- health_title (9 职称)
- health_device_type (8 设备类型)
- health_follow_up_type (5 随访类型)
- health_consultation_type (3 咨询类型)
- health_relationship (5 关系类型)
This commit is contained in:
iven
2026-05-02 11:34:35 +08:00
parent 63ead0c442
commit 23cd62a70f
2 changed files with 215 additions and 0 deletions

View File

@@ -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),
]
}
}

View File

@@ -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::<String>(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(())
}