feat(health): 药物提醒后端 API + 后台任务统一 + dead code 清理
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

P1-3: medication_reminder 全栈实现
  - migration 000096: 创建 medication_reminder 表(含患者关联/提醒时间/频率)
  - entity + dto + service + handler: 完整 CRUD(乐观锁/软删除/审计日志)
  - 路由注册: GET /patients/{id}/medication-reminders, POST/PUT/DELETE
  - HealthError 新增 MedicationReminderNotFound

P2-4: 后台任务启动统一
  - appointment_reminder 迁移到 HealthModule::on_startup()(启动时立即执行 + 周期循环)
  - 删除 main.rs 中重复的 overdue_checker/points_expiration/appointment_reminder 调用
  - 所有 Health 后台任务现由模块 on_startup 统一管理

P2-5: Web dead code 清理
  - 删除 healthData.ts 中 getMiniTrend/getMiniToday(小程序专用端点,Web 无调用)
  - 删除 patients.ts 中 getHealthSummary(标记 TODO 未使用)
This commit is contained in:
iven
2026-04-30 07:18:22 +08:00
parent 30344d474f
commit 26a9781d4f
15 changed files with 529 additions and 39 deletions

View File

@@ -95,6 +95,7 @@ mod m20260429_000092_device_readings_metric;
mod m20260429_000093_trend_analysis_prompt_v2;
mod m20260429_000094_device_readings_unique_constraint;
mod m20260429_000095_seed_alert_device_menus;
mod m20260430_000096_create_medication_reminder;
pub struct Migrator;
@@ -197,6 +198,7 @@ impl MigratorTrait for Migrator {
Box::new(m20260429_000093_trend_analysis_prompt_v2::Migration),
Box::new(m20260429_000094_device_readings_unique_constraint::Migration),
Box::new(m20260429_000095_seed_alert_device_menus::Migration),
Box::new(m20260430_000096_create_medication_reminder::Migration),
]
}
}

View File

@@ -0,0 +1,53 @@
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("medication_reminder"))
.if_not_exists()
.col(ColumnDef::new(Alias::new("id")).uuid().not_null().primary_key())
.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("medication_name")).string().not_null())
.col(ColumnDef::new(Alias::new("dosage")).string())
.col(ColumnDef::new(Alias::new("frequency")).string())
.col(ColumnDef::new(Alias::new("reminder_times")).json().not_null())
.col(ColumnDef::new(Alias::new("start_date")).date())
.col(ColumnDef::new(Alias::new("end_date")).date())
.col(ColumnDef::new(Alias::new("is_active")).boolean().not_null().default(true))
.col(ColumnDef::new(Alias::new("notes")).string())
.col(ColumnDef::new(Alias::new("created_at")).timestamp_with_time_zone().not_null())
.col(ColumnDef::new(Alias::new("updated_at")).timestamp_with_time_zone().not_null())
.col(ColumnDef::new(Alias::new("created_by")).uuid())
.col(ColumnDef::new(Alias::new("updated_by")).uuid())
.col(ColumnDef::new(Alias::new("deleted_at")).timestamp_with_time_zone())
.col(ColumnDef::new(Alias::new("version")).integer().not_null().default(1))
.to_owned(),
)
.await?;
manager
.create_index(
Index::create()
.name("idx_medication_reminder_patient")
.table(Alias::new("medication_reminder"))
.col(Alias::new("tenant_id"))
.col(Alias::new("patient_id"))
.col(Alias::new("deleted_at"))
.to_owned(),
)
.await
}
async fn down(&self, manager: &SchemaManager) -> Result<(), DbErr> {
manager
.drop_table(Table::drop().table(Alias::new("medication_reminder")).to_owned())
.await
}
}