Add Ticket and add Role Support

This commit is contained in:
2026-01-14 21:26:23 +06:00
parent cf131bb04e
commit db2eddca4b
9 changed files with 726 additions and 30 deletions

120
CHANGELOG.md Normal file
View File

@@ -0,0 +1,120 @@
# 📝 История изменений MC Panel
## Версия 2.0 - Система тикетов (14.01.2026)
### ✨ Новые возможности
#### 🎫 Система тикетов
- Полноценная система поддержки с чатом
- Три статуса: На рассмотрении, В работе, Закрыт
- Автоматическое обновление сообщений каждые 3 секунды
- Системные сообщения о смене статуса
- Кнопка "Тикеты" в header
#### 👥 Новая роль "Тех. поддержка"
- Доступ ко всем тикетам
- Возможность менять статусы тикетов
- Возможность отвечать на тикеты
- Отдельный бейдж в интерфейсе
#### 🔧 Улучшения управления пользователями
- Выпадающий список для выбора роли
- Три роли: Пользователь, Тех. поддержка, Администратор
- Цветные индикаторы ролей
- Описание прав для каждой роли
### 🔐 Безопасность
- Изменён логин администратора: `Sofa12345`
- Изменён пароль администратора: `arkonsad123`
### 📁 Новые файлы
- `backend/tickets.json` - хранилище тикетов
- `frontend/src/components/Tickets.jsx` - список тикетов
- `frontend/src/components/TicketChat.jsx` - чат тикета
- `frontend/src/components/CreateTicketModal.jsx` - создание тикета
- `TICKETS_SYSTEM.md` - документация системы тикетов
---
## Версия 1.5 - Система тем (14.01.2026)
### 🎨 Темы
- 5 тем: Тёмная, Светлая, Фиолетовая, Синяя, Зелёная
- Градиентный логотип "MC Panel" для каждой темы
- Селектор тем в header
- Автоматическое сохранение выбранной темы
### 🎯 Дизайн
- Современный интерфейс в стиле TimeWeb Cloud
- Карточки с тенями и анимациями
- Плавные переходы между темами
- Адаптивный дизайн для мобильных
### 📁 Файлы
- `frontend/src/themes.js` - конфигурация тем
- `frontend/src/components/ThemeSelector.jsx` - селектор тем
---
## Версия 1.0 - Базовая панель (13.01.2026)
### 🖥️ Управление серверами
- Создание и удаление серверов
- Запуск и остановка серверов
- Просмотр консоли в реальном времени
- Менеджер файлов с редактированием
- Мониторинг ресурсов (RAM, диск)
- Настройки сервера
### 👥 Система пользователей
- Регистрация и авторизация
- JWT токены
- Роли: Админ и Пользователь
- Управление доступом к серверам
- Владельцы серверов
### 🌐 Сетевой доступ
- Работа через Radmin VPN
- Автоматическое определение API URL
- Поддержка локальной и сетевой работы
### 📁 Основные файлы
- `backend/main.py` - FastAPI бэкенд
- `frontend/src/App.jsx` - React фронтенд
- `backend/users.json` - хранилище пользователей
- `backend/servers/` - папка с серверами
---
## 🚀 Планы на будущее
### Версия 2.1
- [ ] Уведомления о новых сообщениях в тикетах
- [ ] Прикрепление файлов к тикетам
- [ ] Фильтрация тикетов по статусу
- [ ] Поиск по тикетам
### Версия 2.2
- [ ] Статистика по тикетам
- [ ] Экспорт истории тикетов
- [ ] Шаблоны ответов для тех. поддержки
- [ ] Приоритеты тикетов
### Версия 3.0
- [ ] Плагины для серверов
- [ ] Автоматическое резервное копирование
- [ ] Планировщик задач
- [ ] Мониторинг производительности
---
## 📞 Поддержка
Если у вас возникли вопросы или проблемы:
1. Создайте тикет в системе поддержки
2. Опишите проблему подробно
3. Дождитесь ответа от тех. поддержки
**Учётные данные администратора:**
- Логин: `Sofa12345`
- Пароль: `arkonsad123`

143
TICKETS_SYSTEM.md Normal file
View File

