Parcourir la source

feat(pricing): 首页定价添加分页并优化渠道 ID 展示

- 首页定价区域添加响应式分页(移动端6/平板8/桌面9)
- 渠道列表显示 ID,支持在名称中查看
- 渠道定价卡片添加 ID 标签和使用提示 Banner
- 代码示例中展示 API Key 指定渠道的格式

Co-Authored-By: Claude <noreply@anthropic.com>
feat/alipay-payment
fengsilin il y a 1 mois
Parent
révision
2ea8501938
4 fichiers modifiés avec 46 ajouts et 16 suppressions
  1. +3
    -2
      web/src/components/table/channels/ChannelsColumnDefs.jsx
  2. +10
    -1
      web/src/components/table/model-pricing/modal/components/ChannelPricingCard.jsx
  3. +11
    -11
      web/src/components/table/model-pricing/modal/components/ModelCodeSnippet.jsx
  4. +22
    -2
      web/src/pages/Home/HomePricingFilters.jsx

+ 3
- 2
web/src/components/table/channels/ChannelsColumnDefs.jsx Voir le fichier

@@ -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) {


+ 10
- 1
web/src/components/table/model-pricing/modal/components/ChannelPricingCard.jsx Voir le fichier

@@ -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}


+ 11
- 11
web/src/components/table/model-pricing/modal/components/ModelCodeSnippet.jsx Voir le fichier

@@ -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": [


+ 22
- 2
web/src/pages/Home/HomePricingFilters.jsx Voir le fichier

@@ -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>



Chargement…
Annuler
Enregistrer