- AnalysisType 新增 FollowUpSummary 变体(as_str/prompt_name) - HealthDataProvider 新增 get_follow_up_summary_data() + FollowUpSummaryDataDto - erp-health 实现随访数据查询(task + records + PII 解密) - 新增 /ai/analyze/follow-up-summary SSE 端点 - SanitizationService 新增 sanitize_follow_up_data() - 前端 analysisSse.ts/AiAnalysisCard 支持 follow-up-summary 类型 - FollowUpTaskList 操作列新增「AI 小结」按钮
229 lines
5.9 KiB
Rust
229 lines
5.9 KiB
Rust
use async_trait::async_trait;
|
||
use serde::{Deserialize, Serialize};
|
||
use uuid::Uuid;
|
||
|
||
use crate::error::AppResult;
|
||
|
||
/// 健康数据提供者 trait,由 erp-health 实现
|
||
/// 返回的 DTO 已脱去 PII(姓名、身份证号等),只包含年龄/性别/医疗数据
|
||
#[async_trait]
|
||
pub trait HealthDataProvider: Send + Sync {
|
||
/// 获取化验报告(指标列表)
|
||
async fn get_lab_report(&self, tenant_id: Uuid, report_id: Uuid) -> AppResult<LabReportDto>;
|
||
|
||
/// 获取生命体征趋势数据
|
||
async fn get_vital_signs(
|
||
&self,
|
||
tenant_id: Uuid,
|
||
patient_id: Uuid,
|
||
metrics: &[String],
|
||
range: &TimeRange,
|
||
) -> AppResult<Vec<VitalSignDto>>;
|
||
|
||
/// 获取患者摘要(用于个性化方案)
|
||
async fn get_patient_summary(
|
||
&self,
|
||
tenant_id: Uuid,
|
||
patient_id: Uuid,
|
||
) -> AppResult<PatientSummaryDto>;
|
||
|
||
/// 获取完整健康报告(用于摘要生成)
|
||
async fn get_full_report(&self, tenant_id: Uuid, report_id: Uuid)
|
||
-> AppResult<HealthReportDto>;
|
||
|
||
/// 获取趋势分析预计算数据(统计摘要 + 异常检测)
|
||
async fn get_trend_analysis_data(
|
||
&self,
|
||
tenant_id: Uuid,
|
||
patient_id: Uuid,
|
||
metrics: &[String],
|
||
range: &TimeRange,
|
||
) -> AppResult<TrendAnalysisDto>;
|
||
|
||
/// 获取患者即将到来的预约
|
||
async fn get_upcoming_appointments(
|
||
&self,
|
||
tenant_id: Uuid,
|
||
patient_id: Uuid,
|
||
) -> AppResult<Vec<AppointmentSummaryDto>>;
|
||
|
||
/// 获取患者当前用药列表
|
||
async fn get_medication_list(
|
||
&self,
|
||
tenant_id: Uuid,
|
||
patient_id: Uuid,
|
||
) -> AppResult<Vec<MedicationSummaryDto>>;
|
||
|
||
/// 获取患者化验报告列表(简要摘要,不含指标明细)
|
||
async fn get_patient_lab_reports(
|
||
&self,
|
||
tenant_id: Uuid,
|
||
patient_id: Uuid,
|
||
limit: u64,
|
||
) -> AppResult<Vec<LabReportListItemDto>>;
|
||
|
||
/// 获取随访摘要数据(任务 + 已有记录,用于 AI 生成小结)
|
||
async fn get_follow_up_summary_data(
|
||
&self,
|
||
tenant_id: Uuid,
|
||
task_id: Uuid,
|
||
) -> AppResult<FollowUpSummaryDataDto>;
|
||
}
|
||
|
||
// === DTO 定义 ===
|
||
|
||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||
pub struct TimeRange {
|
||
pub start: chrono::DateTime<chrono::Utc>,
|
||
pub end: chrono::DateTime<chrono::Utc>,
|
||
}
|
||
|
||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||
pub struct LabReportDto {
|
||
pub age_group: String,
|
||
pub sex: String,
|
||
pub department: String,
|
||
pub report_date: String,
|
||
pub items: Vec<LabItemDto>,
|
||
}
|
||
|
||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||
pub struct LabItemDto {
|
||
pub name: String,
|
||
pub value: f64,
|
||
pub unit: String,
|
||
pub reference_range: String,
|
||
pub is_abnormal: bool,
|
||
}
|
||
|
||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||
pub struct VitalSignDto {
|
||
pub metric: String,
|
||
pub values: Vec<(String, f64)>,
|
||
pub unit: String,
|
||
}
|
||
|
||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||
pub struct PatientSummaryDto {
|
||
pub age_group: String,
|
||
pub sex: String,
|
||
pub chronic_conditions: Vec<String>,
|
||
pub medications: Vec<String>,
|
||
pub family_history: Vec<String>,
|
||
pub last_checkup_date: String,
|
||
}
|
||
|
||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||
pub struct HealthReportDto {
|
||
pub age_group: String,
|
||
pub sex: String,
|
||
pub department: String,
|
||
pub report_date: String,
|
||
pub sections: Vec<ReportSectionDto>,
|
||
}
|
||
|
||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||
pub struct ReportSectionDto {
|
||
pub title: String,
|
||
pub findings: Vec<String>,
|
||
pub abnormal_items: Vec<String>,
|
||
}
|
||
|
||
// === 趋势分析 DTO ===
|
||
|
||
/// 趋势方向
|
||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||
#[serde(rename_all = "lowercase")]
|
||
pub enum TrendDirection {
|
||
Rising,
|
||
Falling,
|
||
Stable,
|
||
}
|
||
|
||
/// 趋势分析整体 DTO
|
||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||
pub struct TrendAnalysisDto {
|
||
pub patient_id: Uuid,
|
||
pub period_start: String,
|
||
pub period_end: String,
|
||
pub metrics: Vec<MetricTrendAnalysis>,
|
||
}
|
||
|
||
/// 单个指标的趋势分析结果
|
||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||
pub struct MetricTrendAnalysis {
|
||
pub metric: String,
|
||
pub unit: String,
|
||
pub data_point_count: usize,
|
||
/// 线性回归统计(数据不足时为 None)
|
||
pub regression: Option<RegressionStats>,
|
||
/// 检测到的异常点
|
||
pub anomalies: Vec<AnomalyInfo>,
|
||
}
|
||
|
||
/// 线性回归统计摘要
|
||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||
pub struct RegressionStats {
|
||
pub slope: f64,
|
||
pub intercept: f64,
|
||
pub r_squared: f64,
|
||
pub direction: TrendDirection,
|
||
pub daily_change: f64,
|
||
pub period_change: f64,
|
||
}
|
||
|
||
/// 异常点信息
|
||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||
pub struct AnomalyInfo {
|
||
pub date: String,
|
||
pub value: f64,
|
||
pub mean: f64,
|
||
pub std_dev: f64,
|
||
pub deviation: f64,
|
||
}
|
||
|
||
// === Agent 新增 DTO ===
|
||
|
||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||
pub struct AppointmentSummaryDto {
|
||
pub id: Uuid,
|
||
pub department: String,
|
||
pub doctor_name: String,
|
||
pub scheduled_at: String,
|
||
pub status: String,
|
||
}
|
||
|
||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||
pub struct MedicationSummaryDto {
|
||
pub name: String,
|
||
pub dosage: String,
|
||
pub frequency: String,
|
||
}
|
||
|
||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||
pub struct LabReportListItemDto {
|
||
pub id: Uuid,
|
||
pub report_type: String,
|
||
pub report_date: String,
|
||
pub abnormal_count: usize,
|
||
}
|
||
|
||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||
pub struct FollowUpSummaryDataDto {
|
||
pub task_id: Uuid,
|
||
pub patient_id: Uuid,
|
||
pub follow_up_type: String,
|
||
pub planned_date: String,
|
||
pub task_status: String,
|
||
pub records: Vec<FollowUpRecordDto>,
|
||
}
|
||
|
||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||
pub struct FollowUpRecordDto {
|
||
pub executed_date: String,
|
||
pub result: String,
|
||
pub patient_condition: Option<String>,
|
||
pub medical_advice: Option<String>,
|
||
pub next_follow_up_date: Option<String>,
|
||
}
|