import React, { useCallback, useEffect, useState } from 'react'; import { scanDinsarResults } from './api/dinsar'; import { extractDispResults } from './api/idl'; import { clearTaskLogs, deleteTaskLog, getActiveTasks, getTaskLogs } from './api/tasks'; import DinsarCatalogPanel from './components/DinsarCatalogPanel'; const card = { background: '#fff', padding: '12px', borderRadius: '8px', border: '1px solid #e2e8f0', marginBottom: '12px', }; const PRODUCT_TASK_TYPES = [ 'SCAN_DINSAR', 'PUBLISH_DINSAR_PRODUCTS', 'REBUILD_DINSAR_CATALOG', ]; const TASK_TYPE_LABEL = { SCAN_DINSAR: 'D-InSAR结果扫描', PUBLISH_DINSAR_PRODUCTS: 'D-InSAR产物发布', REBUILD_DINSAR_CATALOG: 'D-InSAR目录重建', }; const STATUS_LABEL = { PENDING: '等待中', RUNNING: '运行中', COMPLETED: '已完成', FAILED: '失败', CANCELLED: '已取消', CANCELED: '已取消', }; function formatTaskType(taskType) { return TASK_TYPE_LABEL[taskType] || taskType || '-'; } function formatStatus(status) { return STATUS_LABEL[status] || status || '-'; } export default function DinsarProductsPanel({ readOnly = false, onJobQueued }) { const [extractRootDir, setExtractRootDir] = useState(''); const [extractDestDir, setExtractDestDir] = useState(''); const [extractResult, setExtractResult] = useState(null); const [extracting, setExtracting] = useState(false); const [actionMessage, setActionMessage] = useState(''); const [actionError, setActionError] = useState(false); const [scanning, setScanning] = useState(false); const [activeTask, setActiveTask] = useState(null); const [taskLogs, setTaskLogs] = useState([]); const [taskLogsLoading, setTaskLogsLoading] = useState(false); const [taskLogActionLoading, setTaskLogActionLoading] = useState(false); const [taskLogDeletingId, setTaskLogDeletingId] = useState(null); const loadActiveTask = useCallback(async () => { try { const data = await getActiveTasks(); const tasks = Array.isArray(data) ? data : (data?.tasks || []); const relevantTask = tasks.find(task => PRODUCT_TASK_TYPES.includes(task.task_type)) || null; setActiveTask(relevantTask); } catch { setActiveTask(null); } }, []); const loadTaskLogs = useCallback(async taskId => { if (!taskId) { setTaskLogs([]); return; } setTaskLogsLoading(true); try { const data = await getTaskLogs(taskId, 50, 0); setTaskLogs(data?.logs || []); } catch { setTaskLogs([]); } finally { setTaskLogsLoading(false); } }, []); const handleDeleteTaskLog = useCallback(async logId => { const taskId = activeTask?.task_id; if (!taskId || !logId || taskLogActionLoading) return; if (!window.confirm('确定要删除这条任务日志吗?')) return; setTaskLogDeletingId(logId); setTaskLogActionLoading(true); try { await deleteTaskLog(taskId, logId); await loadTaskLogs(taskId); } catch (error) { setActionMessage(`删除日志失败:${error?.response?.data?.detail || error.message}`); setActionError(true); } finally { setTaskLogDeletingId(null); setTaskLogActionLoading(false); } }, [activeTask?.task_id, loadTaskLogs, taskLogActionLoading]); const handleClearTaskLogs = useCallback(async () => { const taskId = activeTask?.task_id; if (!taskId || taskLogActionLoading || taskLogs.length === 0) return; if (!window.confirm('确定要清空当前任务的全部日志吗?')) return; setTaskLogActionLoading(true); try { await clearTaskLogs(taskId); await loadTaskLogs(taskId); } catch (error) { setActionMessage(`清空日志失败:${error?.response?.data?.detail || error.message}`); setActionError(true); } finally { setTaskLogActionLoading(false); } }, [activeTask?.task_id, loadTaskLogs, taskLogActionLoading, taskLogs.length]); useEffect(() => { loadActiveTask(); }, [loadActiveTask]); useEffect(() => { const timer = setInterval(loadActiveTask, 5000); return () => clearInterval(timer); }, [loadActiveTask]); useEffect(() => { const taskId = activeTask?.task_id || ''; loadTaskLogs(taskId); if (!taskId) return undefined; const timer = setInterval(() => loadTaskLogs(taskId), 5000); return () => clearInterval(timer); }, [activeTask?.task_id, loadTaskLogs]); const handleExtract = async () => { if (!extractRootDir.trim()) return; setExtracting(true); setExtractResult(null); setActionMessage(''); setActionError(false); try { const result = await extractDispResults(extractRootDir.trim(), extractDestDir.trim() || null); setExtractResult(result); } catch (err) { setExtractResult({ error: err?.response?.data?.detail || err.message }); } finally { setExtracting(false); } }; const handleScan = async () => { if (readOnly) return; setScanning(true); setActionMessage(''); setActionError(false); try { const result = await scanDinsarResults(); setActionMessage(result?.message || `D-InSAR结果扫描任务已入队:${result?.task_id || '-'}`); if (result?.task_id) { onJobQueued?.(result.task_id); } loadActiveTask(); } catch (err) { setActionError(true); setActionMessage(err?.response?.data?.detail || err.message || 'D-InSAR结果扫描失败'); } finally { setScanning(false); } }; return (