diff --git a/frontend/src/ServerManager.jsx b/frontend/src/ServerManager.jsx index d5377fb..517daf5 100644 --- a/frontend/src/ServerManager.jsx +++ b/frontend/src/ServerManager.jsx @@ -14,7 +14,8 @@ import { IconUpload, IconAlertTriangle, IconServer, - IconChevronDown + IconChevronDown, + IconLink } from '@tabler/icons-react'; const API_URL = '/api'; @@ -50,10 +51,37 @@ function ServerManager() { const [editModalOpen, setEditModalOpen] = useState(false); const [editModalServer, setEditModalServer] = useState(null); + // Состояние для генератора ссылок + const [linkGeneratorOpen, setLinkGeneratorOpen] = useState(false); + const [linkGeneratorServer, setLinkGeneratorServer] = useState(null); + const [urlSettings, setUrlSettings] = useState({ + baseUrl: 'https://functions.yandexcloud.net/d4eno3im0qgsr4tj5hdo', + cloudflare_gateway: 'SWE-IHOR', + bunny_gateway: 'SWE-IHOR', + fastly_gateway: 'SWE-IHOR', + telegram_gateway: '94.142.140.1', + hetzner_gateway: '94.142.140.1', + type: 'routes', + version: 'v4.rsc' + }); + useEffect(() => { fetchServers(); }, []); + // Загружаем настройки URL из localStorage + useEffect(() => { + const savedSettings = localStorage.getItem('urlSettings'); + if (savedSettings) { + try { + const parsed = JSON.parse(savedSettings); + setUrlSettings(prev => ({ ...prev, ...parsed })); + } catch (e) { + console.error('Ошибка при загрузке настроек URL:', e); + } + } + }, []); + const fetchServers = async () => { setLoading(true); try { @@ -98,6 +126,72 @@ function ServerManager() { setEditModalServer(null); }; + // Функции для генератора ссылок + const handleGenerateLink = (server) => { + setLinkGeneratorServer(server); + setLinkGeneratorOpen(true); + }; + + const handleLinkGeneratorClose = () => { + setLinkGeneratorOpen(false); + setLinkGeneratorServer(null); + }; + + const generateServerUrl = (server) => { + const params = new URLSearchParams(); + + // Добавляем все параметры из настроек + Object.entries(urlSettings).forEach(([key, value]) => { + if (key !== 'baseUrl' && value) { + params.append(key, value); + } + }); + + // Добавляем IP сервера как параметр server + params.append('server', server.ip); + + return `${urlSettings.baseUrl}?${params.toString()}`; + }; + + const copyToClipboard = async (text) => { + try { + await navigator.clipboard.writeText(text); + setSuccess('Ссылка скопирована в буфер обмена!'); + setTimeout(() => setSuccess(''), 3000); + } catch (err) { + setError('Не удалось скопировать ссылку'); + } + }; + + const quickCopyLink = async (server) => { + const url = generateServerUrl(server); + await copyToClipboard(url); + }; + + const exportAllLinks = () => { + const csvContent = [ + ['IP', 'DNS', 'Country', 'Provider', 'Tunnel', 'Generated URL'], + ...servers.map(server => [ + server.ip, + server.dns, + server.country, + server.provider, + server.tunnel, + generateServerUrl(server) + ]) + ].map(row => row.map(cell => `"${cell}"`).join(',')).join('\n'); + + const blob = new Blob([csvContent], { type: 'text/csv;charset=utf-8;' }); + const link = document.createElement('a'); + const url = URL.createObjectURL(blob); + link.setAttribute('href', url); + link.setAttribute('download', `server_links_${new Date().toISOString().split('T')[0]}.csv`); + link.style.visibility = 'hidden'; + document.body.appendChild(link); + link.click(); + document.body.removeChild(link); + }; + const handleCancelEdit = () => { setEditingServer(null); }; @@ -340,7 +434,7 @@ function ServerManager() {