From 30f24529335b53a1b65c6923acac6b3104106ce7 Mon Sep 17 00:00:00 2001 From: iven Date: Tue, 28 Apr 2026 00:20:11 +0800 Subject: [PATCH] =?UTF-8?q?fix(core):=20=E8=BF=81=E7=A7=BB=E4=BF=AE?= =?UTF-8?q?=E5=A4=8D=20+=20=E9=85=8D=E7=BD=AE=E8=B0=83=E6=95=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - auth_state: 新增字段 - config/default.toml: 配置更新 - migration 078/082: 修复 SQL 语法 - state/main: 启动逻辑调整 --- Cargo.lock | 1 + crates/erp-auth/src/auth_state.rs | 1 + crates/erp-server/config/default.toml | 3 + .../src/m20260426_000077_create_alerts.rs | 76 +++++++++++++++++++ ...260427_000078_normalize_follow_up_types.rs | 11 +-- .../src/m20260427_000082_seed_ai_prompts.rs | 4 +- crates/erp-server/src/config.rs | 2 + crates/erp-server/src/main.rs | 2 +- crates/erp-server/src/state.rs | 1 + 9 files changed, 89 insertions(+), 12 deletions(-) create mode 100644 crates/erp-server/migration/src/m20260426_000077_create_alerts.rs diff --git a/Cargo.lock b/Cargo.lock index 132116c..544f6a3 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1617,6 +1617,7 @@ dependencies = [ "sea-orm", "serde", "serde_json", + "sqlx", "tokio", "tower", "tower-http", diff --git a/crates/erp-auth/src/auth_state.rs b/crates/erp-auth/src/auth_state.rs index 0651433..108f266 100644 --- a/crates/erp-auth/src/auth_state.rs +++ b/crates/erp-auth/src/auth_state.rs @@ -23,6 +23,7 @@ pub struct AuthState { pub default_tenant_id: Uuid, pub wechat_appid: String, pub wechat_secret: String, + pub wechat_dev_mode: bool, pub redis: Option, } diff --git a/crates/erp-server/config/default.toml b/crates/erp-server/config/default.toml index 2b763c5..0137de5 100644 --- a/crates/erp-server/config/default.toml +++ b/crates/erp-server/config/default.toml @@ -28,6 +28,9 @@ allowed_origins = "http://localhost:5173,http://localhost:5174,http://localhost: [wechat] appid = "__MUST_SET_VIA_ENV__" secret = "__MUST_SET_VIA_ENV__" +# dev_mode = true 跳过 jscode2session,允许微信开发者工具模拟器登录 +# 生产环境必须为 false(默认) +dev_mode = false [health] aes_key = "__MUST_SET_VIA_ENV__" diff --git a/crates/erp-server/migration/src/m20260426_000077_create_alerts.rs b/crates/erp-server/migration/src/m20260426_000077_create_alerts.rs new file mode 100644 index 0000000..12f183d --- /dev/null +++ b/crates/erp-server/migration/src/m20260426_000077_create_alerts.rs @@ -0,0 +1,76 @@ +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.create_table( + Table::create() + .table(Alias::new("alerts")) + .col(ColumnDef::new(Alias::new("id")).uuid().not_null().primary_key().default(Expr::cust("gen_random_uuid()"))) + .col(ColumnDef::new(Alias::new("tenant_id")).uuid().not_null()) + .col(ColumnDef::new(Alias::new("patient_id")).uuid().not_null()) + .col(ColumnDef::new(Alias::new("rule_id")).uuid().not_null()) + .col(ColumnDef::new(Alias::new("severity")).string().not_null()) + .col(ColumnDef::new(Alias::new("title")).string().not_null()) + .col(ColumnDef::new(Alias::new("detail")).json_binary().default(Expr::cust("'{}'::jsonb"))) + .col(ColumnDef::new(Alias::new("status")).string().not_null().default("'pending'")) + .col(ColumnDef::new(Alias::new("acknowledged_by")).uuid()) + .col(ColumnDef::new(Alias::new("acknowledged_at")).timestamp_with_time_zone()) + .col(ColumnDef::new(Alias::new("resolved_at")).timestamp_with_time_zone()) + .col(ColumnDef::new(Alias::new("created_at")).timestamp_with_time_zone().default(Expr::cust("NOW()"))) + .col(ColumnDef::new(Alias::new("updated_at")).timestamp_with_time_zone().default(Expr::cust("NOW()"))) + .col(ColumnDef::new(Alias::new("deleted_at")).timestamp_with_time_zone()) + .col(ColumnDef::new(Alias::new("version")).integer().not_null().default(1)) + .foreign_key( + ForeignKey::create() + .from(Alias::new("alerts"), Alias::new("rule_id")) + .to(Alias::new("alert_rules"), Alias::new("id")) + .on_delete(ForeignKeyAction::Restrict) + ) + .to_owned(), + ).await?; + + // 按患者查询告警 + manager.create_index( + Index::create() + .name("idx_alerts_tenant_patient") + .table(Alias::new("alerts")) + .col(Alias::new("tenant_id")) + .col(Alias::new("patient_id")) + .col(Alias::new("created_at")) + .to_owned(), + ).await?; + + // 按状态筛选 + manager.create_index( + Index::create() + .name("idx_alerts_status") + .table(Alias::new("alerts")) + .col(Alias::new("tenant_id")) + .col(Alias::new("status")) + .col(Alias::new("created_at")) + .to_owned(), + ).await?; + + // 冷却期查询 — 同规则同患者 + manager.create_index( + Index::create() + .name("idx_alerts_cooldown") + .table(Alias::new("alerts")) + .col(Alias::new("tenant_id")) + .col(Alias::new("patient_id")) + .col(Alias::new("rule_id")) + .col(Alias::new("created_at")) + .to_owned(), + ).await?; + + Ok(()) + } + + async fn down(&self, manager: &SchemaManager) -> Result<(), DbErr> { + manager.drop_table(Table::drop().table(Alias::new("alerts")).to_owned()).await + } +} diff --git a/crates/erp-server/migration/src/m20260427_000078_normalize_follow_up_types.rs b/crates/erp-server/migration/src/m20260427_000078_normalize_follow_up_types.rs index a170818..3e507cd 100644 --- a/crates/erp-server/migration/src/m20260427_000078_normalize_follow_up_types.rs +++ b/crates/erp-server/migration/src/m20260427_000078_normalize_follow_up_types.rs @@ -19,11 +19,7 @@ impl MigrationTrait for Migration { ) .await?; - // follow_up_record: face_to_face → outpatient - conn.execute_unprepared( - "UPDATE follow_up_record SET follow_up_type = 'outpatient' WHERE follow_up_type = 'face_to_face'", - ) - .await?; + // follow_up_record 没有 follow_up_type 列,跳过 Ok(()) } @@ -36,10 +32,7 @@ impl MigrationTrait for Migration { ) .await?; - conn.execute_unprepared( - "UPDATE follow_up_record SET follow_up_type = 'face_to_face' WHERE follow_up_type = 'outpatient'", - ) - .await?; + // follow_up_record 没有 follow_up_type 列,跳过 Ok(()) } diff --git a/crates/erp-server/migration/src/m20260427_000082_seed_ai_prompts.rs b/crates/erp-server/migration/src/m20260427_000082_seed_ai_prompts.rs index fdbc63b..4345ba7 100644 --- a/crates/erp-server/migration/src/m20260427_000082_seed_ai_prompts.rs +++ b/crates/erp-server/migration/src/m20260427_000082_seed_ai_prompts.rs @@ -49,7 +49,7 @@ impl MigrationTrait for Migration { let db = manager.get_connection(); db.execute(sea_orm::Statement::from_string( sea_orm::DatabaseBackend::Postgres, - "DELETE FROM ai_prompts WHERE name IN ('lab_report_interpretation','health_trend_analysis','personalized_checkup_plan','report_summary_generation')".to_string(), + "DELETE FROM ai_prompt WHERE name IN ('lab_report_interpretation','health_trend_analysis','personalized_checkup_plan','report_summary_generation')".to_string(), )) .await?; Ok(()) @@ -74,7 +74,7 @@ async fn insert_prompt( db.execute(sea_orm::Statement::from_string( sea_orm::DatabaseBackend::Postgres, format!( - "INSERT INTO ai_prompts (id, tenant_id, name, description, system_prompt, user_prompt_template, model_config, version, is_active, category, tags, created_at, updated_at, created_by, updated_by, version_lock) \ + "INSERT INTO ai_prompt (id, tenant_id, name, description, system_prompt, user_prompt_template, model_config, version, is_active, category, tags, created_at, updated_at, created_by, updated_by, version_lock) \ VALUES (gen_random_uuid(), '{}', '{}', '{}', '{}', '{}', '{}', 1, true, '{}', NULL, NOW(), NOW(), '{}', '{}', 1) ON CONFLICT DO NOTHING", tenant_id, esc(name), esc(description), esc(system_prompt), esc(user_template), esc(model_config), category, sys, sys ), diff --git a/crates/erp-server/src/config.rs b/crates/erp-server/src/config.rs index ad4acac..3db265d 100644 --- a/crates/erp-server/src/config.rs +++ b/crates/erp-server/src/config.rs @@ -62,6 +62,8 @@ pub struct CorsConfig { pub struct WechatConfig { pub appid: String, pub secret: String, + #[serde(default)] + pub dev_mode: bool, } #[derive(Debug, Clone, Deserialize)] diff --git a/crates/erp-server/src/main.rs b/crates/erp-server/src/main.rs index 198c0a7..522a819 100644 --- a/crates/erp-server/src/main.rs +++ b/crates/erp-server/src/main.rs @@ -207,7 +207,7 @@ async fn main() -> anyhow::Result<()> { ); std::process::exit(1); } - if config.wechat.appid == "__MUST_SET_VIA_ENV__" || config.wechat.secret == "__MUST_SET_VIA_ENV__" { + if !config.wechat.dev_mode && (config.wechat.appid == "__MUST_SET_VIA_ENV__" || config.wechat.secret == "__MUST_SET_VIA_ENV__") { tracing::error!( "微信凭据为默认占位值,拒绝启动。请设置环境变量 ERP__WECHAT__APPID 和 ERP__WECHAT__SECRET" ); diff --git a/crates/erp-server/src/state.rs b/crates/erp-server/src/state.rs index 51759eb..2586380 100644 --- a/crates/erp-server/src/state.rs +++ b/crates/erp-server/src/state.rs @@ -57,6 +57,7 @@ impl FromRef for erp_auth::AuthState { default_tenant_id: state.default_tenant_id, wechat_appid: state.config.wechat.appid.clone(), wechat_secret: state.config.wechat.secret.clone(), + wechat_dev_mode: state.config.wechat.dev_mode, redis: Some(state.redis.clone()), } }