feat(health): patient entity PII 伴生字段 + content_management 编译修复
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

- 迁移 m000064: patient 添加 emergency_contact_phone_hash + key_version
- patient Entity 补充对应字段
- 修复 content_management 迁移: exec_stmt → execute_unprepared
- 修复 article_service: 补全新字段 (status/slug/content_type 等)
- 修复 article_article_tag: 复合主键注解
This commit is contained in:
iven
2026-04-26 10:27:58 +08:00
parent a6d2426f04
commit e0b299ccd4
6 changed files with 132 additions and 0 deletions

View File

@@ -0,0 +1,42 @@
use sea_orm::entity::prelude::*;
use serde::{Deserialize, Serialize};
/// 文章-标签关联表(复合主键)
#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Serialize, Deserialize)]
#[sea_orm(table_name = "article_article_tag")]
pub struct Model {
#[sea_orm(primary_key)]
pub article_id: Uuid,
#[sea_orm(primary_key)]
pub tag_id: Uuid,
}
#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
pub enum Relation {
#[sea_orm(
belongs_to = "super::article::Entity",
from = "Column::ArticleId",
to = "super::article::Column::Id"
)]
Article,
#[sea_orm(
belongs_to = "super::article_tag::Entity",
from = "Column::TagId",
to = "super::article_tag::Column::Id"
)]
Tag,
}
impl Related<super::article::Entity> for Entity {
fn to() -> RelationDef {
Relation::Article.def()
}
}
impl Related<super::article_tag::Entity> for Entity {
fn to() -> RelationDef {
Relation::Tag.def()
}
}
impl ActiveModelBehavior for ActiveModel {}

View File

@@ -28,6 +28,10 @@ pub struct Model {
pub emergency_contact_name: Option<String>,
#[sea_orm(skip_serializing_if = "Option::is_none")]
pub emergency_contact_phone: Option<String>,
#[sea_orm(skip_serializing_if = "Option::is_none")]
pub emergency_contact_phone_hash: Option<String>,
#[sea_orm(skip_serializing_if = "Option::is_none")]
pub key_version: Option<i32>,
pub status: String,
pub verification_status: String,
#[sea_orm(skip_serializing_if = "Option::is_none")]

View File

@@ -87,6 +87,10 @@ fn model_to_list_item(m: article::Model) -> ArticleListItem {
category: m.category,
author: m.author,
published_at: m.published_at,
status: m.status,
view_count: m.view_count,
category_id: None,
tags: vec![],
}
}
@@ -100,6 +104,16 @@ fn model_to_resp(m: article::Model) -> ArticleResp {
category: m.category,
author: m.author,
published_at: m.published_at,
status: m.status,
slug: m.slug,
content_type: m.content_type,
reviewed_by: m.reviewed_by,
reviewed_at: m.reviewed_at,
review_note: m.review_note,
view_count: m.view_count,
sort_order: m.sort_order,
category_id: None,
tags: vec![],
created_at: m.created_at,
updated_at: m.updated_at,
version: m.version,
@@ -128,6 +142,14 @@ pub async fn create_article(
category: Set(req.category),
author: Set(req.author),
published_at: Set(req.published_at),
status: Set("draft".into()),
slug: Set(req.slug),
content_type: Set(req.content_type.unwrap_or_else(|| "rich_text".into())),
reviewed_by: Set(None),
reviewed_at: Set(None),
review_note: Set(None),
view_count: Set(0),
sort_order: Set(0),
created_at: Set(now),
updated_at: Set(now),
created_by: Set(operator_id),

View File

@@ -130,6 +130,8 @@ pub async fn create_patient(
medical_history_summary: Set(req.medical_history_summary),
emergency_contact_name: Set(req.emergency_contact_name),
emergency_contact_phone: Set(req.emergency_contact_phone),
emergency_contact_phone_hash: Set(None),
key_version: Set(None),
status: Set("active".to_string()),
verification_status: Set("pending".to_string()),
source: Set(req.source),

View File

@@ -61,6 +61,9 @@ mod m20260426_000058_merge_daily_monitoring_into_vital_signs;
mod m20260426_000059_seed_menus;
mod m20260426_000060_create_critical_value_thresholds;
mod m20260426_000061_create_consent;
mod m20260427_000062_create_tenant_crypto_keys;
mod m20260427_000063_content_management;
mod m20260427_000064_add_patient_pii_fields;
pub struct Migrator;
@@ -129,6 +132,9 @@ impl MigratorTrait for Migrator {
Box::new(m20260426_000059_seed_menus::Migration),
Box::new(m20260426_000060_create_critical_value_thresholds::Migration),
Box::new(m20260426_000061_create_consent::Migration),
Box::new(m20260427_000062_create_tenant_crypto_keys::Migration),
Box::new(m20260427_000063_content_management::Migration),
Box::new(m20260427_000064_add_patient_pii_fields::Migration),
]
}
}

View File

@@ -0,0 +1,56 @@
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> {
manager
.alter_table(
Table::alter()
.table(Patient::Table)
.add_column(ColumnDef::new(Patient::EmergencyContactPhoneHash).string_len(64).null())
.add_column(ColumnDef::new(Patient::KeyVersion).integer().null())
.to_owned(),
)
.await?;
manager
.create_index(
Index::create()
.name("idx_patient_emergency_phone_hash")
.table(Patient::Table)
.col(Patient::EmergencyContactPhoneHash)
.to_owned(),
)
.await?;
Ok(())
}
async fn down(&self, manager: &SchemaManager) -> Result<(), DbErr> {
manager
.drop_index(Index::drop().name("idx_patient_emergency_phone_hash").to_owned())
.await?;
manager
.alter_table(
Table::alter()
.table(Patient::Table)
.drop_column(Patient::EmergencyContactPhoneHash)
.drop_column(Patient::KeyVersion)
.to_owned(),
)
.await?;
Ok(())
}
}
#[derive(DeriveIden)]
enum Patient {
Table,
EmergencyContactPhoneHash,
KeyVersion,
}