auto-save 2026-05-14 05:49 (~2)
This commit is contained in:
@@ -1,19 +1,5 @@
|
||||
{
|
||||
"entries": [
|
||||
{
|
||||
"files_changed": 9,
|
||||
"hash": "b0ffd03",
|
||||
"message": "auto-save 2026-05-12 16:02 (+2, ~6)",
|
||||
"ts": "2026-05-12T16:05:47+08:00",
|
||||
"type": "commit"
|
||||
},
|
||||
{
|
||||
"files_changed": 1,
|
||||
"hash": "cc31bfe",
|
||||
"message": "auto-save 2026-05-12 16:11 (~1)",
|
||||
"ts": "2026-05-12T16:11:20+08:00",
|
||||
"type": "commit"
|
||||
},
|
||||
{
|
||||
"files_changed": 4,
|
||||
"hash": "35b3278",
|
||||
@@ -3358,6 +3344,19 @@
|
||||
"type": "session-heartbeat",
|
||||
"message": "Claude 会话活跃 · 最近命令:claude · 3 项未提交变更 · 最近提交:auto-save 2026-05-14 05:38 (~3)",
|
||||
"files_changed": 3
|
||||
},
|
||||
{
|
||||
"ts": "2026-05-14T05:43:54+08:00",
|
||||
"type": "commit",
|
||||
"message": "auto-save 2026-05-14 05:43 (~3)",
|
||||
"hash": "1b3148d",
|
||||
"files_changed": 3
|
||||
},
|
||||
{
|
||||
"ts": "2026-05-13T21:48:51Z",
|
||||
"type": "session-heartbeat",
|
||||
"message": "Codex 会话活跃 · 最近命令:codex · 2 项未提交变更 · 最近提交:auto-save 2026-05-14 05:43 (~3)",
|
||||
"files_changed": 2
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -58,7 +58,7 @@ const LIGHTBOX_TABS: Array<{ key: LightboxTab; label: string }> = [
|
||||
|
||||
export function FrameLightbox({ jobId, frames, activeIndex, selected, onClose, onChange, onToggleSelect, onJobUpdate, onSwitchPanel, onCopyImage, embedded = false }: Props) {
|
||||
const [describing, setDescribing] = useState(false)
|
||||
const [cleaning, setCleaning] = useState(false)
|
||||
const [cleaningFrameIds, setCleaningFrameIds] = useState<Set<number>>(new Set())
|
||||
const [batchCleaning, setBatchCleaning] = useState(false)
|
||||
const [batchCleanupProgress, setBatchCleanupProgress] = useState<{ done: number; total: number; failed: number } | null>(null)
|
||||
const [applying, setApplying] = useState(false)
|
||||
@@ -83,7 +83,9 @@ export function FrameLightbox({ jobId, frames, activeIndex, selected, onClose, o
|
||||
const [draftRegion, setDraftRegion] = useState<Region | null>(null) // 当前正在拖的
|
||||
const [dragStart, setDragStart] = useState<{ x: number; y: number } | null>(null)
|
||||
const imgWrapRef = useRef<HTMLDivElement>(null)
|
||||
const activeIndexRef = useRef<number | null>(activeIndex)
|
||||
useEffect(() => setMounted(true), [])
|
||||
useEffect(() => { activeIndexRef.current = activeIndex }, [activeIndex])
|
||||
|
||||
// 切换分镜时清空选区
|
||||
useEffect(() => {
|
||||
@@ -116,6 +118,7 @@ export function FrameLightbox({ jobId, frames, activeIndex, selected, onClose, o
|
||||
const elements = f.elements ?? []
|
||||
const hasCleaned = !!f.cleaned_url
|
||||
const latestSceneAsset = f.scene_assets?.[f.scene_assets.length - 1] ?? null
|
||||
const isCleaningCurrentFrame = cleaningFrameIds.has(f.index)
|
||||
const cleanedFrameCount = frames.filter((frame) => frame.cleaned_applied || frame.cleaned_url).length
|
||||
const pendingCleanFrames = frames.filter((frame) => !frame.cleaned_applied && !frame.cleaned_url)
|
||||
const selectedFrameIndices = Array.from(selected).sort((a, b) => a - b)
|
||||
@@ -140,22 +143,30 @@ export function FrameLightbox({ jobId, frames, activeIndex, selected, onClose, o
|
||||
}
|
||||
|
||||
const handleCleanup = async (useRegions = false) => {
|
||||
setCleaning(true)
|
||||
const frameIdx = f.index
|
||||
const usable = useRegions ? regions.filter((r) => r.w >= 0.03 && r.h >= 0.03) : null
|
||||
setCleaningFrameIds((prev) => new Set(prev).add(frameIdx))
|
||||
try {
|
||||
const usable = useRegions ? regions.filter((r) => r.w >= 0.03 && r.h >= 0.03) : null
|
||||
const updated = await cleanupFrame(jobId, f.index, usable && usable.length > 0 ? usable : null)
|
||||
const updated = await cleanupFrame(jobId, frameIdx, usable && usable.length > 0 ? usable : null)
|
||||
onJobUpdate?.(updated)
|
||||
toast.success(`分镜 ${f.index + 1} 清洗完成${usable && usable.length > 0 ? `(${usable.length} 个区域)` : ""}`)
|
||||
if (useRegions) { setCropMode(false); setRegions([]); setDraftRegion(null) }
|
||||
toast.success(`分镜 ${frameIdx + 1} 清洗完成${usable && usable.length > 0 ? `(${usable.length} 个区域)` : ""}`)
|
||||
if (useRegions && activeIndexRef.current === frameIdx) {
|
||||
setCropMode(false); setRegions([]); setDraftRegion(null)
|
||||
}
|
||||
} catch (e) {
|
||||
toast.error("清洗失败:" + (e instanceof Error ? e.message : String(e)))
|
||||
} finally {
|
||||
setCleaning(false)
|
||||
setCleaningFrameIds((prev) => {
|
||||
const next = new Set(prev)
|
||||
next.delete(frameIdx)
|
||||
return next
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
const handleCleanupAllFrames = async () => {
|
||||
const targets = pendingCleanFrames.length > 0 ? pendingCleanFrames : frames
|
||||
const targets = (pendingCleanFrames.length > 0 ? pendingCleanFrames : frames)
|
||||
.filter((frame) => !cleaningFrameIds.has(frame.index))
|
||||
if (targets.length === 0) return
|
||||
setBatchCleaning(true)
|
||||
setBatchCleanupProgress({ done: 0, total: targets.length, failed: 0 })
|
||||
@@ -502,7 +513,7 @@ export function FrameLightbox({ jobId, frames, activeIndex, selected, onClose, o
|
||||
<button
|
||||
type="button"
|
||||
onClick={handleCleanupAllFrames}
|
||||
disabled={batchCleaning || cleaning || cropMode || frames.length === 0}
|
||||
disabled={batchCleaning || cropMode || frames.length === 0}
|
||||
className="w-full rounded-md bg-cyan-500/75 px-2 py-1.5 text-[11px] font-medium text-white transition hover:bg-cyan-400 disabled:cursor-wait disabled:opacity-45 inline-flex items-center justify-center gap-1.5"
|
||||
title="自动清洗所有未处理关键帧;不满意的帧再手工框选清洗"
|
||||
>
|
||||
@@ -526,12 +537,12 @@ export function FrameLightbox({ jobId, frames, activeIndex, selected, onClose, o
|
||||
<div className="flex items-center gap-1">
|
||||
<button
|
||||
onClick={() => handleCleanup(true)}
|
||||
disabled={cleaning || batchCleaning || regions.length === 0}
|
||||
disabled={isCleaningCurrentFrame || batchCleaning || regions.length === 0}
|
||||
className="flex-1 px-1.5 py-1.5 rounded-md text-[10.5px] font-medium inline-flex items-center justify-center gap-1 transition bg-cyan-500 hover:bg-cyan-400 text-white disabled:opacity-40 disabled:cursor-not-allowed"
|
||||
title="批量清洗所有框内"
|
||||
>
|
||||
{cleaning ? <Loader2 className="h-3 w-3 animate-spin" /> : <Sparkle className="h-3 w-3" />}
|
||||
{cleaning ? "去掉中" : `去掉${regions.length > 1 ? ` ${regions.length}` : ""}`}
|
||||
{isCleaningCurrentFrame ? <Loader2 className="h-3 w-3 animate-spin" /> : <Sparkle className="h-3 w-3" />}
|
||||
{isCleaningCurrentFrame ? "去掉中" : `去掉${regions.length > 1 ? ` ${regions.length}` : ""}`}
|
||||
</button>
|
||||
<button
|
||||
onClick={() => setRegions((prev) => prev.slice(0, -1))}
|
||||
@@ -599,12 +610,12 @@ export function FrameLightbox({ jobId, frames, activeIndex, selected, onClose, o
|
||||
{/* 清洗按钮(全图) */}
|
||||
<button
|
||||
onClick={() => handleCleanup(false)}
|
||||
disabled={cleaning || batchCleaning || cropMode}
|
||||
disabled={isCleaningCurrentFrame || batchCleaning || cropMode}
|
||||
className="w-full px-3 py-1.5 rounded-md text-[11.5px] font-medium inline-flex items-center justify-center gap-1.5 transition bg-gradient-to-r from-cyan-500/80 to-emerald-500/80 hover:from-cyan-500 hover:to-emerald-500 text-white disabled:opacity-40 disabled:cursor-not-allowed"
|
||||
title="清掉水印 / @用户名 / 字幕 / 平台 logo"
|
||||
>
|
||||
{cleaning ? <Loader2 className="h-3.5 w-3.5 animate-spin" /> : <Sparkle className="h-3.5 w-3.5" />}
|
||||
{cleaning ? "清洗中…(5-15 秒)" : hasCleaned ? "重新清洗" : f.cleaned_applied ? "再次清洗" : "清洗水印"}
|
||||
{isCleaningCurrentFrame ? <Loader2 className="h-3.5 w-3.5 animate-spin" /> : <Sparkle className="h-3.5 w-3.5" />}
|
||||
{isCleaningCurrentFrame ? "清洗中…(5-15 秒)" : hasCleaned ? "重新清洗" : f.cleaned_applied ? "再次清洗" : "清洗水印"}
|
||||
</button>
|
||||
</>
|
||||
)}
|
||||
@@ -651,7 +662,7 @@ export function FrameLightbox({ jobId, frames, activeIndex, selected, onClose, o
|
||||
<button
|
||||
type="button"
|
||||
onClick={handleGenerateSceneAsset}
|
||||
disabled={sceneGenerating || cleaning || batchCleaning}
|
||||
disabled={sceneGenerating || isCleaningCurrentFrame || batchCleaning}
|
||||
className="w-full rounded-md bg-emerald-500/65 px-2 py-1.5 text-[11px] font-medium text-white transition hover:bg-emerald-400 disabled:cursor-wait disabled:opacity-45 inline-flex items-center justify-center gap-1"
|
||||
title="生成一张去水印、高清增强后的场景参考图"
|
||||
>
|
||||
|
||||
Reference in New Issue
Block a user