|
@@ -34,27 +34,8 @@
|
|
|
<?php echoUOJPageHeader('日志') ?>
|
|
<?php echoUOJPageHeader('日志') ?>
|
|
|
|
|
|
|
|
<div class="row">
|
|
<div class="row">
|
|
|
- <div class="col-md-3">
|
|
|
|
|
- <?php if (UOJContext::hasBlogPermission()): ?>
|
|
|
|
|
- <div class="btn-group d-flex">
|
|
|
|
|
- <a href="<?=HTML::blog_url(UOJContext::userid(), '/post/new/write')?>" class="btn btn-primary"><span class="glyphicon glyphicon-edit"></span> 写新博客</a>
|
|
|
|
|
- <a href="<?=HTML::blog_url(UOJContext::userid(), '/slide/new/write')?>" class="btn btn-primary"><span class="glyphicon glyphicon-edit"></span> 写新幻灯片</a>
|
|
|
|
|
- </div>
|
|
|
|
|
- <?php endif ?>
|
|
|
|
|
- <div class="card top-buffer-sm">
|
|
|
|
|
- <div class="card-header">标签</div>
|
|
|
|
|
- <div class="card-body">
|
|
|
|
|
- <?php if ($all_tags): ?>
|
|
|
|
|
- <?php foreach ($all_tags as $tag): ?>
|
|
|
|
|
- <?php echoBlogTag($tag['tag']) ?>
|
|
|
|
|
- <?php endforeach ?>
|
|
|
|
|
- <?php else: ?>
|
|
|
|
|
- <div class="text-muted">暂无</div>
|
|
|
|
|
- <?php endif ?>
|
|
|
|
|
- </div>
|
|
|
|
|
- </div>
|
|
|
|
|
- </div>
|
|
|
|
|
- <div class="col-md-9 blog-list">
|
|
|
|
|
|
|
+ <div class="col-12 col-lg-9">
|
|
|
|
|
+ <div class="blog-list">
|
|
|
<?php if (!$blog_tag_required): ?>
|
|
<?php if (!$blog_tag_required): ?>
|
|
|
<?php if ($blogs_pag->isEmpty()): ?>
|
|
<?php if ($blogs_pag->isEmpty()): ?>
|
|
|
<div class="text-muted">此人很懒,什么博客也没留下。</div>
|
|
<div class="text-muted">此人很懒,什么博客也没留下。</div>
|
|
@@ -62,7 +43,6 @@
|
|
|
<?php foreach ($blogs_pag->get() as $blog): ?>
|
|
<?php foreach ($blogs_pag->get() as $blog): ?>
|
|
|
<?php echoBlog($blog, array('is_preview' => true)) ?>
|
|
<?php echoBlog($blog, array('is_preview' => true)) ?>
|
|
|
<?php endforeach ?>
|
|
<?php endforeach ?>
|
|
|
-<div class="text-right text-muted" style="display: none;">共 <?= $blogs_pag->n_rows ?> 篇博客</div>
|
|
|
|
|
<?php endif ?>
|
|
<?php endif ?>
|
|
|
<?php else: ?>
|
|
<?php else: ?>
|
|
|
<?php if ($blogs_pag->isEmpty()): ?>
|
|
<?php if ($blogs_pag->isEmpty()): ?>
|
|
@@ -78,87 +58,111 @@
|
|
|
<?php endforeach ?>
|
|
<?php endforeach ?>
|
|
|
<?php endif ?>
|
|
<?php endif ?>
|
|
|
<?php endif ?>
|
|
<?php endif ?>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ <div id="blog-feed-loading" class="wyoj-blog-feed-loading text-center text-muted top-buffer-sm" style="display: none;">
|
|
|
|
|
+ <span class="spinner-border spinner-border-sm align-middle" role="status" aria-hidden="true"></span>
|
|
|
|
|
+ <span class="align-middle ml-2">正在加载…</span>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ <div id="blog-feed-end" class="text-center text-muted top-buffer-sm" style="display: none;">没有更多了</div>
|
|
|
|
|
+ <div id="blog-feed-error" class="text-center top-buffer-sm" style="display: none;">
|
|
|
|
|
+ <span class="text-danger">加载失败</span>
|
|
|
|
|
+ <a href="#" id="blog-feed-retry" class="ml-2">重试</a>
|
|
|
|
|
+ </div>
|
|
|
</div>
|
|
</div>
|
|
|
- <script>
|
|
|
|
|
- (function () {
|
|
|
|
|
- let currentPage = 1, isLoading = false, hasMore = true;
|
|
|
|
|
- const blogList = document.querySelector('.blog-list');
|
|
|
|
|
- const itemSelector = '.blog-item';
|
|
|
|
|
- const tag = (new URLSearchParams(window.location.search)).get('tag');
|
|
|
|
|
-
|
|
|
|
|
- if (blogList.querySelectorAll('.blog-item').length < 10)
|
|
|
|
|
- hasMore = false;
|
|
|
|
|
-
|
|
|
|
|
- function extractSummary(html) {
|
|
|
|
|
- const div = document.createElement('div');
|
|
|
|
|
- div.innerHTML = html;
|
|
|
|
|
- let text = div.textContent || div.innerText || '';
|
|
|
|
|
- text = text.replace(/\s+/g, ' ').trim();
|
|
|
|
|
- return text;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- function collapseArticle(post) {
|
|
|
|
|
- const content = post.querySelector('.blog-content');
|
|
|
|
|
- const divorig = post.querySelector('.blog-content-orig');
|
|
|
|
|
- const divsummary = post.querySelector('.blog-content-summary');
|
|
|
|
|
-
|
|
|
|
|
- let summary = extractSummary(divorig.innerHTML);
|
|
|
|
|
- const maxLen = 150;
|
|
|
|
|
-
|
|
|
|
|
- if (summary.length < maxLen) return;
|
|
|
|
|
- summary = summary.slice(0, maxLen) + '……';
|
|
|
|
|
- divsummary.innerHTML = summary;
|
|
|
|
|
|
|
+ <div class="col-12 col-lg-3">
|
|
|
|
|
+ <?php uojIncludeView('blog-sidebar', array(
|
|
|
|
|
+ 'owner' => UOJContext::userid(),
|
|
|
|
|
+ 'show_write_buttons' => true,
|
|
|
|
|
+ 'show_tags' => true,
|
|
|
|
|
+ 'all_tags' => $all_tags
|
|
|
|
|
+ )) ?>
|
|
|
|
|
+ </div>
|
|
|
|
|
+</div>
|
|
|
|
|
+<script>
|
|
|
|
|
+ (function () {
|
|
|
|
|
+ let currentPage = 1, isLoading = false, hasMore = true, failed = false;
|
|
|
|
|
+ const blogList = document.querySelector('.blog-list');
|
|
|
|
|
+ const itemSelector = '.blog-item';
|
|
|
|
|
+ const tag = (new URLSearchParams(window.location.search)).get('tag');
|
|
|
|
|
+ const feedBase = window.location.pathname;
|
|
|
|
|
+ const loadingEl = document.getElementById('blog-feed-loading');
|
|
|
|
|
+ const endEl = document.getElementById('blog-feed-end');
|
|
|
|
|
+ const errorEl = document.getElementById('blog-feed-error');
|
|
|
|
|
+ const retryEl = document.getElementById('blog-feed-retry');
|
|
|
|
|
|
|
|
- divsummary.style.display = 'block';
|
|
|
|
|
- divorig.style.display = 'none';
|
|
|
|
|
- content.classList.add('collapsed');
|
|
|
|
|
|
|
+ const initialItems = blogList.querySelectorAll(itemSelector).length;
|
|
|
|
|
+ if (initialItems < 10)
|
|
|
|
|
+ hasMore = false;
|
|
|
|
|
+ if (!hasMore && initialItems > 0)
|
|
|
|
|
+ endEl.style.display = 'block';
|
|
|
|
|
|
|
|
- content.addEventListener('click', () => {
|
|
|
|
|
- divsummary.style.display = 'none';
|
|
|
|
|
- divorig.style.display = 'block';
|
|
|
|
|
- content.classList.remove('collapsed');
|
|
|
|
|
- content.classList.add('expand');
|
|
|
|
|
- });
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ function bindExpand(item) {
|
|
|
|
|
+ const content = item.querySelector('.blog-content');
|
|
|
|
|
+ if (!content) return;
|
|
|
|
|
+ content.addEventListener('click', (e) => {
|
|
|
|
|
+ if (e.target && e.target.closest && e.target.closest('a')) return;
|
|
|
|
|
+ content.classList.add('uoj-clamp-open');
|
|
|
|
|
+ });
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
- document.querySelectorAll('.blog-item').forEach(collapseArticle);
|
|
|
|
|
|
|
+ document.querySelectorAll(itemSelector).forEach(bindExpand);
|
|
|
|
|
|
|
|
- async function loadPage(page) {
|
|
|
|
|
- if (isLoading || !hasMore) return;
|
|
|
|
|
- isLoading = true;
|
|
|
|
|
|
|
+ async function loadPage(page) {
|
|
|
|
|
+ if (isLoading || !hasMore || failed) return;
|
|
|
|
|
+ isLoading = true;
|
|
|
|
|
+ errorEl.style.display = 'none';
|
|
|
|
|
+ loadingEl.style.display = 'block';
|
|
|
|
|
|
|
|
- const url = !tag ? `/?page=${page}` : `/?page=${page}&tag=${tag}`;
|
|
|
|
|
- try {
|
|
|
|
|
- const resp = await fetch(url);
|
|
|
|
|
- const html = await resp.text();
|
|
|
|
|
- const parser = new DOMParser();
|
|
|
|
|
- const doc = parser.parseFromString(html, 'text/html');
|
|
|
|
|
- const items = doc.querySelectorAll(itemSelector);
|
|
|
|
|
- if (items.length == 0) {
|
|
|
|
|
- hasMore = false;
|
|
|
|
|
- return;
|
|
|
|
|
- }
|
|
|
|
|
- items.forEach(item => { blogList.appendChild(item); collapseArticle(item); });
|
|
|
|
|
|
|
+ const url = !tag ? `${feedBase}?page=${page}` : `${feedBase}?page=${page}&tag=${encodeURIComponent(tag)}`;
|
|
|
|
|
+ try {
|
|
|
|
|
+ const resp = await fetch(url);
|
|
|
|
|
+ if (!resp.ok) throw new Error('HTTP ' + resp.status);
|
|
|
|
|
+ const html = await resp.text();
|
|
|
|
|
+ const parser = new DOMParser();
|
|
|
|
|
+ const doc = parser.parseFromString(html, 'text/html');
|
|
|
|
|
+ const items = doc.querySelectorAll(itemSelector);
|
|
|
|
|
+ if (items.length == 0) {
|
|
|
|
|
+ hasMore = false;
|
|
|
|
|
+ } else {
|
|
|
|
|
+ items.forEach(item => { blogList.appendChild(item); bindExpand(item); });
|
|
|
|
|
+ currentPage = page;
|
|
|
if (items.length < 10)
|
|
if (items.length < 10)
|
|
|
hasMore = false;
|
|
hasMore = false;
|
|
|
|
|
|
|
|
MathJax.Hub.Queue(["Typeset", MathJax.Hub]);
|
|
MathJax.Hub.Queue(["Typeset", MathJax.Hub]);
|
|
|
hljs.highlightAll();
|
|
hljs.highlightAll();
|
|
|
$('body').uoj_highlight();
|
|
$('body').uoj_highlight();
|
|
|
- } catch (err) {
|
|
|
|
|
- console.log('加载失败', err);
|
|
|
|
|
- } finally {
|
|
|
|
|
- isLoading = false;
|
|
|
|
|
|
|
+ }
|
|
|
|
|
+ } catch (err) {
|
|
|
|
|
+ failed = true;
|
|
|
|
|
+ console.log('加载失败', err);
|
|
|
|
|
+ } finally {
|
|
|
|
|
+ isLoading = false;
|
|
|
|
|
+ loadingEl.style.display = 'none';
|
|
|
|
|
+ if (failed) {
|
|
|
|
|
+ errorEl.style.display = 'block';
|
|
|
|
|
+ } else if (!hasMore) {
|
|
|
|
|
+ endEl.style.display = 'block';
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
- window.addEventListener('scroll', () => {
|
|
|
|
|
- const scrollTop = document.documentElement.scrollTop;
|
|
|
|
|
- const windowHeight = window.innerHeight;
|
|
|
|
|
- const docHeight = document.documentElement.scrollHeight;
|
|
|
|
|
- if (scrollTop + windowHeight >= docHeight - 200 && !isLoading && hasMore)
|
|
|
|
|
- loadPage(++currentPage);
|
|
|
|
|
- });
|
|
|
|
|
- })();
|
|
|
|
|
- </script>
|
|
|
|
|
-</div>
|
|
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ retryEl.addEventListener('click', (e) => {
|
|
|
|
|
+ e.preventDefault();
|
|
|
|
|
+ if (isLoading) return;
|
|
|
|
|
+ failed = false;
|
|
|
|
|
+ errorEl.style.display = 'none';
|
|
|
|
|
+ loadPage(currentPage + 1);
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ window.addEventListener('scroll', () => {
|
|
|
|
|
+ if (isLoading || !hasMore || failed) return;
|
|
|
|
|
+ const scrollTop = document.documentElement.scrollTop;
|
|
|
|
|
+ const windowHeight = window.innerHeight;
|
|
|
|
|
+ const docHeight = document.documentElement.scrollHeight;
|
|
|
|
|
+ if (scrollTop + windowHeight >= docHeight - 200)
|
|
|
|
|
+ loadPage(currentPage + 1);
|
|
|
|
|
+ });
|
|
|
|
|
+ })();
|
|
|
|
|
+</script>
|
|
|
<?php echoUOJPageFooter() ?>
|
|
<?php echoUOJPageFooter() ?>
|