抖音自律助手终极版(10分钟后暂停整个网页)

带可拖动悬浮计时器和智能黑屏的使用控制

// ==UserScript==
// @name         抖音自律助手终极版(10分钟后暂停整个网页)
// @namespace    http://tampermonkey.net/
// @version      1.5
// @description  带可拖动悬浮计时器和智能黑屏的使用控制
// @author       potato
// @match        *://*.douyin.com/*
// @grant        GM_addStyle
// ==/UserScript==

(function() {
    'use strict';

    // 添加全局样式
    GM_addStyle(`
        /* 黑屏遮罩 */
        #timeout-overlay {
            position: fixed;
            top: 0;
            left: 0;
            width: 100vw;
            height: 100vh;
            background: rgba(0,0,0,0.9);
            z-index: 999999;
            display: none;
            justify-content: center;
            align-items: center;
            color: #fff;
            font-size: 2em;
            text-align: center;
            cursor: not-allowed;
            flex-direction: column;
        }

        /* 倒计时小球 */
        #countdown-ball {
            position: fixed;
            right: 20px;
            bottom: 20px;
            width: 60px;
            height: 60px;
            background: linear-gradient(135deg, #ff6b6b, #ff4757);
            border-radius: 50%;
            box-shadow: 0 4px 15px rgba(255, 107, 107, 0.3);
            cursor: move;
            display: flex;
            align-items: center;
            justify-content: center;
            color: white;
            font-weight: bold;
            font-size: 14px;
            text-align: center;
            line-height: 1.2;
            z-index: 999998;
            user-select: none;
            transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
        }

        #countdown-ball:hover {
            transform: scale(1.1);
            box-shadow: 0 6px 20px rgba(255, 107, 107, 0.4);
        }

        #countdown-ball.dragging {
            transition: none;
            opacity: 0.9;
        }

        /* 黑屏提示文字 */
        .timeout-text {
            animation: pulse 2s infinite;
        }

        @keyframes pulse {
            0% { transform: scale(1); }
            50% { transform: scale(1.05); }
            100% { transform: scale(1); }
        }
    `);

    // 创建黑屏遮罩
    const createOverlay = () => {
        const overlay = document.createElement('div');
        overlay.id = 'timeout-overlay';
        overlay.innerHTML = `
            <div class="timeout-text">
                <div>🕒 已连续使用10分钟</div>
                <div style="font-size:0.6em; margin-top:20px;">请休息片刻再继续</div>
                <div style="font-size:0.4em; margin-top:10px;">(刷新页面可恢复)</div>
            </div>
        `;
        document.body.appendChild(overlay);
        return overlay;
    };

    // 创建倒计时小球
    const createCountdownBall = () => {
        const ball = document.createElement('div');
        ball.id = 'countdown-ball';
        document.body.appendChild(ball);
        return ball;
    };

    class TimerController {
        constructor() {
            this.totalTime = 10 * 60 * 1000; // 10分钟
            this.startTime = Date.now();
            this.remaining = this.totalTime;
            this.timer = null;
            this.ball = createCountdownBall();
            this.overlay = createOverlay();
            this.isDragging = false;
            this.init();
        }

        init() {
            this.setupDrag();
            this.startCountdown();
            this.setupVisibilityListener();
        }

        // 倒计时逻辑
        startCountdown() {
            this.clearTimer();
            this.startTime = Date.now();

            this.timer = setInterval(() => {
                this.remaining = this.totalTime - (Date.now() - this.startTime);

                if (this.remaining <= 0) {
                    this.triggerTimeout();
                    return;
                }

                this.updateDisplay();
            }, 200);
        }

        // 更新显示
        updateDisplay() {
            const minutes = Math.floor(this.remaining / 60000);
            const seconds = Math.floor((this.remaining % 60000) / 1000);
            this.ball.textContent = `${minutes}:${seconds.toString().padStart(2, '0')}`;

            // 动态颜色变化
            const progress = this.remaining / this.totalTime;
            this.ball.style.background = `linear-gradient(135deg,
                hsl(${progress * 120}, 70%, 50%),
                hsl(${progress * 120}, 80%, 45%)
            )`;
        }

        // 触发超时
        triggerTimeout() {
            this.clearTimer();
            document.querySelectorAll('video').forEach(v => v.pause());
            this.overlay.style.display = 'flex';
            this.ball.style.display = 'none';
            document.body.style.overflow = 'hidden';
            this.addOverlayListeners();
        }

        // 页面可见性监听
        setupVisibilityListener() {
            let hiddenTime = 0;

            document.addEventListener('visibilitychange', () => {
                if (document.hidden) {
                    hiddenTime = Date.now();
                    this.clearTimer();
                } else {
                    const elapsed = Date.now() - hiddenTime;
                    this.startTime += elapsed;
                    this.startCountdown();
                }
            });
        }

        // 拖动功能
        setupDrag() {
            let isDragging = false;
            let startX = 0, startY = 0;
            let ballX = 0, ballY = 0;

            const onMouseMove = (e) => {
                if (!isDragging) return;

                const dx = e.clientX - startX;
                const dy = e.clientY - startY;

                const newX = ballX + dx;
                const newY = ballY + dy;

                const maxX = window.innerWidth - this.ball.offsetWidth;
                const maxY = window.innerHeight - this.ball.offsetHeight;

                this.ball.style.left = `${Math.min(Math.max(0, newX), maxX)}px`;
                this.ball.style.top = `${Math.min(Math.max(0, newY), maxY)}px`;
            };

            this.ball.addEventListener('mousedown', (e) => {
                isDragging = true;
                this.ball.classList.add('dragging');
                startX = e.clientX;
                startY = e.clientY;

                const rect = this.ball.getBoundingClientRect();
                ballX = rect.left;
                ballY = rect.top;

                document.addEventListener('mousemove', onMouseMove);
                document.addEventListener('mouseup', () => {
                    isDragging = false;
                    this.ball.classList.remove('dragging');
                    document.removeEventListener('mousemove', onMouseMove);
                }, { once: true });
            });
        }

        // 黑屏事件监听
        addOverlayListeners() {
            const blockInteraction = (e) => {
                e.preventDefault();
                e.stopPropagation();
                e.stopImmediatePropagation();
            };

            document.addEventListener('click', blockInteraction, true);
            document.addEventListener('touchstart', blockInteraction, true);
            document.addEventListener('keydown', blockInteraction, true);
        }

        clearTimer() {
            clearInterval(this.timer);
            this.timer = null;
        }
    }

    // 初始化
    new TimerController();

})();