copy(web): api 标签与整理状态统一
整理记录状态改为排队中 / 整理中 / 已整理 / 部分整理 / 整理失败(列表摘要、组汇总、队列面板同口径); 下载计划「等你批准」「准备提交」;资源评估「可下载」「信息不全」「已跳过」;任务状态带「中」; 识别等待提示改匹配「TMDB 结果在后台查询」。 Co-Authored-By: Claude Opus 5.5 <[email protected]> Claude-Session: https://claude.ai/code/session_01Cxwgnn2pbzQ7rXv3rq7fei
This commit is contained in:
1 parent
148b12f279
commit
592f40ccf8
23 files changed
+58
-59
No files matched your search
@@ -344,8 +344,8 @@ export const REPORT_STATE: Record<
|
|||||||
{ label: string; tone: "success" | "warning" | "destructive" | "neutral" }
|
{ label: string; tone: "success" | "warning" | "destructive" | "neutral" }
|
||||||
> = {
|
> = {
|
||||||
no_actions: { label: "没有产生业务动作", tone: "neutral" },
|
no_actions: { label: "没有产生业务动作", tone: "neutral" },
|
||||||
waiting: { label: "已提交,等待下载/整理", tone: "warning" },
|
waiting: { label: "已提交,等下载和整理", tone: "warning" },
|
||||||
completed: { label: "已核验整理", tone: "success" },
|
completed: { label: "已整理", tone: "success" },
|
||||||
partial: { label: "部分完成", tone: "warning" },
|
partial: { label: "部分完成", tone: "warning" },
|
||||||
failed: { label: "未达成", tone: "destructive" },
|
failed: { label: "未达成", tone: "destructive" },
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -205,7 +205,7 @@ export function useDownloaderNames() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export const DOWNLOAD_STATUS_LABEL: Record<DownloadStatus, string> = {
|
export const DOWNLOAD_STATUS_LABEL: Record<DownloadStatus, string> = {
|
||||||
queued: "排队",
|
queued: "排队中",
|
||||||
submitting: "提交中",
|
submitting: "提交中",
|
||||||
downloading: "下载中",
|
downloading: "下载中",
|
||||||
paused: "已暂停",
|
paused: "已暂停",
|
||||||
@@ -215,7 +215,7 @@ export const DOWNLOAD_STATUS_LABEL: Record<DownloadStatus, string> = {
|
|||||||
imported: "已整理",
|
imported: "已整理",
|
||||||
failed: "失败",
|
failed: "失败",
|
||||||
removed: "已移除",
|
removed: "已移除",
|
||||||
missing: "下载器中缺失",
|
missing: "下载器里找不到",
|
||||||
};
|
};
|
||||||
|
|
||||||
export const DOWNLOAD_STATUS_TONE: Record<DownloadStatus, "success" | "warning" | "destructive" | "neutral"> = {
|
export const DOWNLOAD_STATUS_TONE: Record<DownloadStatus, "success" | "warning" | "destructive" | "neutral"> = {
|
||||||
@@ -234,14 +234,14 @@ export const DOWNLOAD_STATUS_TONE: Record<DownloadStatus, "success" | "warning"
|
|||||||
|
|
||||||
export const PAUSE_REASON_LABEL = {
|
export const PAUSE_REASON_LABEL = {
|
||||||
user: "手动暂停",
|
user: "手动暂停",
|
||||||
threshold: "下载盘满暂停",
|
threshold: "因下载盘暂停",
|
||||||
policy: "策略暂停",
|
policy: "策略暂停",
|
||||||
agent: "智能体暂停",
|
agent: "智能体暂停",
|
||||||
} as const;
|
} as const;
|
||||||
|
|
||||||
export const PLAN_STATUS_LABEL: Record<PlanStatus, string> = {
|
export const PLAN_STATUS_LABEL: Record<PlanStatus, string> = {
|
||||||
draft: "待批准",
|
draft: "等你批准",
|
||||||
reserved: "已预留空间",
|
reserved: "准备提交",
|
||||||
submitted: "已提交",
|
submitted: "已提交",
|
||||||
completed: "已完成",
|
completed: "已完成",
|
||||||
cancelled: "已取消",
|
cancelled: "已取消",
|
||||||
|
|||||||
@@ -19,12 +19,12 @@ export function useInventory(entityIds: string[]) {
|
|||||||
export type OverlayFlag = { key: string; label: string; tone: "success" | "warning" | "neutral"; title?: string };
|
export type OverlayFlag = { key: string; label: string; tone: "success" | "warning" | "neutral"; title?: string };
|
||||||
|
|
||||||
const DECISION_FLAG: Record<string, { label: string; tone: OverlayFlag["tone"] }> = {
|
const DECISION_FLAG: Record<string, { label: string; tone: OverlayFlag["tone"] }> = {
|
||||||
accept: { label: "已选中", tone: "success" },
|
accept: { label: "可下载", tone: "success" },
|
||||||
upgrade: { label: "可升级", tone: "success" },
|
upgrade: { label: "可升级", tone: "success" },
|
||||||
reject: { label: "未选", tone: "warning" },
|
reject: { label: "未选", tone: "warning" },
|
||||||
unknown_field: { label: "字段未知", tone: "warning" },
|
unknown_field: { label: "信息不全", tone: "warning" },
|
||||||
skipped: { label: "被跳过", tone: "neutral" },
|
skipped: { label: "已跳过", tone: "neutral" },
|
||||||
deferred: { label: "延后", tone: "neutral" },
|
deferred: { label: "延后:已有下载在进行", tone: "neutral" },
|
||||||
};
|
};
|
||||||
|
|
||||||
/** 该资源在各 Slot 上的最近一次评估(服务端每个 (Slot, 资源) 只保留一条) */
|
/** 该资源在各 Slot 上的最近一次评估(服务端每个 (Slot, 资源) 只保留一条) */
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ export function parseOrThrow<S extends z.ZodType>(schema: S, data: unknown, path
|
|||||||
console.warn(`[api] ${path} 响应结构不符`, r.error.issues);
|
console.warn(`[api] ${path} 响应结构不符`, r.error.issues);
|
||||||
throw new ApiRequestError(
|
throw new ApiRequestError(
|
||||||
"internal",
|
"internal",
|
||||||
`接口 ${path} 返回的数据结构不符(${first?.path.join(".") || "根"}: ${first?.message ?? "未知"})`,
|
`接口 ${path} 返回的数据结构不符(${first?.path.join(".") || "(root)"}: ${first?.message ?? "未知"})`,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
return r.data;
|
return r.data;
|
||||||
|
|||||||
@@ -47,8 +47,7 @@ export async function fetchAllCursorPages<P extends { items: unknown[]; nextCurs
|
|||||||
const seen = new Set<string>();
|
const seen = new Set<string>();
|
||||||
let cursor = first.nextCursor;
|
let cursor = first.nextCursor;
|
||||||
while (cursor) {
|
while (cursor) {
|
||||||
// copy-allow: 用词规则上线前已有,文案归其它路改
|
if (seen.has(cursor)) throw new ApiRequestError("internal", "分页游标重复。重试");
|
||||||
if (seen.has(cursor)) throw new ApiRequestError("internal", "分页游标重复,请重试");
|
|
||||||
seen.add(cursor);
|
seen.add(cursor);
|
||||||
const page = await fetchPage(cursor);
|
const page = await fetchPage(cursor);
|
||||||
items.push(...page.items);
|
items.push(...page.items);
|
||||||
|
|||||||
@@ -160,11 +160,11 @@ export function useOrganize() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export const RECORD_STATUS_LABEL: Record<OrganizationStatus, string> = {
|
export const RECORD_STATUS_LABEL: Record<OrganizationStatus, string> = {
|
||||||
queued: "排队",
|
queued: "排队中",
|
||||||
running: "执行中",
|
running: "整理中",
|
||||||
succeeded: "成功",
|
succeeded: "已整理",
|
||||||
partial: "部分成功",
|
partial: "部分整理",
|
||||||
failed: "失败",
|
failed: "整理失败",
|
||||||
cancelled: "已取消",
|
cancelled: "已取消",
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ const DecisionPage = cursorPage(Decision);
|
|||||||
const RESOLUTION_LABEL = {
|
const RESOLUTION_LABEL = {
|
||||||
unresolved: "未识别",
|
unresolved: "未识别",
|
||||||
resolved: "已识别",
|
resolved: "已识别",
|
||||||
ambiguous: "有歧义,待确认",
|
ambiguous: "匹配到多部作品,待确认",
|
||||||
unidentifiable: "无法识别",
|
unidentifiable: "无法识别",
|
||||||
rejected: "已排除",
|
rejected: "已排除",
|
||||||
} as const;
|
} as const;
|
||||||
@@ -99,9 +99,9 @@ export function useRecordsForDownload(downloadTaskId: string | undefined) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const TASK_STATUS_TEXT: Record<string, string> = {
|
const TASK_STATUS_TEXT: Record<string, string> = {
|
||||||
pending: "排队",
|
pending: "排队中",
|
||||||
running: "运行中",
|
running: "运行中",
|
||||||
waiting: "等待",
|
waiting: "等待中",
|
||||||
succeeded: "成功",
|
succeeded: "成功",
|
||||||
failed: "失败",
|
failed: "失败",
|
||||||
cancelled: "已取消",
|
cancelled: "已取消",
|
||||||
@@ -111,9 +111,9 @@ const TASK_STATUS_TEXT: Record<string, string> = {
|
|||||||
const TASK_KIND_LABEL: Partial<Record<TaskKind, string>> = {
|
const TASK_KIND_LABEL: Partial<Record<TaskKind, string>> = {
|
||||||
submitDownload: "提交下载",
|
submitDownload: "提交下载",
|
||||||
verifyAndImport: "核验整理",
|
verifyAndImport: "核验整理",
|
||||||
evaluateAcquisition: "评估候选",
|
evaluateAcquisition: "评估资源",
|
||||||
cleanupDownloadCache: "清理缓存",
|
cleanupDownloadCache: "清理缓存",
|
||||||
resolveDecision: "处理待处理事项",
|
resolveDecision: "处理需要处理的事项",
|
||||||
};
|
};
|
||||||
|
|
||||||
const TASK_STATUS_TONE: Record<TaskStatus, TimelineTone> = {
|
const TASK_STATUS_TONE: Record<TaskStatus, TimelineTone> = {
|
||||||
@@ -239,7 +239,7 @@ export function buildTimeline(input: {
|
|||||||
key: `rec-${r.id}`,
|
key: `rec-${r.id}`,
|
||||||
stage: "organization",
|
stage: "organization",
|
||||||
at: r.startedAt ?? r.createdAt,
|
at: r.startedAt ?? r.createdAt,
|
||||||
title: `整理 ${organizationActionLabel(r.action)}:${organizationLabel(r.status).label}`,
|
title: `整理 ${organizationActionLabel(r.action)}:${organizationLabel(r.status).label}`,
|
||||||
detail:
|
detail:
|
||||||
[
|
[
|
||||||
c.total ? `${c.succeeded}/${c.total} 个文件成功` : null,
|
c.total ? `${c.succeeded}/${c.total} 个文件成功` : null,
|
||||||
@@ -259,7 +259,7 @@ export function buildTimeline(input: {
|
|||||||
key: `dec-${d.id}`,
|
key: `dec-${d.id}`,
|
||||||
stage: "agent",
|
stage: "agent",
|
||||||
at: d.createdAt,
|
at: d.createdAt,
|
||||||
title: `待处理:${d.title}`,
|
title: `需要处理:${d.title}`,
|
||||||
detail: d.summary,
|
detail: d.summary,
|
||||||
tone: d.severity === "critical" ? "destructive" : "warning",
|
tone: d.severity === "critical" ? "destructive" : "warning",
|
||||||
href: "/console/inbox",
|
href: "/console/inbox",
|
||||||
|
|||||||
@@ -42,7 +42,7 @@ export const TASK_STATUS: Record<
|
|||||||
> = {
|
> = {
|
||||||
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" },
|
||||||
@@ -63,7 +63,7 @@ export const SUBJECT_LABEL: Record<string, string> = {
|
|||||||
feed_source: "RSS",
|
feed_source: "RSS",
|
||||||
site: "站点",
|
site: "站点",
|
||||||
library_root: "媒体库目录",
|
library_root: "媒体库目录",
|
||||||
cache_volume: "缓存卷",
|
cache_volume: "下载盘",
|
||||||
};
|
};
|
||||||
|
|
||||||
/** 业务任务的对象 → 它的"家"页面 */
|
/** 业务任务的对象 → 它的"家"页面 */
|
||||||
|
|||||||
@@ -155,7 +155,7 @@ export function IdentifyPanel({
|
|||||||
})}
|
})}
|
||||||
</ul>
|
</ul>
|
||||||
) : it.skipped ? null : (
|
) : it.skipped ? null : (
|
||||||
<p className="text-caption text-muted-foreground">没有可信候选。整理时可以手动搜索作品。</p>
|
<p className="text-caption text-muted-foreground">没有可信的候选作品。整理时可以手动搜索作品。</p>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|||||||
@@ -339,7 +339,7 @@ describe("识别远端回填(S-7)", () => {
|
|||||||
candidates: [],
|
candidates: [],
|
||||||
suggestion: { mediaEntityId: null, contentUnitId: null, contentUnit: null },
|
suggestion: { mediaEntityId: null, contentUnitId: null, contentUnit: null },
|
||||||
existing: { assetId: null },
|
existing: { assetId: null },
|
||||||
warnings: ["远端候选在后台查询,查完自动补上"],
|
warnings: ["TMDB 结果在后台查询,查完自动补上"],
|
||||||
...over,
|
...over,
|
||||||
});
|
});
|
||||||
const base = { items: [item("a.mkv"), item("b.mkv")], truncated: false, remoteTaskId: "run-1", remotePending: 1 };
|
const base = { items: [item("a.mkv"), item("b.mkv")], truncated: false, remoteTaskId: "run-1", remotePending: 1 };
|
||||||
|
|||||||
@@ -548,7 +548,7 @@ export function nameTaken(name: string, self: string, siblings: string[]): boole
|
|||||||
|
|
||||||
const identifyKey = (it: Pick<FileIdentifyItem, "root" | "path">) => `${it.root}\u0000${it.path}`;
|
const identifyKey = (it: Pick<FileIdentifyItem, "root" | "path">) => `${it.root}\u0000${it.path}`;
|
||||||
/** 服务端给"远端在后台查"项加的提示;结果回来后去掉 */
|
/** 服务端给"远端在后台查"项加的提示;结果回来后去掉 */
|
||||||
const REMOTE_PENDING_WARNING = /^远端候选在后台查询/;
|
const REMOTE_PENDING_WARNING = /^TMDB 结果在后台查询/;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* SSE identify.completed 回填:taskId 与响应的 remoteTaskId 一致时,按 root + path 用完整结果替换条目;
|
* SSE identify.completed 回填:taskId 与响应的 remoteTaskId 一致时,按 root + path 用完整结果替换条目;
|
||||||
|
|||||||
@@ -123,10 +123,10 @@ export const ORG_STATUS: Record<OrganizationStatus, ToneLabel> = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export const CANDIDATE_DECISION: Record<string, ToneLabel> = {
|
export const CANDIDATE_DECISION: Record<string, ToneLabel> = {
|
||||||
accept: { label: "接受", tone: "success" },
|
accept: { label: "可下载", tone: "success" },
|
||||||
upgrade: { label: "可升级", tone: "success" },
|
upgrade: { label: "可升级", tone: "success" },
|
||||||
reject: { label: "拒绝", tone: "destructive" },
|
reject: { label: "拒绝", tone: "destructive" },
|
||||||
unknown_field: { label: "字段未知", tone: "warning" },
|
unknown_field: { label: "信息不全", tone: "warning" },
|
||||||
skipped: { label: "已跳过", tone: "neutral" },
|
skipped: { label: "已跳过", tone: "neutral" },
|
||||||
deferred: { label: "延后:已有下载在进行", tone: "warning" },
|
deferred: { label: "延后:已有下载在进行", tone: "warning" },
|
||||||
};
|
};
|
||||||
@@ -294,7 +294,7 @@ export const ENRICH_SOURCE_KIND: Record<string, string> = {
|
|||||||
platform: "平台页",
|
platform: "平台页",
|
||||||
douban: "豆瓣摘要",
|
douban: "豆瓣摘要",
|
||||||
snippet: "搜索摘要",
|
snippet: "搜索摘要",
|
||||||
other: "其它网站",
|
other: "其他网站",
|
||||||
};
|
};
|
||||||
|
|
||||||
/** 补全来源链接被跳过的原因 */
|
/** 补全来源链接被跳过的原因 */
|
||||||
|
|||||||
@@ -99,7 +99,7 @@ export function ScrapeRecordView({ record: s, showPath = false }: { record: Scra
|
|||||||
<div className="grid gap-2">
|
<div className="grid gap-2">
|
||||||
<div className="flex flex-wrap items-center gap-2">
|
<div className="flex flex-wrap items-center gap-2">
|
||||||
<StatusBadge tone={SCRAPE_STATUS[s.status].tone}>{SCRAPE_STATUS[s.status].label}</StatusBadge>
|
<StatusBadge tone={SCRAPE_STATUS[s.status].tone}>{SCRAPE_STATUS[s.status].label}</StatusBadge>
|
||||||
{showPath ? <span className="min-w-0 text-sm break-all text-foreground">{s.path || "目录根"}</span> : null}
|
{showPath ? <span className="min-w-0 text-sm break-all text-foreground">{s.path || "(登记目录本身)"}</span> : null}
|
||||||
{done && (files.length || s.status === "succeeded") ? (
|
{done && (files.length || s.status === "succeeded") ? (
|
||||||
<span className="text-sm text-muted-foreground">{scrapeCounts(s) || "没有要写的文件"}</span>
|
<span className="text-sm text-muted-foreground">{scrapeCounts(s) || "没有要写的文件"}</span>
|
||||||
) : null}
|
) : null}
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ function ScrapeQueueItem({ run }: { run: EngineRun }) {
|
|||||||
const scrapeId = input.scrapeRecordId ?? input.recordId;
|
const scrapeId = input.scrapeRecordId ?? input.recordId;
|
||||||
const scrape = useScrapeRecords(scrapeId ? [scrapeId] : []);
|
const scrape = useScrapeRecords(scrapeId ? [scrapeId] : []);
|
||||||
const record = scrape.data?.records[0];
|
const record = scrape.data?.records[0];
|
||||||
const status = run.status === "pending" ? "排队" : run.status === "sleeping" ? "等待" : "执行中";
|
const status = run.status === "pending" ? "排队中" : run.status === "sleeping" ? "等待中" : "整理中";
|
||||||
return (
|
return (
|
||||||
<li className="pg-slab space-y-2 rounded-xl p-4">
|
<li className="pg-slab space-y-2 rounded-xl p-4">
|
||||||
<div className="flex flex-wrap items-center gap-2">
|
<div className="flex flex-wrap items-center gap-2">
|
||||||
@@ -85,7 +85,7 @@ function QueueItem({ run }: { run: EngineRun }) {
|
|||||||
const progress = record ? recordFileProgress(record) : null;
|
const progress = record ? recordFileProgress(record) : null;
|
||||||
const title = record ? recordTitle(record) : (download.data?.name ?? run.business?.title ?? "整理任务");
|
const title = record ? recordTitle(record) : (download.data?.name ?? run.business?.title ?? "整理任务");
|
||||||
const source = record?.source.path ?? download.data?.contentPath ?? download.data?.savePath;
|
const source = record?.source.path ?? download.data?.contentPath ?? download.data?.savePath;
|
||||||
const status = run.status === "pending" ? "排队" : run.status === "sleeping" ? "等待" : "执行中";
|
const status = run.status === "pending" ? "排队中" : run.status === "sleeping" ? "等待中" : "整理中";
|
||||||
return (
|
return (
|
||||||
<li className="pg-slab space-y-2 rounded-xl p-4">
|
<li className="pg-slab space-y-2 rounded-xl p-4">
|
||||||
<div className="flex flex-wrap items-center gap-2">
|
<div className="flex flex-wrap items-center gap-2">
|
||||||
|
|||||||
@@ -114,9 +114,9 @@ describe("整理记录列表:整理方式、分类、分组", () => {
|
|||||||
const st = (...xs: PublicOrganizationRecord["status"][]) => xs.map((status) => ({ status }));
|
const st = (...xs: PublicOrganizationRecord["status"][]) => xs.map((status) => ({ status }));
|
||||||
expect(groupIssues(st("succeeded", "succeeded"))).toEqual([]);
|
expect(groupIssues(st("succeeded", "succeeded"))).toEqual([]);
|
||||||
expect(groupIssues(st("succeeded", "failed", "partial", "running", "queued"))).toEqual([
|
expect(groupIssues(st("succeeded", "failed", "partial", "running", "queued"))).toEqual([
|
||||||
{ label: "失败", n: 1, tone: "destructive" },
|
{ label: "整理失败", n: 1, tone: "destructive" },
|
||||||
{ label: "部分成功", n: 1, tone: "warning" },
|
{ label: "部分整理", n: 1, tone: "warning" },
|
||||||
{ label: "进行中", n: 2, tone: "neutral" },
|
{ label: "整理中", n: 2, tone: "neutral" },
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -80,9 +80,9 @@ export function groupIssues(
|
|||||||
): { label: string; n: number; tone: "destructive" | "warning" | "neutral" }[] {
|
): { label: string; n: number; tone: "destructive" | "warning" | "neutral" }[] {
|
||||||
const n = (f: (s: PublicOrganizationRecord["status"]) => boolean) => rows.filter((r) => f(r.status)).length;
|
const n = (f: (s: PublicOrganizationRecord["status"]) => boolean) => rows.filter((r) => f(r.status)).length;
|
||||||
return [
|
return [
|
||||||
{ label: "失败", n: n((s) => s === "failed"), tone: "destructive" as const },
|
{ label: "整理失败", n: n((s) => s === "failed"), tone: "destructive" as const },
|
||||||
{ label: "部分成功", n: n((s) => s === "partial"), tone: "warning" as const },
|
{ label: "部分整理", n: n((s) => s === "partial"), tone: "warning" as const },
|
||||||
{ label: "进行中", n: n((s) => s === "queued" || s === "running"), tone: "neutral" as const },
|
{ label: "整理中", n: n((s) => s === "queued" || s === "running"), tone: "neutral" as const },
|
||||||
{ label: "已取消", n: n((s) => s === "cancelled"), tone: "neutral" as const },
|
{ label: "已取消", n: n((s) => s === "cancelled"), tone: "neutral" as const },
|
||||||
].filter((x) => x.n > 0);
|
].filter((x) => x.n > 0);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -282,7 +282,7 @@ export const TTL_CARD: CardSpec = {
|
|||||||
ttlField("tmdbMissDays", "TMDB 空结果", "搜索无结果或没识别出的结果也缓存,期内不重复查"),
|
ttlField("tmdbMissDays", "TMDB 空结果", "搜索无结果或没识别出的结果也缓存,期内不重复查"),
|
||||||
ttlField("imageDays", "TMDB 人物与图片"),
|
ttlField("imageDays", "TMDB 人物与图片"),
|
||||||
ttlField("metaSearchDays", "豆瓣 / Bangumi 搜索"),
|
ttlField("metaSearchDays", "豆瓣 / Bangumi 搜索"),
|
||||||
ttlField("metaDetailDays", "豆瓣 / Bangumi 条目"),
|
ttlField("metaDetailDays", "豆瓣 / Bangumi 作品"),
|
||||||
ttlField("siteDetailDays", "站点详情页内容"),
|
ttlField("siteDetailDays", "站点详情页内容"),
|
||||||
ttlField("webSearchDays", "网页搜索结果"),
|
ttlField("webSearchDays", "网页搜索结果"),
|
||||||
],
|
],
|
||||||
|
|||||||
@@ -208,7 +208,7 @@ describe("缓存区名", () => {
|
|||||||
it("已知区显示中文名,未知区原样显示", () => {
|
it("已知区显示中文名,未知区原样显示", () => {
|
||||||
const base = { entries: 1, expired: 0, bytes: 10, lastWriteAt: null };
|
const base = { entries: 1, expired: 0, bytes: 10, lastWriteAt: null };
|
||||||
expect(cacheRow({ region: "tmdb.request", ...base }).label).toBe("TMDB 请求");
|
expect(cacheRow({ region: "tmdb.request", ...base }).label).toBe("TMDB 请求");
|
||||||
expect(cacheRow({ region: "douban.subject", ...base }).label).toBe("豆瓣条目");
|
expect(cacheRow({ region: "douban.subject", ...base }).label).toBe("豆瓣作品");
|
||||||
expect(cacheRow({ region: "bangumi.calendar", ...base }).label).toBe("Bangumi(calendar)");
|
expect(cacheRow({ region: "bangumi.calendar", ...base }).label).toBe("Bangumi(calendar)");
|
||||||
expect(cacheRow({ region: "site.detail", ...base }).label).toBe("站点详情页");
|
expect(cacheRow({ region: "site.detail", ...base }).label).toBe("站点详情页");
|
||||||
expect(cacheRow({ region: "images", ...base }).label).toBe("图片");
|
expect(cacheRow({ region: "images", ...base }).label).toBe("图片");
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ describe("任务行状态", () => {
|
|||||||
});
|
});
|
||||||
it("引擎自身失败 / 进行中照旧;没有业务对象照旧", () => {
|
it("引擎自身失败 / 进行中照旧;没有业务对象照旧", () => {
|
||||||
expect(engineRunStatus({ status: "failed", business: agent("budget_exceeded") }).label).toBe("失败");
|
expect(engineRunStatus({ status: "failed", business: agent("budget_exceeded") }).label).toBe("失败");
|
||||||
expect(engineRunStatus({ status: "running", business: agent("running") }).label).toBe("进行中");
|
expect(engineRunStatus({ status: "running", business: agent("running") }).label).toBe("运行中");
|
||||||
expect(engineRunStatus({ status: "completed", business: null }).label).toBe("完成");
|
expect(engineRunStatus({ status: "completed", business: null }).label).toBe("完成");
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@@ -54,9 +54,9 @@ export const workflowLabel = (name: string) => WORKFLOW_LABEL[name] ?? name;
|
|||||||
|
|
||||||
/** 引擎状态 → 任务状态 */
|
/** 引擎状态 → 任务状态 */
|
||||||
const RUN_STATUS: Record<string, { label: string; tone: StatusTone }> = {
|
const RUN_STATUS: Record<string, { label: string; tone: StatusTone }> = {
|
||||||
pending: { label: "排队", tone: "neutral" },
|
pending: { label: "排队中", tone: "neutral" },
|
||||||
running: { label: "进行中", tone: "neutral" },
|
running: { label: "运行中", tone: "neutral" },
|
||||||
sleeping: { label: "等待", tone: "neutral" },
|
sleeping: { label: "等待中", tone: "neutral" },
|
||||||
completed: { label: "完成", tone: "success" },
|
completed: { label: "完成", tone: "success" },
|
||||||
succeeded: { label: "完成", tone: "success" },
|
succeeded: { label: "完成", tone: "success" },
|
||||||
failed: { label: "失败", tone: "destructive" },
|
failed: { label: "失败", tone: "destructive" },
|
||||||
|
|||||||
@@ -57,10 +57,10 @@ export const decisionKindLabel = (v: string) => DECISION_KIND[v] ?? v;
|
|||||||
|
|
||||||
const ORG: Record<string, Labeled> = {
|
const ORG: Record<string, Labeled> = {
|
||||||
queued: { label: "排队中", tone: "neutral" },
|
queued: { label: "排队中", tone: "neutral" },
|
||||||
running: { label: "进行中", tone: "neutral" },
|
running: { label: "整理中", tone: "neutral" },
|
||||||
succeeded: { label: "成功", tone: "success" },
|
succeeded: { label: "已整理", tone: "success" },
|
||||||
partial: { label: "部分成功", tone: "warning" },
|
partial: { label: "部分整理", tone: "warning" },
|
||||||
failed: { label: "失败", tone: "destructive" },
|
failed: { label: "整理失败", tone: "destructive" },
|
||||||
cancelled: { label: "已取消", tone: "neutral" },
|
cancelled: { label: "已取消", tone: "neutral" },
|
||||||
};
|
};
|
||||||
export const organizationLabel = (v: string | null | undefined) => pick(ORG, v);
|
export const organizationLabel = (v: string | null | undefined) => pick(ORG, v);
|
||||||
|
|||||||
@@ -105,7 +105,7 @@ export default function FilesTrashPage() {
|
|||||||
.mutateAsync({ idempotencyKey: newIdempotencyKey(), ids })
|
.mutateAsync({ idempotencyKey: newIdempotencyKey(), ids })
|
||||||
.then((r) => {
|
.then((r) => {
|
||||||
setPicked(new Set());
|
setPicked(new Set());
|
||||||
toast.success(`已清除 ${r.purged.length} 项${r.failed.length ? `,${r.failed.length} 项失败` : ""}`);
|
toast.success(`已清除 ${r.purged.length} 项${r.failed.length ? `,${r.failed.length} 项失败` : ""}`);
|
||||||
})
|
})
|
||||||
.catch((e) => {
|
.catch((e) => {
|
||||||
toast.error(filesErrorText(e, "清除失败"));
|
toast.error(filesErrorText(e, "清除失败"));
|
||||||
|
|||||||
@@ -100,7 +100,7 @@ const when = (r: Rec) => r.finishedAt ?? r.startedAt ?? r.createdAt;
|
|||||||
/** 状态:成功不加徽章,其余徽章 + 一句原因;需要处理的再给行内动作 */
|
/** 状态:成功不加徽章,其余徽章 + 一句原因;需要处理的再给行内动作 */
|
||||||
function StatusCell({ r, onReorganize }: { r: Rec; onReorganize?: () => void }) {
|
function StatusCell({ r, onReorganize }: { r: Rec; onReorganize?: () => void }) {
|
||||||
const progress = recordFileProgress(r);
|
const progress = recordFileProgress(r);
|
||||||
if (r.status === "succeeded" && !r.reason && !r.attention) return <span className="text-muted-foreground">成功</span>;
|
if (r.status === "succeeded" && !r.reason && !r.attention) return <span className="text-muted-foreground">已整理</span>;
|
||||||
const line = attentionLine(r) ?? reasonLine(r.reason);
|
const line = attentionLine(r) ?? reasonLine(r.reason);
|
||||||
return (
|
return (
|
||||||
<div className="flex flex-col items-start gap-0.5">
|
<div className="flex flex-col items-start gap-0.5">
|
||||||
@@ -314,10 +314,10 @@ function StatsLine({
|
|||||||
}) {
|
}) {
|
||||||
if (!s || (s.total === 0 && !s.attention)) return null;
|
if (!s || (s.total === 0 && !s.attention)) return null;
|
||||||
const parts: { key: OrganizationStatus | "running"; label: string; n: number; tone?: string }[] = [
|
const parts: { key: OrganizationStatus | "running"; label: string; n: number; tone?: string }[] = [
|
||||||
{ key: "succeeded", label: "成功", n: s.succeeded },
|
{ key: "succeeded", label: "已整理", n: s.succeeded },
|
||||||
{ key: "failed", label: "失败", n: s.failed, tone: "text-destructive" },
|
{ key: "failed", label: "整理失败", n: s.failed, tone: "text-destructive" },
|
||||||
{ key: "partial", label: "部分成功", n: s.partial, tone: "text-warning" },
|
{ key: "partial", label: "部分整理", n: s.partial, tone: "text-warning" },
|
||||||
{ key: "running", label: "进行中", n: s.running },
|
{ key: "running", label: "整理中", n: s.running },
|
||||||
{ key: "cancelled", label: "已取消", n: s.cancelled },
|
{ key: "cancelled", label: "已取消", n: s.cancelled },
|
||||||
];
|
];
|
||||||
return (
|
return (
|
||||||
|
|||||||
Reference in new issue
Block a user