import React, { useEffect, useState, useRef } from 'react'; import { ToolBState } from './index'; import * as toolBApi from '../../api/toolB'; interface Step3ProcessingProps { state: ToolBState; updateState: (updates: Partial) => void; onComplete: () => void; } const Step3Processing: React.FC = ({ state, updateState, onComplete }) => { const [logs, setLogs] = useState([]); const hasStarted = useRef(false); // 🔑 防止React Strict Mode重复执行 useEffect(() => { // 🔑 如果已经启动过,直接返回 if (hasStarted.current) { return; } hasStarted.current = true; let intervalId: NodeJS.Timeout | null = null; let failureCount = 0; const MAX_FAILURES = 3; const startTask = async () => { try { // 1. 创建任务 setLogs(prev => [...prev, '正在创建提取任务...']); const { taskId } = await toolBApi.createTask({ projectName: `${state.fileName}_提取任务`, sourceFileKey: state.fileKey, textColumn: state.selectedColumn, diseaseType: state.diseaseType, reportType: state.reportType, targetFields: state.fields.map(f => ({ name: f.name, desc: f.desc })) }); updateState({ taskId }); setLogs(prev => [...prev, `任务创建成功 (ID: ${taskId})`]); setLogs(prev => [...prev, '初始化双模型引擎 (DeepSeek-V3 & Qwen-Max)...']); // 2. 轮询进度 intervalId = setInterval(async () => { try { const progressData = await toolBApi.getTaskProgress(taskId); // 重置失败计数 failureCount = 0; updateState({ progress: progressData.progress }); // 更新日志 if (progressData.progress > 20 && progressData.progress < 25) { setLogs(prev => [...prev, 'PII 脱敏完成...']); } if (progressData.progress > 40 && progressData.progress < 45) { setLogs(prev => [...prev, `DeepSeek: 提取进度 ${progressData.progress}%`]); } if (progressData.progress > 50 && progressData.progress < 55) { setLogs(prev => [...prev, `Qwen: 提取进度 ${progressData.progress}%`]); } if (progressData.progress > 80 && progressData.progress < 85) { setLogs(prev => [...prev, '正在进行交叉验证 (Cross-Validation)...']); } // 完成时 if (progressData.status === 'completed' || progressData.progress >= 100) { if (intervalId) clearInterval(intervalId); setLogs(prev => [...prev, '✅ 提取完成!']); setTimeout(onComplete, 800); } // 失败时 if (progressData.status === 'failed') { if (intervalId) clearInterval(intervalId); setLogs(prev => [...prev, '❌ 任务失败,请重试']); } } catch (error: any) { console.error('Failed to fetch progress:', error); failureCount++; // 失败次数过多,停止轮询 if (failureCount >= MAX_FAILURES) { if (intervalId) clearInterval(intervalId); setLogs(prev => [...prev, `❌ 进度查询失败 (连续${MAX_FAILURES}次),已停止`]); setLogs(prev => [...prev, `错误信息: ${error.message || error}`]); } } }, 1000); } catch (error: any) { console.error('Failed to start task:', error); setLogs(prev => [...prev, `❌ 创建任务失败: ${error.message || error}`]); } }; startTask(); // Cleanup: 组件卸载时清除定时器 return () => { if (intervalId) { clearInterval(intervalId); } }; // eslint-disable-next-line react-hooks/exhaustive-deps }, []); return (

双模型提取交叉验证中...

DeepSeek-V3 & Qwen-Max 双引擎协同工作

{/* 进度条 */}
提取进度 {state.progress || 0}%
{/* 日志输出 */}
{logs.map((log, index) => (
[{new Date().toLocaleTimeString()}] {log}
))}
); }; export default Step3Processing;