- 首页定价区域添加响应式分页(移动端6/平板8/桌面9) - 渠道列表显示 ID,支持在名称中查看 - 渠道定价卡片添加 ID 标签和使用提示 Banner - 代码示例中展示 API Key 指定渠道的格式 Co-Authored-By: Claude <noreply@anthropic.com>feat/alipay-payment
| @@ -304,6 +304,7 @@ export const getChannelsColumns = ({ | |||
| dataIndex: 'name', | |||
| render: (text, record, index) => { | |||
| const passThroughEnabled = isRequestPassThroughEnabled(record); | |||
| const nameWithId = `${record.id} - ${text}`; | |||
| const nameNode = | |||
| record.remark && record.remark.trim() !== '' ? ( | |||
| <Tooltip | |||
| @@ -333,10 +334,10 @@ export const getChannelsColumns = ({ | |||
| trigger='hover' | |||
| position='topLeft' | |||
| > | |||
| <span>{text}</span> | |||
| <span>{nameWithId}</span> | |||
| </Tooltip> | |||
| ) : ( | |||
| <span>{text}</span> | |||
| <span>{nameWithId}</span> | |||
| ); | |||
| if (!passThroughEnabled) { | |||
| @@ -18,7 +18,7 @@ For commercial licensing, please contact support@quantumnous.com | |||
| */ | |||
| import React, { useState, useEffect, useMemo } from 'react'; | |||
| import { Card, Avatar, Typography, Table, Tag, Spin } from '@douyinfe/semi-ui'; | |||
| import { Card, Avatar, Typography, Table, Tag, Spin, Banner } from '@douyinfe/semi-ui'; | |||
| import { IconServer } from '@douyinfe/semi-icons'; | |||
| import { API } from '../../../../../helpers'; | |||
| @@ -103,6 +103,7 @@ const ChannelPricingCard = ({ | |||
| // 准备表格数据 | |||
| const tableData = channelPricingData.map((item, index) => ({ | |||
| key: item.channel_id || index, | |||
| channelId: item.channel_id, | |||
| channelName: `渠道${['一', '二', '三', '四', '五', '六', '七', '八', '九', '十'][index] || ` ${index + 1}`}`, | |||
| channelTags: item.tags || [], // 渠道定价的标签列表 | |||
| channelType: item.channel_type, | |||
| @@ -125,6 +126,9 @@ const ChannelPricingCard = ({ | |||
| dataIndex: 'channelName', | |||
| render: (text, record) => ( | |||
| <div className='flex items-center gap-2 flex-wrap'> | |||
| <Tag color='grey' size='small' shape='circle'> | |||
| ID: {record.channelId} | |||
| </Tag> | |||
| <Tag color='cyan' size='small' shape='circle'> | |||
| {text} | |||
| </Tag> | |||
| @@ -237,6 +241,11 @@ const ChannelPricingCard = ({ | |||
| </div> | |||
| </div> | |||
| </div> | |||
| <Banner | |||
| type='info' | |||
| description={t('在 API Key 后添加 ":渠道ID" 可指定使用特定渠道,如:sk-xxxx:1')} | |||
| className='mb-4' | |||
| /> | |||
| <Table | |||
| dataSource={tableData} | |||
| columns={columns} | |||
| @@ -46,7 +46,7 @@ const getDefaultCodeByLang = () => ({ | |||
| from openai import OpenAI | |||
| client = OpenAI( | |||
| api_key="<Your API Key>", | |||
| api_key="<Your API Key>-<Channel ID>", | |||
| base_url="__BASE_URL__" | |||
| ) | |||
| @@ -66,7 +66,7 @@ print(response.choices[0].message.content) | |||
| import com.openai.OpenAI; | |||
| import com.openai.models.*; | |||
| OpenAI client = new OpenAI("<Your API Key>", "__BASE_URL__"); | |||
| OpenAI client = new OpenAI("<Your API Key>-<Channel ID>", "__BASE_URL__"); | |||
| ChatCompletionRequest request = ChatCompletionRequest.builder() | |||
| .model("__MODEL_NAME__") | |||
| @@ -91,37 +91,37 @@ import ( | |||
| ) | |||
| func main() { | |||
| client := openai.NewClient("<Your API Key>", "__BASE_URL__") | |||
| client := openai.NewClient("<Your API Key>-<Channel ID>", "__BASE_URL__") | |||
| messages := []openai.ChatMessage{ | |||
| {Role: "system", Content: "You are a helpful assistant."}, | |||
| {Role: "user", Content: "Hello, how are you?"}, | |||
| } | |||
| response, err := client.ChatCompletions.Create(context.Background(), openai.ChatCompletionRequest{ | |||
| Model: "__MODEL_NAME__", | |||
| Messages: messages, | |||
| MaxTokens: 128000, | |||
| Temperature: 0.7, | |||
| }) | |||
| if err != nil { | |||
| panic(err) | |||
| } | |||
| fmt.Println(response.Choices[0].Message.Content) | |||
| } | |||
| `, | |||
| shell: ` | |||
| #!/bin/bash | |||
| API_KEY="<Your API Key>" | |||
| API_KEY="<Your API Key>-<Channel ID>" | |||
| MODEL_ID="__MODEL_NAME__" | |||
| BASE_URL="__BASE_URL__" | |||
| curl -X POST "$BASE_URL/v1/chat/completions" \ | |||
| -H "Content-Type: application/json" \ | |||
| -H "Authorization: Bearer $API_KEY" \ | |||
| curl -X POST "$BASE_URL/v1/chat/completions" \\ | |||
| -H "Content-Type: application/json" \\ | |||
| -H "Authorization: Bearer $API_KEY" \\ | |||
| -d '{ | |||
| "model": "'$MODEL_ID'", | |||
| "messages": [ | |||
| @@ -24,6 +24,7 @@ import PricingCardView from '../../components/table/model-pricing/view/card/Pric | |||
| import ModelDetailSideSheet from '../../components/table/model-pricing/modal/ModelDetailSideSheet'; | |||
| import { useModelPricingData } from '../../hooks/model-pricing/useModelPricingData'; | |||
| import { usePricingFilterCounts } from '../../hooks/model-pricing/usePricingFilterCounts'; | |||
| import { useIsMobile } from '../../hooks/common/useIsMobile'; | |||
| import { getLobeHubIcon } from '../../helpers'; | |||
| // 与 model_meta.go ModelType 常量一致:1=Chat, 2=Image, 3=Audio, 4=Video, 5=Embedding, 6=Rerank, 7=Vision, 8=Other | |||
| @@ -38,9 +39,28 @@ const MODEL_TYPE_LIST = [ | |||
| { value: 8, labelKey: '其他' }, | |||
| ]; | |||
| // 首页定价区域分页大小配置 | |||
| // 与 gridColsClass 网格布局配合:移动端1列、平板2列、桌面3列 | |||
| const HOME_PAGE_SIZE = { | |||
| mobile: 6, // 1列 × 6行 | |||
| tablet: 8, // 2列 × 4行 | |||
| desktop: 9, // 3列 × 3行 | |||
| }; | |||
| const HomePricingFilters = ({ t }) => { | |||
| const [showRatio, setShowRatio] = useState(false); | |||
| const isMobile = useIsMobile(); | |||
| const pricingData = useModelPricingData(); | |||
| // 根据屏幕尺寸动态计算分页大小 | |||
| const pageSize = useMemo(() => { | |||
| if (isMobile) return HOME_PAGE_SIZE.mobile; | |||
| // 通过窗口宽度判断平板(768px-1024px 为 md 范围) | |||
| if (typeof window !== 'undefined' && window.innerWidth < 1024) { | |||
| return HOME_PAGE_SIZE.tablet; | |||
| } | |||
| return HOME_PAGE_SIZE.desktop; | |||
| }, [isMobile]); | |||
| const { | |||
| vendorModels, | |||
| typeModels, | |||
| @@ -154,7 +174,7 @@ const HomePricingFilters = ({ t }) => { | |||
| filteredModels={pricingData.filteredModels} | |||
| loading={pricingData.loading} | |||
| rowSelection={null} | |||
| pageSize={pricingData.pageSize} | |||
| pageSize={pageSize} | |||
| setPageSize={pricingData.setPageSize} | |||
| currentPage={pricingData.currentPage} | |||
| setCurrentPage={pricingData.setCurrentPage} | |||
| @@ -171,7 +191,7 @@ const HomePricingFilters = ({ t }) => { | |||
| selectedRowKeys={[]} | |||
| openModelDetail={pricingData.openModelDetail} | |||
| gridColsClass='grid-cols-1 md:grid-cols-2 lg:grid-cols-3' | |||
| showPagination={false} | |||
| showPagination={true} | |||
| /> | |||
| </div> | |||