// API基础地址 const API_BASE = ''; // 自动刷新定时器 let autoRefreshInterval = null; // 页面加载 document.addEventListener('DOMContentLoaded', () => { loadStepDefinitions(); loadActiveProcesses(); loadHistory(); // 启动自动刷新(每2秒) startAutoRefresh(); }); // 启动自动刷新 function startAutoRefresh() { if (autoRefreshInterval) { clearInterval(autoRefreshInterval); } autoRefreshInterval = setInterval(() => { loadActiveProcesses(); }, 2000); } // 加载步骤定义 async function loadStepDefinitions() { try { const response = await fetch(`${API_BASE}/api/process/steps`); const data = await response.json(); if (data.success) { displayStepDefinitions(data.steps); } } catch (error) { console.error('加载步骤定义失败:', error); } } // 显示步骤定义 function displayStepDefinitions(steps) { const container = document.getElementById('steps-flow'); container.innerHTML = steps.map((step, i) => `
${step.num}
${escapeHtml(step.name)}
${escapeHtml(step.description)}
${i < steps.length - 1 ? '' : ''} `).join(''); } // 加载活动处理 async function loadActiveProcesses() { try { const response = await fetch(`${API_BASE}/api/process/active`); const data = await response.json(); if (data.success) { displayActiveProcesses(data.sessions); } } catch (error) { console.error('加载活动处理失败:', error); } } // 显示活动处理 function displayActiveProcesses(sessions) { const container = document.getElementById('active-list'); if (sessions.length === 0) { container.innerHTML = '
暂无正在进行的处理
'; return; } container.innerHTML = sessions.map(item => { const session = item.session; const steps = item.steps || []; const isPaused = session.paused || session.status === 'paused'; return `
${escapeHtml(session.product_name)}
${session.category ? `分类: ${escapeHtml(session.category)} | ` : ''} 会话ID: ${escapeHtml(session.session_id)}
${getStatusText(session.status)}
${renderStepsProgress(steps, session.current_step)}
${session.status === 'running' ? ` ` : ''} ${session.status === 'paused' ? ` ` : ''} ${session.status !== 'completed' ? ` ` : ''}
`; }).join(''); } // 渲染步骤进度 function renderStepsProgress(steps, currentStep) { const totalSteps = 6; const stepStatuses = {}; // 构建步骤状态映射 steps.forEach(s => { stepStatuses[s.step_number] = s.step_status; }); const stepNames = ['搜索内容库', '搜索互联网', '抓取网页', '提取数据', '填充字段', '提交审核']; let html = ''; for (let i = 1; i <= totalSteps; i++) { const status = stepStatuses[i] || (i > currentStep ? 'pending' : ''); let className = ''; if (status === 'completed') className = 'completed'; else if (status === 'running') className = 'running'; else if (status === 'failed') className = 'failed'; else if (status === 'skipped') className = 'skipped'; html += `
${i}
${stepNames[i-1]}
`; } return html; } // 加载历史 async function loadHistory() { try { const response = await fetch(`${API_BASE}/api/process/recent?limit=20`); const data = await response.json(); if (data.success) { displayHistory(data.sessions); } } catch (error) { console.error('加载历史失败:', error); } } // 显示历史 function displayHistory(sessions) { const container = document.getElementById('history-table'); if (sessions.length === 0) { container.innerHTML = '暂无处理历史'; return; } container.innerHTML = sessions.map(session => ` ${escapeHtml(session.product_name)} ${getStatusText(session.status)}
步骤 ${session.current_step || 0}/6
${formatDate(session.started_at || session.created_at)} ${formatDate(session.finished_at) || '-'} `).join(''); } // 暂停处理 async function pauseProcess(sessionId) { try { const response = await fetch(`${API_BASE}/api/process/${sessionId}/pause`, { method: 'POST' }); const data = await response.json(); if (data.success) { showToast('处理已暂停', 'success'); loadActiveProcesses(); } else { showToast('暂停失败: ' + data.error, 'error'); } } catch (error) { showToast('暂停失败', 'error'); } } // 继续处理 async function resumeProcess(sessionId) { try { const response = await fetch(`${API_BASE}/api/process/${sessionId}/resume`, { method: 'POST' }); const data = await response.json(); if (data.success) { showToast('处理已继续', 'success'); loadActiveProcesses(); } else { showToast('继续失败: ' + data.error, 'error'); } } catch (error) { showToast('继续失败', 'error'); } } // 停止处理 async function stopProcess(sessionId) { if (!confirm('确定要停止处理吗?')) return; try { const response = await fetch(`${API_BASE}/api/process/${sessionId}/stop`, { method: 'POST' }); const data = await response.json(); if (data.success) { showToast('处理已停止', 'success'); loadActiveProcesses(); loadHistory(); } else { showToast('停止失败: ' + data.error, 'error'); } } catch (error) { showToast('停止失败', 'error'); } } // 显示处理详情 async function showProcessDetail(sessionId) { try { const response = await fetch(`${API_BASE}/api/process/${sessionId}/status`); const data = await response.json(); if (data.success) { const session = data.data.session; const steps = data.data.steps; document.getElementById('detail-title').innerHTML = ` ${escapeHtml(session.product_name)} - 处理详情`; const body = document.getElementById('detail-body'); body.innerHTML = `
状态: ${getStatusText(session.status)}
分类: ${escapeHtml(session.category || '未分类')}
开始时间: ${formatDate(session.started_at) || '未开始'}
完成时间: ${formatDate(session.finished_at) || '-'}
${session.review_id ? `
审核ID: ${escapeHtml(session.review_id)}
` : ''}

