Greasy Fork

Greasy Fork is available in English.

手机百度贴吧自动展开楼层

有时候用手机的浏览器打开百度贴吧,只想看一眼就走,并不想打开APP,这个脚本用于帮助用户自动展开楼层。注意:只支持手机浏览器,测试环境为Iceraven+Tampermonkey

目前为 2022-06-01 提交的版本,查看 最新版本

// ==UserScript==
// @name         手机百度贴吧自动展开楼层
// @namespace    http://tampermonkey.net/
// @version      1.0
// @description  有时候用手机的浏览器打开百度贴吧,只想看一眼就走,并不想打开APP,这个脚本用于帮助用户自动展开楼层。注意:只支持手机浏览器,测试环境为Iceraven+Tampermonkey
// @author       voeoc
// @match        https://tieba.baidu.com/p/*
// @match        https://jump2.bdimg.com/p/*
// @match        https://tiebac.baidu.com/p/*
// @icon         https://tieba.baidu.com/favicon.ico
// @grant        unsafeWindow
// @grant        GM_addStyle
// @license MIT
// ==/UserScript==

(function () {
    'use strict';
    const DEBUGLOG_SWITCH = false; // 调试信息开关
    const isFixedTitle = false; // 是否将标题置顶

    const PAGE_TYPE = { // 页面类型
        UNKNOW: -1, // 未知
        MAINPAGE: 0, // 主页
        POSTPAGE: 1, // 评论页
        FLOORREPLAYPAGE: 2, //楼中楼页
    };

    let tie = undefined; // 一楼
    let tiebaName = undefined; // 吧名

    let currentHash = unsafeWindow.location.hash; // 存储当前页的Hash
    let oldHash = currentHash; // 存储上一链接的Hash
    let scrollPos = undefined; // 存储当前滚动位置

    function DEBUGLOG(msg, label = "") {
        if (!DEBUGLOG_SWITCH) {
            return;
        }
        let outputFunc = console.log;
        if (label == "error") {
            outputFunc = console.error;
        }
        outputFunc(`voeoc(DEBUG)<${label}>: ${msg}`);
    }

    function waitElementLoaded(selector, func, TIME_OUT = 30) {
        //const TIME_OUT = 30; // 找n次没有找到就放弃
        let findTimeNum = 0; // 记录查找的次数
        let timer = setInterval(() => {
            let element = document.querySelector(selector);
            DEBUGLOG(`${selector}=${element}`, "waitElementLoaded");
            if (element != null) {
                // 清除定时器
                clearInterval(timer);
                func(element);
            } else {
                findTimeNum++;
                if (TIME_OUT < findTimeNum) {
                    // 清除定时器
                    clearInterval(timer);
                }
            }
        }, 200);
    }

    // 简单判断当前页面的类型
    function getPageType(hash = unsafeWindow.location.hash) {
        if (hash === "" || hash === "#/") {
            return PAGE_TYPE.MAINPAGE;
        } else if (RegExp(`postPage\?.*postAuthorId=.*`, 'i').test(hash)) {
            return PAGE_TYPE.POSTPAGE;
        } else if (RegExp(`lzlPage\?.*floor=.*`, 'i').test(hash)) {
            return PAGE_TYPE.FLOORREPLAYPAGE;
        }
        return PAGE_TYPE.UNKNOW;
    }

    // 检测URL Hash变化
    function checkUrlHashChange() {
        let newHash = unsafeWindow.location.hash;
        oldHash = currentHash;
        if(oldHash != newHash) {
            currentHash = newHash;
        } else {
            return false;
        }

        let pageType = getPageType();
        DEBUGLOG(pageType, "onhashchange");
        if (pageType == PAGE_TYPE.POSTPAGE) {
            // 恢复一楼显示
            restore();

            // 页面切换后恢复滚动位置
            scrollTo(scrollPos);
        } else if(pageType == PAGE_TYPE.MAINPAGE) {
            if(tie) {
                // 将剪切走的一楼复制回来
                waitElementLoaded("#replySwitch", (splitline) => { // 等待页面加载完成
                    splitline.parentNode.insertBefore(tie, splitline);
                }, 10);
                scrollTo(0);
            }
        }
        return true;
    }

    // 滚动到指定y坐标
    function scrollTo(yPos) {
        waitElementLoaded(".thread-title", (_) => { // 等待页面加载完成
            document.documentElement.scrollTop = yPos;
            setTimeout(function () {
                document.documentElement.scrollTop = yPos;
                DEBUGLOG(yPos, "scrollTo");
            }, 10);
        });
    }


    // 显示一楼的内容
    function restore() {
        DEBUGLOG("restore")
        waitElementLoaded(".text", (titletext) => { // 等待标题位置加载
            // 显示贴吧名
            try {
                let tiebaNameclone = tiebaName.cloneNode(true);
                titletext.parentNode.replaceChild(tiebaNameclone, titletext);
                // 关联点击贴吧名的事件
                tiebaNameclone.onclick = function () {
                    tiebaName.click();
                }
            } catch (e) { console.error(e); }

            // 显示楼主发帖层
            try {
                // 复原样式丢失
                tie.style.cssText = `
                    margin-left: 0.12rem;
                    margin-right: 0.12rem;
                    margin-bottom: 0.25rem;
                `
                // 尝试找回楼主丢失的头像
                try {
                    let lzavatar = tie.querySelector(".avatar");
                    lzavatar.style.backgroundImage = `url("${lzavatar.getAttribute("data-src")}")`
                } catch (e) { console.error(e); }

                // 尝试复原发帖内容的字体样式
                try {
                    let textContent = tie.querySelector(".thread-text");
                    textContent.style.cssText = `
                            margin-top: 0.18rem;
                            font-size: 0.16rem;
                            line-height: 0.28rem;
                        `
                } catch (e) { console.error(e); }

                let replySwitch = document.querySelector("#replySwitch"); // 标题下方的分割
                replySwitch.parentNode.insertBefore(tie, replySwitch);
            } catch (e) { console.error(e); }

            // 尝试复原标题样式
            try {
                let threadtitle = document.querySelector(".thread-title");
                threadtitle.style.cssText = `
                    margin-bottom: 0.13rem;
                    font-size: 0.22rem;
                    font-weight: 700;
                    line-height: 0.33rem;
                `

                // 置顶标题显示
                if (isFixedTitle) {
                    let threadtitleclone = threadtitle.cloneNode(true)
                    threadtitle.style.visibility = "hidden";
                    threadtitleclone.style.cssText += `
                        position: fixed !important;
                        z-index: 99 !important;
                        opacity: 0.8 !important;
                        background-color: #FFFFFF !important;
                    `
                    threadtitle.parentNode.insertBefore(threadtitleclone, threadtitle)
                }
            } catch (e) { console.error(e); }
        })
    }

    (function main() {
        // 删减多余的打开APP的诱导按钮
        GM_addStyle(`
            .comment-box, .only-lz, .nav-bar-bottom, .open-app, .more-image-desc {
                display: none !important;
                visibility: hidden !important;
            }
        `)

        unsafeWindow.onscroll = function () {
            checkUrlHashChange();

            if (getPageType() == PAGE_TYPE.POSTPAGE) {
                if(unsafeWindow.pageYOffset != 0) {
                    // 记录当前滚动位置
                    scrollPos = unsafeWindow.pageYOffset;
                    //DEBUGLOG(scrollPos, "scrollPos");
                }
            }
        }

        unsafeWindow.onhashchange = function(e) {
            checkUrlHashChange();
        }

        switch (getPageType()) {
            case PAGE_TYPE.MAINPAGE:
                waitElementLoaded(".post-page-entry-btn", (postbtn) => {
                    tiebaName = document.querySelector(".forum-block"); // 获取吧名
                    tie = document.querySelector(".main-thread-content"); // 获取楼主发帖内容

                    // 点击展开按钮
                    postbtn.click();

                    // 手动触发页面刷新检测
                    checkUrlHashChange();
                })
                break;
            case PAGE_TYPE.POSTPAGE:
                // 如果当前刷新加载的是评论页,则需要先打开主页面获取数据
                unsafeWindow.location.hash = "";
                unsafeWindow.location.reload();
                break;
            case PAGE_TYPE.FLOORREPLAYPAGE:
                break;
            default:
                break;
        }
    })()
})();