Большое обновление GUI интерфейс

Большое обновление GUI интерфейс

- Добавлен фраемворr Walles
- Удалена консольная версия
- Проработан интерфейс и дизайн
- Добавлено кеширование для быстрой реакции.
- Сделан .ps1 сборщик для удобной сборки проекта.
- Обновлён Readme
This commit is contained in:
2025-11-14 08:40:25 +07:00
parent 752f294392
commit 02ae56b78c
93 changed files with 7477 additions and 3504 deletions

View File

@@ -0,0 +1,103 @@
/* ============================================
Base Styles & Reset
Базовые стили приложения
============================================ */
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: var(--font-sans);
background: var(--bg-primary);
color: var(--text-primary);
line-height: 1.6;
height: 100vh;
overflow: hidden;
position: relative;
/* Градиентный фон с размытием */
&::before {
content: '';
position: fixed;
top: -50%;
left: -50%;
width: 200%;
height: 200%;
/* background: radial-gradient(circle at 80% 80%, rgba(138, 92, 246, 0.116) 0%, transparent 50%); */
pointer-events: none;
z-index: 0;
}
}
/* Typography */
code {
background: rgba(139, 92, 246, 0.15);
backdrop-filter: var(--backdrop-blur-light);
color: var(--accent-purple-light);
padding: 3px 8px;
border-radius: var(--radius-sm);
font-family: var(--font-mono);
font-size: var(--text-sm);
border: 1px solid var(--glass-border);
box-shadow: var(--shadow-sm);
}
/* Scrollbar Styling */
::-webkit-scrollbar {
width: 8px;
height: 8px;
}
::-webkit-scrollbar-track {
background: rgba(139, 92, 246, 0.05);
border-radius: var(--radius-sm);
}
::-webkit-scrollbar-thumb {
background: rgba(139, 92, 246, 0.3);
border-radius: var(--radius-sm);
&:hover {
background: rgba(139, 92, 246, 0.5);
}
}
/* Animations */
@keyframes fadeIn {
from {
opacity: 0;
transform: translateY(10px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
@keyframes spin {
to {
transform: rotate(360deg);
}
}
@keyframes bounce {
0%, 100% {
transform: translateY(0);
}
50% {
transform: translateY(-20px);
}
}
/* Utility Classes */
.hidden {
display: none !important;
}
.fade-in {
animation: fadeIn var(--transition-slow);
}

View File

@@ -0,0 +1,87 @@
/* ============================================
Badges Component
Единая система бейджей
============================================ */
/* Base Badge */
.badge {
padding: 4px 12px;
border-radius: 20px;
font-size: var(--text-xs);
font-weight: var(--font-bold);
text-transform: uppercase;
letter-spacing: 0.5px;
backdrop-filter: var(--backdrop-blur-light);
display: inline-block;
}
/* Status Badges */
.badge-online {
background: linear-gradient(135deg, rgba(16, 185, 129, 0.25), rgba(16, 185, 129, 0.15));
color: var(--accent-green);
border: 1px solid rgba(16, 185, 129, 0.4);
box-shadow: 0 0 12px rgba(16, 185, 129, 0.3);
}
.badge-offline {
background: linear-gradient(135deg, rgba(239, 68, 68, 0.25), rgba(239, 68, 68, 0.15));
color: var(--accent-red);
border: 1px solid rgba(239, 68, 68, 0.4);
box-shadow: 0 0 12px rgba(239, 68, 68, 0.3);
}
.badge-pending {
background: linear-gradient(135deg, rgba(245, 158, 11, 0.25), rgba(245, 158, 11, 0.15));
color: var(--accent-yellow);
border: 1px solid rgba(245, 158, 11, 0.4);
box-shadow: 0 0 12px rgba(245, 158, 11, 0.3);
}
/* Yes/No Badges */
.badge-yes {
background: rgba(34, 197, 94, 0.2);
color: var(--accent-green);
border: 1px solid var(--accent-green);
}
.badge-no {
background: rgba(100, 116, 139, 0.2);
color: var(--text-muted);
border: 1px solid var(--text-muted);
}
/* Status Indicator (Dot) */
.status-indicator {
width: 7px;
height: 7px;
border-radius: var(--radius-full);
box-shadow: 0 0 8px currentColor;
}
.status-online {
background: var(--accent-green);
color: var(--accent-green);
}
.status-offline {
background: var(--accent-red);
color: var(--accent-red);
}
/* Mini Tags (для таблиц) */
.mini-tag {
display: inline-block;
padding: 4px 10px;
background: rgba(139, 92, 246, 0.15);
border-radius: var(--radius-sm);
font-size: 12px;
font-family: var(--font-mono);
color: var(--accent-purple-light);
margin: 2px;
transition: all var(--transition-base);
&:hover {
background: rgba(139, 92, 246, 0.25);
}
}

View File

@@ -0,0 +1,308 @@
/* ============================================
Buttons Component
Единая система кнопок
============================================ */
/* Base Button Styles */
.btn {
display: inline-flex;
align-items: center;
justify-content: center;
gap: var(--space-sm);
padding: var(--space-sm) var(--space-md);
border: none;
border-radius: var(--radius-md);
font-size: var(--text-base);
font-weight: var(--font-semibold);
cursor: pointer;
transition: all var(--transition-base);
white-space: nowrap;
&:disabled {
opacity: 0.5;
cursor: not-allowed;
}
&:not(:disabled):active {
transform: scale(0.95);
}
}
/* Action Button - Основная кнопка действия */
.action-btn {
padding: var(--space-sm) var(--space-md);
background: rgba(139, 92, 246, 0.15);
backdrop-filter: var(--backdrop-blur-light);
border: 1px solid rgba(139, 92, 246, 0.3);
border-radius: var(--radius-md);
color: var(--accent-purple-light);
font-size: var(--text-base);
font-weight: var(--font-semibold);
&:hover:not(:disabled) {
background: rgba(139, 92, 246, 0.25);
border-color: rgba(139, 92, 246, 0.5);
transform: translateY(-1px);
}
i {
font-size: var(--text-md);
}
}
/* Save Button Variant */
.save-btn {
background: rgba(16, 185, 129, 0.15);
border-color: rgba(16, 185, 129, 0.3);
color: var(--accent-green);
&:hover:not(:disabled) {
background: rgba(16, 185, 129, 0.25);
border-color: rgba(16, 185, 129, 0.5);
}
}
/* Icon Button - Квадратная кнопка с иконкой */
.icon-btn {
width: 32px;
height: 32px;
padding: 0;
background: rgba(139, 92, 246, 0.1);
border: 1px solid rgba(139, 92, 246, 0.3);
border-radius: var(--radius-md);
color: var(--accent-purple-light);
font-size: var(--text-md);
&:hover:not(:disabled) {
background: rgba(139, 92, 246, 0.25);
border-color: rgba(139, 92, 246, 0.5);
transform: translateY(-1px);
}
}
/* Small Icon Button */
.icon-btn-small {
width: 28px;
height: 28px;
background: rgba(239, 68, 68, 0.1);
border: 1px solid rgba(239, 68, 68, 0.3);
border-radius: var(--radius-sm);
color: var(--accent-red);
font-size: 12px;
&:hover:not(:disabled) {
background: rgba(239, 68, 68, 0.2);
}
}
/* Window Control Buttons */
.window-btn {
width: 32px;
height: 32px;
border: none;
background: transparent;
color: var(--text-secondary);
cursor: pointer;
display: flex;
align-items: center;
justify-content: center;
border-radius: var(--radius-sm);
transition: all var(--transition-base);
&:hover {
background: rgba(255, 255, 255, 0.1);
color: var(--text-primary);
}
&:active {
transform: scale(0.95);
}
}
.close-btn:hover {
background: var(--accent-red);
color: white;
}
/* Server Control Button */
.server-control-btn {
display: flex;
align-items: center;
gap: var(--space-sm);
padding: var(--space-sm) 18px;
background: linear-gradient(135deg, rgba(239, 68, 68, 0.2), rgba(239, 68, 68, 0.1));
backdrop-filter: var(--backdrop-blur-light);
border: 1px solid rgba(239, 68, 68, 0.4);
border-radius: 20px;
color: var(--accent-red);
font-size: var(--text-base);
font-weight: var(--font-semibold);
cursor: pointer;
transition: all var(--transition-base);
box-shadow: var(--shadow-red);
&:hover:not(:disabled) {
background: linear-gradient(135deg, rgba(239, 68, 68, 0.3), rgba(239, 68, 68, 0.15));
border-color: rgba(239, 68, 68, 0.6);
transform: translateY(-1px);
}
&:active {
transform: translateY(0);
}
i {
font-size: var(--text-md);
}
}
.server-control-btn.start-mode {
background: linear-gradient(135deg, rgba(16, 185, 129, 0.2), rgba(16, 185, 129, 0.1));
border-color: rgba(16, 185, 129, 0.4);
color: var(--accent-green);
box-shadow: var(--shadow-green);
&:hover:not(:disabled) {
background: linear-gradient(135deg, rgba(16, 185, 129, 0.3), rgba(16, 185, 129, 0.15));
border-color: rgba(16, 185, 129, 0.6);
}
}
/* Status Toggle Buttons */
.status-toggle {
display: flex;
gap: var(--space-sm);
}
.status-btn {
flex: 1;
padding: 10px var(--space-md);
background: rgba(100, 116, 139, 0.1);
border: 1px solid rgba(100, 116, 139, 0.3);
border-radius: var(--radius-md);
color: var(--text-muted);
font-size: var(--text-base);
font-weight: var(--font-semibold);
cursor: pointer;
transition: all var(--transition-base);
display: flex;
align-items: center;
justify-content: center;
gap: var(--space-sm);
&:hover {
background: rgba(100, 116, 139, 0.15);
}
&.active {
background: rgba(16, 185, 129, 0.2);
border-color: rgba(16, 185, 129, 0.5);
color: var(--accent-green);
box-shadow: 0 0 12px rgba(16, 185, 129, 0.2);
}
&:last-child.active {
background: rgba(239, 68, 68, 0.2);
border-color: rgba(239, 68, 68, 0.5);
color: var(--accent-red);
}
}
/* Navigation Buttons */
.nav-item {
width: 48px;
height: 48px;
display: flex;
align-items: center;
justify-content: center;
background: transparent;
border: none;
border-radius: var(--radius-lg);
color: var(--text-secondary);
font-size: 20px;
cursor: pointer;
transition: all var(--transition-base);
position: relative;
&::before {
content: '';
position: absolute;
left: -16px;
top: 50%;
transform: translateY(-50%);
width: 3px;
height: 0;
background: linear-gradient(180deg, var(--accent-purple), var(--accent-purple-light));
border-radius: 0 2px 2px 0;
transition: height var(--transition-base);
}
&:hover {
background: rgba(139, 92, 246, 0.1);
color: var(--accent-purple-light);
}
&.active {
background: rgba(139, 92, 246, 0.15);
color: var(--accent-purple-light);
&::before {
height: 24px;
}
}
}
/* Breadcrumb Buttons */
.breadcrumb-item {
font-size: var(--text-md);
color: var(--text-muted);
background: none;
border: none;
padding: var(--space-sm) var(--space-lg);
border-radius: var(--radius-md);
cursor: pointer;
transition: all var(--transition-base);
display: flex;
align-items: center;
gap: var(--space-sm);
&:hover {
background: rgba(139, 92, 246, 0.1);
color: var(--accent-purple-light);
}
&.active {
color: var(--text-primary);
font-weight: var(--font-medium);
cursor: default;
}
}
/* Tab Buttons */
.vaccess-tab {
flex: 0 0 auto;
padding: 10px 18px;
background: transparent;
border: none;
border-radius: var(--radius-md);
color: var(--text-muted);
font-size: var(--text-base);
font-weight: var(--font-medium);
cursor: pointer;
transition: all var(--transition-base);
display: flex;
align-items: center;
gap: var(--space-sm);
&:hover {
background: rgba(139, 92, 246, 0.1);
color: var(--text-primary);
}
&.active {
background: var(--accent-purple);
color: white;
box-shadow: 0 4px 12px rgba(139, 92, 246, 0.3);
}
}

View File

@@ -0,0 +1,191 @@
/* ============================================
Cards Component
Единая система карточек
============================================ */
/* Service Card */
.service-card {
background: var(--glass-bg-light);
backdrop-filter: var(--backdrop-blur);
border: 1px solid var(--glass-border);
border-radius: var(--radius-2xl);
padding: var(--space-lg);
transition: all var(--transition-bounce);
position: relative;
overflow: hidden;
/* Градиентная линия сверху */
&::before {
content: '';
position: absolute;
top: 0;
left: 0;
right: 0;
height: 3px;
background: linear-gradient(90deg, var(--accent-purple), var(--accent-purple-light), var(--accent-cyan));
opacity: 0;
transition: opacity var(--transition-slow);
}
&:hover {
transform: translateY(-4px);
box-shadow: var(--shadow-purple);
border-color: var(--glass-border-hover);
background: rgba(20, 20, 40, 0.5);
&::before {
opacity: 1;
}
}
}
.service-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 18px;
}
.service-name {
font-size: var(--text-md);
font-weight: var(--font-semibold);
color: var(--text-primary);
display: flex;
align-items: center;
gap: var(--space-sm);
i {
color: var(--accent-purple-light);
font-size: var(--text-lg);
}
}
.service-info {
display: flex;
flex-direction: column;
gap: 10px;
}
.info-row {
display: flex;
justify-content: space-between;
align-items: center;
}
.info-label {
font-size: var(--text-sm);
color: var(--text-secondary);
font-weight: var(--font-medium);
}
.info-value {
font-size: 12px;
color: var(--text-primary);
font-weight: var(--font-semibold);
}
/* Settings Card */
.settings-card {
background: var(--glass-bg-light);
backdrop-filter: var(--backdrop-blur);
border: 1px solid var(--glass-border);
border-radius: var(--radius-xl);
padding: var(--space-lg);
}
.settings-card-title {
font-size: var(--text-lg);
font-weight: var(--font-semibold);
color: var(--text-primary);
margin-bottom: 20px;
padding-bottom: 12px;
border-bottom: 1px solid rgba(255, 255, 255, 0.1);
display: flex;
align-items: center;
gap: var(--space-sm);
i {
color: var(--accent-purple-light);
}
}
/* vAccess Rule Card */
.vaccess-rule-card {
background: rgba(10, 14, 26, 0.4);
border: 1px solid var(--glass-border);
border-radius: var(--radius-lg);
padding: var(--space-lg);
}
.rule-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: var(--space-md);
padding-bottom: 12px;
border-bottom: 1px solid var(--glass-border);
}
.rule-number {
font-size: var(--text-md);
font-weight: var(--font-bold);
color: var(--accent-purple-light);
text-transform: uppercase;
letter-spacing: 0.5px;
}
.rule-content {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 20px;
> .form-group:first-child {
grid-column: 1 / -1;
}
}
/* Help Cards */
.help-card {
background: rgba(255, 255, 255, 0.02);
border-radius: var(--radius-xl);
padding: var(--space-xl);
border: 1px solid var(--glass-border);
transition: all var(--transition-slow);
&:hover {
border-color: var(--glass-border-hover);
box-shadow: 0 8px 24px rgba(0, 0, 0, 0.2);
}
h3 {
font-size: var(--text-2xl);
font-weight: var(--font-semibold);
color: var(--accent-purple-light);
margin: 0 0 20px 0;
display: flex;
align-items: center;
gap: var(--space-lg);
}
ul {
list-style: none;
padding: 0;
margin: 0;
}
li {
padding: 12px 0;
color: var(--text-secondary);
line-height: 1.6;
border-bottom: 1px solid rgba(139, 92, 246, 0.05);
&:last-child {
border-bottom: none;
}
}
}
.help-examples {
background: linear-gradient(135deg, rgba(139, 92, 246, 0.05) 0%, rgba(99, 102, 241, 0.05) 100%);
}

View File

@@ -0,0 +1,219 @@
/* ============================================
Forms Component
Единая система форм
============================================ */
/* Form Container */
.settings-form {
display: flex;
flex-direction: column;
gap: var(--space-md);
}
/* Form Group */
.form-group {
display: flex;
flex-direction: column;
gap: var(--space-sm);
}
/* Form Row (2 columns) */
.form-row {
display: grid;
grid-template-columns: 1fr 1fr;
gap: var(--space-md);
}
/* Form Label */
.form-label {
font-size: 12px;
font-weight: var(--font-semibold);
color: var(--text-secondary);
text-transform: uppercase;
letter-spacing: 0.5px;
}
.field-hint {
font-size: var(--text-xs);
color: var(--text-muted);
font-weight: var(--font-normal);
text-transform: none;
letter-spacing: 0;
}
/* Form Input */
.form-input {
padding: 10px 14px;
background: var(--glass-bg-dark);
border: 1px solid var(--glass-border);
border-radius: var(--radius-md);
color: var(--text-primary);
font-size: var(--text-base);
outline: none;
transition: all var(--transition-base);
&:focus {
border-color: rgba(139, 92, 246, 0.5);
box-shadow: 0 0 12px rgba(139, 92, 246, 0.2);
}
&::placeholder {
color: var(--text-muted);
opacity: 0.5;
}
}
/* Form Info */
.form-info {
font-size: var(--text-sm);
color: var(--text-muted);
line-height: 1.5;
padding: 12px;
background: rgba(139, 92, 246, 0.05);
border-radius: var(--radius-md);
border-left: 3px solid var(--accent-purple);
}
/* Toggle Switch */
.toggle-wrapper {
display: flex;
align-items: center;
gap: var(--space-lg);
}
.toggle-switch {
position: relative;
display: inline-block;
width: 50px;
height: 26px;
input {
opacity: 0;
width: 0;
height: 0;
&:checked + .toggle-slider {
background: rgba(16, 185, 129, 0.2);
border-color: rgba(16, 185, 129, 0.5);
box-shadow: 0 0 16px rgba(16, 185, 129, 0.3);
&::before {
transform: translateX(24px);
background: var(--accent-green);
}
}
}
}
.toggle-slider {
position: absolute;
cursor: pointer;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: rgba(239, 68, 68, 0.2);
border: 1px solid rgba(239, 68, 68, 0.4);
transition: all var(--transition-slow);
border-radius: 26px;
&::before {
position: absolute;
content: "";
height: 18px;
width: 18px;
left: 3px;
bottom: 3px;
background: rgba(239, 68, 68, 0.8);
box-shadow: var(--shadow-sm);
transition: all var(--transition-slow);
border-radius: var(--radius-full);
}
}
.toggle-label {
font-size: var(--text-md);
font-weight: var(--font-semibold);
color: var(--text-primary);
}
/* Checkbox */
.checkbox-label {
display: flex;
align-items: center;
gap: 10px;
cursor: pointer;
font-size: var(--text-base);
color: var(--text-primary);
}
/* Tags Container */
.tags-container {
display: flex;
flex-wrap: wrap;
gap: var(--space-sm);
padding: 12px;
background: var(--glass-bg-dark);
border: 1px solid var(--glass-border);
border-radius: var(--radius-md);
min-height: 48px;
margin-top: var(--space-sm);
}
.tag {
display: inline-flex;
align-items: center;
gap: var(--space-sm);
padding: 4px 10px;
background: rgba(139, 92, 246, 0.2);
border: 1px solid rgba(139, 92, 246, 0.4);
border-radius: 16px;
color: var(--text-primary);
font-size: 12px;
font-weight: var(--font-medium);
}
.tag-remove {
background: transparent;
border: none;
color: var(--accent-red);
cursor: pointer;
padding: 0;
width: 14px;
height: 14px;
display: flex;
align-items: center;
justify-content: center;
border-radius: var(--radius-full);
transition: all var(--transition-base);
&:hover {
background: rgba(239, 68, 68, 0.2);
}
}
.tag-input-wrapper {
display: flex;
gap: var(--space-sm);
.form-input {
flex: 1;
}
.action-btn {
flex-shrink: 0;
}
}
/* Field Editor */
.field-editor {
padding: 20px;
h3 {
font-size: var(--text-xl);
font-weight: var(--font-semibold);
color: var(--accent-purple-light);
margin-bottom: 20px;
}
}

View File

@@ -0,0 +1,223 @@
/* ============================================
Modals Component
Единая система модальных окон
============================================ */
/* Modal Overlay */
.modal-overlay {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: rgba(0, 0, 0, 0.7);
backdrop-filter: var(--backdrop-blur-light);
z-index: var(--z-modal);
display: flex;
align-items: center;
justify-content: center;
opacity: 0;
pointer-events: none;
transition: opacity var(--transition-slow);
&.show {
opacity: 1;
pointer-events: auto;
.modal-window {
transform: scale(1);
}
.notification-content {
transform: scale(1);
}
}
}
/* Modal Window */
.modal-window {
background: rgba(20, 20, 40, 0.95);
backdrop-filter: var(--backdrop-blur);
border: 1px solid var(--glass-border-hover);
border-radius: var(--radius-2xl);
box-shadow: var(--shadow-lg);
min-width: 900px;
max-width: 1200px;
max-height: 85vh;
overflow: hidden;
transform: scale(0.9);
transition: transform var(--transition-slow);
}
.modal-header {
display: flex;
justify-content: space-between;
align-items: center;
padding: 20px var(--space-lg);
border-bottom: 1px solid var(--glass-border);
}
.modal-title {
font-size: var(--text-xl);
font-weight: var(--font-semibold);
color: var(--text-primary);
}
.modal-close-btn {
width: 32px;
height: 32px;
background: transparent;
border: none;
border-radius: var(--radius-md);
color: var(--text-secondary);
cursor: pointer;
transition: all var(--transition-base);
display: flex;
align-items: center;
justify-content: center;
&:hover {
background: rgba(239, 68, 68, 0.2);
color: var(--accent-red);
}
}
.modal-content {
padding: var(--space-lg);
max-height: 60vh;
overflow-y: auto;
}
.modal-footer {
display: flex;
justify-content: flex-end;
gap: var(--space-lg);
padding: 20px var(--space-lg);
border-top: 1px solid var(--glass-border);
}
/* Notification Modal */
.notification {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: rgba(0, 0, 0, 0.6);
backdrop-filter: var(--backdrop-blur-light);
z-index: var(--z-notification);
display: flex;
align-items: center;
justify-content: center;
opacity: 0;
pointer-events: none;
transition: opacity var(--transition-slow);
&.show {
opacity: 1;
pointer-events: auto;
}
}
.notification-content {
min-width: 400px;
max-width: 500px;
padding: var(--space-xl) 40px;
background: rgba(20, 20, 40, 0.95);
backdrop-filter: var(--backdrop-blur);
border: 1px solid var(--glass-border-hover);
border-radius: var(--radius-2xl);
box-shadow: var(--shadow-lg), 0 0 40px rgba(139, 92, 246, 0.3);
display: flex;
flex-direction: column;
align-items: center;
gap: 20px;
text-align: center;
transform: scale(0.9);
transition: transform var(--transition-bounce);
}
.notification.success .notification-content {
border-color: rgba(16, 185, 129, 0.4);
box-shadow: var(--shadow-lg), 0 0 40px rgba(16, 185, 129, 0.3);
}
.notification.error .notification-content {
border-color: rgba(239, 68, 68, 0.4);
box-shadow: var(--shadow-lg), 0 0 40px rgba(239, 68, 68, 0.3);
}
.notification-icon {
font-size: 56px;
i {
display: block;
}
}
.notification.success .notification-icon {
color: var(--accent-green);
}
.notification.error .notification-icon {
color: var(--accent-red);
}
.notification-text {
font-size: var(--text-lg);
font-weight: var(--font-semibold);
color: var(--text-primary);
line-height: 1.6;
}
/* App Loader */
.app-loader {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: linear-gradient(135deg, var(--bg-primary) 0%, var(--bg-secondary) 50%, var(--bg-tertiary) 100%);
z-index: var(--z-loader);
display: flex;
align-items: center;
justify-content: center;
opacity: 1;
transition: opacity 0.5s ease;
&.hide {
opacity: 0;
pointer-events: none;
}
}
.loader-content {
display: flex;
flex-direction: column;
align-items: center;
gap: 20px;
}
.loader-icon {
font-size: 64px;
animation: bounce 1.5s ease-in-out infinite;
}
.loader-text {
font-size: var(--text-xl);
font-weight: var(--font-semibold);
background: linear-gradient(135deg, #7c3aed 0%, #a78bfa 100%);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-clip: text;
}
.loader-spinner {
width: 40px;
height: 40px;
border: 3px solid rgba(139, 92, 246, 0.2);
border-top-color: var(--accent-purple);
border-radius: var(--radius-full);
animation: spin 0.8s linear infinite;
}

View File

@@ -0,0 +1,236 @@
/* ============================================
Tables Component
ЕДИНАЯ система таблиц для всего приложения
============================================ */
/* Table Container */
.table-container {
background: var(--glass-bg-light);
backdrop-filter: var(--backdrop-blur);
border: 1px solid var(--glass-border);
border-radius: var(--radius-2xl);
overflow: hidden;
box-shadow: var(--shadow-md);
}
/* Base Table */
.data-table {
width: 100%;
border-collapse: collapse;
thead {
background: rgba(139, 92, 246, 0.12);
backdrop-filter: var(--backdrop-blur-light);
tr {
border-bottom: 1px solid rgba(255, 255, 255, 0.1);
}
}
th {
padding: 18px 20px;
text-align: left;
font-size: var(--text-sm);
font-weight: var(--font-bold);
color: var(--text-secondary);
text-transform: uppercase;
letter-spacing: 1.2px;
&:last-child {
width: 120px;
text-align: center;
}
}
tbody {
tr {
border-bottom: 1px solid rgba(255, 255, 255, 0.05);
transition: all var(--transition-base);
&:hover {
background: rgba(139, 92, 246, 0.08);
}
}
}
td {
padding: 16px 20px;
font-size: var(--text-base);
color: var(--text-primary);
&:last-child {
text-align: center;
display: flex;
justify-content: center;
align-items: center;
gap: var(--space-sm);
}
}
}
/* vAccess Table - использует те же стили что и data-table */
.vaccess-table-container {
margin-bottom: 20px;
max-height: 55vh;
overflow-y: auto;
}
.vaccess-table {
width: 100%;
border-collapse: collapse;
thead {
tr {
background: rgba(139, 92, 246, 0.05);
display: table-row;
width: 100%;
}
th {
padding: 16px;
text-align: left;
font-size: var(--text-base);
font-weight: var(--font-semibold);
color: var(--text-muted);
text-transform: uppercase;
letter-spacing: 0.5px;
border: none;
display: table-cell;
box-sizing: content-box;
}
}
tbody {
tr {
background: rgba(255, 255, 255, 0.02);
transition: all var(--transition-slow);
cursor: grab;
display: table-row;
width: 100%;
&:hover {
background: rgba(139, 92, 246, 0.08);
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.2);
}
&:active {
cursor: grabbing;
}
&[draggable="true"] {
opacity: 1;
}
}
}
td {
padding: 20px 16px;
font-size: var(--text-md);
color: var(--text-primary);
border-top: 1px solid rgba(139, 92, 246, 0.05);
border-bottom: 1px solid rgba(139, 92, 246, 0.05);
cursor: pointer;
display: table-cell;
box-sizing: content-box;
}
/* Принудительно растягиваем на всю ширину */
thead, tbody {
display: table-row-group;
width: 100%;
}
}
/* Table Column Sizing - адаптивные размеры */
.col-drag {
width: 3%;
min-width: 40px;
text-align: center;
}
.col-type {
width: 8%;
min-width: 80px;
}
.col-files {
width: 15%;
min-width: 120px;
}
.col-paths {
width: 18%;
min-width: 150px;
}
.col-ips {
width: 15%;
min-width: 120px;
}
.col-exceptions {
width: 15%;
min-width: 120px;
}
.col-error {
width: 10%;
min-width: 100px;
}
.col-actions {
width: 5%;
min-width: 60px;
text-align: center;
}
/* Drag Handle */
.drag-handle {
color: var(--text-muted);
opacity: 0.3;
transition: all var(--transition-base);
cursor: grab;
text-align: center;
&:hover {
opacity: 1;
color: var(--accent-purple-light);
}
&:active {
cursor: grabbing;
}
}
/* Empty Field */
.empty-field {
color: var(--text-muted);
opacity: 0.4;
font-style: italic;
}
/* Clickable Link in Tables */
.clickable-link {
color: var(--accent-purple-light);
cursor: pointer;
transition: all var(--transition-base);
text-decoration: none;
display: inline-flex;
align-items: center;
gap: var(--space-xs);
&:hover {
color: var(--accent-purple);
text-decoration: underline;
}
}
/* Responsive Table */
@media (max-width: 600px) {
.table-container {
overflow-x: scroll;
}
}

View File

@@ -0,0 +1,66 @@
/* ============================================
Container Layout
Основной контейнер контента
============================================ */
.container {
height: calc(100vh - var(--header-height));
margin-top: var(--header-height);
margin-left: var(--sidebar-width);
padding: 40px var(--space-3xl);
position: relative;
z-index: var(--z-base);
overflow-y: auto;
overflow-x: hidden;
}
/* Main Content */
.main-content {
display: flex;
flex-direction: column;
gap: var(--space-2xl);
}
/* Section */
.section {
position: relative;
}
.section-title {
font-size: var(--text-md);
font-weight: var(--font-bold);
color: var(--text-primary);
margin-bottom: var(--space-lg);
text-transform: uppercase;
letter-spacing: 1.5px;
display: flex;
align-items: center;
gap: var(--space-lg);
&::before {
content: '';
width: 4px;
height: 16px;
background: linear-gradient(180deg, var(--accent-purple), var(--accent-purple-light));
border-radius: 2px;
}
}
/* Footer */
.footer {
margin-top: var(--space-3xl);
padding: 20px;
text-align: center;
color: var(--text-muted);
font-size: var(--text-sm);
opacity: 0.6;
}
/* Responsive */
@media (max-width: 600px) {
.header {
flex-direction: column;
gap: 10px;
}
}

View File

@@ -0,0 +1,76 @@
/* ============================================
Header Layout
Window controls и title bar
============================================ */
.window-controls {
position: fixed;
top: 0;
left: 0;
right: 0;
z-index: 1000;
background: rgba(10, 14, 26, 0.9);
backdrop-filter: var(--backdrop-blur);
border-bottom: 1px solid var(--glass-border);
}
.title-bar {
display: flex;
justify-content: space-between;
align-items: center;
height: var(--header-height);
padding: 0 var(--space-xl);
--wails-draggable: drag;
}
.title-bar-left {
display: flex;
align-items: center;
gap: var(--space-lg);
}
.app-logo {
display: flex;
align-items: center;
gap: 10px;
}
.logo-icon {
font-size: 24px;
line-height: 1;
}
.logo-text {
font-size: var(--text-xl);
font-weight: var(--font-bold);
color: #ffffff;
user-select: none;
letter-spacing: -0.5px;
}
.title-bar-right {
display: flex;
align-items: center;
gap: var(--space-md);
--wails-draggable: no-drag;
}
/* Server Status */
.server-status {
display: flex;
align-items: center;
gap: var(--space-sm);
padding: var(--space-sm) var(--space-md);
background: linear-gradient(135deg, rgba(16, 185, 129, 0.15), rgba(16, 185, 129, 0.05));
backdrop-filter: var(--backdrop-blur-light);
border-radius: 20px;
border: 1px solid rgba(16, 185, 129, 0.3);
box-shadow: var(--shadow-green);
}
.status-text {
font-size: 12px;
font-weight: var(--font-semibold);
color: var(--text-primary);
}

View File

@@ -0,0 +1,27 @@
/* ============================================
Sidebar Layout
Боковая навигация
============================================ */
.sidebar {
position: fixed;
left: 0;
top: var(--header-height);
width: var(--sidebar-width);
height: calc(100vh - var(--header-height));
background: rgba(10, 14, 26, 0.95);
backdrop-filter: var(--backdrop-blur);
border-right: 1px solid var(--glass-border);
z-index: 100;
display: flex;
flex-direction: column;
padding: 20px 0;
}
.sidebar-nav {
display: flex;
flex-direction: column;
gap: var(--space-sm);
padding: 0 var(--space-md);
}

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,26 @@
/* ============================================
vServer Admin Panel - Main CSS
Профессиональная модульная архитектура
============================================ */
/* 1. Variables & Base */
@import 'variables.css';
@import 'base.css';
/* 2. Components */
@import 'components/buttons.css';
@import 'components/badges.css';
@import 'components/cards.css';
@import 'components/forms.css';
@import 'components/tables.css';
@import 'components/modals.css';
/* 3. Layout */
@import 'layout/header.css';
@import 'layout/sidebar.css';
@import 'layout/container.css';
/* 4. Pages */
@import 'pages/dashboard.css';
@import 'pages/vaccess.css';

View File

@@ -0,0 +1,62 @@
/* ============================================
Dashboard Page
Главная страница с сервисами и таблицами
============================================ */
/* Services Grid */
.services-grid {
display: grid;
grid-template-columns: repeat(5, 1fr);
gap: var(--space-lg);
}
/* Settings Header */
.settings-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: var(--space-lg);
.section-title {
margin-bottom: 0;
padding-bottom: 0;
}
}
/* Settings Grid */
.settings-grid {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: var(--space-lg);
margin-bottom: var(--space-lg);
}
/* Settings Actions */
.settings-actions {
display: flex;
justify-content: flex-end;
}
/* Responsive Grid */
@media (max-width: 1200px) {
.services-grid {
grid-template-columns: repeat(3, 1fr);
}
}
@media (max-width: 900px) {
.services-grid {
grid-template-columns: repeat(2, 1fr);
}
}
@media (max-width: 600px) {
.services-grid {
grid-template-columns: 1fr;
}
.settings-grid {
grid-template-columns: 1fr;
}
}

