сортировка, переделана авторизация, изменен дизайн

This commit is contained in:
2026-07-28 23:48:58 +08:00
parent f97fd63d35
commit 64d0874b0c
20 changed files with 2021 additions and 838 deletions

View File

@@ -130,14 +130,21 @@
</div>
<script>
fetch('/cgi-bin/status.cgi')
.then(response => response.text())
.then(data => {
document.getElementById('status').innerHTML = data;
})
.catch(err => {
document.getElementById('status').innerHTML = 'Ошибка загрузки статуса';
});
(function() {
const statusEl = document.getElementById('status');
if (!statusEl) return;
setTimeout(function() {
fetch('/cgi-bin/status.cgi')
.then(response => response.text())
.then(data => {
statusEl.innerHTML = data.replace(/\n/g, '<br>');
})
.catch(function() {
statusEl.innerHTML = 'Ошибка загрузки статуса';
});
}, 300);
})();
</script>
</footer>
@@ -154,7 +161,55 @@
</div>
<script>
// ============================================
// СОХРАНЯЕМ ТОКЕН В localStorage
// ============================================
(function() {
const urlParams = new URLSearchParams(window.location.search);
const token = urlParams.get('token');
if (token) {
localStorage.setItem('trashbox_token', token);
if (window.history && window.history.replaceState) {
const newUrl = window.location.pathname + window.location.search.replace(/[&?]token=[^&]*/, '').replace(/^&/, '?').replace(/\?$/, '');
window.history.replaceState({}, document.title, newUrl);
}
}
})();
// ============================================
// ДОБАВЛЯЕМ ТОКЕН ВО ВСЕ ССЫЛКИ
// ============================================
document.addEventListener('DOMContentLoaded', function() {
const savedToken = localStorage.getItem('trashbox_token');
if (savedToken) {
document.querySelectorAll('a[href*="/cgi-bin/index.cgi"]').forEach(function(link) {
if (!link.href.includes('token=')) {
link.href += (link.href.includes('?') ? '&' : '?') + 'token=' + savedToken;
}
});
}
});
// ============================================
// ГЛОБАЛЬНЫЕ ФУНКЦИИ
// ============================================
function getCookie(name) {
const value = `; ${document.cookie}`;
const parts = value.split(`; ${name}=`);
if (parts.length === 2) return parts.pop().split(';').shift();
}
// ============================================
// ПОКАЗ ФОРМЫ ПАРОЛЯ (с проверкой токена)
// ============================================
window.showPasswordForm = function(encodedPath, folderName) {
const savedToken = localStorage.getItem('trashbox_token');
if (savedToken) {
window.location.href = '/cgi-bin/index.cgi?path=' + encodedPath + '&token=' + savedToken;
return;
}
const modal = document.getElementById('previewModal');
const content = document.getElementById('previewContent');
const title = document.getElementById('previewTitle');
@@ -166,13 +221,10 @@
}
frame.style.display = 'none';
title.textContent = '🔒 Введите пароль для папки: ' + folderName;
const oldContainer = document.getElementById('passwordFormContainer');
if (oldContainer) {
oldContainer.remove();
}
if (oldContainer) oldContainer.remove();
const container = document.createElement('div');
container.id = 'passwordFormContainer';
@@ -185,7 +237,7 @@
<p style="color:var(--text-secondary);margin-bottom:1.5rem;font-size:0.95rem;">
Введите пароль для доступа к <strong style="color:var(--text-primary);word-break:break-all;">${folderName}</strong>
</p>
<form method="GET" action="/cgi-bin/index.cgi" onsubmit="return validatePasswordForm(this)">
<form method="POST" action="/cgi-bin/index.cgi" onsubmit="return validatePasswordForm(this)">
<input type="hidden" name="path" value="${encodedPath}">
<input type="password" name="password" placeholder="Введите пароль" required style="width:100%;padding:0.75rem 1rem;border:2px solid var(--border-color);border-radius:8px;font-size:1rem;background:var(--bg-primary);color:var(--text-primary);transition:border-color 0.2s ease;box-sizing:border-box;">
<button type="submit" style="width:100%;padding:0.75rem;background:var(--accent-blue);color:white;border:none;border-radius:8px;font-size:1rem;font-weight:600;cursor:pointer;transition:background 0.2s ease;margin-top:0.75rem;">Войти</button>
@@ -196,7 +248,6 @@
`;
content.appendChild(container);
content.style.width = '500px';
content.style.height = 'auto';
content.style.maxWidth = '90vw';
@@ -220,25 +271,34 @@
const password = form.querySelector('input[type="password"]').value;
const errorMsg = form.parentElement.querySelector('.error-msg');
if (!password || password.length < 1) {
if (errorMsg) {
errorMsg.textContent = '❌ Пожалуйста, введите пароль';
}
if (errorMsg) errorMsg.textContent = '❌ Пожалуйста, введите пароль';
return false;
}
return true;
};
window.downloadFile = function(path) {
let cleanPath = path;
cleanPath = cleanPath.replace(/[?&]token=[^&]*/g, '');
cleanPath = cleanPath.replace(/[?&]$/, '');
let fileName = cleanPath.split('/').pop().split('?')[0];
fileName = decodeURIComponent(fileName);
const link = document.createElement('a');
link.href = path;
link.download = path.split('/').pop();
link.href = cleanPath;
link.download = fileName;
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
};
window.copyLink = function(path) {
const url = window.location.origin + path;
let cleanPath = path;
cleanPath = cleanPath.replace(/[?&]token=[^&]*/g, '');
cleanPath = cleanPath.replace(/[?&]$/, '');
if (!cleanPath || cleanPath === '') cleanPath = '/';
const url = window.location.origin + cleanPath;
if (navigator.clipboard && navigator.clipboard.writeText) {
navigator.clipboard.writeText(url).then(function() {
showNotification('✅ Ссылка скопирована!');
@@ -281,10 +341,7 @@
}
window.scrollToTop = function() {
window.scrollTo({
top: 0,
behavior: 'smooth'
});
window.scrollTo({ top: 0, behavior: 'smooth' });
};
window.addEventListener('scroll', function() {
@@ -299,13 +356,10 @@
window.toggleTheme = function() {
const isDark = document.body.classList.contains('dark-theme');
const newTheme = isDark ? 'light' : 'dark';
document.body.classList.toggle('dark-theme');
document.documentElement.classList.toggle('dark-theme');
const button = document.querySelector('.theme-toggle');
button.textContent = isDark ? '🌙' : '☀️';
const date = new Date();
date.setFullYear(date.getFullYear() + 1);
document.cookie = 'theme=' + newTheme + '; expires=' + date.toUTCString() + '; path=/';
@@ -318,12 +372,9 @@
const title = document.getElementById('previewTitle');
const oldContainer = document.getElementById('passwordFormContainer');
if (oldContainer) {
oldContainer.remove();
}
if (oldContainer) oldContainer.remove();
frame.style.display = 'block';
const fileName = fileUrl.split('/').pop();
const decodedFileName = decodeURIComponent(fileName);
title.textContent = decodedFileName;
@@ -350,25 +401,18 @@
if (imageTypes.includes(fileExt)) {
frame.style.display = 'none';
imgContainer.style.display = 'flex';
const img = document.createElement('img');
img.src = fileUrl;
img.alt = fileName;
img.className = 'preview-image';
img.onload = function() {
adjustModalForImage(this);
};
img.onload = function() { adjustModalForImage(this); };
img.onerror = function() {
console.error('Failed to load image:', fileUrl);
frame.style.display = 'block';
imgContainer.style.display = 'none';
frame.src = fileUrl;
};
imgContainer.appendChild(img);
content.style.width = '90vw';
content.style.height = '90vh';
content.style.maxWidth = 'none';
@@ -378,11 +422,9 @@
content.style.left = 'auto';
content.style.top = 'auto';
content.style.transform = 'none';
} else {
frame.style.display = 'block';
imgContainer.style.display = 'none';
if (textTypes.includes(fileExt)) {
content.style.width = '80vw';
content.style.height = '70vh';
@@ -410,13 +452,11 @@
content.style.maxWidth = '1000px';
content.style.maxHeight = '800px';
}
content.style.margin = '2% auto';
content.style.position = 'relative';
content.style.left = 'auto';
content.style.top = 'auto';
content.style.transform = 'none';
frame.src = fileUrl;
}
@@ -428,22 +468,13 @@
const content = document.getElementById('previewContent');
const maxWidth = window.innerWidth * 0.95;
const maxHeight = window.innerHeight * 0.95;
const imgWidth = img.naturalWidth;
const imgHeight = img.naturalHeight;
let scale = 1;
if (imgWidth > maxWidth) {
scale = Math.min(scale, maxWidth / imgWidth);
}
if (imgHeight > maxHeight) {
scale = Math.min(scale, maxHeight / imgHeight);
}
if (imgWidth > maxWidth) scale = Math.min(scale, maxWidth / imgWidth);
if (imgHeight > maxHeight) scale = Math.min(scale, maxHeight / imgHeight);
const displayWidth = imgWidth * scale;
const displayHeight = imgHeight * scale;
content.style.width = (displayWidth + 20) + 'px';
content.style.height = (displayHeight + 80) + 'px';
content.style.margin = 'auto';
@@ -464,9 +495,7 @@
frame.style.display = 'block';
const oldContainer = document.getElementById('passwordFormContainer');
if (oldContainer) {
oldContainer.remove();
}
if (oldContainer) oldContainer.remove();
content.style.width = '';
content.style.height = '';
@@ -491,21 +520,16 @@
};
document.getElementById('previewModal').addEventListener('click', function(e) {
if (e.target === this) {
closePreview();
}
if (e.target === this) closePreview();
});
document.addEventListener('keydown', function(e) {
if (e.key === 'Escape') {
closePreview();
}
if (e.key === 'Escape') closePreview();
});
document.addEventListener('DOMContentLoaded', function() {
const savedTheme = getCookie('theme');
const button = document.querySelector('.theme-toggle');
if (savedTheme === 'dark') {
document.body.classList.add('dark-theme');
button.textContent = '☀️';
@@ -513,11 +537,10 @@
document.body.classList.remove('dark-theme');
button.textContent = '🌙';
}
document.body.classList.add('loaded');
});
document.addEventListener('touchstart', function() {}, { passive: true });
</script>
</body>
</html>
</html>