Commit 3b0d4c84 by Apple\Apple

️refactor: Home Page and Footer

parent 99185dfa
...@@ -6,6 +6,7 @@ ...@@ -6,6 +6,7 @@
"dependencies": { "dependencies": {
"@douyinfe/semi-icons": "^2.63.1", "@douyinfe/semi-icons": "^2.63.1",
"@douyinfe/semi-ui": "^2.69.1", "@douyinfe/semi-ui": "^2.69.1",
"@lobehub/icons": "^2.0.0",
"@visactor/react-vchart": "~1.8.8", "@visactor/react-vchart": "~1.8.8",
"@visactor/vchart": "~1.8.8", "@visactor/vchart": "~1.8.8",
"@visactor/vchart-semi-theme": "~1.8.8", "@visactor/vchart-semi-theme": "~1.8.8",
......
import React, { useEffect, useState, useMemo } from 'react'; import React, { useEffect, useState, useMemo, useContext } from 'react';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
import { getFooterHTML } from '../helpers'; import { Typography } from '@douyinfe/semi-ui';
import { getFooterHTML, getLogo, getSystemName } from '../helpers';
import { StatusContext } from '../context/Status';
const FooterBar = () => { const FooterBar = () => {
const { t } = useTranslation(); const { t } = useTranslation();
const [footer, setFooter] = useState(getFooterHTML()); const [footer, setFooter] = useState(getFooterHTML());
const systemName = getSystemName();
const logo = getLogo();
const [statusState] = useContext(StatusContext);
const isDemoSiteMode = statusState?.status?.demo_site_enabled || false;
const loadFooter = () => { const loadFooter = () => {
let footer_html = localStorage.getItem('footer_html'); let footer_html = localStorage.getItem('footer_html');
...@@ -13,48 +19,93 @@ const FooterBar = () => { ...@@ -13,48 +19,93 @@ const FooterBar = () => {
} }
}; };
const defaultFooter = useMemo(() => ( const currentYear = new Date().getFullYear();
<div className='custom-footer'>
<a const customFooter = useMemo(() => (
href='https://github.com/Calcium-Ion/new-api' <footer className="relative bg-gray-900 dark:bg-[#1C1F23] mt-[60px] h-auto py-16 px-6 md:px-24 w-full flex flex-col items-center justify-between overflow-hidden">
target='_blank' <div className="absolute hidden md:block top-[204px] left-[-100px] w-[151px] h-[151px] rounded-full bg-[#FFD166]"></div>
rel='noreferrer' <div className="absolute md:hidden bottom-[20px] left-[-50px] w-[80px] h-[80px] rounded-full bg-[#FFD166] opacity-60"></div>
>
New API {import.meta.env.VITE_REACT_APP_VERSION}{' '} {isDemoSiteMode && (
</a> <div className="flex flex-col md:flex-row justify-between w-full max-w-[1110px] mb-10 gap-8">
{t('由')}{' '} <div className="flex-shrink-0">
<a href='https://github.com/Calcium-Ion' target='_blank' rel='noreferrer'> <img
Calcium-Ion src={logo}
</a>{' '} alt={systemName}
{t('开发,基于')}{' '} className="w-16 h-16 rounded-full bg-gray-800 p-1.5 object-contain"
<a />
href='https://github.com/songquanpeng/one-api' </div>
target='_blank'
rel='noreferrer' <div className="grid grid-cols-1 sm:grid-cols-2 md:grid-cols-4 gap-8 w-full">
> <div className="text-left">
One API <p className="!text-[#d9dbe1] font-semibold mb-5">{t('关于我们')}</p>
</a> <div className="flex flex-col gap-4">
</div> <a href="https://docs.newapi.pro/wiki/project-introduction/" target="_blank" rel="noopener noreferrer" className="!text-[#d9dbe1]">{t('关于项目')}</a>
), [t]); <a href="https://docs.newapi.pro/support/community-interaction/" target="_blank" rel="noopener noreferrer" className="!text-[#d9dbe1]">{t('联系我们')}</a>
<a href="https://docs.newapi.pro/wiki/features-introduction/" target="_blank" rel="noopener noreferrer" className="!text-[#d9dbe1]">{t('功能特性')}</a>
</div>
</div>
<div className="text-left">
<p className="!text-[#d9dbe1] font-semibold mb-5">{t('文档')}</p>
<div className="flex flex-col gap-4">
<a href="https://docs.newapi.pro/getting-started/" target="_blank" rel="noopener noreferrer" className="!text-[#d9dbe1]">{t('快速开始')}</a>
<a href="https://docs.newapi.pro/installation/" target="_blank" rel="noopener noreferrer" className="!text-[#d9dbe1]">{t('安装指南')}</a>
<a href="https://docs.newapi.pro/api/" target="_blank" rel="noopener noreferrer" className="!text-[#d9dbe1]">{t('API 文档')}</a>
</div>
</div>
<div className="text-left">
<p className="!text-[#d9dbe1] font-semibold mb-5">{t('相关项目')}</p>
<div className="flex flex-col gap-4">
<a href="https://github.com/songquanpeng/one-api" target="_blank" rel="noopener noreferrer" className="!text-[#d9dbe1]">One API</a>
<a href="https://github.com/novicezk/midjourney-proxy" target="_blank" rel="noopener noreferrer" className="!text-[#d9dbe1]">Midjourney-Proxy</a>
<a href="https://github.com/Deeptrain-Community/chatnio" target="_blank" rel="noopener noreferrer" className="!text-[#d9dbe1]">chatnio</a>
<a href="https://github.com/Calcium-Ion/neko-api-key-tool" target="_blank" rel="noopener noreferrer" className="!text-[#d9dbe1]">neko-api-key-tool</a>
</div>
</div>
<div className="text-left">
<p className="!text-[#d9dbe1] font-semibold mb-5">{t('基于New API的项目')}</p>
<div className="flex flex-col gap-4">
<a href="https://github.com/Calcium-Ion/new-api-horizon" target="_blank" rel="noopener noreferrer" className="!text-[#d9dbe1]">new-api-horizon</a>
<a href="https://github.com/VoAPI/VoAPI" target="_blank" rel="noopener noreferrer" className="!text-[#d9dbe1]">VoAPI</a>
</div>
</div>
</div>
</div>
)}
<div className="flex flex-col md:flex-row items-center justify-between w-full max-w-[1110px] gap-6">
<div className="flex flex-wrap items-center gap-2">
<Typography.Text className="text-sm !text-[#d9dbe1]">© {currentYear} {systemName}. {t('版权所有')}</Typography.Text>
</div>
{isDemoSiteMode && (
<div className="text-sm">
<span className="!text-[#d9dbe1]">{t('设计与开发由')} </span>
<span className="!text-[#01ffc3]">Douyin FE</span>
<span className="!text-[#d9dbe1]"> & </span>
<a href="https://github.com/QuantumNous" target="_blank" rel="noreferrer" className="!text-[#01ffc3] hover:!text-[#01ffc3]">QuantumNous</a>
</div>
)}
</div>
</footer>
), [logo, systemName, t, currentYear, isDemoSiteMode]);
useEffect(() => { useEffect(() => {
loadFooter(); loadFooter();
}, []); }, []);
return ( return (
<div <div className="w-full">
style={{
textAlign: 'center',
paddingBottom: '5px',
}}
>
{footer ? ( {footer ? (
<div <div
className='custom-footer' className="custom-footer"
dangerouslySetInnerHTML={{ __html: footer }} dangerouslySetInnerHTML={{ __html: footer }}
></div> ></div>
) : ( ) : (
defaultFooter customFooter
)} )}
</div> </div>
); );
......
...@@ -356,7 +356,7 @@ const HeaderBar = () => { ...@@ -356,7 +356,7 @@ const HeaderBar = () => {
{isLoading ? ( {isLoading ? (
<Skeleton.Image className="h-7 md:h-8 !rounded-full" style={{ width: 32, height: 32 }} /> <Skeleton.Image className="h-7 md:h-8 !rounded-full" style={{ width: 32, height: 32 }} />
) : ( ) : (
<img src={logo} alt="logo" className="h-7 md:h-8 transition-transform duration-300 ease-in-out group-hover:scale-105" /> <img src={logo} alt="logo" className="h-7 md:h-8 transition-transform duration-300 ease-in-out group-hover:scale-105 rounded-full" />
)} )}
<div className="hidden md:flex items-center gap-2"> <div className="hidden md:flex items-center gap-2">
<div className="flex items-center gap-2"> <div className="flex items-center gap-2">
...@@ -374,6 +374,7 @@ const HeaderBar = () => { ...@@ -374,6 +374,7 @@ const HeaderBar = () => {
color={isSelfUseMode ? 'purple' : 'blue'} color={isSelfUseMode ? 'purple' : 'blue'}
className="text-xs px-1.5 py-0.5 rounded whitespace-nowrap shadow-sm" className="text-xs px-1.5 py-0.5 rounded whitespace-nowrap shadow-sm"
size="small" size="small"
shape='circle'
> >
{isSelfUseMode ? t('自用模式') : t('演示站点')} {isSelfUseMode ? t('自用模式') : t('演示站点')}
</Tag> </Tag>
...@@ -387,6 +388,7 @@ const HeaderBar = () => { ...@@ -387,6 +388,7 @@ const HeaderBar = () => {
color={isSelfUseMode ? 'purple' : 'blue'} color={isSelfUseMode ? 'purple' : 'blue'}
className="ml-2 text-xs px-1 py-0.5 rounded whitespace-nowrap shadow-sm" className="ml-2 text-xs px-1 py-0.5 rounded whitespace-nowrap shadow-sm"
size="small" size="small"
shape='circle'
> >
{isSelfUseMode ? t('自用模式') : t('演示站点')} {isSelfUseMode ? t('自用模式') : t('演示站点')}
</Tag> </Tag>
......
import React from 'react'; import React from 'react';
import { Spin } from '@douyinfe/semi-ui'; import { Spin } from '@douyinfe/semi-ui';
const Loading = ({ prompt: name = 'page' }) => { const Loading = ({ prompt: name = '', size = 'large' }) => {
return ( return (
<Spin style={{ height: 100 }} spinning={true}> <div className="fixed inset-0 w-screen h-screen flex items-center justify-center bg-white/80 z-[1000]">
加载{name}... <div className="flex flex-col items-center">
</Spin> <Spin
size={size}
spinning={true}
tip={null}
/>
<span className="whitespace-nowrap mt-2 text-center" style={{ color: 'var(--semi-color-primary)' }}>
{name ? `加载${name}中...` : '加载中...'}
</span>
</div>
</div>
); );
}; };
......
...@@ -1373,5 +1373,19 @@ ...@@ -1373,5 +1373,19 @@
"不需要设置模型价格,系统将弱化用量计算,您可专注于使用模型。": "No need to set the model price, the system will weaken the usage calculation, you can focus on using the model.", "不需要设置模型价格,系统将弱化用量计算,您可专注于使用模型。": "No need to set the model price, the system will weaken the usage calculation, you can focus on using the model.",
"适用于展示系统功能的场景。": "Suitable for scenarios where the system functions are displayed.", "适用于展示系统功能的场景。": "Suitable for scenarios where the system functions are displayed.",
"可在初始化后修改": "Can be modified after initialization", "可在初始化后修改": "Can be modified after initialization",
"初始化系统": "Initialize system" "初始化系统": "Initialize system",
"支持众多的大模型供应商": "Supporting various LLM providers",
"新一代大模型网关与AI资产管理系统,一键接入主流大模型,轻松管理您的AI资产": "Next-generation LLM gateway and AI asset management system, one-click integration with mainstream models, easily manage your AI assets",
"开始使用": "Get Started",
"关于我们": "About Us",
"关于项目": "About Project",
"联系我们": "Contact Us",
"功能特性": "Features",
"快速开始": "Quick Start",
"安装指南": "Installation Guide",
"API 文档": "API Documentation",
"相关项目": "Related Projects",
"基于New API的项目": "Projects Based on New API",
"版权所有": "All rights reserved",
"设计与开发由": "Designed & Developed with love by"
} }
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment