feat(health+mp): S2-3 Patient DTO 最小化
后端: - 新增 PatientSummary DTO(id/name/gender/birth_date/status 5 字段) - 新增 GET /health/patients/summary 端点(权限 health.patient.list) - patient_service::list_summaries 仅查询非敏感字段 前端: - 新增 PatientSummary 类型 + getPatientSummaries() API - auth store loadPatients 改用 summary 端点 - setCurrentPatient 仅存储非敏感字段到 secureSet
This commit is contained in:
@@ -246,3 +246,13 @@ pub struct ReferResultResp {
|
||||
pub from_doctor_id: Option<Uuid>,
|
||||
pub to_doctor_id: Uuid,
|
||||
}
|
||||
|
||||
/// 患者摘要 — 列表/切换用,不含敏感字段
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
|
||||
pub struct PatientSummary {
|
||||
pub id: Uuid,
|
||||
pub name: String,
|
||||
pub gender: Option<String>,
|
||||
pub birth_date: Option<NaiveDate>,
|
||||
pub status: String,
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@ use erp_core::types::{ApiResponse, PaginatedResponse, TenantContext};
|
||||
use crate::dto::DeleteWithVersion;
|
||||
use crate::dto::patient_dto::{
|
||||
BatchImportPatientReq, BatchResultResp, BindByPhoneReq, BindResultResp, CreatePatientReq,
|
||||
FamilyMemberReq, FamilyMemberResp, ManageTagsReq, PatientResp, ReferPatientReq,
|
||||
FamilyMemberReq, FamilyMemberResp, ManageTagsReq, PatientResp, PatientSummary, ReferPatientReq,
|
||||
ReferResultResp, UpdatePatientReq,
|
||||
};
|
||||
use crate::service::patient_service;
|
||||
@@ -57,6 +57,23 @@ where
|
||||
Ok(Json(ApiResponse::ok(result)))
|
||||
}
|
||||
|
||||
/// GET /health/patients/summary — 患者摘要列表(字段最小化,不含敏感信息)
|
||||
pub async fn list_patient_summaries<S>(
|
||||
State(state): State<HealthState>,
|
||||
Extension(ctx): Extension<TenantContext>,
|
||||
Query(params): Query<PatientListParams>,
|
||||
) -> Result<Json<ApiResponse<PaginatedResponse<PatientSummary>>>, AppError>
|
||||
where
|
||||
HealthState: FromRef<S>,
|
||||
S: Clone + Send + Sync + 'static,
|
||||
{
|
||||
require_permission(&ctx, "health.patient.list")?;
|
||||
let page = params.page.unwrap_or(1);
|
||||
let page_size = params.page_size.unwrap_or(20).min(100);
|
||||
let result = patient_service::list_summaries(&state, ctx.tenant_id, page, page_size).await?;
|
||||
Ok(Json(ApiResponse::ok(result)))
|
||||
}
|
||||
|
||||
pub async fn create_patient<S>(
|
||||
State(state): State<HealthState>,
|
||||
Extension(ctx): Extension<TenantContext>,
|
||||
|
||||
@@ -8,6 +8,10 @@ where
|
||||
S: Clone + Send + Sync + 'static,
|
||||
{
|
||||
Router::new()
|
||||
.route(
|
||||
"/health/patients/summary",
|
||||
axum::routing::get(patient_handler::list_patient_summaries),
|
||||
)
|
||||
.route(
|
||||
"/health/patients",
|
||||
axum::routing::get(patient_handler::list_patients)
|
||||
|
||||
@@ -550,3 +550,47 @@ pub async fn bind_by_phone(
|
||||
patient_name: updated.name,
|
||||
})
|
||||
}
|
||||
|
||||
/// 患者摘要列表 — 仅返回非敏感字段,供小程序切换/列表使用
|
||||
pub async fn list_summaries(
|
||||
state: &HealthState,
|
||||
tenant_id: Uuid,
|
||||
page: u64,
|
||||
page_size: u64,
|
||||
) -> HealthResult<PaginatedResponse<PatientSummary>> {
|
||||
let limit = page_size.min(100);
|
||||
let offset = page.saturating_sub(1) * limit;
|
||||
|
||||
let query = patient::Entity::find()
|
||||
.filter(patient::Column::TenantId.eq(tenant_id))
|
||||
.filter(patient::Column::DeletedAt.is_null());
|
||||
|
||||
let total = query.clone().count(&state.db).await?;
|
||||
|
||||
let models = query
|
||||
.order_by_desc(patient::Column::CreatedAt)
|
||||
.offset(offset)
|
||||
.limit(limit)
|
||||
.all(&state.db)
|
||||
.await?;
|
||||
|
||||
let total_pages = total.div_ceil(limit.max(1));
|
||||
let data: Vec<PatientSummary> = models
|
||||
.into_iter()
|
||||
.map(|m| PatientSummary {
|
||||
id: m.id,
|
||||
name: m.name,
|
||||
gender: m.gender,
|
||||
birth_date: m.birth_date,
|
||||
status: m.status,
|
||||
})
|
||||
.collect();
|
||||
|
||||
Ok(PaginatedResponse {
|
||||
data,
|
||||
total,
|
||||
page,
|
||||
page_size: limit,
|
||||
total_pages,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -14,7 +14,7 @@ mod tag;
|
||||
// 从各子模块重新导出所有公开函数,保持 handler 层调用路径不变
|
||||
pub use crud::{
|
||||
batch_import_patients, bind_by_phone, create_patient, delete_patient, get_patient,
|
||||
list_patients, update_patient,
|
||||
list_patients, list_summaries, update_patient,
|
||||
};
|
||||
pub use relation::{
|
||||
assign_doctor, create_family_member, delete_family_member, get_health_summary,
|
||||
|
||||
Reference in New Issue
Block a user