Greasy Fork

Greasy Fork is available in English.

微信读书(上下滚动模式)沉浸式阅读主题

上拉显示头部和侧栏,下拉隐藏,主题切换、侧边栏开关、页面宽度调整、账户信息显示

当前为 2025-03-25 提交的版本,查看 最新版本

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

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

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

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

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

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

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

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

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

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

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

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

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

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

// ==UserScript==
// @name         微信读书(上下滚动模式)沉浸式阅读主题
// @version      1.2.16
// @description  上拉显示头部和侧栏,下拉隐藏,主题切换、侧边栏开关、页面宽度调整、账户信息显示
// @icon         https://i.miji.bid/2025/03/15/560664f99070e139e28703cf92975c73.jpeg
// @author       Grok
// @match        https://weread.qq.com/web/reader/*
// @require      https://code.jquery.com/jquery-3.3.1.min.js
// @grant        GM_setValue
// @grant        GM_getValue
// @grant        GM_xmlhttpRequest
// @license      MIT
// @namespace    http://github.com/lossj
// ==/UserScript==

(function() {
    'use strict';

    // 定义主题对象
    const themes = {
        '极光灰': { background: '#E0E0E0', fontColor: '#222222' },
        '浅咖色': { background: '#FAEBD7', fontColor: '#222222' },
        '米黄色': { background: '#F5F5DC', fontColor: '#332222' },
        '豆沙绿': { background: '#E6F5E6', fontColor: '#223322' },
        '海天蓝': { background: '#EBF5FF', fontColor: '#444444' },
        '晨曦白': { background: '#F8F8F8', fontColor: '#333333' },
        '夜空黑': { background: '#1A1A2E', fontColor: '#E5E5E5' },
        '星辰黑': { background: '#2D2D2D', fontColor: '#F0F0F0' },
        '幽暗黑': { background: '#121212', fontColor: '#FFFFFF' },
        '月影黑': { background: '#2E3440', fontColor: '#D8DEE9' },
        '深林黑': { background: '#1C2526', fontColor: '#B0BEC5' },
        '静夜黑': { background: '#0F1419', fontColor: '#E0E0E0' }
    };

    // 获取或设置存储值
    let currentTheme = GM_getValue('currentTheme', '豆沙绿');
    let hideSidebarOnScrollDown = GM_getValue('hideSidebarOnScrollDown', false);
    let pageWidth = GM_getValue('pageWidth', 1200);

    // 自定义样式
    const customStyle = `
        .readerContent, .app_content, .readerChapterContent {
            font-family: "霞鹜文楷", "PingFang SC", "宋体";
            font-size: 18px !important;
            color: ${themes[currentTheme].fontColor} !important;
            background-color: ${themes[currentTheme].background} !important;
            max-width: ${pageWidth}px !important;
            margin: 0 auto !important;
            padding: 20px !important;
        }

        .readerChapterContent p, .readerChapterContent div, .readerChapterContent span {
            font-family: inherit;
            font-size: inherit !important;
            color: inherit !important;
        }

        body, html {
            background-color: ${themes[currentTheme].background} !important;
        }

        .readerTopBar, .navBar {
            max-width: ${pageWidth}px !important;
            width: 100% !important;
            margin-left: auto !important;
            margin-right: auto !important;
            position: fixed !important;
            top: 4px !important;
            left: 50% !important;
            transform: translateX(-50%) !important;
            transition: transform 0.15s ease-out !important;
            z-index: 1000 !important;
            backdrop-filter: blur(10px) !important;
            -webkit-backdrop-filter: blur(10px) !important;
            background: rgba(255, 255, 255, 0.8) !important;
            box-shadow: 0 1px 10px rgba(0, 0, 0, 0.1) !important;
            padding: 5px 10px !important;
            border-radius: 12px !important;
        }

        .readerTopBar.hidden {
            transform: translateX(-50%) translateY(-115%) !important;
        }

        @media (min-width: 768px) {
            .readerTopBar, .navBar {
                max-width: ${pageWidth}px !important;
                left: 50% !important;
                transform: translateX(-50%) !important;
                padding: 5px 10px !important;
            }
        }

        .readerControls {
            position: fixed !important;
            right: 110px !important;
            bottom: 200px !important;
            left: auto !important;
            transition: opacity 0.3s ease !important;
            opacity: 1 !important;
            z-index: 3000 !important;
        }

        .readerCatalog {
            position: fixed !important;
            left: 50% !important;
            top: 50% !important;
            transform: translate(-50%, -50%) !important;
            right: auto !important;
            bottom: auto !important;
            z-index: 3000 !important;
            margin: 0 !important;
            width: 560px !important;
            max-height: 95vh !important;
            transition: opacity 0.3s ease !important;
            opacity: 1 !important;
            background-color: #fff !important;
            box-shadow: 0 2px 10px rgba(0, 0, 0, 0.2) !important;
            border-radius: 8px !important;
        }

        .readerControls.hidden, .readerCatalog.hidden {
            opacity: 0 !important;
        }

        #themeToggleBtn, #sidebarToggleBtn, #widthAdjustBtn, #accountInfoBtn {
            position: fixed;
            right: 110px !important;
            width: 48px;
            height: 48px;
            background-color: #ffffff !important;
            color: #333 !important;
            border: none;
            border-radius: 50%;
            cursor: pointer;
            z-index: 2000;
            display: flex;
            align-items: center;
            justify-content: center;
            font-size: 20px;
            box-shadow: 0 2px 5px rgba(0, 0, 0, 0.1) !important;
            transition: opacity 0.3s ease !important;
        }

        #accountInfoBtn { bottom: calc(780px); }
        #themeToggleBtn { bottom: calc(707px); }
        #sidebarToggleBtn { bottom: calc(634px); }
        #widthAdjustBtn { bottom: calc(561px); }

        #themeToggleBtn.hidden, #sidebarToggleBtn.hidden, #widthAdjustBtn.hidden, #accountInfoBtn.hidden {
            opacity: 0 !important;
        }

        #sidebarToggleBtn.active {
            background-color: #e0e0e0 !important;
        }

        .themeDot {
            width: 20px;
            height: 20px;
            border-radius: 50%;
            cursor: pointer;
            border: 2px solid #fff;
            box-shadow: 0 0 3px rgba(0, 0, 0, 0.3);
            position: relative;
        }

        .themeDot.active {
            border: 2px solid #000;
        }

        .themeDot::before {
            content: attr(title);
            position: absolute;
            top: -30px;
            left: 50%;
            transform: translateX(-50%);
            background-color: rgba(0, 0, 0, 0.8);
            color: #fff;
            padding: 3px 6px;
            border-radius: 4px;
            font-size: 12px;
            white-space: nowrap;
            visibility: hidden;
            opacity: 0;
            transition: opacity 0.2s ease;
            z-index: 2001;
        }

        .themeDot:hover::before {
            visibility: visible;
            opacity: 1;
        }

        #themePanel, #widthPanel, #accountPanel {
            position: fixed;
            background-color: rgba(255, 255, 255, 0.9);
            padding: 10px;
            border-radius: 8px;
            box-shadow: 0 2px 10px rgba(0, 0, 0, 0.2);
            z-index: 2000;
            display: none;
            flex-direction: column;
            gap: 10px;
            max-width: 250px;
            backdrop-filter: blur(5px);
            transition: all 0.3s ease-out !important;
            opacity: 0;
            transform: translateX(-20px);
        }

        #themePanel.show, #widthPanel.show, #accountPanel.show {
            opacity: 1;
            transform: translateX(0);
        }

        .themeRow {
            display: flex;
            flex-direction: row;
            gap: 5px;
            flex-wrap: nowrap;
        }

        #widthSlider {
            -webkit-appearance: none;
            appearance: none;
            width: 150px;
            height: 2px;
            background: linear-gradient(to right, #000 0%, #000 var(--progress, 0%), #D3D3D3 var(--progress, 0%) 100%);
            outline: none;
            border-radius: 1px;
            cursor: pointer;
        }

        #widthSlider::-webkit-slider-thumb {
            -webkit-appearance: none;
            appearance: none;
            width: 8px;
            height: 8px;
            background: #333;
            border-radius: 50%;
            cursor: pointer;
        }

        #widthSlider::-moz-range-thumb {
            width: 8px;
            height: 8px;
            background: #333;
            border-radius: 50%;
            cursor: pointer;
        }

        #widthLabel {
            font-size: 14px;
            color: #333;
        }

        #accountPanel .data-row {
            display: flex;
            justify-content: space-between;
            min-width: 100px;
        }

        #accountPanel .data-label {
            margin-right: 8px;
            color: #1A1A1A !important;
        }

        #accountPanel .data-value {
            font-weight: 500;
            color: #000000 !important;
        }

        @media (max-width: 768px) {
            #themePanel, #widthPanel, #accountPanel {
                max-width: 200px;
                padding: 5px;
            }
            #widthSlider {
                width: 120px;
            }
            .themeDot {
                width: 18px;
                height: 18px;
            }
            .readerControls, #themeToggleBtn, #sidebarToggleBtn, #widthAdjustBtn, #accountInfoBtn {
                right: 50px !important;
            }
            .readerCatalog {
                width: 400px !important;
            }
        }
    `;

    // 应用样式
    const styleSheet = document.createElement('style');
    styleSheet.type = 'text/css';
    styleSheet.innerText = customStyle;
    document.head.appendChild(styleSheet);

    // 创建账户信息按钮和面板
    const accountInfoBtn = document.createElement('button');
    accountInfoBtn.id = 'accountInfoBtn';
    accountInfoBtn.innerText = '👤';
    document.body.appendChild(accountInfoBtn);

    const accountPanel = document.createElement('div');
    accountPanel.id = 'accountPanel';
    accountPanel.innerHTML = `
        <div class="data-row">
            <span class="data-label">体验卡</span>
            <span class="data-value" id="infinite-card">--</span>
        </div>
        <div class="data-row">
            <span class="data-label">苹果书币</span>
            <span class="data-value" id="ios-coin">--</span>
        </div>
        <div class="data-row">
            <span class="data-label">安卓书币</span>
            <span class="data-value" id="android-coin">--</span>
        </div>
    `;
    document.body.appendChild(accountPanel);

    accountInfoBtn.addEventListener('click', () => {
        const isHidden = accountPanel.style.display === 'none' || accountPanel.style.display === '';
        if (isHidden) {
            accountPanel.style.display = 'flex';
            setTimeout(() => accountPanel.classList.add('show'), 10);
            const btnRect = accountInfoBtn.getBoundingClientRect();
            accountPanel.style.right = `${document.documentElement.clientWidth - btnRect.left + 10}px`;
            accountPanel.style.bottom = `${document.documentElement.clientHeight - btnRect.bottom + (btnRect.height / 2) - (accountPanel.offsetHeight / 2)}px`;
        } else {
            accountPanel.classList.remove('show');
            setTimeout(() => accountPanel.style.display = 'none', 300);
        }
    });

    // 创建主题切换按钮和面板
    const toggleBtn = document.createElement('button');
    toggleBtn.id = 'themeToggleBtn';
    toggleBtn.innerText = '🎨';
    document.body.appendChild(toggleBtn);

    const themePanel = document.createElement('div');
    themePanel.id = 'themePanel';
    document.body.appendChild(themePanel);

    const dayThemes = ['极光灰', '浅咖色', '米黄色', '豆沙绿', '海天蓝', '晨曦白'];
    const nightThemes = ['夜空黑', '星辰黑', '幽暗黑', '月影黑', '深林黑', '静夜黑'];

    const dayRow = document.createElement('div');
    dayRow.className = 'themeRow';
    const nightRow = document.createElement('div');
    nightRow.className = 'themeRow';

    dayThemes.forEach(theme => {
        const dot = document.createElement('div');
        dot.className = 'themeDot';
        dot.style.backgroundColor = themes[theme].background;
        dot.setAttribute('title', theme);
        if (theme === currentTheme) dot.classList.add('active');
        dot.addEventListener('click', () => {
            GM_setValue('currentTheme', theme);
            location.reload();
            themePanel.classList.remove('show');
            setTimeout(() => themePanel.style.display = 'none', 300);
        });
        dayRow.appendChild(dot);
    });

    nightThemes.forEach(theme => {
        const dot = document.createElement('div');
        dot.className = 'themeDot';
        dot.style.backgroundColor = themes[theme].background;
        dot.setAttribute('title', theme);
        if (theme === currentTheme) dot.classList.add('active');
        dot.addEventListener('click', () => {
            GM_setValue('currentTheme', theme);
            location.reload();
            themePanel.classList.remove('show');
            setTimeout(() => themePanel.style.display = 'none', 300);
        });
        nightRow.appendChild(dot);
    });

    themePanel.appendChild(dayRow);
    themePanel.appendChild(nightRow);

    toggleBtn.addEventListener('click', () => {
        const isHidden = themePanel.style.display === 'none' || themePanel.style.display === '';
        if (isHidden) {
            themePanel.style.display = 'flex';
            setTimeout(() => themePanel.classList.add('show'), 10);
            const btnRect = toggleBtn.getBoundingClientRect();
            themePanel.style.right = `${document.documentElement.clientWidth - btnRect.left + 10}px`;
            themePanel.style.bottom = `${document.documentElement.clientHeight - btnRect.bottom + (btnRect.height / 2) - (themePanel.offsetHeight / 2)}px`;
        } else {
            themePanel.classList.remove('show');
            setTimeout(() => themePanel.style.display = 'none', 300);
        }
    });

    function updateActiveDot() {
        document.querySelectorAll('.themeDot').forEach(dot => {
            dot.classList.remove('active');
            if (dot.style.backgroundColor === themes[currentTheme].background) {
                dot.classList.add('active');
            }
        });
    }

    // 创建侧边栏开关按钮
    const sidebarToggleBtn = document.createElement('button');
    sidebarToggleBtn.id = 'sidebarToggleBtn';
    sidebarToggleBtn.innerText = hideSidebarOnScrollDown ? '🙈' : '👁️';
    if (hideSidebarOnScrollDown) sidebarToggleBtn.classList.add('active');
    document.body.appendChild(sidebarToggleBtn);

    sidebarToggleBtn.addEventListener('click', () => {
        hideSidebarOnScrollDown = !hideSidebarOnScrollDown;
        GM_setValue('hideSidebarOnScrollDown', hideSidebarOnScrollDown);
        sidebarToggleBtn.innerText = hideSidebarOnScrollDown ? '🙈' : '👁️';
        sidebarToggleBtn.classList.toggle('active');
    });

    // 创建页面宽度调整按钮和面板
    const widthAdjustBtn = document.createElement('button');
    widthAdjustBtn.id = 'widthAdjustBtn';
    widthAdjustBtn.innerText = '📏';
    document.body.appendChild(widthAdjustBtn);

    const widthPanel = document.createElement('div');
    widthPanel.id = 'widthPanel';
    document.body.appendChild(widthPanel);

    const widthSlider = document.createElement('input');
    widthSlider.type = 'range';
    widthSlider.id = 'widthSlider';
    widthSlider.min = '600';
    widthSlider.max = '1800';
    widthSlider.step = '10';
    widthSlider.value = pageWidth;
    widthPanel.appendChild(widthSlider);

    const widthLabel = document.createElement('span');
    widthLabel.id = 'widthLabel';
    widthLabel.innerText = `${pageWidth}px`;
    widthPanel.appendChild(widthLabel);

    function updateProgress() {
        const slider = document.getElementById('widthSlider');
        const value = ((slider.value - slider.min) / (slider.max - slider.min)) * 100;
        slider.style.setProperty('--progress', `${value}%`);
    }

    widthAdjustBtn.addEventListener('click', () => {
        const isHidden = widthPanel.style.display === 'none' || widthPanel.style.display === '';
        if (isHidden) {
            widthPanel.style.display = 'flex';
            setTimeout(() => widthPanel.classList.add('show'), 10);
            const btnRect = widthAdjustBtn.getBoundingClientRect();
            widthPanel.style.right = `${document.documentElement.clientWidth - btnRect.left + 10}px`;
            widthPanel.style.bottom = `${document.documentElement.clientHeight - btnRect.bottom + (btnRect.height / 2) - (widthPanel.offsetHeight / 2)}px`;
        } else {
            widthPanel.classList.remove('show');
            setTimeout(() => widthPanel.style.display = 'none', 300);
        }
    });

    widthSlider.addEventListener('input', () => {
        pageWidth = parseInt(widthSlider.value);
        GM_setValue('pageWidth', pageWidth);
        widthLabel.innerText = `${pageWidth}px`;
        updateProgress();
        setTimeout(() => location.reload(), 200);
    });

    updateProgress();

    // 获取账户数据
    const fetchAccountData = () => {
        GM_xmlhttpRequest({
            method: 'POST',
            url: 'https://weread.qq.com/web/pay/balance',
            data: 'zoneid=1&release=1&pf=weread_wx-2001-iap-2001-iphone',
            headers: {
                'Content-Type': 'application/x-www-form-urlencoded'
            },
            onload: function(res) {
                try {
                    const data = JSON.parse(res.responseText);
                    const infiniteDays = Math.floor(data.welfare.expiredTime / 86400);
                    document.getElementById('infinite-card').textContent = `${infiniteDays}天`;
                    document.getElementById('ios-coin').textContent = data.giftBalance;
                    document.getElementById('android-coin').textContent = data.peerBalance;
                } catch(e) {
                    console.error('账户数据解析失败:', e);
                }
            }
        });
    };

    // 初始化并定时更新账户数据
    fetchAccountData();
    setInterval(fetchAccountData, 300000);

    // 沉浸式阅读功能
    let windowTop = 0;
    $(window).scroll(function() {
        let scrollS = $(window).scrollTop();
        let topBar = document.querySelector('.readerTopBar');
        let readerControl = document.querySelector('.readerControls');
        let readerCatalog = document.querySelector('.readerCatalog');
        let accountBtn = document.querySelector('#accountInfoBtn');
        let themeBtn = document.querySelector('#themeToggleBtn');
        let sidebarBtn = document.querySelector('#sidebarToggleBtn');
        let widthBtn = document.querySelector('#widthAdjustBtn');

        if (scrollS > windowTop && scrollS > 50) {
            if (topBar && hideSidebarOnScrollDown) topBar.classList.add('hidden');
            if (readerControl && hideSidebarOnScrollDown) readerControl.classList.add('hidden');
            if (readerCatalog && hideSidebarOnScrollDown) readerCatalog.classList.add('hidden');
            if (accountBtn && hideSidebarOnScrollDown) accountBtn.classList.add('hidden');
            if (themeBtn && hideSidebarOnScrollDown) themeBtn.classList.add('hidden');
            if (sidebarBtn && hideSidebarOnScrollDown) sidebarBtn.classList.add('hidden');
            if (widthBtn && hideSidebarOnScrollDown) widthBtn.classList.add('hidden');
            if (accountPanel) accountPanel.style.display = 'none';
            if (themePanel) themePanel.style.display = 'none';
            if (widthPanel) widthPanel.style.display = 'none';
        } else {
            if (topBar) topBar.classList.remove('hidden');
            if (readerControl) readerControl.classList.remove('hidden');
            if (readerCatalog) readerCatalog.classList.remove('hidden');
            if (accountBtn) accountBtn.classList.remove('hidden');
            if (themeBtn) themeBtn.classList.remove('hidden');
            if (sidebarBtn) sidebarBtn.classList.remove('hidden');
            if (widthBtn) widthBtn.classList.remove('hidden');
        }
        windowTop = scrollS;
    });

    updateActiveDot();
})();