diff --git a/web/src/components/table/model-pricing/PricingSidebar.jsx b/web/src/components/table/model-pricing/PricingSidebar.jsx index 39afed0f..b7282160 100644 --- a/web/src/components/table/model-pricing/PricingSidebar.jsx +++ b/web/src/components/table/model-pricing/PricingSidebar.jsx @@ -84,7 +84,7 @@ const PricingSidebar = ({ - + diff --git a/web/src/components/table/model-pricing/PricingTableColumns.js b/web/src/components/table/model-pricing/PricingTableColumns.js index be354671..f0c9783d 100644 --- a/web/src/components/table/model-pricing/PricingTableColumns.js +++ b/web/src/components/table/model-pricing/PricingTableColumns.js @@ -19,8 +19,7 @@ For commercial licensing, please contact support@quantumnous.com import React from 'react'; import { Tag, Space, Tooltip, Switch } from '@douyinfe/semi-ui'; -import { IconHelpCircle, IconCheckCircleStroked, IconClose } from '@douyinfe/semi-icons'; -import { Popover } from '@douyinfe/semi-ui'; +import { IconHelpCircle } from '@douyinfe/semi-icons'; import { renderModelTag, stringToColor } from '../../../helpers'; function renderQuotaType(type, t) { @@ -42,33 +41,6 @@ function renderQuotaType(type, t) { } } -function renderAvailable(available, t) { - if (available) { - return ( - {t('您的分组可以使用该模型')}} - position='top' - key={String(available)} - className="bg-green-50" - > - - - ); - } - - // 分组不可用时显示红色关闭图标 - return ( - {t('你的分组无权使用该模型')}} - position='top' - key="not-available" - className="bg-red-50" - > - - - ); -} - function renderSupportedEndpoints(endpoints) { if (!endpoints || endpoints.length === 0) { return null; @@ -91,22 +63,20 @@ function renderSupportedEndpoints(endpoints) { export const getPricingTableColumns = ({ t, selectedGroup, - usableGroup, groupRatio, copyText, setModalImageUrl, setIsModalOpenurl, currency, - showWithRecharge, tokenUnit, setTokenUnit, displayPrice, - handleGroupClick, showRatio, }) => { const endpointColumn = { title: t('可用端点类型'), dataIndex: 'supported_endpoint_types', + fixed: 'right', render: (text, record, index) => { return renderSupportedEndpoints(text); }, @@ -135,56 +105,7 @@ export const getPricingTableColumns = ({ sorter: (a, b) => a.quota_type - b.quota_type, }; - const enableGroupColumn = { - title: t('可用分组'), - dataIndex: 'enable_groups', - render: (text, record, index) => { - return ( - - {text.map((group) => { - if (usableGroup[group]) { - if (group === selectedGroup) { - return ( - }> - {group} - - ); - } else { - return ( - handleGroupClick(group)} - className="cursor-pointer hover:opacity-80 transition-opacity" - > - {group} - - ); - } - } - })} - - ); - }, - }; - - const baseColumns = [endpointColumn, modelNameColumn, quotaColumn, enableGroupColumn]; - - const availabilityColumn = { - title: t('可用性'), - dataIndex: 'available', - fixed: 'right', - render: (text, record, index) => { - return renderAvailable(record.enable_groups.includes(selectedGroup), t); - }, - sorter: (a, b) => { - const aAvailable = a.enable_groups.includes(selectedGroup); - const bAvailable = b.enable_groups.includes(selectedGroup); - return Number(aAvailable) - Number(bAvailable); - }, - defaultSortOrder: 'descend', - }; + const baseColumns = [modelNameColumn, quotaColumn]; const ratioColumn = { title: () => ( @@ -203,9 +124,8 @@ export const getPricingTableColumns = ({ ), dataIndex: 'model_ratio', render: (text, record, index) => { - let content = text; - let completionRatio = parseFloat(record.completion_ratio.toFixed(3)); - content = ( + const completionRatio = parseFloat(record.completion_ratio.toFixed(3)); + const content = (
{t('模型倍率')}:{record.quota_type === 0 ? text : t('无')} @@ -238,25 +158,23 @@ export const getPricingTableColumns = ({ ), dataIndex: 'model_price', render: (text, record, index) => { - let content = text; if (record.quota_type === 0) { - let inputRatioPriceUSD = record.model_ratio * 2 * groupRatio[selectedGroup]; - let completionRatioPriceUSD = + const inputRatioPriceUSD = record.model_ratio * 2 * groupRatio[selectedGroup]; + const completionRatioPriceUSD = record.model_ratio * record.completion_ratio * 2 * groupRatio[selectedGroup]; const unitDivisor = tokenUnit === 'K' ? 1000 : 1; const unitLabel = tokenUnit === 'K' ? 'K' : 'M'; - let displayInput = displayPrice(inputRatioPriceUSD); - let displayCompletion = displayPrice(completionRatioPriceUSD); + const rawDisplayInput = displayPrice(inputRatioPriceUSD); + const rawDisplayCompletion = displayPrice(completionRatioPriceUSD); - const divisor = unitDivisor; - const numInput = parseFloat(displayInput.replace(/[^0-9.]/g, '')) / divisor; - const numCompletion = parseFloat(displayCompletion.replace(/[^0-9.]/g, '')) / divisor; + const numInput = parseFloat(rawDisplayInput.replace(/[^0-9.]/g, '')) / unitDivisor; + const numCompletion = parseFloat(rawDisplayCompletion.replace(/[^0-9.]/g, '')) / unitDivisor; - displayInput = `${currency === 'CNY' ? '¥' : '$'}${numInput.toFixed(3)}`; - displayCompletion = `${currency === 'CNY' ? '¥' : '$'}${numCompletion.toFixed(3)}`; - content = ( + const displayInput = `${currency === 'CNY' ? '¥' : '$'}${numInput.toFixed(3)}`; + const displayCompletion = `${currency === 'CNY' ? '¥' : '$'}${numCompletion.toFixed(3)}`; + return (
{t('提示')} {displayInput} / 1{unitLabel} tokens @@ -267,15 +185,14 @@ export const getPricingTableColumns = ({
); } else { - let priceUSD = parseFloat(text) * groupRatio[selectedGroup]; - let displayVal = displayPrice(priceUSD); - content = ( + const priceUSD = parseFloat(text) * groupRatio[selectedGroup]; + const displayVal = displayPrice(priceUSD); + return (
{t('模型价格')}:{displayVal}
); } - return content; }, }; @@ -284,6 +201,6 @@ export const getPricingTableColumns = ({ columns.push(ratioColumn); } columns.push(priceColumn); - columns.push(availabilityColumn); + columns.push(endpointColumn); return columns; }; \ No newline at end of file diff --git a/web/src/components/table/model-pricing/filter/PricingGroups.jsx b/web/src/components/table/model-pricing/filter/PricingGroups.jsx index 75bdc2c7..e389bd12 100644 --- a/web/src/components/table/model-pricing/filter/PricingGroups.jsx +++ b/web/src/components/table/model-pricing/filter/PricingGroups.jsx @@ -25,24 +25,30 @@ import SelectableButtonGroup from '../../../common/ui/SelectableButtonGroup'; * @param {string} filterGroup 当前选中的分组,'all' 表示不过滤 * @param {Function} setFilterGroup 设置选中分组 * @param {Record} usableGroup 后端返回的可用分组对象 + * @param {Record} groupRatio 分组倍率对象 * @param {Array} models 模型列表 * @param {boolean} loading 是否加载中 * @param {Function} t i18n */ -const PricingGroups = ({ filterGroup, setFilterGroup, usableGroup = {}, models = [], loading = false, t }) => { +const PricingGroups = ({ filterGroup, setFilterGroup, usableGroup = {}, groupRatio = {}, models = [], loading = false, t }) => { const groups = ['all', ...Object.keys(usableGroup).filter(key => key !== '')]; const items = groups.map((g) => { - let count = 0; + let ratioDisplay = ''; if (g === 'all') { - count = models.length; + ratioDisplay = t('全部'); } else { - count = models.filter(m => m.enable_groups && m.enable_groups.includes(g)).length; + const ratio = groupRatio[g]; + if (ratio !== undefined && ratio !== null) { + ratioDisplay = `x${ratio}`; + } else { + ratioDisplay = 'x1'; + } } return { value: g, label: g === 'all' ? t('全部分组') : g, - tagCount: count, + tagCount: ratioDisplay, }; }); diff --git a/web/src/components/table/model-pricing/modal/PricingFilterModal.jsx b/web/src/components/table/model-pricing/modal/PricingFilterModal.jsx index 6182fb01..84edb454 100644 --- a/web/src/components/table/model-pricing/modal/PricingFilterModal.jsx +++ b/web/src/components/table/model-pricing/modal/PricingFilterModal.jsx @@ -116,6 +116,7 @@ const PricingFilterModal = ({ filterGroup={filterGroup} setFilterGroup={setFilterGroup} usableGroup={categoryProps.usableGroup} + groupRatio={categoryProps.groupRatio} models={categoryProps.models} loading={loading} t={t}