import { useState } from 'react'; import { useTranslation } from 'react-i18next'; import { AutoComplete, Button, Collapse, Divider, Form, Input, InputNumber, Select, Space, Switch, message, } from 'antd'; import { CloudDownloadOutlined, SyncOutlined } from '@ant-design/icons'; import { useFormContext, useWatch } from 'react-hook-form'; import { FormField } from '@/components/form/rhf'; import { HttpUtil } from '@/utils'; export default function TuicFields() { const { t } = useTranslation(); const [messageApi, messageContextHolder] = message.useMessage(); const { control, setValue } = useFormContext(); const [loadingPanelCert, setLoadingPanelCert] = useState(false); const sni = (useWatch({ control, name: 'settings.server.sni' }) ?? '') as string; const certificate = (useWatch({ control, name: 'settings.server.certificate' }) ?? '') as string; const privateKey = (useWatch({ control, name: 'settings.server.private_key' }) ?? '') as string; const nodeId = useWatch({ control, name: 'nodeId' }) as number | null | undefined; const handleSniChange = (newSni: string) => { setValue('settings.server.sni', newSni); }; const autofillFromSni = () => { const cleanSni = (sni || '').trim(); if (!cleanSni) { messageApi.warning(t('pages.xray.tuic.sniRequired')); return; } setValue('settings.server.certificate', `/root/cert/${cleanSni}/fullchain.pem`); setValue('settings.server.private_key', `/root/cert/${cleanSni}/privkey.pem`); }; const setCertFromPanel = async () => { setLoadingPanelCert(true); try { const msg = typeof nodeId === 'number' ? await HttpUtil.get(`/panel/api/nodes/webCert/${nodeId}`, undefined, { silent: true }) : await HttpUtil.post('/panel/api/setting/all', undefined, { silent: true }); if (!msg?.success) { messageApi.warning(msg?.msg || t('pages.inbounds.setDefaultCertEmpty')); return; } const obj = msg.obj as { webCertFile?: string; webKeyFile?: string }; if (!obj?.webCertFile && !obj?.webKeyFile) { messageApi.warning(t('pages.inbounds.setDefaultCertEmpty')); return; } if (obj.webCertFile) { setValue('settings.server.certificate', obj.webCertFile); } if (obj.webKeyFile) { setValue('settings.server.private_key', obj.webKeyFile); } messageApi.success(t('pages.inbounds.setSuccess')); } catch { messageApi.error(t('somethingWentWrong')); } finally { setLoadingPanelCert(false); } }; const certOptions = sni ? [ { value: `/root/cert/${sni}/fullchain.pem` }, { value: `/etc/letsencrypt/live/${sni}/fullchain.pem` }, { value: '/root/cert.pem' }, ] : [{ value: '/root/cert.pem' }]; const keyOptions = sni ? [ { value: `/root/cert/${sni}/privkey.pem` }, { value: `/etc/letsencrypt/live/${sni}/privkey.pem` }, { value: '/root/privkey.pem' }, ] : [{ value: '/root/privkey.pem' }]; const advancedItems = [ { key: 'advanced', label: t('pages.inbounds.advancedTitle'), children: ( <> handleSniChange(e.target.value)} />