import { useState } from 'react' import toast from 'react-hot-toast' import { X } from 'lucide-react' import { toolsAPI } from '../api/tools' import { libraryAPI } from '../api/library' import type { BackgroundTask, TaskItem } from '../api/tasks' const kindLabels: Record = { organize: '整理 / 重命名', scan: '入库扫描', scrape: '刮削', } // ItemRetryDialog lets the operator manually re-handle a single failed item. // It pre-fills the values captured from the failed task so retrying is // reproducible, while still allowing overrides before re-running. export function ItemRetryDialog({ task, item, onClose, }: { task: BackgroundTask item: TaskItem onClose: () => void }) { const [sourcePath, setSourcePath] = useState(item.source || task.source_path || '') const [destPath, setDestPath] = useState(item.dest_path || task.dest_path || '') const [transferMode, setTransferMode] = useState('hardlink') const [scanAfter, setScanAfter] = useState(true) const [scrapeAfter, setScrapeAfter] = useState(true) const [busy, setBusy] = useState(false) const run = async () => { setBusy(true) try { if (item.kind === 'organize') { if (!sourcePath.trim()) { toast.error('整理需要来源路径') return } await toolsAPI.organizeDirectory({ source_path: sourcePath.trim(), dest_path: destPath.trim() || undefined, transfer_mode: transferMode, scan_after: scanAfter, scrape_after: scanAfter && scrapeAfter, }) toast.success(`已重新整理:${item.name}`) } else if (item.kind === 'scan' && item.library_id) { await libraryAPI.scan(item.library_id) toast.success(`已重新入库:${item.name}`) } else if (item.kind === 'scrape' && item.library_id) { await libraryAPI.scrape(item.library_id, { episode_artwork: true, refresh_matched: true, }) toast.success(`已重新刮削:${item.name}`) } else { toast.error(`无法处理该类型条目(${item.kind})`) return } onClose() } catch (err: unknown) { toast.error((err as { response?: { data?: { error?: string } } })?.response?.data?.error ?? '处理失败') } finally { setBusy(false) } } return (
e.stopPropagation()} >

手动处理失败条目

{item.name} · {kindLabels[item.kind] ?? item.kind}

{item.error && (
{item.error}
)}
{item.kind === 'organize' && ( <>
)} {item.kind === 'scan' && (

将重新扫描媒体库「{item.name}」以入库。完成后会自动触发刮削(如已启用)。

)} {item.kind === 'scrape' && (

将重新刮削媒体库「{item.name}」。会重试上次未匹配的条目并刷新元数据。

)}
) }