mirror of
				https://github.com/linux-do/new-api.git
				synced 2025-11-04 13:23:42 +08:00 
			
		
		
		
	feat: 优化界面显示
This commit is contained in:
		
							
								
								
									
										381
									
								
								web/src/App.js
									
									
									
									
									
								
							
							
						
						
									
										381
									
								
								web/src/App.js
									
									
									
									
									
								
							@@ -24,6 +24,7 @@ import { Layout } from '@douyinfe/semi-ui';
 | 
			
		||||
import Midjourney from './pages/Midjourney';
 | 
			
		||||
import Pricing from './pages/Pricing/index.js';
 | 
			
		||||
import Task from "./pages/Task/index.js";
 | 
			
		||||
import FooterBar from './components/Footer.js';
 | 
			
		||||
// import Detail from './pages/Detail';
 | 
			
		||||
 | 
			
		||||
const Home = lazy(() => import('./pages/Home'));
 | 
			
		||||
@@ -58,207 +59,205 @@ function App() {
 | 
			
		||||
  }, []);
 | 
			
		||||
 | 
			
		||||
  return (
 | 
			
		||||
    <Layout>
 | 
			
		||||
      <Layout.Content>
 | 
			
		||||
        <Routes>
 | 
			
		||||
          <Route
 | 
			
		||||
            path='/'
 | 
			
		||||
            element={
 | 
			
		||||
    <>
 | 
			
		||||
      <Routes>
 | 
			
		||||
        <Route
 | 
			
		||||
          path='/'
 | 
			
		||||
          element={
 | 
			
		||||
            <Suspense fallback={<Loading></Loading>}>
 | 
			
		||||
              <Home />
 | 
			
		||||
            </Suspense>
 | 
			
		||||
          }
 | 
			
		||||
        />
 | 
			
		||||
        <Route
 | 
			
		||||
          path='/channel'
 | 
			
		||||
          element={
 | 
			
		||||
            <PrivateRoute>
 | 
			
		||||
              <Channel />
 | 
			
		||||
            </PrivateRoute>
 | 
			
		||||
          }
 | 
			
		||||
        />
 | 
			
		||||
        <Route
 | 
			
		||||
          path='/channel/edit/:id'
 | 
			
		||||
          element={
 | 
			
		||||
            <Suspense fallback={<Loading></Loading>}>
 | 
			
		||||
              <EditChannel />
 | 
			
		||||
            </Suspense>
 | 
			
		||||
          }
 | 
			
		||||
        />
 | 
			
		||||
        <Route
 | 
			
		||||
          path='/channel/add'
 | 
			
		||||
          element={
 | 
			
		||||
            <Suspense fallback={<Loading></Loading>}>
 | 
			
		||||
              <EditChannel />
 | 
			
		||||
            </Suspense>
 | 
			
		||||
          }
 | 
			
		||||
        />
 | 
			
		||||
        <Route
 | 
			
		||||
          path='/token'
 | 
			
		||||
          element={
 | 
			
		||||
            <PrivateRoute>
 | 
			
		||||
              <Token />
 | 
			
		||||
            </PrivateRoute>
 | 
			
		||||
          }
 | 
			
		||||
        />
 | 
			
		||||
        <Route
 | 
			
		||||
          path='/redemption'
 | 
			
		||||
          element={
 | 
			
		||||
            <PrivateRoute>
 | 
			
		||||
              <Redemption />
 | 
			
		||||
            </PrivateRoute>
 | 
			
		||||
          }
 | 
			
		||||
        />
 | 
			
		||||
        <Route
 | 
			
		||||
          path='/user'
 | 
			
		||||
          element={
 | 
			
		||||
            <PrivateRoute>
 | 
			
		||||
              <User />
 | 
			
		||||
            </PrivateRoute>
 | 
			
		||||
          }
 | 
			
		||||
        />
 | 
			
		||||
        <Route
 | 
			
		||||
          path='/user/edit/:id'
 | 
			
		||||
          element={
 | 
			
		||||
            <Suspense fallback={<Loading></Loading>}>
 | 
			
		||||
              <EditUser />
 | 
			
		||||
            </Suspense>
 | 
			
		||||
          }
 | 
			
		||||
        />
 | 
			
		||||
        <Route
 | 
			
		||||
          path='/user/edit'
 | 
			
		||||
          element={
 | 
			
		||||
            <Suspense fallback={<Loading></Loading>}>
 | 
			
		||||
              <EditUser />
 | 
			
		||||
            </Suspense>
 | 
			
		||||
          }
 | 
			
		||||
        />
 | 
			
		||||
        <Route
 | 
			
		||||
          path='/user/reset'
 | 
			
		||||
          element={
 | 
			
		||||
            <Suspense fallback={<Loading></Loading>}>
 | 
			
		||||
              <PasswordResetConfirm />
 | 
			
		||||
            </Suspense>
 | 
			
		||||
          }
 | 
			
		||||
        />
 | 
			
		||||
        <Route
 | 
			
		||||
          path='/login'
 | 
			
		||||
          element={
 | 
			
		||||
            <Suspense fallback={<Loading></Loading>}>
 | 
			
		||||
              <LoginForm />
 | 
			
		||||
            </Suspense>
 | 
			
		||||
          }
 | 
			
		||||
        />
 | 
			
		||||
        <Route
 | 
			
		||||
          path='/register'
 | 
			
		||||
          element={
 | 
			
		||||
            <Suspense fallback={<Loading></Loading>}>
 | 
			
		||||
              <RegisterForm />
 | 
			
		||||
            </Suspense>
 | 
			
		||||
          }
 | 
			
		||||
        />
 | 
			
		||||
        <Route
 | 
			
		||||
          path='/reset'
 | 
			
		||||
          element={
 | 
			
		||||
            <Suspense fallback={<Loading></Loading>}>
 | 
			
		||||
              <PasswordResetForm />
 | 
			
		||||
            </Suspense>
 | 
			
		||||
          }
 | 
			
		||||
        />
 | 
			
		||||
        <Route
 | 
			
		||||
          path='/oauth/github'
 | 
			
		||||
          element={
 | 
			
		||||
            <Suspense fallback={<Loading></Loading>}>
 | 
			
		||||
              <GitHubOAuth />
 | 
			
		||||
            </Suspense>
 | 
			
		||||
          }
 | 
			
		||||
        />
 | 
			
		||||
        <Route
 | 
			
		||||
          path='/setting'
 | 
			
		||||
          element={
 | 
			
		||||
            <PrivateRoute>
 | 
			
		||||
              <Suspense fallback={<Loading></Loading>}>
 | 
			
		||||
                <Home />
 | 
			
		||||
                <Setting />
 | 
			
		||||
              </Suspense>
 | 
			
		||||
            }
 | 
			
		||||
          />
 | 
			
		||||
          <Route
 | 
			
		||||
            path='/channel'
 | 
			
		||||
            element={
 | 
			
		||||
              <PrivateRoute>
 | 
			
		||||
                <Channel />
 | 
			
		||||
              </PrivateRoute>
 | 
			
		||||
            }
 | 
			
		||||
          />
 | 
			
		||||
          <Route
 | 
			
		||||
            path='/channel/edit/:id'
 | 
			
		||||
            element={
 | 
			
		||||
            </PrivateRoute>
 | 
			
		||||
          }
 | 
			
		||||
        />
 | 
			
		||||
        <Route
 | 
			
		||||
          path='/topup'
 | 
			
		||||
          element={
 | 
			
		||||
            <PrivateRoute>
 | 
			
		||||
              <Suspense fallback={<Loading></Loading>}>
 | 
			
		||||
                <EditChannel />
 | 
			
		||||
                <TopUp />
 | 
			
		||||
              </Suspense>
 | 
			
		||||
            }
 | 
			
		||||
          />
 | 
			
		||||
          <Route
 | 
			
		||||
            path='/channel/add'
 | 
			
		||||
            element={
 | 
			
		||||
            </PrivateRoute>
 | 
			
		||||
          }
 | 
			
		||||
        />
 | 
			
		||||
        <Route
 | 
			
		||||
          path='/log'
 | 
			
		||||
          element={
 | 
			
		||||
            <PrivateRoute>
 | 
			
		||||
              <Log />
 | 
			
		||||
            </PrivateRoute>
 | 
			
		||||
          }
 | 
			
		||||
        />
 | 
			
		||||
        <Route
 | 
			
		||||
          path='/detail'
 | 
			
		||||
          element={
 | 
			
		||||
            <PrivateRoute>
 | 
			
		||||
              <Suspense fallback={<Loading></Loading>}>
 | 
			
		||||
                <EditChannel />
 | 
			
		||||
                <Detail />
 | 
			
		||||
              </Suspense>
 | 
			
		||||
            }
 | 
			
		||||
          />
 | 
			
		||||
          <Route
 | 
			
		||||
            path='/token'
 | 
			
		||||
            element={
 | 
			
		||||
              <PrivateRoute>
 | 
			
		||||
                <Token />
 | 
			
		||||
              </PrivateRoute>
 | 
			
		||||
            }
 | 
			
		||||
          />
 | 
			
		||||
          <Route
 | 
			
		||||
            path='/redemption'
 | 
			
		||||
            element={
 | 
			
		||||
              <PrivateRoute>
 | 
			
		||||
                <Redemption />
 | 
			
		||||
              </PrivateRoute>
 | 
			
		||||
            }
 | 
			
		||||
          />
 | 
			
		||||
          <Route
 | 
			
		||||
            path='/user'
 | 
			
		||||
            element={
 | 
			
		||||
              <PrivateRoute>
 | 
			
		||||
                <User />
 | 
			
		||||
              </PrivateRoute>
 | 
			
		||||
            }
 | 
			
		||||
          />
 | 
			
		||||
          <Route
 | 
			
		||||
            path='/user/edit/:id'
 | 
			
		||||
            element={
 | 
			
		||||
            </PrivateRoute>
 | 
			
		||||
          }
 | 
			
		||||
        />
 | 
			
		||||
        <Route
 | 
			
		||||
          path='/midjourney'
 | 
			
		||||
          element={
 | 
			
		||||
            <PrivateRoute>
 | 
			
		||||
              <Suspense fallback={<Loading></Loading>}>
 | 
			
		||||
                <EditUser />
 | 
			
		||||
                <Midjourney />
 | 
			
		||||
              </Suspense>
 | 
			
		||||
            }
 | 
			
		||||
          />
 | 
			
		||||
          <Route
 | 
			
		||||
            path='/user/edit'
 | 
			
		||||
            element={
 | 
			
		||||
            </PrivateRoute>
 | 
			
		||||
          }
 | 
			
		||||
        />
 | 
			
		||||
        <Route
 | 
			
		||||
          path='/task'
 | 
			
		||||
          element={
 | 
			
		||||
            <PrivateRoute>
 | 
			
		||||
              <Suspense fallback={<Loading></Loading>}>
 | 
			
		||||
                <EditUser />
 | 
			
		||||
                <Task />
 | 
			
		||||
              </Suspense>
 | 
			
		||||
            }
 | 
			
		||||
          />
 | 
			
		||||
          <Route
 | 
			
		||||
            path='/user/reset'
 | 
			
		||||
            element={
 | 
			
		||||
              <Suspense fallback={<Loading></Loading>}>
 | 
			
		||||
                <PasswordResetConfirm />
 | 
			
		||||
              </Suspense>
 | 
			
		||||
            }
 | 
			
		||||
          />
 | 
			
		||||
          <Route
 | 
			
		||||
            path='/login'
 | 
			
		||||
            element={
 | 
			
		||||
              <Suspense fallback={<Loading></Loading>}>
 | 
			
		||||
                <LoginForm />
 | 
			
		||||
              </Suspense>
 | 
			
		||||
            }
 | 
			
		||||
          />
 | 
			
		||||
          <Route
 | 
			
		||||
            path='/register'
 | 
			
		||||
            element={
 | 
			
		||||
              <Suspense fallback={<Loading></Loading>}>
 | 
			
		||||
                <RegisterForm />
 | 
			
		||||
              </Suspense>
 | 
			
		||||
            }
 | 
			
		||||
          />
 | 
			
		||||
          <Route
 | 
			
		||||
            path='/reset'
 | 
			
		||||
            element={
 | 
			
		||||
              <Suspense fallback={<Loading></Loading>}>
 | 
			
		||||
                <PasswordResetForm />
 | 
			
		||||
              </Suspense>
 | 
			
		||||
            }
 | 
			
		||||
          />
 | 
			
		||||
          <Route
 | 
			
		||||
            path='/oauth/github'
 | 
			
		||||
            element={
 | 
			
		||||
              <Suspense fallback={<Loading></Loading>}>
 | 
			
		||||
                <GitHubOAuth />
 | 
			
		||||
              </Suspense>
 | 
			
		||||
            }
 | 
			
		||||
          />
 | 
			
		||||
          <Route
 | 
			
		||||
            path='/setting'
 | 
			
		||||
            element={
 | 
			
		||||
              <PrivateRoute>
 | 
			
		||||
                <Suspense fallback={<Loading></Loading>}>
 | 
			
		||||
                  <Setting />
 | 
			
		||||
                </Suspense>
 | 
			
		||||
              </PrivateRoute>
 | 
			
		||||
            }
 | 
			
		||||
          />
 | 
			
		||||
          <Route
 | 
			
		||||
            path='/topup'
 | 
			
		||||
            element={
 | 
			
		||||
              <PrivateRoute>
 | 
			
		||||
                <Suspense fallback={<Loading></Loading>}>
 | 
			
		||||
                  <TopUp />
 | 
			
		||||
                </Suspense>
 | 
			
		||||
              </PrivateRoute>
 | 
			
		||||
            }
 | 
			
		||||
          />
 | 
			
		||||
          <Route
 | 
			
		||||
            path='/log'
 | 
			
		||||
            element={
 | 
			
		||||
              <PrivateRoute>
 | 
			
		||||
                <Log />
 | 
			
		||||
              </PrivateRoute>
 | 
			
		||||
            }
 | 
			
		||||
          />
 | 
			
		||||
          <Route
 | 
			
		||||
            path='/detail'
 | 
			
		||||
            element={
 | 
			
		||||
              <PrivateRoute>
 | 
			
		||||
                <Suspense fallback={<Loading></Loading>}>
 | 
			
		||||
                  <Detail />
 | 
			
		||||
                </Suspense>
 | 
			
		||||
              </PrivateRoute>
 | 
			
		||||
            }
 | 
			
		||||
          />
 | 
			
		||||
          <Route
 | 
			
		||||
            path='/midjourney'
 | 
			
		||||
            element={
 | 
			
		||||
              <PrivateRoute>
 | 
			
		||||
                <Suspense fallback={<Loading></Loading>}>
 | 
			
		||||
                  <Midjourney />
 | 
			
		||||
                </Suspense>
 | 
			
		||||
              </PrivateRoute>
 | 
			
		||||
            }
 | 
			
		||||
          />
 | 
			
		||||
          <Route
 | 
			
		||||
            path='/task'
 | 
			
		||||
            element={
 | 
			
		||||
                <PrivateRoute>
 | 
			
		||||
                    <Suspense fallback={<Loading></Loading>}>
 | 
			
		||||
                        <Task />
 | 
			
		||||
                    </Suspense>
 | 
			
		||||
                </PrivateRoute>
 | 
			
		||||
            }
 | 
			
		||||
          />
 | 
			
		||||
          <Route
 | 
			
		||||
            path='/pricing'
 | 
			
		||||
            element={
 | 
			
		||||
              <Suspense fallback={<Loading></Loading>}>
 | 
			
		||||
                <Pricing />
 | 
			
		||||
              </Suspense>
 | 
			
		||||
            }
 | 
			
		||||
          />
 | 
			
		||||
          <Route
 | 
			
		||||
            path='/about'
 | 
			
		||||
            element={
 | 
			
		||||
              <Suspense fallback={<Loading></Loading>}>
 | 
			
		||||
                <About />
 | 
			
		||||
              </Suspense>
 | 
			
		||||
            }
 | 
			
		||||
          />
 | 
			
		||||
          <Route
 | 
			
		||||
            path='/chat'
 | 
			
		||||
            element={
 | 
			
		||||
              <Suspense fallback={<Loading></Loading>}>
 | 
			
		||||
                <Chat />
 | 
			
		||||
              </Suspense>
 | 
			
		||||
            }
 | 
			
		||||
          />
 | 
			
		||||
          <Route path='*' element={<NotFound />} />
 | 
			
		||||
        </Routes>
 | 
			
		||||
      </Layout.Content>
 | 
			
		||||
    </Layout>
 | 
			
		||||
            </PrivateRoute>
 | 
			
		||||
          }
 | 
			
		||||
        />
 | 
			
		||||
        <Route
 | 
			
		||||
          path='/pricing'
 | 
			
		||||
          element={
 | 
			
		||||
            <Suspense fallback={<Loading></Loading>}>
 | 
			
		||||
              <Pricing />
 | 
			
		||||
            </Suspense>
 | 
			
		||||
          }
 | 
			
		||||
        />
 | 
			
		||||
        <Route
 | 
			
		||||
          path='/about'
 | 
			
		||||
          element={
 | 
			
		||||
            <Suspense fallback={<Loading></Loading>}>
 | 
			
		||||
              <About />
 | 
			
		||||
            </Suspense>
 | 
			
		||||
          }
 | 
			
		||||
        />
 | 
			
		||||
        <Route
 | 
			
		||||
          path='/chat'
 | 
			
		||||
          element={
 | 
			
		||||
            <Suspense fallback={<Loading></Loading>}>
 | 
			
		||||
              <Chat />
 | 
			
		||||
            </Suspense>
 | 
			
		||||
          }
 | 
			
		||||
        />
 | 
			
		||||
        <Route path='*' element={<NotFound />} />
 | 
			
		||||
      </Routes>
 | 
			
		||||
    </>
 | 
			
		||||
  );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -3,7 +3,7 @@ import React, { useEffect, useState } from 'react';
 | 
			
		||||
