Greasy Fork

Greasy Fork is available in English.

知识星球吖

1. 去掉 disabled-copy 类及水印遮挡;2. 自动点击"展开"按钮保持全文展开;3. 点击时间复制帖子内容;4. 15秒无鼠标活动自动刷新

当前为 2025-10-29 提交的版本,查看 最新版本

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Greasemonkey 油猴子Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Userscripts ,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展后才能安装此脚本。

(我已经安装了用户脚本管理器,让我安装!)

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

(我已经安装了用户样式管理器,让我安装!)

// ==UserScript==
// @name         知识星球吖
// @namespace    https://axutongxue.com/
// @version      2.5
// @license      MIT
// @description  1. 去掉 disabled-copy 类及水印遮挡;2. 自动点击"展开"按钮保持全文展开;3. 点击时间复制帖子内容;4. 15秒无鼠标活动自动刷新
// @author       kejin——公众号:懒人股选
// @match        *://wx.zsxq.com/*
// @grant        none
// ==/UserScript==
(function () {
    'use strict';
    /* ************** 通用工具 ************** */
    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;
        btn.dispatchEvent(new MouseEvent('click', { bubbles: true, cancelable: true, view: window }));
        processed.add(btn);
    }
    function expandAll() {
        document.querySelectorAll('p.showAll, button.showAll, span.showAll').forEach(smartClick);
    }
    // 首次+动态
    window.addEventListener('load', () => {
        expandAll();
        new MutationObserver(() => expandAll()).observe(document.body, { childList: true, subtree: true });
        window.addEventListener('hashchange', expandAll);
    });

    /* ************** 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. 15秒无鼠标活动自动刷新 ************** */
    let inactivityTimer = null;
    const INACTIVITY_TIMEOUT = 15000; // 15秒

    function resetInactivityTimer() {
        // 清除现有计时器
        if (inactivityTimer) {
            clearTimeout(inactivityTimer);
        }
        
        // 设置新计时器
        inactivityTimer = setTimeout(() => {
            console.log('15秒无活动,刷新页面');
            location.reload();
        }, INACTIVITY_TIMEOUT);
    }

    // 监听鼠标活动
    const mouseEvents = ['mousemove', 'mousedown', 'click', 'scroll', 'keypress', 'touchstart'];
    mouseEvents.forEach(event => {
        document.addEventListener(event, resetInactivityTimer, true);
    });

    // 页面加载后启动计时器
    window.addEventListener('load', () => {
        resetInactivityTimer();
        console.log('自动刷新功能已启动:15秒无活动将自动刷新');
    });
})();