From fb590caf658ba61663604487e8b59e873d357a6c Mon Sep 17 00:00:00 2001 From: Donkey_kevin <2930705585@qq.com> Date: Wed, 13 May 2026 08:55:16 +0800 Subject: [PATCH 1/4] =?UTF-8?q?=E5=B0=8F=E5=AF=B9=E5=8B=BE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .claude/settings.local.json | 7 +++- docs/intro.md | 2 ++ docusaurus.config.js | 20 ++++++++++- src/css/custom.css | 67 +++++++++++++++++++++++++++++++++++++ 4 files changed, 94 insertions(+), 2 deletions(-) diff --git a/.claude/settings.local.json b/.claude/settings.local.json index 7e63862..54b446a 100644 --- a/.claude/settings.local.json +++ b/.claude/settings.local.json @@ -16,7 +16,12 @@ "Bash(git remote:*)", "Bash(ssh-keygen:*)", "Bash(ssh -T git@gitlink.org.cn)", - "Bash(git branch:*)" + "Bash(git branch:*)", + "Bash(where:*)", + "Bash(findstr :3000)", + "Bash(taskkill:*)", + "Bash(findstr LISTENING)", + "mcp__zai-mcp-server__analyze_image" ] } } diff --git a/docs/intro.md b/docs/intro.md index f8aec7a..204d0e2 100644 --- a/docs/intro.md +++ b/docs/intro.md @@ -21,6 +21,8 @@ GitLink(确实开源)是CCF官方指定的开源创新服务平台,旨在 # 帮助文档 帮助文档有助于您全面了解GitLink平台,让我们一起为开源创新贡献力量! + +
diff --git a/docusaurus.config.js b/docusaurus.config.js index 424ef17..3ec14c5 100644 --- a/docusaurus.config.js +++ b/docusaurus.config.js @@ -16,7 +16,13 @@ module.exports = { favicon: 'img/icon.ico', organizationName: 'luffyZh', // Usually your GitHub org/user name. projectName: 'docusaurus-luffyzh-website', // Usually your repo name. - scripts: [], + scripts: [ + { + src: '/js/reading-progress.js', + async: true, + defer: true, + }, + ], // stylesheets: ['styles/dark-mode.css'], themeConfig: { docs:{ @@ -176,6 +182,18 @@ module.exports = { // sidebarPath: require.resolve('./sidebars.js'), editUrl:'https://www.gitlink.org.cn/Gitlink/gitlink_help_center/tree/master/', routeBasePath: "/", + remarkPlugins: [ + async () => { + const { visit } = await import('unist-util-visit'); + return (tree) => { + visit(tree, 'mdxJsxFlowElement', (node) => { + if (node.name === 'ProgressPanel') { + node.attributes = node.attributes || []; + } + }); + }; + }, + ], }, theme: { customCss: require.resolve('./src/css/custom.css'), diff --git a/src/css/custom.css b/src/css/custom.css index 66c18c0..2d53b25 100644 --- a/src/css/custom.css +++ b/src/css/custom.css @@ -159,4 +159,71 @@ html[data-theme='dark'] .docusaurus-highlight-code-line { .cardContainer:hover { background-color: #cce0ff !important; box-shadow: 0 4px 12px rgba(70, 106, 255, 0.15); +} + +/* 阅读进度条 */ +.reading-progress { + position: fixed; + top: 0; + left: 0; + width: 100%; + height: 4px; + background-color: rgba(70, 106, 255, 0.1); + z-index: 9999; +} + +.reading-progress__bar { + height: 100%; + background: linear-gradient(90deg, #466aff, #6b8cff); + transition: width 0.15s ease-out; +} + +/* 侧边栏完成标记 */ +.sidebar-completed-badge { + display: inline-flex; + align-items: center; + justify-content: center; + width: 16px; + height: 16px; + background-color: #22c55e; + color: white; + border-radius: 50%; + font-size: 10px; + font-weight: bold; + flex-shrink: 0; +} + +/* 进度面板 */ +.progress-panel { + background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); + padding: 16px; + border-radius: 12px; + color: white; + margin-bottom: 16px; +} + +.progress-panel__title { + font-size: 14px; + font-weight: 600; + margin-bottom: 8px; +} + +.progress-panel__bar { + height: 8px; + background-color: rgba(255, 255, 255, 0.3); + border-radius: 4px; + overflow: hidden; + margin-bottom: 8px; +} + +.progress-panel__fill { + height: 100%; + background-color: #22c55e; + border-radius: 4px; + transition: width 0.3s ease; +} + +.progress-panel__text { + font-size: 12px; + opacity: 0.9; } \ No newline at end of file -- 2.34.1 From b572d5cc0282920dffdf56b202c5d356429c2b5a Mon Sep 17 00:00:00 2001 From: Donkey_kevin <2930705585@qq.com> Date: Wed, 13 May 2026 08:58:22 +0800 Subject: [PATCH 2/4] =?UTF-8?q?feat:=20=E6=B7=BB=E5=8A=A0=E6=96=87?= =?UTF-8?q?=E6=A1=A3=E9=98=85=E8=AF=BB=E8=BF=9B=E5=BA=A6=E8=BF=BD=E8=B8=AA?= =?UTF-8?q?=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 添加滚动进度自动检测,滚动到90%自动标记为已读 - 侧边栏显示已读文档绿色对勾标记 - 支持 localStorage 本地存储,刷新页面标记保留 - 自动处理 URL 编码路径问题 - 支持所有文档分类(快速开始、代码库、合并请求等) 🤖 Generated with [Claude Code](https://claude.com/claude-code) --- static/js/reading-progress.js | 118 ++++++++++++++++++++++++++++++++++ 1 file changed, 118 insertions(+) create mode 100644 static/js/reading-progress.js diff --git a/static/js/reading-progress.js b/static/js/reading-progress.js new file mode 100644 index 0000000..3b47085 --- /dev/null +++ b/static/js/reading-progress.js @@ -0,0 +1,118 @@ +// 超级简单的阅读进度追踪 - 直接在浏览器中运行 +(function() { + console.log('📚 阅读进度追踪已启动'); + + const PROGRESS_KEY = 'gitlink_help_center_progress'; + + // 获取已保存的进度 + function getProgress() { + try { + const stored = localStorage.getItem(PROGRESS_KEY); + return stored ? JSON.parse(stored) : {}; + } catch { + return {}; + } + } + + // 保存进度(解码URL) + function saveProgress(path) { + // 解码URL路径 + const decodedPath = decodeURIComponent(path); + const progress = getProgress(); + progress[decodedPath] = true; + localStorage.setItem(PROGRESS_KEY, JSON.stringify(progress)); + console.log('✅ 已保存:', decodedPath); + updateBadges(); + } + + // 检查是否已完成(支持多种路径格式) + function isCompleted(path) { + const progress = getProgress(); + const decodedPath = decodeURIComponent(path); + + // 检查多种可能的路径格式 + return Object.keys(progress).some(key => { + return key === path || key === decodedPath || + path.includes(key) || key.includes(path); + }); + } + + // 更新所有对勾标记 + function updateBadges() { + // 移除所有旧的对勾 + document.querySelectorAll('.reading-checkmark').forEach(el => el.remove()); + + // 找到所有侧边栏菜单链接 + const links = document.querySelectorAll('.menu__link, .menu-link, [class*="sidebar"] a, [class*="menu"] a'); + const progress = getProgress(); + + links.forEach(link => { + const href = link.getAttribute('href'); + if (href && href !== '#' && href !== '/' && !href.startsWith('http')) { + // 只处理文档链接,排除外部链接和锚点 + if (isCompleted(href)) { + // 添加绿色对勾 + const badge = document.createElement('span'); + badge.className = 'reading-checkmark'; + badge.innerHTML = '✓'; + badge.style.cssText = ` + color: #4caf50; + font-weight: bold; + font-size: 16px; + margin-left: 8px; + `; + link.appendChild(badge); + console.log('✓ 添加对勾:', link.textContent.trim(), '->', href); + } + } + }); + } + + // 滚动追踪 + let saved = false; + function trackScroll() { + if (saved) return; + + const scrollPercent = (window.scrollY / (document.documentElement.scrollHeight - window.innerHeight)) * 100; + + if (scrollPercent >= 90) { + const currentPath = window.location.pathname; + saveProgress(currentPath); + saved = true; + } + } + + // 节流函数 + let ticking = false; + function throttledTrack() { + if (!ticking) { + requestAnimationFrame(() => { + trackScroll(); + ticking = false; + }); + ticking = true; + } + } + + // 初始化 + window.addEventListener('scroll', throttledTrack); + + // 页面加载完成后更新对勾 + if (document.readyState === 'loading') { + document.addEventListener('DOMContentLoaded', updateBadges); + } else { + updateBadges(); + } + + // 监听页面变化(SPA路由) + const originalPushState = history.pushState; + history.pushState = function() { + originalPushState.apply(this, arguments); + setTimeout(() => { + saved = false; + updateBadges(); + }, 1000); + }; + + console.log('✅ 阅读进度追踪已就绪'); +})(); -- 2.34.1 From 6a196f192519a0c8b6c4aead0e20a2139f91b024 Mon Sep 17 00:00:00 2001 From: Donkey_kevin <2930705585@qq.com> Date: Wed, 13 May 2026 14:54:55 +0800 Subject: [PATCH 3/4] =?UTF-8?q?feat:=20=E6=B7=BB=E5=8A=A0=E6=96=87?= =?UTF-8?q?=E6=A1=A3=E9=98=85=E8=AF=BB=E8=BF=9B=E5=BA=A6=E8=BF=BD=E8=B8=AA?= =?UTF-8?q?=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 新增阅读进度条,显示页面滚动进度 - 实现侧边栏绿色小勾标记,标识已阅读文档 - 阅读记录保存在浏览器本地存储 - 支持中文路径的 URL 编码/解码 - 添加调试功能方便问题排查 Co-Authored-By: Claude Sonnet 4.6 --- docs/intro.md | 10 +- docusaurus.config.js | 20 ++- src/css/custom.css | 65 ++++++++ static/js/reading-progress.js | 271 ++++++++++++++++++++++++++++++++++ 4 files changed, 361 insertions(+), 5 deletions(-) create mode 100644 static/js/reading-progress.js diff --git a/docs/intro.md b/docs/intro.md index 73610ec..204d0e2 100644 --- a/docs/intro.md +++ b/docs/intro.md @@ -21,6 +21,8 @@ GitLink(确实开源)是CCF官方指定的开源创新服务平台,旨在 # 帮助文档 帮助文档有助于您全面了解GitLink平台,让我们一起为开源创新贡献力量! + +
@@ -32,7 +34,7 @@ GitLink(确实开源)是CCF官方指定的开源创新服务平台,旨在
diff --git a/docusaurus.config.js b/docusaurus.config.js index 424ef17..3ec14c5 100644 --- a/docusaurus.config.js +++ b/docusaurus.config.js @@ -16,7 +16,13 @@ module.exports = { favicon: 'img/icon.ico', organizationName: 'luffyZh', // Usually your GitHub org/user name. projectName: 'docusaurus-luffyzh-website', // Usually your repo name. - scripts: [], + scripts: [ + { + src: '/js/reading-progress.js', + async: true, + defer: true, + }, + ], // stylesheets: ['styles/dark-mode.css'], themeConfig: { docs:{ @@ -176,6 +182,18 @@ module.exports = { // sidebarPath: require.resolve('./sidebars.js'), editUrl:'https://www.gitlink.org.cn/Gitlink/gitlink_help_center/tree/master/', routeBasePath: "/", + remarkPlugins: [ + async () => { + const { visit } = await import('unist-util-visit'); + return (tree) => { + visit(tree, 'mdxJsxFlowElement', (node) => { + if (node.name === 'ProgressPanel') { + node.attributes = node.attributes || []; + } + }); + }; + }, + ], }, theme: { customCss: require.resolve('./src/css/custom.css'), diff --git a/src/css/custom.css b/src/css/custom.css index 8f02718..63fc4c4 100644 --- a/src/css/custom.css +++ b/src/css/custom.css @@ -160,7 +160,72 @@ html[data-theme='dark'] .docusaurus-highlight-code-line { background-color: #cce0ff !important; box-shadow: 0 4px 12px rgba(70, 106, 255, 0.15); } +/* 阅读进度条 */ +.reading-progress { + position: fixed; + top: 0; + left: 0; + width: 100%; + height: 4px; + background-color: rgba(70, 106, 255, 0.1); + z-index: 9999; +} +.reading-progress__bar { + height: 100%; + background: linear-gradient(90deg, #466aff, #6b8cff); + transition: width 0.15s ease-out; +} + +/* 侧边栏完成标记 */ +.sidebar-completed-badge { + display: inline-flex; + align-items: center; + justify-content: center; + width: 16px; + height: 16px; + background-color: #22c55e; + color: white; + border-radius: 50%; + font-size: 10px; + font-weight: bold; + flex-shrink: 0; +} + +/* 进度面板 */ +.progress-panel { + background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); + padding: 16px; + border-radius: 12px; + color: white; + margin-bottom: 16px; +} + +.progress-panel__title { + font-size: 14px; + font-weight: 600; + margin-bottom: 8px; +} + +.progress-panel__bar { + height: 8px; + background-color: rgba(255, 255, 255, 0.3); + border-radius: 4px; + overflow: hidden; + margin-bottom: 8px; +} + +.progress-panel__fill { + height: 100%; + background-color: #22c55e; + border-radius: 4px; + transition: width 0.3s ease; +} + +.progress-panel__text { + font-size: 12px; + opacity: 0.9; +} /* ===== 文档投票组件样式 ===== */ .vote-container { display: flex; diff --git a/static/js/reading-progress.js b/static/js/reading-progress.js new file mode 100644 index 0000000..8b3e62c --- /dev/null +++ b/static/js/reading-progress.js @@ -0,0 +1,271 @@ +(function() { + 'use strict'; + + const STORAGE_KEY = 'gitlink_reading_progress'; + const BADGE_CLASS = 'reading-progress-badge'; + + function getReadDocs() { + try { + const data = localStorage.getItem(STORAGE_KEY); + return data ? JSON.parse(data) : []; + } catch (e) { + console.error('读取进度失败:', e); + return []; + } + } + + function saveReadDocs(docs) { + try { + localStorage.setItem(STORAGE_KEY, JSON.stringify(docs)); + } catch (e) { + console.error('保存进度失败:', e); + } + } + + function normalizePath(path) { + if (!path) return '/'; + + // URL 解码(处理中文路径) + try { + path = decodeURIComponent(path); + } catch (e) { + // 如果解码失败,保持原样 + } + + path = path.replace(/^\/+/, '').replace(/\/+$/, ''); + return '/' + path; + } + + function markAsRead() { + const currentPath = normalizePath(window.location.pathname); + const readDocs = getReadDocs(); + + if (!readDocs.includes(currentPath)) { + readDocs.push(currentPath); + saveReadDocs(readDocs); + console.log('✅ 已标记为已阅读:', currentPath); + updateBadges(); + } else { + console.log('ℹ️ 已经标记过了:', currentPath); + } + } + + function isDocRead(path) { + const readDocs = getReadDocs(); + const normalizedPath = normalizePath(path); + return readDocs.some(docPath => normalizePath(docPath) === normalizedPath); + } + + function createBadge() { + const badge = document.createElement('span'); + badge.className = BADGE_CLASS; + badge.textContent = '✓'; + badge.style.cssText = ` + display: inline-flex !important; + align-items: center !important; + justify-content: center !important; + width: 18px !important; + height: 18px !important; + background-color: #22c55e !important; + color: white !important; + border-radius: 50% !important; + font-size: 11px !important; + font-weight: bold !important; + flex-shrink: 0 !important; + margin-left: 8px !important; + visibility: visible !important; + opacity: 1 !important; + position: relative !important; + `; + return badge; + } + + function updateBadges() { + const readDocs = getReadDocs(); + console.log('📚 已阅读的文档数:', readDocs.length, readDocs); + + if (readDocs.length === 0) { + console.log('⚠️ 还没有已阅读的文档'); + return; + } + + // 清除所有旧标记 + document.querySelectorAll('.' + BADGE_CLASS).forEach(badge => badge.remove()); + + // 获取所有可能的链接元素 + const selectors = [ + 'a.menu__link', + 'a.menu-link', + '.menu a[href^="/"]', + '.sidebar a[href^="/"]', + 'nav a[href^="/"]', + '[class*="sidebar"] a[href^="/"]', + '[class*="menu"] a[href^="/"]' + ]; + + let totalLinks = 0; + let matchedLinks = 0; + + selectors.forEach(selector => { + const links = document.querySelectorAll(selector); + links.forEach(link => { + totalLinks++; + const href = link.getAttribute('href'); + + if (href && !href.startsWith('http') && !href.startsWith('#') && href !== '/') { + const linkPath = normalizePath(href); + + if (isDocRead(linkPath)) { + matchedLinks++; + if (!link.querySelector('.' + BADGE_CLASS)) { + const badge = createBadge(); + link.appendChild(badge); + console.log('✓ 添加标记:', linkPath, '->', link.textContent.trim().substring(0, 30)); + } + } + } + }); + }); + + console.log(`🔍 检查了 ${totalLinks} 个链接,匹配了 ${matchedLinks} 个已阅读文档`); + } + + function initProgressBar() { + if (document.querySelector('[data-reading-progress-bar]')) { + return; + } + + const progressBar = document.createElement('div'); + progressBar.setAttribute('data-reading-progress-bar', 'true'); + progressBar.style.cssText = ` + position: fixed !important; + top: 0 !important; + left: 0 !important; + width: 100% !important; + height: 4px !important; + background-color: rgba(70, 106, 255, 0.1) !important; + z-index: 9999 !important; + pointer-events: none !important; + `; + + const bar = document.createElement('div'); + bar.style.cssText = ` + height: 100% !important; + background: linear-gradient(90deg, #466aff, #6b8cff) !important; + width: 0% !important; + transition: width 0.15s ease-out !important; + `; + + progressBar.appendChild(bar); + document.body.appendChild(progressBar); + + let ticking = false; + window.addEventListener('scroll', () => { + if (!ticking) { + requestAnimationFrame(() => { + const windowHeight = window.innerHeight; + const documentHeight = document.documentElement.scrollHeight - windowHeight; + const scrolled = window.scrollY; + const progress = (scrolled / documentHeight) * 100; + bar.style.width = Math.min(progress, 100) + '%'; + ticking = false; + }); + ticking = true; + } + }); + } + + function initScrollDetection() { + let hasMarked = false; + + function checkScroll() { + const scrollPosition = window.innerHeight + window.scrollY; + const pageHeight = document.documentElement.scrollHeight; + const threshold = 200; + const progress = Math.min((scrollPosition / pageHeight) * 100, 100); + + if (!hasMarked && (progress >= 90 || (pageHeight - scrollPosition < threshold))) { + hasMarked = true; + console.log('📖 滚动进度: ' + Math.round(progress) + '%,标记为已阅读'); + markAsRead(); + setTimeout(() => { hasMarked = false; }, 3000); + } + } + + window.addEventListener('scroll', () => checkScroll()); + setTimeout(checkScroll, 1000); + } + + function init() { + console.log('🚀 初始化阅读进度追踪...'); + + if (document.readyState === 'loading') { + document.addEventListener('DOMContentLoaded', () => setTimeout(initAll, 500)); + } else { + setTimeout(initAll, 500); + } + } + + function initAll() { + console.log('⚙️ 启动功能...'); + initProgressBar(); + updateBadges(); + initScrollDetection(); + + // 定期更新 + setInterval(updateBadges, 3000); + } + + // 启动 + init(); + + // 监听路由变化 + let lastUrl = location.href; + new MutationObserver(() => { + const url = location.href; + if (url !== lastUrl) { + lastUrl = url; + console.log('🔄 页面变化,更新标记'); + setTimeout(updateBadges, 500); + } + }).observe(document, { subtree: true, childList: true }); + + // 暴露调试接口 + window.readingProgressDebug = { + getReadDocs, + markAsRead, + updateBadges, + clearAll: () => { + localStorage.removeItem(STORAGE_KEY); + document.querySelectorAll('.' + BADGE_CLASS).forEach(b => b.remove()); + console.log('🗑️ 已清除所有阅读记录'); + updateBadges(); + }, + test: () => { + console.log('🧪 开始测试...'); + const currentPath = normalizePath(window.location.pathname); + console.log('当前路径:', currentPath); + console.log('已阅读文档:', getReadDocs()); + + const links = document.querySelectorAll('a[href^="/"]'); + console.log('找到链接数:', links.length); + + links.forEach(link => { + const href = link.getAttribute('href'); + if (href && !href.startsWith('http') && href !== '/') { + console.log('链接:', normalizePath(href), '文本:', link.textContent.trim()); + } + }); + + updateBadges(); + } + }; + + console.log('✅ 阅读进度追踪已加载'); + console.log('🔧 调试命令:'); + console.log(' readingProgressDebug.markAsRead() - 手动标记当前页面'); + console.log(' readingProgressDebug.updateBadges() - 更新侧边栏标记'); + console.log(' readingProgressDebug.test() - 运行测试'); + console.log(' readingProgressDebug.clearAll() - 清除所有记录'); + +})(); -- 2.34.1 From c0231e0562b3a5c9025ba89d50e2c35d920b265b Mon Sep 17 00:00:00 2001 From: Donkey_kevin <2930705585@qq.com> Date: Wed, 13 May 2026 14:56:29 +0800 Subject: [PATCH 4/4] 1 --- .claude/settings.local.json | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.claude/settings.local.json b/.claude/settings.local.json index 7e63862..6e01d6e 100644 --- a/.claude/settings.local.json +++ b/.claude/settings.local.json @@ -16,7 +16,10 @@ "Bash(git remote:*)", "Bash(ssh-keygen:*)", "Bash(ssh -T git@gitlink.org.cn)", - "Bash(git branch:*)" + "Bash(git branch:*)", + "Bash(timeout 5 curl -s http://localhost:3000)", + "Bash(timeout 8 curl -s http://localhost:3000)", + "Bash(curl -s http://localhost:3000)" ] } } -- 2.34.1