mirror of
https://gitcode.com/JianFeeeee/ModelRouter.git
synced 2026-09-20 00:48:00 +00:00
fix(ui): stop rebuilding the five KPI cards every 3s poll (was causing a visible flicker)
paintStats() rewrote #kpi-row innerHTML on every 3s refresh, destroying/recreating all five cards + canvases each time -> each poll flashed. Now the card structure is built once (dataset.built guard) and subsequent polls only update the value text (data-kpi attrs) and redraw the canvases. Preserves colored success rate and two-line in/out tokens. Deployed (bak .bak.20260811t), server active.
This commit is contained in:
@ -766,37 +766,52 @@ async function paintStats() {
|
||||
const okr = tot.reqs ? Math.round(tot.ok * 100 / tot.reqs) : 0;
|
||||
const avg = fmtLat(tot.latency_sum_ms, tot.reqs);
|
||||
const kpi = $('#kpi-row');
|
||||
if (kpi) kpi.innerHTML = `
|
||||
if (kpi && !kpi.dataset.built) {
|
||||
kpi.dataset.built = '1';
|
||||
kpi.innerHTML = `
|
||||
<div class="kpi${statsKeyF ? ' kpi-exit' : ''}" title="${statsKeyF ? t('exitKeyView') : ''}" onclick="${statsKeyF ? `renderKeyF('${escAttr(statsKeyF)}')` : ''}">
|
||||
<div class="k-hdr"><span class="k-lab">${t('kpiActive')} <span class="dot"></span></span></div>
|
||||
<div class="k-val">${st.active || 0}</div>
|
||||
<div class="k-val" data-kpi="active"></div>
|
||||
<div class="k-sub">reqs / 3s</div>
|
||||
<div class="k-chart"><canvas id="cv-active"></canvas></div>
|
||||
</div>
|
||||
<div class="kpi">
|
||||
<div class="k-hdr"><span class="k-lab">${t('kpiReqs')}</span></div>
|
||||
<div class="k-val">${fmtN(tot.reqs)}</div>
|
||||
<div class="k-sub">${t('kpiOk')} <b class="${okr >= 90 ? 'okc' : 'errc'}">${okr}%</b></div>
|
||||
<div class="k-val" data-kpi="reqs"></div>
|
||||
<div class="k-sub" data-kpi="reqs-sub"></div>
|
||||
<div class="k-chart"><canvas id="cv-reqs"></canvas></div>
|
||||
</div>
|
||||
<div class="kpi">
|
||||
<div class="k-hdr"><span class="k-lab">${t('kpiTokens')}</span></div>
|
||||
<div class="k-val">${fmtTok(tot.tokens)}</div>
|
||||
<div class="k-sub k2"><span>${t('thPrompt')} ${fmtTok(tot.prompt_tokens)}</span><span>${t('thCompl')} ${fmtTok(tot.completion_tokens)}</span></div>
|
||||
<div class="k-val" data-kpi="tokens"></div>
|
||||
<div class="k-sub k2" data-kpi="tokens-sub"></div>
|
||||
<div class="k-chart"><canvas id="cv-tokens"></canvas></div>
|
||||
<div class="status-legend" id="tb-tokens-legend"></div>
|
||||
</div>
|
||||
<div class="kpi">
|
||||
<div class="k-hdr"><span class="k-lab">${t('kpiLat')}</span></div>
|
||||
<div class="k-val">${fmtMs(avg)}</div>
|
||||
<div class="k-sub">${t('kpiMaxLat')} ${fmtMs(tot.latency_max_ms)}</div>
|
||||
<div class="k-val" data-kpi="lat"></div>
|
||||
<div class="k-sub" data-kpi="lat-sub"></div>
|
||||
<div class="k-chart"><canvas id="cv-lat"></canvas></div>
|
||||
</div>
|
||||
<div class="kpi kpi-status">
|
||||
<div class="k-hdr"><span class="k-lab">${t('dashStatus')}</span><span class="k-sub" id="tb-status-total"></span></div>
|
||||
<div class="k-chart k-chart-pie"><canvas id="cv-status"></canvas><div class="donut-note"></div></div>
|
||||
<div class="k-chart k-chart-pie"><canvas id="cv-status"></canvas></div>
|
||||
<div class="status-legend" id="tb-status"></div>
|
||||
</div>`;
|
||||
}
|
||||
// update values without rebuilding the card DOM (prevents the 3s flicker)
|
||||
const kset = (sel, txt) => { const e = $(sel); if (e) e.textContent = txt; };
|
||||
kset('[data-kpi="active"]', st.active || 0);
|
||||
kset('[data-kpi="reqs"]', fmtN(tot.reqs));
|
||||
const rsub = $('[data-kpi="reqs-sub"]');
|
||||
if (rsub) rsub.innerHTML = `${t('kpiOk')} <b class="${okr >= 90 ? 'okc' : 'errc'}">${okr}%</b>`;
|
||||
kset('[data-kpi="tokens"]', fmtTok(tot.tokens));
|
||||
const tsub = $('[data-kpi="tokens-sub"]');
|
||||
if (tsub) tsub.innerHTML = `<span>${t('thPrompt')} ${fmtTok(tot.prompt_tokens)}</span><span>${t('thCompl')} ${fmtTok(tot.completion_tokens)}</span>`;
|
||||
kset('[data-kpi="lat"]', fmtMs(avg));
|
||||
kset('[data-kpi="lat-sub"]', `${t('kpiMaxLat')} ${fmtMs(tot.latency_max_ms)}`);
|
||||
if (kpi) kpi.classList.toggle('kpi-exit', !!statsKeyF);
|
||||
paintModelTable(st.by_model || []);
|
||||
paintSrcTable(st.by_source || []);
|
||||
paintStatusTable(st.by_status || []);
|
||||
|
||||
Reference in New Issue
Block a user