export type AnalysisType = 'lab-report' | 'trends' | 'checkup-plan' | 'report-summary'; interface AnalyzeBody { report_id?: string; patient_id?: string; metrics?: string[]; } const ENDPOINT_MAP: Record = { 'lab-report': '/ai/analyze/lab-report', 'trends': '/ai/analyze/trends', 'checkup-plan': '/ai/analyze/checkup-plan', 'report-summary': '/ai/analyze/report-summary', }; export interface SseCallbacks { onChunk: (content: string, index: number) => void; onError: (message: string) => void; onDone: (analysisId: string) => void; } export async function startAnalysis( type: AnalysisType, body: AnalyzeBody, callbacks: SseCallbacks, ): Promise { const controller = new AbortController(); const endpoint = ENDPOINT_MAP[type]; const token = localStorage.getItem('hms-token'); const resp = await fetch(`/api/v1${endpoint}`, { method: 'POST', headers: { 'Content-Type': 'application/json', Authorization: `Bearer ${token}`, }, body: JSON.stringify(body), signal: controller.signal, }); if (!resp.ok) { const err = await resp.json().catch(() => ({ message: '分析请求失败' })); callbacks.onError(err?.message || `HTTP ${resp.status}`); return controller; } const reader = resp.body?.getReader(); if (!reader) { callbacks.onError('无法读取响应流'); return controller; } const decoder = new TextDecoder(); let chunkIndex = 0; let buffer = ''; (async () => { try { while (true) { const { done, value } = await reader.read(); if (done) break; buffer += decoder.decode(value, { stream: true }); const lines = buffer.split('\n'); buffer = lines.pop() || ''; for (const line of lines) { if (line.startsWith('data: ')) { const data = line.slice(6); if (data === '[DONE]') { continue; } try { const event = JSON.parse(data); if (event.type === 'chunk' && event.content) { callbacks.onChunk(event.content, chunkIndex++); } else if (event.type === 'done' && event.analysis_id) { callbacks.onDone(event.analysis_id); } else if (event.type === 'error') { callbacks.onError(event.message || '分析出错'); } } catch { // 非 JSON 行,跳过 } } } } } catch (err) { if (!controller.signal.aborted) { callbacks.onError(err instanceof Error ? err.message : '连接中断'); } } })(); return controller; }