mirror of
				https://github.com/songquanpeng/one-api.git
				synced 2025-11-04 15:53:42 +08:00 
			
		
		
		
	chore: update home page style
This commit is contained in:
		@@ -3,11 +3,14 @@ import { Card, Grid, Header, Segment } from 'semantic-ui-react';
 | 
			
		||||
import { API, showError, showNotice, timestamp2string } from '../../helpers';
 | 
			
		||||
import { StatusContext } from '../../context/Status';
 | 
			
		||||
import { marked } from 'marked';
 | 
			
		||||
import { UserContext } from '../../context/User';
 | 
			
		||||
import { Link } from 'react-router-dom';
 | 
			
		||||
 | 
			
		||||
const Home = () => {
 | 
			
		||||
  const [statusState, statusDispatch] = useContext(StatusContext);
 | 
			
		||||
  const [homePageContentLoaded, setHomePageContentLoaded] = useState(false);
 | 
			
		||||
  const [homePageContent, setHomePageContent] = useState('');
 | 
			
		||||
  const [userState] = useContext(UserContext);
 | 
			
		||||
 | 
			
		||||
  const displayNotice = async () => {
 | 
			
		||||
    const res = await API.get('/api/notice');
 | 
			
		||||
@@ -51,82 +54,154 @@ const Home = () => {
 | 
			
		||||
    displayNotice().then();
 | 
			
		||||
    displayHomePageContent().then();
 | 
			
		||||
  }, []);
 | 
			
		||||
 | 
			
		||||
  return (
 | 
			
		||||
    <>
 | 
			
		||||
      {
 | 
			
		||||
        homePageContentLoaded && homePageContent === '' ? <>
 | 
			
		||||
          <Segment>
 | 
			
		||||
            <Header as='h3'>系统状况</Header>
 | 
			
		||||
            <Grid columns={2} stackable>
 | 
			
		||||
              <Grid.Column>
 | 
			
		||||
                <Card fluid>
 | 
			
		||||
                  <Card.Content>
 | 
			
		||||
                    <Card.Header>系统信息</Card.Header>
 | 
			
		||||
                    <Card.Meta>系统信息总览</Card.Meta>
 | 
			
		||||
                    <Card.Description>
 | 
			
		||||
                      <p>名称:{statusState?.status?.system_name}</p>
 | 
			
		||||
                      <p>版本:{statusState?.status?.version ? statusState?.status?.version : "unknown"}</p>
 | 
			
		||||
                      <p>
 | 
			
		||||
                        源码:
 | 
			
		||||
                        <a
 | 
			
		||||
                          href='https://github.com/songquanpeng/one-api'
 | 
			
		||||
                          target='_blank'
 | 
			
		||||
                        >
 | 
			
		||||
                          https://github.com/songquanpeng/one-api
 | 
			
		||||
                        </a>
 | 
			
		||||
                      </p>
 | 
			
		||||
                      <p>启动时间:{getStartTimeString()}</p>
 | 
			
		||||
                    </Card.Description>
 | 
			
		||||
                  </Card.Content>
 | 
			
		||||
                </Card>
 | 
			
		||||
              </Grid.Column>
 | 
			
		||||
              <Grid.Column>
 | 
			
		||||
                <Card fluid>
 | 
			
		||||
                  <Card.Content>
 | 
			
		||||
                    <Card.Header>系统配置</Card.Header>
 | 
			
		||||
                    <Card.Meta>系统配置总览</Card.Meta>
 | 
			
		||||
                    <Card.Description>
 | 
			
		||||
                      <p>
 | 
			
		||||
                        邮箱验证:
 | 
			
		||||
                        {statusState?.status?.email_verification === true
 | 
			
		||||
                          ? '已启用'
 | 
			
		||||
                          : '未启用'}
 | 
			
		||||
                      </p>
 | 
			
		||||
                      <p>
 | 
			
		||||
                        GitHub 身份验证:
 | 
			
		||||
                        {statusState?.status?.github_oauth === true
 | 
			
		||||
                          ? '已启用'
 | 
			
		||||
                          : '未启用'}
 | 
			
		||||
                      </p>
 | 
			
		||||
                      <p>
 | 
			
		||||
                        微信身份验证:
 | 
			
		||||
                        {statusState?.status?.wechat_login === true
 | 
			
		||||
                          ? '已启用'
 | 
			
		||||
                          : '未启用'}
 | 
			
		||||
                      </p>
 | 
			
		||||
                      <p>
 | 
			
		||||
                        Turnstile 用户校验:
 | 
			
		||||
                        {statusState?.status?.turnstile_check === true
 | 
			
		||||
                          ? '已启用'
 | 
			
		||||
                          : '未启用'}
 | 
			
		||||
                      </p>
 | 
			
		||||
                    </Card.Description>
 | 
			
		||||
                  </Card.Content>
 | 
			
		||||
                </Card>
 | 
			
		||||
              </Grid.Column>
 | 
			
		||||
            </Grid>
 | 
			
		||||
          </Segment>
 | 
			
		||||
        </> : <>
 | 
			
		||||
          {
 | 
			
		||||
            homePageContent.startsWith('https://') ? <iframe
 | 
			
		||||
    <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'>
 | 
			
		||||
            <Card.Content>
 | 
			
		||||
              <Card.Header className='header'>系统状况</Card.Header>
 | 
			
		||||
              <Grid columns={2} stackable>
 | 
			
		||||
                <Grid.Column>
 | 
			
		||||
                  <Card fluid className='chart-card'>
 | 
			
		||||
                    <Card.Content>
 | 
			
		||||
                      <Card.Header className='header'>系统信息</Card.Header>
 | 
			
		||||
                      <Card.Meta>系统信息总览</Card.Meta>
 | 
			
		||||
                      <Card.Description style={{ lineHeight: '1.6' }}>
 | 
			
		||||
                        <p>名称:{statusState?.status?.system_name}</p>
 | 
			
		||||
                        <p>版本:{statusState?.status?.version ? statusState?.status?.version : "unknown"}</p>
 | 
			
		||||
                        <p>
 | 
			
		||||
                          源码:
 | 
			
		||||
                          <a href='https://github.com/songquanpeng/one-api' target='_blank'>
 | 
			
		||||
                            https://github.com/songquanpeng/one-api
 | 
			
		||||
                          </a>
 | 
			
		||||
                        </p>
 | 
			
		||||
                        <p>启动时间:{getStartTimeString()}</p>
 | 
			
		||||
                      </Card.Description>
 | 
			
		||||
                    </Card.Content>
 | 
			
		||||
                  </Card>
 | 
			
		||||
                </Grid.Column>
 | 
			
		||||
                <Grid.Column>
 | 
			
		||||
                  <Card fluid className='chart-card'>
 | 
			
		||||
                    <Card.Content>
 | 
			
		||||
                      <Card.Header className='header'>系统配置</Card.Header>
 | 
			
		||||
                      <Card.Meta>系统配置总览</Card.Meta>
 | 
			
		||||
                      <Card.Description style={{ lineHeight: '1.6' }}>
 | 
			
		||||
                        <p>
 | 
			
		||||
                          邮箱验证:
 | 
			
		||||
                          {statusState?.status?.email_verification === true
 | 
			
		||||
                            ? '已启用'
 | 
			
		||||
                            : '未启用'}
 | 
			
		||||
                        </p>
 | 
			
		||||
                        <p>
 | 
			
		||||
                          GitHub 身份验证:
 | 
			
		||||
                          {statusState?.status?.github_oauth === true
 | 
			
		||||
                            ? '已启用'
 | 
			
		||||
                            : '未启用'}
 | 
			
		||||
                        </p>
 | 
			
		||||
                        <p>
 | 
			
		||||
                          微信身份验证:
 | 
			
		||||
                          {statusState?.status?.wechat_login === true
 | 
			
		||||
                            ? '已启用'
 | 
			
		||||
                            : '未启用'}
 | 
			
		||||
                        </p>
 | 
			
		||||
                        <p>
 | 
			
		||||
                          Turnstile 用户校验:
 | 
			
		||||
                          {statusState?.status?.turnstile_check === true
 | 
			
		||||
                            ? '已启用'
 | 
			
		||||
                            : '未启用'}
 | 
			
		||||
                        </p>
 | 
			
		||||
                      </Card.Description>
 | 
			
		||||
                    </Card.Content>
 | 
			
		||||
                  </Card>
 | 
			
		||||
                </Grid.Column>
 | 
			
		||||
              </Grid>
 | 
			
		||||
            </Card.Content>
 | 
			
		||||
          </Card>
 | 
			
		||||
        </>
 | 
			
		||||
      ) : (
 | 
			
		||||
        <>
 | 
			
		||||
          {homePageContent.startsWith('https://') ? (
 | 
			
		||||
            <iframe
 | 
			
		||||
              src={homePageContent}
 | 
			
		||||
              style={{ width: '100%', height: '100vh', border: 'none' }}
 | 
			
		||||
            /> : <div style={{ fontSize: 'larger' }} dangerouslySetInnerHTML={{ __html: homePageContent }}></div>
 | 
			
		||||
          }
 | 
			
		||||
            />
 | 
			
		||||
          ) : (
 | 
			
		||||
            <div
 | 
			
		||||
              style={{ fontSize: 'larger' }}
 | 
			
		||||
              dangerouslySetInnerHTML={{ __html: homePageContent }}
 | 
			
		||||
            ></div>
 | 
			
		||||
          )}
 | 
			
		||||
        </>
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
    </>
 | 
			
		||||
      )}
 | 
			
		||||
    </div>
 | 
			
		||||
  );
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,7 +1,13 @@
 | 
			
		||||
