前端改为美元展示

This commit is contained in:
wood
2023-11-15 04:34:59 +08:00
parent fff889742b
commit 876e0d429b
16 changed files with 112 additions and 88 deletions

View File

@@ -22,7 +22,7 @@ let headerButtons = [
admin: true
},
{
name: '令牌',
name: 'Key',
to: '/token',
icon: 'key',
color: 'var(--czl-primary-color)'

View File

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

View File

@@ -200,7 +200,7 @@ const OperationSetting = () => {
/>
<Form.Checkbox
checked={inputs.DisplayTokenStatEnabled === 'true'}
label='Billing 相关 API 显示令牌额度而非用户额度'
label='Billing 相关 API 显示Key额度而非用户额度'
name='DisplayTokenStatEnabled'
onChange={handleInputChange}
/>

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -5,7 +5,7 @@ import TokensTable from '../../components/TokensTable';
const Token = () => (
<>
<Segment>
<Header as='h3'>我的令牌</Header>
<Header as='h3'>我的Key</Header>
<TokensTable/>
</Segment>
</>

View File

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