diff --git a/api/DTO/movieEdit.ts b/api/DTO/movieEdit.ts index 71ae535..62b67ea 100644 --- a/api/DTO/movieEdit.ts +++ b/api/DTO/movieEdit.ts @@ -119,6 +119,8 @@ export interface SketchResponse { total_count: number; /** 草图数据列表 */ data: SketchData[]; + /** 任务状态 */ + task_status: string; } /** * 角色响应数据接口 @@ -141,6 +143,8 @@ export interface CharacterData { data: CharacterResponse[]; /** 总数 */ total_count: number; + /** 任务状态 */ + task_status: string; } /** * 镜头草图提示JSON结构接口 @@ -191,6 +195,8 @@ export interface ShotSketchResponse { data: ShotSketchData[]; /** 总数 */ total_count: number; + /** 任务状态 */ + task_status: string; } /** * 主要角色列表项 @@ -261,6 +267,8 @@ export interface VideoData { video_name_prefix: string; /** 视频URL列表 */ urls: string[]; + /** 视频状态 */ + video_status: number; } /** * 视频响应数据接口 @@ -275,6 +283,8 @@ export interface VideoResponse { guid: string; /** 项目ID */ project_id: string; + /** 任务状态 */ + task_status: string; } /** * 音乐数据接口 @@ -313,6 +323,8 @@ export interface ProjectContentData { video: VideoResponse; /** 音乐数据 */ music: MusicData; + /** 粗剪视频 */ + final_simple_video: FinalVideo; /** 最终视频 */ final_video: FinalVideo; /** 多语言视频 */ @@ -608,3 +620,54 @@ export interface RoleResponse { character_draft: string; } + +interface Role { + name: string; + url: string; + status: number; +} +interface Scene { + url: string; + script: string; + status: number; +} +interface ShotSketch { + url: string; + script: string; + status: number; +} +interface Video { + video_id: string; + urls: string[]; + video_status: number; +} + +export type Status = 'IN_PROGRESS' | 'COMPLETED' | 'FAILED'; +export type Stage = 'script' | 'character' | 'scene' | 'shot_sketch' | 'video' | 'final_video'; +// 添加 TaskObject 接口 +export interface TaskObject { + title: string; // 标题 + tags?: any[]; // 主题 + currentStage: Stage; // 当前阶段 + status: Status; // 状态 + roles: { + data: Role[]; + total_count: number; + }; // 角色 + scenes: { + data: Scene[]; + total_count: number; + }; // 场景 + shot_sketch: { + data: ShotSketch[]; + total_count: number; + }; // 分镜草图 + videos: { + data: Video[]; + total_count: number; + }; // 视频 + final: { + url: string; + note: string; + }; // 剪辑视频 +} \ No newline at end of file diff --git a/app/service/adapter/oldErrAdapter.ts b/app/service/adapter/oldErrAdapter.ts index d4a1791..d576d82 100644 --- a/app/service/adapter/oldErrAdapter.ts +++ b/app/service/adapter/oldErrAdapter.ts @@ -37,6 +37,10 @@ export class VideoSegmentEntityAdapter { task_status: string = ""; /** 任务结果 */ task_result: Array<{ + /** 任务ID */ + video_id: string; + /** 任务状态 */ + video_status: number|null; /** 叙事目标 */ narrative_goal: string; /** 镜头1描述 */ @@ -175,6 +179,8 @@ export class VideoSegmentEntityAdapter { */ static fromVideoSegmentEntity(entities: VideoSegmentEntity[]): VideoSegmentEntityAdapter { const taskResults: Array<{ + video_id: string; + video_status: number|null; narrative_goal: string; shot_1: string; shot_2: string; @@ -235,6 +241,8 @@ export class VideoSegmentEntityAdapter { taskResults.push({ narrative_goal: narrative_goal, + video_id: entity.id, + video_status: entity.status, shot_1: shots.shot_1 || "", shot_2: shots.shot_2 || "", shot_3: shots.shot_3 || "", diff --git a/app/service/adapter/textToShot.ts b/app/service/adapter/textToShot.ts index 3465975..5dd57ca 100644 --- a/app/service/adapter/textToShot.ts +++ b/app/service/adapter/textToShot.ts @@ -60,7 +60,15 @@ export class TextToShotAdapter { let currentText = text; // 按角色名称长度降序排序,避免短名称匹配到长名称的一部分 - const sortedRoles = [...roles].sort((a, b) => b.name.length - a.name.length); + // 既要兼容 首字母大写 其余小写、还要兼容 全部大写 + const sortedRoles = [...roles].sort((a, b) => b.name.length - a.name.length).map(role => ({ + ...role, + name: role.name.charAt(0).toUpperCase() + role.name.slice(1).toLowerCase() + })).concat([...roles].map(role => ({ + ...role, + name: role.name.toUpperCase() + }))); + while (currentText.length > 0) { let matchFound = false; diff --git a/components/pages/style/work-flow.css b/components/pages/style/work-flow.css index f52b2b8..de416bb 100644 --- a/components/pages/style/work-flow.css +++ b/components/pages/style/work-flow.css @@ -161,10 +161,11 @@ min-height: 0; } .videoContainer-qteKNi { - /* flex: 1; */ + flex: 1; min-height: 0; display: flex; position: relative; + justify-content: center; } .heroVideo-FIzuK1 { object-fit: cover; @@ -224,7 +225,7 @@ @media (height >= 880px) { .imageGrid-ymZV9z { - flex: 1; + /* flex: 1; */ height: auto; min-height: 0; display: grid; diff --git a/components/pages/work-flow.tsx b/components/pages/work-flow.tsx index 4684827..4712df5 100644 --- a/components/pages/work-flow.tsx +++ b/components/pages/work-flow.tsx @@ -17,7 +17,11 @@ import { SaveEditUseCase } from "@/app/service/usecase/SaveEditUseCase"; import { useSearchParams } from "next/navigation"; const WorkFlow = React.memo(function WorkFlow() { - console.log('WorkFlow--0294877777777777') + useEffect(() => { + console.log("init-WorkFlow"); + return () => console.log("unmount-WorkFlow"); + }, []); + const containerRef = useRef(null); const [isEditModalOpen, setIsEditModalOpen] = React.useState(false); const [activeEditTab, setActiveEditTab] = React.useState('1'); @@ -31,8 +35,6 @@ const WorkFlow = React.memo(function WorkFlow() { taskObject, scriptData, taskSketch, - taskScenes, - taskShotSketch, taskVideos, sketchCount, isLoading, @@ -42,8 +44,6 @@ const WorkFlow = React.memo(function WorkFlow() { isGeneratingVideo, currentLoadingText, totalSketchCount, - roles, - music, final, dataLoadError, setCurrentSketchIndex, @@ -54,51 +54,18 @@ const WorkFlow = React.memo(function WorkFlow() { setAnyAttribute, applyScript, fallbackToStep, - originalText, - currentStage + originalText } = useWorkflowData(); const { - isPlaying, isVideoPlaying, - showControls, - setShowControls, - setIsPlaying, togglePlay, toggleVideoPlay, - playTimerRef, } = usePlaybackControls(taskSketch, taskVideos, currentStep); - // 跟踪是否已经自动开始播放过,避免重复触发 - const hasAutoStartedRef = useRef(false); - - // 跟踪循环播放的起始索引,用于判断是否完成一轮循环 - const loopStartIndexRef = useRef(null); - - // 调试:监控关键状态变化 useEffect(() => { - console.log('工作流状态:', { - currentStep, - isGeneratingSketch, - isGeneratingVideo, - isPlaying, - taskSketchLength: taskSketch.length, - sketchCount, - totalSketchCount - }); - }, [currentStep, isGeneratingSketch, isGeneratingVideo, isPlaying, taskSketch.length, sketchCount, totalSketchCount]); - - // 专门监控isPlaying状态变化 - useEffect(() => { - console.log('播放状态变化:', isPlaying ? '开始播放' : '停止播放'); - }, [isPlaying]); - - // 检查分镜数据 - useEffect(() => { - if (taskSketch.length > 0) { - console.log('分镜数据:', `${taskSketch.length}个分镜,当前索引:${currentSketchIndex}`); - } - }, [taskSketch.length, currentSketchIndex]); + console.log('changedIndex_work-flow', currentSketchIndex, taskObject); + }, [currentSketchIndex]); // 模拟 AI 建议 英文 const mockSuggestions = [ @@ -136,7 +103,7 @@ const WorkFlow = React.memo(function WorkFlow() { taskObject={taskObject} currentLoadingText={currentLoadingText} dataLoadError={dataLoadError} - roles={roles} + roles={taskObject.roles.data} isPauseWorkFlow={isPauseWorkFlow} /> @@ -145,7 +112,6 @@ const WorkFlow = React.memo(function WorkFlow() {
{dataLoadError ? ( @@ -182,25 +148,15 @@ const WorkFlow = React.memo(function WorkFlow() { ) : isLoading ? ( ) : ( -
+
)}
- {currentStage !== 'final_video' && currentStage !== 'script' && ( + {taskObject.currentStage !== 'final_video' && taskObject.currentStage !== 'script' && (
void; onEditModalOpen: (tab: string) => void; onToggleVideoPlay: () => void; - onTogglePlay: () => void; - final?: any; setIsPauseWorkFlow: (isPause: boolean) => void; setAnyAttribute: any; isPauseWorkFlow: boolean; applyScript: any; mode: string; - currentStage: string; } export const MediaViewer = React.memo(function MediaViewer({ + taskObject, scriptData, - currentStep, currentSketchIndex, - taskSketch, - taskVideos, isVideoPlaying, - isPlaying, - showControls, - isGeneratingSketch, - isGeneratingVideo, - onControlsChange, onEditModalOpen, onToggleVideoPlay, - onTogglePlay, - final, setIsPauseWorkFlow, setAnyAttribute, isPauseWorkFlow, applyScript, - mode, - currentStage + mode }: MediaViewerProps) { const mainVideoRef = useRef(null); const finalVideoRef = useRef(null); @@ -150,26 +131,26 @@ export const MediaViewer = React.memo(function MediaViewer({ // 使用 useMemo 缓存最终视频元素,避免重复创建和请求 const memoizedFinalVideoElement = useMemo(() => { - console.log('final', final); - if (!final?.url) return null; + console.log('final', taskObject.final); + if (!taskObject.final?.url) return null; return (