import { updateSettings } from "@/api/settings" import { SettingsTab } from "@/components/settings-tab" import { Button } from "@/components/ui/button" import { Card, CardContent } from "@/components/ui/card" import { Checkbox } from "@/components/ui/checkbox" import { Combobox } from "@/components/ui/combobox" import { Form, FormControl, FormDescription, FormField, FormItem, FormLabel, FormMessage, } from "@/components/ui/form" import { Input } from "@/components/ui/input" import { Label } from "@/components/ui/label" import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue, } from "@/components/ui/select" import { Textarea } from "@/components/ui/textarea" import { useAuth } from "@/hooks/useAuth" import { useNotification } from "@/hooks/useNotfication" import useSetting from "@/hooks/useSetting" import { asOptionalField, safeExternalHref } from "@/lib/utils" import { nezhaLang, settingCoverageTypes } from "@/types" import { zodResolver } from "@hookform/resolvers/zod" import { useEffect } from "react" import { useForm } from "react-hook-form" import { useTranslation } from "react-i18next" import { Navigate } from "react-router-dom" import { toast } from "sonner" import { z } from "zod" const settingFormSchema = z.object({ dns_servers: asOptionalField(z.string()), ignored_ip_notification: asOptionalField(z.string()), ip_change_notification_group_id: z.coerce.number().int().min(0), cover: z.coerce.number().int().min(1), site_name: z.string().min(1), language: z.string().min(2), user_template: z.string().min(1), install_host: asOptionalField(z.string()), dashboard_host: asOptionalField(z.string()), reserved_hosts: asOptionalField(z.string()), custom_code: asOptionalField(z.string()), custom_code_dashboard: asOptionalField(z.string()), web_real_ip_header: asOptionalField(z.string()), agent_real_ip_header: asOptionalField(z.string()), tls: asOptionalField(z.boolean()), enable_ip_change_notification: asOptionalField(z.boolean()), enable_plain_ip_in_notification: asOptionalField(z.boolean()), custom_logo: asOptionalField(z.string()), custom_description: asOptionalField(z.string()), custom_links: asOptionalField(z.string()), background_image_day: asOptionalField(z.string()), background_image_night: asOptionalField(z.string()), telegram_bot_token: asOptionalField(z.string()), telegram_admin_chat_id: asOptionalField(z.string()), smtp_server: asOptionalField(z.string()), smtp_user: asOptionalField(z.string()), smtp_password: asOptionalField(z.string()), admin_email: asOptionalField(z.string()), domain_expiry_notification_days: asOptionalField(z.string()), server_expiry_notification_days: asOptionalField(z.string()), expiry_notification_group_id: asOptionalField(z.coerce.number().int().min(0)), enable_mcp: asOptionalField(z.boolean()), }) export default function SettingsPage() { const { t, i18n } = useTranslation() const { data: config, mutate } = useSetting() const { profile, loading: authLoading } = useAuth() const { notifierGroup } = useNotification() const ngroupList = notifierGroup?.map((ng) => ({ value: `${ng.group.id}`, label: ng.group.name, })) || [{ value: "", label: "" }] const isAdmin = profile?.role === 0 // 所有 hooks 必须在条件 return 之前调用,否则违反 rules-of-hooks。 const form = useForm>({ resolver: zodResolver(settingFormSchema) as any, defaultValues: config ? { ...config.config, user_template: config.config?.user_template || Object.keys(config.frontend_templates?.filter((t) => !t.is_admin) || {})[0] || "user-dist", } : { ip_change_notification_group_id: 0, cover: 1, site_name: "", language: "", user_template: "user-dist", expiry_notification_group_id: 0, domain_expiry_notification_days: "", server_expiry_notification_days: "", }, resetOptions: { keepDefaultValues: false, }, }) useEffect(() => { if (config?.config) { form.reset(config?.config) } }, [config?.config, form]) if (authLoading) { return null } if (!isAdmin) { return } const onSubmit = async (values: any) => { try { await updateSettings(values) form.reset() await mutate() } catch (e) { toast(t("Error"), { description: t("Results.ErrorFetchingResource", { error: e?.toString(), }), }) return } if (values.language != i18n.language) { i18n.changeLanguage(values.language) } toast(t("Success")) } return (
( {t("SiteName")} )} /> ( Custom Logo URL )} /> ( Custom Description / Subtitle )} /> ( Custom Links (JSON Array) )} /> ( Background Image (Day) )} /> ( Background Image (Night) )} /> ( Telegram Bot Token )} /> ( Telegram Admin Chat ID )} /> ( SMTP Server (host:port) )} /> ( SMTP User )} /> ( SMTP Password )} /> ( Admin Email (Recipient) )} /> ( {t("Language")} )} /> ( {t("Theme")} {!config?.frontend_templates?.find( (t) => t.path === field.value, )?.is_official && (
{t("CommunityThemeWarning")}
{t("CommunityThemeDescription")}
)}
)} /> ( {t("CustomCodes")}