- PricingCardView 新增 showTryButton 属性,点击跳转 Playground 并预选模型 - 移除 PricingCardView 中未使用的 props (selectedGroup, currency 等) - 首页页脚路由重命名: terms→user-agreement, usage-policy→privacy-policy - i18n: "操练场"更名为"对话" Co-Authored-By: Claude <noreply@anthropic.com>master
| @@ -361,7 +361,7 @@ function App() { | |||||
| } | } | ||||
| /> | /> | ||||
| <Route | <Route | ||||
| path='/terms' | |||||
| path='/user-agreement' | |||||
| element={ | element={ | ||||
| <Suspense fallback={<Loading></Loading>} key={location.pathname}> | <Suspense fallback={<Loading></Loading>} key={location.pathname}> | ||||
| <Terms /> | <Terms /> | ||||
| @@ -369,7 +369,7 @@ function App() { | |||||
| } | } | ||||
| /> | /> | ||||
| <Route | <Route | ||||
| path='/usage-policy' | |||||
| path='/privacy-policy' | |||||
| element={ | element={ | ||||
| <Suspense fallback={<Loading></Loading>} key={location.pathname}> | <Suspense fallback={<Loading></Loading>} key={location.pathname}> | ||||
| <UsagePolicy /> | <UsagePolicy /> | ||||
| @@ -18,6 +18,7 @@ For commercial licensing, please contact support@quantumnous.com | |||||
| */ | */ | ||||
| import React from 'react'; | import React from 'react'; | ||||
| import { useNavigate } from 'react-router-dom'; | |||||
| import { | import { | ||||
| Card, | Card, | ||||
| Tag, | Tag, | ||||
| @@ -36,8 +37,6 @@ import { | |||||
| } from '@douyinfe/semi-illustrations'; | } from '@douyinfe/semi-illustrations'; | ||||
| import { | import { | ||||
| stringToColor, | stringToColor, | ||||
| calculateModelPrice, | |||||
| formatPriceInfo, | |||||
| getLobeHubIcon, | getLobeHubIcon, | ||||
| } from '../../../../../helpers'; | } from '../../../../../helpers'; | ||||
| import PricingCardSkeleton from './PricingCardSkeleton'; | import PricingCardSkeleton from './PricingCardSkeleton'; | ||||
| @@ -61,14 +60,9 @@ const PricingCardView = ({ | |||||
| setPageSize, | setPageSize, | ||||
| currentPage, | currentPage, | ||||
| setCurrentPage, | setCurrentPage, | ||||
| selectedGroup, | |||||
| groupRatio, | |||||
| copyText, | copyText, | ||||
| setModalImageUrl, | setModalImageUrl, | ||||
| setIsModalOpenurl, | setIsModalOpenurl, | ||||
| currency, | |||||
| tokenUnit, | |||||
| displayPrice, | |||||
| showRatio, | showRatio, | ||||
| t, | t, | ||||
| selectedRowKeys = [], | selectedRowKeys = [], | ||||
| @@ -76,6 +70,7 @@ const PricingCardView = ({ | |||||
| openModelDetail, | openModelDetail, | ||||
| gridColsClass = 'grid-cols-1 xl:grid-cols-2 2xl:grid-cols-3', | gridColsClass = 'grid-cols-1 xl:grid-cols-2 2xl:grid-cols-3', | ||||
| showPagination = true, | showPagination = true, | ||||
| showTryButton = false, | |||||
| }) => { | }) => { | ||||
| const showSkeleton = useMinimumLoadingTime(loading); | const showSkeleton = useMinimumLoadingTime(loading); | ||||
| const startIndex = (currentPage - 1) * pageSize; | const startIndex = (currentPage - 1) * pageSize; | ||||
| @@ -84,6 +79,7 @@ const PricingCardView = ({ | |||||
| : filteredModels; | : filteredModels; | ||||
| const getModelKey = (model) => model.key ?? model.model_name ?? model.id; | const getModelKey = (model) => model.key ?? model.model_name ?? model.id; | ||||
| const isMobile = useIsMobile(); | const isMobile = useIsMobile(); | ||||
| const navigate = useNavigate(); | |||||
| const handleCheckboxChange = (model, checked) => { | const handleCheckboxChange = (model, checked) => { | ||||
| if (!setSelectedRowKeys) return; | if (!setSelectedRowKeys) return; | ||||
| @@ -240,15 +236,6 @@ const PricingCardView = ({ | |||||
| const modelKey = getModelKey(model); | const modelKey = getModelKey(model); | ||||
| const isSelected = selectedRowKeys.includes(modelKey); | const isSelected = selectedRowKeys.includes(modelKey); | ||||
| const priceData = calculateModelPrice({ | |||||
| record: model, | |||||
| selectedGroup, | |||||
| groupRatio, | |||||
| tokenUnit, | |||||
| displayPrice, | |||||
| currency, | |||||
| }); | |||||
| return ( | return ( | ||||
| <Card | <Card | ||||
| key={modelKey || index} | key={modelKey || index} | ||||
| @@ -265,9 +252,6 @@ const PricingCardView = ({ | |||||
| <h3 className='text-lg font-bold text-gray-900 break-all'> | <h3 className='text-lg font-bold text-gray-900 break-all'> | ||||
| {model.model_name} | {model.model_name} | ||||
| </h3> | </h3> | ||||
| <div className='text-xs mt-1'> | |||||
| {formatPriceInfo(priceData, t)} | |||||
| </div> | |||||
| </div> | </div> | ||||
| </div> | </div> | ||||
| @@ -324,6 +308,22 @@ const PricingCardView = ({ | |||||
| </Tag> | </Tag> | ||||
| )} | )} | ||||
| {/* 去体验按钮 */} | |||||
| {showTryButton && ( | |||||
| <Button | |||||
| size='small' | |||||
| theme='solid' | |||||
| type='primary' | |||||
| style={{ marginTop: 8, width: '100%' }} | |||||
| onClick={(e) => { | |||||
| e.stopPropagation(); | |||||
| navigate('/console/playground?model=' + encodeURIComponent(model.model_name)); | |||||
| }} | |||||
| > | |||||
| {t('去体验')} → | |||||
| </Button> | |||||
| )} | |||||
| {/* 倍率信息(可选) */} | {/* 倍率信息(可选) */} | ||||
| {showRatio && ( | {showRatio && ( | ||||
| <div className='pt-3'> | <div className='pt-3'> | ||||
| @@ -206,23 +206,6 @@ export const useModelPricingData = () => { | |||||
| m.vendor_description = vendor.description; | m.vendor_description = vendor.description; | ||||
| } | } | ||||
| } | } | ||||
| models.sort((a, b) => { | |||||
| return a.quota_type - b.quota_type; | |||||
| }); | |||||
| models.sort((a, b) => { | |||||
| if (a.model_name.startsWith('gpt') && !b.model_name.startsWith('gpt')) { | |||||
| return -1; | |||||
| } else if ( | |||||
| !a.model_name.startsWith('gpt') && | |||||
| b.model_name.startsWith('gpt') | |||||
| ) { | |||||
| return 1; | |||||
| } else { | |||||
| return a.model_name.localeCompare(b.model_name); | |||||
| } | |||||
| }); | |||||
| setModels(models); | setModels(models); | ||||
| }; | }; | ||||
| @@ -1365,8 +1365,8 @@ | |||||
| "操作成功完成!": "Operation completed successfully!", | "操作成功完成!": "Operation completed successfully!", | ||||
| "操作暂时被禁用": "Operation temporarily disabled", | "操作暂时被禁用": "Operation temporarily disabled", | ||||
| "操作确认": "Operation confirmation", | "操作确认": "Operation confirmation", | ||||
| "操练场": "Playground", | |||||
| "操练场和聊天功能": "Playground and chat functions", | |||||
| "操练场": "Chat", | |||||
| "操练场和聊天功能": "Chat functions", | |||||
| "支付": "Pay", | "支付": "Pay", | ||||
| "支付地址": "Payment address", | "支付地址": "Payment address", | ||||
| "支付失败": "Payment failed", | "支付失败": "Payment failed", | ||||
| @@ -3081,6 +3081,7 @@ | |||||
| "高级设置": "Advanced Settings", | "高级设置": "Advanced Settings", | ||||
| "高级配置": "Advanced Configuration", | "高级配置": "Advanced Configuration", | ||||
| "黑名单": "Blacklist", | "黑名单": "Blacklist", | ||||
| "去体验": "Try it", | |||||
| "默认": "Default", | "默认": "Default", | ||||
| "默认 API 版本": "Default API Version", | "默认 API 版本": "Default API Version", | ||||
| "默认 Responses API 版本,为空则使用上方版本": "Default Responses API version, if empty, uses the version above", | "默认 Responses API 版本,为空则使用上方版本": "Default Responses API version, if empty, uses the version above", | ||||
| @@ -1349,8 +1349,8 @@ | |||||
| "操作成功完成!": "操作成功完成!", | "操作成功完成!": "操作成功完成!", | ||||
| "操作暂时被禁用": "操作暂时被禁用", | "操作暂时被禁用": "操作暂时被禁用", | ||||
| "操作确认": "操作确认", | "操作确认": "操作确认", | ||||
| "操练场": "操练场", | |||||
| "操练场和聊天功能": "操练场和聊天功能", | |||||
| "操练场": "对话", | |||||
| "操练场和聊天功能": "对话和聊天功能", | |||||
| "支付": "支付", | "支付": "支付", | ||||
| "支付地址": "支付地址", | "支付地址": "支付地址", | ||||
| "支付失败": "支付失败", | "支付失败": "支付失败", | ||||
| @@ -3058,6 +3058,7 @@ | |||||
| "高级设置": "高级设置", | "高级设置": "高级设置", | ||||
| "高级配置": "高级配置", | "高级配置": "高级配置", | ||||
| "黑名单": "黑名单", | "黑名单": "黑名单", | ||||
| "去体验": "去体验", | |||||
| "默认": "默认", | "默认": "默认", | ||||
| "默认 API 版本": "默认 API 版本", | "默认 API 版本": "默认 API 版本", | ||||
| "默认 Responses API 版本,为空则使用上方版本": "默认 Responses API 版本,为空则使用上方版本", | "默认 Responses API 版本,为空则使用上方版本": "默认 Responses API 版本,为空则使用上方版本", | ||||
| @@ -178,20 +178,16 @@ const HomePricingFilters = ({ t }) => { | |||||
| setPageSize={pricingData.setPageSize} | setPageSize={pricingData.setPageSize} | ||||
| currentPage={pricingData.currentPage} | currentPage={pricingData.currentPage} | ||||
| setCurrentPage={pricingData.setCurrentPage} | setCurrentPage={pricingData.setCurrentPage} | ||||
| selectedGroup={pricingData.selectedGroup} | |||||
| groupRatio={pricingData.groupRatio} | |||||
| copyText={pricingData.copyText} | copyText={pricingData.copyText} | ||||
| setModalImageUrl={pricingData.setModalImageUrl} | setModalImageUrl={pricingData.setModalImageUrl} | ||||
| setIsModalOpenurl={pricingData.setIsModalOpenurl} | setIsModalOpenurl={pricingData.setIsModalOpenurl} | ||||
| currency={pricingData.currency} | |||||
| tokenUnit={pricingData.tokenUnit} | |||||
| displayPrice={pricingData.displayPrice} | |||||
| showRatio={showRatio} | showRatio={showRatio} | ||||
| t={t} | t={t} | ||||
| selectedRowKeys={[]} | selectedRowKeys={[]} | ||||
| openModelDetail={pricingData.openModelDetail} | openModelDetail={pricingData.openModelDetail} | ||||
| gridColsClass='grid-cols-1 md:grid-cols-2 lg:grid-cols-3' | gridColsClass='grid-cols-1 md:grid-cols-2 lg:grid-cols-3' | ||||
| showPagination={true} | showPagination={true} | ||||
| showTryButton={true} | |||||
| /> | /> | ||||
| </div> | </div> | ||||
| @@ -30,8 +30,8 @@ const HomePageFooter = () => { | |||||
| const currentYear = new Date().getFullYear(); | const currentYear = new Date().getFullYear(); | ||||
| const footerLinks = [ | const footerLinks = [ | ||||
| { label: t('服务条款'), href: '/terms', external: false }, | |||||
| { label: t('使用政策'), href: '/usage-policy', external: false }, | |||||
| { label: t('用户协议'), href: '/user-agreement', external: false }, | |||||
| { label: t('隐私协议'), href: '/privacy-policy', external: false }, | |||||
| ]; | ]; | ||||
| return ( | return ( | ||||