Files
UHD_Media_Tool/apps/web/app/components/schedules/runs-sheet.tsx
T
rootandClaude Opus 5.5 89795802b5 docs(copy): 日志、计划、运行状态文案按 human-copy 重写
- 「立即执行」统一为「立即运行」,Toast 写「已加入队列」
- 巡检不再提「待处理」:触发条件写「有需要处理的事项时」,开关叫「生成巡检报告」
- 下载巡检触发条件写清包含失败的下载

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01Cxwgnn2pbzQ7rXv3rq7fei
2026-10-07 01:46:30 +08:00

70 lines
3.2 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import type { ScheduledJob } from "@umt/contracts";
import { History } from "lucide-react";
import { Link } from "react-router";
import { useScheduleRuns } from "~/api/schedules.ts";
import { DetailSheet } from "~/components/console/detail-sheet.tsx";
import { EmptyState, ErrorState, LoadingState } from "~/components/console/empty-state.tsx";
import { consolePath } from "~/components/console/nav.ts";
import { StatusBadge } from "~/components/console/status-badge.tsx";
import { useListPagination } from "~/components/console/use-list-pagination.ts";
import { Pagination } from "~/components/ui/pagination.tsx";
import { agentRunLabel } from "~/lib/labels.ts";
import { describeSchedule, formatClock, formatMs, RUN_STATUS, TRIGGER_LABEL } from "./labels.ts";
/** 历史抽屉:最近 50 次运行(新→旧) */
export function RunsSheet({ job, onClose }: { job: ScheduledJob | null; onClose: () => void }) {
const runs = useScheduleRuns(job?.id ?? null);
const items = runs.data?.items ?? [];
const paged = useListPagination(items, { resetKey: job?.id });
return (
<DetailSheet
open={!!job}
onOpenChange={(o) => !o && onClose()}
title={job ? `${job.name} · 运行记录` : "运行记录"}
description={
job ? `${describeSchedule(job.schedule)} · 累计 ${job.runCount} 次,失败 ${job.failCount} 次` : undefined
}
>
{runs.isPending ? (
<LoadingState rows={5} />
) : runs.isError ? (
<ErrorState plain error={runs.error} onRetry={() => runs.refetch()} />
) : items.length === 0 ? (
<EmptyState plain icon={History} title="还没有运行记录" />
) : (
<ol className="grid gap-2">
{paged.items?.map((r) => {
const s = RUN_STATUS[r.status];
return (
<li key={r.id} className="grid gap-1 rounded-tight border border-border/70 px-3 py-2">
<div className="flex flex-wrap items-center gap-x-2 gap-y-1 text-meta text-muted-foreground">
<StatusBadge tone={s.tone}>{s.label}</StatusBadge>
<span>{TRIGGER_LABEL[r.trigger]}</span>
<span className="tabular-nums" title={r.startedAt}>
{formatClock(r.startedAt)}
</span>
<span className="ml-auto tabular-nums">{formatMs(r.durationMs)}</span>
</div>
{r.error ? (
<p className="text-caption break-words text-destructive">{r.error}</p>
) : r.summary ? (
<p className="text-caption break-words text-foreground">{r.summary}</p>
) : null}
{r.agentRunId ? (
<Link
to={consolePath("agent", r.agentRunId)}
className="w-fit text-meta text-muted-foreground underline-offset-2 hover:text-foreground hover:underline"
>
查看智能体会话{r.agentStatus ? `(${agentRunLabel(r.agentStatus).label})` : ""}
</Link>
) : null}
</li>
);
})}
</ol>
)}
{items.length > 0 ? <Pagination {...paged.pagination} /> : null}
</DetailSheet>
);
}