VideosCelebs优化

优化 videocelebs.net 增加预览图,视频自动加宽

// ==UserScript==
// @name         VideosCelebs优化
// @namespace    https://t.me/aibiancheng
// @version      0.3
// @description  优化 videocelebs.net 增加预览图,视频自动加宽
// @author       星宿老魔
// @license      MIT
// @match        https://videocelebs.net/*
// @grant        none
// @icon         https://www.google.com/s2/favicons?sz=64&domain=videocelebs.net
// @run-at       document-start
// ==/UserScript==

(function() {
    'use strict';

    // 立即添加样式,避免页面加载时的跳动
    const styleElement = document.createElement('style');
    styleElement.textContent = `
        /* 在页面加载前隐藏内容区域,避免闪烁 */
        .right_sidebar, .midle_div, .list_videos {
            visibility: hidden !important;
        }
    `;
    document.head.appendChild(styleElement);

    // 创建一个函数来应用所有样式
    function applyStyles() {
        // 移除初始隐藏样式
        styleElement.remove();

        // 添加自定义样式
        const customStyle = document.createElement('style');
        customStyle.textContent = `
            /* 全局背景色调整 */
            body {
                background-color: #121212 !important;
                margin: 0 !important;
                padding: 0 !important;
                width: 100% !important;
                overflow-x: hidden !important;
                color: #e0e0e0 !important;
            }
            .wrap_all { width: 100% !important; max-width: 100% !important; padding: 0 !important; margin: 0 !important; }

            /* 右侧边栏 */
            .right_sidebar {
                position: fixed !important; right: 0 !important; width: 260px !important; overflow-y: auto !important;
                z-index: 1000 !important; background-color: #1e2a38 !important; padding: 10px !important;
                border-radius: 8px 0 0 8px !important; box-shadow: 0 0 10px rgba(0,0,0,0.3) !important;
                visibility: visible !important; transition: none !important;
            }
            .right_sidebar h3 { color: #64b5f6 !important; font-weight: bold !important; border-bottom: 1px solid #2c3e50 !important; padding-bottom: 8px !important; }
            .right_sidebar .menu a, .right_sidebar #menu-years a, .right_sidebar .release a { color: #b0bec5 !important; transition: color 0.2s ease !important; }
            .right_sidebar .menu a:hover, .right_sidebar #menu-years a:hover, .right_sidebar .release a:hover { color: #fff !important; }
            .right_sidebar .tagcloud a { color: #b0bec5 !important; display: inline-block !important; margin: 2px !important; padding: 2px 6px !important; background-color: #2c3e50 !important; border-radius: 3px !important; transition: all 0.2s ease !important; }
            .right_sidebar .tagcloud a:hover { background-color: #3498db !important; color: #fff !important; }
            .right_sidebar .pupular_video .wpp-post-title { color: #b0bec5 !important; display: block !important; margin-top: 4px !important; transition: color 0.2s ease !important; }
            .right_sidebar .pupular_video .wpp-post-title:hover { color: #fff !important; }
            .right_sidebar::-webkit-scrollbar { width: 5px !important; }
            .right_sidebar::-webkit-scrollbar-track { background: rgba(0,0,0,0.2) !important; }
            .right_sidebar::-webkit-scrollbar-thumb { background: rgba(52, 152, 219, 0.5) !important; border-radius: 3px !important; }
            .right_sidebar::-webkit-scrollbar-thumb:hover { background: rgba(52, 152, 219, 0.7) !important; }

            /* 主内容区域 */
            .midle_div {
                margin: 0 280px 0 0 !important; padding: 20px 0 20px 0 !important; width: auto !important;
                max-width: calc(100% - 280px) !important; box-sizing: border-box !important; display: block !important;
                visibility: visible !important;
            }
            .midle_div > h1 { margin-left: 0 !important; padding-left: 15px !important; color: #64b5f6 !important; border-bottom: 1px solid #2c3e50 !important; padding-bottom: 10px !important; margin-bottom: 20px !important; }
            .midle_div > center { margin: 0 20px 0 0 !important; }

            /* 统一的内容项卡片样式 (主页 & 热门) */
            .midle_div .item.big, .list_videos .item {
                display: flex !important; flex-direction: column !important; margin: 0 0 20px 0 !important;
                background-color: #1e2a38 !important; border-radius: 8px !important; padding: 15px !important;
                box-shadow: 0 3px 10px rgba(0,0,0,0.3) !important; position: relative !important;
                transition: transform 0.2s ease, box-shadow 0.2s ease !important;
                width: calc(100% - 20px) !important; border-left: 3px solid #3498db !important;
                overflow: visible !important; visibility: visible !important;
            }
            .midle_div .item.big:hover, .list_videos .item:hover {
                transform: translateX(5px) !important; box-shadow: 0 5px 15px rgba(0,0,0,0.4) !important;
                border-left: 3px solid #64b5f6 !important;
            }
             .list_videos .item { width: auto !important; margin-bottom: 15px !important; padding-bottom: 10px !important; }

            /* 统一的标题样式 */
            .midle_div .item.big .title, .list_videos .item .title {
                order: 1 !important; margin-bottom: 12px !important; padding-bottom: 8px !important;
                border-bottom: 1px solid #2c3e50 !important; position: relative !important;
            }
            .midle_div .item.big .title:after, .list_videos .item .title:after {
                content: "" !important; position: absolute !important; bottom: -1px !important; left: 0 !important;
                width: 50px !important; height: 3px !important; background-color: #3498db !important; border-radius: 3px !important;
            }
            .midle_div .item.big .title h2, .list_videos .item .title h2 {
                font-size: 18px !important; margin: 0 !important; padding: 3px 0 !important; line-height: 1.3 !important;
            }
            .list_videos .item .title h2 { font-size: 16px !important; }
            .midle_div .item.big .title h2 a, .list_videos .item .title h2 a {
                color: #64b5f6 !important; text-decoration: none !important; font-weight: 600 !important;
                transition: color 0.2s ease !important;
            }
            .list_videos .item .title h2 a { font-weight: 500 !important; }
            .midle_div .item.big .title h2 a:hover, .list_videos .item .title h2 a:hover { color: #90caf9 !important; }

            /* 统一的预览图网格 */
            .preview-grid {
                display: grid !important; grid-template-columns: repeat(4, 1fr) !important; gap: 10px !important;
                width: 100% !important; margin-top: 8px !important;
            }
            .list_videos .item .preview-grid {
                margin-bottom: 10px !important;
                order: 2 !important; /* 将预览图的顺序设置在标题之后 */
            }

            .preview-grid a {
                position: relative !important; overflow: hidden !important; border-radius: 6px !important;
                cursor: pointer !important; aspect-ratio: 16 / 9 !important;
                box-shadow: 0 2px 5px rgba(0,0,0,0.3) !important; display: block !important;
                border: 2px solid transparent !important; transition: border-color 0.2s ease !important;
            }
            .preview-grid a:hover { border-color: #3498db !important; }
            .preview-grid a img {
                width: 100% !important; height: 100% !important; object-fit: cover !important;
                display: block !important; border-radius: 4px !important;
                transition: transform 0.3s ease !important;
            }
            .preview-grid a:hover img { transform: scale(1.05) !important; }

            /* 隐藏原始图片 */
            .midle_div .item.big .first > a > img, .list_videos .item > a > .img { display: none !important; }
            .midle_div .item.big .wrap, .midle_div .item.big .rating { display: none !important; }
            .midle_div .item.big .first { order: 2 !important; }

            /* 图片查看器 */
            .image-viewer-overlay {
                position: fixed; top: 0; left: 0; width: 100%; height: 100%;
                background-color: rgba(0,0,0,0.95); z-index: 9999; display: flex;
                justify-content: center; align-items: center; cursor: pointer;
            }
            .image-viewer-content { max-width: 90%; max-height: 90%; position: relative; display: flex; justify-content: center; align-items: center; }
            .image-viewer-content img { max-width: 100%; max-height: 90vh; object-fit: contain; border-radius: 4px; box-shadow: 0 0 20px rgba(0,0,0,0.7); }
            .image-viewer-prev, .image-viewer-next {
                position: absolute; top: 50%; transform: translateY(-50%); background-color: rgba(52,152,219,0.3);
                color: white; font-size: 24px; font-weight: bold; width: 50px; height: 50px; border-radius: 50%;
                display: flex; justify-content: center; align-items: center; cursor: pointer;
                transition: background-color 0.3s; z-index: 10000;
            }
            .image-viewer-prev { left: 20px; }
            .image-viewer-next { right: 20px; }
            .image-viewer-prev:hover, .image-viewer-next:hover { background-color: rgba(52,152,219,0.7); }
            .image-viewer-counter { position: absolute; bottom: -30px; color: white; font-size: 14px; background-color: rgba(52,152,219,0.5); padding: 5px 10px; border-radius: 12px; }

            /* 分页导航 */
            .wp-pagenavi { margin-top: 20px !important; padding: 10px !important; background-color: #1e2a38 !important; border-radius: 8px !important; text-align: center !important; box-shadow: 0 2px 5px rgba(0,0,0,0.3) !important; }
            .wp-pagenavi a, .wp-pagenavi span { margin: 0 3px !important; padding: 5px 10px !important; border-radius: 4px !important; border: none !important; background-color: #2c3e50 !important; color: #b0bec5 !important; transition: all 0.2s ease !important; }
            .wp-pagenavi a:hover { background-color: #3498db !important; color: #fff !important; }
            .wp-pagenavi span.current { background-color: #3498db !important; color: #fff !important; }

            /* 大屏幕适配 */
            @media (min-width: 1800px) {
                .bg { display: flex !important; justify-content: center !important; }
                .wrap_all { max-width: 1800px !important; margin: 0 auto !important; }
            }
        `;
        document.head.appendChild(customStyle);
    }

    // 在DOM内容加载后启动
    window.addEventListener('load', function() {
        applyStyles();

        // 创建全局唯一的图片查看器
        const imageViewer = createImageViewer();

        // 调整右侧边栏位置
        adjustSidebar();
        window.addEventListener('resize', adjustSidebar);
        window.addEventListener('scroll', () => requestAnimationFrame(adjustSidebar));

        // 首次执行
        processItems();

        // 监听DOM变化以处理动态加载的内容
        const observer = new MutationObserver((mutations) => {
            const hasNewNodes = mutations.some(m => m.addedNodes.length > 0);
            if (hasNewNodes) {
                // 使用requestAnimationFrame避免频繁触发
                requestAnimationFrame(processItems);
            }
        });

        observer.observe(document.body, {
            childList: true,
            subtree: true
        });
    });

    // 统一处理函数,包含主页和热门视频
    function processItems() {
        restructureMainContent();
        processPopularVideos();
    }

    // 增强版图片查看器
    function createImageViewer() {
        const overlay = document.createElement('div');
        overlay.className = 'image-viewer-overlay';
        overlay.style.display = 'none';
        
        const content = document.createElement('div');
        content.className = 'image-viewer-content';
        
        const img = document.createElement('img');
        const prevButton = document.createElement('div');
        prevButton.className = 'image-viewer-prev';
        prevButton.innerHTML = '❮';
        const nextButton = document.createElement('div');
        nextButton.className = 'image-viewer-next';
        nextButton.innerHTML = '❯';
        const counter = document.createElement('div');
        counter.className = 'image-viewer-counter';

        content.append(img, prevButton, nextButton, counter);
        overlay.appendChild(content);
        document.body.appendChild(overlay);

        let currentImages = [], currentIndex = 0;

        const closeViewer = () => {
            overlay.style.display = 'none';
            document.body.style.overflow = 'auto';
        };

        const updateCounter = () => {
            counter.textContent = `${currentIndex + 1} / ${currentImages.length}`;
            prevButton.style.display = currentIndex > 0 ? 'flex' : 'none';
            nextButton.style.display = currentIndex < currentImages.length - 1 ? 'flex' : 'none';
        };

        const showImage = (index) => {
            currentIndex = index;
            img.src = currentImages[currentIndex];
            updateCounter();
        };

        overlay.addEventListener('click', e => e.target === overlay && closeViewer());
        prevButton.addEventListener('click', e => { e.stopPropagation(); if (currentIndex > 0) showImage(currentIndex - 1); });
        nextButton.addEventListener('click', e => { e.stopPropagation(); if (currentIndex < currentImages.length - 1) showImage(currentIndex + 1); });

        document.addEventListener('keydown', e => {
            if (overlay.style.display !== 'flex') return;
            if (e.key === 'ArrowLeft') { prevButton.click(); }
            else if (e.key === 'ArrowRight') { nextButton.click(); }
            else if (e.key === 'Escape') { closeViewer(); }
        });

        return {
            show: (imgSrc, allImages, index) => {
                currentImages = allImages || [imgSrc];
                currentIndex = Math.max(0, allImages.indexOf(imgSrc));
                if (index !== undefined) currentIndex = index;

                img.src = currentImages[currentIndex];
                overlay.style.display = 'flex';
                document.body.style.overflow = 'hidden';

                if (currentImages.length > 1) {
                    counter.style.display = 'block';
                    updateCounter();
                } else {
                    counter.style.display = 'none';
                    prevButton.style.display = 'none';
                    nextButton.style.display = 'none';
                }
            }
        };
    }
    
    // 异步获取详情页图片
    async function fetchDetailPageImages(url) {
        try {
            const controller = new AbortController();
            const timeoutId = setTimeout(() => controller.abort(), 5000);
            const response = await fetch(url, { signal: controller.signal });
            clearTimeout(timeoutId);
            if (!response.ok) throw new Error(`HTTP error! status: ${response.status}`);
            
            const html = await response.text();
            const doc = new DOMParser().parseFromString(html, 'text/html');
            
            let imageLinks = Array.from(doc.querySelectorAll('a[rel="screenshots"]'), a => a.href);
            if (imageLinks.length === 0) {
                imageLinks = Array.from(doc.querySelectorAll('a[href*="/wp-content/uploads/"]'), a => a.href).filter(href => href.endsWith('.jpg'));
            }
            return imageLinks.slice(0, 4);
        } catch (error) {
            console.error('Error fetching detail page:', error);
            return [];
        }
    }
    
    // 辅助函数:添加预览图到容器
    function addPreviewImages(container, fullSizeUrls, imageViewer) {
        container.innerHTML = '';
        fullSizeUrls.forEach((src, i) => {
            const previewLink = document.createElement('a');
            previewLink.href = 'javascript:void(0);';
            const previewImg = document.createElement('img');
            previewImg.src = src;
            previewImg.onerror = () => previewLink.remove();
            previewLink.addEventListener('click', e => {
                e.preventDefault();
                imageViewer.show(src, fullSizeUrls, i);
            });
            previewLink.appendChild(previewImg);
            container.appendChild(previewLink);
        });
        
        // 根据图片数量调整布局
        const count = fullSizeUrls.length;
        if (count > 0) {
            container.style.gridTemplateColumns = `repeat(${Math.min(count, 4)}, 1fr)`;
        }
    }

    // 重构主页内容
    function restructureMainContent() {
        const imageViewer = window.myImageViewer || (window.myImageViewer = createImageViewer());
        const items = document.querySelectorAll('.midle_div .item.big:not([data-processed="true"])');

        items.forEach(async (item) => {
            item.setAttribute('data-processed', 'true');
            const titleElement = item.querySelector('.title h2 a');
            if (!titleElement) return;

            const postUrl = titleElement.getAttribute('href');
            const imgElement = item.querySelector('.first > a > img');
            if (!imgElement) return;

            const previewContainer = document.createElement('div');
            previewContainer.className = 'preview-grid';

            const imgSrc = imgElement.getAttribute('src');
            let previewUrls = [];

            if (imgSrc.includes('/videos_screenshots/')) {
                const baseImgPath = imgSrc.replace(/\/source\/\d+\.jpg$/, '').replace(/\/\d+x\d+\/.*?\.jpg$/, '');
                for (let i = 1; i <= 4; i++) {
                    previewUrls.push(`${baseImgPath}/source/${i}.jpg`);
                }
            } else if (postUrl) {
                previewUrls = await fetchDetailPageImages(postUrl);
                if (previewUrls.length === 0) previewUrls.push(imgSrc);
            } else {
                previewUrls.push(imgSrc);
            }

            addPreviewImages(previewContainer, previewUrls, imageViewer);
            const firstElement = item.querySelector('.first');
            if (firstElement) {
                firstElement.innerHTML = '';
                firstElement.appendChild(previewContainer);
            }
        });
    }

    // 处理热门视频
    function processPopularVideos() {
        const imageViewer = window.myImageViewer || (window.myImageViewer = createImageViewer());
        const items = document.querySelectorAll('.list_videos .item:not([data-processed="true"])');

        items.forEach((item) => {
            item.setAttribute('data-processed', 'true');
            const img = item.querySelector('img.thumb');
            if (!img || !img.src.includes('/videos_screenshots/')) return;

            const baseImgPath = img.src.replace(/\/\d+x\d+\/.*?\.jpg$/, '');
            const imgCount = parseInt(img.getAttribute('data-cnt')) || 4;
            const maxImages = Math.min(imgCount, 4);
            
            const fullSizeUrls = [];
            for (let i = 1; i <= maxImages; i++) {
                fullSizeUrls.push(`${baseImgPath}/source/${i}.jpg`);
            }
            if(fullSizeUrls.length === 0) return;

            const previewContainer = document.createElement('div');
            previewContainer.className = 'preview-grid';
            
            addPreviewImages(previewContainer, fullSizeUrls, imageViewer);
            item.appendChild(previewContainer);
        });
    }
    
    // 调整右侧栏位置
    function adjustSidebar() {
        const sidebar = document.querySelector('.right_sidebar');
        if (!sidebar) return;
        
        const header = document.querySelector('.header') || document.querySelector('.header_block') || document.querySelector('header');
        const headerHeight = header ? header.getBoundingClientRect().height : 0;
        const scrollTop = window.scrollY || document.documentElement.scrollTop;
        
        sidebar.style.top = (scrollTop >= headerHeight ? 0 : headerHeight - scrollTop) + 'px';
        sidebar.style.height = `calc(100vh - ${sidebar.style.top})`;
    }

})();