feat(web): 技术信息折叠、原因码人话化、待处理「指定作品」(DEAI-2)

- 新增 TechInfo 折叠组件(默认收起,标题「技术信息」);设置新增「界面」分区,
  「默认展开技术信息」开关存本机浏览器
- 原因码表 @umt/contracts reasons.ts(identity_unknown、blocked:target_exists、below_min_size…
  → 一句人话 + 下一步),服务端整理记录 message 与冲突事项标题/摘要改用它
- 整理记录列表/详情、下载详情与时间线:原码、ID、hash、用时、变更序号进技术信息;
  下载完成但入库失败时单独提示;时间线只列有记录的阶段,标题改「经过」
- 待处理:没识别出作品类事项主按钮「指定作品」(搜媒体库 + TMDB,走已有 resolve;
  整理类事项打开重新整理),忽略为次要;去掉正常态徽章与「实时」指示;原始证据改「详细信息」进技术信息
- 整理成功后同时关闭该下载的「没识别出作品」事项

Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
rootandClaude Opus 5.5 committed 2026-09-29 20:42:27 +08:00
1 parent 4480fc346d
commit f0d4935fa7
21 files changed
+688 -78

No files matched your search

+17 -6
View File
@@ -11,7 +11,8 @@ import {
type TaskStatus,
} from "@umt/contracts";
import { organizationActionLabel, organizationLabel } from "~/lib/labels.ts";
import { PLAN_STATUS_LABEL } from "./downloads.ts";
import { humanizeReason, reasonLine } from "~/lib/reasons.ts";
import { PAUSE_REASON_LABEL, PLAN_STATUS_LABEL } from "./downloads.ts";
import { apiParsed } from "./parse.ts";
// 业务任务视图:按 trace 汇总的业务时间线(参考 MovieClaw task-activity)
@@ -173,7 +174,7 @@ export function buildTimeline(input: {
stage: "plan",
at: plan.createdAt,
title: `创建下载计划(${plan.purpose === "fill" ? "补缺" : plan.purpose === "upgrade" ? "升级" : "换源"})`,
detail: plan.statusReason,
detail: humanizeReason(plan.statusReason),
tone: "neutral",
});
if (plan.updatedAt !== plan.createdAt)
@@ -182,7 +183,7 @@ export function buildTimeline(input: {
stage: "plan",
at: plan.updatedAt,
title: `计划状态:${PLAN_STATUS_LABEL[plan.status]}`,
detail: plan.statusReason,
detail: humanizeReason(plan.statusReason),
tone: plan.status === "failed" ? "destructive" : plan.status === "expired" ? "warning" : "neutral",
});
}
@@ -199,7 +200,7 @@ export function buildTimeline(input: {
key: "dl-pause",
stage: "download",
at: task.updatedAt,
title: task.pauseReason === "threshold" ? "缓存达到硬阈值,已暂停" : `已暂停(${task.pauseReason})`,
title: task.pauseReason === "threshold" ? "下载盘超过暂停线,已暂停" : PAUSE_REASON_LABEL[task.pauseReason],
tone: "warning",
ongoing: task.status === "paused",
});
@@ -239,7 +240,15 @@ export function buildTimeline(input: {
stage: "organization",
at: r.startedAt ?? r.createdAt,
title: `整理 ${organizationActionLabel(r.action)}:${organizationLabel(r.status).label}`,
detail: `${c.succeeded}/${c.total} 文件成功${c.failed ? `,${c.failed} 失败` : ""}${c.skipped ? `,${c.skipped} 跳过` : ""}${r.reason ? ` · ${r.reason.message}` : ""}`,
detail:
[
c.total ? `${c.succeeded}/${c.total} 个文件成功` : null,
c.failed ? `${c.failed} 个失败` : null,
c.skipped ? `${c.skipped} 个跳过` : null,
r.reason ? reasonLine(r.reason) : null,
]
.filter(Boolean)
.join(" · ") || null,
tone: RECORD_TONE[r.status],
href: `/console/organize/${r.id}`,
ongoing: r.status === "running" || r.status === "queued",
@@ -275,7 +284,9 @@ export function buildTimeline(input: {
at: t.startedAt ?? t.createdAt,
title: `任务 ${TASK_KIND_LABEL[t.kind] ?? t.kind}:${TASK_STATUS_TEXT[t.status] ?? t.status}`,
detail:
[t.attempts > 1 ? `第 ${t.attempts} 次尝试` : null, t.waitReason, err].filter(Boolean).join(" · ") || null,
[t.attempts > 1 ? `第 ${t.attempts} 次尝试` : null, humanizeReason(t.waitReason), humanizeReason(err)]
.filter(Boolean)
.join(" · ") || null,
tone: TASK_STATUS_TONE[t.status],
href: `/console/tasks/${encodeURIComponent(t.id)}`,
ongoing: ACTIVE_TASK.includes(t.status),