fix: 修复多角色找茬测试 V2 发现的 11 个问题
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

P0 (CRITICAL):
- C1: 统计 API 全部改为 safe_aggregate 容错,防止单个子查询崩溃导致 500
- C2: Token 刷新增加用户身份验证,防止并发场景下身份切换
- C3: 患者端线下活动接口添加患者档案验证,防止 Doctor/HM 越权访问

P1 (HIGH):
- H1: 操作记录用 EntityName 组件解析用户名,不再显示截断 UUID
- H4: 告警标题添加中英文映射 (translateAlertTitle)
- H5: 告警面板补全 message import + 修复 hooks 顺序
- H8: 咨询消息发送按钮添加 AuthButton 权限控制
- H9: routeConfig 日常监测权限码改为 health.daily-monitoring.*

P2 (MEDIUM):
- M4: 咨询类型映射补全 online/phone/doctor/follow_up 中文标签

DTO: LabReportStatisticsResp, AppointmentStatisticsResp, VitalSignsReportRateResp 添加 Default derive
This commit is contained in:
iven
2026-05-08 12:42:41 +08:00
parent 297a151b0c
commit 22b8ac7ac6
11 changed files with 1443 additions and 619 deletions

View File

@@ -42,7 +42,7 @@ pub struct DashboardStatsResp {
// 健康数据统计
// ---------------------------------------------------------------------------
#[derive(Debug, Serialize, Deserialize, ToSchema)]
#[derive(Debug, Default, Serialize, Deserialize, ToSchema)]
pub struct LabReportStatisticsResp {
pub total_reports: i64,
pub this_month: i64,
@@ -56,7 +56,7 @@ pub struct LabReportStatisticsResp {
pub reviewed: i64,
}
#[derive(Debug, Serialize, Deserialize, ToSchema)]
#[derive(Debug, Default, Serialize, Deserialize, ToSchema)]
pub struct AppointmentStatisticsResp {
pub total_appointments: i64,
pub this_month: i64,
@@ -68,7 +68,7 @@ pub struct AppointmentStatisticsResp {
pub cancel_rate: f64,
}
#[derive(Debug, Serialize, Deserialize, ToSchema)]
#[derive(Debug, Default, Serialize, Deserialize, ToSchema)]
pub struct VitalSignsReportRateResp {
/// 总患者数
pub total_patients: i64,
@@ -131,7 +131,7 @@ pub struct PersonalStatsResp {
// 通用结构
// ---------------------------------------------------------------------------
#[derive(Debug, Serialize, Deserialize, ToSchema)]
#[derive(Debug, Default, Serialize, Deserialize, ToSchema)]
pub struct NameValue {
pub name: String,
pub value: i64,

View File

@@ -179,6 +179,8 @@ where
S: Clone + Send + Sync + 'static,
{
require_permission(&ctx, "health.points.list")?;
// 患者端端点:验证当前用户有关联的患者档案
let _patient_id = resolve_patient_id(&state, ctx.tenant_id, ctx.user_id).await?;
let page = params.page.unwrap_or(1);
let page_size = params.page_size.unwrap_or(20);
let result =

View File

@@ -31,7 +31,11 @@ where
S: Clone + Send + Sync + 'static,
{
require_permission(&ctx, "health.consultation.list")?;
let result = stats_service::get_consultation_statistics(&state, ctx.tenant_id).await?;
let result = safe_aggregate(
stats_service::get_consultation_statistics(&state, ctx.tenant_id),
"咨询统计",
)
.await;
Ok(Json(ApiResponse::ok(result)))
}
@@ -96,7 +100,11 @@ where
S: Clone + Send + Sync + 'static,
{
require_permission(&ctx, "health.patient.list")?;
let result = stats_service::get_lab_report_statistics(&state, ctx.tenant_id).await?;
let result = safe_aggregate(
stats_service::get_lab_report_statistics(&state, ctx.tenant_id),
"化验报告统计",
)
.await;
Ok(Json(ApiResponse::ok(result)))
}
@@ -109,7 +117,11 @@ where
S: Clone + Send + Sync + 'static,
{
require_permission(&ctx, "health.patient.list")?;
let result = stats_service::get_appointment_statistics(&state, ctx.tenant_id).await?;
let result = safe_aggregate(
stats_service::get_appointment_statistics(&state, ctx.tenant_id),
"预约统计",
)
.await;
Ok(Json(ApiResponse::ok(result)))
}
@@ -122,7 +134,11 @@ where
S: Clone + Send + Sync + 'static,
{
require_permission(&ctx, "health.patient.list")?;
let result = stats_service::get_vital_signs_report_rate(&state, ctx.tenant_id).await?;
let result = safe_aggregate(
stats_service::get_vital_signs_report_rate(&state, ctx.tenant_id),
"体征上报率统计",
)
.await;
Ok(Json(ApiResponse::ok(result)))
}
@@ -135,8 +151,26 @@ where
S: Clone + Send + Sync + 'static,
{
require_permission(&ctx, "health.patient.list")?;
let result = stats_service::get_health_data_stats(&state, ctx.tenant_id).await?;
Ok(Json(ApiResponse::ok(result)))
let lab_reports = safe_aggregate(
stats_service::get_lab_report_statistics(&state, ctx.tenant_id),
"化验报告统计",
)
.await;
let appointments = safe_aggregate(
stats_service::get_appointment_statistics(&state, ctx.tenant_id),
"预约统计",
)
.await;
let vital_signs_report_rate = safe_aggregate(
stats_service::get_vital_signs_report_rate(&state, ctx.tenant_id),
"体征上报率统计",
)
.await;
Ok(Json(ApiResponse::ok(HealthDataStatsResp {
lab_reports,
appointments,
vital_signs_report_rate,
})))
}
// ---------------------------------------------------------------------------