Files
god_eye/backend/public/index.html
2025-10-06 09:41:23 +09:00

481 lines
16 KiB
HTML
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!DOCTYPE html>
<html lang="ru">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>GodEye Signal Center - Demo</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
background: #f5f7fa;
color: #333;
line-height: 1.6;
}
.container {
max-width: 1200px;
margin: 0 auto;
padding: 20px;
}
.header {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
color: white;
padding: 20px;
border-radius: 10px;
margin-bottom: 20px;
text-align: center;
}
.header h1 {
font-size: 2.5rem;
margin-bottom: 10px;
}
.tabs {
display: flex;
background: white;
border-radius: 10px;
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
margin-bottom: 20px;
overflow: hidden;
}
.tab {
flex: 1;
padding: 15px 20px;
text-align: center;
cursor: pointer;
background: #f8f9ff;
border: none;
font-size: 1rem;
transition: background-color 0.3s;
}
.tab:hover {
background: #e8ebff;
}
.tab.active {
background: #667eea;
color: white;
}
.tab-content {
display: none;
background: white;
border-radius: 10px;
padding: 20px;
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
}
.tab-content.active {
display: block;
}
.status-card {
background: #f8f9fa;
border: 1px solid #dee2e6;
border-radius: 8px;
padding: 15px;
margin-bottom: 15px;
}
.status-connected {
border-left: 4px solid #28a745;
}
.status-disconnected {
border-left: 4px solid #dc3545;
}
.form-group {
margin-bottom: 15px;
}
.form-group label {
display: block;
margin-bottom: 5px;
font-weight: 600;
}
.form-group input,
.form-group select,
.form-group textarea {
width: 100%;
padding: 10px;
border: 1px solid #ddd;
border-radius: 5px;
font-size: 1rem;
}
.btn {
background: #667eea;
color: white;
border: none;
padding: 12px 24px;
border-radius: 5px;
cursor: pointer;
font-size: 1rem;
margin: 5px;
transition: background-color 0.3s;
}
.btn:hover {
background: #5a6fd8;
}
.btn:disabled {
background: #ccc;
cursor: not-allowed;
}
.btn-danger {
background: #dc3545;
}
.btn-danger:hover {
background: #c82333;
}
.btn-success {
background: #28a745;
}
.btn-success:hover {
background: #218838;
}
.device-card, .session-card {
background: #f8f9fa;
border: 1px solid #dee2e6;
border-radius: 8px;
padding: 15px;
margin-bottom: 10px;
}
.device-online {
border-left: 4px solid #28a745;
}
.device-offline {
border-left: 4px solid #6c757d;
}
.session-active {
border-left: 4px solid #007bff;
}
.session-pending {
border-left: 4px solid #ffc107;
}
.session-closed {
border-left: 4px solid #6c757d;
}
.logs {
background: #1e1e1e;
color: #f8f8f2;
padding: 15px;
border-radius: 5px;
font-family: 'Courier New', monospace;
height: 300px;
overflow-y: auto;
font-size: 0.9rem;
line-height: 1.4;
}
.log-entry {
margin-bottom: 5px;
padding: 2px 0;
}
.log-info { color: #66d9ef; }
.log-warn { color: #f4bf75; }
.log-error { color: #f92672; }
.grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
gap: 20px;
}
.stats-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
gap: 15px;
margin-bottom: 20px;
}
.stat-card {
background: white;
padding: 20px;
border-radius: 8px;
text-align: center;
box-shadow: 0 2px 5px rgba(0,0,0,0.1);
}
.stat-number {
font-size: 2rem;
font-weight: bold;
color: #667eea;
}
.stat-label {
color: #666;
font-size: 0.9rem;
margin-top: 5px;
}
.video-container {
position: relative;
width: 100%;
max-width: 640px;
margin: 20px auto;
}
#localVideo, #remoteVideo {
width: 100%;
border-radius: 8px;
box-shadow: 0 4px 8px rgba(0,0,0,0.2);
}
.alert {
padding: 15px;
margin-bottom: 15px;
border-radius: 5px;
font-weight: 500;
}
.alert-info {
background: #d1ecf1;
color: #0c5460;
border: 1px solid #bee5eb;
}
.alert-warning {
background: #fff3cd;
color: #856404;
border: 1px solid #ffeaa7;
}
.alert-danger {
background: #f8d7da;
color: #721c24;
border: 1px solid #f5c6cb;
}
.alert-success {
background: #d4edda;
color: #155724;
border: 1px solid #c3e6cb;
}
@media (max-width: 768px) {
.tabs {
flex-direction: column;
}
.grid {
grid-template-columns: 1fr;
}
.header h1 {
font-size: 2rem;
}
}
</style>
</head>
<body>
<div class="container">
<div class="header">
<h1>🎥 GodEye Signal Center</h1>
<p>Веб-демонстрация системы удаленного доступа к камерам</p>
</div>
<div class="tabs">
<button class="tab active" onclick="showTab('overview')">Обзор</button>
<button class="tab" onclick="showTab('android')">Android Device</button>
<button class="tab" onclick="showTab('operator')">Operator</button>
<button class="tab" onclick="showTab('admin')">Admin</button>
<button class="tab" onclick="showTab('webrtc')">WebRTC Test</button>
</div>
<!-- Overview Tab -->
<div id="overview" class="tab-content active">
<h2>Системная статистика</h2>
<div class="stats-grid" id="stats-grid">
<div class="stat-card">
<div class="stat-number" id="stat-devices">-</div>
<div class="stat-label">Подключенных устройств</div>
</div>
<div class="stat-card">
<div class="stat-number" id="stat-operators">-</div>
<div class="stat-label">Активных операторов</div>
</div>
<div class="stat-card">
<div class="stat-number" id="stat-sessions">-</div>
<div class="stat-label">Активных сессий</div>
</div>
<div class="stat-card">
<div class="stat-number" id="stat-uptime">-</div>
<div class="stat-label">Время работы (мин)</div>
</div>
</div>
<div class="status-card" id="connection-status">
<h3>Состояние подключения</h3>
<p id="connection-text">Подключение...</p>
</div>
<h3>Логи системы</h3>
<div class="logs" id="system-logs"></div>
<button class="btn" onclick="clearLogs()">Очистить логи</button>
</div>
<!-- Android Device Tab -->
<div id="android" class="tab-content">
<h2>Симулятор Android устройства</h2>
<div class="form-group">
<label>Device ID:</label>
<input type="text" id="android-device-id" value="demo-device-001" placeholder="Введите ID устройства">
</div>
<div class="grid">
<div>
<h3>Информация об устройстве</h3>
<div class="form-group">
<label>Модель:</label>
<input type="text" id="android-model" value="Samsung Galaxy S21">
</div>
<div class="form-group">
<label>Производитель:</label>
<input type="text" id="android-manufacturer" value="Samsung">
</div>
<div class="form-group">
<label>Версия Android:</label>
<input type="text" id="android-version" value="12">
</div>
<div class="form-group">
<label>Доступные камеры:</label>
<select id="android-cameras" multiple>
<option value="back" selected>Основная</option>
<option value="front" selected>Фронтальная</option>
<option value="ultra_wide">Широкоугольная</option>
<option value="telephoto">Телеобъектив</option>
</select>
</div>
<button class="btn btn-success" id="android-connect" onclick="connectAndroid()">
Подключить устройство
</button>
<button class="btn btn-danger" id="android-disconnect" onclick="disconnectAndroid()" disabled>
Отключить устройство
</button>
</div>
<div>
<h3>Входящие запросы</h3>
<div id="android-requests"></div>
<h3>Активные сессии</h3>
<div id="android-sessions"></div>
</div>
</div>
</div>
<!-- Operator Tab -->
<div id="operator" class="tab-content">
<h2>Панель оператора</h2>
<div class="form-group">
<label>Operator ID:</label>
<input type="text" id="operator-id" value="demo-operator-001" placeholder="Введите ID оператора">
</div>
<button class="btn btn-success" id="operator-connect" onclick="connectOperator()">
Подключиться как оператор
</button>
<button class="btn btn-danger" id="operator-disconnect" onclick="disconnectOperator()" disabled>
Отключиться
</button>
<div class="grid">
<div>
<h3>Доступные устройства</h3>
<button class="btn" onclick="refreshDevices()">Обновить список</button>
<div id="available-devices"></div>
</div>
<div>
<h3>Мои сессии</h3>
<button class="btn" onclick="refreshSessions()">Обновить сессии</button>
<div id="operator-sessions"></div>
</div>
</div>
</div>
<!-- Admin Tab -->
<div id="admin" class="tab-content">
<h2>Административная панель</h2>
<div class="grid">
<div>
<h3>Управление системой</h3>
<button class="btn" onclick="getSystemHealth()">Проверить здоровье системы</button>
<button class="btn" onclick="getSystemStats()">Получить статистику</button>
<button class="btn btn-danger" onclick="cleanupSystem()">Очистить систему</button>
<div id="admin-info"></div>
</div>
<div>
<h3>Все устройства</h3>
<button class="btn" onclick="getAllDevices()">Загрузить устройства</button>
<div id="all-devices"></div>
<h3>Все сессии</h3>
<button class="btn" onclick="getAllSessions()">Загрузить сессии</button>
<div id="all-sessions"></div>
</div>
</div>
</div>
<!-- WebRTC Test Tab -->
<div id="webrtc" class="tab-content">
<h2>Тест WebRTC соединения</h2>
<div class="alert alert-info">
<strong>Информация:</strong> Этот раздел демонстрирует WebRTC соединение между устройством и оператором.
Сначала подключитесь как Android устройство, затем как оператор и создайте сессию.
</div>
<div class="form-group">
<label>Текущая сессия:</label>
<input type="text" id="current-session-id" placeholder="ID активной сессии" readonly>
</div>
<button class="btn" onclick="startLocalVideo()">Запустить локальное видео</button>
<button class="btn" onclick="stopLocalVideo()">Остановить видео</button>
<div class="video-container">
<video id="localVideo" autoplay muted playsinline></video>
<video id="remoteVideo" autoplay playsinline style="display: none;"></video>
</div>
<div id="webrtc-status"></div>
</div>
</div>
<script src="/socket.io/socket.io.js"></script>
<script src="demo.js"></script>
</body>
</html>