更新 ScriptTabContent 以支持新的剧本数据结构和属性设置逻辑。

This commit is contained in:
北枳 2025-08-07 19:50:15 +08:00
parent e6ed351cfe
commit 7568336be6
4 changed files with 76 additions and 90 deletions

View File

@ -7,6 +7,7 @@ interface AISuggestionBarProps {
suggestions: string[]; suggestions: string[];
onSuggestionClick: (suggestion: string) => void; onSuggestionClick: (suggestion: string) => void;
onSubmit: (text: string) => void; onSubmit: (text: string) => void;
onFocus: () => void;
placeholder?: string; placeholder?: string;
} }
@ -14,6 +15,7 @@ export function AISuggestionBar({
suggestions, suggestions,
onSuggestionClick, onSuggestionClick,
onSubmit, onSubmit,
onFocus,
placeholder = "输入你的想法,或点击预设词条获取 AI 建议..." placeholder = "输入你的想法,或点击预设词条获取 AI 建议..."
}: AISuggestionBarProps) { }: AISuggestionBarProps) {
const [inputText, setInputText] = useState(''); const [inputText, setInputText] = useState('');
@ -177,6 +179,7 @@ export function AISuggestionBar({
if (isCollapsed) { if (isCollapsed) {
toggleCollapse(); toggleCollapse();
} }
onFocus();
}} }}
onBlur={() => setIsFocused(false)} onBlur={() => setIsFocused(false)}
placeholder={isCollapsed ? "点击展开..." : placeholder} placeholder={isCollapsed ? "点击展开..." : placeholder}

View File

@ -248,6 +248,7 @@ export default function WorkFlow() {
suggestions={mockSuggestions} suggestions={mockSuggestions}
onSuggestionClick={handleSuggestionClick} onSuggestionClick={handleSuggestionClick}
onSubmit={handleSubmit} onSubmit={handleSubmit}
onFocus={() => setIsPauseWorkFlow(true)}
placeholder="Please input your ideas, or click the predefined tags to receive AI advice..." placeholder="Please input your ideas, or click the predefined tags to receive AI advice..."
/> />
</ErrorBoundary> </ErrorBoundary>
@ -265,6 +266,10 @@ export default function WorkFlow() {
onSketchSelect={setCurrentSketchIndex} onSketchSelect={setCurrentSketchIndex}
roles={roles} roles={roles}
music={music} music={music}
scriptData={scriptData}
setIsPauseWorkFlow={setIsPauseWorkFlow}
setAnyAttribute={setAnyAttribute}
isPauseWorkFlow={isPauseWorkFlow}
/> />
</ErrorBoundary> </ErrorBoundary>
</div> </div>

View File

@ -1,10 +1,10 @@
'use client'; 'use client';
import React, { useState, useEffect } from 'react'; import React, { useState, useEffect, SetStateAction } from 'react';
import { motion, AnimatePresence } from 'framer-motion'; import { motion, AnimatePresence } from 'framer-motion';
import { X, Image, Users, Video, Music, Settings, FileText, Maximize, Minimize } from 'lucide-react'; import { X, Image, Users, Video, Music, Settings, FileText, Maximize, Minimize } from 'lucide-react';
import { cn } from '@/public/lib/utils'; 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 { SceneTabContent } from './scene-tab-content';
import { ShotTabContent } from './shot-tab-content'; import { ShotTabContent } from './shot-tab-content';
import { SettingsTabContent } from './settings-tab-content'; import { SettingsTabContent } from './settings-tab-content';
@ -23,6 +23,10 @@ interface EditModalProps {
onSketchSelect: (index: number) => void; onSketchSelect: (index: number) => void;
roles?: any[]; roles?: any[];
music?: any; music?: any;
setIsPauseWorkFlow: (isPauseWorkFlow: boolean) => void;
setAnyAttribute: (type: string, value: SetStateAction<string>, tags?: string[]) => void;
isPauseWorkFlow: boolean;
scriptData: any[] | null;
} }
const tabs = [ const tabs = [
@ -46,7 +50,11 @@ export function EditModal({
currentSketchIndex, currentSketchIndex,
onSketchSelect, onSketchSelect,
roles = [], roles = [],
music music,
setIsPauseWorkFlow,
setAnyAttribute,
isPauseWorkFlow,
scriptData
}: EditModalProps) { }: EditModalProps) {
const [activeTab, setActiveTab] = useState(activeEditTab); const [activeTab, setActiveTab] = useState(activeEditTab);
const [currentIndex, setCurrentIndex] = useState(currentSketchIndex); const [currentIndex, setCurrentIndex] = useState(currentSketchIndex);
@ -89,7 +97,12 @@ export function EditModal({
switch (activeTab) { switch (activeTab) {
case '0': case '0':
return ( return (
<ScriptTabContent /> <ScriptTabContent
scriptData={scriptData}
setIsPauseWorkFlow={setIsPauseWorkFlow}
setAnyAttribute={setAnyAttribute}
isPauseWorkFlow={isPauseWorkFlow}
/>
); );
case '1': case '1':
return ( return (

View File

@ -1,65 +1,32 @@
import React, { useState, useCallback, useEffect } from 'react'; import React, { useState, useCallback, useEffect, SetStateAction } from 'react';
import { motion, AnimatePresence } from 'framer-motion'; import { motion, AnimatePresence } from 'framer-motion';
import { X, Check, ChevronDown } from 'lucide-react'; import { FileText } from 'lucide-react';
import * as Popover from '@radix-ui/react-popover'; import { ScriptRenderer } from '@/components/script-renderer/ScriptRenderer';
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
// 组件挂载时获取项目剧本数据 interface ScriptTabContentProps {
useEffect(() => { scriptData: any[] | null;
const initializeScript = async () => { setIsPauseWorkFlow: (isPauseWorkFlow: boolean) => void;
try { setAnyAttribute: (type: string, value: SetStateAction<string>, tags?: string[]) => void;
await fetchProjectScript(projectId); isPauseWorkFlow: boolean;
} catch (error) { }
console.error('初始化剧本数据失败:', error);
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>
);
} }
};
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]);
return ( return (
<div className="flex flex-col h-full"> <div className="flex flex-col h-full">
<motion.div <motion.div
@ -88,10 +55,8 @@ const ScriptTabContent: React.FC = () => {
} }
}} }}
> >
<ScriptRenderer data={scriptData} setIsPauseWorkFlow={setIsPauseWorkFlow} setAnyAttribute={setAnyAttribute} isPauseWorkFlow={isPauseWorkFlow} />
</motion.div> </motion.div>
</div> </div>
); );
}; };
export default ScriptTabContent;