diff --git a/content/post/2026-01-31-Artalk接入AI摘要/index.md b/content/post/2026-01-31-Artalk接入AI摘要/index.md index 7ab72d8f..22021478 100644 --- a/content/post/2026-01-31-Artalk接入AI摘要/index.md +++ b/content/post/2026-01-31-Artalk接入AI摘要/index.md @@ -88,27 +88,38 @@ async function processFiles(dir) { window.artalk.on('list-loaded', function() { // 检查是否有 AI 评论数据 if (window.artalkConfig.aiComment && !document.querySelector('.atk-ai-comment')) { - // 创建 DOM 结构 - var aiDiv = document.createElement('div'); - aiDiv.className = 'atk-comment atk-ai-comment'; - aiDiv.innerHTML = `...`; // 填充 HTML + var listBody = document.querySelector('.atk-list-body') || document.querySelector('.atk-list'); + + if (listBody) { + // 避免同时出现“此时无声胜有声” + var noComment = document.querySelector('.atk-list-no-comment'); + if (noComment) noComment.style.display = 'none'; - // 插入到列表头部 - var listBody = document.querySelector('.atk-list-body'); - if (listBody) listBody.prepend(aiDiv); - - // 简单的打字机效果 - const contentEl = aiDiv.querySelector('.ai-content-text'); - const text = window.artalkConfig.aiComment.content; - let i = 0; - function type() { - if (i < text.length) { - contentEl.textContent += text.charAt(i); - i++; - setTimeout(type, Math.random() * 30 + 20); - } + // 创建 DOM 结构 + var aiDiv = document.createElement('div'); + aiDiv.className = 'atk-comment atk-ai-comment'; + aiDiv.innerHTML = `...`; // 填充 HTML + + // 插入到列表头部 + listBody.prepend(aiDiv); + + // ... (打字机效果) } - setTimeout(type, 500); + } +}); +``` + +## 4. 适配 PJAX + +由于博客使用了 PJAX,页面切换时需要重新初始化 Artalk。我们将初始化逻辑封装在 `initArtalk` 函数中,并在 `pjax:complete` 事件中调用。 + +```javascript +// mypjax.js +document.addEventListener("pjax:complete", function () { + // ... + // 重载评论 + if (typeof window.initArtalk === 'function') { + window.initArtalk(); } }); ``` diff --git a/themes/Ying/assets/css/main.css b/themes/Ying/assets/css/main.css index dc292d66..1a1e6970 100644 --- a/themes/Ying/assets/css/main.css +++ b/themes/Ying/assets/css/main.css @@ -196,8 +196,102 @@ code { background-color: #f6f8fa; /* Day Mode */ color: #24292e; border: 1px solid #d0d7de; + /* Hide scrollbar but allow scrolling */ + scrollbar-width: none; /* Firefox */ + -ms-overflow-style: none; /* IE 10+ */ } +pre::-webkit-scrollbar, +code::-webkit-scrollbar { + display: none; /* Chrome/Safari/Webkit */ +} + +/* Code Folding */ +.code-fold-container { + position: relative; + margin-bottom: 1rem; + border-radius: 4px; /* Optional: match highlight radius */ +} + +.code-fold-container.collapsed { + max-height: 360px; + overflow: hidden; +} + +/* Ensure inner code blocks don't have bottom margin when wrapped */ +.code-fold-container .highlight, +.code-fold-container pre { + margin-bottom: 0; +} + +.code-expand-btn { + display: none; + position: absolute; + bottom: -7px; + left: -146px; + width: 100%; + height: 80px; + text-align: center; + /* Gradient Background for Fade Effect */ + background: linear-gradient(180deg, rgba(246, 248, 250, 0) 0%, rgba(246, 248, 250, 0.9) 50%, rgba(246, 248, 250, 1) 100%); + border: none; + color: #586069; + cursor: pointer; + z-index: 10; + font-size: 13px; + transition: all 0.2s; + align-items: center; + justify-content: center; + padding-top: 20px; +} + +/* Show button when collapsed */ +.code-fold-container.collapsed .code-expand-btn { + display: flex; +} + +/* Button Pill Style */ +.code-expand-btn span { + background: rgba(255, 255, 255, 0.9); + padding: 6px 16px; + border-radius: 20px; + box-shadow: 0 2px 8px rgba(0,0,0,0.08); + display: flex; + align-items: center; + border: 1px solid rgba(0,0,0,0.05); + transition: all 0.2s ease; +} + +.code-expand-btn:hover span { + background: #fff; + transform: translateY(-2px); + box-shadow: 0 4px 12px rgba(0,0,0,0.12); + color: #0366d6; +} + +/* Dark Mode Support */ +[data-theme="dark"] .code-expand-btn { + background: linear-gradient(180deg, rgba(40, 42, 54, 0) 0%, rgba(40, 42, 54, 0.9) 50%, rgba(40, 42, 54, 1) 100%); + color: #f8f8f2; +} + +[data-theme="dark"] .code-expand-btn span { + background: rgba(68, 71, 90, 0.8); + border-color: rgba(255,255,255,0.05); +} + +[data-theme="dark"] .code-expand-btn:hover span { + background: #44475a; + color: #8be9fd; +} + +/* Artalk AI Comment Integration */ +.atk-list.has-ai-comment .atk-list-no-comment { + display: none !important; +} + + + [data-theme="dark"] pre, [data-theme="dark"] code { background-color: #282a36; /* Night Mode */ diff --git a/themes/Ying/assets/js/main.js b/themes/Ying/assets/js/main.js index d695a415..cb39be35 100644 --- a/themes/Ying/assets/js/main.js +++ b/themes/Ying/assets/js/main.js @@ -114,12 +114,19 @@ window.initArtalk = function() { // Inject AI Comment window.artalk.on('list-loaded', function() { - if (window.artalkConfig.aiComment && !document.querySelector('.atk-ai-comment')) { - var listBody = document.querySelector('.atk-list-body') || document.querySelector('.atk-list'); - if (listBody) { - var aiData = window.artalkConfig.aiComment; - var aiDiv = document.createElement('div'); - aiDiv.className = 'atk-comment atk-ai-comment'; + if (window.artalkConfig.aiComment) { + // Force hide "No comments" message via CSS class + var list = document.querySelector('.atk-list'); + if (list) { + list.classList.add('has-ai-comment'); + } + + if (!document.querySelector('.atk-ai-comment')) { + var listBody = document.querySelector('.atk-list-body') || document.querySelector('.atk-list'); + if (listBody) { + var aiData = window.artalkConfig.aiComment; + var aiDiv = document.createElement('div'); + aiDiv.className = 'atk-comment atk-ai-comment'; // Initially empty content for typewriter effect aiDiv.innerHTML = `
@@ -158,7 +165,8 @@ window.initArtalk = function() { setTimeout(type, 500); } } - }); + } +}); // Artalk 初始化完成后,再加载弹幕 (If available) if (typeof isMobile === 'function' && !isMobile() && window.loadBarrager) { @@ -190,7 +198,7 @@ function initCodeCopy() { const copyBtn = document.createElement('button'); copyBtn.className = 'copy-code-btn'; - copyBtn.innerHTML = ''; // 使用 FontAwesome 图标 + copyBtn.innerHTML = ''; // 使用 RemixIcon copyBtn.title = '复制代码'; // 样式 (建议放到 CSS 文件中) @@ -218,15 +226,15 @@ function initCodeCopy() { copyBtn.addEventListener('click', () => { const code = codeBlock.innerText; navigator.clipboard.writeText(code).then(() => { - copyBtn.innerHTML = ''; + copyBtn.innerHTML = ''; setTimeout(() => { - copyBtn.innerHTML = ''; + copyBtn.innerHTML = ''; }, 2000); Qmsg.success("代码复制成功"); }).catch(err => { console.error('复制失败:', err); - copyBtn.innerHTML = ''; + copyBtn.innerHTML = ''; Qmsg.error("复制失败"); }); }); @@ -235,11 +243,73 @@ function initCodeCopy() { }); } -// 页面加载完成后初始化 (Merged into main DOMContentLoaded listener) -// document.addEventListener('DOMContentLoaded', function() { -// initCodeCopy(); -// initDescriptionHitokoto(); -// }); +// 代码折叠功能 +function initCodeFold() { + const threshold = 360; + + // Helper to wrap element + const wrap = (el, wrapper) => { + el.parentNode.insertBefore(wrapper, el); + wrapper.appendChild(el); + }; + + // 1. Process .highlight blocks (Hugo generated) + document.querySelectorAll('.highlight').forEach(hl => { + if (hl.closest('.code-fold-container')) return; // Avoid double processing + + // Check height + if (hl.scrollHeight > threshold) { + const wrapper = document.createElement('div'); + wrapper.className = 'code-fold-container collapsed'; + + // Wrap the highlight block + wrap(hl, wrapper); + + const btn = document.createElement('button'); + btn.className = 'code-expand-btn'; + // Use FontAwesome for reliability + btn.innerHTML = ' 展开代码'; + + btn.addEventListener('click', () => { + wrapper.classList.remove('collapsed'); + btn.remove(); + }); + + wrapper.appendChild(btn); + } + }); + + // 2. Process bare pre blocks (Fallback) + document.querySelectorAll('.post-content > pre').forEach(pre => { + if (pre.parentNode.classList.contains('highlight')) return; + if (pre.closest('.code-fold-container')) return; + if (pre.closest('.code-wrapper')) return; // Old wrapper check + + if (pre.scrollHeight > threshold) { + const wrapper = document.createElement('div'); + wrapper.className = 'code-fold-container collapsed'; + + wrap(pre, wrapper); + + const btn = document.createElement('button'); + btn.className = 'code-expand-btn'; + btn.innerHTML = ' 展开代码'; + + btn.addEventListener('click', () => { + wrapper.classList.remove('collapsed'); + btn.remove(); + }); + wrapper.appendChild(btn); + } + }); +} + +// 页面加载完成后初始化 +document.addEventListener('DOMContentLoaded', function() { + initCodeCopy(); + initCodeFold(); + initDescriptionHitokoto(); +}); // 初始化个人描述一言切换 function initDescriptionHitokoto() { diff --git a/themes/Ying/assets/js/mypjax.js b/themes/Ying/assets/js/mypjax.js index 44b99d6c..1af4f842 100644 --- a/themes/Ying/assets/js/mypjax.js +++ b/themes/Ying/assets/js/mypjax.js @@ -175,6 +175,8 @@ document.addEventListener("pjax:complete", function () { pjax_reload() // 初始化代码复制 initCodeCopy() + // 初始化代码折叠 + initCodeFold() // 重载评论 if (typeof window.initArtalk === 'function') { window.initArtalk();