fix: replace raw codes and internal IDs in the console with Chinese labels
Found in v0.2 visual QA (docs/plan/09-visual-qa.md): - actor strings (admin_session:<uuid>, user:<uuid>, system) -> 管理员/系统/API Key in policy revisions, subscriptions, inbox, trash, business tasks, organize detail - cache volume without key shows the downloader name instead of instance:<uuid> - download timeline/plan: task and organize statuses, plan purpose, priority and status reason localized; audit gets labels for capability/files/site/feed actions - organize record reason uses conflict detail (没有可入库的主视频) instead of blocked:no_main_video; slot/candidate reasons drop inflight:<uuid> - identity decision summary no longer shows no_viable_candidate - upstream test: 'Connection error.' classified as network, with a Chinese hint - new policy draft prefills key default (placeholder looked like a value) - dialog/sheet close sr-only text in Chinese Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
1 parent
d7eb6a45d0
commit
46d37d87fe
23 files changed
+176
-43
No files matched your search
@@ -15,6 +15,7 @@ import { useQueryState } from "~/components/console/use-query-state.ts";
|
||||
import { Button } from "~/components/ui/button.tsx";
|
||||
import { relTime } from "~/components/workbench/release-fields.ts";
|
||||
import { errorMessage, TTL_SECOND } from "~/lib/api.ts";
|
||||
import { actorText } from "~/lib/labels.ts";
|
||||
import { formatDateTime } from "~/lib/utils.ts";
|
||||
|
||||
// 业务任务(/tasks):引擎只负责推进,task 表是面向用户的投影;取消只停后续步骤,重试只对失败任务。
|
||||
@@ -201,7 +202,7 @@ export function BusinessTasks() {
|
||||
key: "by",
|
||||
header: "触发",
|
||||
hideBelow: "lg",
|
||||
cell: (t) => <span className="text-muted-foreground">{t.triggeredBy ?? "—"}</span>,
|
||||
cell: (t) => <span className="text-muted-foreground">{actorText(t.triggeredBy)}</span>,
|
||||
},
|
||||
{
|
||||
key: "at",
|
||||
@@ -294,7 +295,7 @@ export function TaskSummary({ t }: { t: Task }) {
|
||||
<KvList
|
||||
items={[
|
||||
{ label: "尝试", value: `${t.attempts}/${t.maxAttempts}` },
|
||||
{ label: "触发", value: t.triggeredBy },
|
||||
{ label: "触发", value: actorText(t.triggeredBy) },
|
||||
{ label: "创建", value: formatDateTime(t.createdAt) },
|
||||
{ label: "开始", value: formatDateTime(t.startedAt) },
|
||||
{ label: "结束", value: formatDateTime(t.finishedAt) },
|
||||
|
||||
@@ -3,6 +3,7 @@ import { Brush, HardDrive, SlidersHorizontal } from "lucide-react";
|
||||
import { Link, useNavigate } from "react-router";
|
||||
import { toast } from "sonner";
|
||||
import { useCacheCleanup, useCacheVolumes } from "~/api/downloads.ts";
|
||||
import { downloaders } from "~/api/instances.ts";
|
||||
import { ConfirmDialog } from "~/components/console/confirm-dialog.tsx";
|
||||
import { ErrorState, LoadingState } from "~/components/console/empty-state.tsx";
|
||||
import { consolePath, settingsPath } from "~/components/console/nav.ts";
|
||||
@@ -13,7 +14,18 @@ import { cn, formatBytes } from "~/lib/utils.ts";
|
||||
|
||||
type Volume = Dashboard["cache"]["volumes"][number];
|
||||
|
||||
/** 缓存卷显示名:没填缓存卷标识时服务端用 `instance:<id>`,换成下载器实例名,不露内部 ID */
|
||||
export function useVolumeLabel() {
|
||||
const list = downloaders.useList();
|
||||
return (v: Pick<Volume, "volumeKey" | "instanceIds">) => {
|
||||
if (!v.volumeKey.startsWith("instance:")) return v.volumeKey;
|
||||
const names = v.instanceIds.map((id) => list.data?.items.find((i) => i.id === id)?.name).filter(Boolean);
|
||||
return names.length ? names.join("、") : "下载器缓存";
|
||||
};
|
||||
}
|
||||
|
||||
function VolumeBar({ v }: { v: Volume }) {
|
||||
const volumeLabel = useVolumeLabel();
|
||||
const pct = v.usedPercent;
|
||||
const tripped = pct !== null && pct >= v.hardThresholdPercent;
|
||||
const nearing = pct !== null && !tripped && pct >= v.resumePercent;
|
||||
@@ -22,7 +34,7 @@ function VolumeBar({ v }: { v: Volume }) {
|
||||
<div className="flex flex-wrap items-baseline justify-between gap-2">
|
||||
<span className="flex min-w-0 items-center gap-1.5 text-sm font-medium text-foreground">
|
||||
<HardDrive className="h-3.5 w-3.5 shrink-0 text-muted-foreground" />
|
||||
<span className="truncate">{v.volumeKey}</span>
|
||||
<span className="truncate">{volumeLabel(v)}</span>
|
||||
</span>
|
||||
<span className="text-meta text-muted-foreground tabular-nums">
|
||||
{pct === null ? "使用率未知" : `${pct.toFixed(1)}%`}
|
||||
|
||||
@@ -20,10 +20,13 @@ import { StatusBadge } from "~/components/console/status-badge.tsx";
|
||||
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 { formatBytes, formatDateTime } from "~/lib/utils.ts";
|
||||
import { BusinessTimeline } from "./business-timeline.tsx";
|
||||
import { OrganizeDialog } from "./organize-dialog.tsx";
|
||||
|
||||
const PLAN_PURPOSE_LABEL: Record<string, string> = { fill: "补缺", upgrade: "升级", replace_source: "换源" };
|
||||
|
||||
/** 进度:细线 + 文字;总量未知时不伪造百分比 */
|
||||
export function ProgressLine({ t }: { t: DownloadTask }) {
|
||||
const known = t.sizeBytes !== null;
|
||||
@@ -166,9 +169,9 @@ export function DownloadDetail({ task }: { task: DownloadTask }) {
|
||||
<KvList
|
||||
items={[
|
||||
{ label: "状态", value: PLAN_STATUS_LABEL[plan.data.status] },
|
||||
{ label: "用途", value: plan.data.purpose },
|
||||
{ label: "用途", value: PLAN_PURPOSE_LABEL[plan.data.purpose] ?? plan.data.purpose },
|
||||
{ label: "预留空间", value: formatBytes(plan.data.reservedBytes, 1) },
|
||||
{ label: "说明", value: plan.data.statusReason, wide: true },
|
||||
{ label: "说明", value: planReasonText(plan.data.statusReason), wide: true },
|
||||
]}
|
||||
/>
|
||||
<JsonView className="mt-2" label="评估依据" value={plan.data.evaluation} />
|
||||
|
||||
Reference in new issue
Block a user