fix(ai): 修复 AI 分析读取化验报告 items 为空的问题
- parse_lab_items 兼容两种存储格式(item_name/name, string/f64 value, reference_range/reference_low+high) - get_lab_report 添加 PII 解密步骤:数据库中 items 是加密存储的, AI 分析前需要先解密再解析 - HealthDataProviderImpl 添加 PiiCrypto 字段用于解密 - pii_crypto 创建提前到 AI state 构建之前 - default.toml rate_limit.fail_close 改为 false(开发环境)
This commit is contained in:
@@ -64,4 +64,4 @@ max_file_size = "10MB"
|
||||
[rate_limit]
|
||||
# Redis 不可达时是否拒绝请求(fail-close)。默认 true = 安全优先。
|
||||
# 开发环境可设为 false 以避免 Redis 依赖:ERP__RATE_LIMIT__FAIL_CLOSE=false
|
||||
fail_close = true
|
||||
fail_close = false
|
||||
|
||||
@@ -457,6 +457,22 @@ async fn main() -> anyhow::Result<()> {
|
||||
// Extract JWT secret for middleware construction
|
||||
let jwt_secret = config.jwt.secret.clone();
|
||||
|
||||
// Build PII crypto early — needed for AI health_provider (lab report decryption)
|
||||
let pii_crypto = if config.crypto.kek == "__MUST_SET_VIA_ENV__" {
|
||||
#[cfg(debug_assertions)]
|
||||
{
|
||||
tracing::warn!("⚠️ PII KEK 使用开发默认值,仅用于本地开发");
|
||||
erp_core::crypto::PiiCrypto::dev_default()
|
||||
}
|
||||
#[cfg(not(debug_assertions))]
|
||||
{
|
||||
panic!("ERP__CRYPTO__KEK must be set in production. Use a 64-char hex string (32 bytes).");
|
||||
}
|
||||
} else {
|
||||
erp_core::crypto::PiiCrypto::from_kek_hex(&config.crypto.kek)
|
||||
.expect("PII KEK must be valid 64-char hex (32 bytes). Set ERP__CRYPTO__KEK")
|
||||
};
|
||||
|
||||
// Pre-build AI state (avoids per-request reconstruction)
|
||||
let ai_state = {
|
||||
// 构建多 Provider 注册表
|
||||
@@ -558,6 +574,7 @@ async fn main() -> anyhow::Result<()> {
|
||||
let suggestion = std::sync::Arc::new(erp_ai::service::suggestion::SuggestionService);
|
||||
let health_provider = std::sync::Arc::new(erp_health::HealthDataProviderImpl {
|
||||
db: db.clone(),
|
||||
crypto: pii_crypto.clone(),
|
||||
});
|
||||
let quota = std::sync::Arc::new(erp_ai::service::quota::QuotaService::new(
|
||||
db.clone(),
|
||||
@@ -584,26 +601,12 @@ async fn main() -> anyhow::Result<()> {
|
||||
}
|
||||
};
|
||||
|
||||
// Build shared state
|
||||
|
||||
// Start auto trend analysis (every 24h, scans high-risk patients)
|
||||
erp_ai::service::auto_analysis::start_auto_analysis(ai_state.clone());
|
||||
tracing::info!("Auto trend analysis scheduler started");
|
||||
|
||||
// Build shared state
|
||||
let pii_crypto = if config.crypto.kek == "__MUST_SET_VIA_ENV__" {
|
||||
#[cfg(debug_assertions)]
|
||||
{
|
||||
tracing::warn!("⚠️ PII KEK 使用开发默认值,仅用于本地开发");
|
||||
erp_core::crypto::PiiCrypto::dev_default()
|
||||
}
|
||||
#[cfg(not(debug_assertions))]
|
||||
{
|
||||
panic!("ERP__CRYPTO__KEK must be set in production. Use a 64-char hex string (32 bytes).");
|
||||
}
|
||||
} else {
|
||||
erp_core::crypto::PiiCrypto::from_kek_hex(&config.crypto.kek)
|
||||
.expect("PII KEK must be valid 64-char hex (32 bytes). Set ERP__CRYPTO__KEK")
|
||||
};
|
||||
|
||||
let state = AppState {
|
||||
db,
|
||||
config,
|
||||
|
||||
Reference in New Issue
Block a user