import React, { useEffect, useState } from 'react';
 | 
			
		||||
import { Button, Form, Header, Message, Segment } from 'semantic-ui-react';
 | 
			
		||||
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';
 | 
			
		||||
 | 
			
		||||
const EditToken = () => {
 | 
			
		||||
@@ -16,7 +22,7 @@ const EditToken = () => {
 | 
			
		||||
    expired_time: -1,
 | 
			
		||||
    unlimited_quota: false,
 | 
			
		||||
    models: [],
 | 
			
		||||
    subnet: "",
 | 
			
		||||
    subnet: '',
 | 
			
		||||
  };
 | 
			
		||||
  const [inputs, setInputs] = useState(originInputs);
 | 
			
		||||
  const { name, remain_quota, expired_time, unlimited_quota } = inputs;
 | 
			
		||||
@@ -79,7 +85,7 @@ const EditToken = () => {
 | 
			
		||||
        return {
 | 
			
		||||
          key: model,
 | 
			
		||||
          text: model,
 | 
			
		||||
          value: model
 | 
			
		||||
          value: model,
 | 
			
		||||
        };
 | 
			
		||||
      });
 | 
			
		||||
      setModelOptions(options);
 | 
			
		||||
@@ -103,7 +109,10 @@ const EditToken = () => {
 | 
			
		||||
    localInputs.models = localInputs.models.join(',');
 | 
			
		||||
    let res;
 | 
			
		||||
    if (isEdit) {
 | 
			
		||||
      res = await API.put(`/api/token/`, { ...localInputs, id: parseInt(tokenId) });
 | 
			
		||||
      res = await API.put(`/api/token/`, {
 | 
			
		||||
        ...localInputs,
 | 
			
		||||
        id: parseInt(tokenId),
 | 
			
		||||
      });
 | 
			
		||||
    } else {
 | 
			
		||||
      res = await API.post(`/api/token/`, localInputs);
 | 
			
		||||
    }
 | 
			
		||||
@@ -158,7 +167,9 @@ const EditToken = () => {
 | 
			
		||||
            <Form.Input
 | 
			
		||||
              label='IP 限制'
 | 
			
		||||
              name='subnet'
 | 
			
		||||
              placeholder={'请输入允许访问的网段,例如:192.168.0.0/24,请使用英文逗号分隔多个网段'}
 | 
			
		||||
              placeholder={
 | 
			
		||||
                '请输入允许访问的网段,例如:192.168.0.0/24,请使用英文逗号分隔多个网段'
 | 
			
		||||
              }
 | 
			
		||||
              onChange={handleInputChange}
 | 
			
		||||
              value={inputs.subnet}
 | 
			
		||||
              autoComplete='new-password'
 | 
			
		||||
@@ -168,7 +179,9 @@ const EditToken = () => {
 | 
			
		||||
            <Form.Input
 | 
			
		||||
              label='过期时间'
 | 
			
		||||
              name='expired_time'
 | 
			
		||||
              placeholder={'请输入过期时间,格式为 yyyy-MM-dd HH:mm:ss,-1 表示无限制'}
 | 
			
		||||
              placeholder={
 | 
			
		||||
                '请输入过期时间,格式为 yyyy-MM-dd HH:mm:ss,-1 表示无限制'
 | 
			
		||||
              }
 | 
			
		||||
              onChange={handleInputChange}
 | 
			
		||||
              value={expired_time}
 | 
			
		||||
              autoComplete='new-password'
 | 
			
		||||
@@ -176,23 +189,50 @@ const EditToken = () => {
 | 
			
		||||
            />
 | 
			
		||||
          </Form.Field>
 | 
			
		||||
          <div style={{ lineHeight: '40px' }}>
 | 
			
		||||
            <Button type={'button'} onClick={() => {
 | 
			
		||||
              setExpiredTime(0, 0, 0, 0);
 | 
			
		||||
            }}>永不过期</Button>
 | 
			
		||||
            <Button type={'button'} onClick={() => {
 | 
			
		||||
              setExpiredTime(1, 0, 0, 0);
 | 
			
		||||
            }}>一个月后过期</Button>
 | 
			
		||||
            <Button type={'button'} onClick={() => {
 | 
			
		||||
              setExpiredTime(0, 1, 0, 0);
 | 
			
		||||
            }}>一天后过期</Button>
 | 
			
		||||
            <Button type={'button'} onClick={() => {
 | 
			
		||||
              setExpiredTime(0, 0, 1, 0);
 | 
			
		||||
            }}>一小时后过期</Button>
 | 
			
		||||
            <Button type={'button'} onClick={() => {
 | 
			
		||||
              setExpiredTime(0, 0, 0, 1);
 | 
			
		||||
            }}>一分钟后过期</Button>
 | 
			
		||||
            <Button
 | 
			
		||||
              type={'button'}
 | 
			
		||||
              onClick={() => {
 | 
			
		||||
                setExpiredTime(0, 0, 0, 0);
 | 
			
		||||
              }}
 | 
			
		||||
            >
 | 
			
		||||
              永不过期
 | 
			
		||||
            </Button>
 | 
			
		||||
            <Button
 | 
			
		||||
              type={'button'}
 | 
			
		||||
              onClick={() => {
 | 
			
		||||
                setExpiredTime(1, 0, 0, 0);
 | 
			
		||||
              }}
 | 
			
		||||
            >
 | 
			
		||||
              一个月后过期
 | 
			
		||||
            </Button>
 | 
			
		||||
            <Button
 | 
			
		||||
              type={'button'}
 | 
			
		||||
              onClick={() => {
 | 
			
		||||
                setExpiredTime(0, 1, 0, 0);
 | 
			
		||||
              }}
 | 
			
		||||
            >
 | 
			
		||||
              一天后过期
 | 
			
		||||
            </Button>
 | 
			
		||||
            <Button
 | 
			
		||||
              type={'button'}
 | 
			
		||||
              onClick={() => {
 | 
			
		||||
                setExpiredTime(0, 0, 1, 0);
 | 
			
		||||
              }}
 | 
			
		||||
            >
 | 
			
		||||
              一小时后过期
 | 
			
		||||
            </Button>
 | 
			
		||||
            <Button
 | 
			
		||||
              type={'button'}
 | 
			
		||||
              onClick={() => {
 | 
			
		||||
                setExpiredTime(0, 0, 0, 1);
 | 
			
		||||
              }}
 | 
			
		||||
            >
 | 
			
		||||
              一分钟后过期
 | 
			
		||||
            </Button>
 | 
			
		||||
          </div>
 | 
			
		||||
          <Message>注意,令牌的额度仅用于限制令牌本身的最大额度使用量,实际的使用受到账户的剩余额度限制。</Message>
 | 
			
		||||
          <Message>
 | 
			
		||||
            注意,令牌的额度仅用于限制令牌本身的最大额度使用量,实际的使用受到账户的剩余额度限制。
 | 
			
		||||
          </Message>
 | 
			
		||||
          <Form.Field>
 | 
			
		||||
            <Form.Input
 | 
			
		||||
              label={`额度${renderQuotaWithPrompt(remain_quota)}`}
 | 
			
		||||
@@ -205,11 +245,20 @@ const EditToken = () => {
 | 
			
		||||
              disabled={unlimited_quota}
 | 
			
		||||
            />
 | 
			
		||||
          </Form.Field>
 | 
			
		||||
          <Button type={'button'} onClick={() => {
 | 
			
		||||
            setUnlimitedQuota();
 | 
			
		||||
          }}>{unlimited_quota ? '取消无限额度' : '设为无限额度'}</Button>
 | 
			
		||||
          <Button floated='right' positive onClick={submit}>提交</Button>
 | 
			
		||||
          <Button floated='right' onClick={handleCancel}>取消</Button>
 | 
			
		||||
          <Button
 | 
			
		||||
            type={'button'}
 | 
			
		||||
            onClick={() => {
 | 
			
		||||
              setUnlimitedQuota();
 | 
			
		||||
            }}
 | 
			
		||||
          >
 | 
			
		||||
            {unlimited_quota ? '取消无限额度' : '设为无限额度'}
 | 
			
		||||
          </Button>
 | 
			
		||||
          <Button floated='right' positive onClick={submit}>
 | 
			
		||||
            提交
 | 
			
		||||
          </Button>
 | 
			
		||||
          <Button floated='right' onClick={handleCancel}>
 | 
			
		||||
            取消
 | 
			
		||||
          </Button>
 | 
			
		||||
        </Form>
 | 
			
		||||
      </Segment>
 | 
			
		||||
    </>
 | 
			
		||||
 
 | 
			
		||||
@@ -6,7 +6,7 @@ const Token = () => (
 | 
			
		||||
  <>
 | 
			
		||||
    <Segment>
 | 
			
		||||
      <Header as='h3'>我的令牌</Header>
 | 
			
		||||
      <TokensTable/>
 | 
			
		||||
      <TokensTable />
 | 
			
		||||
    </Segment>
 | 
			
		||||
  </>
 | 
			
		||||
);
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user