import { getFooterHTML, getSystemName } from '../helpers';
 | 
			
		||||
import { Layout, Tooltip } from '@douyinfe/semi-ui';
 | 
			
		||||
 | 
			
		||||
const Footer = () => {
 | 
			
		||||
const FooterBar = () => {
 | 
			
		||||
  const systemName = getSystemName();
 | 
			
		||||
  const [footer, setFooter] = useState(getFooterHTML());
 | 
			
		||||
  let remainCheckTimes = 5;
 | 
			
		||||
@@ -56,19 +56,17 @@ const Footer = () => {
 | 
			
		||||
  }, []);
 | 
			
		||||
 | 
			
		||||
  return (
 | 
			
		||||
    <Layout>
 | 
			
		||||
      <Layout.Content style={{ textAlign: 'center' }}>
 | 
			
		||||
        {footer ? (
 | 
			
		||||
          <div
 | 
			
		||||
            className='custom-footer'
 | 
			
		||||
            dangerouslySetInnerHTML={{ __html: footer }}
 | 
			
		||||
          ></div>
 | 
			
		||||
        ) : (
 | 
			
		||||
          defaultFooter
 | 
			
		||||
        )}
 | 
			
		||||
      </Layout.Content>
 | 
			
		||||
    </Layout>
 | 
			
		||||
    <div style={{ textAlign: 'center' }}>
 | 
			
		||||
      {footer ? (
 | 
			
		||||
        <div
 | 
			
		||||
          className='custom-footer'
 | 
			
		||||
          dangerouslySetInnerHTML={{ __html: footer }}
 | 
			
		||||
        ></div>
 | 
			
		||||
      ) : (
 | 
			
		||||
        defaultFooter
 | 
			
		||||
      )}
 | 
			
		||||
    </div>
 | 
			
		||||
  );
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export default Footer;
 | 
			
		||||
export default FooterBar;
 | 
			
		||||
 
 | 
			
		||||
@@ -3,14 +3,23 @@ import { Link, useNavigate } from 'react-router-dom';
 | 
			
		||||
import { UserContext } from '../context/User';
 | 
			
		||||
import { useSetTheme, useTheme } from '../context/Theme';
 | 
			
		||||
 | 
			
		||||
import { API, getLogo, getSystemName, showSuccess } from '../helpers';
 | 
			
		||||
import { API, getLogo, getSystemName, isMobile, showSuccess } from '../helpers';
 | 
			
		||||
import '../index.css';
 | 
			
		||||
 | 
			
		||||
import fireworks from 'react-fireworks';
 | 
			
		||||
 | 
			
		||||
import { IconHelpCircle, IconKey, IconUser } from '@douyinfe/semi-icons';
 | 
			
		||||
import {
 | 
			
		||||
  IconHelpCircle,
 | 
			
		||||
  IconHome,
 | 
			
		||||
  IconHomeStroked,
 | 
			
		||||
  IconKey,
 | 
			
		||||
  IconNoteMoneyStroked,
 | 
			
		||||
  IconPriceTag,
 | 
			
		||||
  IconUser
 | 
			
		||||
} from '@douyinfe/semi-icons';
 | 
			
		||||
import { Avatar, Dropdown, Layout, Nav, Switch } from '@douyinfe/semi-ui';
 | 
			
		||||
import { stringToColor } from '../helpers/render';
 | 
			
		||||
import Text from '@douyinfe/semi-ui/lib/es/typography/text';
 | 
			
		||||
 | 
			
		||||
// HeaderBar Buttons
 | 
			
		||||
let headerButtons = [
 | 
			
		||||
@@ -22,6 +31,21 @@ let headerButtons = [
 | 
			
		||||
  },
 | 
			
		||||
];
 | 
			
		||||
 | 
			
		||||
let buttons = [
 | 
			
		||||
  {
 | 
			
		||||
    text: '首页',
 | 
			
		||||
    itemKey: 'home',
 | 
			
		||||
    to: '/',
 | 
			
		||||
    icon: <IconHomeStroked />,
 | 
			
		||||
  },
 | 
			
		||||
  // {
 | 
			
		||||
  //   text: '模型价格',
 | 
			
		||||
  //   itemKey: 'pricing',
 | 
			
		||||
  //   to: '/pricing',
 | 
			
		||||
  //   icon: <IconNoteMoneyStroked />,
 | 
			
		||||
  // },
 | 
			
		||||
];
 | 
			
		||||
 | 
			
		||||
if (localStorage.getItem('chat_link')) {
 | 
			
		||||
  headerButtons.splice(1, 0, {
 | 
			
		||||
    name: '聊天',
 | 
			
		||||
@@ -90,6 +114,7 @@ const HeaderBar = () => {
 | 
			
		||||
                about: '/about',
 | 
			
		||||
                login: '/login',
 | 
			
		||||
                register: '/register',
 | 
			
		||||
                home: '/',
 | 
			
		||||
              };
 | 
			
		||||
              return (
 | 
			
		||||
                <Link
 | 
			
		||||
@@ -103,6 +128,18 @@ const HeaderBar = () => {
 | 
			
		||||
            selectedKeys={[]}
 | 
			
		||||
            // items={headerButtons}
 | 
			
		||||
            onSelect={(key) => {}}
 | 
			
		||||
            header={isMobile()?{
 | 
			
		||||
              logo: (
 | 
			
		||||
                <img src={logo} alt='logo' style={{ marginRight: '0.75em' }} />
 | 
			
		||||
              ),
 | 
			
		||||
            }:{
 | 
			
		||||
              logo: (
 | 
			
		||||
                <img src={logo} alt='logo' />
 | 
			
		||||
              ),
 | 
			
		||||
              text: systemName,
 | 
			
		||||
 | 
			
		||||
            }}
 | 
			
		||||
            items={buttons}
 | 
			
		||||
            footer={
 | 
			
		||||
              <>
 | 
			
		||||
                {isNewYear && (
 | 
			
		||||
@@ -121,15 +158,19 @@ const HeaderBar = () => {
 | 
			
		||||
                  </Dropdown>
 | 
			
		||||
                )}
 | 
			
		||||
                <Nav.Item itemKey={'about'} icon={<IconHelpCircle />} />
 | 
			
		||||
                <Switch
 | 
			
		||||
                  checkedText='🌞'
 | 
			
		||||
                  size={'large'}
 | 
			
		||||
                  checked={theme === 'dark'}
 | 
			
		||||
                  uncheckedText='🌙'
 | 
			
		||||
                  onChange={(checked) => {
 | 
			
		||||
                    setTheme(checked);
 | 
			
		||||
                  }}
 | 
			
		||||
                />
 | 
			
		||||
                <>
 | 
			
		||||
                {!isMobile() && (
 | 
			
		||||
                    <Switch
 | 
			
		||||
                      checkedText='🌞'
 | 
			
		||||
                      size={'large'}
 | 
			
		||||
                      checked={theme === 'dark'}
 | 
			
		||||
                      uncheckedText='🌙'
 | 
			
		||||
                      onChange={(checked) => {
 | 
			
		||||
                        setTheme(checked);
 | 
			
		||||
                      }}
 | 
			
		||||
                    />
 | 
			
		||||
                  )}
 | 
			
		||||
                </>
 | 
			
		||||
                {userState.user ? (
 | 
			
		||||
                  <>
 | 
			
		||||
                    <Dropdown
 | 
			
		||||
@@ -155,7 +196,7 @@ const HeaderBar = () => {
 | 
			
		||||
                    <Nav.Item
 | 
			
		||||
                      itemKey={'login'}
 | 
			
		||||
                      text={'登录'}
 | 
			
		||||
                      icon={<IconKey />}
 | 
			
		||||
                      // icon={<IconKey />}
 | 
			
		||||
                    />
 | 
			
		||||
                    <Nav.Item
 | 
			
		||||
                      itemKey={'register'}
 | 
			
		||||
 
 | 
			
		||||
@@ -17,7 +17,7 @@ import {
 | 
			
		||||
  IconCalendarClock, IconChecklistStroked,
 | 
			
		||||
  IconComment,
 | 
			
		||||
  IconCreditCard,
 | 
			
		||||
  IconGift,
 | 
			
		||||
  IconGift, IconHelpCircle,
 | 
			
		||||
  IconHistogram,
 | 
			
		||||
  IconHome,
 | 
			
		||||
  IconImage,
 | 
			
		||||
@@ -25,10 +25,12 @@ import {
 | 
			
		||||
  IconLayers,
 | 
			
		||||
  IconPriceTag,
 | 
			
		||||
  IconSetting,
 | 
			
		||||
  IconUser,
 | 
			
		||||
  IconUser
 | 
			
		||||
} from '@douyinfe/semi-icons';
 | 
			
		||||
import { Layout, Nav } from '@douyinfe/semi-ui';
 | 
			
		||||
import { Avatar, Dropdown, Layout, Nav, Switch } from '@douyinfe/semi-ui';
 | 
			
		||||
import { setStatusData } from '../helpers/data.js';
 | 
			
		||||
import { stringToColor } from '../helpers/render.js';
 | 
			
		||||
import { useSetTheme, useTheme } from '../context/Theme/index.js';
 | 
			
		||||
 | 
			
		||||
// HeaderBar Buttons
 | 
			
		||||
 | 
			
		||||
@@ -43,6 +45,8 @@ const SiderBar = () => {
 | 
			
		||||
  const systemName = getSystemName();
 | 
			
		||||
  const logo = getLogo();
 | 
			
		||||
  const [isCollapsed, setIsCollapsed] = useState(defaultIsCollapsed);
 | 
			
		||||
  const theme = useTheme();
 | 
			
		||||
  const setTheme = useSetTheme();
 | 
			
		||||
 | 
			
		||||
  const routerMap = {
 | 
			
		||||
    home: '/',
 | 
			
		||||
@@ -63,11 +67,17 @@ const SiderBar = () => {
 | 
			
		||||
 | 
			
		||||
  const headerButtons = useMemo(
 | 
			
		||||
    () => [
 | 
			
		||||
      // {
 | 
			
		||||
      //   text: '首页',
 | 
			
		||||
      //   itemKey: 'home',
 | 
			
		||||
      //   to: '/',
 | 
			
		||||
      //   icon: <IconHome />,
 | 
			
		||||
      // },
 | 
			
		||||
      {
 | 
			
		||||
        text: '首页',
 | 
			
		||||
        itemKey: 'home',
 | 
			
		||||
        to: '/',
 | 
			
		||||
        icon: <IconHome />,
 | 
			
		||||
        text: '模型价格',
 | 
			
		||||
        itemKey: 'pricing',
 | 
			
		||||
        to: '/pricing',
 | 
			
		||||
        icon: <IconPriceTag />,
 | 
			
		||||
      },
 | 
			
		||||
      {
 | 
			
		||||
        text: '渠道',
 | 
			
		||||
@@ -104,12 +114,6 @@ const SiderBar = () => {
 | 
			
		||||
        to: '/topup',
 | 
			
		||||
        icon: <IconCreditCard />,
 | 
			
		||||
      },
 | 
			
		||||
      {
 | 
			
		||||
        text: '模型价格',
 | 
			
		||||
        itemKey: 'pricing',
 | 
			
		||||
        to: '/pricing',
 | 
			
		||||
        icon: <IconPriceTag />,
 | 
			
		||||
      },
 | 
			
		||||
      {
 | 
			
		||||
        text: '用户管理',
 | 
			
		||||
        itemKey: 'user',
 | 
			
		||||
@@ -205,48 +209,58 @@ const SiderBar = () => {
 | 
			
		||||
 | 
			
		||||
  return (
 | 
			
		||||
    <>
 | 
			
		||||
      <Layout>
 | 
			
		||||
        <div style={{ height: '100%' }}>
 | 
			
		||||
          <Nav
 | 
			
		||||
            // bodyStyle={{ maxWidth: 200 }}
 | 
			
		||||
            style={{ maxWidth: 200 }}
 | 
			
		||||
            defaultIsCollapsed={
 | 
			
		||||
              isMobile() ||
 | 
			
		||||
              localStorage.getItem('default_collapse_sidebar') === 'true'
 | 
			
		||||
            }
 | 
			
		||||
            isCollapsed={isCollapsed}
 | 
			
		||||
            onCollapseChange={(collapsed) => {
 | 
			
		||||
              setIsCollapsed(collapsed);
 | 
			
		||||
            }}
 | 
			
		||||
            selectedKeys={selectedKeys}
 | 
			
		||||
            renderWrapper={({ itemElement, isSubNav, isInSubNav, props }) => {
 | 
			
		||||
              return (
 | 
			
		||||
                <Link
 | 
			
		||||
                  style={{ textDecoration: 'none' }}
 | 
			
		||||
                  to={routerMap[props.itemKey]}
 | 
			
		||||
                >
 | 
			
		||||
                  {itemElement}
 | 
			
		||||
                </Link>
 | 
			
		||||
              );
 | 
			
		||||
            }}
 | 
			
		||||
            items={headerButtons}
 | 
			
		||||
            onSelect={(key) => {
 | 
			
		||||
              setSelectedKeys([key.itemKey]);
 | 
			
		||||
            }}
 | 
			
		||||
            header={{
 | 
			
		||||
              logo: (
 | 
			
		||||
                <img src={logo} alt='logo' style={{ marginRight: '0.75em' }} />
 | 
			
		||||
              ),
 | 
			
		||||
              text: systemName,
 | 
			
		||||
            }}
 | 
			
		||||
            // footer={{
 | 
			
		||||
            //   text: '© 2021 NekoAPI',
 | 
			
		||||
            // }}
 | 
			
		||||
          >
 | 
			
		||||
            <Nav.Footer collapseButton={true}></Nav.Footer>
 | 
			
		||||
          </Nav>
 | 
			
		||||
        </div>
 | 
			
		||||
      </Layout>
 | 
			
		||||
      <Nav
 | 
			
		||||
        style={{ maxWidth: 220, height: '100%' }}
 | 
			
		||||
        defaultIsCollapsed={
 | 
			
		||||
          isMobile() ||
 | 
			
		||||
          localStorage.getItem('default_collapse_sidebar') === 'true'
 | 
			
		||||
        }
 | 
			
		||||
        isCollapsed={isCollapsed}
 | 
			
		||||
        onCollapseChange={(collapsed) => {
 | 
			
		||||
          setIsCollapsed(collapsed);
 | 
			
		||||
        }}
 | 
			
		||||
        selectedKeys={selectedKeys}
 | 
			
		||||
        renderWrapper={({ itemElement, isSubNav, isInSubNav, props }) => {
 | 
			
		||||
          return (
 | 
			
		||||
            <Link
 | 
			
		||||
              style={{ textDecoration: 'none' }}
 | 
			
		||||
              to={routerMap[props.itemKey]}
 | 
			
		||||
            >
 | 
			
		||||
              {itemElement}
 | 
			
		||||
            </Link>
 | 
			
		||||
          );
 | 
			
		||||
        }}
 | 
			
		||||
        items={headerButtons}
 | 
			
		||||
        onSelect={(key) => {
 | 
			
		||||
          setSelectedKeys([key.itemKey]);
 | 
			
		||||
        }}
 | 
			
		||||
        // header={{
 | 
			
		||||
        //   logo: (
 | 
			
		||||
        //     <img src={logo} alt='logo' style={{ marginRight: '0.75em' }} />
 | 
			
		||||
        //   ),
 | 
			
		||||
        //   text: systemName,
 | 
			
		||||
        // }}
 | 
			
		||||
        // footer={{
 | 
			
		||||
        //   text: '© 2021 NekoAPI',
 | 
			
		||||
        // }}
 | 
			
		||||
        footer={
 | 
			
		||||
          <>
 | 
			
		||||
            {isMobile() && (
 | 
			
		||||
              <Switch
 | 
			
		||||
                checkedText='🌞'
 | 
			
		||||
                size={'small'}
 | 
			
		||||
                checked={theme === 'dark'}
 | 
			
		||||
                uncheckedText='🌙'
 | 
			
		||||
                onChange={(checked) => {
 | 
			
		||||
                  setTheme(checked);
 | 
			
		||||
                }}
 | 
			
		||||
              />
 | 
			
		||||
            )}
 | 
			
		||||
          </>
 | 
			
		||||
        }
 | 
			
		||||
      >
 | 
			
		||||
        <Nav.Footer collapseButton={true}></Nav.Footer>
 | 
			
		||||
      </Nav>
 | 
			
		||||
    </>
 | 
			
		||||
  );
 | 
			
		||||
};
 | 
			
		||||
 
 | 
			
		||||
@@ -9,11 +9,12 @@ body {
 | 
			
		||||
  scrollbar-width: none;
 | 
			
		||||
  color: var(--semi-color-text-0) !important;
 | 
			
		||||
  background-color: var(--semi-color-bg-0) !important;
 | 
			
		||||
  height: 100%;
 | 
			
		||||
  height: 100vh;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#root {
 | 
			
		||||
  height: 100%;
 | 
			
		||||
  height: 100vh;
 | 
			
		||||
  flex-direction: column;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@media only screen and (max-width: 767px) {
 | 
			
		||||
@@ -50,9 +51,9 @@ body {
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.semi-layout {
 | 
			
		||||
  height: 100%;
 | 
			
		||||
}
 | 
			
		||||
/*.semi-layout {*/
 | 
			
		||||
/*  height: 100%;*/
 | 
			
		||||
/*}*/
 | 
			
		||||
 | 
			
		||||
.tableShow {
 | 
			
		||||
  display: revert;
 | 
			
		||||
 
 | 
			
		||||
@@ -3,7 +3,6 @@ import ReactDOM from 'react-dom/client';
 | 
			
		||||
import { BrowserRouter } from 'react-router-dom';
 | 
			
		||||
import App from './App';
 | 
			
		||||
import HeaderBar from './components/HeaderBar';
 | 
			
		||||
import Footer from './components/Footer';
 | 
			
		||||
import 'semantic-ui-offline/semantic.min.css';
 | 
			
		||||
import './index.css';
 | 
			
		||||
import { UserProvider } from './context/User';
 | 
			
		||||
@@ -13,35 +12,36 @@ import { StatusProvider } from './context/Status';
 | 
			
		||||
import { Layout } from '@douyinfe/semi-ui';
 | 
			
		||||
import SiderBar from './components/SiderBar';
 | 
			
		||||
import { ThemeProvider } from './context/Theme';
 | 
			
		||||
import FooterBar from './components/Footer';
 | 
			
		||||
 | 
			
		||||
// initialization
 | 
			
		||||
 | 
			
		||||
const root = ReactDOM.createRoot(document.getElementById('root'));
 | 
			
		||||
const { Sider, Content, Header } = Layout;
 | 
			
		||||
const { Sider, Content, Header, Footer } = Layout;
 | 
			
		||||
root.render(
 | 
			
		||||
  <React.StrictMode>
 | 
			
		||||
    <StatusProvider>
 | 
			
		||||
      <UserProvider>
 | 
			
		||||
        <BrowserRouter>
 | 
			
		||||
          <ThemeProvider>
 | 
			
		||||
            <Layout>
 | 
			
		||||
              <Sider>
 | 
			
		||||
                <SiderBar />
 | 
			
		||||
              </Sider>
 | 
			
		||||
              <Layout>
 | 
			
		||||
                <Header>
 | 
			
		||||
                  <HeaderBar />
 | 
			
		||||
                </Header>
 | 
			
		||||
                <Content
 | 
			
		||||
                  style={{
 | 
			
		||||
                    padding: '24px',
 | 
			
		||||
                  }}
 | 
			
		||||
                >
 | 
			
		||||
                  <App />
 | 
			
		||||
                </Content>
 | 
			
		||||
                <Layout.Footer>
 | 
			
		||||
                  <Footer></Footer>
 | 
			
		||||
                </Layout.Footer>
 | 
			
		||||
            <Layout style={{ height: '100vh', display: 'flex', flexDirection: 'column' }}>
 | 
			
		||||
              <Header>
 | 
			
		||||
                <HeaderBar />
 | 
			
		||||
              </Header>
 | 
			
		||||
              <Layout style={{ flex: 1, overflow: 'hidden' }}>
 | 
			
		||||
                <Sider>
 | 
			
		||||
                  <SiderBar />
 | 
			
		||||
                </Sider>
 | 
			
		||||
                <Layout>
 | 
			
		||||
                  <Content
 | 
			
		||||
                    style={{ overflowY: 'auto', padding: '24px' }}
 | 
			
		||||
                  >
 | 
			
		||||
                    <App />
 | 
			
		||||
                  </Content>
 | 
			
		||||
                  <Layout.Footer>
 | 
			
		||||
                    <FooterBar></FooterBar>
 | 
			
		||||
                  </Layout.Footer>
 | 
			
		||||
                </Layout>
 | 
			
		||||
              </Layout>
 | 
			
		||||
              <ToastContainer />
 | 
			
		||||
            </Layout>
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user