import React, { useEffect, useState, useRef } from 'react'; import { Card, Form, Button, Typography, Modal, Banner, Layout, Tag, } from '@douyinfe/semi-ui'; import { API, showError, showNotice } from '../../helpers'; import { useTranslation } from 'react-i18next'; import { IconHelpCircle, IconInfoCircle, IconUser, IconLock, IconSetting, IconCheckCircleStroked, } from '@douyinfe/semi-icons'; import { Shield, Rocket, FlaskConical, Database, Layers } from 'lucide-react'; const Setup = () => { const { t } = useTranslation(); const [loading, setLoading] = useState(false); const [selfUseModeInfoVisible, setUsageModeInfoVisible] = useState(false); const [setupStatus, setSetupStatus] = useState({ status: false, root_init: false, database_type: '', }); const { Text, Title } = Typography; const formRef = useRef(null); const [formData, setFormData] = useState({ username: '', password: '', confirmPassword: '', usageMode: 'external', }); useEffect(() => { fetchSetupStatus(); }, []); const fetchSetupStatus = async () => { try { const res = await API.get('/api/setup'); const { success, data } = res.data; if (success) { setSetupStatus(data); // If setup is already completed, redirect to home if (data.status) { window.location.href = '/'; } } else { showError(t('获取初始化状态失败')); } } catch (error) { console.error('Failed to fetch setup status:', error); showError(t('获取初始化状态失败')); } }; const handleUsageModeChange = (val) => { setFormData({ ...formData, usageMode: val }); }; const onSubmit = () => { if (!formRef.current) { console.error('Form reference is null'); showError(t('表单引用错误,请刷新页面重试')); return; } const values = formRef.current.getValues(); console.log('Form values:', values); // For root_init=false, validate admin username and password if (!setupStatus.root_init) { if (!values.username || !values.username.trim()) { showError(t('请输入管理员用户名')); return; } if (!values.password || values.password.length < 8) { showError(t('密码长度至少为8个字符')); return; } if (values.password !== values.confirmPassword) { showError(t('两次输入的密码不一致')); return; } } // Prepare submission data const formValues = { ...values }; formValues.SelfUseModeEnabled = values.usageMode === 'self'; formValues.DemoSiteEnabled = values.usageMode === 'demo'; // Remove usageMode as it's not needed by the backend delete formValues.usageMode; console.log('Submitting data to backend:', formValues); setLoading(true); // Submit to backend API.post('/api/setup', formValues) .then((res) => { const { success, message } = res.data; console.log('API response:', res.data); if (success) { showNotice(t('系统初始化成功,正在跳转...')); setTimeout(() => { window.location.reload(); }, 1500); } else { showError(message || t('初始化失败,请重试')); } }) .catch((error) => { console.error('API error:', error); showError(t('系统初始化失败,请重试')); setLoading(false); }) .finally(() => { // setLoading(false); }); }; return (
{/* 主卡片容器 */} {/* 顶部装饰性区域 */} {/* 装饰性背景元素 */}
{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 />
)} {/* 主内容区域 */}
{ formRef.current = formApi; console.log('Form API set:', formApi); }} initValues={formData} > {/* 管理员账号设置 */}
{t('管理员账号')}
{t('设置系统管理员的登录信息')}
{setupStatus.root_init ? ( <> } 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} mode="password" validateStatus="default" onChange={(value) => setFormData({ ...formData, password: value }) } /> } showClear size='large' className="!rounded-lg" noLabel={false} mode="password" validateStatus="default" onChange={(value) => setFormData({ ...formData, confirmPassword: value }) } /> )}
{/* 使用模式 */}
{t('使用模式')}
{t('选择适合您使用场景的模式')}
{t('对外运营模式')}
{t('适用于为多个用户提供服务的场景')}
{t('默认模式')}
} />
{t('自用模式')}
{t('适用于个人使用的场景,不需要设置模型价格')}
{t('无需计费')}
} />
{t('演示站点模式')}
{t('适用于展示系统功能的场景,提供基础功能演示')}
{t('演示体验')}
} />
{/* 使用模式说明模态框 */} {t('使用模式说明')} } visible={selfUseModeInfoVisible} onOk={() => setUsageModeInfoVisible(false)} onCancel={() => setUsageModeInfoVisible(false)} closeOnEsc={true} 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('体验试用')}
); }; export default Setup;