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

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

目前為 2025-03-24 提交的版本,檢視 最新版本

您需要先安裝使用者腳本管理器擴展,如 TampermonkeyGreasemonkeyViolentmonkey 之後才能安裝該腳本。

You will need to install an extension such as Tampermonkey to install this script.

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyViolentmonkey 後才能安裝該腳本。

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyUserscripts 後才能安裝該腳本。

你需要先安裝一款使用者腳本管理器擴展,比如 Tampermonkey,才能安裝此腳本

您需要先安裝使用者腳本管理器擴充功能後才能安裝該腳本。

(我已經安裝了使用者腳本管理器,讓我安裝!)

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

(我已經安裝了使用者樣式管理器,讓我安裝!)

// ==UserScript==
// @name         微信读书(上下滚动模式)沉浸式阅读主题
// @version      1.2.14
// @description  上拉显示头部和侧栏,下拉隐藏,主题切换、侧边栏开关、页面宽度调整、账户信息显示
// @icon         https://i.miji.bid/2025/03/15/560664f99070e139e28703cf92975c73.jpeg
// @author       Grok
// @match        https://weread.qq.com/web/reader/*
// @match        https://weread.qq.com/*
// @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 = (data.welfare.expiredTime / 86400).toFixed(1);
                    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();
})();