auto-save 2026-05-14 00:25 (+6, ~5)
This commit is contained in:
@@ -50,12 +50,14 @@ const LAYOUT: Array<{ id: string; type: keyof typeof NODE_TYPES; x: number; y: n
|
||||
{ id: "compose", type: "compose", x: 1640, y: 240, w: 320 },
|
||||
]
|
||||
|
||||
const NODE_WIDTHS_KEY = "skg-tk:node-widths:v1"
|
||||
const NODE_SIZES_KEY = "skg-tk:node-sizes:v2"
|
||||
|
||||
function loadNodeWidths(): Record<string, number> {
|
||||
type NodeSize = { w?: number; h?: number }
|
||||
|
||||
function loadNodeSizes(): Record<string, NodeSize> {
|
||||
if (typeof window === "undefined") return {}
|
||||
try {
|
||||
const raw = window.localStorage.getItem(NODE_WIDTHS_KEY)
|
||||
const raw = window.localStorage.getItem(NODE_SIZES_KEY)
|
||||
return raw ? JSON.parse(raw) : {}
|
||||
} catch {
|
||||
return {}
|
||||
@@ -445,27 +447,36 @@ 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 savedSizes = useMemo(() => loadNodeSizes(), [])
|
||||
const [nodes, setNodes, onNodesChange] = useNodesState<Node>(
|
||||
LAYOUT.map((n) => ({
|
||||
id: n.id,
|
||||
type: n.type,
|
||||
position: { x: n.x, y: n.y },
|
||||
data: nodeData,
|
||||
draggable: true,
|
||||
width: savedWidths[n.id] ?? n.w,
|
||||
})),
|
||||
LAYOUT.map((n) => {
|
||||
const s = savedSizes[n.id] ?? {}
|
||||
const w = s.w ?? n.w
|
||||
const h = s.h
|
||||
return {
|
||||
id: n.id,
|
||||
type: n.type,
|
||||
position: { x: n.x, y: n.y },
|
||||
data: nodeData,
|
||||
draggable: true,
|
||||
width: w,
|
||||
...(typeof h === "number" ? { height: h } : {}),
|
||||
style: { width: w, ...(typeof h === "number" ? { height: h } : {}) },
|
||||
}
|
||||
}),
|
||||
)
|
||||
|
||||
// 持久化每个节点宽度到 localStorage(KeyframePanelNode 自己管尺寸,不写回)
|
||||
// 持久化每个节点宽 / 高到 localStorage(KeyframePanelNode 自己管尺寸,不写回)
|
||||
useEffect(() => {
|
||||
const widths: Record<string, number> = {}
|
||||
const sizes: Record<string, NodeSize> = {}
|
||||
for (const n of nodes) {
|
||||
if (n.id === KEYFRAME_PANEL_ID) continue
|
||||
const w = n.width
|
||||
if (typeof w === "number") widths[n.id] = Math.round(w)
|
||||
const w = typeof n.width === "number" ? Math.round(n.width) : undefined
|
||||
const h = typeof n.height === "number" ? Math.round(n.height) : undefined
|
||||
if (w === undefined && h === undefined) continue
|
||||
sizes[n.id] = { ...(w !== undefined ? { w } : {}), ...(h !== undefined ? { h } : {}) }
|
||||
}
|
||||
try { window.localStorage.setItem(NODE_WIDTHS_KEY, JSON.stringify(widths)) } catch {}
|
||||
try { window.localStorage.setItem(NODE_SIZES_KEY, JSON.stringify(sizes)) } catch {}
|
||||
}, [nodes])
|
||||
const [edges, setEdges, onEdgesChange] = useEdgesState<Edge>(
|
||||
EDGES_RAW.map(([from, to], i) => ({
|
||||
|
||||
Reference in New Issue
Block a user