сделан вывод комментариев в админке , массовое и обычное удаление
This commit is contained in:
@@ -25,7 +25,13 @@
|
||||
* Два дополнительных поля, их названия и обязательные или нет, настраивааются в Админпанели
|
||||
* Валидация обязательных полей на заполненность + проверка на разрешения для файлов
|
||||
* Комментарий - родитель (ветка комментариев)
|
||||
* Если на комментарий Автора другие Пользователи сделали ответ, то удалить такой комментарий Автору будет невозможно, за исключением Администратора, вместо этого текст комментария будет заменен на текст Комментарий удален автором.
|
||||
* Если на комментарий Автора другие Пользователи сделали ответ, то удалить такой комментарий Автору или Администратору в публичной части сайта будет невозможно, вместо этого будет произведено мягкое удаление - удалится все , что относится к данному комментарию (Рейтинги, файлы , текст) и вместо этого будет выводится специальный аватар и текст: Комментарий удален автором либо Комментарий удален администратором. Восстановить данные такого комментария невозможно.
|
||||
* Удаление комментариев в Админке
|
||||
* Одиночные комментарии (не имеющие ответов) удаляются сразу и навсегда.
|
||||
* Комментарии родители (имеющие ответы/ветку ответов) получают два варианта одиночного удаления:
|
||||
* Мягкое удаление (удалится все , что относится к данному комментарию (Рейтинги, файлы , текст) и вместо этого будет выводится специальный аватар и текст: Комментарий удален администратором. Восстановить данные такого комментария невозможно,
|
||||
* Жесткое удаление самого комментария и всей ветки ответов на этот комментарий. Администратор выбирает сам какой вариант ему необходим.
|
||||
* Массовое удаление - одиночные комментарии удаляются сразу, комментарии-родители удаляются Мягким вариантом (с подстановкой текста Комментарий удален Администратором).
|
||||
* Контроль Имен Анонима
|
||||
* Если Анонимный пользователь, в течении жизни куки, сменит имя под которым он опубликовал свой первый комментарий, рядом с именем появится плашка с тултипом в котором будут перечислены все его имена.
|
||||
* Пагинация
|
||||
|
||||
+62
-27
@@ -1222,33 +1222,68 @@ function commentPostDelete($comment_id)
|
||||
}
|
||||
}
|
||||
|
||||
function commentAdminDelete($comment_id)
|
||||
{
|
||||
global $AVE_DB;
|
||||
function commentAdminDelete($comment_id)
|
||||
{
|
||||
global $AVE_DB;
|
||||
|
||||
// 1. Собираем ID в массив (поддерживаем и одиночное, и массовое удаление)
|
||||
if (is_array($comment_id)) {
|
||||
$ids = array_map('intval', $comment_id);
|
||||
} else {
|
||||
$ids = [(int)$comment_id];
|
||||
}
|
||||
|
||||
if (empty($ids)) return;
|
||||
|
||||
$comment_id = (int)$comment_id; // Убедимся, что это целое число
|
||||
// Читаем тип удаления из запроса (для одиночных кликов по иконкам)
|
||||
// Для массового удаления через кнопку "Применить" этот параметр обычно не передается
|
||||
$delete_type = $_REQUEST['admin_action_type'] ?? 'auto';
|
||||
|
||||
// Выполняем запрос к БД на удаление родительского комментария
|
||||
$AVE_DB->Query("
|
||||
DELETE
|
||||
FROM " . PREFIX . "_module_comment_info
|
||||
WHERE Id = '" . $comment_id . "'
|
||||
");
|
||||
foreach ($ids as $id) {
|
||||
if ($id <= 0) continue;
|
||||
|
||||
// Выполняем запрос к БД на удаление дочерних комментариев (ответов)
|
||||
$AVE_DB->Query("
|
||||
DELETE
|
||||
FROM " . PREFIX . "_module_comment_info
|
||||
WHERE parent_id = '" . $comment_id . "'
|
||||
AND parent_id != 0
|
||||
");
|
||||
|
||||
// Используем оператор объединения с null для PHP 8.4
|
||||
$session_id = SESSION ?? '';
|
||||
|
||||
header('Location:index.php?do=modules&action=modedit&mod=comment&moduleaction=1&cp=' . $session_id);
|
||||
exit;
|
||||
}
|
||||
// Проверяем наличие детей
|
||||
$has_children = $AVE_DB->Query("SELECT COUNT(*) FROM " . PREFIX . "_module_comment_info WHERE parent_id = '$id'")->GetCell();
|
||||
|
||||
// ЛОГИКА СОГЛАСНО ДОГОВОРУ:
|
||||
// Если тип 'soft' ИЛИ (тип 'auto' и есть дети) — делаем мягкое удаление
|
||||
if (($delete_type == 'soft') || ($delete_type == 'auto' && $has_children > 0)) {
|
||||
$AVE_DB->Query("
|
||||
UPDATE " . PREFIX . "_module_comment_info
|
||||
SET comment_text = '__DEL_BY_ADM__',
|
||||
comment_author_name = '__DELETED__',
|
||||
comment_author_id = '0',
|
||||
comment_file = '',
|
||||
comment_status = '1',
|
||||
comment_changed = '" . time() . "'
|
||||
WHERE Id = '$id'
|
||||
");
|
||||
}
|
||||
// Если детей нет или принудительно выбран 'full' — удаляем физически
|
||||
else {
|
||||
// Собираем дерево (на случай если это Full Delete для родителя)
|
||||
$all_tree_ids = [$id];
|
||||
$parents = [$id];
|
||||
while (!empty($parents)) {
|
||||
$p_str = implode(',', $parents);
|
||||
$res = $AVE_DB->Query("SELECT Id FROM " . PREFIX . "_module_comment_info WHERE parent_id IN ($p_str)");
|
||||
$parents = [];
|
||||
if ($res) {
|
||||
while ($r = $res->FetchAssocArray()) {
|
||||
$all_tree_ids[] = (int)$r['Id'];
|
||||
$parents[] = (int)$r['Id'];
|
||||
}
|
||||
}
|
||||
}
|
||||
$final_ids_str = implode(',', array_unique($all_tree_ids));
|
||||
$AVE_DB->Query("DELETE FROM " . PREFIX . "_module_comment_info WHERE Id IN ($final_ids_str)");
|
||||
}
|
||||
}
|
||||
|
||||
$session_id = SESSION ?? '';
|
||||
header("Location: index.php?do=modules&action=modedit&mod=comment&moduleaction=1&cp=" . $session_id);
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Метод, предназначенный для вывода детальной информации об авторе комментария
|
||||
@@ -1396,9 +1431,9 @@ function commentAdminListShow($tpl_dir)
|
||||
case 'set_status_0':
|
||||
$AVE_DB->Query("UPDATE " . PREFIX . "_module_comment_info SET comment_status = '0' WHERE Id IN ($final_id_list)");
|
||||
break;
|
||||
case 'delete':
|
||||
$AVE_DB->Query("DELETE FROM " . PREFIX . "_module_comment_info WHERE Id IN ($final_id_list)");
|
||||
break;
|
||||
//case 'delete':
|
||||
// $AVE_DB->Query("DELETE FROM " . PREFIX . "_module_comment_info WHERE Id IN ($final_id_list)");
|
||||
//break;
|
||||
}
|
||||
header("Location: index.php?do=modules&action=modedit&mod=comment&moduleaction=1&cp=" . $session_id);
|
||||
exit;
|
||||
|
||||
+4
-1
@@ -215,4 +215,7 @@ COMMENT_SET_MAIN_TAG = "Основной тег (выводит форму
|
||||
COMMENT_SET_ADDIT_TAG = "Доп. тег (выводит X последних комментариев):"
|
||||
COMMENT_SET_ADDIT_TAG_NUM = "(X - число выводимых комментариев)"
|
||||
COMMENT_SET_COPY = "Скопировать в буфер обмена"
|
||||
COMMENT_SET_GEN = "Общие настройки"
|
||||
COMMENT_SET_GEN = "Общие настройки"
|
||||
COMMENT_TEXT_DEL_BY_ADMIN = "Комментарий удален администратором."
|
||||
COMMENT_TEXT_DEL_BY_AUTHOR = "Комментарий удален автором."
|
||||
COMMENT_STATUS_DELETED = "Удалено"
|
||||
|
||||
+5
-4
@@ -171,10 +171,11 @@ if (defined('ACP') && !empty($_REQUEST['moduleaction']))
|
||||
|
||||
$comment->commentAdminSettingsEdit($tpl_dir);
|
||||
break;
|
||||
case 'admin_del':
|
||||
$comment->commentAdminDelete((int)$_REQUEST['Id']);
|
||||
break;
|
||||
}
|
||||
case 'admin_del':
|
||||
$comment_id = $_REQUEST['id'] ?? $_REQUEST['Id'];
|
||||
$comment->commentAdminDelete($comment_id);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
+267
-151
@@ -1,32 +1,18 @@
|
||||
<style>
|
||||
/* Глобальный шрифт 13px */
|
||||
/* Глобальные шрифты */
|
||||
.tableStatic, .tableStatic tbody td, .author-data-container,
|
||||
.meta-sub-text, .comment-scroll-box, .cell-top-bar a,
|
||||
.cell-top-bar span, .asset-name, #mass_action_select{
|
||||
.cell-top-bar span, .asset-name, #mass_action_select {
|
||||
font-size: 13px !important;
|
||||
}
|
||||
|
||||
|
||||
.blueBtn {
|
||||
font-size: 11px !important;
|
||||
padding: 2px 10px !important; /* Уменьшаем вертикальный отступ */
|
||||
height: 28px !important; /* Фиксируем высоту, чтобы она не прыгала */
|
||||
line-height: 24px !important; /* Центрируем текст по вертикали */
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
/* Верстка таблицы */
|
||||
.tableStatic tbody td { vertical-align: top !important; padding: 8px 10px !important; }
|
||||
|
||||
/* КОЛОНКА АВТОРА */
|
||||
.author-column { width: 240px !important; min-width: 240px; position: relative; }
|
||||
.author-data-container { display: flex; flex-direction: column; gap: 8px; }
|
||||
.author-info-row { display: flex; align-items: center; gap: 12px; }
|
||||
/* Компактная строка */
|
||||
.tableStatic tbody td { vertical-align: middle !important; padding: 4px 10px !important; }
|
||||
|
||||
/* АВАТАР */
|
||||
.admin-avatar-box { width: 45px; height: 45px; flex-shrink: 0; }
|
||||
.admin-avatar-box img { width: 45px; height: 45px; border-radius: 50%; object-fit: cover; border: 1px solid #ddd; }
|
||||
.mod_comment_avatar_letter { width: 45px; height: 45px; border-radius: 50%; display: flex; align-items: center; justify-content: center; font-weight: bold; color: #fff; text-transform: uppercase; font-size: 18px !important; }
|
||||
.admin-avatar-box { width: 34px; height: 34px; flex-shrink: 0; }
|
||||
.admin-avatar-box img { width: 34px; height: 34px; border-radius: 50%; object-fit: cover; border: 1px solid #ddd; }
|
||||
.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; }
|
||||
@@ -35,39 +21,115 @@
|
||||
.av-c7 { background-color: #d63031; } .av-c8 { background-color: #636e72; }
|
||||
.av-c9 { background-color: #fdcb6e; } .av-c10 { background-color: #fd79a8; }
|
||||
|
||||
/* ЗВЕЗДЫ РЕЙТИНГА АВТОРА (Screenshot_13) */
|
||||
.author-stars { color: #ff9800; font-size: 16px; letter-spacing: 0px; margin: 2px 0; line-height: 1; }
|
||||
/* ЗВЕЗДЫ РЕЙТИНГА АВТОРА (справа от имени) */
|
||||
.author-stars { color: #ff9800; font-size: 14px; letter-spacing: 0px; display: inline-block; margin-left: 8px; }
|
||||
.star-grey { color: #ccc !important; }
|
||||
|
||||
/* Мета-данные */
|
||||
.meta-sub-text { color: #666; line-height: 1.6; }
|
||||
.meta-ip { color: #999; }
|
||||
.meta-edit { color: #d35400; font-weight: bold; background: #fff5e6; padding: 0 4px; border-radius: 3px; display: inline-block; }
|
||||
|
||||
/* Контент комментария */
|
||||
.comment-scroll-box { max-height: 200px; overflow-y: auto; line-height: 1.6; color: #333; margin: 10px 0; padding-right: 10px; }
|
||||
|
||||
/* Зебра и Hover */
|
||||
.row-odd { background-color: #ffffff !important; }
|
||||
.row-even { background-color: #f1f6fa !important; }
|
||||
.status-badge { font-size: 10px; padding: 1px 4px; border-radius: 3px; font-weight: bold; text-transform: uppercase; border: 1px solid; }
|
||||
.bg-del-adm { background: #ffebee; color: #c62828; border-color: #ffcdd2; }
|
||||
.bg-del-aut { background: #f5f5f5; color: #757575; border-color: #e0e0e0; font-style: italic; }
|
||||
.row-hidden { background-color: #fff4f4 !important; }
|
||||
.tableStatic tbody tr:hover td { background-color: #edf3f7 !important; transition: background 0.1s ease; }
|
||||
|
||||
/* Линия вложенности (Screenshot_14) */
|
||||
.reply-wrapper { border-left: 3px solid #3498db; padding-left: 15px; position: relative; }
|
||||
/* Контейнер для веера */
|
||||
.files-bundle {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
height: 34px;
|
||||
}
|
||||
|
||||
/* Панели */
|
||||
.cell-top-bar { display: flex; align-items: center; gap: 12px; border-bottom: 1px dashed #ddd; padding-bottom: 8px; }
|
||||
.cell-top-bar > div:last-child { margin-left: auto !important; }
|
||||
.public-rating-row { display: flex; align-items: center; gap: 8px; margin-top: 10px; border-top: 1px solid #f0f0f0; padding-top: 8px; }
|
||||
.star-public { color: #FFD700; font-size: 14px; }
|
||||
/* Базовый стиль для миниатюр в стопке */
|
||||
.thumb-stack {
|
||||
width: 28px;
|
||||
height: 28px;
|
||||
border: 2px solid #fff;
|
||||
border-radius: 4px;
|
||||
object-fit: cover;
|
||||
box-shadow: 0 1px 3px rgba(0,0,0,0.2);
|
||||
margin-left: -15px; /* Наложение картинок друг на друга */
|
||||
transition: all 0.2s ease;
|
||||
cursor: pointer;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
/* Первая картинка в стопке без отступа */
|
||||
.thumb-stack:first-child { margin-left: 0; }
|
||||
|
||||
/* Эффект при наведении на конкретную картинку */
|
||||
.thumb-stack:hover {
|
||||
transform: scale(4.5);
|
||||
z-index: 999;
|
||||
margin: 0 40px; /* Раздвигаем соседей, чтобы не перекрывали зум */
|
||||
box-shadow: 0 5px 15px rgba(0,0,0,0.5);
|
||||
}
|
||||
|
||||
/* Иконка файла в стиле стопки */
|
||||
.file-stack {
|
||||
width: 28px; height: 28px; background: #f8f9fa;
|
||||
display: flex; align-items: center; justify-content: center;
|
||||
font-size: 8px; font-weight: bold; border: 2px solid #fff;
|
||||
border-radius: 4px; color: #555; box-shadow: 0 1px 3px rgba(0,0,0,0.2);
|
||||
margin-left: -15px; transition: all 0.2s ease;
|
||||
}
|
||||
.file-stack:hover { transform: scale(1.5); z-index: 100; }
|
||||
|
||||
/* Стиль индикатора статуса */
|
||||
/* Базовый стиль кружка */
|
||||
.status-dot {
|
||||
width: 10px;
|
||||
height: 10px;
|
||||
border-radius: 50%;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
/* Зеленый - просто светится */
|
||||
.dot-active {
|
||||
background-color: #2ecc71;
|
||||
box-shadow: 0 0 6px #2ecc71;
|
||||
}
|
||||
|
||||
/* Красный - ПУЛЬСИРУЕТ */
|
||||
.dot-hidden {
|
||||
background-color: #e74c3c;
|
||||
animation: pulse-red 1.5s infinite;
|
||||
}
|
||||
|
||||
/* Эффект пульсации */
|
||||
@keyframes pulse-red {
|
||||
0% {
|
||||
transform: scale(0.95);
|
||||
box-shadow: 0 0 0 0 rgba(231, 76, 60, 0.7);
|
||||
}
|
||||
70% {
|
||||
transform: scale(1);
|
||||
box-shadow: 0 0 0 10px rgba(231, 76, 60, 0);
|
||||
}
|
||||
100% {
|
||||
transform: scale(0.95);
|
||||
box-shadow: 0 0 0 0 rgba(231, 76, 60, 0);
|
||||
}
|
||||
}
|
||||
|
||||
/* Стиль для аватара удаленного пользователя */
|
||||
.avatar-deleted {
|
||||
background-color: #bdc3c7 !important; /* Серый цвет */
|
||||
color: #fff !important;
|
||||
font-size: 18px !important;
|
||||
}
|
||||
|
||||
/* Плашки для текста удаленных комментариев */
|
||||
.comment-deleted-info {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
padding: 4px 10px;
|
||||
border-radius: 4px;
|
||||
font-size: 12px;
|
||||
font-weight: 500;
|
||||
gap: 6px;
|
||||
}
|
||||
.del-adm { background: #fff5f5; color: #c0392b; border: 1px solid #fadbd8; }
|
||||
.del-aut { background: #f8f9fa; color: #7f8c8d; border: 1px solid #e5e8e8; font-style: italic; }
|
||||
|
||||
/* Файлы */
|
||||
.comment-assets-inline { display: flex; flex-wrap: wrap; gap: 15px; margin: 12px 0; }
|
||||
.asset-item { width: 90px; text-align: center; }
|
||||
.asset-thumb { width: 90px; height: 70px; border: 1px solid #ccc; border-radius: 5px; background: #fff; display: flex; align-items: center; justify-content: center; overflow: hidden; }
|
||||
.asset-thumb img { width: 100%; height: 100%; object-fit: cover; }
|
||||
.asset-name { display: block; width: 90px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; text-align: center; font-size: 12px !important; color: #555; margin-top: 4px; }
|
||||
</style>
|
||||
|
||||
<div class="title"><h5>{#COMMENT_MODULE_NAME#} (Всего: {$docs|count})</h5></div>
|
||||
@@ -81,125 +143,157 @@
|
||||
<table cellpadding="0" cellspacing="0" width="100%" class="tableStatic">
|
||||
<thead>
|
||||
<tr>
|
||||
<td width="40"><input type="checkbox" id="selectAll" onclick="checkAll(this)" /></td>
|
||||
<td width="50">ID</td>
|
||||
<td class="author-column">Данные Автора</td>
|
||||
<td>Текст комментария и файлы</td>
|
||||
<td width="30"><input type="checkbox" id="selectAll" onclick="checkAll(this)" /></td>
|
||||
<td width="40">ID</td>
|
||||
<td width="30">Статус</td>
|
||||
<td width="220">Автор и Рейтинг</td>
|
||||
<td width="110">IP адрес</td>
|
||||
<td width="130">Дата Создания / Редактирования</td>
|
||||
<td>Текст комментария</td>
|
||||
<td width="100">Файлы</td>
|
||||
<td width="140" align="right">Действия</td>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{if $docs}
|
||||
{foreach from=$docs item=row name=zebraloop}
|
||||
<tr class="{if $row.comment_status == '0'}row-hidden{elseif $smarty.foreach.zebraloop.iteration % 2 == 0}row-even{else}row-odd{/if}">
|
||||
{assign var="is_deleted" value=false}
|
||||
{if $row.comment_author_name == '__DELETED__' || $row.comment_author_name == 'Удалено'}{assign var="is_deleted" value=true}{/if}
|
||||
|
||||
|
||||
<tr class="{if $row.comment_status == '0'}row-hidden deleted-row{elseif $smarty.foreach.zebraloop.iteration % 2 == 0}row-even{else}row-odd{/if}">
|
||||
<td align="center"><input class="row-checkbox" type="checkbox" value="{$row.CId}" /></td>
|
||||
<td align="center"><strong>{$row.CId}</strong></td>
|
||||
<td align="center">
|
||||
{if $row.comment_status == '1'}
|
||||
<span class="status-dot dot-active" title="Активен"></span>
|
||||
{else}
|
||||
<span class="status-dot dot-hidden" title="Скрыт"></span>
|
||||
{/if}
|
||||
</td>
|
||||
|
||||
<td class="author-column">
|
||||
<div class="author-data-container" style="margin-left: {$row.depth_level * 25}px;">
|
||||
<div class="author-info-row">
|
||||
<div class="admin-avatar-box">
|
||||
{if $row.avatar}<img src="{$row.avatar}">{else}
|
||||
<div class="mod_comment_avatar_letter av-c{$row.avatar_color_index}">{$row.first_letter}</div>{/if}
|
||||
</div>
|
||||
<span style="font-weight:bold; color:#2c3e50;">{$row.comment_author_name|escape}</span>
|
||||
</div>
|
||||
<div class="meta-sub-text">
|
||||
<div class="author-stars">
|
||||
{section name=s start=1 loop=6}{if $smarty.section.s.index <= $row.user_rating}★{else}<span class="star-grey">★</span>{/if}{/section}
|
||||
</div>
|
||||
<div>📅 {$row.date_pub}</div>
|
||||
{if $row.date_edit}<div class="meta-edit">📝 ред. {$row.date_edit}</div>{/if}
|
||||
<div class="meta-ip">🌐 {$row.comment_author_ip}</div>
|
||||
</div>
|
||||
<td>
|
||||
<div style="display: flex; align-items: center; gap: 10px;">
|
||||
<div class="admin-avatar-box">
|
||||
{if $is_deleted}
|
||||
<div class="mod_comment_avatar_letter avatar-deleted">?</div>
|
||||
{else}
|
||||
{if $row.avatar}<img src="{$row.avatar}">{else}
|
||||
<div class="mod_comment_avatar_letter av-c{$row.avatar_color_index}">{$row.first_letter}</div>{/if}
|
||||
{/if}
|
||||
</div>
|
||||
<div style="white-space: nowrap;">
|
||||
<span style="font-weight:bold; color:{if $is_deleted}#95a5a6{else}#2c3e50{/if};">
|
||||
{if $is_deleted}Пользователь удален{else}{$row.comment_author_name|escape}{/if}
|
||||
</span>
|
||||
{if !$is_deleted}
|
||||
<span class="author-stars">
|
||||
{section name=s start=1 loop=6}{if $smarty.section.s.index <= $row.user_rating}★{else}<span class="star-grey">★</span>{/if}{/section}
|
||||
</span>
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
<td align="center" style="color:#666; font-family:monospace;">
|
||||
<div style="color:#999; font-size:11px; line-height:1.2; font-family:monospace;">{$row.comment_author_ip}</div>
|
||||
</td>
|
||||
<td>
|
||||
<div style="font-size:11px; line-height:1.2;">
|
||||
<div>{$row.date_pub}</div>
|
||||
{if $row.date_edit}
|
||||
<div style="color:#d35400;">ред. {$row.date_edit}</div>
|
||||
{/if}
|
||||
</div>
|
||||
</td>
|
||||
|
||||
<td>
|
||||
<div class="{if $row.depth_level > 0}reply-wrapper{/if}" style="margin-left: {$row.depth_level * 25}px;">
|
||||
<div class="cell-top-bar">
|
||||
{if $row.parent_id > 0}
|
||||
<span style="background:#e1f5fe; color:#0288d1; padding:2px 8px; border-radius:3px; font-weight:bold; font-size: 10px !important;">ОТВЕТ НА #{$row.parent_id}</span>
|
||||
{/if}
|
||||
<a href="{$ABS_PATH}index.php?id={$row.document_id}" target="_blank" style="color:#2980b9; font-weight:bold; text-decoration:underline;">
|
||||
{$row.document_title|default:"Документ"|truncate:35}
|
||||
</a>
|
||||
<a href="{$ABS_PATH}index.php?id={$row.document_id}#comment-{$row.CId}" target="_blank" style="color:#27ae60; font-weight:bold;">[#] Посмотреть</a>
|
||||
|
||||
<div style="display: flex; gap: 8px; align-items: center; border-left: 1px solid #ddd; padding-left: 10px;">
|
||||
<span style="font-weight:bold; color:{if $row.comment_status=='1'}#27ae60{else}#e74c3c{/if};">
|
||||
{if $row.comment_status=='1'}Одобрен{else}Скрыт{/if}
|
||||
</span>
|
||||
|
||||
{if $row.comment_status == '1'}
|
||||
<a class="icon_sprite ico_unlock_no" title="Скрыть" href="index.php?do=modules&action=modedit&mod=comment&moduleaction=1&admin_action=set_status_0&id={$row.CId}&cp={$sess}"></a>
|
||||
<td>
|
||||
<div style="display: flex; flex-direction: column; gap: 4px;">
|
||||
<div style="margin-bottom: 2px;">
|
||||
<a href="index.php?id={$row.document_id}" target="_blank" style="color:#2980b9; font-weight:bold; text-decoration:none; border-bottom: 1px solid #d1d1d1; font-size: 12px;">
|
||||
{$row.document_title|default:"Документ #`$row.document_id`"}
|
||||
</a>
|
||||
</div>
|
||||
<div style="display: flex; align-items: center; gap: 8px;">
|
||||
{if $row.parent_id > 0}
|
||||
<span style="background:#e1f5fe; color:#0288d1; padding:1px 5px; border-radius:3px; font-weight:bold; font-size: 10px !important;">Ответ на комментарий #{$row.parent_id} »</span>
|
||||
{/if}
|
||||
<div class="comment-text-cell">
|
||||
{if $row.comment_text == '__DEL_BY_ADM__'}
|
||||
<div class="comment-deleted-info del-adm">
|
||||
<span style="font-size:14px;">🚫</span> Комментарий удален администратором
|
||||
</div>
|
||||
{elseif $row.comment_text == '__DEL_BY_AUT__'}
|
||||
<div class="comment-deleted-info del-aut">
|
||||
<span style="font-size:14px;">🗑️</span> Автор удалил свой комментарий
|
||||
</div>
|
||||
{else}
|
||||
<a class="icon_sprite ico_unlock" title="Одобрить" href="index.php?do=modules&action=modedit&mod=comment&moduleaction=1&admin_action=set_status_1&id={$row.CId}&cp={$sess}"></a>
|
||||
{/if}
|
||||
|
||||
<a class="icon_sprite ico_edit" title="Редактировать" href="javascript:void(0);" onClick="windowOpen('index.php?do=modules&action=modedit&mod=comment&moduleaction=admin_edit&pop=1&docid={$row.document_id}&Id={$row.CId}','700','700','1');"></a>
|
||||
|
||||
<a class="icon_sprite ico_delete ConfirmDelete"
|
||||
title="{if $row.has_children}Удалить только этот текст (сохранить ветку){else}Удалить физически{/if}"
|
||||
href="index.php?do=modules&action=modedit&mod=comment&moduleaction=1&admin_action=delete&admin_action_type=soft&id={$row.CId}&cp={$sess}"></a>
|
||||
|
||||
{if $row.has_children}
|
||||
<a class="icon_sprite ico_delete ico_delete_all ConfirmDelete"
|
||||
title="УДАЛИТЬ ВСЮ ВЕТКУ ФИЗИЧЕСКИ (вместе с ответами)"
|
||||
href="index.php?do=modules&action=modedit&mod=comment&moduleaction=1&admin_action=delete&admin_action_type=full&id={$row.CId}&cp={$sess}"></a>
|
||||
{$row.comment_text|strip_tags|truncate:130}
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
|
||||
<div class="comment-scroll-box">{$row.comment_text|nl2br}</div>
|
||||
<td align="center">
|
||||
<div class="files-bundle">
|
||||
{if $row.images}
|
||||
{foreach from=$row.images item=img name=img_loop}
|
||||
{if $smarty.foreach.img_loop.iteration < 5} {* Показываем максимум 4 превью в стопке *}
|
||||
<a href="{$ABS_PATH}uploads/comments/{$img.orig_name}" target="_blank" style="text-decoration:none;">
|
||||
<img src="{$ABS_PATH}uploads/comments/{$img.orig_name}" class="thumb-stack" title="{$img.clean_name}">
|
||||
</a>
|
||||
{/if}
|
||||
{/foreach}
|
||||
{if $row.images|count >= 5}
|
||||
<span style="font-size:10px; color:#999; margin-left:5px;">+{$row.images|count - 4}</span>
|
||||
{/if}
|
||||
{/if}
|
||||
|
||||
{if $row.files}
|
||||
{foreach from=$row.files item=f}
|
||||
<a href="{$ABS_PATH}uploads/comments/{$f.orig_name}" target="_blank" class="file-stack" title="{$f.clean_name}">
|
||||
{$f.ext|upper}
|
||||
</a>
|
||||
{/foreach}
|
||||
{/if}
|
||||
</div>
|
||||
</td>
|
||||
|
||||
{if $row.images || $row.files}
|
||||
<div class="comment-assets-inline">
|
||||
{foreach from=$row.images item=img}
|
||||
<div class="asset-item">
|
||||
<div class="asset-thumb">
|
||||
<a href="{$ABS_PATH}uploads/comments/{$img.orig_name}" class="view fancy" rel="gallery-{$row.CId}">
|
||||
<img src="{$ABS_PATH}uploads/comments/{$img.orig_name}" />
|
||||
</a>
|
||||
</div>
|
||||
<span class="asset-name" title="{$img.clean_name}">{$img.clean_name|truncate:15:"...":true}</span>
|
||||
</div>
|
||||
{/foreach}
|
||||
{foreach from=$row.files item=f}
|
||||
<div class="asset-item">
|
||||
<a href="{$ABS_PATH}uploads/comments/{$f.orig_name}" target="_blank" class="asset-thumb" style="flex-direction: column; text-decoration:none; background:#f9f9f9;">
|
||||
<span style="font-weight: bold; color: #2980b9;">{$f.ext|upper}</span>
|
||||
</a>
|
||||
<span class="asset-name" title="{$f.clean_name}">{$f.clean_name|truncate:15:"...":true}</span>
|
||||
</div>
|
||||
{/foreach}
|
||||
</div>
|
||||
<td align="right">
|
||||
<div style="display: flex; justify-content: flex-end; gap: 6px;">
|
||||
{if !$is_deleted}
|
||||
{if $row.comment_status == '1'}
|
||||
<a class="icon_sprite ico_unlock_no" title="Скрыть" href="index.php?do=modules&action=modedit&mod=comment&moduleaction=1&admin_action=set_status_0&id={$row.CId}&cp={$sess}"></a>
|
||||
{else}
|
||||
<a class="icon_sprite ico_unlock" title="Одобрить" href="index.php?do=modules&action=modedit&mod=comment&moduleaction=1&admin_action=set_status_1&id={$row.CId}&cp={$sess}"></a>
|
||||
{/if}
|
||||
<a class="icon_sprite ico_edit" title="Редактировать" href="javascript:void(0);" onClick="windowOpen('index.php?do=modules&action=modedit&mod=comment&moduleaction=admin_edit&pop=1&docid={$row.document_id}&Id={$row.CId}','700','700','1');"></a>
|
||||
{if $row.has_children}
|
||||
<a class="icon_sprite ico_delete ConfirmDelete" title="Скрыть текст (сохранить ветку)"
|
||||
href="index.php?do=modules&action=modedit&mod=comment&moduleaction=admin_del&admin_action_type=soft&Id={$row.CId}&cp={$sess}"></a>
|
||||
{/if}
|
||||
{/if}
|
||||
|
||||
<div class="public-rating-row">
|
||||
<div class="star-public">
|
||||
{section name=s start=1 loop=6}{if $smarty.section.s.index <= $row.star_public}★{else}<span class="star-grey">☆</span>{/if}{/section}
|
||||
</div>
|
||||
<span style="color:#999;">(Голосов: {$row.r_count|default:0})</span>
|
||||
</div>
|
||||
<a class="icon_sprite ico_delete ico_delete_all ConfirmDelete" title="УДАЛИТЬ ПОЛНОСТЬЮ"
|
||||
href="index.php?do=modules&action=modedit&mod=comment&moduleaction=admin_del&admin_action_type=full&Id={$row.CId}&cp={$sess}"></a>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
{/foreach}
|
||||
{else}
|
||||
<tr>
|
||||
<td colspan="4">
|
||||
<ul class="messages">
|
||||
<li class="highlight yellow"><strong>Сообщение:</strong><br />Нет комментариев.</li>
|
||||
</ul>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="9">
|
||||
<ul class="messages">
|
||||
<li class="highlight yellow"><strong>Сообщение:</strong><br />Нет комментариев.</li>
|
||||
</ul>
|
||||
</td>
|
||||
</tr>
|
||||
{/if}
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<div class="tfoot">
|
||||
<div class="left" style="padding:15px;">
|
||||
<select id="mass_action_select" style="padding:5px;">
|
||||
<select id="mass_action_select">
|
||||
<option value="">Выберите действие...</option>
|
||||
<option value="set_status_1">Опубликовать</option>
|
||||
<option value="set_status_0">Скрыть</option>
|
||||
@@ -211,11 +305,7 @@
|
||||
</div>
|
||||
|
||||
{if $page_nav}
|
||||
<div class="pagination">
|
||||
<ul class="pages">
|
||||
{$page_nav}
|
||||
</ul>
|
||||
</div>
|
||||
<div class="pagination"><ul class="pages">{$page_nav}</ul></div>
|
||||
{/if}
|
||||
|
||||
<script type="text/javascript">
|
||||
@@ -223,16 +313,42 @@ function checkAll(master) {
|
||||
var checkboxes = document.getElementsByClassName('row-checkbox');
|
||||
for (var i = 0; i < checkboxes.length; i++) { checkboxes[i].checked = master.checked; }
|
||||
}
|
||||
|
||||
function runMassAction() {
|
||||
var action = document.getElementById('mass_action_select').value;
|
||||
if (!action) { jAlert('Выберите действие!', 'Внимание'); return; }
|
||||
var select = document.getElementById('mass_action_select');
|
||||
var action = select.value;
|
||||
|
||||
// Красивое уведомление, если не выбрали действие
|
||||
if (!action) {
|
||||
jAlert('Выберите действие из списка!', 'Внимание');
|
||||
return;
|
||||
}
|
||||
|
||||
var checkboxes = document.getElementsByClassName('row-checkbox');
|
||||
var ids = [];
|
||||
for (var i = 0; i < checkboxes.length; i++) { if (checkboxes[i].checked) ids.push(checkboxes[i].value); }
|
||||
if (ids.length === 0) { jAlert('Ничего не выбрано!', 'Ошибка'); return; }
|
||||
var url = 'index.php?do=modules&action=modedit&mod=comment&moduleaction=1&admin_action=' + action + '&ids=' + ids.join(',') + '&cp={$sess}';
|
||||
for (var i = 0; i < checkboxes.length; i++) {
|
||||
if (checkboxes[i].checked) ids.push(checkboxes[i].value);
|
||||
}
|
||||
|
||||
// Красивое уведомление, если не выбрали чекбоксы
|
||||
if (ids.length === 0) {
|
||||
jAlert('Вы не выбрали ни одного комментария для обработки.', 'Ошибка');
|
||||
return;
|
||||
}
|
||||
|
||||
var cp = '{$sess}';
|
||||
var url = '';
|
||||
|
||||
if (action === 'delete') {
|
||||
jConfirm('Удалить выбранные элементы?', 'Подтверждение', function(r) { if(r) window.location.href = url; });
|
||||
} else { window.location.href = url; }
|
||||
var idParams = ids.map(function(id) { return 'id[]=' + id; }).join('&');
|
||||
url = 'index.php?do=modules&action=modedit&mod=comment&moduleaction=admin_del&' + idParams + '&cp=' + cp;
|
||||
} else {
|
||||
url = 'index.php?do=modules&action=modedit&mod=comment&moduleaction=1&admin_action=' + action + '&ids=' + ids.join(',') + '&cp=' + cp;
|
||||
}
|
||||
|
||||
// Красивое подтверждение
|
||||
jConfirm('Выполнить выбранное действие для ' + ids.length + ' эл.?', 'Подтверждение', function(r) {
|
||||
if(r) window.location.href = url;
|
||||
});
|
||||
}
|
||||
</script>
|
||||
Reference in New Issue
Block a user