优化hooks多次初始化ing

This commit is contained in:
北枳 2025-08-16 15:06:54 +08:00
parent fd7aa0a18e
commit adf4579ee1
3 changed files with 69 additions and 93 deletions

View File

@ -58,14 +58,9 @@ const WorkFlow = React.memo(function WorkFlow() {
} = useWorkflowData();
const {
isPlaying,
isVideoPlaying,
showControls,
setShowControls,
setIsPlaying,
togglePlay,
toggleVideoPlay,
playTimerRef,
} = usePlaybackControls(taskSketch, taskVideos, currentStep);
useEffect(() => {
@ -162,10 +157,8 @@ const WorkFlow = React.memo(function WorkFlow() {
taskSketch={taskSketch}
taskVideos={taskVideos}
isVideoPlaying={isVideoPlaying}
showControls={showControls}
isGeneratingSketch={isGeneratingSketch}
isGeneratingVideo={isGeneratingVideo}
onControlsChange={setShowControls}
onEditModalOpen={handleEditModalOpen}
onToggleVideoPlay={toggleVideoPlay}
onTogglePlay={togglePlay}

View File

@ -17,10 +17,8 @@ interface MediaViewerProps {
taskSketch: any[];
taskVideos: any[];
isVideoPlaying: boolean;
showControls: boolean;
isGeneratingSketch: boolean;
isGeneratingVideo: boolean;
onControlsChange: (show: boolean) => void;
onEditModalOpen: (tab: string) => void;
onToggleVideoPlay: () => void;
onTogglePlay: () => void;
@ -39,10 +37,8 @@ export const MediaViewer = React.memo(function MediaViewer({
taskSketch,
taskVideos,
isVideoPlaying,
showControls,
isGeneratingSketch,
isGeneratingVideo,
onControlsChange,
onEditModalOpen,
onToggleVideoPlay,
onTogglePlay,
@ -270,7 +266,6 @@ export const MediaViewer = React.memo(function MediaViewer({
{/* 静音按钮 */}
<GlassIconButton
icon={isMuted ? VolumeX : Volume2}
tooltip={isMuted ? "取消静音" : "静音"}
onClick={toggleMute}
size="sm"
/>
@ -312,10 +307,8 @@ export const MediaViewer = React.memo(function MediaViewer({
<div
className="relative w-full h-full rounded-lg overflow-hidden"
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
className="absolute inset-0 overflow-hidden"
@ -347,21 +340,18 @@ export const MediaViewer = React.memo(function MediaViewer({
{/* 操作按钮组 */}
<AnimatePresence>
{showControls && (
<motion.div
className="absolute top-4 right-4 z-10 flex gap-2"
initial={{ opacity: 0, y: -10 }}
animate={{ opacity: 1, y: 0 }}
exit={{ opacity: 0, y: -10 }}
transition={{ duration: 0.2 }}
>
<GlassIconButton
icon={Edit3}
tooltip="Edit sketch"
onClick={() => handleEditClick('3', 'final')}
/>
</motion.div>
)}
<motion.div
className="absolute top-4 right-4 z-10 gap-2 hidden group-hover:flex"
initial={{ opacity: 0, y: -10 }}
animate={{ opacity: 1, y: 0 }}
exit={{ opacity: 0, y: -10 }}
transition={{ duration: 0.2 }}
>
<GlassIconButton
icon={Edit3}
onClick={() => handleEditClick('3', 'final')}
/>
</motion.div>
</AnimatePresence>
{/* 视频信息浮层 */}
@ -405,7 +395,6 @@ export const MediaViewer = React.memo(function MediaViewer({
>
<GlassIconButton
icon={isFinalVideoPlaying ? Pause : Play}
tooltip={isFinalVideoPlaying ? "Pause video" : "Play video"}
onClick={toggleFinalVideoPlay}
size="sm"
/>
@ -417,7 +406,6 @@ export const MediaViewer = React.memo(function MediaViewer({
{/* 全屏按钮 */}
<GlassIconButton
icon={isFullscreen ? Minimize : Maximize}
tooltip={isFullscreen ? "退出全屏" : "全屏"}
onClick={toggleFullscreen}
size="sm"
/>
@ -442,9 +430,7 @@ export const MediaViewer = React.memo(function MediaViewer({
const renderVideoContent = () => {
return (
<div
className="relative w-full h-full rounded-lg"
onMouseEnter={() => onControlsChange(true)}
onMouseLeave={() => onControlsChange(false)}
className="relative w-full h-full rounded-lg group"
>
{/* 只在生成过程中或没有视频时使用ProgressiveReveal */}
<div className="relative w-full h-full">
@ -500,21 +486,18 @@ export const MediaViewer = React.memo(function MediaViewer({
{/* 操作按钮组 */}
<AnimatePresence>
{showControls && (
<motion.div
className="absolute top-4 right-4 flex gap-2 z-[11]"
initial={{ opacity: 0, y: -10 }}
animate={{ opacity: 1, y: 0 }}
exit={{ opacity: 0, y: -10 }}
transition={{ duration: 0.2 }}
>
<GlassIconButton
icon={Edit3}
tooltip="Edit sketch"
onClick={() => handleEditClick('3')}
/>
</motion.div>
)}
<motion.div
className="absolute top-4 right-4 gap-2 z-[11] hidden group-hover:flex"
initial={{ opacity: 0, y: -10 }}
animate={{ opacity: 1, y: 0 }}
exit={{ opacity: 0, y: -10 }}
transition={{ duration: 0.2 }}
>
<GlassIconButton
icon={Edit3}
onClick={() => handleEditClick('3')}
/>
</motion.div>
</AnimatePresence>
{/* 底部控制区域 */}
@ -535,7 +518,6 @@ export const MediaViewer = React.memo(function MediaViewer({
>
<GlassIconButton
icon={isVideoPlaying ? Pause : Play}
tooltip={isVideoPlaying ? "Pause video" : "Play video"}
onClick={onToggleVideoPlay}
size="sm"
/>
@ -557,9 +539,7 @@ export const MediaViewer = React.memo(function MediaViewer({
return (
<div
className="relative w-full h-full rounded-lg"
onMouseEnter={() => onControlsChange(true)}
onMouseLeave={() => onControlsChange(false)}
className="relative w-full h-full rounded-lg group"
>
{/* 状态 */}
{currentSketch.status === 0 && (
@ -590,21 +570,18 @@ export const MediaViewer = React.memo(function MediaViewer({
{/* 操作按钮组 */}
<AnimatePresence>
{showControls && (
<motion.div
className="absolute top-4 right-4 flex gap-2"
initial={{ opacity: 0, y: -10 }}
animate={{ opacity: 1, y: 0 }}
exit={{ opacity: 0, y: -10 }}
transition={{ duration: 0.2 }}
>
<GlassIconButton
icon={Edit3}
tooltip="Edit sketch"
onClick={() => handleEditClick('1')}
/>
</motion.div>
)}
<motion.div
className="absolute top-4 right-4 gap-2 hidden group-hover:flex"
initial={{ opacity: 0, y: -10 }}
animate={{ opacity: 1, y: 0 }}
exit={{ opacity: 0, y: -10 }}
transition={{ duration: 0.2 }}
>
<GlassIconButton
icon={Edit3}
onClick={() => handleEditClick('1')}
/>
</motion.div>
</AnimatePresence>
{/* 底部播放按钮 */}

View File

@ -1,6 +1,6 @@
'use client';
import { useState, useEffect, useCallback, useRef } from 'react';
import { useState, useEffect, useCallback, useRef, useMemo } from 'react';
import { useSearchParams } from 'next/navigation';
import { detailScriptEpisodeNew, getScriptTitle, getRunningStreamData, pauseMovieProjectPlan, resumeMovieProjectPlan } from '@/api/video_flow';
import { useAppDispatch, useAppSelector } from '@/lib/store/hooks';
@ -42,7 +42,7 @@ type ApiStep = keyof typeof STEP_MAP;
export function useWorkflowData() {
console.log('98877766777777888888990')
console.log('init-useWorkflowData')
const searchParams = useSearchParams();
const episodeId = searchParams.get('episodeId') || '';
@ -78,13 +78,10 @@ export function useWorkflowData() {
// 更新 taskObject 的类型
const [taskObject, setTaskObject] = useState<TaskObject>(tempTaskObject.current);
const [originalText, setOriginalText] = useState<string>('');
const [scriptData, setScriptData] = useState<any>(null);
const [taskSketch, setTaskSketch] = useState<any[]>([]);
const [taskScenes, setTaskScenes] = useState<any[]>([]);
const [taskShotSketch, setTaskShotSketch] = useState<any[]>([]);
const [taskVideos, setTaskVideos] = useState<any[]>([]);
const [isLoading, setIsLoading] = useState(true);
const [currentStep, setCurrentStep] = useState('0');
const [currentSketchIndex, setCurrentSketchIndex] = useState(0);
const [isGeneratingSketch, setIsGeneratingSketch] = useState(false);
@ -97,7 +94,11 @@ export function useWorkflowData() {
const [dataLoadError, setDataLoadError] = useState<string | null>(null);
const [needStreamData, setNeedStreamData] = 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();
@ -110,12 +111,8 @@ export function useWorkflowData() {
applyScript
} = useScriptService();
// 监听剧本加载完毕
useEffect(() => {
if (scriptBlocksMemo.length > 0) {
console.log('scriptBlocksMemo 更新:', scriptBlocksMemo);
setScriptData(scriptBlocksMemo);
// setCurrentLoadingText(LOADING_TEXT_MAP.script);
}
const scriptData = useMemo(() => {
return scriptBlocksMemo.length > 0 ? scriptBlocksMemo : null;
}, [scriptBlocksMemo]);
// 监听继续 请求更新数据
useUpdateEffect(() => {
@ -418,7 +415,7 @@ export function useWorkflowData() {
} catch (error) {
console.error('获取数据失败:', error);
}
}, [episodeId, needStreamData, roles.length, taskShotSketch.length]);
}, [episodeId, needStreamData]);
// 轮询获取流式数据
useUpdateEffect(() => {
@ -440,12 +437,15 @@ export function useWorkflowData() {
const initializeWorkflow = async () => {
if (!episodeId) {
setDataLoadError('缺少必要的参数');
setIsLoading(false);
return;
}
try {
setIsLoading(true);
setState({
mode: 'automatic' as 'automatic' | 'manual' | 'auto',
originalText: '',
isLoading: true
});
setCurrentLoadingText('loading project info...');
// 获取剧集详情
@ -455,9 +455,6 @@ export function useWorkflowData() {
}
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;
@ -585,15 +582,20 @@ export function useWorkflowData() {
console.log('---look-taskData', taskCurrent);
if (taskCurrent.currentStage === 'script') {
console.log('开始初始化剧本', originalText,episodeId);
console.log('开始初始化剧本', original_text,episodeId);
// TODO 为什么一开始没项目id
originalText && initializeFromProject(episodeId, originalText).then(() => {
original_text && initializeFromProject(episodeId, original_text).then(() => {
console.log('应用剧本');
// 自动模式下 应用剧本;手动模式 需要点击 下一步 触发
mode.includes('auto') && applyScript();
});
}
setState({
mode: mode as 'automatic' | 'manual' | 'auto',
originalText: original_text,
isLoading: false
});
// 设置步骤
setTaskObject(prev => {
const newState = JSON.parse(JSON.stringify({...prev, ...taskCurrent}));
@ -606,7 +608,11 @@ export function useWorkflowData() {
} catch (error) {
console.error('初始化失败:', error);
setDataLoadError('加载失败,请重试');
setIsLoading(false);
setState({
mode: 'automatic' as 'automatic' | 'manual' | 'auto',
originalText: '',
isLoading: false
});
}
};
@ -649,7 +655,7 @@ export function useWorkflowData() {
taskShotSketch,
taskVideos,
sketchCount,
isLoading,
isLoading: state.isLoading,
currentStep,
currentSketchIndex,
isGeneratingSketch,
@ -664,11 +670,11 @@ export function useWorkflowData() {
retryLoadData,
handleManualPlay,
isPauseWorkFlow,
mode,
mode: state.mode,
setIsPauseWorkFlow,
setAnyAttribute,
applyScript,
fallbackToStep,
originalText
originalText: state.originalText
};
}