Add structured job progress tracking

This commit is contained in:
2026-06-30 14:18:02 +08:00
parent 93af8bcd3a
commit 442b521705
8 changed files with 454 additions and 9 deletions

View File

@@ -25,6 +25,16 @@ import "./styles.css";
const API_BASE = import.meta.env.VITE_API_BASE ?? "http://localhost:8010";
type JobProgress = {
percent: number | null;
label: string;
stage: string;
current: number | null;
total: number | null;
unit: string | null;
source: string;
};
type Job = {
id: string;
type: string;
@@ -35,6 +45,7 @@ type Job = {
finished_at?: string;
log_tail?: string;
params: Record<string, unknown>;
progress?: JobProgress;
};
type Catalog = {
@@ -273,6 +284,21 @@ function StatusPill({ status }: { status: string }) {
return <span className={`pill pill-${status}`}>{status}</span>;
}
function JobProgressBar({ progress }: { progress?: JobProgress }) {
const percent = typeof progress?.percent === "number" ? Math.max(0, Math.min(100, progress.percent)) : 0;
return (
<div className="progressBox" data-stage={progress?.stage ?? "unknown"}>
<div className="progressTrack" aria-label={progress?.label ?? "job progress"}>
<span style={{ width: `${percent}%` }} />
</div>
<div className="progressMeta">
<span>{progress?.label ?? "等待日志"}</span>
<strong>{typeof progress?.percent === "number" ? `${progress.percent.toFixed(progress.percent % 1 ? 1 : 0)}%` : "..."}</strong>
</div>
</div>
);
}
function App() {
const { catalog, gpus, jobs, results, curves, datasets, datasetValidations, coverage, acceptance, deepAcceptance, error, refresh } = useData();
const [taskType, setTaskType] = useState("mock.echo");
@@ -553,9 +579,12 @@ function App() {
<div className="jobList">
{jobs.slice(0, 12).map((job) => (
<button key={job.id} className="jobRow" onClick={() => inspectJob(job)}>
<span>{job.type}</span>
<StatusPill status={job.status} />
<div className="jobRowTop">
<span>{job.type}</span>
<StatusPill status={job.status} />
</div>
<small>{job.description || job.id.slice(0, 8)}</small>
<JobProgressBar progress={job.progress} />
</button>
))}
</div>
@@ -836,6 +865,7 @@ function App() {
<Square size={18} />
</button>
</div>
{selectedJob && <JobProgressBar progress={selectedJob.progress} />}
<pre>{log || "No log selected."}</pre>
</div>