/** * 药物管理 API 服务 */ import type { DailyMedicationStats, Medication, MedicationAiAnalysisV2, MedicationForm, MedicationRecognitionTask, MedicationRecord, MedicationStatus, RepeatPattern, } from '@/types/medication'; import { api, postTextStream, type TextStreamCallbacks } from './api'; // ==================== DTO 类型定义 ==================== /** * 创建药物 DTO */ export interface CreateMedicationDto { name: string; photoUrl?: string | null; form: MedicationForm; dosageValue: number; dosageUnit: string; timesPerDay: number; medicationTimes: string[]; startDate: string; endDate?: string | null; expiryDate?: string | null; repeatPattern?: RepeatPattern; note?: string; } /** * 更新药物 DTO */ export interface UpdateMedicationDto extends Partial { id: string; isActive?: boolean; } /** * 创建服药记录 DTO */ export interface CreateMedicationRecordDto { medicationId: string; scheduledTime: string; actualTime?: string; status: MedicationStatus; note?: string; } /** * 更新服药记录 DTO */ export interface UpdateMedicationRecordDto { id: string; actualTime?: string; status?: MedicationStatus; note?: string; } /** * 获取药物列表参数 */ export interface GetMedicationsParams { isActive?: boolean; startDate?: string; endDate?: string; } /** * 获取服药记录参数 */ export interface GetMedicationRecordsParams { date?: string; medicationId?: string; startDate?: string; endDate?: string; } // ==================== API 函数 ==================== /** * 获取药物列表 * @param params 查询参数 * @returns 药物列表 */ export const getMedications = async ( params?: GetMedicationsParams ): Promise => { const queryParams = new URLSearchParams(); if (params?.startDate) { queryParams.append('startDate', params.startDate); } if (params?.endDate) { queryParams.append('endDate', params.endDate); } const query = queryParams.toString(); const path = query ? `/medications?${query}` : '/medications'; const response = await api.get<{ rows: Medication[]; total: number }>(path); // 处理不同的响应格式 if (Array.isArray(response)) { return response; } else if (response && typeof response === 'object' && 'rows' in response) { return response.rows; } else { return []; } }; /** * 根据 ID 获取单个药物 * @param id 药物 ID * @returns 药物详情 */ export const getMedicationById = async (id: string): Promise => { return api.get(`/medications/${id}`); }; /** * 创建新药物 * @param dto 创建药物数据 * @returns 创建的药物 */ export const createMedication = async ( dto: CreateMedicationDto ): Promise => { return api.post('/medications', dto); }; /** * 更新药物信息 * @param dto 更新药物数据 * @returns 更新后的药物 */ export const updateMedication = async ( dto: UpdateMedicationDto ): Promise => { const { id, ...data } = dto; return api.put(`/medications/${id}`, data); }; /** * 删除药物 * @param id 药物 ID */ export const deleteMedication = async (id: string): Promise => { return api.delete(`/medications/${id}`); }; /** * 停用药物 * @param id 药物 ID * @returns 更新后的药物 */ export const deactivateMedication = async (id: string): Promise => { return api.post(`/medications/${id}/deactivate`, {}); }; /** * 激活药物(暂不支持,需要通过更新接口实现) * @param id 药物 ID * @returns 更新后的药物 */ export const activateMedication = async (id: string): Promise => { return api.put(`/medications/${id}`, { isActive: true }); }; // ==================== 服药记录相关 ==================== /** * 获取服药记录列表 * @param params 查询参数 * @returns 服药记录列表 */ export const getMedicationRecords = async ( params: GetMedicationRecordsParams ): Promise => { const queryParams = new URLSearchParams(); if (params.date) { queryParams.append('date', params.date); } if (params.medicationId) { queryParams.append('medicationId', params.medicationId); } if (params.startDate) { queryParams.append('startDate', params.startDate); } if (params.endDate) { queryParams.append('endDate', params.endDate); } const query = queryParams.toString(); const path = query ? `/medication-records?${query}` : '/medication-records'; return api.get(path); }; /** * 获取今日服药记录 * @returns 今日服药记录列表 */ export const getTodayMedicationRecords = async (): Promise => { return api.get('/medication-records/today'); }; /** * 创建服药记录 * @param dto 创建服药记录数据 * @returns 创建的服药记录 */ export const createMedicationRecord = async ( dto: CreateMedicationRecordDto ): Promise => { return api.post('/medication-records', dto); }; /** * 更新服药记录 * @param dto 更新服药记录数据 * @returns 更新后的服药记录 */ export const updateMedicationRecord = async ( dto: UpdateMedicationRecordDto ): Promise => { const { id, ...data } = dto; return api.put(`/medication-records/${id}`, data); }; /** * 删除服药记录 * @param id 服药记录 ID */ export const deleteMedicationRecord = async (id: string): Promise => { return api.delete(`/medication-records/${id}`); }; /** * 标记药物为已服用 * @param recordId 服药记录 ID * @param actualTime 实际服药时间(可选,默认为当前时间) * @returns 更新后的服药记录 */ export const takeMedication = async ( recordId: string, actualTime?: string ): Promise => { return api.post(`/medication-records/${recordId}/take`, { actualTime: actualTime || new Date().toISOString(), }); }; /** * 标记药物为已跳过 * @param recordId 服药记录 ID * @param note 跳过原因(可选) * @returns 更新后的服药记录 */ export const skipMedication = async ( recordId: string, note?: string ): Promise => { return api.post(`/medication-records/${recordId}/skip`, { note, }); }; // ==================== 统计相关 ==================== /** * 获取指定日期的服药统计 * @param date 日期 'YYYY-MM-DD' * @returns 每日服药统计 */ export const getDailyStats = async ( date: string ): Promise => { return api.get(`/medication-stats/daily?date=${date}`); }; /** * 获取日期范围内的服药统计 * @param startDate 开始日期 * @param endDate 结束日期 * @returns 统计数据列表 */ export const getStatsRange = async ( startDate: string, endDate: string ): Promise => { return api.get( `/medication-stats/range?startDate=${startDate}&endDate=${endDate}` ); }; /** * 获取总体统计 * @returns 总体统计数据 */ export const getOverallStats = async (): Promise<{ totalMedications: number; totalRecords: number; completionRate: number; streak: number; }> => { return api.get(`/medication-stats/overall`); }; // ==================== AI 分析相关 ==================== /** * 流式获取药品 AI 分析 * @param medicationId 药品 ID * @param callbacks 流式回调 * @returns 包含 abort 方法的对象,用于取消请求 */ export async function analyzeMedicationStream( medicationId: string, callbacks: TextStreamCallbacks ) { return postTextStream( `/api/medications/${medicationId}/ai-analysis`, {}, callbacks, { timeoutMs: 120000 } ); } /** * 获取药品 AI 分析 V2 结构化报告 * @param medicationId 药品 ID * @returns 结构化 AI 分析结果 */ export async function analyzeMedicationV2( medicationId: string ): Promise { return api.post( `/api/medications/${medicationId}/ai-analysis/v2`, {} ); } // ==================== AI 药品识别任务 ==================== export interface CreateMedicationRecognitionDto { frontImageUrl: string; sideImageUrl: string; auxiliaryImageUrl?: string; } export interface ConfirmMedicationRecognitionDto { name?: string; timesPerDay?: number; medicationTimes?: string[]; startDate?: string; endDate?: string | null; note?: string; } export const createMedicationRecognitionTask = async ( dto: CreateMedicationRecognitionDto ): Promise<{ taskId: string; status: MedicationRecognitionTask['status'] }> => { return api.post('/medications/ai-recognize', dto); }; export const getMedicationRecognitionStatus = async ( taskId: string ): Promise => { return api.get(`/medications/ai-recognize/${taskId}/status`); }; export const confirmMedicationRecognition = async ( taskId: string, payload?: ConfirmMedicationRecognitionDto ): Promise => { return api.post(`/medications/ai-recognize/${taskId}/confirm`, payload ?? {}); };