🔧 refactor(pricing-filters): extract display settings & improve mobile layout (#1365)
* **PricingDisplaySettings.jsx**
• Extracted display settings (recharge price, currency, ratio toggle) from PricingSidebar
• Maintains complete styling and functionality as standalone component
* **SelectableButtonGroup.jsx**
• Added isMobile detection with conditional Col spans
• Mobile: `span={12}` (2 buttons per row) for better touch experience
• Desktop: preserved responsive grid `xs={24} sm={24} md={24} lg={12} xl={8}`
* **PricingSidebar.jsx**
• Updated imports to use new PricingDisplaySettings component
• Simplified component structure while preserving reset logic
These changes enhance code modularity and provide optimized mobile UX for filter button groups across the pricing interface.
This commit is contained in:
@@ -18,6 +18,7 @@ For commercial licensing, please contact support@quantumnous.com
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import React, { useState, useRef } from 'react';
|
import React, { useState, useRef } from 'react';
|
||||||
|
import { useIsMobile } from '../../../hooks/common/useIsMobile';
|
||||||
import { Divider, Button, Tag, Row, Col, Collapsible } from '@douyinfe/semi-ui';
|
import { Divider, Button, Tag, Row, Col, Collapsible } from '@douyinfe/semi-ui';
|
||||||
import { IconChevronDown, IconChevronUp } from '@douyinfe/semi-icons';
|
import { IconChevronDown, IconChevronUp } from '@douyinfe/semi-icons';
|
||||||
|
|
||||||
@@ -44,6 +45,7 @@ const SelectableButtonGroup = ({
|
|||||||
collapseHeight = 200
|
collapseHeight = 200
|
||||||
}) => {
|
}) => {
|
||||||
const [isOpen, setIsOpen] = useState(false);
|
const [isOpen, setIsOpen] = useState(false);
|
||||||
|
const isMobile = useIsMobile();
|
||||||
const perRow = 3;
|
const perRow = 3;
|
||||||
const maxVisibleRows = Math.max(1, Math.floor(collapseHeight / 32)); // Approx row height 32
|
const maxVisibleRows = Math.max(1, Math.floor(collapseHeight / 32)); // Approx row height 32
|
||||||
const needCollapse = collapsible && items.length > perRow * maxVisibleRows;
|
const needCollapse = collapsible && items.length > perRow * maxVisibleRows;
|
||||||
@@ -82,10 +84,16 @@ const SelectableButtonGroup = ({
|
|||||||
{items.map((item) => {
|
{items.map((item) => {
|
||||||
const isActive = activeValue === item.value;
|
const isActive = activeValue === item.value;
|
||||||
return (
|
return (
|
||||||
<Col xs={24} sm={24} md={24} lg={12} xl={8} key={item.value}>
|
<Col
|
||||||
|
{...(isMobile
|
||||||
|
? { span: 12 }
|
||||||
|
: { xs: 24, sm: 24, md: 24, lg: 12, xl: 8 }
|
||||||
|
)}
|
||||||
|
key={item.value}
|
||||||
|
>
|
||||||
<Button
|
<Button
|
||||||
onClick={() => onChange(item.value)}
|
onClick={() => onChange(item.value)}
|
||||||
theme={isActive ? 'solid' : 'outline'}
|
theme={isActive ? 'light' : 'outline'}
|
||||||
type={isActive ? 'primary' : 'tertiary'}
|
type={isActive ? 'primary' : 'tertiary'}
|
||||||
icon={item.icon}
|
icon={item.icon}
|
||||||
style={{ width: '100%' }}
|
style={{ width: '100%' }}
|
||||||
|
|||||||
@@ -18,12 +18,20 @@ For commercial licensing, please contact support@quantumnous.com
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import PricingSearchBar from './PricingSearchBar.jsx';
|
import PricingSearchBar from './PricingSearchBar';
|
||||||
import PricingTable from './PricingTable.jsx';
|
import PricingTable from './PricingTable';
|
||||||
|
|
||||||
const PricingContent = (props) => {
|
const PricingContent = ({ isMobile, sidebarProps, ...props }) => {
|
||||||
return (
|
return (
|
||||||
<div className="pricing-scroll-hide">
|
<div
|
||||||
|
className={isMobile ? "" : "pricing-scroll-hide"}
|
||||||
|
style={isMobile ? {
|
||||||
|
height: '100%',
|
||||||
|
display: 'flex',
|
||||||
|
flexDirection: 'column',
|
||||||
|
overflow: 'auto'
|
||||||
|
} : {}}
|
||||||
|
>
|
||||||
{/* 固定的搜索和操作区域 */}
|
{/* 固定的搜索和操作区域 */}
|
||||||
<div
|
<div
|
||||||
style={{
|
style={{
|
||||||
@@ -36,14 +44,15 @@ const PricingContent = (props) => {
|
|||||||
zIndex: 5,
|
zIndex: 5,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<PricingSearchBar {...props} />
|
<PricingSearchBar {...props} isMobile={isMobile} sidebarProps={sidebarProps} />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* 可滚动的内容区域 */}
|
{/* 可滚动的内容区域 */}
|
||||||
<div
|
<div
|
||||||
style={{
|
style={{
|
||||||
flex: 1,
|
flex: 1,
|
||||||
overflow: 'auto'
|
overflow: 'auto',
|
||||||
|
...(isMobile && { minHeight: 0 })
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<PricingTable {...props} />
|
<PricingTable {...props} />
|
||||||
|
|||||||
@@ -19,13 +19,15 @@ For commercial licensing, please contact support@quantumnous.com
|
|||||||
|
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { Layout, ImagePreview } from '@douyinfe/semi-ui';
|
import { Layout, ImagePreview } from '@douyinfe/semi-ui';
|
||||||
import PricingSidebar from './PricingSidebar.jsx';
|
import PricingSidebar from './PricingSidebar';
|
||||||
import PricingContent from './PricingContent.jsx';
|
import PricingContent from './PricingContent';
|
||||||
import { useModelPricingData } from '../../../hooks/model-pricing/useModelPricingData.js';
|
import { useModelPricingData } from '../../../hooks/model-pricing/useModelPricingData';
|
||||||
|
import { useIsMobile } from '../../../hooks/common/useIsMobile';
|
||||||
|
|
||||||
const PricingPage = () => {
|
const PricingPage = () => {
|
||||||
const pricingData = useModelPricingData();
|
const pricingData = useModelPricingData();
|
||||||
const { Sider, Content } = Layout;
|
const { Sider, Content } = Layout;
|
||||||
|
const isMobile = useIsMobile();
|
||||||
|
|
||||||
// 显示倍率状态
|
// 显示倍率状态
|
||||||
const [showRatio, setShowRatio] = React.useState(false);
|
const [showRatio, setShowRatio] = React.useState(false);
|
||||||
@@ -33,19 +35,21 @@ const PricingPage = () => {
|
|||||||
return (
|
return (
|
||||||
<div className="bg-white">
|
<div className="bg-white">
|
||||||
<Layout style={{ height: 'calc(100vh - 60px)', overflow: 'hidden', marginTop: '60px' }}>
|
<Layout style={{ height: 'calc(100vh - 60px)', overflow: 'hidden', marginTop: '60px' }}>
|
||||||
{/* 左侧边栏 */}
|
{/* 左侧边栏 - 只在桌面端显示 */}
|
||||||
<Sider
|
{!isMobile && (
|
||||||
className="pricing-scroll-hide"
|
<Sider
|
||||||
style={{
|
className="pricing-scroll-hide"
|
||||||
width: 460,
|
style={{
|
||||||
height: 'calc(100vh - 60px)',
|
width: 460,
|
||||||
backgroundColor: 'var(--semi-color-bg-0)',
|
height: 'calc(100vh - 60px)',
|
||||||
borderRight: '1px solid var(--semi-color-border)',
|
backgroundColor: 'var(--semi-color-bg-0)',
|
||||||
overflow: 'auto'
|
borderRight: '1px solid var(--semi-color-border)',
|
||||||
}}
|
overflow: 'auto'
|
||||||
>
|
}}
|
||||||
<PricingSidebar {...pricingData} showRatio={showRatio} setShowRatio={setShowRatio} />
|
>
|
||||||
</Sider>
|
<PricingSidebar {...pricingData} showRatio={showRatio} setShowRatio={setShowRatio} />
|
||||||
|
</Sider>
|
||||||
|
)}
|
||||||
|
|
||||||
{/* 右侧内容区 */}
|
{/* 右侧内容区 */}
|
||||||
<Content
|
<Content
|
||||||
@@ -57,7 +61,12 @@ const PricingPage = () => {
|
|||||||
flexDirection: 'column'
|
flexDirection: 'column'
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<PricingContent {...pricingData} showRatio={showRatio} />
|
<PricingContent
|
||||||
|
{...pricingData}
|
||||||
|
showRatio={showRatio}
|
||||||
|
isMobile={isMobile}
|
||||||
|
sidebarProps={{ ...pricingData, showRatio, setShowRatio }}
|
||||||
|
/>
|
||||||
</Content>
|
</Content>
|
||||||
</Layout>
|
</Layout>
|
||||||
|
|
||||||
|
|||||||
@@ -17,9 +17,10 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|||||||
For commercial licensing, please contact support@quantumnous.com
|
For commercial licensing, please contact support@quantumnous.com
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import React, { useMemo } from 'react';
|
import React, { useMemo, useState } from 'react';
|
||||||
import { Input, Button } from '@douyinfe/semi-ui';
|
import { Input, Button } from '@douyinfe/semi-ui';
|
||||||
import { IconSearch, IconCopy } from '@douyinfe/semi-icons';
|
import { IconSearch, IconCopy, IconFilter } from '@douyinfe/semi-icons';
|
||||||
|
import PricingFilterModal from './modal/PricingFilterModal';
|
||||||
|
|
||||||
const PricingSearchBar = ({
|
const PricingSearchBar = ({
|
||||||
selectedRowKeys,
|
selectedRowKeys,
|
||||||
@@ -27,8 +28,12 @@ const PricingSearchBar = ({
|
|||||||
handleChange,
|
handleChange,
|
||||||
handleCompositionStart,
|
handleCompositionStart,
|
||||||
handleCompositionEnd,
|
handleCompositionEnd,
|
||||||
|
isMobile,
|
||||||
|
sidebarProps,
|
||||||
t
|
t
|
||||||
}) => {
|
}) => {
|
||||||
|
const [showFilterModal, setShowFilterModal] = useState(false);
|
||||||
|
|
||||||
const SearchAndActions = useMemo(() => (
|
const SearchAndActions = useMemo(() => (
|
||||||
<div className="flex items-center gap-4 w-full">
|
<div className="flex items-center gap-4 w-full">
|
||||||
{/* 搜索框 */}
|
{/* 搜索框 */}
|
||||||
@@ -45,19 +50,45 @@ const PricingSearchBar = ({
|
|||||||
|
|
||||||
{/* 操作按钮 */}
|
{/* 操作按钮 */}
|
||||||
<Button
|
<Button
|
||||||
theme='light'
|
theme='outline'
|
||||||
type='primary'
|
type='primary'
|
||||||
icon={<IconCopy />}
|
icon={<IconCopy />}
|
||||||
onClick={() => copyText(selectedRowKeys)}
|
onClick={() => copyText(selectedRowKeys)}
|
||||||
disabled={selectedRowKeys.length === 0}
|
disabled={selectedRowKeys.length === 0}
|
||||||
className="!bg-blue-500 hover:!bg-blue-600 text-white"
|
className="!bg-blue-500 hover:!bg-blue-600 text-white"
|
||||||
>
|
>
|
||||||
{t('复制选中模型')}
|
{t('复制')}
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
|
||||||
), [selectedRowKeys, t, handleCompositionStart, handleCompositionEnd, handleChange, copyText]);
|
|
||||||
|
|
||||||
return SearchAndActions;
|
{/* 移动端筛选按钮 */}
|
||||||
|
{isMobile && (
|
||||||
|
<Button
|
||||||
|
theme="outline"
|
||||||
|
type='tertiary'
|
||||||
|
icon={<IconFilter />}
|
||||||
|
onClick={() => setShowFilterModal(true)}
|
||||||
|
>
|
||||||
|
{t('筛选')}
|
||||||
|
</Button>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
), [selectedRowKeys, t, handleCompositionStart, handleCompositionEnd, handleChange, copyText, isMobile]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
{SearchAndActions}
|
||||||
|
|
||||||
|
{/* 移动端筛选Modal */}
|
||||||
|
{isMobile && (
|
||||||
|
<PricingFilterModal
|
||||||
|
visible={showFilterModal}
|
||||||
|
onClose={() => setShowFilterModal(false)}
|
||||||
|
sidebarProps={sidebarProps}
|
||||||
|
t={t}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</>
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default PricingSearchBar;
|
export default PricingSearchBar;
|
||||||
@@ -18,11 +18,11 @@ For commercial licensing, please contact support@quantumnous.com
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { Divider, Button, Switch, Select, Tooltip } from '@douyinfe/semi-ui';
|
import { Button } from '@douyinfe/semi-ui';
|
||||||
import { IconHelpCircle } from '@douyinfe/semi-icons';
|
import PricingCategories from './filter/PricingCategories';
|
||||||
import PricingCategories from './sidebar/PricingCategories.jsx';
|
import PricingGroups from './filter/PricingGroups';
|
||||||
import PricingGroups from './sidebar/PricingGroups.jsx';
|
import PricingQuotaTypes from './filter/PricingQuotaTypes';
|
||||||
import PricingQuotaTypes from './sidebar/PricingQuotaTypes.jsx';
|
import PricingDisplaySettings from './filter/PricingDisplaySettings';
|
||||||
|
|
||||||
const PricingSidebar = ({
|
const PricingSidebar = ({
|
||||||
showWithRecharge,
|
showWithRecharge,
|
||||||
@@ -79,13 +79,13 @@ const PricingSidebar = ({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="p-4">
|
<div className="p-4">
|
||||||
{/* 筛选标题和重置按钮 */}
|
|
||||||
<div className="flex items-center justify-between mb-6">
|
<div className="flex items-center justify-between mb-6">
|
||||||
<div className="text-lg font-semibold text-gray-800">
|
<div className="text-lg font-semibold text-gray-800">
|
||||||
{t('筛选')}
|
{t('筛选')}
|
||||||
</div>
|
</div>
|
||||||
<Button
|
<Button
|
||||||
theme="outline"
|
theme="outline"
|
||||||
|
type='tertiary'
|
||||||
onClick={handleResetFilters}
|
onClick={handleResetFilters}
|
||||||
className="text-gray-500 hover:text-gray-700"
|
className="text-gray-500 hover:text-gray-700"
|
||||||
>
|
>
|
||||||
@@ -93,54 +93,16 @@ const PricingSidebar = ({
|
|||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* 显示设置 */}
|
<PricingDisplaySettings
|
||||||
<div className="mb-6">
|
showWithRecharge={showWithRecharge}
|
||||||
<Divider margin='12px' align='left'>
|
setShowWithRecharge={setShowWithRecharge}
|
||||||
{t('显示设置')}
|
currency={currency}
|
||||||
</Divider>
|
setCurrency={setCurrency}
|
||||||
<div className="px-2">
|
showRatio={showRatio}
|
||||||
<div className="flex items-center justify-between mb-3">
|
setShowRatio={setShowRatio}
|
||||||
<span className="text-sm text-gray-700">{t('以充值价格显示')}</span>
|
t={t}
|
||||||
<Switch
|
/>
|
||||||
checked={showWithRecharge}
|
|
||||||
onChange={setShowWithRecharge}
|
|
||||||
size="small"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
{showWithRecharge && (
|
|
||||||
<div className="mt-2 mb-3">
|
|
||||||
<div className="text-xs text-gray-500 mb-1">{t('货币单位')}</div>
|
|
||||||
<Select
|
|
||||||
value={currency}
|
|
||||||
onChange={setCurrency}
|
|
||||||
size="small"
|
|
||||||
className="w-full"
|
|
||||||
>
|
|
||||||
<Select.Option value="USD">USD ($)</Select.Option>
|
|
||||||
<Select.Option value="CNY">CNY (¥)</Select.Option>
|
|
||||||
</Select>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
<div className="flex items-center justify-between">
|
|
||||||
<div className="flex items-center gap-1">
|
|
||||||
<span className="text-sm text-gray-700">{t('显示倍率')}</span>
|
|
||||||
<Tooltip content={t('倍率是用于系统计算不同模型的最终价格用的,如果您不理解倍率,请忽略')}>
|
|
||||||
<IconHelpCircle
|
|
||||||
size="small"
|
|
||||||
style={{ color: 'var(--semi-color-text-2)', cursor: 'help' }}
|
|
||||||
/>
|
|
||||||
</Tooltip>
|
|
||||||
</div>
|
|
||||||
<Switch
|
|
||||||
checked={showRatio}
|
|
||||||
onChange={setShowRatio}
|
|
||||||
size="small"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* 模型分类 */}
|
|
||||||
<PricingCategories {...categoryProps} setActiveKey={setActiveKey} t={t} />
|
<PricingCategories {...categoryProps} setActiveKey={setActiveKey} t={t} />
|
||||||
|
|
||||||
<PricingGroups filterGroup={filterGroup} setFilterGroup={setFilterGroup} usableGroup={categoryProps.usableGroup} models={categoryProps.models} t={t} />
|
<PricingGroups filterGroup={filterGroup} setFilterGroup={setFilterGroup} usableGroup={categoryProps.usableGroup} models={categoryProps.models} t={t} />
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ import {
|
|||||||
IllustrationNoResult,
|
IllustrationNoResult,
|
||||||
IllustrationNoResultDark
|
IllustrationNoResultDark
|
||||||
} from '@douyinfe/semi-illustrations';
|
} from '@douyinfe/semi-illustrations';
|
||||||
import { getPricingTableColumns } from './PricingTableColumns.js';
|
import { getPricingTableColumns } from './PricingTableColumns';
|
||||||
|
|
||||||
const PricingTable = ({
|
const PricingTable = ({
|
||||||
filteredModels,
|
filteredModels,
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ For commercial licensing, please contact support@quantumnous.com
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import SelectableButtonGroup from '../../../common/ui/SelectableButtonGroup.jsx';
|
import SelectableButtonGroup from '../../../common/ui/SelectableButtonGroup';
|
||||||
|
|
||||||
const PricingCategories = ({ activeKey, setActiveKey, modelCategories, categoryCounts, availableCategories, t }) => {
|
const PricingCategories = ({ activeKey, setActiveKey, modelCategories, categoryCounts, availableCategories, t }) => {
|
||||||
const items = Object.entries(modelCategories)
|
const items = Object.entries(modelCategories)
|
||||||
@@ -0,0 +1,82 @@
|
|||||||
|
/*
|
||||||
|
Copyright (C) 2025 QuantumNous
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU Affero General Public License as
|
||||||
|
published by the Free Software Foundation, either version 3 of the
|
||||||
|
License, or (at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU Affero General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Affero General Public License
|
||||||
|
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
For commercial licensing, please contact support@quantumnous.com
|
||||||
|
*/
|
||||||
|
|
||||||
|
import React from 'react';
|
||||||
|
import { Divider, Switch, Select, Tooltip } from '@douyinfe/semi-ui';
|
||||||
|
import { IconHelpCircle } from '@douyinfe/semi-icons';
|
||||||
|
|
||||||
|
const PricingDisplaySettings = ({
|
||||||
|
showWithRecharge,
|
||||||
|
setShowWithRecharge,
|
||||||
|
currency,
|
||||||
|
setCurrency,
|
||||||
|
showRatio,
|
||||||
|
setShowRatio,
|
||||||
|
t
|
||||||
|
}) => {
|
||||||
|
return (
|
||||||
|
<div className="mb-6">
|
||||||
|
<Divider margin='12px' align='left'>
|
||||||
|
{t('显示设置')}
|
||||||
|
</Divider>
|
||||||
|
<div className="px-2">
|
||||||
|
<div className="flex items-center justify-between mb-3">
|
||||||
|
<span className="text-sm text-gray-700">{t('以充值价格显示')}</span>
|
||||||
|
<Switch
|
||||||
|
checked={showWithRecharge}
|
||||||
|
onChange={setShowWithRecharge}
|
||||||
|
size="small"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
{showWithRecharge && (
|
||||||
|
<div className="mt-2 mb-3">
|
||||||
|
<div className="text-xs text-gray-500 mb-1">{t('货币单位')}</div>
|
||||||
|
<Select
|
||||||
|
value={currency}
|
||||||
|
onChange={setCurrency}
|
||||||
|
size="small"
|
||||||
|
className="w-full"
|
||||||
|
>
|
||||||
|
<Select.Option value="USD">USD ($)</Select.Option>
|
||||||
|
<Select.Option value="CNY">CNY (¥)</Select.Option>
|
||||||
|
</Select>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
<div className="flex items-center justify-between">
|
||||||
|
<div className="flex items-center gap-1">
|
||||||
|
<span className="text-sm text-gray-700">{t('显示倍率')}</span>
|
||||||
|
<Tooltip content={t('倍率是用于系统计算不同模型的最终价格用的,如果您不理解倍率,请忽略')}>
|
||||||
|
<IconHelpCircle
|
||||||
|
size="small"
|
||||||
|
style={{ color: 'var(--semi-color-text-2)', cursor: 'help' }}
|
||||||
|
/>
|
||||||
|
</Tooltip>
|
||||||
|
</div>
|
||||||
|
<Switch
|
||||||
|
checked={showRatio}
|
||||||
|
onChange={setShowRatio}
|
||||||
|
size="small"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default PricingDisplaySettings;
|
||||||
@@ -18,7 +18,7 @@ For commercial licensing, please contact support@quantumnous.com
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import SelectableButtonGroup from '../../../common/ui/SelectableButtonGroup.jsx';
|
import SelectableButtonGroup from '../../../common/ui/SelectableButtonGroup';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 分组筛选组件
|
* 分组筛选组件
|
||||||
@@ -18,7 +18,7 @@ For commercial licensing, please contact support@quantumnous.com
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import SelectableButtonGroup from '../../../common/ui/SelectableButtonGroup.jsx';
|
import SelectableButtonGroup from '../../../common/ui/SelectableButtonGroup';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 计费类型筛选组件
|
* 计费类型筛选组件
|
||||||
@@ -18,4 +18,4 @@ For commercial licensing, please contact support@quantumnous.com
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
// 为了向后兼容,这里重新导出新的 PricingPage 组件
|
// 为了向后兼容,这里重新导出新的 PricingPage 组件
|
||||||
export { default } from './PricingPage.jsx';
|
export { default } from './PricingPage';
|
||||||
@@ -0,0 +1,48 @@
|
|||||||
|
/*
|
||||||
|
Copyright (C) 2025 QuantumNous
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU Affero General Public License as
|
||||||
|
published by the Free Software Foundation, either version 3 of the
|
||||||
|
License, or (at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU Affero General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Affero General Public License
|
||||||
|
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
For commercial licensing, please contact support@quantumnous.com
|
||||||
|
*/
|
||||||
|
|
||||||
|
import React from 'react';
|
||||||
|
import { Modal } from '@douyinfe/semi-ui';
|
||||||
|
import PricingSidebar from '../PricingSidebar';
|
||||||
|
|
||||||
|
const PricingFilterModal = ({
|
||||||
|
visible,
|
||||||
|
onClose,
|
||||||
|
sidebarProps,
|
||||||
|
t
|
||||||
|
}) => {
|
||||||
|
return (
|
||||||
|
<Modal
|
||||||
|
title={t('筛选')}
|
||||||
|
visible={visible}
|
||||||
|
onCancel={onClose}
|
||||||
|
footer={null}
|
||||||
|
style={{ width: '100%', height: '100%', margin: 0 }}
|
||||||
|
bodyStyle={{
|
||||||
|
padding: 0,
|
||||||
|
height: 'calc(100vh - 110px)',
|
||||||
|
overflow: 'auto'
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<PricingSidebar {...sidebarProps} />
|
||||||
|
</Modal>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default PricingFilterModal;
|
||||||
@@ -699,7 +699,6 @@
|
|||||||
"个": "indivual",
|
"个": "indivual",
|
||||||
"倍率是本站的计算方式,不同模型有着不同的倍率,并非官方价格的多少倍,请务必知晓。": "The magnification is the calculation method of this website. Different models have different magnifications, which are not multiples of the official price. Please be sure to know.",
|
"倍率是本站的计算方式,不同模型有着不同的倍率,并非官方价格的多少倍,请务必知晓。": "The magnification is the calculation method of this website. Different models have different magnifications, which are not multiples of the official price. Please be sure to know.",
|
||||||
"所有各厂聊天模型请统一使用OpenAI方式请求,支持OpenAI官方库<br/>Claude()Claude官方格式请求": "Please use the OpenAI method to request all chat models from each factory, and support the OpenAI official library<br/>Claude()Claude official format request",
|
"所有各厂聊天模型请统一使用OpenAI方式请求,支持OpenAI官方库<br/>Claude()Claude官方格式请求": "Please use the OpenAI method to request all chat models from each factory, and support the OpenAI official library<br/>Claude()Claude official format request",
|
||||||
"复制选中模型": "Copy selected model",
|
|
||||||
"分组说明": "Group description",
|
"分组说明": "Group description",
|
||||||
"倍率是为了方便换算不同价格的模型": "The magnification is to facilitate the conversion of models with different prices.",
|
"倍率是为了方便换算不同价格的模型": "The magnification is to facilitate the conversion of models with different prices.",
|
||||||
"点击查看倍率说明": "Click to view the magnification description",
|
"点击查看倍率说明": "Click to view the magnification description",
|
||||||
|
|||||||
Reference in New Issue
Block a user