Greasy Fork 支持简体中文。

批量enhance放大

Create a button to select files and simulate dragging them onto a webpage element

// ==UserScript==
// @name         批量enhance放大
// @namespace    http://tampermonkey.net/
// @version      0.5
// @description  Create a button to select files and simulate dragging them onto a webpage element
// @author       axing
// @match        https://novelai.net/image
// @grant        GM_setValue
// @grant        GM_getValue
// @grant        GM_registerMenuCommand
// ==/UserScript==

(function() {
    'use strict';

    // 定义默认值
    const DEFAULT_DELAY = 1000;//默认等待时间
    const DEFAULT_STRENGTH = 0.3;//默认重绘幅度
    const DEFAULT_SCALE_FACTOR = 1.5; // 默认尺寸大小倍率

    // 从油猴存储中获取用户设置的值,如果没有设置,则使用默认值
    let delay = GM_getValue('dragDelay', DEFAULT_DELAY);
    let strength = GM_getValue('dragStrength', DEFAULT_STRENGTH);
    let scaleFactor = GM_getValue('scaleFactor', DEFAULT_SCALE_FACTOR);

    // 创建按钮
    let button = document.createElement("button");
    button.innerHTML = "选择文件";
    button.style.position = "fixed";
    button.style.bottom = "10px";
    button.style.right = "10px";
    button.style.zIndex = "9999";
    document.body.appendChild(button);

    // 创建拖放区域
    let dropArea = document.createElement("div");
    dropArea.innerHTML = "拖动文件到此区域";
    dropArea.style.position = "fixed";
    dropArea.style.bottom = "50px";
    dropArea.style.right = "10px";
    dropArea.style.width = "100px";
    dropArea.style.height = "100px";
    dropArea.style.border = "2px dashed #ccc";
    dropArea.style.display = "flex";
    dropArea.style.alignItems = "center";
    dropArea.style.justifyContent = "center";
    dropArea.style.zIndex = "99999"; // 确保设置为最高层级
    dropArea.style.backgroundColor = "rgba(255, 255, 255, 0.8)"; // 可选:添加背景色以增强可见性
    document.body.appendChild(dropArea);

    // 阻止默认行为
    ['dragenter', 'dragover', 'dragleave', 'drop'].forEach(eventName => {
        dropArea.addEventListener(eventName, preventDefaults, false);
    });

    function preventDefaults (e) {
        e.preventDefault();
        e.stopPropagation();
    }

    // 添加拖放事件
    dropArea.addEventListener("drop", handleDrop, false);

    function handleDrop(e) {
        let dt = e.dataTransfer;
        let files = dt.files;

        handleFiles(files);
    }


    async function handleFiles(files) {
        let fileArray = Array.from(files);
        let fileNames = fileArray.map(file => file.name);
        console.log(fileNames);

        // 对每个文件执行两次拖放操作
        for (let file of files) {
            for (let i = 0; i < 2; i++) {
                await 文件拖入网页([file], i);
            }
            await 修改参数();
            await 生成大图();
            }
    }





    // 添加按钮点击事件
    button.addEventListener("click", async function() {
        // 创建文件输入框
        let fileInput = document.createElement("input");
        fileInput.type = "file";
        fileInput.multiple = true;
        fileInput.style.display = "none";

        // 添加文件选择事件
        fileInput.addEventListener("change", async function() {
            let files = fileInput.files;
            if (files.length === 0) return;
            let fileNames = Array.from(files).map(file => file.name);
            console.log(fileNames);

            // 对每个文件执行两次拖放操作
            for (let file of files) {
                for (let i = 0; i < 2; i++) {
                    await 文件拖入网页([file], i);
                }
                await 修改参数();
                await 生成大图();
                console.log("完成_____________________");
            }
        });

        // 触发文件选择对话框
        fileInput.click();
    });

    // 定义 async 函数以模拟拖放文件到网页
    async function 文件拖入网页(files, index) {
        let targetElement = document.querySelector("#__next > div.sc-a2d0901c-0.gkbaSQ > div.sc-7a0ddb82-0.bcbLQo");
        if (!targetElement) {
            console.error("目标元素未找到!");
            return;
        }

        // 模拟拖放事件
        let dataTransfer = new DataTransfer();
        for (let file of files) {
            dataTransfer.items.add(file);
        }

        let dragEnterEvent = new DragEvent('dragenter', {
            bubbles: true,
            cancelable: true,
            dataTransfer: dataTransfer
        });

        let dragOverEvent = new DragEvent('dragover', {
            bubbles: true,
            cancelable: true,
            dataTransfer: dataTransfer
        });

        let dropEvent = new DragEvent('drop', {
            bubbles: true,
            cancelable: true,
            dataTransfer: dataTransfer
        });

        // 触发拖放事件
        targetElement.dispatchEvent(dragEnterEvent);
        targetElement.dispatchEvent(dragOverEvent);
        targetElement.dispatchEvent(dropEvent);

        console.log("文件已拖放到目标元素");

        // 延迟指定时间后执行下一步操作
        await new Promise(resolve => setTimeout(resolve, delay));

        let targetElement2;
        if (index == 0) {
            targetElement2 = document.querySelector("body > div:nth-child(21) > div > div.sc-b8ec890b-17.dBXrlS.modal.modal-large > div > div > div:nth-child(4) > div:nth-child(2) > button");
        } else {
            targetElement2 = document.querySelector("body > div:nth-child(21) > div > div.sc-b8ec890b-17.dBXrlS.modal.modal-large > div > div > div:nth-child(2) > div:nth-child(3) > button:nth-child(1)");
        }

        if (!targetElement2) {
            console.error("目标按钮未找到!");
            return;
        }

        console.log("点击按钮:");
        console.log(targetElement2);
        targetElement2.click();
    }
    async function 修改参数(){
        
        let targetElementXPath = '/html/body/div[1]/div[2]/div[4]/div[1]/div[3]/div[2]/div/div[5]/div/div[2]/div[1]/input';
        let Strength选择器 = document.evaluate(targetElementXPath, document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue;

        let 尺寸X = '/html/body/div[1]/div[2]/div[4]/div[1]/div[3]/div[3]/div/div[2]/div[2]/input[1]';
        let 尺寸X选择器 = document.evaluate(尺寸X, document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue;
        let 尺寸Y = '/html/body/div[1]/div[2]/div[4]/div[1]/div[3]/div[3]/div/div[2]/div[2]/input[2]';
        let 尺寸Y选择器 = document.evaluate(尺寸Y, document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue;


        console.log("Strength选择器",Strength选择器);
        await 修改值(Strength选择器,strength);
        await 修改值(尺寸X选择器,scaleFactor * 尺寸X选择器.value);
        await 修改值(尺寸Y选择器,scaleFactor * 尺寸Y选择器.value);
    };




    // 模拟点击元素
    async function 生成大图() {
        await new Promise(resolve => setTimeout(resolve, delay));
        // 记录已经点击过的元素
        const clickedElements = new Set();

        // 获取可点击的元素
        //const element = document.querySelector("#__next > div.sc-a2d0901c-0.gkbaSQ > div:nth-child(4) > div.sc-d09fe33a-0.isLCYD > div:nth-child(5) > button:not([disabled])");
        const xpath = "/html/body/div[1]/div[2]/div[4]/div[1]/div[5]/button[not(@disabled)]";
        const element = document.evaluate(xpath, document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue;

        console.log(`Found clickable element`);
        console.log(`element`, element);

        // 如果组内存在点击过的元素,那么不执行
        if (element && !clickedElements.has(element)) {
            try {
                element.click(); // 点击
                console.log('已经点击'); // 打印日志
                clickedElements.add(element); // 添加元素到组内
                await waitForElementEnabled(element); // 等待延迟
            } catch (error) {
                console.error('Error clicking element:', error);
            }
        }
        clickedElements.clear(); // 清空已点击的元素集合
    }

    // 等待元素重新变回可点击状态
    async function waitForElementEnabled(element) {
        return new Promise(resolve => {
            const observer = new MutationObserver(mutations => {
                for (const mutation of mutations) {
                    if (mutation.type === 'attributes' && mutation.attributeName === 'class') {
                        if (!element.disabled) {
                            observer.disconnect();
                            resolve();
                        }
                    }
                }
            });
            observer.observe(element, { attributes: true });
        });
    }

    // 辅助函数:延迟执行
    async function sleep(ms) {
        return new Promise(resolve => setTimeout(resolve, ms));
    }















    async function 修改值(textField,新值){
        await new Promise(resolve => setTimeout(resolve, delay));
        let lastValue = textField.value;
        textField.value= 新值;
        let event = new Event('input', { bubbles: true })
        let tracker = textField._valueTracker
        if(tracker) {
            tracker.setValue(lastValue)
        }
        textField.dispatchEvent(event)
    };
    // 添加油猴选项页面链接
    GM_registerMenuCommand('设置拖动延迟', function() {
        let newDelay = prompt('请输入拖动延迟时间(毫秒):', delay);
        if (newDelay !== null && !isNaN(newDelay)) {
            delay = parseInt(newDelay, 10);
            GM_setValue('dragDelay', delay);
        }
    });

    GM_registerMenuCommand('设置重绘尺度', function() {
        let newStrength = prompt('重绘大小(0-1.0的小数):', strength);
        if (newStrength !== null && !isNaN(newStrength)) {
            strength = parseFloat(newStrength); // 使用 parseFloat 处理小数
            GM_setValue('dragStrength', strength);
        }
    });

    GM_registerMenuCommand('设置尺寸大小倍率', function() {
        let newScaleFactor = prompt('请输入尺寸大小倍率(如 1.0):', scaleFactor);
        if (newScaleFactor !== null && !isNaN(newScaleFactor)) {
            scaleFactor = parseFloat(newScaleFactor); // 使用 parseFloat 处理小数
            GM_setValue('scaleFactor', scaleFactor);
        }
    });
})();