summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--assets/css/like-button.css151
-rw-r--r--assets/js/like-button.js109
-rw-r--r--layouts/partials/components/like-button.html260
3 files changed, 270 insertions, 250 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/partials/components/like-button.html b/layouts/partials/components/like-button.html
index aa665453..b377bf78 100644
--- a/layouts/partials/components/like-button.html
+++ b/layouts/partials/components/like-button.html
@@ -9,255 +9,15 @@
</div>
</div>
-<script>
-(function() {
- const pageId = "{{ .File.UniqueID | urlize }}";
- const countEl = document.getElementById("like-count-" + pageId);
- const btnEl = document.getElementById("like-btn-" + pageId);
- const containerEl = document.getElementById("like-container-" + pageId);
-
- 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;
+<!-- 内嵌CSS样式 -->
+{{ with resources.Get "css/like-button.css" | minify }}
+<style>{{ .Content | safeCSS }}</style>
+{{ end }}
- if (window.location.hostname !== 'localhost') {
- 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();
-})();
+<!-- 设置页面ID并内嵌JavaScript -->
+<script>
+ window.likeButtonPageId = "{{ .File.UniqueID | urlize }}";
</script>
-
-<style>
-.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);
- }
-}
-</style>
+{{ with resources.Get "js/like-button.js" | minify }}
+<script>{{ .Content | safeJS }}</script>
+{{ end }}