feat(pricing): support processing tier multipliers

This commit is contained in:
elky
2026-07-16 23:30:42 +08:00
parent 312583f055
commit 0be380243b
40 changed files with 5012 additions and 565 deletions
@@ -250,11 +250,12 @@
</span>
</div>
<ServiceTierFacts
v-if="hasServiceTierFacts"
v-if="hasServiceTierFacts || processingTierPriceMultiplier !== null"
class="mt-3"
:requested="serviceTierFacts.requested"
:actual="serviceTierFacts.actual"
:billing="serviceTierFacts.billing"
:price-multiplier="processingTierPriceMultiplier"
/>
</div>
@@ -313,13 +314,13 @@
<div class="grid grid-cols-2 gap-x-4 gap-y-1 text-muted-foreground sm:hidden">
<div class="grid grid-cols-[max-content_1fr] items-baseline gap-x-1">
<span>输入</span>
<span class="text-right">${{ formatPrice(tier.input_price_per_1m) }}/M</span>
<span class="text-right">{{ formatPricePerMillion(tier.input_price_per_1m) }}</span>
</div>
<div
class="grid grid-cols-[max-content_1fr] items-baseline gap-x-1"
>
<span>输出</span>
<span class="text-right">${{ formatPrice(tier.output_price_per_1m) }}/M</span>
<span class="text-right">{{ formatPricePerMillion(tier.output_price_per_1m) }}</span>
</div>
<template v-if="getTierActiveCacheCreationDisplay(tier) || shouldShowCacheReadPrice(tier)">
<div
@@ -341,8 +342,8 @@
</template>
</div>
<div class="text-muted-foreground hidden items-center gap-2 flex-wrap sm:flex">
<span>输入 ${{ formatPrice(tier.input_price_per_1m) }}/M</span>
<span>输出 ${{ formatPrice(tier.output_price_per_1m) }}/M</span>
<span>输入 {{ formatPricePerMillion(tier.input_price_per_1m) }}</span>
<span>输出 {{ formatPricePerMillion(tier.output_price_per_1m) }}</span>
<span v-if="getTierActiveCacheCreationDisplay(tier)">
{{ getTierActiveCacheCreationDisplay(tier)?.label }}
${{ formatPrice(getTierActiveCacheCreationDisplay(tier)?.price || 0) }}/M
@@ -906,6 +907,12 @@ import {
resolveUsageStreamLabelSegments,
} from '../utils/status'
import { resolveRequestFailureNotice } from '../utils/errorNotice'
import {
formatPricePerMillion,
resolveProcessingTierPriceMultiplier,
resolveSettlementPricingSourceLabel,
resolveSettlementPricingTiers,
} from '../utils/settlement-pricing'
// 子组件
import RequestHeadersContent from './RequestDetailDrawer/RequestHeadersContent.vue'
@@ -1355,6 +1362,9 @@ const failureNotice = computed(() => resolveRequestFailureNotice(detail.value))
const serviceTierFacts = computed(() => resolveServiceTierFacts(detail.value))
const hasServiceTierFacts = computed(() => hasServiceTierFact(serviceTierFacts.value))
const processingTierPriceMultiplier = computed(() => (
resolveProcessingTierPriceMultiplier(detail.value)
))
const settlementInfo = computed<JsonRecord | null>(() =>
asRecord(detail.value?.settlement ?? null),
@@ -1643,20 +1653,10 @@ const hasValidConversation = computed(() => {
return false
})
// 价格来源标签
// tiered_pricing.source 表示定价来源: 'provider' 或 'global'
// 价格来源优先使用 v3 结算快照,旧 tiered_pricing.source 仅作回退。
const priceSourceLabel = computed(() => {
if (!detail.value) return '历史定价'
const source = detail.value.tiered_pricing?.source
if (source === 'provider') {
return '提供商定价'
} else if (source === 'global') {
return '全局定价'
}
// 没有 tiered_pricing 时,使用历史价格
return '历史定价'
return resolveSettlementPricingSourceLabel(detail.value) ?? '历史定价'
})
const cacheCreationInputTokens5m = computed(() => {
@@ -1896,10 +1896,9 @@ const activeCacheTtlMinutes = computed(() => {
const displayTiers = computed(() => {
if (!detail.value) return []
// 如果有阶梯定价数据,直接使用
if (detail.value.tiered_pricing?.tiers && detail.value.tiered_pricing.tiers.length > 0) {
return detail.value.tiered_pricing.tiers
}
// 优先展示结算快照中已解析的价格目录,旧字段仅作回退。
const resolvedTiers = resolveSettlementPricingTiers(detail.value)
if (resolvedTiers) return resolvedTiers as PricingTierLike[]
// 否则用历史价格构建单阶梯(无上限)
return [{