forked from 77media/video-flow
优化hooks多次初始化ing
This commit is contained in:
parent
fd7aa0a18e
commit
adf4579ee1
@ -58,14 +58,9 @@ const WorkFlow = React.memo(function WorkFlow() {
|
|||||||
} = useWorkflowData();
|
} = useWorkflowData();
|
||||||
|
|
||||||
const {
|
const {
|
||||||
isPlaying,
|
|
||||||
isVideoPlaying,
|
isVideoPlaying,
|
||||||
showControls,
|
|
||||||
setShowControls,
|
|
||||||
setIsPlaying,
|
|
||||||
togglePlay,
|
togglePlay,
|
||||||
toggleVideoPlay,
|
toggleVideoPlay,
|
||||||
playTimerRef,
|
|
||||||
} = usePlaybackControls(taskSketch, taskVideos, currentStep);
|
} = usePlaybackControls(taskSketch, taskVideos, currentStep);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@ -162,10 +157,8 @@ const WorkFlow = React.memo(function WorkFlow() {
|
|||||||
taskSketch={taskSketch}
|
taskSketch={taskSketch}
|
||||||
taskVideos={taskVideos}
|
taskVideos={taskVideos}
|
||||||
isVideoPlaying={isVideoPlaying}
|
isVideoPlaying={isVideoPlaying}
|
||||||
showControls={showControls}
|
|
||||||
isGeneratingSketch={isGeneratingSketch}
|
isGeneratingSketch={isGeneratingSketch}
|
||||||
isGeneratingVideo={isGeneratingVideo}
|
isGeneratingVideo={isGeneratingVideo}
|
||||||
onControlsChange={setShowControls}
|
|
||||||
onEditModalOpen={handleEditModalOpen}
|
onEditModalOpen={handleEditModalOpen}
|
||||||
onToggleVideoPlay={toggleVideoPlay}
|
onToggleVideoPlay={toggleVideoPlay}
|
||||||
onTogglePlay={togglePlay}
|
onTogglePlay={togglePlay}
|
||||||
|
|||||||
@ -17,10 +17,8 @@ interface MediaViewerProps {
|
|||||||
taskSketch: any[];
|
taskSketch: any[];
|
||||||
taskVideos: any[];
|
taskVideos: any[];
|
||||||
isVideoPlaying: boolean;
|
isVideoPlaying: boolean;
|
||||||
showControls: boolean;
|
|
||||||
isGeneratingSketch: boolean;
|
isGeneratingSketch: boolean;
|
||||||
isGeneratingVideo: boolean;
|
isGeneratingVideo: boolean;
|
||||||
onControlsChange: (show: boolean) => void;
|
|
||||||
onEditModalOpen: (tab: string) => void;
|
onEditModalOpen: (tab: string) => void;
|
||||||
onToggleVideoPlay: () => void;
|
onToggleVideoPlay: () => void;
|
||||||
onTogglePlay: () => void;
|
onTogglePlay: () => void;
|
||||||
@ -39,10 +37,8 @@ export const MediaViewer = React.memo(function MediaViewer({
|
|||||||
taskSketch,
|
taskSketch,
|
||||||
taskVideos,
|
taskVideos,
|
||||||
isVideoPlaying,
|
isVideoPlaying,
|
||||||
showControls,
|
|
||||||
isGeneratingSketch,
|
isGeneratingSketch,
|
||||||
isGeneratingVideo,
|
isGeneratingVideo,
|
||||||
onControlsChange,
|
|
||||||
onEditModalOpen,
|
onEditModalOpen,
|
||||||
onToggleVideoPlay,
|
onToggleVideoPlay,
|
||||||
onTogglePlay,
|
onTogglePlay,
|
||||||
@ -270,7 +266,6 @@ export const MediaViewer = React.memo(function MediaViewer({
|
|||||||
{/* 静音按钮 */}
|
{/* 静音按钮 */}
|
||||||
<GlassIconButton
|
<GlassIconButton
|
||||||
icon={isMuted ? VolumeX : Volume2}
|
icon={isMuted ? VolumeX : Volume2}
|
||||||
tooltip={isMuted ? "取消静音" : "静音"}
|
|
||||||
onClick={toggleMute}
|
onClick={toggleMute}
|
||||||
size="sm"
|
size="sm"
|
||||||
/>
|
/>
|
||||||
@ -312,10 +307,8 @@ export const MediaViewer = React.memo(function MediaViewer({
|
|||||||
<div
|
<div
|
||||||
className="relative w-full h-full rounded-lg overflow-hidden"
|
className="relative w-full h-full rounded-lg overflow-hidden"
|
||||||
key={`render-video-${taskObject.final.note}`}
|
key={`render-video-${taskObject.final.note}`}
|
||||||
onMouseEnter={() => onControlsChange(true)}
|
|
||||||
onMouseLeave={() => onControlsChange(false)}
|
|
||||||
>
|
>
|
||||||
<div className="relative w-full h-full">
|
<div className="relative w-full h-full group">
|
||||||
{/* 背景模糊的视频 */}
|
{/* 背景模糊的视频 */}
|
||||||
<motion.div
|
<motion.div
|
||||||
className="absolute inset-0 overflow-hidden"
|
className="absolute inset-0 overflow-hidden"
|
||||||
@ -347,21 +340,18 @@ export const MediaViewer = React.memo(function MediaViewer({
|
|||||||
|
|
||||||
{/* 操作按钮组 */}
|
{/* 操作按钮组 */}
|
||||||
<AnimatePresence>
|
<AnimatePresence>
|
||||||
{showControls && (
|
<motion.div
|
||||||
<motion.div
|
className="absolute top-4 right-4 z-10 gap-2 hidden group-hover:flex"
|
||||||
className="absolute top-4 right-4 z-10 flex gap-2"
|
initial={{ opacity: 0, y: -10 }}
|
||||||
initial={{ opacity: 0, y: -10 }}
|
animate={{ opacity: 1, y: 0 }}
|
||||||
animate={{ opacity: 1, y: 0 }}
|
exit={{ opacity: 0, y: -10 }}
|
||||||
exit={{ opacity: 0, y: -10 }}
|
transition={{ duration: 0.2 }}
|
||||||
transition={{ duration: 0.2 }}
|
>
|
||||||
>
|
<GlassIconButton
|
||||||
<GlassIconButton
|
icon={Edit3}
|
||||||
icon={Edit3}
|
onClick={() => handleEditClick('3', 'final')}
|
||||||
tooltip="Edit sketch"
|
/>
|
||||||
onClick={() => handleEditClick('3', 'final')}
|
</motion.div>
|
||||||
/>
|
|
||||||
</motion.div>
|
|
||||||
)}
|
|
||||||
</AnimatePresence>
|
</AnimatePresence>
|
||||||
|
|
||||||
{/* 视频信息浮层 */}
|
{/* 视频信息浮层 */}
|
||||||
@ -405,7 +395,6 @@ export const MediaViewer = React.memo(function MediaViewer({
|
|||||||
>
|
>
|
||||||
<GlassIconButton
|
<GlassIconButton
|
||||||
icon={isFinalVideoPlaying ? Pause : Play}
|
icon={isFinalVideoPlaying ? Pause : Play}
|
||||||
tooltip={isFinalVideoPlaying ? "Pause video" : "Play video"}
|
|
||||||
onClick={toggleFinalVideoPlay}
|
onClick={toggleFinalVideoPlay}
|
||||||
size="sm"
|
size="sm"
|
||||||
/>
|
/>
|
||||||
@ -417,7 +406,6 @@ export const MediaViewer = React.memo(function MediaViewer({
|
|||||||
{/* 全屏按钮 */}
|
{/* 全屏按钮 */}
|
||||||
<GlassIconButton
|
<GlassIconButton
|
||||||
icon={isFullscreen ? Minimize : Maximize}
|
icon={isFullscreen ? Minimize : Maximize}
|
||||||
tooltip={isFullscreen ? "退出全屏" : "全屏"}
|
|
||||||
onClick={toggleFullscreen}
|
onClick={toggleFullscreen}
|
||||||
size="sm"
|
size="sm"
|
||||||
/>
|
/>
|
||||||
@ -442,9 +430,7 @@ export const MediaViewer = React.memo(function MediaViewer({
|
|||||||
const renderVideoContent = () => {
|
const renderVideoContent = () => {
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className="relative w-full h-full rounded-lg"
|
className="relative w-full h-full rounded-lg group"
|
||||||
onMouseEnter={() => onControlsChange(true)}
|
|
||||||
onMouseLeave={() => onControlsChange(false)}
|
|
||||||
>
|
>
|
||||||
{/* 只在生成过程中或没有视频时使用ProgressiveReveal */}
|
{/* 只在生成过程中或没有视频时使用ProgressiveReveal */}
|
||||||
<div className="relative w-full h-full">
|
<div className="relative w-full h-full">
|
||||||
@ -500,21 +486,18 @@ export const MediaViewer = React.memo(function MediaViewer({
|
|||||||
|
|
||||||
{/* 操作按钮组 */}
|
{/* 操作按钮组 */}
|
||||||
<AnimatePresence>
|
<AnimatePresence>
|
||||||
{showControls && (
|
<motion.div
|
||||||
<motion.div
|
className="absolute top-4 right-4 gap-2 z-[11] hidden group-hover:flex"
|
||||||
className="absolute top-4 right-4 flex gap-2 z-[11]"
|
initial={{ opacity: 0, y: -10 }}
|
||||||
initial={{ opacity: 0, y: -10 }}
|
animate={{ opacity: 1, y: 0 }}
|
||||||
animate={{ opacity: 1, y: 0 }}
|
exit={{ opacity: 0, y: -10 }}
|
||||||
exit={{ opacity: 0, y: -10 }}
|
transition={{ duration: 0.2 }}
|
||||||
transition={{ duration: 0.2 }}
|
>
|
||||||
>
|
<GlassIconButton
|
||||||
<GlassIconButton
|
icon={Edit3}
|
||||||
icon={Edit3}
|
onClick={() => handleEditClick('3')}
|
||||||
tooltip="Edit sketch"
|
/>
|
||||||
onClick={() => handleEditClick('3')}
|
</motion.div>
|
||||||
/>
|
|
||||||
</motion.div>
|
|
||||||
)}
|
|
||||||
</AnimatePresence>
|
</AnimatePresence>
|
||||||
|
|
||||||
{/* 底部控制区域 */}
|
{/* 底部控制区域 */}
|
||||||
@ -535,7 +518,6 @@ export const MediaViewer = React.memo(function MediaViewer({
|
|||||||
>
|
>
|
||||||
<GlassIconButton
|
<GlassIconButton
|
||||||
icon={isVideoPlaying ? Pause : Play}
|
icon={isVideoPlaying ? Pause : Play}
|
||||||
tooltip={isVideoPlaying ? "Pause video" : "Play video"}
|
|
||||||
onClick={onToggleVideoPlay}
|
onClick={onToggleVideoPlay}
|
||||||
size="sm"
|
size="sm"
|
||||||
/>
|
/>
|
||||||
@ -557,9 +539,7 @@ export const MediaViewer = React.memo(function MediaViewer({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className="relative w-full h-full rounded-lg"
|
className="relative w-full h-full rounded-lg group"
|
||||||
onMouseEnter={() => onControlsChange(true)}
|
|
||||||
onMouseLeave={() => onControlsChange(false)}
|
|
||||||
>
|
>
|
||||||
{/* 状态 */}
|
{/* 状态 */}
|
||||||
{currentSketch.status === 0 && (
|
{currentSketch.status === 0 && (
|
||||||
@ -590,21 +570,18 @@ export const MediaViewer = React.memo(function MediaViewer({
|
|||||||
|
|
||||||
{/* 操作按钮组 */}
|
{/* 操作按钮组 */}
|
||||||
<AnimatePresence>
|
<AnimatePresence>
|
||||||
{showControls && (
|
<motion.div
|
||||||
<motion.div
|
className="absolute top-4 right-4 gap-2 hidden group-hover:flex"
|
||||||
className="absolute top-4 right-4 flex gap-2"
|
initial={{ opacity: 0, y: -10 }}
|
||||||
initial={{ opacity: 0, y: -10 }}
|
animate={{ opacity: 1, y: 0 }}
|
||||||
animate={{ opacity: 1, y: 0 }}
|
exit={{ opacity: 0, y: -10 }}
|
||||||
exit={{ opacity: 0, y: -10 }}
|
transition={{ duration: 0.2 }}
|
||||||
transition={{ duration: 0.2 }}
|
>
|
||||||
>
|
<GlassIconButton
|
||||||
<GlassIconButton
|
icon={Edit3}
|
||||||
icon={Edit3}
|
onClick={() => handleEditClick('1')}
|
||||||
tooltip="Edit sketch"
|
/>
|
||||||
onClick={() => handleEditClick('1')}
|
</motion.div>
|
||||||
/>
|
|
||||||
</motion.div>
|
|
||||||
)}
|
|
||||||
</AnimatePresence>
|
</AnimatePresence>
|
||||||
|
|
||||||
{/* 底部播放按钮 */}
|
{/* 底部播放按钮 */}
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
'use client';
|
'use client';
|
||||||
|
|
||||||
import { useState, useEffect, useCallback, useRef } from 'react';
|
import { useState, useEffect, useCallback, useRef, useMemo } from 'react';
|
||||||
import { useSearchParams } from 'next/navigation';
|
import { useSearchParams } from 'next/navigation';
|
||||||
import { detailScriptEpisodeNew, getScriptTitle, getRunningStreamData, pauseMovieProjectPlan, resumeMovieProjectPlan } from '@/api/video_flow';
|
import { detailScriptEpisodeNew, getScriptTitle, getRunningStreamData, pauseMovieProjectPlan, resumeMovieProjectPlan } from '@/api/video_flow';
|
||||||
import { useAppDispatch, useAppSelector } from '@/lib/store/hooks';
|
import { useAppDispatch, useAppSelector } from '@/lib/store/hooks';
|
||||||
@ -42,7 +42,7 @@ type ApiStep = keyof typeof STEP_MAP;
|
|||||||
|
|
||||||
|
|
||||||
export function useWorkflowData() {
|
export function useWorkflowData() {
|
||||||
console.log('98877766777777888888990')
|
console.log('init-useWorkflowData')
|
||||||
|
|
||||||
const searchParams = useSearchParams();
|
const searchParams = useSearchParams();
|
||||||
const episodeId = searchParams.get('episodeId') || '';
|
const episodeId = searchParams.get('episodeId') || '';
|
||||||
@ -78,13 +78,10 @@ export function useWorkflowData() {
|
|||||||
|
|
||||||
// 更新 taskObject 的类型
|
// 更新 taskObject 的类型
|
||||||
const [taskObject, setTaskObject] = useState<TaskObject>(tempTaskObject.current);
|
const [taskObject, setTaskObject] = useState<TaskObject>(tempTaskObject.current);
|
||||||
const [originalText, setOriginalText] = useState<string>('');
|
|
||||||
const [scriptData, setScriptData] = useState<any>(null);
|
|
||||||
const [taskSketch, setTaskSketch] = useState<any[]>([]);
|
const [taskSketch, setTaskSketch] = useState<any[]>([]);
|
||||||
const [taskScenes, setTaskScenes] = useState<any[]>([]);
|
const [taskScenes, setTaskScenes] = useState<any[]>([]);
|
||||||
const [taskShotSketch, setTaskShotSketch] = useState<any[]>([]);
|
const [taskShotSketch, setTaskShotSketch] = useState<any[]>([]);
|
||||||
const [taskVideos, setTaskVideos] = useState<any[]>([]);
|
const [taskVideos, setTaskVideos] = useState<any[]>([]);
|
||||||
const [isLoading, setIsLoading] = useState(true);
|
|
||||||
const [currentStep, setCurrentStep] = useState('0');
|
const [currentStep, setCurrentStep] = useState('0');
|
||||||
const [currentSketchIndex, setCurrentSketchIndex] = useState(0);
|
const [currentSketchIndex, setCurrentSketchIndex] = useState(0);
|
||||||
const [isGeneratingSketch, setIsGeneratingSketch] = useState(false);
|
const [isGeneratingSketch, setIsGeneratingSketch] = useState(false);
|
||||||
@ -97,7 +94,11 @@ export function useWorkflowData() {
|
|||||||
const [dataLoadError, setDataLoadError] = useState<string | null>(null);
|
const [dataLoadError, setDataLoadError] = useState<string | null>(null);
|
||||||
const [needStreamData, setNeedStreamData] = useState(false);
|
const [needStreamData, setNeedStreamData] = useState(false);
|
||||||
const [isPauseWorkFlow, setIsPauseWorkFlow] = useState(false);
|
const [isPauseWorkFlow, setIsPauseWorkFlow] = useState(false);
|
||||||
const [mode, setMode] = useState<'automatic' | 'manual' | 'auto'>('automatic');
|
const [state, setState] = useState({
|
||||||
|
mode: 'automatic' as 'automatic' | 'manual' | 'auto',
|
||||||
|
originalText: '',
|
||||||
|
isLoading: true
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
const dispatch = useAppDispatch();
|
const dispatch = useAppDispatch();
|
||||||
@ -110,12 +111,8 @@ export function useWorkflowData() {
|
|||||||
applyScript
|
applyScript
|
||||||
} = useScriptService();
|
} = useScriptService();
|
||||||
// 监听剧本加载完毕
|
// 监听剧本加载完毕
|
||||||
useEffect(() => {
|
const scriptData = useMemo(() => {
|
||||||
if (scriptBlocksMemo.length > 0) {
|
return scriptBlocksMemo.length > 0 ? scriptBlocksMemo : null;
|
||||||
console.log('scriptBlocksMemo 更新:', scriptBlocksMemo);
|
|
||||||
setScriptData(scriptBlocksMemo);
|
|
||||||
// setCurrentLoadingText(LOADING_TEXT_MAP.script);
|
|
||||||
}
|
|
||||||
}, [scriptBlocksMemo]);
|
}, [scriptBlocksMemo]);
|
||||||
// 监听继续 请求更新数据
|
// 监听继续 请求更新数据
|
||||||
useUpdateEffect(() => {
|
useUpdateEffect(() => {
|
||||||
@ -418,7 +415,7 @@ export function useWorkflowData() {
|
|||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('获取数据失败:', error);
|
console.error('获取数据失败:', error);
|
||||||
}
|
}
|
||||||
}, [episodeId, needStreamData, roles.length, taskShotSketch.length]);
|
}, [episodeId, needStreamData]);
|
||||||
|
|
||||||
// 轮询获取流式数据
|
// 轮询获取流式数据
|
||||||
useUpdateEffect(() => {
|
useUpdateEffect(() => {
|
||||||
@ -440,12 +437,15 @@ export function useWorkflowData() {
|
|||||||
const initializeWorkflow = async () => {
|
const initializeWorkflow = async () => {
|
||||||
if (!episodeId) {
|
if (!episodeId) {
|
||||||
setDataLoadError('缺少必要的参数');
|
setDataLoadError('缺少必要的参数');
|
||||||
setIsLoading(false);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
setIsLoading(true);
|
setState({
|
||||||
|
mode: 'automatic' as 'automatic' | 'manual' | 'auto',
|
||||||
|
originalText: '',
|
||||||
|
isLoading: true
|
||||||
|
});
|
||||||
setCurrentLoadingText('loading project info...');
|
setCurrentLoadingText('loading project info...');
|
||||||
|
|
||||||
// 获取剧集详情
|
// 获取剧集详情
|
||||||
@ -455,9 +455,6 @@ export function useWorkflowData() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const { name, status, data, tags, mode, original_text } = response.data;
|
const { name, status, data, tags, mode, original_text } = response.data;
|
||||||
setMode(mode as 'automatic' | 'manual' | 'auto');
|
|
||||||
setOriginalText(original_text);
|
|
||||||
setIsLoading(false);
|
|
||||||
|
|
||||||
const { current: taskCurrent } = tempTaskObject;
|
const { current: taskCurrent } = tempTaskObject;
|
||||||
|
|
||||||
@ -585,15 +582,20 @@ export function useWorkflowData() {
|
|||||||
console.log('---look-taskData', taskCurrent);
|
console.log('---look-taskData', taskCurrent);
|
||||||
|
|
||||||
if (taskCurrent.currentStage === 'script') {
|
if (taskCurrent.currentStage === 'script') {
|
||||||
console.log('开始初始化剧本', originalText,episodeId);
|
console.log('开始初始化剧本', original_text,episodeId);
|
||||||
// TODO 为什么一开始没项目id
|
// TODO 为什么一开始没项目id
|
||||||
originalText && initializeFromProject(episodeId, originalText).then(() => {
|
original_text && initializeFromProject(episodeId, original_text).then(() => {
|
||||||
console.log('应用剧本');
|
console.log('应用剧本');
|
||||||
// 自动模式下 应用剧本;手动模式 需要点击 下一步 触发
|
// 自动模式下 应用剧本;手动模式 需要点击 下一步 触发
|
||||||
mode.includes('auto') && applyScript();
|
mode.includes('auto') && applyScript();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
setState({
|
||||||
|
mode: mode as 'automatic' | 'manual' | 'auto',
|
||||||
|
originalText: original_text,
|
||||||
|
isLoading: false
|
||||||
|
});
|
||||||
// 设置步骤
|
// 设置步骤
|
||||||
setTaskObject(prev => {
|
setTaskObject(prev => {
|
||||||
const newState = JSON.parse(JSON.stringify({...prev, ...taskCurrent}));
|
const newState = JSON.parse(JSON.stringify({...prev, ...taskCurrent}));
|
||||||
@ -606,7 +608,11 @@ export function useWorkflowData() {
|
|||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('初始化失败:', error);
|
console.error('初始化失败:', error);
|
||||||
setDataLoadError('加载失败,请重试');
|
setDataLoadError('加载失败,请重试');
|
||||||
setIsLoading(false);
|
setState({
|
||||||
|
mode: 'automatic' as 'automatic' | 'manual' | 'auto',
|
||||||
|
originalText: '',
|
||||||
|
isLoading: false
|
||||||
|
});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -649,7 +655,7 @@ export function useWorkflowData() {
|
|||||||
taskShotSketch,
|
taskShotSketch,
|
||||||
taskVideos,
|
taskVideos,
|
||||||
sketchCount,
|
sketchCount,
|
||||||
isLoading,
|
isLoading: state.isLoading,
|
||||||
currentStep,
|
currentStep,
|
||||||
currentSketchIndex,
|
currentSketchIndex,
|
||||||
isGeneratingSketch,
|
isGeneratingSketch,
|
||||||
@ -664,11 +670,11 @@ export function useWorkflowData() {
|
|||||||
retryLoadData,
|
retryLoadData,
|
||||||
handleManualPlay,
|
handleManualPlay,
|
||||||
isPauseWorkFlow,
|
isPauseWorkFlow,
|
||||||
mode,
|
mode: state.mode,
|
||||||
setIsPauseWorkFlow,
|
setIsPauseWorkFlow,
|
||||||
setAnyAttribute,
|
setAnyAttribute,
|
||||||
applyScript,
|
applyScript,
|
||||||
fallbackToStep,
|
fallbackToStep,
|
||||||
originalText
|
originalText: state.originalText
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user