Files
yarmarka/templates/mobile_debug.html
2026-03-16 18:57:22 +03:00

556 lines
20 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, maximum-scale=1.0, user-scalable=no">
<title>Mobile Debug - Rabota.Today</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif;
}
body {
background: #0b1c34;
padding: 20px;
color: #333;
}
.container {
max-width: 500px;
margin: 0 auto;
}
.card {
background: white;
border-radius: 24px;
padding: 25px;
margin-bottom: 20px;
box-shadow: 0 10px 30px rgba(0,0,0,0.2);
}
h1 {
font-size: 24px;
margin-bottom: 20px;
color: #0b1c34;
}
h2 {
font-size: 18px;
margin-bottom: 15px;
color: #1f3f60;
}
.info-row {
background: #f5f9ff;
padding: 12px;
border-radius: 12px;
margin-bottom: 10px;
font-size: 14px;
word-break: break-all;
}
.info-label {
font-weight: 600;
color: #1f3f60;
margin-bottom: 4px;
}
.info-value {
color: #333;
font-family: monospace;
}
.success {
color: #10b981;
font-weight: 600;
}
.error {
color: #ef4444;
font-weight: 600;
}
.warning {
color: #f59e0b;
font-weight: 600;
}
button {
background: #0b1c34;
color: white;
border: none;
padding: 14px 20px;
border-radius: 40px;
font-weight: 600;
font-size: 16px;
width: 100%;
margin: 10px 0;
cursor: pointer;
transition: 0.2s;
}
button:active {
transform: scale(0.98);
background: #1b3f6b;
}
button.secondary {
background: #e5e7eb;
color: #1f3f60;
}
.test-result {
margin-top: 15px;
padding: 15px;
background: #f5f5f5;
border-radius: 16px;
font-size: 14px;
max-height: 300px;
overflow-y: auto;
display: none;
}
.test-result pre {
white-space: pre-wrap;
word-wrap: break-word;
font-family: monospace;
font-size: 12px;
}
.loader {
display: inline-block;
width: 20px;
height: 20px;
border: 3px solid #f3f3f3;
border-top: 3px solid #0b1c34;
border-radius: 50%;
animation: spin 1s linear infinite;
margin-right: 10px;
}
@keyframes spin {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}
.flex {
display: flex;
align-items: center;
justify-content: center;
gap: 10px;
}
.ip-input {
width: 100%;
padding: 12px;
border: 2px solid #dee9f5;
border-radius: 30px;
font-size: 16px;
margin-bottom: 10px;
}
</style>
</head>
<body>
<div class="container">
<!-- Информация об устройстве -->
<div class="card">
<h1>📱 Mobile Debug Tool</h1>
<div class="info-row">
<div class="info-label">User Agent:</div>
<div class="info-value" id="userAgent"></div>
</div>
<div class="info-row">
<div class="info-label">Платформа:</div>
<div class="info-value" id="platform"></div>
</div>
<div class="info-row">
<div class="info-label">Язык:</div>
<div class="info-value" id="language"></div>
</div>
<div class="info-row">
<div class="info-label">Размер экрана:</div>
<div class="info-value" id="screenSize"></div>
</div>
<div class="info-row">
<div class="info-label">Онлайн:</div>
<div class="info-value" id="online"></div>
</div>
</div>
<!-- Настройки подключения -->
<div class="card">
<h2>🔧 Настройки подключения</h2>
<input type="text" class="ip-input" id="serverIp" placeholder="IP сервера (например, 192.168.1.100)">
<div class="info-row">
<div class="info-label">Текущий URL:</div>
<div class="info-value" id="currentUrl"></div>
</div>
<div class="flex">
<button onclick="testConnection()" id="testBtn">🔍 Проверить соединение</button>
<button class="secondary" onclick="copyInfo()">📋 Копировать</button>
</div>
<div id="connectionResult" class="test-result"></div>
</div>
<!-- Тесты API -->
<div class="card">
<h2>🧪 Тесты API</h2>
<button onclick="testHealth()">🏥 Проверить Health</button>
<div id="healthResult" class="test-result"></div>
<button onclick="testRegister()">📝 Тест регистрации</button>
<div id="registerResult" class="test-result"></div>
<button onclick="testLogin()">🔑 Тест входа</button>
<div id="loginResult" class="test-result"></div>
<button onclick="testCORS()">🌐 Проверить CORS</button>
<div id="corsResult" class="test-result"></div>
</div>
<!-- Логи ошибок -->
<div class="card">
<h2>⚠️ Логи ошибок</h2>
<div id="errorLogs" class="info-row" style="min-height: 100px; max-height: 200px; overflow-y: auto;">
Ошибок нет
</div>
<button class="secondary" onclick="clearLogs()">Очистить логи</button>
</div>
</div>
<script>
// Конфигурация
let serverIp = localStorage.getItem('serverIp') || window.location.hostname;
document.getElementById('serverIp').value = serverIp;
// Логирование ошибок
let errorLogs = [];
function logError(message, data = null) {
const timestamp = new Date().toLocaleTimeString();
const logEntry = `[${timestamp}] ${message} ${data ? JSON.stringify(data) : ''}`;
errorLogs.push(logEntry);
const logsDiv = document.getElementById('errorLogs');
logsDiv.innerHTML = errorLogs.map(log => `<div>${log}</div>`).join('');
console.error(logEntry);
}
function clearLogs() {
errorLogs = [];
document.getElementById('errorLogs').innerHTML = 'Ошибок нет';
}
// Информация об устройстве
function updateDeviceInfo() {
document.getElementById('userAgent').textContent = navigator.userAgent;
document.getElementById('platform').textContent = navigator.platform;
document.getElementById('language').textContent = navigator.language;
document.getElementById('screenSize').textContent = `${window.screen.width}x${window.screen.height}`;
document.getElementById('online').textContent = navigator.onLine ? '✅ Да' : '❌ Нет';
document.getElementById('currentUrl').textContent = window.location.href;
}
updateDeviceInfo();
// Сохранение IP
document.getElementById('serverIp').addEventListener('change', function(e) {
serverIp = e.target.value;
localStorage.setItem('serverIp', serverIp);
});
// Копирование информации
function copyInfo() {
const info = {
userAgent: navigator.userAgent,
platform: navigator.platform,
language: navigator.language,
screenSize: `${window.screen.width}x${window.screen.height}`,
online: navigator.onLine,
url: window.location.href,
serverIp: serverIp
};
navigator.clipboard.writeText(JSON.stringify(info, null, 2))
.then(() => alert('Информация скопирована!'))
.catch(() => alert('Ошибка копирования'));
}
// Проверка соединения
async function testConnection() {
const btn = document.getElementById('testBtn');
const resultDiv = document.getElementById('connectionResult');
btn.disabled = true;
btn.innerHTML = '<div class="loader"></div> Проверка...';
resultDiv.style.display = 'block';
resultDiv.innerHTML = '<div class="flex"><div class="loader"></div> Проверка соединения...</div>';
try {
// Пробуем разные варианты подключения
const urls = [
`http://${serverIp}:8000/api/health`,
`http://${serverIp}:8000/health`,
`http://${window.location.hostname}:8000/api/health`,
`http://127.0.0.1:8000/api/health`,
`http://localhost:8000/api/health`
];
let success = false;
let results = [];
for (const url of urls) {
try {
const start = Date.now();
const response = await fetch(url, {
mode: 'no-cors',
headers: { 'Accept': 'application/json' }
});
const time = Date.now() - start;
results.push({
url,
status: response.status,
time: `${time}ms`,
ok: response.ok
});
if (response.ok) {
success = true;
}
} catch (e) {
results.push({
url,
error: e.message,
time: 'failed'
});
}
}
let html = '<h3>Результаты проверки:</h3>';
results.forEach(r => {
html += `<div style="margin: 10px 0; padding: 8px; background: ${r.ok ? '#d1fae5' : '#fee2e2'}; border-radius: 8px;">`;
html += `<div><strong>URL:</strong> ${r.url}</div>`;
if (r.status) html += `<div><strong>Статус:</strong> ${r.status}</div>`;
if (r.time) html += `<div><strong>Время:</strong> ${r.time}</div>`;
if (r.error) html += `<div><strong>Ошибка:</strong> ${r.error}</div>`;
if (r.ok) html += `<div class="success">✅ Доступно</div>`;
else html += `<div class="error">❌ Недоступно</div>`;
html += '</div>';
});
html += `<div style="margin-top: 15px; font-weight: 600;">
Общий статус: ${success ? '✅ Сервер доступен' : '❌ Сервер недоступен'}
</div>`;
resultDiv.innerHTML = html;
} catch (error) {
logError('Connection test error', error);
resultDiv.innerHTML = `<div class="error">❌ Ошибка: ${error.message}</div>`;
}
btn.disabled = false;
btn.innerHTML = '🔍 Проверить соединение';
}
// Тест Health
async function testHealth() {
const resultDiv = document.getElementById('healthResult');
resultDiv.style.display = 'block';
resultDiv.innerHTML = '<div class="flex"><div class="loader"></div> Проверка...</div>';
try {
const url = `http://${serverIp}:8000/api/health`;
const response = await fetch(url, {
headers: { 'Accept': 'application/json' }
});
const data = await response.json();
resultDiv.innerHTML = `
<div class="success">✅ Успешно!</div>
<pre>${JSON.stringify(data, null, 2)}</pre>
`;
} catch (error) {
logError('Health test error', error);
resultDiv.innerHTML = `
<div class="error">❌ Ошибка: ${error.message}</div>
<div style="margin-top: 10px;">
<strong>Проверьте:</strong>
<ul>
<li>Правильный ли IP сервера? (${serverIp})</li>
<li>Сервер запущен? (python main.py)</li>
<li>Оба устройства в одной WiFi сети?</li>
<li>Firewall не блокирует порт 8000?</li>
</ul>
</div>
`;
}
}
// Тест CORS
async function testCORS() {
const resultDiv = document.getElementById('corsResult');
resultDiv.style.display = 'block';
resultDiv.innerHTML = '<div class="flex"><div class="loader"></div> Проверка CORS...</div>';
try {
const url = `http://${serverIp}:8000/api/health`;
// Пробуем разные режимы
const tests = [
{ mode: 'cors', credentials: 'omit' },
{ mode: 'cors', credentials: 'include' },
{ mode: 'no-cors' }
];
let results = [];
for (const test of tests) {
try {
const response = await fetch(url, {
mode: test.mode,
credentials: test.credentials,
headers: {
'Content-Type': 'application/json',
'Accept': 'application/json'
}
});
results.push({
test: JSON.stringify(test),
status: response.status,
ok: response.ok
});
} catch (e) {
results.push({
test: JSON.stringify(test),
error: e.message
});
}
}
let html = '<h3>Результаты CORS тестов:</h3>';
results.forEach(r => {
html += `<div style="margin: 10px 0; padding: 8px; background: ${r.ok ? '#d1fae5' : '#fee2e2'}; border-radius: 8px;">`;
html += `<div><strong>Тест:</strong> ${r.test}</div>`;
if (r.status) html += `<div><strong>Статус:</strong> ${r.status}</div>`;
if (r.error) html += `<div><strong>Ошибка:</strong> ${r.error}</div>`;
html += '</div>';
});
resultDiv.innerHTML = html;
} catch (error) {
logError('CORS test error', error);
resultDiv.innerHTML = `<div class="error">❌ Ошибка: ${error.message}</div>`;
}
}
// Тест регистрации
async function testRegister() {
const resultDiv = document.getElementById('registerResult');
resultDiv.style.display = 'block';
resultDiv.innerHTML = '<div class="flex"><div class="loader"></div> Тест регистрации...</div>';
const testData = {
full_name: "Тест Тестов",
email: `test${Date.now()}@example.com`,
phone: "+7 (999) 123-45-67",
telegram: "@test",
password: "password123",
role: "employee"
};
try {
const url = `http://${serverIp}:8000/api/register`;
const response = await fetch(url, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Accept': 'application/json'
},
body: JSON.stringify(testData)
});
const data = await response.json();
resultDiv.innerHTML = `
<div class="${response.ok ? 'success' : 'error'}">
${response.ok ? '✅ Успешно!' : '❌ Ошибка'}
</div>
<div><strong>Статус:</strong> ${response.status}</div>
<pre>${JSON.stringify(data, null, 2)}</pre>
`;
} catch (error) {
logError('Register test error', error);
resultDiv.innerHTML = `
<div class="error">❌ Ошибка: ${error.message}</div>
<div style="margin-top: 10px;">
<strong>Тип ошибки:</strong> ${error.name}<br>
<strong>Стектрейс:</strong> ${error.stack}
</div>
`;
}
}
// Тест входа
async function testLogin() {
const resultDiv = document.getElementById('loginResult');
resultDiv.style.display = 'block';
resultDiv.innerHTML = '<div class="flex"><div class="loader"></div> Тест входа...</div>';
try {
const url = `http://${serverIp}:8000/api/login`;
const response = await fetch(url, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Accept': 'application/json'
},
body: JSON.stringify({
email: "admin@rabota.today",
password: "admin123"
})
});
const data = await response.json();
resultDiv.innerHTML = `
<div class="${response.ok ? 'success' : 'error'}">
${response.ok ? '✅ Успешно!' : '❌ Ошибка'}
</div>
<div><strong>Статус:</strong> ${response.status}</div>
<pre>${JSON.stringify(data, null, 2)}</pre>
`;
} catch (error) {
logError('Login test error', error);
resultDiv.innerHTML = `<div class="error">❌ Ошибка: ${error.message}</div>`;
}
}
// Автоматический тест при загрузке
setTimeout(() => {
testConnection();
}, 1000);
</script>
</body>
</html>