video-flow-b/components/pages/script-overview.tsx
2025-07-04 17:06:26 +08:00

281 lines
11 KiB
TypeScript

"use client";
import { useState } from 'react';
import { motion } from 'framer-motion';
import {
DndContext,
closestCenter,
KeyboardSensor,
PointerSensor,
useSensor,
useSensors,
} from '@dnd-kit/core';
import {
arrayMove,
SortableContext,
sortableKeyboardCoordinates,
verticalListSortingStrategy,
} from '@dnd-kit/sortable';
import type { DragEndEvent } from '@dnd-kit/core';
import { ScriptMetaInfo } from '../script-overview/script-meta-info';
import { SceneFilmstrip } from '../script-overview/scene-filmstrip';
import { SceneCardList } from '../script-overview/scene-card-list';
import { FloatingToolbar } from '../script-overview/floating-toolbar';
// 场景数据结构
export interface Scene {
id: string;
name: string;
description: string;
plot: string;
dialogue: string;
narration: string;
imageUrl: string;
}
// 剧本元信息数据结构
export interface ScriptMeta {
title: string;
type: string;
genre: string;
tags: string[];
duration: string;
uploadTime: string;
}
export default function ScriptOverview() {
// Configure drag sensors
const sensors = useSensors(
useSensor(PointerSensor),
useSensor(KeyboardSensor, {
coordinateGetter: sortableKeyboardCoordinates,
})
);
// Example Data
const [scriptMeta] = useState<ScriptMeta>({
title: "Lost Stars",
type: "Short Drama",
genre: "Sci-Fi/Mystery",
tags: ["Space", "Psychology", "Future"],
duration: "20-25 minutes",
uploadTime: "2024-03-20"
});
const [scenes, setScenes] = useState<Scene[]>([
{
id: "scene-1",
name: "Space Station Interior",
description: "Main control room of the International Space Station",
plot: "Protagonist discovers an anomalous signal",
dialogue: "Captain: This signal... it's not from Earth",
narration: "In the darkness of space, a faint light blinks",
imageUrl: "https://smart-video-ai.oss-cn-beijing.aliyuncs.com/frames/d877fa43-4856-4acb-9a3b-627c28275343/frame_000007.jpg/1750507514_tmphfb431oc_000007.jpg",
},
{
id: "scene-2",
name: "Space Station Interior",
description: "Main control room of the International Space Station",
plot: "Protagonist discovers an anomalous signal",
dialogue: "Captain: This signal... it's not from Earth",
narration: "In the darkness of space, a faint light blinks",
imageUrl: "https://smart-video-ai.oss-cn-beijing.aliyuncs.com/frames/d877fa43-4856-4acb-9a3b-627c28275343/frame_000007.jpg/1750507514_tmphfb431oc_000007.jpg",
},
{
id: "scene-3",
name: "Space Station Interior",
description: "Main control room of the International Space Station",
plot: "Protagonist discovers an anomalous signal",
dialogue: "Captain: This signal... it's not from Earth",
narration: "In the darkness of space, a faint light blinks",
imageUrl: "https://smart-video-ai.oss-cn-beijing.aliyuncs.com/frames/d877fa43-4856-4acb-9a3b-627c28275343/frame_000007.jpg/1750507514_tmphfb431oc_000007.jpg",
},
{
id: "scene-5",
name: "Space Station Interior",
description: "Main control room of the International Space Station",
plot: "Protagonist discovers an anomalous signal",
dialogue: "Captain: This signal... it's not from Earth",
narration: "In the darkness of space, a faint light blinks",
imageUrl: "https://smart-video-ai.oss-cn-beijing.aliyuncs.com/frames/d877fa43-4856-4acb-9a3b-627c28275343/frame_000007.jpg/1750507514_tmphfb431oc_000007.jpg",
},
{
id: "scene-6",
name: "Space Station Interior",
description: "Main control room of the International Space Station",
plot: "Protagonist discovers an anomalous signal",
dialogue: "Captain: This signal... it's not from Earth",
narration: "In the darkness of space, a faint light blinks",
imageUrl: "https://smart-video-ai.oss-cn-beijing.aliyuncs.com/frames/d877fa43-4856-4acb-9a3b-627c28275343/frame_000007.jpg/1750507514_tmphfb431oc_000007.jpg",
},
{
id: "scene-7",
name: "Space Station Interior",
description: "Main control room of the International Space Station",
plot: "Protagonist discovers an anomalous signal",
dialogue: "Captain: This signal... it's not from Earth",
narration: "In the darkness of space, a faint light blinks",
imageUrl: "https://smart-video-ai.oss-cn-beijing.aliyuncs.com/frames/d877fa43-4856-4acb-9a3b-627c28275343/frame_000007.jpg/1750507514_tmphfb431oc_000007.jpg",
},
{
id: "scene-8",
name: "Space Station Interior",
description: "Main control room of the International Space Station",
plot: "Protagonist discovers an anomalous signal",
dialogue: "Captain: This signal... it's not from Earth",
narration: "In the darkness of space, a faint light blinks",
imageUrl: "https://smart-video-ai.oss-cn-beijing.aliyuncs.com/frames/d877fa43-4856-4acb-9a3b-627c28275343/frame_000007.jpg/1750507514_tmphfb431oc_000007.jpg",
},
{
id: "scene-9",
name: "Space Station Interior",
description: "Main control room of the International Space Station",
plot: "Protagonist discovers an anomalous signal",
dialogue: "Captain: This signal... it's not from Earth",
narration: "In the darkness of space, a faint light blinks",
imageUrl: "https://smart-video-ai.oss-cn-beijing.aliyuncs.com/frames/d877fa43-4856-4acb-9a3b-627c28275343/frame_000007.jpg/1750507514_tmphfb431oc_000007.jpg",
},
{
id: "scene-10",
name: "Space Station Interior",
description: "Main control room of the International Space Station",
plot: "Protagonist discovers an anomalous signal",
dialogue: "Captain: This signal... it's not from Earth",
narration: "In the darkness of space, a faint light blinks",
imageUrl: "https://smart-video-ai.oss-cn-beijing.aliyuncs.com/frames/d877fa43-4856-4acb-9a3b-627c28275343/frame_000007.jpg/1750507514_tmphfb431oc_000007.jpg",
},
{
id: "scene-11",
name: "Space Station Interior",
description: "Main control room of the International Space Station",
plot: "Protagonist discovers an anomalous signal",
dialogue: "Captain: This signal... it's not from Earth",
narration: "In the darkness of space, a faint light blinks",
imageUrl: "https://smart-video-ai.oss-cn-beijing.aliyuncs.com/frames/d877fa43-4856-4acb-9a3b-627c28275343/frame_000007.jpg/1750507514_tmphfb431oc_000007.jpg",
},
{
id: "scene-12",
name: "Space Station Interior",
description: "Main control room of the International Space Station",
plot: "Protagonist discovers an anomalous signal",
dialogue: "Captain: This signal... it's not from Earth",
narration: "In the darkness of space, a faint light blinks",
imageUrl: "https://smart-video-ai.oss-cn-beijing.aliyuncs.com/frames/d877fa43-4856-4acb-9a3b-627c28275343/frame_000007.jpg/1750507514_tmphfb431oc_000007.jpg",
},
{
id: "scene-13",
name: "Space Station Interior",
description: "Main control room of the International Space Station",
plot: "Protagonist discovers an anomalous signal",
dialogue: "Captain: This signal... it's not from Earth",
narration: "In the darkness of space, a faint light blinks",
imageUrl: "https://smart-video-ai.oss-cn-beijing.aliyuncs.com/frames/d877fa43-4856-4acb-9a3b-627c28275343/frame_000007.jpg/1750507514_tmphfb431oc_000007.jpg",
},
{
id: "scene-14",
name: "Space Station Interior",
description: "Main control room of the International Space Station",
plot: "Protagonist discovers an anomalous signal",
dialogue: "Captain: This signal... it's not from Earth",
narration: "In the darkness of space, a faint light blinks",
imageUrl: "https://smart-video-ai.oss-cn-beijing.aliyuncs.com/frames/d877fa43-4856-4acb-9a3b-627c28275343/frame_000007.jpg/1750507514_tmphfb431oc_000007.jpg",
}
// ... 更多场景数据
]);
const [selectedSceneId, setSelectedSceneId] = useState<string>();
// Handle scene drag and drop sorting
const handleDragEnd = (event: DragEndEvent) => {
const { active, over } = event;
if (active.id === over?.id) {
return;
}
const oldIndex = scenes.findIndex(scene => scene.id === active.id);
const newIndex = scenes.findIndex(scene => scene.id === over?.id);
if (oldIndex === -1 || newIndex === -1) {
return;
}
setScenes(arrayMove(scenes, oldIndex, newIndex));
};
// Handle scene updates
const handleSceneUpdate = (sceneId: string, updates: Partial<Scene>) => {
setScenes(scenes.map(scene =>
scene.id === sceneId ? { ...scene, ...updates } : scene
));
};
// Handle scene deletion
const handleSceneDelete = (sceneId: string) => {
setScenes(scenes.filter(scene => scene.id !== sceneId));
if (selectedSceneId === sceneId) {
setSelectedSceneId(undefined);
}
};
// Handle scene duplication
const handleSceneDuplicate = (sceneId: string) => {
const sceneToDuplicate = scenes.find(scene => scene.id === sceneId);
if (!sceneToDuplicate) return;
const newScene = {
...sceneToDuplicate,
id: `scene-${Date.now()}`,
name: `${sceneToDuplicate.name} (Copy)`
};
setScenes([...scenes, newScene]);
};
return (
<div className="h-full bg-[#0C0E11] text-white">
<div className="h-full flex">
{/* Left: Script Meta Info */}
<div className="flex-shrink-0 h-full">
<ScriptMetaInfo meta={scriptMeta} />
</div>
{/* Right: Scene Content */}
<div className="flex-grow min-w-0 h-full overflow-hidden flex flex-col">
{/* Scene Card List */}
<div className="flex-grow overflow-y-auto px-8">
<DndContext
sensors={sensors}
collisionDetection={closestCenter}
onDragEnd={handleDragEnd}
>
<SortableContext
items={scenes.map(scene => scene.id)}
strategy={verticalListSortingStrategy}
>
<SceneCardList
scenes={scenes}
selectedSceneId={selectedSceneId}
onSceneUpdate={handleSceneUpdate}
onSceneDelete={handleSceneDelete}
onSceneDuplicate={handleSceneDuplicate}
/>
</SortableContext>
</DndContext>
</div>
{/* Filmstrip Preview */}
<div className="flex-shrink-0 py-6 px-8">
<SceneFilmstrip
scenes={scenes}
selectedSceneId={selectedSceneId}
onSceneSelect={(sceneId: string) => {
setSelectedSceneId(sceneId);
}}
/>
</div>
</div>
</div>
</div>
);
}