后端: - alert_service: list_alerts 批量查询 patient_name 填充 AlertResponse - consultation_service: list_sessions 批量查询 patient_name/doctor_name - erp-ai handler: list_analysis 通过 raw SQL 查询 patient_name 前端: - AlertList/AlertDashboard: 使用后端返回的 patient_name 替代 ID 截断 - ConsultationDetail: 使用 patient_name/doctor_name 替代 ID 截断 - AiAnalysisList: 使用 patient_name 替代 ID 截断 - constants/health: SEVERITY 补 high/medium, STATUS 补 active - AdminDashboard: 医护人数改为 API 查询(useStatsData 新增 doctorCount) - DeviceManage: 患者 ID 输入改为 PatientSelect 搜索选择器
85 lines
2.8 KiB
TypeScript
85 lines
2.8 KiB
TypeScript
import { useEffect, useState, useCallback } from 'react';
|
|
import {
|
|
pointsApi,
|
|
type PatientStatistics,
|
|
type ConsultationStatistics,
|
|
type FollowUpStatistics,
|
|
type PointsStatistics,
|
|
type HealthDataStats,
|
|
type DialysisStatistics,
|
|
} from '../../../api/health/points';
|
|
import { doctorApi } from '../../../api/health/doctors';
|
|
|
|
export interface StatsData {
|
|
patientStats: PatientStatistics | null;
|
|
consultationStats: ConsultationStatistics | null;
|
|
followUpStats: FollowUpStatistics | null;
|
|
pointsStats: PointsStatistics | null;
|
|
healthDataStats: HealthDataStats | null;
|
|
dialysisStats: DialysisStatistics | null;
|
|
doctorCount: number;
|
|
loading: boolean;
|
|
error: string | null;
|
|
refresh: () => void;
|
|
}
|
|
|
|
export function useStatsData(): StatsData {
|
|
const [loading, setLoading] = useState(true);
|
|
const [error, setError] = useState<string | null>(null);
|
|
|
|
const [patientStats, setPatientStats] = useState<PatientStatistics | null>(null);
|
|
const [consultationStats, setConsultationStats] = useState<ConsultationStatistics | null>(null);
|
|
const [followUpStats, setFollowUpStats] = useState<FollowUpStatistics | null>(null);
|
|
const [pointsStats, setPointsStats] = useState<PointsStatistics | null>(null);
|
|
const [healthDataStats, setHealthDataStats] = useState<HealthDataStats | null>(null);
|
|
const [dialysisStats, setDialysisStats] = useState<DialysisStatistics | null>(null);
|
|
const [doctorCount, setDoctorCount] = useState(0);
|
|
|
|
const fetchAllStats = useCallback(async () => {
|
|
setLoading(true);
|
|
setError(null);
|
|
|
|
let hasAnyError = false;
|
|
const errors: string[] = [];
|
|
|
|
const tryFetch = async <T,>(fn: () => Promise<T>, setter: (v: T) => void, label: string) => {
|
|
try {
|
|
const data = await fn();
|
|
setter(data);
|
|
} catch {
|
|
hasAnyError = true;
|
|
errors.push(label);
|
|
}
|
|
};
|
|
|
|
await Promise.all([
|
|
tryFetch(pointsApi.getPatientStats, setPatientStats, '患者'),
|
|
tryFetch(pointsApi.getConsultationStats, setConsultationStats, '咨询'),
|
|
tryFetch(pointsApi.getFollowUpStats, setFollowUpStats, '随访'),
|
|
tryFetch(pointsApi.getStatistics, setPointsStats, '积分'),
|
|
tryFetch(pointsApi.getHealthDataStats, setHealthDataStats, '健康数据'),
|
|
tryFetch(pointsApi.getDialysisStats, setDialysisStats, '透析'),
|
|
tryFetch(
|
|
async () => { const r = await doctorApi.list({ page: 1, page_size: 1 }); return r.total; },
|
|
setDoctorCount,
|
|
'医护',
|
|
),
|
|
]);
|
|
|
|
if (hasAnyError && errors.length === 7) {
|
|
setError('加载统计数据失败');
|
|
}
|
|
|
|
setLoading(false);
|
|
}, []);
|
|
|
|
useEffect(() => {
|
|
fetchAllStats();
|
|
}, [fetchAllStats]);
|
|
|
|
return {
|
|
patientStats, consultationStats, followUpStats, pointsStats, healthDataStats, dialysisStats, doctorCount,
|
|
loading, error, refresh: fetchAllStats,
|
|
};
|
|
}
|