feat: show request progress timing

This commit is contained in:
Codex
2026-06-21 23:43:03 +08:00
parent 60cf55f755
commit fd7e92b026
3 changed files with 202 additions and 6 deletions
+82
View File
@@ -0,0 +1,82 @@
"use client";
import {
formatElapsedSeconds,
getElapsedNotice,
getProgressStages,
type ProgressAction,
} from "../lib/progress/progress";
interface TimingStep {
label: string;
duration_ms: number;
}
interface TimingSummary {
total_ms: number;
steps: TimingStep[];
}
interface ProgressPanelProps {
action: ProgressAction | null;
elapsedSeconds: number;
lastTiming: TimingSummary | null;
}
export function ProgressPanel({
action,
elapsedSeconds,
lastTiming,
}: ProgressPanelProps) {
if (!action && !lastTiming) return null;
const completedTiming = lastTiming;
return (
<section className="progress-panel" aria-live="polite">
{action ? (
<>
<div className="progress-summary">
<strong>{getActionLabel(action)}</strong>
<span> {formatElapsedSeconds(elapsedSeconds)}</span>
</div>
<p>{getElapsedNotice(elapsedSeconds)}</p>
<ol className="progress-steps">
{getProgressStages(action).map((stage) => (
<li key={stage.label}>{stage.label}</li>
))}
</ol>
</>
) : completedTiming ? (
<>
<div className="progress-summary">
<strong></strong>
<span>{formatMilliseconds(completedTiming.total_ms)}</span>
</div>
{completedTiming.steps.length > 0 && (
<ol className="progress-steps">
{completedTiming.steps.map((step) => (
<li key={`${step.label}-${step.duration_ms}`}>
{step.label}: {formatMilliseconds(step.duration_ms)}
</li>
))}
</ol>
)}
</>
) : null}
</section>
);
}
function getActionLabel(action: ProgressAction) {
if (action === "analyze") return "正在分析文章";
if (action === "confirm") return "正在确认事实卡";
return "正在优化文章";
}
function formatMilliseconds(milliseconds: number) {
const seconds = Math.round(milliseconds / 1000);
if (seconds < 60) return `${seconds}`;
const minutes = Math.floor(seconds / 60);
const remainingSeconds = seconds % 60;
return `${minutes}${remainingSeconds}`;
}