import { useCallback, useEffect, useState } from 'react'; import { useI18n } from './i18n/I18nContext'; import { getPromptTemplates, createDiagnosis, listDiagnoses, deleteDiagnosis, getAiStatus, } from './api/ai'; import { getDinsarResults } from './api/dinsar'; import AiDiagnosisModal from './components/AiDiagnosisModal'; import TaskStatusPanel from './components/tasks/TaskStatusPanel'; import useTaskMonitor from './hooks/useTaskMonitor'; const cardStyle = { background: '#fff', padding: '12px', borderRadius: '8px', border: '1px solid #e2e8f0', marginBottom: '12px', }; export default function AiAnalysisPanel({ readOnly = false, onJobQueued }) { const { en } = useI18n(); const aiTaskMonitor = useTaskMonitor({ taskTypes: ['AI_DIAGNOSIS'], showRecent: true, recentLimit: 1, }); // 状态 const [aiStatus, setAiStatus] = useState(null); const [promptTemplates, setPromptTemplates] = useState({}); const [dinsarResults, setDinsarResults] = useState([]); const [diagnoses, setDiagnoses] = useState([]); const [totalDiagnoses, setTotalDiagnoses] = useState(0); const [currentPage, setCurrentPage] = useState(1); const [pageSize] = useState(20); const [loading, setLoading] = useState(false); const [message, setMessage] = useState(''); // 表单状态 const [selectedResultId, setSelectedResultId] = useState(''); const [selectedModel, setSelectedModel] = useState('llama3.2-vision'); const [selectedTemplate, setSelectedTemplate] = useState('standard'); const [customPrompt, setCustomPrompt] = useState(''); const [useCustomPrompt, setUseCustomPrompt] = useState(false); // 过滤器 const [filterResultId, setFilterResultId] = useState(''); const [filterRiskLevel, setFilterRiskLevel] = useState(''); // Modal const [selectedDiagnosis, setSelectedDiagnosis] = useState(null); // 加载初始数据 const loadInitialData = useCallback(async () => { try { const [status, templates, results] = await Promise.all([ getAiStatus(), getPromptTemplates(), getDinsarResults({ limit: 100, offset: 0 }), ]); setAiStatus(status); setPromptTemplates(templates); // 兼容不同的响应格式 const resultsList = results.results || results.items || []; setDinsarResults(resultsList); if (resultsList.length === 0) { setMessage(en ? 'No D-InSAR results found. Please scan data first.' : '未找到 D-InSAR 结果,请先扫描数据。'); } } catch (error) { console.error('Failed to load initial data:', error); setMessage(en ? `Failed to load data: ${error.message}` : `加载数据失败: ${error.message}`); } }, [en]); useEffect(() => { loadInitialData(); }, [loadInitialData]); useEffect(() => { const models = aiStatus?.ollama_vlm_models || []; if (models.length > 0 && !models.includes(selectedModel)) { setSelectedModel(aiStatus?.default_vlm_model && models.includes(aiStatus.default_vlm_model) ? aiStatus.default_vlm_model : models[0]); } }, [aiStatus, selectedModel]); // 加载诊断列表 const loadDiagnoses = useCallback(async () => { setLoading(true); try { const params = { page: currentPage, page_size: pageSize, }; if (filterResultId) params.result_id = parseInt(filterResultId); if (filterRiskLevel) params.risk_level = filterRiskLevel; const data = await listDiagnoses(params); setDiagnoses(data.items || []); setTotalDiagnoses(data.total || 0); } catch (error) { console.error('Failed to load diagnoses:', error); setMessage(en ? 'Failed to load diagnoses' : '加载诊断列表失败'); } finally { setLoading(false); } }, [currentPage, pageSize, filterResultId, filterRiskLevel, en]); useEffect(() => { loadDiagnoses(); }, [loadDiagnoses]); // 创建诊断 const handleCreateDiagnosis = async () => { if (readOnly) { setMessage(en ? 'Read-only account cannot create diagnosis' : '只读账号无法创建诊断'); return; } if (!selectedResultId) { setMessage(en ? 'Please select a D-InSAR result' : '请选择 D-InSAR 结果'); return; } if (!aiStatus?.ollama_online) { setMessage(en ? 'Failed: Ollama is offline' : '失败: Ollama 未在线'); return; } if (!aiStatus?.ollama_vlm_models?.length) { setMessage(en ? 'Failed: no local Ollama vision model is installed' : '失败: 未检测到本机 Ollama 视觉模型'); return; } setLoading(true); setMessage(''); try { const payload = { result_id: parseInt(selectedResultId), model_name: selectedModel, prompt_template: selectedTemplate, }; if (useCustomPrompt && customPrompt.trim()) { payload.custom_prompt = customPrompt.trim(); } const diagnosis = await createDiagnosis(payload); setMessage(en ? 'Diagnosis task created' : '诊断任务已创建'); if (diagnosis.task_id) { onJobQueued?.(diagnosis.task_id); } // 刷新列表 setTimeout(() => loadDiagnoses(), 1000); } catch (error) { const detail = error?.response?.data?.detail || error?.message || (en ? 'Unknown error' : '未知错误'); setMessage(`${en ? 'Failed' : '失败'}: ${detail}`); } finally { setLoading(false); } }; // 删除诊断 const handleDeleteDiagnosis = async (diagnosisId) => { if (readOnly) { setMessage(en ? 'Read-only account cannot delete' : '只读账号无法删除'); return; } if (!confirm(en ? 'Delete this diagnosis?' : '确认删除此诊断记录?')) return; try { await deleteDiagnosis(diagnosisId); setMessage(en ? 'Diagnosis deleted' : '诊断记录已删除'); loadDiagnoses(); } catch { setMessage(en ? 'Failed to delete' : '删除失败'); } }; // 查看诊断详情 const handleViewDiagnosis = (diagnosis) => { setSelectedDiagnosis(diagnosis); }; const riskLevelColors = { low: '#48bb78', medium: '#ed8936', high: '#f56565', critical: '#c53030', }; const ollamaVlmModels = aiStatus?.ollama_vlm_models || []; const modelOptions = ollamaVlmModels.length > 0 ? ollamaVlmModels : [aiStatus?.default_vlm_model || selectedModel].filter(Boolean); const canCreateDiagnosis = !!selectedResultId && !!aiStatus?.ollama_online && ollamaVlmModels.length > 0; const totalPages = Math.ceil(totalDiagnoses / pageSize); return (
{/* Header */}

{en ? 'D-InSAR Diagnosis' : 'D-InSAR诊断'}

{/* Content */}
{/* Ollama Status */}
{en ? 'Ollama Status' : 'Ollama 状态'}
{aiStatus && (
{en ? 'Online' : '在线'}: {aiStatus.ollama_online ? (en ? 'Yes' : '是') : (en ? 'No' : '否')}
)}
{/* Create Diagnosis Form */}

{en ? 'Create Diagnosis' : '创建诊断'}

{/* D-InSAR Result Selection */}
{dinsarResults.length === 0 && (
{en ? 'No D-InSAR results found. Please go to "D-InSAR Results" tab and scan data first.' : '未找到 D-InSAR 结果。请前往"D-InSAR 结果"选项卡先扫描数据。'}
)}
{/* Model Selection */}
{aiStatus?.ollama_online && ollamaVlmModels.length === 0 && (
{en ? 'Ollama is online, but no local vision model is installed.' : 'Ollama 已在线,但未检测到本机视觉模型。'}
)}
{/* Prompt Template Selection */}
{/* Custom Prompt Toggle */}
{/* Custom Prompt Textarea */} {useCustomPrompt && (