Files
crm.clientright.ru/view_server_logs.html

341 lines
11 KiB
HTML
Raw 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>Просмотр серверных логов AI Drawer</title>
<style>
body {
font-family: Arial, sans-serif;
margin: 0;
padding: 20px;
background: #f5f5f5;
}
.container {
max-width: 1200px;
margin: 0 auto;
background: white;
padding: 20px;
border-radius: 10px;
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
}
.header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 20px;
padding-bottom: 20px;
border-bottom: 2px solid #007bff;
}
.status {
padding: 10px 15px;
border-radius: 5px;
font-weight: bold;
}
.status.success {
background: #d4edda;
color: #155724;
}
.status.error {
background: #f8d7da;
color: #721c24;
}
.status.warning {
background: #fff3cd;
color: #856404;
}
.controls {
margin-bottom: 20px;
display: flex;
gap: 10px;
flex-wrap: wrap;
}
.btn {
padding: 10px 20px;
border: none;
border-radius: 5px;
cursor: pointer;
font-size: 14px;
font-weight: bold;
}
.btn-primary {
background: #007bff;
color: white;
}
.btn-secondary {
background: #6c757d;
color: white;
}
.btn-danger {
background: #dc3545;
color: white;
}
.btn:hover {
opacity: 0.8;
}
.log-container {
background: #f8f9fa;
border: 1px solid #dee2e6;
border-radius: 5px;
padding: 15px;
max-height: 600px;
overflow-y: auto;
font-family: 'Courier New', monospace;
font-size: 12px;
white-space: pre-wrap;
}
.log-entry {
margin: 5px 0;
padding: 8px;
border-radius: 3px;
border-left: 4px solid #ccc;
}
.log-info {
border-left-color: #17a2b8;
background: #d1ecf1;
}
.log-success {
border-left-color: #28a745;
background: #d4edda;
}
.log-warning {
border-left-color: #ffc107;
background: #fff3cd;
}
.log-error {
border-left-color: #dc3545;
background: #f8d7da;
}
.log-debug {
border-left-color: #6c757d;
background: #e2e3e5;
}
.stats {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
gap: 15px;
margin-bottom: 20px;
}
.stat-card {
background: #f8f9fa;
padding: 15px;
border-radius: 5px;
border-left: 4px solid #007bff;
}
.stat-title {
font-size: 12px;
color: #6c757d;
margin-bottom: 5px;
}
.stat-value {
font-size: 24px;
font-weight: bold;
color: #007bff;
}
</style>
</head>
<body>
<div class="container">
<div class="header">
<h1>📋 Серверные логи AI Drawer</h1>
<div id="server-status" class="status">Проверка...</div>
</div>
<div class="stats" id="stats-container">
<!-- Статистика будет загружена здесь -->
</div>
<div class="controls">
<button class="btn btn-primary" onclick="loadLogs()">🔄 Обновить</button>
<button class="btn btn-secondary" onclick="loadLogs(100)">📄 Последние 100</button>
<button class="btn btn-secondary" onclick="loadLogs(500)">📄 Последние 500</button>
<button class="btn btn-danger" onclick="clearLogs()">🗑️ Очистить все</button>
<button class="btn btn-secondary" onclick="exportLogs()">💾 Экспорт</button>
</div>
<div id="log-container" class="log-container">
Загрузка логов...
</div>
</div>
<script>
let currentLogs = [];
function updateStatus(message, type = 'info') {
const statusEl = document.getElementById('server-status');
statusEl.textContent = message;
statusEl.className = `status ${type}`;
}
function updateStats(logs) {
const statsContainer = document.getElementById('stats-container');
const totalLogs = logs.length;
const errorLogs = logs.filter(log => log.data.type === 'error').length;
const warningLogs = logs.filter(log => log.data.type === 'warning').length;
const successLogs = logs.filter(log => log.data.type === 'success').length;
const uniqueDevices = new Set(logs.map(log => log.data.screenSize)).size;
const uniqueBrowsers = new Set(logs.map(log => log.data.userAgent?.split(' ')[0])).size;
statsContainer.innerHTML = `
<div class="stat-card">
<div class="stat-title">Всего записей</div>
<div class="stat-value">${totalLogs}</div>
</div>
<div class="stat-card">
<div class="stat-title">Ошибки</div>
<div class="stat-value" style="color: #dc3545;">${errorLogs}</div>
</div>
<div class="stat-card">
<div class="stat-title">Предупреждения</div>
<div class="stat-value" style="color: #ffc107;">${warningLogs}</div>
</div>
<div class="stat-card">
<div class="stat-title">Успешные</div>
<div class="stat-value" style="color: #28a745;">${successLogs}</div>
</div>
<div class="stat-card">
<div class="stat-title">Устройства</div>
<div class="stat-value">${uniqueDevices}</div>
</div>
<div class="stat-card">
<div class="stat-title">Браузеры</div>
<div class="stat-value">${uniqueBrowsers}</div>
</div>
`;
}
function displayLogs(logs) {
const container = document.getElementById('log-container');
currentLogs = logs;
if (logs.length === 0) {
container.innerHTML = 'Логи не найдены';
return;
}
const logHTML = logs.map(log => {
const type = log.data.type || 'info';
const details = log.data.details ?
`\nДетали: ${JSON.stringify(log.data.details, null, 2)}` : '';
return `
<div class="log-entry log-${type}">
<strong>[${log.timestamp}] ${log.data.type?.toUpperCase() || 'INFO'}:</strong> ${log.data.message}
${details}
<div style="margin-top: 5px; font-size: 10px; color: #6c757d;">
Устройство: ${log.data.screenSize || 'N/A'} |
Браузер: ${log.data.userAgent?.split(' ')[0] || 'N/A'}
</div>
</div>
`;
}).join('');
container.innerHTML = logHTML;
updateStats(logs);
}
function loadLogs(limit = 50) {
updateStatus('Загрузка логов...', 'info');
fetch(`/test_log_server.php?action=read&limit=${limit}`)
.then(response => response.json())
.then(data => {
if (data.success) {
displayLogs(data.logs);
updateStatus(`Загружено ${data.logs.length} записей`, 'success');
} else {
updateStatus(`Ошибка: ${data.message}`, 'error');
}
})
.catch(error => {
updateStatus(`Ошибка подключения: ${error.message}`, 'error');
});
}
function clearLogs() {
if (!confirm('Вы уверены, что хотите очистить все логи?')) {
return;
}
updateStatus('Очистка логов...', 'warning');
fetch('/test_log_server.php?action=clear')
.then(response => response.json())
.then(data => {
if (data.success) {
updateStatus('Логи очищены', 'success');
document.getElementById('log-container').innerHTML = 'Логи очищены';
document.getElementById('stats-container').innerHTML = '';
} else {
updateStatus(`Ошибка: ${data.message}`, 'error');
}
})
.catch(error => {
updateStatus(`Ошибка подключения: ${error.message}`, 'error');
});
}
function exportLogs() {
if (currentLogs.length === 0) {
alert('Нет логов для экспорта');
return;
}
const logText = currentLogs.map(log => {
const details = log.data.details ?
`\nДетали: ${JSON.stringify(log.data.details, null, 2)}` : '';
return `[${log.timestamp}] ${log.data.type?.toUpperCase() || 'INFO'}: ${log.data.message}${details}`;
}).join('\n\n');
const blob = new Blob([logText], { type: 'text/plain' });
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = `ai-drawer-server-logs-${new Date().toISOString().slice(0, 19)}.txt`;
a.click();
URL.revokeObjectURL(url);
updateStatus('Логи экспортированы', 'success');
}
// Загружаем логи при загрузке страницы
document.addEventListener('DOMContentLoaded', function() {
loadLogs();
// Автообновление каждые 30 секунд
setInterval(() => {
loadLogs();
}, 30000);
});
</script>
</body>
</html>