gui version

This commit is contained in:
Den Piligrim
2026-01-28 12:05:10 +03:00
parent f574931c25
commit ba6db6edd5
102 changed files with 19151 additions and 2673 deletions
+86
View File
@@ -0,0 +1,86 @@
import React from 'react';
import { Box, Container, Grid, Typography, IconButton, Link, Stack, useTheme } from '@mui/material';
import { GitHub, YouTube, Telegram, Article } from '@mui/icons-material';
export default function Footer() {
const theme = useTheme();
return (
<Box
component="footer"
sx={{
py: 3,
px: 2,
mt: 'auto', // Ключевой стиль для прижатия к низу
backgroundColor: (theme) =>
theme.palette.mode === 'light'
? theme.palette.grey[200]
: theme.palette.grey[900],
}}
>
<Container maxWidth={false}>
<Grid container spacing={4} justifyContent="space-between" alignItems="center">
{/* Логотип и копирайт */}
<Grid size={{ xs: 12, sm: 4 }}>
<Stack direction="row" alignItems="center" spacing={1}>
<img src="/img/logo.png" alt="Logo" width={32} height={32} style={{ marginRight: 14 }} />
</Stack>
</Grid>
{/* Ссылка на документацию */}
<Grid size={{ xs: 12, sm: 4 }} sx={{ textAlign: { xs: 'left', sm: 'center' } }}>
<Link
href="https://3dp-manager.com/docs/intro" // Ссылка на ваш репо или доку
target="_blank"
rel="noopener"
color="text.primary"
underline="hover"
sx={{ display: 'inline-flex', alignItems: 'center', gap: 1, fontWeight: 500 }}
>
Документация
</Link>
</Grid>
{/* Социальные иконки */}
<Grid size={{ xs: 12, sm: 4 }} sx={{ textAlign: { xs: 'left', sm: 'right' } }}>
<Stack direction="row" spacing={1} justifyContent={{ xs: 'flex-start', sm: 'flex-end' }}>
<IconButton
component="a"
href="https://github.com/denpiligrim"
target="_blank"
aria-label="GitHub"
color="inherit"
>
<GitHub />
</IconButton>
<IconButton
component="a"
href="https://youtube.com/@denpiligrim"
target="_blank"
aria-label="YouTube"
color="inherit"
>
<YouTube />
</IconButton>
<IconButton
component="a"
href="https://t.me/denpiligrim_web"
target="_blank"
aria-label="Telegram"
color="inherit"
>
<Telegram />
</IconButton>
</Stack>
</Grid>
</Grid>
</Container>
</Box>
);
}
+140
View File
@@ -0,0 +1,140 @@
import React, { useState } from 'react';
import {
AppBar, Toolbar, Typography, IconButton, Tooltip, Box,
Dialog, DialogTitle, DialogContent, DialogContentText, DialogActions, Button, List, ListItem, ListItemText
} from '@mui/material';
import {
Brightness7, Brightness4, BrightnessAuto,
Logout, HelpOutline
} from '@mui/icons-material';
import { useNavigate } from 'react-router-dom';
import { useThemeContext } from '../ThemeContext';
import { useAuth } from '../auth/AuthContext';
export default function Header() {
const { mode, toggleColorMode } = useThemeContext();
const { logout } = useAuth();
const navigate = useNavigate();
// Состояние для модального окна справки
const [helpOpen, setHelpOpen] = useState(false);
// Логика выхода
const handleLogout = () => {
if (confirm('Вы действительно хотите выйти?')) {
logout();
navigate('/login');
}
};
const getThemeIcon = () => {
switch (mode) {
case 'light': return <Brightness7 />;
case 'dark': return <Brightness4 />;
case 'system': return <BrightnessAuto />;
}
};
const getThemeLabel = () => {
switch (mode) {
case 'light': return 'Светлая тема';
case 'dark': return 'Темная тема';
case 'system': return 'Системная тема';
}
};
return (
<>
<AppBar
position="fixed"
sx={{ zIndex: (theme) => theme.zIndex.drawer + 1 }}
>
<Toolbar>
<img src="/img/logo.png" alt="Logo" width={32} height={32} style={{ marginRight: 14 }} />
<Typography variant="h6" noWrap component="div" sx={{ flexGrow: 1, fontWeight: 'bold', color: '#1395de' }}>
3DP-MANAGER
</Typography>
<Box sx={{ display: 'flex', gap: 1 }}>
{/* Кнопка Справки */}
<Tooltip title="Справка о программе">
<IconButton color="inherit" onClick={() => setHelpOpen(true)}>
<HelpOutline />
</IconButton>
</Tooltip>
{/* Кнопка Темы */}
<Tooltip title={`Режим: ${getThemeLabel()}`}>
<IconButton color="inherit" onClick={toggleColorMode}>
{getThemeIcon()}
</IconButton>
</Tooltip>
{/* Кнопка Выхода */}
<Tooltip title="Выйти из системы">
<IconButton color="inherit" onClick={handleLogout}>
<Logout />
</IconButton>
</Tooltip>
</Box>
</Toolbar>
</AppBar>
{/* Модальное окно справки */}
<Dialog
open={helpOpen}
onClose={() => setHelpOpen(false)}
maxWidth="sm"
fullWidth
>
<DialogTitle>Об утилите 3DP-MANAGER</DialogTitle>
<DialogContent dividers>
<DialogContentText paragraph>
Утилита для автогенерации инбаундов к панели 3x-ui, формирования единой подписки и настройки перенаправления трафика с промежуточного сервера на основной.
</DialogContentText>
<Typography variant="subtitle1" gutterBottom sx={{ fontWeight: 'bold' }}>
Основные возможности:
</Typography>
<List dense>
<ListItem>
<ListItemText
primary="Автоматическая генерация"
secondary="Система создает новые инбаунды в заданном интервале."
/>
</ListItem>
<ListItem>
<ListItemText
primary="Управление подписками"
secondary="Создание пользователей с уникальными UUID. Одна подписка генерирует множество подключений."
/>
</ListItem>
<ListItem>
<ListItemText
primary="Белый список доменов"
secondary="Для работы инбаундов необходим список доменов, под которые маскируется трафик."
/>
</ListItem>
<ListItem>
<ListItemText
primary="Перенаправление"
secondary="Если вы используете Каскадную схему подключения, то вы сможете добавить свои промежуточные сервера."
/>
</ListItem>
</List>
<Typography variant="body2" color="text.secondary" sx={{ mt: 2 }}>
Версия: 2.0.0<br />
Разработчик: DenPiligrim
</Typography>
</DialogContent>
<DialogActions>
<Button onClick={() => setHelpOpen(false)}>Понятно</Button>
</DialogActions>
</Dialog>
</>
);
}
+81
View File
@@ -0,0 +1,81 @@
import React from 'react';
import {
Toolbar, Drawer, List, ListItem,
ListItemButton, ListItemIcon, ListItemText, Box
} from '@mui/material';
import { People, Settings, Dns, SwapHoriz } from '@mui/icons-material';
import { useNavigate, useLocation, Outlet } from 'react-router-dom';
import Header from './Header'; // <--- Новый компонент
import Footer from './Footer';
const drawerWidth = 240;
export default function Layout() {
const navigate = useNavigate();
const location = useLocation();
const menuItems = [
{ text: 'Подписки', icon: <People />, path: '/' },
{ text: 'Домены', icon: <Dns />, path: '/domains' },
{ text: 'Перенаправление', icon: <SwapHoriz />, path: '/tunnels' },
{ text: 'Настройки', icon: <Settings />, path: '/settings' },
];
return (
<Box sx={{ display: 'flex', minHeight: '100vh', width: '100%' }}>
{/* Шапка */}
<Header />
{/* Боковое меню */}
<Drawer
variant="permanent"
sx={{
width: drawerWidth,
flexShrink: 0,
[`& .MuiDrawer-paper`]: { width: drawerWidth, boxSizing: 'border-box' },
}}
>
<Toolbar />
<Box sx={{ overflow: 'auto' }}>
<List>
{menuItems.map((item) => (
<ListItem key={item.text} disablePadding>
<ListItemButton
selected={location.pathname === item.path}
onClick={() => navigate(item.path)}
>
<ListItemIcon>{item.icon}</ListItemIcon>
<ListItemText primary={item.text} />
</ListItemButton>
</ListItem>
))}
</List>
</Box>
</Drawer>
{/* Основной контейнер контента */}
<Box
component="main"
sx={{
flexGrow: 1,
display: 'flex',
flexDirection: 'column',
minHeight: '100vh',
width: '100%'
}}
>
<Toolbar />
{/* Контент страницы */}
<Box sx={{ flexGrow: 1, p: 3 }}>
<Outlet />
</Box>
{/* Футер */}
<Footer />
</Box>
</Box>
);
}