View File

@@ -0,0 +1,264 @@
/* ============================================
vAccess Editor Page
Страница редактора правил доступа
============================================ */
.vaccess-page {
animation: fadeIn var(--transition-slow);
}
/* Breadcrumbs */
.breadcrumbs {
display: flex;
align-items: center;
justify-content: space-between;
gap: var(--space-lg);
margin-bottom: var(--space-md);
padding: var(--space-md) 20px;
background: rgba(139, 92, 246, 0.05);
border-radius: var(--radius-lg);
border: 1px solid var(--glass-border);
}
.breadcrumbs-left {
display: flex;
align-items: center;
gap: var(--space-sm);
}
.breadcrumbs-tabs {
display: flex;
align-items: center;
gap: var(--space-sm);
}
.breadcrumb-separator {
color: var(--text-muted);
opacity: 0.3;
}
/* vAccess Header */
.vaccess-header {
display: flex;
justify-content: space-between;
align-items: flex-start;
margin-bottom: var(--space-md);
padding: var(--space-lg);
background: rgba(139, 92, 246, 0.03);
border-radius: var(--radius-xl);
border: 1px solid var(--glass-border);
}
.vaccess-title-block {
flex: 1;
}
.vaccess-actions {
display: flex;
flex-direction: column;
gap: var(--space-sm);
min-width: 200px;
.action-btn {
width: 100%;
justify-content: center;
padding: 10px var(--space-md);
font-size: var(--text-base);
}
}
.vaccess-title {
font-size: var(--text-3xl);
font-weight: var(--font-semibold);
color: var(--text-primary);
margin: 0 0 var(--space-sm) 0;
display: flex;
align-items: center;
gap: var(--space-lg);
i {
color: var(--accent-purple-light);
font-size: 24px;
}
}
.vaccess-subtitle {
font-size: var(--text-md);
color: var(--text-muted);
margin: 0;
}
/* vAccess Tab Content */
.vaccess-tab-content {
animation: fadeIn var(--transition-slow);
}
/* vAccess Rules Container */
.vaccess-rules-container {
/* Контейнер без padding чтобы таблица была на всю ширину */
width: 100%;
}
/* vAccess Rules List */
.vaccess-rules-list {
display: flex;
flex-direction: column;
gap: 20px;
margin-bottom: 20px;
max-height: 55vh;
overflow-y: auto;
padding-right: var(--space-sm);
}
/* Empty State */
.vaccess-empty {
text-align: center;
padding: 80px 40px;
color: var(--text-muted);
}
.empty-icon {
font-size: 64px;
margin-bottom: var(--space-lg);
opacity: 0.3;
}
.vaccess-empty h3 {
font-size: var(--text-2xl);
font-weight: var(--font-semibold);
color: var(--text-primary);
margin-bottom: 12px;
}
.vaccess-empty p {
font-size: var(--text-md);
margin-bottom: var(--space-lg);
}
/* vAccess Help */
.vaccess-help {
display: flex;
flex-direction: column;
gap: var(--space-lg);
}
/* Help Parameters */
.help-params {
display: flex;
flex-direction: column;
gap: var(--space-lg);
}
.help-param {
padding: 20px;
background: rgba(139, 92, 246, 0.03);
border-radius: var(--radius-lg);
border-left: 3px solid var(--accent-purple);
strong {
display: block;
font-size: 15px;
color: var(--accent-purple-light);
margin-bottom: var(--space-sm);
}
p {
margin: var(--space-sm) 0 0 0;
color: var(--text-secondary);
line-height: 1.6;
}
ul {
margin: 12px 0 0 20px;
}
code {
padding: 3px 8px;
background: rgba(139, 92, 246, 0.15);
border-radius: var(--radius-sm);
font-size: var(--text-base);
color: var(--accent-purple-light);
}
}
.help-warning {
color: rgba(251, 191, 36, 0.9) !important;
margin-top: var(--space-sm);
font-size: var(--text-base);
display: flex;
align-items: center;
gap: var(--space-sm);
}
/* Help Patterns */
.help-patterns {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
gap: var(--space-md);
}
.pattern-item {
display: flex;
flex-direction: column;
gap: var(--space-sm);
padding: var(--space-md);
background: rgba(139, 92, 246, 0.05);
border-radius: 10px;
transition: all var(--transition-base);
&:hover {
background: rgba(139, 92, 246, 0.1);
}
code {
font-size: var(--text-md);
font-weight: var(--font-semibold);
color: var(--accent-purple-light);
}
span {
font-size: var(--text-base);
color: var(--text-muted);
}
}
/* Help Examples */
.help-example {
margin-bottom: var(--space-xl);
&:last-child {
margin-bottom: 0;
}
h4 {
font-size: var(--text-lg);
font-weight: var(--font-semibold);
color: var(--text-primary);
margin-bottom: var(--space-md);
}
}
.example-rule {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
gap: 12px;
padding: 20px;
background: rgba(255, 255, 255, 0.02);
border-radius: 10px;
border: 1px solid var(--glass-border);
div {
font-size: var(--text-md);
color: var(--text-secondary);
}
strong {
color: var(--text-muted);
margin-right: var(--space-sm);
}
code {
color: var(--accent-purple-light);
}
}

