增强版时区劫持(改进UI)

更可靠的页面时区修改方法,带有友好的选择界面

// ==UserScript==
// @name         增强版时区劫持(改进UI)
// @namespace    http://tampermonkey.net/
// @version      1.2
// @description  更可靠的页面时区修改方法,带有友好的选择界面
// @author       kendrick
// @match        *://*.sankuai.com/*
// @grant        GM_setValue
// @grant        GM_getValue
// @grant        GM_registerMenuCommand
// @grant        GM_addStyle
// @run-at       document-start
// @license MIT
// ==/UserScript==

(function() {
    'use strict';

    // 定义可用时区及其偏移量(分钟)
    const TIMEZONES = {
        'default': { name: '系统默认', offset: null },
        'china': { name: '中国 (UTC+8)', offset: -480 },
        'europe': { name: '欧洲 (UTC+1)', offset: -60 },
        'middleeast': { name: '中东 (UTC+3)', offset: -180 }
    };

    // 获取保存的时区设置,默认为系统时区
    const selectedTimezone = GM_getValue('selectedTimezone', 'default');

    // 添加CSS样式
    GM_addStyle(`
        .tz-modal-overlay {
            position: fixed;
            top: 0;
            left: 0;
            right: 0;
            bottom: 0;
            background-color: rgba(0, 0, 0, 0.5);
            display: flex;
            justify-content: center;
            align-items: center;
            z-index: 10000;
        }
        .tz-modal {
            background: white;
            border-radius: 8px;
            padding: 20px;
            width: 300px;
            box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
        }
        .tz-modal-title {
            font-size: 18px;
            font-weight: bold;
            margin-bottom: 15px;
            text-align: center;
            color: #333;
        }
        .tz-options {
            display: flex;
            flex-direction: column;
            gap: 10px;
        }
        .tz-option {
            padding: 12px;
            border: 1px solid #ddd;
            border-radius: 6px;
            cursor: pointer;
            transition: all 0.2s;
            background: #f8f8f8;
            text-align: center;
        }
        .tz-option:hover {
            background: #e8f0fe;
            border-color: #4285f4;
        }
        .tz-option.selected {
            background: #e8f0fe;
            border-color: #4285f4;
            position: relative;
        }
        .tz-option.selected::after {
            content: "✓";
            position: absolute;
            right: 10px;
            color: #4285f4;
        }
        .tz-indicator {
            position: fixed;
            bottom: 10px;
            right: 10px;
            background: rgba(0,0,0,0.7);
            color: white;
            padding: 5px 10px;
            border-radius: 3px;
            font-size: 12px;
            z-index: 9999;
            cursor: pointer;
            opacity: 0.7;
            transition: opacity 0.3s;
        }
        .tz-indicator:hover {
            opacity: 1;
        }
    `);

    // 如果选择了默认时区,则不进行劫持
    if (selectedTimezone === 'default') {
        setupMenuCommands();
        return;
    }

    // 获取目标时区偏移
    const targetOffset = TIMEZONES[selectedTimezone].offset;

    // 执行注入脚本
    injectScript();

    // 设置菜单命令
    setupMenuCommands();

    // 在页面完全加载后添加时区指示器
    window.addEventListener('load', function() {
        addTimezoneIndicator();
    });

    // 注入脚本到页面
    function injectScript() {
        const scriptText = `
            (function() {
                // 保存原始Date对象
                const OriginalDate = Date;

                // 目标时区偏移(分钟)
                const targetOffset = ${targetOffset};

                // 获取本地时区偏移
                const localOffset = new OriginalDate().getTimezoneOffset();

                // 计算时区差异(分钟)
                const offsetDiff = localOffset - targetOffset;

                // 创建自定义Date构造函数
                function CustomDate() {
                    // 处理不同构造函数调用情况
                    if (arguments.length === 0) {
                        // 无参数调用 - 返回当前时间,但调整为目标时区
                        const date = new OriginalDate();
                        date.setTime(date.getTime() + offsetDiff * 60 * 1000);
                        return date;
                    } else {
                        // 有参数调用 - 正常创建日期对象
                        return new (Function.prototype.bind.apply(
                            OriginalDate,
                            [null].concat(Array.prototype.slice.call(arguments))
                        ))();
                    }
                }

                // 复制静态方法
                CustomDate.UTC = OriginalDate.UTC;
                CustomDate.parse = OriginalDate.parse;

                // 修改now方法以反映目标时区
                CustomDate.now = function() {
                    return OriginalDate.now() + offsetDiff * 60 * 1000;
                };

                // 继承原型
                CustomDate.prototype = OriginalDate.prototype;

                // 修改getTimezoneOffset方法
                const originalGetTimezoneOffset = OriginalDate.prototype.getTimezoneOffset;
                OriginalDate.prototype.getTimezoneOffset = function() {
                    return targetOffset;
                };

                // 覆盖全局Date对象
                window.Date = CustomDate;

                // 输出调试信息
                console.log('[时区修改器] 已将时区修改为: ${TIMEZONES[selectedTimezone].name}');

                // 验证劫持是否成功
                const testDate = new Date();
                console.log('[时区修改器] 当前时间:', testDate.toLocaleString());
                console.log('[时区修改器] 时区偏移:', testDate.getTimezoneOffset(), '分钟');
            })();
        `;

        // 创建脚本元素
        const scriptElement = document.createElement('script');
        scriptElement.textContent = scriptText;

        // 确保脚本尽早执行
        if (document.documentElement) {
            document.documentElement.appendChild(scriptElement);
            document.documentElement.removeChild(scriptElement);
        } else {
            // 如果documentElement不可用,则等待它可用
            const observer = new MutationObserver(function(mutations, obs) {
                if (document.documentElement) {
                    document.documentElement.appendChild(scriptElement);
                    document.documentElement.removeChild(scriptElement);
                    obs.disconnect();
                }
            });

            observer.observe(document, {
                childList: true,
                subtree: true
            });
        }
    }

    // 创建时区选择器对话框
    function createTimezoneSelector() {
        // 创建已有的模态框覆盖层
        if (document.querySelector('.tz-modal-overlay')) {
            return;
        }

        const overlay = document.createElement('div');
        overlay.className = 'tz-modal-overlay';

        const modal = document.createElement('div');
        modal.className = 'tz-modal';

        const title = document.createElement('div');
        title.className = 'tz-modal-title';
        title.textContent = '选择时区';

        const options = document.createElement('div');
        options.className = 'tz-options';

        // 创建时区选项
        for (const [key, value] of Object.entries(TIMEZONES)) {
            const option = document.createElement('div');
            option.className = 'tz-option';
            if (key === selectedTimezone) {
                option.classList.add('selected');
            }
            option.textContent = value.name;
            option.dataset.timezone = key;

            option.addEventListener('click', function() {
                const timezone = this.dataset.timezone;
                GM_setValue('selectedTimezone', timezone);
                overlay.remove();
                alert(`已将时区设置为: ${TIMEZONES[timezone].name}\n请刷新页面以应用更改`);
                location.reload();
            });

            options.appendChild(option);
        }

        // 组装模态框
        modal.appendChild(title);
        modal.appendChild(options);
        overlay.appendChild(modal);

        // 点击覆盖层关闭模态框
        overlay.addEventListener('click', function(e) {
            if (e.target === overlay) {
                overlay.remove();
            }
        });

        document.body.appendChild(overlay);
    }

    // 设置油猴菜单命令
    function setupMenuCommands() {
        // 时区选择菜单
        GM_registerMenuCommand("选择时区", function() {
            if (document.body) {
                createTimezoneSelector();
            } else {
                // 如果body还不存在,等待DOM加载完成
                window.addEventListener('DOMContentLoaded', createTimezoneSelector);
            }
        });

        // 显示当前时区设置
        GM_registerMenuCommand(`当前时区: ${TIMEZONES[selectedTimezone].name}`, function(){});
    }

    // 添加时区指示器
    function addTimezoneIndicator() {
        if (selectedTimezone === 'default') return;

        const indicator = document.createElement('div');
        indicator.textContent = `🌐 ${TIMEZONES[selectedTimezone].name}`;
        indicator.className = 'tz-indicator';

        indicator.addEventListener('click', function() {
            createTimezoneSelector();
        });

        document.body.appendChild(indicator);
    }
})();

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址