Greasy Fork

Greasy Fork is available in English.

随机鼠标移动器 (调试版-修复view属性)

在5-10秒随机时间内(用于测试),挪动鼠标至随机位置,右侧贴边有启动/关闭开关、记录移动次数和下次移动倒计时。

当前为 2025-06-06 提交的版本,查看 最新版本

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Greasemonkey 油猴子Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Userscripts ,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展后才能安装此脚本。

(我已经安装了用户脚本管理器,让我安装!)

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

(我已经安装了用户样式管理器,让我安装!)

// ==UserScript==
// @name         随机鼠标移动器 (调试版-修复view属性)
// @namespace    http://tampermonkey.net/
// @version      1.2.2
// @description  在5-10秒随机时间内(用于测试),挪动鼠标至随机位置,右侧贴边有启动/关闭开关、记录移动次数和下次移动倒计时。
// @author       Your Name (替换成你的名字)
// @match        *://*/*
// @grant        GM_setValue
// @grant        GM_getValue
// @grant        GM_addStyle
// @grant        unsafeWindow
// @license      MPL-2.0 License
// ==/UserScript==

(function() {
    'use strict';

    let moveTimeoutId; // 用于 setTimeout 的 ID
    let countdownIntervalId; // 用于 setInterval 更新倒计时的 ID
    let isRunning = false;
    let moveCount = GM_getValue('mouseMoveCount', 0) || 0;
    let nextMoveTime = 0; // 下次移动的精确时间戳

    // --- 样式 ---
    GM_addStyle(`
        #mouseMoverControlPanel {
            position: fixed;
            top: 50%;
            right: 0;
            transform: translateY(-50%);
            background-color: rgba(0, 0, 0, 0.75);
            color: white;
            padding: 15px;
            border-top-left-radius: 8px;
            border-bottom-left-radius: 8px;
            z-index: 99999999; /* 确保非常高 */
            font-family: Arial, sans-serif;
            font-size: 14px;
            box-shadow: -2px 0px 5px rgba(0,0,0,0.5);
            display: flex;
            flex-direction: column;
            gap: 10px;
        }

        #mouseMoverControlPanel button {
            background-color: #4CAF50;
            color: white;
            border: none;
            padding: 10px;
            text-align: center;
            text-decoration: none;
            display: inline-block;
            font-size: 14px;
            cursor: pointer;
            border-radius: 4px;
            transition: background-color 0.3s ease;
        }

        #mouseMoverControlPanel button:hover {
            background-color: #45a049;
        }

        #mouseMoverControlPanel button.stop {
            background-color: #f44336;
        }

        #mouseMoverControlPanel button.stop:hover {
            background-color: #da190b;
        }

        #mouseMoverControlPanel div[id$="Text"] {
            font-weight: normal;
            text-align: center;
            padding: 3px 0;
        }
         #mouseMoverControlPanel #statusText {
            font-weight: bold;
        }
        #mouseMoverControlPanel #countdownText {
            font-style: italic;
            color: #c8ff00;
        }
    `);

    // --- 创建控制面板 ---
    const controlPanel = document.createElement('div');
    controlPanel.id = 'mouseMoverControlPanel';
    document.body.appendChild(controlPanel);

    const statusText = document.createElement('div');
    statusText.id = 'statusText';
    statusText.textContent = '状态: 已停止';
    controlPanel.appendChild(statusText);

    const toggleButton = document.createElement('button');
    toggleButton.id = 'toggleButton';
    toggleButton.textContent = '启动';
    controlPanel.appendChild(toggleButton);

    const countText = document.createElement('div');
    countText.id = 'countText';
    countText.textContent = `移动次数: ${moveCount}`;
    controlPanel.appendChild(countText);

    const countdownTextElement = document.createElement('div');
    countdownTextElement.id = 'countdownText';
    countdownTextElement.textContent = '下次移动: --:--';
    controlPanel.appendChild(countdownTextElement);

    const resetButton = document.createElement('button');
    resetButton.textContent = '重置计数';
    resetButton.style.backgroundColor = '#ff9800';
    resetButton.addEventListener('mouseover', () => resetButton.style.backgroundColor = '#e68a00');
    resetButton.addEventListener('mouseout', () => resetButton.style.backgroundColor = '#ff9800');
    controlPanel.appendChild(resetButton);


    // --- 功能函数 ---

    function moveMouse(x, y) {
        console.log(`[调试] moveMouse: 准备移动到 (${x}, ${y})`);
        const event = new MouseEvent('mousemove', {
            bubbles: true,
            cancelable: true,
            clientX: x,
            clientY: y,
            view: unsafeWindow // 修改: 使用 unsafeWindow 代替 window
        });
        try {
            let dispatchedOn = null;
            if (document.activeElement && document.activeElement !== document.body) {
                 // 尝试派发到当前活动元素,如果它不是 body
                document.activeElement.dispatchEvent(event);
                dispatchedOn = "document.activeElement";
            } else if (document.documentElement) {
                document.documentElement.dispatchEvent(event);
                dispatchedOn = "document.documentElement";
            } else if (document.body) { // 如果 documentElement 不存在,则尝试 body
                document.body.dispatchEvent(event);
                dispatchedOn = "document.body";
            }

            if (dispatchedOn) {
                console.log(`[调试] moveMouse: 鼠标移动事件已派发到 ${dispatchedOn} 到: (${x}, ${y})`);
                // 为了更明显地看到效果,可以临时添加一个视觉反馈,比如闪烁背景色
                // document.body.style.transition = 'background-color 0.1s ease-out';
                // const originalBg = document.body.style.backgroundColor;
                // document.body.style.backgroundColor = 'rgba(255,0,0,0.2)';
                // setTimeout(() => { document.body.style.backgroundColor = originalBg; }, 100);
            } else {
                 console.warn("[调试] moveMouse: 未找到合适的元素来派发鼠标事件。");
            }

        } catch (e) {
            console.error("[调试] moveMouse: 派发鼠标移动事件时出错:", e);
        }
    }

    function getRandomPosition() {
        const x = Math.floor(Math.random() * window.innerWidth);
        const y = Math.floor(Math.random() * window.innerHeight);
        return { x, y };
    }

    // 获取随机时间 (修改为5-10秒用于测试)
    function getRandomTime() {
        // 原来的: 5-10分钟 (300000 - 600000毫秒)
        // return Math.floor(Math.random() * (600000 - 300000 + 1)) + 300000;

        // 测试用: 5-10秒 (5000 - 10000毫秒)
        const randomShortTime = Math.floor(Math.random() * (10000 - 5000 + 1)) + 5000;
        console.log(`[调试] getRandomTime: 生成的随机延时为 ${randomShortTime} ms`);
        return randomShortTime;
    }

    function updateCountdownDisplay() {
        if (!isRunning || nextMoveTime <= 0) {
            countdownTextElement.textContent = '下次移动: --:--';
            return;
        }

        const now = Date.now();
        const timeLeftMs = nextMoveTime - now;

        if (timeLeftMs <= 0) {
            countdownTextElement.textContent = '下次移动: 即将...';
            return;
        }

        const totalSeconds = Math.max(0, Math.floor(timeLeftMs / 1000));
        const minutes = Math.floor(totalSeconds / 60);
        const seconds = totalSeconds % 60;

        countdownTextElement.textContent = `下次移动: ${String(minutes).padStart(2, '0')}:${String(seconds).padStart(2, '0')}`;
    }

    function startMoving() {
        if (isRunning) {
            console.log('[调试] startMoving: 已在运行,无需再次启动。');
            return;
        }
        isRunning = true;
        statusText.textContent = '状态: 运行中';
        toggleButton.textContent = '停止';
        toggleButton.classList.add('stop');
        console.log('[调试] startMoving: 随机鼠标移动已启动');

        scheduleMove(); // 直接开始调度
    }

    function scheduleMove() {
        if (!isRunning) {
            console.log('[调试] scheduleMove: isRunning 为 false, 停止调度。');
            return;
        }

        const randomTimeDelay = getRandomTime();
        nextMoveTime = Date.now() + randomTimeDelay;
        console.log(`[调试] scheduleMove: 下一次移动操作将在 ${randomTimeDelay} ms (即 ${(randomTimeDelay / 1000).toFixed(1)} 秒) 后执行。`);

        if (countdownIntervalId) clearInterval(countdownIntervalId);
        countdownIntervalId = setInterval(updateCountdownDisplay, 1000);
        updateCountdownDisplay(); // 立即更新一次

        moveTimeoutId = setTimeout(() => {
            console.log('[调试] setTimeout 回调: 准备执行移动。');
            if (!isRunning) {
                console.log('[调试] setTimeout 回调: isRunning 为 false, 取消本次移动。');
                clearInterval(countdownIntervalId); // 确保倒计时也停止
                nextMoveTime = 0;
                updateCountdownDisplay();
                return;
            }

            const position = getRandomPosition();
            console.log(`[调试] setTimeout 回调: 获取到随机位置 (${position.x}, ${position.y})。`);
            moveMouse(position.x, position.y);
            moveCount++;
            GM_setValue('mouseMoveCount', moveCount);
            countText.textContent = `移动次数: ${moveCount}`;
            console.log(`[调试] setTimeout 回调: 移动次数更新为 ${moveCount}。`);

            if (isRunning) {
                console.log('[调试] setTimeout 回调: 准备调度下一次移动。');
                scheduleMove();
            } else {
                console.log('[调试] setTimeout 回调: isRunning 变为 false, 停止后续调度。');
                clearInterval(countdownIntervalId);
                nextMoveTime = 0;
                updateCountdownDisplay();
            }
        }, randomTimeDelay);
        console.log(`[调试] scheduleMove: setTimeout 已设置,ID: ${moveTimeoutId}`);
    }

    function stopMoving() {
        if (!isRunning) {
            console.log('[调试] stopMoving: 已停止,无需再次操作。');
            return;
        }
        isRunning = false;
        console.log(`[调试] stopMoving: 准备清除 setTimeout (ID: ${moveTimeoutId}) 和 setInterval (ID: ${countdownIntervalId})。`);
        clearTimeout(moveTimeoutId);
        clearInterval(countdownIntervalId);
        nextMoveTime = 0;
        statusText.textContent = '状态: 已停止';
        toggleButton.textContent = '启动';
        toggleButton.classList.remove('stop');
        updateCountdownDisplay();
        console.log('[调试] stopMoving: 随机鼠标移动已停止。');
    }

    function resetCounter() {
        if (confirm('确定要重置移动次数吗?')) {
            moveCount = 0;
            GM_setValue('mouseMoveCount', moveCount);
            countText.textContent = `移动次数: ${moveCount}`;
            console.log('[调试] resetCounter: 移动次数已重置。');
        }
    }

    // --- 事件监听 ---
    toggleButton.addEventListener('click', () => {
        if (isRunning) {
            stopMoving();
        } else {
            startMoving();
        }
    });

    resetButton.addEventListener('click', resetCounter);

    // 脚本加载时,默认是停止状态
    console.log('[调试] 脚本已加载并初始化。');

})();