View File

@@ -0,0 +1,100 @@
/* ============================================
CSS Custom Properties (Design Tokens)
Профессиональная система переменных
============================================ */
:root {
/* Colors - Background */
--bg-primary: #0b101f;
--bg-secondary: #121420;
--bg-tertiary: #0d0f1c;
/* Colors - Glass Effect */
--glass-bg: rgba(20, 20, 40, 0.4);
--glass-bg-light: rgba(20, 20, 40, 0.3);
--glass-bg-dark: rgba(10, 14, 26, 0.5);
--glass-border: rgba(139, 92, 246, 0.15);
--glass-border-hover: rgba(139, 92, 246, 0.3);
/* Colors - Accent */
--accent-blue: #5b21b6;
--accent-blue-light: #7c3aed;
--accent-purple: #8b5cf6;
--accent-purple-light: #a78bfa;
--accent-cyan: #06b6d4;
--accent-green: #10b981;
--accent-red: #ef4444;
--accent-yellow: #f59e0b;
/* Colors - Text */
--text-primary: #e2e8f0;
--text-secondary: #94a3b8;
--text-muted: #64748b;
/* Shadows */
--shadow-sm: 0 2px 8px rgba(0, 0, 0, 0.3);
--shadow-md: 0 8px 32px rgba(0, 0, 0, 0.5);
--shadow-lg: 0 12px 40px rgba(0, 0, 0, 0.7);
--shadow-purple: 0 8px 32px rgba(139, 92, 246, 0.3);
--shadow-green: 0 4px 12px rgba(16, 185, 129, 0.3);
--shadow-red: 0 4px 12px rgba(239, 68, 68, 0.3);
/* Spacing */
--space-xs: 4px;
--space-sm: 8px;
--space-md: 16px;
--space-lg: 24px;
--space-xl: 32px;
--space-2xl: 48px;
--space-3xl: 60px;
/* Border Radius */
--radius-sm: 6px;
--radius-md: 8px;
--radius-lg: 12px;
--radius-xl: 16px;
--radius-2xl: 10px;
--radius-full: 50%;
/* Transitions */
--transition-fast: 0.15s ease;
--transition-base: 0.2s ease;
--transition-slow: 0.3s ease;
--transition-bounce: 0.3s cubic-bezier(0.4, 0, 0.2, 1);
/* Typography */
--font-sans: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
--font-mono: 'Consolas', 'Courier New', monospace;
/* Font Sizes */
--text-xs: 10px;
--text-sm: 11px;
--text-base: 13px;
--text-md: 14px;
--text-lg: 16px;
--text-xl: 18px;
--text-2xl: 20px;
--text-3xl: 28px;
/* Font Weights */
--font-normal: 400;
--font-medium: 500;
--font-semibold: 600;
--font-bold: 700;
/* Z-Index Scale */
--z-base: 1;
--z-dropdown: 100;
--z-modal: 9998;
--z-notification: 9999;
--z-loader: 10000;
/* Layout */
--header-height: 60px;
--sidebar-width: 80px;
/* Backdrop Filter */
--backdrop-blur: blur(20px) saturate(180%);
--backdrop-blur-light: blur(10px);
}