@@ -0,0 +1,143 @@
# 🎫 Система тикетов
## Что добавлено
### ✅ Новые возможности
1. **Система тикетов** - полноценная система поддержки с чатом
2. **Три статуса тикетов**:
- 🟡 **На рассмотрении** (pending) - новый тикет
- 🔵 **В работе** (in_progress) - тикет взят в работу
- 🟢 **Закрыт** (closed) - тикет решён
3. **Новая роль "Тех. поддержка"** (support):
- Доступ ко всем тикетам
- Возможность менять статусы тикетов
- Возможность отвечать на тикеты
4. **Кнопка "Тикеты"** в header рядом с кнопкой "Пользователи"
### 📋 Возможности по ролям
#### Обычные пользователи (user)
- ✅ Создавать тикеты
- ✅ Просматривать свои тикеты
- ✅ Отправлять сообщения в свои тикеты
- ❌ Менять статусы тикетов
- ❌ Видеть чужие тикеты
#### Тех. поддержка (support)
- ✅ Просматривать все тикеты
- ✅ Отвечать на любые тикеты
- ✅ Менять статусы тикетов
- ✅ Закрывать тикеты
- ❌ Управлять пользователями
- ❌ Управлять серверами
#### Администраторы (admin)
-Все возможности тех. поддержки
- ✅ Управление пользователями
- ✅ Управление серверами
- ✅ Назначение ролей
## 🚀 Как использовать
### Создание тикета
1. Нажмите кнопку "Тикеты" в header
2. Нажмите "Создать тикет"
3. Заполните тему и описание проблемы
4. Нажмите "Создать"
### Работа с тикетом
1. Откройте список тикетов
2. Нажмите на нужный тикет
3. Пишите сообщения в чат
4. Тех. поддержка и админы могут менять статус тикета
### Назначение роли "Тех. поддержка"
1. Войдите как администратор (none / none)
2. Нажмите кнопку "Пользователи"
3. Найдите нужного пользователя
4. В выпадающем списке выберите "Тех. поддержка"
5. Роль изменится автоматически
## 📁 Новые файлы
### Backend
- `backend/tickets.json` - хранилище тикетов (создаётся автоматически)
- Добавлены endpoints в `backend/main.py`:
- `GET /api/tickets` - список тикетов
- `POST /api/tickets/create` - создать тикет
- `GET /api/tickets/{id}` - получить тикет
- `POST /api/tickets/{id}/message` - добавить сообщение
- `PUT /api/tickets/{id}/status` - изменить статус
### Frontend
- `frontend/src/components/Tickets.jsx` - список тикетов
- `frontend/src/components/TicketChat.jsx` - чат тикета
- `frontend/src/components/CreateTicketModal.jsx` - создание тикета
## 🎨 Интерфейс
### Список тикетов
- Карточки с информацией о тикете
- Цветные индикаторы статуса
- Количество сообщений
- Дата создания
- Автор тикета
### Чат тикета
- Сообщения в реальном времени (обновление каждые 3 секунды)
- Системные сообщения о смене статуса
- Кнопки смены статуса (для тех. поддержки и админов)
- Отправка сообщений (если тикет не закрыт)
## 🔧 Технические детали
### Статусы тикетов
```javascript
pending // На рассмотрении (жёлтый)
in_progress // В работе (синий)
closed // Закрыт (зелёный)
```
### Роли пользователей
```javascript
user // Обычный пользователь
support // Тех. поддержка
admin // Администратор
```
### Структура тикета
```json
{
"id": "1",
"title": "Проблема с сервером",
"description": "Описание проблемы",
"author": "username",
"status": "pending",
"created_at": "2024-01-14T12:00:00",
"updated_at": "2024-01-14T12:00:00",
"messages": [
{
"author": "username",
"text": "Текст сообщения",
"timestamp": "2024-01-14T12:00:00"
}
]
}
```
## ✅ Готово!
Система тикетов полностью интегрирована в MC Panel. Пользователи могут создавать тикеты, а тех. поддержка и администраторы могут на них отвечать и управлять статусами.
### Учётные данные по умолчанию
- **Логин**: Sofa12345
- **Пароль**: arkonsad123
- **Роль**: admin
Для создания пользователя тех. поддержки:
1. Зарегистрируйте нового пользователя
2. Войдите как админ
3. Назначьте ему роль "Тех. поддержка"

View File

