花瓣图片导入PS

为花瓣网站上的图片添加导入PS按钮,并为付费素材添加蒙版标记

// ==UserScript==
// @license MIT
// @name         花瓣图片导入PS
// @namespace    http://tampermonkey.net/
// @version      0.7
// @description  为花瓣网站上的图片添加导入PS按钮,并为付费素材添加蒙版标记
// @author       You
// @match        https://huaban.com/*
// @grant        none
// ==/UserScript==

(function() {
    'use strict';

    // 额外检查:确保不在 pins 页面执行
    if (window.location.href.includes('/pins/')) {
        return;
    }

    // ========== 透明度设置 ==========
    // 设置蒙版透明度等级:0-10 (0=透明, 10=纯黑)
    const OPACITY_LEVEL = 2;
    // ================================

    // 将等级转换为实际透明度值 (0-1)
    const actualOpacity = OPACITY_LEVEL / 10;

    // 添加样式
    const style = document.createElement('style');
    style.className = 'huaban-btn-style';
    style.textContent = `
        .huaban-img-btn-wrap { position: relative !important; display: inline-block !important; }
        .huaban-img-btn-icon {
            position: absolute; top: 10px; right: 10px; z-index: 1000;
            width: 48px; height: 48px; display: flex; align-items: center; justify-content: center;
            cursor: pointer; border: none; background: transparent; padding: 0; margin: 0;
            border-radius: 8px;
            box-sizing: border-box;
            opacity: 0;
            transition: opacity 0.3s ease;
        }
        .huaban-img-btn-icon img { width: 36px; height: 36px; background: transparent; border: none; display: block; }
        .huaban-img-btn-icon.clicked {
            border: 10px solid rgba(20, 134, 226, 0.5) !important;
            border-radius: 20px !important;
            animation: borderFade 0.8s ease !important;
        }

        @keyframes borderFade {
            0% {
                border-width: 0px;
                opacity: 0;
            }
            50% {
                border-width: 10px;
                opacity: 1;
            }
            100% {
                border-width: 0px;
                opacity: 0;
            }
        }

        .huaban-img-btn-wrap:hover .huaban-img-btn-icon {
            opacity: 1;
        }

        .huaban-img-btn-icon:hover {
            transform: scale(1.1);
            transition: transform 0.2s ease;
        }
    `;
    document.head.appendChild(style);

    // 判断图片是否为花瓣大图
    function isHuabanImg(img) {
        const src = img.getAttribute('src') || '';
        const srcset = img.getAttribute('srcset') || '';

        // 检查主链接
        if (src.startsWith('https://gd-hbimg.huaban.com')) {
            // 屏蔽结尾是 _fw86(后面不能有其他字符)
            if (/_fw86($|\?)/.test(src)) {
                return false;
            }
            return true;
        }
        // 检查srcset里是否有合格的链接
        if (srcset.includes('https://gd-hbimg.huaban.com')) {
            // 只要srcset里有一个不是_fw86结尾的就可以
            return srcset.split(',').some(part => {
                const url = part.trim().split(' ')[0];
                return url.startsWith('https://gd-hbimg.huaban.com') &&
                    !/_fw86($|\?)/.test(url);
            });
        }
        return false;
    }

    // 在脚本顶部定义
    const imgOriginalHTMLMap = new WeakMap();

    // 检查图片是否在排除的选择器内
    function isInExcludedSelector(img) {
        // 排除的选择器列表
        const excludedSelectors = [
            '#__next > main > div.wrapper > div > div.vB0yuKZj',
            '#__next > main > div.mmxqWRkC > div',
            '#pin_detail > div.xSGn1h2H'
        ];

        // 检查图片是否在任何一个排除选择器内
        for (const selector of excludedSelectors) {
            try {
                const excludedElement = document.querySelector(selector);
                if (excludedElement && excludedElement.contains(img)) {
                    return true;
                }
            } catch (error) {
                // 如果选择器无效,跳过这个选择器
                console.log(`无效的选择器: ${selector}`);
            }
        }

        // 检查所有 rc-tabs-*-panel-board 选择器
        try {
            const allTabsPanels = document.querySelectorAll('[id^="rc-tabs-"][id$="-panel-board"]');
            for (const panel of allTabsPanels) {
                if (panel.contains(img)) {
                    return true;
                }
            }
        } catch (error) {
            console.log('检查 rc-tabs 面板时出错');
        }

        return false;
    }

    // 为图片添加按钮
    function addButtonToImage(img) {
        // 避免重复添加
        if (img.parentElement && img.parentElement.classList.contains('huaban-img-btn-wrap')) return;
        if (!isHuabanImg(img)) return;
        if (isInExcludedSelector(img)) return;

        // 包裹图片
        const wrapper = document.createElement('span');
        wrapper.className = 'huaban-img-btn-wrap';
        img.parentNode.insertBefore(wrapper, img);
        wrapper.appendChild(img);

        // 创建按钮
        const button = document.createElement('div');
        button.className = 'huaban-img-btn-icon';
        button.innerHTML = `<img src="https://files.getquicker.net/_icons/42122268BF4547AB8E6955A2C3D552BC70E197DA.png" alt="icon">`;

        // 保证页面有唯一的虚拟选择器
        let marker = document.querySelector('.tampermonkey-huaban-marker');
        if (!marker) {
            marker = document.createElement('div');
            marker.className = 'tampermonkey-huaban-marker';
            marker.style.display = 'none';
            document.body.appendChild(marker);
        }

        // 按钮点击事件
        button.addEventListener('click', (e) => {
            e.preventDefault();
            e.stopPropagation();

            // 添加调试信息
            console.log('按钮被点击了!');

            button.classList.add('clicked');
            setTimeout(() => button.classList.remove('clicked'), 800);

            // 跳转到Quicker动作
            window.location.href = 'quicker:runaction:2db1eb7e-6a80-4e5f-2859-08ddc0fbdd92?woda';

            // 注入“原始图片HTML”到虚拟选择器
            marker.innerHTML = imgOriginalHTMLMap.get(img) || '';
        });

        wrapper.appendChild(button);
    }

    // 处理所有图片
    function processImages() {
        document.querySelectorAll('img').forEach(img => {
            // 只处理未被包裹的图片
            if (!img.parentElement || !img.parentElement.classList.contains('huaban-img-btn-wrap')) {
                if (isHuabanImg(img) && !isInExcludedSelector(img)) {
                    // 只保存一次原始HTML
                    if (!imgOriginalHTMLMap.has(img)) {
                        imgOriginalHTMLMap.set(img, img.outerHTML);
                    }
                    addButtonToImage(img);
                }
            }
        });
    }

    // 处理付费素材蒙版
    function processPremiumOverlays() {
        // 再次检查当前URL
        if (window.location.href.includes('/pins/')) {
            return;
        }

        const elements = document.evaluate(
            '//div[@data-content-type="素材采集"]',
            document,
            null,
            XPathResult.ORDERED_NODE_SNAPSHOT_TYPE,
            null
        );

        for (let i = 0; i < elements.snapshotLength; i++) {
            const element = elements.snapshotItem(i);

            // 检查是否已经添加过蒙版
            if (element.querySelector('.premium-overlay')) continue;

            // 设置容器样式
            element.style.position = 'relative';
            element.style.overflow = 'hidden';

            // 创建蒙版层
            const overlay = document.createElement('div');
            overlay.className = 'premium-overlay';
            overlay.innerHTML = '<span>💰 付费素材</span>';
            overlay.style.cssText = `
                position: absolute;
                top: 0;
                left: 0;
                width: 100%;
                height: 100%;
                background: rgba(0, 0, 0, ${actualOpacity});
                display: flex;
                align-items: center;
                justify-content: center;
                z-index: 1000;
                transition: opacity 0.3s ease;
                pointer-events: none;
            `;

            // 设置文字样式
            const span = overlay.querySelector('span');
            span.style.cssText = `
                color: white;
                font-size: 16px;
                font-weight: bold;
                text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.8);
                background: rgba(255, 255, 255, 0.1);
                padding: 8px 16px;
                border-radius: 20px;
                border: 2px solid rgba(255, 255, 255, 0.3);
                pointer-events: none;
            `;

            // 鼠标悬停时减淡蒙版
            element.addEventListener('mouseenter', () => {
                overlay.style.opacity = '0.3';
            });

            element.addEventListener('mouseleave', () => {
                overlay.style.opacity = '1';
            });

            element.appendChild(overlay);
        }
    }

    // 监听DOM变化
    const observer = new MutationObserver(() => {
        processImages();
        processPremiumOverlays();
    });
    observer.observe(document.body, { childList: true, subtree: true });

    // 初始处理
    processImages();
    processPremiumOverlays();

    // 延迟处理,确保页面完全加载
    setTimeout(() => {
        processImages();
        processPremiumOverlays();
    }, 1000);
})();