'use client'; import { useEffect, useState } from 'react'; import { useMutation, useQueryClient, type UseQueryResult, } from '@tanstack/react-query'; import { Globe, Loader2, Mail, Search, Server, Sparkles } from 'lucide-react'; import { Button } from '@/components/ui/button'; import { Card, CardContent, CardDescription, CardHeader, CardTitle, } from '@/components/ui/card'; import { Input } from '@/components/ui/input'; import { Label } from '@/components/ui/label'; import { Switch } from '@/components/ui/switch'; import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, } from '@/components/ui/dialog'; import { Badge } from '@/components/ui/badge'; import services from '@/lib/services'; import type { SystemConfig } from '@/lib/services/admin'; import { toast } from 'sonner'; interface SystemTabProps { configs: Record; systemConfigsQuery: UseQueryResult; } export function SystemTab({ configs, systemConfigsQuery }: SystemTabProps) { const queryClient = useQueryClient(); const [serverAddress, setServerAddress] = useState(''); const [siteName, setSiteName] = useState(''); const [smtpHost, setSmtpHost] = useState(''); const [smtpPort, setSmtpPort] = useState(''); const [smtpUsername, setSmtpUsername] = useState(''); const [smtpPassword, setSmtpPassword] = useState(''); const [smtpTestOpen, setSmtpTestOpen] = useState(false); const [smtpTestTo, setSmtpTestTo] = useState(''); const [smtpTestLog, setSmtpTestLog] = useState(''); const [smtpTestSuccess, setSmtpTestSuccess] = useState(null); const [smtpTestError, setSmtpTestError] = useState(''); useEffect(() => { if (systemConfigsQuery.data) { setServerAddress(configs['server_address']?.value || ''); setSiteName(configs['site_name']?.value || ''); setSmtpHost(configs['smtp_host']?.value || ''); setSmtpPort(configs['smtp_port']?.value || '587'); setSmtpUsername(configs['smtp_username']?.value || ''); setSmtpPassword(configs['smtp_password']?.value || ''); } }, [systemConfigsQuery.data, configs]); const handleDetectAddress = () => { if (typeof window !== 'undefined') { setServerAddress(window.location.origin); toast.success('已自动获取当前域名并填充'); } }; const updateConfigMutation = useMutation({ mutationFn: async ({ key, value }: { key: string; value: boolean }) => { const config = configs[key]; if (!config) { throw new Error(`缺少配置项: ${key}`); } await services.adminSystemConfig.updateSystemConfig(key, { value: value ? 'true' : 'false', description: config.description, }); }, onSuccess: async () => { await queryClient.invalidateQueries({ queryKey: ['admin', 'system-configs'], }); await queryClient.invalidateQueries({ queryKey: ['public-config'] }); toast.success('配置已更新'); }, onError: (error: Error) => { toast.error(error.message || '更新配置失败'); }, }); const saveSystemMutation = useMutation({ mutationFn: async () => { const currentAddrCfg = configs['server_address']; const currentSiteCfg = configs['site_name']; await Promise.all([ services.adminSystemConfig.updateSystemConfig('server_address', { value: serverAddress, description: currentAddrCfg?.description || '服务器地址', }), services.adminSystemConfig.updateSystemConfig('site_name', { value: siteName, description: currentSiteCfg?.description || '系统平台的展示名称', }), ]); }, onSuccess: async () => { await Promise.all([ queryClient.invalidateQueries({ queryKey: ['admin', 'system-configs'], }), queryClient.invalidateQueries({ queryKey: ['public-config'] }), ]); toast.success('通用配置已成功保存'); }, onError: (error: Error) => { toast.error(error.message || '保存配置失败'); }, }); const handleSystemSave = (e: React.FormEvent) => { e.preventDefault(); saveSystemMutation.mutate(); }; const saveSmtpMutation = useMutation({ mutationFn: async () => { const updates = [ { key: 'smtp_host', value: smtpHost }, { key: 'smtp_port', value: smtpPort }, { key: 'smtp_username', value: smtpUsername }, { key: 'smtp_password', value: smtpPassword }, ]; for (const update of updates) { const currentCfg = configs[update.key]; if ( update.key === 'smtp_password' && (update.value === '' || update.value === '******') ) { // If already configured and sent empty or mask, skip updating it (keep existing) if (currentCfg && currentCfg.value === '******') { continue; } } await services.adminSystemConfig.updateSystemConfig(update.key, { value: update.value, description: currentCfg?.description || '', }); } }, onSuccess: async () => { await queryClient.invalidateQueries({ queryKey: ['admin', 'system-configs'], }); toast.success('SMTP 邮件配置已成功保存'); }, onError: (error: Error) => { toast.error(error.message || '保存配置失败'); }, }); const handleSmtpSave = (e: React.FormEvent) => { e.preventDefault(); saveSmtpMutation.mutate(); }; const testSmtpMutation = useMutation({ mutationFn: async () => { setSmtpTestLog('正在发起连接测试...\n'); setSmtpTestSuccess(null); setSmtpTestError(''); const res = await services.adminSystemConfig.testSMTP({ smtp_host: smtpHost, smtp_port: parseInt(smtpPort, 10) || 587, smtp_username: smtpUsername, smtp_password: smtpPassword, to: smtpTestTo, }); return res; }, onSuccess: (data) => { setSmtpTestLog(data.log); if (data.success) { setSmtpTestSuccess(true); toast.success('测试邮件发送成功'); } else { setSmtpTestSuccess(false); setSmtpTestError(data.error || '发送失败,请检查配置和日志。'); toast.error('测试邮件发送失败'); } }, onError: (error: Error) => { setSmtpTestSuccess(false); setSmtpTestError(error.message || '请求发送失败'); setSmtpTestLog((prev) => prev + `\n[请求错误] ${error.message}\n`); toast.error(error.message || '测试请求发送失败'); }, }); const handleSmtpTestSubmit = (e: React.FormEvent) => { e.preventDefault(); if (!smtpTestTo) { toast.error('请输入目标邮箱地址'); return; } testSmtpMutation.mutate(); }; const indexingEnabled = configs['search_engine_indexing_enabled']?.value === 'true'; return (
{/* 通用设置 */}
通用设置 配置站点标识、服务地址与搜索引擎收录策略
setSiteName(e.target.value)} placeholder='例如: OpenFlare' className='border-dashed bg-card text-xs' />

用于网页标题、登录注册页面、管理后台与系统邮件。

setServerAddress(e.target.value)} placeholder='例如: https://example.com' className='border-dashed bg-card text-xs' />

限定 API 的允许来源;留空将开放任意来源访问。

搜索引擎抓取与收录 {indexingEnabled ? '允许收录' : '禁止收录'}

控制 Google、Baidu、Bing 等搜索引擎是否可以索引公开页面。

updateConfigMutation.mutate({ key: 'search_engine_indexing_enabled', value: checked, }) } />
地址变更会影响跨域访问策略,请填写完整协议与域名。
{/* SMTP 邮件设置 */}
SMTP 邮件设置 配置系统的邮件发送服务 (SMTP)
setSmtpHost(e.target.value)} placeholder='例如: smtp.example.com' className='bg-card border-dashed text-xs' />
setSmtpPort(e.target.value)} placeholder='例如: 587 或 465' className='bg-card border-dashed text-xs' />
setSmtpUsername(e.target.value)} placeholder='例如: sender@example.com' className='bg-card border-dashed text-xs' />
setSmtpPassword(e.target.value)} placeholder={ configs['smtp_password']?.value === '******' ? '•••••• (已配置,留空或输入新值)' : '输入凭证密码' } className='bg-card border-dashed text-xs' />
SMTP 发件测试 输入接收测试邮件的邮箱地址。系统将使用您在表单中当前填写的 SMTP 配置进行发件测试。
setSmtpTestTo(e.target.value)} placeholder='例如: receiver@example.com' className='bg-card border-dashed text-xs' disabled={testSmtpMutation.isPending} />
{smtpTestLog && (
                  {smtpTestLog}
                
)} {smtpTestSuccess === true && (
测试成功!邮件已顺利发出。
)} {smtpTestSuccess === false && (
测试失败:{smtpTestError}
)}
); }