// ==UserScript== // @name 知识星球吖 // @namespace https://axutongxue.com/ // @version 2.8 // @license MIT // @description 1. 去掉 disabled-copy 类及水印遮挡;2. 自动点击"展开"按钮保持全文展开;3. 点击时间复制帖子内容;4. 每3分钟自动刷新(可开关);5. 界面美化和侧边栏控制 // @author kejin——公众号:懒人股选 // @match *://wx.zsxq.com/* // @grant GM_addStyle // @downloadURL none // ==/UserScript== (function () { 'use strict'; /* ************** 样式注入 ************** */ // 添加自定义样式 if (typeof GM_addStyle !== 'undefined') { GM_addStyle(` .group-list-container { transition: transform 0.2s ease-out; background: #fff; z-index: 10; } #toggle-sidebar { height: 20px; font-size: 12px; margin-left: 10px; padding: 0px 6px; border-radius: 4px; cursor: pointer; color: rgb(80, 234, 203); background-color: rgba(52, 146, 112, 0.05); border: 1px solid rgba(65,183,140,.2); } #toggle-sidebar:hover { background-color: #e0e0e0; } #auto-refresh-control { position: fixed; top: 10px; right: 10px; background: white; padding: 6px 10px; border-radius: 6px; box-shadow: 0 2px 8px rgba(0,0,0,0.1); z-index: 9999; display: flex; align-items: center; gap: 8px; font-size: 13px; } .control-item { display: flex; align-items: center; gap: 5px; } .control-divider { width: 1px; height: 16px; background: #e0e0e0; } #toggle-sidebar-btn { height: 24px; font-size: 12px; padding: 0px 10px; border-radius: 4px; cursor: pointer; color: white; background-color: #50EACB; border: none; transition: background-color 0.2s; } #toggle-sidebar-btn:hover { background-color: #3DD4B5; } #auto-refresh-toggle.active { background: #EF97AF; } #refresh-countdown { color: #666; font-size: 12px; min-width: 40px; text-align: right; } #auto-refresh-toggle.active { background: #EF97AF; } #refresh-countdown { color: #666; font-size: 12px; min-width: 45px; text-align: right; } #auto-refresh-toggle { position: relative; width: 40px; height: 20px; background: #ccc; border-radius: 10px; cursor: pointer; transition: background 0.3s; } #auto-refresh-toggle.active { background: rgb(80, 234, 203); } #auto-refresh-toggle::after { content: ''; position: absolute; top: 2px; left: 2px; width: 16px; height: 16px; background: white; border-radius: 50%; transition: transform 0.3s; } #auto-refresh-toggle.active::after { transform: translateX(20px); } #refresh-countdown { color: #666; font-size: 12px; min-width: 80px; } `); } else { // 如果 GM_addStyle 不可用,使用传统方式 const style = document.createElement('style'); style.textContent = ` .group-list-container { transition: transform 0.2s ease-out; background: #fff; z-index: 10; } #toggle-sidebar { height: 20px; font-size: 12px; margin-left: 10px; padding: 0px 6px; border-radius: 4px; cursor: pointer; color: rgb(80, 234, 203); background-color: rgba(52, 146, 112, 0.05); border: 1px solid rgba(65,183,140,.2); } #toggle-sidebar:hover { background-color: #e0e0e0; } #auto-refresh-control { position: fixed; top: 10px; right: 10px; background: white; padding: 10px 15px; border-radius: 6px; box-shadow: 0 2px 8px rgba(0,0,0,0.1); z-index: 9999; display: flex; align-items: center; gap: 15px; font-size: 13px; } .control-item { display: flex; align-items: center; gap: 8px; } .control-divider { width: 1px; height: 20px; background: #e0e0e0; } #toggle-sidebar-btn { height: 24px; font-size: 12px; padding: 0px 10px; border-radius: 4px; cursor: pointer; color: rgb(80, 234, 203); background-color: rgba(52, 146, 112, 0.05); border: 1px solid rgba(65,183,140,.2); transition: background-color 0.2s; } #toggle-sidebar-btn:hover { background-color: rgba(52, 146, 112, 0.1); } #auto-refresh-toggle { position: relative; width: 40px; height: 20px; background: #ccc; border-radius: 10px; cursor: pointer; transition: background 0.3s; } #auto-refresh-toggle.active { background: rgb(80, 234, 203); } #auto-refresh-toggle::after { content: ''; position: absolute; top: 2px; left: 2px; width: 16px; height: 16px; background: white; border-radius: 50%; transition: transform 0.3s; } #auto-refresh-toggle.active::after { transform: translateX(20px); } #refresh-countdown { color: #666; font-size: 12px; min-width: 80px; } `; document.head.appendChild(style); } /* ************** 通用工具 ************** */ function waitForKeyElements(selectorOrFunction, callback, waitOnce = true, interval = 300, maxIntervals = -1) { const select = () => (typeof selectorOrFunction === 'function' ? selectorOrFunction() : document.querySelectorAll(selectorOrFunction)); const tick = () => { const nodes = select(); if (nodes.length) { nodes.forEach(n => { if (n.dataset.alreadyFound) return; const cancel = callback(n); if (!cancel) n.dataset.alreadyFound = '1'; }); } if (--maxIntervals !== 0 && !(waitOnce && nodes.length)) { setTimeout(tick, interval); } }; tick(); } /* ************** 1. 解除复制限制 ************** */ waitForKeyElements('.disabled-copy', el => el.classList.remove('disabled-copy'), false, 1000); waitForKeyElements('[watermark]', el => el.setAttribute('style', 'padding:10px;'), false, 1000); /* ************** 2. 帖子自动展开 ************** */ const processed = new WeakSet(); function smartClick(btn) { if (!btn || processed.has(btn)) return; const txt = btn.textContent.trim(); if (!/展[开示]/.test(txt)) return; // 尝试多种点击方式 try { btn.click(); // 原生点击 } catch (e) { btn.dispatchEvent(new MouseEvent('click', { bubbles: true, cancelable: true, view: window })); } processed.add(btn); } function expandAll() { // 扩展选择器,覆盖更多可能的展开按钮 const selectors = [ 'p.showAll', 'button.showAll', 'span.showAll', '[class*="showAll"]', '[class*="show-all"]', '[class*="展开"]', 'button:not([data-expanded])', 'span:not([data-expanded])', 'p:not([data-expanded])' ]; selectors.forEach(selector => { document.querySelectorAll(selector).forEach(el => { const text = el.textContent.trim(); if (/展[开示]|show\s*all|show\s*more/i.test(text)) { smartClick(el); } }); }); } // 首次+动态 let expandObserver = null; window.addEventListener('load', () => { // 立即执行一次 expandAll(); // 延迟执行确保DOM完全加载 setTimeout(expandAll, 500); setTimeout(expandAll, 1000); setTimeout(expandAll, 2000); // 监听DOM变化 if (expandObserver) expandObserver.disconnect(); expandObserver = new MutationObserver(() => { expandAll(); }); expandObserver.observe(document.body, { childList: true, subtree: true, attributes: false }); window.addEventListener('hashchange', expandAll); // 滚动时也尝试展开 let scrollTimer = null; window.addEventListener('scroll', () => { if (scrollTimer) clearTimeout(scrollTimer); scrollTimer = setTimeout(expandAll, 300); }, { passive: true }); }); /* ************** 3. 点击时间复制帖子内容 ************** */ const timeClickProcessed = new WeakSet(); function findPostContent(timeElement) { // 向上查找帖子容器 let container = timeElement.closest('[class*="topic"], [class*="post"], [class*="feed-item"]'); if (!container) { container = timeElement.closest('div[class*="item"]'); } if (!container) return null; // 查找内容区域(尝试多种可能的选择器) const contentSelectors = [ '.content', '[class*="content"]', '.text', '[class*="text"]', '.description', '[class*="description"]' ]; for (const selector of contentSelectors) { const content = container.querySelector(selector); if (content && content.textContent.trim()) { return content.textContent.trim(); } } return null; } function copyToClipboard(text) { if (navigator.clipboard && navigator.clipboard.writeText) { navigator.clipboard.writeText(text).then(() => { showCopyTip('复制成功!'); }).catch(() => { fallbackCopy(text); }); } else { fallbackCopy(text); } } function fallbackCopy(text) { const textarea = document.createElement('textarea'); textarea.value = text; textarea.style.position = 'fixed'; textarea.style.opacity = '0'; document.body.appendChild(textarea); textarea.select(); try { document.execCommand('copy'); showCopyTip('复制成功!'); } catch (err) { showCopyTip('复制失败,请手动复制'); } document.body.removeChild(textarea); } function showCopyTip(message) { const tip = document.createElement('div'); tip.textContent = message; tip.style.cssText = ` position: fixed; top: 50%; left: 50%; transform: translate(-50%, -50%); background: rgba(0, 0, 0, 0.8); color: white; padding: 12px 24px; border-radius: 6px; font-size: 14px; z-index: 10000; pointer-events: none; `; document.body.appendChild(tip); setTimeout(() => tip.remove(), 2000); } function addTimeClickListener(timeElement) { if (timeClickProcessed.has(timeElement)) return; // 添加样式提示可点击 timeElement.style.cursor = 'pointer'; timeElement.title = '点击复制帖子内容'; timeElement.addEventListener('click', (e) => { e.preventDefault(); e.stopPropagation(); const content = findPostContent(timeElement); if (content) { copyToClipboard(content); } else { showCopyTip('未找到帖子内容'); } }); timeClickProcessed.add(timeElement); } // 监听时间元素(尝试多种可能的选择器) function attachTimeListeners() { const timeSelectors = [ '[class*="time"]', '[class*="date"]', 'time', 'span[title*="202"]', // 匹配包含年份的时间 ]; timeSelectors.forEach(selector => { waitForKeyElements(selector, (el) => { // 检查是否是时间格式 const text = el.textContent.trim(); if (/\d{4}-\d{2}-\d{2}/.test(text) || /\d{2}:\d{2}/.test(text)) { addTimeClickListener(el); } }, false, 1000); }); } // 启动时间点击监听 window.addEventListener('load', () => { attachTimeListeners(); }); /* ************** 4. 自动刷新功能(3分钟) ************** */ let refreshTimer = null; let countdownInterval = null; let isAutoRefreshEnabled = localStorage.getItem('autoRefreshEnabled') !== 'false'; // 默认开启 const REFRESH_INTERVAL = 180000; // 3分钟 = 180秒 = 180000毫秒 let remainingTime = REFRESH_INTERVAL; // 创建控制面板 function createRefreshControl() { const controlDiv = document.createElement('div'); controlDiv.id = 'auto-refresh-control'; controlDiv.innerHTML = `
自动刷新
`; document.body.appendChild(controlDiv); const toggle = document.getElementById('auto-refresh-toggle'); const countdown = document.getElementById('refresh-countdown'); // 切换开关 toggle.addEventListener('click', () => { isAutoRefreshEnabled = !isAutoRefreshEnabled; localStorage.setItem('autoRefreshEnabled', isAutoRefreshEnabled); toggle.classList.toggle('active'); if (isAutoRefreshEnabled) { startAutoRefresh(); console.log('自动刷新已启用:每3分钟刷新一次'); } else { stopAutoRefresh(); countdown.textContent = '已禁用'; console.log('自动刷新已禁用'); } }); return countdown; } // 格式化时间显示 function formatTime(ms) { const totalSeconds = Math.floor(ms / 1000); const minutes = Math.floor(totalSeconds / 60); const seconds = totalSeconds % 60; return `${minutes}:${seconds.toString().padStart(2, '0')}`; } // 更新倒计时显示 function updateCountdown(countdownElement) { if (!isAutoRefreshEnabled) { countdownElement.textContent = '已禁用'; return; } countdownElement.textContent = formatTime(remainingTime); } // 启动自动刷新 function startAutoRefresh() { stopAutoRefresh(); // 先清除旧的定时器 remainingTime = REFRESH_INTERVAL; const countdownElement = document.getElementById('refresh-countdown'); // 更新倒计时(每秒更新一次) countdownInterval = setInterval(() => { remainingTime -= 1000; if (remainingTime <= 0) { remainingTime = 0; } updateCountdown(countdownElement); }, 1000); // 设置刷新定时器 refreshTimer = setTimeout(() => { console.log('3分钟到,刷新页面'); location.reload(); }, REFRESH_INTERVAL); updateCountdown(countdownElement); } // 停止自动刷新 function stopAutoRefresh() { if (refreshTimer) { clearTimeout(refreshTimer); refreshTimer = null; } if (countdownInterval) { clearInterval(countdownInterval); countdownInterval = null; } } // 页面加载后初始化 window.addEventListener('load', () => { setTimeout(() => { const countdownElement = createRefreshControl(); if (isAutoRefreshEnabled) { startAutoRefresh(); console.log('自动刷新功能已启动:每3分钟刷新一次'); } else { updateCountdown(countdownElement); console.log('自动刷新功能已禁用(可通过右上角开关启用)'); } }, 500); }); /* ************** 5. 界面优化功能 ************** */ // 5.1 为精华帖添加红色边框 function addRedBorder() { const listItems = document.querySelectorAll('.ng-star-inserted'); listItems.forEach((item) => { const headerContainer = item.querySelector('.header-container'); if (headerContainer) { const topicFlag = headerContainer.querySelector('.topic-flag'); if (topicFlag) { const digestElement = topicFlag.querySelector('.digest'); if (digestElement) { const topicContainer = item.querySelector('.topic-container'); if (topicContainer) { topicContainer.style.border = '1px solid rgb(80, 234, 203)'; topicContainer.style.backgroundColor = 'rgba(80, 234, 203, 0.1)'; } } } } }); } // 5.2 设置侧边栏切换功能 function setupSidebarToggle() { const sidebar = document.querySelector('.group-list-container'); if (!sidebar) return; // 获取视口宽度 const clientWidth = document.documentElement.clientWidth; const transX = clientWidth - 1526 / 2; // 初始化侧边栏状态(从localStorage读取,默认显示) const isHidden = localStorage.getItem('sidebarHidden') === 'true'; if (isHidden) { sidebar.classList.add('hide'); sidebar.style.transform = 'translateX(calc(-100% - ' + transX + 'px))'; } else { sidebar.classList.remove('hide'); sidebar.style.transform = 'translateX(0)'; } // 绑定到右上角按钮 const toggleButton = document.getElementById('toggle-sidebar-btn'); if (toggleButton && !toggleButton.dataset.bound) { toggleButton.dataset.bound = 'true'; toggleButton.addEventListener('click', () => { sidebar.classList.toggle('hide'); if (sidebar.classList.contains('hide')) { sidebar.style.transform = 'translateX(calc(-100% - ' + transX + 'px))'; localStorage.setItem('sidebarHidden', 'true'); } else { sidebar.style.transform = 'translateX(0)'; localStorage.setItem('sidebarHidden', 'false'); } }); } } // 5.3 隐藏不必要的界面元素 function hideElements() { // 头部 const headerContainer = document.querySelector('.header-container'); if (headerContainer) { const redirect = headerContainer.querySelector('.redirect'); const userAvatar = headerContainer.querySelector('.user-avatar'); if (redirect) { redirect.style.display = 'none'; } if (userAvatar) { userAvatar.style.display = 'none'; } } const leftLogo = document.querySelector('.logo-container .left'); const noteLogo = document.querySelector('.logo-container .note'); if (leftLogo) { leftLogo.style.display = 'none'; } if (noteLogo) { noteLogo.style.display = 'none'; } // .topic-flow-container const topicFlowContainer = document.querySelector('.topic-flow-container'); if (topicFlowContainer) { topicFlowContainer.style.setProperty('width', '100%', 'important'); topicFlowContainer.style.setProperty('padding-left', '100px', 'important'); topicFlowContainer.style.setProperty('padding-right', '100px', 'important'); } // 主体上部分 const topicContainer = document.querySelector('.topic-container'); if (topicContainer) { const ngStarInserted = topicContainer.querySelector('.ng-star-inserted'); if (ngStarInserted) { ngStarInserted.style.display = 'none'; } } // 主体中部分 const mainContentContainer = document.querySelector('.main-content-container'); if (mainContentContainer) { mainContentContainer.style.setProperty('margin-left', '10%', 'important'); mainContentContainer.style.setProperty('margin-right', '10%', 'important'); } // 右侧边栏 const groupPreviewContainer = document.querySelector('.group-preview-container'); if (groupPreviewContainer) { groupPreviewContainer.style.display = 'none'; } } // 5.4 启动界面优化功能 function initUIEnhancements() { addRedBorder(); setupSidebarToggle(); hideElements(); // 监听DOM变化,持续应用样式 const observer = new MutationObserver(() => { addRedBorder(); setupSidebarToggle(); hideElements(); }); observer.observe(document.body, { childList: true, subtree: true }); } // 页面加载完成后执行界面优化 window.addEventListener('load', () => { setTimeout(initUIEnhancements, 500); }); })();