diff --git a/class/comment.php b/class/comment.php index a8aca97..8b98e1e 100644 --- a/class/comment.php +++ b/class/comment.php @@ -1278,7 +1278,24 @@ function commentAdminDelete($comment_id) } $session_id = SESSION ?? ''; - header("Location: index.php?do=modules&action=modedit&mod=comment&moduleaction=1&cp=" . $session_id); + // --- Сохраняем состояние фильтров --- + $s_query = $_REQUEST['search_query'] ?? ''; + $s_order = $_REQUEST['sort_order'] ?? 'new'; + $f_type = $_REQUEST['filter_type'] ?? ''; + $v_mode = $_REQUEST['view_mode'] ?? 'flat'; + $p_page = $_REQUEST['per_page'] ?? '15'; + $d_from = $_REQUEST['date_from'] ?? ''; + $d_to = $_REQUEST['date_to'] ?? ''; + + header("Location: index.php?do=modules&action=modedit&mod=comment&moduleaction=1" . + "&cp=" . $session_id . + "&search_query=" . urlencode($s_query) . + "&sort_order=" . $s_order . + "&filter_type=" . $f_type . + "&view_mode=" . $v_mode . + "&per_page=" . $p_page . + "&date_from=" . $d_from . + "&date_to=" . $d_to); exit; } @@ -1479,26 +1496,96 @@ function commentAdminListShow($tpl_dir) break; } - header("Location: index.php?do=modules&action=modedit&mod=comment&moduleaction=1&cp=" . $session_id); + // 1. Сначала вытаскиваем текущие настройки из запроса + $s_query = $_GET['search_query'] ?? ''; + $s_order = $_GET['sort_order'] ?? 'new'; + $f_type = $_GET['filter_type'] ?? ''; + $v_mode = $_GET['view_mode'] ?? 'flat'; + $p_page = $_GET['per_page'] ?? '15'; + $d_from = $_GET['date_from'] ?? ''; + $d_to = $_GET['date_to'] ?? ''; + + // 2. Формируем строку возврата (редирект), чтобы настройки НЕ СЛЕТЕЛИ + header("Location: index.php?do=modules&action=modedit&mod=comment&moduleaction=1" . + "&cp=" . $session_id . + "&search_query=" . urlencode($s_query) . + "&sort_order=" . $s_order . + "&filter_type=" . $f_type . + "&view_mode=" . $v_mode . + "&per_page=" . $p_page . + "&date_from=" . $d_from . + "&date_to=" . $d_to); exit; } - // --- ЛОГИКА ВЫВОДА (С ПАГИНАЦИЕЙ) --- - $num = $AVE_DB->Query("SELECT COUNT(*) FROM " . PREFIX . "_module_comment_info")->GetCell(); - $limit = $this->_limit; + + + + +// --- ПАРАМЕТРЫ ФИЛЬТРАЦИИ --- + $search = $_GET['search_query'] ?? ''; + $sort = $_GET['sort_order'] ?? 'new'; + $filter = $_GET['filter_type'] ?? ''; + $view_mode = $_GET['view_mode'] ?? 'flat'; + $per_page = isset($_GET['per_page']) ? (int)$_GET['per_page'] : 15; + $date_from = $_GET['date_from'] ?? ''; + $date_to = $_GET['date_to'] ?? ''; + + $where = ["1=1"]; + + // Поиск + if ($search) { + $s = $AVE_DB->Escape($search); + $where[] = "(cmnt.comment_author_name LIKE '%$s%' OR cmnt.comment_author_ip LIKE '%$s%' OR cmnt.comment_text LIKE '%$s%')"; + } + + // Даты + if ($date_from) $where[] = "cmnt.comment_published >= " . strtotime($date_from); + if ($date_to) $where[] = "cmnt.comment_published <= " . (strtotime($date_to) + 86399); + + // Спец. фильтры + if ($filter == 'with_files') $where[] = "cmnt.comment_file != ''"; + if ($filter == 'hidden') $where[] = "cmnt.comment_status = '0'"; + + $where_sql = implode(" AND ", $where); + + // Сортировка + switch ($sort) { + case 'old': $order_sql = "cmnt.comment_published ASC"; break; + case 'popular': $order_sql = "cmnt.rating_sum DESC, cmnt.rating_count DESC"; break; + case 'discussed': $order_sql = "(SELECT COUNT(*) FROM " . PREFIX . "_module_comment_info WHERE parent_id = cmnt.Id) DESC"; break; + case 'user_rating': $order_sql = "cmnt.user_rating DESC"; break; + default: $order_sql = "cmnt.comment_published DESC"; break; + } + + // --- ПАГИНАЦИЯ --- + $num = $AVE_DB->Query("SELECT COUNT(*) FROM " . PREFIX . "_module_comment_info AS cmnt WHERE $where_sql")->GetCell(); + $limit = $per_page; $seiten = ceil($num / $limit); - $start = get_current_page() * $limit - $limit; + $page = get_current_page(); + $start = ($page * $limit) - $limit; $sql = $AVE_DB->Query(" SELECT cmnt.*, doc.document_title, doc.document_alias FROM " . PREFIX . "_module_comment_info AS cmnt LEFT JOIN " . PREFIX . "_documents AS doc ON doc.Id = cmnt.document_id - ORDER BY cmnt.comment_published DESC + WHERE $where_sql + ORDER BY $order_sql LIMIT " . (int)$start . "," . (int)$limit ); $all_items = array(); - $format = "%d %B %Y, %H:%M"; + $format = "%d %B %Y, %H:%M"; + + + + +// --- ПЕРЕД ЦИКЛОМ: Получаем список всех скрытых ID в системе --- +$locked_ids = []; +$res_locked = $AVE_DB->Query("SELECT Id FROM " . PREFIX . "_module_comment_info WHERE comment_status = '0'"); +if ($res_locked) { + while ($rl = $res_locked->FetchAssocArray()) { $locked_ids[] = (int)$rl['Id']; } +} while ($row = $sql->FetchAssocArray()) { $name = !empty($row['comment_author_name']) ? stripslashes($row['comment_author_name']) : 'Guest'; @@ -1533,6 +1620,11 @@ function commentAdminListShow($tpl_dir) } $row['CId'] = $row['Id']; + + // ДОБАВЛЯЕМ ПРОВЕРКУ РОДИТЕЛЯ (для линейного вида): + // Если parent_id этого комментария есть в списке скрытых ($locked_ids) + $row['parent_locked'] = (in_array((int)$row['parent_id'], $locked_ids)) ? 1 : 0; + $row['comment_text'] = stripslashes($row['comment_text']); $ts_pub = (int)$row['comment_published']; $row['date_pub'] = ($ts_pub > 0) ? pretty_date(ave_date_format($format, $ts_pub)) : '—'; @@ -1561,6 +1653,10 @@ function commentAdminListShow($tpl_dir) } + + + + // --- ПОСТРОЕНИЕ ДЕРЕВА --- $child_map = []; foreach ($all_items as $id => $item) { @@ -1573,45 +1669,56 @@ function commentAdminListShow($tpl_dir) } unset($item_for_check); - $docs = []; +$docs = []; $processed = []; - // Универсальная функция с наследованием блокировки parent_locked - $buildTree = function($parent_id, $level, $is_parent_hidden) use (&$buildTree, &$docs, &$processed, &$all_items, &$child_map) { - if (isset($child_map[$parent_id])) { - foreach ($child_map[$parent_id] as $child_id) { - if (!in_array($child_id, $processed)) { - $item = $all_items[$child_id]; - $item['depth_level'] = $level; - - // Блокируем ребенка, если скрыт его родитель или кто-то выше по дереву - $item['parent_locked'] = ($is_parent_hidden || $all_items[$parent_id]['comment_status'] == '0') ? 1 : 0; - - $docs[] = $item; - $processed[] = $child_id; - $buildTree($child_id, $level + 1, $item['parent_locked']); + // Если выбран линейный вид — просто выводим список без иерархии +if ($view_mode == 'flat') { + foreach ($all_items as $item) { + $item['depth_level'] = 0; + // Теперь мы берем parent_locked, который вычислили выше + $docs[] = $item; + } +} + // Если вид древовидный — используем твою отлаженную логику + else { + // Универсальная функция с наследованием блокировки parent_locked + $buildTree = function($parent_id, $level, $is_parent_hidden) use (&$buildTree, &$docs, &$processed, &$all_items, &$child_map) { + if (isset($child_map[$parent_id])) { + foreach ($child_map[$parent_id] as $child_id) { + if (!in_array($child_id, $processed)) { + $item = $all_items[$child_id]; + $item['depth_level'] = $level; + + // Блокируем ребенка, если скрыт его родитель или кто-то выше по дереву + $item['parent_locked'] = ($is_parent_hidden || $all_items[$parent_id]['comment_status'] == '0') ? 1 : 0; + + $docs[] = $item; + $processed[] = $child_id; + $buildTree($child_id, $level + 1, $item['parent_locked']); + } } } - } - }; + }; - // Собираем дерево, начиная с корней - foreach ($all_items as $id => $item) { - if ($item['parent_id'] == 0 && !in_array($id, $processed)) { - $item['depth_level'] = 0; - $item['parent_locked'] = 0; - $docs[] = $item; - $processed[] = $id; - $buildTree($id, 1, false); + // Собираем дерево, начиная с корней + foreach ($all_items as $id => $item) { + if ($item['parent_id'] == 0 && !in_array($id, $processed)) { + $item['depth_level'] = 0; + $item['parent_locked'] = 0; + $docs[] = $item; + $processed[] = $id; + $buildTree($id, 1, false); + } } - } - // Добираем то, что не попало в иерархию (битые связи) - foreach ($all_items as $id => $item) { - if (!in_array($id, $processed)) { - $item['depth_level'] = 0; - $item['parent_locked'] = 0; - $docs[] = $item; + // Добираем то, что не попало в иерархию (битые связи) + foreach ($all_items as $id => $item) { + if (!in_array($id, $processed)) { + $item['depth_level'] = 0; + $item['parent_locked'] = 0; + $docs[] = $item; + } } } // --- КОНЕЦ ПОСТРОЕНИЯ ДЕРЕВА --- @@ -1625,15 +1732,25 @@ function commentAdminListShow($tpl_dir) $AVE_Template->assign('comment_rating_type', (int)$comment_rating_type); - $AVE_Template->assign([ - 'docs' => $docs, - 'page_nav' => ($num > $limit) ? get_pagination($seiten, 'page', ' {t} ') : '', - 'sess' => $session_id - ]); +// Собираем все текущие GET-параметры, кроме страницы +$current_params = $_GET; +unset($current_params['page']); +$query_string = http_build_query($current_params); + +$AVE_Template->assign([ + 'docs' => $docs, + 'page_nav' => ($num > $limit) ? get_pagination($seiten, 'page', ' {t} ') : '', + 'sess' => $session_id +]); $AVE_Template->assign('content', $AVE_Template->fetch($tpl_dir . $this->_admin_comments_tpl)); } + + + + + /** * Метод, предназначенный для редактирования комментариев в Административной части. * diff --git a/templates/admin_comments.tpl b/templates/admin_comments.tpl index a6a6848..b45b7ef 100644 --- a/templates/admin_comments.tpl +++ b/templates/admin_comments.tpl @@ -15,11 +15,18 @@ .mod_comment_avatar_letter { width: 34px; height: 34px; border-radius: 50%; display: flex; align-items: center; justify-content: center; font-weight: bold; color: #fff; text-transform: uppercase; font-size: 14px !important; } /* Цвета для букв аватара */ - .av-c1 { background-color: #6c5ce7; } .av-c2 { background-color: #2ecc71; } - .av-c3 { background-color: #e67e22; } .av-c4 { background-color: #e91e63; } - .av-c5 { background-color: #00cec9; } .av-c6 { background-color: #0984e3; } - .av-c7 { background-color: #d63031; } .av-c8 { background-color: #636e72; } - .av-c9 { background-color: #fdcb6e; } .av-c10 { background-color: #fd79a8; } +.av-c1 { background-color: #6c5ce7; } +.av-c2 { background-color: #2ecc71; } +.av-c3 { background-color: #e67e22; } +.av-c4 { background-color: #e91e63; } +.av-c5 { background-color: #00cec9; } +.av-c6 { background-color: #0984e3; } +.av-c7 { background-color: #d63031; } +.av-c8 { background-color: #636e72; } +.av-c9 { background-color: #fdcb6e; } +.av-c10 { background-color: #fd79a8; } +.av-c11 { background-color: #a29bfe; } +.av-c12 { background-color: #273c75; } /* ЗВЕЗДЫ РЕЙТИНГА АВТОРА (справа от имени) */ .author-stars { color: #ff9800; font-size: 14px; letter-spacing: 0px; display: inline-block; margin-left: 8px; } @@ -135,7 +142,91 @@ .comm-stars { color: #f1c40f; font-size: 13px; text-align: center; } .comm-likes { color: #e74c3c; font-size: 13px; font-weight: bold; display: flex; align-items: center; gap: 4px; justify-content: center; } .rating-count-box { font-size: 10px; color: #999; font-weight: normal; margin-top: -2px; } - .bi-heart-fill { font-size: 12px; } + .bi-heart-fill { font-size: 12px; } + +/* Направляющие для дерева ответов */ + .tree-branch { + display: flex; + align-items: center; + align-self: stretch; + position: relative; + } + .branch-line { + border-left: 1px solid #c8d6e5; + border-bottom: 1px solid #c8d6e5; + width: 12px; + height: 14px; + margin-right: 8px; + margin-top: -10px; /* Поднимаем к центру текста */ + flex-shrink: 0; + border-bottom-left-radius: 4px; + } + .depth-1 { margin-left: 15px; } + .depth-2 { margin-left: 30px; } + .depth-3 { margin-left: 45px; } + .depth-4 { margin-left: 60px; } + .depth-5 { margin-left: 75px; } + + /* в линейном виде отступ */ + .depth-0 { margin-left: 0; } + .tree-branch { min-height: 20px; } + +/* элементы выравниваем по центру*/ +.searchLine .grid-container { + display: flex !important; + flex-wrap: wrap; + align-items: center !important; + gap: 15px; +} + +/* Label и Инпут внутри групп стояли рядом */ +.searchLine .form-group { + display: flex !important; + align-items: center !important; + gap: 8px; + margin: 0 !important; +} + +/* Убираем вертикальные отступы у меток, чтобы они не тянули линию вверх */ +.searchLine .form-group label { + margin-bottom: 0 !important; + white-space: nowrap; +} + +/* выравнивание для FormStyler и кнопок */ +.searchLine .jq-selectbox, +.searchLine .jq-selectbox__select, +.searchLine input[type="text"], +.searchLine input[type="date"], +.searchLine .blueBtn, +.searchLine .redBtn { + vertical-align: middle !important; + margin: 0 !important; +} + +/* Кнопки: убираем лишний внешний отступ сверху у контейнера кнопок */ +.searchLine .buttons-container { + margin-top: 0 !important; + display: flex; + gap: 10px; + align-items: center; +} +.searchLine input[type="date"]::-webkit-calendar-picker-indicator { + cursor: pointer !important; + display: block; /* Иногда помогает "проявить" элемент для CSS */ +} +/* Делаем дату максимально похожей на стилизованный Поиск */ +.searchLine input[type="date"] { + border: 1px solid #c5cdd4 !important; + background: #fff url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAAUCAYAAAB9S9CDAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAACpJREFUeNpi/P//PwMTAwMDIwMDEwMDEyMTAyMTEyMTExMTIxMTYyADAgwA7ncD8e89v98AAAAASUVORK5CYII=') repeat-x !important; /* Легкий градиент как у селектов */ + height: 16pt !important; + font-size: 12px !important; + border-radius: 3px !important; + width: 130px; + color: #444444 !important; + font-family: 'Cuprum', sans-serif; + +} @@ -146,7 +237,78 @@
{#COMMENT_MODULE_COMENTS#}
{#COMMENT_MODULE_SETTINGS#}
+{if !empty($docs)} +
+
+ + + + + +
+
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ +
+ {assign var="get_view" value=$smarty.get.view_mode|default:'flat'} + {assign var="get_limit" value=$smarty.get.per_page|default:'15'} + + +
+
+ +
+ +
+ + + +
+
+ +
+ + +
+
+
+
+{/if} @@ -215,29 +377,39 @@ @@ -315,35 +487,40 @@ {else} {* Обычные кнопки, если родитель активен *} {if $row.comment_status == '1'} - + {* ИЗМЕНЕНО: Добавлены параметры в href *} + {else} - + {* ИЗМЕНЕНО: Добавлены параметры в href *} + {/if} {/if} {* --- ОСТАЛЬНЫЕ КНОПКИ ОСТАЮТСЯ ВНУТРИ ПРОВЕРКИ --- *} {if !$is_deleted} + {* ИЗМЕНЕНО: Добавлены параметры в href *} {if $row.has_children} + {* ИЗМЕНЕНО: Добавлены параметры в href *} + href="index.php?do=modules&action=modedit&mod=comment&moduleaction=admin_del&admin_action_type=soft&Id={$row.CId}&cp={$sess}&sort_order={$smarty.get.sort_order|default:'new'}&view_mode={$smarty.get.view_mode|default:'flat'}&filter_type={$smarty.get.filter_type|default:''}&per_page={$smarty.get.per_page|default:'15'}"> {/if} {/if} {* Полное удаление всегда снаружи *} + {* ИЗМЕНЕНО: Добавлены параметры в href *} + href="index.php?do=modules&action=modedit&mod=comment&moduleaction=admin_del&admin_action_type=full&Id={$row.CId}&cp={$sess}&sort_order={$smarty.get.sort_order|default:'new'}&view_mode={$smarty.get.view_mode|default:'flat'}&filter_type={$smarty.get.filter_type|default:''}&per_page={$smarty.get.per_page|default:'15'}"> {/foreach} {else} -
-
+
+ {if $row.depth_level == 0} -
- {if $row.parent_id > 0} - {#COMMENT_ANSWER_ADM#} #{$row.parent_id} » + {/if} +
+ {if $row.depth_level > 0} +
{/if} -
- {if $row.comment_text == '__DEL_BY_ADM__'} -
- 🚫 {#COMMENT_DEL_ADM_ADM#} -
- {elseif $row.comment_text == '__DEL_BY_AUT__'} -
- 🗑️ {#COMMENT_DEL_AVT_ADM#} -
- {else} - {$row.comment_text|strip_tags|truncate:130} - {/if} -
+ +
+ {if $row.parent_id > 0} + #{$row.parent_id} » + {/if} + +
+ {if $row.comment_text == '__DEL_BY_ADM__'} +
+ 🚫 {#COMMENT_DEL_ADM_ADM#} +
+ {elseif $row.comment_text == '__DEL_BY_AUT__'} +
+ 🗑️ {#COMMENT_DEL_AVT_ADM#} +
+ {else} + {$row.comment_text|strip_tags|truncate:130} + {/if} +
+
+
  • {#COMMENT_NOT_COOMENTS_MES#}
    {#COMMENT_NOT_COOMENTS_MES_A#}
@@ -352,7 +529,7 @@ {/if}
- + {if !empty($docs)}
+ {/if} {if $page_nav} @@ -371,6 +549,21 @@ {/if}