chore(web): 合并 U / V / W 后的收尾——剩余「入库」文案、设置新分区深链、冒烟锚点

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01Cxwgnn2pbzQ7rXv3rq7fei
This commit is contained in:
rootandClaude Opus 5.5 committed 2026-10-06 18:25:20 +08:00
1 parent ee3ebcb25c
commit f397687a5f
11 files changed
+31 -36

No files matched your search

+1 -1
View File
@@ -110,7 +110,7 @@ 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: "处理待处理事项",
+1 -1
View File
@@ -88,7 +88,7 @@ describe("控制台导航", () => {
}); });
it("settingsPath 只认新分区名", () => { it("settingsPath 只认新分区名", () => {
expect(settingsPath("automation", "cache")).toBe("/console/settings#automation/cache"); expect(settingsPath("downloaders", "cache")).toBe("/console/settings#downloaders/cache");
expect(settingsPath("agent")).toBe("/console/settings#agent"); expect(settingsPath("agent")).toBe("/console/settings#agent");
}); });
}); });
+9 -6
View File
@@ -51,7 +51,7 @@ export const NAV_GROUPS: NavGroup[] = [
to: "/console", to: "/console",
label: "首页", label: "首页",
icon: House, icon: House,
description: "在忙什么、要我处理什么、最近入库了什么", description: "在忙什么、要我处理什么、最近整理了什么",
}, },
{ {
to: "/console/agent", to: "/console/agent",
@@ -139,15 +139,18 @@ export const NAV_ITEMS = NAV_GROUPS.flatMap((g) => g.items);
/** 设置页深链(IA-2):`/console/settings#分区[/节]`。调用方只认新分区名 */ /** 设置页深链(IA-2):`/console/settings#分区[/节]`。调用方只认新分区名 */
export type SettingsSection = export type SettingsSection =
| "automation"
| "sites"
| "downloaders" | "downloaders"
| "library"
| "media-servers" | "media-servers"
| "sites"
| "metadata" | "metadata"
| "acquire"
| "library"
| "organize"
| "agent" | "agent"
| "api-keys" | "system"
| "account"; | "cache"
| "account"
| "interface";
export function settingsPath(section: SettingsSection, anchor?: string): string { export function settingsPath(section: SettingsSection, anchor?: string): string {
return `${CONSOLE_BASE}/settings#${section}${anchor ? `/${anchor}` : ""}`; return `${CONSOLE_BASE}/settings#${section}${anchor ? `/${anchor}` : ""}`;
} }
@@ -28,7 +28,7 @@ export const TASK_KIND_LABEL: Record<TaskKind, string> = {
resolveObservation: "识别资源", resolveObservation: "识别资源",
evaluateAcquisition: "评估候选", evaluateAcquisition: "评估候选",
submitDownload: "提交下载", submitDownload: "提交下载",
verifyAndImport: "核验入库", verifyAndImport: "核验整理",
refreshMetadata: "刷新元数据", refreshMetadata: "刷新元数据",
reconcileLibrary: "文件核对", reconcileLibrary: "文件核对",
cleanupDownloadCache: "清理缓存", cleanupDownloadCache: "清理缓存",
@@ -246,7 +246,7 @@ export function BusinessTasks() {
empty={{ empty={{
icon: ListTodo, icon: ListTodo,
title: f.active ? "没有符合筛选的任务" : "还没有业务任务", title: f.active ? "没有符合筛选的任务" : "还没有业务任务",
description: f.active ? undefined : "提交下载、核验入库、清理缓存、对账等后台任务会出现在这里。", description: f.active ? undefined : "提交下载、核验整理、清理缓存、对账等后台任务会出现在这里。",
}} }}
/> />
<DetailSheet <DetailSheet
@@ -106,7 +106,7 @@ export function CacheVolumes() {
<h2 className="text-label font-semibold tracking-[0.18em] text-muted-foreground uppercase">下载盘</h2> <h2 className="text-label font-semibold tracking-[0.18em] text-muted-foreground uppercase">下载盘</h2>
<div className="flex flex-wrap gap-2"> <div className="flex flex-wrap gap-2">
<Button asChild variant="ghost" size="sm"> <Button asChild variant="ghost" size="sm">
<Link to={settingsPath("automation", "cache")}> <Link to={settingsPath("downloaders", "cache")}>
<SlidersHorizontal /> <SlidersHorizontal />
调整阈值 调整阈值
</Link> </Link>
@@ -20,7 +20,7 @@ import { cn, formatBytes, formatDateTime } from "~/lib/utils.ts";
// 运行状态页「存储」节(FIX-5):GET /system/health 的存储告警 + GET /system/storage 明细(库体积与预算、表 top 10、 // 运行状态页「存储」节(FIX-5):GET /system/health 的存储告警 + GET /system/storage 明细(库体积与预算、表 top 10、
// 缓存用量、图片 / 备份 / 会话与证据、DATA_DIR 分目录、各清理任务),手动清理调 POST /system/storage/cleanup/{target}。 // 缓存用量、图片 / 备份 / 会话与证据、DATA_DIR 分目录、各清理任务),手动清理调 POST /system/storage/cleanup/{target}。
// 预算与保留期在「设置 → 自动化 → 存储与保留」改,见 docs/runbook/storage.md。 // 预算与保留期在「设置 → 系统 → 存储预算 / 数据保留」改,见 docs/runbook/storage.md。
const LEVEL: Record<HealthLevel, { label: string; tone: StatusTone }> = { const LEVEL: Record<HealthLevel, { label: string; tone: StatusTone }> = {
ok: { label: "正常", tone: "success" }, ok: { label: "正常", tone: "success" },
+1 -1
View File
@@ -36,7 +36,7 @@ export const WORKFLOW_LABEL: Record<string, string> = {
resolveObservation: "识别资源", resolveObservation: "识别资源",
evaluateAcquisition: "评估候选", evaluateAcquisition: "评估候选",
submitDownload: "提交下载", submitDownload: "提交下载",
verifyAndImport: "核验入库", verifyAndImport: "核验整理",
scrapeMedia: "刮削", scrapeMedia: "刮削",
refreshMetadata: "刷新元数据", refreshMetadata: "刷新元数据",
reconcileLibrary: "文件核对", reconcileLibrary: "文件核对",
+9 -9
View File
@@ -36,7 +36,7 @@ import { qk } from "~/lib/query-keys.ts";
import { useSse } from "~/lib/sse.ts"; import { useSse } from "~/lib/sse.ts";
import { cn } from "~/lib/utils.ts"; import { cn } from "~/lib/utils.ts";
// 首页概览:自动化、存储与下载器状态,以及当前工作、要我处理的汇总计数(整理需要处理 / 等你批准 / 系统健康)和最近入库。 // 首页概览:自动化、存储与下载器状态,以及当前工作、要我处理的汇总计数(整理需要处理 / 等你批准 / 系统健康)和最近整理。
/** 首页关心的事件:任意一个到达就(节流)刷新聚合 */ /** 首页关心的事件:任意一个到达就(节流)刷新聚合 */
const DASHBOARD_EVENTS = [ const DASHBOARD_EVENTS = [
@@ -102,7 +102,7 @@ function Row({ children }: { children: ReactNode }) {
return <li className="flex min-w-0 items-center justify-between gap-3 py-1.5 text-sm">{children}</li>; return <li className="flex min-w-0 items-center justify-between gap-3 py-1.5 text-sm">{children}</li>;
} }
/** 非零项拼一句:[[3, "个下载"], [0, "个入库中"]] → "3 个下载" */ /** 非零项拼一句:[[3, "个下载"], [0, "个整理中"]] → "3 个下载" */
function nonZero(parts: [number, string][]): string { function nonZero(parts: [number, string][]): string {
return parts return parts
.filter(([n]) => n > 0) .filter(([n]) => n > 0)
@@ -157,7 +157,7 @@ function StatusLine({ d }: { d: Dashboard }) {
) : a.readOnlyReconcile ? ( ) : a.readOnlyReconcile ? (
<> <>
只读模式:不会自动下载和整理。 只读模式:不会自动下载和整理。
<Link to={settingsPath("automation", "advanced")} className="underline underline-offset-4"> <Link to={settingsPath("system", "readonly")} className="underline underline-offset-4">
去设置关闭 去设置关闭
</Link> </Link>
</> </>
@@ -211,7 +211,7 @@ function Busy({ w }: { w: Dashboard["currentWork"] }) {
const agents = w.agentRuns.slice(0, 2); const agents = w.agentRuns.slice(0, 2);
const summary = nonZero([ const summary = nonZero([
[w.downloading, "个下载中"], [w.downloading, "个下载中"],
[w.importing, "个入库中"], [w.importing, "个整理中"],
[w.stalled, "个没有进展"], [w.stalled, "个没有进展"],
[w.paused, "个已暂停"], [w.paused, "个已暂停"],
]); ]);
@@ -275,14 +275,14 @@ function NeedsMe() {
); );
} }
// ─── 最近入库了什么:成功 / 部分成功的整理 ─── // ─── 最近整理了什么:成功 / 部分成功的整理 ───
function RecentImports({ d }: { d: Dashboard }) { function RecentImports({ d }: { d: Dashboard }) {
const rows = d.recentOutput.filter((r) => r.status === "succeeded" || r.status === "partial").slice(0, 6); const rows = d.recentOutput.filter((r) => r.status === "succeeded" || r.status === "partial").slice(0, 6);
const today = d.automation.today.filesImported; const today = d.automation.today.filesImported;
return ( return (
<Section title="最近入库" icon={LibraryIcon} to={consolePath("organize")}> <Section title="最近整理" icon={LibraryIcon} to={consolePath("organize")}>
{rows.length === 0 ? ( {rows.length === 0 ? (
<EmptyState plain icon={LibraryIcon} title="最近没有新入库的作品" className="py-6" /> <EmptyState plain icon={LibraryIcon} title="最近没有新整理的作品" className="py-6" />
) : ( ) : (
<ul className="divide-y divide-border/60"> <ul className="divide-y divide-border/60">
{rows.map((r) => ( {rows.map((r) => (
@@ -294,7 +294,7 @@ function RecentImports({ d }: { d: Dashboard }) {
<span className="block truncate">{r.title ?? r.targetPath?.split("/").pop() ?? "未关联作品"}</span> <span className="block truncate">{r.title ?? r.targetPath?.split("/").pop() ?? "未关联作品"}</span>
{r.status === "partial" ? ( {r.status === "partial" ? (
<span className="block text-meta text-warning"> <span className="block text-meta text-warning">
{r.counts.succeeded}/{r.counts.total} 个文件入库 {r.counts.succeeded}/{r.counts.total} 个文件已整理
</span> </span>
) : null} ) : null}
</Link> </Link>
@@ -303,7 +303,7 @@ function RecentImports({ d }: { d: Dashboard }) {
))} ))}
</ul> </ul>
)} )}
{today ? <p className="mt-auto pt-3 text-meta text-muted-foreground">今天入库 {today} 个文件</p> : null} {today ? <p className="mt-auto pt-3 text-meta text-muted-foreground">今天整理 {today} 个文件</p> : null}
</Section> </Section>
); );
} }
+1 -1
View File
@@ -59,7 +59,7 @@ const OP_KIND: Record<AssetOperation["kind"], string> = {
delete_source: "删除源文件", delete_source: "删除源文件",
delete_target: "删除目标文件", delete_target: "删除目标文件",
verify: "校验", verify: "校验",
register: "登记入库", register: "登记",
qb_pause: "暂停下载", qb_pause: "暂停下载",
qb_resume: "恢复下载", qb_resume: "恢复下载",
qb_remove: "移除下载", qb_remove: "移除下载",
+5 -3
View File
@@ -75,9 +75,11 @@ const STATIC_ROUTES = [
"/console/settings#media-servers", "/console/settings#media-servers",
"/console/settings#metadata", "/console/settings#metadata",
"/console/settings#agent", "/console/settings#agent",
"/console/settings#api-keys", "/console/settings#acquire",
"/console/settings#organize",
"/console/settings#system",
"/console/settings#cache",
"/console/settings#interface", "/console/settings#interface",
"/console/settings#automation/advanced",
"/console/settings#account", "/console/settings#account",
]; ];
@@ -128,7 +130,7 @@ const REDIRECT_ROUTES = [
{ from: "/console/identity?tab=external", to: "/console/library?view=identities" }, { from: "/console/identity?tab=external", to: "/console/library?view=identities" },
// 设置旧页签 ?tab= → 分区 hash(IA-2) // 设置旧页签 ?tab= → 分区 hash(IA-2)
{ from: "/console/settings?tab=pi", to: "/console/settings#agent" }, { from: "/console/settings?tab=pi", to: "/console/settings#agent" },
{ from: "/console/settings?tab=storage", to: "/console/settings#automation/cache" }, { from: "/console/settings?tab=storage", to: "/console/settings#downloaders/cache" },
{ from: "/console/settings?tab=path-mappings", to: "/console/settings#downloaders" }, { from: "/console/settings?tab=path-mappings", to: "/console/settings#downloaders" },
{ from: "/console/settings?tab=site-credentials", to: "/console/settings#sites" }, { from: "/console/settings?tab=site-credentials", to: "/console/settings#sites" },
]; ];
-10
View File
@@ -59,16 +59,6 @@ const TERM_PENDING = new Set([
"apps/web/app/components/agent/mock.ts", "apps/web/app/components/agent/mock.ts",
"apps/web/app/components/agent/quick-goals.ts", "apps/web/app/components/agent/quick-goals.ts",
"apps/web/app/api/agent.ts", "apps/web/app/api/agent.ts",
"apps/web/app/api/tasks.ts",
"apps/web/app/components/console/nav.ts",
"apps/web/app/components/downloads/business-tasks.tsx",
"apps/web/app/components/settings/automation.tsx",
"apps/web/app/components/settings/instances.tsx",
"apps/web/app/components/settings/library.tsx",
"apps/web/app/components/settings/organize-sources.tsx",
"apps/web/app/components/tasks/labels.ts",
"apps/web/app/routes/console/home.tsx",
"apps/web/app/routes/console/tasks.$id.tsx",
"apps/server/src/modules/agent/report.ts", "apps/server/src/modules/agent/report.ts",
]); ]);
let termScope = true; let termScope = true;