处理步骤

${steps.map(step => renderDetailStep(step)).join('')}
`; document.getElementById('process-detail-modal').classList.add('active'); } } catch (error) { showToast('获取详情失败', 'error'); } } // 渲染详情步骤 function renderDetailStep(step) { const statusColors = { 'completed': '#10b981', 'running': '#667eea', 'failed': '#ef4444', 'skipped': '#9ca3af', 'pending': '#e9ecef' }; let stepDataHtml = ''; if (step.step_data) { try { const data = typeof step.step_data === 'string' ? JSON.parse(step.step_data) : step.step_data; stepDataHtml = `
${escapeHtml(JSON.stringify(data, null, 2))}
`; } catch (e) { stepDataHtml = escapeHtml(step.step_data); } } return `
步骤${step.step_number}: ${escapeHtml(step.step_name)}
${step.step_status}
${stepDataHtml ? `
${stepDataHtml}
` : ''} ${step.error_message ? `
${escapeHtml(step.error_message)}
` : ''}
${step.started_at ? `开始: ${formatDate(step.started_at)}` : ''} ${step.finished_at ? ` | 完成: ${formatDate(step.finished_at)}` : ''} ${step.duration_ms ? ` | 耗时: ${step.duration_ms}ms` : ''}
`; } // 刷新数据 function refreshData() { loadActiveProcesses(); loadHistory(); } // 关闭模态框 function closeModal(modalId) { document.getElementById(modalId).classList.remove('active'); } // 获取状态文本 function getStatusText(status) { const statusMap = { 'pending': '等待中', 'running': '处理中', 'paused': '已暂停', 'completed': '已完成', 'failed': '失败', 'stopped': '已停止' }; return statusMap[status] || status; } // HTML转义 function escapeHtml(text) { if (!text) return ''; const div = document.createElement('div'); div.textContent = text; return div.innerHTML; } // 日期格式化 function formatDate(dateString) { if (!dateString) return ''; const date = new Date(dateString); return date.toLocaleString('zh-CN', { month: '2-digit', day: '2-digit', hour: '2-digit', minute: '2-digit' }); } // 显示提示 function showToast(message, type = '') { const toast = document.getElementById('toast'); toast.textContent = message; toast.className = `toast active ${type}`; setTimeout(() => { toast.classList.remove('active'); }, 3000); }