Greasy Fork

Greasy Fork is available in English.

IT之家移动页面热门评论高亮

在全部评论中匹配热门评论并高亮显示,避免重复查看热门评论、精简评论样式、隐藏0赞0反按钮、自动点击更多评论、根据评论总数隐藏一部分低赞低反评论

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

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

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

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

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

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

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

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

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

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

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

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

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

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

// ==UserScript==
// @name         IT之家移动页面热门评论高亮
// @namespace    http://tampermonkey.net/
// @version      1.0.5
// @description  在全部评论中匹配热门评论并高亮显示,避免重复查看热门评论、精简评论样式、隐藏0赞0反按钮、自动点击更多评论、根据评论总数隐藏一部分低赞低反评论
// @author       hui-Zz
// @match        http*://m.ithome.com/*
// @match        http*://bbs.hupu.com/*
// @icon         https://www.emojiall.com/en/header-svg/%F0%9F%93%B0.svg
// @grant        none
// @license      MIT
// ==/UserScript==

(function () {
    'use strict';

    /* 站点配置 */
    const SITE_CONFIG = {
        'm.ithome.com': {
            hotCommentSelector: '.hot-comment .placeholder',   // 热门评论容器选择器
            allCommentSelector: '.all-comment .placeholder',   // 全部评论容器选择器
            usernameSelector: '.user-name',                     // 用户名元素选择器
            contentSelector: '.user-review',                    // 评论内容选择器
            commentContainerHot: '.hot-comment',               // 热门评论区域选择器
            commentContainer: '.all-comment',                   // 全部评论区域选择器
            initAction: () => $('.hot-comment').hide()          // 初始化操作:隐藏热门评论区域
        }
    };

    // 获取当前站点配置
    const hostname = window.location.hostname;
    const config = SITE_CONFIG[hostname];
    if (!config) return; // 非目标站点直接退出
    config.initAction(); // 执行站点初始化操作

    /* 工具函数:生成评论唯一标识 */
    const getCommentKey = comment => `${comment.username}_${comment.content}`;

    /* 核心功能实现 */
    class CommentHighlighter {
        constructor() {
            this.hotComments = new Map();   // 使用Map存储热门评论(O(1)查找)
            this.isDarkMode = window.matchMedia('(prefers-color-scheme: dark)').matches;
            this.commentElementCount = 0;
            this.initObservers();
            this.collectHotComments();     // 初始收集热门评论
            this.highlightComments();      // 初始高亮匹配到的热门评论
        }

        /* 初始化MutationObserver监听 */
        initObservers() {
            // 热门评论区域监听
            this.observeArea(config.commentContainerHot, () => this.collectHotComments());
            // 全部评论区域监听
            this.observeArea(config.commentContainer, () => this.highlightComments());
        }

        /* 通用区域监听方法 */
        observeArea(selector, callback) {
            const targetNode = document.querySelector(selector);
            if (!targetNode) return;

            new MutationObserver(() => callback())
                .observe(targetNode, {
                    childList: true,  // 监听子元素变化
                    subtree: true     // 监听所有后代元素
                });
        }

        /* 收集热门评论 */
        collectHotComments() {
            this.hotComments.clear();

            document.querySelectorAll(config.hotCommentSelector)
                .forEach(commentElement => {
                    const username = this.getText(commentElement, config.usernameSelector);
                    const content = this.getText(commentElement, config.contentSelector);

                    if (username && content) {
                        this.hotComments.set(getCommentKey({ username, content }), true);
                        this.processSpecialElements(commentElement); // 处理特殊元素
                    }
                });
        }

        /* 高亮匹配评论 */
        highlightComments() {
            this.commentElementCount = (el => el ? parseInt(el.textContent, 10) : 0)(document.querySelector('.comment-number'));
            document.querySelectorAll(config.allCommentSelector)
                .forEach(commentElement => {
                    const username = this.getText(commentElement, config.usernameSelector);
                    const content = this.getText(commentElement, config.contentSelector);

                    if (hostname === 'm.ithome.com') {
                        // 点击更多评论
                        commentElement.querySelector('.look-more')?.click();
                        // 处理IP显示
                        this.processHupuIP(commentElement);
                        const reply = commentElement.querySelector('.reply');
                        // 始终隐藏回复按钮(🎈想回复评论注释掉下一行代码)
                        // if (reply) reply.style.display = 'none';
                        const userfloor = commentElement.querySelector('.user-floor');
                        const userwritemsg = commentElement.querySelector('.user-write-msg');
                        const userreview = commentElement.querySelector('.user-review');
                        userfloor.style.float = 'none';
                        userfloor.style.marginLeft = '10px';
                        userwritemsg.style.float = 'right';
                        userwritemsg.style.marginTop = '-20px';
                        userreview.style.marginTop = '5px';
                        // 根据评论总数隐藏一部分低赞低反评论(🎈不隐藏看所有评论注释掉下一行代码)
                        this.hideComments(commentElement);
                    }
                    // 高亮匹配的评论
                    if (username && content && this.hotComments.has(getCommentKey({ username, content }))) {
                        commentElement.classList.add('hot-comment-highlight');
                    }
                });
        }

        /* 隐藏低赞反评论 */
        hideComments(commentElement) {
            if (hostname === 'm.ithome.com') {
                // 获取所有交互元素(安全访问)
                const standby = commentElement.querySelector('.stand-by');
                const oppose = commentElement.querySelector('.oppose');
                const reviewfooter = commentElement.querySelector('.review-footer');

                // 根据评论数量确定支持/反对的隐藏阈值
                let hideStandbyThreshold = [];
                let opposeStandbyThreshold = [];
                if (this.commentElementCount < 20) {
                    // 小于20条,显示所有
                    hideStandbyThreshold = [];
                    opposeStandbyThreshold = [];
                } else if (this.commentElementCount < 50) {
                    // 20-50条,隐藏0、1、2
                    hideStandbyThreshold = [0, 1, 2];
                    opposeStandbyThreshold = [0, 1, 2];
                } else if (this.commentElementCount < 200) {
                    // 50-200条,隐藏0、1、2、3、4
                    hideStandbyThreshold = [0, 1, 2, 3, 4];
                    opposeStandbyThreshold = [0, 1, 2, 3, 4];
                } else {
                    // 大于200条,隐藏10以下
                    hideStandbyThreshold = Array.from({ length: 10 }, (_, i) => i);
                    opposeStandbyThreshold = Array.from({ length: 10 }, (_, i) => i);
                }

                // 处理支持按钮
                if (standby) {
                    const standbyText = standby.textContent?.trim();
                    const match = standbyText?.match(/支持\((\d+)\)/);
                    if (match) {
                        const count = parseInt(match[1]);
                        if (hideStandbyThreshold.includes(count)) {
                            standby.style.display = 'none';
                        }
                    }
                }
                // 处理反对按钮
                if (oppose) {
                    const opposeText = oppose.textContent?.trim();
                    const match = opposeText?.match(/反对\((\d+)\)/);
                    if (match) {
                        const count = parseInt(match[1]);
                        if (opposeStandbyThreshold.includes(count)) {
                            oppose.style.display = 'none';
                        }
                    }
                }
                // 当支持/反对都符合条件时隐藏底部栏
                if (reviewfooter && standby && oppose) {
                    const standbyText = standby.textContent?.trim();
                    const opposeText = oppose.textContent?.trim();
                    const standbyMatch = standbyText?.match(/支持\((\d+)\)/);
                    const opposeMatch = opposeText?.match(/反对\((\d+)\)/);

                    if (standbyMatch && opposeMatch) {
                        const standbyCount = parseInt(standbyMatch[1]);
                        const opposeCount = parseInt(opposeMatch[1]);

                        if (hideStandbyThreshold.includes(standbyCount) && opposeStandbyThreshold.includes(opposeCount)) {
                            reviewfooter.style.display = 'none';
                            var hasDeputyFloor = commentElement.querySelector('li.placeholder.deputy-floor');
                            if (!hasDeputyFloor && commentElement.classList.contains('placeholder') && commentElement.classList.contains('main-floor')) {
                                // 隐藏当前符合隐藏条件并且没有回复的评论
                                commentElement.style.display = 'none';
                            }
                        }
                    }
                }
            }

        }

        /* 辅助方法:安全获取文本内容 */
        getText(element, selector) {
            return element.querySelector(selector)?.textContent?.trim();
        }

        /* 处理IP地址显示 */
        processHupuIP(element) {
            const ipElement = element.querySelector('.user-ip');
            const ipText = ipElement?.textContent?.trim();
            const match = ipText?.match(/IT之家(.*?)网友/);
            if (match) ipElement.textContent = match[1];
        }

        /* 处理站点特殊元素 */
        processSpecialElements(element) {
            // IT之家特殊处理(示例)
            if (hostname === 'm.ithome.com') {
                element.style.display = 'block';
            }
        }
    }

    /* 样式注入 */
    const style = document.createElement('style');
    style.textContent = `
        .hot-comment-highlight {
            background-color: yellow !important;
            border: 2px solid orange !important;
        }
        @media (prefers-color-scheme: dark) {
            .hot-comment-highlight {
                background-color: #333 !important;
                color: #fff !important;
            }
        }
    `;
    document.head.appendChild(style);

    // 启动高亮系统
    new CommentHighlighter();

})();