фиксим все что можно
This commit is contained in:
@@ -257,6 +257,7 @@ function commentListShow($tpl_dir)
|
||||
$assign['im'] = $settings['comment_use_antispam'];
|
||||
$assign['comment_allowed_extensions'] = $settings['comment_allowed_extensions'] ?? 'jpg,jpeg,png,gif';
|
||||
$assign['comment_max_file_size'] = $settings['comment_max_file_size'] ?? 2048;
|
||||
$assign['comment_max_files'] = (int)($settings['comment_max_files'] ?? 5);
|
||||
$comments = array();
|
||||
|
||||
if ($settings['comment_use_page_nav'] == 1)
|
||||
@@ -482,6 +483,21 @@ function commentListShow($tpl_dir)
|
||||
$uploaded_files = [];
|
||||
if ($settings['comment_allow_files'] == 1 && isset($_FILES['comment_image']))
|
||||
{
|
||||
// --- ДОБАВЛЯЕМ ПРОВЕРКУ ЛИМИТА КОЛИЧЕСТВА ---
|
||||
$max_files_limit = (int)($settings['comment_max_files'] ?? 5);
|
||||
$total_incoming = 0;
|
||||
if (is_array($_FILES['comment_image']['name'])) {
|
||||
foreach($_FILES['comment_image']['name'] as $fname) if(!empty($fname)) $total_incoming++;
|
||||
} elseif(!empty($_FILES['comment_image']['name'])) {
|
||||
$total_incoming = 1;
|
||||
}
|
||||
|
||||
if ($total_incoming > $max_files_limit) {
|
||||
if ($ajax) { echo 'error_max_files'; exit; }
|
||||
else { header('Location:' . $link . '#end'); exit; }
|
||||
}
|
||||
// --- КОНЕЦ ПРОВЕРКИ ---
|
||||
|
||||
$upload_path = BASE_DIR . '/uploads/comments/';
|
||||
if (!is_dir($upload_path)) {
|
||||
@mkdir($upload_path, 0775, true);
|
||||
@@ -612,6 +628,7 @@ function commentPostEdit($comment_id)
|
||||
if ($comment_id <= 0 || $user_group <= 0) exit('INVALID_ID');
|
||||
|
||||
// 2. Получаем данные комментария и настройки модуля (JOIN)
|
||||
// ДОБАВЛЕНО: cmnt.comment_max_files в выборку
|
||||
$row = $AVE_DB->Query("
|
||||
SELECT
|
||||
msg.*,
|
||||
@@ -620,7 +637,8 @@ function commentPostEdit($comment_id)
|
||||
cmnt.comment_user_groups,
|
||||
cmnt.comment_edit_time,
|
||||
cmnt.comment_allowed_extensions,
|
||||
cmnt.comment_max_file_size
|
||||
cmnt.comment_max_file_size,
|
||||
cmnt.comment_max_files
|
||||
FROM " . PREFIX . "_module_comment_info AS msg
|
||||
JOIN " . PREFIX . "_module_comments AS cmnt ON cmnt.Id = 1
|
||||
WHERE msg.Id = '" . $comment_id . "'
|
||||
@@ -685,10 +703,24 @@ function commentPostEdit($comment_id)
|
||||
}
|
||||
}
|
||||
|
||||
// --- Б. Загрузка новых файлов (если есть) ---
|
||||
// Проверяем, что пришел массив файлов
|
||||
// --- Б. Загрузка новых файлов (с проверкой лимита) ---
|
||||
if (isset($_FILES['comment_image']) && is_array($_FILES['comment_image']['name'])) {
|
||||
|
||||
// 1. Считаем, сколько реально новых файлов пытаются загрузить
|
||||
$new_files_to_upload_count = 0;
|
||||
foreach ($_FILES['comment_image']['name'] as $k => $fname) {
|
||||
if (!empty($fname) && $_FILES['comment_image']['error'][$k] == UPLOAD_ERR_OK) {
|
||||
$new_files_to_upload_count++;
|
||||
}
|
||||
}
|
||||
|
||||
// 2. Проверка лимита: (Оставшиеся старые + Новые) не должно быть больше MAX
|
||||
$max_limit = (int)($row['comment_max_files'] ?? 5);
|
||||
if ((count($current_files) + $new_files_count) > $max_limit) {
|
||||
echo "MAX_FILES_LIMIT_EXCEEDED"; // Это поймает JS
|
||||
exit;
|
||||
}
|
||||
|
||||
$allowed_ext_str = $row['comment_allowed_extensions'] ?? 'jpg,jpeg,png,gif,webp';
|
||||
$allowed_extensions = array_map('trim', explode(',', strtolower($allowed_ext_str)));
|
||||
$max_kb = (int)($row['comment_max_file_size'] ?? 2048);
|
||||
|
||||
205
js/comment.js
205
js/comment.js
@@ -530,26 +530,27 @@ if ($foundImgs.length > 0) {
|
||||
}
|
||||
|
||||
// --- СБОРКА ФОРМЫ ---
|
||||
var editHtml = `
|
||||
<div class="edit-form-container border rounded p-3 bg-light mt-2 mb-2">
|
||||
<textarea rows="5" id="ta_${cid}" class="form-control mb-3">${cleanText}</textarea>
|
||||
${starsEditBlock}
|
||||
|
||||
<p class="small text-muted mb-1">Загруженные файлы:</p>
|
||||
${existingImagesHtml}
|
||||
|
||||
<div class="mb-2">
|
||||
<label class="small text-muted mb-1">Добавить новые:</label>
|
||||
<input type="file" name="comment_image[]" id="new_file_${cid}" class="form-control form-control-sm" accept="image/*" multiple>
|
||||
</div>
|
||||
<input type="hidden" name="delete_files" id="delete_files_${cid}" value="">
|
||||
|
||||
<div class="d-flex gap-2 mt-3 align-items-center">
|
||||
<button type="button" class="btn btn-sm btn-primary saveButton" data-id="${cid}">Сохранить</button>
|
||||
<button type="button" class="btn btn-sm btn-secondary cancelButton">Отмена</button>
|
||||
<small class="ms-auto text-muted">Осталось: <span id="charsLeft_${cid}"></span></small>
|
||||
</div>
|
||||
</div>`;
|
||||
var editHtml = `
|
||||
<div class="edit-form-container border rounded p-3 bg-light mt-2 mb-2" data-cid="${cid}">
|
||||
<textarea rows="5" id="ta_${cid}" class="form-control mb-3">${cleanText}</textarea>
|
||||
${starsEditBlock}
|
||||
|
||||
<p class="small text-muted mb-1">Загруженные файлы:</p>
|
||||
${existingImagesHtml}
|
||||
|
||||
<div class="mb-2">
|
||||
<label class="small text-muted mb-1">Добавить новые:</label>
|
||||
<div id="file_error_${cid}" class="js-file-error text-danger small fw-bold mb-1" style="display:none;"></div>
|
||||
<input type="file" name="comment_image[]" id="new_file_${cid}" class="form-control form-control-sm" accept="image/*" multiple>
|
||||
</div>
|
||||
<input type="hidden" name="delete_files" id="delete_files_${cid}" value="">
|
||||
|
||||
<div class="d-flex gap-2 mt-3 align-items-center">
|
||||
<button type="button" class="btn btn-sm btn-primary saveButton" data-id="${cid}">Сохранить</button>
|
||||
<button type="button" class="btn btn-sm btn-secondary cancelButton">Отмена</button>
|
||||
<small class="ms-auto text-muted">Осталось: <span id="charsLeft_${cid}"></span></small>
|
||||
</div>
|
||||
</div>`;
|
||||
|
||||
$textBlock.hide();
|
||||
$attachedImagesBlock.hide();
|
||||
@@ -562,51 +563,69 @@ if ($foundImgs.length > 0) {
|
||||
|
||||
$wrapper.find('.edit-form-container').data('pendingFiles', pendingFiles);
|
||||
|
||||
$('#new_file_' + cid).on('change', function() {
|
||||
var files = this.files;
|
||||
var $previewContainer = $('#new_files_preview_' + cid);
|
||||
|
||||
if ($previewContainer.length === 0) {
|
||||
$(this).after(`<div id="new_files_preview_${cid}" class="d-flex flex-wrap gap-2 mt-2"></div>`);
|
||||
$previewContainer = $('#new_files_preview_' + cid);
|
||||
}
|
||||
|
||||
// Мы НЕ удаляем старые превью ($previewContainer.empty() убрали),
|
||||
// а просто добавляем новые в массив и в контейнер
|
||||
if (files) {
|
||||
$.each(files, function(i, file) {
|
||||
if (!file.type.match('image.*')) return;
|
||||
$('#new_file_' + cid).on('change', function() {
|
||||
var files = this.files;
|
||||
var $input = $(this);
|
||||
var $currentEditForm = $input.closest('.edit-form-container');
|
||||
|
||||
// ИЩЕМ ТОЛЬКО ПО КЛАССУ ОТНОСИТЕЛЬНО ИНПУТА
|
||||
var $errorDisplay = $input.prev('.js-file-error');
|
||||
|
||||
var maxLimit = parseInt(typeof MAX_FILES_COUNT !== 'undefined' ? MAX_FILES_COUNT : 5);
|
||||
|
||||
if (files) {
|
||||
// Очищаем при каждом новом выборе
|
||||
$errorDisplay.text('').hide();
|
||||
|
||||
$.each(files, function(i, file) {
|
||||
var alreadyInPost = $currentEditForm.find('[id^="existing_wrapper_"]').length;
|
||||
var inPending = pendingFiles.filter(f => f !== null).length;
|
||||
|
||||
if ((alreadyInPost + inPending) >= maxLimit) {
|
||||
// ВЫВОДИМ ТЕКСТ
|
||||
$errorDisplay.text('⚠️ Лимит: ' + maxLimit + ' шт. Лишние файлы проигнорированы.').show();
|
||||
|
||||
// Добавляем файл в наш список
|
||||
pendingFiles.push(file);
|
||||
var currentIndex = pendingFiles.length - 1;
|
||||
$input.val('');
|
||||
return false;
|
||||
}
|
||||
|
||||
var reader = new FileReader();
|
||||
reader.onload = function(e) {
|
||||
$previewContainer.append(`
|
||||
<div class="position-relative new-file-item" data-index="${currentIndex}">
|
||||
<img src="${e.target.result}" class="img-thumbnail" style="width: 80px; height: 80px; object-fit: cover; border: 2px solid #0d6efd;">
|
||||
<span class="badge bg-primary position-absolute top-0 start-0 m-1" style="font-size: 0.6rem;">NEW</span>
|
||||
<button type="button" class="btn btn-danger btn-sm position-absolute top-0 end-0 remove-new-file"
|
||||
style="padding: 0 5px; margin: 2px; line-height: 1; z-index: 10;">
|
||||
<i class="bi bi-x-lg" style="font-size: 0.7rem;"></i>
|
||||
</button>
|
||||
</div>`);
|
||||
};
|
||||
reader.readAsDataURL(file);
|
||||
});
|
||||
}
|
||||
// Очищаем инпут, чтобы браузер позволил выбрать те же файлы снова
|
||||
$(this).val('');
|
||||
});
|
||||
if (!file.type.match('image.*')) return true;
|
||||
|
||||
// Обработчик удаления НОВОГО файла из превью (до сохранения)
|
||||
$doc.off('click', '.remove-new-file').on('click', '.remove-new-file', function() {
|
||||
var $item = $(this).closest('.new-file-item');
|
||||
var index = $item.data('index');
|
||||
pendingFiles[index] = null; // Помечаем как удаленный
|
||||
$item.remove();
|
||||
});
|
||||
pendingFiles.push(file);
|
||||
var currentIndex = pendingFiles.length - 1;
|
||||
|
||||
var reader = new FileReader();
|
||||
reader.onload = function(e) {
|
||||
var $previewContainer = $('#new_files_preview_' + cid);
|
||||
if ($previewContainer.length === 0) {
|
||||
$input.after(`<div id="new_files_preview_${cid}" class="d-flex flex-wrap gap-2 mt-2"></div>`);
|
||||
$previewContainer = $('#new_files_preview_' + cid);
|
||||
}
|
||||
$previewContainer.append(`
|
||||
<div class="position-relative new-file-item" data-index="${currentIndex}">
|
||||
<img src="${e.target.result}" class="img-thumbnail" style="width: 80px; height: 80px; object-fit: cover; border: 2px solid #0d6efd;">
|
||||
<button type="button" class="btn btn-danger btn-sm position-absolute top-0 end-0 remove-new-file" style="padding: 0 5px; margin: 2px; line-height: 1;">
|
||||
<i class="bi bi-x-lg" style="font-size: 0.7rem;"></i>
|
||||
</button>
|
||||
</div>`);
|
||||
};
|
||||
reader.readAsDataURL(file);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// Обработчик удаления НОВОГО файла из превью (до сохранения)
|
||||
$doc.off('click', '.remove-new-file').on('click', '.remove-new-file', function() {
|
||||
var $item = $(this).closest('.new-file-item');
|
||||
var index = $item.data('index');
|
||||
|
||||
pendingFiles[index] = null; // Помечаем как удаленный
|
||||
$item.remove();
|
||||
|
||||
// ЗАМЕНЯЕМ СТАРУЮ СТРОКУ НА ЭТУ:
|
||||
// Ищем через ближайший контейнер формы, чтобы точно попасть в нужный блок текста
|
||||
$(this).closest('.edit-form-container').find('.js-file-error').hide().text('');
|
||||
});
|
||||
// --- КОНЕЦ ВСТАВКИ ---
|
||||
|
||||
// Добавил поддержку лимита символов
|
||||
@@ -622,10 +641,12 @@ if ($foundImgs.length > 0) {
|
||||
|
||||
$doc.on('click', '.remove-existing-img', function() {
|
||||
var cid = $(this).data('id');
|
||||
var imgPath = $(this).data('img-path'); // Имя файла
|
||||
var imgPath = $(this).data('img-path');
|
||||
var targetId = $(this).data('target');
|
||||
|
||||
// Добавляем имя файла в скрытый инпут для сервера
|
||||
// 1. Очищаем текст ошибки, так как место освободилось
|
||||
$('#file_error_' + cid).addClass('d-none').text('');
|
||||
|
||||
var $deleteInput = $('#delete_files_' + cid);
|
||||
var currentDeleteList = $deleteInput.val() ? $deleteInput.val().split(',') : [];
|
||||
|
||||
@@ -634,29 +655,34 @@ $doc.on('click', '.remove-existing-img', function() {
|
||||
$deleteInput.val(currentDeleteList.join(','));
|
||||
}
|
||||
|
||||
// Скрываем блок с картинкой
|
||||
$('#' + targetId).fadeOut(300);
|
||||
// 2. Скрываем и УДАЛЯЕМ элемент, чтобы счетчик .length его больше не видел
|
||||
$('#' + targetId).fadeOut(300, function() {
|
||||
$(this).remove();
|
||||
});
|
||||
});
|
||||
|
||||
// Обработка выбора НОВОГО файла при редактировании
|
||||
$doc.on('change', 'input[id^="new_file_"]', function() {
|
||||
var cid = $(this).attr('id').replace('new_file_', '');
|
||||
var input = this;
|
||||
var $errorBox = $('#file_error_' + cid);
|
||||
|
||||
// 1. Сначала находим блок (БЕЗ ОШИБОК В ПЕРЕМЕННЫХ)
|
||||
var $errorBox = $('#file_error_' + cid);
|
||||
var $previewWrapper = $('#edit_preview_wrapper_' + cid);
|
||||
|
||||
// Очищаем превью перед новым выбором
|
||||
$previewWrapper.find('.preview-item-new').remove();
|
||||
$errorBox.addClass('d-none').text('');
|
||||
|
||||
if (input.files && input.files.length > 0) {
|
||||
// 2. НЕ ОЧИЩАЕМ ТЕКСТ СРАЗУ, даем checkFileConsistency шанс вывести ошибку
|
||||
$previewWrapper.find('.preview-item-new').remove();
|
||||
$previewWrapper.removeClass('d-none');
|
||||
|
||||
Array.from(input.files).forEach(function(file) {
|
||||
// 3. Передаем именно найденный объект
|
||||
if (checkFileConsistency(file, $errorBox)) {
|
||||
// Если файл прошел проверку - только тогда можно спрятать старую ошибку
|
||||
$errorBox.addClass('d-none').text('');
|
||||
|
||||
var reader = new FileReader();
|
||||
reader.onload = function(e) {
|
||||
// Создаем новое превью для каждого файла
|
||||
var item = `
|
||||
<div class="position-relative preview-item-new">
|
||||
<img src="${e.target.result}" class="img-thumbnail" style="max-height: 100px;">
|
||||
@@ -666,10 +692,6 @@ $doc.on('change', 'input[id^="new_file_"]', function() {
|
||||
reader.readAsDataURL(file);
|
||||
}
|
||||
});
|
||||
|
||||
// Прячем старое фото и помечаем на удаление
|
||||
$('#existing_preview_wrapper_' + cid).addClass('d-none');
|
||||
$('#del_img_' + cid).prop('checked', true);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -750,6 +772,8 @@ $doc.on('click', '.saveButton', function() {
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
|
||||
// Глобальный массив для файлов НОВОГО комментария
|
||||
var newCommentPendingFiles = [];
|
||||
|
||||
@@ -758,27 +782,40 @@ var newCommentPendingFiles = [];
|
||||
$doc.off('change', '#comment_image').on('change', '#comment_image', function() {
|
||||
var files = this.files;
|
||||
var $previewWrapper = $('#image_preview_wrapper');
|
||||
var $errorDisplay = $('#file_error'); // добавили переменную для ошибок
|
||||
var $errorDisplay = $('#file_error');
|
||||
|
||||
// 1. Лимит из настроек
|
||||
var maxLimit = parseInt(typeof MAX_FILES_COUNT !== 'undefined' ? MAX_FILES_COUNT : 5);
|
||||
|
||||
if (files) {
|
||||
$errorDisplay.addClass('d-none').text(''); // Сбрасываем старые ошибки
|
||||
|
||||
$.each(files, function(i, file) {
|
||||
// --- ТВОЯ ВАЛИДАЦИЯ (Screenshot 7 и 8) ---
|
||||
// 2. Считаем, сколько сейчас РЕАЛЬНО файлов в очереди (не null)
|
||||
var currentInQueue = newCommentPendingFiles.filter(function(f) { return f !== null; }).length;
|
||||
|
||||
// 3. ПРОВЕРКА ЛИМИТА: если уже достигли максимума
|
||||
if (currentInQueue >= maxLimit) {
|
||||
$errorDisplay.removeClass('d-none').text('Достигнут лимит (' + maxLimit + ' шт.). Лишние файлы проигнорированы.');
|
||||
return false; // break - полностью выходим из цикла $.each
|
||||
}
|
||||
|
||||
// 4. Твоя существующая валидация (размер, расширение)
|
||||
if (typeof checkFileConsistency === 'function') {
|
||||
if (!checkFileConsistency(file, $errorDisplay)) {
|
||||
return true; // если файл плохой - пропускаем его
|
||||
return true; // continue - этот файл плохой, идем к следующему
|
||||
}
|
||||
}
|
||||
// ------------------------------------------
|
||||
|
||||
// Если прошли все проверки — добавляем в очередь
|
||||
newCommentPendingFiles.push(file);
|
||||
var currentIndex = newCommentPendingFiles.length - 1;
|
||||
|
||||
var reader = new FileReader();
|
||||
reader.onload = function(e) {
|
||||
// ПРОВЕРКА: если превью для этого файла уже есть - не добавляем второе
|
||||
if ($previewWrapper.find(`[data-index="${currentIndex}"]`).length > 0) return;
|
||||
|
||||
$previewWrapper.removeClass('d-none'); // показываем только когда есть что показать
|
||||
$previewWrapper.removeClass('d-none');
|
||||
$previewWrapper.append(`
|
||||
<div class="position-relative new-comment-file-item" data-index="${currentIndex}">
|
||||
<img src="${e.target.result}" class="img-thumbnail" style="width: 80px; height: 80px; object-fit: cover; border: 2px solid #198754;">
|
||||
@@ -791,7 +828,8 @@ $doc.off('change', '#comment_image').on('change', '#comment_image', function() {
|
||||
reader.readAsDataURL(file);
|
||||
});
|
||||
}
|
||||
// Очищаем инпут
|
||||
|
||||
// Очищаем инпут в любом случае, чтобы можно было выбрать те же файлы снова
|
||||
$(this).val('');
|
||||
});
|
||||
|
||||
@@ -800,6 +838,7 @@ $doc.on('click', '.remove-new-comment-img', function() {
|
||||
var $item = $(this).closest('.new-comment-file-item');
|
||||
var index = $item.data('index');
|
||||
newCommentPendingFiles[index] = null; // Помечаем удаленным
|
||||
$('#file_error').addClass('d-none').text('');
|
||||
$item.fadeOut(200, function() {
|
||||
$(this).remove();
|
||||
if ($('#image_preview_wrapper').children().length === 0) {
|
||||
|
||||
8
sql.php
8
sql.php
@@ -5,7 +5,7 @@
|
||||
*
|
||||
* Обновленная структура с поддержкой выбора типа рейтинга,
|
||||
* идентификации анонимов, загрузки файлов и защиты по IP.
|
||||
* ДОБАВЛЕНО: Управление расширениями и максимальным размером файлов.
|
||||
* ДОБАВЛЕНО: Управление расширениями, размером и КОЛИЧЕСТВОМ файлов.
|
||||
* СИНХРОНИЗАЦИЯ: Добавлен формат webp по умолчанию.
|
||||
*/
|
||||
|
||||
@@ -39,6 +39,7 @@ $module_sql_install[] = "CREATE TABLE `%%PRFX%%_module_comments` (
|
||||
`comment_allow_files` tinyint(1) NOT NULL default '0',
|
||||
`comment_allowed_extensions` varchar(255) NOT NULL default 'jpg,jpeg,png,gif,webp',
|
||||
`comment_max_file_size` int(10) NOT NULL default '2048',
|
||||
`comment_max_files` tinyint(2) NOT NULL default '5',
|
||||
`comment_rating_type` tinyint(1) NOT NULL default '0',
|
||||
`comment_show_user_rating` tinyint(1) NOT NULL default '0',
|
||||
`comment_show_user_rating_replies` tinyint(1) NOT NULL default '0',
|
||||
@@ -93,8 +94,8 @@ $module_sql_install[] = "CREATE TABLE `%%PRFX%%_module_comment_votes` (
|
||||
KEY `remote_addr` (`remote_addr`)
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=utf8;";
|
||||
|
||||
/* Настройки по умолчанию */
|
||||
$module_sql_install[] = "INSERT INTO `%%PRFX%%_module_comments` VALUES (1, 1000, '1,3', '1,2,3,4', '0', '1', '1' , '0', '', 1, 0, '', 1, 0, '', 0, 'jpg,jpeg,png,gif,webp', 2048, 0, 1, 0, 0, 0, 0, 60, 30);";
|
||||
/* Настройки по умолчанию (добавлено значение 5 для comment_max_files) */
|
||||
$module_sql_install[] = "INSERT INTO `%%PRFX%%_module_comments` VALUES (1, 1000, '1,3', '1,2,3,4', '0', '1', '1' , '0', '', 1, 0, '', 1, 0, '', 0, 'jpg,jpeg,png,gif,webp', 2048, 5, 0, 1, 0, 0, 0, 0, 60, 30);";
|
||||
|
||||
// =================================================================================
|
||||
// 2. ОБНОВЛЕНИЕ МОДУЛЯ (ALTER TABLE)
|
||||
@@ -112,5 +113,6 @@ $module_sql_update[] = "ALTER TABLE `%%PRFX%%_module_comments` ADD COLUMN IF NOT
|
||||
/* Новые поля для файлов при обновлении */
|
||||
$module_sql_update[] = "ALTER TABLE `%%PRFX%%_module_comments` ADD COLUMN IF NOT EXISTS `comment_allowed_extensions` VARCHAR(255) NOT NULL DEFAULT 'jpg,jpeg,png,gif,webp';";
|
||||
$module_sql_update[] = "ALTER TABLE `%%PRFX%%_module_comments` ADD COLUMN IF NOT EXISTS `comment_max_file_size` INT(10) NOT NULL DEFAULT '2048';";
|
||||
$module_sql_update[] = "ALTER TABLE `%%PRFX%%_module_comments` ADD COLUMN IF NOT EXISTS `comment_max_files` TINYINT(2) NOT NULL DEFAULT '5';";
|
||||
|
||||
?>
|
||||
@@ -202,7 +202,7 @@
|
||||
<tr>
|
||||
<td>Допустимые расширения:</td>
|
||||
<td style="border-right: 1px solid #ddd;">
|
||||
<input name="comment_allowed_extensions" type="text" value="{$comment_allowed_extensions|default:'jpg,jpeg,png,gif'}" style="width: 90%;" placeholder="Пример: jpg, png, gif" />
|
||||
<input name="comment_allowed_extensions" type="text" value="{$comment_allowed_extensions|default:'jpg,jpeg,png,gif,webp'}" style="width: 90%;" placeholder="Пример: jpg, png, gif" />
|
||||
</td>
|
||||
<td>Макс. размер файла (Кб):</td>
|
||||
<td>
|
||||
@@ -210,6 +210,15 @@
|
||||
<span style="color: #888; font-size: 11px; margin-left: 5px;">KB</span>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Макс. кол-во файлов:</td>
|
||||
<td style="border-right: 1px solid #ddd;">
|
||||
<input name="comment_max_files" type="text" value="{$comment_max_files|default:'5'}" size="4" style="width: 50px;" />
|
||||
<span style="color: #888; font-size: 11px; margin-left: 5px;">шт. на один комментарий</span>
|
||||
</td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td colspan="4" class="submitArea">
|
||||
|
||||
@@ -151,12 +151,12 @@
|
||||
<div class="small text-muted mb-2">
|
||||
Разрешены: <span class="fw-bold">{$comment_allowed_extensions|default:'jpg, png, gif'}</span>.
|
||||
Макс. размер: <span class="fw-bold">{$comment_max_file_size|default:'2048'} Кб</span>.
|
||||
{* ВНЕДРЯЕМ ЛИМИТ КОЛИЧЕСТВА *}
|
||||
Макс. количество: <span class="fw-bold text-primary">{$comment_max_files|default:'5'} шт.</span>
|
||||
</div>
|
||||
|
||||
{* Ключевое изменение: name="comment_image[]" и атрибут multiple *}
|
||||
<input type="file" name="comment_image[]" id="comment_image" class="form-control form-control-sm" multiple>
|
||||
|
||||
{* Контейнер для нескольких превью *}
|
||||
<div id="image_preview_wrapper" class="mt-2 d-flex flex-wrap gap-2 d-none">
|
||||
{* Сюда JS будет добавлять превью *}
|
||||
</div>
|
||||
@@ -271,6 +271,7 @@
|
||||
// --- ПЕРЕМЕННЫЕ ДЛЯ ВАЛИДАЦИИ ФАЙЛОВ ---
|
||||
var ALLOWED_EXTENSIONS = '{$comment_allowed_extensions|default:"jpg,jpeg,png,gif"}';
|
||||
var MAX_FILE_SIZE_KB = '{$comment_max_file_size|default:2048}';
|
||||
var MAX_FILES_COUNT = '{$comment_max_files|default:5}';
|
||||
</script>
|
||||
<script src="{$ABS_PATH}modules/comment/js/comment.js" type="text/javascript"></script>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user