добавлен метод вывода информации об Авторе комментария
This commit is contained in:
@@ -1501,37 +1501,92 @@ function commentAdminDelete($comment_id)
|
||||
*
|
||||
* @param string $tpl_dir - путь к шаблонам модуля
|
||||
*/
|
||||
function commentPostInfoShow($tpl_dir)
|
||||
{
|
||||
global $AVE_DB, $AVE_Template;
|
||||
|
||||
$comment_id = (int)($_REQUEST['Id'] ?? 0);
|
||||
function commentPostInfoShow($tpl_dir)
|
||||
{
|
||||
global $AVE_DB, $AVE_Template;
|
||||
|
||||
$comment_id = (int)($_REQUEST['Id'] ?? 0);
|
||||
|
||||
// Получаем полную информацию о комментарии
|
||||
$row = $AVE_DB->Query("
|
||||
SELECT *
|
||||
FROM " . PREFIX . "_module_comment_info
|
||||
WHERE Id = '" . $comment_id . "'
|
||||
")->FetchAssocArray();
|
||||
// 1. Получаем данные комментария и настройки заголовков
|
||||
$row = $AVE_DB->Query("
|
||||
SELECT c.*, m.comment_name_f1, m.comment_name_f2
|
||||
FROM " . PREFIX . "_module_comment_info AS c
|
||||
LEFT JOIN " . PREFIX . "_module_comments AS m ON 1=1
|
||||
WHERE c.Id = '$comment_id'
|
||||
LIMIT 1
|
||||
")->FetchAssocArray();
|
||||
|
||||
// Преобразуем адрес сайта к формату ссылки
|
||||
$row['comment_author_website'] = str_replace('http://', '', $row['comment_author_website']);
|
||||
$row['comment_author_website'] = ($row['comment_author_website'] != '')
|
||||
? '<a target="_blank" href="http://' . $row['comment_author_website'] . '">' . $row['comment_author_website'] .'</a>'
|
||||
: '';
|
||||
if (!$row) exit('Данные не найдены');
|
||||
|
||||
// Выполняем запрос к БД на получение количества всех комментариев, оставленных данным пользователем
|
||||
$row['num'] = $AVE_DB->Query("
|
||||
SELECT COUNT(*)
|
||||
FROM " . PREFIX . "_module_comment_info
|
||||
WHERE comment_author_id = '" . $row['comment_author_id'] . "'
|
||||
AND comment_author_id != 0
|
||||
")->GetCell();
|
||||
$author_id = (int)($row['comment_author_id'] ?? 0);
|
||||
$a_key = $row['anon_key'] ?? '';
|
||||
|
||||
// Отображаем окно с информацией
|
||||
$AVE_Template->assign('c', $row);
|
||||
$AVE_Template->display($tpl_dir . $this->_postinfo_tpl);
|
||||
}
|
||||
// --- ЛОГИКА ДАТ ---
|
||||
if ($author_id > 0) {
|
||||
$user_data = $AVE_DB->Query("SELECT reg_time, last_visit FROM " . PREFIX . "_users WHERE Id = '$author_id' LIMIT 1")->FetchAssocArray();
|
||||
$row['date_label'] = 'Дата регистрации';
|
||||
$row['date_value'] = $user_data['reg_time'] ?? 0;
|
||||
$row['last_visit'] = $user_data['last_visit'] ?? 0;
|
||||
} else {
|
||||
$first_time = ($a_key != '') ? $AVE_DB->Query("SELECT MIN(comment_published) FROM " . PREFIX . "_module_comment_info WHERE anon_key = '" . addslashes($a_key) . "'")->GetCell() : 0;
|
||||
$row['date_label'] = 'Дата первого комментария';
|
||||
$row['date_value'] = $first_time;
|
||||
$row['last_visit'] = 0;
|
||||
}
|
||||
|
||||
// --- ПОДСЧЕТ КОММЕНТАРИЕВ И СУММАРНОГО РЕЙТИНГА ---
|
||||
if ($author_id > 0) {
|
||||
$where = "comment_author_id = '$author_id'";
|
||||
} elseif ($a_key != '') {
|
||||
$where = "anon_key = '" . addslashes($a_key) . "'";
|
||||
} else {
|
||||
$where = "Id = '$comment_id'"; // Крайний случай
|
||||
}
|
||||
|
||||
// Считаем всё одним запросом: количество, сумму звезд и сумму голосов
|
||||
$stats = $AVE_DB->Query("
|
||||
SELECT
|
||||
COUNT(*) as total_cnt,
|
||||
SUM(rating_sum) as sum_stars,
|
||||
SUM(rating_count) as sum_votes
|
||||
FROM " . PREFIX . "_module_comment_info
|
||||
WHERE $where
|
||||
")->FetchAssocArray();
|
||||
|
||||
$row['num'] = $stats['total_cnt'] ?? 1;
|
||||
|
||||
// Вычисляем средний рейтинг (от 1 до 5)
|
||||
$avg_rating = 0;
|
||||
if (!empty($stats['sum_votes'])) {
|
||||
$avg_rating = round($stats['sum_stars'] / $stats['sum_votes']);
|
||||
}
|
||||
$row['avg_rating'] = $avg_rating;
|
||||
$row['total_votes'] = $stats['sum_votes'];
|
||||
|
||||
// --- ОБРАБОТКА ДОП. ПОЛЕЙ (F1, F2) ---
|
||||
$custom_fields = [];
|
||||
$fields_to_check = [
|
||||
['val' => $row['comment_author_website'], 'title' => $row['comment_name_f1'], 'default' => 'Личный сайт'],
|
||||
['val' => $row['comment_author_city'], 'title' => $row['comment_name_f2'], 'default' => 'Откуда']
|
||||
];
|
||||
foreach ($fields_to_check as $f) {
|
||||
$val = trim($f['val'] ?? '');
|
||||
if ($val != '') {
|
||||
$title = (!empty($f['title'])) ? $f['title'] : $f['default'];
|
||||
$value = (preg_match('/^(http|https|www\.)/i', $val))
|
||||
? '<a target="_blank" href="http://' . str_replace(['http://', 'https://'], '', $val) . '">' . str_replace(['http://', 'https://'], '', $val) . '</a>'
|
||||
: htmlspecialchars($val);
|
||||
$custom_fields[] = ['title' => $title, 'value' => $value];
|
||||
}
|
||||
}
|
||||
|
||||
$AVE_Template->assign('c', $row);
|
||||
$AVE_Template->assign('custom_fields', $custom_fields);
|
||||
|
||||
header('Content-Type: text/html; charset=utf-8');
|
||||
$AVE_Template->display($tpl_dir . $this->_postinfo_tpl);
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Метод, предназначенный для управления запретом или разрешением отвечать на комментарии
|
||||
|
||||
@@ -1,54 +1,47 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<div class="author-info-popover">
|
||||
<ul class="list-unstyled mb-0 small">
|
||||
<li class="mb-1">
|
||||
<strong>{#COMMENT_USER_NAME#}:</strong>
|
||||
{$c.comment_author_name|stripslashes|escape}
|
||||
</li>
|
||||
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=windows-1251" />
|
||||
<title>{#COMMENT_INFO#}</title>
|
||||
<link href="templates/{$smarty.request.theme|escape}/css/style.css" rel="stylesheet" type="text/css" media="screen" />
|
||||
</head>
|
||||
{if $c.date_value}
|
||||
<li class="mb-1">
|
||||
<strong>{$c.date_label}:</strong>
|
||||
{$c.date_value|date_format:$TIME_FORMAT|pretty_date}
|
||||
</li>
|
||||
{/if}
|
||||
|
||||
<body id="body_popup">
|
||||
{if $c.last_visit}
|
||||
<li class="mb-1">
|
||||
<strong>Последний визит:</strong>
|
||||
{$c.last_visit|date_format:$TIME_FORMAT|pretty_date}
|
||||
</li>
|
||||
{/if}
|
||||
|
||||
<div id="module_header"><h2>{#COMMENT_INFO#}</h2></div>
|
||||
{foreach from=$custom_fields item=field}
|
||||
<li class="mb-1">
|
||||
<strong>{$field.title}:</strong> {$field.value}
|
||||
</li>
|
||||
{/foreach}
|
||||
|
||||
<div id="module_content">
|
||||
<table width="100%" border="0" cellspacing="1" cellpadding="4">
|
||||
<tr>
|
||||
<td width="160">{#COMMENT_USER_NAME#}</td>
|
||||
<td>{$c.comment_author_name|stripslashes|escape}</td>
|
||||
</tr>
|
||||
<li class="mb-1">
|
||||
<strong>{#COMMENT_USER_COMMENTS#}:</strong>
|
||||
{$c.num}
|
||||
</li>
|
||||
|
||||
<tr>
|
||||
<td width="160">{#COMMENT_DATE_CREATE#}</td>
|
||||
<td>{$c.comment_published|date_format:$TIME_FORMAT|pretty_date}</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td width="160">{#COMMENT_USER_EMAIL#}</td>
|
||||
<td>
|
||||
{assign var=comment_author_email value=$c.comment_author_email}
|
||||
{mailto address="$comment_author_email" encode="javascript_charcode"}
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td width="160">{#COMMENT_USER_SITE#}</td>
|
||||
<td>{$c.comment_author_website|default:'-'}</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td width="160">{#COMMENT_USER_FROM#}</td>
|
||||
<td>{$c.comment_author_city|stripslashes|escape|default:'-'}</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td width="160">{#COMMENT_USER_COMMENTS#}</td>
|
||||
<td>{$c.num|default:'-'}</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<p><input onclick="window.close();" type="button" class="button" value="{#COMMENT_CLOSE_BUTTON#}" /></p>
|
||||
</div>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
<li class="mt-2 pt-2 border-top">
|
||||
<strong>Рейтинг автора:</strong>
|
||||
<span class="text-warning shadow-sm-text">
|
||||
{section name=star start=1 loop=6}
|
||||
{if $smarty.section.star.index <= $c.avg_rating}
|
||||
<i class="bi-star-fill"></i>
|
||||
{else}
|
||||
<i class="bi-star text-muted"></i>
|
||||
{/if}
|
||||
{/section}
|
||||
</span>
|
||||
<small class="text-secondary">({$c.total_votes|default:0} гол.)</small>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
@@ -1,3 +1,41 @@
|
||||
{literal}
|
||||
<style>
|
||||
/* Стили для стандартной шапки поповера */
|
||||
.popover-header {
|
||||
background-color: #f0f0f0 !important; /* Тот самый серый цвет */
|
||||
border-bottom: 1px solid #dee2e6 !important;
|
||||
padding: 8px 12px !important;
|
||||
font-size: 0.9rem !important;
|
||||
font-weight: 600 !important;
|
||||
}
|
||||
|
||||
/* Кнопка закрытия в шапке */
|
||||
.pop-close {
|
||||
background: none !important;
|
||||
border: none !important;
|
||||
font-size: 22px !important;
|
||||
line-height: 1 !important;
|
||||
color: #999 !important;
|
||||
cursor: pointer !important;
|
||||
padding: 0 !important;
|
||||
margin-left: 10px !important;
|
||||
}
|
||||
|
||||
.pop-close:hover {
|
||||
color: #f00 !important;
|
||||
}
|
||||
|
||||
.popover-body {
|
||||
padding: 12px !important;
|
||||
min-width: 230px !important;
|
||||
}
|
||||
.author-popover, .author-popover:focus, .author-popover:active {
|
||||
outline: none !important;
|
||||
box-shadow: none !important;
|
||||
text-decoration: none !important;
|
||||
}
|
||||
</style>
|
||||
{/literal}
|
||||
{foreach from=$subcomments item=c name=sub_loop}
|
||||
{* ОПРЕДЕЛЯЕМ СТАТУС УДАЛЕНИЯ *}
|
||||
{assign var="is_deleted" value=false}
|
||||
@@ -60,7 +98,13 @@
|
||||
{if !$is_deleted}
|
||||
<span class="d-flex align-items-center">
|
||||
<i class="bi bi-person me-1"></i>
|
||||
<a title="{#COMMENT_INFO#}" href="javascript:void(0);" onclick="popup('{$ABS_PATH}index.php?module=comment&action=postinfo&pop=1&Id={$c.Id}&theme={$theme}','comment','500','300','1');" class="fw-bold link-dark text-decoration-none">{$c.comment_author_name|stripslashes|escape}</a>
|
||||
<a href="javascript:void(0);"
|
||||
class="author-popover fw-bold link-dark text-decoration-none"
|
||||
data-id="{$c.Id}"
|
||||
role="button"
|
||||
tabindex="0">
|
||||
{$c.comment_author_name|stripslashes|escape}
|
||||
</a>
|
||||
{* ПРОВЕРКА ИСТОРИИ ИМЕН АНОНИМА *}
|
||||
{if !empty($c.past_names)}
|
||||
<span class="badge rounded-pill bg-light text-danger border border-danger ms-1"
|
||||
@@ -284,4 +328,78 @@
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
{/foreach}
|
||||
{/foreach}
|
||||
|
||||
{literal}
|
||||
<script type="text/javascript">
|
||||
(function() {
|
||||
// Глобальный обработчик для крестика
|
||||
document.addEventListener('click', function(e) {
|
||||
if (e.target.closest('.pop-close')) {
|
||||
const pid = e.target.closest('.pop-close').getAttribute('data-id');
|
||||
const trigger = document.querySelector(`.author-popover[data-id="${pid}"]`);
|
||||
if (trigger) {
|
||||
const ins = bootstrap.Popover.getInstance(trigger);
|
||||
if (ins) ins.hide();
|
||||
trigger.blur();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
const startInitialization = () => {
|
||||
if (typeof bootstrap === 'undefined') return false;
|
||||
|
||||
document.querySelectorAll('.author-popover').forEach(el => {
|
||||
if (el.getAttribute('data-popover-initialized')) return;
|
||||
|
||||
new bootstrap.Popover(el, {
|
||||
html: true,
|
||||
sanitize: false,
|
||||
trigger: 'focus',
|
||||
placement: 'top',
|
||||
// ВОТ ЗДЕСЬ ВОЗВРАЩАЕМ ШАПКУ
|
||||
title: function() {
|
||||
const cid = el.getAttribute('data-id');
|
||||
return `
|
||||
<span>Информация об авторе</span>
|
||||
<button type="button" class="pop-close" data-id="${cid}">×</button>
|
||||
`;
|
||||
},
|
||||
content: function() {
|
||||
const commentId = el.getAttribute('data-id');
|
||||
const popoverId = 'popover-content-' + commentId;
|
||||
|
||||
setTimeout(() => {
|
||||
const popContent = document.getElementById(popoverId);
|
||||
if (popContent && popContent.innerHTML === '...') {
|
||||
if (el.getAttribute('data-loading') === 'true') return;
|
||||
el.setAttribute('data-loading', 'true');
|
||||
|
||||
fetch('index.php?module=comment&action=postinfo&pop=1&Id=' + commentId)
|
||||
.then(res => res.text())
|
||||
.then(html => {
|
||||
popContent.innerHTML = html;
|
||||
el.setAttribute('data-loading', 'false');
|
||||
})
|
||||
.catch(() => { popContent.innerHTML = 'Ошибка'; el.setAttribute('data-loading', 'false'); });
|
||||
}
|
||||
}, 30);
|
||||
return `<div id="${popoverId}">...</div>`;
|
||||
},
|
||||
// ПЕРЕОПРЕДЕЛЯЕМ ШАБЛОН (чтобы шапка была флексовой для крестика)
|
||||
template: `
|
||||
<div class="popover" role="tooltip">
|
||||
<div class="popover-arrow"></div>
|
||||
<h3 class="popover-header d-flex justify-content-between align-items-center"></h3>
|
||||
<div class="popover-body"></div>
|
||||
</div>`
|
||||
});
|
||||
el.setAttribute('data-popover-initialized', 'true');
|
||||
});
|
||||
return true;
|
||||
};
|
||||
|
||||
let timer = setInterval(() => { if (startInitialization()) clearInterval(timer); }, 300);
|
||||
})();
|
||||
</script>
|
||||
{/literal}
|
||||
Reference in New Issue
Block a user