From c833394f0697d55a463ed4385dd62a06511d568f Mon Sep 17 00:00:00 2001 From: hz4th_coder Date: Tue, 14 Jul 2026 15:36:18 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E7=BB=9F=E4=B8=80=E5=A4=84=E7=90=86?= =?UTF-8?q?=E6=B5=81=E7=A8=8B=E5=92=8C=E5=90=8E=E5=8F=B0=E4=BB=BB=E5=8A=A1?= =?UTF-8?q?=E6=98=BE=E7=A4=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 处理流程抓取失败时记录到失败URL库 - /search页面新增产品处理会话展示区 - 同时显示后台抓取任务和产品处理会话 - 自动刷新同时更新三种数据:任务、会话、失败URL --- services/process_monitor.py | 14 ++++++-- static/css/search.css | 16 ++++++++++ static/js/search.js | 64 +++++++++++++++++++++++++++++++++++++ templates/search.html | 20 ++++++++++++ 4 files changed, 112 insertions(+), 2 deletions(-) diff --git a/services/process_monitor.py b/services/process_monitor.py index f05d141..f44dfb2 100644 --- a/services/process_monitor.py +++ b/services/process_monitor.py @@ -102,6 +102,7 @@ class ProcessMonitor: self._start_step(session_id, product_name, 3, '抓取网页内容') try: fetched = [] + failed_count = 0 urls_to_fetch = [r['url'] for r in all_data['internet_results'][:5]] for i, url in enumerate(urls_to_fetch): @@ -135,12 +136,21 @@ class ProcessMonitor: logger.info(f"[{session_id}] 已保存到内容库: {title[:30]}") except Exception as save_error: logger.warning(f"[{session_id}] 保存内容库失败: {save_error}") + else: + # 记录失败URL + failed_count += 1 + error_msg = fetch_result.get('error', '抓取失败') + try: + db.add_failed_url(url, product_name, error_msg, source='process_monitor') + logger.warning(f"[{session_id}] 抓取失败,已记录: {url}") + except Exception as e: + logger.error(f"[{session_id}] 记录失败URL出错: {e}") time.sleep(0.3) all_data['fetched_contents'] = fetched - self._complete_step(session_id, 3, {'count': len(fetched)}) - logger.info(f"[{session_id}] 步骤3完成: 抓取 {len(fetched)} 个网页") + self._complete_step(session_id, 3, {'count': len(fetched), 'failed': failed_count}) + logger.info(f"[{session_id}] 步骤3完成: 抓取 {len(fetched)} 个网页, 失败 {failed_count} 个") except Exception as e: self._fail_step(session_id, 3, str(e)) diff --git a/static/css/search.css b/static/css/search.css index 5d65135..6886185 100644 --- a/static/css/search.css +++ b/static/css/search.css @@ -472,6 +472,22 @@ color: #3730a3; } +/* 产品处理会话区域 */ +.process-sessions-section { + background: white; + border-radius: 12px; + box-shadow: 0 2px 4px rgba(0,0,0,0.05); + margin-top: 20px; +} + +.process-sessions-section .panel-header { + background: #fef3c7; +} + +.process-sessions-section .panel-header h2 { + color: #92400e; +} + .background-tasks-list { display: flex; flex-direction: column; diff --git a/static/js/search.js b/static/js/search.js index 3b51e01..f3d225c 100644 --- a/static/js/search.js +++ b/static/js/search.js @@ -22,6 +22,7 @@ document.addEventListener('DOMContentLoaded', () => { // 加载失败URL和后台任务 loadFailedUrls(); loadBackgroundTasks(); + loadProcessSessions(); // 启动自动刷新后台任务列表(每3秒) startAutoRefreshTasks(); @@ -880,6 +881,8 @@ function startAutoRefreshTasks() { autoRefreshTasksInterval = setInterval(() => { loadBackgroundTasks(); + loadProcessSessions(); // 同时刷新处理会话 + loadFailedUrls(); // 同时刷新失败URL }, 3000); // 每3秒刷新一次 } @@ -889,4 +892,65 @@ function stopAutoRefreshTasks() { clearInterval(autoRefreshTasksInterval); autoRefreshTasksInterval = null; } +} + +// 加载产品处理会话 +async function loadProcessSessions() { + try { + const response = await fetch(`${API_BASE}/api/process/recent?limit=10`); + const data = await response.json(); + + if (data.success) { + const container = document.getElementById('process-sessions-list'); + + if (data.sessions.length === 0) { + container.innerHTML = '
暂无处理会话
'; + } else { + container.innerHTML = data.sessions.map(session => { + const statusClass = { + 'pending': 'status-pending', + 'running': 'status-running', + 'paused': 'status-warning', + 'completed': 'status-success', + 'failed': 'status-error', + 'stopped': 'status-warning' + }[session.status] || ''; + + const statusText = { + 'pending': '等待中', + 'running': '处理中', + 'paused': '已暂停', + 'completed': '已完成', + 'failed': '失败', + 'stopped': '已停止' + }[session.status] || session.status; + + return ` +
+
+
${escapeHtml(session.product_name)}
+
+ ${statusText} + ${session.status === 'running' || session.status === 'paused' ? + `步骤 ${session.current_step || 0}/6` : ''} + ${session.category ? `分类: ${escapeHtml(session.category)}` : ''} + ${session.review_id ? `审核ID: ${escapeHtml(session.review_id)}` : ''} +
+
${session.created_at || ''} + ${session.finished_at ? ' → ' + session.finished_at : ''} +
+
+ +
+ `; + }).join(''); + } + } + } catch (error) { + console.error('加载处理会话出错:', error); + } } \ No newline at end of file diff --git a/templates/search.html b/templates/search.html index 55f9ac3..3f89c6c 100644 --- a/templates/search.html +++ b/templates/search.html @@ -111,6 +111,26 @@ + +
+
+

产品处理会话

+
+ + 监控页面 + + +
+
+
+
+
暂无处理会话
+
+
+
+