Commit 486ee646 by renyizhao

价格展示修改

parent b40dc588
......@@ -106,10 +106,12 @@
<template #default="{ row }">
<div v-if="Number(row?.quotaType) === 1">-</div>
<div v-else-if="row?.billingMode === 'tiered_expr' && row?.tiers && row.tiers.length > 0">
<b>¥{{ formatPrice(row.tiers[0].inputRatio) }} / 1M</b>
<b>{{ formatDynamicRange(row.tiers) }}</b>
<span style="margin-left: 2px; color: #999; font-size: 12px;"> / 1M</span>
</div>
<div v-else>
<b>¥{{ formatPrice(row.inputPrice) }} / 1M</b>
<b>¥{{ formatPrice(row.inputPrice) }}</b>
<span style="margin-left: 2px; color: #999; font-size: 12px;"> / 1M</span>
</div>
</template>
</el-table-column>
......@@ -117,10 +119,12 @@
<template #default="{ row }">
<div v-if="Number(row?.quotaType) === 1">-</div>
<div v-else-if="row?.billingMode === 'tiered_expr' && row?.tiers && row.tiers.length > 0">
<b>¥{{ formatPrice(row.tiers[0].outputRatio) }} / 1M</b>
<b>{{ formatDynamicRange(row.tiers) }}</b>
<span style="margin-left: 2px; color: #999; font-size: 12px;"> / 1M</span>
</div>
<div v-else>
<b>¥{{ formatPrice(row.outputPrice) }} / 1M</b>
<b>¥{{ formatPrice(row.outputPrice) }}</b>
<span style="margin-left: 2px; color: #999; font-size: 12px;"> / 1M</span>
</div>
</template>
</el-table-column>
......@@ -469,8 +473,8 @@
<div class="tier-name">{{ tier.name }}</div>
<div v-if="tier.conditionDesc" class="tier-condition">{{ tier.conditionDesc }}</div>
</div>
<div class="tier-cell price-cell">{{ formatModelPrice(tier.inputRatio) }}</div>
<div class="tier-cell price-cell">{{ formatModelPrice(tier.outputRatio) }}</div>
<div class="tier-cell price-cell">{{ formatModelPrice(getTierDisplayPrice(tier, 'input')) }}</div>
<div class="tier-cell price-cell">{{ formatModelPrice(getTierDisplayPrice(tier, 'output')) }}</div>
<div v-for="col in tierExtraPriceColumns" :key="col.key" class="tier-cell price-cell">
{{ tier[col.key] != null && tier[col.key] > 0 ? formatModelPrice(tier[col.key]) : '-' }}
</div>
......@@ -628,6 +632,18 @@ function formatModelPrice(price) {
return num.toFixed(4)
}
// 提取动态计费档位的展示价格:seedance 风格优先用 tokensMultiplier(每百万 token 价格),
// 其次才是 inputRatio/outputRatio
function getTierDisplayPrice(tier, side) {
if (!tier) return null
if (tier.tokensMultiplier != null && Number(tier.tokensMultiplier) > 0) {
return tier.tokensMultiplier
}
if (side === 'output') return tier.outputRatio != null ? tier.outputRatio : null
if (side === 'input') return tier.inputRatio != null ? tier.inputRatio : null
return tier.inputRatio != null ? tier.inputRatio : null
}
// 格式化条件描述
function formatConditionDesc(desc) {
if (!desc) return ''
......@@ -704,6 +720,10 @@ const tierExtraPriceColumns = computed(() => {
if (tiers.some(t => t.audioOutputRatio != null && t.audioOutputRatio > 0)) {
columns.push({ key: 'audioOutputRatio', label: '音频输出' })
}
// 检查 tokensMultiplier(seedance 风格:u("tokens") * X / 1000000 中的 X)
if (tiers.some(t => t.tokensMultiplier != null && Number(t.tokensMultiplier) > 0)) {
columns.push({ key: 'tokensMultiplier', label: '每百万token价格' })
}
return columns
})
......@@ -1125,6 +1145,35 @@ function formatPrice(price) {
return num.toFixed(4).replace(/\.?0+$/, '')
}
// 动态计费模型汇总价格范围:聚合所有 tiers 中有值的价格字段(按 tokensMultiplier > inputRatio > outputRatio 优先级),
// 返回 { min, max, same }。same=true 表示所有档价格一致,可退化为单值展示。
function getDynamicPriceRange(tiers) {
if (!Array.isArray(tiers) || tiers.length === 0) return null
let min = Infinity
let max = -Infinity
const candidateFields = ['tokensMultiplier', 'inputRatio', 'outputRatio']
for (const tier of tiers) {
if (!tier) continue
for (const field of candidateFields) {
const v = Number(tier[field])
if (Number.isFinite(v) && v > 0) {
if (v < min) min = v
if (v > max) max = v
}
}
}
if (min === Infinity || max === -Infinity) return null
return { min, max, same: min === max }
}
// 渲染动态计费模型的价格范围文案。与 NewAPI 卡片一致:单档展示 ¥X,多档展示 ¥X ~ ¥Y。
function formatDynamicRange(tiers) {
const range = getDynamicPriceRange(tiers)
if (!range) return '¥-'
if (range.same) return ${formatPrice(range.min)}`
return ${formatPrice(range.min)} ~ ¥${formatPrice(range.max)}`
}
function billingTagText(model) {
if (Number(model?.quotaType) === 1) return '按次收费'
if (model?.billingMode === 'tiered_expr') return '动态计费'
......
......@@ -39,13 +39,10 @@
<template v-if="isPerCall">
<span>每次调用<b>¥{{ formatPrice(model.inputPrice) }}</b></span>
</template>
<!-- 分档计费:显示第一档 -->
<!-- 分档计费:显示价格范围(与 NewAPI 卡片一致:¥X ~ ¥Y / 1M token) -->
<template v-else-if="hasTieredPrice">
<span>输入价格:<b>¥{{ formatPrice(model.tiers[0].inputRatio) }}</b></span>
<span class="unit"> / 1M</span>
<span class="divider"></span>
<span>输出价格:<b>¥{{ formatPrice(model.tiers[0].outputRatio) }}</b></span>
<span class="unit"> / 1M</span>
<span>动态价格:<b>{{ formatDynamicRange(model.tiers) }}</b></span>
<span class="unit"> / 1M token</span>
</template>
<!-- 按量计费:输入/输出 -->
<template v-else>
......@@ -134,6 +131,35 @@ function formatPrice(price) {
if (Number.isNaN(num)) return '-'
return num.toFixed(4).replace(/\.?0+$/, '')
}
// 动态计费模型汇总价格范围:聚合所有 tiers 中有值的价格字段(按 tokensMultiplier > inputRatio > outputRatio 优先级),
// 返回 { min, max, same }。same=true 表示所有档价格一致,可退化为单值展示。
function getDynamicPriceRange(tiers) {
if (!Array.isArray(tiers) || tiers.length === 0) return null
let min = Infinity
let max = -Infinity
const candidateFields = ['tokensMultiplier', 'inputRatio', 'outputRatio']
for (const tier of tiers) {
if (!tier) continue
for (const field of candidateFields) {
const v = Number(tier[field])
if (Number.isFinite(v) && v > 0) {
if (v < min) min = v
if (v > max) max = v
}
}
}
if (min === Infinity || max === -Infinity) return null
return { min, max, same: min === max }
}
// 渲染动态计费模型的价格范围文案:单档 ¥X,多档 ¥X ~ ¥Y。
function formatDynamicRange(tiers) {
const range = getDynamicPriceRange(tiers)
if (!range) return '¥-'
if (range.same) return ${formatPrice(range.min)}`
return ${formatPrice(range.min)} ~ ¥${formatPrice(range.max)}`
}
</script>
<style scoped lang="scss">
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment