fix(web): make unavailable organize targets explicit
This commit is contained in:
1 parent
407cb7eb36
commit
1475ffcce4
2 files changed
+39
-8
No files matched your search
@@ -321,7 +321,19 @@ export function OrganizeWizard({ source, onClose }: { source: OrganizeSource; on
|
|||||||
Number.isFinite(Number(minMb)) &&
|
Number.isFinite(Number(minMb)) &&
|
||||||
Number(minMb) >= 0 &&
|
Number(minMb) >= 0 &&
|
||||||
Number.isSafeInteger(Math.round(Number(minMb) * MIB));
|
Number.isSafeInteger(Math.round(Number(minMb) * MIB));
|
||||||
|
const targetUnavailable =
|
||||||
|
options.target.mode === "root" &&
|
||||||
|
rootsQ.isSuccess &&
|
||||||
|
!roots.some(
|
||||||
|
(r) =>
|
||||||
|
options.target.mode === "root" &&
|
||||||
|
r.id === options.target.rootId &&
|
||||||
|
r.kind === "library" &&
|
||||||
|
r.writable &&
|
||||||
|
r.health !== "offline",
|
||||||
|
);
|
||||||
const canPreview =
|
const canPreview =
|
||||||
|
!targetUnavailable &&
|
||||||
(!needsReview || recoveryConfirmed) &&
|
(!needsReview || recoveryConfirmed) &&
|
||||||
!ambiguous &&
|
!ambiguous &&
|
||||||
!lookupPending &&
|
!lookupPending &&
|
||||||
@@ -548,6 +560,11 @@ export function OrganizeWizard({ source, onClose }: { source: OrganizeSource; on
|
|||||||
批量重新整理使用本次统一设置。要沿用各记录的洗版与文件覆写,逐条打开重新整理。
|
批量重新整理使用本次统一设置。要沿用各记录的洗版与文件覆写,逐条打开重新整理。
|
||||||
</p>
|
</p>
|
||||||
) : null}
|
) : null}
|
||||||
|
{targetUnavailable ? (
|
||||||
|
<p role="alert" className="text-caption text-warning">
|
||||||
|
原目标媒体库不可用,在高级选项中重新选择目标。
|
||||||
|
</p>
|
||||||
|
) : null}
|
||||||
{src.recovery ? (
|
{src.recovery ? (
|
||||||
<div className="space-y-2 text-caption">
|
<div className="space-y-2 text-caption">
|
||||||
<p className="text-muted-foreground">
|
<p className="text-muted-foreground">
|
||||||
@@ -580,7 +597,7 @@ export function OrganizeWizard({ source, onClose }: { source: OrganizeSource; on
|
|||||||
</div>
|
</div>
|
||||||
) : null}
|
) : null}
|
||||||
<details
|
<details
|
||||||
open={advancedOpen || ambiguous || (needsReview && !recoveryConfirmed)}
|
open={advancedOpen || ambiguous || targetUnavailable || (needsReview && !recoveryConfirmed)}
|
||||||
onToggle={(e) => setAdvancedOpen(e.currentTarget.open)}
|
onToggle={(e) => setAdvancedOpen(e.currentTarget.open)}
|
||||||
className="rounded-xl border border-border p-3"
|
className="rounded-xl border border-border p-3"
|
||||||
>
|
>
|
||||||
@@ -769,6 +786,9 @@ export function OrganizeWizard({ source, onClose }: { source: OrganizeSource; on
|
|||||||
value: "auto",
|
value: "auto",
|
||||||
label: profile ? `自动 · ${profile.name}` : "自动 · 按作品类型与已有目录",
|
label: profile ? `自动 · ${profile.name}` : "自动 · 按作品类型与已有目录",
|
||||||
},
|
},
|
||||||
|
...(targetUnavailable
|
||||||
|
? [{ value: targetValue, label: "原媒体库不可用 · 重新选择", disabled: true }]
|
||||||
|
: []),
|
||||||
...libRoots.map((r) => ({ value: r.id, label: r.name })),
|
...libRoots.map((r) => ({ value: r.id, label: r.name })),
|
||||||
{ value: "dir", label: "选择目录…" },
|
{ value: "dir", label: "选择目录…" },
|
||||||
]}
|
]}
|
||||||
@@ -962,7 +982,19 @@ export function OrganizeWizard({ source, onClose }: { source: OrganizeSource; on
|
|||||||
className="min-w-0 space-y-3 border-t border-border p-4 sm:p-5 lg:border-t-0 lg:border-l"
|
className="min-w-0 space-y-3 border-t border-border p-4 sm:p-5 lg:border-t-0 lg:border-l"
|
||||||
aria-label="整理预览"
|
aria-label="整理预览"
|
||||||
>
|
>
|
||||||
<h3 className="text-caption font-medium">整理预览</h3>
|
<div className="flex items-center justify-between gap-2">
|
||||||
|
<h3 className="text-caption font-medium">整理预览</h3>
|
||||||
|
<Button
|
||||||
|
variant="ghost"
|
||||||
|
size="sm"
|
||||||
|
onClick={() => {
|
||||||
|
setAdvancedOpen(true);
|
||||||
|
setPreviewOpen(false);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
修改整理选项
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
{notice ? <p className="text-meta text-warning">{notice}</p> : null}
|
{notice ? <p className="text-meta text-warning">{notice}</p> : null}
|
||||||
{dry.isPending ? (
|
{dry.isPending ? (
|
||||||
<p role="status" className="flex gap-2 text-caption text-muted-foreground">
|
<p role="status" className="flex gap-2 text-caption text-muted-foreground">
|
||||||
|
|||||||
@@ -60,12 +60,11 @@ export function PreviewStatsBar({
|
|||||||
}) {
|
}) {
|
||||||
return (
|
return (
|
||||||
<div className="flex flex-wrap items-center gap-1.5">
|
<div className="flex flex-wrap items-center gap-1.5">
|
||||||
<StatusBadge>
|
<span className="text-meta text-muted-foreground">
|
||||||
{stats.groups} 组 · {stats.files} 个文件
|
{stats.groups} 组 · {stats.files} 个文件 · 可执行 {stats.executable}
|
||||||
</StatusBadge>
|
</span>
|
||||||
<StatusBadge tone={stats.executable ? "success" : "neutral"}>可执行 {stats.executable}</StatusBadge>
|
{stats.conflicts ? <span className="text-meta text-warning">· 冲突 {stats.conflicts}</span> : null}
|
||||||
{stats.conflicts ? <StatusBadge tone="warning">冲突 {stats.conflicts}</StatusBadge> : null}
|
{stats.failed ? <span className="text-meta text-destructive">· 不能执行 {stats.failed}</span> : null}
|
||||||
{stats.failed ? <StatusBadge tone="destructive">不能执行 {stats.failed}</StatusBadge> : null}
|
|
||||||
<div className="ml-auto flex items-center gap-2 text-caption text-muted-foreground">
|
<div className="ml-auto flex items-center gap-2 text-caption text-muted-foreground">
|
||||||
<span aria-hidden>只看问题</span>
|
<span aria-hidden>只看问题</span>
|
||||||
<Switch checked={onlyProblems} onCheckedChange={onOnlyProblems} aria-label="只看问题" />
|
<Switch checked={onlyProblems} onCheckedChange={onOnlyProblems} aria-label="只看问题" />
|
||||||
|
|||||||
Reference in new issue
Block a user