Files
sub2api/frontend/src/utils/usagePricing.ts
yangjianbo 87f4ed591e fix(billing): 修复 OpenAI fast 档位计费并补齐展示
- 打通 service_tier 在 OpenAI HTTP、WS、passthrough 与 usage 记录中的传递
- 修正 priority/flex 计费逻辑,并将 fast 归一化为 priority
- 在用户端和管理端补齐服务档位与计费明细展示
- 补齐前后端测试,并修复 WS 限流信号重复持久化导致的全量回归失败

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-09 09:51:26 +08:00

50 lines
1.3 KiB
TypeScript

export const TOKENS_PER_MILLION = 1_000_000
interface TokenPriceFormatOptions {
fractionDigits?: number
withCurrencySymbol?: boolean
emptyValue?: string
}
function isFiniteNumber(value: unknown): value is number {
return typeof value === 'number' && Number.isFinite(value)
}
export function calculateTokenUnitPrice(
cost: number | null | undefined,
tokens: number | null | undefined
): number | null {
if (!isFiniteNumber(cost) || !isFiniteNumber(tokens) || tokens <= 0) {
return null
}
return cost / tokens
}
export function calculateTokenPricePerMillion(
cost: number | null | undefined,
tokens: number | null | undefined
): number | null {
const unitPrice = calculateTokenUnitPrice(cost, tokens)
if (unitPrice == null) {
return null
}
return unitPrice * TOKENS_PER_MILLION
}
export function formatTokenPricePerMillion(
cost: number | null | undefined,
tokens: number | null | undefined,
options: TokenPriceFormatOptions = {}
): string {
const pricePerMillion = calculateTokenPricePerMillion(cost, tokens)
if (pricePerMillion == null) {
return options.emptyValue ?? '-'
}
const fractionDigits = options.fractionDigits ?? 4
const formatted = pricePerMillion.toFixed(fractionDigits)
return options.withCurrencySymbol == false ? formatted : `$${formatted}`
}