diff --git a/web/src/components/table/ChannelsTable.js b/web/src/components/table/ChannelsTable.js index f8145056..0f4b428b 100644 --- a/web/src/components/table/ChannelsTable.js +++ b/web/src/components/table/ChannelsTable.js @@ -7,9 +7,23 @@ import { timestamp2string, renderGroup, renderNumberWithPoint, - renderQuota + renderQuota, + getChannelIcon } from '../../helpers/index.js'; +import { + CheckCircle, + XCircle, + AlertCircle, + HelpCircle, + TestTube, + Zap, + Timer, + Clock, + AlertTriangle, + Coins +} from 'lucide-react'; + import { CHANNEL_OPTIONS, ITEMS_PER_PAGE } from '../../constants/index.js'; import { Button, @@ -63,7 +77,12 @@ const ChannelsTable = () => { type2label[0] = { value: 0, label: t('未知类型'), color: 'grey' }; } return ( - + {type2label[type]?.label} ); @@ -87,25 +106,25 @@ const ChannelsTable = () => { switch (status) { case 1: return ( - + }> {t('已启用')} ); case 2: return ( - + }> {t('已禁用')} ); case 3: return ( - + }> {t('自动禁用')} ); default: return ( - + }> {t('未知状态')} ); @@ -117,31 +136,31 @@ const ChannelsTable = () => { time = time.toFixed(2) + t(' 秒'); if (responseTime === 0) { return ( - + }> {t('未测试')} ); } else if (responseTime <= 1000) { return ( - + }> {time} ); } else if (responseTime <= 3000) { return ( - + }> {time} ); } else if (responseTime <= 5000) { return ( - + }> {time} ); } else { return ( - + }> {time} ); @@ -228,7 +247,7 @@ const ChannelsTable = () => {
- + }> {renderQuota(record.used_quota)} @@ -238,6 +257,7 @@ const ChannelsTable = () => { type='ghost' size='large' shape='circle' + prefixIcon={} onClick={() => updateChannelBalance(record)} > ${renderNumberWithPoint(record.balance)} @@ -249,7 +269,7 @@ const ChannelsTable = () => { } else { return ( - + }> {renderQuota(record.used_quota)} diff --git a/web/src/components/table/LogsTable.js b/web/src/components/table/LogsTable.js index 60c6be32..d25460d1 100644 --- a/web/src/components/table/LogsTable.js +++ b/web/src/components/table/LogsTable.js @@ -1,5 +1,18 @@ import React, { useEffect, useState } from 'react'; import { useTranslation } from 'react-i18next'; +import { + CreditCard, + ShoppingCart, + Settings, + Server, + AlertTriangle, + HelpCircle, + Zap, + Play, + Clock, + Hash, + Key +} from 'lucide-react'; import { API, copy, @@ -20,7 +33,7 @@ import { renderQuota, stringToColor, getLogOther, - renderModelTag, + renderModelTag } from '../../helpers'; import { @@ -38,7 +51,7 @@ import { Card, Typography, Divider, - Form, + Form } from '@douyinfe/semi-ui'; import { ITEMS_PER_PAGE } from '../../constants'; import Paragraph from '@douyinfe/semi-ui/lib/es/typography/paragraph'; @@ -71,37 +84,37 @@ const LogsTable = () => { switch (type) { case 1: return ( - + }> {t('充值')} ); case 2: return ( - + }> {t('消费')} ); case 3: return ( - + }> {t('管理')} ); case 4: return ( - + }> {t('系统')} ); case 5: return ( - + }> {t('错误')} ); default: return ( - + }> {t('未知')} ); @@ -111,13 +124,13 @@ const LogsTable = () => { function renderIsStream(bool) { if (bool) { return ( - + }> {t('流')} ); } else { return ( - + }> {t('非流')} ); @@ -128,21 +141,21 @@ const LogsTable = () => { const time = parseInt(type); if (time < 101) { return ( - + }> {' '} {time} s{' '} ); } else if (time < 300) { return ( - + }> {' '} {time} s{' '} ); } else { return ( - + }> {' '} {time} s{' '} @@ -155,21 +168,21 @@ const LogsTable = () => { time = time.toFixed(1); if (time < 3) { return ( - + }> {' '} {time} s{' '} ); } else if (time < 10) { return ( - + }> {' '} {time} s{' '} ); } else { return ( - + }> {' '} {time} s{' '} @@ -356,6 +369,7 @@ const LogsTable = () => { color={colors[parseInt(text) % colors.length]} size='large' shape='circle' + prefixIcon={} > {' '} {text}{' '} @@ -408,6 +422,7 @@ const LogsTable = () => { color='grey' size='large' shape='circle' + prefixIcon={} onClick={(event) => { //cancel the row click event copyText(event, text); diff --git a/web/src/components/table/MjLogsTable.js b/web/src/components/table/MjLogsTable.js index f4eeed44..b78d3c13 100644 --- a/web/src/components/table/MjLogsTable.js +++ b/web/src/components/table/MjLogsTable.js @@ -1,12 +1,38 @@ import React, { useEffect, useState } from 'react'; import { useTranslation } from 'react-i18next'; +import { + Palette, + ZoomIn, + Shuffle, + Move, + FileText, + Blend, + Upload, + Minimize2, + RotateCcw, + PaintBucket, + Focus, + Move3D, + Monitor, + UserCheck, + HelpCircle, + CheckCircle, + Clock, + Copy, + FileX, + Pause, + XCircle, + Loader, + AlertCircle, + Hash +} from 'lucide-react'; import { API, copy, isAdmin, showError, showSuccess, - timestamp2string, + timestamp2string } from '../../helpers'; import { @@ -22,13 +48,13 @@ import { Skeleton, Table, Tag, - Typography, + Typography } from '@douyinfe/semi-ui'; import { ITEMS_PER_PAGE } from '../../constants'; import { IconEyeOpened, IconSearch, - IconSetting, + IconSetting } from '@douyinfe/semi-icons'; const { Text } = Typography; @@ -153,103 +179,103 @@ const LogsTable = () => { switch (type) { case 'IMAGINE': return ( - + }> {t('绘图')} ); case 'UPSCALE': return ( - + }> {t('放大')} ); case 'VARIATION': return ( - + }> {t('变换')} ); case 'HIGH_VARIATION': return ( - + }> {t('强变换')} ); case 'LOW_VARIATION': return ( - + }> {t('弱变换')} ); case 'PAN': return ( - + }> {t('平移')} ); case 'DESCRIBE': return ( - + }> {t('图生文')} ); case 'BLEND': return ( - + }> {t('图混合')} ); case 'UPLOAD': return ( - + }> 上传文件 ); case 'SHORTEN': return ( - + }> {t('缩词')} ); case 'REROLL': return ( - + }> {t('重绘')} ); case 'INPAINT': return ( - + }> {t('局部重绘-提交')} ); case 'ZOOM': return ( - + }> {t('变焦')} ); case 'CUSTOM_ZOOM': return ( - + }> {t('自定义变焦-提交')} ); case 'MODAL': return ( - + }> {t('窗口处理')} ); case 'SWAP_FACE': return ( - + }> {t('换脸')} ); default: return ( - + }> {t('未知')} ); @@ -260,31 +286,31 @@ const LogsTable = () => { switch (code) { case 1: return ( - + }> {t('已提交')} ); case 21: return ( - + }> {t('等待中')} ); case 22: return ( - + }> {t('重复提交')} ); case 0: return ( - + }> {t('未提交')} ); default: return ( - + }> {t('未知')} ); @@ -295,43 +321,43 @@ const LogsTable = () => { switch (type) { case 'SUCCESS': return ( - + }> {t('成功')} ); case 'NOT_START': return ( - + }> {t('未启动')} ); case 'SUBMITTED': return ( - + }> {t('队列中')} ); case 'IN_PROGRESS': return ( - + }> {t('执行中')} ); case 'FAILURE': return ( - + }> {t('失败')} ); case 'MODAL': return ( - + }> {t('窗口等待')} ); default: return ( - + }> {t('未知')} ); @@ -361,7 +387,7 @@ const LogsTable = () => { const color = durationSec > 60 ? 'red' : 'green'; return ( - + }> {durationSec} {t('秒')} ); @@ -397,6 +423,7 @@ const LogsTable = () => { color={colors[parseInt(text) % colors.length]} size='large' shape='circle' + prefixIcon={} onClick={() => { copyText(text); }} diff --git a/web/src/components/table/RedemptionsTable.js b/web/src/components/table/RedemptionsTable.js index 4f9779a9..dbe527a5 100644 --- a/web/src/components/table/RedemptionsTable.js +++ b/web/src/components/table/RedemptionsTable.js @@ -8,6 +8,14 @@ import { renderQuota } from '../../helpers'; +import { + CheckCircle, + XCircle, + Minus, + HelpCircle, + Coins +} from 'lucide-react'; + import { ITEMS_PER_PAGE } from '../../constants'; import { Button, @@ -20,7 +28,7 @@ import { Space, Table, Tag, - Typography, + Typography } from '@douyinfe/semi-ui'; import { IconPlus, @@ -31,7 +39,7 @@ import { IconDelete, IconStop, IconPlay, - IconMore, + IconMore } from '@douyinfe/semi-icons'; import EditRedemption from '../../pages/Redemption/EditRedemption'; import { useTranslation } from 'react-i18next'; @@ -49,25 +57,25 @@ const RedemptionsTable = () => { switch (status) { case 1: return ( - + }> {t('未使用')} ); case 2: return ( - + }> {t('已禁用')} ); case 3: return ( - + }> {t('已使用')} ); default: return ( - + }> {t('未知状态')} ); @@ -95,7 +103,13 @@ const RedemptionsTable = () => { title: t('额度'), dataIndex: 'quota', render: (text, record, index) => { - return
{renderQuota(parseInt(text))}
; + return ( +
+ }> + {renderQuota(parseInt(text))} + +
+ ); }, }, { diff --git a/web/src/components/table/TaskLogsTable.js b/web/src/components/table/TaskLogsTable.js index cc8cd6d5..f8a3214e 100644 --- a/web/src/components/table/TaskLogsTable.js +++ b/web/src/components/table/TaskLogsTable.js @@ -1,12 +1,25 @@ import React, { useEffect, useState } from 'react'; import { useTranslation } from 'react-i18next'; +import { + Music, + FileText, + HelpCircle, + CheckCircle, + Pause, + Clock, + Play, + XCircle, + Loader, + List, + Hash +} from 'lucide-react'; import { API, copy, isAdmin, showError, showSuccess, - timestamp2string, + timestamp2string } from '../../helpers'; import { @@ -21,13 +34,13 @@ import { Skeleton, Table, Tag, - Typography, + Typography } from '@douyinfe/semi-ui'; import { ITEMS_PER_PAGE } from '../../constants'; import { IconEyeOpened, IconSearch, - IconSetting, + IconSetting } from '@douyinfe/semi-icons'; const { Text } = Typography; @@ -96,7 +109,7 @@ function renderDuration(submit_time, finishTime) { // 返回带有样式的颜色标签 return ( - + }> {durationSec} 秒 ); @@ -187,19 +200,19 @@ const LogsTable = () => { switch (type) { case 'MUSIC': return ( - + }> {t('生成音乐')} ); case 'LYRICS': return ( - + }> {t('生成歌词')} ); default: return ( - + }> {t('未知')} ); @@ -210,13 +223,13 @@ const LogsTable = () => { switch (type) { case 'suno': return ( - + }> Suno ); default: return ( - + }> {t('未知')} ); @@ -227,55 +240,55 @@ const LogsTable = () => { switch (type) { case 'SUCCESS': return ( - + }> {t('成功')} ); case 'NOT_START': return ( - + }> {t('未启动')} ); case 'SUBMITTED': return ( - + }> {t('队列中')} ); case 'IN_PROGRESS': return ( - + }> {t('执行中')} ); case 'FAILURE': return ( - + }> {t('失败')} ); case 'QUEUED': return ( - + }> {t('排队中')} ); case 'UNKNOWN': return ( - + }> {t('未知')} ); case '': return ( - + }> {t('正在提交')} ); default: return ( - + }> {t('未知')} ); @@ -320,6 +333,7 @@ const LogsTable = () => { color={colors[parseInt(text) % colors.length]} size='large' shape='circle' + prefixIcon={} onClick={() => { copyText(text); }} diff --git a/web/src/components/table/TokensTable.js b/web/src/components/table/TokensTable.js index 9d0ec522..20d18a21 100644 --- a/web/src/components/table/TokensTable.js +++ b/web/src/components/table/TokensTable.js @@ -6,7 +6,8 @@ import { showSuccess, timestamp2string, renderGroup, - renderQuota + renderQuota, + getQuotaPerUnit } from '../../helpers'; import { ITEMS_PER_PAGE } from '../../constants'; @@ -19,9 +20,20 @@ import { Space, SplitButtonGroup, Table, - Tag, + Tag } from '@douyinfe/semi-ui'; +import { + CheckCircle, + Shield, + XCircle, + Clock, + Gauge, + HelpCircle, + Infinity, + Coins +} from 'lucide-react'; + import { IconPlus, IconCopy, @@ -32,7 +44,7 @@ import { IconDelete, IconStop, IconPlay, - IconMore, + IconMore } from '@douyinfe/semi-icons'; import EditToken from '../../pages/Token/EditToken'; import { useTranslation } from 'react-i18next'; @@ -49,38 +61,38 @@ const TokensTable = () => { case 1: if (model_limits_enabled) { return ( - + }> {t('已启用:限制模型')} ); } else { return ( - + }> {t('已启用')} ); } case 2: return ( - + }> {t('已禁用')} ); case 3: return ( - + }> {t('已过期')} ); case 4: return ( - + }> {t('已耗尽')} ); default: return ( - + }> {t('未知状态')} ); @@ -111,21 +123,45 @@ const TokensTable = () => { title: t('已用额度'), dataIndex: 'used_quota', render: (text, record, index) => { - return
{renderQuota(parseInt(text))}
; + return ( +
+ }> + {renderQuota(parseInt(text))} + +
+ ); }, }, { title: t('剩余额度'), dataIndex: 'remain_quota', render: (text, record, index) => { + const getQuotaColor = (quotaValue) => { + const quotaPerUnit = getQuotaPerUnit(); + const dollarAmount = quotaValue / quotaPerUnit; + + if (dollarAmount <= 0) { + return 'red'; + } else if (dollarAmount <= 100) { + return 'yellow'; + } else { + return 'green'; + } + }; + return (
{record.unlimited_quota ? ( - + }> {t('无限制')} ) : ( - + } + > {renderQuota(parseInt(text))} )} diff --git a/web/src/components/table/UsersTable.js b/web/src/components/table/UsersTable.js index 5574dab7..6fbf368c 100644 --- a/web/src/components/table/UsersTable.js +++ b/web/src/components/table/UsersTable.js @@ -1,5 +1,20 @@ import React, { useEffect, useState } from 'react'; import { API, showError, showSuccess, renderGroup, renderNumber, renderQuota } from '../../helpers'; + +import { + User, + Shield, + Crown, + HelpCircle, + CheckCircle, + XCircle, + Minus, + Coins, + Activity, + Users, + DollarSign, + UserPlus +} from 'lucide-react'; import { Button, Card, @@ -10,7 +25,7 @@ import { Space, Table, Tag, - Typography, + Typography } from '@douyinfe/semi-ui'; import { IconPlus, @@ -22,7 +37,7 @@ import { IconMore, IconUserAdd, IconArrowUp, - IconArrowDown, + IconArrowDown } from '@douyinfe/semi-icons'; import { ITEMS_PER_PAGE } from '../../constants'; import AddUser from '../../pages/User/AddUser'; @@ -38,25 +53,25 @@ const UsersTable = () => { switch (role) { case 1: return ( - + }> {t('普通用户')} ); case 10: return ( - + }> {t('管理员')} ); case 100: return ( - + }> {t('超级管理员')} ); default: return ( - + }> {t('未知身份')} ); @@ -66,16 +81,16 @@ const UsersTable = () => { const renderStatus = (status) => { switch (status) { case 1: - return {t('已激活')}; + return }>{t('已激活')}; case 2: return ( - + }> {t('已封禁')} ); default: return ( - + }> {t('未知状态')} ); @@ -105,13 +120,13 @@ const UsersTable = () => { return (
- + }> {t('剩余')}: {renderQuota(record.quota)} - + }> {t('已用')}: {renderQuota(record.used_quota)} - + }> {t('调用')}: {renderNumber(record.request_count)} @@ -126,13 +141,13 @@ const UsersTable = () => { return (
- + }> {t('邀请')}: {renderNumber(record.aff_count)} - + }> {t('收益')}: {renderQuota(record.aff_history_quota)} - + }> {record.inviter_id === 0 ? t('无邀请人') : `邀请人: ${record.inviter_id}`} @@ -154,7 +169,7 @@ const UsersTable = () => { return (
{record.DeletedAt !== null ? ( - {t('已注销')} + }>{t('已注销')} ) : ( renderStatus(text) )} diff --git a/web/src/helpers/render.js b/web/src/helpers/render.js index 833a046d..5d3e0e81 100644 --- a/web/src/helpers/render.js +++ b/web/src/helpers/render.js @@ -24,6 +24,13 @@ import { XAI, Ollama, Doubao, + Suno, + Xinference, + OpenRouter, + Dify, + Coze, + SiliconCloud, + FastGPT } from '@lobehub/icons'; import { @@ -40,6 +47,7 @@ import { User, Settings, CircleUser, + Users } from 'lucide-react'; // 侧边栏图标颜色映射 @@ -308,6 +316,88 @@ export const getModelCategories = (() => { }; })(); + +/** + * 根据渠道类型返回对应的厂商图标 + * @param {number} channelType - 渠道类型值 + * @returns {JSX.Element|null} - 对应的厂商图标组件 + */ +export function getChannelIcon(channelType) { + const iconSize = 14; + + switch (channelType) { + case 1: // OpenAI + case 3: // Azure OpenAI + return ; + case 2: // Midjourney Proxy + case 5: // Midjourney Proxy Plus + return ; + case 36: // Suno API + return ; + case 4: // Ollama + return ; + case 14: // Anthropic Claude + case 33: // AWS Claude + return ; + case 41: // Vertex AI + return ; + case 34: // Cohere + return ; + case 39: // Cloudflare + return ; + case 43: // DeepSeek + return ; + case 15: // 百度文心千帆 + case 46: // 百度文心千帆V2 + return ; + case 17: // 阿里通义千问 + return ; + case 18: // 讯飞星火认知 + return ; + case 16: // 智谱 ChatGLM + case 26: // 智谱 GLM-4V + return ; + case 24: // Google Gemini + case 11: // Google PaLM2 + return ; + case 47: // Xinference + return ; + case 25: // Moonshot + return ; + case 20: // OpenRouter + return ; + case 19: // 360 智脑 + return ; + case 23: // 腾讯混元 + return ; + case 31: // 零一万物 + return ; + case 35: // MiniMax + return ; + case 37: // Dify + return ; + case 38: // Jina + return ; + case 40: // SiliconCloud + return ; + case 42: // Mistral AI + return ; + case 45: // 字节火山方舟、豆包通用 + return ; + case 48: // xAI + return ; + case 49: // Coze + return ; + case 8: // 自定义渠道 + case 22: // 知识库:FastGPT + return ; + case 21: // 知识库:AI Proxy + case 44: // 嵌入模型:MokaAI M3E + default: + return null; // 未知类型或自定义渠道不显示图标 + } +} + // 颜色列表 const colors = [ 'amber', @@ -490,7 +580,7 @@ export function renderText(text, limit) { export function renderGroup(group) { if (group === '') { return ( - + }> {i18next.t('用户分组')} ); @@ -513,13 +603,14 @@ export function renderGroup(group) { color={tagColors[group] || stringToColor(group)} key={group} shape='circle' + prefixIcon={} onClick={async (event) => { event.stopPropagation(); if (await copy(group)) { showSuccess(i18next.t('已复制:') + group); } else { Modal.error({ - title: t('无法复制到剪贴板,请手动复制'), + title: i18next.t('无法复制到剪贴板,请手动复制'), content: group, }); } @@ -956,23 +1047,23 @@ export function renderModelPrice( const extraServices = [ webSearch && webSearchCallCount > 0 ? i18next.t( - ' + Web搜索 {{count}}次 / 1K 次 * ${{price}} * 分组倍率 {{ratio}}', - { - count: webSearchCallCount, - price: webSearchPrice, - ratio: groupRatio, - }, - ) + ' + Web搜索 {{count}}次 / 1K 次 * ${{price}} * 分组倍率 {{ratio}}', + { + count: webSearchCallCount, + price: webSearchPrice, + ratio: groupRatio, + }, + ) : '', fileSearch && fileSearchCallCount > 0 ? i18next.t( - ' + 文件搜索 {{count}}次 / 1K 次 * ${{price}} * 分组倍率 {{ratio}}', - { - count: fileSearchCallCount, - price: fileSearchPrice, - ratio: groupRatio, - }, - ) + ' + 文件搜索 {{count}}次 / 1K 次 * ${{price}} * 分组倍率 {{ratio}}', + { + count: fileSearchCallCount, + price: fileSearchPrice, + ratio: groupRatio, + }, + ) : '', ].join(''); @@ -1156,10 +1247,10 @@ export function renderAudioModelPrice( let audioPrice = (audioInputTokens / 1000000) * inputRatioPrice * audioRatio * groupRatio + (audioCompletionTokens / 1000000) * - inputRatioPrice * - audioRatio * - audioCompletionRatio * - groupRatio; + inputRatioPrice * + audioRatio * + audioCompletionRatio * + groupRatio; let price = textPrice + audioPrice; return ( <> @@ -1215,27 +1306,27 @@ export function renderAudioModelPrice(

{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), - }, - ) + '文字提示 {{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), - }, - )} + '文字提示 {{input}} tokens / 1M tokens * ${{price}} + 文字补全 {{completion}} tokens / 1M tokens * ${{compPrice}} = ${{total}}', + { + input: inputTokens, + price: inputRatioPrice, + completion: completionTokens, + compPrice: completionRatioPrice, + total: textPrice.toFixed(6), + }, + )}

{i18next.t( @@ -1372,33 +1463,33 @@ export function renderClaudeModelPrice(

{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), - }, - ) + '提示 {{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), - }, - )} + '提示 {{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), + }, + )}

{i18next.t('仅供参考,以实际扣费为准')}

diff --git a/web/src/index.css b/web/src/index.css index ebdc149a..2aec8e77 100644 --- a/web/src/index.css +++ b/web/src/index.css @@ -73,6 +73,7 @@ code { .semi-page-item, .semi-navigation-item, .semi-tag-closable, +.semi-input-wrapper, .semi-datepicker-range-input { border-radius: 9999px !important; }