forked from 77media/video-flow
301 lines
12 KiB
TypeScript
301 lines
12 KiB
TypeScript
import React from 'react';
|
|
import { Scissors } from 'lucide-react';
|
|
import { TypewriterText } from './common/TypewriterText';
|
|
import { ContentCard } from './common/ContentCard';
|
|
import { ProgressBar } from './common/ProgressBar';
|
|
import { DotLoading } from './common/DotLoading';
|
|
import { SkeletonCard } from './common/SkeletonCard';
|
|
import { IconLoading } from './common/IconLoading';
|
|
|
|
interface EditingContent {
|
|
rhythm?: {
|
|
stableId: string;
|
|
concept: string;
|
|
application: string;
|
|
current: string;
|
|
progress: number;
|
|
};
|
|
audioVideo?: Array<{
|
|
id: string;
|
|
stableId: string;
|
|
aspect: string;
|
|
details: string;
|
|
sync?: string;
|
|
balance?: string;
|
|
progress: number;
|
|
}>;
|
|
emotionProgression?: {
|
|
stableId: string;
|
|
stages: string;
|
|
techniques: string;
|
|
current: string;
|
|
progress: number;
|
|
};
|
|
transitions?: Array<{
|
|
id: string;
|
|
stableId: string;
|
|
type: string;
|
|
usage: string;
|
|
}>;
|
|
styleUnity?: {
|
|
stableId: string;
|
|
colorGrading: string;
|
|
toneCurve: string;
|
|
progress: number;
|
|
};
|
|
finalOutput?: {
|
|
format: string;
|
|
resolution: string;
|
|
bitrate: string;
|
|
audio: string;
|
|
duration: string;
|
|
status: string;
|
|
progress: number;
|
|
};
|
|
}
|
|
|
|
interface EditorProps {
|
|
currentContent: EditingContent;
|
|
isPlaying: boolean;
|
|
}
|
|
|
|
const Editor: React.FC<EditorProps> = ({ currentContent, isPlaying }) => {
|
|
return (
|
|
<div className="space-y-4 h-full 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>Editing rhythm control</span>
|
|
<IconLoading icon={Scissors} isActive={isPlaying} color="#f59e0b" />
|
|
</h3>
|
|
{currentContent.rhythm ? (
|
|
<ContentCard className="space-y-3">
|
|
<div>
|
|
<div className="text-amber-300 text-sm font-medium mb-1">Rhythm Concept</div>
|
|
<div className="text-gray-300 text-xs">
|
|
<TypewriterText text={currentContent.rhythm.concept} stableId={`${currentContent.rhythm.stableId}-concept`} />
|
|
</div>
|
|
</div>
|
|
<div>
|
|
<div className="text-amber-300 text-sm font-medium mb-1">Practical Application</div>
|
|
<div className="text-gray-300 text-xs">
|
|
<TypewriterText text={currentContent.rhythm.application} stableId={`${currentContent.rhythm.stableId}-application`} />
|
|
</div>
|
|
</div>
|
|
<div>
|
|
<div className="text-amber-300 text-sm font-medium mb-1">Current Status</div>
|
|
<div className="text-gray-300 text-xs">
|
|
<TypewriterText text={currentContent.rhythm.current} stableId={`${currentContent.rhythm.stableId}-current`} />
|
|
</div>
|
|
</div>
|
|
<ProgressBar progress={currentContent.rhythm.progress} color="#f59e0b" label="Rhythm Analysis" />
|
|
</ContentCard>
|
|
) : (
|
|
<div className="space-y-3">
|
|
{Array.from({length: 3}, (_, i) => (
|
|
<SkeletonCard key={i} className="bg-amber-500/20 rounded-lg p-3 border border-amber-500/30" />
|
|
))}
|
|
<SkeletonCard className="h-2 bg-amber-500/20 rounded-full border border-amber-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>Audio and video relationship processing</span>
|
|
<IconLoading icon={Scissors} isActive={isPlaying} color="#f59e0b" />
|
|
</h3>
|
|
<div className="space-y-3">
|
|
{currentContent.audioVideo ? (
|
|
currentContent.audioVideo.map((av) => (
|
|
<ContentCard
|
|
key={av.stableId}
|
|
className="bg-amber-500/20 rounded-lg p-3"
|
|
>
|
|
<div className="text-amber-300 font-medium text-sm mb-1">{av.aspect}</div>
|
|
<div className="text-gray-300 text-xs mb-2">
|
|
<TypewriterText text={av.details} stableId={av.stableId} />
|
|
</div>
|
|
<div className="text-amber-200 text-xs mb-2">
|
|
{av.sync && `Synchronization accuracy: ${av.sync}`}
|
|
{av.balance && `Balanced Strategy: ${av.balance}`}
|
|
</div>
|
|
<ProgressBar progress={av.progress} color="#f59e0b" />
|
|
</ContentCard>
|
|
))
|
|
) : (
|
|
Array.from({length: 3}, (_, i) => (
|
|
<SkeletonCard key={i} className="bg-amber-500/20 rounded-lg p-3 border border-amber-500/30" />
|
|
))
|
|
)}
|
|
</div>
|
|
</div>
|
|
|
|
<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>Emotional Progressive Adjustment</span>
|
|
<IconLoading icon={Scissors} isActive={isPlaying} color="#f59e0b" />
|
|
</h3>
|
|
{currentContent.emotionProgression ? (
|
|
<ContentCard className="space-y-3">
|
|
<div>
|
|
<div className="text-amber-300 text-sm font-medium mb-1">The progressive stage</div>
|
|
<div className="text-gray-300 text-xs">
|
|
<TypewriterText text={currentContent.emotionProgression.stages} stableId={`${currentContent.emotionProgression.stableId}-stages`} />
|
|
</div>
|
|
</div>
|
|
<div>
|
|
<div className="text-amber-300 text-sm font-medium mb-1">Adjustment Techniques</div>
|
|
<div className="text-gray-300 text-xs">
|
|
<TypewriterText text={currentContent.emotionProgression.techniques} stableId={`${currentContent.emotionProgression.stableId}-techniques`} />
|
|
</div>
|
|
</div>
|
|
<div>
|
|
<div className="text-amber-300 text-sm font-medium mb-1">Current progress</div>
|
|
<div className="text-gray-300 text-xs">
|
|
<TypewriterText text={currentContent.emotionProgression.current} stableId={`${currentContent.emotionProgression.stableId}-current`} />
|
|
</div>
|
|
</div>
|
|
<ProgressBar progress={currentContent.emotionProgression.progress} color="#f59e0b" label="Emotional Adjustment" />
|
|
</ContentCard>
|
|
) : (
|
|
<div className="space-y-3">
|
|
{Array.from({length: 3}, (_, i) => (
|
|
<SkeletonCard key={i} className="bg-amber-500/20 rounded-lg p-3 border border-amber-500/30" />
|
|
))}
|
|
<SkeletonCard className="h-2 bg-amber-500/20 rounded-full border border-amber-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>Transition effect selection</span>
|
|
<IconLoading icon={Scissors} isActive={isPlaying} color="#f59e0b" />
|
|
</h3>
|
|
<div className="space-y-2">
|
|
{currentContent.transitions ? (
|
|
currentContent.transitions.map((trans) => (
|
|
<ContentCard
|
|
key={trans.stableId}
|
|
className="bg-amber-400/20 rounded p-2"
|
|
>
|
|
<div className="text-amber-200 text-sm font-medium">{trans.type}</div>
|
|
<div className="text-gray-300 text-xs">
|
|
<TypewriterText text={trans.usage} stableId={trans.stableId} />
|
|
</div>
|
|
</ContentCard>
|
|
))
|
|
) : (
|
|
Array.from({length: 4}, (_, i) => (
|
|
<SkeletonCard key={i} className="bg-amber-500/20 rounded-lg p-2 border border-amber-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>Unified overall style</span>
|
|
<IconLoading icon={Scissors} isActive={isPlaying} color="#f59e0b" />
|
|
</h3>
|
|
{currentContent.styleUnity ? (
|
|
<ContentCard className="space-y-3">
|
|
<div>
|
|
<div className="text-amber-300 text-sm font-medium mb-1">Color uniformity</div>
|
|
<div className="text-gray-300 text-xs">
|
|
<TypewriterText text={currentContent.styleUnity.colorGrading} stableId={`${currentContent.styleUnity.stableId}-colorGrading`} />
|
|
</div>
|
|
</div>
|
|
<div>
|
|
<div className="text-amber-300 text-sm font-medium mb-1">Tone Curve</div>
|
|
<div className="text-gray-300 text-xs">
|
|
<TypewriterText text={currentContent.styleUnity.toneCurve} stableId={`${currentContent.styleUnity.stableId}-toneCurve`} />
|
|
</div>
|
|
</div>
|
|
<ProgressBar progress={currentContent.styleUnity.progress} color="#f59e0b" label="Unified style" />
|
|
</ContentCard>
|
|
) : (
|
|
<div className="space-y-3">
|
|
{Array.from({length: 2}, (_, i) => (
|
|
<SkeletonCard key={i} className="bg-amber-500/20 rounded-lg p-3 border border-amber-500/30" />
|
|
))}
|
|
<SkeletonCard className="h-2 bg-amber-500/20 rounded-full border border-amber-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>Final Output</span>
|
|
{currentContent.finalOutput ? (
|
|
<DotLoading isActive={currentContent.finalOutput.progress < 100} color="#f59e0b" size="medium" />
|
|
) : (
|
|
<IconLoading icon={Scissors} isActive={isPlaying} color="#f59e0b" />
|
|
)}
|
|
</h3>
|
|
{currentContent.finalOutput ? (
|
|
<>
|
|
<div className="grid grid-cols-2 gap-4">
|
|
<div className="space-y-2">
|
|
{Object.entries({
|
|
'Format': currentContent.finalOutput.format,
|
|
'Resolution': currentContent.finalOutput.resolution,
|
|
'Bitrate': currentContent.finalOutput.bitrate
|
|
}).map(([key, value]) => (
|
|
<div key={key} className="flex justify-between text-xs">
|
|
<span className="text-gray-400">{key}:</span>
|
|
<span className="text-amber-300">{value}</span>
|
|
</div>
|
|
))}
|
|
</div>
|
|
<div className="space-y-2">
|
|
{Object.entries({
|
|
'Audio': currentContent.finalOutput.audio,
|
|
'Duration': currentContent.finalOutput.duration,
|
|
'Status': currentContent.finalOutput.status
|
|
}).map(([key, value]) => (
|
|
<div key={key} className="flex justify-between text-xs">
|
|
<span className="text-gray-400">{key}:</span>
|
|
<span className="text-amber-300">{value}</span>
|
|
</div>
|
|
))}
|
|
</div>
|
|
</div>
|
|
<div className="mt-4">
|
|
<ProgressBar progress={currentContent.finalOutput.progress} color="#f59e0b" label="Output progress" />
|
|
</div>
|
|
</>
|
|
) : (
|
|
<>
|
|
<div className="grid grid-cols-2 gap-4">
|
|
<div className="space-y-2">
|
|
{Array.from({length: 3}, (_, i) => (
|
|
<SkeletonCard key={i} className="h-6 bg-amber-500/20 rounded border border-amber-500/30" />
|
|
))}
|
|
</div>
|
|
<div className="space-y-2">
|
|
{Array.from({length: 3}, (_, i) => (
|
|
<SkeletonCard key={i} className="h-6 bg-amber-500/20 rounded border border-amber-500/30" />
|
|
))}
|
|
</div>
|
|
</div>
|
|
<div className="mt-4">
|
|
<SkeletonCard className="h-2 bg-amber-500/20 rounded-full border border-amber-500/30" />
|
|
</div>
|
|
</>
|
|
)}
|
|
</div>
|
|
</div>
|
|
);
|
|
};
|
|
|
|
export default Editor;
|