style(web): format code
This commit is contained in:
@@ -44,7 +44,10 @@ export function renderGroup(group) {
|
||||
if (await copy(group)) {
|
||||
showSuccess(i18next.t('已复制:') + group);
|
||||
} else {
|
||||
Modal.error({ title: t('无法复制到剪贴板,请手动复制'), content: group });
|
||||
Modal.error({
|
||||
title: t('无法复制到剪贴板,请手动复制'),
|
||||
content: group,
|
||||
});
|
||||
}
|
||||
}}
|
||||
>
|
||||
@@ -64,28 +67,37 @@ export function renderRatio(ratio) {
|
||||
} else if (ratio > 1) {
|
||||
color = 'blue';
|
||||
}
|
||||
return <Tag color={color}>{ratio}x {i18next.t('倍率')}</Tag>;
|
||||
return (
|
||||
<Tag color={color}>
|
||||
{ratio}x {i18next.t('倍率')}
|
||||
</Tag>
|
||||
);
|
||||
}
|
||||
|
||||
const measureTextWidth = (text, style = {
|
||||
fontSize: '14px',
|
||||
fontFamily: '-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif'
|
||||
}, containerWidth) => {
|
||||
const measureTextWidth = (
|
||||
text,
|
||||
style = {
|
||||
fontSize: '14px',
|
||||
fontFamily:
|
||||
'-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif',
|
||||
},
|
||||
containerWidth,
|
||||
) => {
|
||||
const span = document.createElement('span');
|
||||
|
||||
|
||||
span.style.visibility = 'hidden';
|
||||
span.style.position = 'absolute';
|
||||
span.style.whiteSpace = 'nowrap';
|
||||
span.style.fontSize = style.fontSize;
|
||||
span.style.fontFamily = style.fontFamily;
|
||||
|
||||
|
||||
span.textContent = text;
|
||||
|
||||
|
||||
document.body.appendChild(span);
|
||||
const width = span.offsetWidth;
|
||||
|
||||
|
||||
document.body.removeChild(span);
|
||||
|
||||
|
||||
return width;
|
||||
};
|
||||
|
||||
@@ -94,7 +106,7 @@ export function truncateText(text, maxWidth = 200) {
|
||||
return text;
|
||||
}
|
||||
if (!text) return text;
|
||||
|
||||
|
||||
try {
|
||||
// Handle percentage-based maxWidth
|
||||
let actualMaxWidth = maxWidth;
|
||||
@@ -103,19 +115,19 @@ export function truncateText(text, maxWidth = 200) {
|
||||
// Use window width as fallback container width
|
||||
actualMaxWidth = window.innerWidth * percentage;
|
||||
}
|
||||
|
||||
|
||||
const width = measureTextWidth(text);
|
||||
if (width <= actualMaxWidth) return text;
|
||||
|
||||
|
||||
let left = 0;
|
||||
let right = text.length;
|
||||
let result = text;
|
||||
|
||||
|
||||
while (left <= right) {
|
||||
const mid = Math.floor((left + right) / 2);
|
||||
const truncated = text.slice(0, mid) + '...';
|
||||
const currentWidth = measureTextWidth(truncated);
|
||||
|
||||
|
||||
if (currentWidth <= actualMaxWidth) {
|
||||
result = truncated;
|
||||
left = mid + 1;
|
||||
@@ -123,10 +135,13 @@ export function truncateText(text, maxWidth = 200) {
|
||||
right = mid - 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return result;
|
||||
} catch (error) {
|
||||
console.warn('Text measurement failed, falling back to character count', error);
|
||||
console.warn(
|
||||
'Text measurement failed, falling back to character count',
|
||||
error,
|
||||
);
|
||||
if (text.length > 20) {
|
||||
return text.slice(0, 17) + '...';
|
||||
}
|
||||
@@ -149,11 +164,11 @@ export const renderGroupOption = (item) => {
|
||||
emptyContent,
|
||||
...rest
|
||||
} = item;
|
||||
|
||||
|
||||
const baseStyle = {
|
||||
display: 'flex',
|
||||
justifyContent: 'space-between',
|
||||
alignItems: 'center',
|
||||
display: 'flex',
|
||||
justifyContent: 'space-between',
|
||||
alignItems: 'center',
|
||||
padding: '8px 16px',
|
||||
cursor: disabled ? 'not-allowed' : 'pointer',
|
||||
backgroundColor: focused ? 'var(--semi-color-fill-0)' : 'transparent',
|
||||
@@ -162,8 +177,8 @@ export const renderGroupOption = (item) => {
|
||||
backgroundColor: 'var(--semi-color-primary-light-default)',
|
||||
}),
|
||||
'&:hover': {
|
||||
backgroundColor: !disabled && 'var(--semi-color-fill-1)'
|
||||
}
|
||||
backgroundColor: !disabled && 'var(--semi-color-fill-1)',
|
||||
},
|
||||
};
|
||||
|
||||
const handleClick = () => {
|
||||
@@ -177,9 +192,9 @@ export const renderGroupOption = (item) => {
|
||||
onMouseEnter(e);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
return (
|
||||
<div
|
||||
<div
|
||||
style={baseStyle}
|
||||
onClick={handleClick}
|
||||
onMouseEnter={handleMouseEnter}
|
||||
@@ -188,7 +203,7 @@ export const renderGroupOption = (item) => {
|
||||
<Typography.Text strong type={disabled ? 'tertiary' : undefined}>
|
||||
{value}
|
||||
</Typography.Text>
|
||||
<Typography.Text type="secondary" size="small">
|
||||
<Typography.Text type='secondary' size='small'>
|
||||
{label}
|
||||
</Typography.Text>
|
||||
</div>
|
||||
@@ -222,8 +237,7 @@ export function renderQuotaNumberWithDigit(num, digits = 2) {
|
||||
}
|
||||
|
||||
export function renderNumberWithPoint(num) {
|
||||
if (num === undefined)
|
||||
return '';
|
||||
if (num === undefined) return '';
|
||||
num = num.toFixed(2);
|
||||
if (num >= 100000) {
|
||||
// Convert number to string to manipulate it
|
||||
@@ -302,11 +316,14 @@ export function renderModelPrice(
|
||||
cacheRatio = 1.0,
|
||||
) {
|
||||
if (modelPrice !== -1) {
|
||||
return i18next.t('模型价格:${{price}} * 分组倍率:{{ratio}} = ${{total}}', {
|
||||
price: modelPrice,
|
||||
ratio: groupRatio,
|
||||
total: modelPrice * groupRatio
|
||||
});
|
||||
return i18next.t(
|
||||
'模型价格:${{price}} * 分组倍率:{{ratio}} = ${{total}}',
|
||||
{
|
||||
price: modelPrice,
|
||||
ratio: groupRatio,
|
||||
total: modelPrice * groupRatio,
|
||||
},
|
||||
);
|
||||
} else {
|
||||
if (completionRatio === undefined) {
|
||||
completionRatio = 0;
|
||||
@@ -314,54 +331,72 @@ export function renderModelPrice(
|
||||
let inputRatioPrice = modelRatio * 2.0;
|
||||
let completionRatioPrice = modelRatio * 2.0 * completionRatio;
|
||||
let cacheRatioPrice = modelRatio * 2.0 * cacheRatio;
|
||||
|
||||
|
||||
// Calculate effective input tokens (non-cached + cached with ratio applied)
|
||||
const effectiveInputTokens = (inputTokens - cacheTokens) + (cacheTokens * cacheRatio);
|
||||
|
||||
const effectiveInputTokens =
|
||||
inputTokens - cacheTokens + cacheTokens * cacheRatio;
|
||||
|
||||
let price =
|
||||
(effectiveInputTokens / 1000000) * inputRatioPrice * groupRatio +
|
||||
(completionTokens / 1000000) * completionRatioPrice * groupRatio;
|
||||
|
||||
|
||||
return (
|
||||
<>
|
||||
<article>
|
||||
<p>{i18next.t('提示价格:${{price}} / 1M tokens', {
|
||||
price: inputRatioPrice,
|
||||
})}</p>
|
||||
<p>{i18next.t('补全价格:${{price}} * {{completionRatio}} = ${{total}} / 1M tokens (补全倍率: {{completionRatio}})', {
|
||||
price: inputRatioPrice,
|
||||
total: completionRatioPrice,
|
||||
completionRatio: completionRatio
|
||||
})}</p>
|
||||
{cacheTokens > 0 && (
|
||||
<p>{i18next.t('缓存价格:${{price}} * {{cacheRatio}} = ${{total}} / 1M tokens (缓存倍率: {{cacheRatio}})', {
|
||||
<p>
|
||||
{i18next.t('提示价格:${{price}} / 1M tokens', {
|
||||
price: inputRatioPrice,
|
||||
total: inputRatioPrice * cacheRatio,
|
||||
cacheRatio: cacheRatio
|
||||
})}</p>
|
||||
})}
|
||||
</p>
|
||||
<p>
|
||||
{i18next.t(
|
||||
'补全价格:${{price}} * {{completionRatio}} = ${{total}} / 1M tokens (补全倍率: {{completionRatio}})',
|
||||
{
|
||||
price: inputRatioPrice,
|
||||
total: completionRatioPrice,
|
||||
completionRatio: completionRatio,
|
||||
},
|
||||
)}
|
||||
</p>
|
||||
{cacheTokens > 0 && (
|
||||
<p>
|
||||
{i18next.t(
|
||||
'缓存价格:${{price}} * {{cacheRatio}} = ${{total}} / 1M tokens (缓存倍率: {{cacheRatio}})',
|
||||
{
|
||||
price: inputRatioPrice,
|
||||
total: inputRatioPrice * cacheRatio,
|
||||
cacheRatio: cacheRatio,
|
||||
},
|
||||
)}
|
||||
</p>
|
||||
)}
|
||||
<p></p>
|
||||
<p>
|
||||
{cacheTokens > 0 ?
|
||||
i18next.t('提示 {{nonCacheInput}} tokens / 1M tokens * ${{price}} + 缓存 {{cacheInput}} tokens / 1M tokens * ${{cachePrice}} + 补全 {{completion}} tokens / 1M tokens * ${{compPrice}} * 分组 {{ratio}} = ${{total}}', {
|
||||
nonCacheInput: inputTokens - cacheTokens,
|
||||
cacheInput: cacheTokens,
|
||||
cachePrice: inputRatioPrice * cacheRatio,
|
||||
price: inputRatioPrice,
|
||||
completion: completionTokens,
|
||||
compPrice: completionRatioPrice,
|
||||
ratio: groupRatio,
|
||||
total: price.toFixed(6)
|
||||
}) :
|
||||
i18next.t('提示 {{input}} tokens / 1M tokens * ${{price}} + 补全 {{completion}} tokens / 1M tokens * ${{compPrice}} * 分组 {{ratio}} = ${{total}}', {
|
||||
input: inputTokens,
|
||||
price: inputRatioPrice,
|
||||
completion: completionTokens,
|
||||
compPrice: completionRatioPrice,
|
||||
ratio: groupRatio,
|
||||
total: price.toFixed(6)
|
||||
})
|
||||
}
|
||||
{cacheTokens > 0
|
||||
? i18next.t(
|
||||
'提示 {{nonCacheInput}} tokens / 1M tokens * ${{price}} + 缓存 {{cacheInput}} tokens / 1M tokens * ${{cachePrice}} + 补全 {{completion}} tokens / 1M tokens * ${{compPrice}} * 分组 {{ratio}} = ${{total}}',
|
||||
{
|
||||
nonCacheInput: inputTokens - cacheTokens,
|
||||
cacheInput: cacheTokens,
|
||||
cachePrice: inputRatioPrice * cacheRatio,
|
||||
price: inputRatioPrice,
|
||||
completion: completionTokens,
|
||||
compPrice: completionRatioPrice,
|
||||
ratio: groupRatio,
|
||||
total: price.toFixed(6),
|
||||
},
|
||||
)
|
||||
: i18next.t(
|
||||
'提示 {{input}} tokens / 1M tokens * ${{price}} + 补全 {{completion}} tokens / 1M tokens * ${{compPrice}} * 分组 {{ratio}} = ${{total}}',
|
||||
{
|
||||
input: inputTokens,
|
||||
price: inputRatioPrice,
|
||||
completion: completionTokens,
|
||||
compPrice: completionRatioPrice,
|
||||
ratio: groupRatio,
|
||||
total: price.toFixed(6),
|
||||
},
|
||||
)}
|
||||
</p>
|
||||
<p>{i18next.t('仅供参考,以实际扣费为准')}</p>
|
||||
</article>
|
||||
@@ -380,19 +415,22 @@ export function renderModelPriceSimple(
|
||||
if (modelPrice !== -1) {
|
||||
return i18next.t('价格:${{price}} * 分组:{{ratio}}', {
|
||||
price: modelPrice,
|
||||
ratio: groupRatio
|
||||
ratio: groupRatio,
|
||||
});
|
||||
} else {
|
||||
if (cacheTokens !== 0) {
|
||||
return i18next.t('模型: {{ratio}} * 分组: {{groupRatio}} * 缓存: {{cacheRatio}}', {
|
||||
ratio: modelRatio,
|
||||
groupRatio: groupRatio,
|
||||
cacheRatio: cacheRatio
|
||||
});
|
||||
return i18next.t(
|
||||
'模型: {{ratio}} * 分组: {{groupRatio}} * 缓存: {{cacheRatio}}',
|
||||
{
|
||||
ratio: modelRatio,
|
||||
groupRatio: groupRatio,
|
||||
cacheRatio: cacheRatio,
|
||||
},
|
||||
);
|
||||
} else {
|
||||
return i18next.t('模型: {{ratio}} * 分组: {{groupRatio}}', {
|
||||
ratio: modelRatio,
|
||||
groupRatio: groupRatio
|
||||
groupRatio: groupRatio,
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -414,11 +452,14 @@ export function renderAudioModelPrice(
|
||||
) {
|
||||
// 1 ratio = $0.002 / 1K tokens
|
||||
if (modelPrice !== -1) {
|
||||
return i18next.t('模型价格:${{price}} * 分组倍率:{{ratio}} = ${{total}}', {
|
||||
price: modelPrice,
|
||||
ratio: groupRatio,
|
||||
total: modelPrice * groupRatio
|
||||
});
|
||||
return i18next.t(
|
||||
'模型价格:${{price}} * 分组倍率:{{ratio}} = ${{total}}',
|
||||
{
|
||||
price: modelPrice,
|
||||
ratio: groupRatio,
|
||||
total: modelPrice * groupRatio,
|
||||
},
|
||||
);
|
||||
} else {
|
||||
if (completionRatio === undefined) {
|
||||
completionRatio = 0;
|
||||
@@ -430,81 +471,120 @@ export function renderAudioModelPrice(
|
||||
let inputRatioPrice = modelRatio * 2.0;
|
||||
let completionRatioPrice = modelRatio * 2.0 * completionRatio;
|
||||
let cacheRatioPrice = modelRatio * 2.0 * cacheRatio;
|
||||
|
||||
|
||||
// Calculate effective input tokens (non-cached + cached with ratio applied)
|
||||
const effectiveInputTokens = (inputTokens - cacheTokens) + (cacheTokens * cacheRatio);
|
||||
|
||||
const effectiveInputTokens =
|
||||
inputTokens - cacheTokens + cacheTokens * cacheRatio;
|
||||
|
||||
let textPrice =
|
||||
(effectiveInputTokens / 1000000) * inputRatioPrice * groupRatio +
|
||||
(completionTokens / 1000000) * completionRatioPrice * groupRatio
|
||||
(completionTokens / 1000000) * completionRatioPrice * groupRatio;
|
||||
let audioPrice =
|
||||
(audioInputTokens / 1000000) * inputRatioPrice * audioRatio * groupRatio +
|
||||
(audioCompletionTokens / 1000000) * inputRatioPrice * audioRatio * audioCompletionRatio * groupRatio;
|
||||
(audioCompletionTokens / 1000000) *
|
||||
inputRatioPrice *
|
||||
audioRatio *
|
||||
audioCompletionRatio *
|
||||
groupRatio;
|
||||
let price = textPrice + audioPrice;
|
||||
return (
|
||||
<>
|
||||
<article>
|
||||
<p>{i18next.t('提示价格:${{price}} / 1M tokens', {
|
||||
price: inputRatioPrice,
|
||||
})}</p>
|
||||
<p>{i18next.t('补全价格:${{price}} * {{completionRatio}} = ${{total}} / 1M tokens (补全倍率: {{completionRatio}})', {
|
||||
price: inputRatioPrice,
|
||||
total: completionRatioPrice,
|
||||
completionRatio: completionRatio
|
||||
})}</p>
|
||||
{cacheTokens > 0 && (
|
||||
<p>{i18next.t('缓存价格:${{price}} * {{cacheRatio}} = ${{total}} / 1M tokens (缓存倍率: {{cacheRatio}})', {
|
||||
<p>
|
||||
{i18next.t('提示价格:${{price}} / 1M tokens', {
|
||||
price: inputRatioPrice,
|
||||
total: inputRatioPrice * cacheRatio,
|
||||
cacheRatio: cacheRatio
|
||||
})}</p>
|
||||
})}
|
||||
</p>
|
||||
<p>
|
||||
{i18next.t(
|
||||
'补全价格:${{price}} * {{completionRatio}} = ${{total}} / 1M tokens (补全倍率: {{completionRatio}})',
|
||||
{
|
||||
price: inputRatioPrice,
|
||||
total: completionRatioPrice,
|
||||
completionRatio: completionRatio,
|
||||
},
|
||||
)}
|
||||
</p>
|
||||
{cacheTokens > 0 && (
|
||||
<p>
|
||||
{i18next.t(
|
||||
'缓存价格:${{price}} * {{cacheRatio}} = ${{total}} / 1M tokens (缓存倍率: {{cacheRatio}})',
|
||||
{
|
||||
price: inputRatioPrice,
|
||||
total: inputRatioPrice * cacheRatio,
|
||||
cacheRatio: cacheRatio,
|
||||
},
|
||||
)}
|
||||
</p>
|
||||
)}
|
||||
<p>{i18next.t('音频提示价格:${{price}} * {{audioRatio}} = ${{total}} / 1M tokens (音频倍率: {{audioRatio}})', {
|
||||
price: inputRatioPrice,
|
||||
total: inputRatioPrice * audioRatio,
|
||||
audioRatio: audioRatio
|
||||
})}</p>
|
||||
<p>{i18next.t('音频补全价格:${{price}} * {{audioRatio}} * {{audioCompRatio}} = ${{total}} / 1M tokens (音频补全倍率: {{audioCompRatio}})', {
|
||||
price: inputRatioPrice,
|
||||
total: inputRatioPrice * audioRatio * audioCompletionRatio,
|
||||
audioRatio: audioRatio,
|
||||
audioCompRatio: audioCompletionRatio
|
||||
})}</p>
|
||||
<p>
|
||||
{cacheTokens > 0 ?
|
||||
i18next.t('文字提示 {{nonCacheInput}} tokens / 1M tokens * ${{price}} + 缓存 {{cacheInput}} tokens / 1M tokens * ${{cachePrice}} + 文字补全 {{completion}} tokens / 1M tokens * ${{compPrice}} = ${{total}}', {
|
||||
nonCacheInput: inputTokens - cacheTokens,
|
||||
cacheInput: cacheTokens,
|
||||
cachePrice: inputRatioPrice * cacheRatio,
|
||||
{i18next.t(
|
||||
'音频提示价格:${{price}} * {{audioRatio}} = ${{total}} / 1M tokens (音频倍率: {{audioRatio}})',
|
||||
{
|
||||
price: inputRatioPrice,
|
||||
completion: completionTokens,
|
||||
compPrice: completionRatioPrice,
|
||||
total: textPrice.toFixed(6)
|
||||
}) :
|
||||
i18next.t('文字提示 {{input}} tokens / 1M tokens * ${{price}} + 文字补全 {{completion}} tokens / 1M tokens * ${{compPrice}} = ${{total}}', {
|
||||
input: inputTokens,
|
||||
price: inputRatioPrice,
|
||||
completion: completionTokens,
|
||||
compPrice: completionRatioPrice,
|
||||
total: textPrice.toFixed(6)
|
||||
})
|
||||
}
|
||||
total: inputRatioPrice * audioRatio,
|
||||
audioRatio: audioRatio,
|
||||
},
|
||||
)}
|
||||
</p>
|
||||
<p>
|
||||
{i18next.t('音频提示 {{input}} tokens / 1M tokens * ${{audioInputPrice}} + 音频补全 {{completion}} tokens / 1M tokens * ${{audioCompPrice}} = ${{total}}', {
|
||||
input: audioInputTokens,
|
||||
completion: audioCompletionTokens,
|
||||
audioInputPrice: audioRatio * inputRatioPrice,
|
||||
audioCompPrice: audioRatio * audioCompletionRatio * inputRatioPrice,
|
||||
total: audioPrice.toFixed(6)
|
||||
})}
|
||||
{i18next.t(
|
||||
'音频补全价格:${{price}} * {{audioRatio}} * {{audioCompRatio}} = ${{total}} / 1M tokens (音频补全倍率: {{audioCompRatio}})',
|
||||
{
|
||||
price: inputRatioPrice,
|
||||
total: inputRatioPrice * audioRatio * audioCompletionRatio,
|
||||
audioRatio: audioRatio,
|
||||
audioCompRatio: audioCompletionRatio,
|
||||
},
|
||||
)}
|
||||
</p>
|
||||
<p>
|
||||
{i18next.t('总价:文字价格 {{textPrice}} + 音频价格 {{audioPrice}} = ${{total}}', {
|
||||
total: price.toFixed(6),
|
||||
textPrice: textPrice.toFixed(6),
|
||||
audioPrice: audioPrice.toFixed(6)
|
||||
})}
|
||||
{cacheTokens > 0
|
||||
? i18next.t(
|
||||
'文字提示 {{nonCacheInput}} tokens / 1M tokens * ${{price}} + 缓存 {{cacheInput}} tokens / 1M tokens * ${{cachePrice}} + 文字补全 {{completion}} tokens / 1M tokens * ${{compPrice}} = ${{total}}',
|
||||
{
|
||||
nonCacheInput: inputTokens - cacheTokens,
|
||||
cacheInput: cacheTokens,
|
||||
cachePrice: inputRatioPrice * cacheRatio,
|
||||
price: inputRatioPrice,
|
||||
completion: completionTokens,
|
||||
compPrice: completionRatioPrice,
|
||||
total: textPrice.toFixed(6),
|
||||
},
|
||||
)
|
||||
: i18next.t(
|
||||
'文字提示 {{input}} tokens / 1M tokens * ${{price}} + 文字补全 {{completion}} tokens / 1M tokens * ${{compPrice}} = ${{total}}',
|
||||
{
|
||||
input: inputTokens,
|
||||
price: inputRatioPrice,
|
||||
completion: completionTokens,
|
||||
compPrice: completionRatioPrice,
|
||||
total: textPrice.toFixed(6),
|
||||
},
|
||||
)}
|
||||
</p>
|
||||
<p>
|
||||
{i18next.t(
|
||||
'音频提示 {{input}} tokens / 1M tokens * ${{audioInputPrice}} + 音频补全 {{completion}} tokens / 1M tokens * ${{audioCompPrice}} = ${{total}}',
|
||||
{
|
||||
input: audioInputTokens,
|
||||
completion: audioCompletionTokens,
|
||||
audioInputPrice: audioRatio * inputRatioPrice,
|
||||
audioCompPrice:
|
||||
audioRatio * audioCompletionRatio * inputRatioPrice,
|
||||
total: audioPrice.toFixed(6),
|
||||
},
|
||||
)}
|
||||
</p>
|
||||
<p>
|
||||
{i18next.t(
|
||||
'总价:文字价格 {{textPrice}} + 音频价格 {{audioPrice}} = ${{total}}',
|
||||
{
|
||||
total: price.toFixed(6),
|
||||
textPrice: textPrice.toFixed(6),
|
||||
audioPrice: audioPrice.toFixed(6),
|
||||
},
|
||||
)}
|
||||
</p>
|
||||
<p>{i18next.t('仅供参考,以实际扣费为准')}</p>
|
||||
</article>
|
||||
@@ -517,7 +597,9 @@ export function renderQuotaWithPrompt(quota, digits) {
|
||||
let displayInCurrency = localStorage.getItem('display_in_currency');
|
||||
displayInCurrency = displayInCurrency === 'true';
|
||||
if (displayInCurrency) {
|
||||
return ' | ' + i18next.t('等价金额') + ': ' + renderQuota(quota, digits) + '';
|
||||
return (
|
||||
' | ' + i18next.t('等价金额') + ': ' + renderQuota(quota, digits) + ''
|
||||
);
|
||||
}
|
||||
return '';
|
||||
}
|
||||
@@ -537,7 +619,7 @@ const colors = [
|
||||
'red',
|
||||
'teal',
|
||||
'violet',
|
||||
'yellow'
|
||||
'yellow',
|
||||
];
|
||||
|
||||
// 基础10色色板 (N ≤ 10)
|
||||
@@ -551,7 +633,7 @@ const baseColors = [
|
||||
'#304D77',
|
||||
'#B48DEB',
|
||||
'#009488',
|
||||
'#FF7DDA'
|
||||
'#FF7DDA',
|
||||
];
|
||||
|
||||
// 扩展20色色板 (10 < N ≤ 20)
|
||||
@@ -575,7 +657,7 @@ const extendedColors = [
|
||||
'#009488',
|
||||
'#59BAA8',
|
||||
'#FF7DDA',
|
||||
'#FFCFEE'
|
||||
'#FFCFEE',
|
||||
];
|
||||
|
||||
export const modelColorMap = {
|
||||
@@ -631,14 +713,14 @@ export function modelToColor(modelName) {
|
||||
// 2. 生成一个稳定的数字作为索引
|
||||
let hash = 0;
|
||||
for (let i = 0; i < modelName.length; i++) {
|
||||
hash = ((hash << 5) - hash) + modelName.charCodeAt(i);
|
||||
hash = (hash << 5) - hash + modelName.charCodeAt(i);
|
||||
hash = hash & hash; // Convert to 32-bit integer
|
||||
}
|
||||
hash = Math.abs(hash);
|
||||
|
||||
// 3. 根据模型名称长度选择不同的色板
|
||||
const colorPalette = modelName.length > 10 ? extendedColors : baseColors;
|
||||
|
||||
|
||||
// 4. 使用hash值选择颜色
|
||||
const index = hash % colorPalette.length;
|
||||
return colorPalette[index];
|
||||
@@ -668,12 +750,15 @@ export function renderClaudeModelPrice(
|
||||
const ratioLabel = false ? i18next.t('专属倍率') : i18next.t('分组倍率');
|
||||
|
||||
if (modelPrice !== -1) {
|
||||
return i18next.t('模型价格:${{price}} * {{ratioType}}:{{ratio}} = ${{total}}', {
|
||||
price: modelPrice,
|
||||
ratioType: ratioLabel,
|
||||
ratio: groupRatio,
|
||||
total: modelPrice * groupRatio
|
||||
});
|
||||
return i18next.t(
|
||||
'模型价格:${{price}} * {{ratioType}}:{{ratio}} = ${{total}}',
|
||||
{
|
||||
price: modelPrice,
|
||||
ratioType: ratioLabel,
|
||||
ratio: groupRatio,
|
||||
total: modelPrice * groupRatio,
|
||||
},
|
||||
);
|
||||
} else {
|
||||
if (completionRatio === undefined) {
|
||||
completionRatio = 0;
|
||||
@@ -687,9 +772,10 @@ export function renderClaudeModelPrice(
|
||||
|
||||
// Calculate effective input tokens (non-cached + cached with ratio applied + cache creation with ratio applied)
|
||||
const nonCachedTokens = inputTokens;
|
||||
const effectiveInputTokens = nonCachedTokens +
|
||||
(cacheTokens * cacheRatio) +
|
||||
(cacheCreationTokens * cacheCreationRatio);
|
||||
const effectiveInputTokens =
|
||||
nonCachedTokens +
|
||||
cacheTokens * cacheRatio +
|
||||
cacheCreationTokens * cacheCreationRatio;
|
||||
|
||||
let price =
|
||||
(effectiveInputTokens / 1000000) * inputRatioPrice * groupRatio +
|
||||
@@ -698,56 +784,78 @@ export function renderClaudeModelPrice(
|
||||
return (
|
||||
<>
|
||||
<article>
|
||||
<p>{i18next.t('提示价格:${{price}} / 1M tokens', {
|
||||
price: inputRatioPrice,
|
||||
})}</p>
|
||||
<p>{i18next.t('补全价格:${{price}} * {{ratio}} = ${{total}} / 1M tokens', {
|
||||
price: inputRatioPrice,
|
||||
ratio: completionRatio,
|
||||
total: completionRatioPrice
|
||||
})}</p>
|
||||
{cacheTokens > 0 && (
|
||||
<p>{i18next.t('缓存价格:${{price}} * {{ratio}} = ${{total}} / 1M tokens (缓存倍率: {{cacheRatio}})', {
|
||||
<p>
|
||||
{i18next.t('提示价格:${{price}} / 1M tokens', {
|
||||
price: inputRatioPrice,
|
||||
ratio: cacheRatio,
|
||||
total: cacheRatioPrice,
|
||||
cacheRatio: cacheRatio
|
||||
})}</p>
|
||||
})}
|
||||
</p>
|
||||
<p>
|
||||
{i18next.t(
|
||||
'补全价格:${{price}} * {{ratio}} = ${{total}} / 1M tokens',
|
||||
{
|
||||
price: inputRatioPrice,
|
||||
ratio: completionRatio,
|
||||
total: completionRatioPrice,
|
||||
},
|
||||
)}
|
||||
</p>
|
||||
{cacheTokens > 0 && (
|
||||
<p>
|
||||
{i18next.t(
|
||||
'缓存价格:${{price}} * {{ratio}} = ${{total}} / 1M tokens (缓存倍率: {{cacheRatio}})',
|
||||
{
|
||||
price: inputRatioPrice,
|
||||
ratio: cacheRatio,
|
||||
total: cacheRatioPrice,
|
||||
cacheRatio: cacheRatio,
|
||||
},
|
||||
)}
|
||||
</p>
|
||||
)}
|
||||
{cacheCreationTokens > 0 && (
|
||||
<p>{i18next.t('缓存创建价格:${{price}} * {{ratio}} = ${{total}} / 1M tokens (缓存创建倍率: {{cacheCreationRatio}})', {
|
||||
price: inputRatioPrice,
|
||||
ratio: cacheCreationRatio,
|
||||
total: cacheCreationRatioPrice,
|
||||
cacheCreationRatio: cacheCreationRatio
|
||||
})}</p>
|
||||
<p>
|
||||
{i18next.t(
|
||||
'缓存创建价格:${{price}} * {{ratio}} = ${{total}} / 1M tokens (缓存创建倍率: {{cacheCreationRatio}})',
|
||||
{
|
||||
price: inputRatioPrice,
|
||||
ratio: cacheCreationRatio,
|
||||
total: cacheCreationRatioPrice,
|
||||
cacheCreationRatio: cacheCreationRatio,
|
||||
},
|
||||
)}
|
||||
</p>
|
||||
)}
|
||||
<p></p>
|
||||
<p>
|
||||
{(cacheTokens > 0 || cacheCreationTokens > 0) ?
|
||||
i18next.t('提示 {{nonCacheInput}} tokens / 1M tokens * ${{price}} + 缓存 {{cacheInput}} tokens / 1M tokens * ${{cachePrice}} + 缓存创建 {{cacheCreationInput}} tokens / 1M tokens * ${{cacheCreationPrice}} + 补全 {{completion}} tokens / 1M tokens * ${{compPrice}} * 分组 {{ratio}} = ${{total}}', {
|
||||
nonCacheInput: nonCachedTokens,
|
||||
cacheInput: cacheTokens,
|
||||
cacheRatio: cacheRatio,
|
||||
cacheCreationInput: cacheCreationTokens,
|
||||
cacheCreationRatio: cacheCreationRatio,
|
||||
cachePrice: cacheRatioPrice,
|
||||
cacheCreationPrice: cacheCreationRatioPrice,
|
||||
price: inputRatioPrice,
|
||||
completion: completionTokens,
|
||||
compPrice: completionRatioPrice,
|
||||
ratio: groupRatio,
|
||||
total: price.toFixed(6)
|
||||
}) :
|
||||
i18next.t('提示 {{input}} tokens / 1M tokens * ${{price}} + 补全 {{completion}} tokens / 1M tokens * ${{compPrice}} * 分组 {{ratio}} = ${{total}}', {
|
||||
input: inputTokens,
|
||||
price: inputRatioPrice,
|
||||
completion: completionTokens,
|
||||
compPrice: completionRatioPrice,
|
||||
ratio: groupRatio,
|
||||
total: price.toFixed(6)
|
||||
})
|
||||
}
|
||||
{cacheTokens > 0 || cacheCreationTokens > 0
|
||||
? i18next.t(
|
||||
'提示 {{nonCacheInput}} tokens / 1M tokens * ${{price}} + 缓存 {{cacheInput}} tokens / 1M tokens * ${{cachePrice}} + 缓存创建 {{cacheCreationInput}} tokens / 1M tokens * ${{cacheCreationPrice}} + 补全 {{completion}} tokens / 1M tokens * ${{compPrice}} * 分组 {{ratio}} = ${{total}}',
|
||||
{
|
||||
nonCacheInput: nonCachedTokens,
|
||||
cacheInput: cacheTokens,
|
||||
cacheRatio: cacheRatio,
|
||||
cacheCreationInput: cacheCreationTokens,
|
||||
cacheCreationRatio: cacheCreationRatio,
|
||||
cachePrice: cacheRatioPrice,
|
||||
cacheCreationPrice: cacheCreationRatioPrice,
|
||||
price: inputRatioPrice,
|
||||
completion: completionTokens,
|
||||
compPrice: completionRatioPrice,
|
||||
ratio: groupRatio,
|
||||
total: price.toFixed(6),
|
||||
},
|
||||
)
|
||||
: i18next.t(
|
||||
'提示 {{input}} tokens / 1M tokens * ${{price}} + 补全 {{completion}} tokens / 1M tokens * ${{compPrice}} * 分组 {{ratio}} = ${{total}}',
|
||||
{
|
||||
input: inputTokens,
|
||||
price: inputRatioPrice,
|
||||
completion: completionTokens,
|
||||
compPrice: completionRatioPrice,
|
||||
ratio: groupRatio,
|
||||
total: price.toFixed(6),
|
||||
},
|
||||
)}
|
||||
</p>
|
||||
<p>{i18next.t('仅供参考,以实际扣费为准')}</p>
|
||||
</article>
|
||||
@@ -770,17 +878,20 @@ export function renderClaudeLogContent(
|
||||
return i18next.t('模型价格 ${{price}},{{ratioType}} {{ratio}}', {
|
||||
price: modelPrice,
|
||||
ratioType: ratioLabel,
|
||||
ratio: groupRatio
|
||||
ratio: groupRatio,
|
||||
});
|
||||
} else {
|
||||
return i18next.t('模型倍率 {{modelRatio}},补全倍率 {{completionRatio}},缓存倍率 {{cacheRatio}},缓存创建倍率 {{cacheCreationRatio}},{{ratioType}} {{ratio}}', {
|
||||
modelRatio: modelRatio,
|
||||
completionRatio: completionRatio,
|
||||
cacheRatio: cacheRatio,
|
||||
cacheCreationRatio: cacheCreationRatio,
|
||||
ratioType: ratioLabel,
|
||||
ratio: groupRatio
|
||||
});
|
||||
return i18next.t(
|
||||
'模型倍率 {{modelRatio}},补全倍率 {{completionRatio}},缓存倍率 {{cacheRatio}},缓存创建倍率 {{cacheCreationRatio}},{{ratioType}} {{ratio}}',
|
||||
{
|
||||
modelRatio: modelRatio,
|
||||
completionRatio: completionRatio,
|
||||
cacheRatio: cacheRatio,
|
||||
cacheCreationRatio: cacheCreationRatio,
|
||||
ratioType: ratioLabel,
|
||||
ratio: groupRatio,
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -799,22 +910,25 @@ export function renderClaudeModelPriceSimple(
|
||||
return i18next.t('价格:${{price}} * {{ratioType}}:{{ratio}}', {
|
||||
price: modelPrice,
|
||||
ratioType: ratioLabel,
|
||||
ratio: groupRatio
|
||||
ratio: groupRatio,
|
||||
});
|
||||
} else {
|
||||
if (cacheTokens !== 0 || cacheCreationTokens !== 0) {
|
||||
return i18next.t('模型: {{ratio}} * {{ratioType}}: {{groupRatio}} * 缓存: {{cacheRatio}}', {
|
||||
ratio: modelRatio,
|
||||
ratioType: ratioLabel,
|
||||
groupRatio: groupRatio,
|
||||
cacheRatio: cacheRatio,
|
||||
cacheCreationRatio: cacheCreationRatio
|
||||
});
|
||||
return i18next.t(
|
||||
'模型: {{ratio}} * {{ratioType}}: {{groupRatio}} * 缓存: {{cacheRatio}}',
|
||||
{
|
||||
ratio: modelRatio,
|
||||
ratioType: ratioLabel,
|
||||
groupRatio: groupRatio,
|
||||
cacheRatio: cacheRatio,
|
||||
cacheCreationRatio: cacheCreationRatio,
|
||||
},
|
||||
);
|
||||
} else {
|
||||
return i18next.t('模型: {{ratio}} * {{ratioType}}: {{groupRatio}}', {
|
||||
ratio: modelRatio,
|
||||
ratioType: ratioLabel,
|
||||
groupRatio: groupRatio
|
||||
groupRatio: groupRatio,
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -824,7 +938,7 @@ export function renderLogContent(
|
||||
modelRatio,
|
||||
completionRatio,
|
||||
modelPrice = -1,
|
||||
groupRatio
|
||||
groupRatio,
|
||||
) {
|
||||
const ratioLabel = false ? i18next.t('专属倍率') : i18next.t('分组倍率');
|
||||
|
||||
@@ -832,14 +946,17 @@ export function renderLogContent(
|
||||
return i18next.t('模型价格 ${{price}},{{ratioType}} {{ratio}}', {
|
||||
price: modelPrice,
|
||||
ratioType: ratioLabel,
|
||||
ratio: groupRatio
|
||||
ratio: groupRatio,
|
||||
});
|
||||
} else {
|
||||
return i18next.t('模型倍率 {{modelRatio}},补全倍率 {{completionRatio}},{{ratioType}} {{ratio}}', {
|
||||
modelRatio: modelRatio,
|
||||
completionRatio: completionRatio,
|
||||
ratioType: ratioLabel,
|
||||
ratio: groupRatio
|
||||
});
|
||||
return i18next.t(
|
||||
'模型倍率 {{modelRatio}},补全倍率 {{completionRatio}},{{ratioType}} {{ratio}}',
|
||||
{
|
||||
modelRatio: modelRatio,
|
||||
completionRatio: completionRatio,
|
||||
ratioType: ratioLabel,
|
||||
ratio: groupRatio,
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user