mirror of
				https://github.com/songquanpeng/one-api.git
				synced 2025-11-04 15:53:42 +08:00 
			
		
		
		
	feat: able to customize system name & logo now
This commit is contained in:
		@@ -11,6 +11,7 @@ var Version = "v0.0.0"            // this hard coding will be replaced automatic
 | 
			
		||||
var SystemName = "One API"
 | 
			
		||||
var ServerAddress = "http://localhost:3000"
 | 
			
		||||
var Footer = ""
 | 
			
		||||
var Logo = ""
 | 
			
		||||
var TopUpLink = ""
 | 
			
		||||
 | 
			
		||||
var UsingSQLite = false
 | 
			
		||||
 
 | 
			
		||||
@@ -20,6 +20,7 @@ func GetStatus(c *gin.Context) {
 | 
			
		||||
			"github_oauth":       common.GitHubOAuthEnabled,
 | 
			
		||||
			"github_client_id":   common.GitHubClientId,
 | 
			
		||||
			"system_name":        common.SystemName,
 | 
			
		||||
			"logo":               common.Logo,
 | 
			
		||||
			"footer_html":        common.Footer,
 | 
			
		||||
			"wechat_qrcode":      common.WeChatAccountQRCodeImageURL,
 | 
			
		||||
			"wechat_login":       common.WeChatAuthEnabled,
 | 
			
		||||
 
 | 
			
		||||
@@ -41,6 +41,8 @@ func InitOptionMap() {
 | 
			
		||||
	common.OptionMap["About"] = ""
 | 
			
		||||
	common.OptionMap["HomePageContent"] = ""
 | 
			
		||||
	common.OptionMap["Footer"] = common.Footer
 | 
			
		||||
	common.OptionMap["SystemName"] = common.SystemName
 | 
			
		||||
	common.OptionMap["Logo"] = common.Logo
 | 
			
		||||
	common.OptionMap["ServerAddress"] = ""
 | 
			
		||||
	common.OptionMap["GitHubClientId"] = ""
 | 
			
		||||
	common.OptionMap["GitHubClientSecret"] = ""
 | 
			
		||||
@@ -134,6 +136,10 @@ func updateOptionMap(key string, value string) (err error) {
 | 
			
		||||
		common.GitHubClientSecret = value
 | 
			
		||||
	case "Footer":
 | 
			
		||||
		common.Footer = value
 | 
			
		||||
	case "SystemName":
 | 
			
		||||
		common.SystemName = value
 | 
			
		||||
	case "Logo":
 | 
			
		||||
		common.Logo = value
 | 
			
		||||
	case "WeChatServerAddress":
 | 
			
		||||
		common.WeChatServerAddress = value
 | 
			
		||||
	case "WeChatServerToken":
 | 
			
		||||
 
 | 
			
		||||
@@ -42,6 +42,8 @@ function App() {
 | 
			
		||||
    if (success) {
 | 
			
		||||
      localStorage.setItem('status', JSON.stringify(data));
 | 
			
		||||
      statusDispatch({ type: 'set', payload: data });
 | 
			
		||||
      localStorage.setItem('system_name', data.system_name);
 | 
			
		||||
      localStorage.setItem('logo', data.logo);
 | 
			
		||||
      localStorage.setItem('footer_html', data.footer_html);
 | 
			
		||||
      if (
 | 
			
		||||
        data.version !== process.env.REACT_APP_VERSION &&
 | 
			
		||||
 
 | 
			
		||||
@@ -1,40 +1,37 @@
 | 
			
		||||
import React, { useEffect, useState } from 'react';
 | 
			
		||||
import React from 'react';
 | 
			
		||||
 | 
			
		||||
import { Container, Segment } from 'semantic-ui-react';
 | 
			
		||||
import { getFooterHTML, getSystemName } from '../helpers';
 | 
			
		||||
 | 
			
		||||
const Footer = () => {
 | 
			
		||||
  const [Footer, setFooter] = useState('');
 | 
			
		||||
  useEffect(() => {
 | 
			
		||||
    let savedFooter = localStorage.getItem('footer_html');
 | 
			
		||||
    if (!savedFooter) savedFooter = '';
 | 
			
		||||
    setFooter(savedFooter);
 | 
			
		||||
  });
 | 
			
		||||
  const systemName = getSystemName();
 | 
			
		||||
  const footer = getFooterHTML();
 | 
			
		||||
 | 
			
		||||
  return (
 | 
			
		||||
    <Segment vertical>
 | 
			
		||||
      <Container textAlign="center">
 | 
			
		||||
        {Footer === '' ? (
 | 
			
		||||
          <div className="custom-footer">
 | 
			
		||||
      <Container textAlign='center'>
 | 
			
		||||
        {footer ? (
 | 
			
		||||
          <div
 | 
			
		||||
            className='custom-footer'
 | 
			
		||||
            dangerouslySetInnerHTML={{ __html: footer }}
 | 
			
		||||
          ></div>
 | 
			
		||||
        ) : (
 | 
			
		||||
          <div className='custom-footer'>
 | 
			
		||||
            <a
 | 
			
		||||
              href="https://github.com/songquanpeng/one-api"
 | 
			
		||||
              target="_blank"
 | 
			
		||||
              href='https://github.com/songquanpeng/one-api'
 | 
			
		||||
              target='_blank'
 | 
			
		||||
            >
 | 
			
		||||
              One API {process.env.REACT_APP_VERSION}{' '}
 | 
			
		||||
              {systemName} {process.env.REACT_APP_VERSION}{' '}
 | 
			
		||||
            </a>
 | 
			
		||||
            由{' '}
 | 
			
		||||
            <a href="https://github.com/songquanpeng" target="_blank">
 | 
			
		||||
            <a href='https://github.com/songquanpeng' target='_blank'>
 | 
			
		||||
              JustSong
 | 
			
		||||
            </a>{' '}
 | 
			
		||||
            构建,源代码遵循{' '}
 | 
			
		||||
            <a href="https://opensource.org/licenses/mit-license.php">
 | 
			
		||||
            <a href='https://opensource.org/licenses/mit-license.php'>
 | 
			
		||||
              MIT 协议
 | 
			
		||||
            </a>
 | 
			
		||||
          </div>
 | 
			
		||||
        ) : (
 | 
			
		||||
          <div
 | 
			
		||||
            className="custom-footer"
 | 
			
		||||
            dangerouslySetInnerHTML={{ __html: Footer }}
 | 
			
		||||
          ></div>
 | 
			
		||||
        )}
 | 
			
		||||
      </Container>
 | 
			
		||||
    </Segment>
 | 
			
		||||
 
 | 
			
		||||
@@ -3,7 +3,7 @@ import { Link, useNavigate } from 'react-router-dom';
 | 
			
		||||
import { UserContext } from '../context/User';
 | 
			
		||||
 | 
			
		||||
import { Button, Container, Dropdown, Icon, Menu, Segment } from 'semantic-ui-react';
 | 
			
		||||
import { API, isAdmin, isMobile, showSuccess } from '../helpers';
 | 
			
		||||
import { API, getLogo, getSystemName, isAdmin, isMobile, showSuccess } from '../helpers';
 | 
			
		||||
import '../index.css';
 | 
			
		||||
 | 
			
		||||
// Header Buttons
 | 
			
		||||
@@ -53,6 +53,8 @@ const Header = () => {
 | 
			
		||||
  let navigate = useNavigate();
 | 
			
		||||
 | 
			
		||||
  const [showSidebar, setShowSidebar] = useState(false);
 | 
			
		||||
  const systemName = getSystemName();
 | 
			
		||||
  const logo = getLogo();
 | 
			
		||||
 | 
			
		||||
  async function logout() {
 | 
			
		||||
    setShowSidebar(false);
 | 
			
		||||
@@ -111,12 +113,12 @@ const Header = () => {
 | 
			
		||||
          <Container>
 | 
			
		||||
            <Menu.Item as={Link} to='/'>
 | 
			
		||||
              <img
 | 
			
		||||
                src='/logo.png'
 | 
			
		||||
                src={logo}
 | 
			
		||||
                alt='logo'
 | 
			
		||||
                style={{ marginRight: '0.75em' }}
 | 
			
		||||
              />
 | 
			
		||||
              <div style={{ fontSize: '20px' }}>
 | 
			
		||||
                <b>One API</b>
 | 
			
		||||
                <b>{systemName}</b>
 | 
			
		||||
              </div>
 | 
			
		||||
            </Menu.Item>
 | 
			
		||||
            <Menu.Menu position='right'>
 | 
			
		||||
@@ -168,9 +170,9 @@ const Header = () => {
 | 
			
		||||
      <Menu borderless style={{ borderTop: 'none' }}>
 | 
			
		||||
        <Container>
 | 
			
		||||
          <Menu.Item as={Link} to='/' className={'hide-on-mobile'}>
 | 
			
		||||
            <img src='/logo.png' alt='logo' style={{ marginRight: '0.75em' }} />
 | 
			
		||||
            <img src={logo} alt='logo' style={{ marginRight: '0.75em' }} />
 | 
			
		||||
            <div style={{ fontSize: '20px' }}>
 | 
			
		||||
              <b>One API</b>
 | 
			
		||||
              <b>{systemName}</b>
 | 
			
		||||
            </div>
 | 
			
		||||
          </Menu.Item>
 | 
			
		||||
          {renderButtons(false)}
 | 
			
		||||
 
 | 
			
		||||
@@ -12,7 +12,7 @@ import {
 | 
			
		||||
} from 'semantic-ui-react';
 | 
			
		||||
import { Link, useNavigate, useSearchParams } from 'react-router-dom';
 | 
			
		||||
import { UserContext } from '../context/User';
 | 
			
		||||
import { API, showError, showSuccess } from '../helpers';
 | 
			
		||||
import { API, getLogo, showError, showSuccess } from '../helpers';
 | 
			
		||||
 | 
			
		||||
const LoginForm = () => {
 | 
			
		||||
  const [inputs, setInputs] = useState({
 | 
			
		||||
@@ -27,6 +27,7 @@ const LoginForm = () => {
 | 
			
		||||
  let navigate = useNavigate();
 | 
			
		||||
 | 
			
		||||
  const [status, setStatus] = useState({});
 | 
			
		||||
  const logo = getLogo();
 | 
			
		||||
 | 
			
		||||
  useEffect(() => {
 | 
			
		||||
    if (searchParams.get("expired")) {
 | 
			
		||||
@@ -95,7 +96,7 @@ const LoginForm = () => {
 | 
			
		||||
    <Grid textAlign="center" style={{ marginTop: '48px' }}>
 | 
			
		||||
      <Grid.Column style={{ maxWidth: 450 }}>
 | 
			
		||||
        <Header as="h2" color="" textAlign="center">
 | 
			
		||||
          <Image src="/logo.png" /> 用户登录
 | 
			
		||||
          <Image src={logo} /> 用户登录
 | 
			
		||||
        </Header>
 | 
			
		||||
        <Form size="large">
 | 
			
		||||
          <Segment>
 | 
			
		||||
 
 | 
			
		||||
@@ -8,6 +8,8 @@ const OtherSetting = () => {
 | 
			
		||||
    Footer: '',
 | 
			
		||||
    Notice: '',
 | 
			
		||||
    About: '',
 | 
			
		||||
    SystemName: '',
 | 
			
		||||
    Logo: '',
 | 
			
		||||
    HomePageContent: '',
 | 
			
		||||
  });
 | 
			
		||||
  let originInputs = {};
 | 
			
		||||
@@ -66,6 +68,14 @@ const OtherSetting = () => {
 | 
			
		||||
    await updateOption('Footer', inputs.Footer);
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  const submitSystemName = async () => {
 | 
			
		||||
    await updateOption('SystemName', inputs.SystemName);
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  const submitLogo = async () => {
 | 
			
		||||
    await updateOption('Logo', inputs.Logo);
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  const submitAbout = async () => {
 | 
			
		||||
    await updateOption('About', inputs.About);
 | 
			
		||||
  };
 | 
			
		||||
@@ -114,6 +124,27 @@ const OtherSetting = () => {
 | 
			
		||||
          <Form.Button onClick={submitNotice}>保存公告</Form.Button>
 | 
			
		||||
          <Divider />
 | 
			
		||||
          <Header as='h3'>个性化设置</Header>
 | 
			
		||||
          <Form.Group widths='equal'>
 | 
			
		||||
            <Form.Input
 | 
			
		||||
              label='系统名称'
 | 
			
		||||
              placeholder='在此输入系统名称'
 | 
			
		||||
              value={inputs.SystemName}
 | 
			
		||||
              name='SystemName'
 | 
			
		||||
              onChange={handleInputChange}
 | 
			
		||||
            />
 | 
			
		||||
          </Form.Group>
 | 
			
		||||
          <Form.Button onClick={submitSystemName}>设置系统名称</Form.Button>
 | 
			
		||||
          <Form.Group widths='equal'>
 | 
			
		||||
            <Form.Input
 | 
			
		||||
              label='Logo 图片地址'
 | 
			
		||||
              placeholder='在此输入 Logo 图片地址'
 | 
			
		||||
              value={inputs.Logo}
 | 
			
		||||
              name='Logo'
 | 
			
		||||
              type='url'
 | 
			
		||||
              onChange={handleInputChange}
 | 
			
		||||
            />
 | 
			
		||||
          </Form.Group>
 | 
			
		||||
          <Form.Button onClick={submitLogo}>设置 Logo</Form.Button>
 | 
			
		||||
          <Form.Group widths='equal'>
 | 
			
		||||
            <Form.TextArea
 | 
			
		||||
              label='首页内容'
 | 
			
		||||
 
 | 
			
		||||
@@ -9,7 +9,7 @@ import {
 | 
			
		||||
  Segment,
 | 
			
		||||
} from 'semantic-ui-react';
 | 
			
		||||
import { Link, useNavigate } from 'react-router-dom';
 | 
			
		||||
import { API, showError, showInfo, showSuccess } from '../helpers';
 | 
			
		||||
import { API, getLogo, showError, showInfo, showSuccess } from '../helpers';
 | 
			
		||||
import Turnstile from 'react-turnstile';
 | 
			
		||||
 | 
			
		||||
const RegisterForm = () => {
 | 
			
		||||
@@ -26,6 +26,7 @@ const RegisterForm = () => {
 | 
			
		||||
  const [turnstileSiteKey, setTurnstileSiteKey] = useState('');
 | 
			
		||||
  const [turnstileToken, setTurnstileToken] = useState('');
 | 
			
		||||
  const [loading, setLoading] = useState(false);
 | 
			
		||||
  const logo = getLogo();
 | 
			
		||||
 | 
			
		||||
  useEffect(() => {
 | 
			
		||||
    let status = localStorage.getItem('status');
 | 
			
		||||
@@ -100,7 +101,7 @@ const RegisterForm = () => {
 | 
			
		||||
    <Grid textAlign='center' style={{ marginTop: '48px' }}>
 | 
			
		||||
      <Grid.Column style={{ maxWidth: 450 }}>
 | 
			
		||||
        <Header as='h2' color='' textAlign='center'>
 | 
			
		||||
          <Image src='/logo.png' /> 新用户注册
 | 
			
		||||
          <Image src={logo} /> 新用户注册
 | 
			
		||||
        </Header>
 | 
			
		||||
        <Form size='large'>
 | 
			
		||||
          <Segment>
 | 
			
		||||
 
 | 
			
		||||
@@ -15,6 +15,22 @@ export function isRoot() {
 | 
			
		||||
  return user.role >= 100;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export function getSystemName() {
 | 
			
		||||
  let system_name = localStorage.getItem('system_name');
 | 
			
		||||
  if (!system_name) return 'One API';
 | 
			
		||||
  return system_name;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export function getLogo() {
 | 
			
		||||
  let logo = localStorage.getItem('logo');
 | 
			
		||||
  if (!logo) return '/logo.png';
 | 
			
		||||
  return logo
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export function getFooterHTML() {
 | 
			
		||||
  return localStorage.getItem('footer_html');
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export async function copy(text) {
 | 
			
		||||
  let okay = true;
 | 
			
		||||
  try {
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user