Greasy Fork

Greasy Fork is available in English.

[银河奶牛]游戏内链接快速查看

说明:游戏里面的链接还是直接在游戏里面查看比较方便,这个插件能帮到你。

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

// ==UserScript==
// @name            [银河奶牛]游戏内链接快速查看
// @name:en         [MWI]In-Game Link Quick Viewer
// @namespace       https://cnb.cool/shenhuanjie/skyner-cn/tamper-monkey-script/mwi-dialog-link-viewer
// @description     说明:游戏里面的链接还是直接在游戏里面查看比较方便,这个插件能帮到你。
// @description:en  It's more convenient to check the links within the game directly, and this plugin can assist you with that.
// @version         1.0.3
// @author          shenhuanjie
// @license         MIT
// @homepage        http://greasyfork.icu/scripts/535885
// @supportURL      http://greasyfork.icu/scripts/535885
// @match           https://www.milkywayidle.com/*
// @icon            https://www.milkywayidle.com/favicon.svg
// @grant           GM_addStyle
// @grant           unsafeWindow
// ==/UserScript==

(function() {
    'use strict';

    // 添加样式
    GM_addStyle(`
        #dialog-container {
            position: fixed;
            top: 0;
            left: 0;
            width: 100%;
            height: 100%;
            background-color: rgba(0,0,0,0.5);
            display: none;
            justify-content: center;
            align-items: center;
            z-index: 9999;
            transition: opacity 0.3s ease;
        }

        #dialog-container.active {
            display: flex;
        }

        #dialog-content {
            background-color: white;
            width: 90%;
            height: 90%;
            max-width: 1600px;
            max-height: 900px;
            border-radius: 8px;
            box-shadow: 0 8px 32px rgba(0,0,0,0.3);
            display: flex;
            flex-direction: column;
            transform: scale(0.95);
            transition: transform 0.3s ease;
        }

        #dialog-container.active #dialog-content {
            transform: scale(1);
        }

        #dialog-header {
            padding: 16px 24px;
            border-bottom: 1px solid #e0e0e0;
            display: flex;
            justify-content: space-between;
            align-items: center;
            background-color: #f8f9fa;
        }

        #dialog-title {
            font-size: 20px;
            font-weight: 600;
            color: #333;
            max-width: 80%;
            white-space: nowrap;
            overflow: hidden;
            text-overflow: ellipsis;
        }

        #dialog-close {
            cursor: pointer;
            font-size: 28px;
            line-height: 1;
            color: #666;
            transition: color 0.2s;
        }

        #dialog-close:hover {
            color: #333;
        }

        #dialog-body {
            flex-grow: 1;
            overflow: hidden;
            position: relative;
        }

        #dialog-iframe {
            width: 100%;
            height: 100%;
            border: none;
        }

        .dialog-loading {
            position: absolute;
            top: 0;
            left: 0;
            width: 100%;
            height: 100%;
            display: flex;
            justify-content: center;
            align-items: center;
            background-color: white;
            z-index: 1;
            opacity: 1;
            transition: opacity 0.3s;
        }

        .dialog-loading.hidden {
            opacity: 0;
            pointer-events: none;
        }

        .dialog-spinner {
            width: 40px;
            height: 40px;
            border: 4px solid #f3f3f3;
            border-top: 4px solid #3498db;
            border-radius: 50%;
            animation: spin 1s linear infinite;
        }

        @keyframes spin {
            0% { transform: rotate(0deg); }
            100% { transform: rotate(360deg); }
        }

        .dialog-error {
            text-align: center;
            padding: 20px;
        }

        .dialog-error p {
            margin: 10px 0;
        }

        .dialog-error a {
            color: #2196F3;
            text-decoration: underline;
        }
    `);

    // 创建容器元素
    const container = document.createElement('div');
    container.id = 'dialog-container';
    container.innerHTML = `
        <div id="dialog-content">
            <div id="dialog-header">
                <div id="dialog-title"></div>
                <div id="dialog-close">&times;</div>
            </div>
            <div id="dialog-body">
                <div class="dialog-loading">
                    <div class="dialog-spinner"></div>
                </div>
                <iframe id="dialog-iframe" sandbox="allow-same-origin allow-scripts allow-popups allow-forms"></iframe>
            </div>
        </div>
    `;
    document.body.appendChild(container);

    // 获取元素引用
    const dialogContainer = document.getElementById('dialog-container');
    const dialogTitle = document.getElementById('dialog-title');
    const dialogIframe = document.getElementById('dialog-iframe');
    const dialogClose = document.getElementById('dialog-close');
    const dialogLoading = container.querySelector('.dialog-loading');

    let currentUrl = '';

    // 关闭对话框
    dialogClose.addEventListener('click', () => {
        closeDialog();
    });

    // 点击外部关闭
    dialogContainer.addEventListener('click', (e) => {
        if (e.target === dialogContainer) {
            closeDialog();
        }
    });

    // 关闭对话框函数
    function closeDialog() {
        dialogContainer.classList.remove('active');
        setTimeout(() => {
            dialogIframe.src = 'about:blank';
        }, 300);
    }

    // 键盘事件监听
    document.addEventListener('keydown', (e) => {
        if (e.key === 'Escape' && dialogContainer.classList.contains('active')) {
            closeDialog();
        }
    });

    // 拦截链接点击
    document.addEventListener('click', (e) => {
        const link = e.target.closest('a');
        if (link && !link.hasAttribute('download') && !link.hasAttribute('target')) {
            // 阻止事件冒泡和默认行为
            e.stopPropagation();
            e.preventDefault();

            // 获取完整URL
            const url = new URL(link.href, window.location.href).href;
            openLinkInDialog(url, link.textContent);
        }
    }, true); // 使用捕获阶段

    // 在对话框中打开链接
    function openLinkInDialog(url, title) {
        // 防止重复打开同一个链接
        if (url === currentUrl) {
            return;
        }
        // 防止打开内部链接
        if (url.startsWith(window.location.origin)) {
            // 内部链接
            window.location.href = url;
            return;
        }
        currentUrl = url;
        dialogTitle.textContent = title || url;
        dialogLoading.classList.remove('hidden');
        dialogLoading.innerHTML = '<div class="dialog-spinner"></div>';
        dialogContainer.classList.add('active');

        // 设置iframe源
        dialogIframe.src = url;

        // 监听iframe加载完成
        dialogIframe.onload = () => {
            try {
                // 尝试获取iframe标题更新对话框标题
                const iframeDoc = dialogIframe.contentDocument;
                if (iframeDoc && iframeDoc.title) {
                    dialogTitle.textContent = iframeDoc.title;
                }
            } catch (e) {
                // 跨域访问会抛出异常
            }

            setTimeout(() => {
                dialogLoading.classList.add('hidden');
            }, 300);
        };

        // 错误处理
        dialogIframe.onerror = () => {
            dialogLoading.innerHTML = `
                <div class="dialog-error">
                    <p style="color:red;">无法在iframe中加载此页面</p>
                    <p>可能是因为网站安全策略限制</p>
                    <a href="${url}" target="_blank">点击此处直接访问</a>
                </div>
            `;
        };
    }

    // 添加MutationObserver监听DOM变化
    let debounceTimer;
    const observer = new MutationObserver(() => {
        clearTimeout(debounceTimer);
        debounceTimer = setTimeout(() => {
            // 重新绑定新添加的链接
            bindDynamicLinks();
        }, 300);
    });

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

    // 绑定动态加载的链接
    function bindDynamicLinks() {
      // 劫持页面上所有a标签的点击事件
        document.querySelectorAll('a').forEach(link => {
          // 保存原始的href属性
          const originalHref = link.getAttribute('href');
          // 为每个a标签添加点击事件监听器
          link.addEventListener('click', function(e) {
            // 阻止默认的点击行为
            e.preventDefault();

            openLinkInDialog(originalHref, link.textContent);
          });
        });
    }

    // 初始化绑定所有链接
    bindDynamicLinks();
})();