马一丁

Fix Report Engine Progress Bar Error

@@ -3641,10 +3641,7 @@ @@ -3641,10 +3641,7 @@
3641 reportTaskId = null; 3641 reportTaskId = null;
3642 3642
3643 // 停止可能正在进行的轮询 3643 // 停止可能正在进行的轮询
3644 - if (reportPollingInterval) {  
3645 - clearInterval(reportPollingInterval);  
3646 - reportPollingInterval = null;  
3647 - } 3644 + stopProgressPolling();
3648 3645
3649 // 向所有运行中的应用发送搜索请求(通过刷新iframe传递参数) 3646 // 向所有运行中的应用发送搜索请求(通过刷新iframe传递参数)
3650 let totalRunning = 0; 3647 let totalRunning = 0;
@@ -5268,10 +5265,11 @@ @@ -5268,10 +5265,11 @@
5268 resetReportLogsForNewTask(taskId, '检测到正在运行的报告任务,日志已重新开始'); 5265 resetReportLogsForNewTask(taskId, '检测到正在运行的报告任务,日志已重新开始');
5269 reportTaskId = taskId; 5266 reportTaskId = taskId;
5270 reportAutoPreviewLoaded = false; 5267 reportAutoPreviewLoaded = false;
  5268 + startProgressPolling(taskId);
