forked from 77media/video-flow
305 lines
8.1 KiB
TypeScript
305 lines
8.1 KiB
TypeScript
import { useState, useEffect, useRef, useCallback } from 'react';
|
|
import { TaskObject, SketchItem, VideoItem, STEP_MESSAGES, MOCK_SKETCH_COUNT } from '@/components/work-flow/constants';
|
|
import {
|
|
getTaskDetail,
|
|
getTaskSketch,
|
|
getTaskRole,
|
|
getTaskBackgroundAudio,
|
|
getTaskFinalProduct,
|
|
getTaskVideo
|
|
} from '@/components/work-flow/api';
|
|
|
|
export const useWorkFlow = () => {
|
|
// 基础状态
|
|
const [taskObject, setTaskObject] = useState<TaskObject | null>(null);
|
|
const [taskSketch, setTaskSketch] = useState<SketchItem[]>([]);
|
|
const [taskVideos, setTaskVideos] = useState<VideoItem[]>([]);
|
|
const [isLoading, setIsLoading] = useState(true);
|
|
const [currentStep, setCurrentStep] = useState('0');
|
|
const [currentSketchIndex, setCurrentSketchIndex] = useState(0);
|
|
const [currentLoadingText, setCurrentLoadingText] = useState('加载中...');
|
|
|
|
// 生成状态
|
|
const [isGeneratingSketch, setIsGeneratingSketch] = useState(false);
|
|
const [isGeneratingVideo, setIsGeneratingVideo] = useState(false);
|
|
const [sketchCount, setSketchCount] = useState(0);
|
|
|
|
// 播放状态
|
|
const [isPlaying, setIsPlaying] = useState(false);
|
|
const [isVideoPlaying, setIsVideoPlaying] = useState(true);
|
|
const playTimerRef = useRef<NodeJS.Timeout | null>(null);
|
|
const videoPlayTimerRef = useRef<NodeJS.Timeout | null>(null);
|
|
const mainVideoRef = useRef<HTMLVideoElement>(null);
|
|
|
|
// 拖拽状态
|
|
const [isDragging, setIsDragging] = useState(false);
|
|
const [startX, setStartX] = useState(0);
|
|
const [scrollLeft, setScrollLeft] = useState(0);
|
|
|
|
// 界面状态
|
|
const [showControls, setShowControls] = useState(false);
|
|
const [isEditModalOpen, setIsEditModalOpen] = useState(false);
|
|
const [activeEditTab, setActiveEditTab] = useState('1');
|
|
|
|
// 初始化工作流
|
|
useEffect(() => {
|
|
const initWorkFlow = async () => {
|
|
const taskId = localStorage.getItem("taskId") || "taskId-123";
|
|
|
|
try {
|
|
// 获取任务详情
|
|
const data = await getTaskDetail(taskId);
|
|
setTaskObject(data);
|
|
setIsLoading(false);
|
|
setCurrentStep('1');
|
|
|
|
// 获取分镜草图
|
|
await handleGetTaskSketch(taskId);
|
|
await delay(2000);
|
|
updateTaskStatus('2');
|
|
setCurrentStep('2');
|
|
|
|
// 绘制角色
|
|
await getTaskRole(taskId);
|
|
await delay(2000);
|
|
updateTaskStatus('3');
|
|
setCurrentStep('3');
|
|
|
|
// 获取分镜视频
|
|
await handleGetTaskVideo(taskId);
|
|
await delay(2000);
|
|
updateTaskStatus('4');
|
|
setCurrentStep('4');
|
|
|
|
// 获取背景音
|
|
await getTaskBackgroundAudio(taskId);
|
|
await delay(2000);
|
|
updateTaskStatus('5');
|
|
setCurrentStep('5');
|
|
|
|
// 获取最终成品
|
|
await getTaskFinalProduct(taskId);
|
|
await delay(2000);
|
|
updateTaskStatus('6');
|
|
setCurrentStep('6');
|
|
} catch (error) {
|
|
console.error('工作流初始化失败:', error);
|
|
}
|
|
};
|
|
|
|
initWorkFlow();
|
|
}, []);
|
|
|
|
const delay = (ms: number) => new Promise(resolve => setTimeout(resolve, ms));
|
|
|
|
const updateTaskStatus = (status: string) => {
|
|
setTaskObject(prev => prev ? { ...prev, taskStatus: status } : null);
|
|
};
|
|
|
|
const handleGetTaskSketch = async (taskId: string) => {
|
|
if (isGeneratingSketch || taskSketch.length > 0) return;
|
|
|
|
setIsGeneratingSketch(true);
|
|
setTaskSketch([]);
|
|
|
|
await getTaskSketch(taskId, (newSketch, index) => {
|
|
setTaskSketch(prev => {
|
|
if (prev.find(sketch => sketch.id === newSketch.id)) {
|
|
return prev;
|
|
}
|
|
return [...prev, newSketch];
|
|
});
|
|
setCurrentSketchIndex(index);
|
|
setSketchCount(index + 1);
|
|
});
|
|
|
|
setIsGeneratingSketch(false);
|
|
};
|
|
|
|
const handleGetTaskVideo = async (taskId: string) => {
|
|
setIsGeneratingVideo(true);
|
|
setTaskVideos([]);
|
|
|
|
await getTaskVideo(taskId, taskSketch.length, (newVideo, index) => {
|
|
setTaskVideos(prev => {
|
|
if (prev.find(video => video.id === newVideo.id)) {
|
|
return prev;
|
|
}
|
|
return [...prev, newVideo];
|
|
});
|
|
setCurrentSketchIndex(index);
|
|
});
|
|
|
|
setIsGeneratingVideo(false);
|
|
};
|
|
|
|
// 自动播放逻辑
|
|
useEffect(() => {
|
|
if (isPlaying && taskSketch.length > 0) {
|
|
playTimerRef.current = setInterval(() => {
|
|
setCurrentSketchIndex(prev => (prev + 1) % taskSketch.length);
|
|
}, 2000);
|
|
} else if (playTimerRef.current) {
|
|
clearInterval(playTimerRef.current);
|
|
}
|
|
|
|
return () => {
|
|
if (playTimerRef.current) {
|
|
clearInterval(playTimerRef.current);
|
|
}
|
|
};
|
|
}, [isPlaying, taskSketch.length]);
|
|
|
|
// 视频播放逻辑
|
|
useEffect(() => {
|
|
if (isVideoPlaying && taskVideos.length > 0) {
|
|
if (mainVideoRef.current) {
|
|
mainVideoRef.current.play().catch(error => {
|
|
console.log('视频播放失败:', error);
|
|
setIsVideoPlaying(false);
|
|
});
|
|
}
|
|
} else {
|
|
if (mainVideoRef.current) {
|
|
mainVideoRef.current.pause();
|
|
}
|
|
if (videoPlayTimerRef.current) {
|
|
clearInterval(videoPlayTimerRef.current);
|
|
}
|
|
}
|
|
|
|
return () => {
|
|
if (videoPlayTimerRef.current) {
|
|
clearInterval(videoPlayTimerRef.current);
|
|
}
|
|
};
|
|
}, [isVideoPlaying, taskVideos.length]);
|
|
|
|
// 当切换视频时重置播放
|
|
useEffect(() => {
|
|
if (mainVideoRef.current) {
|
|
mainVideoRef.current.currentTime = 0;
|
|
if (isVideoPlaying) {
|
|
mainVideoRef.current.play().catch(error => {
|
|
console.log('视频播放失败:', error);
|
|
setIsVideoPlaying(false);
|
|
});
|
|
}
|
|
}
|
|
}, [currentSketchIndex]);
|
|
|
|
// 更新加载文字
|
|
useEffect(() => {
|
|
if (isLoading) {
|
|
setCurrentLoadingText(STEP_MESSAGES.loading);
|
|
return;
|
|
}
|
|
|
|
switch (currentStep) {
|
|
case '1':
|
|
setCurrentLoadingText(
|
|
isGeneratingSketch
|
|
? STEP_MESSAGES.sketch(sketchCount, MOCK_SKETCH_COUNT)
|
|
: STEP_MESSAGES.sketchComplete
|
|
);
|
|
break;
|
|
case '2':
|
|
setCurrentLoadingText(STEP_MESSAGES.character);
|
|
break;
|
|
case '3':
|
|
setCurrentLoadingText(
|
|
isGeneratingVideo
|
|
? STEP_MESSAGES.video(taskVideos.length, taskSketch.length)
|
|
: STEP_MESSAGES.videoComplete
|
|
);
|
|
break;
|
|
case '4':
|
|
setCurrentLoadingText(STEP_MESSAGES.audio);
|
|
break;
|
|
case '5':
|
|
setCurrentLoadingText(STEP_MESSAGES.final);
|
|
break;
|
|
default:
|
|
setCurrentLoadingText(STEP_MESSAGES.complete);
|
|
}
|
|
}, [isLoading, currentStep, isGeneratingSketch, sketchCount, isGeneratingVideo, taskVideos.length, taskSketch.length]);
|
|
|
|
// 控制函数
|
|
const togglePlay = useCallback(() => {
|
|
setIsPlaying(prev => !prev);
|
|
}, []);
|
|
|
|
const toggleVideoPlay = useCallback(() => {
|
|
if (mainVideoRef.current) {
|
|
if (isVideoPlaying) {
|
|
mainVideoRef.current.pause();
|
|
} else {
|
|
mainVideoRef.current.play();
|
|
}
|
|
}
|
|
setIsVideoPlaying(prev => !prev);
|
|
}, [isVideoPlaying]);
|
|
|
|
const handleEditModalOpen = (tab: string) => {
|
|
setIsPlaying(false);
|
|
setIsVideoPlaying(false);
|
|
setActiveEditTab(tab);
|
|
setIsEditModalOpen(true);
|
|
};
|
|
|
|
// 当切换到视频模式时,停止播放
|
|
useEffect(() => {
|
|
if (currentStep === '3') {
|
|
setIsPlaying(false);
|
|
}
|
|
}, [currentStep]);
|
|
|
|
// 当切换到分镜草图模式时,停止视频播放
|
|
useEffect(() => {
|
|
if (currentStep !== '3') {
|
|
setIsVideoPlaying(false);
|
|
}
|
|
}, [currentStep]);
|
|
|
|
return {
|
|
// 数据状态
|
|
taskObject,
|
|
taskSketch,
|
|
taskVideos,
|
|
isLoading,
|
|
currentStep,
|
|
currentSketchIndex,
|
|
setCurrentSketchIndex,
|
|
currentLoadingText,
|
|
|
|
// 生成状态
|
|
isGeneratingSketch,
|
|
isGeneratingVideo,
|
|
sketchCount,
|
|
|
|
// 播放状态
|
|
isPlaying,
|
|
isVideoPlaying,
|
|
mainVideoRef,
|
|
|
|
// 拖拽状态
|
|
isDragging,
|
|
setIsDragging,
|
|
startX,
|
|
setStartX,
|
|
scrollLeft,
|
|
setScrollLeft,
|
|
|
|
// 界面状态
|
|
showControls,
|
|
setShowControls,
|
|
isEditModalOpen,
|
|
setIsEditModalOpen,
|
|
activeEditTab,
|
|
|
|
// 控制函数
|
|
togglePlay,
|
|
toggleVideoPlay,
|
|
handleEditModalOpen,
|
|
};
|
|
};
|