auto-save 2026-05-14 03:31 (~4)

This commit is contained in:
2026-05-14 03:31:49 +08:00
parent 65f81efec8
commit 6ff4f59051
4 changed files with 113 additions and 22 deletions

View File

@@ -88,10 +88,10 @@ export default function Home() {
const [selectedFrames, setSelectedFrames] = useState<Set<number>>(new Set())
const [expandedFrame, setExpandedFrame] = useState<number | null>(null)
const [framePanelScale, setFramePanelScale] = useState(1)
const [framePanelPinned, setFramePanelPinned] = useState(false)
const [framePanelPinned, setFramePanelPinned] = useState(true)
const [videoPanelJobId, setVideoPanelJobId] = useState<string | null>(null)
const [videoPanelScale, setVideoPanelScale] = useState(1)
const [videoPanelDock, setVideoPanelDock] = useState<CanvasPanelDock>("canvas")
const [videoPanelDock, setVideoPanelDock] = useState<CanvasPanelDock>("left")
const [videoPanelOpenTick, setVideoPanelOpenTick] = useState(0)
const [storyboardFrame, setStoryboardFrame] = useState<number | null>(null)
const [workbenchOpen, setWorkbenchOpen] = useState(false)
@@ -191,9 +191,10 @@ export default function Home() {
const handleOpenVideoPanel = useCallback((jobId: string) => {
setActiveJobId(jobId)
if (!videoPanelJobId) setVideoPanelDock("left")
setVideoPanelJobId(jobId)
setVideoPanelOpenTick((n) => n + 1)
}, [])
}, [videoPanelJobId])
const handleVideoPanelScaleChange = useCallback((scale: number) => {
setVideoPanelScale(Math.max(0.65, Math.min(1.6, Number(scale.toFixed(2)))))
@@ -209,30 +210,38 @@ export default function Home() {
}, [])
const handleOpenFramePanel = useCallback((idx: number) => {
if (expandedFrame === null) setFramePanelPinned(true)
setExpandedFrame(idx)
}, [])
}, [expandedFrame])
const handleFramePanelScaleChange = useCallback((scale: number) => {
setFramePanelScale(Math.max(0.65, Math.min(1.6, Number(scale.toFixed(2)))))
}, [])
const handleDeleteFrame = useCallback(async (idx: number) => {
if (!activeJobId) return
const handleDeleteFrameForJob = useCallback(async (jobId: string, idx: number) => {
const wasActive = activeJobId === jobId
try {
const updated = await deleteFrame(activeJobId, idx)
setJob(updated)
const updated = await deleteFrame(jobId, idx)
setJobs((prev) => prev.map((item) => item.id === updated.id ? updated : item))
setActiveJobId(updated.id)
setSelectedFrames((prev) => {
if (!wasActive) return new Set()
if (!prev.has(idx)) return prev
const next = new Set(prev)
next.delete(idx)
return next
})
if (expandedFrame === idx) setExpandedFrame(null)
if (!wasActive || expandedFrame === idx) setExpandedFrame(null)
toast.success(`分镜 ${idx + 1} 已删除`)
} catch (e) {
toast.error("删除失败:" + (e instanceof Error ? e.message : String(e)))
}
}, [activeJobId, expandedFrame, setJob])
}, [activeJobId, expandedFrame])
const handleDeleteFrame = useCallback(async (idx: number) => {
if (!activeJobId) return
await handleDeleteFrameForJob(activeJobId, idx)
}, [activeJobId, handleDeleteFrameForJob])
const handleDeleteGenerated = useCallback(async (frameIdx: number, genId: string) => {
if (!activeJobId) return
@@ -512,6 +521,7 @@ export default function Home() {
onJobUpdate: setJob as any,
onDeleteJob: handleDeleteJob,
onDeleteFrame: handleDeleteFrame,
onDeleteFrameForJob: handleDeleteFrameForJob,
onDeleteGenerated: handleDeleteGenerated,
onDeleteVideo: handleDeleteVideo,
onDeleteCutout: handleDeleteCutout,
@@ -523,7 +533,7 @@ export default function Home() {
onCopyImage: handleCopyImage,
pinnedNodes,
onToggleNodePin: handleToggleNodePin,
}), [job, jobs, activeJobId, submitting, analyzing, selectedFrames, expandedFrame, framePanelScale, framePanelPinned, videoPanelJobId, videoPanelScale, videoPanelDock, handleSubmit, handleUpload, handleAnalyze, handleToggleFrame, handleOpenFramePanel, handleFramePanelScaleChange, handleAddManualFrame, handleAddManualFrameForJob, handleOpenVideoPanel, handleVideoPanelScaleChange, handleSwitchJob, setJob, handleDeleteJob, handleDeleteFrame, handleDeleteGenerated, handleDeleteVideo, handleDeleteCutout, handleCopyImage, pinnedNodes, handleToggleNodePin])
}), [job, jobs, activeJobId, submitting, analyzing, selectedFrames, expandedFrame, framePanelScale, framePanelPinned, videoPanelJobId, videoPanelScale, videoPanelDock, handleSubmit, handleUpload, handleAnalyze, handleToggleFrame, handleOpenFramePanel, handleFramePanelScaleChange, handleAddManualFrame, handleAddManualFrameForJob, handleOpenVideoPanel, handleVideoPanelScaleChange, handleSwitchJob, setJob, handleDeleteJob, handleDeleteFrame, handleDeleteFrameForJob, handleDeleteGenerated, handleDeleteVideo, handleDeleteCutout, handleCopyImage, pinnedNodes, handleToggleNodePin])
// 用 useNodesState 让 ReactFlow 自己管位置(避免轮询时重置 drag
const savedSizes = useMemo(() => loadNodeSizes(), [])
@@ -681,7 +691,7 @@ export default function Home() {
},
]
})
if (shouldFocusNewPanel) {
if (shouldFocusNewPanel && !framePanelPinned) {
window.setTimeout(() => {
flowRef.current?.fitView?.({
nodes: [{ id: KEYFRAME_PANEL_ID }, { id: "visual" }],