Files
UHD_Media_Tool/apps/web/app/components/downloads/business-timeline.tsx
T

66 lines
2.5 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 { ExternalLink } from "lucide-react";
import { Link } from "react-router";
import type { TimelineEvent, TimelineStage } from "~/api/tasks.ts";
import { LoadingState } from "~/components/console/empty-state.tsx";
import { StatusBadge } from "~/components/console/status-badge.tsx";
import { Timeline } from "~/components/console/timeline.tsx";
// 业务时间线(参考 MovieClaw task-activity):把观察 → 计划 → 下载 → 整理 → Agent 串成一个业务过程,
// 阶段计数与首页/侧栏同口径;每条事件都有文字说明,不只靠颜色。
export const STAGE_LABEL: Record<TimelineStage, string> = {
observation: "发现",
plan: "准备",
download: "下载",
organization: "整理",
agent: "智能体",
engine: "任务",
};
const ORDER: TimelineStage[] = ["observation", "plan", "download", "organization", "agent", "engine"];
export function BusinessTimeline({ events, loading }: { events: TimelineEvent[]; loading?: boolean }) {
const counts = new Map<TimelineStage, number>();
for (const e of events) counts.set(e.stage, (counts.get(e.stage) ?? 0) + 1);
const ongoing = events.filter((e) => e.ongoing);
return (
<div className="space-y-3">
<div className="flex flex-wrap gap-1.5">
{ORDER.filter((s) => counts.get(s)).map((s) => {
const bad = events.some((e) => e.stage === s && e.tone === "destructive");
return (
<StatusBadge key={s} tone={bad ? "destructive" : "neutral"}>
{STAGE_LABEL[s]} · {counts.get(s)}
</StatusBadge>
);
})}
</div>
{ongoing.length ? (
<p className="text-caption text-muted-foreground">当前:{ongoing.map((e) => e.title).join(";")}</p>
) : null}
{loading && !events.length ? (
<LoadingState rows={3} />
) : (
<Timeline
items={events.map((e) => ({
id: e.key,
at: e.at,
tone: e.tone,
meta: STAGE_LABEL[e.stage],
title: e.href ? (
<Link to={e.href} className="inline-flex items-center gap-1 underline-offset-4 hover:underline">
{e.title}
<ExternalLink className="h-3 w-3" />
</Link>
) : (
e.title
),
description: e.detail ?? undefined,
}))}
/>
)}
{loading && events.length ? <p className="text-meta text-muted-foreground">加载整理记录和引擎运行…</p> : null}
</div>
);
}