auto-save 2026-05-13 20:01 (~6)

This commit is contained in:
2026-05-13 20:01:52 +08:00
parent 28de936c7c
commit 3f9075f2ce
6 changed files with 68 additions and 36 deletions

View File

@@ -37,8 +37,8 @@ export interface NodeData {
onDeleteFrame?: (idx: number) => void // 删整张关键帧
onDeleteGenerated?: (frameIdx: number, genId: string) => void // 删单张生成图
onOpenStoryboard?: (frameIdx: number) => void // 打开分镜头编排专属面板
onOpenWorkbench?: (frameIdx?: number) => void // 打开全屏分镜编排工作台
onCopyImage?: (ref: ImageRef) => void // 复制图片到全局剪贴板(粘贴到分镜头编排工作台插槽)
onOpenWorkbench?: (frameIdx?: number) => void // 展开顶部分镜编排内嵌面板
onCopyImage?: (ref: ImageRef) => void // 复制图片到全局剪贴板(粘贴到分镜头编排插槽)
}
/* ---- 状态映射工具 ---- */
@@ -522,8 +522,9 @@ export function KeyframePanelNode({ data }: any) {
const getStoryboardDockTop = () => {
if (typeof window === "undefined") return 64
const dock = document.querySelector<HTMLElement>('[data-storyboard-dock="true"]')
const bar = document.querySelector<HTMLElement>('[data-storyboard-bar="true"]')
const bottom = bar?.getBoundingClientRect().bottom ?? 52
const bottom = (dock ?? bar)?.getBoundingClientRect().bottom ?? 52
return Math.max(56, Math.min(window.innerHeight - 120, bottom + 10))
}
@@ -535,7 +536,8 @@ export function KeyframePanelNode({ data }: any) {
}
syncDock()
const bar = document.querySelector<HTMLElement>('[data-storyboard-bar="true"]')
const bar = document.querySelector<HTMLElement>('[data-storyboard-dock="true"]')
?? document.querySelector<HTMLElement>('[data-storyboard-bar="true"]')
let observer: ResizeObserver | null = null
if (bar && "ResizeObserver" in window) {
observer = new ResizeObserver(syncDock)

View File

@@ -9,9 +9,10 @@ interface Props {
selectedFrames: Set<number>
focusedFrame: number | null
onFocusFrame: (idx: number | null) => void
onOpenWorkbench?: (frameIdx?: number) => void
}
export function StoryboardBar({ job, selectedFrames, focusedFrame, onFocusFrame }: Props) {
export function StoryboardBar({ job, selectedFrames, focusedFrame, onFocusFrame, onOpenWorkbench }: Props) {
const [collapsed, setCollapsed] = useState(false)
const [mounted, setMounted] = useState(false)
useEffect(() => setMounted(true), [])
@@ -64,8 +65,10 @@ export function StoryboardBar({ job, selectedFrames, focusedFrame, onFocusFrame
<button
onClick={() => {
if (frames.length === 0) return
if (focusedFrame === null) onFocusFrame(frames[0].index)
const nextFrame = focusedFrame ?? frames[0].index
if (focusedFrame === null) onFocusFrame(nextFrame)
setCollapsed(false)
onOpenWorkbench?.(nextFrame)
}}
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"

View File

@@ -1,6 +1,5 @@
"use client"
import { useEffect, useState, useRef, type ReactNode } from "react"
import { createPortal } from "react-dom"
import { X, LayoutGrid, Loader2, Check, Wand2 } from "lucide-react"
import {
type Job, type StoryboardScene, type ImageRef,
@@ -94,9 +93,9 @@ export function StoryboardWorkbench({ job, selectedFrames, open, onClose, onJobU
const aspect = job.height > 0 ? `${job.width}/${job.height}` : "9/16"
return createPortal(
return (
<div
className="fixed inset-0 z-[200] bg-black/92 backdrop-blur-xl flex flex-col"
className="relative z-20 h-[min(680px,calc(100vh-170px))] flex-shrink-0 border-b border-white/10 bg-black/90 backdrop-blur-xl flex flex-col shadow-2xl"
style={{ animation: "drawer-in 0.2s cubic-bezier(0.32, 0.72, 0, 1)" }}
>
{/* Header */}
@@ -117,9 +116,9 @@ export function StoryboardWorkbench({ job, selectedFrames, open, onClose, onJobU
<button
onClick={onClose}
className="h-8 px-3 rounded-md bg-white/10 hover:bg-white/20 text-white inline-flex items-center gap-1.5 text-[12px]"
title="返回 DAG (Esc)"
title="收起编排 (Esc)"
>
<X className="h-3.5 w-3.5" /> DAG
<X className="h-3.5 w-3.5" />
</button>
</div>
</header>
@@ -338,10 +337,9 @@ export function StoryboardWorkbench({ job, selectedFrames, open, onClose, onJobU
{/* 底部快捷 */}
<footer className="border-t border-white/10 px-5 py-1.5 text-[10px] text-white/40 font-mono text-center bg-black/40">
ESC DAG ·
ESC ·
</footer>
</div>,
document.body,
</div>
)
}