auto-save 2026-05-13 10:49 (~2)

This commit is contained in:
2026-05-13 10:49:59 +08:00
parent e4989f6065
commit 99bcb80710
2 changed files with 46 additions and 2 deletions

View File

@@ -1257,6 +1257,19 @@
"message": "auto-save 2026-05-13 10:38 (~5)",
"hash": "98d4ecb",
"files_changed": 5
},
{
"ts": "2026-05-13T10:44:25+08:00",
"type": "commit",
"message": "auto-save 2026-05-13 10:44 (~4)",
"hash": "e4989f6",
"files_changed": 4
},
{
"ts": "2026-05-13T02:47:36Z",
"type": "session-heartbeat",
"message": "Claude 会话活跃 · 最近命令claude · 2 项未提交变更 · 最近提交auto-save 2026-05-13 10:44 (~4)",
"files_changed": 2
}
]
}

View File

@@ -14,7 +14,7 @@ import {
} from "@/components/nodes"
import { ThemeToggle } from "@/components/theme-toggle"
import { Dashboard, type DashboardHandle } from "@/components/dashboard"
import { addManualFrame, analyzeJob, createJob, getJob, uploadJob, type Job } from "@/lib/api"
import { addManualFrame, analyzeJob, createJob, getJob, uploadJob, deleteFrame, deleteGeneratedImage, type Job } from "@/lib/api"
import { VideoLightbox } from "@/components/video-lightbox"
const NODE_TYPES = {
@@ -160,6 +160,35 @@ export default function Home() {
})
}, [])
const handleDeleteFrame = useCallback(async (idx: number) => {
if (!activeJobId) return
try {
const updated = await deleteFrame(activeJobId, idx)
setJob(updated)
setSelectedFrames((prev) => {
if (!prev.has(idx)) return prev
const next = new Set(prev)
next.delete(idx)
return next
})
if (expandedFrame === idx) setExpandedFrame(null)
toast.success(`分镜 ${idx + 1} 已删除`)
} catch (e) {
toast.error("删除失败:" + (e instanceof Error ? e.message : String(e)))
}
}, [activeJobId, expandedFrame, setJob])
const handleDeleteGenerated = useCallback(async (frameIdx: number, genId: string) => {
if (!activeJobId) return
try {
const updated = await deleteGeneratedImage(activeJobId, frameIdx, genId)
setJob(updated)
toast.success("生成图已删除")
} catch (e) {
toast.error("删除失败:" + (e instanceof Error ? e.message : String(e)))
}
}, [activeJobId, setJob])
// URL ?job=xxx,yyy 自动恢复多个 job
useEffect(() => {
const params = new URLSearchParams(window.location.search)
@@ -227,7 +256,9 @@ export default function Home() {
onSwitchJob: handleSwitchJob,
onJobUpdate: setJob as any,
onOpenPanel: (key: string) => dashboardRef.current?.openPanel(key),
}), [job, jobs, activeJobId, submitting, analyzing, selectedFrames, expandedFrame, handleSubmit, handleUpload, handleAnalyze, handleToggleFrame, handleAddManualFrame, handleSwitchJob, setJob])
onDeleteFrame: handleDeleteFrame,
onDeleteGenerated: handleDeleteGenerated,
}), [job, jobs, activeJobId, submitting, analyzing, selectedFrames, expandedFrame, handleSubmit, handleUpload, handleAnalyze, handleToggleFrame, handleAddManualFrame, handleSwitchJob, setJob, handleDeleteFrame, handleDeleteGenerated])
// 用 useNodesState 让 ReactFlow 自己管位置(避免轮询时重置 drag
const [nodes, setNodes, onNodesChange] = useNodesState<Node>(