⭐网页瞬间加载/跳过进度条直接加载网页(附重定向链接优化)⭐

任何链接内容跳过进度条秒加载,并优化删除重定向链接(解决95%的重定向问题,如知乎,微博等),所有参数可高度自定义

Installa questo script?
Script suggerito dall'autore

Potresti essere interessato/a anche a 🌙 高级定制网页护眼模式🌙

Installa questo script
// ==UserScript==
// @name         ⭐网页瞬间加载/跳过进度条直接加载网页(附重定向链接优化)⭐ 
// @namespace    fenda
// @version      1.0.15
// @description  任何链接内容跳过进度条秒加载,并优化删除重定向链接(解决95%的重定向问题,如知乎,微博等),所有参数可高度自定义
// @icon         data:image/png;base64,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
// @author       fenda
// @match        *://*/*
// @grant        GM_getValue
// @grant        GM_setValue
// @grant        GM_registerMenuCommand
// @run-at       document-end
// @license      MPL-2.0
// ==/UserScript==

(function() {
    'use strict';

    /**
     * 添加一个新的样式标签到文档的头部,如果已有同名ID的标签则不执行添加。
     * 
     * @param {string} styleId - 样式标签的ID,用于检查是否已经存在具有相同ID的样式。
     * @param {string} cssRules - 要添加的CSS规则的字符串表示,用于设置style标签的内容。
     */
    function addStyle(styleId, cssRules) {
        if (!document.getElementById(styleId)) {
            const style = document.createElement('style');
            style.id = styleId;
            style.setAttribute('type', 'text/css');
            style.innerHTML = cssRules;
            document.head.appendChild(style);
        }
    }

    function createElementWithStylesAndAttributes(tag, styles, attributes) {
        let element = document.createElement(tag);
        if (styles) {
            Object.assign(element.style, styles);
        }
        if (attributes) {
            for (const key in attributes) {
                if (attributes.hasOwnProperty(key)) {
                    if (key in element) {
                        element[key] = attributes[key];
                    } else {
                        element.setAttribute(key, attributes[key]);
                    }
                }
            }
        }
        return element;
    }

    /* ------------------------------- 以下是脚本的设置面板函数 ------------------------------- */

    /**
     * 主动画循环。
     */
    function animate() {
        if (loadingPanel.style.display === 'block') {
            stats.update();
        }
        requestAnimationFrame(animate);
    }
    /**
     * 检查是否有更新。
     */
    function checkForUpdates() {
        var lastCheckedTime = GM_getValue('lastCheckedTime', 0);
        var currentTime = Date.now();

        if (currentTime - lastCheckedTime >= 3600000) {
            GM_setValue('lastCheckedTime', currentTime);
            var updateURL = "https://update.greasyfork.org/scripts/493851/%E2%AD%90%E7%BD%91%E9%A1%B5%E7%9E%AC%E9%97%B4%E5%8A%A0%E8%BD%BD%E8%B7%B3%E8%BF%87%E8%BF%9B%E5%BA%A6%E6%9D%A1%E7%9B%B4%E6%8E%A5%E5%8A%A0%E8%BD%BD%E7%BD%91%E9%A1%B5%E2%AD%90.meta.js";

            fetch(updateURL).then(function(response) {
                response.text().then(function(text) {
                    var latestVersion = text.match(/@version\s+([^\n]+)/)[1];
                    if (latestVersion) {
                        GM_setValue('latestVersion', latestVersion);
                    }
                });
            }).catch(function(error) {
                console.error('An error occurred while checking for updates:', error);
            });
        }
    }

    /**
     * 创建特性列表项。
     *
     * @param {Array} features - 特性描述列表。
     * @returns {Array} - 转换为HTML元素列表的数组。
     */
    function createFeatureListItems(features) {
        return features.map(feature => {
            let parts = feature.split(',').map(part => part.trim());
            let listItem = createElementWithStylesAndAttributes('div', { width: '85px', height: '32px', lineHeight: '32px', backgroundColor: '#E0E5EC', margin: '3px 0', borderRadius: '5px', boxShadow: 'inset 2px 2px 4px #BECBD8, inset -2px -2px 4px #FFFFFF', textAlign: 'center', userSelect: 'none', whiteSpace: 'nowrap', fontSize: '14px', }, { innerText: parts[0] });
            let featureContainer = createElementWithStylesAndAttributes('div', { display: 'flex', justifyContent: 'space-between', alignItems: 'center', width: 'calc(100% - 6px)', marginTop: '3px', marginLeft: '3px', marginRight: '3px', boxSizing: 'border-box' });
            featureContainer.appendChild(listItem);
            if (parts.includes('information')) {
                function parseMarkdown(mdText) {
                    let htmlText = mdText;
                    htmlText = htmlText.replace(/\*\*(.*?)\*\*/g, "<strong>$1</strong>"); // 加粗
                    htmlText = htmlText.replace(/\*(.*?)\*/g, "<em>$1</em>"); // 斜体
                    htmlText = htmlText.replace(/##(.*?)\n/g, "<h2>$1</h2>"); // 标题
                    htmlText = htmlText.replace(/\n/g, "<br>"); // 换行
                    htmlText = htmlText.replace(/\[([^\]]+)\]\(([^)]+)\)/g, '<a href="$2" target="_blank">$1</a>'); // 链接
                    return htmlText;
                }
                let infoIcon = createElementWithStylesAndAttributes("div", { position: 'relative', cursor: 'pointer', display: 'flex', alignItems: 'left', justifyContent: 'center' }, { innerHTML: `<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"></circle><line x1="12" y1="16" x2="12" y2="12"></line><line x1="12" y1="8" x2="12.01" y2="8"></line></svg>` });
                let infoBox = createElementWithStylesAndAttributes("div", { width: "300px", height: "auto", overflow: "auto", display: "none", position: "absolute", transform: "translateX(-50%)", backgroundColor: "#E0E5EC", borderRadius: "12px", boxShadow: "2px 2px 4px #AEBEC7, -2px -2px 4px #FFFFFF", zIndex: "2000" });
                let parsedContent = parseMarkdown(parts[4]);
                let infoText = createElementWithStylesAndAttributes("div", { padding: "10px", margin: "0", fontSize: "15px", fontWeight: "bold", textAlign: "left", textShadow: "2px 2px 3px rgba(0, 0, 0, 0.2)", color: "#4B5563" }, { innerHTML: parsedContent });

                infoBox.appendChild(infoText);
                document.body.appendChild(infoBox);
                document.addEventListener('mousemove', function(e) {
                    const mouseX = e.pageX;
                    const mouseY = e.pageY;
                    const offsetX = 20;
                    const offsetY = 20;
                    infoBox.style.left = `${mouseX + offsetX}px`;
                    infoBox.style.top = `${mouseY + offsetY}px`;
                });
                featureContainer.appendChild(infoIcon);
                infoIcon.addEventListener('mouseover', function() {
                    infoBox.style.display = 'block';
                });
                infoIcon.addEventListener('mouseout', function() {
                    infoBox.style.display = 'none';
                });
            }
            if (parts.includes('styleSelector')) {
                addStyle("neumorphic-checkbox-style", `
                    .neumorphic-checkbox { -webkit-appearance: none; appearance: none; background-color: #e0e5ec; margin: 0; font: inherit; color: currentColor; width: 30px; height: 30px; border: 2px solid #d1d9e6; border-radius: 4px; transform: translateY(-0.075em); display: grid; place-content: center; }
                    .neumorphic-checkbox { background-color: #ff3b3b; /* red for false */ }
                    .neumorphic-checkbox:checked { background-color: #3bff3b; /* green for true */ border-color: #28a745; box-shadow: inset 3px 3px 5px #b8c4d8, inset -3px -3px 5px #ffffff; }
                    .neumorphic-checkbox + span { vertical-align: middle; }
                `);

                let Selector = GM_getValue(parts[6]);
                let styleSelectorCheckbox = createElementWithStylesAndAttributes("input", {}, {
                    type: "checkbox",
                    checked: Selector || false,
                    className: "neumorphic-checkbox"
                });

                styleSelectorCheckbox.addEventListener("change", function() {
                    GM_setValue(parts[6], styleSelectorCheckbox.checked);

                    // 将背景颜色设置为红色或绿色取决于复选框的状态
                    styleSelectorCheckbox.style.backgroundColor = styleSelectorCheckbox.checked ? '#3bff3b' : '#ff3b3b';
                });

                // 设置初始背景颜色
                styleSelectorCheckbox.style.backgroundColor = Selector ? '#3bff3b' : '#ff3b3b';

                let checkboxContainer = createElementWithStylesAndAttributes("label", { display: 'flex', alignItems: 'center', justifyContent: 'space-between' });
                checkboxContainer.appendChild(styleSelectorCheckbox);
                featureContainer.appendChild(checkboxContainer);
            };

            if (parts.includes('settingButton')) {

                const settingButtonContainer = createElementWithStylesAndAttributes('div', { display: 'flex', alignItems: 'center', justifyContent: 'center', width: '80px', height: '32px', margin: '5px 0' });

                const settingButton = createElementWithStylesAndAttributes('div', { cursor: 'pointer', display: 'flex', alignItems: 'center', justifyContent: 'center', width: '24px', height: '24px', }, { innerHTML: `<svg xmlns="http://www.w3.org/2000/svg" height="1.5em" fill="currentColor" viewBox="0 0 512 512"><path d="M 188 37 Q 192 20 205 10 L 205 10 Q 218 0 235 0 L 277 0 Q 294 0 307 10 Q 320 20 324 37 L 332 71 L 333 71 L 363 53 Q 378 44 394 46 Q 410 48 422 60 L 452 90 Q 464 102 466 118 Q 468 134 459 149 L 441 179 L 441 180 L 475 188 Q 492 192 502 205 Q 512 218 512 235 L 512 277 Q 512 294 502 307 Q 492 320 475 324 L 441 332 L 441 333 L 459 363 Q 468 378 466 394 Q 464 410 452 422 L 422 452 Q 410 464 394 466 Q 378 468 363 459 L 333 441 L 332 441 L 324 475 Q 319 492 307 502 Q 294 512 277 512 L 235 512 Q 218 512 205 502 Q 192 492 188 475 L 180 441 L 179 441 L 149 459 Q 134 468 118 466 Q 102 464 90 452 L 60 422 Q 48 410 46 394 Q 44 378 53 363 L 72 333 L 71 332 L 37 324 Q 20 320 10 307 Q 0 294 0 277 L 0 235 Q 0 218 10 205 Q 20 192 37 188 L 71 180 L 71 179 L 53 149 Q 44 134 46 118 Q 48 102 60 90 L 90 60 Q 102 48 118 46 Q 134 44 149 53 L 179 72 L 180 71 L 188 37 L 188 37 Z M 277 48 L 235 48 L 224 95 Q 220 107 208 112 Q 198 115 188 120 Q 176 125 165 119 L 124 94 L 94 124 L 119 165 Q 126 176 120 188 Q 115 198 112 208 Q 107 220 95 224 L 48 235 L 48 277 L 95 288 Q 107 292 112 304 Q 115 314 120 324 Q 125 336 119 347 L 94 388 L 124 418 L 165 393 Q 176 387 188 392 Q 198 397 208 400 Q 220 405 224 417 L 235 464 L 277 464 L 288 417 Q 292 405 304 400 Q 314 397 324 392 Q 336 387 347 393 L 388 418 L 418 388 L 393 347 Q 387 336 392 324 Q 397 314 400 304 Q 405 292 417 288 L 464 277 L 464 235 L 417 224 Q 405 220 400 208 Q 397 198 392 188 Q 387 176 393 165 L 418 124 L 388 94 L 347 119 Q 336 126 324 120 Q 314 115 304 112 Q 292 107 288 95 L 277 48 L 277 48 Z M 292 163 L 260 355 Q 255 373 237 372 Q 219 367 220 349 L 252 157 Q 257 139 275 140 Q 293 145 292 163 L 292 163 Z M 198 230 L 172 256 L 198 282 Q 210 296 198 310 Q 184 322 170 310 L 130 270 Q 118 256 130 242 L 170 202 Q 184 190 198 202 Q 210 216 198 230 L 198 230 Z M 342 202 L 382 242 Q 394 256 382 270 L 342 310 Q 328 322 314 310 Q 302 296 314 282 L 340 256 L 314 230 Q 302 216 314 202 Q 328 190 342 202 L 342 202 Z" /></svg>` });


                settingButton.addEventListener('click', function() {
                    document.body.style.overflow = 'hidden';
                    const settingParametersPanel = createElementWithStylesAndAttributes('div', { display: 'none', position: 'fixed', top: '50%', left: '50%', transform: 'translate(-50%, -50%)', flexDirection: 'column', background: '#E0E5EC', border: '1px solid #BECBD8', borderRadius: '10px', boxShadow: '2px 2px 8px #BECBD8, -2px -2px 8px #FFFFFF', width: '300px', height: '300px', zIndex: '1500' });
                    const settingTitle = createElementWithStylesAndAttributes('div', { fontSize: '16px', fontWeight: 'bold', margin: '10px 0', textAlign: 'center' }, { innerHTML: '重定向调试菜单' });
                    const settingOptions = createElementWithStylesAndAttributes('div', { userSelect: 'none', fontSize: '14px', padding: '10px', textAlign: 'left', whiteSpace: 'nowrap', display: 'flex', flexDirection: 'column', justifyContent: 'space-between', position: 'relative' });
                    const siteLinksOption = createElementWithStylesAndAttributes('div', { cursor: 'pointer', fontSize: '14px', padding: '10px', textAlign: 'left', whiteSpace: 'nowrap', borderBottom: '1px solid #BECBD8' }, { innerHTML: '本站链接' });
                    const parametersOption = createElementWithStylesAndAttributes('div', { cursor: 'pointer', fontSize: '14px', padding: '10px', textAlign: 'left', whiteSpace: 'nowrap' }, { innerHTML: '参数设置' });
                    let count = 1;
                    let preloadedLinks = GM_getValue('preloadedLinks', []);
                    const settingInputBox = createElementWithStylesAndAttributes('div', { fontSize: '13px', id: 'redirectConversionLinks', padding: '10px', flex: '1 1', height: '230px', resize: 'none', borderRadius: '10px', boxShadow: 'inset 2px 2px 4px #a3b1c6, inset -2px -2px 4px #ffffff', overflow: 'auto' }, { innerHTML: preloadedLinks.map(linkData => { return `<div class="styledPanel"> <strong>${count++}.</strong> <br>原链接:${linkData.url} <br>优化后:${linkData.optimizedUrl || linkData.url} <br>重定向参数: ${linkData.redirectParameter} </div> `; }).join('') });
                    addStyle('customDisplayStyles', ` .styledPanel { width: 100%; margin: 5px 0; padding: 10px; box-shadow: 0 0 10px rgba(0, 0, 0, 0.1); white-space: pre-line; /* 允许长单词换行 */ word-wrap: break-word; } `);
                    const settingOptionsContainer = createElementWithStylesAndAttributes('div', { display: 'flex', flexDirection: 'row', overflow: 'hidden', alignItems: 'top', marginRight: '15px' });
                    const settingCloseButton = createElementWithStylesAndAttributes('div', { cursor: 'pointer', display: 'flex', alignItems: 'center', justifyContent: 'center', width: '24px', height: '24px', position: 'absolute', top: '0', right: '0', margin: '10px 0 20px 10px' }, { innerHTML: `<svg xmlns="http://www.w3.org/2000/svg" height="1em" fill="currentColor" viewBox="0 0 334 334"><path d="M 320 48 Q 334 31 320 14 Q 303 0 286 14 L 167 133 L 48 14 Q 31 0 14 14 Q 0 31 14 48 L 133 167 L 14 286 Q 0 303 14 320 Q 31 334 48 320 L 167 201 L 286 320 Q 303 334 320 320 Q 334 303 320 286 L 201 167 L 320 48 L 320 48 Z" /></svg>` });
                    settingOptionsContainer.appendChild(settingOptions);
                    settingOptionsContainer.appendChild(settingInputBox);
                    settingParametersPanel.appendChild(settingTitle);
                    settingParametersPanel.appendChild(settingOptionsContainer);
                    settingParametersPanel.appendChild(settingCloseButton);
                    document.body.appendChild(settingParametersPanel);
                    settingCloseButton.addEventListener('click', function() {
                        const newQueryItemsText = document.getElementById('queryItemsList').value.split(',');
                        console.log(newQueryItemsText);
                        if (newQueryItemsText) {
                            GM_setValue('queryItemsList', newQueryItemsText);
                            showAlert("重定向参数保存成功");
                            console.log(GM_getValue('queryItemsList'));
                        } else {
                            showAlert("请确保输入参数后再保存!");
                        }
                        settingParametersPanel.style.display = 'none';
                        document.body.style.overflow = 'auto';
                    });
                    const originalContent = settingInputBox.innerHTML;
                    siteLinksOption.addEventListener('click', function() {
                        settingInputBox.innerHTML = originalContent;
                    });
                    parametersOption.addEventListener('click', function() {
                        settingInputBox.innerHTML = '';
                        console.log(GM_getValue('queryItemsList'));
                        const joinQueryItems = GM_getValue('queryItemsList').join(',');
                        settingInputBox.innerHTML = `<textarea id="queryItemsList" class="styledPanel" style="height: calc(100% - 20px); width: calc(100%-10px); overflow: auto ;">${joinQueryItems}</textarea>`;
                    });
                    settingParametersPanel.style.display = 'flex';
                    settingOptions.appendChild(siteLinksOption);
                    settingOptions.appendChild(parametersOption);
                });



                settingButtonContainer.appendChild(settingButton);
                featureContainer.appendChild(settingButtonContainer);
            }
            parts.slice(1).forEach((componentType, idx) => {
                let component;
                let defaultValue;
                switch (componentType) {
                    case 'numberPicker':
                        defaultValue = GM_getValue(parts[idx + 2]);
                        component = createUIComponent('numberPicker', { value: defaultValue, min: 0, max: 100, step: 1, key: parts[idx + 2] });
                        break;
                    case 'inputBox':
                        defaultValue = GM_getValue(parts[idx + 2]);
                        component = createUIComponent('inputBox', { type: 'text', value: defaultValue, key: parts[idx + 2] });
                        break;
                    case 'selector':
                        defaultValue = GM_getValue(parts[idx + 2]);
                        component = createUIComponent('selector', { options: optionsArray, key: parts[idx + 2] });
                        break;
                    case 'switch':
                        defaultValue = GM_getValue(parts[idx + 2]);
                        component = createUIComponent('switch', { checked: defaultValue, key: parts[idx + 2] });
                        break;
                    case 'shortcutKeySetting':
                        defaultValue = GM_getValue(parts[idx + 2]);
                        component = createUIComponent('shortcutKeySetting', { value: defaultValue, key: parts[idx + 2] });
                        break;
                    default:
                        break;
                }
                if (component) {
                    featureContainer.appendChild(component);
                }
            });



            return featureContainer;
        });
    }

    /**
     * 创建并初始化特色功能面板。
     *
     * @param {string} id - 该面板的HTML元素ID。
     * @param {number} translateX - 初始移动位置的距离。
     * @returns {HTMLElement} - 创建的特色功能面板元素。
     */
    function createShowcaseFeaturesPanel(id, translateX) {
        let showcaseFeatures = createElementWithStylesAndAttributes('div', { position: "absolute", width: "250px", height: "270px", borderRadius: "15px", display: "flex", alignItems: "flex-start", flexDirection: "column", justifyContent: "flex-start", background: "#E0E5EC", boxShadow: "2px 2px 8px #BECBD8, -2px -2px 8px #FFFFFF", transition: "transform 0.5s ease", transform: `translateX(${translateX}px)`, overflow: "hidden" });
        showcaseFeatures.id = id;
        return showcaseFeatures;
    }

    /**
     * 创建不同的UI组件。
     *
     * @param {string} type - 组件类型。
     * @param {Object} options - 用于创建组件的选项。
     * @param {string} [options.value] - 组件的当前值。
     * @param {Object} options.min - 组件的最小值。
     * @param {Object} options.max - 组件的最大值。
     * @param {Object} options.step - 组件的步长值。
     * @param {Array} options.options - 下拉选项。
     * @param {boolean} options.checked - 开关的选中状态。
     * @returns {HTMLElement} - 相应类型的行内UI组件。
     */
    function createUIComponent(type, options, ) {

        if (type === 'switch') {
            addStyle('optimized-switch-style', `
                .optimizedswitchcontainer input[type="checkbox"] {  width: 0; height: 0; opacity: 0; }
                .optimizedswitchcontainer { position: relative; display: inline-block; width: 34px; height: 14px; }
                .optimizedswitchslider { position: absolute; cursor: pointer; top: 0; bottom: 0; left: 0; right: 0; background-color: #ccc; transition: .4s; }
                .optimizedswitchslider:before { position: absolute; content: ""; height: 20px; width: 20px; left: 0; bottom: -3px; background-color: white; transition: .4s; box-shadow: 0 2px 5px rgba(0,0,0,0.3); }
                .optimizedswitchcontainer input:checked + .optimizedswitchslider { background-color: #00FF00; }
                .optimizedswitchcontainer input:focus + .optimizedswitchslider { box-shadow: 0 0 1px #2196F3; }
                .optimizedswitchcontainer input:checked + .optimizedswitchslider:before { transform: translateX(18px); }
            `);
            let switchContainer = createElementWithStylesAndAttributes("label", {}, {
                className: "optimizedswitchcontainer"
            });

            let switchInput = createElementWithStylesAndAttributes("input", {}, {
                type: "checkbox",
                checked: options.checked || false,
            });

            switchInput.addEventListener("change", function() {
                GM_setValue(options.key, this.checked);
            });

            let switchSlider = createElementWithStylesAndAttributes("span", {}, {
                className: "optimizedswitchslider"
            });

            switchContainer.appendChild(switchInput);
            switchContainer.appendChild(switchSlider);

            return switchContainer;
        } else if (type === 'inputBox') {
            addStyle("neumorphic-style",
                `.neu-display-box { font-size: 14px; background: #e0e5ec; border-radius: 10px; box-shadow: 2px 2px 4px #a3b1c6, -2px -2px 4px #ffffff; transition: all 0.3s; display: flex; justify-content: center; align-items: center; cursor: pointer; width: 80px; height: 30px; overflow: hidden; white-space: nowrap; }
                .neu-input-modal { width: 200px;height: 300px; display: none; position: fixed; top: 50%; left: 50%; transform: translate(-50%, -50%); background: #e0e5ec; border-radius: 10px; box-shadow: 2px 2px 4px #a3b1c6, -2px -2px 4px #ffffff; width: 280px; box-sizing: border-box; justify-content: center; align-items: center; flex-direction: column;z-index: 1500; }
                .neu-text-input, .button-row button { border: none; background: none; outline: none; }
                .neu-text-input { padding: 10px;width: 250px; height: 200px; resize: none; margin-bottom: 10px; border-radius: 10px; box-shadow: inset 2px 2px 4px #a3b1c6, inset -2px -2px 4px #ffffff; }
                .button-row { display: flex; justify-content: space-between; width: calc(100% - 34px); }
                .button-row button { width: 95px; cursor: pointer; background: #e0e5ec; border-radius: 5px;  box-shadow: 2px 2px 4px #a3b1c6, -2px -2px 4px #ffffff; }
                .button-row button:hover { box-shadow: inset 2px 2px 4px #a3b1c6, inset -2px -2px 4px #ffffff; }
            `);

            let modal = createElementWithStylesAndAttributes("div", {}, {
                className: "neu-input-modal",
            });

            let textInput = createElementWithStylesAndAttributes("textarea", {}, {
                className: "neu-text-input",
                value: GM_getValue(options.key) || "",
            });

            let valueDisplay = options.value.join(',').length > 5 ? options.value.join(',').substring(0, 5) + '...' : options.value.join(',') || "点击输入";
            let displayBox = createElementWithStylesAndAttributes("div", { id: "displayBox" }, {
                className: "neu-display-box",
                innerHTML: valueDisplay,
                onclick: function() {
                    modal.style.display = 'flex';
                    textInput.focus();
                    var textLength = textInput.value.length;
                    textInput.setSelectionRange(textLength, textLength);
                }
            });

            let buttonRow = createElementWithStylesAndAttributes("div", {}, {
                className: "button-row",
            });


            let saveButton = createElementWithStylesAndAttributes("button", {}, {
                innerHTML: '保存',
                onclick: function() {
                    modal.style.display = 'none';
                    let userInput = textInput.value.trim();
                    let userDomains = userInput ? userInput.split(',') : [];
                    GM_setValue(options.key, userDomains);
                    updateDomainLists();
                    displayBox.textContent = userDomains.join(',').length > 5 ? userDomains.join(',').substring(0, 5) + '...' : userDomains.join(',') || "点击输入";
                    showAlert('域名已保存!');
                }
            });


            let addDomainButton = createElementWithStylesAndAttributes("button", {}, {
                innerHTML: '添加当前域名到输入框',
                onclick: function() {
                    var domain = window.location.hostname;
                    var domainList = GM_getValue(options.key, []);
                    if (!domainList.includes(domain)) {
                        domainList.push(domain);
                        GM_setValue(options.key, domainList);
                        updateDomainLists();
                        modal.style.display = 'none';
                        textInput.value = domainList.join(',');
                        displayBox.textContent = domainList.join(',').length > 5 ? domainList.join(',').substring(0, 5) + '...' : domainList.join(',');
                        showAlert('域名已保存!');
                    } else {
                        showAlert('域名已存在!');
                    }
                }
            });

            buttonRow.appendChild(saveButton);
            buttonRow.appendChild(addDomainButton);

            modal.appendChild(textInput);
            modal.appendChild(buttonRow);

            document.body.appendChild(modal);

            return displayBox;
        } else if (type === 'selector') {
            addStyle("neumorphic-selector-modal-style",
                `.neu-selector-display {  font-size: 14px; line-height: 32px;height: 32px; width: 80px; background: #e0e5ec; border-radius: 10px; box-shadow: 2px 2px 4px #a3b1c6, -2px -2px 4px #ffffff;cursor: pointer; user-select: none; position: relative; text-align: center; }
                .neu-selector-modal { display: none; position: absolute; background: #e0e5ec; box-shadow: 2px 2px 4px #a3b1c6, -2px -2px 4px #ffffff; border-radius: 10px; z-index: 1000; flex-direction: column; }
                .neu-selector-modal-open { display: flex; }
                .neu-selector-option { font-size: 18px;margin-bottom: 2px;white-space: nowrap; cursor: pointer; user-select: none; text-align: center; width: 70px; box-sizing: border-box; }
                .neu-selector-option:hover { background-color: #d1d9e6; }
            `);

            let selectorDisplay = createElementWithStylesAndAttributes("div", {}, {
                className: "neu-selector-display"
            });

            let modal = createElementWithStylesAndAttributes("div", {}, {
                className: "neu-selector-modal"
            });

            let container = document.createElement("div");
            container.style.position = "relative";

            function selectOption(option) {
                GM_setValue(options.key, option);
                selectorDisplay.textContent = GM_getValue(options.key);
                modal.className = "neu-selector-modal";
            }

            optionsArray.forEach((option) => {
                let optionElement = createElementWithStylesAndAttributes("div", {}, {
                    className: "neu-selector-option",
                    textContent: option,
                    onclick: () => selectOption(option)
                });
                modal.appendChild(optionElement);
            });

            selectorDisplay.addEventListener("click", function(event) {
                event.stopPropagation();
                modal.className = modal.className.includes("neu-selector-modal-open") ? "neu-selector-modal" : "neu-selector-modal neu-selector-modal-open";
                let modalRect = modal.getBoundingClientRect();
                modal.style.left = `-${selectorDisplay.offsetWidth}px`;
                modal.style.top = `${(selectorDisplay.offsetHeight - modalRect.height) / 2}px`;
            });
            document.addEventListener("click", function() {
                modal.className = "neu-selector-modal";
            });
            container.appendChild(selectorDisplay);
            container.appendChild(modal);
            selectorDisplay.textContent = GM_getValue(options.key);

            return container;
        } else if (type === 'shortcutKeySetting') {
            addStyle("shortcutKeySetting-style", `
                .shortcutKeySetting-displayBox { width: 80px; height: 32px; overflow:auto ;background: #e0e5ec; border-radius: 5px; box-shadow: inset 2px 2px 4px #BECBD8, inset -2px -2px 4px #FFFFFF; border: none;  margin: 5px 0; flex: 1; text-align: center; outline: none; width: 80px; }
                .shortcutKeySetting-button { width: 60px; height: 32px; margin-left: 10px; background: #e0e5ec; border-radius: 10px; box-shadow: 2px 2px 4px #a3b1c6, -2px -2px 4px #ffffff; border: none; cursor: pointer; user-select: none; }
                .shortcutKeySetting-container { display: flex; justify-content: space-between; align-items: center; box-sizing: border-box;  }
            `);

            let container = createElementWithStylesAndAttributes('div', {}, {
                className: "shortcutKeySetting-container"
            });

            let shortcutKeyValue = GM_getValue(options.key);
            let displayPlaceholder = shortcutKeyValue ? shortcutKeyValue.toUpperCase() : '快捷键';

            let displayBox = createElementWithStylesAndAttributes('input', {}, {
                type: 'text',
                readOnly: true,
                placeholder: displayPlaceholder,
                className: "shortcutKeySetting-displayBox"
            });

            let setButton = createElementWithStylesAndAttributes('button', {}, {
                innerText: '设定',
                className: "shortcutKeySetting-button"
            });

            setButton.addEventListener('click', function() {
                displayBox.value = '按下任意键...';
                displayBox.disabled = false;
                let keySequence = [];

                let keyDownEvent = function(event) {
                    event.preventDefault();
                    let key = event.key.toLowerCase();
                    if (!keySequence.includes(key)) {
                        keySequence.push(key);
                        displayBox.value = keySequence.join('+').toUpperCase();
                        GM_setValue(options.key, keySequence.join('+'));
                        console.log(GM_getValue(options.key));
                    }
                };

                let keyUpEvent = function() {
                    document.removeEventListener('keydown', keyDownEvent);
                    displayBox.disabled = true;
                    document.removeEventListener('keyup', keyUpEvent);
                };

                document.addEventListener('keydown', keyDownEvent);
                document.addEventListener('keyup', keyUpEvent);
            });

            container.appendChild(displayBox);
            container.appendChild(setButton);

            return container;
        } else if (type === 'numberPicker') {
            addStyle("neumorphic-numberPicker-style",
                `.neu-numberPicker-container { max-width: 121px;width: 100%; height: 32px; display: flex; align-items: center; justify-content: space-between; background: #e0e5ec; border-radius: 10px; box-shadow: 2px 2px 4px #a3b1c6, -2px -2px 4px #ffffff; }
                 .neu-numberPicker-button { background: #e0e5ec; border: none; border-radius: 100%; box-shadow: 2px 2px 4px #a3b1c6, -2px -2px 4px #ffffff; width: 30px; height: 30px; cursor: pointer; font-size: 15px; display: flex; align-items: center; justify-content: center; user-select: none; min-width: 30px;}
                 .neu-numberPicker-button:active {box-shadow: inset 2px 2px 4px #a3b1c6, inset -2px -2px 4px #ffffff; }
                 .neu-numberPicker-value {width: 40px; text-align: center; font-size: 16px; background: transparent; border: none; outline: none; margin: 0 auto;  
            }`);

            let container = createElementWithStylesAndAttributes("div", {}, {
                className: "neu-numberPicker-container"
            });

            let intervalId = null;

            const updateValue = (increment) => {
                let currentValue = parseInt(valueDisplay.value, 10) || 0;
                let newValue = increment ? currentValue + 1 : currentValue - 1;
                if (newValue < 1) {
                    newValue = 1; // 最小值限制
                    showAlert('亲,“1”难道还不够小嘛');
                }
                valueDisplay.value = newValue;
                GM_setValue(options.key, valueDisplay.value);
            };

            const createContinuousButton = (innerHTML, increment) => {
                let button = createElementWithStylesAndAttributes("button", {}, {
                    innerHTML: innerHTML,
                    className: "neu-numberPicker-button"
                });

                button.addEventListener("mousedown", function() {
                    updateValue(increment);
                    intervalId = setInterval(() => updateValue(increment), 200);
                });

                ['mouseup', 'mouseleave'].forEach(event => {
                    button.addEventListener(event, function() {
                        clearInterval(intervalId);
                    });
                });

                return button;
            };

            let currentValue = GM_getValue(options.key, 0);

            let valueDisplay = createElementWithStylesAndAttributes("input", {}, {
                type: "text",
                value: currentValue,
                className: "neu-numberPicker-value",
                oninput: function() {
                    this.value = this.value.replace(/[^0-9]/g, '');
                    GM_setValue(options.key, this.value);
                }
            });

            let minusButton = createContinuousButton('➖', false);
            let plusButton = createContinuousButton('➕', true);

            container.appendChild(minusButton);
            container.appendChild(valueDisplay);
            container.appendChild(plusButton);

            return container;
        } else {
            throw new Error('不支持的UI组件类型');
        }
    }

    /**
     * 创建显示版本信息的元素,并添加到页面中。
     *
     * @returns {HTMLElement} - 包含版本信息和更新日志按钮的元素。
     */
    function createVersionInfoElement() {
        const versionInfo = createElementWithStylesAndAttributes('div', {
            position: 'relative',
            left: '20px',
            width: 'auto',
            bottom: `5px`,
            fontSize: '10px',
            color: '#666',
            display: 'flex',
            marginTop: '10px',
        });

        const currentVersion = '1.0.15';
        versionInfo.innerHTML = `<strong>当前版本:${currentVersion}(最新版本:${GM_getValue('latestVersion', '1.0.15')})</strong>`;

        const updateLogButton = document.createElement('button');
        updateLogButton.innerHTML = '更新日志';
        updateLogButton.style.cssText = 'display: flex; flex-direction: row; flex-wrap: wrap; position: relative; right: 0px; background-color: #e0e5ec; border: none; border-radius: 10px; cursor: pointer;';

        if (updateLogButton) {
            updateLogButton.onclick = fetchAndDisplayVersionHistory;
        }

        versionInfo.appendChild(updateLogButton);

        return versionInfo;
    }

    /**
     * 显示版本历史面板。
     *
     * @param {string} versionHistory - 版本历史内容的HTML字符串。
     */
    function displayVersionHistoryPanel(versionHistory) {
        let versionHistoryPanel = document.getElementById('versionHistoryPanel');
        if (!versionHistoryPanel) {
            versionHistoryPanel = document.createElement('div');
            versionHistoryPanel.id = 'versionHistoryPanel';
            document.body.appendChild(versionHistoryPanel);
        } else {

            versionHistoryPanel.style.display = 'block';
        }
        versionHistoryPanel.innerHTML = `
            <div id="versionHistoryContent" style="padding: 10px; position: relative; width: 300px; height: 300px; overflow: auto; position: fixed; top: 50%; left: 50%; transform: translate(-50%, -50%); background: #e0e5ec; box-shadow: 0 4px 8px 0 rgba(0,0,0,0.4), 0 6px 20px 0 rgba(0,0,0,0.19); border-radius: 15px; box-sizing: border-box; z-index: 10000; display: block; font-family: Arial, sans-serif;">
                <button id="closeVersionHistory" style="position: absolute; top: 10px; right: 10px; background: none; border: none; cursor: pointer;">
                    <svg xmlns="http://www.w3.org/2000/svg" height="24" fill="currentColor" viewBox="0 0 334 334"><path d="M 320 48 Q 334 31 320 14 Q 303 0 286 14 L 167 133 L 48 14 Q 31 0 14 14 Q 0 31 14 48 L 133 167 L 14 286 Q 0 303 14 320 Q 31 334 48 320 L 167 201 L 286 320 Q 303 334 320 320 Q 334 303 320 286 L 201 167 L 320 48 L 320 48 Z" /></svg>
                </button>
                <h2 style="text-align: center; font-size: 20px; font-weight: bold; color: #333; margin-bottom: 20px; text-shadow: 1px 1px 2px #888;">更新日志</h2>
                ${versionHistory}
            </div>
        `;

        document.getElementById('closeVersionHistory').addEventListener('click', function() {
            versionHistoryPanel.style.display = 'none';
        });
    }

    /**
     * 通过Greasy Fork网站获取版本历史信息并显示在自定义面板中。
     */
    async function fetchAndDisplayVersionHistory() {
        const url = 'https://greasyfork.org/zh-CN/scripts/493851-%E7%BD%91%E9%A1%B5%E7%9E%AC%E9%97%B4%E5%8A%A0%E8%BD%BD-%E8%B7%B3%E8%BF%87%E8%BF%9B%E5%BA%A6%E6%9D%A1%E7%9B%B4%E6%8E%A5%E5%8A%A0%E8%BD%BD%E7%BD%91%E9%A1%B5/versions';

        try {
            const response = await fetch(url);
            const text = await response.text();
            const parser = new DOMParser();
            const doc = parser.parseFromString(text, 'text/html');
            const versionHistory = doc.querySelector('.history_versions');
            if (versionHistory) {
                displayVersionHistoryPanel(versionHistory.innerHTML);
            } else {
                throw new Error('无法找到更新历史信息的元素');
            }
        } catch (error) {
            console.error('Failed to fetch version history', error);
            showAlert('无法获取更新历史,请稍后重试。');
        }
    }

    /**
     * 初始化默认设置并存储。
     */
    function initializeDefaultSettings() {
        const defaultSettings = {
            backToThePreviousPage: "shift+r",
            blacklistDomains: [],
            blackSelector: true,
            concurrentLoadingNumber: 5,
            forward: "shift+f",
            goToTheCorrespondingPage: "shift+e",
            lazyLoadImages: false,
            loadedStyle: "下划线",
            manipulatorBall: true,
            mobileGestures: true,
            previewHoverWindow: false,
            redirectOptimization: true,
            setShortcuts: "shift+s",
            asynchronousResources: true,
            whitelistDomains: [],
            whiteSelector: false,
            maxContentSize: 5,
            maxStorageItems: 100,
            dataCleanupInterval: 1,
            is_loadedStyle: true,
            monitorRefresh: 2,
        };

        Object.keys(defaultSettings).forEach((key) => {
            let currentValue = GM_getValue(key);
            if (currentValue === undefined || currentValue === null) {
                GM_setValue(key, defaultSettings[key]);
            }
        });
    }

    function replaceDownloadLink() {
        if (/lanz/.test(window.location.hostname)) {
            let downloadLinks = document.querySelectorAll('a');
            downloadLinks.forEach(link => {
                if (link.textContent.includes('立即下载')) {
                    let scripts = document.querySelectorAll('script');
                    scripts.forEach(script => {
                        let match = script.textContent.match(/var link = '(.*?)';/);
                        if (match) {
                            let newLink = window.location.hostname + '/' + match[1] + "##";
                            console.log(newLink);
                            link.href = '//' + newLink;
                        }
                    });
                } else if (/下载\(\s*[\d\.]+\s*K\s*\)/.test(link.textContent)) {
                    let scripts = document.querySelectorAll('script');
                    let vkjxld, hyggid;

                    scripts.forEach(script => {
                        let match_vk = script.textContent.match(/var vkjxld = '(.*?)';/);
                        let match_hy = script.textContent.match(/var hyggid = '(.*?)';/);

                        if (match_vk) {
                            vkjxld = match_vk[1];
                        }

                        if (match_hy) {
                            hyggid = match_hy[1];
                        }
                    });

                    if (vkjxld && hyggid) {
                        let newLink = vkjxld + hyggid;
                        console.log(newLink);
                        link.href = newLink;
                    }
                }
            });
        }
    }



    /**
     * 设置当前激活的面板,并对动画进行处理。
     *
     * @param {string} activePanelId - 要激活的面板ID。
     */
    function setActivePanel(activePanelId) {
        if (isAnimating) return;
        isAnimating = true;
        updateActiveIndicator(activePanelId);

        const panelIds = ['panel1', 'panel2', 'panel3']; // 面板ID列表按顺序
        const currentActiveIndex = panelIds.indexOf(currentActivePanelId);
        const targetActiveIndex = panelIds.indexOf(activePanelId);
        const direction = targetActiveIndex > currentActiveIndex ? -1 : 1; // 目标在右边则向左(-1), 否则向右(1)

        // 根据目标和当前激活的面板,计算出移动距离
        let moveDistance = direction * Math.abs(targetActiveIndex - currentActiveIndex) * 290; // 每个面板间隔250px宽度

        // 创建移动函数,面板根据方向和距离移动
        const animatePanel = (panelId, distance) => {
            const panel = document.getElementById(panelId);
            let currentTranslateX = parseFloat(panel.style.transform.replace('translateX(', '').replace('px)', '')) || 0;
            panel.style.transform = `translateX(${currentTranslateX + distance}px)`;
        };

        panelIds.forEach(id => {
            animatePanel(id, moveDistance);
        });

        // 动画结束后,重置面板位置并只显示目标面板
        setTimeout(() => {
            panelIds.forEach(id => {
                const panel = document.getElementById(id);
                panel.style.transform = `translateX(${(panelIds.indexOf(id) - targetActiveIndex) * 270}px)`;
            });
            currentActivePanelId = activePanelId;
            isAnimating = false;
        }, 500);
    }

    /**
     * 在屏幕上显示一段提示信息。
     *
     * @param {string} message - 需要展示的消息。
     */
    function showAlert(message) {
        let alertBox = createElementWithStylesAndAttributes("div", { width: "300px", position: "fixed", bottom: "10px", left: "50%", transform: "translateX(-50%)", backgroundColor: "#E0E5EC", borderRadius: "5px", boxShadow: "2px 2px 2px #AEBEC7, -2px -2px 2px #FFFFFF", zIndex: "2000" });
        let alertText = createElementWithStylesAndAttributes("div", { margin: "0", fontSize: "16px", fontWeight: "bold", textAlign: "center", textShadow: "2px 2px 3px rgba(0, 0, 0, 0.2)", color: "#4B5563" }, { innerText: message });
        alertBox.appendChild(alertText);
        document.body.appendChild(alertBox);

        setTimeout(function() {
            alertBox.style.opacity = "1";
        }, 10);

        setTimeout(function() {
            alertBox.style.opacity = "0";
            alertBox.addEventListener('transitionend', function() {
                document.body.removeChild(alertBox);
            }, { once: true });
        }, 1500);
    }

    /**
     * 性能分析工具的主要类。
     */
    var Stats = function() {
        var currentMode = 0;
        var container = createElementWithStylesAndAttributes('div', { position: 'fixed', bottom: '10px', right: '10px', left: '10px', cursor: 'pointer', opacity: '0.9', zIndex: '10000' });
        container.addEventListener('click', function(event) {
            event.preventDefault();
            showPanel(++currentMode % container.children.length);
        }, false);
        // 初始化性能监视计时
        var startTime = (performance || Date).now(),
            prevTime = startTime;
        var frames = 0;
        // 创建并添加面板
        var fpsPanel = addPanel(new Stats.Panel('FPS', '#0ff', '#002'));
        var msPanel = addPanel(new Stats.Panel('MS', '#0f0', '#020'));
        var memPanel;
        // 判断performance.memory是否可用以监视内存使用
        if (self.performance && self.performance.memory) {
            memPanel = addPanel(new Stats.Panel('MB', '#f08', '#201'));
        }

        showPanel(0);

        function addPanel(panel) {
            container.appendChild(panel.dom);
            return panel;
        }

        function showPanel(mode) {
            for (var i = 0; i < container.children.length; i++) {
                container.children[i].style.display = i === mode ? 'block' : 'none';
            }
            currentMode = mode;
        }
        return {
            dom: container,
            addPanel: addPanel,
            showPanel: showPanel,
            begin: function() {
                startTime = (performance || Date).now();
            },
            end: function() {
                frames++;
                var time = (performance || Date).now();
                msPanel.update(time - startTime, 200);

                if (time > prevTime + GM_getValue('monitorRefresh', 2) * 1000) {
                    fpsPanel.update((frames * 1000) / (time - prevTime), 100);
                    prevTime = time;
                    frames = 0;
                    if (memPanel) {
                        var memory = performance.memory;
                        memPanel.update(memory.usedJSHeapSize / 1048576, memory.jsHeapSizeLimit / 1048576);
                    }
                }
                return time;
            },
            update: function() {
                startTime = this.end();
            }
        };
    };

    /**
     * Stats中的Panel类,用来展示性能数据。
     *
     * @param {string} name - 面板显示的标题。
     * @param {string} fg - 前景色。
     * @param {string} bg - 背景色。
     */
    Stats.Panel = function(name, fg, bg) {
        var min = Infinity,
            max = 0;
        var round = Math.round;
        var pixelRatio = round(window.devicePixelRatio || 1);
        var width = 80 * pixelRatio,
            height = 48 * pixelRatio;
        var textPadding = 3 * pixelRatio,
            textHeight = 2 * pixelRatio;
        var graphX = 3 * pixelRatio,
            graphY = 15 * pixelRatio;
        var graphWidth = 74 * pixelRatio,
            graphHeight = 30 * pixelRatio;
        var canvas = document.createElement('canvas');
        canvas.width = width;
        canvas.height = height;
        canvas.style.cssText = 'width:80px;height:48px';
        var context = canvas.getContext('2d');
        context.font = 'bold ' + (9 * pixelRatio) + 'px Helvetica,Arial,sans-serif';
        context.textBaseline = 'top';
        context.fillStyle = bg;
        context.fillRect(0, 0, width, height);
        context.fillStyle = fg;
        context.fillText(name, textPadding, textHeight);
        context.fillRect(graphX, graphY, graphWidth, graphHeight);
        context.fillStyle = bg;
        context.globalAlpha = 0.9;
        context.fillRect(graphX, graphY, graphWidth, graphHeight);

        return {
            dom: canvas,
            update: function(value, maxValue) {
                min = Math.min(min, value);
                max = Math.max(max, value);
                context.fillStyle = bg;
                context.globalAlpha = 1;
                context.fillRect(0, 0, width, graphY);
                context.fillStyle = fg;
                context.fillText(round(value) + ' ' + name + ' (' + round(min) + '-' + round(max) + ')', textPadding, textHeight);
                context.drawImage(canvas, graphX + pixelRatio, graphY, graphWidth - pixelRatio, graphHeight, graphX, graphY, graphWidth - pixelRatio, graphHeight);
                context.fillRect(graphX + graphWidth - pixelRatio, graphY, pixelRatio, graphHeight);
                context.fillStyle = bg;
                context.globalAlpha = 0.9;
                context.fillRect(graphX + graphWidth - pixelRatio, graphY, pixelRatio, round((1 - value / maxValue) * graphHeight));
            }

        };
    };

    /**
     * 更新当前激活面板的指示器样式。
     *
     * @param {string} activePanelId - 当前激活的面板ID。
     */
    function updateActiveIndicator(activePanelId) {
        // 首先重置所有按钮的样式
        [settingsParameters, additionalFeatures, shortcutKeys].forEach(button => {
            button.style.fontSize = "20px";
            button.style.textShadow = "none";
        });

        // 根据当前激活的面板ID,将对应按钮的字体放大并添加立体效果
        if (activePanelId === 'panel1') {
            settingsParameters.style.fontSize = "24px";
            settingsParameters.style.textShadow = "1px 1px #888888";
        } else if (activePanelId === 'panel2') {
            additionalFeatures.style.fontSize = "24px";
            additionalFeatures.style.textShadow = "1px 1px #888888";
        } else if (activePanelId === 'panel3') {
            shortcutKeys.style.fontSize = "24px";
            shortcutKeys.style.textShadow = "1px 1px #888888";
        }
    }

    /*-------------以下为重定向优化的具体实现函数-------------*/

    /**
     * 重定向优化的主要参数,每个参数代表重定向的查询参数名称(基本涵盖95%的重定向链接)。
     */
    const queryItems = [
        'url', 'target', 'href', 'tid', 'u', 'goto', 'link',
        'remoteUrl', 'to', 'redirect', 'iv', 'safecheck', 'black',
        'sinaurl', 'newredirectconfirmcgi', 'view', 'go.shtml', 'link',
        'linkout', 'link2', 'go-wild', 'id', 'jump', 'jump.php', 'web',
        'security', 'r', 'redirect_link', 'youtube.com/redirect',
    ];



    if (typeof GM_getValue === 'function') {
        var queryItemsList = GM_getValue('queryItemsList', []);
        var queryItemsLists = [...new Set([...queryItemsList, ...queryItems])];
        GM_setValue('queryItemsList', queryItemsLists);

    }

    /**
     * 额外的重定向判断条件。
     * @param {string} urlObj 
     * @param {HTMLAnchorElement} linkElement 
     * @returns 
     */
    function extractTargetUrl(urlObj, linkElement) {
        if (urlObj.pathname.includes('jump.php')) {
            extractFromJumpPhp(urlObj, linkElement);
            return;
        }

        for (const item of queryItemsList) {
            try {
                const target = urlObj.searchParams.get(item);

                if (target && isValidHttpUrl(decodeURIComponent(target))) {
                    updateLink(target, linkElement, item);
                    return;
                }
            } catch (e) {
                console.error('URI 解码错误:', e);
            }
        }
    }

    /**
     * 单独对jump.php的处理。
     * @param {string} urlObj 
     * @param {HTMLAnchorElement} linkElement 
     */
    function extractFromJumpPhp(urlObj, linkElement) {
        const fullUrl = urlObj.href;
        const targetUrl = fullUrl.substring(fullUrl.indexOf('jump.php?') + 9);
        updateLink(targetUrl, linkElement);
    }

    let preloadedLinks = [];

    /**
     * 对链接优化的主要函数
     * @param {string} target 
     * @param {HTMLAnchorElement} linkElement 
     * @param {string} item
     */
    function updateLink(target, linkElement, item) {
        const originalHref = linkElement.href;
        const linkName = linkElement.textContent || linkElement.innerText;
        try {
            const targetUrl = decodeURIComponent(target);
            if (isValidHttpUrl(targetUrl)) {
                linkElement.href = targetUrl;
                console.log('优化的重定向链接:', originalHref, 'to:', targetUrl);
                preloadedLinks.push({ redirectParameter: item, name: linkName, url: originalHref, optimizedUrl: targetUrl });
                GM_setValue('preloadedLinks', preloadedLinks);
            }
        } catch (e) {
            console.error('URI 解码错误:', e);
        }
    }

    function isValidHttpUrl(string) {
        try {
            const url = new URL(string);
            return url.protocol === "http:" || url.protocol === "https:";
        } catch (_) {
            return false;
        }
    }

    function optimizeRedirects() {
        document.querySelectorAll('a[href]').forEach(link => {
            if (link.dataset.optimized) return;
            try {
                const urlObj = new URL(link.href);
                extractTargetUrl(urlObj, link);
                link.dataset.optimized = true;
            } catch (e) {
                console.error('错误处理链接:', link.href, '; Error:', e);
            }
        });
    }
    /**
     * 初始化重定向链接
     */
    function init() {
        if (GM_getValue('redirectOptimization')) {
            window.addEventListener('load', () => {
                optimizeRedirects();
                replaceDownloadLink();
                setInterval(replaceDownloadLink, 200); // 每0.5秒执行一次
            });
            const observer = new MutationObserver(() => {
                optimizeRedirects();
                replaceDownloadLink();
            });
            observer.observe(document.body, { childList: true, subtree: true });
            window.addEventListener('beforeunload', () => observer.disconnect());
        }
    }

    init();

    /* ----------------------------- 以下为预加载链接的具体代码实现 ---------------------------- */

    /**
     * 为链接添加视觉提醒,指示其已被预加载。
     *
     * @param {HTMLElement} element - 链接元素。
     */
    function addAVisualLinkReminder(element) {
        var href = element.href;
        try {
            var linkURL = new URL(href);
            var currentOrigin = window.location.origin;
            if (linkURL.origin === currentOrigin) {
                if (element.dataset.preloaded && GM_getValue('is_loadedStyle')) {
                    switch (GM_getValue('loadedStyle', "下划线")) {
                        case '下划线':
                            element.style.textDecoration = 'underline';
                            element.style.textDecorationSkipInk = 'none';
                            break;
                        case '高亮':
                            element.style.backgroundColor = 'yellow';
                            break;
                        case '品红':
                            element.style.color = '#FF00FF';
                            break;
                        case '加粗':
                            element.style.fontWeight = 'bold';
                            break;
                        case '边框':
                            element.style.border = '2px solid red';
                            element.style.borderRadius = '4px';
                            break;
                        default:
                            break;
                    }
                }
            }
        } catch (e) {
            console.error('Error adding visual link reminder:', e);
        }
    }

    /**
     * 添加可拖动的图标到页面上。
     */
    function addDraggableIcon() {
        var svgHTML = '<svg id="draggableIcon" style="position: fixed; top: 50%; right: -20px; transform: translateY(-50%); cursor: pointer; z-index: 9999999;" width="50" height="50" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path fill="currentColor" d="M3.464 20.536C4.93 22 7.286 22 12 22c4.714 0 7.071 0 8.535-1.465C22 19.072 22 16.714 22 12s0-7.071-1.465-8.536C19.072 2 16.714 2 12 2S4.929 2 3.464 3.464C2 4.93 2 7.286 2 12c0 4.714 0 7.071 1.464 8.535" opacity=".5"/><path fill="currentColor" d="M12.03 9.53a.75.75 0 0 0-1.06-1.06l-3 3a.75.75 0 0 0 0 1.06l3 3a.75.75 0 1 0 1.06-1.06L9.56 12z"/><path fill="currentColor" d="M16.03 9.53a.75.75 0 0 0-1.06-1.06l-3 3a.75.75 0 0 0 0 1.06l3 3a.75.75 0 1 0 1.06-1.06L13.56 12z"/></svg>',
            div = document.createElement('div');
        div.innerHTML = svgHTML;
        document.body.appendChild(div.firstChild);

        function onDrag(e, move) {
            var startX = ('touches' in e ? e.touches[0] : e).clientX - dragIcon.getBoundingClientRect().left,
                startY = ('touches' in e ? e.touches[0] : e).clientY - dragIcon.getBoundingClientRect().top;

            function dragging(ev) {
                var clientX = ('touches' in ev ? ev.touches[0] : ev).clientX,
                    clientY = ('touches' in ev ? ev.touches[0] : ev).clientY;
                dragIcon.style.left = clientX - startX + 'px';
                dragIcon.style.top = clientY - startY + 'px';
            }

            function endDrag() {
                document.removeEventListener(move ? 'mousemove' : 'touchmove', dragging);
                document.removeEventListener(move ? 'mouseup' : 'touchend', endDrag);
                document.body.style.overflow = '';
                dragIcon.style.transition = '';
                GM_setValue('iconPosition', { left: dragIcon.style.left, top: dragIcon.style.top });
            }
            document.addEventListener(move ? 'mousemove' : 'touchmove', dragging);
            document.addEventListener(move ? 'mouseup' : 'touchend', endDrag);
            document.body.style.overflow = 'hidden';
            dragIcon.style.transition = 'none';
            if (!move) {
                dragIcon.dataset.pressTimer = setTimeout(endDrag, 500);
            }
        }

        var dragIcon = document.getElementById('draggableIcon');
        dragIcon.style.display = 'none';
        var savedPosition = GM_getValue('iconPosition');
        savedPosition && (dragIcon.style.left = savedPosition.left, dragIcon.style.top = savedPosition.top);

        dragIcon.ontouchstart = function(e) {
            onDrag(e, false);
        };
        dragIcon.ontouchend = function() {
            clearTimeout(dragIcon.dataset.pressTimer);
        };
        dragIcon.onmousedown = function(e) {
            e.preventDefault();
            onDrag(e, true);
        };
    }

    /**
     * 将一个链接添加到预加载队列中。
     *
     * @param {string} url - 链接的地址。
     * @param {HTMLElement} element - 对应的链接元素。
     */
    function addToPreloadQueue(url, element) {
        // 增加了对集合中存在性的检查
        if (isInViewport(element) && !preloadSet.has(url)) {
            preloadSet.add(url);
            preloadQueue.push({ url: url, element: element });
        }
    }

    /**
     * 将二进制大对象(blob)转换为Base64编码的字符串。
     *
     * @param {Blob} blob - 需要转换的blob对象。
     * @returns {Promise<string>} - 包含Base64编码字符串的Promise。
     */
    function blobToBase64(blob) {
        return new Promise((resolve, reject) => {
            const reader = new FileReader();
            reader.onloadend = () => resolve(reader.result);
            reader.onerror = e => reject(e);
            reader.readAsDataURL(blob);
        });
    }

    /**
     * 取消一个指定链接的预加载。
     *
     * @param {string} url - 需要取消预加载的链接URL。
     */
    function cancelPreload(url) {
        if (abortControllers[url]) {
            abortControllers[url].abort();
            delete abortControllers[url]; // 删除abortController实例的引用以防内存泄露
            console.log("Preload cancelled for link out of viewport:", url);
            currentPreloads--; // 更新计数
            preloadNext(); // 尝试开始下一个预加载
        }
        // 从预加载队列中移除链接
        preloadQueue = preloadQueue.filter(item => item.url !== url);
        preloadSet.delete(url); // 从预加载集合中移除链接
    }

    /**
     * 检查预加载的锚点链接并添加相应的视觉提醒。
     */
    function checkAndAddBulletsForPreloadedLinks() {
        var links = document.querySelectorAll('a');
        links.forEach(function(link) {
            if (link.dataset.preloaded) {
                addAVisualLinkReminder(link);
            }
        });
    }

    /**
     * 清理预加载队列,移出不符合条件的链接。
     */
    function cleanPreloadQueue() {
        // 清理已经预加载或者不在视口内的链接
        preloadQueue = preloadQueue.filter(item => {
            if (!(isInViewport(document.querySelector(`a[href="${item.url}"]`)) && !document.querySelector(`a[href="${item.url}"]`).dataset.preloaded)) {
                preloadSet.delete(item.url); // 如果不满足条件,则从集合中删除
                return false;
            }
            return true;
        });
    }

    /**
     * 清理已经超时或已经中止的AbortController实例。
     */
    function cleanAbortControllers() {
        // 获取当前时间
        var now = Date.now();

        // 遍历abortControllers对象的属性
        for (var url in abortControllers) {
            // 如果请求已经很久没有响应,那么我们认为它可能已经失效,需要删除控制器
            // 或如果请求已经被中止,亦应删除
            var controller = abortControllers[url];
            if ((controller.timestamp && now - controller.timestamp > 30000) || controller.signal.aborted) { // 30秒或已中止
                delete abortControllers[url];
            }
        }
    }

    /**
     * 防抖函数,用于延迟执行并防止函数在短时间内多次触发。
     *
     * @param {Function} func - 需要防抖的函数。
     * @param {number} wait - 延迟执行的时间,单位为毫秒。
     * @param {boolean} immediate - 是否立即执行。
     * @returns 防抖处理后的函数。
     */
    function debounce(func, wait, immediate) {
        var timeout, called = false;
        return function() {
            var context = this,
                args = arguments;
            var later = function() {
                timeout = null;
                if (!immediate && !called) func.apply(context, args);
                called = false; // 重置调用标志
            };
            var callNow = immediate && !timeout;
            if (callNow) {
                func.apply(context, args);
                called = true; // 立即执行时,设置调用标志
            }
            clearTimeout(timeout);
            timeout = setTimeout(later, wait);
        };
    }

    /**
     * 从IndexedDB数据库中删除旧内容。
     */
    function deleteOldContentFromDB() {
        const now = Date.now();
        const transaction = db.transaction([dbStoreName], 'readwrite');
        const store = transaction.objectStore(dbStoreName);

        var contentRequest = store.getAll();

        contentRequest.onsuccess = function() {
            var contents = contentRequest.result;
            // 如有必要,根据最后访问时间进行排序
            contents.sort((a, b) => b.timestamp - a.timestamp);

            // 判断记录是否超出最大存储量或者是否过期,然后执行删除
            contents.forEach((content, index) => {
                if (now - content.timestamp > dataCleanupInterval || index >= maxStorageItems) { // 检查每一项是否过期或超出容量限制
                    store.delete(content.url);
                }
            });
        };

        contentRequest.onerror = function(event) {
            console.error("Error fetching contents from IndexedDB", event.target.error);
        };
    }

    /**
     * 显示预加载的内容。
     *
     * @param {string} base64Content - 预加载内容的Base64编码。
     * @param {string} url - 内容对应的链接地址。
     */
    function displayPreloadedContent(base64Content, url) {
        if (base64Content.startsWith('data:')) {
            var binary = atob(base64Content.split(',')[1]);
            var array = new Uint8Array(binary.length);
            for (var i = 0; i < binary.length; i++) {
                array[i] = binary.charCodeAt(i);
            }
            var documentEncoding = document.characterSet || 'UTF-8';
            var blobContent = new Blob([array], { type: `text/html;charset=${documentEncoding}` });

            var reader = new FileReader();
            reader.onload = function() {
                var existingFullPageDiv = document.getElementById('fullPageDiv');
                if (existingFullPageDiv) {
                    existingFullPageDiv.parentNode.removeChild(existingFullPageDiv);
                    existingFullPageDiv.remove();
                }

                var fullPageDiv = document.createElement('div');
                fullPageDiv.id = 'fullPageDiv';
                fullPageDiv.style.cssText = `
                    position: fixed;
                    top: 0;
                    left: 0;
                    width: 100%;
                    height: 100%;
                    overflow: auto;
                    z-index: 1000;
                    background: white;
                `;
                fullPageDiv.innerHTML = reader.result;
                toggleDragIconVisibility(true);
                document.body.style.overflow = 'hidden';
                document.body.appendChild(fullPageDiv);
                if (GM_getValue('asynchronousResources')) {
                    var iframe = document.createElement('iframe');
                    iframe.style.cssText = ' top: 0; left: 0; width: 100%; height: 100%; display: block; visibility: hidden;';
                    iframe.src = url;
                    document.body.appendChild(iframe);

                    fullPageDiv.onscroll = function() {
                        if (iframe.contentWindow) {
                            iframe.contentWindow.scrollTo(0, fullPageDiv.scrollY);
                            iframe.contentWindow.scrollTo(0, fullPageDiv.scrollTop);
                        }
                    };

                    iframe.onload = function() {
                        iframe.contentWindow.onscroll = function() {
                            var iframeDocument = iframe.contentDocument || iframe.contentWindow.document;
                            fullPageDiv.innerHTML = iframeDocument.documentElement.outerHTML; // 更新内容
                        };
                    }
                }
            };
            reader.readAsText(blobContent, documentEncoding);
        }
    }


    /**
     * 初始化IndexedDB数据库。
     *
     * @param {Function} success - 数据库就绪后执行的回调函数。
     */
    function initDB(success) {
        if (!dbReady) {
            openDB(success);
        } else if (typeof success === 'function') {
            success();
        }
    }

    /**
     * 判断一个元素是否在视口内。
     *
     * @param {HTMLElement} element - 需要判断的HTML元素。
     * @returns {boolean} - 元素是否在视口内。
     */
    function isInViewport(element) {
        var rect = element.getBoundingClientRect();
        var inViewport = (
            rect.top >= 0 &&
            rect.left >= 0 &&
            rect.bottom <= (window.innerHeight || document.documentElement.clientHeight) &&
            rect.right <= (window.innerWidth || document.documentElement.clientWidth)
        );

        if (!inViewport && element.dataset.preloaded) {
            cancelPreload(element.href); // 如果链接不在视窗中并且已被标记为预加载,取消它的预加载
            element.dataset.preloaded = false; // 移除预加载标记
        }

        return inViewport;
    }

    /**
     * 判断当前设备是否为移动设备。
     *
     * @returns {boolean} - 是否为移动设备。
     */
    function isMobileDevice() {
        return /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent);
    }

    /**
     * 使用MutationObserver监听DOM变化。
     */
    function observeDOMChanges() {
        var handledLinks = new Set(); // 用于储存处理过的链接

        var config = { childList: true, subtree: true };
        var callback = function(mutationsList, observer) {
            requestAnimationFrame(function() {
                mutationsList.forEach(debounce(function(mutation) {
                    if (mutation.type == 'childList' && mutation.addedNodes.length) {
                        mutation.addedNodes.forEach(function(node) {
                            if (node.nodeType === 1 && node.matches('a[href]')) {
                                var href = node.getAttribute('href');
                                if (!preloadSet.has(href) && !handledLinks.has(href)) {
                                    preloadLink(href, node);
                                    handledLinks.add(href); // 将链接添加到 handledLinks 中进行标记
                                    preloadSet.add(href); // 将链接添加到 preloadSet 中
                                }
                            }
                        });
                    }
                }, 250));
                preloadVisibleLinks();
            });
        };

        var observer = new MutationObserver(callback);
        observer.observe(document.body, config);
    }

    /**
     * 打开IndexedDB数据库。
     *
     * @param {Function} callback - 数据库打开成功的回调函数。
     */
    function openDB(callback) {
        if (dbInitializationPromise) { // 如果存在初始化的Promise,直接返回它并添加回调
            dbInitializationPromise.then(callback).catch(err => console.error('IndexedDB init error:', err));
            return;
        }

        // 新建一个Promise来处理初始化过程
        dbInitializationPromise = new Promise((resolve, reject) => {
            var request = indexedDB.open(dbName, dbVersion);

            request.onupgradeneeded = function(event) {
                var db = event.target.result;
                if (!db.objectStoreNames.contains(dbStoreName)) {
                    db.createObjectStore(dbStoreName, { keyPath: 'url' });
                }
            };

            request.onsuccess = function(event) {
                db = event.target.result;
                dbReady = true;
                console.log('IndexedDB database opened successfully');
                db.onerror = function(event) {
                    console.error("Database error: " + event.target.error.message);
                };
                resolve(db);
            };

            request.onerror = function(event) {
                console.error('IndexedDB database open error:', event.target.errorCode);
                dbInitializationPromise = null; // 如果Promise失败,我们重置这个变量
                reject(event.target.error);
            };
        });

        // 调用传入的回调函数
        dbInitializationPromise.then(callback).catch(err => console.error('IndexedDB init error:', err));
    }

    /**
     * 将一个链接的属性值视为适当。
     *
     * @param {string} url - 链接的URL地址。
     * @returns {string} - 适当的属性值。
     */
    function appropriateAsAttributeValue(url) {
        if (url.endsWith('.css')) {
            return 'style';
        } else if (url.endsWith('.js')) {
            return 'script';
        } else if (url.match(/(.jpg|.jpeg|.png|.gif)$/)) {
            return 'image';
        } else if (url.endsWith('.json')) {
            return 'fetch';
        } else {
            return 'fetch';
        }
    }

    /**
     * 预加载指定的链接。
     *
     * @param {string} url - 需要预加载的链接URL。
     * @param {HTMLElement} element - 对应的链接元素。
     */
    function preloadLink(url, element) {
        try {
            var linkURL = new URL(url);

            if (linkURL.protocol !== 'http:' && linkURL.protocol !== 'https:') {
                console.log('Not preloading: Non-HTTP link:', url);
                return;
            }
            if (isBlacklistModeEnabled && blacklistDomains.includes(linkURL.hostname)) {
                console.log('Not preloading: Blacklisted domain:', linkURL.hostname);
                return;
            }
            // 跳过与当前页面相同或者跨域的URL
            if (linkURL.hostname !== window.location.hostname || linkURL.href === window.location.href) {
                console.warn('Not preloading: Same page or cross-origin link:', url);
                return;
            }
            if (preloadSet.has(url) || element.dataset.preloaded) {
                console.log('Not preloading: Already preloaded or enqueued for preload:', url);
                return;
            }

            if (currentPreloads < maxConcurrentPreloads) {
                currentPreloads++;
                let options = {
                    cache: "force-cache", // 使用force-cache可以帮助减少不必要的网络请求
                    as: appropriateAsAttributeValue(url), // 根据不同的链接类型,为 'as' 属性设置适当的值
                    credentials: "include",
                    headers: new Headers(window.headers)
                };

                if (element.rel && (element.rel.includes('noreferrer') || element.rel.includes('noopener'))) {
                    options.referrerPolicy = 'no-referrer';
                }

                // 创建一个新的abortController实例,并将signal传给fetch
                var controller = new AbortController();
                controller.timestamp = Date.now();
                var signal = controller.signal;
                options.signal = signal; // 将signal添加到fetch选项中
                abortControllers[url] = controller;

                fetch(linkURL.href, options).then(function(response) {
                    if (!response.ok) {
                        throw new Error('HTTP error, status = ' + response.status);
                    }
                    return response.blob();
                }).then(function(blob) {
                    saveContentToDB(url, blob);
                    addAVisualLinkReminder(element);
                }).catch(function(error) {
                    console.error('Preload failed for ', url, ':', error.message);
                }).finally(function() {
                    currentPreloads--;
                    preloadNext();
                    delete abortControllers[url];
                });
            } else {
                addToPreloadQueue(url, element);
                return;
            }
        } catch (e) {
            console.error('Error preloading link:', e.message);
        }
    }

    /**
     * 继续预加载队列中的下一个链接。
     */
    function preloadNext() {
        if (preloadQueue.length > 0 && currentPreloads < maxConcurrentPreloads) {
            var nextPreload = preloadQueue.shift();
            preloadLink(nextPreload.url, nextPreload.element);
            delete abortControllers[nextPreload.url];
        }
    }

    /**
     * 预加载所有可见的链接。
     */
    function preloadVisibleLinks() {
        if (!isMobileDevice()) {
            return;
        }
        var links = document.querySelectorAll('a');

        var visibleLinks = Array.from(links).filter(function(link) {
            var href = link.href;
            return isInViewport(link) && !link.dataset.preloaded && (shouldPreloadMapping[href] !== false);
        });

        visibleLinks.sort(function(a, b) {
            var aRect = a.getBoundingClientRect();
            var bRect = b.getBoundingClientRect();
            return (window.innerHeight - aRect.bottom) - (window.innerHeight - bRect.bottom);
        });

        var preloadLimit = Math.min(visibleLinks.length, maxConcurrentPreloads - currentPreloads);

        for (var i = 0; i < preloadLimit; i++) {
            (function(linkElement) {
                var href = linkElement.href;
                if (shouldPreloadMapping[href] === undefined) {
                    // 如果该链接的预加载状态尚未决定,则发起检查
                    shouldPreload(linkElement.href).then(function(should) {
                        shouldPreloadMapping[href] = should;
                        if (should && isInViewport(linkElement)) {
                            preloadLink(linkElement.href, linkElement);
                            linkElement.dataset.preloaded = true;
                        }
                    });
                } else if (shouldPreloadMapping[href]) {
                    // 如果已经确定需要预加载,则直接预加载,无需重复检查
                    preloadLink(linkElement.href, linkElement);
                    linkElement.dataset.preloaded = true;
                }
            })(visibleLinks[i]);
        }
    }

    /**
     * 处理数据库写入队列。
     */
    function processDBWriteQueue() {
        if (dbWriteInProgress || dbWriteQueue.length === 0) {
            return;
        }

        dbWriteInProgress = true;
        var item = dbWriteQueue.shift();

        blobToBase64(item.blob).then(base64data => {
            var transaction = db.transaction([dbStoreName], 'readwrite');
            var objectStore = transaction.objectStore(dbStoreName);

            // 处理事务完成
            return new Promise((resolve, reject) => {
                var request = objectStore.put({ url: item.url, htmlContent: base64data, timestamp: Date.now() });
                request.onsuccess = () => resolve();
                request.onerror = () => reject(request.error);
            });
        }).then(() => {
            console.log('Page content saved to IndexedDB for', item.url);
            dbWriteInProgress = false;
            processDBWriteQueue(); // 递归处理队列中的下一项
        }).catch(error => {
            console.error('IndexedDB save operation failed for', item.url, error);
            dbWriteQueue.unshift(item); // 发生错误时重新将项目放入队列
            dbWriteInProgress = false;
            setTimeout(processDBWriteQueue, 1000); // 延迟重试
        });
    }

    /**
     * 从数据库中读取内容。
     *
     * @param {string} url - 内容的URL。
     * @param {Function} callback - 读取到内容后的回调函数。
     */
    function readContentFromDB(url, callback) {
        var transaction = db.transaction([dbStoreName], 'readonly');
        var objectStore = transaction.objectStore(dbStoreName);
        var request = objectStore.get(url);

        request.onsuccess = function(event) {
            callback(event.target.result);
        };

        request.onerror = function(event) {
            console.error('IndexedDB read failed for', url);
            callback(null);
        };
    }

    /**
     * 将内容保存到IndexedDB数据库中。
     *
     * @param {string} url - 内容的URL。
     * @param {Blob} blob - 包含要保存内容的Blob对象。
     */
    function saveContentToDB(url, blob) {
        if (!dbReady) {
            console.error('IndexedDB is not ready for writing data.');
            return;
        }

        if (blob.size > maxContentSize) {
            console.log('Content size exceeds the maxContentSize limit. Not saving to IndexedDB');
            return;
        }

        dbWriteQueue.push({ url, blob });

        if (!dbWriteInProgress) {
            processDBWriteQueue();
        }
    }


    /**
     * 安排下一次数据库内容清理。
     */
    function scheduleNextCleanup() {
        // 删除旧内容后,再次调用此函数以依据当前间隔设定继续调度
        setTimeout(function() {
            deleteOldContentFromDB();
            scheduleNextCleanup();
        }, dataCleanupInterval);
    }

    /**
     * 设置鼠标悬停预加载行为。
     */
    function setupMouseHoverPreload() {
        document.addEventListener('mouseover', function(event) {
            var target = event.target.closest('a');
            if (target && !target.dataset.preloaded) {

                // 判断链接是否指向图片,如果是,就不进行预加载处理
                var href = target.getAttribute('href');

                // 更新正则表达式来匹配 Greasy Fork 的特定图片链接模式
                if (href.match(/\.(jpeg|jpg|gif|png|webp)$/i) ||
                    href.includes("active_storage/blobs/redirect")) {
                    console.log('Skip preloading for image link', href);
                    return; // 如果链接指向图片,直接返回,不设置预加载
                }

                // 鼠标悬停65毫秒以上就启动预加载
                target.dataset.hoverTimeout = setTimeout(function() {
                    shouldPreload(target.href).then(function(shouldPreloadResult) {
                        if (shouldPreloadResult && !target.dataset.preloaded) {
                            preloadLink(target.href, target);
                            target.dataset.preloaded = true; // 设置链接已预加载
                            addAVisualLinkReminder(target); // 添加小圆球指示器
                        }
                    });
                }, 65);
            }
        });

        document.addEventListener('mouseout', function(event) {
            var target = event.target.closest('a');
            if (target && target.dataset.hoverTimeout) {
                // 当鼠标移开时清除定时器
                clearTimeout(target.dataset.hoverTimeout);
                target.dataset.hoverTimeout = null;
            }
        });
    }

    /**
     * 判断一个链接是否应该被预加载。
     *
     * @param {string} url - 需要判断的链接URL。
     * @returns {Promise<boolean>} - 是否应该预加载该链接。
     */
    function shouldPreload(url) {
        if (!(url instanceof URL)) {
            var linkURL = new URL(url);
        }

        if (signoutLinks.some(link => linkURL.pathname.includes(link))) {
            console.log('Not preloading: Signout link:', url);
            return Promise.resolve(false);
        }

        var domain = new URL(url).hostname;

        if (isWhitelistModeEnabled && !whitelistDomains.includes(domain)) {
            return Promise.resolve(false);
        }

        if (isBlacklistModeEnabled && blacklistDomains.includes(domain)) {
            return Promise.resolve(false);
        }
        return fetch(url, { method: 'GET', mode: 'no-cors' })
            .then(function(response) {
                return response.text();
            })
            .then(function(html) {
                // 检查页面是否包含跳转脚本
                var redirectRegex = /window\.location\.href\s*=\s*['"]([^'"]+)['"]/;
                var match = redirectRegex.exec(html);
                if (match && match[1]) {
                    // 页面有跳转,打印消息并返回 false
                    console.log('The page has a redirect script. Skipping preload for:', url);
                    return false;
                }
                // 页面没有跳转,返回 true
                return true;
            })
            .catch(function(error) {
                console.error('Error fetching page for preload check:', error);
                return false;
            });
    }

    /**
     * 切换可拖动图标的显示状态。
     *
     * @param {boolean} show - 是否显示图标。
     */
    function toggleDragIconVisibility(show) {
        var dragIcon = document.getElementById('draggableIcon');
        if (dragIcon) {
            dragIcon.style.display = show ? 'block' : 'none';
        }
    }

    /**
     * 开始预加载链接。
     */
    function startLinkPreloading() {
        initDB(preloadVisibleLinks);
    }

    /**
     * 处理回退导航。
     */
    function handleBackNavigation() {
        if (currentPreviewIndex > 0) {
            currentPreviewIndex -= 1;
            var prevURL = clickedLinks[currentPreviewIndex];

            readContentFromDB(prevURL, function(data) {
                if (data) {
                    displayPreloadedContent(data.htmlContent, prevURL);
                } else {
                    location.href = prevURL;
                }
            });
        } else {
            var fullPageDiv = document.getElementById('fullPageDiv');

            if (fullPageDiv) {
                fullPageDiv.remove();
                toggleDragIconVisibility(false);
                document.body.style.overflow = '';
            }

            clickedLinks = [];
            currentPreviewIndex = -1;
        }
    }

    /**
     * 处理前进导航。
     */
    function handleForwardNavigation() {
        if (currentPreviewIndex < clickedLinks.length - 1) {
            currentPreviewIndex += 1;
            var nextURL = clickedLinks[currentPreviewIndex];

            readContentFromDB(nextURL, function(data) {
                if (data) {
                    displayPreloadedContent(data.htmlContent, nextURL);
                } else {
                    location.href = nextURL;
                }
            });
        }
    }

    /**
     * 导航到URL。
     */
    function navigateToURL() {
        if (clickedLinks.length > 0 && currentPreviewIndex >= 0) {
            var currentURL = clickedLinks[currentPreviewIndex];
            window.location.href = currentURL;
        }
    }

    /*-------------以下为设置面板的具体代码初始化代码-------------*/

    initializeDefaultSettings();
    checkForUpdates();
    var indexedDB = window.indexedDB || window.mozIndexedDB || window.webkitIndexedDB || window.msIndexedDB;
    var dbVersion = 1;
    var dbName = 'preloadedPagesDB';
    var dbStoreName = 'preloadedPages';

    var maxConcurrentPreloads = GM_getValue('concurrentLoadingNumber', 5);
    var dataCleanupInterval = GM_getValue('dataCleanupInterval', 1) * 3600000;
    var maxContentSize = GM_getValue('maxContentSize', 5) * 1024 * 1024;
    var maxStorageItems = GM_getValue('maxStorageItems', 100);
    var isWhitelistModeEnabled = GM_getValue('whiteSelector', false);
    var isBlacklistModeEnabled = GM_getValue('blackSelector', true);
    var defaultBlacklistDomains = [
        'www.bilibili.com',
        'www.bing.com',
        'www.huya.com',
        'www.vimeo.com',
        'www.tiktok.com',
        'www.twitch.tv',
        'www.youtube.com',
        'www.dailymotion.com',
        'www.liveleak.com',
        'www.metacafe.com',
        'www.youku.com',
        'www.iqiyi.com',
        'www.netflix.com',
        'www.hulu.com',
        'www.primevideo.com'
    ];
    const signoutLinks = [
        '/sign_out', // 一般的 sign out 链接
        '/logout', // 常见的登出链接
        '/signoff', // 另一个常见的退出链接
        '/signout', // 没有下划线的 signout 链接
        '/logoff', // log off 形式的退出链接
        '/exit', // exit 链接
        '/user/logout', // 用户目录下的 logout 链接
        '/account/signout', // 帐户目录下的 signout 链接
        '/users/sign_out', // 复数形式 users 的 sign out 链接
        '/session/logout', // session 目录下的 logout 链接
        '/auth/logout', // 认证目录下的 logout 链接
        '/disconnect', // disconnect 形式的退出链接
        '/member/signout', // 会员目录下的 signout 链接
        '/user/sign_out', // 单个用户的 sign out 链接
        '/users/logout', // 复数形式 users 的 logout 链接
        '/sessions/signout', // sessions 目录下的 signout 链接
        '/api/logout', // API 目录下的 logout 链接
        '/app/logout', // APP 目录下的 logout 链接
        '/dashboard/logout', // 仪表盘目录下的 logout 链接
        '/home/logout', // 主页目录下的 logout 链接
        '/profile/logout', // 个人资料目录下的 logout 链接
        '/log_out', // 带下划线的 log out 链接
        '/signoff_user', // 带下划线的 sign off user 链接
    ];

    if (typeof GM_getValue === 'function') {
        var storedBlacklistDomains = GM_getValue('blacklistDomains', []);
        var blacklistDomains = [...new Set([...storedBlacklistDomains, ...defaultBlacklistDomains])]; //将检索到的黑名单与默认黑名单合并,确保没有重复项
        GM_setValue('blacklistDomains', blacklistDomains);

        var whitelistDomains = GM_getValue('whitelistDomains', []);
    }

    function updateDomainLists() {
        blacklistDomains = GM_getValue('blacklistDomains', []);
        whitelistDomains = GM_getValue('whitelistDomains', []);
    }

    var currentPreloads = 0;
    var preloadQueue = [];
    var preloadSet = new Set();
    var abortControllers = {};
    var db;
    var dbReady = false;
    var clickedLinks = [];
    var currentPreviewIndex = -1;
    var dbWriteQueue = [];
    var dbWriteInProgress = false;
    var shouldPreloadMapping = {};
    let touchStartX = 0;
    let touchStartY = 0;
    let iconVisible = false;
    const svgBack = '<svg id="sliderBIcon" style="position: fixed; top: 50%; left: 100%; transform: translateY(-50%); cursor: pointer; z-index: 9999999;" width="100" height="50" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M14.53 7.53a.75.75 0 0 0-1.06-1.06l-5 5a.75.75 0 0 0 0 1.06l5 5a.75.75 0 1 0 1.06-1.06L10.06 12l4.47-4.47Z"/><path fill-rule="evenodd" d="M12 1.25C6.063 1.25 1.25 6.063 1.25 12S6.063 22.75 12 22.75 22.75 17.937 22.75 12 17.937 1.25 12 1.25ZM2.75 12a9.25 9.25 0 1 1 18.5 0 9.25 9.25 0 0 1-18.5 0Z"/></svg>';
    const svgForward = '<svg id="sliderFIcon" style="position: fixed; top: 50%; right: 100%; transform: translateY(-50%); cursor: pointer; z-index: 9999999;" width="100" height="50" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M10.53 6.47a.75.75 0 1 0-1.06 1.06L13.94 12l-4.47 4.47a.75.75 0 1 0 1.06 1.06l5-5a.75.75 0 0 0 0-1.06l-5-5Z"/><path fill-rule="evenodd" d="M12 1.25C6.063 1.25 1.25 6.063 1.25 12S6.063 22.75 12 22.75 22.75 17.937 22.75 12 17.937 1.25 12 1.25ZM2.75 12a9.25 9.25 0 1 1 18.5 0 9.25 9.25 0 0 1-18.5 0Z"/></svg>';
    const divBack = document.createElement('div');
    const divForward = document.createElement('div');
    divBack.innerHTML = svgBack;
    divForward.innerHTML = svgForward;
    document.body.appendChild(divBack);
    document.body.appendChild(divForward);
    var dbInitializationPromise = null;

    let currentActivePanelId = 'panel1';
    let isAnimating = false;
    let loadingPanel = createElementWithStylesAndAttributes('div', { position: "fixed", width: "305px", height: "auto", top: "50%", left: "50%", transform: "translate(-50%, -50%)", zIndex: "1001", backgroundColor: "#E0E5EC", borderRadius: "15px", boxShadow: "2px 2px 8px #BECBD8, -2px -2px 8px #FFFFFF", display: "none", flexDirection: "column" }, { className: 'loadingPanel customFontStyle' });
    let showcaseFeaturesPanel = createElementWithStylesAndAttributes('div', { position: "relative", width: "275px", height: "300px", borderRadius: "15px", display: "flex", alignItems: "center", justifyContent: "center", margin: "10px auto", overflowY: "hidden", overflowX: "hidden", flexWrap: "wrap", background: "#E0E5EC", boxShadow: "inset 9px 9px 16px #BABEC6, inset -9px -9px 16px #FFFFFF" }, { className: "showcaseFeaturesPanel" });
    const versionInfoElement = createVersionInfoElement();
    let font_style = `.customFontStyle *:not([class*='icon']):not(.fa):not(.fas):not(i) { font-family: 'PingFang SC', 'Heiti SC', 'myfont', 'Microsoft YaHei', 'Source Han Sans SC', 'Noto Sans CJK SC', 'HanHei SC', 'sans-serif' ,'icomoon','Icons' ,'brand-icons' ,'FontAwesome','Material Icons','Material Icons Extended','Glyphicons Halflings' !important; text-shadow: 1px 1px 10px #c3c3c3 !important; font-weight: bold !important; }`;
    const parameterFunction = [
        "并发加载数,numberPicker,concurrentLoadingNumber,information,⑴设计原则: 限制同时加载的页面数量,防止某些网页限制了并发数网站限制如:吾爱破解论坛。\n⑵功能: 应对网页限制策略",
        "最大内存项,numberPicker,maxContentSize,information,单位:(MB)\n⑴设计原则: 防止单个预加载页面占用过多内存资源,避免浏览器崩溃或响应缓慢。\n⑵功能: 允许用户设定每个页面预加载内容的内存使用上限,优化资源管理。",
        "最大储存项,numberPicker,maxStorageItems,information,⑴设计原则: 限制缓存预加载内容的数量,以防数据库溢出或过度占用存储空间。\n⑵功能: 用户可自定义预加载内容储存数量上限,以维护存储空间的有效利用。",
        "加载完样式,selector,loadedStyle,information,开关关闭则无提示样式\n⑴设计原则: 增强用户界面友好性,通过视觉反馈让用户明确知晓哪些内容已经被预加载。\n⑵功能: 提供多种可选样式(如下划线、高亮等),用户可以根据个人偏好设置预加载成功后元素的显示方式。,styleSelector,is_loadedStyle",
        "黑名单列表,inputBox,blacklistDomains,information,⑴设计原则: 考虑到不同网页对动态内容加载的特殊要求,通过设定黑名单避免兼容性问题。\n⑵功能: 用户可以指定脚本不适用的网页域名,防止在这些网页上执行可能导致冲突的操作。,styleSelector,blackSelector",
        "白名单列表,inputBox,whitelistDomains,information,⑴设计原则: 为了专注资源和优化特定网站的加载速度,通过白名单机制确保仅在指定域名上启用功能。\n⑵功能: 用户可设定脚本只在特定的网站或页面上运行,从而提高脚本的运行效率和兼容性。,styleSelector,whiteSelector",
    ];

    const additionalFeaturesFunction = [
        "清理间隔项,numberPicker,dataCleanupInterval,information,单位:(小时)\n⑴设计原则: 通过定期清理过期或不常用的缓存数据,减少对存储资源的占用率,防止存储溢出和数据膨胀。⑵功能: 网页长时间不用则自动清理内存缓存,节省存储空间。",
        "异步の资源,switch,asynchronousResources,information,建议电脑开启\n⑴设计原则: 对于异步加载的资源进行实时更新,比如:动态加载的图片等。\n⑵功能: 在本模式下,可以加载出一些异步资源,如果你关闭,那么久不会异步加载资源,但是加载会更流畅。",
        "图片懒加载,switch,lazyLoadImages,information,未完善状态,由于效果并不是特别明显,暂且搁置\n⑴设计原则: 一种提高网页加载速度的技术,通过延迟加载图片,只加载当前可见区域的图片,提高页面加载速度。\n⑵功能: 当用户滚动页面时,提前加载屏幕外一个屏幕距离的图片,提升页面整体加载速度。",
        "重定向优化,switch,redirectOptimization,information,⑴设计原则: 无疑重定向链接是重要的,但它有很多问题如:SEO影响、性能影响、重定循环(恶意钓鱼)等。\n⑵基于此,本选项提供删除重定向的功能,默认的重定向参数已经涵盖95%的重定向链接,你可以快捷方便地自己添加参数,settingButton",
        "监控器刷新,numberPicker,monitorRefresh,information,单位:(秒)\n下方性能监控器点击可切换监控内容\n⑴设计原则: 决定下方的网页性能监控的刷新间隔,保证性能\n⑵功能: 设定刷新监控的间隔时间"
    ];

    const shortcutKeysFunction = [
        "跳转对应页,shortcutKeySetting,goToTheCorrespondingPage",
        "返回上一页,shortcutKeySetting,backToThePreviousPage",
        "设置快捷键,shortcutKeySetting,setShortcuts",
        "前进快捷键,shortcutKeySetting,forward",
        "手势指示器,switch,mobileGestures,information,⑴移动端手势:本插件提供便捷操作方式,如左向右滑动后退,右向左滑动前进。且会显示一个指示器,关闭此选项后,手势操作仍然有效,但不再显示指示器占用屏幕空间",
        "启用操作球,switch,manipulatorBall,information,操作球显示在屏幕右方且仅在预加载页面显示。\n⑴手机用户默认开启手势\n⑵电脑用户默认启用操作球"
    ];

    const optionsArray = ['下划线', '无样式', '高亮', '品红', '加粗', '边框'];
    const title = createElementWithStylesAndAttributes('h1', { color: "#4B5563", textAlign: "center", marginBottom: "10px", marginTop: "10px", fontSize: "24px", fontWeight: "bold", textShadow: "2px 2px 3px rgba(0, 0, 0, 0.2)", userSelect: "none" }, { className: 'title', innerText: '网页瞬间加载' });
    const closeSetting = createElementWithStylesAndAttributes('span', { cursor: 'pointer', marginLeft: '30px', width: '11px', height: '11px', display: 'inline-block', verticalAlign: 'middle' }, { innerHTML: `<svg xmlns="http://www.w3.org/2000/svg" height="1em" fill="currentColor" viewBox="0 0 334 334"><path d="M 320 48 Q 334 31 320 14 Q 303 0 286 14 L 167 133 L 48 14 Q 31 0 14 14 Q 0 31 14 48 L 133 167 L 14 286 Q 0 303 14 320 Q 31 334 48 320 L 167 201 L 286 320 Q 303 334 320 320 Q 334 303 320 286 L 201 167 L 320 48 L 320 48 Z" /></svg>` });
    const settingsParameters = createElementWithStylesAndAttributes('div', { color: "#4B5563", textAlign: "center", marginBottom: "10px", fontSize: "24px", textShadow: "1px 1px #888888", fontWeight: "bold", cursor: "pointer", userSelect: "none" }, { className: 'settingsParameters', innerText: '参数' });
    const additionalFeatures = createElementWithStylesAndAttributes('div', { color: "#4B5563", textAlign: "center", marginBottom: "10px", fontSize: "20px", fontWeight: "bold", cursor: "pointer", userSelect: "none" }, { className: 'additionalFeatures', innerText: '高级' });
    const shortcutKeys = createElementWithStylesAndAttributes('div', { color: "#4B5563", textAlign: "center", marginBottom: "10px", fontSize: "20px", fontWeight: "bold", cursor: "pointer", userSelect: "none" }, { className: 'shortcutKeys', innerText: '操作' });
    const selectTheContainer = createElementWithStylesAndAttributes('div', { display: "flex", justifyContent: "space-around" }, {});
    const showcaseFeaturesPanel1 = createShowcaseFeaturesPanel('panel1', 0);
    const showcaseFeaturesPanel2 = createShowcaseFeaturesPanel('panel2', 280);
    const showcaseFeaturesPanel3 = createShowcaseFeaturesPanel('panel3', 560);

    createFeatureListItems(parameterFunction).forEach(featureElement => {
        showcaseFeaturesPanel1.appendChild(featureElement);
    });
    createFeatureListItems(additionalFeaturesFunction).forEach(featureElement => {
        showcaseFeaturesPanel2.appendChild(featureElement);
    });
    createFeatureListItems(shortcutKeysFunction).forEach(featureElement => {
        showcaseFeaturesPanel3.appendChild(featureElement);
    });

    settingsParameters.addEventListener('click', () => setActivePanel('panel1'));
    additionalFeatures.addEventListener('click', () => setActivePanel('panel2'));
    shortcutKeys.addEventListener('click', () => setActivePanel('panel3'));
    closeSetting.addEventListener('click', () => { loadingPanel.style.display = 'none'; });

    addStyle('custom-font-style', font_style);

    var stats = new Stats();
    stats.dom.style.cssText = 'position: absolute; display: block; bottom: 10px; left: 10px; ';
    showcaseFeaturesPanel2.appendChild(stats.dom);
    stats.showPanel(0);


    settingsParameters.addEventListener('click', () => setActivePanel('panel1'));
    additionalFeatures.addEventListener('click', () => setActivePanel('panel2'));
    shortcutKeys.addEventListener('click', () => setActivePanel('panel3'));
    loadingPanel.appendChild(title);
    title.appendChild(closeSetting);
    selectTheContainer.appendChild(settingsParameters);
    selectTheContainer.appendChild(additionalFeatures);
    selectTheContainer.appendChild(shortcutKeys);
    loadingPanel.appendChild(selectTheContainer);
    loadingPanel.appendChild(showcaseFeaturesPanel);
    loadingPanel.appendChild(versionInfoElement);
    showcaseFeaturesPanel.appendChild(showcaseFeaturesPanel1);
    showcaseFeaturesPanel.appendChild(showcaseFeaturesPanel2);
    showcaseFeaturesPanel.appendChild(showcaseFeaturesPanel3);
    document.body.appendChild(loadingPanel);


    GM_registerMenuCommand('显示/隐藏 参数与功能设置菜单', function() {
        loadingPanel.style.display = loadingPanel.style.display === 'none' ? 'block' : 'none';
    });
    animate();


    document.addEventListener('touchstart', function(e) {
        touchStartX = e.changedTouches[0].screenX;
        touchStartY = e.changedTouches[0].screenY;
    });

    if (GM_getValue('mobileGestures', true)) {
        document.addEventListener('touchmove', function(e) {
            let touchMoveX = e.changedTouches[0].screenX;
            let touchMoveY = e.changedTouches[0].screenY;
            let moveRightDistance = touchMoveX - touchStartX;
            let moveLeftDistance = touchStartX - touchMoveX;
            let moveYDistance = Math.abs(touchMoveY - touchStartY);
            if (moveYDistance > 100) {
                iconVisible = false;
                divForward.firstChild.style.right = '100%';
                divBack.firstChild.style.left = '100%';
                return;
            }
            if (moveRightDistance > 50 && !iconVisible) {
                iconVisible = true;
                divBack.firstChild.style.left = '-20px';
            } else if (moveRightDistance <= 50 && iconVisible) {
                iconVisible = false;
                divBack.firstChild.style.left = '100%';
            }
            if (iconVisible && moveRightDistance <= 100) {
                divBack.firstChild.style.left = `${0.8 * (moveRightDistance - 50)}px`;
            } else if (moveRightDistance > 100) {
                divBack.firstChild.style.left = '-20px';
            }

            if (moveLeftDistance > 50 && !iconVisible) {
                iconVisible = true;
                divForward.firstChild.style.right = '-20px';
            } else if (moveLeftDistance <= 50 && iconVisible) {
                iconVisible = false;
                divForward.firstChild.style.right = '100%';
            }
            if (iconVisible && moveLeftDistance <= 100) {
                divForward.firstChild.style.right = `${0.8 * (moveLeftDistance - 50)}px`;
            } else if (moveLeftDistance > 100) {
                divForward.firstChild.style.right = '-20px';
            }
        });
    }

    document.addEventListener('touchend', function(e) {
        let touchEndX = e.changedTouches[0].screenX;
        let touchEndY = e.changedTouches[0].screenY;
        let touchDistance = touchEndX - touchStartX;
        let touchYDistance = Math.abs(touchEndY - touchStartY);

        if (touchYDistance > 100) {
            return;
        }
        if (touchDistance > 150) {
            handleBackNavigation();
        }
        if (touchDistance < -150) {
            handleForwardNavigation();
        }

        iconVisible = false;
        divBack.firstChild.style.left = '100%';
        divForward.firstChild.style.right = '100%';
    });

    document.addEventListener('keydown', function(e) {
        var returnShortcutKeyString = GM_getValue('backToThePreviousPage', 'shift+r').toLowerCase();
        var returnShortcutKeys = returnShortcutKeyString.split('+').map(key => key.toLowerCase());

        var directShortcutKeyString = GM_getValue('goToTheCorrespondingPage', 'shift+e').toLowerCase();
        var directShortcutKeys = directShortcutKeyString.split('+').map(key => key.toLowerCase());

        var forwardShortcutKey = GM_getValue('forward', 'shift+f').toLowerCase();
        var forwardShortcutKeys = forwardShortcutKey.split('+').map(key => key.toLowerCase());
        var loadingShortcutKey = GM_getValue('setShortcuts', 'shift+s').toLowerCase();
        var loadingShortcutKeys = loadingShortcutKey.split('+').map(key => key.toLowerCase());
        var keyPressed = {
            'alt': e.altKey,
            'shift': e.shiftKey,
            'control': e.ctrlKey,
            'meta': e.metaKey // 对于 Mac 的 Command 键
        };
        keyPressed[e.key.toLowerCase()] = true;

        var returnKeysPressed = returnShortcutKeys.every(key => keyPressed[key]);
        var directKeysPressed = directShortcutKeys.every(key => keyPressed[key]);
        var forwardKeysPressed = forwardShortcutKeys.every(key => keyPressed[key]);
        var loadingKeysPressed = loadingShortcutKeys.every(key => keyPressed[key]);
        if (returnKeysPressed) {
            handleBackNavigation(); // 对应的操作函数
        }
        if (directKeysPressed) {
            navigateToURL(); // 对应的操作函数
        }
        if (forwardKeysPressed) {
            handleForwardNavigation(); // 对应的操作函数
        }
        if (loadingKeysPressed) {
            loadingPanel.style.display = loadingPanel.style.display === 'none' ? 'block' : 'none';
        }
    });

    var debouncedScrollHandler = debounce(function() {
        cleanPreloadQueue();
        cleanAbortControllers();
        preloadVisibleLinks();
        checkAndAddBulletsForPreloadedLinks();
    }, 10);

    var debouncedScrollHandlerPC = debounce(function() {
        cleanPreloadQueue();
        cleanAbortControllers();
        checkAndAddBulletsForPreloadedLinks();
    }, 10);


    document.addEventListener('click', function(event) {
        var target = event.target.closest('a');
        if (target && target.href) {
            event.preventDefault();
            if (event.ctrlKey && !event.shiftKey) {
                // 用户按下了Ctrl键并点击了链接 - 在后台新标签页中打开
                window.open(target.href);
            } else if (event.shiftKey) {
                // 用户按下了Shift键并点击了链接 - 在前台新标签页中打开
                window.open(target.href, '_blank');
            } else {
                // 正常点击 - 不打开新标签页,遵循预加载逻辑以下或直接导航到链接地址
                if (!clickedLinks.includes(target.href)) {
                    clickedLinks.push(target.href);
                }
                currentPreviewIndex = clickedLinks.indexOf(target.href);

                if (target.dataset.preloaded) {
                    readContentFromDB(target.href, function(data) {
                        if (data) {
                            displayPreloadedContent(data.htmlContent, target.href);
                        } else {
                            location.href = target.href;
                        }
                    });
                } else {
                    location.href = target.href;
                }
            }
        }
    });

    observeDOMChanges();
    openDB();
    startLinkPreloading();
    initDB(function() {
        deleteOldContentFromDB();
        scheduleNextCleanup();
    });
    if (isMobileDevice()) {
        GM_setValue('mobileGestures', false);
        window.addEventListener('touchend', debouncedScrollHandler);
        if (GM_getValue('manipulatorBall')) {
            addDraggableIcon();
            document.getElementById('draggableIcon').onclick = handleBackNavigation;
        }
    } else {
        window.addEventListener('scroll', debouncedScrollHandlerPC);
        setupMouseHoverPreload();
        if (GM_getValue('manipulatorBall', true)) {
            addDraggableIcon();
            document.getElementById('draggableIcon').onclick = handleBackNavigation;
        }
    }


})();