mirror of
https://github.com/linux-do/new-api.git
synced 2025-09-18 00:16:37 +08:00
commit
24722a8ee2
BIN
web/public/ratio.png
Normal file
BIN
web/public/ratio.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 140 KiB |
@ -1,4 +1,4 @@
|
|||||||
import React, { useContext, useEffect, useRef, useState } from 'react';
|
import React, { useContext, useEffect, useRef, useMemo, useState } from 'react';
|
||||||
import { API, copy, showError, showSuccess } from '../helpers';
|
import { API, copy, showError, showSuccess } from '../helpers';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
@ -10,8 +10,16 @@ import {
|
|||||||
Table,
|
Table,
|
||||||
Tag,
|
Tag,
|
||||||
Tooltip,
|
Tooltip,
|
||||||
|
Popover,
|
||||||
|
ImagePreview,
|
||||||
|
Button,
|
||||||
} from '@douyinfe/semi-ui';
|
} from '@douyinfe/semi-ui';
|
||||||
import { stringToColor } from '../helpers/render.js';
|
import {
|
||||||
|
IconMore,
|
||||||
|
IconVerify,
|
||||||
|
IconUploadError,
|
||||||
|
IconHelpCircle,
|
||||||
|
} from '@douyinfe/semi-icons';
|
||||||
import { UserContext } from '../context/User/index.js';
|
import { UserContext } from '../context/User/index.js';
|
||||||
import Text from '@douyinfe/semi-ui/lib/es/typography/text';
|
import Text from '@douyinfe/semi-ui/lib/es/typography/text';
|
||||||
|
|
||||||
@ -20,42 +28,74 @@ function renderQuotaType(type) {
|
|||||||
switch (type) {
|
switch (type) {
|
||||||
case 1:
|
case 1:
|
||||||
return (
|
return (
|
||||||
<Tag color='green' size='large'>
|
<Tag color='teal' size='large'>
|
||||||
按次计费
|
按次计费
|
||||||
</Tag>
|
</Tag>
|
||||||
);
|
);
|
||||||
case 0:
|
case 0:
|
||||||
return (
|
return (
|
||||||
<Tag color='blue' size='large'>
|
<Tag color='violet' size='large'>
|
||||||
按量计费
|
按量计费
|
||||||
</Tag>
|
</Tag>
|
||||||
);
|
);
|
||||||
default:
|
default:
|
||||||
return (
|
return '未知';
|
||||||
<Tag color='white' size='large'>
|
|
||||||
未知
|
|
||||||
</Tag>
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function renderAvailable(available) {
|
function renderAvailable(available) {
|
||||||
return available ? (
|
return available ? (
|
||||||
<Tag color='green' size='large'>
|
<Popover
|
||||||
可用
|
content={
|
||||||
</Tag>
|
<div style={{ padding: 8 }}>您的分组可以使用该模型</div>
|
||||||
|
}
|
||||||
|
position='top'
|
||||||
|
key={available}
|
||||||
|
style={{
|
||||||
|
backgroundColor: 'rgba(var(--semi-blue-4),1)',
|
||||||
|
borderColor: 'rgba(var(--semi-blue-4),1)',
|
||||||
|
color: 'var(--semi-color-white)',
|
||||||
|
borderWidth: 1,
|
||||||
|
borderStyle: 'solid',
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<IconVerify style={{ color: 'green' }} size="large" />
|
||||||
|
</Popover>
|
||||||
) : (
|
) : (
|
||||||
<Tooltip content='您所在的分组不可用'>
|
<Popover
|
||||||
<Tag color='red' size='large'>
|
content={
|
||||||
不可用
|
<div style={{ padding: 8 }}>您的分组无权使用该模型</div>
|
||||||
</Tag>
|
}
|
||||||
</Tooltip>
|
position='top'
|
||||||
|
key={available}
|
||||||
|
style={{
|
||||||
|
backgroundColor: 'rgba(var(--semi-blue-4),1)',
|
||||||
|
borderColor: 'rgba(var(--semi-blue-4),1)',
|
||||||
|
color: 'var(--semi-color-white)',
|
||||||
|
borderWidth: 1,
|
||||||
|
borderStyle: 'solid',
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<IconUploadError style={{ color: '#FFA54F' }} size="large" />
|
||||||
|
</Popover>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const ModelPricing = () => {
|
const ModelPricing = () => {
|
||||||
const [filteredValue, setFilteredValue] = useState([]);
|
const [filteredValue, setFilteredValue] = useState([]);
|
||||||
const compositionRef = useRef({ isComposition: false });
|
const compositionRef = useRef({ isComposition: false });
|
||||||
|
const [selectedRowKeys, setSelectedRowKeys] = useState([]);
|
||||||
|
const [modalImageUrl, setModalImageUrl] = useState('');
|
||||||
|
const [isModalOpenurl, setIsModalOpenurl] = useState(false);
|
||||||
|
|
||||||
|
const rowSelection = useMemo(
|
||||||
|
() => ({
|
||||||
|
onChange: (selectedRowKeys, selectedRows) => {
|
||||||
|
setSelectedRowKeys(selectedRowKeys);
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
[]
|
||||||
|
);
|
||||||
|
|
||||||
const handleChange = (value) => {
|
const handleChange = (value) => {
|
||||||
if (compositionRef.current.isComposition) {
|
if (compositionRef.current.isComposition) {
|
||||||
@ -103,7 +143,7 @@ const ModelPricing = () => {
|
|||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Tag
|
<Tag
|
||||||
color={stringToColor(text)}
|
color='green'
|
||||||
size='large'
|
size='large'
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
copyText(text);
|
copyText(text);
|
||||||
@ -114,7 +154,8 @@ const ModelPricing = () => {
|
|||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
onFilter: (value, record) => record.model_name.includes(value),
|
onFilter: (value, record) =>
|
||||||
|
record.model_name.toLowerCase().includes(value.toLowerCase()),
|
||||||
filteredValue,
|
filteredValue,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -126,18 +167,43 @@ const ModelPricing = () => {
|
|||||||
sorter: (a, b) => a.quota_type - b.quota_type,
|
sorter: (a, b) => a.quota_type - b.quota_type,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '模型倍率',
|
title: () => (
|
||||||
|
<span style={{'display':'flex','alignItems':'center'}}>
|
||||||
|
倍率
|
||||||
|
<Popover
|
||||||
|
content={
|
||||||
|
<div style={{ padding: 8 }}>倍率是为了方便换算不同价格的模型<br/>点击查看倍率说明</div>
|
||||||
|
}
|
||||||
|
position='top'
|
||||||
|
style={{
|
||||||
|
backgroundColor: 'rgba(var(--semi-blue-4),1)',
|
||||||
|
borderColor: 'rgba(var(--semi-blue-4),1)',
|
||||||
|
color: 'var(--semi-color-white)',
|
||||||
|
borderWidth: 1,
|
||||||
|
borderStyle: 'solid',
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<IconHelpCircle
|
||||||
|
onClick={() => {
|
||||||
|
setModalImageUrl('/ratio.png');
|
||||||
|
setIsModalOpenurl(true);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</Popover>
|
||||||
|
</span>
|
||||||
|
),
|
||||||
dataIndex: 'model_ratio',
|
dataIndex: 'model_ratio',
|
||||||
render: (text, record, index) => {
|
render: (text, record, index) => {
|
||||||
return <div>{record.quota_type === 0 ? text : 'N/A'}</div>;
|
let content = text;
|
||||||
},
|
let completionRatio = parseFloat(record.completion_ratio.toFixed(3));
|
||||||
},
|
content = (
|
||||||
{
|
<>
|
||||||
title: '补全倍率',
|
<Text>模型:{record.quota_type === 0 ? text : '无'}</Text>
|
||||||
dataIndex: 'completion_ratio',
|
<br />
|
||||||
render: (text, record, index) => {
|
<Text>补全:{record.quota_type === 0 ? completionRatio : '无'}</Text>
|
||||||
let ratio = parseFloat(text.toFixed(3));
|
</>
|
||||||
return <div>{record.quota_type === 0 ? ratio : 'N/A'}</div>;
|
);
|
||||||
|
return <div>{content}</div>;
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -175,7 +241,7 @@ const ModelPricing = () => {
|
|||||||
|
|
||||||
const setModelsFormat = (models, groupRatio) => {
|
const setModelsFormat = (models, groupRatio) => {
|
||||||
for (let i = 0; i < models.length; i++) {
|
for (let i = 0; i < models.length; i++) {
|
||||||
models[i].key = i;
|
models[i].key = models[i].model_name;
|
||||||
models[i].group_ratio = groupRatio;
|
models[i].group_ratio = groupRatio;
|
||||||
}
|
}
|
||||||
// sort by quota_type
|
// sort by quota_type
|
||||||
@ -238,15 +304,38 @@ const ModelPricing = () => {
|
|||||||
<Layout>
|
<Layout>
|
||||||
{userState.user ? (
|
{userState.user ? (
|
||||||
<Banner
|
<Banner
|
||||||
type='info'
|
type="success"
|
||||||
|
fullMode={false}
|
||||||
|
closeIcon="null"
|
||||||
description={`您的分组为:${userState.user.group},分组倍率为:${groupRatio}`}
|
description={`您的分组为:${userState.user.group},分组倍率为:${groupRatio}`}
|
||||||
/>
|
/>
|
||||||
) : (
|
) : (
|
||||||
<Banner
|
<Banner
|
||||||
type='warning'
|
type='warning'
|
||||||
|
fullMode={false}
|
||||||
|
closeIcon="null"
|
||||||
description={`您还未登陆,显示的价格为默认分组倍率: ${groupRatio}`}
|
description={`您还未登陆,显示的价格为默认分组倍率: ${groupRatio}`}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
<br/>
|
||||||
|
<Banner
|
||||||
|
type="info"
|
||||||
|
fullMode={false}
|
||||||
|
description={<div>按量计费费用 = 分组倍率 × 模型倍率 × (提示token数 + 补全token数 × 补全倍率)/ 500000 (单位:美元)</div>}
|
||||||
|
closeIcon="null"
|
||||||
|
/>
|
||||||
|
<br/>
|
||||||
|
<Button
|
||||||
|
theme='light'
|
||||||
|
type='tertiary'
|
||||||
|
style={{width: 150}}
|
||||||
|
onClick={() => {
|
||||||
|
copyText(selectedRowKeys);
|
||||||
|
}}
|
||||||
|
disabled={selectedRowKeys == ""}
|
||||||
|
>
|
||||||
|
复制选中模型
|
||||||
|
</Button>
|
||||||
<Table
|
<Table
|
||||||
style={{ marginTop: 5 }}
|
style={{ marginTop: 5 }}
|
||||||
columns={columns}
|
columns={columns}
|
||||||
@ -256,6 +345,12 @@ const ModelPricing = () => {
|
|||||||
pageSize: models.length,
|
pageSize: models.length,
|
||||||
showSizeChanger: false,
|
showSizeChanger: false,
|
||||||
}}
|
}}
|
||||||
|
rowSelection={rowSelection}
|
||||||
|
/>
|
||||||
|
<ImagePreview
|
||||||
|
src={modalImageUrl}
|
||||||
|
visible={isModalOpenurl}
|
||||||
|
onVisibleChange={(visible) => setIsModalOpenurl(visible)}
|
||||||
/>
|
/>
|
||||||
</Layout>
|
</Layout>
|
||||||
</>
|
</>
|
||||||
|
Loading…
Reference in New Issue
Block a user