B站♥视频评级

计算B站视频的加权互动播放比并显示,点击复制信息并显示浮动特效,支持动态更新

// ==UserScript==
// @name         B站♥视频评级
// @namespace    http://tampermonkey.net/
// @version      2.0.1
// @description  计算B站视频的加权互动播放比并显示,点击复制信息并显示浮动特效,支持动态更新
// @author       Zola
// @match        https://www.bilibili.com/video/*
// @grant        none
// @license      MIT
// ==/UserScript==

(function() {
    'use strict';

    // 解析包含“万”或“亿”的数字
    function parseCount(text) {
        if (!text) return 0;
        if (text.includes('万')) return parseFloat(text) * 10000;
        if (text.includes('亿')) return parseFloat(text) * 100000000;
        return parseInt(text.replace(/,/g, '')) || 0;
    }

    // 获取评级HTML
    function getRating(ratio) {
        const r = parseFloat(ratio);
        const ratings = [
            [100, '满分视频', '#02c8d3'],    // ≥ 100%
            [95, '好评如潮', 'green'],      // 95%-99.99%
            [80, '非常好评', 'limegreen'],  // 80%-94.99%
            [70, '多半好评', 'yellowgreen'], // 70%-79.99%
            [40, '褒贬不一', 'orange'],     // 40%-69.99%
            [20, '多半差评', 'orangered'],  // 20%-39.99%
            [0, '差评如潮', 'red']          // 0%-19.99%
        ];
        const [_, text, color] = ratings.find(([min]) => r >= min) || ratings[ratings.length - 1];
        return `<span style="color:${color}">${text}</span>`;
    }

    // 获取纯文本评级
    function getPlainRating(ratio) {
        const r = parseFloat(ratio);
        if (r >= 100) return '满分视频';
        if (r >= 95) return '好评如潮';
        if (r >= 80) return '非常好评';
        if (r >= 70) return '多半好评';
        if (r >= 40) return '褒贬不一';
        if (r >= 20) return '多半差评';
        return '差评如潮';
    }

    // 显示浮动特效
    function showCopyEffect(event) {
        const effect = document.createElement('div');
        const isCool = Math.random() > 0.5;
        Object.assign(effect.style, {
            position: 'absolute',
            left: `${event.pageX}px`,
            top: `${event.pageY - 30}px`,
            padding: '6px 12px',
            zIndex: '9999',
            pointerEvents: 'none',
            opacity: '1',
            transition: 'all 0.6s ease-out'
        });

        if (isCool) {
            effect.textContent = 'Copied!';
            Object.assign(effect.style, {
                background: 'linear-gradient(45deg, #ff00cc, #3333ff)',
                color: '#fff',
                borderRadius: '8px',
                fontFamily: 'monospace',
                boxShadow: '0 0 15px rgba(255, 0, 204, 0.8)'
            });
            setTimeout(() => effect.style.transform = 'translateY(-30px) rotate(-5deg)', 50);
        } else {
            effect.textContent = '复制啦~';
            Object.assign(effect.style, {
                background: 'rgba(255, 182, 193, 0.9)',
                color: '#fff',
                border: '2px solid #ff69b4',
                borderRadius: '15px',
                fontFamily: 'Comic Sans MS, cursive'
            });
            setTimeout(() => effect.style.transform = 'translateY(-20px) scale(1.1)', 50);
        }

        setTimeout(() => effect.style.opacity = '0', 50);
        document.body.appendChild(effect);
        setTimeout(() => effect.remove(), 650);
    }

    // 创建工具栏元素
    function createToolbarItem(className, title, content) {
        const wrapper = document.createElement('div');
        wrapper.className = `toolbar-left-item-wrap zola-${className}`;
        const item = document.createElement('div');
        item.className = `${className} video-toolbar-left-item zola-${className}`;
        item.title = title;
        item.innerHTML = `<span class="${className}-info video-toolbar-item-text">${content}</span>`;
        wrapper.appendChild(item);
        return { wrapper, item };
    }

    // 获取视频数据
    function getVideoData() {
        const viewCount = parseCount(document.querySelector('.view-text')?.innerText.trim() || '0');
        const likeCount = parseCount(document.querySelector('.video-like-info.video-toolbar-item-text')?.innerText.trim().replace(/,/g, '') || '0');
        const coinCount = parseCount(document.querySelector('.video-coin-info.video-toolbar-item-text')?.innerText.trim().replace(/,/g, '') || '0');
        const favCount = parseCount(document.querySelector('.video-fav-info.video-toolbar-item-text')?.innerText.trim().replace(/,/g, '') || '0');
        const shareCount = parseCount(document.querySelector('.video-share-info-text')?.innerText.trim().replace(/,/g, '') || '0');
        return { viewCount, likeCount, coinCount, favCount, shareCount };
    }

    // 更新比率和评级
    function updateRatioDisplay() {
        const toolbar = document.querySelector('.video-toolbar-left-main');
        if (!toolbar) return;

        const { viewCount, likeCount, coinCount, favCount, shareCount } = getVideoData();
        const weightedInteractions = (likeCount * 1.5) + (coinCount * 2) + (favCount * 3) + (shareCount * 4);
        let weightedRatio = viewCount < 1000 ? 0 : ((weightedInteractions / viewCount) * 100 * 3).toFixed(2);

        let displayRatio = weightedRatio;
        if (weightedRatio >= 75) {
            displayRatio = 90 + (weightedRatio - 75) * (10 / (200 - 75));
            displayRatio = displayRatio.toFixed(2);
        }

        const displayText = viewCount < 1000 ? '播放不足' : `好评:${displayRatio}%`;
        // 使用 displayRatio 而不是 weightedRatio 来确定评级
        const ratingText = viewCount < 1000 ? '' : getRating(displayRatio);

        let ratioElement = document.querySelector('.zola-video-like-ratio');
        let ratingElement = document.querySelector('.zola-video-like-rating');

        if (!ratioElement) {
            const { wrapper, item } = createToolbarItem('video-like-ratio', '互动播放比', displayText);
            toolbar.appendChild(wrapper);
            ratioElement = item;
        } else {
            ratioElement.querySelector('.video-like-ratio-info').innerHTML = displayText;
        }

        if (!ratingElement) {
            const { wrapper, item } = createToolbarItem('video-like-rating', '评价', ratingText);
            toolbar.appendChild(wrapper);
            ratingElement = item;
        } else {
            ratingElement.querySelector('.video-like-rating-info').innerHTML = ratingText;
        }

        // 绑定点击事件,实时计算复制内容
        [ratioElement, ratingElement].forEach(element => {
            if (!element.hasAttribute('data-click-bound')) {
                element.addEventListener('click', (event) => {
                    event.stopPropagation();
                    // 实时获取最新视频数据
                    const { viewCount, likeCount, coinCount, favCount, shareCount } = getVideoData();
                    const weightedInteractions = (likeCount * 1.5) + (coinCount * 2) + (favCount * 3) + (shareCount * 4);
                    let weightedRatio = viewCount < 1000 ? 0 : ((weightedInteractions / viewCount) * 100 * 3).toFixed(2);
                    let displayRatio = weightedRatio;
                    if (weightedRatio >= 75) {
                        displayRatio = 90 + (weightedRatio - 75) * (10 / (200 - 75));
                        displayRatio = displayRatio.toFixed(2);
                    }
                    const displayText = viewCount < 1000 ? '播放不足' : `好评:${displayRatio}%`;
                    const plainRating = viewCount < 1000 ? '' : getPlainRating(displayRatio);

                    const cleanUrl = window.location.href.split('?')[0];
                    const cleanTitle = document.title.replace('_哔哩哔哩_bilibili', '');
                    const textToCopy = `【${cleanTitle}】【${cleanUrl}】 好评率: ${displayText.replace('好评:', '')} 好评分级: ${plainRating}`;
                    navigator.clipboard.writeText(textToCopy).then(() => showCopyEffect(event));
                });
                element.setAttribute('data-click-bound', 'true');
            }
        });
    }

    // 初始化
    window.addEventListener('load', () => {
        setTimeout(() => {
            updateRatioDisplay();
            setInterval(updateRatioDisplay, 2000); // 每2秒刷新显示
        }, 2000); // 延迟2秒启动
    });
})();

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址