diff --git a/static/app.js b/static/app.js
index 8c5d65f..2d215a3 100644
--- a/static/app.js
+++ b/static/app.js
@@ -12,6 +12,18 @@ function number(value, digits = 0) {
return Number(value).toLocaleString('zh-CN', { maximumFractionDigits: digits, minimumFractionDigits: digits })
}
+function usd(value, digits = 3) {
+ const numeric = Number(value)
+ if (value === null || value === undefined || !Number.isFinite(numeric)) return '—'
+ const formatter = new Intl.NumberFormat('zh-CN', { maximumFractionDigits: digits, minimumFractionDigits: digits })
+ const parts = formatter.formatToParts(numeric)
+ const whole = parts.filter(({ type }) => ['minusSign', 'plusSign', 'integer', 'group'].includes(type)).map(({ value: part }) => part).join('')
+ const point = parts.find(({ type }) => type === 'decimal')?.value ?? '.'
+ const fraction = parts.find(({ type }) => type === 'fraction')?.value ?? ''.padEnd(digits, '0')
+ const label = `$${formatter.format(numeric)}`
+ return `$${escapeHtml(whole)}${escapeHtml(point)}${escapeHtml(fraction)}`
+}
+
function compact(value) {
if (value === null || value === undefined) return '—'
return new Intl.NumberFormat('zh-CN', { notation: 'compact', maximumFractionDigits: 2 }).format(Number(value))
@@ -134,7 +146,7 @@ function renderScoreRows() {
${row.ttftP95Ms == null ? '—' : `${number(row.ttftP95Ms)} ms`} |
${compact(usage.requestCount)} |
${compact(usage.tokenCount)} |
- ${usage.apiAmountUsd == null ? '—' : `$${number(usage.apiAmountUsd, 3)}`} |
+ ${usd(usage.apiAmountUsd)} |
${number(row.failoverRecovered)} / ${number(row.failoverRequests)} |
${row.currentlyAvailable ? '可用' : '不可用'} |
`
@@ -180,10 +192,10 @@ async function rankingPage() {
const data = await requestJson('/api/ranking')
const ranking = data.ranking
$('#ranking-range').textContent = `${ranking.startDate} 至 ${ranking.endDate}`
- $('#ranking-cost').textContent = `$${number(ranking.totals.actualCost, 3)}`
+ $('#ranking-cost').innerHTML = usd(ranking.totals.actualCost)
$('#ranking-requests').textContent = compact(ranking.totals.requests)
$('#ranking-tokens').textContent = compact(ranking.totals.tokens)
- $('#ranking-body').innerHTML = ranking.rows.length ? ranking.rows.map((row) => `| ${String(row.rank).padStart(2, '0')} | ${escapeHtml(row.displayName)} | $${number(row.actualCost, 3)} | ${compact(row.requests)} | ${compact(row.tokens)} |
`).join('') : '| 当前窗口暂无用量 |
'
+ $('#ranking-body').innerHTML = ranking.rows.length ? ranking.rows.map((row) => `| ${String(row.rank).padStart(2, '0')} | ${escapeHtml(row.displayName)} | ${usd(row.actualCost)} | ${compact(row.requests)} | ${compact(row.tokens)} |
`).join('') : '| 当前窗口暂无用量 |
'
}
function creditLabel(status) {
diff --git a/static/ranking.html b/static/ranking.html
index e8b8b15..85316cf 100644
--- a/static/ranking.html
+++ b/static/ranking.html
@@ -13,7 +13,7 @@
- | 名次 | 用户 | API USD | 请求 | Token |
|---|
| 正在读取用量... |
+ | 名次 | 用户 | API USD | 请求 | Token |
|---|
| 正在读取用量... |