archive.php 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168
  1. <?php
  2. requirePHPLib('form');
  3. if (!UOJContext::userid())
  4. $blogs_cond = "is_draft = false";
  5. else
  6. $blogs_cond = "poster = '".UOJContext::userid()."' and is_draft = false";
  7. if (!UOJContext::hasBlogPermission()) {
  8. $blogs_cond .= " and is_hidden = false";
  9. }
  10. $display_blogs_cond = $blogs_cond;
  11. if (isset($_GET['tag'])) {
  12. $blog_tag_required = $_GET['tag'];
  13. $display_blogs_cond .= " and '".DB::escape($blog_tag_required)."' in (select tag from blogs_tags where blogs_tags.blog_id = blogs.id)";
  14. } else {
  15. $blog_tag_required = null;
  16. }
  17. $blogs_pag = new Paginator(array(
  18. 'col_names' => array('*'),
  19. 'table_name' => 'blogs',
  20. 'cond' => $display_blogs_cond,
  21. 'tail' => 'order by post_time desc',
  22. 'page_len' => 10
  23. ));
  24. $all_tags = DB::selectAll("select distinct tag from blogs_tags where blog_id in (select id from blogs where $blogs_cond)");
  25. requireLib('mathjax');
  26. requireLib('hljs');
  27. ?>
  28. <?php echoUOJPageHeader('日志') ?>
  29. <div class="row">
  30. <div class="col-12 col-lg-9">
  31. <div class="blog-list">
  32. <?php if (!$blog_tag_required): ?>
  33. <?php if ($blogs_pag->isEmpty()): ?>
  34. <div class="text-muted">此人很懒,什么博客也没留下。</div>
  35. <?php else: ?>
  36. <?php foreach ($blogs_pag->get() as $blog): ?>
  37. <?php echoBlog($blog, array('is_preview' => true)) ?>
  38. <?php endforeach ?>
  39. <?php endif ?>
  40. <?php else: ?>
  41. <?php if ($blogs_pag->isEmpty()): ?>
  42. <div class="alert alert-danger">
  43. 没有找到包含 “<?= HTML::escape($blog_tag_required) ?>” 标签的博客:
  44. </div>
  45. <?php else: ?>
  46. <div class="alert alert-success" style="">
  47. 共找到 <?= $blogs_pag->n_rows ?> 篇包含 “<?= HTML::escape($blog_tag_required) ?>” 标签的博客:
  48. </div>
  49. <?php foreach ($blogs_pag->get() as $blog): ?>
  50. <?php echoBlog($blog, array('is_preview' => true)) ?>
  51. <?php endforeach ?>
  52. <?php endif ?>
  53. <?php endif ?>
  54. </div>
  55. <div id="blog-feed-loading" class="wyoj-blog-feed-loading text-center text-muted top-buffer-sm" style="display: none;">
  56. <span class="spinner-border spinner-border-sm align-middle" role="status" aria-hidden="true"></span>
  57. <span class="align-middle ml-2">正在加载…</span>
  58. </div>
  59. <div id="blog-feed-end" class="text-center text-muted top-buffer-sm" style="display: none;">没有更多了</div>
  60. <div id="blog-feed-error" class="text-center top-buffer-sm" style="display: none;">
  61. <span class="text-danger">加载失败</span>
  62. <a href="#" id="blog-feed-retry" class="ml-2">重试</a>
  63. </div>
  64. </div>
  65. <div class="col-12 col-lg-3">
  66. <?php uojIncludeView('blog-sidebar', array(
  67. 'owner' => UOJContext::userid(),
  68. 'show_write_buttons' => true,
  69. 'show_tags' => true,
  70. 'all_tags' => $all_tags
  71. )) ?>
  72. </div>
  73. </div>
  74. <script>
  75. (function () {
  76. let currentPage = 1, isLoading = false, hasMore = true, failed = false;
  77. const blogList = document.querySelector('.blog-list');
  78. const itemSelector = '.blog-item';
  79. const tag = (new URLSearchParams(window.location.search)).get('tag');
  80. const feedBase = window.location.pathname;
  81. const loadingEl = document.getElementById('blog-feed-loading');
  82. const endEl = document.getElementById('blog-feed-end');
  83. const errorEl = document.getElementById('blog-feed-error');
  84. const retryEl = document.getElementById('blog-feed-retry');
  85. const initialItems = blogList.querySelectorAll(itemSelector).length;
  86. if (initialItems < 10)
  87. hasMore = false;
  88. if (!hasMore && initialItems > 0)
  89. endEl.style.display = 'block';
  90. function bindExpand(item) {
  91. const content = item.querySelector('.blog-content');
  92. if (!content) return;
  93. content.addEventListener('click', (e) => {
  94. if (e.target && e.target.closest && e.target.closest('a')) return;
  95. content.classList.add('uoj-clamp-open');
  96. });
  97. }
  98. document.querySelectorAll(itemSelector).forEach(bindExpand);
  99. async function loadPage(page) {
  100. if (isLoading || !hasMore || failed) return;
  101. isLoading = true;
  102. errorEl.style.display = 'none';
  103. loadingEl.style.display = 'block';
  104. const url = !tag ? `${feedBase}?page=${page}` : `${feedBase}?page=${page}&tag=${encodeURIComponent(tag)}`;
  105. try {
  106. const resp = await fetch(url);
  107. if (!resp.ok) throw new Error('HTTP ' + resp.status);
  108. const html = await resp.text();
  109. const parser = new DOMParser();
  110. const doc = parser.parseFromString(html, 'text/html');
  111. const items = doc.querySelectorAll(itemSelector);
  112. if (items.length == 0) {
  113. hasMore = false;
  114. } else {
  115. items.forEach(item => { blogList.appendChild(item); bindExpand(item); });
  116. currentPage = page;
  117. if (items.length < 10)
  118. hasMore = false;
  119. MathJax.Hub.Queue(["Typeset", MathJax.Hub]);
  120. hljs.highlightAll();
  121. $('body').uoj_highlight();
  122. }
  123. } catch (err) {
  124. failed = true;
  125. console.log('加载失败', err);
  126. } finally {
  127. isLoading = false;
  128. loadingEl.style.display = 'none';
  129. if (failed) {
  130. errorEl.style.display = 'block';
  131. } else if (!hasMore) {
  132. endEl.style.display = 'block';
  133. }
  134. }
  135. }
  136. retryEl.addEventListener('click', (e) => {
  137. e.preventDefault();
  138. if (isLoading) return;
  139. failed = false;
  140. errorEl.style.display = 'none';
  141. loadPage(currentPage + 1);
  142. });
  143. window.addEventListener('scroll', () => {
  144. if (isLoading || !hasMore || failed) return;
  145. const scrollTop = document.documentElement.scrollTop;
  146. const windowHeight = window.innerHeight;
  147. const docHeight = document.documentElement.scrollHeight;
  148. if (scrollTop + windowHeight >= docHeight - 200)
  149. loadPage(currentPage + 1);
  150. });
  151. })();
  152. </script>
  153. <?php echoUOJPageFooter() ?>