chore: update home page style

This commit is contained in:
JustSong
2025-01-31 22:45:57 +08:00
parent abe2d2dba8
commit e8ea87fff3
3 changed files with 224 additions and 100 deletions

View File

@@ -3,11 +3,14 @@ import { Card, Grid, Header, Segment } from 'semantic-ui-react';
import { API, showError, showNotice, timestamp2string } from '../../helpers'; import { API, showError, showNotice, timestamp2string } from '../../helpers';
import { StatusContext } from '../../context/Status'; import { StatusContext } from '../../context/Status';
import { marked } from 'marked'; import { marked } from 'marked';
import { UserContext } from '../../context/User';
import { Link } from 'react-router-dom';
const Home = () => { const Home = () => {
const [statusState, statusDispatch] = useContext(StatusContext); const [statusState, statusDispatch] = useContext(StatusContext);
const [homePageContentLoaded, setHomePageContentLoaded] = useState(false); const [homePageContentLoaded, setHomePageContentLoaded] = useState(false);
const [homePageContent, setHomePageContent] = useState(''); const [homePageContent, setHomePageContent] = useState('');
const [userState] = useContext(UserContext);
const displayNotice = async () => { const displayNotice = async () => {
const res = await API.get('/api/notice'); const res = await API.get('/api/notice');
@@ -51,27 +54,92 @@ const Home = () => {
displayNotice().then(); displayNotice().then();
displayHomePageContent().then(); displayHomePageContent().then();
}, []); }, []);
return ( return (
<div className='dashboard-container'>
<Card fluid className='chart-card'>
<Card.Content>
<Card.Header className='header'>
欢迎使用 One API
</Card.Header>
<Card.Description style={{ lineHeight: '1.6' }}>
<p>
One API 是一个 OpenAI 接口管理和分发系统可以帮助您更好地管理和使用 OpenAI API
</p>
{!userState.user && (
<p>
如需使用请先<Link to='/login'>登录</Link>
<Link to='/register'>注册</Link>
</p>
)}
</Card.Description>
</Card.Content>
</Card>
<Grid columns={3} stackable className='charts-grid'>
<Grid.Column>
<Card fluid className='chart-card'>
<Card.Content>
<Card.Header className='header'>
使用说明
</Card.Header>
<Card.Description style={{ lineHeight: '1.6' }}>
<p>1. 登录并获取令牌</p>
<p>2. 在您的应用中使用令牌</p>
<p>3. 监控使用情况和费用</p>
</Card.Description>
</Card.Content>
</Card>
</Grid.Column>
<Grid.Column>
<Card fluid className='chart-card'>
<Card.Content>
<Card.Header className='header'>
功能特点
</Card.Header>
<Card.Description style={{ lineHeight: '1.6' }}>
<p> 多渠道接口管理</p>
<p> 实时监控和统计</p>
<p> 灵活的配额控制</p>
</Card.Description>
</Card.Content>
</Card>
</Grid.Column>
<Grid.Column>
<Card fluid className='chart-card'>
<Card.Content>
<Card.Header className='header'>
技术支持
</Card.Header>
<Card.Description style={{ lineHeight: '1.6' }}>
<p> 完整的API文档</p>
<p> 详细的使用教程</p>
<p> 及时的问题解答</p>
</Card.Description>
</Card.Content>
</Card>
</Grid.Column>
</Grid>
{homePageContentLoaded && homePageContent === '' ? (
<> <>
{ <Card fluid className='chart-card'>
homePageContentLoaded && homePageContent === '' ? <> <Card.Content>
<Segment> <Card.Header className='header'>系统状况</Card.Header>
<Header as='h3'>系统状况</Header>
<Grid columns={2} stackable> <Grid columns={2} stackable>
<Grid.Column> <Grid.Column>
<Card fluid> <Card fluid className='chart-card'>
<Card.Content> <Card.Content>
<Card.Header>系统信息</Card.Header> <Card.Header className='header'>系统信息</Card.Header>
<Card.Meta>系统信息总览</Card.Meta> <Card.Meta>系统信息总览</Card.Meta>
<Card.Description> <Card.Description style={{ lineHeight: '1.6' }}>
<p>名称{statusState?.status?.system_name}</p> <p>名称{statusState?.status?.system_name}</p>
<p>版本{statusState?.status?.version ? statusState?.status?.version : "unknown"}</p> <p>版本{statusState?.status?.version ? statusState?.status?.version : "unknown"}</p>
<p> <p>
源码 源码
<a <a href='https://github.com/songquanpeng/one-api' target='_blank'>
href='https://github.com/songquanpeng/one-api'
target='_blank'
>
https://github.com/songquanpeng/one-api https://github.com/songquanpeng/one-api
</a> </a>
</p> </p>
@@ -81,11 +149,11 @@ const Home = () => {
</Card> </Card>
</Grid.Column> </Grid.Column>
<Grid.Column> <Grid.Column>
<Card fluid> <Card fluid className='chart-card'>
<Card.Content> <Card.Content>
<Card.Header>系统配置</Card.Header> <Card.Header className='header'>系统配置</Card.Header>
<Card.Meta>系统配置总览</Card.Meta> <Card.Meta>系统配置总览</Card.Meta>
<Card.Description> <Card.Description style={{ lineHeight: '1.6' }}>
<p> <p>
邮箱验证 邮箱验证
{statusState?.status?.email_verification === true {statusState?.status?.email_verification === true
@@ -115,18 +183,25 @@ const Home = () => {
</Card> </Card>
</Grid.Column> </Grid.Column>
</Grid> </Grid>
</Segment> </Card.Content>
</> : <> </Card>
{ </>
homePageContent.startsWith('https://') ? <iframe ) : (
<>
{homePageContent.startsWith('https://') ? (
<iframe
src={homePageContent} src={homePageContent}
style={{ width: '100%', height: '100vh', border: 'none' }} style={{ width: '100%', height: '100vh', border: 'none' }}
/> : <div style={{ fontSize: 'larger' }} dangerouslySetInnerHTML={{ __html: homePageContent }}></div> />
} ) : (
</> <div
} style={{ fontSize: 'larger' }}
dangerouslySetInnerHTML={{ __html: homePageContent }}
></div>
)}
</> </>
)}
</div>
); );
}; };

View File

@@ -1,7 +1,13 @@
import React, { useEffect, useState } from 'react'; import React, { useEffect, useState } from 'react';
import { Button, Form, Header, Message, Segment } from 'semantic-ui-react'; import { Button, Form, Header, Message, Segment } from 'semantic-ui-react';
import { useNavigate, useParams } from 'react-router-dom'; import { useNavigate, useParams } from 'react-router-dom';
import { API, copy, showError, showSuccess, timestamp2string } from '../../helpers'; import {
API,
copy,
showError,
showSuccess,
timestamp2string,
} from '../../helpers';
import { renderQuotaWithPrompt } from '../../helpers/render'; import { renderQuotaWithPrompt } from '../../helpers/render';
const EditToken = () => { const EditToken = () => {
@@ -16,7 +22,7 @@ const EditToken = () => {
expired_time: -1, expired_time: -1,
unlimited_quota: false, unlimited_quota: false,
models: [], models: [],
subnet: "", subnet: '',
}; };
const [inputs, setInputs] = useState(originInputs); const [inputs, setInputs] = useState(originInputs);
const { name, remain_quota, expired_time, unlimited_quota } = inputs; const { name, remain_quota, expired_time, unlimited_quota } = inputs;
@@ -79,7 +85,7 @@ const EditToken = () => {
return { return {
key: model, key: model,
text: model, text: model,
value: model value: model,
}; };
}); });
setModelOptions(options); setModelOptions(options);
@@ -103,7 +109,10 @@ const EditToken = () => {
localInputs.models = localInputs.models.join(','); localInputs.models = localInputs.models.join(',');
let res; let res;
if (isEdit) { if (isEdit) {
res = await API.put(`/api/token/`, { ...localInputs, id: parseInt(tokenId) }); res = await API.put(`/api/token/`, {
...localInputs,
id: parseInt(tokenId),
});
} else { } else {
res = await API.post(`/api/token/`, localInputs); res = await API.post(`/api/token/`, localInputs);
} }
@@ -158,7 +167,9 @@ const EditToken = () => {
<Form.Input <Form.Input
label='IP 限制' label='IP 限制'
name='subnet' name='subnet'
placeholder={'请输入允许访问的网段例如192.168.0.0/24请使用英文逗号分隔多个网段'} placeholder={
'请输入允许访问的网段例如192.168.0.0/24请使用英文逗号分隔多个网段'
}
onChange={handleInputChange} onChange={handleInputChange}
value={inputs.subnet} value={inputs.subnet}
autoComplete='new-password' autoComplete='new-password'
@@ -168,7 +179,9 @@ const EditToken = () => {
<Form.Input <Form.Input
label='过期时间' label='过期时间'
name='expired_time' name='expired_time'
placeholder={'请输入过期时间,格式为 yyyy-MM-dd HH:mm:ss-1 表示无限制'} placeholder={
'请输入过期时间,格式为 yyyy-MM-dd HH:mm:ss-1 表示无限制'
}
onChange={handleInputChange} onChange={handleInputChange}
value={expired_time} value={expired_time}
autoComplete='new-password' autoComplete='new-password'
@@ -176,23 +189,50 @@ const EditToken = () => {
/> />
</Form.Field> </Form.Field>
<div style={{ lineHeight: '40px' }}> <div style={{ lineHeight: '40px' }}>
<Button type={'button'} onClick={() => { <Button
type={'button'}
onClick={() => {
setExpiredTime(0, 0, 0, 0); setExpiredTime(0, 0, 0, 0);
}}>永不过期</Button> }}
<Button type={'button'} onClick={() => { >
永不过期
</Button>
<Button
type={'button'}
onClick={() => {
setExpiredTime(1, 0, 0, 0); setExpiredTime(1, 0, 0, 0);
}}>一个月后过期</Button> }}
<Button type={'button'} onClick={() => { >
一个月后过期
</Button>
<Button
type={'button'}
onClick={() => {
setExpiredTime(0, 1, 0, 0); setExpiredTime(0, 1, 0, 0);
}}>一天后过期</Button> }}
<Button type={'button'} onClick={() => { >
一天后过期
</Button>
<Button
type={'button'}
onClick={() => {
setExpiredTime(0, 0, 1, 0); setExpiredTime(0, 0, 1, 0);
}}>一小时后过期</Button> }}
<Button type={'button'} onClick={() => { >
一小时后过期
</Button>
<Button
type={'button'}
onClick={() => {
setExpiredTime(0, 0, 0, 1); setExpiredTime(0, 0, 0, 1);
}}>一分钟后过期</Button> }}
>
一分钟后过期
</Button>
</div> </div>
<Message>注意令牌的额度仅用于限制令牌本身的最大额度使用量实际的使用受到账户的剩余额度限制</Message> <Message>
注意令牌的额度仅用于限制令牌本身的最大额度使用量实际的使用受到账户的剩余额度限制
</Message>
<Form.Field> <Form.Field>
<Form.Input <Form.Input
label={`额度${renderQuotaWithPrompt(remain_quota)}`} label={`额度${renderQuotaWithPrompt(remain_quota)}`}
@@ -205,11 +245,20 @@ const EditToken = () => {
disabled={unlimited_quota} disabled={unlimited_quota}
/> />
</Form.Field> </Form.Field>
<Button type={'button'} onClick={() => { <Button
type={'button'}
onClick={() => {
setUnlimitedQuota(); setUnlimitedQuota();
}}>{unlimited_quota ? '取消无限额度' : '设为无限额度'}</Button> }}
<Button floated='right' positive onClick={submit}>提交</Button> >
<Button floated='right' onClick={handleCancel}>取消</Button> {unlimited_quota ? '取消无限额度' : '设为无限额度'}
</Button>
<Button floated='right' positive onClick={submit}>
提交
</Button>
<Button floated='right' onClick={handleCancel}>
取消
</Button>
</Form> </Form>
</Segment> </Segment>
</> </>

View File

@@ -6,7 +6,7 @@ const Token = () => (
<> <>
<Segment> <Segment>
<Header as='h3'>我的令牌</Header> <Header as='h3'>我的令牌</Header>
<TokensTable/> <TokensTable />
</Segment> </Segment>
</> </>
); );