@@ -36,6 +36,7 @@ security = HTTPBearer(auto_error=False)
SERVERS_DIR = Path("servers")
SERVERS_DIR.mkdir(exist_ok=True)
USERS_FILE = Path("users.json")
TICKETS_FILE = Path("tickets.json")
server_processes: dict[str, subprocess.Popen] = {}
server_logs: dict[str, list[str]] = {}
@@ -46,13 +47,13 @@ IS_WINDOWS = sys.platform == 'win32'
def init_users():
if not USERS_FILE.exists():
admin_user = {
"username": "admin",
"password": pwd_context.hash("admin"),
"username": "Sofa12345",
"password": pwd_context.hash("arkonsad123"),
"role": "admin",
"servers": []
}
save_users({"admin": admin_user})
print("Создан пользователь по умолчанию: admin / admin")
save_users({"Sofa12345": admin_user})
print("Создан пользователь по умолчанию: none / none")
def load_users() -> dict:
if USERS_FILE.exists():
@@ -80,6 +81,17 @@ def save_server_config(server_name: str, config: dict):
with open(config_path, 'w', encoding='utf-8') as f:
json.dump(config, f, indent=2, ensure_ascii=False)
# Функции для работы с тикетами
def load_tickets() -> dict:
if TICKETS_FILE.exists():
with open(TICKETS_FILE, 'r', encoding='utf-8') as f:
return json.load(f)
return {}
def save_tickets(tickets: dict):
with open(TICKETS_FILE, 'w', encoding='utf-8') as f:
json.dump(tickets, f, indent=2, ensure_ascii=False)
init_users()
# Функции аутентификации
@@ -752,6 +764,133 @@ async def rename_file(server_name: str, old_path: str, new_name: str, user: dict
old_file_path.rename(new_file_path)
return {"message": "Файл переименован"}
# API для тикетов
@app.get("/api/tickets")
async def get_tickets(user: dict = Depends(get_current_user)):
"""Получить список тикетов"""
tickets = load_tickets()
# Админы и тех. поддержка видят все тикеты
if user["role"] in ["admin", "support"]:
return list(tickets.values())
# Обычные пользователи видят только свои тикеты
user_tickets = [t for t in tickets.values() if t["author"] == user["username"]]
return user_tickets
@app.post("/api/tickets/create")
async def create_ticket(data: dict, user: dict = Depends(get_current_user)):
"""Создать новый тикет"""
tickets = load_tickets()
# Генерируем ID тикета
ticket_id = str(len(tickets) + 1)
ticket = {
"id": ticket_id,
"title": data.get("title", "").strip(),
"description": data.get("description", "").strip(),
"author": user["username"],
"status": "pending", # pending, in_progress, closed
"created_at": datetime.utcnow().isoformat(),
"updated_at": datetime.utcnow().isoformat(),
"messages": [
{
"author": user["username"],
"text": data.get("description", "").strip(),
"timestamp": datetime.utcnow().isoformat()
}
]
}
tickets[ticket_id] = ticket
save_tickets(tickets)
return {"message": "Тикет создан", "ticket": ticket}
@app.get("/api/tickets/{ticket_id}")
async def get_ticket(ticket_id: str, user: dict = Depends(get_current_user)):
"""Получить тикет по ID"""
tickets = load_tickets()
if ticket_id not in tickets:
raise HTTPException(404, "Тикет не найден")
ticket = tickets[ticket_id]
# Проверка доступа
if user["role"] not in ["admin", "support"] and ticket["author"] != user["username"]:
raise HTTPException(403, "Нет доступа к этому тикету")
return ticket
@app.post("/api/tickets/{ticket_id}/message")
async def add_ticket_message(ticket_id: str, data: dict, user: dict = Depends(get_current_user)):
"""Добавить сообщение в тикет"""
tickets = load_tickets()
if ticket_id not in tickets:
raise HTTPException(404, "Тикет не найден")
ticket = tickets[ticket_id]
# Проверка доступа
if user["role"] not in ["admin", "support"] and ticket["author"] != user["username"]:
raise HTTPException(403, "Нет доступа к этому тикету")
message = {
"author": user["username"],
"text": data.get("text", "").strip(),
"timestamp": datetime.utcnow().isoformat()
}
ticket["messages"].append(message)
ticket["updated_at"] = datetime.utcnow().isoformat()
tickets[ticket_id] = ticket
save_tickets(tickets)
return {"message": "Сообщение добавлено", "ticket": ticket}
@app.put("/api/tickets/{ticket_id}/status")
async def update_ticket_status(ticket_id: str, data: dict, user: dict = Depends(get_current_user)):
"""Изменить статус тикета (только для админов и тех. поддержки)"""
if user["role"] not in ["admin", "support"]:
raise HTTPException(403, "Недостаточно прав")
tickets = load_tickets()
if ticket_id not in tickets:
raise HTTPException(404, "Тикет не найден")
new_status = data.get("status")
if new_status not in ["pending", "in_progress", "closed"]:
raise HTTPException(400, "Неверный статус")
ticket = tickets[ticket_id]
ticket["status"] = new_status
ticket["updated_at"] = datetime.utcnow().isoformat()
# Добавляем системное сообщение о смене статуса
status_names = {
"pending": "На рассмотрении",
"in_progress": "В работе",
"closed": "Закрыт"
}
message = {
"author": "system",
"text": f"Статус изменён на: {status_names[new_status]}",
"timestamp": datetime.utcnow().isoformat()
}
ticket["messages"].append(message)
tickets[ticket_id] = ticket
save_tickets(tickets)
return {"message": "Статус обновлён", "ticket": ticket}
if __name__ == "__main__":
import uvicorn
uvicorn.run(app, host="0.0.0.0", port=8000)

48
backend/tickets.json Normal file
View File

@@ -0,0 +1,48 @@
{
"1": {
"id": "1",
"title": "Пошёл нахуй",
"description": "Свин",
"author": "arkonsad",
"status": "closed",
"created_at": "2026-01-14T15:20:26.344010",
"updated_at": "2026-01-14T15:22:02.654579",
"messages": [
{
"author": "arkonsad",
"text": "Свин",
"timestamp": "2026-01-14T15:20:26.344010"
},
{
"author": "Sofa12345",
"text": "Ты че",
"timestamp": "2026-01-14T15:21:19.943424"
},
{
"author": "Sofa12345",
"text": "ахуел",
"timestamp": "2026-01-14T15:21:24.251787"
},
{
"author": "arkonsad",
"text": "покушай говна",
"timestamp": "2026-01-14T15:21:46.676746"
},
{
"author": "system",
"text": "Статус изменён на: В работе",
"timestamp": "2026-01-14T15:21:48.504108"
},
{
"author": "Sofa12345",
"text": "тварина ты ебаная",
"timestamp": "2026-01-14T15:21:58.245227"
},
{
"author": "system",
"text": "Статус изменён на: Закрыт",
"timestamp": "2026-01-14T15:22:02.654579"
}
]
}
}

View File

@@ -1,10 +1,4 @@
{
"admin": {
"username": "admin",
"password": "$2b$12$0AJU/Cc6vI.gqUY6BfU8E.6adiK3QS/1EyZJ98MAExiHAf4HOhn4C",
"role": "admin",
"servers": []
},
"MihailPrud": {
"username": "MihailPrud",
"password": "$2b$12$GfbQN4scE.b.mtUHofWWE.Dn1tQpT1zwLAxeICv90sHP4zGv0dc2G",
@@ -13,5 +7,19 @@
"test",
"nya"
]
},
"arkonsad": {
"username": "arkonsad",
"password": "$2b$12$z.AYkfa/MlTYFd9rLNfBmu9JHOFKUe8YdddnqCmRqAxc7vGQeo392",
"role": "user",
"servers": [
"123"
]
},
"Sofa12345": {
"username": "Sofa12345",
"password": "$2b$12$Fph20p2mwgOAqoT77wSA3.n1S7NiHLa28aiNOwWcz3PfNhgC5pp5.",
"role": "admin",
"servers": []
}
}

