链接新标签页打开❓

为同域名和跨域名链接分别设置打开行为

目前為 2025-04-07 提交的版本,檢視 最新版本

// ==UserScript==
// @name         链接新标签页打开❓
// @namespace    http://tampermonkey.net/
// @version      1.43
// @description  为同域名和跨域名链接分别设置打开行为
// @author       Grey333
// @match        *://*/*
// @grant        GM_setValue
// @grant        GM_getValue
// @license      MIT
// @grant        GM_registerMenuCommand
// ==/UserScript==



(function() {
    'use strict';

    const currentDomain = window.location.hostname;
    const getTopLevelDomain = (domain) => {
        const parts = domain.split('.');
        return parts.length > 2 ? parts.slice(-2).join('.') : domain;
    };
    const currentTopLevelDomain = getTopLevelDomain(currentDomain);

    // 获取和设置行为
    const getSameDomainBehavior = () => GM_getValue(currentDomain + '_sameDomain_behavior', 'default');
    const setSameDomainBehavior = (value) => GM_setValue(currentDomain + '_sameDomain_behavior', value);
    const getSubDomainBehavior = () => GM_getValue(currentDomain + '_subDomain_behavior', 'default');
    const setSubDomainBehavior = (value) => GM_setValue(currentDomain + '_subDomain_behavior', value);
    const getCrossDomainBehavior = () => GM_getValue(currentDomain + '_crossDomain_behavior', 'default');
    const setCrossDomainBehavior = (value) => GM_setValue(currentDomain + '_crossDomain_behavior', value);

    // 创建图形界面
    function createGUI() {
        if (document.getElementById('linkControlPanel')) return;

        const panel = document.createElement('div');
        panel.id = 'linkControlPanel';
        panel.style.cssText = `
            position: fixed; top: 20px; right: 20px; background: #f9f9f9;
            border: 1px solid #ddd; border-radius: 8px; padding: 15px;
            z-index: 10000; box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
            font-family: Arial, sans-serif; transition: opacity 0.3s ease-in-out;
            opacity: 0; max-width: 350px; min-width: 250px;
        `;

        const title = document.createElement('h3');
        title.textContent = `链接控制 - ${currentDomain}`;
        title.style.margin = '0 0 10px';
        panel.appendChild(title);

        const options = [
            { group: '同域名链接', key: 'sameDomain', get: getSameDomainBehavior, set: setSameDomainBehavior },
            { group: '子域名链接', key: 'subDomain', get: getSubDomainBehavior, set: setSubDomainBehavior },
            { group: '跨域名链接', key: 'crossDomain', get: getCrossDomainBehavior, set: setCrossDomainBehavior }
        ];

        options.forEach(({ group, key, get, set }) => {
            const groupTitle = document.createElement('h4');
            groupTitle.textContent = group;
            groupTitle.style.margin = '10px 0 5px';
            panel.appendChild(groupTitle);

            const behaviorOptions = [
                { label: '默认(不干预)', value: 'default' },
                { label: '强制新标签页', value: 'forceNewTab' },
                { label: '禁止新标签页', value: 'forceSameTab' }
            ];

            behaviorOptions.forEach(opt => {
                const label = document.createElement('label');
                label.style.display = 'block';
                label.style.margin = '5px 0';

                const radio = document.createElement('input');
                radio.type = 'radio';
                radio.name = `${key}_behavior`;
                radio.value = opt.value;
                if (get() === opt.value) radio.checked = true;

                radio.addEventListener('change', () => {
                    set(opt.value);
                    alert(`已为 ${group} 设置: ${opt.label}`);
                });

                label.appendChild(radio);
                label.appendChild(document.createTextNode(` ${opt.label}`));
                panel.appendChild(label);
            });
        });

        const closeBtn = document.createElement('button');
        closeBtn.textContent = '关闭';
        closeBtn.style.cssText = `
            margin-top: 15px; padding: 5px 10px; background: #007bff;
            color: #fff; border: none; border-radius: 4px; cursor: pointer;
        `;
        closeBtn.addEventListener('click', () => {
            panel.style.opacity = '0';
            setTimeout(() => panel.remove(), 300);
        });
        panel.appendChild(closeBtn);

        document.body.appendChild(panel);
        setTimeout(() => panel.style.opacity = '1', 10);
    }

    GM_registerMenuCommand('设置链接行为', createGUI);

    // 拦截 window.open
    const originalOpen = unsafeWindow.open;
    unsafeWindow.open = function(url, name, features) {
        try {
            const absoluteURL = new URL(url, window.location.href);
            const linkDomain = absoluteURL.hostname;
            const linkTopLevelDomain = getTopLevelDomain(linkDomain);
            let behavior;

            if (linkDomain === currentDomain) {
                behavior = getSameDomainBehavior();
            } else if (linkTopLevelDomain === currentTopLevelDomain && linkDomain !== currentDomain) {
                behavior = getSubDomainBehavior();
            } else {
                behavior = getCrossDomainBehavior();
            }

            console.log(`window.open 拦截: ${url} -> ${behavior}`);

            if (behavior === 'forceSameTab') {
                window.location.href = absoluteURL.href;
                return null; // 阻止新窗口
            } else if (behavior === 'forceNewTab') {
                return originalOpen.call(this, url, name, features);
            } else {
                return originalOpen.call(this, url, name, features); // 默认行为
            }
        } catch (error) {
            console.error('window.open 拦截失败:', error);
            return originalOpen.call(this, url, name, features);
        }
    };

    // 应用链接行为
    function applyLinkBehavior() {
        const sameDomainBehavior = getSameDomainBehavior();
        const subDomainBehavior = getSubDomainBehavior();
        const crossDomainBehavior = getCrossDomainBehavior();

        document.addEventListener('click', (e) => {
            const link = e.target.closest('a');
            if (!link || !link.href) return;

            try {
                const absoluteURL = new URL(link.href, window.location.href);
                const linkDomain = absoluteURL.hostname;
                const linkTopLevelDomain = getTopLevelDomain(linkDomain);
                let behavior;

                if (linkDomain === currentDomain) {
                    behavior = sameDomainBehavior;
                    console.log(`同域名链接: ${link.href} -> ${behavior}`);
                } else if (linkTopLevelDomain === currentTopLevelDomain && linkDomain !== currentDomain) {
                    behavior = subDomainBehavior;
                    console.log(`子域名链接: ${link.href} -> ${behavior}`);
                } else {
                    behavior = crossDomainBehavior;
                    console.log(`跨域名链接: ${link.href} -> ${behavior}`);
                }

                if (behavior === 'default') return;

                e.preventDefault();
                e.stopImmediatePropagation();

                if (behavior === 'forceNewTab') {
                    window.open(absoluteURL.href, '_blank');
                } else if (behavior === 'forceSameTab') {
                    console.log(`强制当前页面跳转: ${absoluteURL.href}`);
                    window.location.href = absoluteURL.href;
                }
            } catch (error) {
                console.error('无法解析链接:', error);
            }
        }, { capture: true });

        // 移除 target="_blank"
        const observer = new MutationObserver((mutations) => {
            mutations.forEach(() => {
                document.querySelectorAll('a[href]').forEach(link => {
                    try {
                        const absoluteURL = new URL(link.href, window.location.href);
                        const linkDomain = absoluteURL.hostname;
                        const linkTopLevelDomain = getTopLevelDomain(linkDomain);
                        let behavior;

                        if (linkDomain === currentDomain) {
                            behavior = sameDomainBehavior;
                        } else if (linkTopLevelDomain === currentTopLevelDomain && linkDomain !== currentDomain) {
                            behavior = subDomainBehavior;
                        } else {
                            behavior = crossDomainBehavior;
                        }

                        if (behavior === 'forceSameTab') {
                            if (link.getAttribute('target') === '_blank') {
                                link.removeAttribute('target');
                                console.log(`移除 target="_blank": ${link.href}`);
                            }
                        }
                    } catch (error) {
                        console.error('MutationObserver 错误:', error);
                    }
                });
            });
        });
        observer.observe(document.body, { childList: true, subtree: true, attributes: true });
    }

    applyLinkBehavior();
})();

QingJ © 2025

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