'use client'; import React, { useState, useEffect, useRef } from 'react'; import NetworkTimeline from '@/components/dashboard/network-timeline'; import { useSearchParams } from 'next/navigation'; import { getProjectTaskList, retryTask } from '@/api/video_flow'; import { mockDashboardData } from '@/components/dashboard/demo-data'; import { cn } from '@/public/lib/utils'; export default function DashboardPage() { const searchParams = useSearchParams(); // 使用真实项目ID,如果URL没有提供则使用默认的真实项目ID const projectId = searchParams.get('project_id') || 'bc43bc81-c781-4caa-8256-9710fd5bee80'; const [dashboardData, setDashboardData] = useState(null); const [loading, setLoading] = useState(true); const [error, setError] = useState(null); const [isUsingMockData, setIsUsingMockData] = useState(false); const [isBackgroundRefreshing, setIsBackgroundRefreshing] = useState(false); const [lastUpdateTime, setLastUpdateTime] = useState(null); const [connectionStatus, setConnectionStatus] = useState<'connected' | 'disconnected' | 'checking'>('checking'); // 支付成功状态 const [showPaymentSuccess, setShowPaymentSuccess] = useState(false); const [paymentData, setPaymentData] = useState(null); // 使用 ref 来存储最新的状态,避免定时器闭包问题 const stateRef = useRef({ isUsingMockData, dashboardData }); // 智能请求控制和性能监控 const requestInProgress = useRef(false); const lastRequestTime = useRef(0); const lastRequestDuration = useRef(0); // 记录上次请求耗时 const performanceHistory = useRef([]); // 性能历史记录 // 检测支付成功 useEffect(() => { const sessionId = searchParams.get('session_id'); const payment = searchParams.get('payment'); if (sessionId && payment === 'success') { // 显示支付成功提示 setShowPaymentSuccess(true); // 获取支付详情 fetchPaymentDetails(sessionId); // 清除URL参数,避免刷新页面时重复显示 const newUrl = new URL(window.location.href); newUrl.searchParams.delete('session_id'); newUrl.searchParams.delete('payment'); window.history.replaceState({}, '', newUrl.pathname); } }, [searchParams]); // 获取支付详情 const fetchPaymentDetails = async (sessionId: string) => { try { const User = JSON.parse(localStorage.getItem("currentUser") || "{}"); const response = await fetch(`/api/payment/checkout-status/${sessionId}?user_id=${String(User.id)}`); const result = await response.json(); if (result.successful && result.data) { setPaymentData(result.data); } } catch (error) { console.error('获取支付详情失败:', error); } }; // 初始加载数据 const fetchInitialData = async () => { try { setLoading(true); setError(null); setConnectionStatus('checking'); console.log('正在获取项目数据,项目ID:', projectId); // 调用新的任务列表API const response = await getProjectTaskList({ project_id: projectId }); console.log('API响应:', response); if (response.code === 0 && response.data) { // 直接使用新API数据,不进行格式转换 setDashboardData(response.data); setIsUsingMockData(false); setLastUpdateTime(new Date()); setConnectionStatus('connected'); console.log('成功获取真实数据:', response.data); } else { console.warn('API返回错误或无数据,使用演示数据'); setDashboardData(mockDashboardData); setIsUsingMockData(true); setLastUpdateTime(new Date()); setConnectionStatus('disconnected'); setError(`API返回: ${response.message || '无数据'} (已切换到演示模式)`); } } catch (err: any) { console.error('获取数据失败:', err); // 详细的错误分析 let errorMessage = '未知错误'; if (err.code === 'NETWORK_ERROR' || err.message?.includes('Network Error')) { errorMessage = '网络连接失败,请检查网络连接'; } else if (err.code === 'ECONNABORTED' || err.message?.includes('timeout')) { errorMessage = '请求超时,服务器响应缓慢'; } else if (err.response?.status === 404) { errorMessage = 'API接口不存在'; } else if (err.response?.status === 500) { errorMessage = '服务器内部错误'; } else if (err.response?.status === 403) { errorMessage = '访问被拒绝,请检查权限'; } else if (err.message) { errorMessage = err.message; } // 如果API调用失败,回退到演示数据 console.log('API调用失败,使用演示数据'); setDashboardData(mockDashboardData); setIsUsingMockData(true); setLastUpdateTime(new Date()); setConnectionStatus('disconnected'); setError(`${errorMessage} (已切换到演示模式)`); } finally { setLoading(false); } }; // 优化的数据变化检测(避免深度JSON比较,但保持准确性) const hasDataChanged = (newData: any, oldData: any) => { if (!oldData || !newData) return true; if (!Array.isArray(newData) || !Array.isArray(oldData)) return true; if (newData.length !== oldData.length) return true; // 添加性能监控 const startTime = Date.now(); try { // 快速比较:只检查关键字段,但保持完整性 for (let i = 0; i < newData.length; i++) { const newTask = newData[i]; const oldTask = oldData[i]; if (!newTask || !oldTask) return true; // 比较关键字段 if (newTask.task_id !== oldTask.task_id || newTask.task_status !== oldTask.task_status || newTask.progress !== oldTask.progress || newTask.end_time !== oldTask.end_time || newTask.start_time !== oldTask.start_time) { return true; } // 检查子任务变化(保持原有逻辑) const newSubCount = newTask.sub_tasks?.length || 0; const oldSubCount = oldTask.sub_tasks?.length || 0; if (newSubCount !== oldSubCount) return true; // 检查task_result的关键变化 if (newTask.task_result?.total_count !== oldTask.task_result?.total_count || newTask.task_result?.completed_count !== oldTask.task_result?.completed_count) { return true; } } return false; // 没有关键变化 } finally { const endTime = Date.now(); if (endTime - startTime > 10) { // 只记录超过10ms的比较 console.log(`[性能] 数据比较耗时: ${endTime - startTime}ms`); } } }; // 智能后台刷新:支持10秒间隔但避免重叠 const refreshDataSilently = async () => { // 防止重复请求 if (requestInProgress.current) { console.log('[刷新] 请求进行中,跳过本次刷新'); return; } // 智能频率控制:根据上次请求耗时动态调整最小间隔 const now = Date.now(); const timeSinceLastRequest = now - lastRequestTime.current; // 如果上次请求还没完成足够长时间,跳过本次请求 // 这样可以支持10秒间隔,但避免在后端处理慢时重叠 if (timeSinceLastRequest < 2000) { console.log(`[刷新] 距离上次请求仅${timeSinceLastRequest}ms,跳过本次刷新`); return; } try { requestInProgress.current = true; lastRequestTime.current = now; setIsBackgroundRefreshing(true); console.log('[刷新] 开始后台数据刷新...'); const startTime = Date.now(); // 调用优化后的任务列表API const response = await getProjectTaskList({ project_id: projectId }); const endTime = Date.now(); const duration = endTime - startTime; // 更新性能监控数据 lastRequestDuration.current = duration; performanceHistory.current.push(duration); // 只保留最近10次的性能数据 if (performanceHistory.current.length > 10) { performanceHistory.current.shift(); } // 计算平均响应时间 const avgDuration = performanceHistory.current.reduce((a, b) => a + b, 0) / performanceHistory.current.length; console.log(`[刷新] API调用完成,耗时: ${duration}ms (平均: ${Math.round(avgDuration)}ms)`); // 智能性能警告:基于历史数据判断 if (duration > 5000) { console.warn(`[性能警告] 后端API处理过慢: ${duration}ms,平均耗时: ${Math.round(avgDuration)}ms`); } // 如果平均响应时间超过8秒,建议调整轮询策略 if (avgDuration > 8000) { console.warn(`[轮询建议] 平均响应时间${Math.round(avgDuration)}ms,建议考虑延长轮询间隔`); } if (response.code === 0 && response.data) { // 使用优化的数据比较 if (hasDataChanged(response.data, dashboardData)) { console.log('[刷新] 检测到数据变化,更新UI'); setDashboardData(response.data); setIsUsingMockData(false); setLastUpdateTime(new Date()); setConnectionStatus('connected'); setError(null); } else { console.log('[刷新] 数据无变化,仅更新时间戳'); setLastUpdateTime(new Date()); setConnectionStatus('connected'); } } else { console.warn('[刷新] API返回错误,保持当前数据'); setConnectionStatus('disconnected'); } } catch (err: any) { console.error('[刷新] 后台刷新失败:', err); setConnectionStatus('disconnected'); // 如果是超时错误,给用户更明确的提示 if (err.message?.includes('超时')) { setError('网络连接超时,请检查网络状态'); } } finally { requestInProgress.current = false; setIsBackgroundRefreshing(false); } }; // 智能轮询策略:动态调整间隔,避免请求重叠 const getRefreshInterval = React.useCallback(() => { if (!dashboardData || isUsingMockData) return 60000; // mock数据时60秒刷新一次 // 检查是否有正在运行的任务 const hasRunningTasks = Array.isArray(dashboardData) && dashboardData.some((task: any) => task.task_status === 'IN_PROGRESS' || task.task_status === 'INIT' || task.task_status === 'RETRYING' || // 包含重试状态 (task.sub_tasks && Array.isArray(task.sub_tasks) && task.sub_tasks.some((subTask: any) => subTask.task_status === 'IN_PROGRESS' || subTask.task_status === 'INIT' || subTask.task_status === 'RETRYING' )) ); // 根据连接状态调整间隔 if (connectionStatus === 'disconnected') { return 60000; // 连接断开时降低频率 } // 智能间隔策略:基于实际API性能动态调整 // 目标:10秒间隔,但要避免请求重叠 if (hasRunningTasks) { // 有运行任务时使用10秒间隔,但通过请求去重避免重叠 return 10000; } else { // 无运行任务时使用较长间隔节省资源 return 30000; } }, [dashboardData, isUsingMockData, connectionStatus]); // 初始加载数据 - 只在 projectId 变化时执行 useEffect(() => { fetchInitialData(); }, [projectId]); // 只依赖 projectId // 更新 ref 中的状态 useEffect(() => { stateRef.current = { isUsingMockData, dashboardData }; }, [isUsingMockData, dashboardData]); // 优化的智能定时刷新 - 根据数据状态动态调整刷新间隔 useEffect(() => { if (!dashboardData) return; // 没有数据时不设置定时器 const refreshInterval = getRefreshInterval(); const hasRunningTasks = Array.isArray(dashboardData) && dashboardData.some((task: any) => task.task_status === 'IN_PROGRESS' || task.task_status === 'INIT' || task.task_status === 'RETRYING' ); // 计算当前平均响应时间用于日志显示 const avgDuration = performanceHistory.current.length > 0 ? Math.round(performanceHistory.current.reduce((a, b) => a + b, 0) / performanceHistory.current.length) : 0; console.log(`[轮询] 设置刷新间隔: ${refreshInterval / 1000}秒 (有运行任务: ${hasRunningTasks}, 平均响应: ${avgDuration}ms)`); const interval = setInterval(() => { // 使用 ref 中的最新状态 if (!stateRef.current.isUsingMockData) { console.log('[轮询] 执行定时刷新'); refreshDataSilently(); } else { console.log('[轮询] 跳过刷新 (使用Mock数据)'); } }, refreshInterval); return () => { console.log('[轮询] 清理定时器'); clearInterval(interval); }; }, [getRefreshInterval]); // 只依赖 getRefreshInterval if (loading) { return (

加载数据面板...

); } if (error && !dashboardData) { return (
⚠️

连接失败

{error}

如果问题持续存在,请检查:

  • • 网络连接是否正常
  • • 服务器是否可访问
  • • 项目ID是否正确
); } return (
{/* 支付成功提示 */} {showPaymentSuccess && paymentData && (

支付成功!

您的订阅已激活,订单号: {paymentData.biz_order_no}

)} {/* 后台刷新指示器 - 优化用户体验 */} {isBackgroundRefreshing && (
数据更新中...
)} {/* 手动刷新按钮和状态指示器 */}
{/* 手动刷新按钮 */}
{/* 顶部状态栏 */}
{/* 项目信息 */}

Video Flow Dashboard

项目ID: {projectId}
{/* 连接状态和统计 */}
{/* 连接状态指示器 */}
{connectionStatus === 'connected' ? '实时连接' : connectionStatus === 'checking' ? '连接中...' : '离线模式'}
{/* 最后更新时间 */} {lastUpdateTime && (
更新于 {lastUpdateTime.toLocaleTimeString()}
)}
{/* 主内容区域 */}
{ console.log('切换轮询状态'); }} onRetryTask={async (taskId: string) => { console.log('重试任务:', taskId); try { // 1. 乐观更新:立即更新任务状态为重试中 setDashboardData((prevData: any[]) => { if (!Array.isArray(prevData)) return prevData; return prevData.map(task => { if (task.task_id === taskId) { return { ...task, task_status: 'RETRYING' }; } // 检查子任务 if (task.sub_tasks && Array.isArray(task.sub_tasks)) { const updatedSubTasks = task.sub_tasks.map((subTask: { task_id: string; task_status: string }) => subTask.task_id === taskId ? { ...subTask, task_status: 'RETRYING' } : subTask ); return { ...task, sub_tasks: updatedSubTasks }; } return task; }); }); // 2. 调用重试任务API const retryResponse = await retryTask({ task_id: taskId }); if (retryResponse.code === 0 && retryResponse.data?.success) { console.log('任务重试成功:', retryResponse.data); // 3. 重试成功后,使用静默刷新获取最新状态 setTimeout(() => { refreshDataSilently(); }, 2000); // 给后端一些处理时间 } else { console.error('任务重试失败:', retryResponse.message); // 4. 重试失败,恢复原状态并静默刷新 setTimeout(() => { refreshDataSilently(); }, 1000); } } catch (error) { console.error('重试任务时发生错误:', error); // 5. 发生错误时,恢复状态并静默刷新 setTimeout(() => { refreshDataSilently(); }, 1000); } }} />
); }