feat(monitor): 当前阶段进度放大——「当前步骤 · X」的百分比 20px 加粗、阶段进度条 14px 高(原来 12.5px/8px 太小);顶部步骤条当前格的百分比也放大加色;顺带把已完成格子的「用时」改用累计值(续跑的阶段不再只显示最后一段)

This commit is contained in:
cbb
2026-10-18 17:13:35 +08:00
parent db0bbbc15d
commit c65b9986ca
+8 -5
View File
@@ -57,6 +57,7 @@
.step.active .ic { background: #5aa9ff22; border-color: var(--accent); color: var(--accent); box-shadow: 0 0 0 4px #5aa9ff1f; } .step.active .ic { background: #5aa9ff22; border-color: var(--accent); color: var(--accent); box-shadow: 0 0 0 4px #5aa9ff1f; }
.step.fail .ic { background: #f8717122; border-color: var(--bad); color: var(--bad); } .step.fail .ic { background: #f8717122; border-color: var(--bad); color: var(--bad); }
.step .nm { font-size: 12.5px; color: var(--text); white-space: nowrap; } .step .ds { font-size: 11px; color: var(--dim2); white-space: nowrap; } .step .nm { font-size: 12.5px; color: var(--text); white-space: nowrap; } .step .ds { font-size: 11px; color: var(--dim2); white-space: nowrap; }
.step .ds.big { font-size: 14px; font-weight: 650; color: var(--accent); }
.step.pending .nm { color: var(--dim); } .step.pending .nm { color: var(--dim); }
.step.active .ds { color: var(--accent); } .step.active .ds { color: var(--accent); }
@@ -127,8 +128,9 @@
button.danger { color: var(--bad); border-color: #f8717166; } button.danger:hover { background: #f8717114; } button.danger { color: var(--bad); border-color: #f8717166; } button.danger:hover { background: #f8717114; }
.overall { display: flex; align-items: flex-end; justify-content: space-between; gap: 16px; flex-wrap: wrap; } .overall { display: flex; align-items: flex-end; justify-content: space-between; gap: 16px; flex-wrap: wrap; }
.overall .now { font-size: 13px; color: var(--dim); } .overall .now b { display: block; color: var(--text); font-size: 18px; font-weight: 650; margin: 2px 0 2px; } .overall .now { font-size: 13px; color: var(--dim); } .overall .now b { display: block; color: var(--text); font-size: 18px; font-weight: 650; margin: 2px 0 2px; }
.sublabel { font-size: 12.5px; color: var(--dim); display: flex; justify-content: space-between; margin-top: 4px; } .sublabel { font-size: 15px; color: var(--dim); display: flex; justify-content: space-between; align-items: baseline; margin-top: 6px; }
.bar.thin { height: 8px; margin: 8px 0 4px; } .bar.ind .fill { width: 30% !important; animation: ind 1.6s ease-in-out infinite; } .sublabel b { font: 700 20px/1 var(--mono); color: var(--text); }
.bar.thin { height: 14px; margin: 10px 0 4px; } .bar.ind .fill { width: 30% !important; animation: ind 1.6s ease-in-out infinite; }
@keyframes ind { 0% { margin-left: 0; } 50% { margin-left: 70%; } 100% { margin-left: 0; } } @keyframes ind { 0% { margin-left: 0; } 50% { margin-left: 70%; } 100% { margin-left: 0; } }
.ctlrow { display: flex; gap: 10px; margin-top: 14px; align-items: center; flex-wrap: wrap; } .ctlrow { display: flex; gap: 10px; margin-top: 14px; align-items: center; flex-wrap: wrap; }
.ctlrow .hint { font-size: 12px; color: var(--dim2); } .ctlrow .hint { font-size: 12px; color: var(--dim2); }
@@ -500,11 +502,12 @@ function stages(s) {
if (P) { // 有流水线记录:以它为准 if (P) { // 有流水线记录:以它为准
const plan = P.plan && P.plan.length ? P.plan : STAGE_META.map(x => x[0]).filter(k => k !== 'setup'); const plan = P.plan && P.plan.length ? P.plan : STAGE_META.map(x => x[0]).filter(k => k !== 'setup');
const keys = STAGE_META.map(x => x[0]).filter(k => plan.includes(k) || P.stages[k]); const keys = STAGE_META.map(x => x[0]).filter(k => plan.includes(k) || P.stages[k]);
const el = P.elapsed || {}; // 累计用时(跨停止/续跑),没有就退回本段
return keys.map(k => { return keys.map(k => {
const r = P.stages[k], nm = SM[k].n; const r = P.stages[k], nm = SM[k].n;
if (!r) return [nm, 'pending', '—']; if (!r) return [nm, 'pending', '—'];
if (P.current === k) return [nm, 'active', P.progress && P.progress.frac != null ? pct(P.progress.frac, 0) : '进行中']; if (P.current === k) return [nm, 'active', P.progress && P.progress.frac != null ? pct(P.progress.frac, 0) : '进行中'];
if (r.rc === 0) return [nm, 'done', '用时 ' + hmsShort(r.end - r.start)]; if (r.rc === 0) return [nm, 'done', '用时 ' + hmsShort(el[k] != null ? el[k] : r.end - r.start)];
if (r.rc === -15 || r.rc === 143) return [nm, 'fail', '已停止']; if (r.rc === -15 || r.rc === 143) return [nm, 'fail', '已停止'];
if (r.rc != null) return [nm, 'fail', `失败(返回码 ${r.rc})`]; if (r.rc != null) return [nm, 'fail', `失败(返回码 ${r.rc})`];
return [nm, 'fail', '中断']; return [nm, 'fail', '中断'];
@@ -531,7 +534,7 @@ function stages(s) {
} }
function renderStatus(s) { function renderStatus(s) {
const L = stages(s); const L = stages(s);
$('steps').innerHTML = L.map(([nm, st, ds], i) => `<div class="step ${st}"><div class="ic">${st === 'done' ? '✓' : st === 'fail' ? '!' : i + 1}</div><div class="nm">${nm}</div><div class="ds">${ds}</div></div>`).join(''); $('steps').innerHTML = L.map(([nm, st, ds], i) => `<div class="step ${st}"><div class="ic">${st === 'done' ? '✓' : st === 'fail' ? '!' : i + 1}</div><div class="nm">${nm}</div><div class="ds${st === 'active' ? ' big' : ''}">${ds}</div></div>`).join('');
const nDone = L.filter(x => x[1] === 'done').length; $('stepnote').textContent = `${nDone} / ${L.length} 完成`; const nDone = L.filter(x => x[1] === 'done').length; $('stepnote').textContent = `${nDone} / ${L.length} 完成`;
// GPU + CPU(同一个框:上面是 GPU 环 + 显存/温度/功耗,下面接 CPU 总占用与每核条) // GPU + CPU(同一个框:上面是 GPU 环 + 显存/温度/功耗,下面接 CPU 总占用与每核条)
@@ -630,7 +633,7 @@ function renderPipe(s) {
$('pipe').innerHTML = `<h2><span>全流程</span><span class="r">${doneN} / ${plan.length} 步完成</span></h2> $('pipe').innerHTML = `<h2><span>全流程</span><span class="r">${doneN} / ${plan.length} 步完成</span></h2>
<div class="overall">${head}<div class="bigpct">${(100 * frac).toFixed(1)}<small>%</small></div></div> <div class="overall">${head}<div class="bigpct">${(100 * frac).toFixed(1)}<small>%</small></div></div>
<div class="bar ${cur ? '' : 'idle'}"><div class="fill" style="width:${100 * frac}%"></div></div> <div class="bar ${cur ? '' : 'idle'}"><div class="fill" style="width:${100 * frac}%"></div></div>
${cur ? `<div class="sublabel"><span>当前步骤 · ${SM[cur]?.n}</span><span>${pr.frac != null ? pct(pr.frac) : '无法计量,按用时估'}</span></div> ${cur ? `<div class="sublabel"><span>当前步骤 · ${SM[cur]?.n}</span>${pr.frac != null ? `<b>${pct(pr.frac)}</b>` : '<span>无法计量,按用时估</span>'}</div>
<div class="bar thin ${pr.frac == null ? 'ind' : ''}"><div class="fill" style="width:${pr.frac != null ? 100 * pr.frac : 30}%"></div></div>` : ''} <div class="bar thin ${pr.frac == null ? 'ind' : ''}"><div class="fill" style="width:${pr.frac != null ? 100 * pr.frac : 30}%"></div></div>` : ''}
<div class="facts"> <div class="facts">
<div class="fact"><div class="k">总用时</div><div class="v">${hms(plan.reduce((a, k) => a + ((P.elapsed || {})[k] || 0), 0))}</div></div> <div class="fact"><div class="k">总用时</div><div class="v">${hms(plan.reduce((a, k) => a + ((P.elapsed || {})[k] || 0), 0))}</div></div>