文案(下载):重写下载面板、后台任务、下载盘与手动下载文案
Co-Authored-By: Claude Opus 5.5 <[email protected]> Claude-Session: https://claude.ai/code/session_01Cxwgnn2pbzQ7rXv3rq7fei
This commit is contained in:
1 parent
5aa19a9a9b
commit
3853a65754
7 files changed
+30
-30
No files matched your search
@@ -24,15 +24,15 @@ import { formatDateTime } from "~/lib/utils.ts";
|
|||||||
const TaskPage = cursorPage(Task);
|
const TaskPage = cursorPage(Task);
|
||||||
|
|
||||||
export const TASK_KIND_LABEL: Record<TaskKind, string> = {
|
export const TASK_KIND_LABEL: Record<TaskKind, string> = {
|
||||||
ingestFeed: "抓取 Feed",
|
ingestFeed: "抓取 RSS",
|
||||||
resolveObservation: "识别资源",
|
resolveObservation: "识别资源",
|
||||||
evaluateAcquisition: "评估候选",
|
evaluateAcquisition: "评估资源",
|
||||||
submitDownload: "提交下载",
|
submitDownload: "提交下载",
|
||||||
verifyAndImport: "核验整理",
|
verifyAndImport: "核验整理",
|
||||||
refreshMetadata: "刷新元数据",
|
refreshMetadata: "刷新元数据",
|
||||||
reconcileLibrary: "文件核对",
|
reconcileLibrary: "文件核对",
|
||||||
cleanupDownloadCache: "清理缓存",
|
cleanupDownloadCache: "清理缓存",
|
||||||
resolveDecision: "处理待处理事项",
|
resolveDecision: "处理事项",
|
||||||
agentRun: "智能体运行",
|
agentRun: "智能体运行",
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -40,13 +40,13 @@ export const TASK_STATUS: Record<
|
|||||||
TaskStatus,
|
TaskStatus,
|
||||||
{ label: string; tone: "success" | "warning" | "destructive" | "neutral" }
|
{ label: string; tone: "success" | "warning" | "destructive" | "neutral" }
|
||||||
> = {
|
> = {
|
||||||
pending: { label: "排队", tone: "neutral" },
|
pending: { label: "排队中", tone: "neutral" },
|
||||||
running: { label: "运行中", tone: "neutral" },
|
running: { label: "运行中", tone: "neutral" },
|
||||||
waiting: { label: "等待", tone: "warning" },
|
waiting: { label: "等待", tone: "warning" },
|
||||||
succeeded: { label: "成功", tone: "success" },
|
succeeded: { label: "成功", tone: "success" },
|
||||||
failed: { label: "失败", tone: "destructive" },
|
failed: { label: "失败", tone: "destructive" },
|
||||||
cancelled: { label: "已取消", tone: "neutral" },
|
cancelled: { label: "已取消", tone: "neutral" },
|
||||||
dead: { label: "放弃", tone: "destructive" },
|
dead: { label: "已放弃", tone: "destructive" },
|
||||||
};
|
};
|
||||||
|
|
||||||
export const ACTIVE_TASK: TaskStatus[] = ["pending", "running", "waiting"];
|
export const ACTIVE_TASK: TaskStatus[] = ["pending", "running", "waiting"];
|
||||||
@@ -245,8 +245,8 @@ export function BusinessTasks() {
|
|||||||
loadingMore={list.isFetchingNextPage}
|
loadingMore={list.isFetchingNextPage}
|
||||||
empty={{
|
empty={{
|
||||||
icon: ListTodo,
|
icon: ListTodo,
|
||||||
title: f.active ? "没有符合筛选的任务" : "还没有业务任务",
|
title: f.active ? "没有符合筛选的任务" : "还没有后台任务",
|
||||||
description: f.active ? undefined : "提交下载、核验整理、清理缓存、对账等后台任务会出现在这里。",
|
description: f.active ? undefined : "提交下载、核验整理、清理缓存、文件核对等任务会出现在这里。",
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
<DetailSheet
|
<DetailSheet
|
||||||
@@ -259,7 +259,7 @@ export function BusinessTasks() {
|
|||||||
<>
|
<>
|
||||||
<TaskActions t={open} />
|
<TaskActions t={open} />
|
||||||
<Button asChild size="sm">
|
<Button asChild size="sm">
|
||||||
<Link to={consolePath("tasks", open.id)}>在独立页面打开</Link>
|
<Link to={consolePath("tasks", open.id)}>打开详情页</Link>
|
||||||
</Button>
|
</Button>
|
||||||
</>
|
</>
|
||||||
) : null
|
) : null
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ export function BusinessTimeline({ events, loading }: { events: TimelineEvent[];
|
|||||||
})}
|
})}
|
||||||
</div>
|
</div>
|
||||||
{ongoing.length ? (
|
{ongoing.length ? (
|
||||||
<p className="text-caption text-muted-foreground">当前:{ongoing.map((e) => e.title).join(";")}</p>
|
<p className="text-caption text-muted-foreground">当前:{ongoing.map((e) => e.title).join(";")}</p>
|
||||||
) : null}
|
) : null}
|
||||||
{loading && !events.length ? (
|
{loading && !events.length ? (
|
||||||
<LoadingState rows={3} />
|
<LoadingState rows={3} />
|
||||||
@@ -60,7 +60,7 @@ export function BusinessTimeline({ events, loading }: { events: TimelineEvent[];
|
|||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
{loading && events.length ? (
|
{loading && events.length ? (
|
||||||
<p className="text-meta text-muted-foreground">正在加载关联的整理记录与引擎运行…</p>
|
<p className="text-meta text-muted-foreground">加载整理记录和引擎运行…</p>
|
||||||
) : null}
|
) : null}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -81,9 +81,9 @@ function VolumeBar({ v }: { v: Volume }) {
|
|||||||
/>
|
/>
|
||||||
<div className="mt-1.5 flex flex-wrap gap-1.5">
|
<div className="mt-1.5 flex flex-wrap gap-1.5">
|
||||||
{pct === null ? <StatusBadge tone="warning">读不到磁盘状态,已暂停新提交</StatusBadge> : null}
|
{pct === null ? <StatusBadge tone="warning">读不到磁盘状态,已暂停新提交</StatusBadge> : null}
|
||||||
{tripped ? <StatusBadge tone="destructive">超过暂停线,停止新下载</StatusBadge> : null}
|
{tripped ? <StatusBadge tone="destructive">超过暂停线,已停止新下载</StatusBadge> : null}
|
||||||
{v.pausedByThreshold ? (
|
{v.pausedByThreshold ? (
|
||||||
<StatusBadge tone="warning">因下载盘暂停 {v.pausedByThreshold} 个任务</StatusBadge>
|
<StatusBadge tone="warning">超过暂停线,暂停了 {v.pausedByThreshold} 个任务</StatusBadge>
|
||||||
) : null}
|
) : null}
|
||||||
</div>
|
</div>
|
||||||
{v.notes.map((n) => (
|
{v.notes.map((n) => (
|
||||||
@@ -119,7 +119,7 @@ export function CacheVolumes() {
|
|||||||
</Button>
|
</Button>
|
||||||
}
|
}
|
||||||
title="按规则清理下载缓存?"
|
title="按规则清理下载缓存?"
|
||||||
description="只清理已整理、且满足保留期与 H&R 的本工具任务,其余不动。"
|
description="只清理本工具管理、已整理且满足保留期和 H&R 要求的任务,其余不动。"
|
||||||
confirmLabel="清理"
|
confirmLabel="清理"
|
||||||
onConfirm={() =>
|
onConfirm={() =>
|
||||||
cleanup.mutateAsync(undefined).then(
|
cleanup.mutateAsync(undefined).then(
|
||||||
@@ -138,7 +138,7 @@ export function CacheVolumes() {
|
|||||||
) : vols.error ? (
|
) : vols.error ? (
|
||||||
<ErrorState plain error={vols.error} onRetry={() => void vols.refetch()} />
|
<ErrorState plain error={vols.error} onRetry={() => void vols.refetch()} />
|
||||||
) : !vols.data.length ? (
|
) : !vols.data.length ? (
|
||||||
<p className="text-caption text-muted-foreground">还没有缓存卷数据。登记下载器并完成巡检后显示。</p>
|
<p className="text-caption text-muted-foreground">还没有下载盘。添加下载器后显示。</p>
|
||||||
) : (
|
) : (
|
||||||
<div className="grid gap-5 md:grid-cols-2">
|
<div className="grid gap-5 md:grid-cols-2">
|
||||||
{vols.data.map((v) => (
|
{vols.data.map((v) => (
|
||||||
|
|||||||
@@ -333,11 +333,11 @@ export const BOARD_EMPTY: Record<DownloadBoardState, { title: string; descriptio
|
|||||||
active: {
|
active: {
|
||||||
icon: Download,
|
icon: Download,
|
||||||
title: "没有进行中的下载",
|
title: "没有进行中的下载",
|
||||||
description: "自动收录或在站点页下载后出现在这里,等批准、等磁盘空间的也在这里;下载完成的在「已完成」。",
|
description: "自动收录和手动下载的任务都在这里,包括等批准、等磁盘空间的。下载完成后移到「已完成」。",
|
||||||
},
|
},
|
||||||
completed: {
|
completed: {
|
||||||
icon: CheckCircle2,
|
icon: CheckCircle2,
|
||||||
title: "还没有下载完成的任务",
|
title: "还没有下载完成的任务",
|
||||||
description: "下载完成(含做种)后出现在这里。",
|
description: "下载完成的任务在这里,包括做种中的。",
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
@@ -49,7 +49,7 @@ export function DownloadStatusBadges({ t }: { t: DownloadTask }) {
|
|||||||
<span className="flex flex-wrap gap-1">
|
<span className="flex flex-wrap gap-1">
|
||||||
<StatusBadge tone={DOWNLOAD_STATUS_TONE[t.status]}>{DOWNLOAD_STATUS_LABEL[t.status]}</StatusBadge>
|
<StatusBadge tone={DOWNLOAD_STATUS_TONE[t.status]}>{DOWNLOAD_STATUS_LABEL[t.status]}</StatusBadge>
|
||||||
{t.pauseReason === "threshold" ? (
|
{t.pauseReason === "threshold" ? (
|
||||||
<StatusBadge tone="warning">下载盘满,已暂停</StatusBadge>
|
<StatusBadge tone="warning">超过暂停线,已暂停</StatusBadge>
|
||||||
) : t.pauseReason ? (
|
) : t.pauseReason ? (
|
||||||
<StatusBadge>{PAUSE_REASON_LABEL[t.pauseReason]}</StatusBadge>
|
<StatusBadge>{PAUSE_REASON_LABEL[t.pauseReason]}</StatusBadge>
|
||||||
) : null}
|
) : null}
|
||||||
@@ -151,7 +151,7 @@ export function DownloadDetail({ task, live }: { task: DownloadTask; live?: Down
|
|||||||
) : null}
|
) : null}
|
||||||
{task.noProgressSince ? (
|
{task.noProgressSince ? (
|
||||||
<p className="rounded-lg border border-warning/40 bg-warning/10 px-3 py-2 text-caption text-warning">
|
<p className="rounded-lg border border-warning/40 bg-warning/10 px-3 py-2 text-caption text-warning">
|
||||||
自 {formatDateTime(task.noProgressSince)} 起无进展,不会自动换源;开了自动调查时智能体会在授权内尝试恢复。
|
{formatDateTime(task.noProgressSince)} 起没有进展,不会自动换源。开启自动调查时,智能体会在持续授权范围内尝试恢复。
|
||||||
</p>
|
</p>
|
||||||
) : null}
|
) : null}
|
||||||
|
|
||||||
|
|||||||
@@ -85,7 +85,7 @@ describe("保存目录", () => {
|
|||||||
expect(custom).not.toHaveProperty("downloaderInstanceId");
|
expect(custom).not.toHaveProperty("downloaderInstanceId");
|
||||||
});
|
});
|
||||||
|
|
||||||
it("界面:并排两个下拉,下方写明将保存到哪;自定义时展开输入框", () => {
|
it("界面:并排两个下拉,下方写明保存到哪;自定义时展开输入框", () => {
|
||||||
const props = {
|
const props = {
|
||||||
formId: "f",
|
formId: "f",
|
||||||
instances: paths.instances,
|
instances: paths.instances,
|
||||||
@@ -101,10 +101,10 @@ describe("保存目录", () => {
|
|||||||
const html = render(createElement(SaveTargetFields, props));
|
const html = render(createElement(SaveTargetFields, props));
|
||||||
expect(html).toContain("下载器");
|
expect(html).toContain("下载器");
|
||||||
expect(html).toContain("自动:qb-main");
|
expect(html).toContain("自动:qb-main");
|
||||||
expect(html).toContain("将保存到:/data/downloads(本机 /mnt/dl)");
|
expect(html).toContain("保存到:/data/downloads(本机 /mnt/dl)");
|
||||||
expect(html).not.toContain("自定义路径</label>");
|
expect(html).not.toContain("自定义路径</label>");
|
||||||
const custom = render(createElement(SaveTargetFields, { ...props, dir: CUSTOM_DIR, custom: "/x" }));
|
const custom = render(createElement(SaveTargetFields, { ...props, dir: CUSTOM_DIR, custom: "/x" }));
|
||||||
expect(custom).toContain("将保存到:/x");
|
expect(custom).toContain("保存到:/x");
|
||||||
expect(custom).toContain('id="f-custom"');
|
expect(custom).toContain('id="f-custom"');
|
||||||
const none = render(
|
const none = render(
|
||||||
createElement(SaveTargetFields, { ...props, instances: [], autoInstanceId: null, target: null }),
|
createElement(SaveTargetFields, { ...props, instances: [], autoInstanceId: null, target: null }),
|
||||||
@@ -136,7 +136,7 @@ describe("作品身份", () => {
|
|||||||
expect(html).toContain("未识别");
|
expect(html).toContain("未识别");
|
||||||
expect(html).toContain("TMDB 编号");
|
expect(html).toContain("TMDB 编号");
|
||||||
expect(html).toContain('id="f-tmdb"');
|
expect(html).toContain('id="f-tmdb"');
|
||||||
expect(html).toContain("暂未识别到作品");
|
expect(html).toContain("没识别出作品");
|
||||||
});
|
});
|
||||||
|
|
||||||
it("已识别:折叠只显示当前作品", () => {
|
it("已识别:折叠只显示当前作品", () => {
|
||||||
|
|||||||
@@ -282,7 +282,7 @@ export function ManualDownloadDialog({
|
|||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Bot />
|
<Bot />
|
||||||
委托智能体
|
交给智能体
|
||||||
</Button>
|
</Button>
|
||||||
) : null}
|
) : null}
|
||||||
<Button
|
<Button
|
||||||
@@ -329,7 +329,7 @@ export function ResourceSummary({ resource: r }: { resource: ManualDownloadResou
|
|||||||
{r.leechers ?? "—"}
|
{r.leechers ?? "—"}
|
||||||
</span>
|
</span>
|
||||||
) : null}
|
) : null}
|
||||||
{r.publishedAt ? <span title={absTime(r.publishedAt)}>发布 {relTime(r.publishedAt)}</span> : null}
|
{r.publishedAt ? <span title={absTime(r.publishedAt)}>发布于 {relTime(r.publishedAt)}</span> : null}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
@@ -372,7 +372,7 @@ export function SaveTargetFields({
|
|||||||
: !target && dir !== CUSTOM_DIR
|
: !target && dir !== CUSTOM_DIR
|
||||||
? "没有可用的下载器,先在设置里添加下载器和保存目录"
|
? "没有可用的下载器,先在设置里添加下载器和保存目录"
|
||||||
: resolved
|
: resolved
|
||||||
? `将保存到:${savePathText(resolved)}`
|
? `保存到:${savePathText(resolved)}`
|
||||||
: "填写下载器能访问的路径";
|
: "填写下载器能访问的路径";
|
||||||
return (
|
return (
|
||||||
<div className="grid items-start gap-x-3 sm:grid-cols-2">
|
<div className="grid items-start gap-x-3 sm:grid-cols-2">
|
||||||
@@ -504,7 +504,7 @@ export function IdentitySection({
|
|||||||
<div id={`${formId}-identity`} className="space-y-3 border-t border-border px-3 pt-3 pb-1">
|
<div id={`${formId}-identity`} className="space-y-3 border-t border-border px-3 pt-3 pb-1">
|
||||||
{unrecognized && !changed ? (
|
{unrecognized && !changed ? (
|
||||||
<p className="text-caption text-warning">
|
<p className="text-caption text-warning">
|
||||||
暂未识别到作品。指定后绑定到这个资源;不指定也能下载,整理时再补全识别和元数据。
|
没识别出作品。指定后绑定到这个资源;不指定也能下载,整理时再识别。
|
||||||
</p>
|
</p>
|
||||||
) : null}
|
) : null}
|
||||||
{picked ? (
|
{picked ? (
|
||||||
@@ -533,7 +533,7 @@ export function IdentitySection({
|
|||||||
<FormField
|
<FormField
|
||||||
label="TMDB 编号"
|
label="TMDB 编号"
|
||||||
htmlFor={`${formId}-tmdb`}
|
htmlFor={`${formId}-tmdb`}
|
||||||
error={tmdbId && !valid ? "TMDB 编号是数字" : preview.error ? errorMessage(preview.error) : null}
|
error={tmdbId && !valid ? "TMDB 编号只能是数字" : preview.error ? errorMessage(preview.error) : null}
|
||||||
hint={
|
hint={
|
||||||
preview.data
|
preview.data
|
||||||
? `${preview.data.title}${preview.data.year ? ` (${preview.data.year})` : ""}${preview.data.localEntityId ? " · 在媒体库" : ""}`
|
? `${preview.data.title}${preview.data.year ? ` (${preview.data.year})` : ""}${preview.data.localEntityId ? " · 在媒体库" : ""}`
|
||||||
@@ -602,8 +602,8 @@ export function ExistingVersionsSection({
|
|||||||
selected: string[];
|
selected: string[];
|
||||||
onSelectedChange: (ids: string[]) => void;
|
onSelectedChange: (ids: string[]) => void;
|
||||||
}) {
|
}) {
|
||||||
if (loading) return <p className="text-caption text-muted-foreground">正在读取已有版本…</p>;
|
if (loading) return <p className="text-caption text-muted-foreground">读取已有版本…</p>;
|
||||||
if (error) return <p className="text-caption text-destructive">已有版本读取失败,重试后再选洗版</p>;
|
if (error) return <p className="text-caption text-destructive">读取已有版本失败,重新打开后再选洗版</p>;
|
||||||
if (!versions.length) return null;
|
if (!versions.length) return null;
|
||||||
return (
|
return (
|
||||||
<div className="min-w-0 space-y-2">
|
<div className="min-w-0 space-y-2">
|
||||||
@@ -640,7 +640,7 @@ export function ExistingVersionsSection({
|
|||||||
))}
|
))}
|
||||||
</fieldset>
|
</fieldset>
|
||||||
<p className="text-meta text-muted-foreground">
|
<p className="text-meta text-muted-foreground">
|
||||||
本次新文件整理成功后替换所选旧文件。剧集只替换成功对应的季集,其余保留。
|
新文件整理成功后替换所选旧文件。剧集只替换整理成功的季集,其余保留。
|
||||||
</p>
|
</p>
|
||||||
</>
|
</>
|
||||||
) : null}
|
) : null}
|
||||||
|
|||||||
Reference in new issue
Block a user