diff --git a/web/src/App.js b/web/src/App.js
index 93b4e496..2d715767 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 { useSetupCheck } from './hooks/useSetupCheck.js';
+import SetupCheck from './components/layout/SetupCheck.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/layout/SetupCheck.js b/web/src/components/layout/SetupCheck.js
new file mode 100644
index 00000000..3fbd9012
--- /dev/null
+++ b/web/src/components/layout/SetupCheck.js
@@ -0,0 +1,18 @@
+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/hooks/useSetupCheck.js b/web/src/hooks/useSetupCheck.js
deleted file mode 100644
index d2233de8..00000000
--- a/web/src/hooks/useSetupCheck.js
+++ /dev/null
@@ -1,32 +0,0 @@
-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
index a6583591..eba69e08 100644
--- a/web/src/hooks/useTokenKeys.js
+++ b/web/src/hooks/useTokenKeys.js
@@ -13,7 +13,7 @@ export function useTokenKeys(id) {
if (fetchedKeys.length === 0) {
showError('当前没有可用的启用令牌,请确认是否有令牌处于启用状态!');
setTimeout(() => {
- window.location.href = '/token';
+ window.location.href = '/console/token';
}, 1500); // 延迟 1.5 秒后跳转
}
setKeys(fetchedKeys);
diff --git a/web/src/i18n/locales/en.json b/web/src/i18n/locales/en.json
index 3ab3a51f..e0575264 100644
--- a/web/src/i18n/locales/en.json
+++ b/web/src/i18n/locales/en.json
@@ -1367,7 +1367,7 @@
"提示 {{nonCacheInput}} tokens + 缓存 {{cacheInput}} tokens * {{cacheRatio}} / 1M tokens * ${{price}} + 补全 {{completion}} tokens / 1M tokens * ${{compPrice}} * 分组 {{ratio}} = ${{total}}": "Prompt {{nonCacheInput}} tokens + cache {{cacheInput}} tokens * {{cacheRatio}} / 1M tokens * ${{price}} + completion {{completion}} tokens / 1M tokens * ${{compPrice}} * group {{ratio}} = ${{total}}",
"缓存 Tokens": "Cache Tokens",
"系统初始化": "System initialization",
- "管理员账号已经初始化过,请继续设置系统参数": "The admin account has already been initialized, please continue to set the system parameters",
+ "管理员账号已经初始化过,请继续设置其他参数": "The admin account has already been initialized, please continue to set other parameters",
"管理员账号": "Admin account",
"请输入管理员用户名": "Please enter the admin username",
"请输入管理员密码": "Please enter the admin password",
@@ -1532,5 +1532,24 @@
"搜索条件": "Search Conditions",
"加载中...": "Loading...",
"暂无公告": "No Notice",
- "操练场": "Playground"
+ "操练场": "Playground",
+ "欢迎使用,请完成以下设置以开始使用系统": "Welcome to use, please complete the following settings to start using the system",
+ "数据库信息": "Database Information",
+ "您正在使用 MySQL 数据库。MySQL 是一个可靠的关系型数据库管理系统,适合生产环境使用。": "You are using the MySQL database. MySQL is a reliable relational database management system, suitable for production environments.",
+ "您正在使用 PostgreSQL 数据库。PostgreSQL 是一个功能强大的开源关系型数据库系统,提供了出色的可靠性和数据完整性,适合生产环境使用。": "You are using the PostgreSQL database. PostgreSQL is a powerful open-source relational database system that provides excellent reliability and data integrity, suitable for production environments.",
+ "设置系统管理员的登录信息": "Set the login information for the system administrator",
+ "选择适合您使用场景的模式": "Select the mode suitable for your usage scenario",
+ "使用模式说明": "Usage mode description",
+ "计费模式": "Billing mode",
+ "多用户支持": "Multi-user support",
+ "个人使用": "Personal use",
+ "功能演示": "Function demonstration",
+ "体验试用": "Experience trial",
+ "默认模式": "Default Mode",
+ "无需计费": "No Charge",
+ "演示体验": "Demo Experience",
+ "提供基础功能演示,方便用户了解系统特性。": "Provide basic feature demonstrations to help users understand the system features.",
+ "适用于为多个用户提供服务的场景": "Suitable for scenarios where multiple users are provided.",
+ "适用于个人使用的场景,不需要设置模型价格": "Suitable for personal use, no need to set model price.",
+ "适用于展示系统功能的场景,提供基础功能演示": "Suitable for scenarios where the system functions are displayed, providing basic feature demonstrations."
}
\ No newline at end of file
diff --git a/web/src/pages/Setup/index.js b/web/src/pages/Setup/index.js
index 3079676a..54240b37 100644
--- a/web/src/pages/Setup/index.js
+++ b/web/src/pages/Setup/index.js
@@ -6,14 +6,20 @@ import {
Typography,
Modal,
Banner,
+ Layout,
+ Tag,
} from '@douyinfe/semi-ui';
import { API, showError, showNotice } from '../../helpers';
import { useTranslation } from 'react-i18next';
import {
IconHelpCircle,
IconInfoCircle,
- IconAlertTriangle,
+ IconUser,
+ IconLock,
+ IconSetting,
+ IconCheckCircleStroked,
} from '@douyinfe/semi-icons';
+import { Shield, Rocket, FlaskConical, Database, Layers } from 'lucide-react';
const Setup = () => {
const { t } = useTranslation();
@@ -127,163 +133,443 @@ const Setup = () => {
};
return (
- <>
-
-
-
- {t('系统初始化')}
-
-
- {setupStatus.database_type === 'sqlite' && (
- }
- closeIcon={null}
- title={t('数据库警告')}
- description={
-
-
- {t(
- '您正在使用 SQLite 数据库。如果您在容器环境中运行,请确保已正确设置数据库文件的持久化映射,否则容器重启后所有数据将丢失!',
- )}
-
-
- {t(
- '建议在生产环境中使用 MySQL 或 PostgreSQL 数据库,或确保 SQLite 数据库文件已映射到宿主机的持久化存储。',
- )}
-
-
- }
- style={{ marginBottom: '24px' }}
- />
- )}
-
-
-
- setFormData({ ...formData, username: value })
- }
- />
-
- setFormData({ ...formData, password: value })
- }
- />
-
- setFormData({ ...formData, confirmPassword: value })
- }
- />
-
- )}
-
-
- {t('系统设置')}
-
- }
- >
-
- {t('使用模式')}
- {
- // e.preventDefault();
- // e.stopPropagation();
- setUsageModeInfoVisible(true);
- }}
- />
+
+
+
+
+
+ {/* 主卡片容器 */}
+
+ {/* 顶部装饰性区域 */}
+
+ {/* 装饰性背景元素 */}
+
- }
- extraText={t('可在初始化后修改')}
- initValue='external'
- onChange={handleUsageModeChange}
- >
- {t('对外运营模式')}
- {t('自用模式')}
- {t('演示站点模式')}
-
-
-
-
-
+
+
+
+
+
+
+ {t('系统初始化')}
+
+
+ {t('欢迎使用,请完成以下设置以开始使用系统')}
+
+
+
+ {/* 数据库警告 */}
+ {setupStatus.database_type === 'sqlite' && (
+
+
+
+
+ }
+ closeIcon={null}
+ title={
+
+ {t('数据库警告')}
+
+ SQLite
+
+
+ }
+ description={
+
+
+ {t(
+ '您正在使用 SQLite 数据库。如果您在容器环境中运行,请确保已正确设置数据库文件的持久化映射,否则容器重启后所有数据将丢失!',
+ )}
+
+
+ {t(
+ '建议在生产环境中使用 MySQL 或 PostgreSQL 数据库,或确保 SQLite 数据库文件已映射到宿主机的持久化存储。',
+ )}
+
+
+ }
+ className="!rounded-xl mb-6"
+ fullMode={false}
+ bordered
+ />
+
+ )}
+ {/* MySQL数据库提示 */}
+ {setupStatus.database_type === 'mysql' && (
+
+
+
+
+ }
+ closeIcon={null}
+ title={
+
+ {t('数据库信息')}
+
+ MySQL
+
+
+ }
+ description={
+
+
+ {t(
+ '您正在使用 MySQL 数据库。MySQL 是一个可靠的关系型数据库管理系统,适合生产环境使用。',
+ )}
+
+
+ }
+ className="!rounded-xl mb-6"
+ fullMode={false}
+ bordered
+ />
+
+ )}
+ {/* PostgreSQL数据库提示 */}
+ {setupStatus.database_type === 'postgres' && (
+
+
+
+
+ }
+ closeIcon={null}
+ title={
+
+ {t('数据库信息')}
+
+ PostgreSQL
+
+
+ }
+ description={
+
+
+ {t(
+ '您正在使用 PostgreSQL 数据库。PostgreSQL 是一个功能强大的开源关系型数据库系统,提供了出色的可靠性和数据完整性,适合生产环境使用。',
+ )}
+
+
+ }
+ className="!rounded-xl mb-6"
+ fullMode={false}
+ bordered
+ />
+
+ )}
+
+
+ {/* 主内容区域 */}
+
+ }
+ closeIcon={null}
+ description={
+
+ {t('管理员账号已经初始化过,请继续设置其他参数')}
+
+ }
+ className="!rounded-lg"
+ />
+ >
+ ) : (
+ <>
+ }
+ showClear
+ size='large'
+ className="mb-4 !rounded-lg"
+ noLabel={false}
+ validateStatus="default"
+ onChange={(value) =>
+ setFormData({ ...formData, username: value })
+ }
+ />
+ }
+ showClear
+ size='large'
+ className="mb-4 !rounded-lg"
+ noLabel={false}
+ validateStatus="default"
+ onChange={(value) =>
+ setFormData({ ...formData, password: value })
+ }
+ />
+ }
+ showClear
+ size='large'
+ className="!rounded-lg"
+ noLabel={false}
+ validateStatus="default"
+ onChange={(value) =>
+ setFormData({ ...formData, confirmPassword: value })
+ }
+ />
+ >
+ )}
+
+
+ {/* 使用模式 */}
+
+
+
+
+
+
+
+
+ {t('使用模式')}
+ }
+ size='small'
+ onClick={() => setUsageModeInfoVisible(true)}
+ className="!rounded-full"
+ />
+
+
{t('选择适合您使用场景的模式')}
+
+
+
+
+
+
+
+
+
+
+
{t('对外运营模式')}
+
{t('适用于为多个用户提供服务的场景')}
+
+ {t('默认模式')}
+
+
+
+ }
+ />
+
+
+
+
+
+
{t('自用模式')}
+
{t('适用于个人使用的场景,不需要设置模型价格')}
+
+ {t('无需计费')}
+
+
+
+ }
+ />
+
+
+
+
+
+
{t('演示站点模式')}
+
{t('适用于展示系统功能的场景,提供基础功能演示')}
+
+ {t('演示体验')}
+
+
+
+ }
+ />
+
+
+
+
+
+
+ }
+ >
+ {t('初始化系统')}
+
+
+
+
-
-
+
+
+ {/* 使用模式说明模态框 */}
+
+ {t('使用模式说明')}
+
+ }
visible={selfUseModeInfoVisible}
onOk={() => setUsageModeInfoVisible(false)}
onCancel={() => setUsageModeInfoVisible(false)}
closeOnEsc={true}
- okText={t('确定')}
+ okText={t('我已了解')}
cancelText={null}
+ centered={true}
+ size='medium'
+ className="[&_.semi-modal-body]:!p-6"
>
-
-
{t('对外运营模式')}
-
{t('默认模式,适用于为多个用户提供服务的场景。')}
-
- {t(
- '此模式下,系统将计算每次调用的用量,您需要对每个模型都设置价格,如果没有设置价格,用户将无法使用该模型。',
- )}
-
-
-
-
{t('自用模式')}
-
{t('适用于个人使用的场景。')}
-
- {t('不需要设置模型价格,系统将弱化用量计算,您可专注于使用模型。')}
-
-
-
-
{t('演示站点模式')}
-
{t('适用于展示系统功能的场景。')}
+
+ {/* 对外运营模式 */}
+
+
+
+
+
+
+
{t('对外运营模式')}
+
+
{t('默认模式,适用于为多个用户提供服务的场景。')}
+
{t('此模式下,系统将计算每次调用的用量,您需要对每个模型都设置价格,如果没有设置价格,用户将无法使用该模型。')}
+
+ {t('计费模式')}
+ {t('多用户支持')}
+
+
+
+
+
+
+ {/* 自用模式 */}
+
+
+
+
+
+
+
{t('自用模式')}
+
+
{t('适用于个人使用的场景。')}
+
{t('不需要设置模型价格,系统将弱化用量计算,您可专注于使用模型。')}
+
+ {t('无需计费')}
+ {t('个人使用')}
+
+
+
+
+
+
+ {/* 演示站点模式 */}
+
+
+
+
+
+
+
{t('演示站点模式')}
+
+
{t('适用于展示系统功能的场景。')}
+
{t('提供基础功能演示,方便用户了解系统特性。')}
+
+ {t('功能演示')}
+ {t('体验试用')}
+
+
+
+
+
- >
+
);
};