B站视频时长计算器

计算B站视频列表中到指定集数的剩余时长

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

您需要先安装一个扩展,例如 篡改猴Greasemonkey暴力猴,之后才能安装此脚本。

您需要先安装一个扩展,例如 篡改猴暴力猴,之后才能安装此脚本。

您需要先安装一个扩展,例如 篡改猴暴力猴,之后才能安装此脚本。

您需要先安装一个扩展,例如 篡改猴Userscripts ,之后才能安装此脚本。

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

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

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

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

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

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

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

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

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

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

// ==UserScript==
// @name         B站视频时长计算器
// @namespace    http://tampermonkey.net/
// @version      0.5
// @description  计算B站视频列表中到指定集数的剩余时长
// @author       Your name
// @match        https://www.bilibili.com/video/*
// @license      MIT
// @grant        none
// ==/UserScript==

(function() {
    'use strict';

    // ... 其他函数保持不变 ...

    // 获取当前播放的集数
    function getCurrentEpisode() {
        // 尝试从URL中获取当前集数
        const urlParams = new URLSearchParams(window.location.search);
        const p = urlParams.get('p');
        return p ? parseInt(p) : 1;
    }

    // 更新结果显示
    function updateDisplay(resultBox, input) {
        const currentPage = parseInt(input.value) || getCurrentEpisode();
        const result = calculateTotalDuration(currentPage);
        resultBox.textContent = `从第${currentPage}集到最后还有: ${result.duration}`;
        resultBox.style.display = 'block';
    }

    // 初始化插件
    function init() {
        setTimeout(() => {
            const { button, input, resultBox } = createControls();

            // 设置输入框的默认值为当前集数
            input.value = getCurrentEpisode();

            // 页面加载时计算当前集数到最后的时长
            updateDisplay(resultBox, input);

            button.addEventListener('click', () => {
                updateDisplay(resultBox, input);
            });

            // 输入框回车触发计算
            input.addEventListener('keypress', (e) => {
                if (e.key === 'Enter') {
                    button.click();
                }
            });

            button.addEventListener('mouseover', () => {
                if (resultBox.textContent) {
                    resultBox.style.display = 'block';
                }
            });

            button.addEventListener('mouseout', () => {
                resultBox.style.display = 'none';
            });

            // 监听URL变化
            let lastUrl = location.href;
            new MutationObserver(() => {
                const url = location.href;
                if (url !== lastUrl) {
                    lastUrl = url;
                    // URL发生变化时更新输入框和显示
                    setTimeout(() => {
                        input.value = getCurrentEpisode();
                        updateDisplay(resultBox, input);
                    }, 1000); // 等待1秒确保页面更新完成
                }
            }).observe(document, { subtree: true, childList: true });

            // 监听视频播放器的变化
            const observer = new MutationObserver((mutations) => {
                mutations.forEach((mutation) => {
                    if (mutation.target.classList.contains('video-episode-card__info-playing')) {
                        // 当前播放的视频发生变化时更新
                        input.value = getCurrentEpisode();
                        updateDisplay(resultBox, input);
                    }
                });
            });

            // 开始观察视频列表区域
            const videoList = document.querySelector('.video-episode-card');
            if (videoList) {
                observer.observe(videoList.parentElement, {
                    subtree: true,
                    attributes: true,
                    attributeFilter: ['class']
                });
            }
        }, 2000);
    }

    // 等待页面加载完成后初始化
    window.addEventListener('load', init);
})();