добавлен функционал опубликовать после проверки и скрытия показа комментариев

This commit is contained in:
2026-01-08 11:11:39 +05:00
parent 35a39031e0
commit 215afa655c
5 changed files with 148 additions and 135 deletions

View File

@@ -257,6 +257,20 @@ function commentListShow($tpl_dir)
$current_user_id = (int)($_SESSION['user_id'] ?? 0);
$anon_key = $this->_getAnonKey();
// --- УСЛОВИЕ ВИДИМОСТИ (Свои неодобренные + Все одобренные) ---
if ($user_group == 1) {
$where_visibility = ""; // Админ видит всё
} else {
$cond = "comment_status = '1'";
if ($current_user_id > 0) {
$cond .= " OR (comment_status = '0' AND comment_author_id = '$current_user_id')";
}
if (!empty($anon_key)) {
$cond .= " OR (comment_status = '0' AND anon_key = '$anon_key')";
}
$where_visibility = "AND (" . $cond . ")";
}
// Получаем ВСЕ настройки модуля разом (из БД)
$settings = $this->_commentSettingsGet();
@@ -291,131 +305,100 @@ function commentListShow($tpl_dir)
$assign['ajax_replies_limit'] = (int)($settings['comment_ajax_replies_limit'] ?? 0);
$comments = array();
// --- ВЫБОРКА ИЗ БД ---
if ($settings['comment_use_page_nav'] == 1)
{
$limit = (int)$settings['comment_page_nav_count'];
if ($limit <= 0)
{
$sql = $AVE_DB->Query("SELECT * FROM " . PREFIX . "_module_comment_info WHERE document_id = '" . $document_id . "' " . $where_visibility . " ORDER BY comment_published ASC");
$page_nav = '';
}
else
{
$start = get_current_page() * $limit - $limit;
// 1. Считаем только РОДИТЕЛЕЙ для пагинации (с учетом видимости)
$num = $AVE_DB->Query("SELECT COUNT(*) FROM " . PREFIX . "_module_comment_info WHERE document_id = '" . $document_id . "' AND parent_id = '0' " . $where_visibility)->GetCell();
// 2. Основной запрос
$sql = $AVE_DB->Query("
SELECT * FROM " . PREFIX . "_module_comment_info
WHERE document_id = '" . $document_id . "'
AND (
id IN (SELECT id FROM (SELECT id FROM " . PREFIX . "_module_comment_info WHERE document_id = '" . $document_id . "' AND parent_id = '0' " . $where_visibility . " ORDER BY comment_published ASC LIMIT " . (int)$start . "," . (int)$limit . ") as tmp)
OR
parent_id != '0'
)
" . $where_visibility . "
ORDER BY comment_published ASC
");
if ($settings['comment_use_page_nav'] == 1)
{
$limit = (int)$settings['comment_page_nav_count'];
// Если лимит включен, но равен 0 — это то же самое, что лимит выключен
if ($limit <= 0)
{
$sql = $AVE_DB->Query("SELECT * FROM " . PREFIX . "_module_comment_info WHERE document_id = '" . $document_id . "' " . ($user_group == 1 ? '' : "AND comment_status = '1'") . " ORDER BY comment_published ASC");
$page_nav = '';
}
else
{
$start = get_current_page() * $limit - $limit;
// 1. Считаем только РОДИТЕЛЕЙ для пагинации
$num = $AVE_DB->Query("SELECT COUNT(*) FROM " . PREFIX . "_module_comment_info WHERE document_id = '" . $document_id . "' AND parent_id = '0'")->GetCell();
// 2. Основной запрос: выбираем ВСЮ ветку (родителя и всё, что под ним)
$sql = $AVE_DB->Query("
SELECT * FROM " . PREFIX . "_module_comment_info
WHERE document_id = '" . $document_id . "'
AND (
id IN (SELECT id FROM (SELECT id FROM " . PREFIX . "_module_comment_info WHERE document_id = '" . $document_id . "' AND parent_id = '0' ORDER BY comment_published ASC LIMIT " . (int)$start . "," . (int)$limit . ") as tmp)
OR
parent_id != '0'
)
" . ($user_group == 1 ? '' : "AND comment_status = '1'") . "
ORDER BY comment_published ASC
");
if ($num > $limit)
{
$page_nav = '<a class="page_nav" href="index.php?id=' . $AVE_Core->curentdoc->Id
. '&amp;doc=' . (empty($AVE_Core->curentdoc->document_alias) ? prepare_url($AVE_Core->curentdoc->document_title) : $AVE_Core->curentdoc->document_alias)
. ((isset($artpage) && is_numeric($artpage)) ? '&amp;artpage=' . $artpage : '')
. ((isset($apage) && is_numeric($apage)) ? '&amp;apage=' . $apage : '')
. '&amp;page={s}">{t}</a> ';
// Теперь деление на $limit безопасно, так как мы выше проверили, что он > 0
$total_pages = ceil($num / $limit);
$page_nav = get_pagination($total_pages, 'page', $page_nav, get_settings('navi_box'));
$page_nav = str_ireplace('"//"', '"/"', str_ireplace('///', '/', rewrite_link($page_nav)));
$page_nav = preg_replace('/(?<!:)\/\//', '/', $page_nav);
$GLOBALS['page_id'][$document_id]['page'] = ($GLOBALS['page_id'][$document_id]['page'] > $total_pages ? $GLOBALS['page_id'][$document_id]['page'] : $total_pages);
}
else { $page_nav = ''; }
}
}
else
{
$sql = $AVE_DB->Query("SELECT * FROM " . PREFIX . "_module_comment_info WHERE document_id = '" . $document_id . "' " . ($user_group == 1 ? '' : "AND comment_status = '1'") . " ORDER BY comment_published ASC");
$page_nav = '';
}
if ($num > $limit)
{
$page_nav = '<a class="page_nav" href="index.php?id=' . $AVE_Core->curentdoc->Id
. '&amp;doc=' . (empty($AVE_Core->curentdoc->document_alias) ? prepare_url($AVE_Core->curentdoc->document_title) : $AVE_Core->curentdoc->document_alias)
. ((isset($artpage) && is_numeric($artpage)) ? '&amp;artpage=' . $artpage : '')
. ((isset($apage) && is_numeric($apage)) ? '&amp;apage=' . $apage : '')
. '&amp;page={s}">{t}</a> ';
$total_pages = ceil($num / $limit);
$page_nav = get_pagination($total_pages, 'page', $page_nav, get_settings('navi_box'));
$page_nav = str_ireplace('"//"', '"/"', str_ireplace('///', '/', rewrite_link($page_nav)));
$page_nav = preg_replace('/(?<!:)\/\//', '/', $page_nav);
$GLOBALS['page_id'][$document_id]['page'] = ($GLOBALS['page_id'][$document_id]['page'] > $total_pages ? $GLOBALS['page_id'][$document_id]['page'] : $total_pages);
}
else { $page_nav = ''; }
}
}
else
{
$sql = $AVE_DB->Query("SELECT * FROM " . PREFIX . "_module_comment_info WHERE document_id = '" . $document_id . "' " . $where_visibility . " ORDER BY comment_published ASC");
$page_nav = '';
}
$date_time_format = $AVE_Template->get_config_vars('COMMENT_DATE_TIME_FORMAT');
$now = time();
// получение лимита времени из настроек БД
$conf_limit = (int)($settings['comment_edit_time'] ?? 0);
while ($row = $sql->FetchAssocArray())
{
if ($assign['saved_anon']['exists'] == false && !empty($row['anon_key']) && $row['anon_key'] == $anon_key) {
$assign['saved_anon'] = [
'name' => stripslashes($row['comment_author_name']),
'email' => stripslashes($row['comment_author_email']),
'exists' => true
];
}
if ($assign['saved_anon']['exists'] == false && !empty($row['anon_key']) && $row['anon_key'] == $anon_key) {
$assign['saved_anon'] = [
'name' => stripslashes($row['comment_author_name']),
'email' => stripslashes($row['comment_author_email']),
'exists' => true
];
}
// Аватар
if (isset($row['comment_author_id']) && $row['comment_author_id'] > 0) {
$row['avatar'] = getAvatar($row['comment_author_id'], 48);
} else {
$row['avatar'] = '';
}
// Получаем аватар через стандартную функцию системы
if (isset($row['comment_author_id']) && $row['comment_author_id'] > 0)
{
$row['avatar'] = getAvatar($row['comment_author_id'], 48);
}
else
{
$row['avatar'] = '';
}
if (!empty($row['avatar']) && strpos($row['avatar'], 'user.png') !== false) {
$row['avatar'] = '';
}
// Если функция вернула системную заглушку, считаем, что аватара нет
if (!empty($row['avatar']) && strpos($row['avatar'], 'user.png') !== false)
{
$row['avatar'] = '';
}
if (empty($row['avatar'])) {
$name = !empty($row['comment_author_name']) ? stripslashes($row['comment_author_name']) : 'Guest';
$row['first_letter'] = mb_substr(trim($name), 0, 1, 'UTF-8');
$row['avatar_color_index'] = (abs(crc32($name)) % 12) + 1;
}
// Если аватара нет (пусто или мы его обнулили выше)
if (empty($row['avatar']))
{
// Берем имя автора (если пусто — 'Guest')
$name = !empty($row['comment_author_name']) ? stripslashes($row['comment_author_name']) : 'Guest';
// Получаем первую букву имени (в верхнем регистре)
$row['first_letter'] = mb_substr(trim($name), 0, 1, 'UTF-8');
// Вычисляем индекс цвета (от 1 до 8) на основе имени
$row['avatar_color_index'] = (abs(crc32($name)) % 12) + 1;
}
// --- ТАЙМЕР И ПРАВА (УЧЕТ АДМИНА) ---
// --- ТАЙМЕР И ПРАВА ---
$row['can_edit'] = 0;
$is_admin = ($user_group === 1);
// Проверяем авторство
$is_author = ($current_user_id > 0 && $current_user_id == $row['comment_author_id']) ||
($row['comment_author_id'] == 0 && !empty($row['anon_key']) && $row['anon_key'] == $anon_key);
if ($is_admin) {
$row['can_edit'] = 1;
// Для админа таймер не нужен, ставим 0, чтобы JS его игнорировал
$row['edit_time_left'] = 0;
} else {
// Рассчитываем остаток времени только для простых смертных
$elapsed = $now - (int)$row['comment_published'];
$time_left = $conf_limit - $elapsed;
$row['edit_time_left'] = ($time_left > 0) ? $time_left : 0;
@@ -426,22 +409,20 @@ else
}
$row['is_my_own'] = $is_author;
// --- Получаем историю имен для анонима ---
$row['past_names'] = [];
if (!empty($row['anon_key'])) {
$row['past_names'] = $this->_getAnonNamesHistory($row['anon_key'], $row['comment_author_name']);
}
// История имен
$row['past_names'] = [];
if (!empty($row['anon_key'])) {
$row['past_names'] = $this->_getAnonNamesHistory($row['anon_key'], $row['comment_author_name']);
}
$row['comment_published_raw'] = $row['comment_published'];
$row['comment_published'] = ave_date_format($date_time_format, $row['comment_published']);
$row['comment_published_raw'] = $row['comment_published'];
$row['comment_published'] = ave_date_format($date_time_format, $row['comment_published']);
// Если время изменения больше 0, тогда форматируем.
// Иначе — ставим 0, чтобы шаблон не выводил плашку.
if ($row['comment_changed'] > 0) {
$row['comment_changed'] = ave_date_format($date_time_format, $row['comment_changed']);
} else {
$row['comment_changed'] = 0;
}
if ($row['comment_changed'] > 0) {
$row['comment_changed'] = ave_date_format($date_time_format, $row['comment_changed']);
} else {
$row['comment_changed'] = 0;
}
$comments[$row['parent_id']][] = $row;
}
@@ -452,25 +433,21 @@ if ($row['comment_changed'] > 0) {
$page_nav = '';
}
// --- НАЧАЛО ВСТАВКИ ДЛЯ AJAX ---
$assign['more_counts'] = [];
// Проверяем, не запросил ли пользователь раскрыть конкретную ветку
$requested_branch = (int)($_REQUEST['ajax_load_branch'] ?? 0);
// --- AJAX ЛИМИТЫ ---
$assign['more_counts'] = [];
$requested_branch = (int)($_REQUEST['ajax_load_branch'] ?? 0);
if ($assign['ajax_replies_limit'] > 0 && !empty($comments)) {
foreach ($comments as $parentId => $subList) {
if ($parentId > 0 && count($subList) > $assign['ajax_replies_limit']) {
// Если это ТА САМАЯ ветка, которую мы подгружаем по AJAX — НЕ обрезаем её
if ($requested_branch == $parentId) {
continue;
if ($assign['ajax_replies_limit'] > 0 && !empty($comments)) {
foreach ($comments as $parentId => $subList) {
if ($parentId > 0 && count($subList) > $assign['ajax_replies_limit']) {
if ($requested_branch == $parentId) {
continue;
}
$assign['more_counts'][$parentId] = count($subList) - $assign['ajax_replies_limit'];
$comments[$parentId] = array_slice($subList, 0, $assign['ajax_replies_limit']);
}
}
$assign['more_counts'][$parentId] = count($subList) - $assign['ajax_replies_limit'];
$comments[$parentId] = array_slice($subList, 0, $assign['ajax_replies_limit']);
}
}
}
$assign['closed'] = @$comments[0][0]['comments_close'];
$assign['comments'] = $comments;

View File

@@ -208,18 +208,44 @@ if ($fileInput.length && $fileInput[0].files.length > 0) {
}
// показать / скрыть комментарий
// показать / скрыть комментарий
if (action === 'unlock' || action === 'lock') {
var $icon = $btn.find('i');
var $card = $btn.closest('.mod_comment_comment');
if (action === 'lock') {
// Статус 0: СКРЫТО. Ставим красный перечеркнутый глаз.
// --- Статус 0: СКРЫТО ---
$icon.attr('class', 'bi bi-eye-slash');
$btn.removeClass('text-success text-muted').addClass('text-danger').attr('title', COMMENT_ICON_SHOW);
$card.addClass('opacity-75 border-warning');
// Ищем плашку. Если её нет — создаем один раз.
var $alert = $card.find('.alert-warning');
if ($alert.length === 0) {
var alertHtml = '<div class="alert alert-warning py-1 px-2 mb-2 small d-flex align-items-center border-0 shadow-sm" style="border-left: 4px solid #ffc107 !important; display:none;">' +
'<i class="bi bi-clock-history me-2 text-dark"></i>' +
'<span class="text-dark">' + COMMENT_WAITING_MODERATION + '</span>' +
'</div>';
$card.find('.flex-grow-1').prepend(alertHtml);
$alert = $card.find('.alert-warning');
}
$alert.stop(true, true).fadeIn(300);
} else {
// Статус 1: ВИДИМО. Ставим зеленый открытый глаз.
// --- Статус 1: ВИДИМО ---
$icon.attr('class', 'bi bi-eye');
$btn.removeClass('text-danger text-muted').addClass('text-success').attr('title', COMMENT_ICON_HIDE);
$card.removeClass('opacity-75 border-warning');
// Надежное скрытие: используем callback, чтобы после анимации точно убрать элемент
$card.find('.alert-warning').stop(true, true).fadeOut(300, function() {
$(this).remove(); // Удаляем плашку из кода совсем, чтобы при следующем "скрыть" она создалась чисто
});
}
}
});
}

View File

@@ -119,6 +119,7 @@ COMMENT_JS_LOADS_F = "Загрузка:"
COMMENT_JS_LOADS_R = "Отправка..."
COMMENT_JS_SEC_CODE_WRONG = "Код капчи введен неверно!"
COMMENT_JS_ERR_SRV = "Ошибка связи с сервером"
COMMENT_WAITING_MODERATION = "Ваш комментарий на проверке и виден пока только вам."

View File

@@ -299,7 +299,7 @@
var COMMENT_JS_LOADS_R = '{#COMMENT_JS_LOADS_R#}';
var COMMENT_JS_SEC_CODE_WRONG = '{#COMMENT_JS_SEC_CODE_WRONG#}';
var COMMENT_JS_ERR_SRV = '{#COMMENT_JS_ERR_SRV#}';
var COMMENT_WAITING_MODERATION = '{#COMMENT_WAITING_MODERATION#}';
var REQ_F1 = '{$comment_req_f1}';
var REQ_F2 = '{$comment_req_f2}';

View File

@@ -1,5 +1,5 @@
{foreach from=$subcomments item=c name=sub_loop}
<div class="card mb-3 mod_comment_comment{if $c.parent_id} ms-2 ms-md-4{/if}"
<div class="card mb-3 mod_comment_comment {if $c.comment_status == 0}opacity-75 border-warning{/if} {if $c.parent_id} ms-2 ms-md-4{/if}"
id="comment_wrapper_{$c.Id}"
data-parent="{$c.parent_id|default:0}"
data-user-rating="{$c.user_rating|default:0}"
@@ -24,6 +24,15 @@
</div>
<div class="flex-grow-1 min-w-0">
{* ПРОВЕРКА НА МОДЕРАЦИЮ ДЛЯ АВТОРА *}
{if $c.comment_status == 0}
<div class="alert alert-warning py-1 px-2 mb-2 small d-flex align-items-center border-0 shadow-sm" style="border-left: 4px solid #ffc107 !important;">
<i class="bi bi-clock-history me-2 text-dark"></i>
<span class="text-dark">
{#COMMENT_WAITING_MODERATION#}
</span>
</div>
{/if}
{* Информация об авторе и дате *}
<div class="mod_comment_meta text-muted small d-flex flex-wrap align-items-center">
<span class="d-flex align-items-center">