|
|
@@ -609,6 +609,93 @@ export const selectFilter = (input, option) => { |
|
|
|
|
|
|
|
|
// ------------------------------- |
|
|
// ------------------------------- |
|
|
// 模型定价计算工具函数 |
|
|
// 模型定价计算工具函数 |
|
|
|
|
|
export const hasDisplayPricing = (record) => |
|
|
|
|
|
Array.isArray(record?.display_pricing) && record.display_pricing.length > 0; |
|
|
|
|
|
|
|
|
|
|
|
export const normalizeDisplayPricingItems = (record) => { |
|
|
|
|
|
if (!hasDisplayPricing(record)) return []; |
|
|
|
|
|
return [...record.display_pricing] |
|
|
|
|
|
.map((item) => { |
|
|
|
|
|
const discountRate = |
|
|
|
|
|
Number(item.discount_rate) > 0 && Number(item.discount_rate) <= 1 |
|
|
|
|
|
? Number(item.discount_rate) |
|
|
|
|
|
: 1; |
|
|
|
|
|
const price = Number(item.price || 0); |
|
|
|
|
|
return { |
|
|
|
|
|
...item, |
|
|
|
|
|
price, |
|
|
|
|
|
discount_rate: discountRate, |
|
|
|
|
|
effectivePrice: price * discountRate, |
|
|
|
|
|
unit: item.unit || 'call', |
|
|
|
|
|
sort_order: Number(item.sort_order || 0), |
|
|
|
|
|
}; |
|
|
|
|
|
}) |
|
|
|
|
|
.sort((a, b) => { |
|
|
|
|
|
if (a.sort_order !== b.sort_order) return a.sort_order - b.sort_order; |
|
|
|
|
|
return String(a.specification || '').localeCompare( |
|
|
|
|
|
String(b.specification || ''), |
|
|
|
|
|
); |
|
|
|
|
|
}); |
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
export const formatDisplayPricingItem = ({ |
|
|
|
|
|
item, |
|
|
|
|
|
displayPrice, |
|
|
|
|
|
t = (key) => key, |
|
|
|
|
|
}) => { |
|
|
|
|
|
const unit = item.unit || 'call'; |
|
|
|
|
|
const effectivePrice = Number(item.effectivePrice ?? item.price ?? 0); |
|
|
|
|
|
const hasDiscount = item.discount_rate > 0 && item.discount_rate < 1; |
|
|
|
|
|
return { |
|
|
|
|
|
...item, |
|
|
|
|
|
formattedPrice: `${displayPrice(effectivePrice)} / ${t(unit)}`, |
|
|
|
|
|
originalPrice: hasDiscount |
|
|
|
|
|
? `${displayPrice(Number(item.price || 0))} / ${t(unit)}` |
|
|
|
|
|
: '', |
|
|
|
|
|
discountText: hasDiscount |
|
|
|
|
|
? `${Math.round(item.discount_rate * 100) / 10}折` |
|
|
|
|
|
: '-', |
|
|
|
|
|
}; |
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
export const summarizeDisplayPricing = ({ |
|
|
|
|
|
record, |
|
|
|
|
|
displayPrice, |
|
|
|
|
|
t = (key) => key, |
|
|
|
|
|
}) => { |
|
|
|
|
|
const items = normalizeDisplayPricingItems(record); |
|
|
|
|
|
if (items.length === 0) return null; |
|
|
|
|
|
|
|
|
|
|
|
const groups = new Map(); |
|
|
|
|
|
items.forEach((item) => { |
|
|
|
|
|
const unit = item.unit || 'call'; |
|
|
|
|
|
const list = groups.get(unit) || []; |
|
|
|
|
|
list.push(item); |
|
|
|
|
|
groups.set(unit, list); |
|
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
|
|
const lines = Array.from(groups.entries()).map(([unit, list]) => { |
|
|
|
|
|
const prices = list.map((item) => Number(item.effectivePrice || 0)); |
|
|
|
|
|
const min = Math.min(...prices); |
|
|
|
|
|
const max = Math.max(...prices); |
|
|
|
|
|
const priceText = |
|
|
|
|
|
min === max |
|
|
|
|
|
? displayPrice(min) |
|
|
|
|
|
: `${displayPrice(min)} - ${displayPrice(max)}`; |
|
|
|
|
|
return `${priceText} / ${t(unit)}`; |
|
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
|
|
return { |
|
|
|
|
|
isDisplayPricing: true, |
|
|
|
|
|
price: lines.join('\n'), |
|
|
|
|
|
unit: '', |
|
|
|
|
|
details: items |
|
|
|
|
|
.slice(0, 3) |
|
|
|
|
|
.map((item) => formatDisplayPricingItem({ item, displayPrice, t })), |
|
|
|
|
|
hiddenDetailCount: Math.max(0, items.length - 3), |
|
|
|
|
|
}; |
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
export const hasMatrixPricing = (record) => |
|
|
export const hasMatrixPricing = (record) => |
|
|
!!( |
|
|
!!( |
|
|
record?.pricing_config && |
|
|
record?.pricing_config && |
|
|
@@ -724,6 +811,7 @@ export const calculateModelPrice = ({ |
|
|
displayPrice, |
|
|
displayPrice, |
|
|
currency, |
|
|
currency, |
|
|
precision = 4, |
|
|
precision = 4, |
|
|
|
|
|
t = (key) => key, |
|
|
}) => { |
|
|
}) => { |
|
|
// 1. 选择实际使用的分组 |
|
|
// 1. 选择实际使用的分组 |
|
|
const ratios = groupRatio || {}; |
|
|
const ratios = groupRatio || {}; |
|
|
@@ -754,6 +842,19 @@ export const calculateModelPrice = ({ |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
// 2. 根据计费类型计算价格 |
|
|
// 2. 根据计费类型计算价格 |
|
|
|
|
|
if (hasDisplayPricing(record)) { |
|
|
|
|
|
const summary = summarizeDisplayPricing({ |
|
|
|
|
|
record, |
|
|
|
|
|
displayPrice, |
|
|
|
|
|
t, |
|
|
|
|
|
}); |
|
|
|
|
|
return { |
|
|
|
|
|
...summary, |
|
|
|
|
|
usedGroup, |
|
|
|
|
|
usedGroupRatio, |
|
|
|
|
|
}; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
if (hasMatrixPricing(record)) { |
|
|
if (hasMatrixPricing(record)) { |
|
|
const summary = summarizeMatrixPricing({ |
|
|
const summary = summarizeMatrixPricing({ |
|
|
record, |
|
|
record, |
|
|
|