Files
writer-work-flow/apps/web/components/chain/ChainProgress.tsx

75 lines
2.3 KiB
TypeScript
Raw Permalink 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.

"use client";
import { Badge } from "@/components/ui/Badge";
import { Card } from "@/components/ui/Card";
import type { BadgeVariant } from "@/lib/ui/variants";
import type { ChainPhase, ChainResultView } from "@/lib/chain/chain";
interface ChainProgressProps {
phase: ChainPhase;
progress: number;
result: ChainResultView;
}
const PHASE_LABEL: Record<ChainPhase, string> = {
running: "运行中",
awaiting: "等待裁决",
completed: "已完成",
failed: "已失败",
};
// 相位 → 语义色:失败用危险色而非朱砂品牌色,运行/等待/完成各取信息/警示/成功。
const PHASE_VARIANT: Record<ChainPhase, BadgeVariant> = {
running: "info",
awaiting: "warning",
completed: "success",
failed: "danger",
};
// 链进度视图:相位徽标 + 进度条 + 已写章号清单token/正文绝不展示result 只含元数据)。
export function ChainProgress({ phase, progress, result }: ChainProgressProps) {
return (
<Card
as="section"
className="flex flex-col gap-3 p-5"
aria-label="链进度"
>
<div className="flex items-center justify-between gap-3">
<h2 className="font-serif text-lg text-ink"></h2>
<Badge variant={PHASE_VARIANT[phase]} aria-live="polite">
{PHASE_LABEL[phase]}
</Badge>
</div>
<div
className="h-2 w-full overflow-hidden rounded bg-bg"
role="progressbar"
aria-label="链写章进度"
aria-valuenow={progress}
aria-valuemin={0}
aria-valuemax={100}
aria-valuetext={`已完成 ${result.written.length}`}
>
<div
className="h-full bg-cinnabar motion-safe:transition-all"
style={{ width: `${progress}%` }}
/>
</div>
<p className="text-sm text-ink-soft">
{result.written.length}
{result.written.length > 0 ? (
<span className="ml-1 font-mono text-ink">
{result.written.join("、")}
</span>
) : null}
</p>
{phase === "awaiting" && result.awaitingChapter !== null ? (
<p className="text-sm text-conflict">
{result.awaitingChapter}
</p>
) : null}
</Card>
);
}