diff --git a/internal/lua/plugins/billing.lua b/internal/lua/plugins/billing.lua index 39978e2..72e4a2b 100644 --- a/internal/lua/plugins/billing.lua +++ b/internal/lua/plugins/billing.lua @@ -547,21 +547,30 @@ plugin.ui = { if (!b.cache_reported_reqs) return "n/r"; return ((hit / prompt) * 100).toFixed(1) + "%"; } + // fmtInt 千分位分组:2e8 级 token 总数可读、也更短,降低撑宽风险。 + function fmtInt(n) { + return (Number(n) || 0).toLocaleString("en-US"); + } function row(name, b, cur) { var fresh = (b.cache_fresh_tokens === undefined) ? (b.prompt_tokens || 0) : b.cache_fresh_tokens; - return "" + esc(name) + "" + money(b.cost, cur) + - "" + (b.requests || 0) + "" + (b.prompt_tokens || 0) + - "" + fresh + - "" + (b.cache_hit_tokens || 0) + - "" + esc(cacheRate(b)) + - "" + (b.completion_tokens || 0) + ""; + // 名称列 ellipsis(title 悬停看全名);数字列 break-all 在列宽内换行而不是 + // 把表格撑出卡片。单元格结构与列数不变,列数判据不受影响。 + return "" + esc(name) + "" + + "" + money(b.cost, cur) + "" + + "" + fmtInt(b.requests || 0) + "" + + "" + fmtInt(b.prompt_tokens || 0) + "" + + "" + fmtInt(fresh) + "" + + "" + fmtInt(b.cache_hit_tokens || 0) + "" + + "" + esc(cacheRate(b)) + "" + + "" + fmtInt(b.completion_tokens || 0) + ""; } function tableFor(el, obj, cur, empty) { var keys = Object.keys(obj || {}); if (!keys.length) { el.innerHTML = '
' + empty + "
"; return; } keys.sort(function (a, b) { return (obj[b].cost || 0) - (obj[a].cost || 0); }); var TH = L(); - var h = "" + + var h = "
" + "
" + TH.thName + "" + TH.thCost + "" + TH.thReqs + "" + TH.thPrompt + "" + TH.thFresh + "" + TH.thCache + "" + TH.thCachePct + @@ -589,20 +598,23 @@ plugin.ui = { var t = st.total || {}; document.getElementById("billing-kpis").innerHTML = [ [T.total, money(t.cost, cur)], - [T.requests, t.requests || 0], - [T.degraded, st.degraded_reqs || 0], - [T.unpriced, st.unpriced_reqs || 0], - [T.prompt, t.prompt_tokens || 0], - [T.completion, t.completion_tokens || 0], + [T.requests, fmtInt(t.requests || 0)], + [T.degraded, fmtInt(st.degraded_reqs || 0)], + [T.unpriced, fmtInt(st.unpriced_reqs || 0)], + [T.prompt, fmtInt(t.prompt_tokens || 0)], + [T.completion, fmtInt(t.completion_tokens || 0)], [T.failures, t.failures || 0], // Cache KPIs: last session added the table columns but the KPI cards // were left out — the edit's assert failed and the retry only re-did the // tables. The numbers existed in state and nowhere in the UI. [T.cacheRate, cacheRate(t)], - [T.cacheTokens, t.cache_hit_tokens || 0] + [T.cacheTokens, fmtInt(t.cache_hit_tokens || 0)] ].map(function (kv) { - return "
" + - kv[0] + "
" + + // min-width:0:grid item 默认 min-width:auto,2e8 级长数字会把轨道撑出 + // 容器造成横向溢出。标签 nowrap 截断,数值 break-all 换行。 + return "
" + + "
" + + esc(kv[0]) + "
" + esc(kv[1]) + "
"; }).join(""); var TD = L();