diff --git a/web/src/App.js b/web/src/App.js
index ff0abbbb..93b4e496 100644
--- a/web/src/App.js
+++ b/web/src/App.js
@@ -25,7 +25,7 @@ import Playground from './pages/Playground/index.js';
import OAuth2Callback from './components/auth/OAuth2Callback.js';
import PersonalSetting from './components/settings/PersonalSetting.js';
import Setup from './pages/Setup/index.js';
-import SetupCheck from './components/SetupCheck';
+import { useSetupCheck } from './hooks/useSetupCheck.js';
const Home = lazy(() => import('./pages/Home'));
const Detail = lazy(() => import('./pages/Detail'));
@@ -35,7 +35,7 @@ function App() {
const location = useLocation();
return (
-
+
} />
-
+
);
}
diff --git a/web/src/components/SetupCheck.js b/web/src/components/SetupCheck.js
deleted file mode 100644
index 99364b00..00000000
--- a/web/src/components/SetupCheck.js
+++ /dev/null
@@ -1,18 +0,0 @@
-import React, { useContext, useEffect } from 'react';
-import { Navigate, useLocation } from 'react-router-dom';
-import { StatusContext } from '../context/Status';
-
-const SetupCheck = ({ children }) => {
- const [statusState] = useContext(StatusContext);
- const location = useLocation();
-
- useEffect(() => {
- if (statusState?.status?.setup === false && location.pathname !== '/setup') {
- window.location.href = '/setup';
- }
- }, [statusState?.status?.setup, location.pathname]);
-
- return children;
-};
-
-export default SetupCheck;
\ No newline at end of file
diff --git a/web/src/components/fetchTokenKeys.js b/web/src/components/fetchTokenKeys.js
deleted file mode 100644
index e9cec001..00000000
--- a/web/src/components/fetchTokenKeys.js
+++ /dev/null
@@ -1,68 +0,0 @@
-// src/hooks/useTokenKeys.js
-import { useEffect, useState } from 'react';
-import { API, showError } from '../helpers';
-
-async function fetchTokenKeys() {
- try {
- const response = await API.get('/api/token/?p=0&size=100');
- const { success, data } = response.data;
- if (success) {
- const activeTokens = data.filter((token) => token.status === 1);
- return activeTokens.map((token) => token.key);
- } else {
- throw new Error('Failed to fetch token keys');
- }
- } catch (error) {
- console.error('Error fetching token keys:', error);
- return [];
- }
-}
-
-function getServerAddress() {
- let status = localStorage.getItem('status');
- let serverAddress = '';
-
- if (status) {
- try {
- status = JSON.parse(status);
- serverAddress = status.server_address || '';
- } catch (error) {
- console.error('Failed to parse status from localStorage:', error);
- }
- }
-
- if (!serverAddress) {
- serverAddress = window.location.origin;
- }
-
- return serverAddress;
-}
-
-export function useTokenKeys(id) {
- const [keys, setKeys] = useState([]);
- // const [chatLink, setChatLink] = useState('');
- const [serverAddress, setServerAddress] = useState('');
- const [isLoading, setIsLoading] = useState(true);
-
- useEffect(() => {
- const loadAllData = async () => {
- const fetchedKeys = await fetchTokenKeys();
- if (fetchedKeys.length === 0) {
- showError('当前没有可用的启用令牌,请确认是否有令牌处于启用状态!');
- setTimeout(() => {
- window.location.href = '/token';
- }, 1500); // 延迟 1.5 秒后跳转
- }
- setKeys(fetchedKeys);
- setIsLoading(false);
- // setChatLink(link);
-
- const address = getServerAddress();
- setServerAddress(address);
- };
-
- loadAllData();
- }, []);
-
- return { keys, serverAddress, isLoading };
-}
diff --git a/web/src/helpers/index.js b/web/src/helpers/index.js
index c43be2c9..1524afbe 100644
--- a/web/src/helpers/index.js
+++ b/web/src/helpers/index.js
@@ -5,3 +5,4 @@ export * from './api';
export * from './render';
export * from './log';
export * from './data';
+export * from './token';
diff --git a/web/src/helpers/token.js b/web/src/helpers/token.js
new file mode 100644
index 00000000..ecdeaa3a
--- /dev/null
+++ b/web/src/helpers/token.js
@@ -0,0 +1,45 @@
+import { API } from './api';
+
+/**
+ * 获取可用的token keys
+ * @returns {Promise} 返回active状态的token key数组
+ */
+export async function fetchTokenKeys() {
+ try {
+ const response = await API.get('/api/token/?p=0&size=100');
+ const { success, data } = response.data;
+ if (success) {
+ const activeTokens = data.filter((token) => token.status === 1);
+ return activeTokens.map((token) => token.key);
+ } else {
+ throw new Error('Failed to fetch token keys');
+ }
+ } catch (error) {
+ console.error('Error fetching token keys:', error);
+ return [];
+ }
+}
+
+/**
+ * 获取服务器地址
+ * @returns {string} 服务器地址
+ */
+export function getServerAddress() {
+ let status = localStorage.getItem('status');
+ let serverAddress = '';
+
+ if (status) {
+ try {
+ status = JSON.parse(status);
+ serverAddress = status.server_address || '';
+ } catch (error) {
+ console.error('Failed to parse status from localStorage:', error);
+ }
+ }
+
+ if (!serverAddress) {
+ serverAddress = window.location.origin;
+ }
+
+ return serverAddress;
+}
\ No newline at end of file
diff --git a/web/src/hooks/useSetupCheck.js b/web/src/hooks/useSetupCheck.js
new file mode 100644
index 00000000..d2233de8
--- /dev/null
+++ b/web/src/hooks/useSetupCheck.js
@@ -0,0 +1,32 @@
+import { useContext, useEffect } from 'react';
+import { useLocation } from 'react-router-dom';
+import { StatusContext } from '../context/Status';
+
+/**
+ * 自定义Hook:检查系统setup状态并进行重定向
+ * @param {Object} options - 配置选项
+ * @param {boolean} options.autoRedirect - 是否自动重定向,默认true
+ * @param {string} options.setupPath - setup页面路径,默认'/setup'
+ * @returns {Object} 返回setup状态信息
+ */
+export function useSetupCheck(options = {}) {
+ const { autoRedirect = true, setupPath = '/setup' } = options;
+ const [statusState] = useContext(StatusContext);
+ const location = useLocation();
+
+ const isSetupComplete = statusState?.status?.setup !== false;
+ const needsSetup = !isSetupComplete && location.pathname !== setupPath;
+
+ useEffect(() => {
+ if (autoRedirect && needsSetup) {
+ window.location.href = setupPath;
+ }
+ }, [autoRedirect, needsSetup, setupPath]);
+
+ return {
+ isSetupComplete,
+ needsSetup,
+ statusState,
+ currentPath: location.pathname
+ };
+}
\ No newline at end of file
diff --git a/web/src/hooks/useTokenKeys.js b/web/src/hooks/useTokenKeys.js
new file mode 100644
index 00000000..a6583591
--- /dev/null
+++ b/web/src/hooks/useTokenKeys.js
@@ -0,0 +1,30 @@
+import { useEffect, useState } from 'react';
+import { fetchTokenKeys, getServerAddress } from '../helpers/token';
+import { showError } from '../helpers';
+
+export function useTokenKeys(id) {
+ const [keys, setKeys] = useState([]);
+ const [serverAddress, setServerAddress] = useState('');
+ const [isLoading, setIsLoading] = useState(true);
+
+ useEffect(() => {
+ const loadAllData = async () => {
+ const fetchedKeys = await fetchTokenKeys();
+ if (fetchedKeys.length === 0) {
+ showError('当前没有可用的启用令牌,请确认是否有令牌处于启用状态!');
+ setTimeout(() => {
+ window.location.href = '/token';
+ }, 1500); // 延迟 1.5 秒后跳转
+ }
+ setKeys(fetchedKeys);
+ setIsLoading(false);
+
+ const address = getServerAddress();
+ setServerAddress(address);
+ };
+
+ loadAllData();
+ }, []);
+
+ return { keys, serverAddress, isLoading };
+}
\ No newline at end of file
diff --git a/web/src/index.js b/web/src/index.js
index dc0c438d..0f57f5a1 100644
--- a/web/src/index.js
+++ b/web/src/index.js
@@ -16,7 +16,7 @@ import './index.css';
const root = ReactDOM.createRoot(document.getElementById('root'));
const { Sider, Content, Header, Footer } = Layout;
root.render(
- //
+
@@ -28,5 +28,5 @@ root.render(
- // ,
+ ,
);
diff --git a/web/src/pages/Chat/index.js b/web/src/pages/Chat/index.js
index 77ece906..bd4e19a1 100644
--- a/web/src/pages/Chat/index.js
+++ b/web/src/pages/Chat/index.js
@@ -1,5 +1,5 @@
import React, { useEffect } from 'react';
-import { useTokenKeys } from '../../components/fetchTokenKeys';
+import { useTokenKeys } from '../../hooks/useTokenKeys';
import { Banner, Layout } from '@douyinfe/semi-ui';
import { useParams } from 'react-router-dom';
diff --git a/web/src/pages/Chat2Link/index.js b/web/src/pages/Chat2Link/index.js
index a7b5e6ae..553dab3f 100644
--- a/web/src/pages/Chat2Link/index.js
+++ b/web/src/pages/Chat2Link/index.js
@@ -1,5 +1,5 @@
import React from 'react';
-import { useTokenKeys } from '../../components/fetchTokenKeys';
+import { useTokenKeys } from '../../hooks/useTokenKeys';
const chat2page = () => {
const { keys, chatLink, serverAddress, isLoading } = useTokenKeys();
diff --git a/web/src/pages/Home/index.js b/web/src/pages/Home/index.js
index ba0c738c..4e8a61d6 100644
--- a/web/src/pages/Home/index.js
+++ b/web/src/pages/Home/index.js
@@ -5,7 +5,7 @@ import { StatusContext } from '../../context/Status';
import { marked } from 'marked';
import { useTranslation } from 'react-i18next';
import { IconGithubLogo } from '@douyinfe/semi-icons';
-import exampleImage from '..//example.png';
+import exampleImage from '/example.png';
import { Link } from 'react-router-dom';
import NoticeModal from '../../components/layout/NoticeModal';
import { Moonshot, OpenAI, XAI, Zhipu, Volcengine, Cohere, Claude, Gemini, Suno, Minimax, Wenxin, Spark, Qingyan, DeepSeek, Qwen, Midjourney, Grok, AzureAI, Hunyuan, Xinference } from '@lobehub/icons';