manage-comments.php 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378
  1. <?php
  2. include 'common.php';
  3. include 'header.php';
  4. include 'menu.php';
  5. $stat = \Widget\Stat::alloc();
  6. $comments = \Widget\Comments\Admin::alloc();
  7. $isAllComments = ('on' == $request->get('__typecho_all_comments') || 'on' == \Typecho\Cookie::get('__typecho_all_comments'));
  8. ?>
  9. <div class="main">
  10. <div class="body container">
  11. <?php include 'page-title.php'; ?>
  12. <div class="row typecho-page-main" role="main">
  13. <div class="col-mb-12 typecho-list">
  14. <div class="clearfix">
  15. <ul class="typecho-option-tabs right">
  16. <?php if($user->pass('editor', true) && !isset($request->cid)): ?>
  17. <li class="<?php if($isAllComments): ?> current<?php endif; ?>"><a href="<?php echo $request->makeUriByRequest('__typecho_all_comments=on'); ?>"><?php _e('所有'); ?></a></li>
  18. <li class="<?php if(!$isAllComments): ?> current<?php endif; ?>"><a href="<?php echo $request->makeUriByRequest('__typecho_all_comments=off'); ?>"><?php _e('我的'); ?></a></li>
  19. <?php endif; ?>
  20. </ul>
  21. <ul class="typecho-option-tabs">
  22. <li<?php if(!isset($request->status) || 'approved' == $request->get('status')): ?> class="current"<?php endif; ?>><a href="<?php $options->adminUrl('manage-comments.php'
  23. . (isset($request->cid) ? '?cid=' . $request->filter('encode')->cid : '')); ?>"><?php _e('已通过'); ?></a></li>
  24. <li<?php if('waiting' == $request->get('status')): ?> class="current"<?php endif; ?>><a href="<?php $options->adminUrl('manage-comments.php?status=waiting'
  25. . (isset($request->cid) ? '&cid=' . $request->filter('encode')->cid : '')); ?>"><?php _e('待审核'); ?>
  26. <?php if(!$isAllComments && $stat->myWaitingCommentsNum > 0 && !isset($request->cid)): ?>
  27. <span class="balloon"><?php $stat->myWaitingCommentsNum(); ?></span>
  28. <?php elseif($isAllComments && $stat->waitingCommentsNum > 0 && !isset($request->cid)): ?>
  29. <span class="balloon"><?php $stat->waitingCommentsNum(); ?></span>
  30. <?php elseif(isset($request->cid) && $stat->currentWaitingCommentsNum > 0): ?>
  31. <span class="balloon"><?php $stat->currentWaitingCommentsNum(); ?></span>
  32. <?php endif; ?>
  33. </a></li>
  34. <li<?php if('spam' == $request->get('status')): ?> class="current"<?php endif; ?>><a href="<?php $options->adminUrl('manage-comments.php?status=spam'
  35. . (isset($request->cid) ? '&cid=' . $request->filter('encode')->cid : '')); ?>"><?php _e('垃圾'); ?>
  36. <?php if(!$isAllComments && $stat->mySpamCommentsNum > 0 && !isset($request->cid)): ?>
  37. <span class="balloon"><?php $stat->mySpamCommentsNum(); ?></span>
  38. <?php elseif($isAllComments && $stat->spamCommentsNum > 0 && !isset($request->cid)): ?>
  39. <span class="balloon"><?php $stat->spamCommentsNum(); ?></span>
  40. <?php elseif(isset($request->cid) && $stat->currentSpamCommentsNum > 0): ?>
  41. <span class="balloon"><?php $stat->currentSpamCommentsNum(); ?></span>
  42. <?php endif; ?>
  43. </a></li>
  44. </ul>
  45. </div>
  46. <div class="typecho-list-operate clearfix">
  47. <form method="get">
  48. <div class="operate">
  49. <label><i class="sr-only"><?php _e('全选'); ?></i><input type="checkbox" class="typecho-table-select-all" /></label>
  50. <div class="btn-group btn-drop">
  51. <button class="btn dropdown-toggle btn-s" type="button"><i class="sr-only"><?php _e('操作'); ?></i><?php _e('选中项'); ?> <i class="i-caret-down"></i></button>
  52. <ul class="dropdown-menu">
  53. <li><a href="<?php $security->index('/action/comments-edit?do=approved'); ?>"><?php _e('通过'); ?></a></li>
  54. <li><a href="<?php $security->index('/action/comments-edit?do=waiting'); ?>"><?php _e('待审核'); ?></a></li>
  55. <li><a href="<?php $security->index('/action/comments-edit?do=spam'); ?>"><?php _e('标记垃圾'); ?></a></li>
  56. <li><a lang="<?php _e('你确认要删除这些评论吗?'); ?>" href="<?php $security->index('/action/comments-edit?do=delete'); ?>"><?php _e('删除'); ?></a></li>
  57. </ul>
  58. <?php if('spam' == $request->get('status')): ?>
  59. <button lang="<?php _e('你确认要删除所有垃圾评论吗?'); ?>" class="btn btn-s btn-warn btn-operate" href="<?php $security->index('/action/comments-edit?do=delete-spam'); ?>"><?php _e('删除所有垃圾评论'); ?></button>
  60. <?php endif; ?>
  61. </div>
  62. </div>
  63. <div class="search" role="search">
  64. <?php if ('' != $request->keywords || '' != $request->category): ?>
  65. <a href="<?php $options->adminUrl('manage-comments.php'
  66. . (isset($request->status) || isset($request->cid) ? '?' .
  67. (isset($request->status) ? 'status=' . $request->filter('encode')->status : '') .
  68. (isset($request->cid) ? (isset($request->status) ? '&' : '') . 'cid=' . $request->filter('encode')->cid : '') : '')); ?>"><?php _e('&laquo; 取消筛选'); ?></a>
  69. <?php endif; ?>
  70. <input type="text" class="text-s" placeholder="<?php _e('请输入关键字'); ?>" value="<?php echo $request->filter('html')->keywords; ?>"<?php if ('' == $request->keywords): ?> onclick="value='';name='keywords';" <?php else: ?> name="keywords"<?php endif; ?>/>
  71. <?php if(isset($request->status)): ?>
  72. <input type="hidden" value="<?php echo $request->filter('html')->status; ?>" name="status" />
  73. <?php endif; ?>
  74. <?php if(isset($request->cid)): ?>
  75. <input type="hidden" value="<?php echo $request->filter('html')->cid; ?>" name="cid" />
  76. <?php endif; ?>
  77. <button type="submit" class="btn btn-s"><?php _e('筛选'); ?></button>
  78. </div>
  79. </form>
  80. </div><!-- end .typecho-list-operate -->
  81. <form method="post" name="manage_comments" class="operate-form">
  82. <div class="typecho-table-wrap">
  83. <table class="typecho-list-table">
  84. <colgroup>
  85. <col width="3%" class="kit-hidden-mb"/>
  86. <col width="6%" class="kit-hidden-mb" />
  87. <col width="20%"/>
  88. <col width="71%"/>
  89. </colgroup>
  90. <thead>
  91. <tr>
  92. <th class="kit-hidden-mb"> </th>
  93. <th><?php _e('作者'); ?></th>
  94. <th class="kit-hidden-mb"> </th>
  95. <th><?php _e('内容'); ?></th>
  96. </tr>
  97. </thead>
  98. <tbody>
  99. <?php if($comments->have()): ?>
  100. <?php while($comments->next()): ?>
  101. <tr id="<?php $comments->theId(); ?>" data-comment="<?php
  102. $comment = array(
  103. 'author' => $comments->author,
  104. 'mail' => $comments->mail,
  105. 'url' => $comments->url,
  106. 'ip' => $comments->ip,
  107. 'type' => $comments->type,
  108. 'text' => $comments->text
  109. );
  110. echo htmlspecialchars(json_encode($comment));
  111. ?>">
  112. <td valign="top" class="kit-hidden-mb">
  113. <input type="checkbox" value="<?php $comments->coid(); ?>" name="coid[]"/>
  114. </td>
  115. <td valign="top" class="kit-hidden-mb">
  116. <div class="comment-avatar">
  117. <?php if ('comment' == $comments->type): ?>
  118. <?php $comments->gravatar(40); ?>
  119. <?php endif; ?>
  120. <?php if ('comment' != $comments->type): ?>
  121. <?php _e('引用'); ?>
  122. <?php endif; ?>
  123. </div>
  124. </td>
  125. <td valign="top" class="comment-head">
  126. <div class="comment-meta">
  127. <strong class="comment-author"><?php $comments->author(true); ?></strong>
  128. <?php if($comments->mail): ?>
  129. <br /><span><a href="<?php $comments->mail(true); ?>"><?php $comments->mail(); ?></a></span>
  130. <?php endif; ?>
  131. <?php if($comments->ip): ?>
  132. <br /><span><?php $comments->ip(); ?></span>
  133. <?php endif; ?>
  134. </div>
  135. </td>
  136. <td valign="top" class="comment-body">
  137. <div class="comment-date"><?php $comments->dateWord(); ?> 于 <a href="<?php $comments->permalink(); ?>"><?php $comments->title(); ?></a></div>
  138. <div class="comment-content">
  139. <?php $comments->content(); ?>
  140. </div>
  141. <div class="comment-action hidden-by-mouse">
  142. <?php if('approved' == $comments->status): ?>
  143. <span class="weak"><?php _e('通过'); ?></span>
  144. <?php else: ?>
  145. <a href="<?php $security->index('/action/comments-edit?do=approved&coid=' . $comments->coid); ?>" class="operate-approved"><?php _e('通过'); ?></a>
  146. <?php endif; ?>
  147. <?php if('waiting' == $comments->status): ?>
  148. <span class="weak"><?php _e('待审核'); ?></span>
  149. <?php else: ?>
  150. <a href="<?php $security->index('/action/comments-edit?do=waiting&coid=' . $comments->coid); ?>" class="operate-waiting"><?php _e('待审核'); ?></a>
  151. <?php endif; ?>
  152. <?php if('spam' == $comments->status): ?>
  153. <span class="weak"><?php _e('垃圾'); ?></span>
  154. <?php else: ?>
  155. <a href="<?php $security->index('/action/comments-edit?do=spam&coid=' . $comments->coid); ?>" class="operate-spam"><?php _e('垃圾'); ?></a>
  156. <?php endif; ?>
  157. <a href="#<?php $comments->theId(); ?>" rel="<?php $security->index('/action/comments-edit?do=edit&coid=' . $comments->coid); ?>" class="operate-edit"><?php _e('编辑'); ?></a>
  158. <?php if('approved' == $comments->status && 'comment' == $comments->type): ?>
  159. <a href="#<?php $comments->theId(); ?>" rel="<?php $security->index('/action/comments-edit?do=reply&coid=' . $comments->coid); ?>" class="operate-reply"><?php _e('回复'); ?></a>
  160. <?php endif; ?>
  161. <a lang="<?php _e('你确认要删除%s的评论吗?', htmlspecialchars($comments->author)); ?>" href="<?php $security->index('/action/comments-edit?do=delete&coid=' . $comments->coid); ?>" class="operate-delete"><?php _e('删除'); ?></a>
  162. </div>
  163. </td>
  164. </tr>
  165. <?php endwhile; ?>
  166. <?php else: ?>
  167. <tr>
  168. <td colspan="4"><h6 class="typecho-list-table-title"><?php _e('没有评论') ?></h6></td>
  169. </tr>
  170. <?php endif; ?>
  171. </tbody>
  172. </table><!-- end .typecho-list-table -->
  173. </div><!-- end .typecho-table-wrap -->
  174. <?php if(isset($request->cid)): ?>
  175. <input type="hidden" value="<?php echo $request->filter('html')->cid; ?>" name="cid" />
  176. <?php endif; ?>
  177. </form><!-- end .operate-form -->
  178. <div class="typecho-list-operate clearfix">
  179. <form method="get">
  180. <div class="operate">
  181. <label><i class="sr-only"><?php _e('全选'); ?></i><input type="checkbox" class="typecho-table-select-all" /></label>
  182. <div class="btn-group btn-drop">
  183. <button class="btn dropdown-toggle btn-s" type="button"><i class="sr-only"><?php _e('操作'); ?></i><?php _e('选中项'); ?> <i class="i-caret-down"></i></button>
  184. <ul class="dropdown-menu">
  185. <li><a href="<?php $security->index('/action/comments-edit?do=approved'); ?>"><?php _e('通过'); ?></a></li>
  186. <li><a href="<?php $security->index('/action/comments-edit?do=waiting'); ?>"><?php _e('待审核'); ?></a></li>
  187. <li><a href="<?php $security->index('/action/comments-edit?do=spam'); ?>"><?php _e('标记垃圾'); ?></a></li>
  188. <li><a lang="<?php _e('你确认要删除这些评论吗?'); ?>" href="<?php $security->index('/action/comments-edit?do=delete'); ?>"><?php _e('删除'); ?></a></li>
  189. </ul>
  190. <?php if('spam' == $request->get('status')): ?>
  191. <button lang="<?php _e('你确认要删除所有垃圾评论吗?'); ?>" class="btn btn-s btn-warn btn-operate" href="<?php $security->index('/action/comments-edit?do=delete-spam'); ?>"><?php _e('删除所有垃圾评论'); ?></button>
  192. <?php endif; ?>
  193. </div>
  194. </div>
  195. <?php if($comments->have()): ?>
  196. <ul class="typecho-pager">
  197. <?php $comments->pageNav(); ?>
  198. </ul>
  199. <?php endif; ?>
  200. </form>
  201. </div><!-- end .typecho-list-operate -->
  202. </div><!-- end .typecho-list -->
  203. </div><!-- end .typecho-page-main -->
  204. </div>
  205. </div>
  206. <?php
  207. include 'copyright.php';
  208. include 'common-js.php';
  209. include 'table-js.php';
  210. ?>
  211. <script type="text/javascript">
  212. $(document).ready(function () {
  213. // 记住滚动条
  214. function rememberScroll () {
  215. $(window).bind('beforeunload', function () {
  216. $.cookie('__typecho_comments_scroll', $('body').scrollTop());
  217. });
  218. }
  219. // 自动滚动
  220. (function () {
  221. var scroll = $.cookie('__typecho_comments_scroll');
  222. if (scroll) {
  223. $.cookie('__typecho_comments_scroll', null);
  224. $('html, body').scrollTop(scroll);
  225. }
  226. })();
  227. $('.operate-delete').click(function () {
  228. var t = $(this), href = t.attr('href'), tr = t.parents('tr');
  229. if (confirm(t.attr('lang'))) {
  230. tr.fadeOut(function () {
  231. rememberScroll();
  232. window.location.href = href;
  233. });
  234. }
  235. return false;
  236. });
  237. $('.operate-approved, .operate-waiting, .operate-spam').click(function () {
  238. rememberScroll();
  239. window.location.href = $(this).attr('href');
  240. return false;
  241. });
  242. $('.operate-reply').click(function () {
  243. var td = $(this).parents('td'), t = $(this);
  244. if ($('.comment-reply', td).length > 0) {
  245. $('.comment-reply').remove();
  246. } else {
  247. var form = $('<form method="post" action="'
  248. + t.attr('rel') + '" class="comment-reply">'
  249. + '<p><label for="text" class="sr-only"><?php _e('内容'); ?></label><textarea id="text" name="text" class="w-90 mono" rows="3"></textarea></p>'
  250. + '<p><button type="submit" class="btn btn-s primary"><?php _e('回复'); ?></button> <button type="button" class="btn btn-s cancel"><?php _e('取消'); ?></button></p>'
  251. + '</form>').insertBefore($('.comment-action', td));
  252. $('.cancel', form).click(function () {
  253. $(this).parents('.comment-reply').remove();
  254. });
  255. var textarea = $('textarea', form).focus();
  256. form.submit(function () {
  257. var t = $(this), tr = t.parents('tr'),
  258. reply = $('<div class="comment-reply-content"></div>').insertAfter($('.comment-content', tr));
  259. var html = DOMPurify.sanitize(textarea.val(), {USE_PROFILES: {html: true}});
  260. reply.html('<p>' + html + '</p>');
  261. $.post(t.attr('action'), t.serialize(), function (o) {
  262. var html = DOMPurify.sanitize(o.comment.content, {USE_PROFILES: {html: true}});
  263. reply.html(html)
  264. .effect('highlight');
  265. }, 'json');
  266. t.remove();
  267. return false;
  268. });
  269. }
  270. return false;
  271. });
  272. $('.operate-edit').click(function () {
  273. var tr = $(this).parents('tr'), t = $(this), id = tr.attr('id'), comment = tr.data('comment');
  274. tr.hide();
  275. var edit = $('<tr class="comment-edit"><td> </td>'
  276. + '<td colspan="2" valign="top"><form method="post" action="'
  277. + t.attr('rel') + '" class="comment-edit-info">'
  278. + '<p><label for="' + id + '-author"><?php _e('用户名'); ?></label><input class="text-s w-100" id="'
  279. + id + '-author" name="author" type="text"></p>'
  280. + '<p><label for="' + id + '-mail"><?php _e('电子邮箱'); ?></label>'
  281. + '<input class="text-s w-100" type="email" name="mail" id="' + id + '-mail"></p>'
  282. + '<p><label for="' + id + '-url"><?php _e('个人主页'); ?></label>'
  283. + '<input class="text-s w-100" type="text" name="url" id="' + id + '-url"></p></form></td>'
  284. + '<td valign="top"><form method="post" action="'
  285. + t.attr('rel') + '" class="comment-edit-content"><p><label for="' + id + '-text"><?php _e('内容'); ?></label>'
  286. + '<textarea name="text" id="' + id + '-text" rows="6" class="w-90 mono"></textarea></p>'
  287. + '<p><button type="submit" class="btn btn-s primary"><?php _e('提交'); ?></button> '
  288. + '<button type="button" class="btn btn-s cancel"><?php _e('取消'); ?></button></p></form></td></tr>')
  289. .data('id', id).data('comment', comment).insertAfter(tr);
  290. $('input[name=author]', edit).val(comment.author);
  291. $('input[name=mail]', edit).val(comment.mail);
  292. $('input[name=url]', edit).val(comment.url);
  293. $('textarea[name=text]', edit).val(comment.text).focus();
  294. $('.cancel', edit).click(function () {
  295. var tr = $(this).parents('tr');
  296. $('#' + tr.data('id')).show();
  297. tr.remove();
  298. });
  299. $('form', edit).submit(function () {
  300. var t = $(this), tr = t.parents('tr'),
  301. oldTr = $('#' + tr.data('id')),
  302. comment = oldTr.data('comment');
  303. $('form', tr).each(function () {
  304. var items = $(this).serializeArray();
  305. for (var i = 0; i < items.length; i ++) {
  306. var item = items[i];
  307. comment[item.name] = item.value;
  308. }
  309. });
  310. var unsafeHTML = '<strong class="comment-author">'
  311. + (comment.url ? '<a target="_blank" href="' + comment.url + '">'
  312. + comment.author + '</a>' : comment.author) + '</strong>'
  313. + ('comment' != comment.type ? '<small><?php _e('引用'); ?></small>' : '')
  314. + (comment.mail ? '<br /><span><a href="mailto:' + comment.mail + '">'
  315. + comment.mail + '</a></span>' : '')
  316. + (comment.ip ? '<br /><span>' + comment.ip + '</span>' : '');
  317. var html = DOMPurify.sanitize(unsafeHTML, {USE_PROFILES: {html: true}});
  318. var content = DOMPurify.sanitize(comment.text, {USE_PROFILES: {html: true}});
  319. $('.comment-meta', oldTr).html(html)
  320. .effect('highlight');
  321. $('.comment-content', oldTr).html('<p>' + content + '</p>');
  322. oldTr.data('comment', comment);
  323. $.post(t.attr('action'), comment, function (o) {
  324. var content = DOMPurify.sanitize(o.comment.content, {USE_PROFILES: {html: true}});
  325. $('.comment-content', oldTr).html('<p>' + content + '</p>')
  326. .effect('highlight');
  327. }, 'json');
  328. oldTr.show();
  329. tr.remove();
  330. return false;
  331. });
  332. return false;
  333. });
  334. });
  335. </script>
  336. <?php
  337. include 'footer.php';
  338. ?>