// ==UserScript== // @name 知识星球吖 // @namespace https://axutongxue.com/ // @version 3.3 // @license MIT // @description 1. 去水印;2. 自动展开;3. 点击复制;4. 自动刷新);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: #FFFFFF; background-color: rgb(22, 185, 152); border: none; transition: all 0.2s; } #toggle-sidebar-btn:hover { background-color: rgb(18, 165, 135); } #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 = `