🎨 refactor(ui): modernize setup page
- Refactored system initialization page using TailwindCSS 3 and SemiUI components - Changed layout from step navigation to single page display for all configurations - Modified top area from vertical to more compact horizontal layout - Updated gradient color scheme from blue/purple to orange/pink - Fixed form field name duplication issues and optimized Form implementation - Changed usage mode selection from three-column grid to vertical layout - Replaced usage mode card icons from settings to more appropriate Layers icon - Added specific prompts for different database types (SQLite/MySQL/PostgreSQL) - Removed configuration summary section while keeping the initialization button - Fixed useSetupCheck issue by using SetupCheck as a direct component for proper redirection
This commit is contained in:
@@ -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 (
|
||||
<useSetupCheck>
|
||||
<SetupCheck>
|
||||
<Routes>
|
||||
<Route
|
||||
path='/'
|
||||
@@ -290,7 +290,7 @@ function App() {
|
||||
/>
|
||||
<Route path='*' element={<NotFound />} />
|
||||
</Routes>
|
||||
</useSetupCheck>
|
||||
</SetupCheck>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
18
web/src/components/layout/SetupCheck.js
Normal file
18
web/src/components/layout/SetupCheck.js
Normal file
@@ -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;
|
||||
@@ -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
|
||||
};
|
||||
}
|
||||
@@ -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);
|
||||
|
||||
@@ -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."
|
||||
}
|
||||
@@ -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 (
|
||||
<>
|
||||
<div style={{ maxWidth: '800px', margin: '0 auto', padding: '20px' }}>
|
||||
<Card>
|
||||
<Title heading={2} style={{ marginBottom: '24px' }}>
|
||||
{t('系统初始化')}
|
||||
</Title>
|
||||
|
||||
{setupStatus.database_type === 'sqlite' && (
|
||||
<Banner
|
||||
type='warning'
|
||||
icon={<IconAlertTriangle size='large' />}
|
||||
closeIcon={null}
|
||||
title={t('数据库警告')}
|
||||
description={
|
||||
<div>
|
||||
<p>
|
||||
{t(
|
||||
'您正在使用 SQLite 数据库。如果您在容器环境中运行,请确保已正确设置数据库文件的持久化映射,否则容器重启后所有数据将丢失!',
|
||||
)}
|
||||
</p>
|
||||
<p>
|
||||
{t(
|
||||
'建议在生产环境中使用 MySQL 或 PostgreSQL 数据库,或确保 SQLite 数据库文件已映射到宿主机的持久化存储。',
|
||||
)}
|
||||
</p>
|
||||
</div>
|
||||
}
|
||||
style={{ marginBottom: '24px' }}
|
||||
/>
|
||||
)}
|
||||
|
||||
<Form
|
||||
getFormApi={(formApi) => {
|
||||
formRef.current = formApi;
|
||||
console.log('Form API set:', formApi);
|
||||
}}
|
||||
initValues={formData}
|
||||
>
|
||||
{setupStatus.root_init ? (
|
||||
<Banner
|
||||
type='info'
|
||||
icon={<IconInfoCircle />}
|
||||
closeIcon={null}
|
||||
description={t('管理员账号已经初始化过,请继续设置系统参数')}
|
||||
style={{ marginBottom: '24px' }}
|
||||
/>
|
||||
) : (
|
||||
<Form.Section text={t('管理员账号')}>
|
||||
<Form.Input
|
||||
field='username'
|
||||
label={t('用户名')}
|
||||
placeholder={t('请输入管理员用户名')}
|
||||
showClear
|
||||
onChange={(value) =>
|
||||
setFormData({ ...formData, username: value })
|
||||
}
|
||||
/>
|
||||
<Form.Input
|
||||
field='password'
|
||||
label={t('密码')}
|
||||
placeholder={t('请输入管理员密码')}
|
||||
type='password'
|
||||
showClear
|
||||
onChange={(value) =>
|
||||
setFormData({ ...formData, password: value })
|
||||
}
|
||||
/>
|
||||
<Form.Input
|
||||
field='confirmPassword'
|
||||
label={t('确认密码')}
|
||||
placeholder={t('请确认管理员密码')}
|
||||
type='password'
|
||||
showClear
|
||||
onChange={(value) =>
|
||||
setFormData({ ...formData, confirmPassword: value })
|
||||
}
|
||||
/>
|
||||
</Form.Section>
|
||||
)}
|
||||
|
||||
<Form.Section
|
||||
text={
|
||||
<div style={{ display: 'flex', alignItems: 'center' }}>
|
||||
{t('系统设置')}
|
||||
</div>
|
||||
}
|
||||
>
|
||||
<Form.RadioGroup
|
||||
field='usageMode'
|
||||
label={
|
||||
<div style={{ display: 'flex', alignItems: 'center' }}>
|
||||
{t('使用模式')}
|
||||
<IconHelpCircle
|
||||
style={{
|
||||
marginLeft: '4px',
|
||||
color: 'var(--semi-color-primary)',
|
||||
verticalAlign: 'middle',
|
||||
cursor: 'pointer',
|
||||
}}
|
||||
onClick={(e) => {
|
||||
// e.preventDefault();
|
||||
// e.stopPropagation();
|
||||
setUsageModeInfoVisible(true);
|
||||
}}
|
||||
/>
|
||||
<div className="min-h-screen bg-gray-50">
|
||||
<Layout>
|
||||
<Layout.Content>
|
||||
<div className="flex justify-center px-4 py-8">
|
||||
<div className="w-full max-w-3xl">
|
||||
{/* 主卡片容器 */}
|
||||
<Card className="!rounded-2xl shadow-lg border-0">
|
||||
{/* 顶部装饰性区域 */}
|
||||
<Card
|
||||
className="!rounded-2xl !border-0 !shadow-2xl overflow-hidden mb-6"
|
||||
style={{
|
||||
background: 'linear-gradient(135deg, #f97316 0%, #f59e0b 25%, #f43f5e 50%, #ec4899 75%, #e879f9 100%)',
|
||||
position: 'relative'
|
||||
}}
|
||||
bodyStyle={{ padding: 0 }}
|
||||
>
|
||||
{/* 装饰性背景元素 */}
|
||||
<div className="absolute inset-0 overflow-hidden">
|
||||
<div className="absolute -top-10 -right-10 w-40 h-40 bg-white opacity-10 rounded-full"></div>
|
||||
<div className="absolute -bottom-16 -left-16 w-48 h-48 bg-white opacity-5 rounded-full"></div>
|
||||
<div className="absolute top-1/2 right-1/4 w-24 h-24 bg-yellow-400 opacity-10 rounded-full"></div>
|
||||
</div>
|
||||
}
|
||||
extraText={t('可在初始化后修改')}
|
||||
initValue='external'
|
||||
onChange={handleUsageModeChange}
|
||||
>
|
||||
<Form.Radio value='external'>{t('对外运营模式')}</Form.Radio>
|
||||
<Form.Radio value='self'>{t('自用模式')}</Form.Radio>
|
||||
<Form.Radio value='demo'>{t('演示站点模式')}</Form.Radio>
|
||||
</Form.RadioGroup>
|
||||
</Form.Section>
|
||||
</Form>
|
||||
|
||||
<div style={{ marginTop: '24px', textAlign: 'right' }}>
|
||||
<Button type='primary' onClick={onSubmit} loading={loading}>
|
||||
{t('初始化系统')}
|
||||
</Button>
|
||||
<div className="relative py-5 px-6 flex items-center" style={{ color: 'white' }}>
|
||||
<div className="w-14 h-14 rounded-full bg-white bg-opacity-20 flex items-center justify-center mr-5 shadow-lg flex-shrink-0">
|
||||
<IconSetting size="large" style={{ color: 'white' }} />
|
||||
</div>
|
||||
<div className="text-left">
|
||||
<Title heading={3} style={{ color: 'white', marginBottom: '2px' }}>
|
||||
{t('系统初始化')}
|
||||
</Title>
|
||||
<Text style={{ color: 'rgba(255, 255, 255, 0.9)', fontSize: '15px' }}>
|
||||
{t('欢迎使用,请完成以下设置以开始使用系统')}
|
||||
</Text>
|
||||
</div>
|
||||
</div>
|
||||
{/* 数据库警告 */}
|
||||
{setupStatus.database_type === 'sqlite' && (
|
||||
<div className="px-4">
|
||||
<Banner
|
||||
type='warning'
|
||||
icon={
|
||||
<div className="w-12 h-12 rounded-lg bg-orange-50 flex items-center justify-center">
|
||||
<Database size={22} className="text-orange-500" />
|
||||
</div>
|
||||
}
|
||||
closeIcon={null}
|
||||
title={
|
||||
<div className="flex items-center">
|
||||
<span className="font-medium">{t('数据库警告')}</span>
|
||||
<Tag color='orange' size='small' className="ml-2 !rounded-full">
|
||||
SQLite
|
||||
</Tag>
|
||||
</div>
|
||||
}
|
||||
description={
|
||||
<div>
|
||||
<p>
|
||||
{t(
|
||||
'您正在使用 SQLite 数据库。如果您在容器环境中运行,请确保已正确设置数据库文件的持久化映射,否则容器重启后所有数据将丢失!',
|
||||
)}
|
||||
</p>
|
||||
<p className="mt-1">
|
||||
<strong>{t(
|
||||
'建议在生产环境中使用 MySQL 或 PostgreSQL 数据库,或确保 SQLite 数据库文件已映射到宿主机的持久化存储。',
|
||||
)}</strong>
|
||||
</p>
|
||||
</div>
|
||||
}
|
||||
className="!rounded-xl mb-6"
|
||||
fullMode={false}
|
||||
bordered
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
{/* MySQL数据库提示 */}
|
||||
{setupStatus.database_type === 'mysql' && (
|
||||
<div className="px-4">
|
||||
<Banner
|
||||
type='info'
|
||||
icon={
|
||||
<div className="w-12 h-12 rounded-lg bg-blue-50 flex items-center justify-center">
|
||||
<Database size={22} className="text-blue-500" />
|
||||
</div>
|
||||
}
|
||||
closeIcon={null}
|
||||
title={
|
||||
<div className="flex items-center">
|
||||
<span className="font-medium">{t('数据库信息')}</span>
|
||||
<Tag color='blue' size='small' className="ml-2 !rounded-full">
|
||||
MySQL
|
||||
</Tag>
|
||||
</div>
|
||||
}
|
||||
description={
|
||||
<div>
|
||||
<p>
|
||||
{t(
|
||||
'您正在使用 MySQL 数据库。MySQL 是一个可靠的关系型数据库管理系统,适合生产环境使用。',
|
||||
)}
|
||||
</p>
|
||||
</div>
|
||||
}
|
||||
className="!rounded-xl mb-6"
|
||||
fullMode={false}
|
||||
bordered
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
{/* PostgreSQL数据库提示 */}
|
||||
{setupStatus.database_type === 'postgres' && (
|
||||
<div className="px-4">
|
||||
<Banner
|
||||
type='success'
|
||||
icon={
|
||||
<div className="w-12 h-12 rounded-lg bg-green-50 flex items-center justify-center">
|
||||
<Database size={22} className="text-green-500" />
|
||||
</div>
|
||||
}
|
||||
closeIcon={null}
|
||||
title={
|
||||
<div className="flex items-center">
|
||||
<span className="font-medium">{t('数据库信息')}</span>
|
||||
<Tag color='green' size='small' className="ml-2 !rounded-full">
|
||||
PostgreSQL
|
||||
</Tag>
|
||||
</div>
|
||||
}
|
||||
description={
|
||||
<div>
|
||||
<p>
|
||||
{t(
|
||||
'您正在使用 PostgreSQL 数据库。PostgreSQL 是一个功能强大的开源关系型数据库系统,提供了出色的可靠性和数据完整性,适合生产环境使用。',
|
||||
)}
|
||||
</p>
|
||||
</div>
|
||||
}
|
||||
className="!rounded-xl mb-6"
|
||||
fullMode={false}
|
||||
bordered
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
</Card>
|
||||
|
||||
{/* 主内容区域 */}
|
||||
<Form
|
||||
getFormApi={(formApi) => {
|
||||
formRef.current = formApi;
|
||||
console.log('Form API set:', formApi);
|
||||
}}
|
||||
initValues={formData}
|
||||
>
|
||||
{/* 管理员账号设置 */}
|
||||
<Card className="!rounded-2xl shadow-sm border-0 mb-6">
|
||||
<div className="flex items-center mb-4 p-6 rounded-xl" style={{
|
||||
background: 'linear-gradient(135deg, #1e3a8a 0%, #2563eb 50%, #3b82f6 100%)',
|
||||
position: 'relative'
|
||||
}}>
|
||||
<div className="absolute inset-0 overflow-hidden">
|
||||
<div className="absolute -top-10 -right-10 w-40 h-40 bg-white opacity-5 rounded-full"></div>
|
||||
<div className="absolute -bottom-8 -left-8 w-24 h-24 bg-white opacity-10 rounded-full"></div>
|
||||
</div>
|
||||
<div className="w-10 h-10 rounded-full bg-white/20 flex items-center justify-center mr-4 relative">
|
||||
<IconUser size="large" style={{ color: '#ffffff' }} />
|
||||
</div>
|
||||
<div className="relative">
|
||||
<Text style={{ color: '#ffffff' }} className="text-lg font-medium">{t('管理员账号')}</Text>
|
||||
<div style={{ color: '#ffffff' }} className="text-sm opacity-80">{t('设置系统管理员的登录信息')}</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{setupStatus.root_init ? (
|
||||
<>
|
||||
<Banner
|
||||
type='info'
|
||||
icon={
|
||||
<div className="w-10 h-10 rounded-full bg-blue-50 flex items-center justify-center">
|
||||
<IconCheckCircleStroked size="large" className="text-blue-500" />
|
||||
</div>
|
||||
}
|
||||
closeIcon={null}
|
||||
description={
|
||||
<div className="flex items-center">
|
||||
<span>{t('管理员账号已经初始化过,请继续设置其他参数')}</span>
|
||||
</div>
|
||||
}
|
||||
className="!rounded-lg"
|
||||
/>
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
<Form.Input
|
||||
field='username'
|
||||
label={t('用户名')}
|
||||
placeholder={t('请输入管理员用户名')}
|
||||
prefix={<IconUser />}
|
||||
showClear
|
||||
size='large'
|
||||
className="mb-4 !rounded-lg"
|
||||
noLabel={false}
|
||||
validateStatus="default"
|
||||
onChange={(value) =>
|
||||
setFormData({ ...formData, username: value })
|
||||
}
|
||||
/>
|
||||
<Form.Input
|
||||
field='password'
|
||||
label={t('密码')}
|
||||
placeholder={t('请输入管理员密码')}
|
||||
type='password'
|
||||
prefix={<IconLock />}
|
||||
showClear
|
||||
size='large'
|
||||
className="mb-4 !rounded-lg"
|
||||
noLabel={false}
|
||||
validateStatus="default"
|
||||
onChange={(value) =>
|
||||
setFormData({ ...formData, password: value })
|
||||
}
|
||||
/>
|
||||
<Form.Input
|
||||
field='confirmPassword'
|
||||
label={t('确认密码')}
|
||||
placeholder={t('请确认管理员密码')}
|
||||
type='password'
|
||||
prefix={<IconLock />}
|
||||
showClear
|
||||
size='large'
|
||||
className="!rounded-lg"
|
||||
noLabel={false}
|
||||
validateStatus="default"
|
||||
onChange={(value) =>
|
||||
setFormData({ ...formData, confirmPassword: value })
|
||||
}
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
</Card>
|
||||
|
||||
{/* 使用模式 */}
|
||||
<Card className="!rounded-2xl shadow-sm border-0 mb-6">
|
||||
<div className="flex items-center mb-4 p-6 rounded-xl" style={{
|
||||
background: 'linear-gradient(135deg, #4c1d95 0%, #6d28d9 50%, #7c3aed 100%)',
|
||||
position: 'relative'
|
||||
}}>
|
||||
<div className="absolute inset-0 overflow-hidden">
|
||||
<div className="absolute -top-10 -right-10 w-40 h-40 bg-white opacity-5 rounded-full"></div>
|
||||
<div className="absolute -bottom-8 -left-8 w-24 h-24 bg-white opacity-10 rounded-full"></div>
|
||||
</div>
|
||||
<div className="w-10 h-10 rounded-full bg-white/20 flex items-center justify-center mr-4 relative">
|
||||
<Layers size={22} style={{ color: '#ffffff' }} />
|
||||
</div>
|
||||
<div className="relative">
|
||||
<div className="flex items-center">
|
||||
<Text style={{ color: '#ffffff' }} className="text-lg font-medium">{t('使用模式')}</Text>
|
||||
<Button
|
||||
theme='borderless'
|
||||
type='tertiary'
|
||||
icon={<IconHelpCircle size="small" style={{ color: '#ffffff' }} />}
|
||||
size='small'
|
||||
onClick={() => setUsageModeInfoVisible(true)}
|
||||
className="!rounded-full"
|
||||
/>
|
||||
</div>
|
||||
<div style={{ color: '#ffffff' }} className="text-sm opacity-80">{t('选择适合您使用场景的模式')}</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<Form.RadioGroup
|
||||
field='usageMode'
|
||||
noLabel={true}
|
||||
initValue='external'
|
||||
onChange={handleUsageModeChange}
|
||||
type='pureCard'
|
||||
className="[&_.semi-radio-addon-buttonRadio-wrapper]:!rounded-xl"
|
||||
validateStatus="default"
|
||||
>
|
||||
<div className="space-y-3 mt-2">
|
||||
<Form.Radio
|
||||
value='external'
|
||||
className="!p-4 !rounded-xl hover:!bg-blue-50 transition-colors w-full"
|
||||
extra={
|
||||
<div className="flex items-start">
|
||||
<div className="w-10 h-10 rounded-full bg-blue-50 flex items-center justify-center mr-3 flex-shrink-0">
|
||||
<Rocket size={20} className="text-blue-500" />
|
||||
</div>
|
||||
<div className="flex-1">
|
||||
<div className="font-medium text-gray-900 mb-1">{t('对外运营模式')}</div>
|
||||
<div className="text-sm text-gray-500">{t('适用于为多个用户提供服务的场景')}</div>
|
||||
<Tag color='blue' size='small' className="!rounded-full mt-2">
|
||||
{t('默认模式')}
|
||||
</Tag>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
/>
|
||||
<Form.Radio
|
||||
value='self'
|
||||
className="!p-4 !rounded-xl hover:!bg-green-50 transition-colors w-full"
|
||||
extra={
|
||||
<div className="flex items-start">
|
||||
<div className="w-10 h-10 rounded-full bg-green-50 flex items-center justify-center mr-3 flex-shrink-0">
|
||||
<Shield size={20} className="text-green-500" />
|
||||
</div>
|
||||
<div className="flex-1">
|
||||
<div className="font-medium text-gray-900 mb-1">{t('自用模式')}</div>
|
||||
<div className="text-sm text-gray-500">{t('适用于个人使用的场景,不需要设置模型价格')}</div>
|
||||
<Tag color='green' size='small' className="!rounded-full mt-2">
|
||||
{t('无需计费')}
|
||||
</Tag>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
/>
|
||||
<Form.Radio
|
||||
value='demo'
|
||||
className="!p-4 !rounded-xl hover:!bg-purple-50 transition-colors w-full"
|
||||
extra={
|
||||
<div className="flex items-start">
|
||||
<div className="w-10 h-10 rounded-full bg-purple-50 flex items-center justify-center mr-3 flex-shrink-0">
|
||||
<FlaskConical size={20} className="text-purple-500" />
|
||||
</div>
|
||||
<div className="flex-1">
|
||||
<div className="font-medium text-gray-900 mb-1">{t('演示站点模式')}</div>
|
||||
<div className="text-sm text-gray-500">{t('适用于展示系统功能的场景,提供基础功能演示')}</div>
|
||||
<Tag color='purple' size='small' className="!rounded-full mt-2">
|
||||
{t('演示体验')}
|
||||
</Tag>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
</Form.RadioGroup>
|
||||
</Card>
|
||||
</Form>
|
||||
|
||||
<div className="flex justify-center mt-6">
|
||||
<Button
|
||||
type='primary'
|
||||
onClick={onSubmit}
|
||||
loading={loading}
|
||||
size='large'
|
||||
className="!rounded-lg !bg-gradient-to-r !from-orange-500 !to-pink-500 hover:!from-orange-600 hover:!to-pink-600 !border-0 !px-8"
|
||||
icon={<IconCheckCircleStroked />}
|
||||
>
|
||||
{t('初始化系统')}
|
||||
</Button>
|
||||
</div>
|
||||
</Card>
|
||||
</div>
|
||||
</div>
|
||||
</Card>
|
||||
</div>
|
||||
</Layout.Content>
|
||||
</Layout>
|
||||
|
||||
{/* 使用模式说明模态框 */}
|
||||
<Modal
|
||||
title={t('使用模式说明')}
|
||||
title={
|
||||
<div className="flex items-center">
|
||||
<IconInfoCircle className="mr-2 text-blue-500" />
|
||||
{t('使用模式说明')}
|
||||
</div>
|
||||
}
|
||||
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"
|
||||
>
|
||||
<div style={{ padding: '8px 0' }}>
|
||||
<Title heading={6}>{t('对外运营模式')}</Title>
|
||||
<p>{t('默认模式,适用于为多个用户提供服务的场景。')}</p>
|
||||
<p>
|
||||
{t(
|
||||
'此模式下,系统将计算每次调用的用量,您需要对每个模型都设置价格,如果没有设置价格,用户将无法使用该模型。',
|
||||
)}
|
||||
</p>
|
||||
</div>
|
||||
<div style={{ padding: '8px 0' }}>
|
||||
<Title heading={6}>{t('自用模式')}</Title>
|
||||
<p>{t('适用于个人使用的场景。')}</p>
|
||||
<p>
|
||||
{t('不需要设置模型价格,系统将弱化用量计算,您可专注于使用模型。')}
|
||||
</p>
|
||||
</div>
|
||||
<div style={{ padding: '8px 0' }}>
|
||||
<Title heading={6}>{t('演示站点模式')}</Title>
|
||||
<p>{t('适用于展示系统功能的场景。')}</p>
|
||||
<div className="space-y-6">
|
||||
{/* 对外运营模式 */}
|
||||
<div className="bg-blue-50 rounded-xl p-4">
|
||||
<div className="flex items-start">
|
||||
<div className="w-10 h-10 rounded-full bg-blue-100 flex items-center justify-center mr-3 flex-shrink-0">
|
||||
<Rocket size={20} className="text-blue-600" />
|
||||
</div>
|
||||
<div>
|
||||
<Title heading={6} className="text-blue-900 mb-2">{t('对外运营模式')}</Title>
|
||||
<div className="space-y-2 text-sm text-gray-700">
|
||||
<p>{t('默认模式,适用于为多个用户提供服务的场景。')}</p>
|
||||
<p>{t('此模式下,系统将计算每次调用的用量,您需要对每个模型都设置价格,如果没有设置价格,用户将无法使用该模型。')}</p>
|
||||
<div className="mt-3">
|
||||
<Tag color='blue' className="!rounded-full mr-2">{t('计费模式')}</Tag>
|
||||
<Tag color='blue' className="!rounded-full">{t('多用户支持')}</Tag>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* 自用模式 */}
|
||||
<div className="bg-green-50 rounded-xl p-4">
|
||||
<div className="flex items-start">
|
||||
<div className="w-10 h-10 rounded-full bg-green-100 flex items-center justify-center mr-3 flex-shrink-0">
|
||||
<Shield size={20} className="text-green-600" />
|
||||
</div>
|
||||
<div>
|
||||
<Title heading={6} className="text-green-900 mb-2">{t('自用模式')}</Title>
|
||||
<div className="space-y-2 text-sm text-gray-700">
|
||||
<p>{t('适用于个人使用的场景。')}</p>
|
||||
<p>{t('不需要设置模型价格,系统将弱化用量计算,您可专注于使用模型。')}</p>
|
||||
<div className="mt-3">
|
||||
<Tag color='green' className="!rounded-full mr-2">{t('无需计费')}</Tag>
|
||||
<Tag color='green' className="!rounded-full">{t('个人使用')}</Tag>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* 演示站点模式 */}
|
||||
<div className="bg-purple-50 rounded-xl p-4">
|
||||
<div className="flex items-start">
|
||||
<div className="w-10 h-10 rounded-full bg-purple-100 flex items-center justify-center mr-3 flex-shrink-0">
|
||||
<FlaskConical size={20} className="text-purple-600" />
|
||||
</div>
|
||||
<div>
|
||||
<Title heading={6} className="text-purple-900 mb-2">{t('演示站点模式')}</Title>
|
||||
<div className="space-y-2 text-sm text-gray-700">
|
||||
<p>{t('适用于展示系统功能的场景。')}</p>
|
||||
<p>{t('提供基础功能演示,方便用户了解系统特性。')}</p>
|
||||
<div className="mt-3">
|
||||
<Tag color='purple' className="!rounded-full mr-2">{t('功能演示')}</Tag>
|
||||
<Tag color='purple' className="!rounded-full">{t('体验试用')}</Tag>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</Modal>
|
||||
</>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user