summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEltrac <hi@guhub.cn>2025-06-20 00:44:00 +0800
committerEltrac <hi@guhub.cn>2025-06-20 00:44:00 +0800
commita8bb91eb500e6c45c1f33c27be6b70f1b0d5ba22 (patch)
treefa0807894fc986874cd7e7bb1d12fcf75edcc2a6
parentb97b6638ff00134a7a1fa06225983443861dd447 (diff)
parente276f3a456980c64a80eb5cc29567703f4268fb7 (diff)
Merge branch 'master' of https://github.com/BigCoke233/geek-death-project
-rw-r--r--assets/css/like-button.css151
-rw-r--r--assets/js/like-button.js109
-rw-r--r--layouts/fictions/single.html1
-rw-r--r--layouts/partials/components/like-button.html23
-rw-r--r--layouts/posts/single.html1
-rw-r--r--static/img/heart-organ.svg2
6 files changed, 287 insertions, 0 deletions
diff --git a/assets/css/like-button.css b/assets/css/like-button.css
new file mode 100644
index 00000000..8c347b6c
--- /dev/null
+++ b/assets/css/like-button.css
@@ -0,0 +1,151 @@
+.floating-like-container {
+ position: fixed;
+ bottom: 30px;
+ right: 30px;
+ z-index: 1000;
+ opacity: 0.3;
+ transition: all 0.3s ease;
+}
+
+.floating-like-container:hover {
+ opacity: 1;
+}
+
+.floating-like-container.near-comments {
+ opacity: 0.6;
+ animation: gentle-shake 2s ease-in-out infinite;
+}
+
+.floating-like-container.near-comments:hover {
+ opacity: 1;
+ animation: none;
+}
+
+/* 已点赞状态:保持最高不透明度,不再晃动 */
+.floating-like-container.liked {
+ opacity: 1 !important;
+}
+
+.floating-like-container.liked.near-comments {
+ animation: none !important;
+}
+
+.floating-like-button {
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ cursor: pointer;
+ background: none;
+ border: none;
+ padding: 8px;
+ transition: all 0.3s ease;
+ position: relative;
+}
+
+.floating-like-button:hover {
+ transform: scale(1.1);
+}
+
+/* 已点赞状态下禁用hover放大效果 */
+.liked .floating-like-button:hover {
+ transform: none;
+}
+
+.floating-like-button.clicked {
+ transform: scale(0.9);
+}
+
+.floating-like-button:disabled {
+ cursor: not-allowed;
+}
+
+#like-button-icon {
+ width: 32px;
+ height: 32px;
+ transition: all 0.3s ease;
+ filter: drop-shadow(0 2px 4px rgba(0,0,0,0.2));
+}
+
+.liked #like-button-icon {
+ filter: brightness(0) saturate(100%) invert(8%) sepia(100%) saturate(7500%) hue-rotate(0deg) brightness(70%) contrast(150%) drop-shadow(0 2px 4px rgba(0,0,0,0.2));
+ animation: heartbeat 1.5s ease-in-out infinite;
+}
+
+.like-count-display {
+ margin-top: 4px;
+ font-size: 12px;
+ font-weight: bold;
+ color: var(--secondary-text-color);
+ text-align: center;
+ min-width: 20px;
+ 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 .like-count-display {
+ color: #8B0000;
+}
+
+/* 悬浮提示样式 */
+.floating-like-button::before {
+ content: attr(title);
+ position: absolute;
+ bottom: 100%;
+ right: 0;
+ 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;
+ transform: translateY(5px);
+ transition: all 0.3s ease;
+ pointer-events: none;
+ margin-bottom: 8px;
+}
+
+.floating-like-button:hover::before {
+ opacity: 1;
+ visibility: visible;
+ transform: translateY(0);
+}
+
+/* 动画定义 */
+@keyframes gentle-shake {
+ 0%, 100% { transform: translateX(0); }
+ 25% { transform: translateX(-2px); }
+ 75% { transform: translateX(2px); }
+}
+
+@keyframes heartbeat {
+ 0%, 100% { transform: scale(1); }
+ 25% { transform: scale(1.1); }
+ 50% { transform: scale(1.2); }
+ 75% { transform: scale(1.1); }
+}
+
+/* 移动端适配 */
+@media screen and (max-width: 768px) {
+ .floating-like-container {
+ bottom: 20px;
+ right: 20px;
+ }
+
+ #like-button-icon {
+ width: 28px;
+ height: 28px;
+ }
+
+ .floating-like-button::before {
+ right: -10px;
+ transform: translateX(50%) translateY(5px);
+ }
+
+ .floating-like-button:hover::before {
+ transform: translateX(50%) translateY(0);
+ }
+} \ No newline at end of file
diff --git a/assets/js/like-button.js b/assets/js/like-button.js
new file mode 100644
index 00000000..e03e5447
--- /dev/null
+++ b/assets/js/like-button.js
@@ -0,0 +1,109 @@
+(function() {
+ // 获取页面ID(需要在HTML中设置)
+ const pageId = window.likeButtonPageId;
+ if (!pageId) {
+ console.error('Like button: pageId not found');
+ 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) {
+ console.error('Like button: required elements not found');
+ return;
+ }
+
+ let isNearComments = false;
+
+ function checkScrollPosition() {
+ const commentsSection = document.querySelector('.post-comments');
+ if (!commentsSection) return;
+
+ const rect = commentsSection.getBoundingClientRect();
+ const windowHeight = window.innerHeight;
+
+ // 当评论区进入视窗下半部分时触发
+ const shouldHighlight = rect.top < windowHeight * 0.8;
+
+ if (shouldHighlight !== isNearComments) {
+ isNearComments = shouldHighlight;
+ // 如果已经点赞,不添加 near-comments 类(避免晃动)
+ if (containerEl.classList.contains('liked')) {
+ return;
+ }
+
+ if (isNearComments) {
+ containerEl.classList.add('near-comments');
+ } else {
+ containerEl.classList.remove('near-comments');
+ }
+ }
+ }
+
+ 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");
+ // 移除可能存在的 near-comments 类
+ containerEl.classList.remove('near-comments');
+ 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');
+ }
+ }
+
+ // 添加点击效果
+ btnEl.classList.add("clicked");
+ setTimeout(() => {
+ btnEl.classList.remove("clicked");
+ }, 300);
+
+ 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");
+ // 移除 near-comments 类,停止晃动
+ containerEl.classList.remove('near-comments');
+ updateTooltip();
+ })
+ .catch(() => {
+ alert("点赞失败,请稍后再试");
+ });
+ };
+
+ // 监听滚动事件
+ window.addEventListener('scroll', checkScrollPosition);
+ window.addEventListener('resize', checkScrollPosition);
+
+ // 初始化
+ fetchLikes();
+ checkScrollPosition();
+})(); \ No newline at end of file
diff --git a/layouts/fictions/single.html b/layouts/fictions/single.html
index 83db7d60..e503f901 100644
--- a/layouts/fictions/single.html
+++ b/layouts/fictions/single.html
@@ -21,6 +21,7 @@
</div>
<!-- Comment -->
+ {{ partial "components/like-button.html" . }}
{{ partial "components/comment.html" . }}
</article>
{{ end }}
diff --git a/layouts/partials/components/like-button.html b/layouts/partials/components/like-button.html
new file mode 100644
index 00000000..b377bf78
--- /dev/null
+++ b/layouts/partials/components/like-button.html
@@ -0,0 +1,23 @@
+<div class="floating-like-container" id="like-container-{{ .File.UniqueID | urlize }}">
+ <div class="floating-like-button"
+ onclick="sendLike('{{ .File.UniqueID | urlize }}')"
+ id="like-btn-{{ .File.UniqueID | urlize }}"
+ title="为这篇文章献上心脏"
+ data-liked-title="你已经献上心脏了">
+ <img id="like-button-icon" src="/img/heart-organ.svg" alt="点赞" />
+ <div class="like-count-display" id="like-count-{{ .File.UniqueID | urlize }}">...</div>
+ </div>
+</div>
+
+<!-- 内嵌CSS样式 -->
+{{ with resources.Get "css/like-button.css" | minify }}
+<style>{{ .Content | safeCSS }}</style>
+{{ end }}
+
+<!-- 设置页面ID并内嵌JavaScript -->
+<script>
+ window.likeButtonPageId = "{{ .File.UniqueID | urlize }}";
+</script>
+{{ with resources.Get "js/like-button.js" | minify }}
+<script>{{ .Content | safeJS }}</script>
+{{ end }}
diff --git a/layouts/posts/single.html b/layouts/posts/single.html
index 7a7051f0..5b69c403 100644
--- a/layouts/posts/single.html
+++ b/layouts/posts/single.html
@@ -37,6 +37,7 @@
</div>
<!-- Comment -->
+ {{ partial "components/like-button.html" . }}
{{ partial "components/comment.html" . }}
<!-- Now Read This -->
{{ partial "components/now-read-this.html" . }}
diff --git a/static/img/heart-organ.svg b/static/img/heart-organ.svg
new file mode 100644
index 00000000..0b218639
--- /dev/null
+++ b/static/img/heart-organ.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="M289.188 22.72c-6.5.162-12.792 2.26-17.594 7.124-.483.488-.916.983-1.344 1.5l-.188-.188c-17.848 22.67-35.71 51.21-45.718 83.094-11.197 35.67-12.8 74.75 5.687 114.78l-16.968 7.845c-14.305-30.974-17.807-61.916-14.53-90.97-8.475 4.99-16.412 11.178-23.688 18.314-22.368-29.2-49.978-56.593-76.5-76-1.404-1.4-2.996-2.655-4.813-3.69-3.378-1.922-6.98-2.86-10.624-3.03-.38-.018-.745-.032-1.125-.03-.38 0-.774.016-1.155.03-5.33.203-10.67 1.93-15.438 4.563-8.72 4.816-16.545 12.77-22.5 22.937-5.954 10.168-9.036 20.86-8.906 30.78.132 9.922 3.896 20.06 12.907 25.19.368.208.753.375 1.126.56l-.126.25c27.298 16.83 63.364 39.376 86.626 67.626-6.582 22.99-7.837 46.735-2.625 67.406 15.303 60.707 62.425 115.8 113.03 150.657 25.304 17.427 51.403 29.785 74.22 35.5 22.816 5.713 41.874 4.546 53.906-2.658 27.152-16.25 45.328-45.636 56.312-80.53-6.824 4.01-14.074 7.32-21.625 9.874-35.777 12.102-78.105 8.732-113.624-10.062-35.52-18.794-64.105-53.724-70.53-103.22l18.53-2.405c5.673 43.69 29.907 72.772 60.75 89.092 30.844 16.32 68.41 19.18 98.875 8.875 30.465-10.304 53.67-32.64 59.033-68.906 4.434-29.985-3.865-70.527-33.844-121.374-19.14 2.18-38.67 6.368-56.626 11.563l-5.188-17.94c12.73-3.682 26.192-6.87 39.875-9.28 2.63.22 5.328.024 8.033-.72 1.02-.28 1.996-.63 2.937-1.03.032-.005.062-.027.094-.03-.005-.008.004-.025 0-.032 8.222-3.55 13.437-11.472 15.906-20.032 2.76-9.57 2.698-20.724-.28-32.125-2.98-11.4-8.362-21.14-15.47-28.06-5.33-5.193-12.214-9.005-19.53-9.44-2.236-.13-4.497.065-6.783.626l-.093-.406c-16.036 5.84-33.733 13.757-51 24.125-8.947 11.378-15.964 22.483-20.5 33.375-7.047 16.92-8.512 33.12-2.438 51.438l-17.72 5.906c-7.46-22.5-5.505-44.333 2.908-64.53 7.425-17.828 19.73-34.594 34.656-51.376l-.156-.157c.622-.507 1.232-1.036 1.812-1.624 7.286-7.377 8.24-18.11 5.844-27.78-2.395-9.67-8.032-19.274-16.313-27.657l-.062-.032c-8.27-8.358-17.777-14.095-27.375-16.532-2.404-.61-4.868-.992-7.344-1.125-.464-.024-.942-.055-1.406-.06-.435-.007-.88-.012-1.313 0zm.656 18.624c.36 0 .755 0 1.156.03 1.07.084 2.28.308 3.656.657 5.51 1.4 12.564 5.332 18.72 11.564 6.154 6.23 10.07 13.385 11.468 19.03 1.398 5.647.36 8.778-1 10.157-1.362 1.38-4.27 2.37-9.78.97-5.512-1.4-12.565-5.362-18.72-11.594-6.155-6.23-10.07-13.385-11.47-19.03-1.398-5.647-.36-8.747 1-10.126.895-.905 2.445-1.648 4.97-1.656zm-208.156 58.78c1.09.03 1.962.298 2.593.657 1.685.96 3.395 3.504 3.47 9.19.075 5.684-1.918 13.503-6.344 21.06-4.426 7.56-10.314 13.22-15.406 16.032-5.092 2.813-8.378 2.615-10.063 1.657-1.684-.96-3.393-3.504-3.468-9.19-.076-5.684 1.916-13.535 6.343-21.093 4.426-7.557 10.314-13.187 15.406-16 2.545-1.406 4.643-2.064 6.31-2.25.418-.046.794-.072 1.157-.062zm109.937 1.282c-13 .075-26.444 5.487-34 14.125 6.848 7.143 13.47 14.445 19.78 21.876 7.846-5.784 16.262-10.73 25.19-14.594 1.14-4.79 2.448-9.514 3.905-14.156.432-1.375.887-2.73 1.344-4.094-4.97-2.18-10.548-3.188-16.22-3.156zm203.125 15.78c.272-.02.57-.02.875 0 1.826.14 4.258 1.214 7.313 4.19 4.072 3.966 8.222 10.9 10.437 19.374 2.215 8.474 2.018 16.63.406 22.22-1.61 5.588-4.068 7.798-5.936 8.31-1.87.514-4.865-.095-8.938-4.06-4.072-3.968-8.223-10.902-10.437-19.376-2.216-8.474-2.02-16.63-.408-22.22 1.612-5.588 4.07-7.798 5.938-8.31.234-.066.478-.106.75-.126z"/></svg> \ No newline at end of file