+

-
-
{p.name}
-
来自分镜 {p.frameIdx + 1} · 点击进入分镜头编排
+
+ {p.name}
+ 来自分镜 {p.frameIdx + 1}
,
diff --git a/web/components/storyboard-bar.tsx b/web/components/storyboard-bar.tsx
index eee3ae2..5121c9e 100644
--- a/web/components/storyboard-bar.tsx
+++ b/web/components/storyboard-bar.tsx
@@ -1,16 +1,17 @@
"use client"
import { useEffect, useRef, useState } from "react"
import { createPortal } from "react-dom"
-import { LayoutGrid, ChevronDown, ChevronUp, Sparkle } from "lucide-react"
-import { type Job, type KeyFrame, effectiveFrameUrl } from "@/lib/api"
+import { LayoutGrid, ChevronDown, ChevronUp, Sparkle, X, Wand2, Brush } from "lucide-react"
+import { type Job, type KeyFrame, effectiveFrameUrl, cutoutUrl } from "@/lib/api"
interface Props {
job: Job | null
selectedFrames: Set
- onOpenStoryboard: (idx: number) => void
+ focusedFrame: number | null // 当前 focus 的分镜(imagegen 节点 / bar 缩略图点击触发)
+ onFocusFrame: (idx: number | null) => void
}
-export function StoryboardBar({ job, selectedFrames, onOpenStoryboard }: Props) {
+export function StoryboardBar({ job, selectedFrames, focusedFrame, onFocusFrame }: Props) {
const [collapsed, setCollapsed] = useState(false)
const [mounted, setMounted] = useState(false)
useEffect(() => setMounted(true), [])
@@ -20,7 +21,6 @@ export function StoryboardBar({ job, selectedFrames, onOpenStoryboard }: Props)
if (!job) return null
- // 按时间序排已选用的分镜
const frames = job.frames
.filter((f) => selectedFrames.has(f.index))
.sort((a, b) => a.timestamp - b.timestamp)
@@ -31,6 +31,16 @@ export function StoryboardBar({ job, selectedFrames, onOpenStoryboard }: Props)
0,
)
+ // focused 分镜数据
+ const focusFrame = focusedFrame !== null
+ ? job.frames.find((f) => f.index === focusedFrame) ?? null
+ : null
+ const focusSeq = focusFrame
+ ? job.frames.filter((f) => selectedFrames.has(f.index) && f.timestamp <= focusFrame.timestamp).length
+ : 0
+ const focusElements = focusFrame?.elements ?? []
+ const focusCutCount = focusElements.filter((e) => e.cutout_id).length
+
return (
{/* header */}
@@ -41,18 +51,36 @@ export function StoryboardBar({ job, selectedFrames, onOpenStoryboard }: Props)
{frames.length} 分镜 · {totalElements} 元素
-
- · 组织分镜画面 → 为生成视频做准备
-
+ {focusFrame ? (
+
+ · 编排中:分镜 {focusSeq}
+
+ ) : (
+
+ · 组织分镜画面 → 为生成视频做准备
+
+ )}
+
+
+ {focusFrame && (
+
+ )}
+
-
{/* thumbnails row */}
@@ -67,18 +95,23 @@ export function StoryboardBar({ job, selectedFrames, onOpenStoryboard }: Props)
const elementCount = f.elements?.filter((e) => e.cutout_id).length ?? 0
const totalElCount = f.elements?.length ?? 0
const cleaned = f.cleaned_applied
+ const isFocused = focusedFrame === f.index
return (