diff --git a/apps/web/src/pages/editing-planner/components/TimelinePanel.tsx b/apps/web/src/pages/editing-planner/components/TimelinePanel.tsx deleted file mode 100644 index 15a564a50..000000000 --- a/apps/web/src/pages/editing-planner/components/TimelinePanel.tsx +++ /dev/null @@ -1,200 +0,0 @@ -/** - * 水平轨道时间线 — 支持裁剪手柄、分割、右键菜单 - * 时间标尺 + 片段轨道 + HTML5拖拽排序 - * - * 子组件(timeline/): - * - TimeRuler - 时间标尺 - * - ClipCard - 片段卡片 - * - ClipTrack - 片段轨道(播放头+片段列表+添加卡片) - * - TimelineHeader - 时间线头部(标题+缩放+操作按钮) - * - TrimPreview - 裁剪预览 tooltip - * - ContextMenu - 右键菜单 - * - * Hooks: - * - useClipDrag - 片段拖拽排序 - * - useTrimDrag - 裁剪拖拽 - * - useTimelineMenus - 菜单 & 面板 - * - usePlayheadDrag - 播放头拖拽 - */ -import React from "react" -import type { ClipData, ClipType, TrimConfig } from "../types" -import { DEFAULT_PIXELS_PER_SECOND } from "../constants/timeline" -import { useClipDrag } from "../hooks/useClipDrag" -import { useTrimDrag } from "../hooks/useTrimDrag" -import { useTimelineMenus } from "../hooks/useTimelineMenus" -import { usePlayheadDrag } from "./timeline/hooks/usePlayheadDrag" -import { TimeRuler } from "./timeline/TimeRuler" -import { ClipTrack } from "./timeline/ClipTrack" -import { TimelineHeader } from "./timeline/TimelineHeader" -import { TrimPreview } from "./timeline/TrimPreview" -import { ContextMenu } from "./timeline/ContextMenu" - -interface TimelinePanelProps { - clips: ClipData[] - selectedClipId: string | null - currentMode: string - onClipSelect: (clipId: string) => void - onClipReorder: (fromIdx: number, toIdx: number) => void - onClipRemove: (clipId: string) => void - onAddClip: (type: ClipType, duration: number) => void - /** 裁剪更新:调整片段的 trim_config 和 duration */ - onClipTrim?: (clipId: string, trimConfig: TrimConfig, newDuration: number) => void - /** 在指定位置分割片段 */ - onClipSplit?: (clipId: string, splitRatio: number) => void - /** 恢复片段原始长度 */ - onClipResetTrim?: (clipId: string) => void - /** 当前播放时间(秒) */ - currentTime?: number - /** 缩放:每秒像素数 */ - pixelsPerSecond?: number - /** 缩放变更回调 */ - onZoomChange?: (pps: number) => void - /** 播放头跳转回调 */ - onSeek?: (time: number) => void - /** 总时长(秒),可选(默认由 clips 计算) */ - totalDuration?: number -} - -const TimelinePanel: React.FC = ({ - clips, - selectedClipId, - currentMode, - onClipSelect, - onClipReorder, - onClipRemove, - onAddClip, - onClipTrim, - onClipSplit, - onClipResetTrim, - currentTime = 0, - pixelsPerSecond = 40, - onZoomChange, - onSeek, - totalDuration: totalDurationProp, -}) => { - /* ── 缩放 & 时长 ── */ - const pps = pixelsPerSecond ?? DEFAULT_PIXELS_PER_SECOND - const totalDuration = totalDurationProp ?? clips.reduce((s, c) => s + c.duration, 0) - - /* ── 裁剪拖拽 ── */ - const { trimDrag, trimPreview, handleTrimHandleMouseDown } = useTrimDrag(clips, pps, onClipTrim) - - /* ── 片段拖拽排序 ── */ - const { - dragIdx, - dragOverIdx, - handleDragStart, - handleDragOver, - handleDragEnd, - handleDrop, - handleEmptyDragOver, - } = useClipDrag(onClipReorder, !!trimDrag) - - /* ── 菜单 & 面板 ── */ - const { - contextMenu, - contextMenuRef, - handleContextMenu, - handleContextSplit, - handleContextResetTrim, - handleContextDelete, - addCardRef, - handleConfirmAdd, - hoveredClipId, - setHoveredClipId, - } = useTimelineMenus(clips, currentMode, onAddClip, onClipSplit, onClipResetTrim, onClipRemove) - - /* ── 播放头拖拽 ── */ - const { trackRef, handlePlayheadMouseDown, handleRulerClick } = usePlayheadDrag({ - currentTime, - pps, - totalDuration, - onSeek, - }) - - /* ── 撤销最后一个片段 ── */ - const handleUndoClip = () => { - if (clips.length > 1) { - const last = clips[clips.length - 1] - onClipRemove(last.id) - } - } - - return ( -
- {/* 时间线头部 */} - - - {/* 一镜到底提示 */} - {currentMode === "one_take" &&
🎥 一镜到底模式无片段
} - - {/* 时间标尺 */} - {currentMode !== "one_take" && ( - - )} - - {/* 水平片段轨道 */} - {currentMode !== "one_take" && ( - setHoveredClipId(null)} - onTrimHandleMouseDown={handleTrimHandleMouseDown} - onClipRemove={onClipRemove} - onTogglePicker={handleConfirmAdd} - /> - )} - - {/* 裁剪预览 tooltip */} - {trimPreview && ( - - )} - - {/* 右键菜单 */} - {contextMenu && ( - c.id === contextMenu.clipId)?.trim_config} - onSplit={handleContextSplit} - onResetTrim={handleContextResetTrim} - onDelete={handleContextDelete} - /> - )} -
- ) -} - -export default TimelinePanel