// ==UserScript== // @name HDSky 体育沙龙 // @namespace http://tampermonkey.net/ // @version 1.8 // @description 在 HDSky 论坛页面右上角显示控制面板,可以添加特殊关注用户并高亮显示他们的回复,支持快速翻页和收藏功能,可折叠面板 // @author 江畔 // @match https://hdsky.me/* // @match https://www.hdsky.me/* // @icon https://hdsky.me/favicon.ico // @grant GM_setValue // @grant GM_getValue // @charset UTF-8 // @license MIT // @downloadURL none // ==/UserScript== (function() { 'use strict'; // 从存储中获取特殊关注名单 function getSpecialFollowList() { const listStr = GM_getValue('specialFollowList', ''); if (!listStr) return []; return listStr.split(',').map(name => name.trim()).filter(name => name); } // 保存特殊关注名单到存储 function saveSpecialFollowList(list) { GM_setValue('specialFollowList', list.join(',')); } // 从存储中获取收藏列表 function getBookmarkList() { const listStr = GM_getValue('bookmarkList', '[]'); try { return JSON.parse(listStr); } catch (e) { return []; } } // 保存收藏列表到存储 function saveBookmarkList(list) { GM_setValue('bookmarkList', JSON.stringify(list)); } // 创建控制面板 function createControlPanel() { // 创建容器,包含面板和折叠按钮 const container = document.createElement('div'); container.id = 'hdsky-panel-container'; container.style.cssText = ` position: fixed; top: 10px; right: 10px; display: flex; align-items: flex-start; z-index: 10000; `; // 创建折叠按钮 const toggleBtn = document.createElement('button'); toggleBtn.id = 'panel-toggle-btn'; toggleBtn.innerHTML = '◀'; toggleBtn.title = '收起面板'; toggleBtn.style.cssText = ` background: #e0e0e0; color: #666; border: none; border-radius: 4px 0 0 4px; width: 24px; height: 40px; cursor: pointer; font-size: 14px; transition: background 0.3s; margin-right: -2px; z-index: 1; `; toggleBtn.onmouseover = () => toggleBtn.style.background = '#d0d0d0'; toggleBtn.onmouseout = () => toggleBtn.style.background = '#e0e0e0'; toggleBtn.onclick = togglePanel; const panel = document.createElement('div'); panel.id = 'hdsky-special-follow-panel'; panel.style.cssText = ` background: #fff; border: 1px solid #ddd; border-radius: 8px; padding: 15px; box-shadow: 0 4px 8px rgba(0,0,0,0.2); min-width: 200px; font-family: Arial, sans-serif; transition: all 0.3s ease; `; // 面板标题 const title = document.createElement('div'); title.textContent = '特殊关注面板'; title.style.cssText = ` font-size: 16px; font-weight: bold; margin-bottom: 12px; color: #333; text-align: center; border-bottom: 1px solid #ddd; padding-bottom: 8px; `; panel.appendChild(title); // 显示当前关注列表(可点击编辑) const followListDiv = document.createElement('div'); followListDiv.id = 'current-follow-list'; followListDiv.style.cssText = ` font-size: 12px; color: #666; margin-bottom: 10px; max-height: 60px; overflow-y: auto; padding: 8px; background: #f9f9f9; border-radius: 4px; cursor: pointer; border: 1px solid #ddd; transition: all 0.3s; `; followListDiv.title = '点击编辑特殊关注名单'; followListDiv.onmouseover = () => { followListDiv.style.background = '#e8f5e9'; followListDiv.style.borderColor = '#4CAF50'; }; followListDiv.onmouseout = () => { followListDiv.style.background = '#f9f9f9'; followListDiv.style.borderColor = '#ddd'; }; followListDiv.onclick = handleFollowListClick; updateFollowListDisplay(followListDiv); panel.appendChild(followListDiv); // 按钮容器 const buttonContainer = document.createElement('div'); buttonContainer.style.cssText = ` display: flex; flex-direction: column; gap: 8px; `; // 高亮按钮 const filterBtn = document.createElement('button'); filterBtn.textContent = '高亮特殊关注'; filterBtn.id = 'filter-toggle-btn'; filterBtn.style.cssText = ` padding: 10px 15px; background: #2196F3; color: white; border: none; border-radius: 5px; cursor: pointer; font-size: 14px; font-weight: bold; transition: background 0.3s; `; filterBtn.onmouseover = () => filterBtn.style.background = '#0b7dda'; filterBtn.onmouseout = () => { if (filterBtn.dataset.filtering === 'true') { filterBtn.style.background = '#f44336'; } else { filterBtn.style.background = '#2196F3'; } }; filterBtn.onclick = handleFilterButtonClick; buttonContainer.appendChild(filterBtn); // 收藏功能按钮容器 const bookmarkContainer = document.createElement('div'); bookmarkContainer.id = 'bookmark-container'; bookmarkContainer.style.cssText = ` display: flex; flex-direction: row; gap: 8px; `; // 收藏按钮 const bookmarkBtn = document.createElement('button'); bookmarkBtn.textContent = '收藏'; bookmarkBtn.id = 'bookmark-btn'; bookmarkBtn.style.cssText = ` padding: 8px 12px; background: #2196F3; color: white; border: none; border-radius: 5px; cursor: pointer; font-size: 13px; font-weight: bold; transition: background 0.3s; flex: 1; `; bookmarkBtn.onmouseover = () => bookmarkBtn.style.background = '#0b7dda'; bookmarkBtn.onmouseout = () => bookmarkBtn.style.background = '#2196F3'; bookmarkBtn.onclick = addBookmark; bookmarkContainer.appendChild(bookmarkBtn); // 收藏夹按钮 const bookmarkListBtn = document.createElement('button'); bookmarkListBtn.textContent = '收藏夹'; bookmarkListBtn.id = 'bookmark-list-btn'; bookmarkListBtn.style.cssText = ` padding: 8px 12px; background: #2196F3; color: white; border: none; border-radius: 5px; cursor: pointer; font-size: 13px; font-weight: bold; transition: background 0.3s; flex: 1; `; bookmarkListBtn.onmouseover = () => bookmarkListBtn.style.background = '#0b7dda'; bookmarkListBtn.onmouseout = () => bookmarkListBtn.style.background = '#2196F3'; bookmarkListBtn.onclick = showBookmarkList; bookmarkContainer.appendChild(bookmarkListBtn); buttonContainer.appendChild(bookmarkContainer); // 页码导航按钮容器(上一页/下一页) const navContainer = document.createElement('div'); navContainer.id = 'nav-container'; navContainer.style.cssText = ` display: flex; flex-direction: row; gap: 8px; `; // 上一页按钮 const prevBtn = document.createElement('button'); prevBtn.textContent = '上一页'; prevBtn.id = 'prev-page-btn'; prevBtn.style.cssText = ` padding: 8px 12px; background: #2196F3; color: white; border: none; border-radius: 5px; cursor: pointer; font-size: 13px; font-weight: bold; transition: background 0.3s; flex: 1; `; prevBtn.onmouseover = () => prevBtn.style.background = '#0b7dda'; prevBtn.onmouseout = () => prevBtn.style.background = '#2196F3'; prevBtn.onclick = goToPrevPage; navContainer.appendChild(prevBtn); // 下一页按钮 const nextBtn = document.createElement('button'); nextBtn.textContent = '下一页'; nextBtn.id = 'next-page-btn'; nextBtn.style.cssText = ` padding: 8px 12px; background: #2196F3; color: white; border: none; border-radius: 5px; cursor: pointer; font-size: 13px; font-weight: bold; transition: background 0.3s; flex: 1; `; nextBtn.onmouseover = () => nextBtn.style.background = '#0b7dda'; nextBtn.onmouseout = () => nextBtn.style.background = '#2196F3'; nextBtn.onclick = goToNextPage; navContainer.appendChild(nextBtn); buttonContainer.appendChild(navContainer); panel.appendChild(buttonContainer); // 将按钮和面板添加到容器 container.appendChild(toggleBtn); container.appendChild(panel); // 添加到页面 document.body.appendChild(container); } // 切换面板显示/隐藏 function togglePanel() { const panel = document.getElementById('hdsky-special-follow-panel'); const toggleBtn = document.getElementById('panel-toggle-btn'); if (panel.style.display === 'none') { // 展开面板 panel.style.display = 'block'; toggleBtn.innerHTML = '◀'; toggleBtn.title = '收起面板'; toggleBtn.style.borderRadius = '4px 0 0 4px'; } else { // 收起面板 panel.style.display = 'none'; toggleBtn.innerHTML = '▶'; toggleBtn.title = '展开面板'; toggleBtn.style.borderRadius = '4px'; } } // 更新关注列表显示 function updateFollowListDisplay(container) { const followList = getSpecialFollowList(); if (followList.length === 0) { container.textContent = '当前无关注用户'; } else { container.textContent = '关注: ' + followList.join(', '); } } // 全局变量:高亮帖子列表 let highlightedPosts = []; // 跳转到上一页 function goToPrevPage() { // 查找页面中的"上一页"链接 const prevLinks = document.querySelectorAll('a'); let prevPageLink = null; for (let link of prevLinks) { const text = link.textContent.trim(); if (text.includes('上一页') || text === '<<上一页') { prevPageLink = link; break; } } if (prevPageLink && prevPageLink.href) { window.location.href = prevPageLink.href; } else { alert('没有找到上一页链接'); } } // 跳转到下一页 function goToNextPage() { // 查找页面中的"下一页"链接 const nextLinks = document.querySelectorAll('a'); let nextPageLink = null; for (let link of nextLinks) { const text = link.textContent.trim(); if (text.includes('下一页') || text === '下一页 >>') { nextPageLink = link; break; } } if (nextPageLink && nextPageLink.href) { window.location.href = nextPageLink.href; } else { alert('没有找到下一页链接'); } } // 添加收藏 function addBookmark() { const currentUrl = window.location.href; let currentTitle = document.title || '未命名页面'; // 从标题中提取引号里的内容 const match = currentTitle.match(/"([^"]+)"/); if (match && match[1]) { currentTitle = match[1]; } else { // 如果没有引号,则删掉常见的前后缀 currentTitle = currentTitle.replace(/^HDSky :: 查看主题\s+/i, ''); currentTitle = currentTitle.replace(/^HDSky :: /i, ''); currentTitle = currentTitle.replace(/\s*高清视界.*$/i, ''); currentTitle = currentTitle.replace(/\s*-\s*Powered by.*$/i, ''); } // 获取现有收藏列表 const bookmarks = getBookmarkList(); // 检查是否已经收藏 const exists = bookmarks.some(b => b.url === currentUrl); if (exists) { alert('该页面已经在收藏夹中了!'); return; } // 添加新收藏 bookmarks.push({ url: currentUrl, title: currentTitle, time: new Date().toLocaleString() }); // 保存 saveBookmarkList(bookmarks); alert('收藏成功!\n标题:' + currentTitle); } // 显示收藏夹 function showBookmarkList() { const bookmarks = getBookmarkList(); // 移除旧的收藏夹窗口(如果存在) const oldDialog = document.getElementById('bookmark-dialog'); if (oldDialog) { oldDialog.remove(); } // 创建遮罩层 const overlay = document.createElement('div'); overlay.id = 'bookmark-dialog'; overlay.style.cssText = ` position: fixed; top: 0; left: 0; width: 100%; height: 100%; background: rgba(0, 0, 0, 0.5); z-index: 10003; display: flex; justify-content: center; align-items: center; `; // 创建弹窗 const dialog = document.createElement('div'); dialog.style.cssText = ` background: white; border-radius: 10px; padding: 20px; width: 600px; max-height: 70vh; overflow-y: auto; box-shadow: 0 4px 20px rgba(0,0,0,0.3); `; // 标题栏 const header = document.createElement('div'); header.style.cssText = ` display: flex; justify-content: space-between; align-items: center; margin-bottom: 15px; padding-bottom: 10px; border-bottom: 2px solid #2196F3; background: transparent; `; const title = document.createElement('h2'); title.textContent = '我的收藏夹'; title.style.cssText = ` margin: 0; padding: 0; color: #2196F3; font-size: 20px; background: transparent; border: none; outline: none; `; header.appendChild(title); const closeBtn = document.createElement('button'); closeBtn.textContent = '✕'; closeBtn.style.cssText = ` background: #f44336; color: white; border: none; border-radius: 50%; width: 30px; height: 30px; cursor: pointer; font-size: 18px; font-weight: bold; transition: background 0.3s; `; closeBtn.onmouseover = () => closeBtn.style.background = '#d32f2f'; closeBtn.onmouseout = () => closeBtn.style.background = '#f44336'; closeBtn.onclick = () => overlay.remove(); header.appendChild(closeBtn); dialog.appendChild(header); // 收藏列表 if (bookmarks.length === 0) { const emptyMsg = document.createElement('div'); emptyMsg.textContent = '收藏夹还是空的,快去收藏喜欢的页面吧!'; emptyMsg.style.cssText = ` text-align: center; color: #999; padding: 40px 20px; font-size: 14px; background: #f9f9f9; border-radius: 5px; margin-top: 10px; `; dialog.appendChild(emptyMsg); } else { bookmarks.forEach((bookmark, index) => { const item = createBookmarkItem(bookmark, index); dialog.appendChild(item); }); } overlay.appendChild(dialog); document.body.appendChild(overlay); // 点击遮罩层关闭 overlay.onclick = (e) => { if (e.target === overlay) { overlay.remove(); } }; } // 创建收藏项 function createBookmarkItem(bookmark, index) { const item = document.createElement('div'); item.style.cssText = ` display: flex; justify-content: space-between; align-items: center; padding: 12px; margin-bottom: 10px; background: #fafafa; border: 1px solid #e0e0e0; border-radius: 5px; transition: all 0.3s; `; item.onmouseover = () => { item.style.background = '#e3f2fd'; item.style.borderColor = '#2196F3'; item.style.transform = 'translateX(5px)'; item.style.boxShadow = '0 2px 8px rgba(33, 150, 243, 0.2)'; }; item.onmouseout = () => { item.style.background = '#fafafa'; item.style.borderColor = '#e0e0e0'; item.style.transform = 'translateX(0)'; item.style.boxShadow = 'none'; }; // 左侧内容区 const content = document.createElement('div'); content.style.cssText = ` flex: 1; cursor: pointer; overflow: hidden; `; content.onclick = () => window.location.href = bookmark.url; const titleDiv = document.createElement('div'); titleDiv.textContent = bookmark.title; titleDiv.style.cssText = ` font-size: 14px; font-weight: bold; color: #2196F3; margin-bottom: 5px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; `; content.appendChild(titleDiv); const timeDiv = document.createElement('div'); timeDiv.textContent = '收藏时间: ' + bookmark.time; timeDiv.style.cssText = ` font-size: 12px; color: #999; `; content.appendChild(timeDiv); item.appendChild(content); // 删除按钮 const deleteBtn = document.createElement('button'); deleteBtn.textContent = '✕'; deleteBtn.style.cssText = ` background: #ff5722; color: white; border: none; border-radius: 50%; width: 25px; height: 25px; cursor: pointer; font-size: 14px; font-weight: bold; transition: background 0.3s; margin-left: 10px; `; deleteBtn.onmouseover = () => deleteBtn.style.background = '#e64a19'; deleteBtn.onmouseout = () => deleteBtn.style.background = '#ff5722'; deleteBtn.onclick = (e) => { e.stopPropagation(); if (confirm('确定要删除这个收藏吗?\n' + bookmark.title)) { deleteBookmark(index); showBookmarkList(); // 刷新列表 } }; item.appendChild(deleteBtn); return item; } // 删除收藏 function deleteBookmark(index) { const bookmarks = getBookmarkList(); bookmarks.splice(index, 1); saveBookmarkList(bookmarks); } // 处理关注列表点击(编辑) function handleFollowListClick() { const currentList = getSpecialFollowList(); const currentStr = currentList.join(','); const input = prompt('请输入特殊关注名单(用逗号分隔):\n例如: DFBCOLD19,李知恩', currentStr); if (input !== null) { // 用户点击了确定(包括空字符串) const newList = input.split(',').map(name => name.trim()).filter(name => name); saveSpecialFollowList(newList); // 更新显示 const followListDiv = document.getElementById('current-follow-list'); updateFollowListDisplay(followListDiv); alert('特殊关注名单已更新!\n当前关注: ' + (newList.length > 0 ? newList.join(', ') : '无')); } } // 处理高亮按钮点击 function handleFilterButtonClick() { const filterBtn = document.getElementById('filter-toggle-btn'); const isFiltering = filterBtn.dataset.filtering === 'true'; if (isFiltering) { // 取消高亮 clearHighlights(); filterBtn.dataset.filtering = 'false'; filterBtn.textContent = '高亮特殊关注'; filterBtn.style.background = '#2196F3'; } else { // 应用高亮 const followList = getSpecialFollowList(); if (followList.length === 0) { alert('请先设置特殊关注名单!'); return; } highlightFollowedPosts(followList); filterBtn.dataset.filtering = 'true'; filterBtn.textContent = '取消高亮'; filterBtn.style.background = '#f44336'; } } // 高亮特殊关注用户的帖子 function highlightFollowedPosts(followList) { // 找到所有回复帖子(每个帖子在一个带有 margin-top 和 margin-bottom 的 div 中) const allPosts = document.querySelectorAll('div[style*="margin-top: 8pt"]'); // 重置高亮列表 highlightedPosts = []; let firstHighlightedPost = null; allPosts.forEach(post => { // 在帖子中查找用户名链接 const userLinks = post.querySelectorAll('a[href*="userdetails.php"]'); let isFollowedUser = false; userLinks.forEach(link => { const username = link.textContent.trim(); // 检查是否在关注列表中 if (followList.some(followName => username === followName)) { isFollowedUser = true; } }); if (isFollowedUser) { // 高亮显示关注用户的回复div post.style.background = '#fffacd'; post.style.border = '2px solid #ffd700'; post.style.borderRadius = '5px'; post.style.padding = '5px'; // 找到并高亮下面的table(回复内容表格) const tables = post.querySelectorAll('table'); tables.forEach(table => { table.style.background = '#fff8dc'; table.style.border = '2px solid #ffb700'; }); // 标记为已高亮 post.dataset.highlighted = 'true'; // 添加到高亮列表 highlightedPosts.push(post); // 记录第一个高亮的帖子 if (!firstHighlightedPost) { firstHighlightedPost = post; } } }); // 如果找到高亮的帖子,滚动到第一个 if (firstHighlightedPost) { firstHighlightedPost.scrollIntoView({ behavior: 'smooth', block: 'center' }); } // 显示高亮结果提示 showHighlightResult(highlightedPosts.length); } // 清除所有高亮 function clearHighlights() { // 找到所有被高亮的帖子 const posts = document.querySelectorAll('div[data-highlighted="true"]'); posts.forEach(post => { // 清除div的高亮样式 post.style.background = ''; post.style.border = ''; post.style.borderRadius = ''; post.style.padding = ''; post.removeAttribute('data-highlighted'); // 清除table的高亮样式 const tables = post.querySelectorAll('table'); tables.forEach(table => { table.style.background = ''; table.style.border = ''; }); }); // 重置全局变量 highlightedPosts = []; // 移除通知提示 const resultDiv = document.getElementById('highlight-result-notification'); if (resultDiv) { resultDiv.remove(); } } // 显示高亮结果通知 function showHighlightResult(highlightCount) { // 移除旧的通知 const oldNotification = document.getElementById('highlight-result-notification'); if (oldNotification) { oldNotification.remove(); } const notification = document.createElement('div'); notification.id = 'highlight-result-notification'; notification.style.cssText = ` position: fixed; top: 50%; left: 50%; transform: translate(-50%, -50%); background: rgba(0, 0, 0, 0.8); color: white; padding: 20px 30px; border-radius: 10px; font-size: 16px; z-index: 10001; text-align: center; `; if (highlightCount > 0) { notification.innerHTML = `