From 32bf49a1480a1de045edabc4263e896850457458 Mon Sep 17 00:00:00 2001
From: root
Date: Wed, 7 Oct 2026 01:48:20 +0800
Subject: [PATCH 1/4] =?UTF-8?q?=E6=96=87=E6=A1=88(=E6=96=87=E4=BB=B6?=
=?UTF-8?q?=E7=AE=A1=E7=90=86):=E6=8C=89=20human-copy=20=E9=87=8D=E5=86=99?=
=?UTF-8?q?=E5=AF=B9=E8=AF=9D=E6=A1=86=E3=80=81=E7=8A=B6=E6=80=81=E3=80=81?=
=?UTF-8?q?=E8=8F=9C=E5=8D=95=E4=B8=8E=E6=8F=90=E7=A4=BA?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
- 永久删除的说明改成实际开关 FILES_ALLOW_PERMANENT_DELETE,去掉「在设置里开启」的错误说法
- 去掉「待处理」「仅 TMDB」「目录根」等旧称,收录版本退回状态写「需处理」
- 删除、移动/复制、重命名、刮削、刷新元数据对话框去掉复述界面的说明
- 加载与进行中文字统一带省略号;Toast 只写结果
Co-Authored-By: Claude Opus 5.5
Claude-Session: https://claude.ai/code/session_01Cxwgnn2pbzQ7rXv3rq7fei
---
apps/web/app/components/files/dialogs.tsx | 95 +++++++++----------
apps/web/app/components/files/dir-tree.tsx | 6 +-
.../app/components/files/directory-dialog.tsx | 22 +++--
apps/web/app/components/files/file-detail.tsx | 10 +-
apps/web/app/components/files/file-list.tsx | 2 +-
.../web/app/components/files/file-preview.tsx | 2 +-
.../app/components/files/identify-panel.tsx | 8 +-
apps/web/app/components/files/mock.ts | 2 +-
apps/web/app/components/files/model.test.ts | 4 +-
apps/web/app/components/files/model.ts | 18 ++--
.../app/components/files/shortcuts-dialog.tsx | 4 +-
11 files changed, 87 insertions(+), 86 deletions(-)
diff --git a/apps/web/app/components/files/dialogs.tsx b/apps/web/app/components/files/dialogs.tsx
index 643bca6b..f9398f73 100644
--- a/apps/web/app/components/files/dialogs.tsx
+++ b/apps/web/app/components/files/dialogs.tsx
@@ -145,7 +145,7 @@ export function UploadButton({ root, path }: { root: FileRoot; path: string }) {
setBusy(null);
if (input.current) input.current.value = "";
if (ok) toast.success(`已上传 ${ok} 个文件到 ${displayPath(root, path)}`);
- if (failed.length) toast.error(`${failed.length} 个文件没有上传`, { description: failed.join("\n") });
+ if (failed.length) toast.error(`${failed.length} 个文件上传失败`, { description: failed.join("\n") });
};
return (
@@ -190,7 +190,7 @@ export function MkdirDialog({
onOpenChange(false);
onCreated?.(r.path);
},
- onError: (e) => setErr(filesErrorReason(e) === "exists" ? "同名项已存在" : filesErrorText(e)),
+ onError: (e) => setErr(filesErrorReason(e) === "exists" ? "同名已存在" : filesErrorText(e)),
},
);
};
@@ -232,13 +232,13 @@ export function MkdirDialog({
// ─── 重命名 ─────────────────────────────────────────────────────
const SUGGEST_REASON: Record = {
- identity_uncertain: "识别不可信,没有推荐名",
+ identity_uncertain: "认不准作品,没有推荐名",
};
const TEMPLATE_SOURCE: Record = {
entity: "作品覆盖",
root: "媒体库目录",
global: "全局",
- override: "覆写",
+ override: "保留原文件名",
};
function suggestReasonText(r: string | null): string {
@@ -418,17 +418,17 @@ export function RenameDialog({
{suggest.isPending && !suggested ? (
- 取推荐名…
+ 生成推荐名…
) : suggest.error ? (
-
{filesErrorText(suggest.error, "取推荐名失败")}
+
{filesErrorText(suggest.error, "生成推荐名失败")}
) : suggested && !suggested.name ? (
{suggestReasonText(suggested.reason)}
) : suggested?.name ? (
<>
{suggested.name === entry.name
- ? "当前名称与命名模板一致"
+ ? "已符合命名模板"
: usingSuggestion
? "已填入推荐名"
: `推荐名:${suggested.name}`}
@@ -460,17 +460,17 @@ export function RenameDialog({
{!isDir ? (
- 同名附属文件一起改
- 主干相同的字幕、NFO、图片
+ 附属文件一起改名
+ 主文件名相同的字幕、NFO 和图片
-
+
) : null}
{changed && !problem && !taken ? (
{preview.isPending ? (
- 预览中
+ 预览中…
) : null}
{pvErr ?
{filesErrorText(pvErr)} : null}
@@ -487,10 +487,10 @@ export function RenameDialog({
))}
{pv.assetLocations > 0 ? (
-
同步 {pv.assetLocations} 条文件位置,写一条整理记录。
+
会同步 {pv.assetLocations} 条文件位置,并写一条整理记录。
) : null}
{pv.bindings.length > 0 ? (
-
这是作品或季的绑定目录。改名后旧绑定标为已替代,之后整理用新目录。
+
这是作品或季的绑定目录。改名后旧绑定作废,之后整理用新目录。
) : null}
>
) : null}
@@ -570,11 +570,11 @@ export function TransferDialog({
const ok = r.executed?.succeeded.length ?? 0;
const failed = r.executed?.failed ?? [];
const recordId = r.executed?.recordId;
- const msg = `${mode === "move" ? "已移动" : "已复制"} ${ok} 项${failed.length ? `,${failed.length} 项失败` : ""}`;
+ const msg = `${mode === "move" ? "已移动" : "已复制"} ${ok} 项${failed.length ? `,${failed.length} 项失败` : ""}`;
(failed.length ? toast.warning : toast.success)(msg, {
description: failed
.slice(0, 3)
- .map((f) => `${baseName(f.path)}:${f.message}`)
+ .map((f) => `${baseName(f.path)}:${f.message}`)
.join("\n"),
action: recordId
? { label: "整理记录", onClick: () => window.location.assign(`/console/organize/${recordId}`) }
@@ -599,8 +599,7 @@ export function TransferDialog({
{mode === "move" ? "移动到…" : "复制到…"}
- {items.length === 1 ? baseName(items[0]?.path ?? "") : `${items.length} 项`} · 先预览再执行。跨卷移动按复制
- → 核验 → 删源。
+ {items.length === 1 ? baseName(items[0]?.path ?? "") : `${items.length} 项`} · 跨卷移动会先复制、核验,再删除源文件。
@@ -637,7 +636,7 @@ export function TransferDialog({
className="max-h-72 md:max-h-96"
/>
- 可选可写的媒体库目录或 Alist 存储;本机和 Alist 之间会上传或下载。
+ 目标可以是可写的媒体库目录或 Alist 存储。
@@ -647,11 +646,11 @@ export function TransferDialog({
{displayPath(targetRoot, target.path)}
) : (
-
在左侧选择目标目录。
+
选择目标目录。
)}
{dry.isPending ? (
- 生成预览
+ 生成预览…
) : null}
{err ?
{err} : null}
@@ -666,15 +665,15 @@ export function TransferDialog({
{plan.freeBytes != null ? ` · 剩余 ${formatBytes(plan.freeBytes, 1)}` : ""}
{conflicts.length ? (
-
冲突 {conflicts.length}(跳过,不覆盖)
+
{conflicts.length} 项目标已存在 · 跳过
) : null}
{plan.pairs.some((p) => p.registered) ? (
-
含已整理文件,执行后同步位置
+
含已整理文件,会同步文件位置
) : null}
{hnrBlocked ? (
- {plan.hnrBlocks.length} 项做种中且 H&R 未满足,不能移动。改用复制,或等 H&R 满足后再移动。
+ {plan.hnrBlocks.length} 项做种中且 H&R 未满足,不能移动。可以改用复制。
) : (
@@ -1230,7 +1229,7 @@ export function ScrapeDialog({ items, root, onClose }: { items: FileEntry[]; roo
认不准作品,选一个再刮削
{choices.map((c) => (
-
{c.path || "目录根"}
+
{c.path || "(登记目录本身)"}
加载中… : null}
{skipped.map((x) => (
- {x.path || "目录根"}:{SKIP_TEXT[x.reason] ?? x.reason}
+ {x.path || "(登记目录本身)"}:{SKIP_TEXT[x.reason] ?? x.reason}
))}
diff --git a/apps/web/app/components/files/dir-tree.tsx b/apps/web/app/components/files/dir-tree.tsx
index 2e35ec99..180e9977 100644
--- a/apps/web/app/components/files/dir-tree.tsx
+++ b/apps/web/app/components/files/dir-tree.tsx
@@ -230,7 +230,7 @@ function Children({
className="flex items-center gap-2 py-1 text-meta text-muted-foreground"
style={{ paddingLeft: depth * 14 + 28 }}
>
- 加载中
+ 加载中…
);
if (q.error)
@@ -242,7 +242,7 @@ function Children({
if (!dirs.length)
return (
- 无子目录
+ 没有子目录
);
return (
@@ -293,7 +293,7 @@ function Children({
{paginate && dirs.length > 0 ? : null}
{q.data?.truncated ? (
- 子目录过多,只列出一部分
+ 子目录太多,只列出一部分
) : null}
diff --git a/apps/web/app/components/files/directory-dialog.tsx b/apps/web/app/components/files/directory-dialog.tsx
index 779269a7..74cfdb66 100644
--- a/apps/web/app/components/files/directory-dialog.tsx
+++ b/apps/web/app/components/files/directory-dialog.tsx
@@ -43,8 +43,10 @@ export function DirectoryDialog({
) : null}
{it.skipped === "below_min_size" ? (
- 低于最小体积,没有查候选。
+ 文件小于最小体积,没有查找候选。
) : null}
{it.warnings.map((w) => (
@@ -132,7 +132,7 @@ export function IdentifyPanel({
{c.year ? ` (${c.year})` : ""}
置信 {LEVEL[c.level]?.label ?? c.level}
- {c.mediaEntityId ? null : 仅 TMDB}
+ {c.mediaEntityId ? null : 不在媒体库}
{[
diff --git a/apps/web/app/components/files/mock.ts b/apps/web/app/components/files/mock.ts
index 635ea41d..71711b00 100644
--- a/apps/web/app/components/files/mock.ts
+++ b/apps/web/app/components/files/mock.ts
@@ -951,7 +951,7 @@ function organize(body: {
recordId: body.dryRun || conflict ? null : `rec-${++seq}`,
taskId: body.dryRun || conflict ? null : `task-${seq}`,
warnings: items.some((x) => x.season != null) && !tv ? ["电影不使用季/集覆写"] : [],
- error: conflict ? { code: "plan_blocked", message: "目标已存在同名文件,按「交给待处理」整组不执行" } : null,
+ error: conflict ? { code: "plan_blocked", message: "目标已存在同名文件,整组不执行" } : null,
action: body.action,
entity: items.some((x) => x.external)
? { provider: "tmdb", externalId: "95396", created: true, title: "人生切割术" }
diff --git a/apps/web/app/components/files/model.test.ts b/apps/web/app/components/files/model.test.ts
index 9d7c2112..20b60395 100644
--- a/apps/web/app/components/files/model.test.ts
+++ b/apps/web/app/components/files/model.test.ts
@@ -312,7 +312,7 @@ describe("transferTargetProblem(U13)", () => {
];
it("目标就是源所在目录 / 在源目录之内时拦下", () => {
expect(transferTargetProblem(items, { root: "dl", path: "a" })).toMatch(/已在这个目录里/);
- expect(transferTargetProblem(items, { root: "dl", path: "pack/sub" })).toMatch(/目标在源目录之内/);
+ expect(transferTargetProblem(items, { root: "dl", path: "pack/sub" })).toMatch(/目标不能是 pack 或它的子目录/);
expect(transferTargetProblem([{ root: "dl", path: "x.mkv" }], { root: "dl", path: "" })).toMatch(/已在/);
});
it("其他目录、其他根放行", () => {
@@ -370,7 +370,7 @@ describe("识别远端回填(S-7)", () => {
{ ...other, taskId: "run-1", status: "failed", error: "超时" } as never,
);
expect(f.remoteTaskId).toBeNull();
- expect(f.items[0]?.warnings).toEqual(["远端查询失败,只有本地结果:超时"]);
+ expect(f.items[0]?.warnings).toEqual(["TMDB 查询失败,只显示本地结果:超时"]);
});
});
diff --git a/apps/web/app/components/files/model.ts b/apps/web/app/components/files/model.ts
index 81e44dd6..0e44c95d 100644
--- a/apps/web/app/components/files/model.ts
+++ b/apps/web/app/components/files/model.ts
@@ -15,11 +15,11 @@ export type StatusView = { label: string; tone: StatusTone; hint?: string };
/** 行主状态 → 徽标(文字必带,不只靠颜色) */
export function entryStatusView(e: Pick): StatusView | null {
- if (e.escape) return { label: "链接越界", tone: "destructive", hint: "符号链接指向登记目录之外,所有操作已禁用" };
+ if (e.escape) return { label: "链接越界", tone: "destructive", hint: "符号链接指向登记目录之外,不能操作" };
const s: FileStatus = e.status;
switch (s) {
case "temp":
- return { label: "未完成", tone: "neutral", hint: "下载器或整理过程中的未完成文件" };
+ return { label: "未完成", tone: "neutral", hint: "下载或整理还没完成的临时文件" };
case "downloading":
return {
label: e.download?.progress != null ? `下载中 ${Math.floor(e.download.progress * 100)}%` : "下载中",
@@ -44,7 +44,7 @@ export const FILTER_CHIPS = [
{ value: "unidentified", label: "未识别" },
{ value: "registered", label: "已整理" },
{ value: "downloading", label: "下载中" },
- { value: "temp", label: "未完成下载" },
+ { value: "temp", label: "未完成" },
] as const;
export const SORT_OPTIONS = [
@@ -100,7 +100,7 @@ export function opDisabledReason(op: FileOp, e: FileEntry, root: Pick(items: T[], max: number): (T | null)[] {
export function nameProblem(name: string): string | null {
const n = name.trim();
if (!n) return "名称不能为空";
- if (n === "." || n === "..") return "不能用 . 或 ..";
+ if (n === "." || n === "..") return "名称不能是 . 或 ..";
if (/[/\\]/.test(n)) return "名称不能包含 / 或 \\";
// biome-ignore lint/suspicious/noControlCharactersInRegex: 过滤控制字符
if (/[\u0000-\u001f]/.test(n)) return "名称不能包含控制字符";
- if (n.length > 255) return "名称过长";
+ if (n.length > 255) return "名称不能超过 255 个字符";
return null;
}
@@ -318,7 +318,7 @@ export function deleteBlockText(b: string | null): { text: string; soft: boolean
case "needs_unbind":
return { text: "是作品或季的绑定目录,勾选「解除路径绑定」后才能删除", soft: true };
case "root_unavailable":
- return { text: "目录离线,不能确认文件状态", soft: false };
+ return { text: "目录离线,无法确认文件状态", soft: false };
case "not_found":
return { text: "文件已不存在", soft: false };
case "escape":
@@ -557,7 +557,7 @@ const REMOTE_PENDING_WARNING = /^远端候选在后台查询/;
export function applyIdentifyCompleted(r: FilesIdentifyResult, p: IdentifyCompletedPayload): FilesIdentifyResult {
if (!r.remoteTaskId || p.taskId !== r.remoteTaskId) return r;
if (p.status === "failed") {
- const note = `远端查询失败,只有本地结果${p.error ? `:${p.error.slice(0, 200)}` : ""}`;
+ const note = `TMDB 查询失败,只显示本地结果${p.error ? `:${p.error.slice(0, 200)}` : ""}`;
return {
...r,
remoteTaskId: null,
diff --git a/apps/web/app/components/files/shortcuts-dialog.tsx b/apps/web/app/components/files/shortcuts-dialog.tsx
index 2d845dd7..3a19a7a8 100644
--- a/apps/web/app/components/files/shortcuts-dialog.tsx
+++ b/apps/web/app/components/files/shortcuts-dialog.tsx
@@ -9,11 +9,11 @@ const KEYS: [string, string][] = [
["Ctrl/⌘+A", "全选"],
["Ctrl/⌘+Enter", "整理选中项"],
["F2", "重命名"],
- ["Del", "删除(先进回收站)"],
+ ["Del", "删除(移入回收站)"],
["/", "搜索当前目录"],
["Esc", "清除选择"],
["Shift+F10 / 菜单键", "打开操作菜单"],
- ["拖到目录", "移动到(按住 Alt 复制),先出预览"],
+ ["拖到目录", "移动(按住 Alt 复制),先预览"],
["?", "显示这张表"],
];
From a15d81360bdc8a93f1ba39bfd884932bffb3e68c Mon Sep 17 00:00:00 2001
From: root
Date: Wed, 7 Oct 2026 01:49:25 +0800
Subject: [PATCH 2/4] =?UTF-8?q?=E6=96=87=E6=A1=88(=E6=95=B4=E7=90=86?=
=?UTF-8?q?=E8=AE=B0=E5=BD=95=E4=B8=8E=E9=98=9F=E5=88=97):=E6=8C=89=20huma?=
=?UTF-8?q?n-copy=20=E9=87=8D=E5=86=99=E9=98=9F=E5=88=97=E9=9D=A2=E6=9D=BF?=
=?UTF-8?q?=E3=80=81=E5=88=A0=E9=99=A4=E7=A1=AE=E8=AE=A4=E3=80=81=E6=95=B4?=
=?UTF-8?q?=E7=90=86=E6=9D=A5=E6=BA=90=E9=80=89=E6=8B=A9?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
- 队列面板与按钮统一叫「队列」,阶段文字去掉「登记媒体库」「NFO / 图片」等重复说明
- 「选择整理策略」改「选择整理来源」(策略是收录策略的词),「来源配置」统一为「整理来源」
- 扫描存量结果只列非零项;失败 Toast 写清是哪个动作失败
Co-Authored-By: Claude Opus 5.5
Claude-Session: https://claude.ai/code/session_01Cxwgnn2pbzQ7rXv3rq7fei
---
.../organize/delete-records-dialog.tsx | 12 ++++----
.../organize/file-source-selection.tsx | 14 ++++-----
.../components/organize/organize-queue.tsx | 30 +++++++++----------
.../organize/organize-scrape-history.tsx | 8 ++---
.../components/organize/queue-model.test.ts | 14 ++++-----
.../app/components/organize/queue-model.ts | 18 +++++------
.../components/organize/record-attention.tsx | 12 ++++----
.../components/organize/source-selection.tsx | 30 +++++++++++++------
8 files changed, 74 insertions(+), 64 deletions(-)
diff --git a/apps/web/app/components/organize/delete-records-dialog.tsx b/apps/web/app/components/organize/delete-records-dialog.tsx
index 4f63aadb..fd78b424 100644
--- a/apps/web/app/components/organize/delete-records-dialog.tsx
+++ b/apps/web/app/components/organize/delete-records-dialog.tsx
@@ -86,7 +86,7 @@ export function DeleteRecordsDialog({
setDst(e.target.checked)} />
同时删除媒体库里的文件
- 整理后放进媒体库的文件,会从媒体库移除。
+ 整理到媒体库目录里的文件。
@@ -127,8 +127,8 @@ function Summary({
src: boolean;
withFiles: boolean;
}) {
- if (error) return {errorMessage(error, "核对失败")}
;
- if (!plan) return {pending ? "正在核对要删的文件…" : null}
;
+ if (error) return {errorMessage(error, "检查失败")}
;
+ if (!plan) return {pending ? "检查要删的文件…" : null}
;
const files = [
plan.sourceFiles ? `${plan.sourceFiles} 个源文件` : null,
plan.targetFiles ? `${plan.targetFiles} 个媒体库文件` : null,
@@ -137,15 +137,15 @@ function Summary({
{files.length ? (
- {files.join("、")}({formatBytes(plan.bytes, 1)})会移入回收站,可以在回收站还原。
+ {files.join("、")}({formatBytes(plan.bytes, 1)})会移入回收站,可以还原。
{plan.assets ? `其中 ${plan.assets} 个是已整理文件,会从媒体库移除。` : ""}
) : (
{withFiles ? "没有找到还在的文件,只删记录。" : "只删记录,文件不动。"}
)}
- {src && plan.sourceFiles ?
下载器里的任务不会删除。
: null}
+ {src && plan.sourceFiles ?
下载器里的任务不受影响。
: null}
{plan.autoRetry ? (
-
{plan.autoRetry} 个下载任务没有别的整理记录了,几分钟后会重新自动整理。
+
{plan.autoRetry} 个下载任务没有别的整理记录了,几分钟后会自动重新整理。
) : null}
);
diff --git a/apps/web/app/components/organize/file-source-selection.tsx b/apps/web/app/components/organize/file-source-selection.tsx
index a51925a1..43eb1941 100644
--- a/apps/web/app/components/organize/file-source-selection.tsx
+++ b/apps/web/app/components/organize/file-source-selection.tsx
@@ -24,7 +24,7 @@ export function FileSourceSelection({
const profile = matches[0];
onSelect(
profile
- ? { ...source, sourceConfigId: profile.id, defaultAction: profile.action, label: `来源 · ${profile.name}` }
+ ? { ...source, sourceConfigId: profile.id, defaultAction: profile.action, label: `整理来源 · ${profile.name}` }
: source,
);
}, [profiles.isSuccess, matches, source, onSelect]);
@@ -32,14 +32,14 @@ export function FileSourceSelection({
))}
{!result ? : null}
- {g.truncated ? 文件过多,预览只列出前一部分。
: null}
+ {g.truncated ? 文件太多,只列出前一部分。
: null}
{!result && nested.length ? (
{nested.map((n) => (
@@ -248,8 +248,8 @@ export function PreviewGroupCard({
排除 {g.excluded.length} 个:
{g.excluded
.slice(0, 6)
- .map((e) => `${baseName(e.source)}(${EXCLUDE_REASON[e.reason] ?? e.reason})`)
- .join(",")}
+ .map((e) => `${baseName(e.source)}(${EXCLUDE_REASON[e.reason] ?? e.reason})`)
+ .join("、")}
{g.excluded.length > 6 ? "…" : ""}
) : null}
diff --git a/apps/web/app/components/organize-wizard/structure-picker.tsx b/apps/web/app/components/organize-wizard/structure-picker.tsx
index 271d9103..30290e9f 100644
--- a/apps/web/app/components/organize-wizard/structure-picker.tsx
+++ b/apps/web/app/components/organize-wizard/structure-picker.tsx
@@ -64,7 +64,7 @@ export function StructurePicker({
/>
) : null}
- {list.error ? 剧集组列表暂时取不到,只能跟随作品。
: null}
+ {list.error ? 读取剧集组失败,只能跟随作品
: null}
);
}
From 058519fa0e16f2f72316f84b6288e291f844eb97 Mon Sep 17 00:00:00 2001
From: root
Date: Wed, 7 Oct 2026 01:52:30 +0800
Subject: [PATCH 4/4] =?UTF-8?q?=E6=96=87=E6=A1=88:=E6=A0=BC=E5=BC=8F?=
=?UTF-8?q?=E5=8C=96=E6=9C=AC=E8=BD=AE=E6=94=B9=E5=8A=A8=E7=9A=84=E6=96=87?=
=?UTF-8?q?=E4=BB=B6?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Co-Authored-By: Claude Opus 5.5
Claude-Session: https://claude.ai/code/session_01Cxwgnn2pbzQ7rXv3rq7fei
---
apps/web/app/components/files/dialogs.tsx | 31 +++++++------------
.../organize-wizard/organize-wizard.tsx | 8 ++---
.../organize/file-source-selection.tsx | 4 +--
.../components/organize/organize-queue.tsx | 4 +--
.../components/organize/source-selection.tsx | 4 +--
5 files changed, 16 insertions(+), 35 deletions(-)
diff --git a/apps/web/app/components/files/dialogs.tsx b/apps/web/app/components/files/dialogs.tsx
index f9398f73..59525b02 100644
--- a/apps/web/app/components/files/dialogs.tsx
+++ b/apps/web/app/components/files/dialogs.tsx
@@ -599,7 +599,8 @@ export function TransferDialog({
{mode === "move" ? "移动到…" : "复制到…"}
- {items.length === 1 ? baseName(items[0]?.path ?? "") : `${items.length} 项`} · 跨卷移动会先复制、核验,再删除源文件。
+ {items.length === 1 ? baseName(items[0]?.path ?? "") : `${items.length} 项`} ·
+ 跨卷移动会先复制、核验,再删除源文件。
@@ -635,9 +636,7 @@ export function TransferDialog({
}}
className="max-h-72 md:max-h-96"
/>
-
- 目标可以是可写的媒体库目录或 Alist 存储。
-
+
目标可以是可写的媒体库目录或 Alist 存储。
{target && targetRoot ? (
@@ -687,9 +686,7 @@ export function TransferDialog({
) : null}
- {plan.truncated ? (
-
文件太多,只列出前一部分。执行时全部处理。
- ) : null}
+ {plan.truncated ?
文件太多,只列出前一部分。执行时全部处理。 : null}
{plan.pairs.map((p) => {
const sr = rootById.get(p.source.root);
@@ -875,9 +872,7 @@ export function DeleteDialog({
{d.hnr === "satisfied" ? "已满足" : d.hnr === "unsatisfied" ? "未满足" : "未知"}
))}
- {c.assets.length ? (
- 含 {c.assets.length} 个已整理文件
- ) : null}
+ {c.assets.length ? 含 {c.assets.length} 个已整理文件
: null}
{c.bindings.map((bd) => (
路径绑定:{bd.title}
@@ -907,9 +902,7 @@ export function DeleteDialog({
setUnbind(e.target.checked)} />
解除路径绑定
-
- 绑定作废,这个作品下次整理时重新选目录。
-
+ 绑定作废,这个作品下次整理时重新选目录。
) : null}
@@ -943,7 +936,9 @@ export function DeleteDialog({
永久删除
- {isAdmin ? "无法恢复。部署时设置 FILES_ALLOW_PERMANENT_DELETE=true 才能用。" : "只有管理员会话可用。"}
+ {isAdmin
+ ? "无法恢复。部署时设置 FILES_ALLOW_PERMANENT_DELETE=true 才能用。"
+ : "只有管理员会话可用。"}
@@ -1051,9 +1046,7 @@ export function RefreshMetadataDialog({ items, onClose }: { items: FileEntry[];
onSuccess: (r) => {
setResult(r);
const skipped = r.skipped.length ? `,${r.skipped.length} 个跳过` : "";
- (r.skipped.length ? toast.warning : toast.success)(
- `已提交 ${r.submitted.length} 个作品${skipped}`,
- );
+ (r.skipped.length ? toast.warning : toast.success)(`已提交 ${r.submitted.length} 个作品${skipped}`);
},
onError: (e) => toast.error(filesErrorText(e, "提交失败")),
},
@@ -1177,9 +1170,7 @@ export function ScrapeDialog({ items, root, onClose }: { items: FileEntry[]; roo
刮削{single ? ` · ${single.name}` : ` · ${items.length} 项`}
-
- 按路径识别作品,在文件所在目录写 NFO 和图片。没整理过的文件也能刮削。
-
+ 按路径识别作品,在文件所在目录写 NFO 和图片。没整理过的文件也能刮削。
{!started ? (
diff --git a/apps/web/app/components/organize-wizard/organize-wizard.tsx b/apps/web/app/components/organize-wizard/organize-wizard.tsx
index 761663ca..910add78 100644
--- a/apps/web/app/components/organize-wizard/organize-wizard.tsx
+++ b/apps/web/app/components/organize-wizard/organize-wizard.tsx
@@ -398,9 +398,7 @@ export function OrganizeWizard({ source, onClose }: { source: OrganizeSource; on
{baseName(r.path)}
-
- {r.entity ? entityLabel(r.entity) : "未识别"}
-
+
{r.entity ? entityLabel(r.entity) : "未识别"}
{rowProblem(r) ?
{rowProblem(r)}
: null}
),
@@ -711,9 +709,7 @@ export function OrganizeWizard({ source, onClose }: { source: OrganizeSource; on
整理后刮削
-
- 整理完成后写 NFO 和图片
-
+ 整理完成后写 NFO 和图片
{profiles.isPending ? "读取整理来源…" : "选择整理来源"}
-
- 整理时沿用所选整理来源的整理方式、目标目录和分类。
-
+ 整理时沿用所选整理来源的整理方式、目标目录和分类。
{profiles.isPending ? (
diff --git a/apps/web/app/components/organize/organize-queue.tsx b/apps/web/app/components/organize/organize-queue.tsx
index 03c86f74..de8d04a1 100644
--- a/apps/web/app/components/organize/organize-queue.tsx
+++ b/apps/web/app/components/organize/organize-queue.tsx
@@ -98,9 +98,7 @@ function QueueItem({ run }: { run: EngineRun }) {
来源
{source ??
- (detail.isFetching || download.isFetching || recordQuery.isFetching
- ? "加载中…"
- : "读取不到来源")}
+ (detail.isFetching || download.isFetching || recordQuery.isFetching ? "加载中…" : "读取不到来源")}
diff --git a/apps/web/app/components/organize/source-selection.tsx b/apps/web/app/components/organize/source-selection.tsx
index 72921db3..c2363a3d 100644
--- a/apps/web/app/components/organize/source-selection.tsx
+++ b/apps/web/app/components/organize/source-selection.tsx
@@ -85,9 +85,7 @@ export function SourceSelection({
onSuccess: (r) =>
r.items.length
? onSelect(stockWizardSource(p, r))
- : toast.info(
- `没有可整理的文件${stockNotes(r)}`,
- ),
+ : toast.info(`没有可整理的文件${stockNotes(r)}`),
onError: (e) => toast.error(filesErrorText(e, "扫描存量失败")),
},
)