5271 if (window.EventSource) { 5269 if (window.EventSource) {
5272 openReportStream(reportTaskId); 5270 openReportStream(reportTaskId);
5273 } else { 5271 } else {
5274 - startProgressPolling(taskId); 5272 + appendReportStreamLine('浏览器不支持SSE,已切换为轮询模式', 'warn', { badge: 'SSE', force: true });
5275 } 5273 }
5276 } else if (statusData.current_task.status === 'completed') { 5274 } else if (statusData.current_task.status === 'completed') {
5277 lastCompletedReportTask = statusData.current_task; 5275 lastCompletedReportTask = statusData.current_task;
@@ -5346,13 +5344,25 @@ @@ -5346,13 +5344,25 @@
5346 const downloadPdfButton = document.getElementById('downloadPdfButton'); 5344 const downloadPdfButton = document.getElementById('downloadPdfButton');
5347 if (!downloadButton || !downloadPdfButton) return; 5345 if (!downloadButton || !downloadPdfButton) return;
5348 5346
5349 - if (task && task.status === 'completed' && (task.report_file_ready || task.report_file_path)) { 5347 + const htmlReady = task && task.status === 'completed' && (
  5348 + task.report_file_ready ||
  5349 + task.report_file_path ||
  5350 + task.has_result // 有内容即可允许尝试下载/预览
  5351 + );
  5352 + const pdfReady = task && task.status === 'completed' && (
  5353 + task.ir_file_ready ||
  5354 + task.ir_file_path ||
  5355 + task.report_file_ready ||
  5356 + task.report_file_path
  5357 + );
  5358 +
  5359 + if (htmlReady) {
5350 downloadButton.disabled = false; 5360 downloadButton.disabled = false;
5351 downloadButton.dataset.taskId = task.task_id; 5361 downloadButton.dataset.taskId = task.task_id;
5352 downloadButton.dataset.filename = task.report_file_name || ''; 5362 downloadButton.dataset.filename = task.report_file_name || '';
5353 const label = task.report_file_name ? `下载HTML (${task.report_file_name})` : '下载HTML'; 5363 const label = task.report_file_name ? `下载HTML (${task.report_file_name})` : '下载HTML';
5354 downloadButton.textContent = label; 5364 downloadButton.textContent = label;
5355 - downloadPdfButton.disabled = false; 5365 + downloadPdfButton.disabled = !pdfReady;
5356 downloadPdfButton.dataset.taskId = task.task_id; 5366 downloadPdfButton.dataset.taskId = task.task_id;
5357 lastCompletedReportTask = task; 5367 lastCompletedReportTask = task;
5358 } else if (!lastCompletedReportTask || (task && task.status !== 'completed')) { 5368 } else if (!lastCompletedReportTask || (task && task.status !== 'completed')) {
@@ -5631,10 +5641,13 @@ @@ -5631,10 +5641,13 @@
5631 // 确保从任务开始就能读取日志 5641 // 确保从任务开始就能读取日志
5632 reportLogManager.start(); 5642 reportLogManager.start();
5633 5643
  5644 + // 【兜底】立即启动进度轮询,SSE连上后会自动停止
  5645 + startProgressPolling(reportTaskId);
  5646 +
5634 if (window.EventSource) { 5647 if (window.EventSource) {
5635 openReportStream(reportTaskId); 5648 openReportStream(reportTaskId);
5636 } else { 5649 } else {
5637 - startProgressPolling(data.task_id); 5650 + appendReportStreamLine('浏览器不支持SSE,已切换为轮询模式', 'warn', { badge: 'SSE', force: true });
5638 } 5651 }
5639 } else { 5652 } else {
5640 updateTaskProgressStatus(null, 'error', '启动失败: ' + data.error); 5653 updateTaskProgressStatus(null, 'error', '启动失败: ' + data.error);
@@ -5664,12 +5677,19 @@ @@ -5664,12 +5677,19 @@
5664 // 【新函数】使用新的日志管理器 5677 // 【新函数】使用新的日志管理器
5665 // 旧的startReportLogRefresh和stopReportLogRefresh已废弃,请使用reportLogManager 5678 // 旧的startReportLogRefresh和stopReportLogRefresh已废弃,请使用reportLogManager
5666 5679
5667 - // 开始进度轮询  
5668 - function startProgressPolling(taskId) { 5680 + // 开始/停止进度轮询(SSE不可用或断开时兜底使用)
  5681 + function stopProgressPolling() {
5669 if (reportPollingInterval) { 5682 if (reportPollingInterval) {
5670 clearInterval(reportPollingInterval); 5683 clearInterval(reportPollingInterval);
  5684 + reportPollingInterval = null;
5671 } 5685 }
  5686 + }
5672 5687
  5688 + function startProgressPolling(taskId) {
  5689 + if (!taskId) return;
  5690 + stopProgressPolling();
  5691 + // 先立即拉取一次,避免长时间停留在5%
  5692 + checkTaskProgress(taskId);
5673 reportPollingInterval = setInterval(() => { 5693 reportPollingInterval = setInterval(() => {
5674 checkTaskProgress(taskId); 5694 checkTaskProgress(taskId);
5675 }, 2000); 5695 }, 2000);
@@ -5687,7 +5707,7 @@ @@ -5687,7 +5707,7 @@
5687 // reportLogManager会自动处理轮询 5707 // reportLogManager会自动处理轮询
5688 5708
5689 if (data.task.status === 'completed') { 5709 if (data.task.status === 'completed') {
5690 - clearInterval(reportPollingInterval); 5710 + stopProgressPolling();
5691 showMessage('报告生成完成!', 'success'); 5711 showMessage('报告生成完成!', 'success');
5692 5712
5693 // 自动显示报告 5713 // 自动显示报告
@@ -5699,7 +5719,7 @@ @@ -5699,7 +5719,7 @@
5699 reportTaskId = null; 5719 reportTaskId = null;
5700 setGenerateButtonState(false); 5720 setGenerateButtonState(false);
5701 } else if (data.task.status === 'error') { 5721 } else if (data.task.status === 'error') {
5702 - clearInterval(reportPollingInterval); 5722 + stopProgressPolling();
5703 showMessage('报告生成失败: ' + data.task.error_message, 'error'); 5723 showMessage('报告生成失败: ' + data.task.error_message, 'error');
5704 5724
5705 // 重置自动生成标志,允许重新尝试 5725 // 重置自动生成标志,允许重新尝试
@@ -5863,10 +5883,6 @@ @@ -5863,10 +5883,6 @@
5863 startProgressPolling(taskId); 5883 startProgressPolling(taskId);
5864 return; 5884 return;
5865 } 5885 }
5866 - if (reportPollingInterval) {  
5867 - clearInterval(reportPollingInterval);  
5868 - reportPollingInterval = null;  
5869 - }  
5870 if (reportEventSource && reportEventSource.__taskId === taskId) { 5886 if (reportEventSource && reportEventSource.__taskId === taskId) {
5871 if (reportEventSource.readyState !== EventSource.CLOSED) { 5887 if (reportEventSource.readyState !== EventSource.CLOSED) {
5872 return; 5888 return;
@@ -5913,6 +5929,7 @@ @@ -5913,6 +5929,7 @@
5913 if (reportTaskId) { 5929 if (reportTaskId) {
5914 reportLogManager.start(); 5930 reportLogManager.start();
5915 } 5931 }
  5932 + startProgressPolling(taskId);
5916 scheduleReportStreamReconnect(taskId); 5933 scheduleReportStreamReconnect(taskId);
5917 }; 5934 };
5918 5935
@@ -6060,6 +6077,7 @@ @@ -6060,6 +6077,7 @@
6060 break; 6077 break;
6061 case 'completed': 6078 case 'completed':
6062 appendReportStreamLine(payload.message || '任务完成', 'success'); 6079 appendReportStreamLine(payload.message || '任务完成', 'success');
  6080 + stopProgressPolling();
6063 6081
6064 // 【修复】任务完成前强制刷新最后一次日志,确保所有日志都被读取 6082 // 【修复】任务完成前强制刷新最后一次日志,确保所有日志都被读取
6065 if (reportLogManager && reportLogManager.isRunning) { 6083 if (reportLogManager && reportLogManager.isRunning) {
@@ -6084,6 +6102,7 @@ @@ -6084,6 +6102,7 @@
6084 break; 6102 break;
6085 case 'cancelled': 6103 case 'cancelled':
6086 appendReportStreamLine(payload.message || '任务已取消', 'warn'); 6104 appendReportStreamLine(payload.message || '任务已取消', 'warn');
  6105 + stopProgressPolling();
6087 safeCloseReportStream(); 6106 safeCloseReportStream();
6088 updateReportStreamStatus('idle'); 6107 updateReportStreamStatus('idle');
6089 reportTaskId = null; 6108 reportTaskId = null;
@@ -6091,6 +6110,7 @@ @@ -6091,6 +6110,7 @@
6091 break; 6110 break;
6092 case 'error': 6111 case 'error':
6093 appendReportStreamLine(payload.message || '任务失败', 'error', { badge: 'ERROR' }); 6112 appendReportStreamLine(payload.message || '任务失败', 'error', { badge: 'ERROR' });
  6113 + stopProgressPolling();
6094 safeCloseReportStream(); 6114 safeCloseReportStream();
6095 updateReportStreamStatus('error'); 6115 updateReportStreamStatus('error');
6096 reportTaskId = null; 6116 reportTaskId = null;