feat(blog): hide comment
All checks were successful
continuous-integration/drone/push Build is passing

This commit is contained in:
Baoshuo Ren 2023-02-07 18:38:24 +08:00
parent e350a96dd7
commit d6e47f1de5
Signed by: baoshuo
GPG Key ID: 00CB9680AB29F51A
6 changed files with 137 additions and 15 deletions

View File

@ -323,12 +323,12 @@ if (UOJContest::cur()) {
</div> </div>
<div class="tab-pane" id="submit"> <div class="tab-pane" id="submit">
<?php if ($pre_submit_check_ret !== true) : ?> <?php if ($pre_submit_check_ret !== true) : ?>
<p class="text-warning h4"><?= $pre_submit_check_ret ?></p> <p class="text-warning-emphasis h4"><?= $pre_submit_check_ret ?></p>
<?php elseif ($no_more_submission) : ?> <?php elseif ($no_more_submission) : ?>
<p class="text-warning h4"><?= $no_more_submission ?></p> <p class="text-warning-emphasis h4"><?= $no_more_submission ?></p>
<?php else : ?> <?php else : ?>
<?php if ($submission_warning) : ?> <?php if ($submission_warning) : ?>
<p class="text-warning h4"><?= $submission_warning ?></p> <p class="text-warning-emphasis h4"><?= $submission_warning ?></p>
<?php endif ?> <?php endif ?>
<?php if (isset($zip_answer_form)) : ?> <?php if (isset($zip_answer_form)) : ?>
<?php $zip_answer_form->printHTML(); ?> <?php $zip_answer_form->printHTML(); ?>

View File

@ -13,6 +13,8 @@ $blog = UOJBlog::info();
function getCommentContentToDisplay($comment) { function getCommentContentToDisplay($comment) {
if (!$comment['is_hidden']) { if (!$comment['is_hidden']) {
return $comment['content']; return $comment['content'];
} else if (UOJUserBlog::userHasManagePermission(Auth::user())) {
return '<span class="text-muted mb-3">【' . HTML::escape($comment['reason_to_hide']) . '】</span>' . $comment['content'];
} else { } else {
return '<span class="text-muted">【' . HTML::escape($comment['reason_to_hide']) . '】</span>'; return '<span class="text-muted">【' . HTML::escape($comment['reason_to_hide']) . '】</span>';
} }
@ -162,6 +164,34 @@ $reply_form->handle = function (&$vdata) {
$reply_form->config['ctrl_enter_submit'] = true; $reply_form->config['ctrl_enter_submit'] = true;
$reply_form->runAtServer(); $reply_form->runAtServer();
if (UOJUserBlog::userHasManagePermission(Auth::user())) {
$hide_form = new UOJForm('hide');
$hide_form->addHidden('comment_hide_id', '', 'validateCommentId', null);
$hide_form->addSelect('comment_hide_type', [
'label' => '隐藏理由',
'options' => UOJBlogComment::HIDE_REASONS,
'default_value' => 'spam',
]);
$hide_form->addInput('comment_hide_reason', [
'div_class' => 'mt-3',
'label' => '自定义隐藏理由',
'default_value' => '该评论由于违反社区规定,已被管理员隐藏',
'validator_php' => 'validateString',
]);
$hide_form->handle = function (&$vdata) {
if ($_POST['comment_hide_type'] == 'unhide') {
$reason = '';
} else if ($_POST['comment_hide_type'] == 'other') {
$reason = $_POST['comment_hide_reason'];
} else {
$reason = '该评论由于' . UOJBlogComment::HIDE_REASONS[$_POST['comment_hide_type']] . ',已被管理员隐藏';
}
$vdata['comment_hide_id']->hide($reason);
};
$hide_form->runAtServer();
}
$comments_pag = new Paginator([ $comments_pag = new Paginator([
'col_names' => ['*'], 'col_names' => ['*'],
'table_name' => 'blogs_comments', 'table_name' => 'blogs_comments',
@ -170,9 +200,38 @@ $comments_pag = new Paginator([
'page_len' => 20 'page_len' => 20
]); ]);
?> ?>
<?php echoUOJPageHeader(HTML::stripTags($blog['title']) . ' - 博客') ?> <?php echoUOJPageHeader(HTML::stripTags($blog['title']) . ' - 博客') ?>
<script>
var user_can_hide_comment = <?= json_encode(isset($hide_form)) ?>;
</script>
<?php UOJBlog::cur()->echoView(['show_title_only' => isset($_GET['page']) && $_GET['page'] != 1]) ?> <?php UOJBlog::cur()->echoView(['show_title_only' => isset($_GET['page']) && $_GET['page'] != 1]) ?>
<?php if (isset($hide_form)) : ?>
<div class="modal fade" id="HideCommentModal" tabindex="-1" aria-labelledby="HideCommentModalLabel" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h1 class="modal-title fs-5" id="HideCommentModalLabel">隐藏评论</h1>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
<div class="mb-3">
<div class="mb-2">原评论ID: <span id="span-comment_hide_id"></span></div>
<blockquote id="HideCommentModalOriginalComment" class="border-start border-3 ps-3 text-muted"></blockquote>
</div>
<hr>
<?php $hide_form->printHTML(); ?>
</div>
</div>
</div>
</div>
<?php endif ?>
<h2> <h2>
评论 评论
<i class="bi bi-chat-fill"></i> <i class="bi bi-chat-fill"></i>
@ -216,13 +275,20 @@ $comments_pag = new Paginator([
<?= ClickZans::getBlock('BC', $comment['id'], $comment['zan']) ?> <?= ClickZans::getBlock('BC', $comment['id'], $comment['zan']) ?>
</div> </div>
</div> </div>
<div class="comment-content my-2"><?= $comment['content'] ?></div> <div class="comment-content my-2" id="comment-content-<?= $comment['id'] ?>"><?= getCommentContentToDisplay($comment) ?></div>
<ul class="list-inline mb-0 text-end"> <ul class="list-inline mb-0 text-end">
<li class="list-inline-item small text-muted"> <li class="list-inline-item small text-muted">
<?= $comment['post_time'] ?> <?= $comment['post_time'] ?>
</li> </li>
<?php if (isset($hide_form)) : ?>
<li class="list-inline-item"> <li class="list-inline-item">
<a class="text-decoration-none" id="reply-to-<?= $comment['id'] ?>" href="#"> <a href="#" class="text-warning-emphasis text-decoration-none p-0 uoj-blog-hide-comment-btn" data-comment-id="<?= $comment['id'] ?>">
隐藏
</a>
</li>
<?php endif ?>
<li class="list-inline-item">
<a id="reply-to-<?= $comment['id'] ?>" href="#">
回复 回复
</a> </a>
</li> </li>
@ -249,4 +315,14 @@ $comments_pag = new Paginator([
<?php $reply_form->printHTML() ?> <?php $reply_form->printHTML() ?>
</div> </div>
<script>
$('.uoj-blog-hide-comment-btn').each(function() {
$(this).click(function() {
var comment_id = $(this).data('comment-id');
toggleModalHideComment(comment_id, $('#comment-content-' + comment_id).html());
});
})
</script>
<?php echoUOJPageFooter() ?> <?php echoUOJPageFooter() ?>

View File

@ -75,8 +75,8 @@ function validateURL($url) {
return filter_var($url, FILTER_VALIDATE_URL) !== false; return filter_var($url, FILTER_VALIDATE_URL) !== false;
} }
function validateString($str) { function validateString($x) {
return preg_match('/[^0-9a-zA-Z]/', $str) !== true; return is_string($x) ? '' : '不合法的字符串';
} }
function validateGitHubUsername($username) { function validateGitHubUsername($username) {
@ -95,6 +95,20 @@ function validateUserAndStoreByUsername($username, &$vdata) {
return ''; return '';
} }
function validateCommentId($id) {
if (!validateUInt($id)) {
return 'ID 不合法';
}
$comment = UOJBlogComment::query($id);
if (!$comment) {
return '评论不存在';
}
return ['error' => '', 'store' => $comment];
}
function is_short_string($str) { function is_short_string($str) {
return is_string($str) && strlen($str) <= 256; return is_string($str) && strlen($str) <= 256;
} }

View File

@ -3,6 +3,15 @@
class UOJBlogComment { class UOJBlogComment {
use UOJDataTrait; use UOJDataTrait;
const HIDE_REASONS = [
'unhide' => '解除隐藏',
'spam' => '疑似为垃圾信息',
'garbage' => '疑似为无意义的乱码',
'insult' => '包含不和谐内容',
'violate' => '违反法律法规',
'other' => '其他(请在下方说明)',
];
public static function query($id) { public static function query($id) {
if (!isset($id) || !validateUInt($id)) { if (!isset($id) || !validateUInt($id)) {
return null; return null;

View File

@ -33,6 +33,14 @@ class UOJUserBlog {
return self::$user['username'] === $user['username']; return self::$user['username'] === $user['username'];
} }
public static function userHasManagePermission(?array $user) {
if ($user === null) {
return false;
}
return isSuperUser($user) || UOJUser::checkPermission($user, 'blogs.manage');
}
public static function userCanManage(?array $user, ?string $whose_blog = null) { public static function userCanManage(?array $user, ?string $whose_blog = null) {
if ($whose_blog === null) { if ($whose_blog === null) {
$whose_blog = self::id(); $whose_blog = self::id();

View File

@ -1577,6 +1577,14 @@ function custom_test_onsubmit(response_text, div_result, url) {
setTimeout(update, 500); setTimeout(update, 500);
} }
// hide comment
function toggleModalHideComment(id, content) {
$('#input-comment_hide_id').val(id);
$('#span-comment_hide_id').text(id);
$('#HideCommentModalOriginalComment').html(content);
$('#HideCommentModal').modal('show');
}
// comment // comment
function showCommentReplies(id, replies) { function showCommentReplies(id, replies) {
var toggleFormReply = function(from, text) { var toggleFormReply = function(from, text) {
@ -1596,7 +1604,6 @@ function showCommentReplies(id, replies) {
$(r).val(text).focus(); $(r).val(text).focus();
}); });
}); });
} else if ($(q).css('display') != 'none') { } else if ($(q).css('display') != 'none') {
$(q).appendTo(p).hide('fast'); $(q).appendTo(p).hide('fast');
} else { } else {
@ -1629,6 +1636,14 @@ function showCommentReplies(id, replies) {
).append( ).append(
$('<ul class="text-end mb-0 list-inline" />').append( $('<ul class="text-end mb-0 list-inline" />').append(
'<li class="list-inline-item small text-muted">' + reply.post_time + '</li>' '<li class="list-inline-item small text-muted">' + reply.post_time + '</li>'
).append(
user_can_hide_comment
? $('<li class="list-inline-item" />').append(
$('<a href="#" class="text-warning-emphasis text-decoration-none p-0" />').data('comment-id', reply.id).text('隐藏').click(function() {
toggleModalHideComment(reply.id, reply.content);
})
)
: ''
).append( ).append(
$('<li class="list-inline-item" />').append( $('<li class="list-inline-item" />').append(
$('<a href="#">回复</a>').click(function (e) { $('<a href="#">回复</a>').click(function (e) {