import { useState, useEffect } from 'react'; import { Server, Plus, Trash2, Edit, RefreshCw, CheckCircle, XCircle, Activity } from 'lucide-react'; import axios from 'axios'; import { API_URL } from '../config'; import { notify } from './NotificationSystem'; export default function Daemons({ token }) { const [daemons, setDaemons] = useState([]); const [loading, setLoading] = useState(true); const [showAddModal, setShowAddModal] = useState(false); const [editingDaemon, setEditingDaemon] = useState(null); const [formData, setFormData] = useState({ name: '', address: '', port: 24444, key: '', remarks: '' }); useEffect(() => { loadDaemons(); const interval = setInterval(loadDaemons, 10000); // Обновляем каждые 10 секунд return () => clearInterval(interval); }, []); const loadDaemons = async () => { try { const { data } = await axios.get(`${API_URL}/api/daemons`, { headers: { Authorization: `Bearer ${token}` } }); setDaemons(data); setLoading(false); } catch (error) { console.error('Ошибка загрузки демонов:', error); setLoading(false); } }; const handleSubmit = async (e) => { e.preventDefault(); try { if (editingDaemon) { await axios.put( `${API_URL}/api/daemons/${editingDaemon.id}`, formData, { headers: { Authorization: `Bearer ${token}` } } ); notify('success', 'Демон обновлен', 'Демон успешно обновлен'); } else { await axios.post( `${API_URL}/api/daemons`, formData, { headers: { Authorization: `Bearer ${token}` } } ); notify('success', 'Демон добавлен', 'Демон успешно добавлен'); } setShowAddModal(false); setEditingDaemon(null); setFormData({ name: '', address: '', port: 24444, key: '', remarks: '' }); loadDaemons(); } catch (error) { notify('error', 'Ошибка', error.response?.data?.detail || 'Не удалось сохранить демон'); } }; const handleDelete = async (daemonId) => { if (!confirm('Вы уверены, что хотите удалить этот демон?')) return; try { await axios.delete(`${API_URL}/api/daemons/${daemonId}`, { headers: { Authorization: `Bearer ${token}` } }); notify('success', 'Демон удален', 'Демон успешно удален'); loadDaemons(); } catch (error) { notify('error', 'Ошибка удаления', error.response?.data?.detail || 'Не удалось удалить демон'); } }; const handleEdit = (daemon) => { setEditingDaemon(daemon); setFormData({ name: daemon.name, address: daemon.address, port: daemon.port, key: daemon.key, remarks: daemon.remarks || '' }); setShowAddModal(true); }; const formatBytes = (bytes) => { if (!bytes) return '0 B'; const k = 1024; const sizes = ['B', 'KB', 'MB', 'GB', 'TB']; const i = Math.floor(Math.log(bytes) / Math.log(k)); return Math.round(bytes / Math.pow(k, i) * 100) / 100 + ' ' + sizes[i]; }; if (loading) { return (
Загрузка демонов...
); } return (

Демоны

Управление удаленными серверами

{daemons.length === 0 ? (

Нет демонов

Добавьте первый демон для управления удаленными серверами

) : (
{daemons.map((daemon) => (

{daemon.name}

{daemon.status === 'online' ? ( Онлайн ) : ( Оффлайн )}

{daemon.address}:{daemon.port}

{daemon.remarks && (

{daemon.remarks}

)}
{daemon.status === 'online' && daemon.system && (
CPU
{daemon.system.cpu_usage?.toFixed(1)}%
ОЗУ
{daemon.system.memory_percent?.toFixed(1)}%
{formatBytes(daemon.system.memory_used)} / {formatBytes(daemon.system.memory_total)}
Диск
{daemon.system.disk_percent?.toFixed(1)}%
{formatBytes(daemon.system.disk_used)} / {formatBytes(daemon.system.disk_total)}
)} {daemon.status === 'online' && daemon.servers && (
Серверов: {daemon.servers.total || 0} Запущено: {daemon.servers.running || 0}
)}
))}
)} {/* Модальное окно добавления/редактирования */} {showAddModal && (
setShowAddModal(false)}>
e.stopPropagation()}>

{editingDaemon ? 'Редактировать демон' : 'Добавить демон'}

setFormData({ ...formData, name: e.target.value })} className="input" placeholder="Main Server" />
setFormData({ ...formData, address: e.target.value })} className="input" placeholder="192.168.1.100" />
setFormData({ ...formData, port: parseInt(e.target.value) })} className="input" placeholder="24444" />
setFormData({ ...formData, key: e.target.value })} className="input" placeholder="your-secret-key" />

Ключ должен совпадать с DAEMON_KEY в .env файле демона