auto-save 2026-05-14 00:02 (+3, ~4)

This commit is contained in:
2026-05-14 00:03:09 +08:00
parent 12daaa2be6
commit 4c11a4ccc4
7 changed files with 530 additions and 13 deletions

View File

@@ -39,17 +39,29 @@ const KEYFRAME_PANEL_ID = "keyframe-detail-panel"
// 合并 input + download + split 为一个节点
// 分叉:上路 input → keyframe → storyboard → videogen ↘
// 下路 input → asr → translate → rewrite ──────→ storyboard / compose
const LAYOUT: Array<{ id: string; type: keyof typeof NODE_TYPES; x: number; y: number }> = [
{ id: "input", type: "input", x: 40, y: 240 },
{ id: "keyframe", type: "keyframe", x: 460, y: 60 },
{ id: "asr", type: "asr", x: 460, y: 440 },
{ id: "translate", type: "translate", x: 840, y: 440 },
{ id: "storyboard", type: "storyboard", x: 880, y: 60 },
{ id: "rewrite", type: "rewrite", x: 1220, y: 440 },
{ id: "videogen", type: "videogen", x: 1260, y: 60 },
{ id: "compose", type: "compose", x: 1640, y: 240 },
const LAYOUT: Array<{ id: string; type: keyof typeof NODE_TYPES; x: number; y: number; w: number }> = [
{ id: "input", type: "input", x: 40, y: 240, w: 320 },
{ id: "keyframe", type: "keyframe", x: 460, y: 60, w: 360 },
{ id: "asr", type: "asr", x: 460, y: 440, w: 320 },
{ id: "translate", type: "translate", x: 840, y: 440, w: 320 },
{ id: "storyboard", type: "storyboard", x: 880, y: 60, w: 360 },
{ id: "rewrite", type: "rewrite", x: 1220, y: 440, w: 320 },
{ id: "videogen", type: "videogen", x: 1260, y: 60, w: 280 },
{ id: "compose", type: "compose", x: 1640, y: 240, w: 320 },
]
const NODE_WIDTHS_KEY = "skg-tk:node-widths:v1"
function loadNodeWidths(): Record<string, number> {
if (typeof window === "undefined") return {}
try {
const raw = window.localStorage.getItem(NODE_WIDTHS_KEY)
return raw ? JSON.parse(raw) : {}
} catch {
return {}
}
}
const EDGES_RAW: Array<[string, string]> = [
["input", "keyframe"],
["input", "asr"],
@@ -433,6 +445,7 @@ export default function Home() {
}), [job, jobs, activeJobId, submitting, analyzing, selectedFrames, expandedFrame, framePanelScale, framePanelPinned, handleSubmit, handleUpload, handleAnalyze, handleToggleFrame, handleOpenFramePanel, handleFramePanelScaleChange, handleAddManualFrame, handleSwitchJob, setJob, handleDeleteFrame, handleDeleteGenerated, handleDeleteVideo, handleCopyImage])
// 用 useNodesState 让 ReactFlow 自己管位置(避免轮询时重置 drag
const savedWidths = useMemo(() => loadNodeWidths(), [])
const [nodes, setNodes, onNodesChange] = useNodesState<Node>(
LAYOUT.map((n) => ({
id: n.id,
@@ -440,8 +453,21 @@ export default function Home() {
position: { x: n.x, y: n.y },
data: nodeData,
draggable: true,
width: savedWidths[n.id] ?? n.w,
style: { width: savedWidths[n.id] ?? n.w },
})),
)
// 持久化每个节点宽度到 localStorageKeyframePanelNode 自己管尺寸,不写回)
useEffect(() => {
const widths: Record<string, number> = {}
for (const n of nodes) {
if (n.id === KEYFRAME_PANEL_ID) continue
const w = (n.style?.width ?? n.width) as number | string | undefined
if (typeof w === "number") widths[n.id] = Math.round(w)
}
try { window.localStorage.setItem(NODE_WIDTHS_KEY, JSON.stringify(widths)) } catch {}
}, [nodes])
const [edges, setEdges, onEdgesChange] = useEdgesState<Edge>(
EDGES_RAW.map(([from, to], i) => ({
id: `e${i}`, source: from, target: to, animated: false, type: "default",