import { useState, useEffect, useCallback } from 'react'; import { detailScriptEpisodeNew, getScriptTitle, getRunningStreamData, StreamData } from '@/api/video_flow'; import { useSearchParams } from 'next/navigation'; import { ApiResponse } from '@/api/common'; // 步骤映射 const STEP_MAP = { 'sketch': '1', 'character': '2', 'video': '3', 'music': '4', 'final_video': '6' } as const; type ApiStep = keyof typeof STEP_MAP; interface TaskData { sketch?: Array<{ url: string; script: string; bg_rgb: string[]; }>; roles?: Array<{ name: string; url: string; sound: string; soundDescription: string; roleDescription: string; }>; videos?: Array<{ url: string; script: string; audio: string; }>; music?: Array<{ url: string; script: string; name: string; duration: string; totalDuration: string; isLooped: boolean; }>; final?: { url: string; }; } export const useApiData = () => { const searchParams = useSearchParams(); const episodeId = searchParams.get('episodeId'); const [title, setTitle] = useState(''); const [currentStep, setCurrentStep] = useState('1'); const [currentLoadingText, setCurrentLoadingText] = useState(''); const [needStreamData, setNeedStreamData] = useState(false); const [taskData, setTaskData] = useState({}); const [streamInterval, setStreamInterval] = useState(null); // 处理流式数据 const handleStreamData = useCallback((streamData: ApiResponse) => { const { category, message, data, status } = streamData.data; // 更新加载文本 setCurrentLoadingText(message); // 根据类别更新任务数据 setTaskData(prevData => { const newData = { ...prevData }; switch (category) { case 'sketch': if (!newData.sketch) newData.sketch = []; // 更新或追加分镜数据 const existingSketchIndex = newData.sketch.findIndex(s => s.url === data.url); if (existingSketchIndex === -1) { newData.sketch.push(data); } else { newData.sketch[existingSketchIndex] = data; } break; case 'character': if (!newData.roles) newData.roles = []; // 更新或追加角色数据 const existingRoleIndex = newData.roles.findIndex(r => r.name === data.name); if (existingRoleIndex === -1) { newData.roles.push(data); } else { newData.roles[existingRoleIndex] = data; } break; case 'video': if (!newData.videos) newData.videos = []; // 更新或追加视频数据 const existingVideoIndex = newData.videos.findIndex(v => v.url === data.url); if (existingVideoIndex === -1) { newData.videos.push(data); } else { newData.videos[existingVideoIndex] = data; } break; case 'music': if (!newData.music) newData.music = []; newData.music = [data]; break; case 'final_video': newData.final = data; break; } return newData; }); // 如果状态为 completed,停止获取流式数据 if (status === 'completed' || streamData.data.all_completed) { setNeedStreamData(false); } }, []); // 获取流式数据 const fetchStreamData = useCallback(async () => { if (!episodeId || !needStreamData) return; try { const streamData = await getRunningStreamData({ project_id: episodeId }); handleStreamData(streamData); } catch (error) { console.error('获取流式数据失败:', error); } }, [episodeId, needStreamData, handleStreamData]); // 启动流式数据轮询 useEffect(() => { if (needStreamData && !streamInterval) { const interval = setInterval(fetchStreamData, 10000); // 修改为10秒 setStreamInterval(interval); } else if (!needStreamData && streamInterval) { clearInterval(streamInterval); setStreamInterval(null); } return () => { if (streamInterval) { clearInterval(streamInterval); } }; }, [needStreamData, fetchStreamData, streamInterval]); // 获取标题的轮询函数 const pollTitle = useCallback(async () => { if (!episodeId) return; try { const response = await getScriptTitle({ project_id: episodeId }); if (response.successful && response.data) { setTitle(response.data.name); return true; } } catch (error) { console.error('获取标题失败:', error); } return false; }, [episodeId]); // 获取剧集详情 const fetchEpisodeDetail = useCallback(async () => { if (!episodeId) return; try { const response = await detailScriptEpisodeNew({ project_id: episodeId }); if (response.successful) { const { name, status, step, last_message, data } = response.data; // 设置标题 if (name) { setTitle(name); } // 设置步骤 if (step && STEP_MAP[step as ApiStep]) { setCurrentStep(STEP_MAP[step as ApiStep]); } // 设置加载文本 setCurrentLoadingText(last_message || ''); // 设置是否需要流式数据 setNeedStreamData(status === 'running'); // 设置任务数据 if (data) { setTaskData(data); } return true; } } catch (error) { console.error('获取剧集详情失败:', error); } return false; }, [episodeId]); // 初始化数据 useEffect(() => { let titleInterval: NodeJS.Timeout; const initData = async () => { const detailSuccess = await fetchEpisodeDetail(); // 如果详情接口没有返回标题,开始轮询标题 if (detailSuccess && !title) { titleInterval = setInterval(async () => { const success = await pollTitle(); if (success) { clearInterval(titleInterval); } }, 3000); } }; initData(); return () => { if (titleInterval) { clearInterval(titleInterval); } }; }, [episodeId, fetchEpisodeDetail, pollTitle, title]); return { title, currentStep, currentLoadingText, needStreamData, taskData }; };