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