From 28de936c7cc96e4bbafaf9b0402560a13474ee45 Mon Sep 17 00:00:00 2001 From: kang Date: Wed, 13 May 2026 19:56:22 +0800 Subject: [PATCH] auto-save 2026-05-13 19:56 (~4) --- .memory/worklog.json | 7 ++++++ docs/source-analysis.html | 12 +++++++++++ web/components/nodes/index.tsx | 36 ++++++++++++++++++++++++++++--- web/components/storyboard-bar.tsx | 2 +- 4 files changed, 53 insertions(+), 4 deletions(-) diff --git a/.memory/worklog.json b/.memory/worklog.json index d4d8633..bf9fc0a 100644 --- a/.memory/worklog.json +++ b/.memory/worklog.json @@ -2248,6 +2248,13 @@ "type": "session-heartbeat", "message": "Codex 会话活跃 · 最近命令:codex · 4 项未提交变更 · 最近提交:auto-save 2026-05-13 19:45 (~3)", "files_changed": 4 + }, + { + "ts": "2026-05-13T19:50:51+08:00", + "type": "commit", + "message": "auto-save 2026-05-13 19:50 (~4)", + "hash": "a471f89", + "files_changed": 4 } ] } diff --git a/docs/source-analysis.html b/docs/source-analysis.html index c933501..d2641da 100644 --- a/docs/source-analysis.html +++ b/docs/source-analysis.html @@ -830,6 +830,18 @@ api/main.py

变更记录

这个记录不是 git log 的替代品。它记录“产品理解发生了什么变化、影响了哪些源码、你以后描述需求时该怎么说”。后续每次改功能都要补一条。

+
+
+

2026-05-13 · 钉住面板停靠到分镜头编排边缘

+ KeyframePanelNode + StoryboardBar +
+
+

问题:关键帧详情钉住在浏览器左侧固定位置时,会遮挡顶部分镜头编排栏展开后的缩略图区域。

+

改动:StoryboardBar 增加稳定 DOM 标记;钉住面板实时读取该区域下边缘,并吸附到其下方。展开 / 折叠分镜头编排时,钉住面板自动让位。

+

影响:web/components/storyboard-bar.tsxweb/components/nodes/index.tsx

+
+

2026-05-13 · 顶部分镜头编排不再跳转全屏工作台

diff --git a/web/components/nodes/index.tsx b/web/components/nodes/index.tsx index fa29fff..45f20d1 100644 --- a/web/components/nodes/index.tsx +++ b/web/components/nodes/index.tsx @@ -517,10 +517,40 @@ export function KeyframePanelNode({ data }: any) { const { getZoom } = useReactFlow() const panelRef = useRef(null) const [pinRect, setPinRect] = useState<{ left: number; top: number }>({ left: 24, top: 72 }) - if (!d.job || d.expandedFrame === null) return null - const active = d.job.frames.find((f) => f.index === d.expandedFrame) const scale = d.framePanelScale ?? 1 const pinned = d.framePanelPinned ?? false + + const getStoryboardDockTop = () => { + if (typeof window === "undefined") return 64 + const bar = document.querySelector('[data-storyboard-bar="true"]') + const bottom = bar?.getBoundingClientRect().bottom ?? 52 + return Math.max(56, Math.min(window.innerHeight - 120, bottom + 10)) + } + + useEffect(() => { + if (!pinned || typeof window === "undefined") return + + const syncDock = () => { + setPinRect({ left: 16, top: getStoryboardDockTop() }) + } + + syncDock() + const bar = document.querySelector('[data-storyboard-bar="true"]') + let observer: ResizeObserver | null = null + if (bar && "ResizeObserver" in window) { + observer = new ResizeObserver(syncDock) + observer.observe(bar) + } + window.addEventListener("resize", syncDock) + + return () => { + observer?.disconnect() + window.removeEventListener("resize", syncDock) + } + }, [pinned]) + + if (!d.job || d.expandedFrame === null) return null + const active = d.job.frames.find((f) => f.index === d.expandedFrame) const panelWidth = Math.round(760 * scale) const panelHeight = Math.round(746 * scale) const bodyHeight = Math.max(520, panelHeight - 27) @@ -533,7 +563,7 @@ export function KeyframePanelNode({ data }: any) { if (!pinned) { const zoom = getZoom() setScale(scale * zoom) - setPinRect({ left: 16, top: 64 }) + setPinRect({ left: 16, top: getStoryboardDockTop() }) } d.onFramePanelPinnedChange?.(!pinned) } diff --git a/web/components/storyboard-bar.tsx b/web/components/storyboard-bar.tsx index 295ba4a..a21b18f 100644 --- a/web/components/storyboard-bar.tsx +++ b/web/components/storyboard-bar.tsx @@ -41,7 +41,7 @@ export function StoryboardBar({ job, selectedFrames, focusedFrame, onFocusFrame return ( -
+
{/* header */}