fix(downloads): humanized reasons and TechInfo on the download panel (DL-2b)
- board organize hint uses DEAI-2 reasonLine; add transfer_failed, blocked, blocked_by_conflict, main_failed, not_imported_kind, target_root_not_managed, download_removed to the reason table with tests - download detail / plans tab: internal ids, raw codes and JSON moved into TechInfo - library versions tech block switched to TechInfo (TODO(DEAI-2)) - copy: glossary terms (no 接管/候选), plan reason codes no longer shown raw Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
1 parent
8315ece4d1
commit
3f1c4d6c3b
11 files changed
+105
-65
No files matched your search
@@ -42,13 +42,27 @@ describe("下载面板展示换算(DL-2)", () => {
|
||||
decision: { id: "00000000-0000-4000-8000-000000000002", kind: "identity_unresolved" },
|
||||
}),
|
||||
});
|
||||
// 原因码不直接给人看
|
||||
expect(failed).toMatchObject({ label: "入库失败", tone: "destructive", hint: null });
|
||||
// 原因码转成人话,不直接给人看
|
||||
expect(failed).toMatchObject({
|
||||
label: "入库失败",
|
||||
tone: "destructive",
|
||||
hint: "没识别出作品。指定作品后重新整理",
|
||||
});
|
||||
expect(failed.to).toBe("/console/inbox?kind=identity_unresolved");
|
||||
expect(organizeState({ status: "completed", organize: rec("failed", { reason: "磁盘已满" }) }).hint).toBe(
|
||||
"磁盘已满",
|
||||
);
|
||||
expect(organizeState({ status: "completed", organize: rec("partial") }).label).toBe("部分入库");
|
||||
expect(organizeState({ status: "completed", organize: rec("failed", { reason: "transfer_failed" }) }).hint).toBe(
|
||||
"文件没有整理成功。在整理记录里查看失败的文件",
|
||||
);
|
||||
expect(
|
||||
organizeState({ status: "completed", organize: rec("partial", { reason: "blocked:target_exists" }) }).hint,
|
||||
).toBe("媒体库里已有同名文件。在待处理里选择替换或跳过");
|
||||
// 不认识的码不显示
|
||||
expect(
|
||||
organizeState({ status: "completed", organize: rec("failed", { reason: "some_new_code" }) }).hint,
|
||||
).toBeNull();
|
||||
expect(organizeState({ status: "completed", organize: rec("cancelled") })).toMatchObject({
|
||||
label: "待整理",
|
||||
to: null,
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import type { DownloadBoardItem, DownloadBoardState, DownloadLive } from "@umt/contracts";
|
||||
import { consolePath } from "~/components/console/nav.ts";
|
||||
import { reasonLine } from "~/lib/reasons.ts";
|
||||
import { formatBytes } from "~/lib/utils.ts";
|
||||
|
||||
// 下载面板(DL-2)的展示换算:速度、剩余时间、整理状态、实时状态补充。
|
||||
@@ -33,10 +34,9 @@ export type OrganizeState = {
|
||||
hint: string | null;
|
||||
};
|
||||
|
||||
/** 原因:内部码(小写下划线)不显示,其余原样。TODO(DEAI-2 合并后):改用 ~/lib/reasons.ts 的 reasonLine 人话化 */
|
||||
/** 原因 → 一句人话(DEAI-2 原因码表);不认识的内部码不给人看,原码在详情的技术信息里 */
|
||||
export function reasonHint(raw: string | null | undefined): string | null {
|
||||
if (!raw) return null;
|
||||
return /^[a-z0-9_]+([:.,][a-z0-9_:.,-]*)?$/.test(raw) ? null : raw;
|
||||
return reasonLine(raw, "") || null;
|
||||
}
|
||||
|
||||
/** 已完成任务的最近一次整理结果:已入库 / 整理中 / 待整理 / 入库失败 / 部分入库 */
|
||||
|
||||
@@ -24,7 +24,7 @@ import { Button } from "~/components/ui/button.tsx";
|
||||
import { relTime } from "~/components/workbench/release-fields.ts";
|
||||
import { errorMessage } from "~/lib/api.ts";
|
||||
import { planReasonText } from "~/lib/labels.ts";
|
||||
import { humanizeReason, reasonLine } from "~/lib/reasons.ts";
|
||||
import { humanizeReason, reasonCode, reasonLine } from "~/lib/reasons.ts";
|
||||
import { formatBytes, formatDateTime } from "~/lib/utils.ts";
|
||||
import { liveItems } from "./board-format.ts";
|
||||
import { BusinessTimeline } from "./business-timeline.tsx";
|
||||
@@ -162,7 +162,7 @@ export function DownloadDetail({ task, live }: { task: DownloadTask; live?: Down
|
||||
<KvList
|
||||
className="mt-3"
|
||||
items={[
|
||||
{ label: "下载器", value: names.data?.get(task.instanceId) ?? task.instanceId.slice(0, 8) },
|
||||
{ label: "下载器", value: names.data?.get(task.instanceId) ?? "未知" },
|
||||
{ label: "大小", value: task.sizeBytes === null ? "未知" : formatBytes(task.sizeBytes, 2) },
|
||||
{ label: "剩余", value: task.remainingBytes === null ? "未知" : formatBytes(task.remainingBytes, 2) },
|
||||
...liveItems(live),
|
||||
@@ -181,6 +181,9 @@ export function DownloadDetail({ task, live }: { task: DownloadTask; live?: Down
|
||||
{ label: "内容路径", value: task.contentPath, wide: true },
|
||||
{ label: "torrent hash", value: task.torrentHash, wide: true },
|
||||
{ label: "任务 ID", value: task.id, wide: true },
|
||||
{ label: "下载器 ID", value: task.instanceId, wide: true },
|
||||
importFailed ? { label: "整理失败原因码", value: reasonCode(importFailed.reason) } : null,
|
||||
importFailed ? { label: "整理记录 ID", value: importFailed.id, wide: true } : null,
|
||||
]}
|
||||
>
|
||||
{task.lastError ? <JsonView label="下载器错误原文" value={task.lastError} tone="destructive" /> : null}
|
||||
@@ -201,7 +204,13 @@ export function DownloadDetail({ task, live }: { task: DownloadTask; live?: Down
|
||||
{ label: "说明", value: planReasonText(plan.data.statusReason), wide: true },
|
||||
]}
|
||||
/>
|
||||
<TechInfo className="mt-2">
|
||||
<TechInfo
|
||||
className="mt-2"
|
||||
items={[
|
||||
{ label: "计划 ID", value: plan.data.id, wide: true },
|
||||
{ label: "说明原码", value: plan.data.statusReason },
|
||||
]}
|
||||
>
|
||||
<JsonView label="评估依据" value={plan.data.evaluation} />
|
||||
</TechInfo>
|
||||
</DetailSection>
|
||||
|
||||
Reference in new issue
Block a user