From 007afd3b83c40d8c2b56573cc315d126fc89da4a Mon Sep 17 00:00:00 2001 From: Den Piligrim <89912505+vasiljevdenis@users.noreply.github.com> Date: Tue, 3 Feb 2026 10:34:24 +0300 Subject: [PATCH] fix errors --- client/src/components/Footer.tsx | 2 +- client/src/pages/SettingsPage.tsx | 76 +++++++++++++++++-- install.sh | 8 +- server/src/rotation/rotation.service.ts | 9 ++- server/src/settings/settings.controller.ts | 8 ++ server/src/settings/settings.module.ts | 3 +- .../subscriptions/subscriptions.service.ts | 1 - server/src/xui/xui.service.ts | 23 ++++++ 8 files changed, 113 insertions(+), 17 deletions(-) diff --git a/client/src/components/Footer.tsx b/client/src/components/Footer.tsx index 2bc8c9a..0b2fc2f 100644 --- a/client/src/components/Footer.tsx +++ b/client/src/components/Footer.tsx @@ -42,7 +42,7 @@ export default function Footer() { (''); + const [loadingRotate, setLoadingRotate] = useState(false); useEffect(() => { loadSettings(); @@ -37,6 +38,42 @@ export default function SettingsPage() { } }, [settings.rotation_interval]); + const cleanData = () => { + const cleaned = { ...settings }; + + if (cleaned.xui_url) { + cleaned.xui_url = cleaned.xui_url.replace(/\/+$/, ''); + } + + if (cleaned.xui_login) cleaned.xui_login = cleaned.xui_login.trim(); + if (cleaned.xui_password) cleaned.xui_password = cleaned.xui_password.trim(); + + setSettings(prev => ({ ...prev, ...cleaned })); + + return cleaned; + }; + + const handleCheckConnection = async () => { + const data = cleanData(); // Сначала чистим + + try { + setMsg({ open: true, type: 'success', text: 'Проверка...' }); + const res = await api.post('/settings/check', { + xui_url: data.xui_url, + xui_login: data.xui_login, + xui_password: data.xui_password + }); + + if (res.data.success) { + setMsg({ open: true, type: 'success', text: 'Подключение успешно!' }); + } else { + setMsg({ open: true, type: 'error', text: 'Ошибка: Неверные данные или нет доступа' }); + } + } catch (e) { + setMsg({ open: true, type: 'error', text: 'Ошибка сети при проверке' }); + } + }; + const loadSettings = async () => { try { const { data } = await api.get('/settings'); @@ -64,8 +101,10 @@ export default function SettingsPage() { return; } + const data = cleanData(); + try { - await api.post('/settings', settings); + await api.post('/settings', data); setMsg({ open: true, type: 'success', text: 'Настройки сохранены!' }); } catch (e) { setMsg({ open: true, type: 'error', text: 'Ошибка сохранения' }); @@ -86,13 +125,25 @@ export default function SettingsPage() { } }; - const handleForceRotate = async () => { +const handleForceRotate = async () => { if (confirm('ВНИМАНИЕ: Это немедленно обновит конфиги в подписках.\n\nИнтервал автоматической ротации НЕ будет сброшен.\n\nПродолжить?')) { try { - await api.post('/rotation/rotate-all'); - setMsg({ open: true, type: 'success', text: 'Ротация успешно выполнена!' }); + setLoadingRotate(true); + const res = await api.post('/rotation/rotate-all'); + + setLoadingRotate(false); + if (res.data && res.data.success) { + setMsg({ open: true, type: 'success', text: res.data.message || 'Ротация успешно выполнена!' }); + } else { + setMsg({ + open: true, + type: 'error', + text: res.data?.message || 'Ошибка выполнения ротации' + }); + } } catch (e) { - setMsg({ open: true, type: 'error', text: 'Ошибка при запуске ротации' }); + setLoadingRotate(false); + setMsg({ open: true, type: 'error', text: 'Ошибка сети или сервера' }); } } }; @@ -111,7 +162,7 @@ export default function SettingsPage() { Сохранить подключение + {settings.xui_url && settings.xui_login && settings.xui_password && ( + + )} @@ -162,6 +223,7 @@ export default function SettingsPage() {