Greasy Fork

Greasy Fork is available in English.

喝水提醒(间隔30分钟)

从早上9:00开始,可自定义间隔弹出喝水提醒

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

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

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

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

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

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

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

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

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

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

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

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

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

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

// ==UserScript==
// @name   喝水提醒(间隔30分钟)
// @namespace    http://tampermonkey.net/
// @version      v251120_1118
// @description  从早上9:00开始,可自定义间隔弹出喝水提醒
// @author       liuyoyo
// @match        *://*/*
// @grant        none
// @run-at       document-start
// @license MIT
// ==/UserScript==

(function() {
    'use strict';

    // ===== 可自定义的变量 =====
    const REMINDER_INTERVAL_MINUTES = 30; // 提醒间隔(分钟)
    const START_HOUR = 9;                 // 开始小时(24小时制)
    const START_MINUTE = 0;              // 开始分钟
    const START_SECOND = 0;               // 开始秒数
    // =========================

    let reminderDiv = null;
    let nextReminderTime = null; // 跟踪下一次提醒的预期时间

    // 检查是否应该开始提醒
    function shouldStartReminders() {
        const now = new Date();
        const currentTime = now.getHours() * 3600 + now.getMinutes() * 60 + now.getSeconds();
        const startTime = START_HOUR * 3600 + START_MINUTE * 60 + START_SECOND;

        return currentTime >= startTime;
    }

    // 格式化时间显示
    function formatTime(date) {
        const hours = date.getHours().toString().padStart(2, '0');
        const minutes = date.getMinutes().toString().padStart(2, '0');
        const seconds = date.getSeconds().toString().padStart(2, '0');
        return `${hours}:${minutes}:${seconds}`;
    }

    // 创建提醒弹窗
    function createReminderPopup(nextTime) {
        // 如果已经存在提醒弹窗,先移除
        if (reminderDiv) {
            reminderDiv.remove();
        }

        // 创建弹窗容器
        reminderDiv = document.createElement('div');
        reminderDiv.id = 'water-reminder-popup';

        // 设置样式
        reminderDiv.style.cssText = `
            position: fixed;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            width: 1600px;
            height: 700px;
            background-color: white;
            border: 3px solid #00BFFF;
            border-radius: 15px;
            box-shadow: 0 0 20px rgba(0, 0, 0, 0.3);
            z-index: 10000;
            display: flex;
            flex-direction: column;
            align-items: center;
            justify-content: center;
            font-family: "Ink Free", "Segoe Print", "Bradley Hand", "Comic Sans MS", cursive, sans-serif;
        `;

        // 创建关闭按钮
        const closeButton = document.createElement('button');
        closeButton.textContent = '✕';
        closeButton.style.cssText = `
            position: absolute;
            top: 15px;
            right: 15px;
            background: none;
            border: none;
            font-size: 24px;
            cursor: pointer;
            color: #00BFFF;
            width: 40px;
            height: 40px;
            border-radius: 50%;
            display: flex;
            align-items: center;
            justify-content: center;
        `;

        // 关闭按钮悬停效果
        closeButton.addEventListener('mouseover', function() {
            this.style.backgroundColor = '#f0f0f0';
        });

        closeButton.addEventListener('mouseout', function() {
            this.style.backgroundColor = 'transparent';
        });

        // 关闭功能
        closeButton.addEventListener('click', function() {
            reminderDiv.remove();
            reminderDiv = null;
        });

        // 创建提醒文字
        const reminderText = document.createElement('div');
        reminderText.textContent = "It's time to drink water !";
        reminderText.style.cssText = `
            color: #00BFFF;
            font-size: 8em;
            font-weight: bold;
            text-align: center;
            text-shadow: 2px 2px 4px rgba(0, 191, 255, 0.3);
            padding: 20px;
            margin-bottom: 20px;
        `;

        // 创建下次提醒时间文字
        const nextReminderText = document.createElement('div');
        nextReminderText.textContent = `下次提醒时间: ${formatTime(nextTime)}`;
        nextReminderText.style.cssText = `
            color: #666;
            font-size: 1em;
            text-align: center;
            position: absolute;
            bottom: 30px;
            width: 100%;
        `;

        // 添加到弹窗
        reminderDiv.appendChild(closeButton);
        reminderDiv.appendChild(reminderText);
        reminderDiv.appendChild(nextReminderText);

        // 添加到页面
        document.body.appendChild(reminderDiv);
    }

    // 显示提醒(仅在激活的标签页中显示,且时间差不超过2秒)
    function showReminder() {
        const now = new Date();
        const timeDiff = Math.abs(now.getTime() - nextReminderTime.getTime());

        // 检查页面是否可见且时间差不超过2秒
        if (!document.hidden && timeDiff <= 2000) {
            const actualNextTime = new Date(nextReminderTime.getTime() + REMINDER_INTERVAL_MINUTES * 60 * 1000);
            createReminderPopup(actualNextTime);
            console.log(`显示喝水提醒,下次提醒将在 ${formatTime(actualNextTime)}`);
        }

        // 计算并调度下一次提醒
        nextReminderTime = new Date(nextReminderTime.getTime() + REMINDER_INTERVAL_MINUTES * 60 * 1000);
        const delay = nextReminderTime.getTime() - new Date().getTime();
        setTimeout(showReminder, delay);
    }

    // 主函数
    function init() {
        if (!shouldStartReminders()) {
            // 如果还没到开始时间,设置定时器检查
            const now = new Date();
            const startTime = new Date(now);
            startTime.setHours(START_HOUR, START_MINUTE, START_SECOND, 0);

            if (now < startTime) {
                const timeUntilStart = startTime.getTime() - now.getTime();
                console.log(`喝水提醒脚本将在 ${formatTime(startTime)} 开始,间隔 ${REMINDER_INTERVAL_MINUTES} 分钟`);
                setTimeout(init, timeUntilStart);
            }
            return;
        }

        // 到了开始时间,计算第一次提醒的时间
        const now = new Date();
        const startTime = new Date(now);
        startTime.setHours(START_HOUR, START_MINUTE, START_SECOND, 0);

        // 根据当前时间计算下次提醒时间
        if (now > startTime) {
            const timeSinceStart = now.getTime() - startTime.getTime();
            const intervals = Math.ceil(timeSinceStart / (REMINDER_INTERVAL_MINUTES * 60 * 1000));
            nextReminderTime = new Date(startTime.getTime() + intervals * REMINDER_INTERVAL_MINUTES * 60 * 1000);
        } else {
            nextReminderTime = startTime;
        }

        // 调度第一次提醒
        const delay = nextReminderTime.getTime() - now.getTime();
        setTimeout(showReminder, delay);
    }

    // 页面加载后启动
    if (document.readyState === 'loading') {
        document.addEventListener('DOMContentLoaded', init);
    } else {
        init();
    }

    // 当页面可见性改变时(切换标签页),如果弹窗存在且页面变为非激活状态,则关闭弹窗
    document.addEventListener('visibilitychange', function() {
        if (document.hidden && reminderDiv) {
            reminderDiv.remove();
            reminderDiv = null;
        }
    });
})();