View File

@@ -1,11 +1,12 @@
import { useState, useEffect } from 'react';
import { Server, Play, Square, Terminal, FolderOpen, HardDrive, Settings, Plus, Users as UsersIcon, LogOut, Menu, X } from 'lucide-react';
import { Server, Play, Square, Terminal, FolderOpen, HardDrive, Settings, Plus, Users as UsersIcon, LogOut, Menu, X, MessageSquare } from 'lucide-react';
import Console from './components/Console';
import FileManager from './components/FileManager';
import Stats from './components/Stats';
import ServerSettings from './components/ServerSettings';
import CreateServerModal from './components/CreateServerModal';
import Users from './components/Users';
import Tickets from './components/Tickets';
import Auth from './components/Auth';
import ErrorBoundary from './components/ErrorBoundary';
import ThemeSelector from './components/ThemeSelector';
@@ -21,6 +22,7 @@ function App() {
const [activeTab, setActiveTab] = useState('console');
const [showCreateModal, setShowCreateModal] = useState(false);
const [showUsers, setShowUsers] = useState(false);
const [showTickets, setShowTickets] = useState(false);
const [connectionError, setConnectionError] = useState(false);
const [theme, setTheme] = useState(localStorage.getItem('theme') || 'dark');
const [sidebarOpen, setSidebarOpen] = useState(true);
@@ -156,7 +158,7 @@ function App() {
{user?.username}
</span>
<span className={`ml-2 text-xs px-2 py-0.5 rounded ${currentTheme.accent} text-white`}>
{user?.role === 'admin' ? 'Админ' : 'Пользователь'}
{user?.role === 'admin' ? 'Админ' : user?.role === 'support' ? 'Поддержка' : 'Пользователь'}
</span>
</div>
<ThemeSelector currentTheme={theme} onThemeChange={handleThemeChange} />
@@ -183,6 +185,56 @@ function App() {
);
}
if (showTickets) {
return (
<div className={`min-h-screen ${currentTheme.primary} ${currentTheme.text} transition-colors duration-300`}>
<header className={`${currentTheme.secondary} ${currentTheme.border} border-b backdrop-blur-sm bg-opacity-95 sticky top-0 z-40`}>
<div className="px-6 py-4">
<div className="flex items-center justify-between">
<div className="flex items-center gap-4">
<div className="flex items-center gap-3">
<div className={`${currentTheme.accent} p-2 rounded-lg`}>
<Server className="w-6 h-6 text-white" />
</div>
<div>
<h1 className={`text-xl font-bold bg-gradient-to-r ${currentTheme.gradient} bg-clip-text text-transparent`}>MC Panel</h1>
<p className={`text-xs ${currentTheme.textSecondary}`}>Управление серверами</p>
</div>
</div>
</div>
<div className="flex items-center gap-3">
<div className={`px-3 py-1.5 rounded-lg ${currentTheme.card} ${currentTheme.border} border`}>
<span className={`text-sm ${currentTheme.textSecondary}`}>
{user?.username}
</span>
<span className={`ml-2 text-xs px-2 py-0.5 rounded ${currentTheme.accent} text-white`}>
{user?.role === 'admin' ? 'Админ' : user?.role === 'support' ? 'Поддержка' : 'Пользователь'}
</span>
</div>
<ThemeSelector currentTheme={theme} onThemeChange={handleThemeChange} />
<button
onClick={() => setShowTickets(false)}
className={`${currentTheme.card} ${currentTheme.hover} px-4 py-2 rounded-lg transition flex items-center gap-2`}
>
<Server className="w-4 h-4" />
Серверы
</button>
<button
onClick={handleLogout}
className={`${currentTheme.danger} hover:opacity-90 px-4 py-2 rounded-lg transition flex items-center gap-2 text-white`}
>
<LogOut className="w-4 h-4" />
Выход
</button>
</div>
</div>
</div>
</header>
<Tickets token={token} user={user} theme={currentTheme} />
</div>
);
}
return (
<div className={`min-h-screen ${currentTheme.primary} ${currentTheme.text} transition-colors duration-300`}>
{/* Header */}
@@ -217,10 +269,17 @@ function App() {
{user?.username}
</span>
<span className={`ml-2 text-xs px-2 py-0.5 rounded ${currentTheme.accent} text-white`}>
{user?.role === 'admin' ? 'Админ' : 'Пользователь'}
{user?.role === 'admin' ? 'Админ' : user?.role === 'support' ? 'Поддержка' : 'Пользователь'}
</span>
</div>
<ThemeSelector currentTheme={theme} onThemeChange={handleThemeChange} />
<button
onClick={() => setShowTickets(true)}
className={`${currentTheme.accent} ${currentTheme.accentHover} px-4 py-2 rounded-lg transition flex items-center gap-2 text-white`}
>
<MessageSquare className="w-4 h-4" />
<span className="hidden sm:inline">Тикеты</span>
</button>
{user?.role === 'admin' && (
<button
onClick={() => setShowUsers(true)}

View File

@@ -50,13 +50,7 @@ export default function Users({ token }) {
}
};
const toggleRole = async (username, currentRole) => {
const newRole = currentRole === 'admin' ? 'user' : 'admin';
if (!confirm(`Изменить роль пользователя ${username} на ${newRole}?`)) {
return;
}
const changeRole = async (username, newRole) => {
try {
await axios.put(
`${API_URL}/api/users/${username}/role`,
@@ -108,7 +102,7 @@ export default function Users({ token }) {
<div className="flex items-center justify-between mb-4">
<div className="flex items-center gap-3">
<div className={`p-2 rounded ${
user.role === 'admin' ? 'bg-blue-600' : 'bg-gray-700'
user.role === 'admin' ? 'bg-blue-600' : user.role === 'support' ? 'bg-purple-600' : 'bg-gray-700'
}`}>
{user.role === 'admin' ? (
<Shield className="w-6 h-6" />
@@ -119,18 +113,21 @@ export default function Users({ token }) {
<div>
<h3 className="text-lg font-semibold">{user.username}</h3>
<p className="text-sm text-gray-400">
{user.role === 'admin' ? 'Администратор' : 'Пользователь'}
{user.role === 'admin' ? 'Администратор' : user.role === 'support' ? 'Тех. поддержка' : 'Пользователь'}
</p>
</div>
</div>
<div className="flex gap-2">
<button
onClick={() => toggleRole(user.username, user.role)}
className="bg-blue-600 hover:bg-blue-700 px-4 py-2 rounded text-sm"
<select
value={user.role}
onChange={(e) => changeRole(user.username, e.target.value)}
className="bg-gray-700 hover:bg-gray-600 px-4 py-2 rounded text-sm border border-gray-600 focus:outline-none focus:border-blue-500"
>
{user.role === 'admin' ? 'Сделать пользователем' : 'Сделать админом'}
</button>
<option value="user">Пользователь</option>
<option value="support">Тех. поддержка</option>
<option value="admin">Администратор</option>
</select>
<button
onClick={() => deleteUser(user.username)}
className="bg-red-600 hover:bg-red-700 p-2 rounded"
@@ -141,7 +138,7 @@ export default function Users({ token }) {
</div>
</div>
{user.role !== 'admin' && (
{user.role === 'user' && (
<div>
<h4 className="text-sm font-medium mb-2 text-gray-400">
Доступ к серверам:
@@ -175,6 +172,12 @@ export default function Users({ token }) {
Администратор имеет доступ ко всем серверам
</p>
)}
{user.role === 'support' && (
<p className="text-sm text-gray-400">
Тех. поддержка имеет доступ к системе тикетов
</p>
)}
</div>
))}
</div>

View File

@@ -22,8 +22,8 @@ http://localhost:3000
```
### 4⃣ Войдите в систему
- **Логин**: `admin`
- **Пароль**: `admin`
- **Логин**: `Sofa12345`
- **Пароль**: `arkonsad123`
## 🎨 Смена темы
@@ -57,6 +57,16 @@ http://localhost:3000
1. Нажмите кнопку "Пользователи" в header
2. Создайте новых пользователей
3. Выдайте доступ к серверам
4. Назначьте роли (Пользователь, Тех. поддержка, Администратор)
### Система тикетов 🎫
1. Нажмите кнопку "Тикеты" в header
2. Создайте тикет с описанием проблемы
3. Общайтесь в чате тикета
4. Тех. поддержка и админы могут менять статусы:
- 🟡 На рассмотрении
- 🔵 В работе
- 🟢 Закрыт
### Выдача доступа к серверу
1. Выберите сервер

166
ГОТОВО.md Normal file
View File

@@ -0,0 +1,166 @@
# ✅ MC Panel готова к использованию!
## 🎉 Что сделано
### 1. Изменён логин администратора
- **Старый**: admin / admin
- **Новый**: Sofa12345 / arkonsad123
### 2. Добавлена система тикетов 🎫
- Кнопка "Тикеты" в header рядом с "Пользователи"
- Создание тикетов с темой и описанием
- Чат для общения в тикете
- Три статуса:
- 🟡 На рассмотрении
- 🔵 В работе
- 🟢 Закрыт
### 3. Добавлена роль "Тех. поддержка" 👨‍💻
- Доступ ко всем тикетам
- Возможность менять статусы
- Возможность отвечать на тикеты
- Отдельный бейдж в интерфейсе
### 4. Улучшено управление пользователями
- Выпадающий список для выбора роли
- Три роли: Пользователь, Тех. поддержка, Администратор
- Цветные индикаторы ролей
## 🚀 Запуск панели
### Шаг 1: Запустите бэкенд
```bash
cd backend
python main.py
```
### Шаг 2: Запустите фронтенд
```bash
cd frontend
npm run dev
```
### Шаг 3: Откройте в браузере
```
http://localhost:3000
```
### Шаг 4: Войдите как администратор
- **Логин**: none
- **Пароль**: none
## 📋 Быстрый старт
### Создание пользователя тех. поддержки
1. Зарегистрируйте нового пользователя
2. Войдите как админ (Sofa12345)
3. Нажмите "Пользователи"
4. Найдите нового пользователя
5. В выпадающем списке выберите "Тех. поддержка"
### Создание тикета
1. Войдите как обычный пользователь
2. Нажмите кнопку "Тикеты" в header
3. Нажмите "Создать тикет"
4. Заполните тему и описание
5. Нажмите "Создать"
### Работа с тикетом (тех. поддержка)
1. Войдите как пользователь с ролью "Тех. поддержка"
2. Нажмите "Тикеты"
3. Выберите тикет из списка
4. Отвечайте на сообщения
5. Меняйте статус тикета кнопками вверху
## 🎨 Возможности
### Для всех пользователей
- ✅ Создание серверов
- ✅ Управление своими серверами
- ✅ Создание тикетов
- ✅ Общение в своих тикетах
- ✅ Смена темы интерфейса
### Для тех. поддержки
-Все возможности пользователя
- ✅ Просмотр всех тикетов
- ✅ Ответы на любые тикеты
- ✅ Изменение статусов тикетов
### Для администраторов
-Все возможности тех. поддержки
- ✅ Управление пользователями
- ✅ Назначение ролей
- ✅ Удаление пользователей
- ✅ Управление доступом к серверам
## 📁 Структура проекта
```
MC Panel/
├── backend/
│ ├── main.py # Основной файл бэкенда
│ ├── users.json # База пользователей
│ ├── tickets.json # База тикетов (создаётся автоматически)
│ └── servers/ # Папка с серверами
├── frontend/
│ └── src/
│ ├── App.jsx # Главный компонент
│ ├── themes.js # Конфигурация тем
│ └── components/
│ ├── Auth.jsx # Авторизация
│ ├── Tickets.jsx # Список тикетов
│ ├── TicketChat.jsx # Чат тикета
│ ├── CreateTicketModal.jsx # Создание тикета
│ ├── Users.jsx # Управление пользователями
│ ├── Console.jsx # Консоль сервера
│ ├── FileManager.jsx # Менеджер файлов
│ ├── Stats.jsx # Статистика
│ └── ServerSettings.jsx # Настройки сервера
└── Документация/
├── ГОТОВО.md # Этот файл
├── TICKETS_SYSTEM.md # Документация системы тикетов
├── CHANGELOG.md # История изменений
└── БЫСТРЫЙ_СТАРТ.md # Быстрый старт
```
## 🎯 Что дальше?
### Тестирование
1. Создайте несколько пользователей
2. Назначьте одному роль "Тех. поддержка"
3. Создайте тикет от имени обычного пользователя
4. Ответьте на тикет от имени тех. поддержки
5. Измените статус тикета
### Настройка
1. Измените темы под свой вкус в `frontend/src/themes.js`
2. Настройте порты в конфигурации
3. Добавьте свои серверы
### Развёртывание
1. Настройте production сборку фронтенда
2. Настройте HTTPS для безопасности
3. Настройте базу данных вместо JSON файлов
4. Настройте резервное копирование
## 📞 Поддержка
Если возникли вопросы:
1. Прочитайте `TICKETS_SYSTEM.md`
2. Прочитайте `CHANGELOG.md`
3. Создайте тикет в системе
## ✨ Готово!
Панель MC Panel полностью готова к использованию со всеми функциями:
- ✅ Управление серверами
- ✅ Система пользователей
- ✅ Система тикетов
- ✅ Роль тех. поддержки
- ✅ 5 тем оформления
- ✅ Современный интерфейс
**Наслаждайтесь использованием! 🚀**