diff --git a/components/SmartChatBox/QuickActionTags.tsx b/components/SmartChatBox/QuickActionTags.tsx index 6d48b74..22aaecf 100644 --- a/components/SmartChatBox/QuickActionTags.tsx +++ b/components/SmartChatBox/QuickActionTags.tsx @@ -1,20 +1,22 @@ import React, { useRef, useCallback } from 'react'; import { motion } from 'framer-motion'; -import { ChevronLeft, ChevronRight } from 'lucide-react'; +import { ChevronLeft, ChevronRight, Cloudy, UserRound, PersonStanding, Shirt, Smile, RefreshCcw } from 'lucide-react'; /** 快捷操作标签的数据结构 */ export interface QuickAction { id: string; label: string; + icon: any; } /** 预设的快捷操作标签 */ export const DEFAULT_QUICK_ACTIONS: QuickAction[] = [ - { id: 'weather', label: 'Change video scene weather' }, - { id: 'character', label: 'Change a character in the video' }, - { id: 'costume', label: 'Change the clothing of a character in the video' }, - { id: 'scene', label: 'Change video scene background' }, - { id: 'action', label: 'Change character action' } + { id: 'weather', label: 'change weather', icon: Cloudy }, + { id: 'character', label: 'change character', icon: UserRound }, + { id: 'costume', label: 'change clothing', icon: Shirt }, + { id: 'action', label: 'change action', icon: PersonStanding }, + { id: 'emotion', label: 'change emotion', icon: Smile }, + { id: 'retry', label: 'retry failed video', icon: RefreshCcw } ]; interface QuickActionTagsProps { @@ -48,10 +50,10 @@ export function QuickActionTags({ actions = DEFAULT_QUICK_ACTIONS, onTagClick }: return (
{/* 左侧渐变遮罩 */} -
+ {/*
*/} {/* 左滚动按钮 */} onTagClick(action)} whileHover={{ scale: 1.05 }} whileTap={{ scale: 0.95 }} - className="flex-none px-[8px] py-[3px] rounded-full text-[10px] text-white/80 + className="flex items-center flex-shrink-0 gap-1 px-[8px] py-[3px] rounded-full text-[10px] text-white/80 backdrop-blur-md bg-white/10 border border-white/20 hover:bg-white/20 hover:text-white transition-colors duration-200 shadow-[0_4px_6px_-1px_rgba(0,0,0,0.1),0_2px_4px_-1px_rgba(0,0,0,0.06)]" data-alt={`quick-action-${action.id}`} > + {action.icon && } {action.label} ))}
{/* 右侧渐变遮罩 */} -
+ {/*
*/} {/* 右滚动按钮 */} (null); const aiEditingButtonRef = useRef<{ handleAIEditing: () => Promise }>(null); + const [editingStatus, setEditingStatus] = React.useState<'initial' | 'idle' | 'success' | 'error'>('initial'); const searchParams = useSearchParams(); const episodeId = searchParams.get('episodeId') || ''; @@ -53,6 +54,7 @@ const WorkFlow = React.memo(function WorkFlow() { const handleEditPlanGenerated = useCallback(() => { console.log('✨ 编辑计划生成完成,开始AI剪辑'); setIsHandleEdit(true); + setEditingStatus('idle'); aiEditingButtonRef.current?.handleAIEditing(); editingNotificationKey.current = `editing-${Date.now()}`; showEditingNotification({ @@ -65,6 +67,7 @@ const WorkFlow = React.memo(function WorkFlow() { console.log('Editing failed'); // 清缓存 生成计划 视频重新分析 localStorage.removeItem(`isLoaded_plan_${episodeId}`); + setEditingStatus('error'); // 3秒后关闭通知 setTimeout(() => { if (editingNotificationKey.current) { @@ -82,9 +85,7 @@ const WorkFlow = React.memo(function WorkFlow() { isLoading, currentSketchIndex, currentLoadingText, - dataLoadError, setCurrentSketchIndex, - retryLoadData, isPauseWorkFlow, mode, setIsPauseWorkFlow, @@ -122,6 +123,7 @@ const WorkFlow = React.memo(function WorkFlow() { onComplete: () => { console.log('Editing successful'); localStorage.setItem(`isLoaded_plan_${episodeId}`, 'true'); + setEditingStatus('success'); // 3秒后关闭通知 setTimeout(() => { if (editingNotificationKey.current) { @@ -200,7 +202,7 @@ const WorkFlow = React.memo(function WorkFlow() { currentLoadingText={currentLoadingText} roles={taskObject.roles.data} isPauseWorkFlow={isPauseWorkFlow} - showGotoCutButton={showGotoCutButton} + showGotoCutButton={showGotoCutButton || editingStatus !== 'idle'} onGotoCut={generateEditPlan} setIsPauseWorkFlow={setIsPauseWorkFlow} /> @@ -232,7 +234,7 @@ const WorkFlow = React.memo(function WorkFlow() { setPreviewVideoUrl(url); setPreviewVideoId(id); }} - showGotoCutButton={showGotoCutButton} + showGotoCutButton={showGotoCutButton || editingStatus !== 'idle'} onGotoCut={generateEditPlan} isSmartChatBoxOpen={isSmartChatBoxOpen} onRetryVideo={(video_id) => handleRetryVideo(video_id)} diff --git a/components/pages/work-flow/use-workflow-data.tsx b/components/pages/work-flow/use-workflow-data.tsx index c1fc383..11971b5 100644 --- a/components/pages/work-flow/use-workflow-data.tsx +++ b/components/pages/work-flow/use-workflow-data.tsx @@ -148,8 +148,8 @@ export function useWorkflowData({ onEditPlanGenerated }: UseWorkflowDataProps = showEditingNotification({ key: notificationKey, description: 'Generating intelligent editing plan...', - successDescription: 'Generating successful', - timeoutDescription: 'Generating failed, please try again', + successDescription: '剪辑计划生成完成', + timeoutDescription: '剪辑计划生成失败,请重试', timeout: 3 * 60 * 1000 }); // 先停止轮询 @@ -168,8 +168,8 @@ export function useWorkflowData({ onEditPlanGenerated }: UseWorkflowDataProps = showEditingNotification({ key: notificationKey, isCompleted: true, - description: 'Generating intelligent editing plan...', - successDescription: 'Generating successful', + description: '正在生成剪辑计划...', + successDescription: '剪辑计划生成完成', timeout: 3000 }); setTimeout(() => { @@ -186,8 +186,8 @@ export function useWorkflowData({ onEditPlanGenerated }: UseWorkflowDataProps = // 显示失败通知3秒 showEditingNotification({ key: notificationKey, - description: 'Generating intelligent editing plan...', - timeoutDescription: 'Generating failed, please try again', + description: '正在生成剪辑计划...', + timeoutDescription: '剪辑计划生成失败,请重试', timeout: 3000 }); setTimeout(() => {