1- import { Row } from "antd" ;
1+ import { Row , Typography } from "antd" ;
22import { SCROLL_STYLE } from "@/constant" ;
33import { modelHub } from "ai-model-hub" ;
4+ import { ProCard , ProTable } from "@ant-design/pro-components" ;
45
5- // const RenderContent = (prop: {
6- // title: ReactNode;
7- // data: ProviderModelListType;
8- // }) => {
9- // const getPrice = (price: number) => {
10- // // 将数字转换为字符串
11- // const priceString = price.toString();
12- // // 找到小数点的位置
13- // const decimalIndex = priceString.indexOf('.');
14- //
15- // // 如果没有小数点,或者小数点后不足两位,则补足两位小数
16- // if (decimalIndex === -1 || priceString.length - decimalIndex <= 2) {
17- // return price.toFixed(2);
18- // } else {
19- // // 如果有两位以上的小数,则保留原始的小数位数
20- // return priceString;
21- // }
22- // }
23- // const renderTokenPrice = (record: ModelListType, type: "prompt" | "complete") => {
24- // const value = record.price[type];
25- // const {Text} = Typography;
26- //
27- // if (value === null) {
28- // return <Text type={"secondary"}>-</Text>;
29- // } else {
30- // return (
31- // <>
32- // <Text>${getPrice(value)}</Text>
33- // <Text type={"secondary"}> / {record.price.unit || "1M tokens"}</Text>
34- // </>
35- // );
36- // }
37- // }
38- // const renderTimesPrice = (record: ModelListType) => {
39- // const value = record.price.times;
40- // const {Text} = Typography;
41- // if (value === null) {
42- // return <Text type={"secondary"}>-</Text>;
43- // }
44- // if (typeof value === "number") {
45- // return (
46- // <>
47- // <Text>${getPrice(value)}</Text>
48- // <Text type={"secondary"}> / {record.price.unit || "次"}</Text>
49- // </>
50- // )
51- // }
52- // if (typeof value === "object") {
53- // if (value.columns) return (
54- // <table style={{width: "100%", borderCollapse: "collapse"}}>
55- // <thead style={{textAlign: "center", background: "#f2f2f2", fontSize: 13}}>
56- // <tr style={{textAlign: "center"}}>
57- // {value.columns.map((col: any, index: number) => (
58- // <th key={`header-${index}`}
59- // style={{border: "1px solid #ddd", padding: "4px"}}
60- // >
61- // {col.title}
62- // </th>
63- // ))}
64- // </tr>
65- // </thead>
66- // <tbody style={{textAlign: "center", fontSize: 12}}>
67- // {value.dataSource.map((row: any, rowIndex: number) => (
68- // <tr key={`row-${rowIndex}`}>
69- // {value.columns.map((col: any, colIndex: number) => (
70- // <td key={`cell-${rowIndex}-${colIndex}`}
71- // style={{border: "1px solid #ddd", padding: "4px"}}>
72- // {col.name === "price" ?
73- // <Typography.Text style={{fontSize: 12}}>${getPrice(row[col.name])}
74- // <Typography.Text style={{fontSize: 12}} type={"secondary"}>
75- // / {record.price.unit || "次"}
76- // </Typography.Text>
77- // </Typography.Text> : row[col.name]}
78- // </td>
79- // ))}
80- // </tr>
81- // ))}
82- // </tbody>
83- // </table>
84- // );
85- // }
86- // }
87- //
88- //
89- // return (
90- // <ProCard
91- // title={prop.title}
92- // bordered
93- // headerBordered
94- // >
95- // <Table
96- // pagination={false}
97- // size={"small"}
98- // columns={[
99- // {
100- // title: "模型名称",
101- // dataIndex: "model",
102- // render: (value) => <Typography.Text strong copyable>{value}</Typography.Text>,
103- // width: "20%",
104- // },
105- // {
106- // title: "类型",
107- // dataIndex: "category",
108- // width: "10%",
109- // },
110- // {
111- // title: "提示价格",
112- // dataIndex: ["price", "prompt"],
113- // render: (_, record) => renderTokenPrice(record, "prompt"),
114- // width: "15%",
115- // },
116- // {
117- // title: "补全价格",
118- // dataIndex: ["price", "complete"],
119- // render: (_, record) => renderTokenPrice(record, "complete"),
120- // width: "15%",
121- // },
122- // {
123- // title: "按次价格",
124- // dataIndex: ["price", "times"],
125- // render: (_, record) => renderTimesPrice(record),
126- // width: "20%",
127- // },
128- // {
129- // title: "备注",
130- // dataIndex: "mark",
131- // width: "15%",
132- // },
133- // {
134- // title: "更多",
135- // key: "more",
136- // width: "5%",
137- // align: "center",
138- // render: () => <Typography.Link>详情</Typography.Link>
139- // }
140- // ]}
141- // scroll={{x: 900}}
142- // />
143- // </ProCard>
144- // );
145- // }
6+ const { Text} = Typography ;
1467
1478export function PricingPage ( ) {
1489 return (
@@ -151,13 +12,93 @@ export function PricingPage() {
15112 gutter = { [ 16 , 16 ] }
15213 style = { { ...SCROLL_STYLE , height : "100%" , padding : 32 , borderRadius : 16 } }
15314 >
154- { modelHub . getAll ( ) . map ( ( provider ) => {
155- return (
156- < >
157- { provider . models_list }
158- </ >
159- ) ;
160- } ) }
15+ < >
16+ { modelHub . getAll ( ) . map ( ( provider ) => {
17+ return (
18+ < ProCard
19+ title = { provider . provider }
20+ key = { provider . provider }
21+ bordered
22+ headerBordered
23+ >
24+ < ProTable
25+ options = { false }
26+ pagination = { false }
27+ search = { false }
28+ size = { "small" }
29+ dataSource = { provider . models_list }
30+ columns = { [
31+ {
32+ title : "模型名称" ,
33+ dataIndex : "name" ,
34+ width : "15%" ,
35+ render : ( _ , record ) => < Text strong copyable > { record . name } </ Text >
36+ } ,
37+ {
38+ title : "发布时间" ,
39+ dataIndex : "release_time" ,
40+ width : "10%" ,
41+ render : ( _ , record ) => {
42+ try {
43+ const timestamp = Number ( record . release_time ) * 1000 ;
44+ if ( isNaN ( timestamp ) || timestamp < 0 ) {
45+ return < Text type = { "secondary" } > -</ Text >
46+ } else {
47+ const date = {
48+ year : new Date ( timestamp ) . getFullYear ( ) ,
49+ month : new Date ( timestamp ) . getMonth ( ) + 1 ,
50+ day : new Date ( timestamp ) . getDate ( ) ,
51+ } ;
52+ return < Text > { date . year } -{ ( date . month ) . toString ( ) . padStart ( 2 , "0" ) } -{ ( date . day ) . toString ( ) . padStart ( 2 , "0" ) } </ Text >
53+ }
54+ } catch ( e ) {
55+ return < Text type = { "secondary" } > -</ Text >
56+ }
57+ } ,
58+ } ,
59+ {
60+ title : "模型介绍" ,
61+ dataIndex : "description" ,
62+ width : "50%" ,
63+ ellipsis : true ,
64+ } ,
65+ {
66+ title : "价格(输入)" ,
67+ render : ( _ , record ) => {
68+ const price = record ?. price ?. [ 0 ] ?. input ;
69+ const isFree = price === 0 ;
70+ return (
71+ price ? isFree ? < Text type = { "success" } > 免费</ Text > :
72+ < Text > ${ price } / 1M tokens</ Text > :
73+ < Text type = { "secondary" } > 暂无</ Text >
74+ )
75+ } ,
76+ width : "10%" ,
77+ } ,
78+ {
79+ title : "价格(输出)" ,
80+ render : ( _ , record ) => {
81+ const price = record ?. price ?. [ 0 ] ?. output ;
82+ const isFree = price === 0 ;
83+ return (
84+ price ? isFree ? < Text type = { "success" } > 免费</ Text > :
85+ < Text > ${ price } / 1M tokens</ Text > :
86+ < Text type = { "secondary" } > 暂无</ Text >
87+ )
88+ } ,
89+ width : "10%" ,
90+ } ,
91+ ] }
92+ />
93+ </ ProCard >
94+ ) ;
95+ } ) }
96+ < Text type = { "secondary" } style = { { marginTop : 6 } } >
97+ You can view the update records of model information, submit feedback or suggestions in
98+ our < Typography . Link
99+ href = { "https://github.com/OpenAI-Next/ai-model-hub" } > GitHub Repository</ Typography . Link > .
100+ </ Text >
101+ </ >
161102 </ Row >
162103 </ div >
163104 ) ;
0 commit comments