Files
erv-clientright/miniapp2.html
2026-03-13 10:42:01 +03:00

424 lines
14 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>Загрузка файлов</title>
<script src="https://telegram.org/js/telegram-web-app.js"></script>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
min-height: 100vh;
display: flex;
align-items: center;
justify-content: center;
padding: 20px;
}
.container {
background: white;
border-radius: 20px;
padding: 30px;
box-shadow: 0 20px 40px rgba(0,0,0,0.1);
width: 100%;
max-width: 400px;
}
.header {
text-align: center;
margin-bottom: 30px;
}
.header h1 {
color: #333;
font-size: 24px;
font-weight: 600;
margin-bottom: 10px;
}
.header p {
color: #666;
font-size: 14px;
}
.file-upload {
margin-bottom: 25px;
}
.file-upload label {
display: block;
margin-bottom: 8px;
color: #333;
font-weight: 500;
font-size: 14px;
}
.file-input-wrapper {
position: relative;
border: 2px dashed #ddd;
border-radius: 12px;
padding: 20px;
text-align: center;
transition: all 0.3s ease;
cursor: pointer;
}
.file-input-wrapper:hover {
border-color: #667eea;
background-color: #f8f9ff;
}
.file-input-wrapper.dragover {
border-color: #667eea;
background-color: #f0f2ff;
}
.file-input {
position: absolute;
opacity: 0;
width: 100%;
height: 100%;
cursor: pointer;
}
.file-input-text {
color: #666;
font-size: 14px;
}
.file-input-text strong {
color: #667eea;
}
.file-preview {
margin-top: 10px;
padding: 10px;
background: #f8f9fa;
border-radius: 8px;
display: none;
}
.file-preview.show {
display: block;
}
.file-preview .file-name {
font-weight: 500;
color: #333;
margin-bottom: 5px;
}
.file-preview .file-size {
font-size: 12px;
color: #666;
}
.submit-btn {
width: 100%;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
color: white;
border: none;
padding: 15px;
border-radius: 12px;
font-size: 16px;
font-weight: 600;
cursor: pointer;
transition: all 0.3s ease;
margin-top: 20px;
}
.submit-btn:hover {
transform: translateY(-2px);
box-shadow: 0 10px 20px rgba(102, 126, 234, 0.3);
}
.submit-btn:disabled {
background: #ccc;
cursor: not-allowed;
transform: none;
box-shadow: none;
}
.status {
margin-top: 15px;
padding: 10px;
border-radius: 8px;
text-align: center;
display: none;
}
.status.success {
background: #d4edda;
color: #155724;
border: 1px solid #c3e6cb;
}
.status.error {
background: #f8d7da;
color: #721c24;
border: 1px solid #f5c6cb;
}
.loading {
display: none;
text-align: center;
margin-top: 15px;
}
.spinner {
border: 3px solid #f3f3f3;
border-top: 3px solid #667eea;
border-radius: 50%;
width: 30px;
height: 30px;
animation: spin 1s linear infinite;
margin: 0 auto 10px;
}
@keyframes spin {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}
</style>
</head>
<body>
<div class="container">
<div class="header">
<h1>📁 Загрузка файлов</h1>
<p>Выберите два файла для отправки</p>
</div>
<form id="uploadForm">
<div class="file-upload">
<label for="file1">Первый файл</label>
<div class="file-input-wrapper" onclick="document.getElementById('file1').click()">
<input type="file" id="file1" class="file-input" accept="*/*">
<div class="file-input-text">
<strong>Нажмите</strong> или перетащите файл сюда
</div>
</div>
<div id="preview1" class="file-preview">
<div class="file-name"></div>
<div class="file-size"></div>
</div>
</div>
<div class="file-upload">
<label for="file2">Второй файл</label>
<div class="file-input-wrapper" onclick="document.getElementById('file2').click()">
<input type="file" id="file2" class="file-input" accept="*/*">
<div class="file-input-text">
<strong>Нажмите</strong> или перетащите файл сюда
</div>
</div>
<div id="preview2" class="file-preview">
<div class="file-name"></div>
<div class="file-size"></div>
</div>
</div>
<button type="submit" class="submit-btn" id="submitBtn">
📤 Отправить файлы
</button>
</form>
<div class="loading" id="loading">
<div class="spinner"></div>
<p>Отправляем файлы...</p>
</div>
<div class="status" id="status"></div>
</div>
<script>
// Инициализация Telegram Web App с проверкой доступности
let tg = window.Telegram?.WebApp;
// Проверяем, доступен ли Telegram Web App API
if (tg) {
tg.ready();
tg.expand();
}
// Универсальная функция закрытия мини-аппа
function closeMiniApp() {
if (tg && typeof tg.close === 'function') {
// Если доступен Telegram Web App API
tg.close();
} else if (window.parent && window.parent !== window) {
// Если открыто в iframe (n8n webhook)
try {
window.parent.postMessage({ type: 'close' }, '*');
} catch (e) {
console.log('Не удалось закрыть через postMessage');
}
} else {
// Альтернативный способ - попытка закрыть окно
try {
window.close();
} catch (e) {
console.log('Не удалось закрыть окно');
}
}
}
// Настройка темы
if (tg && tg.colorScheme === 'dark') {
document.body.style.background = 'linear-gradient(135deg, #2c3e50 0%, #34495e 100%)';
document.querySelector('.container').style.background = '#2c3e50';
document.querySelector('.container').style.color = 'white';
}
const file1Input = document.getElementById('file1');
const file2Input = document.getElementById('file2');
const preview1 = document.getElementById('preview1');
const preview2 = document.getElementById('preview2');
const submitBtn = document.getElementById('submitBtn');
const loading = document.getElementById('loading');
const status = document.getElementById('status');
// Функция для отображения предварительного просмотра файла
function showFilePreview(file, previewElement) {
if (file) {
const fileName = file.name;
const fileSize = (file.size / 1024).toFixed(2) + ' KB';
previewElement.querySelector('.file-name').textContent = fileName;
previewElement.querySelector('.file-size').textContent = fileSize;
previewElement.classList.add('show');
} else {
previewElement.classList.remove('show');
}
}
// Обработчики для файлов
file1Input.addEventListener('change', (e) => {
showFilePreview(e.target.files[0], preview1);
updateSubmitButton();
});
file2Input.addEventListener('change', (e) => {
showFilePreview(e.target.files[0], preview2);
updateSubmitButton();
});
// Drag and drop функциональность
function setupDragAndDrop(inputElement, previewElement) {
const wrapper = inputElement.parentElement;
wrapper.addEventListener('dragover', (e) => {
e.preventDefault();
wrapper.classList.add('dragover');
});
wrapper.addEventListener('dragleave', (e) => {
e.preventDefault();
wrapper.classList.remove('dragover');
});
wrapper.addEventListener('drop', (e) => {
e.preventDefault();
wrapper.classList.remove('dragover');
const files = e.dataTransfer.files;
if (files.length > 0) {
inputElement.files = files;
showFilePreview(files[0], previewElement);
updateSubmitButton();
}
});
}
setupDragAndDrop(file1Input, preview1);
setupDragAndDrop(file2Input, preview2);
// Обновление состояния кнопки отправки
function updateSubmitButton() {
const file1 = file1Input.files[0];
const file2 = file2Input.files[0];
if (file1 && file2) {
submitBtn.disabled = false;
submitBtn.textContent = '📤 Отправить файлы';
} else {
submitBtn.disabled = true;
submitBtn.textContent = '⚠️ Выберите оба файла';
}
}
// Обработка отправки формы
document.getElementById('uploadForm').addEventListener('submit', async (e) => {
e.preventDefault();
const file1 = file1Input.files[0];
const file2 = file2Input.files[0];
if (!file1 || !file2) {
showStatus('Пожалуйста, выберите оба файла', 'error');
return;
}
// Показываем загрузку
loading.style.display = 'block';
submitBtn.disabled = true;
status.style.display = 'none';
try {
// Создаем FormData для отправки файлов
const formData = new FormData();
formData.append('file1', file1);
formData.append('file2', file2);
formData.append('user_id', tg?.initDataUnsafe?.user?.id || 'unknown');
// Здесь должна быть логика отправки на ваш сервер
// Для демонстрации используем setTimeout
await new Promise(resolve => setTimeout(resolve, 2000));
// Симуляция успешной отправки
showStatus('✅ Файлы успешно отправлены!', 'success');
// Очищаем форму
file1Input.value = '';
file2Input.value = '';
preview1.classList.remove('show');
preview2.classList.remove('show');
updateSubmitButton();
// Закрываем мини-апп через 2 секунды после успешной отправки
setTimeout(() => {
closeMiniApp();
}, 2000);
} catch (error) {
showStatus('❌ Ошибка при отправке файлов: ' + error.message, 'error');
} finally {
loading.style.display = 'none';
submitBtn.disabled = false;
}
});
// Функция для отображения статуса
function showStatus(message, type) {
status.textContent = message;
status.className = `status ${type}`;
status.style.display = 'block';
// Скрываем статус через 5 секунд
setTimeout(() => {
status.style.display = 'none';
}, 5000);
}
// Инициализация
updateSubmitButton();
</script>
</body>
</html>