forked from 77media/video-flow
提示进度
This commit is contained in:
parent
bac656d6f7
commit
7b7a93832d
@ -14,7 +14,7 @@ const darkGlassStyle = {
|
||||
const studioContainerStyle = {
|
||||
position: 'relative' as const,
|
||||
width: '100%',
|
||||
height: '120px',
|
||||
height: '100px',
|
||||
marginBottom: '16px',
|
||||
background: 'rgba(26, 27, 30, 0.6)',
|
||||
borderRadius: '8px',
|
||||
|
||||
@ -56,9 +56,13 @@ const WorkFlow = React.memo(function WorkFlow() {
|
||||
aiEditingButtonRef.current?.handleAIEditing();
|
||||
editingNotificationKey.current = `editing-${Date.now()}`;
|
||||
showEditingNotification({
|
||||
description: 'Performing intelligent editing...',
|
||||
successDescription: 'Editing successful',
|
||||
timeoutDescription: 'Editing failed, please try again',
|
||||
timeout: 5 * 60 * 1000,
|
||||
key: editingNotificationKey.current,
|
||||
onFail: () => {
|
||||
console.log('编辑失败');
|
||||
console.log('Editing failed');
|
||||
// 清缓存 生成计划 视频重新分析
|
||||
localStorage.removeItem(`isLoaded_plan_${episodeId}`);
|
||||
// 3秒后关闭通知
|
||||
@ -109,7 +113,10 @@ const WorkFlow = React.memo(function WorkFlow() {
|
||||
if (taskObject.final.url && editingNotificationKey.current && isHandleEdit) {
|
||||
// 更新通知状态为完成
|
||||
showEditingNotification({
|
||||
isCompleted: true,
|
||||
description: 'Performing intelligent editing...',
|
||||
successDescription: 'Editing successful',
|
||||
timeoutDescription: 'Editing failed, please try again',
|
||||
timeout: 5 * 60 * 1000,
|
||||
key: editingNotificationKey.current,
|
||||
onComplete: () => {
|
||||
console.log('编辑完成');
|
||||
|
||||
@ -36,14 +36,22 @@ const descriptionStyle = {
|
||||
interface EditingNotificationProps {
|
||||
/** 编辑是否完成 */
|
||||
isCompleted?: boolean;
|
||||
/** 自定义描述 */
|
||||
/** 初始描述文案 */
|
||||
description?: string;
|
||||
/** 编辑成功时的描述文案 */
|
||||
successDescription?: string;
|
||||
/** 编辑超时失败时的描述文案 */
|
||||
timeoutDescription?: string;
|
||||
/** key */
|
||||
key?: string;
|
||||
/** 完成时的回调 */
|
||||
onComplete?: () => void;
|
||||
/** 失败时的回调 */
|
||||
onFail?: () => void;
|
||||
/** 超时时间(毫秒),默认10分钟 */
|
||||
timeout?: number;
|
||||
/** 是否显示关闭按钮,默认false */
|
||||
showCloseIcon?: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -54,9 +62,13 @@ export const showEditingNotification = (props: EditingNotificationProps) => {
|
||||
const {
|
||||
isCompleted = false,
|
||||
description = 'The intelligent editing platform is currently editing the videos.',
|
||||
successDescription = 'The editing is complete, and the updated video has been displayed on the page.',
|
||||
timeoutDescription = 'The editing timed out, please try again.',
|
||||
key,
|
||||
onComplete,
|
||||
onFail,
|
||||
timeout = 8 * 60 * 1000, // 默认8分钟
|
||||
showCloseIcon = false,
|
||||
} = props;
|
||||
|
||||
const NotificationContent = () => {
|
||||
@ -66,6 +78,19 @@ export const showEditingNotification = (props: EditingNotificationProps) => {
|
||||
const timerRef = useRef<NodeJS.Timeout>();
|
||||
const startTimeRef = useRef(Date.now());
|
||||
|
||||
// 重置进度条
|
||||
const resetProgress = () => {
|
||||
setProgress(0);
|
||||
setStatus('active');
|
||||
setCurrentDescription(description);
|
||||
startTimeRef.current = Date.now();
|
||||
};
|
||||
|
||||
// 将重置方法暴露给外部
|
||||
if (props.key && typeof window !== 'undefined') {
|
||||
(window as any)[`resetProgress_${props.key}`] = resetProgress;
|
||||
}
|
||||
|
||||
const scissorsIcon = useMemo(() => (
|
||||
<motion.div
|
||||
style={{ display: 'inline-flex', marginRight: '8px' }}
|
||||
@ -86,7 +111,7 @@ export const showEditingNotification = (props: EditingNotificationProps) => {
|
||||
useEffect(() => {
|
||||
const updateProgress = () => {
|
||||
const elapsed = Date.now() - startTimeRef.current;
|
||||
const timeLimit = 10 * 60 * 1000; // 10分钟
|
||||
const timeLimit = timeout; // 使用传入的超时时间
|
||||
|
||||
if (isCompleted) {
|
||||
// 如果完成了,快速增加到100%
|
||||
@ -94,7 +119,7 @@ export const showEditingNotification = (props: EditingNotificationProps) => {
|
||||
const next = prev + (100 - prev) / 10;
|
||||
if (next >= 99.9) {
|
||||
setStatus('success');
|
||||
setCurrentDescription('The editing is complete, and the updated video has been displayed on the page.');
|
||||
setCurrentDescription(successDescription);
|
||||
onComplete?.();
|
||||
clearInterval(timerRef.current);
|
||||
return 100;
|
||||
@ -104,7 +129,7 @@ export const showEditingNotification = (props: EditingNotificationProps) => {
|
||||
} else if (elapsed >= timeLimit) {
|
||||
// 超时失败
|
||||
setStatus('exception');
|
||||
setCurrentDescription('The editing timed out, please try again.');
|
||||
setCurrentDescription(timeoutDescription);
|
||||
onFail?.();
|
||||
clearInterval(timerRef.current);
|
||||
return;
|
||||
@ -166,7 +191,7 @@ export const showEditingNotification = (props: EditingNotificationProps) => {
|
||||
placement: 'topRight',
|
||||
style: darkGlassStyle,
|
||||
className: 'dark-glass-notification',
|
||||
closeIcon: null
|
||||
closeIcon: showCloseIcon ? undefined : null
|
||||
});
|
||||
|
||||
// 返回key以便外部可以手动关闭通知
|
||||
|
||||
@ -582,9 +582,8 @@ export const MediaViewer = React.memo(function MediaViewer({
|
||||
)}
|
||||
{currentSketch.status === 2 && (
|
||||
<div className="absolute inset-0 bg-red-500/10 flex items-center justify-center">
|
||||
<div className="text-red-500 text-2xl font-bold flex items-center gap-2">
|
||||
<div className="text-[#813b9dcc] text-2xl font-bold flex items-center gap-2">
|
||||
<X className="w-10 h-10" />
|
||||
<span>Failed</span>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
@ -2,6 +2,8 @@
|
||||
|
||||
import { useState, useEffect, useCallback, useRef, useMemo } from 'react';
|
||||
import { useSearchParams } from 'next/navigation';
|
||||
import { notification } from 'antd';
|
||||
import { showEditingNotification } from '@/components/pages/work-flow/editing-notification';
|
||||
import { detailScriptEpisodeNew, getScriptTitle, getRunningStreamData, pauseMovieProjectPlan, resumeMovieProjectPlan, getGenerateEditPlan, regenerateVideoNew } from '@/api/video_flow';
|
||||
import { useScriptService } from "@/app/service/Interaction/ScriptService";
|
||||
import { useUpdateEffect } from '@/app/hooks/useUpdateEffect';
|
||||
@ -13,16 +15,25 @@ interface UseWorkflowDataProps {
|
||||
}
|
||||
|
||||
export function useWorkflowData({ onEditPlanGenerated }: UseWorkflowDataProps = {}) {
|
||||
useEffect(() => {
|
||||
console.log("init-useWorkflowData");
|
||||
return () => console.log("unmount-useWorkflowData");
|
||||
}, []);
|
||||
|
||||
const searchParams = useSearchParams();
|
||||
const episodeId = searchParams.get('episodeId') || '';
|
||||
const from = searchParams.get('from') || '';
|
||||
const token = localStorage.getItem('token') || '';
|
||||
const useid = JSON.parse(localStorage.getItem("currentUser") || '{}').id || NaN;
|
||||
const notificationKey = useMemo(() => `video-workflow-${episodeId}`, [episodeId]);
|
||||
|
||||
useEffect(() => {
|
||||
console.log("init-useWorkflowData");
|
||||
return () => {
|
||||
console.log("unmount-useWorkflowData");
|
||||
// 组件卸载时销毁通知
|
||||
notification.destroy(notificationKey);
|
||||
// 清理window上的重置函数
|
||||
if (typeof window !== 'undefined') {
|
||||
delete (window as any)[`resetProgress_${notificationKey}`];
|
||||
}
|
||||
};
|
||||
}, [notificationKey]);
|
||||
// 查看缓存中 是否已经 加载过 这个项目的 剪辑计划
|
||||
let isLoadedRef = useRef<string | null>(localStorage.getItem(`isLoaded_plan_${episodeId}`));
|
||||
|
||||
@ -61,6 +72,7 @@ export function useWorkflowData({ onEditPlanGenerated }: UseWorkflowDataProps =
|
||||
const [isPauseWorkFlow, setIsPauseWorkFlow] = useState(false);
|
||||
const [canGoToCut, setCanGoToCut] = useState(false);
|
||||
const [isShowError, setIsShowError] = useState(false);
|
||||
const [isAnalyzing, setIsAnalyzing] = useState(false);
|
||||
const [isGenerateEditPlan, setIsGenerateEditPlan] = useState(false);
|
||||
const [state, setState] = useState({
|
||||
mode: 'automatic' as 'automatic' | 'manual' | 'auto',
|
||||
@ -127,6 +139,19 @@ export function useWorkflowData({ onEditPlanGenerated }: UseWorkflowDataProps =
|
||||
if (isLoadedRef.current) {
|
||||
return;
|
||||
}
|
||||
// 调用重置方法
|
||||
const resetFunc = (window as any)[`resetProgress_${notificationKey}`];
|
||||
if (resetFunc) {
|
||||
resetFunc();
|
||||
}
|
||||
// 更新通知内容
|
||||
showEditingNotification({
|
||||
key: notificationKey,
|
||||
description: 'Generating intelligent editing plan...',
|
||||
successDescription: 'Generating successful',
|
||||
timeoutDescription: 'Generating failed, please try again',
|
||||
timeout: 3 * 60 * 1000
|
||||
});
|
||||
// 先停止轮询
|
||||
await new Promise(resolve => {
|
||||
setNeedStreamData(false);
|
||||
@ -138,14 +163,38 @@ export function useWorkflowData({ onEditPlanGenerated }: UseWorkflowDataProps =
|
||||
setIsGenerateEditPlan(true);
|
||||
isLoadedRef.current = 'true';
|
||||
setNeedStreamData(true);
|
||||
|
||||
// 显示成功通知3秒
|
||||
showEditingNotification({
|
||||
key: notificationKey,
|
||||
isCompleted: true,
|
||||
description: 'Generating intelligent editing plan...',
|
||||
successDescription: 'Generating successful',
|
||||
timeout: 3000
|
||||
});
|
||||
setTimeout(() => {
|
||||
notification.destroy(notificationKey);
|
||||
}, 3000);
|
||||
|
||||
// 触发回调,通知父组件计划生成完成
|
||||
onEditPlanGenerated?.();
|
||||
} catch (error) {
|
||||
console.error('生成剪辑计划失败:', error);
|
||||
setNeedStreamData(true);
|
||||
setIsGenerateEditPlan(false);
|
||||
|
||||
// 显示失败通知3秒
|
||||
showEditingNotification({
|
||||
key: notificationKey,
|
||||
description: 'Generating intelligent editing plan...',
|
||||
timeoutDescription: 'Generating failed, please try again',
|
||||
timeout: 3000
|
||||
});
|
||||
setTimeout(() => {
|
||||
notification.destroy(notificationKey);
|
||||
}, 3000);
|
||||
}
|
||||
}, [episodeId, onEditPlanGenerated]);
|
||||
}, [episodeId, onEditPlanGenerated, notificationKey]);
|
||||
|
||||
const openEditPlan = useCallback(async () => {
|
||||
window.open(`https://smartcut.movieflow.ai/ai-editor/${episodeId}?token=${token}&user_id=${useid}`, '_target');
|
||||
@ -336,11 +385,35 @@ export function useWorkflowData({ onEditPlanGenerated }: UseWorkflowDataProps =
|
||||
const total_count = taskCurrent.videos.data.length;
|
||||
let analyze_video_completed_count = all_task_data.filter((item: any) => item.task_name === 'generate_analyze_video' && item.task_status !== 'INIT' && item.task_status !== 'RUNNING').length;
|
||||
let analyze_video_total_count = all_task_data.filter((item: any) => item.task_name === 'generate_analyze_video').length;
|
||||
|
||||
// 检查是否需要开始显示视频分析进度
|
||||
// 只在第一次检测到视频分析任务时显示通知
|
||||
if (analyze_video_total_count > 0 && !isAnalyzing && analyze_video_completed_count !== analyze_video_total_count) {
|
||||
setIsAnalyzing(true);
|
||||
// 如果是第一次显示通知,才调用showEditingNotification
|
||||
const resetFunc = (window as any)[`resetProgress_${notificationKey}`];
|
||||
if (!resetFunc) {
|
||||
showEditingNotification({
|
||||
key: notificationKey,
|
||||
description: 'Preparing intelligent editing plan...',
|
||||
successDescription: 'Preparing successful',
|
||||
timeoutDescription: 'Preparing failed, please try again',
|
||||
timeout: 3 * 60 * 1000
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if (analyze_video_total_count && analyze_video_completed_count === analyze_video_total_count) {
|
||||
if(error_totle < total_count * errorConfig)
|
||||
// 视频分析完成
|
||||
if(error_totle < total_count * errorConfig) {
|
||||
setCanGoToCut(true);
|
||||
else
|
||||
// 重置进度条,显示生成剪辑计划进度
|
||||
setIsAnalyzing(false);
|
||||
} else {
|
||||
setIsShowError(true);
|
||||
notification.destroy(notificationKey);
|
||||
setIsAnalyzing(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -644,7 +717,7 @@ export function useWorkflowData({ onEditPlanGenerated }: UseWorkflowDataProps =
|
||||
fallbackToStep,
|
||||
originalText: state.originalText,
|
||||
// showGotoCutButton: from && currentLoadingText.includes('Post-production') ? true : false,
|
||||
showGotoCutButton: canGoToCut && (isGenerateEditPlan || taskObject.currentStage === 'final_video') ? true : false,
|
||||
showGotoCutButton: (canGoToCut && (isGenerateEditPlan || taskObject.currentStage === 'final_video') || isShowError) ? true : false,
|
||||
generateEditPlan: openEditPlan,
|
||||
handleRetryVideo
|
||||
};
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user