forked from 77media/video-flow
573 lines
23 KiB
TypeScript
573 lines
23 KiB
TypeScript
'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<any>(null);
|
||
const [loading, setLoading] = useState(true);
|
||
const [error, setError] = useState<string | null>(null);
|
||
const [isUsingMockData, setIsUsingMockData] = useState(false);
|
||
const [isBackgroundRefreshing, setIsBackgroundRefreshing] = useState(false);
|
||
const [lastUpdateTime, setLastUpdateTime] = useState<Date | null>(null);
|
||
const [connectionStatus, setConnectionStatus] = useState<'connected' | 'disconnected' | 'checking'>('checking');
|
||
|
||
// 支付成功状态
|
||
const [showPaymentSuccess, setShowPaymentSuccess] = useState(false);
|
||
const [paymentData, setPaymentData] = useState<any>(null);
|
||
|
||
// 使用 ref 来存储最新的状态,避免定时器闭包问题
|
||
const stateRef = useRef({ isUsingMockData, dashboardData });
|
||
|
||
// 智能请求控制和性能监控
|
||
const requestInProgress = useRef(false);
|
||
const lastRequestTime = useRef(0);
|
||
const lastRequestDuration = useRef(0); // 记录上次请求耗时
|
||
const performanceHistory = useRef<number[]>([]); // 性能历史记录
|
||
|
||
|
||
|
||
// 检测支付成功
|
||
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=${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 (
|
||
<div className="flex items-center justify-center min-h-screen">
|
||
<div className="text-center">
|
||
<div className="animate-spin rounded-full h-32 w-32 border-b-2 border-blue-500 mx-auto"></div>
|
||
<p className="mt-4 text-lg text-gray-600">加载数据面板...</p>
|
||
</div>
|
||
</div>
|
||
);
|
||
}
|
||
|
||
if (error && !dashboardData) {
|
||
return (
|
||
<div className="flex items-center justify-center min-h-screen bg-gradient-to-br from-gray-900 via-gray-800 to-gray-900">
|
||
<div className="text-center max-w-md mx-auto p-8 bg-black/20 backdrop-blur-sm rounded-xl border border-white/10">
|
||
<div className="text-red-400 text-6xl mb-6">⚠️</div>
|
||
<h2 className="text-white text-2xl font-bold mb-4">连接失败</h2>
|
||
<p className="text-gray-300 mb-6 leading-relaxed">{error}</p>
|
||
|
||
<div className="space-y-3">
|
||
<button
|
||
onClick={fetchInitialData}
|
||
disabled={loading}
|
||
className="w-full px-6 py-3 bg-blue-500 hover:bg-blue-600 disabled:opacity-50 disabled:cursor-not-allowed text-white rounded-lg transition-colors flex items-center justify-center gap-2"
|
||
>
|
||
{loading ? (
|
||
<>
|
||
<div className="w-4 h-4 animate-spin rounded-full border-b-2 border-white"></div>
|
||
<span>重新连接中...</span>
|
||
</>
|
||
) : (
|
||
<>
|
||
<svg className="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M4 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-15.357-2m15.357 2H15" />
|
||
</svg>
|
||
<span>重新连接</span>
|
||
</>
|
||
)}
|
||
</button>
|
||
|
||
<button
|
||
onClick={() => {
|
||
setDashboardData(mockDashboardData);
|
||
setIsUsingMockData(true);
|
||
setError(null);
|
||
setConnectionStatus('disconnected');
|
||
}}
|
||
className="w-full px-6 py-3 bg-gray-600 hover:bg-gray-700 text-white rounded-lg transition-colors"
|
||
>
|
||
使用演示数据
|
||
</button>
|
||
</div>
|
||
|
||
<div className="mt-6 text-sm text-gray-400">
|
||
<p>如果问题持续存在,请检查:</p>
|
||
<ul className="mt-2 text-left space-y-1">
|
||
<li>• 网络连接是否正常</li>
|
||
<li>• 服务器是否可访问</li>
|
||
<li>• 项目ID是否正确</li>
|
||
</ul>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
);
|
||
}
|
||
|
||
return (
|
||
<div className="h-full bg-gradient-to-br from-gray-900 via-gray-800 to-gray-900 flex flex-col overflow-hidden">
|
||
{/* 支付成功提示 */}
|
||
{showPaymentSuccess && paymentData && (
|
||
<div className="fixed top-4 left-1/2 transform -translate-x-1/2 z-50 bg-green-50 border border-green-200 rounded-lg p-4 shadow-lg max-w-md">
|
||
<div className="flex items-center">
|
||
<div className="flex-shrink-0">
|
||
<svg className="h-5 w-5 text-green-400" viewBox="0 0 20 20" fill="currentColor">
|
||
<path fillRule="evenodd" d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.707-9.293a1 1 0 00-1.414-1.414L9 10.586 7.707 9.293a1 1 0 00-1.414 1.414l2 2a1 1 0 001.414 0l4-4z" clipRule="evenodd" />
|
||
</svg>
|
||
</div>
|
||
<div className="ml-3">
|
||
<h3 className="text-sm font-medium text-green-800">支付成功!</h3>
|
||
<p className="text-sm text-green-700 mt-1">
|
||
您的订阅已激活,订单号: {paymentData.biz_order_no}
|
||
</p>
|
||
</div>
|
||
<div className="ml-auto pl-3">
|
||
<button
|
||
onClick={() => setShowPaymentSuccess(false)}
|
||
className="text-green-400 hover:text-green-600"
|
||
>
|
||
<svg className="h-4 w-4" viewBox="0 0 20 20" fill="currentColor">
|
||
<path fillRule="evenodd" d="M4.293 4.293a1 1 0 011.414 0L10 8.586l4.293-4.293a1 1 0 111.414 1.414L11.414 10l4.293 4.293a1 1 0 01-1.414 1.414L10 11.414l-4.293 4.293a1 1 0 01-1.414-1.414L8.586 10 4.293 5.707a1 1 0 010-1.414z" clipRule="evenodd" />
|
||
</svg>
|
||
</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
)}
|
||
|
||
{/* 后台刷新指示器 - 优化用户体验 */}
|
||
{isBackgroundRefreshing && (
|
||
<div className="fixed top-4 right-4 z-50 bg-blue-500/90 backdrop-blur-sm text-white px-4 py-2 rounded-lg shadow-lg flex items-center gap-2 max-w-xs">
|
||
<div className="w-4 h-4 animate-spin rounded-full border-b-2 border-white"></div>
|
||
<div className="flex flex-col">
|
||
<span className="text-sm font-medium">数据更新中...</span>
|
||
</div>
|
||
</div>
|
||
)}
|
||
|
||
{/* 手动刷新按钮和状态指示器 */}
|
||
<div className="fixed bottom-4 right-4 z-40 flex flex-col items-end gap-2">
|
||
{/* 手动刷新按钮 */}
|
||
<button
|
||
onClick={refreshDataSilently}
|
||
disabled={isBackgroundRefreshing}
|
||
className="bg-blue-500/80 hover:bg-blue-500 disabled:opacity-50 disabled:cursor-not-allowed backdrop-blur-sm text-white p-2 rounded-full shadow-lg transition-all duration-200 hover:scale-105"
|
||
title="手动刷新数据"
|
||
>
|
||
<svg className={`w-4 h-4 ${isBackgroundRefreshing ? 'animate-spin' : ''}`} fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M4 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-15.357-2m15.357 2H15" />
|
||
</svg>
|
||
</button>
|
||
</div>
|
||
|
||
{/* 顶部状态栏 */}
|
||
<div className="bg-gray-900 border-b border-gray-800 px-6 py-4">
|
||
<div className="flex items-center justify-between">
|
||
{/* 项目信息 */}
|
||
<div className="flex items-center gap-4">
|
||
<div className="flex items-center gap-2">
|
||
<div className="w-3 h-3 rounded-full bg-cyan-400 animate-pulse"></div>
|
||
<h1 className="text-xl font-bold text-white">Video Flow Dashboard</h1>
|
||
</div>
|
||
<div className="text-sm text-gray-400">
|
||
项目ID: <span className="font-mono text-gray-300">{projectId}</span>
|
||
</div>
|
||
</div>
|
||
|
||
{/* 连接状态和统计 */}
|
||
<div className="flex items-center gap-6">
|
||
{/* 连接状态指示器 */}
|
||
<div className="flex items-center gap-2">
|
||
<div className={cn(
|
||
"w-2 h-2 rounded-full",
|
||
connectionStatus === 'connected' ? 'bg-emerald-400' :
|
||
connectionStatus === 'checking' ? 'bg-amber-400 animate-pulse' :
|
||
'bg-rose-400'
|
||
)}></div>
|
||
<span className="text-sm text-gray-400">
|
||
{connectionStatus === 'connected' ? '实时连接' :
|
||
connectionStatus === 'checking' ? '连接中...' :
|
||
'离线模式'}
|
||
</span>
|
||
</div>
|
||
|
||
{/* 最后更新时间 */}
|
||
{lastUpdateTime && (
|
||
<div className="text-sm text-gray-500">
|
||
更新于 {lastUpdateTime.toLocaleTimeString()}
|
||
</div>
|
||
)}
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
{/* 主内容区域 */}
|
||
<div className="flex-1 min-h-0">
|
||
<NetworkTimeline
|
||
tasks={dashboardData || []}
|
||
onRefresh={fetchInitialData}
|
||
isRefreshing={loading}
|
||
isPolling={!isBackgroundRefreshing}
|
||
lastUpdate={lastUpdateTime || undefined}
|
||
onTogglePolling={() => {
|
||
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);
|
||
}
|
||
}}
|
||
/>
|
||
</div>
|
||
|
||
|
||
</div>
|
||
);
|
||
}
|