r
This commit is contained in:
@@ -40,7 +40,6 @@
|
||||
<nav>
|
||||
<button onclick="showSection('tasks')">Задачи</button>
|
||||
<button onclick="showSection('create-task')">Создать задачу</button>
|
||||
<button onclick="showSection('tasks')">Мои задачи</button>
|
||||
<button onclick="showTasksWithoutDate()" id="tasks-no-date-btn">Задачи без срока</button>
|
||||
<button onclick="showSection('logs')">Лог активности</button>
|
||||
<button onclick="window.location.href = '/admin'" style="background: linear-gradient(135deg, #e74c3c, #c0392b);">Админ-панель</button>
|
||||
|
||||
368
public/script.js
368
public/script.js
@@ -214,11 +214,24 @@ async function loadTasks() {
|
||||
|
||||
const response = await fetch(url);
|
||||
tasks = await response.json();
|
||||
|
||||
// Загружаем файлы для всех задач
|
||||
await Promise.all(tasks.map(async (task) => {
|
||||
try {
|
||||
const filesResponse = await fetch(`/api/tasks/${task.id}/files`);
|
||||
if (filesResponse.ok) {
|
||||
task.files = await filesResponse.json();
|
||||
} else {
|
||||
task.files = [];
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(`Ошибка загрузки файлов для задачи ${task.id}:`, error);
|
||||
task.files = [];
|
||||
}
|
||||
}));
|
||||
|
||||
renderTasks();
|
||||
|
||||
tasks.forEach(task => {
|
||||
loadTaskFiles(task.id);
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('Ошибка загрузки задач:', error);
|
||||
}
|
||||
@@ -244,6 +257,21 @@ async function loadTasksWithoutDate() {
|
||||
return hasTaskDueDate && hasAssignmentDueDates;
|
||||
});
|
||||
|
||||
// Загружаем файлы для всех задач
|
||||
await Promise.all(tasks.map(async (task) => {
|
||||
try {
|
||||
const filesResponse = await fetch(`/api/tasks/${task.id}/files`);
|
||||
if (filesResponse.ok) {
|
||||
task.files = await filesResponse.json();
|
||||
} else {
|
||||
task.files = [];
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(`Ошибка загрузки файлов для задачи ${task.id}:`, error);
|
||||
task.files = [];
|
||||
}
|
||||
}));
|
||||
|
||||
renderTasks();
|
||||
} catch (error) {
|
||||
console.error('Ошибка загрузки задач без срока:', error);
|
||||
@@ -389,7 +417,11 @@ function renderTasks() {
|
||||
${showingTasksWithoutDate ? '<span class="no-date-badge">Без срока</span>' : ''}
|
||||
</div>
|
||||
<div class="file-list" id="files-${task.id}">
|
||||
<strong>Файлы:</strong> <span class="files-placeholder">скрыто</span>
|
||||
<strong>Файлы:</strong>
|
||||
${task.files && task.files.length > 0 ?
|
||||
`<div class="file-icons-container">${task.files.map(file => renderFileIcon(file)).join('')}</div>` :
|
||||
'<span class="no-files">нет файлов</span>'
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -417,6 +449,7 @@ function toggleTask(taskId) {
|
||||
expandedTasks.delete(taskId);
|
||||
} else {
|
||||
expandedTasks.add(taskId);
|
||||
loadTaskFiles(taskId); // Эта строка должна быть
|
||||
}
|
||||
renderTasks();
|
||||
}
|
||||
@@ -1122,19 +1155,328 @@ async function loadTaskFiles(taskId) {
|
||||
} else {
|
||||
container.innerHTML = `
|
||||
<strong>Файлы:</strong>
|
||||
${files.map(file => `
|
||||
<div class="file-item">
|
||||
<a href="/api/files/${file.id}/download" download="${file.original_name}">
|
||||
${file.original_name}
|
||||
</a>
|
||||
(${(file.file_size / 1024 / 1024).toFixed(2)} MB)
|
||||
<small> - загрузил: ${file.user_name}</small>
|
||||
</div>
|
||||
`).join('')}
|
||||
<div class="file-icons-container">
|
||||
${files.map(file => renderFileIcon(file)).join('')}
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Ошибка загрузки файлов:', error);
|
||||
}
|
||||
}
|
||||
|
||||
function renderFileIcon(file) {
|
||||
// Исправляем кодировку имени файла
|
||||
const fixEncoding = (str) => {
|
||||
if (!str) return '';
|
||||
try {
|
||||
// Пробуем разные способы декодирования
|
||||
if (str.includes('Ð') || str.includes('Ñ')) {
|
||||
// UTF-8 неправильно декодированный как Latin-1
|
||||
return decodeURIComponent(escape(str));
|
||||
}
|
||||
return str;
|
||||
} catch (e) {
|
||||
return str;
|
||||
}
|
||||
};
|
||||
|
||||
const fileName = fixEncoding(file.original_name);
|
||||
const fileSize = (file.file_size / 1024 / 1024).toFixed(2);
|
||||
const uploadedBy = file.user_name;
|
||||
|
||||
let iconColor = '';
|
||||
let iconText = '';
|
||||
let textClass = '';
|
||||
|
||||
// Определяем расширение файла
|
||||
const extension = fileName.includes('.') ?
|
||||
fileName.split('.').pop().toLowerCase() :
|
||||
'';
|
||||
|
||||
// Определяем тип файла на основе расширения
|
||||
if (extension) {
|
||||
switch (extension) {
|
||||
case 'pdf':
|
||||
iconColor = '#e74c3c';
|
||||
iconText = 'PDF';
|
||||
textClass = 'short';
|
||||
break;
|
||||
case 'doc':
|
||||
iconColor = '#3498db';
|
||||
iconText = 'DOC';
|
||||
textClass = 'short';
|
||||
break;
|
||||
case 'docx':
|
||||
iconColor = '#3498db';
|
||||
iconText = 'DOCX';
|
||||
textClass = 'medium';
|
||||
break;
|
||||
case 'xls':
|
||||
iconColor = '#2ecc71';
|
||||
iconText = 'XLS';
|
||||
textClass = 'short';
|
||||
break;
|
||||
case 'xlsx':
|
||||
iconColor = '#2ecc71';
|
||||
iconText = 'XLSX';
|
||||
textClass = 'medium';
|
||||
break;
|
||||
case 'csv':
|
||||
iconColor = '#2ecc71';
|
||||
iconText = 'CSV';
|
||||
textClass = 'short';
|
||||
break;
|
||||
case 'ppt':
|
||||
iconColor = '#e67e22';
|
||||
iconText = 'PPT';
|
||||
textClass = 'short';
|
||||
break;
|
||||
case 'pptx':
|
||||
iconColor = '#e67e22';
|
||||
iconText = 'PPTX';
|
||||
textClass = 'medium';
|
||||
break;
|
||||
case 'zip':
|
||||
iconColor = '#f39c12';
|
||||
iconText = 'ZIP';
|
||||
textClass = 'short';
|
||||
break;
|
||||
case 'rar':
|
||||
iconColor = '#f39c12';
|
||||
iconText = 'RAR';
|
||||
textClass = 'short';
|
||||
break;
|
||||
case '7z':
|
||||
iconColor = '#f39c12';
|
||||
iconText = '7Z';
|
||||
textClass = 'short';
|
||||
break;
|
||||
case 'tar':
|
||||
iconColor = '#f39c12';
|
||||
iconText = 'TAR';
|
||||
textClass = 'short';
|
||||
break;
|
||||
case 'gz':
|
||||
iconColor = '#f39c12';
|
||||
iconText = 'GZ';
|
||||
textClass = 'short';
|
||||
break;
|
||||
case 'txt':
|
||||
iconColor = '#95a5a6';
|
||||
iconText = 'TXT';
|
||||
textClass = 'short';
|
||||
break;
|
||||
case 'log':
|
||||
iconColor = '#95a5a6';
|
||||
iconText = 'LOG';
|
||||
textClass = 'short';
|
||||
break;
|
||||
case 'md':
|
||||
iconColor = '#95a5a6';
|
||||
iconText = 'MD';
|
||||
textClass = 'short';
|
||||
break;
|
||||
case 'jpg':
|
||||
iconColor = '#9b59b6';
|
||||
iconText = 'JPG';
|
||||
textClass = 'short';
|
||||
break;
|
||||
case 'jpeg':
|
||||
iconColor = '#9b59b6';
|
||||
iconText = 'JPEG';
|
||||
textClass = 'medium';
|
||||
break;
|
||||
case 'png':
|
||||
iconColor = '#9b59b6';
|
||||
iconText = 'PNG';
|
||||
textClass = 'short';
|
||||
break;
|
||||
case 'gif':
|
||||
iconColor = '#9b59b6';
|
||||
iconText = 'GIF';
|
||||
textClass = 'short';
|
||||
break;
|
||||
case 'bmp':
|
||||
iconColor = '#9b59b6';
|
||||
iconText = 'BMP';
|
||||
textClass = 'short';
|
||||
break;
|
||||
case 'svg':
|
||||
iconColor = '#9b59b6';
|
||||
iconText = 'SVG';
|
||||
textClass = 'short';
|
||||
break;
|
||||
case 'webp':
|
||||
iconColor = '#9b59b6';
|
||||
iconText = 'WEBP';
|
||||
textClass = 'medium';
|
||||
break;
|
||||
case 'mp3':
|
||||
iconColor = '#1abc9c';
|
||||
iconText = 'MP3';
|
||||
textClass = 'short';
|
||||
break;
|
||||
case 'wav':
|
||||
iconColor = '#1abc9c';
|
||||
iconText = 'WAV';
|
||||
textClass = 'short';
|
||||
break;
|
||||
case 'ogg':
|
||||
iconColor = '#1abc9c';
|
||||
iconText = 'OGG';
|
||||
textClass = 'short';
|
||||
break;
|
||||
case 'flac':
|
||||
iconColor = '#1abc9c';
|
||||
iconText = 'FLAC';
|
||||
textClass = 'medium';
|
||||
break;
|
||||
case 'mp4':
|
||||
iconColor = '#d35400';
|
||||
iconText = 'MP4';
|
||||
textClass = 'short';
|
||||
break;
|
||||
case 'avi':
|
||||
iconColor = '#d35400';
|
||||
iconText = 'AVI';
|
||||
textClass = 'short';
|
||||
break;
|
||||
case 'mkv':
|
||||
iconColor = '#d35400';
|
||||
iconText = 'MKV';
|
||||
textClass = 'short';
|
||||
break;
|
||||
case 'mov':
|
||||
iconColor = '#d35400';
|
||||
iconText = 'MOV';
|
||||
textClass = 'short';
|
||||
break;
|
||||
case 'wmv':
|
||||
iconColor = '#d35400';
|
||||
iconText = 'WMV';
|
||||
textClass = 'short';
|
||||
break;
|
||||
case 'exe':
|
||||
iconColor = '#c0392b';
|
||||
iconText = 'EXE';
|
||||
textClass = 'short';
|
||||
break;
|
||||
case 'msi':
|
||||
iconColor = '#c0392b';
|
||||
iconText = 'MSI';
|
||||
textClass = 'short';
|
||||
break;
|
||||
case 'js':
|
||||
iconColor = '#2980b9';
|
||||
iconText = 'JS';
|
||||
textClass = 'short';
|
||||
break;
|
||||
case 'html':
|
||||
iconColor = '#2980b9';
|
||||
iconText = 'HTML';
|
||||
textClass = 'medium';
|
||||
break;
|
||||
case 'css':
|
||||
iconColor = '#2980b9';
|
||||
iconText = 'CSS';
|
||||
textClass = 'short';
|
||||
break;
|
||||
case 'php':
|
||||
iconColor = '#2980b9';
|
||||
iconText = 'PHP';
|
||||
textClass = 'short';
|
||||
break;
|
||||
case 'py':
|
||||
iconColor = '#2980b9';
|
||||
iconText = 'PY';
|
||||
textClass = 'short';
|
||||
break;
|
||||
case 'java':
|
||||
iconColor = '#2980b9';
|
||||
iconText = 'JAVA';
|
||||
textClass = 'medium';
|
||||
break;
|
||||
case 'json':
|
||||
iconColor = '#8e44ad';
|
||||
iconText = 'JSON';
|
||||
textClass = 'medium';
|
||||
break;
|
||||
case 'xml':
|
||||
iconColor = '#8e44ad';
|
||||
iconText = 'XML';
|
||||
textClass = 'short';
|
||||
break;
|
||||
case 'yml':
|
||||
iconColor = '#8e44ad';
|
||||
iconText = 'YML';
|
||||
textClass = 'short';
|
||||
break;
|
||||
case 'yaml':
|
||||
iconColor = '#8e44ad';
|
||||
iconText = 'YAML';
|
||||
textClass = 'medium';
|
||||
break;
|
||||
case 'sql':
|
||||
iconColor = '#27ae60';
|
||||
iconText = 'SQL';
|
||||
textClass = 'short';
|
||||
break;
|
||||
case 'db':
|
||||
iconColor = '#27ae60';
|
||||
iconText = 'DB';
|
||||
textClass = 'short';
|
||||
break;
|
||||
case 'sqlite':
|
||||
iconColor = '#27ae60';
|
||||
iconText = 'SQLITE';
|
||||
textClass = 'long';
|
||||
break;
|
||||
default:
|
||||
// Для других расширений используем расширение или первые 4 символа
|
||||
iconColor = '#7f8c8d';
|
||||
iconText = extension.length > 4 ?
|
||||
extension.substring(0, 4).toUpperCase() :
|
||||
extension.toUpperCase();
|
||||
|
||||
// Определяем класс по длине текста
|
||||
if (iconText.length <= 2) {
|
||||
textClass = 'short';
|
||||
} else if (iconText.length <= 4) {
|
||||
textClass = 'medium';
|
||||
} else {
|
||||
textClass = 'long';
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Если нет расширения
|
||||
iconColor = '#7f8c8d';
|
||||
iconText = 'ФАЙЛ';
|
||||
textClass = 'short';
|
||||
}
|
||||
|
||||
// Исправляем кодировку для отображения
|
||||
const safeFileName = fileName;
|
||||
const displayFileName = truncateFileName(safeFileName);
|
||||
|
||||
return `
|
||||
<a href="/api/files/${file.id}/download"
|
||||
download="${encodeURIComponent(safeFileName)}"
|
||||
class="file-icon-container"
|
||||
title="${safeFileName} (${fileSize} MB) - Загрузил: ${uploadedBy}">
|
||||
<div class="file-icon" style="background: ${iconColor}">
|
||||
<span class="file-extension ${textClass}">${iconText}</span>
|
||||
</div>
|
||||
<div class="file-name">${displayFileName}</div>
|
||||
</a>
|
||||
`;
|
||||
}
|
||||
|
||||
function truncateFileName(fileName, maxLength = 20) {
|
||||
if (fileName.length <= maxLength) return fileName;
|
||||
const extension = fileName.split('.').pop();
|
||||
const name = fileName.substring(0, fileName.lastIndexOf('.'));
|
||||
const truncatedName = name.substring(0, maxLength - extension.length - 3) + '...';
|
||||
return truncatedName + '.' + extension;
|
||||
}
|
||||
392
public/style.css
392
public/style.css
@@ -425,6 +425,11 @@ button.edit-date-btn:hover {
|
||||
color: #856404;
|
||||
}
|
||||
|
||||
.task-dates-files .file-list strong {
|
||||
display: block;
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
.task-dates-files .files-placeholder {
|
||||
color: #6c757d;
|
||||
font-style: italic;
|
||||
@@ -1342,4 +1347,391 @@ button.reopen-btn:hover {
|
||||
.task-dates-files .file-list {
|
||||
min-width: 100%;
|
||||
}
|
||||
}
|
||||
/* Стили для иконок файлов */
|
||||
.file-icons-container {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 15px;
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
.file-icon-container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
width: 80px;
|
||||
cursor: pointer;
|
||||
transition: transform 0.2s ease;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.file-icon-container:hover {
|
||||
transform: translateY(-5px);
|
||||
}
|
||||
|
||||
.file-icon {
|
||||
width: 60px;
|
||||
height: 60px;
|
||||
border-radius: 10px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2);
|
||||
transition: all 0.3s ease;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.file-icon:hover {
|
||||
transform: scale(1.05);
|
||||
box-shadow: 0 6px 12px rgba(0, 0, 0, 0.3);
|
||||
}
|
||||
|
||||
.file-icon::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
height: 20px;
|
||||
background: rgba(255, 255, 255, 0.2);
|
||||
}
|
||||
|
||||
.file-extension {
|
||||
color: white;
|
||||
font-size: 0.8rem;
|
||||
font-weight: bold;
|
||||
text-shadow: 1px 1px 2px rgba(0, 0, 0, 0.3);
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.file-name {
|
||||
margin-top: 5px;
|
||||
font-size: 0.75rem;
|
||||
color: #495057;
|
||||
text-align: center;
|
||||
max-width: 100%;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
transition: color 0.2s ease;
|
||||
}
|
||||
|
||||
.file-download-link {
|
||||
text-decoration: none;
|
||||
color: inherit;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.file-download-link:hover .file-name {
|
||||
color: #3498db;
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
/* Тултип при наведении */
|
||||
.file-icon-container::before {
|
||||
content: attr(title);
|
||||
position: absolute;
|
||||
bottom: 100%;
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
background: rgba(0, 0, 0, 0.8);
|
||||
color: white;
|
||||
padding: 5px 10px;
|
||||
border-radius: 4px;
|
||||
font-size: 0.8rem;
|
||||
white-space: nowrap;
|
||||
opacity: 0;
|
||||
visibility: hidden;
|
||||
transition: opacity 0.3s ease, visibility 0.3s ease;
|
||||
z-index: 100;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.file-icon-container:hover::before {
|
||||
opacity: 1;
|
||||
visibility: visible;
|
||||
}
|
||||
|
||||
/* Адаптивность */
|
||||
@media (max-width: 768px) {
|
||||
.file-icons-container {
|
||||
gap: 10px;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.file-icon-container {
|
||||
width: 70px;
|
||||
}
|
||||
|
||||
.file-icon {
|
||||
width: 50px;
|
||||
height: 50px;
|
||||
}
|
||||
|
||||
.file-extension {
|
||||
font-size: 0.7rem;
|
||||
}
|
||||
|
||||
.file-name {
|
||||
font-size: 0.7rem;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 480px) {
|
||||
.file-icons-container {
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.file-icon-container {
|
||||
width: 60px;
|
||||
}
|
||||
|
||||
.file-icon {
|
||||
width: 45px;
|
||||
height: 45px;
|
||||
}
|
||||
|
||||
.file-extension {
|
||||
font-size: 0.65rem;
|
||||
}
|
||||
|
||||
.file-name {
|
||||
font-size: 0.65rem;
|
||||
}
|
||||
}
|
||||
.no-files {
|
||||
color: #6c757d;
|
||||
font-style: italic;
|
||||
font-size: 0.9rem;
|
||||
}
|
||||
|
||||
/* Сделаем файлы видимыми всегда */
|
||||
.task-dates-files .file-list {
|
||||
flex: 1;
|
||||
min-width: 250px;
|
||||
font-size: 0.95rem;
|
||||
color: #856404;
|
||||
}
|
||||
|
||||
.task-dates-files .file-list strong {
|
||||
display: block;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
/* Уменьшим отступы для компактности */
|
||||
.task-dates-files {
|
||||
margin: 10px 0;
|
||||
padding: 12px;
|
||||
background: linear-gradient(135deg, #fff3cd, #ffeaa7);
|
||||
border-radius: 10px;
|
||||
border-left: 4px solid #f39c12;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: flex-start;
|
||||
flex-wrap: wrap;
|
||||
gap: 15px;
|
||||
}
|
||||
/* Стили для иконок файлов */
|
||||
.file-icons-container {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 15px;
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
.file-icon-container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
width: 80px;
|
||||
cursor: pointer;
|
||||
transition: transform 0.2s ease;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.file-icon-container:hover {
|
||||
transform: translateY(-5px);
|
||||
}
|
||||
|
||||
.file-icon {
|
||||
width: 60px;
|
||||
height: 60px;
|
||||
border-radius: 10px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2);
|
||||
transition: all 0.3s ease;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.file-icon:hover {
|
||||
transform: scale(1.05);
|
||||
box-shadow: 0 6px 12px rgba(0, 0, 0, 0.3);
|
||||
}
|
||||
|
||||
.file-icon::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
height: 20px;
|
||||
background: rgba(255, 255, 255, 0.2);
|
||||
}
|
||||
|
||||
.file-extension {
|
||||
color: white;
|
||||
font-size: 0.8rem;
|
||||
font-weight: bold;
|
||||
text-shadow: 1px 1px 2px rgba(0, 0, 0, 0.3);
|
||||
z-index: 1;
|
||||
padding: 0 5px;
|
||||
text-align: center;
|
||||
line-height: 1.2;
|
||||
max-width: 100%;
|
||||
word-break: break-all;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
display: -webkit-box;
|
||||
-webkit-line-clamp: 2;
|
||||
-webkit-box-orient: vertical;
|
||||
}
|
||||
|
||||
/* Для коротких текстов (1-2 символа) */
|
||||
.file-extension.short {
|
||||
font-size: 1rem;
|
||||
}
|
||||
|
||||
/* Для средних текстов (3-4 символа) */
|
||||
.file-extension.medium {
|
||||
font-size: 0.9rem;
|
||||
}
|
||||
|
||||
/* Для длинных текстов (5+ символов) */
|
||||
.file-extension.long {
|
||||
font-size: 0.7rem;
|
||||
}
|
||||
|
||||
.file-name {
|
||||
margin-top: 5px;
|
||||
font-size: 0.75rem;
|
||||
color: #495057;
|
||||
text-align: center;
|
||||
max-width: 100%;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
transition: color 0.2s ease;
|
||||
}
|
||||
|
||||
.file-download-link {
|
||||
text-decoration: none;
|
||||
color: inherit;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.file-download-link:hover .file-name {
|
||||
color: #3498db;
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
/* Тултип при наведении */
|
||||
.file-icon-container::before {
|
||||
content: attr(title);
|
||||
position: absolute;
|
||||
bottom: 100%;
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
background: rgba(0, 0, 0, 0.8);
|
||||
color: white;
|
||||
padding: 5px 10px;
|
||||
border-radius: 4px;
|
||||
font-size: 0.8rem;
|
||||
white-space: nowrap;
|
||||
opacity: 0;
|
||||
visibility: hidden;
|
||||
transition: opacity 0.3s ease, visibility 0.3s ease;
|
||||
z-index: 100;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.file-icon-container:hover::before {
|
||||
opacity: 1;
|
||||
visibility: visible;
|
||||
}
|
||||
|
||||
/* Адаптивность */
|
||||
@media (max-width: 768px) {
|
||||
.file-icons-container {
|
||||
gap: 10px;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.file-icon-container {
|
||||
width: 70px;
|
||||
}
|
||||
|
||||
.file-icon {
|
||||
width: 50px;
|
||||
height: 50px;
|
||||
}
|
||||
|
||||
.file-extension {
|
||||
font-size: 0.7rem;
|
||||
}
|
||||
|
||||
.file-extension.short {
|
||||
font-size: 0.9rem;
|
||||
}
|
||||
|
||||
.file-extension.medium {
|
||||
font-size: 0.8rem;
|
||||
}
|
||||
|
||||
.file-extension.long {
|
||||
font-size: 0.6rem;
|
||||
}
|
||||
|
||||
.file-name {
|
||||
font-size: 0.7rem;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 480px) {
|
||||
.file-icons-container {
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.file-icon-container {
|
||||
width: 60px;
|
||||
}
|
||||
|
||||
.file-icon {
|
||||
width: 45px;
|
||||
height: 45px;
|
||||
}
|
||||
|
||||
.file-extension {
|
||||
font-size: 0.65rem;
|
||||
}
|
||||
|
||||
.file-extension.short {
|
||||
font-size: 0.8rem;
|
||||
}
|
||||
|
||||
.file-extension.medium {
|
||||
font-size: 0.7rem;
|
||||
}
|
||||
|
||||
.file-extension.long {
|
||||
font-size: 0.55rem;
|
||||
}
|
||||
|
||||
.file-name {
|
||||
font-size: 0.65rem;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user