- 修复 stores/auth.ts 三种登录方式从错误路径提取 roles(resp.roles → resp.user.roles) - 首页添加医护人员自动跳转医生端(useDidShow + isMedicalStaff) - services/auth.ts credentialLogin 返回类型补全 roles 字段 - Web 前端 healthData.ts 字段对齐后端 DTO(indicators→items, content→overall_assessment) - Web 前端 medicationReminders.ts 字段对齐(time_slots→reminder_times) - 小程序 report.ts / reports 页面字段对齐后端(indicators→items, doctor_interpretation→doctor_notes) - 小程序 patient.ts / followup.ts / alert.ts 补全缺失字段 - 后端 stats_handler.rs 权限码修正(health.patient.list→health.dashboard.manage) - 新增 V1 E2E 测试报告和五专家组评审报告
305 lines
7.8 KiB
TypeScript
305 lines
7.8 KiB
TypeScript
import client from '../client';
|
|
import type { PaginatedResponse } from '../types';
|
|
|
|
// --- Types ---
|
|
export interface VitalSigns {
|
|
id: string;
|
|
patient_id: string;
|
|
record_date: string;
|
|
systolic_bp_morning?: number;
|
|
diastolic_bp_morning?: number;
|
|
systolic_bp_evening?: number;
|
|
diastolic_bp_evening?: number;
|
|
heart_rate?: number;
|
|
weight?: number;
|
|
blood_sugar?: number;
|
|
water_intake_ml?: number;
|
|
urine_output_ml?: number;
|
|
notes?: string;
|
|
created_at: string;
|
|
updated_at: string;
|
|
version: number;
|
|
}
|
|
|
|
export interface CreateVitalSignsReq {
|
|
record_date: string;
|
|
systolic_bp_morning?: number;
|
|
diastolic_bp_morning?: number;
|
|
systolic_bp_evening?: number;
|
|
diastolic_bp_evening?: number;
|
|
heart_rate?: number;
|
|
weight?: number;
|
|
blood_sugar?: number;
|
|
water_intake_ml?: number;
|
|
urine_output_ml?: number;
|
|
notes?: string;
|
|
}
|
|
|
|
export interface LabReport {
|
|
id: string;
|
|
patient_id: string;
|
|
report_date: string;
|
|
report_type: string;
|
|
items?: unknown;
|
|
image_urls?: string[];
|
|
doctor_notes?: string;
|
|
source?: string;
|
|
status: string;
|
|
reviewed_by?: string;
|
|
reviewed_at?: string;
|
|
created_at: string;
|
|
updated_at: string;
|
|
version: number;
|
|
}
|
|
|
|
export interface CreateLabReportReq {
|
|
report_date: string;
|
|
report_type: string;
|
|
items?: unknown;
|
|
image_urls?: string[];
|
|
doctor_notes?: string;
|
|
}
|
|
|
|
export interface HealthRecord {
|
|
id: string;
|
|
patient_id: string;
|
|
record_type: string;
|
|
record_date: string;
|
|
overall_assessment?: string;
|
|
report_file_url?: string;
|
|
source?: string;
|
|
notes?: string;
|
|
created_at: string;
|
|
updated_at: string;
|
|
version: number;
|
|
}
|
|
|
|
export interface CreateHealthRecordReq {
|
|
record_type: string;
|
|
record_date: string;
|
|
overall_assessment?: string;
|
|
report_file_url?: string;
|
|
}
|
|
|
|
export interface DailyMonitoring {
|
|
id: string;
|
|
patient_id: string;
|
|
record_date: string;
|
|
morning_bp_systolic?: number;
|
|
morning_bp_diastolic?: number;
|
|
evening_bp_systolic?: number;
|
|
evening_bp_diastolic?: number;
|
|
weight?: number;
|
|
blood_sugar?: number;
|
|
fluid_intake?: number;
|
|
urine_output?: number;
|
|
notes?: string;
|
|
created_at: string;
|
|
updated_at: string;
|
|
version: number;
|
|
}
|
|
|
|
export interface CreateDailyMonitoringReq {
|
|
patient_id: string;
|
|
record_date: string;
|
|
morning_bp_systolic?: number;
|
|
morning_bp_diastolic?: number;
|
|
evening_bp_systolic?: number;
|
|
evening_bp_diastolic?: number;
|
|
weight?: number;
|
|
blood_sugar?: number;
|
|
fluid_intake?: number;
|
|
urine_output?: number;
|
|
notes?: string;
|
|
}
|
|
|
|
export interface TrendData {
|
|
id: string;
|
|
patient_id: string;
|
|
indicator: string;
|
|
trend_data: { date: string; value: number }[];
|
|
generated_at: string;
|
|
}
|
|
|
|
// --- API ---
|
|
export const healthDataApi = {
|
|
// Vital Signs
|
|
listVitalSigns: async (
|
|
patientId: string,
|
|
params: { page?: number; page_size?: number },
|
|
) => {
|
|
const { data } = await client.get<{
|
|
success: boolean;
|
|
data: PaginatedResponse<VitalSigns>;
|
|
}>(`/health/patients/${patientId}/vital-signs`, { params });
|
|
return data.data;
|
|
},
|
|
|
|
createVitalSigns: async (patientId: string, req: CreateVitalSignsReq) => {
|
|
const { data } = await client.post<{
|
|
success: boolean;
|
|
data: VitalSigns;
|
|
}>(`/health/patients/${patientId}/vital-signs`, req);
|
|
return data.data;
|
|
},
|
|
|
|
updateVitalSigns: async (
|
|
patientId: string,
|
|
id: string,
|
|
req: Partial<CreateVitalSignsReq> & { version: number },
|
|
) => {
|
|
const { data } = await client.put<{
|
|
success: boolean;
|
|
data: VitalSigns;
|
|
}>(`/health/patients/${patientId}/vital-signs/${id}`, req);
|
|
return data.data;
|
|
},
|
|
|
|
deleteVitalSigns: async (patientId: string, id: string) => {
|
|
await client.delete(`/health/patients/${patientId}/vital-signs/${id}`);
|
|
},
|
|
|
|
// Lab Reports
|
|
listLabReports: async (
|
|
patientId: string,
|
|
params: { page?: number; page_size?: number },
|
|
) => {
|
|
const { data } = await client.get<{
|
|
success: boolean;
|
|
data: PaginatedResponse<LabReport>;
|
|
}>(`/health/patients/${patientId}/lab-reports`, { params });
|
|
return data.data;
|
|
},
|
|
|
|
createLabReport: async (patientId: string, req: CreateLabReportReq) => {
|
|
const { data } = await client.post<{
|
|
success: boolean;
|
|
data: LabReport;
|
|
}>(`/health/patients/${patientId}/lab-reports`, req);
|
|
return data.data;
|
|
},
|
|
|
|
updateLabReport: async (
|
|
patientId: string,
|
|
id: string,
|
|
req: Partial<CreateLabReportReq> & { version: number },
|
|
) => {
|
|
const { data } = await client.put<{
|
|
success: boolean;
|
|
data: LabReport;
|
|
}>(`/health/patients/${patientId}/lab-reports/${id}`, req);
|
|
return data.data;
|
|
},
|
|
|
|
deleteLabReport: async (patientId: string, id: string) => {
|
|
await client.delete(`/health/patients/${patientId}/lab-reports/${id}`);
|
|
},
|
|
|
|
reviewLabReport: async (patientId: string, reportId: string, req: { version: number; doctor_notes?: string }) => {
|
|
const { data } = await client.put<{
|
|
success: boolean;
|
|
data: Record<string, unknown>;
|
|
}>(`/health/patients/${patientId}/lab-reports/${reportId}/review`, req);
|
|
return data.data;
|
|
},
|
|
|
|
// Health Records
|
|
listHealthRecords: async (
|
|
patientId: string,
|
|
params: { page?: number; page_size?: number },
|
|
) => {
|
|
const { data } = await client.get<{
|
|
success: boolean;
|
|
data: PaginatedResponse<HealthRecord>;
|
|
}>(`/health/patients/${patientId}/health-records`, { params });
|
|
return data.data;
|
|
},
|
|
|
|
createHealthRecord: async (
|
|
patientId: string,
|
|
req: CreateHealthRecordReq,
|
|
) => {
|
|
const { data } = await client.post<{
|
|
success: boolean;
|
|
data: HealthRecord;
|
|
}>(`/health/patients/${patientId}/health-records`, req);
|
|
return data.data;
|
|
},
|
|
|
|
updateHealthRecord: async (
|
|
patientId: string,
|
|
id: string,
|
|
req: Partial<CreateHealthRecordReq> & { version: number },
|
|
) => {
|
|
const { data } = await client.put<{
|
|
success: boolean;
|
|
data: HealthRecord;
|
|
}>(`/health/patients/${patientId}/health-records/${id}`, req);
|
|
return data.data;
|
|
},
|
|
|
|
deleteHealthRecord: async (patientId: string, id: string) => {
|
|
await client.delete(`/health/patients/${patientId}/health-records/${id}`);
|
|
},
|
|
|
|
// Trends
|
|
listTrends: async (patientId: string) => {
|
|
const { data } = await client.get<{
|
|
success: boolean;
|
|
data: TrendData[];
|
|
}>(`/health/patients/${patientId}/trends`);
|
|
return data.data;
|
|
},
|
|
|
|
generateTrend: async (patientId: string, req: { indicator: string; start_date?: string; end_date?: string }) => {
|
|
const { data } = await client.post<{
|
|
success: boolean;
|
|
data: TrendData;
|
|
}>(`/health/patients/${patientId}/trends/generate`, req);
|
|
return data.data;
|
|
},
|
|
|
|
getIndicatorTimeseries: async (patientId: string, indicator: string) => {
|
|
const { data } = await client.get<{
|
|
success: boolean;
|
|
data: { date: string; value: number }[];
|
|
}>(`/health/patients/${patientId}/trends/${encodeURIComponent(indicator)}`);
|
|
return data.data;
|
|
},
|
|
|
|
// Daily Monitoring
|
|
listDailyMonitoring: async (
|
|
patientId: string,
|
|
params: { page?: number; page_size?: number },
|
|
) => {
|
|
const { data } = await client.get<{
|
|
success: boolean;
|
|
data: PaginatedResponse<DailyMonitoring>;
|
|
}>(`/health/patients/${patientId}/daily-monitoring`, { params });
|
|
return data.data;
|
|
},
|
|
|
|
createDailyMonitoring: async (req: CreateDailyMonitoringReq) => {
|
|
const { data } = await client.post<{
|
|
success: boolean;
|
|
data: DailyMonitoring;
|
|
}>('/health/daily-monitoring', req);
|
|
return data.data;
|
|
},
|
|
|
|
updateDailyMonitoring: async (
|
|
id: string,
|
|
req: Partial<CreateDailyMonitoringReq> & { version: number },
|
|
) => {
|
|
const { data } = await client.put<{
|
|
success: boolean;
|
|
data: DailyMonitoring;
|
|
}>(`/health/daily-monitoring/${id}`, req);
|
|
return data.data;
|
|
},
|
|
|
|
deleteDailyMonitoring: async (id: string, version: number) => {
|
|
await client.delete(`/health/daily-monitoring/${id}`, { data: { version } });
|
|
},
|
|
};
|