From eae685eacf577e1b5dfeef2f37e0f6e48a7855f2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=98=D0=B3=D0=BE=D1=80=D1=8C=20=D0=9D=D0=B0=D0=B4=D0=B5?= =?UTF-8?q?=D0=B8=D0=BD?= Date: Fri, 28 Nov 2025 08:14:08 +0300 Subject: [PATCH] =?UTF-8?q?Fix:=20=D1=83=D0=BB=D1=83=D1=87=D1=88=D0=B5?= =?UTF-8?q?=D0=BD=D0=B0=20=D0=B7=D0=B0=D0=B3=D1=80=D1=83=D0=B7=D0=BA=D0=B0?= =?UTF-8?q?=20=D0=B2=D0=B8=D0=B4=D0=B5=D0=BE=20=D0=B8=20=D1=81=D0=B4=D0=B5?= =?UTF-8?q?=D0=BB=D0=B0=D0=BD=20=D1=82=D0=B5=D0=BA=D1=81=D1=82=20=D0=BD?= =?UTF-8?q?=D0=B5=D0=BE=D0=B1=D1=8F=D0=B7=D0=B0=D1=82=D0=B5=D0=BB=D1=8C?= =?UTF-8?q?=D0=BD=D1=8B=D0=BC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Исправления видео: - Видео элементы теперь создаются программно через createElement - Удалён setTimeout, добавлена прямая замена placeholder'ов - video.load() вызывается сразу после создания элемента - Исправлен доступ к правильному контейнеру вложения Текст необязателен при файлах: - Удалён атрибут required у textarea - Добавлена валидация: должен быть либо текст, либо файлы - При отправке файла без текста отправляется пустая строка - Показывается alert если нет ни текста, ни файлов --- .../js/components/chatMessageTemplates.js | 42 +++++++++++++++---- .../templates/communications/chat_detail.html | 12 ++++-- 2 files changed, 44 insertions(+), 10 deletions(-) diff --git a/backend/static/js/components/chatMessageTemplates.js b/backend/static/js/components/chatMessageTemplates.js index 85a9e990..3c5b508c 100644 --- a/backend/static/js/components/chatMessageTemplates.js +++ b/backend/static/js/components/chatMessageTemplates.js @@ -223,14 +223,42 @@ export function createMessageElement(msg, options = {}) { wrap.innerHTML = `${bubble}${ava}`; } - // Принудительно загружаем видео после добавления в DOM + // Принудительно создаём и загружаем видео элементы после добавления в DOM if (msg.has_attachments && msg.attachments && msg.attachments.length > 0) { - setTimeout(() => { - const videos = wrap.querySelectorAll('video'); - videos.forEach(video => { - video.load(); - }); - }, 100); + // Находим все video placeholder'ы и заменяем их реальными элементами + const videoContainers = wrap.querySelectorAll('.attachment-item'); + msg.attachments.forEach((att, index) => { + if (att.file_type === 'video') { + const container = videoContainers[index]; + if (container) { + // Очищаем контейнер + container.innerHTML = ''; + + // Создаём video элемент программно + const video = document.createElement('video'); + video.controls = true; + video.preload = 'metadata'; + video.className = 'w-100'; + video.style.maxWidth = '400px'; + + const source = document.createElement('source'); + source.src = att.file_url; + source.type = att.mime_type; + + video.appendChild(source); + + const textDiv = document.createElement('div'); + textDiv.className = 'small text-secondary'; + textDiv.textContent = att.file_name; + + container.appendChild(video); + container.appendChild(textDiv); + + // Загружаем видео + video.load(); + } + } + }); } return wrap; diff --git a/backend/templates/communications/chat_detail.html b/backend/templates/communications/chat_detail.html index 0e2d17b8..379feeac 100644 --- a/backend/templates/communications/chat_detail.html +++ b/backend/templates/communications/chat_detail.html @@ -200,8 +200,7 @@ id="id_content" class="form-control composer-textarea" rows="1" - placeholder="Напишите сообщение…" - required> + placeholder="Напишите сообщение…"> @@ -349,10 +348,17 @@ document.addEventListener('DOMContentLoaded', function() { const textarea = document.getElementById('id_content'); const content = textarea.value.trim(); + // Проверка: должен быть либо текст, либо файлы + if (!content && selectedFiles.length === 0) { + alert('Введите текст сообщения или прикрепите файл'); + return; + } + // Если есть вложения, отправляем через API if (selectedFiles.length > 0) { const formData = new FormData(); - formData.append('content', content || 'Вложение'); + // Если текст пустой, отправляем пустую строку + formData.append('content', content || ''); selectedFiles.forEach((file, index) => { formData.append(`file_${index}`, file);