forked from 77media/video-flow
更新 ScriptTabContent 以支持新的剧本数据结构和属性设置逻辑。
This commit is contained in:
parent
e6ed351cfe
commit
7568336be6
@ -7,6 +7,7 @@ interface AISuggestionBarProps {
|
||||
suggestions: string[];
|
||||
onSuggestionClick: (suggestion: string) => void;
|
||||
onSubmit: (text: string) => void;
|
||||
onFocus: () => void;
|
||||
placeholder?: string;
|
||||
}
|
||||
|
||||
@ -14,6 +15,7 @@ export function AISuggestionBar({
|
||||
suggestions,
|
||||
onSuggestionClick,
|
||||
onSubmit,
|
||||
onFocus,
|
||||
placeholder = "输入你的想法,或点击预设词条获取 AI 建议..."
|
||||
}: AISuggestionBarProps) {
|
||||
const [inputText, setInputText] = useState('');
|
||||
@ -177,6 +179,7 @@ export function AISuggestionBar({
|
||||
if (isCollapsed) {
|
||||
toggleCollapse();
|
||||
}
|
||||
onFocus();
|
||||
}}
|
||||
onBlur={() => setIsFocused(false)}
|
||||
placeholder={isCollapsed ? "点击展开..." : placeholder}
|
||||
|
||||
@ -248,6 +248,7 @@ export default function WorkFlow() {
|
||||
suggestions={mockSuggestions}
|
||||
onSuggestionClick={handleSuggestionClick}
|
||||
onSubmit={handleSubmit}
|
||||
onFocus={() => setIsPauseWorkFlow(true)}
|
||||
placeholder="Please input your ideas, or click the predefined tags to receive AI advice..."
|
||||
/>
|
||||
</ErrorBoundary>
|
||||
@ -265,6 +266,10 @@ export default function WorkFlow() {
|
||||
onSketchSelect={setCurrentSketchIndex}
|
||||
roles={roles}
|
||||
music={music}
|
||||
scriptData={scriptData}
|
||||
setIsPauseWorkFlow={setIsPauseWorkFlow}
|
||||
setAnyAttribute={setAnyAttribute}
|
||||
isPauseWorkFlow={isPauseWorkFlow}
|
||||
/>
|
||||
</ErrorBoundary>
|
||||
</div>
|
||||
|
||||
@ -1,10 +1,10 @@
|
||||
'use client';
|
||||
|
||||
import React, { useState, useEffect } from 'react';
|
||||
import React, { useState, useEffect, SetStateAction } from 'react';
|
||||
import { motion, AnimatePresence } from 'framer-motion';
|
||||
import { X, Image, Users, Video, Music, Settings, FileText, Maximize, Minimize } from 'lucide-react';
|
||||
import { cn } from '@/public/lib/utils';
|
||||
import ScriptTabContent from './script-tab-content';
|
||||
import { ScriptTabContent } from './script-tab-content';
|
||||
import { SceneTabContent } from './scene-tab-content';
|
||||
import { ShotTabContent } from './shot-tab-content';
|
||||
import { SettingsTabContent } from './settings-tab-content';
|
||||
@ -23,6 +23,10 @@ interface EditModalProps {
|
||||
onSketchSelect: (index: number) => void;
|
||||
roles?: any[];
|
||||
music?: any;
|
||||
setIsPauseWorkFlow: (isPauseWorkFlow: boolean) => void;
|
||||
setAnyAttribute: (type: string, value: SetStateAction<string>, tags?: string[]) => void;
|
||||
isPauseWorkFlow: boolean;
|
||||
scriptData: any[] | null;
|
||||
}
|
||||
|
||||
const tabs = [
|
||||
@ -46,7 +50,11 @@ export function EditModal({
|
||||
currentSketchIndex,
|
||||
onSketchSelect,
|
||||
roles = [],
|
||||
music
|
||||
music,
|
||||
setIsPauseWorkFlow,
|
||||
setAnyAttribute,
|
||||
isPauseWorkFlow,
|
||||
scriptData
|
||||
}: EditModalProps) {
|
||||
const [activeTab, setActiveTab] = useState(activeEditTab);
|
||||
const [currentIndex, setCurrentIndex] = useState(currentSketchIndex);
|
||||
@ -89,7 +97,12 @@ export function EditModal({
|
||||
switch (activeTab) {
|
||||
case '0':
|
||||
return (
|
||||
<ScriptTabContent />
|
||||
<ScriptTabContent
|
||||
scriptData={scriptData}
|
||||
setIsPauseWorkFlow={setIsPauseWorkFlow}
|
||||
setAnyAttribute={setAnyAttribute}
|
||||
isPauseWorkFlow={isPauseWorkFlow}
|
||||
/>
|
||||
);
|
||||
case '1':
|
||||
return (
|
||||
|
||||
@ -1,97 +1,62 @@
|
||||
import React, { useState, useCallback, useEffect } from 'react';
|
||||
import React, { useState, useCallback, useEffect, SetStateAction } from 'react';
|
||||
import { motion, AnimatePresence } from 'framer-motion';
|
||||
import { X, Check, ChevronDown } from 'lucide-react';
|
||||
import * as Popover from '@radix-ui/react-popover';
|
||||
import { mockSceneOptions, mockCharacterOptions } from '@/app/model/enums';
|
||||
import { Button } from './button';
|
||||
import { Input } from './input';
|
||||
|
||||
const ScriptTabContent: React.FC = () => {
|
||||
// 获取当前项目ID(这里需要根据实际项目路由或上下文获取)
|
||||
const projectId = 'current-project-id'; // TODO: 从路由或上下文获取实际项目ID
|
||||
import { FileText } from 'lucide-react';
|
||||
import { ScriptRenderer } from '@/components/script-renderer/ScriptRenderer';
|
||||
|
||||
|
||||
// 组件挂载时获取项目剧本数据
|
||||
useEffect(() => {
|
||||
const initializeScript = async () => {
|
||||
try {
|
||||
await fetchProjectScript(projectId);
|
||||
} catch (error) {
|
||||
console.error('初始化剧本数据失败:', error);
|
||||
}
|
||||
};
|
||||
interface ScriptTabContentProps {
|
||||
scriptData: any[] | null;
|
||||
setIsPauseWorkFlow: (isPauseWorkFlow: boolean) => void;
|
||||
setAnyAttribute: (type: string, value: SetStateAction<string>, tags?: string[]) => void;
|
||||
isPauseWorkFlow: boolean;
|
||||
}
|
||||
|
||||
initializeScript();
|
||||
}, [projectId, fetchProjectScript]);
|
||||
|
||||
// 处理AI生成按钮点击
|
||||
const handleAiGenerate = useCallback(async () => {
|
||||
if (!userPrompt.trim()) return;
|
||||
|
||||
try {
|
||||
await fetchScriptData(userPrompt);
|
||||
} catch (error) {
|
||||
console.error('生成剧本失败:', error);
|
||||
}
|
||||
}, [userPrompt, fetchScriptData]);
|
||||
|
||||
// 处理重置按钮点击
|
||||
const handleReset = useCallback(() => {
|
||||
resetScript();
|
||||
}, [resetScript]);
|
||||
|
||||
// 处理确认按钮点击
|
||||
const handleConfirm = useCallback(async () => {
|
||||
try {
|
||||
await applyScript();
|
||||
} catch (error) {
|
||||
console.error('应用剧本失败:', error);
|
||||
}
|
||||
}, [applyScript]);
|
||||
|
||||
// 处理提示词输入变化
|
||||
const handlePromptChange = useCallback((value: string) => {
|
||||
updateUserPrompt(value);
|
||||
}, [updateUserPrompt]);
|
||||
|
||||
// 处理剧本片段文本变化
|
||||
const handleScriptSliceChange = useCallback((sliceId: string, text: string) => {
|
||||
setFocusedSlice(sliceId);
|
||||
updateScriptSliceText(text);
|
||||
}, [setFocusedSlice, updateScriptSliceText]);
|
||||
export function ScriptTabContent({
|
||||
scriptData = [],
|
||||
setIsPauseWorkFlow,
|
||||
setAnyAttribute,
|
||||
isPauseWorkFlow
|
||||
}: ScriptTabContentProps) {
|
||||
|
||||
// 如果没有数据,显示空状态
|
||||
if (!scriptData || scriptData.length === 0) {
|
||||
return (
|
||||
<div className="flex flex-col items-center justify-center min-h-[400px] text-white/50">
|
||||
<FileText className="w-16 h-16 mb-4" />
|
||||
<p>No script data</p>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
return (
|
||||
<div className="flex flex-col h-full">
|
||||
<motion.div
|
||||
className="relative w-full h-[90vh] backdrop-blur-xl rounded-2xl shadow-2xl overflow-hidden flex flex-col"
|
||||
initial={{ scale: 0.95, y: 10, opacity: 0 }}
|
||||
animate={{
|
||||
scale: 1,
|
||||
y: 0,
|
||||
opacity: 1,
|
||||
transition: {
|
||||
type: "spring",
|
||||
duration: 0.3,
|
||||
bounce: 0.15,
|
||||
stiffness: 300,
|
||||
damping: 25
|
||||
}
|
||||
}}
|
||||
exit={{
|
||||
scale: 0.95,
|
||||
y: 10,
|
||||
opacity: 0,
|
||||
transition: {
|
||||
type: "tween",
|
||||
duration: 0.1,
|
||||
ease: "easeOut"
|
||||
}
|
||||
}}
|
||||
>
|
||||
|
||||
</motion.div>
|
||||
className="relative w-full h-[90vh] backdrop-blur-xl rounded-2xl shadow-2xl overflow-hidden flex flex-col"
|
||||
initial={{ scale: 0.95, y: 10, opacity: 0 }}
|
||||
animate={{
|
||||
scale: 1,
|
||||
y: 0,
|
||||
opacity: 1,
|
||||
transition: {
|
||||
type: "spring",
|
||||
duration: 0.3,
|
||||
bounce: 0.15,
|
||||
stiffness: 300,
|
||||
damping: 25
|
||||
}
|
||||
}}
|
||||
exit={{
|
||||
scale: 0.95,
|
||||
y: 10,
|
||||
opacity: 0,
|
||||
transition: {
|
||||
type: "tween",
|
||||
duration: 0.1,
|
||||
ease: "easeOut"
|
||||
}
|
||||
}}
|
||||
>
|
||||
<ScriptRenderer data={scriptData} setIsPauseWorkFlow={setIsPauseWorkFlow} setAnyAttribute={setAnyAttribute} isPauseWorkFlow={isPauseWorkFlow} />
|
||||
</motion.div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default ScriptTabContent;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user