"use client" import {useEffect, useState} from "react" import {useMutation, useQueryClient} from "@tanstack/react-query" import {Loader2, Mail, Server} 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 {Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle} from "@/components/ui/dialog" import {AdminService} from "@/lib/services" import type {SystemConfig} from "@/lib/services/admin" import {toast} from "sonner" interface SystemTabProps { configs: Record systemConfigsQuery: any } export function SystemTab({ configs, systemConfigsQuery }: SystemTabProps) { const queryClient = useQueryClient() const [serverAddress, setServerAddress] = 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 || "") 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 saveSystemMutation = useMutation({ mutationFn: async () => { const currentCfg = configs["server_address"] await AdminService.updateSystemConfig("server_address", { value: serverAddress, description: currentCfg?.description || "服务器地址", }) }, onSuccess: async () => { await queryClient.invalidateQueries({ queryKey: ["admin", "system-configs"] }) 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 AdminService.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 AdminService.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() } return (
{/* 通用设置 */}
通用设置 配置系统的全局通用参数
setServerAddress(e.target.value)} placeholder="例如: https://example.com" className="bg-card border-dashed text-xs" />

这里可以编辑更改服务器地址。默认不设定,允许从任意源(*)访问 API,此时存在跨域安全风险;如果手动设置服务器地址,CORS 允许源将更新为该地址,消除跨域安全隐患。

{/* 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}
)}
) }