video-flow-b/components/workflow/work-office/storyboard-artist copy.tsx
2025-07-25 11:41:12 +08:00

253 lines
11 KiB
TypeScript

import React from 'react';
import { Camera } from 'lucide-react';
import { TypewriterText } from './common/TypewriterText';
import { ContentCard } from './common/ContentCard';
import { SkeletonCard } from './common/SkeletonCard';
import { IconLoading } from './common/IconLoading';
interface StoryboardArtistProps {
currentContent: any;
isPlaying: boolean;
sketchType: string;
}
const SceneStoryboard = (currentContent: any, isPlaying: boolean) => {
return (
<div className="space-y-4 h-full overflow-y-auto">
<div className='grid grid-cols-2 gap-4'>
{/* 场景定位选择 */}
<div className="bg-black/30 rounded-lg p-4">
<h3 className="text-white font-semibold mb-3 flex items-center space-x-2">
<span>Scene location selection</span>
<IconLoading icon={Camera} isActive={isPlaying} color="#06b6d4" />
</h3>
<div className="space-y-3">
{currentContent.location ? (
<div className="text-gray-300 text-xs">
<TypewriterText text={currentContent.location} stableId={currentContent.location} />
</div>
) : (
<SkeletonCard className="bg-cyan-500/20 rounded-lg p-3 border border-cyan-500/30" />
)}
</div>
</div>
{/* 场景氛围选择 */}
<div className="bg-black/30 rounded-lg p-4">
<h3 className="text-white font-semibold mb-3 flex items-center space-x-2">
<span>Scene atmosphere selection</span>
<IconLoading icon={Camera} isActive={isPlaying} color="#06b6d4" />
</h3>
<div className="space-y-3">
{currentContent.core_atmosphere ? (
<div className="text-gray-300 text-xs">
<TypewriterText text={currentContent.core_atmosphere} stableId={currentContent.core_atmosphere} />
</div>
) : (
<SkeletonCard className="bg-cyan-500/20 rounded-lg p-3 border border-cyan-500/30" />
)}
</div>
</div>
</div>
{/* 场景描述 */}
<div className='bg-black/30 rounded-lg p-4'>
<h3 className="text-white font-semibold mb-3 flex items-center space-x-2">
<span>Scene description</span>
<IconLoading icon={Camera} isActive={isPlaying} color="#06b6d4" />
</h3>
<div className='space-y-3'>
{currentContent.description ? (
<div className="text-gray-300 text-xs">
<TypewriterText text={currentContent.description} stableId={currentContent.description} />
</div>
) : (
<SkeletonCard className="bg-cyan-500/20 rounded-lg p-3 border border-cyan-500/30" />
)}
</div>
</div>
</div>
);
}
const ShotSketchStoryboard = (currentContent: any, isPlaying: boolean) => {
return (
<div className="grid grid-cols-2 gap-4 h-full">
{/* 左侧:镜头语言和构图美学 */}
<div className="space-y-4 overflow-y-auto">
{/* 镜头语言选择 */}
<div className="bg-black/30 rounded-lg p-4">
<h3 className="text-white font-semibold mb-3 flex items-center space-x-2">
<span>Shot language selection</span>
<IconLoading icon={Camera} isActive={isPlaying} color="#06b6d4" />
</h3>
<div className="space-y-3">
{currentContent.shotLanguage && currentContent.shotLanguage.length > 0 ? (
currentContent.shotLanguage.map((shot: any, index: number) => (
<ContentCard
key={index}
className="bg-cyan-500/20 rounded-lg p-3 border border-cyan-500/30"
>
<div className="flex justify-between items-center mb-2">
<span className="text-cyan-300 font-medium text-sm">{shot}</span>
</div>
<div className="text-gray-300 text-xs leading-relaxed">
<TypewriterText text={currentContent.frame_description} stableId={`shot${index}`} />
</div>
</ContentCard>
))
) : (
Array.from({length: 4}, (_, i) => (
<SkeletonCard key={i} className="bg-cyan-500/20 rounded-lg p-3 border border-cyan-500/30" />
))
)}
</div>
</div>
{/* 构图美学运用 */}
<div className="bg-black/30 rounded-lg p-4">
<h3 className="text-white font-semibold mb-3 flex items-center space-x-2">
<span>Composition aesthetics</span>
<IconLoading icon={Camera} isActive={isPlaying} color="#06b6d4" />
</h3>
{currentContent.atmosphere && currentContent.atmosphere.length > 0 ? (
<ContentCard className="space-y-3">
{currentContent.atmosphere.map((atmosphere: any, index: number) => (
<div key={index}>
<div className="text-cyan-300 text-sm font-medium">
<TypewriterText text={atmosphere} stableId={`${index}-atmosphere`} />
</div>
</div>
))}
</ContentCard>
) : (
<div className="space-y-3">
{Array.from({length: 3}, (_, i) => (
<SkeletonCard key={i} className="bg-cyan-500/20 rounded-lg p-3 border border-cyan-500/30" />
))}
</div>
)}
</div>
</div>
{/* 右侧:摄影机运动和叙事逻辑 */}
<div className="space-y-4 overflow-y-auto">
{/* 摄影机运动设计 */}
<div className="bg-black/30 rounded-lg p-4">
<h3 className="text-white font-semibold mb-3 flex items-center space-x-2">
<span>Camera movement design</span>
<IconLoading icon={Camera} isActive={isPlaying} color="#06b6d4" />
</h3>
<div className="space-y-3">
{currentContent.camera_motion && currentContent.camera_motion.length > 0 ? (
currentContent.camera_motion.map((move: any, index: number) => (
<ContentCard
key={index}
className="bg-cyan-400/20 rounded-lg p-3"
>
<div className="text-cyan-200 font-medium text-sm mb-1">{move}</div>
<div className="text-cyan-300 text-xs">
<TypewriterText text={currentContent.composition} stableId={`${index}-composition`} />
</div>
</ContentCard>
))
) : (
Array.from({length: 3}, (_, i) => (
<SkeletonCard key={i} className="bg-cyan-500/20 rounded-lg p-3 border border-cyan-500/30" />
))
)}
</div>
</div>
{/* 视觉叙事逻辑 */}
<div className="bg-black/30 rounded-lg p-4">
<h3 className="text-white font-semibold mb-3 flex items-center space-x-2">
<span>Visual storytelling logic</span>
<IconLoading icon={Camera} isActive={isPlaying} color="#06b6d4" />
</h3>
{currentContent.key_action ? (
<ContentCard className="space-y-3">
<div>
<div className="text-cyan-300 text-sm font-medium mb-1">Storytelling logic</div>
<div className="text-gray-300 text-xs">
<TypewriterText text={currentContent.frame_description} stableId={`frame-description-logic`} />
</div>
</div>
<div>
<div className="text-cyan-300 text-sm font-medium mb-1">Key emphasis</div>
<div className="text-gray-300 text-xs">
<TypewriterText text={currentContent.key_action} stableId={`key-action-emphasis`} />
</div>
</div>
</ContentCard>
) : (
<div className="space-y-3">
{Array.from({length: 3}, (_, i) => (
<SkeletonCard key={i} className="bg-cyan-500/20 rounded-lg p-3 border border-cyan-500/30" />
))}
</div>
)}
</div>
{/* 对话表演 */}
<div className="bg-black/30 rounded-lg p-4">
<h3 className="text-white font-semibold mb-3 flex items-center space-x-2">
<span>Dialogue performance</span>
<IconLoading icon={Camera} isActive={isPlaying} color="#06b6d4" />
</h3>
<div className="space-y-2">
{currentContent.dialogue_performance ? (
<>
<ContentCard
className="bg-cyan-300/20 rounded p-2"
>
<div className="text-cyan-200 text-sm font-medium">Speaker</div>
<div className="text-gray-300 text-xs">
<TypewriterText text={currentContent.dialogue_performance.speaker} stableId={`speaker`} />
</div>
</ContentCard>
<ContentCard
className="bg-cyan-300/20 rounded p-2"
>
<div className="text-cyan-200 text-sm font-medium">Language</div>
<div className="text-gray-300 text-xs">
<TypewriterText text={currentContent.dialogue_performance.language} stableId={`language`} />
</div>
</ContentCard>
<ContentCard
className="bg-cyan-300/20 rounded p-2"
>
<div className="text-cyan-200 text-sm font-medium">Delivery</div>
<div className="text-gray-300 text-xs">
<TypewriterText text={currentContent.dialogue_performance.delivery} stableId={`delivery`} />
</div>
</ContentCard>
<ContentCard
className="bg-cyan-300/20 rounded p-2"
>
<div className="text-cyan-200 text-sm font-medium">Line</div>
<div className="text-gray-300 text-xs">
<TypewriterText text={currentContent.dialogue_performance.line} stableId={`line`} />
</div>
</ContentCard>
</>
) : (
Array.from({length: 4}, (_, i) => (
<SkeletonCard key={i} className="bg-cyan-500/20 rounded-lg p-3 border border-cyan-500/30" />
))
)}
</div>
</div>
</div>
</div>
);
}
const StoryboardArtist: React.FC<StoryboardArtistProps> = ({ currentContent, isPlaying, sketchType }) => {
return (
<>
{sketchType === 'scene' ? <SceneStoryboard currentContent={currentContent} isPlaying={isPlaying} /> : <ShotSketchStoryboard currentContent={currentContent} isPlaying={isPlaying} />}
</>
);
};
export default StoryboardArtist;