добавлено: если используется [mod_comment:X] - X число желаемых последних комментариев на странице, вывод происходит в шаблоне last_comments.tpl
This commit is contained in:
@@ -1629,6 +1629,98 @@ function commentAdminSettingsEdit($tpl_dir)
|
||||
$AVE_Template->assign('content', $AVE_Template->fetch($tpl_dir . $this->_admin_settings_tpl));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Метод для получения последних X комментариев
|
||||
*/
|
||||
function getLatestComments($limit = 10)
|
||||
{
|
||||
global $AVE_DB;
|
||||
|
||||
// 1. Принудительно подключаем CSS
|
||||
$GLOBALS['user_header']['comment_css'] = '<link rel="stylesheet" href="' . ABS_PATH . 'modules/comment/css/mod_comment_styles.css" type="text/css" />';
|
||||
|
||||
$sql = $AVE_DB->Query("
|
||||
SELECT
|
||||
comm.*,
|
||||
doc.document_title,
|
||||
doc.document_alias
|
||||
FROM " . PREFIX . "_module_comment_info AS comm
|
||||
LEFT JOIN " . PREFIX . "_documents AS doc ON doc.Id = comm.document_id
|
||||
WHERE comm.comment_status = '1'
|
||||
ORDER BY comm.comment_published DESC
|
||||
LIMIT " . (int)$limit
|
||||
);
|
||||
|
||||
$items = array();
|
||||
if ($sql && $sql->NumRows() > 0) {
|
||||
while ($res = $sql->FetchAssocArray()) {
|
||||
$row = array_change_key_case($res, CASE_LOWER);
|
||||
|
||||
// Обработка текста комментария
|
||||
$row['comment_text'] = mb_strimwidth(strip_tags($row['comment_text'] ?? ''), 0, 150, "...");
|
||||
$row['date'] = ave_date_format(get_settings('date_format'), $row['comment_published']);
|
||||
|
||||
// Логика аватара (системный или буквенный)
|
||||
if (isset($row['comment_author_id']) && $row['comment_author_id'] > 0) {
|
||||
$row['avatar'] = function_exists('getAvatar') ? getAvatar($row['comment_author_id'], 48) : '';
|
||||
} else {
|
||||
$row['avatar'] = '';
|
||||
}
|
||||
|
||||
if (empty($row['avatar']) || strpos($row['avatar'], 'user.png') !== false) {
|
||||
$row['avatar'] = '';
|
||||
$name = !empty($row['comment_author_name']) ? stripslashes($row['comment_author_name']) : 'Guest';
|
||||
$row['first_letter'] = mb_strtoupper(mb_substr(trim($name), 0, 1, 'UTF-8'));
|
||||
$row['avatar_color_index'] = (abs(crc32($name)) % 12) + 1;
|
||||
}
|
||||
|
||||
// Авторские звезды
|
||||
$user_rating = (int)($row['user_rating'] ?? 0);
|
||||
$stars_html = '';
|
||||
if ($user_rating > 0) {
|
||||
for ($i = 1; $i <= 5; $i++) {
|
||||
if ($i <= $user_rating) {
|
||||
$stars_html .= '<i class="bi bi-star-fill text-warning me-1" style="font-size: 0.8rem;"></i>';
|
||||
} else {
|
||||
$stars_html .= '<i class="bi bi-star text-muted me-1" style="font-size: 0.8rem; opacity: 0.5;"></i>';
|
||||
}
|
||||
}
|
||||
}
|
||||
$row['stars'] = $stars_html;
|
||||
|
||||
// Формирование ссылки
|
||||
$doc_id = (int)$row['document_id'];
|
||||
$alias = (!empty($row['document_alias']) && $row['document_alias'] != '/') ? $row['document_alias'] : '';
|
||||
$raw_url = "index.php?id=" . $doc_id . "&doc=" . $alias . "/";
|
||||
|
||||
$final_url = function_exists('rewrite_link') ? rewrite_link($raw_url) : $alias;
|
||||
|
||||
// Чистим слеши
|
||||
$final_url = preg_replace('/(?<!:)\/\//', '/', str_ireplace(['"//"', '///'], ['/', '/'], $final_url));
|
||||
$final_url = rtrim($final_url, '/');
|
||||
|
||||
// ФИКС ГЛАВНОЙ: если ссылка пустая после rtrim, значит это корень сайта
|
||||
if (empty($final_url)) {
|
||||
$final_url = '/';
|
||||
}
|
||||
|
||||
// Собираем финальный URL с якорем
|
||||
$row['link'] = $final_url . '#comment_wrapper_' . ($row['id'] ?? 0);
|
||||
|
||||
// Дополнительная проверка корректности начала ссылки
|
||||
if (isset($row['link'][0]) && $row['link'][0] == '#') {
|
||||
$row['link'] = '/' . $row['link'];
|
||||
}
|
||||
|
||||
$row['document_title'] = !empty($row['document_title']) ? $row['document_title'] : 'Документ #' . $doc_id;
|
||||
|
||||
$items[] = $row;
|
||||
}
|
||||
}
|
||||
return $items;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
?>
|
||||
@@ -231,4 +231,62 @@
|
||||
.comment-image-item .card-link-wrapper:hover .file-box {
|
||||
box-shadow: 0 4px 12px rgba(0,0,0,0.15) !important;
|
||||
border-color: #0d6efd !important; /* Цвет границы при наведении (синий) */
|
||||
}
|
||||
}
|
||||
|
||||
/*стили при переходе с блока последние коммента*/
|
||||
/* Плавная прокрутка */
|
||||
html {
|
||||
scroll-behavior: smooth !important;
|
||||
}
|
||||
|
||||
/* Отступ от фиксированного меню */
|
||||
[id^="comment_wrapper_"] {
|
||||
scroll-margin-top: 100px !important;
|
||||
}
|
||||
|
||||
/* Эффект подсветки */
|
||||
[id^="comment_wrapper_"]:target {
|
||||
animation: highlight-fade 3s ease-in-out !important;
|
||||
outline: 2px solid #ffc107 !important;
|
||||
border-radius: 0.375rem;
|
||||
}
|
||||
|
||||
@keyframes highlight-fade {
|
||||
0% { background-color: #fff9c4 !important; }
|
||||
100% { background-color: transparent; }
|
||||
}
|
||||
|
||||
/* Геометрия аватаров для виджета */
|
||||
.lc-avatar-wrapper {
|
||||
width: 42px;
|
||||
height: 42px;
|
||||
margin-right: 12px;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.lc-avatar-wrapper img {
|
||||
width: 42px;
|
||||
height: 42px;
|
||||
border-radius: 50%;
|
||||
object-fit: cover;
|
||||
}
|
||||
|
||||
.lc-letter-circle {
|
||||
width: 42px;
|
||||
height: 42px;
|
||||
border-radius: 50%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
color: #fff;
|
||||
font-weight: bold;
|
||||
font-size: 1.1rem;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
.lc-reply-label {
|
||||
font-size: 0.8rem;
|
||||
color: #6c757d;
|
||||
font-weight: normal;
|
||||
margin-left: 5px;
|
||||
}
|
||||
|
||||
33
info.php
33
info.php
@@ -1,20 +1,19 @@
|
||||
<?php
|
||||
if (! defined('BASE_DIR'))
|
||||
exit;
|
||||
if (!defined('BASE_DIR')) exit;
|
||||
|
||||
$module = array(
|
||||
'ModuleSysName' => 'comment',
|
||||
'ModuleVersion' => '3.30',
|
||||
'ModuleAutor' => 'Repellent',
|
||||
'ModuleCopyright' => '© 2007-' . date('Y') . ' AVE.cms',
|
||||
'ModuleStatus' => 1,
|
||||
'ModuleIsFunction' => 1,
|
||||
'ModuleTemplate' => 0,
|
||||
'ModuleAdminEdit' => 1,
|
||||
'ModuleFunction' => 'mod_comment',
|
||||
'ModuleTag' => '[mod_comment]',
|
||||
'ModuleTagLink' => null,
|
||||
'ModuleAveTag' => '#\\\[mod_comment]#',
|
||||
'ModulePHPTag' => '<?php mod_comment(); ?>'
|
||||
);
|
||||
$module = array(
|
||||
'ModuleSysName' => 'comment',
|
||||
'ModuleVersion' => '3.33',
|
||||
'ModuleAutor' => 'Repellent',
|
||||
'ModuleCopyright' => '© 2007-' . date('Y') . ' AVE.cms',
|
||||
'ModuleStatus' => 1,
|
||||
'ModuleIsFunction' => 1,
|
||||
'ModuleTemplate' => 0,
|
||||
'ModuleAdminEdit' => 1,
|
||||
'ModuleFunction' => 'mod_comment',
|
||||
'ModuleTag' => '[mod_comment]',
|
||||
'ModuleTagLink' => null,
|
||||
'ModuleAveTag' => '#\\\[mod_comment(:[\\\d]+)?]#',
|
||||
'ModulePHPTag' => '<?php mod_comment("$1"); ?>'
|
||||
);
|
||||
?>
|
||||
43
module.php
43
module.php
@@ -14,21 +14,42 @@ if(!defined('BASE_DIR')) exit;
|
||||
* Функция, предназначенная для вывода списка комментариев к данному документу.
|
||||
* Она будет выполнена при парсинге шаблона вместо системного тега [mod_comment].
|
||||
*/
|
||||
function mod_comment()
|
||||
function mod_comment($param = '')
|
||||
{
|
||||
global $AVE_Template;
|
||||
global $AVE_Template;
|
||||
|
||||
// Подключаем класс и создаем объект дял работы
|
||||
require_once(BASE_DIR . '/modules/comment/class/comment.php');
|
||||
$comment = new Comment;
|
||||
// 1. Подключаем класс
|
||||
require_once(BASE_DIR . '/modules/comment/class/comment.php');
|
||||
$comment = new Comment;
|
||||
|
||||
// Подключаем языковые файлы
|
||||
$tpl_dir = BASE_DIR . '/modules/comment/templates/';
|
||||
$lang_file = BASE_DIR . '/modules/comment/lang/' . $_SESSION['user_language'] . '.txt';
|
||||
$AVE_Template->config_load($lang_file, 'module');
|
||||
// 2. Проверяем: если в теге передана цифра [mod_comment:5]
|
||||
// $param может прийти в виде ":5" или просто "5" в зависимости от парсера
|
||||
$limit = (int)str_replace(':', '', $param);
|
||||
|
||||
// Обращаемся к методу commentListShow() и отображаем список комментариев
|
||||
$comment->commentListShow($tpl_dir);
|
||||
if ($limit > 0) {
|
||||
// --- РЕЖИМ "ПОСЛЕДНИЕ ОТЗЫВЫ" ---
|
||||
$tpl_dir = BASE_DIR . '/modules/comment/templates/';
|
||||
|
||||
// Загружаем переводы (даты, заголовки)
|
||||
$lang_file = BASE_DIR . '/modules/comment/lang/' . ($_SESSION['user_language'] ?? 'ru') . '.txt';
|
||||
if (file_exists($lang_file)) $AVE_Template->config_load($lang_file, 'module');
|
||||
|
||||
// Берем данные из метода
|
||||
$items = $comment->getLatestComments($limit);
|
||||
$AVE_Template->assign('last_comments_items', $items);
|
||||
|
||||
// Выводим специальный шаблон для виджета
|
||||
echo $AVE_Template->fetch($tpl_dir . 'last_comments.tpl');
|
||||
return; // Выходим, чтобы под виджетом не вылез список комментов статьи
|
||||
}
|
||||
|
||||
// --- СТАНДАРТНЫЙ РЕЖИМ (список под статьей) ---
|
||||
// Если параметров нет или это обычный [mod_comment]
|
||||
$tpl_dir = BASE_DIR . '/modules/comment/templates/';
|
||||
$lang_file = BASE_DIR . '/modules/comment/lang/' . ($_SESSION['user_language'] ?? 'ru') . '.txt';
|
||||
if (file_exists($lang_file)) $AVE_Template->config_load($lang_file, 'module');
|
||||
|
||||
$comment->commentListShow($tpl_dir);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
60
templates/last_comments.tpl
Normal file
60
templates/last_comments.tpl
Normal file
@@ -0,0 +1,60 @@
|
||||
<div class="last-comments-widget" style="max-width: 400px;">
|
||||
<h4 class="widget-title mb-4" style="font-weight: 700; border-left: 4px solid #0d6efd; padding-left: 15px; line-height: 1.2;">Свежие отзывы</h4>
|
||||
|
||||
<div class="list-group list-group-flush">
|
||||
{foreach from=$last_comments_items item=c}
|
||||
<div class="list-group-item bg-transparent px-0 py-3 border-bottom" style="border-color: #f0f0f0 !important;">
|
||||
|
||||
<div class="d-flex align-items-start mb-2">
|
||||
<div class="lc-avatar-wrapper">
|
||||
{if $c.avatar}
|
||||
<img src="{$c.avatar}" alt="{$c.comment_author_name|escape}">
|
||||
{else}
|
||||
<div class="lc-letter-circle av-c{$c.avatar_color_index|default:1}">
|
||||
{$c.first_letter|default:'?'|upper}
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
<div class="flex-grow-1 min-w-0">
|
||||
<div class="d-flex justify-content-between align-items-start">
|
||||
<div>
|
||||
<strong style="color: #333; font-size: 0.95rem; display: block; line-height: 1.2;">
|
||||
{$c.comment_author_name}
|
||||
{if $c.parent_id > 0}
|
||||
<span class="lc-reply-label">
|
||||
<i class="bi bi-reply-all-fill text-primary"></i> ответил(а)
|
||||
</span>
|
||||
{/if}
|
||||
</strong>
|
||||
|
||||
{if $c.stars}
|
||||
<div class="d-flex align-items-center" style="margin-top: 3px; line-height: 1;">
|
||||
{$c.stars}
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
<span class="text-muted" style="font-size: 0.7rem; white-space: nowrap;">
|
||||
<i class="bi bi-clock me-1"></i>{$c.date}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div style="margin-left: 54px;">
|
||||
<div class="mb-2">
|
||||
<a href="{$c.link}" class="text-decoration-none d-flex align-items-center fw-medium" style="color: #0d6efd; font-size: 0.85rem;">
|
||||
<i class="bi bi-file-earmark-text me-1 text-secondary"></i>
|
||||
<span class="text-truncate">{$c.document_title}</span>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div style="color: #444; font-size: 0.9rem; line-height: 1.4; background: #f9f9f9; padding: 10px 12px; border-radius: 0 8px 8px 8px; border-left: 2px solid #0d6efd;">
|
||||
«{$c.comment_text}»
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
{/foreach}
|
||||
</div>
|
||||
</div>
|
||||
Reference in New Issue
Block a user