feat: show request progress timing
This commit is contained in:
@@ -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} 秒`;
|
||||
}
|
||||
Reference in New Issue
Block a user