auto-save 2026-05-13 18:18 (~5)

This commit is contained in:
2026-05-13 18:18:55 +08:00
parent 40cf8b0b8d
commit 22261986d5
5 changed files with 37 additions and 9 deletions

View File

@@ -31,7 +31,7 @@ export interface NodeData {
onDeleteFrame?: (idx: number) => void // 删整张关键帧
onDeleteGenerated?: (frameIdx: number, genId: string) => void // 删单张生成图
onOpenStoryboard?: (frameIdx: number) => void // 打开分镜头编排专属面板
onOpenWorkbench?: () => void // 打开全屏分镜编排工作台
onOpenWorkbench?: (frameIdx?: number) => void // 打开全屏分镜编排工作台
onCopyImage?: (ref: ImageRef) => void // 复制图片到全局剪贴板(粘贴到分镜头编排工作台插槽)
}
@@ -641,8 +641,11 @@ export function StoryboardNode({ data, selected }: any) {
<button
onClick={(e) => {
e.stopPropagation()
if (!d.selectedFrames.has(p.frameIdx)) {
d.onToggleFrame(p.frameIdx)
}
d.onOpenStoryboard?.(p.frameIdx)
d.onOpenWorkbench?.()
d.onOpenWorkbench?.(p.frameIdx)
}}
title={`${p.name} · 来自分镜 ${p.frameIdx + 1} · 点击进入分镜编排`}
className="absolute inset-0 w-full h-full"

View File

@@ -10,7 +10,7 @@ interface Props {
focusedFrame: number | null
onFocusFrame: (idx: number | null) => void
onJobUpdate?: (j: Job) => void
onOpenWorkbench?: () => void
onOpenWorkbench?: (frameIdx?: number) => void
}
export function StoryboardBar({ job, selectedFrames, focusedFrame, onFocusFrame, onJobUpdate, onOpenWorkbench }: Props) {
@@ -65,7 +65,7 @@ export function StoryboardBar({ job, selectedFrames, focusedFrame, onFocusFrame,
<div className="flex items-center gap-2 shrink-0">
{onOpenWorkbench && (
<button
onClick={onOpenWorkbench}
onClick={() => onOpenWorkbench(focusedFrame ?? frames[0]?.index)}
disabled={frames.length === 0}
className="text-[11px] px-2.5 py-1 rounded-md bg-gradient-to-r from-violet-500 to-pink-500 hover:from-violet-400 hover:to-pink-400 text-white inline-flex items-center gap-1 disabled:opacity-40 disabled:cursor-not-allowed font-medium shadow"
title={frames.length === 0 ? "先到关键帧节点选用分镜" : "全屏进入分镜头编排工作台"}
@@ -102,7 +102,10 @@ export function StoryboardBar({ job, selectedFrames, focusedFrame, onFocusFrame,
<button
key={f.index}
ref={(el) => { btnRefs.current[f.index] = el }}
onClick={() => onFocusFrame(f.index)}
onClick={() => {
onFocusFrame(f.index)
onOpenWorkbench?.(f.index)
}}
onMouseEnter={() => {
const el = btnRefs.current[f.index]
if (el) setHover({
@@ -187,4 +190,3 @@ export function StoryboardBar({ job, selectedFrames, focusedFrame, onFocusFrame,
</div>
)
}

View File

@@ -15,13 +15,14 @@ interface Props {
onClose: () => void
onJobUpdate?: (j: Job) => void
clipboard: ImageRef | null // 全局剪贴板page.tsx 提供)
focusedFrame: number | null
}
const emptyScene = (): StoryboardScene => ({
subject: "", product: "", scene: "", action: "", duration: 0, reference_ids: [],
})
export function StoryboardWorkbench({ job, selectedFrames, open, onClose, onJobUpdate, clipboard }: Props) {
export function StoryboardWorkbench({ job, selectedFrames, open, onClose, onJobUpdate, clipboard, focusedFrame }: Props) {
const [mounted, setMounted] = useState(false)
useEffect(() => setMounted(true), [])
@@ -39,6 +40,14 @@ export function StoryboardWorkbench({ job, selectedFrames, open, onClose, onJobU
return () => window.removeEventListener("keydown", onKey)
}, [open, onClose])
// 外部点击某个分镜 / 元素时,直接定位到那一帧。
useEffect(() => {
if (!open || !job || focusedFrame === null) return
if (!selectedFrames.has(focusedFrame)) return
if (!job.frames.some((f) => f.index === focusedFrame)) return
setFocusedIdx(focusedFrame)
}, [open, job?.id, job?.frames, selectedFrames, focusedFrame])
// 默认选第一个分镜
useEffect(() => {
if (!open || !job) return