diff options
| author | Eltrac <hi@guhub.cn> | 2025-06-27 21:02:06 +0800 |
|---|---|---|
| committer | Eltrac <hi@guhub.cn> | 2025-06-27 21:02:06 +0800 |
| commit | 0e81bee435826e4209cf1033f521b63ad3bafcc1 (patch) | |
| tree | d6be1298ff5222a8c30c2bc7456c26f923b51dd9 | |
| parent | b83a498655b954384213b1ec02db8adc9eb0db3a (diff) | |
feat: add post action tabs with like and comment features
| -rw-r--r-- | assets/css/components/_post.scss | 2 | ||||
| -rw-r--r-- | layouts/partials/components/comment.html | 15 | ||||
| -rw-r--r-- | layouts/partials/components/post-tabs.html | 362 | ||||
| -rw-r--r-- | layouts/posts/single.html | 5 | ||||
| -rw-r--r-- | static/img/coffee.svg | 2 | ||||
| -rw-r--r-- | static/img/comments.svg | 16 | ||||
| -rw-r--r-- | static/img/paper-plane.svg | 15 |
7 files changed, 399 insertions, 18 deletions
diff --git a/assets/css/components/_post.scss b/assets/css/components/_post.scss index d1a2d151..d6f8ab3a 100644 --- a/assets/css/components/_post.scss +++ b/assets/css/components/_post.scss @@ -97,7 +97,7 @@ /* related posts */ .nrt { - margin-top: 5rem; + margin-top: 2rem; padding-bottom: 2rem; /* in case nrt-title overlaps */ position: relative; .nrt-title { diff --git a/layouts/partials/components/comment.html b/layouts/partials/components/comment.html index 13fff97e..804570bc 100644 --- a/layouts/partials/components/comment.html +++ b/layouts/partials/components/comment.html @@ -25,16 +25,6 @@ {{ T "postPage.commentNotLoaded" }} </p> </div> - {{ if eq .Site.Language.Lang "zh" }} - <p class="links-container"> - <a href="https://t.me/teaparty418" target="_blank" - data-umami-event="✈️ Click Telegram link from comment footer"> - <img src="/img/telegram.svg" alt="Telegram Logo" /> - 加入 Telegram 群组参与讨论 - </a> - <a href="/sponsor" data-umami-event="💗 Click sponsor button from comment footer"><span>💗</span>赞助作者</a> - </p> - {{ end }} <!-- giscus script --> <script id="giscus-script" src="https://giscus.app/client.js" @@ -45,11 +35,10 @@ data-mapping="{{ .Site.Params.giscus.mapping }}" data-strict="{{ .Site.Params.giscus.strict }}" data-reactions-enabled="{{ .Site.Params.giscus.reactionsEnabled }}" - data-emit-metadata="{{ .Site.Params.giscus.emitMetadata }}" + data-emit-metadata="1" data-input-position="{{ .Site.Params.giscus.inputPosition }}" data-theme="{{ .Site.Params.giscus.theme }}" data-lang="{{ T "lang" }}" - crossorigin="anonymous" - async> + crossorigin="anonymous"> </script> </div> diff --git a/layouts/partials/components/post-tabs.html b/layouts/partials/components/post-tabs.html new file mode 100644 index 00000000..cb377fe4 --- /dev/null +++ b/layouts/partials/components/post-tabs.html @@ -0,0 +1,362 @@ +<div class="post-actions-container"> + <!-- 操作按钮组 --> + <div class="post-actions-nav"> + <div class="left-actions"> + <button class="action-btn" id="comments-toggle" title="评论"> + <img src="/img/comments.svg" width="20" height="20" alt="评论" class="icon" /> + <span class="count-badge" id="comment-count">...</span> + </button> + + <!-- 点赞按钮 --> + <div class="like-button-container" id="like-container-{{ .File.UniqueID | urlize }}"> + <button class="action-btn like-btn" + onclick="sendLike('{{ .File.UniqueID | urlize }}')" + id="like-btn-{{ .File.UniqueID | urlize }}" + title="为这篇文章献上心脏" + data-liked-title="你已经献上心脏了"> + <img src="/img/heart-organ.svg" width="20" height="20" alt="点赞" class="like-icon" /> + <span class="count-badge" id="like-count-{{ .File.UniqueID | urlize }}">...</span> + </button> + </div> + </div> + + <div class="right-actions"> + <a href="https://t.me/teaparty418" target="_blank" class="action-btn small-btn" title="Telegram 群组" data-umami-event="✈️ Click Telegram link from post tabs"> + <img src="/img/paper-plane.svg" width="16" height="16" alt="Telegram" class="icon" /> + </a> + <a href="/sponsor" class="action-btn small-btn" title="赞助作者" data-umami-event="💗 Click sponsor button from post tabs"> + <img src="/img/coffee.svg" width="16" height="16" alt="赞助" class="icon" /> + </a> + </div> + </div> + + <!-- 评论区域 --> + <div class="comments-section" id="comments-section" style="display: none;"> + {{ partial "components/comment.html" . }} + </div> +</div> + +<style> +.post-actions-container { + margin: 2rem 0 1rem 0; +} + +.post-actions-nav { + display: flex; + justify-content: space-between; + align-items: center; + margin-bottom: 1.5rem; +} + +.left-actions { + display: flex; + gap: 0.5rem; +} + +.right-actions { + display: flex; + gap: 0.25rem; +} + +.action-btn { + display: flex; + align-items: center; + justify-content: center; + gap: 6px; + min-width: 48px; + height: 48px; + padding: 0 8px; + border: none; + background: transparent; + color: #666; + cursor: pointer; + text-decoration: none; + position: relative; + transition: all 0.2s ease; +} + +.action-btn:hover { + background: rgba(0, 0, 0, 0.05); + border-radius: 8px; +} + +/* 右侧小按钮样式 */ +.small-btn { + min-width: 32px; + height: 32px; + padding: 0 4px; +} + +.small-btn:hover { + background: transparent; + opacity: 0.7; +} + +/* 图标样式 */ +.icon { + filter: invert(0.4); + flex-shrink: 0; +} + +/* Tooltip 样式 */ +.action-btn::before { + content: attr(title); + position: absolute; + bottom: 100%; + left: 50%; + transform: translateX(-50%) translateY(5px); + background: rgba(0, 0, 0, 0.8); + color: white; + padding: 6px 10px; + border-radius: 4px; + font-size: 12px; + white-space: nowrap; + opacity: 0; + visibility: hidden; + transition: all 0.3s ease; + pointer-events: none; + margin-bottom: 8px; + z-index: 1000; +} + +.action-btn:hover::before { + opacity: 1; + visibility: visible; + transform: translateX(-50%) translateY(0); +} + +.like-button-container { + position: relative; +} + +.like-icon { + filter: invert(0.4); + flex-shrink: 0; + transition: all 0.3s ease; +} + +.liked .like-icon { + filter: brightness(0) saturate(100%) invert(8%) sepia(100%) saturate(7500%) hue-rotate(0deg) brightness(70%) contrast(150%); + animation: heartbeat 1.5s ease-in-out infinite; +} + +.count-badge { + font-size: 12px; + font-weight: bold; + color: #666; + min-width: 16px; + text-align: center; + background: rgba(255, 255, 255, 0.9); + border-radius: 10px; + padding: 2px 6px; + box-shadow: 0 1px 3px rgba(0,0,0,0.1); +} + +.liked .count-badge { + color: #8B0000; +} + +.comments-section { + margin-top: 1rem; +} + +/* 心脏搏动动画 */ +@keyframes heartbeat { + 0%, 100% { transform: scale(1); } + 25% { transform: scale(1.1); } + 50% { transform: scale(1.2); } + 75% { transform: scale(1.1); } +} + +/* 暗色主题适配 */ +@media (prefers-color-scheme: dark) { + .action-btn { + color: #999; + } + + .action-btn:hover { + background: rgba(255, 255, 255, 0.05); + } + + .small-btn:hover { + background: transparent; + opacity: 0.7; + } + + /* 暗色模式下的图标滤镜 */ + .icon { + filter: invert(0.7) brightness(1.2); + } + + .like-icon { + filter: invert(0.7) brightness(1.2); + } + + .liked .like-icon { + filter: brightness(0) saturate(100%) invert(8%) sepia(100%) saturate(7500%) hue-rotate(0deg) brightness(70%) contrast(150%); + animation: heartbeat 1.5s ease-in-out infinite; + } + + .action-btn::before { + background: rgba(255, 255, 255, 0.9); + color: #000; + } + + .count-badge { + color: #999; + background: rgba(0, 0, 0, 0.7); + } +} + +/* 移动端适配 */ +@media (max-width: 768px) { + .post-actions-nav { + gap: 0.5rem; + } + + .left-actions { + gap: 0.5rem; + } + + .right-actions { + gap: 0.25rem; + } + + .action-btn { + min-width: 44px; + height: 44px; + padding: 0 6px; + } + + .small-btn { + min-width: 28px; + height: 28px; + padding: 0 2px; + } + + .action-btn::before { + left: 50%; + transform: translateX(-50%) translateY(5px); + } + + .action-btn:hover::before { + transform: translateX(-50%) translateY(0); + } +} +</style> + +<script> +// 评论展开/收起功能 +document.addEventListener('DOMContentLoaded', function() { + const commentsToggle = document.getElementById('comments-toggle'); + const commentsSection = document.getElementById('comments-section'); + + if (commentsToggle && commentsSection) { + commentsToggle.addEventListener('click', function() { + if (commentsSection.style.display === 'none') { + commentsSection.style.display = 'block'; + this.style.background = 'rgba(0, 0, 0, 0.1)'; + } else { + commentsSection.style.display = 'none'; + this.style.background = 'transparent'; + } + }); + } +}); + +// 获取 Giscus 评论数量 +function fetchGiscusCommentCount() { + const commentCountEl = document.getElementById('comment-count'); + if (!commentCountEl) return; + + // 设置初始值 + commentCountEl.textContent = '0'; + + // 监听 Giscus 的消息事件 + window.addEventListener('message', function(event) { + if (event.origin !== 'https://giscus.app') return; + + const giscusData = event.data; + + // 检查是否为 IMetadataMessage - 数据结构是 {giscus: {discussion: {...}}} + if (giscusData.giscus && giscusData.giscus.discussion) { + const discussion = giscusData.giscus.discussion; + + // 计算总评论数:主评论数 + 回复数 + const totalComments = (discussion.totalCommentCount || 0) + (discussion.totalReplyCount || 0); + commentCountEl.textContent = totalComments.toString(); + } + }); +} + +// 点赞功能 +(function() { + const pageId = "{{ .File.UniqueID | urlize }}"; + if (!pageId) { + return; + } + + const countEl = document.getElementById("like-count-" + pageId); + const btnEl = document.getElementById("like-btn-" + pageId); + const containerEl = document.getElementById("like-container-" + pageId); + + if (!countEl || !btnEl || !containerEl) { + return; + } + + function updateTooltip() { + if (containerEl.classList.contains('liked')) { + btnEl.setAttribute('title', btnEl.getAttribute('data-liked-title')); + } else { + btnEl.setAttribute('title', '为这篇文章献上心脏'); + } + } + + function fetchLikes() { + fetch("https://like.guhub.cn/like/" + pageId) + .then(resp => resp.json()) + .then(data => { + countEl.innerText = data.likes ?? 0; + if (localStorage.getItem("liked_" + pageId)) { + btnEl.disabled = true; + containerEl.classList.add("liked"); + updateTooltip(); + } + }) + .catch(() => { + countEl.innerText = "❌"; + }); + } + + window.sendLike = function(pageId) { + if (localStorage.getItem("liked_" + pageId)) return; + + if (window.location.hostname !== 'localhost') { + if (typeof umami !== 'undefined') { + umami.track('👍 Hit Like Button'); + } + } + + fetch("https://like.guhub.cn/like/" + pageId, { method: "POST" }) + .then(resp => resp.json()) + .then(data => { + localStorage.setItem("liked_" + pageId, "1"); + countEl.innerText = data.likes ?? 1; + btnEl.disabled = true; + containerEl.classList.add("liked"); + updateTooltip(); + }) + .catch(() => { + alert("点赞失败,请稍后再试"); + }); + }; + + // 初始化 + fetchLikes(); +})(); + +// 初始化评论数量获取 +document.addEventListener('DOMContentLoaded', function() { + fetchGiscusCommentCount(); +}); +</script>
\ No newline at end of file diff --git a/layouts/posts/single.html b/layouts/posts/single.html index 5b69c403..94f9be6f 100644 --- a/layouts/posts/single.html +++ b/layouts/posts/single.html @@ -36,10 +36,7 @@ {{ partial "components/endnotes" . }} </div> - <!-- Comment --> - {{ partial "components/like-button.html" . }} - {{ partial "components/comment.html" . }} - <!-- Now Read This --> + {{ partial "components/post-tabs.html" . }} {{ partial "components/now-read-this.html" . }} </article> {{ end }} diff --git a/static/img/coffee.svg b/static/img/coffee.svg new file mode 100644 index 00000000..e3633def --- /dev/null +++ b/static/img/coffee.svg @@ -0,0 +1,2 @@ +<?xml version="1.0" encoding="utf-8"?><!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools --> +<svg width="800px" height="800px" viewBox="0 0 512 512" xmlns="http://www.w3.org/2000/svg"><path fill="#000000" d="M221.97 54.406c-40.375 0-77.013 8.01-104.345 21.563C90.293 89.52 70.937 109.51 70.937 134c0 2.57.213 5.094.626 7.563l-.032 5.875c-.555 82.898 16.25 164.612 14.97 244.718-.372 23.295 14.294 43.908 38 57.594s56.797 21.5 97.125 21.5c40.357 0 71.338-8.024 92.906-22.03 21.57-14.008 33.408-34.712 33.408-56.908 0-3.17.054-6.345.125-9.53 42.143-1.114 75.316-23.45 97.125-52.563 22.235-29.684 34.027-66.306 34.687-99.626.66-33.32-9.983-66.91-39.156-80.594-14.588-6.842-30.593-6.573-49.25-1.125-6.16 1.798-12.548 4.25-19.126 7.375.07-2.93.125-5.86.125-8.75v-6.72c.33-2.214.5-4.484.5-6.78 0-24.49-19.357-44.478-46.69-58.03-27.33-13.554-63.937-21.564-104.31-21.564zm0 18.688c37.87 0 72.087 7.752 96.03 19.625 23.943 11.87 36.28 26.974 36.28 41.28 0 14.306-12.337 29.44-36.28 41.313-23.943 11.87-58.16 19.593-96.03 19.593-37.87 0-72.09-7.722-96.032-19.594-23.943-11.87-36.313-27.006-36.313-41.312 0-14.306 12.37-29.41 36.313-41.28 23.942-11.874 58.16-19.626 96.03-19.626zm-69.657 39.03c-23.19 6.707-37.907 16.684-37.907 27.814 0 20.193 48.398 36.562 108.094 36.562 59.696 0 108.063-16.37 108.063-36.563 0-10.264-12.52-19.546-32.657-26.187 5.266 4.105 8.22 8.692 8.22 13.563 0 17.186-36.765 31.124-82.126 31.124-45.36 0-82.125-13.938-82.125-31.125 0-5.518 3.788-10.693 10.438-15.187zm263.312 68.282c4.34-.023 7.825.793 10.53 2.063 10.826 5.076 18.406 22.81 17.908 48.124-.5 25.313-9.714 55.51-26.844 78.375-16.296 21.75-38.106 36.352-67.126 37.905 4.352-49.843 14.23-100.49 19.28-147.844 20.724-13.842 35.894-18.567 46.25-18.624z"/></svg>
\ No newline at end of file diff --git a/static/img/comments.svg b/static/img/comments.svg new file mode 100644 index 00000000..8860c78e --- /dev/null +++ b/static/img/comments.svg @@ -0,0 +1,16 @@ +<?xml version="1.0" encoding="iso-8859-1"?>
+<!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg fill="#000000" version="1.1" id="Capa_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
+ width="800px" height="800px" viewBox="0 0 254.782 254.782"
+ xml:space="preserve">
+<g>
+ <path d="M23.384,30.344c-33.205,22.27-28.035,55.087-3.307,80.888c5.724,5.974,12.032,10.995,18.701,15.515
+ c11.129,7.547,31.201,17.451,43.912,23.635c2.168,1.05,4.328,2.132,6.441,3.249c12.498,6.604,12.32,5.744,11.191-8.347
+ c-2.672-33.196,36.268-59.115,37.318-74.839c-0.047-14.875-2.589-26.581-7.045-35.688C112.593-2.032,63.408,3.499,23.384,30.344z"
+ />
+ <path d="M151.204,100.091c39.886-14.885,114.67,36.044,102.191,81.215c-6.757,24.447-29.922,37.67-51.754,46.772
+ c-13.549,5.648-33.401,8.855-49.907,15.039c-13.232,4.962-12.141,4.835-9.474-9.045c4.924-25.621-20.313-49.506-23.098-77.659
+ c-1.279-12.903,1.737-26.252,8.585-37.016C133.2,110.81,141.104,103.859,151.204,100.091z"/>
+</g>
+</svg>
\ No newline at end of file diff --git a/static/img/paper-plane.svg b/static/img/paper-plane.svg new file mode 100644 index 00000000..67fca9f1 --- /dev/null +++ b/static/img/paper-plane.svg @@ -0,0 +1,15 @@ +<?xml version="1.0" encoding="iso-8859-1"?>
+<!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
+<svg fill="#000000" height="800px" width="800px" version="1.1" id="Capa_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
+ viewBox="0 0 428.911 428.911" xml:space="preserve">
+<path d="M417.357,166.575C282.714,124.794,155.465,69.879,28.09,9.932c-9.982-4.697-19.105,2.212-20.878,10.33
+ c-6.866,3.392-10.21,12.619-3.75,20.223c0.118,0.14,0.244,0.274,0.366,0.414C5.2,57.972,21.851,82.359,27.767,94.353
+ c7.748,15.693,15.232,32.188,23.406,48.242c29.032,85.566,59.174,170.731,87.834,256.46c3.64,10.894,18.648,16.915,27.243,7.193
+ c16.072-18.177,33.112-34.867,50.547-51.106c19.546,17.273,40.978,34.392,64.168,47.092c2.387,3.411,4.207,7.065,6.74,10.415
+ c6.291,8.319,22.481,12.432,27.783,0c19.499-45.694,38.698-111.68,24.699-162.514c27.814-7.449,52.185-35.533,81.031-54.023
+ C433.019,188.547,430.864,170.766,417.357,166.575z M307.861,318.4c-2.221,17.749-6.602,34.94-11.794,51.919
+ c-12.361-18.032-23.115-37.032-33.168-56.538c2.229-1.822,4.199-3.819,6.452-5.627c7.134-5.725,5.767-17.771,0-23.7
+ c-65.416-67.25-129.227-136.049-193.466-204.432c24.887,14.526,49.27,29.922,73.106,46.408
+ c50.878,35.19,96.863,88.288,150.273,118.256c3.963,2.221,7.673,3.21,11.436,4.449C308.488,272.082,310.753,295.279,307.861,318.4z"
+ />
+</svg>
\ No newline at end of file |
