forked from 77media/video-flow
246 lines
8.1 KiB
TypeScript
246 lines
8.1 KiB
TypeScript
'use client';
|
|
|
|
import { useState, useEffect, useRef, useCallback } from 'react';
|
|
import { getRandomMockData, STEP_MESSAGES } from '@/components/work-flow/constants';
|
|
|
|
// 当前选择的mock数据
|
|
let selectedMockData = getRandomMockData();
|
|
|
|
export function useWorkflowData() {
|
|
const [taskObject, setTaskObject] = useState<any>(null);
|
|
const [taskSketch, setTaskSketch] = useState<any[]>([]);
|
|
const [taskVideos, setTaskVideos] = useState<any[]>([]);
|
|
const [sketchCount, setSketchCount] = useState(0);
|
|
const [isLoading, setIsLoading] = useState(true);
|
|
const [currentStep, setCurrentStep] = useState('0');
|
|
const [currentSketchIndex, setCurrentSketchIndex] = useState(0);
|
|
const [isGeneratingSketch, setIsGeneratingSketch] = useState(false);
|
|
const [isGeneratingVideo, setIsGeneratingVideo] = useState(false);
|
|
const [currentLoadingText, setCurrentLoadingText] = useState('Loading task information...');
|
|
|
|
// 模拟接口请求 获取任务详情
|
|
const getTaskDetail = async (taskId: string) => {
|
|
// 每次进入页面时重新随机选择数据
|
|
selectedMockData = getRandomMockData();
|
|
|
|
const data = {
|
|
projectId: selectedMockData.detail.projectId,
|
|
projectName: selectedMockData.detail.projectName,
|
|
taskId: taskId,
|
|
taskName: selectedMockData.detail.taskName,
|
|
taskDescription: selectedMockData.detail.taskDescription,
|
|
taskStatus: selectedMockData.detail.taskStatus,
|
|
taskProgress: 0,
|
|
mode: selectedMockData.detail.mode,
|
|
resolution: selectedMockData.detail.resolution.toString(),
|
|
};
|
|
return data;
|
|
};
|
|
|
|
// 模拟接口请求 每次获取一个分镜草图 轮询获取
|
|
const getTaskSketch = async (taskId: string) => {
|
|
if (isGeneratingSketch || taskSketch.length > 0) return;
|
|
|
|
setIsGeneratingSketch(true);
|
|
setTaskSketch([]);
|
|
|
|
const sketchData = selectedMockData.sketch;
|
|
const totalSketches = sketchData.length;
|
|
|
|
// 模拟分批获取分镜草图
|
|
for (let i = 0; i < totalSketches; i++) {
|
|
await new Promise(resolve => setTimeout(resolve, 5000)); // 10s
|
|
|
|
const newSketch = {
|
|
id: `sketch-${i}`,
|
|
url: sketchData[i].url,
|
|
script: sketchData[i].script,
|
|
bg_rgb: sketchData[i].bg_rgb,
|
|
status: 'done'
|
|
};
|
|
|
|
setTaskSketch(prev => {
|
|
if (prev.find(sketch => sketch.id === newSketch.id)) {
|
|
return prev;
|
|
}
|
|
return [...prev, newSketch];
|
|
});
|
|
setCurrentSketchIndex(i);
|
|
setSketchCount(i + 1);
|
|
}
|
|
|
|
// 等待最后一个动画完成再设置生成状态为false
|
|
await new Promise(resolve => setTimeout(resolve, 1500));
|
|
setIsGeneratingSketch(false);
|
|
};
|
|
|
|
// 模拟接口请求 每次获取一个角色 轮询获取
|
|
const getTaskRole = async (taskId: string) => {
|
|
await new Promise(resolve => setTimeout(resolve, 2000 * selectedMockData.roles.length)); // 延长到30秒
|
|
};
|
|
|
|
// 模拟接口请求 获取背景音
|
|
const getTaskBackgroundAudio = async (taskId: string) => {
|
|
await new Promise(resolve => setTimeout(resolve, 2000)); // 10s
|
|
};
|
|
|
|
// 模拟接口请求 获取最终成品
|
|
const getTaskFinalProduct = async (taskId: string) => {
|
|
await new Promise(resolve => setTimeout(resolve, 10000)); // 50s
|
|
};
|
|
|
|
// 模拟接口请求 每次获取一个分镜视频 轮询获取
|
|
const getTaskVideo = async (taskId: string) => {
|
|
setIsGeneratingVideo(true);
|
|
setTaskVideos([]);
|
|
|
|
const videoData = selectedMockData.video;
|
|
const totalVideos = videoData.length;
|
|
|
|
// 模拟分批获取分镜视频
|
|
for (let i = 0; i < totalVideos; i++) {
|
|
await new Promise(resolve => setTimeout(resolve, 6000)); // 60s
|
|
|
|
const newVideo = {
|
|
id: `video-${i}`,
|
|
url: videoData[i].url,
|
|
script: videoData[i].script,
|
|
status: 'done'
|
|
};
|
|
|
|
setTaskVideos(prev => {
|
|
if (prev.find(video => video.id === newVideo.id)) {
|
|
return prev;
|
|
}
|
|
return [...prev, newVideo];
|
|
});
|
|
setCurrentSketchIndex(i);
|
|
}
|
|
|
|
// 等待最后一个动画完成再设置生成状态为false
|
|
await new Promise(resolve => setTimeout(resolve, 1500));
|
|
setIsGeneratingVideo(false);
|
|
};
|
|
|
|
// 更新加载文字
|
|
useEffect(() => {
|
|
if (isLoading) {
|
|
setCurrentLoadingText(STEP_MESSAGES.loading);
|
|
return;
|
|
}
|
|
|
|
const totalSketches = selectedMockData.sketch.length;
|
|
|
|
if (currentStep === '1') {
|
|
if (isGeneratingSketch) {
|
|
setCurrentLoadingText(STEP_MESSAGES.sketch(sketchCount, totalSketches));
|
|
} else {
|
|
setCurrentLoadingText(STEP_MESSAGES.sketchComplete);
|
|
}
|
|
} else if (currentStep === '2') {
|
|
setCurrentLoadingText(STEP_MESSAGES.character);
|
|
} else if (currentStep === '3') {
|
|
if (isGeneratingVideo) {
|
|
setCurrentLoadingText(STEP_MESSAGES.video(taskVideos.length, totalSketches));
|
|
} else {
|
|
setCurrentLoadingText(STEP_MESSAGES.videoComplete);
|
|
}
|
|
} else if (currentStep === '4') {
|
|
setCurrentLoadingText(STEP_MESSAGES.audio);
|
|
} else if (currentStep === '5') {
|
|
setCurrentLoadingText(STEP_MESSAGES.final);
|
|
} else {
|
|
setCurrentLoadingText(STEP_MESSAGES.complete);
|
|
}
|
|
}, [isLoading, currentStep, isGeneratingSketch, sketchCount, isGeneratingVideo, taskVideos.length, taskSketch.length]);
|
|
|
|
// 初始化数据
|
|
useEffect(() => {
|
|
const taskId = localStorage.getItem("taskId") || "taskId-123";
|
|
getTaskDetail(taskId).then(async (data) => {
|
|
setTaskObject(data);
|
|
setIsLoading(false);
|
|
setCurrentStep('1');
|
|
|
|
// 只在任务详情加载完成后获取分镜草图
|
|
await getTaskSketch(taskId);
|
|
|
|
// 修改 taskObject 下的 taskStatus 为 '2'
|
|
setTaskObject((prev: any) => ({
|
|
...prev,
|
|
taskStatus: '2'
|
|
}));
|
|
setCurrentStep('2');
|
|
|
|
// 获取分镜草图后,开始绘制角色
|
|
await getTaskRole(taskId);
|
|
|
|
// 修改 taskObject 下的 taskStatus 为 '3'
|
|
setTaskObject((prev: any) => ({
|
|
...prev,
|
|
taskStatus: '3'
|
|
}));
|
|
setCurrentStep('3');
|
|
|
|
// 获取绘制角色后,开始获取分镜视频
|
|
await getTaskVideo(taskId);
|
|
|
|
// 修改 taskObject 下的 taskStatus 为 '4'
|
|
setTaskObject((prev: any) => ({
|
|
...prev,
|
|
taskStatus: '4'
|
|
}));
|
|
setCurrentStep('4');
|
|
|
|
// 获取分镜视频后,开始获取背景音
|
|
await getTaskBackgroundAudio(taskId);
|
|
await new Promise(resolve => setTimeout(resolve, 2000));
|
|
|
|
// 修改 taskObject 下的 taskStatus 为 '5'
|
|
setTaskObject((prev: any) => ({
|
|
...prev,
|
|
taskStatus: '5'
|
|
}));
|
|
setCurrentStep('5');
|
|
// 后期制作:抽卡中 对口型中 配音中 一致性处理中
|
|
setCurrentLoadingText(STEP_MESSAGES.postProduction('Selecting optimal frames'));
|
|
await new Promise(resolve => setTimeout(resolve, 10000));
|
|
setCurrentLoadingText(STEP_MESSAGES.postProduction('Aligning lip sync'));
|
|
await new Promise(resolve => setTimeout(resolve, 10000));
|
|
setCurrentLoadingText(STEP_MESSAGES.postProduction('Adding background audio'));
|
|
await new Promise(resolve => setTimeout(resolve, 10000));
|
|
setCurrentLoadingText(STEP_MESSAGES.postProduction('Consistency processing'));
|
|
await new Promise(resolve => setTimeout(resolve, 10000));
|
|
// 获取背景音后,开始获取最终成品
|
|
await getTaskFinalProduct(taskId);
|
|
await new Promise(resolve => setTimeout(resolve, 2000));
|
|
|
|
// 修改 taskObject 下的 taskStatus 为 '6'
|
|
setTaskObject((prev: any) => ({
|
|
...prev,
|
|
taskStatus: '6'
|
|
}));
|
|
setCurrentStep('6');
|
|
});
|
|
}, []);
|
|
|
|
return {
|
|
// 状态数据
|
|
taskObject,
|
|
taskSketch,
|
|
taskVideos,
|
|
sketchCount,
|
|
isLoading,
|
|
currentStep,
|
|
currentSketchIndex,
|
|
isGeneratingSketch,
|
|
isGeneratingVideo,
|
|
currentLoadingText,
|
|
totalSketchCount: selectedMockData.sketch.length,
|
|
roles: selectedMockData.roles,
|
|
music: selectedMockData.music,
|
|
final: selectedMockData.final,
|
|
// 操作方法
|
|
setCurrentSketchIndex,
|
|
};
|
|
}
|