feat: 视频计费增强与影子计费系统

This commit is contained in:
fawney19
2026-02-03 18:48:39 +08:00
parent ed68aebfb0
commit 00442c41fa
84 changed files with 6507 additions and 1678 deletions

View File

@@ -103,8 +103,18 @@
${{ formatPrice(model.effective_price_per_request ?? model.price_per_request) }}/
</span>
</template>
<!-- 视频费用计费 -->
<template v-if="hasVideoPricing(model)">
<span class="text-muted-foreground text-right">视频:</span>
<span
class="font-mono font-semibold"
:title="getVideoPricingTooltip(model)"
>
{{ getVideoPricingDisplay(model) }}
</span>
</template>
<!-- 无计费配置 -->
<template v-if="!hasTokenPricing(model) && !hasRequestPricing(model)">
<template v-if="!hasTokenPricing(model) && !hasRequestPricing(model) && !hasVideoPricing(model)">
<span class="text-muted-foreground"></span>
</template>
</div>
@@ -217,6 +227,7 @@ import {
} from '@/components/ui'
import { useToast } from '@/composables/useToast'
import { useClipboard } from '@/composables/useClipboard'
import { sortResolutionEntries } from '@/utils/form'
import {
getProviderModels,
getProviderMappingPreview,
@@ -345,6 +356,38 @@ function hasRequestPricing(model: Model): boolean {
return requestPrice != null && requestPrice > 0
}
// 检查是否有视频分辨率计费配置
function hasVideoPricing(model: Model): boolean {
const priceByResolution = model.effective_config?.billing?.video?.price_per_second_by_resolution
|| model.config?.billing?.video?.price_per_second_by_resolution
return priceByResolution && typeof priceByResolution === 'object' && Object.keys(priceByResolution).length > 0
}
// 获取视频计费的显示文本
function getVideoPricingDisplay(model: Model): string {
const priceByResolution = model.effective_config?.billing?.video?.price_per_second_by_resolution
|| model.config?.billing?.video?.price_per_second_by_resolution
if (!priceByResolution || typeof priceByResolution !== 'object') return ''
const entries = sortResolutionEntries(Object.entries(priceByResolution))
if (entries.length === 0) return ''
// 获取最低分辨率和价格
const [firstRes, firstPrice] = entries[0]
const priceStr = `${firstRes} $${(firstPrice as number).toFixed(2)}/s`
if (entries.length > 1) {
return `${priceStr} [${entries.length}种]`
}
return priceStr
}
// 获取视频计费详情的 tooltip
function getVideoPricingTooltip(model: Model): string {
const priceByResolution = model.effective_config?.billing?.video?.price_per_second_by_resolution
|| model.config?.billing?.video?.price_per_second_by_resolution
if (!priceByResolution || typeof priceByResolution !== 'object') return ''
const entries = sortResolutionEntries(Object.entries(priceByResolution))
return entries.map(([res, price]) => `${res}: $${(price as number).toFixed(4)}/s`).join('\n')
}
// 获取状态指示灯样式
function getStatusIndicatorClass(model: Model): string {
if (!model.is_active) {