diff --git a/apps/web/src/pages/editing-planner/components/timeline/ClipTrack.tsx b/apps/web/src/pages/editing-planner/components/timeline/ClipTrack.tsx new file mode 100644 index 000000000..4b84f871b --- /dev/null +++ b/apps/web/src/pages/editing-planner/components/timeline/ClipTrack.tsx @@ -0,0 +1,147 @@ +import React from "react" +import type { ClipData, TrimConfig } from "../../types" +import { ClipCard } from "./ClipCard" + +interface ClipTrackProps { + /** 片段列表 */ + clips: ClipData[] + /** 选中的片段ID */ + selectedClipId: string | null + /** 缩放:每秒像素数 */ + pps: number + /** 当前播放时间(秒) */ + currentTime: number + /** 总时长(秒) */ + totalDuration: number + /** 正在拖拽的片段索引 */ + dragIdx: number | null + /** 拖拽悬停的片段索引 */ + dragOverIdx: number | null + /** 悬停的片段ID */ + hoveredClipId: string | null + /** 是否正在裁剪拖拽 */ + trimDragActive: boolean + /** 是否显示裁剪手柄 */ + showTrimHandles: boolean + /** 轨道ref */ + trackRef: React.RefObject + /** 添加卡片ref */ + addCardRef: React.RefObject + /** 播放头拖拽开始 */ + onPlayheadMouseDown: (e: React.MouseEvent) => void + /** 片段选中 */ + onClipSelect: (clipId: string) => void + /** 拖拽开始 */ + onDragStart: (idx: number, e: React.DragEvent) => void + /** 拖拽悬停 */ + onDragOver: (idx: number, e: React.DragEvent) => void + /** 拖拽结束 */ + onDragEnd: () => void + /** 放置 */ + onDrop: (idx: number, e: React.DragEvent) => void + /** 空区域拖拽悬停 */ + onEmptyDragOver: (e: React.DragEvent) => void + /** 右键菜单 */ + onContextMenu: (clipId: string, e: React.MouseEvent) => void + /** 片段悬停进入 */ + onClipMouseEnter: (clipId: string) => void + /** 片段悬停离开 */ + onClipMouseLeave: () => void + /** 裁剪手柄按下 */ + onTrimHandleMouseDown: (clipId: string, side: "start" | "end", e: React.MouseEvent) => void + /** 删除片段 */ + onClipRemove: (clipId: string) => void + /** 点击添加卡片 */ + onTogglePicker: () => void +} + +/** + * 片段轨道组件 + * 包含播放头、片段列表、空状态和添加卡片 + */ +export const ClipTrack: React.FC = ({ + clips, + selectedClipId, + pps, + currentTime, + totalDuration, + dragIdx, + dragOverIdx, + hoveredClipId, + trimDragActive, + showTrimHandles, + trackRef, + addCardRef, + onPlayheadMouseDown, + onClipSelect, + onDragStart, + onDragOver, + onDragEnd, + onDrop, + onEmptyDragOver, + onContextMenu, + onClipMouseEnter, + onClipMouseLeave, + onTrimHandleMouseDown, + onClipRemove, + onTogglePicker, +}) => { + return ( +
+ {/* 播放头 */} + {totalDuration > 0 && ( +
+
+
+ )} + {clips.length === 0 ? ( +
+
🎬
+
点击右侧 + 添加片段
+
+ ) : ( + clips.map((clip, idx) => ( + onClipMouseEnter(clip.id)} + onMouseLeave={onClipMouseLeave} + onTrimHandleMouseDown={onTrimHandleMouseDown} + onRemove={onClipRemove} + /> + )) + )} + + {/* ── 轨道末尾 "+" 添加卡片 ── */} +
+
+ + +
+
+
+ ) +} +