feat: able to customize system name & logo now
This commit is contained in:
parent
2cdc718fde
commit
926951ee03
@ -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 {
|
||||
|
Loading…
Reference in New Issue
Block a user