FSM 猜你喜欢全屏图片快捷查看

为FSM推荐项目添加全屏图片审核界面,支持图片拖动和链接跳转

// ==UserScript==
// @name         FSM 猜你喜欢全屏图片快捷查看
// @namespace    http://tampermonkey.net/
// @version      0.5
// @description  为FSM推荐项目添加全屏图片审核界面,支持图片拖动和链接跳转
// @author       You
// @match        https://fsm.name/Recommend*
// @grant        none
// @license MIT
// ==/UserScript==

(function() {
    'use strict';

    // 注入样式
    const style = document.createElement('style');
    style.textContent = `
        .review-overlay {
            position: fixed;
            top: 0;
            left: 0;
            width: 100vw;
            height: 100vh;
            background: rgba(0, 0, 0, 0.95);
            z-index: 9999;
            display: flex;
            flex-direction: column;
            align-items: center;
            justify-content: space-between;
            padding: 20px;
        }

        .review-header {
            width: 100%;
            display: flex;
            justify-content: space-between;
            align-items: center;
            padding: 10px;
            color: white;
        }

        .review-close {
            background: none;
            border: none;
            color: white;
            font-size: 24px;
            cursor: pointer;
            padding: 10px;
            border-radius: 50%;
            display: flex;
            align-items: center;
            justify-content: center;
            transition: background 0.3s;
        }

        .review-close:hover {
            background: rgba(255, 255, 255, 0.1);
        }

        .review-info {
            color: white;
            text-align: center;
            font-size: 16px;
        }

        .review-content {
            flex: 1;
            display: flex;
            flex-direction: column;
            align-items: center;
            justify-content: center;
            width: 100%;
            height: calc(100vh - 150px);
            margin: 10px 0;
            overflow: hidden;
        }

        .review-image {
            max-width: 100%;
            max-height: 100%;
            object-fit: contain;
            border-radius: 8px;
            cursor: grab;
            transition: transform 0.3s ease;
        }

        .review-image.zoomed {
            max-width: none;
            max-height: none;
            transform: scale(1.5);
            cursor: grabbing;
        }

        .image-container {
            display: flex;
            align-items: center;
            justify-content: center;
            overflow: auto;
            width: 100%;
            height: 100%;
            position: relative;
        }

        .review-title {
            color: white;
            margin-top: 15px;
            text-align: center;
            font-size: 16px;
            max-width: 800px;
            cursor: pointer;
            text-decoration: underline;
            transition: color 0.2s;
        }

        .review-title:hover {
            color: #2196F3;
        }

        .review-actions {
            display: flex;
            gap: 20px;
            margin-top: 20px;
        }

        .review-button {
            padding: 12px 24px;
            border: none;
            border-radius: 25px;
            cursor: pointer;
            font-size: 16px;
            font-weight: bold;
            display: flex;
            align-items: center;
            gap: 8px;
            transition: transform 0.2s;
        }

        .review-button:hover {
            transform: scale(1.05);
        }

        .review-favorite {
            background: #4CAF50;
            color: white;
        }

        .review-skip {
            background: #2196F3;
            color: white;
        }

        .review-dislike {
            background: #F44336;
            color: white;
        }

        .trigger-button {
            position: fixed;
            top: 20px;
            right: 20px;
            z-index: 9998;
            padding: 10px 20px;
            background: #2196F3;
            color: white;
            border: none;
            border-radius: 20px;
            cursor: pointer;
            font-size: 14px;
            box-shadow: 0 2px 5px rgba(0,0,0,0.2);
            transition: transform 0.2s;
        }

        .trigger-button:hover {
            transform: scale(1.05);
        }

        .itemSolved {
            opacity: 0.5;
        }
    `;
    document.head.appendChild(style);

    // 全局变量
    let currentKeyHandler = null;

    function createReviewInterface() {
        let currentIndex = 0;
        let isZoomed = false;

        // 获取所有图片元素
        const items = Array.from(document.querySelectorAll('.img-blk.recommend-blk')).map(item => {
            const img = item.querySelector('.lazy__img');
            const link = item.querySelector('a[href*="/Torrents/details"]');
            return {
                img: img.src,
                tid: link.href.split('tid=')[1],
                title: link.closest('.waterfall-card').querySelector('.img-beautify').title || '无标题',
                element: item
            };
        });

        if (items.length === 0) {
            if (window.$notify) {
                window.$notify({
                    message: '没有找到可审核的内容',
                    type: 'warning'
                });
            }
            return;
        }

        const overlay = document.createElement('div');
        overlay.className = 'review-overlay';

        // 头部
        const header = document.createElement('div');
        header.className = 'review-header';

        const closeButton = document.createElement('button');
        closeButton.className = 'review-close';
        closeButton.innerHTML = '×';
        closeButton.onclick = () => {
            overlay.remove();
            if (currentKeyHandler) {
                document.removeEventListener('keydown', currentKeyHandler);
                currentKeyHandler = null;
            }
        };

        const info = document.createElement('div');
        info.className = 'review-info';

        header.appendChild(info);
        header.appendChild(closeButton);

        // 内容区
        const content = document.createElement('div');
        content.className = 'review-content';

        // 创建图片容器
        const imageContainer = document.createElement('div');
        imageContainer.className = 'image-container';

        const image = document.createElement('img');
        image.className = 'review-image';
        image.addEventListener('error', () => {
            // 图片加载失败时的处理
            image.src = 'data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjAwIiBoZWlnaHQ9IjIwMCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48cmVjdCB3aWR0aD0iMjAwIiBoZWlnaHQ9IjIwMCIgZmlsbD0iI2VlZSIvPjx0ZXh0IHg9IjUwJSIgeT0iNTAlIiBmb250LWZhbWlseT0iQXJpYWwsIHNhbnMtc2VyaWYiIGZvbnQtc2l6ZT0iMjQiIHRleHQtYW5jaG9yPSJtaWRkbGUiIGFsaWdubWVudC1iYXNlbGluZT0ibWlkZGxlIiBmaWxsPSIjOTk5Ij7lm77niYfliqDovb3lpLHotKU8L3RleHQ+PC9zdmc+';
        });

        // 添加图片拖动和缩放功能
        let isDragging = false;
        let startX, startY, translateX = 0, translateY = 0;

        // 双击缩放
        image.addEventListener('dblclick', (e) => {
            isZoomed = !isZoomed;
            if (isZoomed) {
                image.classList.add('zoomed');
                image.style.cursor = 'grabbing';
            } else {
                image.classList.remove('zoomed');
                image.style.cursor = 'grab';
                // 重置位置
                translateX = 0;
                translateY = 0;
                image.style.transform = '';
            }
        });

        // 鼠标按下
        image.addEventListener('mousedown', (e) => {
            if (isZoomed) {
                isDragging = true;
                startX = e.clientX - translateX;
                startY = e.clientY - translateY;
                image.style.cursor = 'grabbing';
                e.preventDefault();
            }
        });

        // 鼠标移动
        document.addEventListener('mousemove', (e) => {
            if (isDragging && isZoomed) {
                translateX = e.clientX - startX;
                translateY = e.clientY - startY;
                image.style.transform = `translate(${translateX}px, ${translateY}px) scale(1.5)`;
            }
        });

        // 鼠标释放
        document.addEventListener('mouseup', () => {
            if (isDragging) {
                isDragging = false;
                image.style.cursor = 'grab';
            }
        });

        // 鼠标离开
        document.addEventListener('mouseleave', () => {
            if (isDragging) {
                isDragging = false;
                image.style.cursor = 'grab';
            }
        });

        imageContainer.appendChild(image);

        const title = document.createElement('div');
        title.className = 'review-title';

        // 添加标题点击跳转功能
        title.addEventListener('click', () => {
            const item = items[currentIndex];
            if (item && item.tid) {
                window.open(`https://fsm.name/Torrents/details?tid=${item.tid}`, '_blank');
            }
        });

        content.appendChild(imageContainer);
        content.appendChild(title);

        // 操作按钮
        const actions = document.createElement('div');
        actions.className = 'review-actions';

        const favoriteButton = document.createElement('button');
        favoriteButton.className = 'review-button review-favorite';
        favoriteButton.innerHTML = '⭐ 收藏';

        const skipButton = document.createElement('button');
        skipButton.className = 'review-button review-skip';
        skipButton.innerHTML = '⏭️ 跳过';

        const dislikeButton = document.createElement('button');
        dislikeButton.className = 'review-button review-dislike';
        dislikeButton.innerHTML = '👎 不喜欢';

        actions.appendChild(favoriteButton);
        actions.appendChild(skipButton);
        actions.appendChild(dislikeButton);

        overlay.appendChild(header);
        overlay.appendChild(content);
        overlay.appendChild(actions);

        function updateDisplay() {
            if (currentIndex >= items.length) {
                overlay.remove();
                if (currentKeyHandler) {
                    document.removeEventListener('keydown', currentKeyHandler);
                    currentKeyHandler = null;
                }
                return;
            }

            const item = items[currentIndex];

            // 重置缩放状态和位置
            isZoomed = false;
            image.classList.remove('zoomed');
            image.style.cursor = 'grab';
            image.style.transform = '';
            translateX = 0;
            translateY = 0;

            // 先清空src,然后重新设置,这样可以触发图片重新加载
            image.src = '';
            setTimeout(() => {
                image.src = item.img;
            }, 10);

            title.textContent = item.title;
            title.title = `点击查看详情 (TID: ${item.tid})`;
            info.textContent = `${currentIndex + 1} / ${items.length}`;
        }

        function voteTorrent(tid, value) {
            const authorization = localStorage.getItem('token');
            const deviceId = localStorage.getItem('DeviceId');
            const formData = new FormData();
            formData.append('tid', tid);
            formData.append('status', value);

            return fetch('/api/Torrents/voteTorrent', {
                method: 'POST',
                headers: {
                    'accept': 'application/json',
                    'authorization': authorization,
                    'deviceid': deviceId,
                },
                body: formData
            })
            .then(response => response.json())
            .then(res => {
                if (res && res.success) {
                    if (window.$notify) {
                        window.$notify({
                            message: '操作成功',
                            type: 'success'
                        });
                    }
                    return true;
                }
                return false;
            })
            .catch(error => {
                console.error('操作失败:', error);
                if (window.$notify) {
                    window.$notify({
                        message: '操作失败',
                        type: 'error'
                    });
                }
                return false;
            });
        }

        favoriteButton.onclick = () => {
            const item = items[currentIndex];
            voteTorrent(item.tid, 'VALUE').then((success) => {
                if (success) {
                    // 标记对应的卡片为已处理
                    if (item.element) {
                        item.element.classList.add('itemSolved');
                    }
                }
                currentIndex++;
                updateDisplay();
            }).catch(error => {
                console.error('收藏操作出错:', error);
                // 出错时也继续下一个
                currentIndex++;
                updateDisplay();
            });
        };

        skipButton.onclick = () => {
            currentIndex++;
            updateDisplay();
        };

        dislikeButton.onclick = () => {
            const item = items[currentIndex];
            voteTorrent(item.tid, 'POINTLESS').then((success) => {
                if (success) {
                    // 标记对应的卡片为已处理
                    if (item.element) {
                        item.element.classList.add('itemSolved');
                    }
                }
                currentIndex++;
                updateDisplay();
            }).catch(error => {
                console.error('不喜欢操作出错:', error);
                // 出错时也继续下一个
                currentIndex++;
                updateDisplay();
            });
        };

        // 键盘快捷键
        const keyHandler = function(e) {
            if (!overlay.isConnected) {
                document.removeEventListener('keydown', keyHandler);
                currentKeyHandler = null;
                return;
            }

            switch(e.key) {
                case 'ArrowLeft':
                case 'a':
                    if (currentIndex > 0) {
                        currentIndex--;
                        updateDisplay();
                    }
                    break;
                case 'ArrowRight':
                case 'd':
                    if (currentIndex < items.length - 1) {
                        currentIndex++;
                        updateDisplay();
                    }
                    break;
                case 'f':
                    favoriteButton.click();
                    break;
                case 's':
                    skipButton.click();
                    break;
                case 'x':
                    dislikeButton.click();
                    break;
                case 'z':
                    // 添加缩放快捷键
                    image.click();
                    break;
                case 'Escape':
                    // 如果当前处于缩放状态,先退出缩放
                    if (isZoomed) {
                        isZoomed = false;
                        image.classList.remove('zoomed');
                        image.style.cursor = 'zoom-in';
                    } else {
                        overlay.remove();
                        document.removeEventListener('keydown', keyHandler);
                        currentKeyHandler = null;
                    }
                    break;
            }
        };

        // 设置全局键盘处理器
        if (currentKeyHandler) {
            document.removeEventListener('keydown', currentKeyHandler);
        }
        currentKeyHandler = keyHandler;
        document.addEventListener('keydown', keyHandler);

        updateDisplay();
        return overlay;
    }

    // 添加触发按钮
    function addTriggerButton() {
        const existingButton = document.querySelector('.trigger-button');
        if (existingButton) {
            existingButton.remove();
        }

        const triggerButton = document.createElement('button');
        triggerButton.className = 'trigger-button';
        triggerButton.innerHTML = '🖼️ 快速审核';

        triggerButton.onclick = () => {
            const overlay = createReviewInterface();
            document.body.appendChild(overlay);
        };

        document.body.appendChild(triggerButton);
    }

    // 页面加载完成后添加按钮
    if (document.readyState === 'loading') {
        document.addEventListener('DOMContentLoaded', addTriggerButton);
    } else {
        addTriggerButton();
    }
})();

QingJ © 2025

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