mirror of
https://github.com/songquanpeng/one-api.git
synced 2025-11-17 13:43:42 +08:00
前端改为美元展示
This commit is contained in:
@@ -22,7 +22,7 @@ let headerButtons = [
|
||||
admin: true
|
||||
},
|
||||
{
|
||||
name: '令牌',
|
||||
name: 'Key',
|
||||
to: '/token',
|
||||
icon: 'key',
|
||||
color: 'var(--czl-primary-color)'
|
||||
|
||||
@@ -276,7 +276,7 @@ const LogsTable = () => {
|
||||
|
||||
<Form>
|
||||
<Form.Group>
|
||||
<Form.Input fluid label={'令牌名称'} width={3} value={token_name}
|
||||
<Form.Input fluid label={'Key名称'} width={3} value={token_name}
|
||||
placeholder={'可选值'} name='token_name' onChange={handleInputChange} />
|
||||
<Form.Input fluid label='模型名称' width={3} value={model_name} placeholder='可选值'
|
||||
name='model_name'
|
||||
@@ -360,7 +360,7 @@ const LogsTable = () => {
|
||||
}}
|
||||
width={1}
|
||||
>
|
||||
令牌
|
||||
Key
|
||||
</Table.HeaderCell>
|
||||
<Table.HeaderCell
|
||||
style={{ cursor: 'pointer' }}
|
||||
@@ -387,7 +387,7 @@ const LogsTable = () => {
|
||||
}}
|
||||
width={1}
|
||||
>
|
||||
提示
|
||||
输入
|
||||
</Table.HeaderCell>
|
||||
<Table.HeaderCell
|
||||
style={{ cursor: 'pointer' }}
|
||||
@@ -396,7 +396,7 @@ const LogsTable = () => {
|
||||
}}
|
||||
width={1}
|
||||
>
|
||||
补全
|
||||
输出
|
||||
</Table.HeaderCell>
|
||||
<Table.HeaderCell
|
||||
style={{ cursor: 'pointer' }}
|
||||
|
||||
@@ -200,7 +200,7 @@ const OperationSetting = () => {
|
||||
/>
|
||||
<Form.Checkbox
|
||||
checked={inputs.DisplayTokenStatEnabled === 'true'}
|
||||
label='Billing 相关 API 显示令牌额度而非用户额度'
|
||||
label='Billing 相关 API 显示Key额度而非用户额度'
|
||||
name='DisplayTokenStatEnabled'
|
||||
onChange={handleInputChange}
|
||||
/>
|
||||
|
||||
@@ -131,7 +131,7 @@ const PersonalSetting = () => {
|
||||
const handleSystemTokenClick = async (e) => {
|
||||
e.target.select();
|
||||
await copy(e.target.value);
|
||||
showSuccess(`系统令牌已复制到剪切板`);
|
||||
showSuccess(`系统Key已复制到剪切板`);
|
||||
};
|
||||
|
||||
const deleteAccount = async () => {
|
||||
@@ -228,12 +228,12 @@ const PersonalSetting = () => {
|
||||
<Divider />
|
||||
<Header as='h3'>通用设置</Header>
|
||||
{/* <Message>
|
||||
注意,此处生成的令牌用于系统管理,而非用于请求 OpenAI 相关的服务,请知悉。
|
||||
注意,此处生成的Key用于系统管理,而非用于请求 OpenAI 相关的服务,请知悉。
|
||||
</Message> */}
|
||||
<Button as={Link} to={`/user/edit/`}>
|
||||
更新个人信息
|
||||
</Button>
|
||||
{/* <Button onClick={generateAccessToken}>生成系统访问令牌</Button> */}
|
||||
{/* <Button onClick={generateAccessToken}>生成系统访问Key</Button> */}
|
||||
<Button onClick={getAffLink}>复制邀请链接</Button>
|
||||
|
||||
{systemToken && (
|
||||
|
||||
@@ -109,7 +109,7 @@ const TokensTable = () => {
|
||||
if (await copy(url)) {
|
||||
showSuccess('已复制到剪贴板!');
|
||||
} else {
|
||||
showWarning('无法复制到剪贴板,请手动复制,已将令牌填入搜索框。');
|
||||
showWarning('无法复制到剪贴板,请手动复制,已将Key填入搜索框。');
|
||||
setSearchKeyword(url);
|
||||
}
|
||||
};
|
||||
@@ -241,7 +241,7 @@ const TokensTable = () => {
|
||||
icon='search'
|
||||
fluid
|
||||
iconPosition='left'
|
||||
placeholder='搜索令牌的名称 ...'
|
||||
placeholder='搜索Key的名称 ...'
|
||||
value={searchKeyword}
|
||||
loading={searching}
|
||||
onChange={handleKeywordChange}
|
||||
@@ -349,7 +349,7 @@ const TokensTable = () => {
|
||||
}}
|
||||
style={{ backgroundColor: 'var(--czl-error-color)', borderColor: 'var(--czl-error-color)' }}
|
||||
>
|
||||
删除令牌 {token.name}
|
||||
删除Key {token.name}
|
||||
</Button>
|
||||
</Popup>
|
||||
<Button
|
||||
@@ -390,7 +390,7 @@ const TokensTable = () => {
|
||||
loading={loading}
|
||||
style={{ color: "var(--czl-main)", backgroundColor: "var(--czl-link-color)" }}
|
||||
>
|
||||
添加新的令牌
|
||||
添加新的Key
|
||||
</Button>
|
||||
<Button size='small' onClick={refresh} loading={loading}>刷新</Button>
|
||||
|
||||
|
||||
@@ -37,22 +37,26 @@ export function renderNumber(num) {
|
||||
}
|
||||
}
|
||||
|
||||
export function renderQuota(quota, digits = 2) {
|
||||
export function renderQuota(quota, digits = 10) {
|
||||
let quotaPerUnit = localStorage.getItem('quota_per_unit');
|
||||
let displayInCurrency = localStorage.getItem('display_in_currency');
|
||||
quotaPerUnit = parseFloat(quotaPerUnit);
|
||||
displayInCurrency = displayInCurrency === 'true';
|
||||
if (displayInCurrency) {
|
||||
return '$' + (quota / quotaPerUnit).toFixed(digits);
|
||||
let displayValue = (quota / quotaPerUnit).toFixed(digits);
|
||||
// 去除尾部多余的零
|
||||
displayValue = parseFloat(displayValue).toString();
|
||||
return '$' + displayValue;
|
||||
}
|
||||
return renderNumber(quota);
|
||||
}
|
||||
|
||||
|
||||
export function renderQuotaWithPrompt(quota, digits) {
|
||||
let displayInCurrency = localStorage.getItem('display_in_currency');
|
||||
displayInCurrency = displayInCurrency === 'true';
|
||||
if (displayInCurrency) {
|
||||
return `(等价金额:${renderQuota(quota, digits)})`;
|
||||
return `(金额:${renderQuota(quota, digits)})`;
|
||||
}
|
||||
return '';
|
||||
}
|
||||
@@ -53,6 +53,7 @@ const EditChannel = () => {
|
||||
const [groupOptions, setGroupOptions] = useState([]);
|
||||
const [basicModels, setBasicModels] = useState([]);
|
||||
const [basicNoGPTModels, setBasicNoGPTModels] = useState([]);
|
||||
const [fullNo32KOPENAIModels, setfullNo32KOPENAIModels] = useState([]);
|
||||
const [fullOPENAIModels, setFullOPENAIModels] = useState([]);
|
||||
const [customModel, setCustomModel] = useState('');
|
||||
const handleInputChange = (e, { name, value }) => {
|
||||
@@ -126,6 +127,10 @@ const EditChannel = () => {
|
||||
return (model.id.startsWith('gpt-') || model.id.startsWith('text-') || model.id.startsWith('dall-') || model.id.startsWith('whisper-') || model.id.startsWith('code-')) && !model.id.startsWith('text-embedding-v1');
|
||||
}).map((model) => model.id));
|
||||
|
||||
setfullNo32KOPENAIModels(res.data.data.filter((model) => {
|
||||
return (model.id.startsWith('gpt-') || model.id.startsWith('text-') || model.id.startsWith('dall-') || model.id.startsWith('whisper-') || model.id.startsWith('code-')) && !model.id.startsWith('text-embedding-v1') && !model.id.startsWith('gpt-4-32k');
|
||||
}).map((model) => model.id));
|
||||
|
||||
setBasicModels(res.data.data.filter((model) => {
|
||||
return (model.id.startsWith('gpt-3') || model.id.startsWith('text-') || model.id.startsWith('dall-') || model.id.startsWith('whisper-') || model.id.startsWith('code-')) && !model.id.startsWith('text-embedding-v1');
|
||||
}).map((model) => model.id));
|
||||
@@ -368,18 +373,21 @@ const EditChannel = () => {
|
||||
/>
|
||||
</Form.Field>
|
||||
<div style={{ lineHeight: '40px', marginBottom: '12px' }}>
|
||||
<Button type={'button'} onClick={() => {
|
||||
handleInputChange(null, { name: 'models', value: basicNoGPTModels });
|
||||
}}>基础无gpt模型</Button>
|
||||
<Button type={'button'} onClick={() => {
|
||||
handleInputChange(null, { name: 'models', value: basicModels });
|
||||
}}>填入基础OPENAI模型</Button>
|
||||
}}>基础OPENAI模型</Button>
|
||||
<Button type={'button'} onClick={() => {
|
||||
handleInputChange(null, { name: 'models', value: basicNoGPTModels });
|
||||
}}>填入基础无gpt模型</Button>
|
||||
handleInputChange(null, { name: 'models', value: fullNo32KOPENAIModels });
|
||||
}}>无32K OPENAI模型</Button>
|
||||
<Button type={'button'} onClick={() => {
|
||||
handleInputChange(null, { name: 'models', value: fullOPENAIModels });
|
||||
}}>填入所有OPENAI模型</Button>
|
||||
}}>OPENAI模型</Button>
|
||||
<Button type={'button'} onClick={() => {
|
||||
handleInputChange(null, { name: 'models', value: [] });
|
||||
}}>清除所有模型</Button>
|
||||
}}>清除</Button>
|
||||
<Input
|
||||
action={
|
||||
<Button type={'button'} onClick={addCustomModel}>填入</Button>
|
||||
|
||||
@@ -12,7 +12,7 @@ const EditRedemption = () => {
|
||||
const [loading, setLoading] = useState(isEdit);
|
||||
const originInputs = {
|
||||
name: '',
|
||||
quota: 100000,
|
||||
quota: 100,
|
||||
count: 1
|
||||
};
|
||||
const [inputs, setInputs] = useState(originInputs);
|
||||
@@ -21,7 +21,7 @@ const EditRedemption = () => {
|
||||
const handleCancel = () => {
|
||||
navigate('/redemption');
|
||||
};
|
||||
|
||||
|
||||
const handleInputChange = (e, { name, value }) => {
|
||||
setInputs((inputs) => ({ ...inputs, [name]: value }));
|
||||
};
|
||||
@@ -30,6 +30,8 @@ const EditRedemption = () => {
|
||||
let res = await API.get(`/api/redemption/${redemptionId}`);
|
||||
const { success, message, data } = res.data;
|
||||
if (success) {
|
||||
let quotaPerUnit = parseFloat(localStorage.getItem('quota_per_unit'));
|
||||
data.quota = data.quota / quotaPerUnit;
|
||||
setInputs(data);
|
||||
} else {
|
||||
showError(message);
|
||||
@@ -46,7 +48,8 @@ const EditRedemption = () => {
|
||||
if (!isEdit && inputs.name === '') return;
|
||||
let localInputs = inputs;
|
||||
localInputs.count = parseInt(localInputs.count);
|
||||
localInputs.quota = parseInt(localInputs.quota);
|
||||
let quotaPerUnit = parseFloat(localStorage.getItem('quota_per_unit'));
|
||||
localInputs.quota = Math.ceil(parseFloat(localInputs.quota) * quotaPerUnit);
|
||||
let res;
|
||||
if (isEdit) {
|
||||
res = await API.put(`/api/redemption/`, { ...localInputs, id: parseInt(redemptionId) });
|
||||
@@ -93,7 +96,8 @@ const EditRedemption = () => {
|
||||
</Form.Field>
|
||||
<Form.Field>
|
||||
<Form.Input
|
||||
label={`额度${renderQuotaWithPrompt(quota)}`}
|
||||
label={`额度(单位:美金)`}
|
||||
// ${renderQuotaWithPrompt(quota)}
|
||||
name='quota'
|
||||
placeholder={'请输入单个兑换码中包含的额度'}
|
||||
onChange={handleInputChange}
|
||||
|
||||
@@ -11,7 +11,7 @@ const EditToken = () => {
|
||||
const [loading, setLoading] = useState(isEdit);
|
||||
const originInputs = {
|
||||
name: '',
|
||||
remain_quota: isEdit ? 0 : 500000,
|
||||
remain_quota: isEdit ? 0 : renderQuota(500000),
|
||||
expired_time: -1,
|
||||
unlimited_quota: false
|
||||
};
|
||||
@@ -50,6 +50,8 @@ const EditToken = () => {
|
||||
if (data.expired_time !== -1) {
|
||||
data.expired_time = timestamp2string(data.expired_time);
|
||||
}
|
||||
let quotaPerUnit = parseFloat(localStorage.getItem('quota_per_unit'));
|
||||
data.remain_quota = data.remain_quota / quotaPerUnit;
|
||||
setInputs(data);
|
||||
} else {
|
||||
showError(message);
|
||||
@@ -65,7 +67,8 @@ const EditToken = () => {
|
||||
const submit = async () => {
|
||||
if (!isEdit && inputs.name === '') return;
|
||||
let localInputs = inputs;
|
||||
localInputs.remain_quota = parseInt(localInputs.remain_quota);
|
||||
let quotaPerUnit = parseFloat(localStorage.getItem('quota_per_unit'));
|
||||
localInputs.remain_quota = Math.ceil(parseFloat(localInputs.remain_quota) * quotaPerUnit);
|
||||
if (localInputs.expired_time !== -1) {
|
||||
let time = Date.parse(localInputs.expired_time);
|
||||
if (isNaN(time)) {
|
||||
@@ -83,9 +86,9 @@ const EditToken = () => {
|
||||
const { success, message } = res.data;
|
||||
if (success) {
|
||||
if (isEdit) {
|
||||
showSuccess('令牌更新成功!');
|
||||
showSuccess('Key更新成功!');
|
||||
} else {
|
||||
showSuccess('令牌创建成功,请在列表页面点击复制获取令牌!');
|
||||
showSuccess('Key创建成功,请在列表页面点击复制获取Key!');
|
||||
setInputs(originInputs);
|
||||
}
|
||||
} else {
|
||||
@@ -96,7 +99,7 @@ const EditToken = () => {
|
||||
return (
|
||||
<>
|
||||
<Segment loading={loading}>
|
||||
<Header as='h3'>{isEdit ? '更新令牌信息' : '创建新的令牌'}</Header>
|
||||
<Header as='h3'>{isEdit ? '更新Key信息' : '创建新的Key'}</Header>
|
||||
<Form autoComplete='new-password'>
|
||||
<Form.Field>
|
||||
<Form.Input
|
||||
@@ -137,10 +140,10 @@ const EditToken = () => {
|
||||
setExpiredTime(0, 0, 0, 1);
|
||||
}}>一分钟后过期</Button>
|
||||
</div>
|
||||
<Message>注意,令牌的额度仅用于限制令牌本身的最大额度使用量,实际的使用受到账户的剩余额度限制。</Message>
|
||||
<Message>注意,Key的额度仅用于限制Key本身的最大额度使用量,实际的使用受到账户的剩余额度限制。</Message>
|
||||
<Form.Field>
|
||||
<Form.Input
|
||||
label={`额度${renderQuotaWithPrompt(remain_quota)}`}
|
||||
label={`额度(单位:美金)`}
|
||||
name='remain_quota'
|
||||
placeholder={'请输入额度'}
|
||||
onChange={handleInputChange}
|
||||
|
||||
@@ -5,7 +5,7 @@ import TokensTable from '../../components/TokensTable';
|
||||
const Token = () => (
|
||||
<>
|
||||
<Segment>
|
||||
<Header as='h3'>我的令牌</Header>
|
||||
<Header as='h3'>我的Key</Header>
|
||||
<TokensTable/>
|
||||
</Segment>
|
||||
</>
|
||||
|
||||
@@ -50,6 +50,8 @@ const EditUser = () => {
|
||||
const { success, message, data } = res.data;
|
||||
if (success) {
|
||||
data.password = '';
|
||||
let quotaPerUnit = parseFloat(localStorage.getItem('quota_per_unit'));
|
||||
data.quota = data.quota / quotaPerUnit;
|
||||
setInputs(data);
|
||||
} else {
|
||||
showError(message);
|
||||
@@ -67,6 +69,8 @@ const EditUser = () => {
|
||||
let res = undefined;
|
||||
if (userId) {
|
||||
let data = { ...inputs, id: parseInt(userId) };
|
||||
let quotaPerUnit = parseFloat(localStorage.getItem('quota_per_unit'));
|
||||
data.quota = Math.ceil(parseFloat(data.quota) * quotaPerUnit);
|
||||
if (typeof data.quota === 'string') {
|
||||
data.quota = parseInt(data.quota);
|
||||
}
|
||||
@@ -138,7 +142,7 @@ const EditUser = () => {
|
||||
</Form.Field>
|
||||
<Form.Field>
|
||||
<Form.Input
|
||||
label={`剩余额度${renderQuotaWithPrompt(quota)}`}
|
||||
label={`剩余额度(单位:美金)`}
|
||||
name='quota'
|
||||
placeholder={'请输入新的剩余额度'}
|
||||
onChange={handleInputChange}
|
||||
|
||||
Reference in New Issue
Block a user