use axum::Extension; use axum::extract::{FromRef, Json, Path, Query, State}; use erp_core::error::AppError; use erp_core::rbac::require_permission; use erp_core::types::{ApiResponse, PaginatedResponse, TenantContext}; use serde::Deserialize; use validator::Validate; use crate::dto::consent_dto::*; use crate::service::consent_service; use crate::state::HealthState; #[derive(Debug, Deserialize, utoipa::IntoParams)] pub struct ConsentListParams { pub page: Option, pub page_size: Option, } #[utoipa::path( get, path = "/health/patients/{patient_id}/consents", responses((status = 200, description = "知情同意列表")), tag = "知情同意", security(("bearer_auth" = [])), )] pub async fn list_consents( State(state): State, Extension(ctx): Extension, Path(patient_id): Path, Query(params): Query, ) -> Result>>, AppError> where HealthState: FromRef, S: Clone + Send + Sync + 'static, { require_permission(&ctx, "health.consent.list")?; let page = params.page.unwrap_or(1); let page_size = params.page_size.unwrap_or(20); let result = consent_service::list_consents(&state, ctx.tenant_id, patient_id, page, page_size).await?; Ok(Json(ApiResponse::ok(result))) } #[utoipa::path( post, path = "/health/consents", responses((status = 200, description = "授权成功")), tag = "知情同意", security(("bearer_auth" = [])), )] pub async fn grant_consent( State(state): State, Extension(ctx): Extension, Json(req): Json, ) -> Result>, AppError> where HealthState: FromRef, S: Clone + Send + Sync + 'static, { require_permission(&ctx, "health.consent.manage")?; let mut req = req; req.sanitize(); let result = consent_service::grant_consent(&state, ctx.tenant_id, Some(ctx.user_id), req).await?; Ok(Json(ApiResponse::ok(result))) } #[utoipa::path( put, path = "/health/consents/{consent_id}/revoke", responses((status = 200, description = "撤销成功")), tag = "知情同意", security(("bearer_auth" = [])), )] pub async fn revoke_consent( State(state): State, Extension(ctx): Extension, Path(consent_id): Path, Json(req): Json, ) -> Result>, AppError> where HealthState: FromRef, S: Clone + Send + Sync + 'static, { require_permission(&ctx, "health.consent.manage")?; let mut req = req; req.sanitize(); let result = consent_service::revoke_consent(&state, ctx.tenant_id, consent_id, Some(ctx.user_id), req) .await?; Ok(Json(ApiResponse::ok(result))) } /// 患者端签署知情同意 — 验证 consent 归属当前患者后更新状态为 granted #[utoipa::path( post, path = "/health/consents/{consent_id}/patient-sign", request_body = PatientSignConsentReq, responses( (status = 200, description = "签署成功"), (status = 400, description = "状态不允许签署或不属于该患者"), (status = 404, description = "知情同意记录不存在"), ), tag = "知情同意", security(("bearer_auth" = [])), )] pub async fn patient_sign_consent( State(state): State, Extension(ctx): Extension, Path(consent_id): Path, Json(req): Json, ) -> Result>, AppError> where HealthState: FromRef, S: Clone + Send + Sync + 'static, { // 患者自己签署,只需认证,不需要特殊权限 req.validate() .map_err(|e| AppError::Validation(e.to_string()))?; let result = consent_service::patient_sign_consent(&state, ctx.tenant_id, ctx.user_id, consent_id, req) .await?; Ok(Json(ApiResponse::ok(result))) }