Greasy Fork is available in English.

POE2 Trade ST工具箱

自动转换简繁中文(页面转简体,输入转繁体)- stomtian

// ==UserScript==
// @name         POE2 Trade ST工具箱
// @namespace    http://tampermonkey.net/
// @version      2.2.1
// @description  自动转换简繁中文(页面转简体,输入转繁体)- stomtian
// @author       stomtian
// @match        https://www.pathofexile.com/trade*
// @match        https://pathofexile.com/trade*
// @grant        GM_getValue
// @grant        GM_setValue
// @grant        unsafeWindow
// @license      MIT
// @require      https://cdn.jsdelivr.net/npm/[email protected]/dist/umd/full.min.js
// @run-at       document-end
// @noframes     true
// ==/UserScript==
    
(function() {
    'use strict';
    
    console.log('POE2 Trade ST工具箱已加载');
    
    const STATE = {
        pageSimplified: GM_getValue('pageSimplified', true),
        inputTraditional: GM_getValue('inputTraditional', true),
        originalTexts: new WeakMap(),
        configs: GM_getValue('savedConfigs', {}),  // 保存的配置
        autoLoadEnabled: GM_getValue('autoLoadEnabled', false),  // 自动加载开关
        matchedCards: [], // 添加匹配的卡片列表
        currentMatchIndex: -1, // 添加当前匹配索引
        showOnlyMatched: GM_getValue('showOnlyMatched', false), // 添加新的状态
        searchPresets: GM_getValue('searchPresets', {}) // 添加预设关键词存储
    };
    
    const CUSTOM_DICT = [
        ['回覆', '回復'],
        ['恢覆', '恢復'],
    ];
    
    const CONFIG = {
        maxAttempts: 50,
        checkInterval: 100,
        inputSelector: 'input[type="text"]:not(#config-name):not(#config-category), textarea',
        textSelector: '.search-bar, .search-advanced-pane, .results-container, .resultset',
        excludeSelector: 'script, style, input, textarea, select, .converter-controls'
    };
    
    function waitForElement(selector) {
        return new Promise(resolve => {
            if (document.querySelector(selector)) {
                resolve();
                return;
            }
    
            const observer = new MutationObserver(() => {
                try {
                    if (document.querySelector(selector)) {
                        observer.disconnect();
                        resolve();
                    }
                } catch (error) {}
            });
    
            observer.observe(document.body, {
                childList: true,
                subtree: true
            });
        });
    }
    
    function waitForOpenCC() {
        return new Promise((resolve, reject) => {
            if (typeof window.OpenCC !== 'undefined') {
                resolve(window.OpenCC);
                return;
            }
    
            let attempts = 0;
            const checkInterval = setInterval(() => {
                if (typeof window.OpenCC !== 'undefined') {
                    clearInterval(checkInterval);
                    resolve(window.OpenCC);
                    return;
                }
    
                if (++attempts >= CONFIG.maxAttempts) {
                    clearInterval(checkInterval);
                    reject(new Error('OpenCC 加载超时'));
                }
            }, CONFIG.checkInterval);
        });
    }
    
    function createConverters(OpenCC) {
        const toTraditional = OpenCC.ConverterFactory(
            OpenCC.Locale.from.cn,
            OpenCC.Locale.to.tw.concat([CUSTOM_DICT])
        );
    
        const toSimplified = OpenCC.ConverterFactory(
            OpenCC.Locale.from.tw,
            OpenCC.Locale.to.cn
        );
    
        return { toTraditional, toSimplified };
    }
    
    function createInputHandler(converter) {
        return function handleInput(e) {
            // 如果输入框标记了不需要转换,则直接返回
            if (e?.target?.dataset?.noConvert === 'true') return;

            if (!STATE.inputTraditional) return;
            if (!e?.target?.value) return;
    
            const cursorPosition = e.target.selectionStart;
            const text = e.target.value;
    
            requestAnimationFrame(() => {
                try {
                    const convertedText = converter.toTraditional(text);
                    if (text === convertedText) return;
    
                    e.target.value = convertedText;
    
                    if (typeof cursorPosition === 'number') {
                        e.target.setSelectionRange(cursorPosition, cursorPosition);
                    }
    
                    e.target.dispatchEvent(new Event('input', {
                        bubbles: true,
                        cancelable: true
                    }));
                } catch (error) {}
            });
        };
    }
    
    function convertPageText(converter, forceRestore = false) {
        if (!STATE.pageSimplified && !forceRestore) return;
    
        try {
            const elements = document.querySelectorAll(CONFIG.textSelector);
            if (!elements.length) return;
    
            elements.forEach(root => {
                try {
                    const walker = document.createTreeWalker(
                        root,
                        NodeFilter.SHOW_TEXT,
                        {
                            acceptNode: function(node) {
                                try {
                                    if (!node.textContent.trim()) return NodeFilter.FILTER_REJECT;
    
                                    const parent = node.parentNode;
                                    if (!parent) return NodeFilter.FILTER_REJECT;
    
                                    if (parent.closest?.(CONFIG.excludeSelector)) {
                                        return NodeFilter.FILTER_REJECT;
                                    }
    
                                    return NodeFilter.FILTER_ACCEPT;
                                } catch (error) {
                                    return NodeFilter.FILTER_REJECT;
                                }
                            }
                        }
                    );
    
                    let node;
                    while (node = walker.nextNode()) {
                        try {
                            const text = node.textContent.trim();
                            if (!text) continue;
    
                            if (!STATE.originalTexts.has(node)) {
                                STATE.originalTexts.set(node, text);
                            }
    
                            if (STATE.pageSimplified) {
                                const convertedText = converter.toSimplified(text);
                                if (text !== convertedText) {
                                    node.textContent = convertedText;
                                }
                            } else {
                                const originalText = STATE.originalTexts.get(node);
                                if (originalText && node.textContent !== originalText) {
                                    node.textContent = originalText;
                                }
                            }
                        } catch (error) {}
                    }
                } catch (error) {}
            });
        } catch (error) {}
    }
    
    function attachInputListener(handleInput) {
        try {
            const inputElements = document.querySelectorAll(CONFIG.inputSelector);
    
            inputElements.forEach(element => {
                try {
                    // 排除搜索框
                    if (element?.dataset?.hasConverter || element?.dataset?.isSearchInput) return;
                    element.addEventListener('input', handleInput);
                    element.dataset.hasConverter = 'true';
                } catch (error) {}
            });
        } catch (error) {}
    }
    
    function createObserver(handleInput, converter) {
        return new MutationObserver(mutations => {
            try {
                let needsTextConversion = false;
    
                for (const mutation of mutations) {
                    if (!mutation.addedNodes.length) continue;
    
                    try {
                        const hasNewInputs = Array.from(mutation.addedNodes).some(node => {
                            try {
                                return node.querySelectorAll?.(CONFIG.inputSelector)?.length > 0;
                            } catch (error) {
                                return false;
                            }
                        });
    
                        if (hasNewInputs) {
                            attachInputListener(handleInput);
                        }
    
                        needsTextConversion = true;
                    } catch (error) {}
                }
    
                if (needsTextConversion) {
                    setTimeout(() => convertPageText(converter), 100);
                }
            } catch (error) {}
        });
    }
    
    function createConfigModal() {
        const modalHtml = `
            <div id="config-modal" style="display: none; position: fixed; top: 50%; left: 50%; transform: translate(-50%, -50%);
                background: #1a1a1a; padding: 20px; border-radius: 8px; z-index: 10000; min-width: 600px; color: #fff;">
                <div style="display: flex; justify-content: space-between; margin-bottom: 15px;">
                    <h3 style="margin: 0;">ST工具箱</h3>
                    <button id="close-config-modal" style="background: none; border: none; color: #fff; cursor: pointer;">✕</button>
                </div>
    
                <!-- 标签栏 -->
                <div style="display: flex; gap: 10px; margin-bottom: 15px; border-bottom: 1px solid #444; padding-bottom: 10px;">
                    <button id="tab-configs" class="modal-tab active" style="padding: 8px 20px; background: #4a90e2; border: none; color: #fff; cursor: pointer; border-radius: 4px; transition: all 0.2s;">配置管理</button>
                    <button id="tab-presets" class="modal-tab" style="padding: 8px 20px; background: #3d3d3d; border: none; color: #fff; cursor: pointer; border-radius: 4px; transition: all 0.2s;">预设关键词</button>
                    <button id="tab-settings" class="modal-tab" style="padding: 8px 20px; background: #3d3d3d; border: none; color: #fff; cursor: pointer; border-radius: 4px; transition: all 0.2s;">设置</button>
                </div>
    
                <!-- 配置管理面板 -->
                <div id="panel-configs" class="panel" style="display: block;">
                    <div style="padding: 15px; background: #2d2d2d; border-radius: 4px;">
                        <div style="margin-bottom: 15px;">
                            <input type="text" id="config-name" placeholder="配置名称"
                                style="padding: 5px; margin-right: 10px; background: #3d3d3d; border: 1px solid #444; color: #fff; width: 200px;">
                            <div class="custom-select" style="display: inline-block; position: relative; width: 150px; margin-right: 10px;">
                                <input type="text" id="config-category" placeholder="选择或输入分类"
                                    style="padding: 5px; background: #3d3d3d; border: 1px solid #444; color: #fff; width: 100%; cursor: pointer;">
                                <div id="category-dropdown" style="display: none; position: absolute; top: 100%; left: 0; width: 100%;
                                    background: #3d3d3d; border: 1px solid #444; border-top: none; max-height: 200px; overflow-y: auto; z-index: 1000;">
                                </div>
                            </div>
                            <button id="save-config" style="padding: 5px 10px; background: #4a90e2; border: none; color: #fff; cursor: pointer; border-radius: 3px;">
                                保存当前配置
                            </button>
                        </div>
                        <div id="category-tabs" style="margin-bottom: 15px; border-bottom: 1px solid #444; padding-bottom: 10px;"></div>
                        <div id="config-list" style="max-height: 300px; overflow-y: auto;">
                        </div>
                    </div>
                </div>
    
                <!-- 设置面板 -->
                <div id="panel-settings" class="panel" style="display: none;">
                    <div style="padding: 15px; background: #2d2d2d; border-radius: 4px;">
                        <!-- 功能开关 -->
                        <div style="margin-bottom: 20px;">
                            <div style="font-weight: bold; margin-bottom: 10px; color: #4a90e2;">功能开关</div>
                            <div style="display: flex; gap: 10px;">
                                <button id="toggle-page-simplified" style="flex: 1; padding: 8px 15px; background: ${STATE.pageSimplified ? '#4a90e2' : '#3d3d3d'}; border: none; color: #fff; cursor: pointer; border-radius: 3px; transition: background-color 0.2s; text-align: center;">
                                    ${STATE.pageSimplified ? '✓ 页面简体' : '✗ 页面简体'}
                                </button>
                                <button id="toggle-input-traditional" style="flex: 1; padding: 8px 15px; background: ${STATE.inputTraditional ? '#4a90e2' : '#3d3d3d'}; border: none; color: #fff; cursor: pointer; border-radius: 3px; transition: background-color 0.2s; text-align: center;">
                                    ${STATE.inputTraditional ? '✓ 输入繁体' : '✗ 输入繁体'}
                                </button>
                                <button id="toggle-auto-load" style="flex: 1; padding: 8px 15px; background: ${STATE.autoLoadEnabled ? '#4a90e2' : '#3d3d3d'}; border: none; color: #fff; cursor: pointer; border-radius: 3px; transition: background-color 0.2s; text-align: center;">
                                    ${STATE.autoLoadEnabled ? '✓ 自动加载' : '✗ 自动加载'}
                                </button>
                            </div>
                        </div>
    
                        <!-- 配置导入导出 -->
                        <div style="margin-top: 20px;">
                            <div style="font-weight: bold; margin-bottom: 10px; color: #4a90e2;">配置导入导出</div>
                            <div style="display: flex; gap: 10px;">
                                <button id="export-configs" style="flex: 1; padding: 8px 15px; background: #27ae60; border: none; color: #fff; cursor: pointer; border-radius: 3px;">导出配置</button>
                                <button id="import-configs" style="flex: 1; padding: 8px 15px; background: #e67e22; border: none; color: #fff; cursor: pointer; border-radius: 3px;">导入配置</button>
                                <input type="file" id="import-file" accept=".json" style="display: none;">
                            </div>
                        </div>
                    </div>
                </div>

                <!-- 预设关键词面板 -->
                <div id="panel-presets" class="panel" style="display: none;">
                    <div style="padding: 15px; background: #2d2d2d; border-radius: 4px;">
                        <div style="margin-bottom: 15px; display: flex; justify-content: flex-end;">
                            <button id="add-preset" style="padding: 8px 20px; background: #4a90e2; border: none; color: #fff; cursor: pointer; border-radius: 4px; transition: all 0.2s;">
                                添加预设
                            </button>
                        </div>
                        <div id="preset-list" style="max-height: 400px; overflow-y: auto;">
                        </div>
                    </div>
                </div>
            </div>

            <!-- 预设编辑弹窗 -->
            <div id="preset-edit-modal" style="display: none; position: fixed; top: 50%; left: 50%; transform: translate(-50%, -50%);
                background: #1a1a1a; padding: 20px; border-radius: 8px; z-index: 10002; width: 800px; color: #fff; box-shadow: 0 0 20px rgba(0, 0, 0, 0.5);">
                <div style="display: flex; justify-content: space-between; margin-bottom: 15px;">
                    <h3 style="margin: 0;" id="preset-edit-title">添加预设</h3>
                    <button id="close-preset-edit" style="background: none; border: none; color: #fff; cursor: pointer; font-size: 20px;">✕</button>
                </div>
                <div style="margin-bottom: 15px;">
                    <div style="margin-bottom: 10px;">
                        <label style="display: block; margin-bottom: 5px;">预设名称</label>
                        <input type="text" id="preset-name" style="width: 100%; padding: 8px; background: #2d2d2d; border: 1px solid #444; color: #fff; border-radius: 4px;">
                    </div>
                    <div>
                        <label style="display: block; margin-bottom: 5px;">关键词(用;分隔)</label>
                        <textarea id="preset-keywords" style="width: 100%; height: 200px; padding: 8px; background: #2d2d2d; border: 1px solid #444; color: #fff; border-radius: 4px; resize: vertical; font-family: monospace;"></textarea>
                    </div>
                </div>
                <div style="display: flex; justify-content: flex-end; gap: 10px;">
                    <button id="cancel-preset-edit" style="padding: 8px 20px; background: #3d3d3d; border: none; color: #fff; cursor: pointer; border-radius: 4px;">
                        取消
                    </button>
                    <button id="save-preset" style="padding: 8px 20px; background: #4a90e2; border: none; color: #fff; cursor: pointer; border-radius: 4px;">
                        保存
                    </button>
                </div>
            </div>

            <!-- 添加遮罩层 -->
            <div id="preset-edit-overlay" style="display: none; position: fixed; top: 0; left: 0; width: 100%; height: 100%; background: rgba(0, 0, 0, 0.7); z-index: 10001;"></div>
        </div>
    `;
    
        document.body.insertAdjacentHTML('beforeend', modalHtml);
    
        // 添加遮罩
        const overlay = document.createElement('div');
        overlay.id = 'config-modal-overlay';
        overlay.style.cssText = `
            display: none;
            position: fixed;
            top: 0;
            left: 0;
            width: 100%;
            height: 100%;
            background: rgba(0, 0, 0, 0.5);
            z-index: 9999;
        `;
        document.body.appendChild(overlay);
    
        // 添加样式
        const style = document.createElement('style');
        style.textContent = `
            .modal-tab.active {
                background: #4a90e2 !important;
            }
            .modal-tab:hover {
                background: #357abd !important;
            }
            .panel {
                transition: opacity 0.3s ease;
            }
            #config-list::-webkit-scrollbar {
                width: 8px;
            }
            #config-list::-webkit-scrollbar-track {
                background: #1a1a1a;
            }
            #config-list::-webkit-scrollbar-thumb {
                background: #444;
                border-radius: 4px;
            }
            #config-list::-webkit-scrollbar-thumb:hover {
                background: #555;
            }
        `;
        document.head.appendChild(style);
    
        setupConfigModalEvents();
        updateConfigList();
        setupCategoryDropdown();
    }
    
    function setupCategoryDropdown() {
        const categoryInput = document.getElementById('config-category');
        const dropdown = document.getElementById('category-dropdown');
        let isDropdownVisible = false;
    
        function updateDropdown() {
            const categories = Object.keys(STATE.configs);
            const inputValue = categoryInput.value.toLowerCase();
    
            dropdown.innerHTML = '';
    
            categories
                .filter(category => category.toLowerCase().includes(inputValue))
                .forEach(category => {
                    const item = document.createElement('div');
                    item.className = 'dropdown-item';
                    item.textContent = category;
                    item.onclick = () => {
                        categoryInput.value = category;
                        hideDropdown();
                    };
                    dropdown.appendChild(item);
                });
    
            if (categories.length === 0) {
                const item = document.createElement('div');
                item.className = 'dropdown-item';
                item.textContent = '无已有分类';
                item.style.color = '#666';
                dropdown.appendChild(item);
            }
        }
    
        function showDropdown() {
            updateDropdown();
            dropdown.style.display = 'block';
            isDropdownVisible = true;
        }
    
        function hideDropdown() {
            dropdown.style.display = 'none';
            isDropdownVisible = false;
        }
    
        categoryInput.addEventListener('focus', showDropdown);
        categoryInput.addEventListener('input', updateDropdown);
    
        // 点击外部区域时隐藏下拉列表
        document.addEventListener('click', (e) => {
            const isClickInside = categoryInput.contains(e.target) || dropdown.contains(e.target);
            if (!isClickInside && isDropdownVisible) {
                hideDropdown();
            }
        });
    
        // 阻止事件冒泡,避免点击下拉列表时触发外部点击事件
        dropdown.addEventListener('click', (e) => {
            e.stopPropagation();
        });
    }
    
    function setupConfigModalEvents() {
        const modal = document.getElementById('config-modal');
        const overlay = document.getElementById('config-modal-overlay');
        const closeBtn = document.getElementById('close-config-modal');
        const saveBtn = document.getElementById('save-config');
        const togglePageBtn = document.getElementById('toggle-page-simplified');
        const toggleInputBtn = document.getElementById('toggle-input-traditional');
        const toggleAutoLoadBtn = document.getElementById('toggle-auto-load');
        const exportBtn = document.getElementById('export-configs');
        const importBtn = document.getElementById('import-configs');
        const importFile = document.getElementById('import-file');
        const tabConfigs = document.getElementById('tab-configs');
        const tabSettings = document.getElementById('tab-settings');
        const tabPresets = document.getElementById('tab-presets');
        const panelConfigs = document.getElementById('panel-configs');
        const panelSettings = document.getElementById('panel-settings');
        const panelPresets = document.getElementById('panel-presets');
        const savePresetBtn = document.getElementById('save-preset');

        const addPresetBtn = document.getElementById('add-preset');
        const presetEditModal = document.getElementById('preset-edit-modal');
        const presetEditOverlay = document.getElementById('preset-edit-overlay');
        const closePresetEdit = document.getElementById('close-preset-edit');
        const cancelPresetEdit = document.getElementById('cancel-preset-edit');
        const presetEditTitle = document.getElementById('preset-edit-title');

        // 标签切换函数
        function switchTab(activeTab) {
            // 重置所有标签和面板
            [tabConfigs, tabSettings, tabPresets].forEach(tab => {
                tab.classList.remove('active');
                tab.style.background = '#3d3d3d';
            });
            [panelConfigs, panelSettings, panelPresets].forEach(panel => {
                panel.style.display = 'none';
            });

            // 激活选中的标签和面板
            activeTab.classList.add('active');
            activeTab.style.background = '#4a90e2';
            
            // 显示对应的面板
            if (activeTab === tabConfigs) {
                panelConfigs.style.display = 'block';
            } else if (activeTab === tabSettings) {
                panelSettings.style.display = 'block';
            } else if (activeTab === tabPresets) {
                panelPresets.style.display = 'block';
                updatePresetList();
            }
        }

        // 标签切换事件
        tabConfigs.addEventListener('click', () => switchTab(tabConfigs));
        tabSettings.addEventListener('click', () => switchTab(tabSettings));
        tabPresets.addEventListener('click', () => switchTab(tabPresets));

        // 初始化显示配置管理标签
        switchTab(tabConfigs);

        closeBtn.addEventListener('click', () => {
            modal.style.display = 'none';
            overlay.style.display = 'none';
        });
    
        overlay.addEventListener('click', () => {
            modal.style.display = 'none';
            overlay.style.display = 'none';
        });
    
        togglePageBtn.addEventListener('click', () => {
            STATE.pageSimplified = !STATE.pageSimplified;
            GM_setValue('pageSimplified', STATE.pageSimplified);
            togglePageBtn.textContent = STATE.pageSimplified ? '✓ 页面简体' : '✗ 页面简体';
            togglePageBtn.style.backgroundColor = STATE.pageSimplified ? '#4a90e2' : '#3d3d3d';
            convertPageText(window.converter, true);
        });
    
        toggleInputBtn.addEventListener('click', () => {
            STATE.inputTraditional = !STATE.inputTraditional;
            GM_setValue('inputTraditional', STATE.inputTraditional);
            toggleInputBtn.textContent = STATE.inputTraditional ? '✓ 输入繁体' : '✗ 输入繁体';
            toggleInputBtn.style.backgroundColor = STATE.inputTraditional ? '#4a90e2' : '#3d3d3d';
        });
    
        toggleAutoLoadBtn.addEventListener('click', () => {
            STATE.autoLoadEnabled = !STATE.autoLoadEnabled;
            GM_setValue('autoLoadEnabled', STATE.autoLoadEnabled);
            toggleAutoLoadBtn.textContent = STATE.autoLoadEnabled ? '✓ 自动加载' : '✗ 自动加载';
            toggleAutoLoadBtn.style.backgroundColor = STATE.autoLoadEnabled ? '#4a90e2' : '#3d3d3d';
        });
    
        saveBtn.addEventListener('click', saveCurrentConfig);
    
        // 修改导出配置
        exportBtn.addEventListener('click', () => {
            const configData = {
                version: '2.0.0',
                configs: {},
                searchPresets: STATE.searchPresets
            };

            // 复制配置,但不包含 timestamp
            Object.keys(STATE.configs).forEach(category => {
                configData.configs[category] = {};
                Object.keys(STATE.configs[category]).forEach(name => {
                    configData.configs[category][name] = {
                        url: STATE.configs[category][name].url
                    };
                });
            });
            
            const blob = new Blob([JSON.stringify(configData, null, 2)], { type: 'application/json' });
            const url = URL.createObjectURL(blob);
            const a = document.createElement('a');
            a.href = url;
            a.download = `poe2_trade_configs_${new Date().toISOString().slice(0,10)}.json`;
            document.body.appendChild(a);
            a.click();
            document.body.removeChild(a);
            URL.revokeObjectURL(url);
        });
    
        // 导入配置按钮点击
        importBtn.addEventListener('click', () => {
            importFile.click();
        });
    
        // 处理文件导入
        importFile.addEventListener('change', (e) => {
            const file = e.target.files[0];
            if (!file) return;
    
            const reader = new FileReader();
            reader.onload = (event) => {
                try {
                    const importedData = JSON.parse(event.target.result);
                    
                    // 验证导入的数据
                    if (!importedData.version || (!importedData.configs && !importedData.searchPresets)) {
                        throw new Error('无效的配置文件格式');
                    }
    
                    // 确认导入
                    if (confirm(`确定要导入这些配置吗?\n这将会覆盖同名的现有配置和预设关键词。`)) {
                        // 合并配置
                        if (importedData.configs) {
                            Object.keys(importedData.configs).forEach(category => {
                                if (!STATE.configs[category]) {
                                    STATE.configs[category] = {};
                                }
                                Object.assign(STATE.configs[category], importedData.configs[category]);
                            });
                            GM_setValue('savedConfigs', STATE.configs);
                            updateConfigList();
                        }

                        // 合并预设关键词
                        if (importedData.searchPresets) {
                            Object.assign(STATE.searchPresets, importedData.searchPresets);
                            GM_setValue('searchPresets', STATE.searchPresets);
                            updatePresetList();
                        }

                        alert('配置导入成功!');
                    }
                } catch (error) {
                    alert('导入失败:' + error.message);
                }
                
                // 清除文件选择,允许重复导入同一个文件
                importFile.value = '';
            };
            reader.readAsText(file);
        });
    
        // 添加预设标签切换事件
        tabPresets.addEventListener('click', () => {
            tabPresets.classList.add('active');
            tabConfigs.classList.remove('active');
            tabSettings.classList.remove('active');
            tabConfigs.style.background = '#3d3d3d';
            tabSettings.style.background = '#3d3d3d';
            panelConfigs.style.display = 'none';
            panelSettings.style.display = 'none';
            panelPresets.style.display = 'block';
            updatePresetList();
        });
    
        // 添加保存预设事件
        savePresetBtn.addEventListener('click', saveSearchPreset);

        function closePresetEditModal() {
            presetEditModal.style.display = 'none';
            presetEditOverlay.style.display = 'none';
        }

        // 打开预设编辑弹窗
        addPresetBtn.addEventListener('click', () => {
            presetEditModal.style.display = 'block';
            presetEditOverlay.style.display = 'block';
            presetEditTitle.textContent = '添加预设';
            document.getElementById('preset-name').value = '';
            document.getElementById('preset-keywords').value = '';
            document.getElementById('preset-name').dataset.editMode = 'false';
        });

        // 关闭预设编辑弹窗
        [closePresetEdit, cancelPresetEdit, presetEditOverlay].forEach(btn => {
            btn.addEventListener('click', closePresetEditModal);
        });

        // 添加预设名称和关键词输入框的事件处理
        const presetNameInput = document.getElementById('preset-name');
        const presetKeywordsInput = document.getElementById('preset-keywords');

        // 标记这些输入框不需要转换
        presetNameInput.dataset.noConvert = 'true';
        presetKeywordsInput.dataset.noConvert = 'true';

        // 移除原有的输入转换处理
        [presetNameInput, presetKeywordsInput].forEach(input => {
            const oldInput = input.cloneNode(true);
            input.parentNode.replaceChild(oldInput, input);
        });
    }
    
    // 修改 saveCurrentConfig 函数
    function saveCurrentConfig() {
        const name = document.getElementById('config-name').value.trim();
        const category = document.getElementById('config-category').value.trim();

        if (!name) {
            alert('请输入配置名称');
            return;
        }

        if (!category) {
            alert('请输入分类名称');
            return;
        }

        if (!STATE.configs[category]) {
            STATE.configs[category] = {};
        }

        STATE.configs[category][name] = {
            url: window.location.href
        };

        GM_setValue('savedConfigs', STATE.configs);
        updateConfigList();

        document.getElementById('config-name').value = '';
        document.getElementById('config-category').value = '';
    }
    
    function updateConfigList() {
        const configList = document.getElementById('config-list');
        const categoryTabs = document.getElementById('category-tabs');
        configList.innerHTML = '';
        categoryTabs.innerHTML = '';
    
        // 获取所有分类
        const categories = Object.keys(STATE.configs);
    
        // 如果没有配置,显示提示信息
        if (categories.length === 0) {
            configList.innerHTML = '<div style="text-align: center; color: #666;">暂无保存的配置</div>';
            return;
        }
    
        // 创建标签
        categories.forEach((category, index) => {
            const tabButton = document.createElement('button');
            tabButton.textContent = category;
            tabButton.style.cssText = `
                background: ${index === 0 ? '#4a90e2' : '#3d3d3d'};
                border: none;
                color: #fff;
                padding: 5px 15px;
                cursor: pointer;
                border-radius: 3px;
                transition: background-color 0.2s;
                margin-right: 10px;
            `;
            tabButton.dataset.category = category;
            tabButton.title = '双击删除分类';
    
            tabButton.addEventListener('click', (e) => {
                document.querySelectorAll('#category-tabs button[data-category]').forEach(btn => {
                    btn.style.backgroundColor = '#3d3d3d';
                });
                tabButton.style.backgroundColor = '#4a90e2';
                showCategoryConfigs(category);
            });
    
            tabButton.addEventListener('dblclick', (e) => {
                e.stopPropagation();
                deleteCategory(category);
            });
    
            categoryTabs.appendChild(tabButton);
        });
    
        // 默认显示第一个分类的配置
        showCategoryConfigs(categories[0]);
    }
    
    function deleteCategory(category) {
        const configCount = Object.keys(STATE.configs[category]).length;
        if (confirm(`确定要删除分类 "${category}" 及其包含的 ${configCount} 个配置吗?`)) {
            delete STATE.configs[category];
            GM_setValue('savedConfigs', STATE.configs);
            updateConfigList();
        }
    }
    
    function showCategoryConfigs(category) {
        const configList = document.getElementById('config-list');
        configList.innerHTML = '';
        const configs = STATE.configs[category];
    
        Object.entries(configs).forEach(([name, data]) => {
            const configItem = document.createElement('div');
            configItem.style.cssText = `
                display: grid;
                grid-template-columns: 1fr auto auto auto;
                align-items: center;
                padding: 8px;
                margin: 5px 0;
                background: #3d3d3d;
                border-radius: 4px;
                gap: 10px;
            `;
    
            const nameSpan = document.createElement('span');
            nameSpan.textContent = name;
            nameSpan.style.cssText = `
                overflow: hidden;
                text-overflow: ellipsis;
                white-space: nowrap;
            `;
    
            const loadBtn = document.createElement('button');
            loadBtn.textContent = '读取';
            loadBtn.style.cssText = `
                background: #4a90e2;
                border: none;
                color: #fff;
                padding: 3px 12px;
                cursor: pointer;
                border-radius: 3px;
                transition: background-color 0.2s;
            `;
            loadBtn.onclick = () => loadConfig(data.url);
    
            const updateBtn = document.createElement('button');
            updateBtn.textContent = '更新';
            updateBtn.style.cssText = `
                background: #27ae60;
                border: none;
                color: #fff;
                padding: 3px 12px;
                cursor: pointer;
                border-radius: 3px;
                transition: background-color 0.2s;
            `;
            updateBtn.onclick = (e) => {
                e.stopPropagation();
                updateConfig(category, name);
            };
    
            const deleteBtn = document.createElement('button');
            deleteBtn.textContent = '删除';
            deleteBtn.style.cssText = `
                background: #e74c3c;
                border: none;
                color: #fff;
                padding: 3px 12px;
                cursor: pointer;
                border-radius: 3px;
                transition: background-color 0.2s;
            `;
            deleteBtn.onclick = (e) => {
                e.stopPropagation();
                deleteConfig(category, name);
            };
    
            configItem.appendChild(nameSpan);
            configItem.appendChild(loadBtn);
            configItem.appendChild(updateBtn);
            configItem.appendChild(deleteBtn);
            configList.appendChild(configItem);
        });
    }
    
    function loadConfig(url) {
        window.location.href = url;
    }
    
    function deleteConfig(category, name) {
        if (confirm(`确定要删除配置 "${name}" 吗?`)) {
            delete STATE.configs[category][name];
            if (Object.keys(STATE.configs[category]).length === 0) {
                delete STATE.configs[category];
            }
            GM_setValue('savedConfigs', STATE.configs);
            updateConfigList();
        }
    }
    
    function createConfigButton() {
        const floatingButton = document.createElement('div');
        floatingButton.style.cssText = `
            position: fixed;
            right: 20px;
            top: 50%;
            transform: translateY(-50%);
            width: 50px;
            height: 50px;
            background: linear-gradient(135deg, #3c3c28 0%, #2a2a1c 100%);
            border-radius: 25px;
            display: flex;
            align-items: center;
            justify-content: center;
            cursor: pointer;
            color: #ffd700;
            font-weight: bold;
            font-family: 'Fontin SmallCaps', Arial, sans-serif;
            font-size: 18px;
            box-shadow: 0 0 20px rgba(0,0,0,0.5),
                        inset 0 0 8px rgba(255, 215, 0, 0.3),
                        0 0 30px rgba(255, 215, 0, 0.2);
            border: 1px solid rgba(255, 215, 0, 0.4);
            z-index: 9998;
            transition: all 0.3s ease;
            user-select: none;
            touch-action: none;
            text-shadow: 0 0 10px rgba(255, 215, 0, 0.6);
            animation: normalGlowing 2s ease-in-out infinite;
        `;
        floatingButton.textContent = 'ST';
        floatingButton.title = 'ST工具箱 (按住可拖动)';
    
        // 添加悬停效果
        floatingButton.addEventListener('mouseenter', () => {
            if (!isDragging) {
                floatingButton.style.transform = 'scale(1.1)';
                floatingButton.style.boxShadow = `
                    0 0 25px rgba(0,0,0,0.5),
                    inset 0 0 12px rgba(255, 215, 0, 0.5),
                    0 0 40px rgba(255, 215, 0, 0.3)
                `;
                floatingButton.style.color = '#ffe44d';
                floatingButton.style.textShadow = '0 0 15px rgba(255, 215, 0, 0.8)';
                floatingButton.style.border = '1px solid rgba(255, 215, 0, 0.6)';
                floatingButton.style.animation = 'none';
    
                if (isHidden) {
                    showButton();
                }
            }
        });
    
        floatingButton.addEventListener('mouseleave', () => {
            if (!isDragging) {
                floatingButton.style.transform = 'scale(1)';
                floatingButton.style.boxShadow = `
                    0 0 20px rgba(0,0,0,0.5),
                    inset 0 0 8px rgba(255, 215, 0, 0.3),
                    0 0 30px rgba(255, 215, 0, 0.2)
                `;
                floatingButton.style.color = '#ffd700';
                floatingButton.style.textShadow = '0 0 10px rgba(255, 215, 0, 0.6)';
                floatingButton.style.border = '1px solid rgba(255, 215, 0, 0.4)';
                floatingButton.style.animation = 'normalGlowing 2s ease-in-out infinite';
    
                checkAndHideButton();
            }
        });
    
        // 添加拖拽功能
        let isDragging = false;
        let startX, startY;
        let lastX = GM_getValue('floatingButtonX', window.innerWidth - 70);
        let lastY = GM_getValue('floatingButtonY', window.innerHeight / 2);
        let dragDistance = 0;
        let mouseDownTime = 0;
        let isHidden = false;
    
        function dragStart(e) {
            isDragging = true;
            dragDistance = 0;
            mouseDownTime = Date.now();
            const rect = floatingButton.getBoundingClientRect();
            startX = e.clientX - rect.left;
            startY = e.clientY - rect.top;
            floatingButton.style.transition = 'none';
            floatingButton.style.transform = 'scale(1)';
        }
    
        function drag(e) {
            if (!isDragging) return;
            e.preventDefault();
    
            const x = e.clientX - startX;
            const y = e.clientY - startY;
    
            // 计算拖动距离
            const dx = x - lastX;
            const dy = y - lastY;
            dragDistance += Math.sqrt(dx * dx + dy * dy);
    
            // 限制拖动范围
            const maxX = window.innerWidth - floatingButton.offsetWidth;
            const maxY = window.innerHeight - floatingButton.offsetHeight;
            lastX = Math.max(0, Math.min(x, maxX));
            lastY = Math.max(0, Math.min(y, maxY));
    
            floatingButton.style.left = lastX + 'px';
            floatingButton.style.top = lastY + 'px';
            floatingButton.style.right = 'auto';
        }
    
        function dragEnd(e) {
            if (!isDragging) return;
    
            const dragDuration = Date.now() - mouseDownTime;
            isDragging = false;
            floatingButton.style.transition = 'all 0.3s ease';
    
            // 调整位置,使按钮居中对齐边缘
            const buttonWidth = floatingButton.offsetWidth;
            const buttonHeight = floatingButton.offsetHeight;
            const windowWidth = window.innerWidth;
            const windowHeight = window.innerHeight;
            const threshold = 20;
    
            if (lastX < threshold) {
                lastX = 0;
            } else if (lastX + buttonWidth > windowWidth - threshold) {
                lastX = windowWidth - buttonWidth;
            }
    
            if (lastY < threshold) {
                lastY = 0;
            } else if (lastY + buttonHeight > windowHeight - threshold) {
                lastY = windowHeight - buttonHeight;
            }
    
            floatingButton.style.left = lastX + 'px';
            floatingButton.style.top = lastY + 'px';
    
            // 保存位置
            GM_setValue('floatingButtonX', lastX);
            GM_setValue('floatingButtonY', lastY);
    
            // 检查是否需要隐藏按钮
            checkAndHideButton();
    
            // 如果拖动距离小于5像素且时间小于200ms,则认为是点击
            if (dragDistance < 5 && dragDuration < 200) {
                document.getElementById('config-modal').style.display = 'block';
                document.getElementById('config-modal-overlay').style.display = 'block';
            }
        }
    
        function checkAndHideButton() {
            const threshold = 20; // 距离边缘多少像素时触发隐藏
            const buttonWidth = floatingButton.offsetWidth;
            const buttonHeight = floatingButton.offsetHeight;
            const buttonRight = lastX + buttonWidth;
            const buttonBottom = lastY + buttonHeight;
            const windowWidth = window.innerWidth;
            const windowHeight = window.innerHeight;
    
            // 检查各个边缘
            if (buttonRight > windowWidth - threshold) {
                // 右边缘
                hideButton('right');
            } else if (lastX < threshold) {
                // 左边缘
                hideButton('left');
            } else if (lastY < threshold) {
                // 上边缘
                hideButton('top');
            } else if (buttonBottom > windowHeight - threshold) {
                // 下边缘
                hideButton('bottom');
            }
        }
    
        function hideButton(direction) {
            isHidden = true;
            floatingButton.style.transition = 'all 0.3s ease';
    
            // 添加金光动画
            floatingButton.style.animation = 'none';
            floatingButton.offsetHeight; // 触发重绘
            floatingButton.style.animation = 'glowing 1.5s ease-in-out infinite';
            floatingButton.style.background = 'linear-gradient(135deg, #5a5a42 0%, #3a3a2c 100%)';
    
            switch (direction) {
                case 'right':
                    floatingButton.style.transform = 'translateY(-50%) translateX(60%)';
                    floatingButton.style.borderRadius = '25px 0 0 25px';
                    break;
                case 'left':
                    floatingButton.style.transform = 'translateY(-50%) translateX(-60%)';
                    floatingButton.style.borderRadius = '0 25px 25px 0';
                    break;
                case 'top':
                    floatingButton.style.transform = 'translateX(-50%) translateY(-60%)';
                    floatingButton.style.borderRadius = '0 0 25px 25px';
                    break;
                case 'bottom':
                    floatingButton.style.transform = 'translateX(-50%) translateY(60%)';
                    floatingButton.style.borderRadius = '25px 25px 0 0';
                    break;
            }
        }
    
        function showButton() {
            isHidden = false;
            floatingButton.style.transition = 'all 0.3s ease';
            floatingButton.style.animation = 'normalGlowing 2s ease-in-out infinite';
            floatingButton.style.background = 'linear-gradient(135deg, #3c3c28 0%, #2a2a1c 100%)';
            floatingButton.style.transform = 'scale(1)';
            floatingButton.style.borderRadius = '25px';
        }
    
        // 添加金光动画样式
        const glowingStyle = document.createElement('style');
        glowingStyle.textContent = `
            @keyframes normalGlowing {
                0% {
                    box-shadow: 0 0 20px rgba(0,0,0,0.5),
                                inset 0 0 8px rgba(255, 215, 0, 0.3),
                                0 0 30px rgba(255, 215, 0, 0.2);
                    border-color: rgba(255, 215, 0, 0.4);
                    color: #ffd700;
                    text-shadow: 0 0 10px rgba(255, 215, 0, 0.6);
                }
                50% {
                    box-shadow: 0 0 25px rgba(0,0,0,0.5),
                                inset 0 0 12px rgba(255, 215, 0, 0.4),
                                0 0 40px rgba(255, 215, 0, 0.3),
                                0 0 60px rgba(255, 215, 0, 0.2);
                    border-color: rgba(255, 215, 0, 0.5);
                    color: #ffe44d;
                    text-shadow: 0 0 15px rgba(255, 215, 0, 0.7);
                }
                100% {
                    box-shadow: 0 0 20px rgba(0,0,0,0.5),
                                inset 0 0 8px rgba(255, 215, 0, 0.3),
                                0 0 30px rgba(255, 215, 0, 0.2);
                    border-color: rgba(255, 215, 0, 0.4);
                    color: #ffd700;
                    text-shadow: 0 0 10px rgba(255, 215, 0, 0.6);
                }
            }
    
            @keyframes glowing {
                0% {
                    box-shadow: 0 0 20px rgba(0,0,0,0.5),
                                inset 0 0 8px rgba(255, 215, 0, 0.5),
                                0 0 30px rgba(255, 215, 0, 0.4),
                                0 0 50px rgba(255, 215, 0, 0.2);
                    border-color: rgba(255, 215, 0, 0.6);
                    color: #ffd700;
                    text-shadow: 0 0 15px rgba(255, 215, 0, 0.8);
                }
                50% {
                    box-shadow: 0 0 30px rgba(0,0,0,0.6),
                                inset 0 0 20px rgba(255, 215, 0, 0.8),
                                0 0 60px rgba(255, 215, 0, 0.6),
                                0 0 100px rgba(255, 215, 0, 0.4),
                                0 0 150px rgba(255, 215, 0, 0.2);
                    border-color: rgba(255, 223, 0, 1);
                    color: #ffe44d;
                    text-shadow: 0 0 25px rgba(255, 215, 0, 1),
                                0 0 35px rgba(255, 215, 0, 0.7),
                                0 0 45px rgba(255, 215, 0, 0.4);
                }
                100% {
                    box-shadow: 0 0 20px rgba(0,0,0,0.5),
                                inset 0 0 8px rgba(255, 215, 0, 0.5),
                                0 0 30px rgba(255, 215, 0, 0.4),
                                0 0 50px rgba(255, 215, 0, 0.2);
                    border-color: rgba(255, 215, 0, 0.6);
                    color: #ffd700;
                    text-shadow: 0 0 15px rgba(255, 215, 0, 0.8);
                }
            }
        `;
        document.head.appendChild(glowingStyle);
    
        // 监听窗口大小变化
        window.addEventListener('resize', () => {
            if (!isDragging) {
                // 确保按钮不会超出窗口
                const maxX = window.innerWidth - floatingButton.offsetWidth;
                const maxY = window.innerHeight - floatingButton.offsetHeight;
                lastX = Math.min(lastX, maxX);
                lastY = Math.min(lastY, maxY);
    
                floatingButton.style.left = lastX + 'px';
                floatingButton.style.top = lastY + 'px';
    
                // 检查是否需要隐藏按钮
                checkAndHideButton();
            }
        });
    
        floatingButton.addEventListener('mousedown', dragStart);
        document.addEventListener('mousemove', drag);
        document.addEventListener('mouseup', dragEnd);
    
        // 恢复上次保存的位置或使用默认位置
        const savedX = GM_getValue('floatingButtonX', window.innerWidth - 70);
        const savedY = GM_getValue('floatingButtonY', window.innerHeight / 2);
        lastX = savedX;
        lastY = savedY;
        floatingButton.style.right = 'auto';
        floatingButton.style.top = lastY + 'px';
        floatingButton.style.left = lastX + 'px';
        floatingButton.style.transform = 'scale(1)';
    
        // 检查初始位置是否需要隐藏
        setTimeout(checkAndHideButton, 100);
    
        return floatingButton;
    }
    
    function createControls() {
        const floatingButton = createConfigButton();
        document.body.appendChild(floatingButton);

        // 创建搜索框但不立即显示
        createSearchBox();

        // 添加快捷键监听
        document.addEventListener('keydown', (e) => {
            if (e.altKey && !e.ctrlKey && !e.shiftKey && e.key.toLowerCase() === 'f') {
                e.preventDefault(); // 阻止默认行为
                toggleSearchBox();
            }
        });
    }

    // 切换搜索框显示状态
    function toggleSearchBox() {
        const searchBox = document.querySelector('.search-box-container');
        if (searchBox) {
            searchBox.style.display = searchBox.style.display === 'none' ? 'flex' : 'none';
            if (searchBox.style.display === 'flex') {
                // 当显示搜索框时,自动聚焦到输入框
                const searchInput = searchBox.querySelector('input');
                if (searchInput) {
                    searchInput.focus();
                }
            }
        }
    }

    // 创建搜索框
    function createSearchBox(handleInput) {
        const searchBoxContainer = document.createElement('div');
        searchBoxContainer.className = 'search-box-container';
        searchBoxContainer.style.cssText = `
            position: fixed;
            top: 10px;
            left: 20px;
            z-index: 9999;
            background: rgba(28, 28, 28, 0.95);
            padding: 15px 10px 10px;
            border-radius: 8px;
            box-shadow: 0 0 10px rgba(0, 0, 0, 0.5);
            border: 1px solid #444;
            display: none;
            flex-direction: column;
            gap: 8px;
        `;

        const searchRow = document.createElement('div');
        searchRow.style.cssText = `
            display: flex;
            gap: 8px;
            align-items: center;
        `;

        const navigationRow = document.createElement('div');
        navigationRow.style.cssText = `
            display: flex;
            gap: 8px;
            align-items: center;
        `;

        // 创建搜索输入框
        const searchInput = document.createElement('input');
        searchInput.type = 'text';
        searchInput.placeholder = '输入关键词(用;分隔)';
        searchInput.dataset.isSearchInput = 'true';
        searchInput.style.cssText = `
            width: 250px;
            padding: 5px 10px;
            border: 1px solid #666;
            border-radius: 4px;
            background: #2d2d2d;
            color: #fff;
        `;

        // 添加搜索事件
        searchInput.addEventListener('input', (e) => {
            if (!e?.target?.value) return;

            // 如果页面是繁体模式,则将输入转换为繁体
            if (!STATE.pageSimplified) {
                const cursorPosition = e.target.selectionStart;
                const text = e.target.value;

                requestAnimationFrame(() => {
                    try {
                        const convertedText = window.converter.toTraditional(text);
                        if (text === convertedText) return;

                        e.target.value = convertedText;

                        if (typeof cursorPosition === 'number') {
                            e.target.setSelectionRange(cursorPosition, cursorPosition);
                        }
                    } catch (error) {}
                });
            }
        });

        const searchButton = document.createElement('button');
        searchButton.textContent = '搜索';
        searchButton.style.cssText = `
            padding: 5px 15px;
            background: #4a90e2;
            border: none;
            border-radius: 4px;
            color: #fff;
            cursor: pointer;
            transition: background 0.2s;
        `;

        // 添加预设下拉框
        const presetSelectContainer = document.createElement('div');
        presetSelectContainer.style.cssText = `
            position: relative;
            width: 120px;
        `;

        const presetInput = document.createElement('input');
        presetInput.readOnly = true;
        presetInput.placeholder = '选择预设';
        presetInput.style.cssText = `
            width: 100%;
            padding: 5px;
            background: #2d2d2d;
            border: 1px solid #666;
            border-radius: 4px;
            color: #fff;
            cursor: pointer;
        `;

        // 修改预设选择框的样式
        const presetDropdown = document.createElement('div');
        presetDropdown.style.cssText = `
            display: none;
            position: absolute;
            top: 100%;
            left: 0;
            width: 200px;
            max-height: 300px;
            overflow-y: auto;
            background: #2d2d2d;
            border: 1px solid #666;
            border-radius: 4px;
            z-index: 10000;
            margin-top: 4px;
            padding-top: 30px; // 为搜索框留出空间
            color: #fff; // 添加默认文字颜色
        `;

        // 添加预设搜索框
        const presetSearchInput = document.createElement('input');
        presetSearchInput.type = 'text';
        presetSearchInput.placeholder = '搜索预设...';
        presetSearchInput.style.cssText = `
            position: absolute;
            top: 0;
            left: 0;
            width: calc(100% - 16px);
            margin: 8px;
            padding: 4px 8px;
            background: #3d3d3d;
            border: 1px solid #666;
            border-radius: 3px;
            color: #fff;
            font-size: 12px;
        `;

        // 阻止搜索框的点击事件冒泡,避免关闭下拉框
        presetSearchInput.addEventListener('click', (e) => {
            e.stopPropagation();
        });

        // 添加搜索框的输入事件
        presetSearchInput.addEventListener('input', (e) => {
            const searchText = e.target.value.toLowerCase();
            const options = presetDropdown.querySelectorAll('.preset-option');
            options.forEach(option => {
                const name = option.querySelector('span').textContent.toLowerCase();
                if (name.includes(searchText)) {
                    option.style.display = '';
                } else {
                    option.style.display = 'none';
                }
            });
        });

        presetDropdown.appendChild(presetSearchInput);

        // 添加滚动条样式
        const styleSheet = document.createElement('style');
        styleSheet.textContent = `
            .preset-dropdown::-webkit-scrollbar {
                width: 8px;
            }
            .preset-dropdown::-webkit-scrollbar-track {
                background: #1a1a1a;
            }
            .preset-dropdown::-webkit-scrollbar-thumb {
                background: #444;
                border-radius: 4px;
            }
            .preset-dropdown::-webkit-scrollbar-thumb:hover {
                background: #555;
            }
        `;
        document.head.appendChild(styleSheet);

        let selectedPresets = new Set();

        // 修改预设选项的样式
        function updatePresetOptions() {
            // 保留搜索框
            presetDropdown.innerHTML = '';
            presetDropdown.appendChild(presetSearchInput);
            presetSearchInput.value = ''; // 清空搜索框

            // 创建分隔线
            const createDivider = () => {
                const divider = document.createElement('div');
                divider.style.cssText = `
                    height: 1px;
                    background: #666;
                    margin: 5px 0;
                `;
                return divider;
            };

            // 创建预设选项
            const createPresetOption = (name, keywords, isSelected) => {
                const option = document.createElement('div');
                option.className = 'preset-option'; // 添加类名以便搜索
                option.style.cssText = `
                    padding: 6px 10px;
                    cursor: pointer;
                    display: flex;
                    align-items: center;
                    gap: 8px;
                    transition: all 0.2s;
                    color: #fff;
                    ${isSelected ? 'background: #2a4a6d;' : ''}
                `;

                const checkbox = document.createElement('input');
                checkbox.type = 'checkbox';
                checkbox.checked = isSelected;
                checkbox.style.cssText = `
                    margin: 0;
                    cursor: pointer;
                `;

                const label = document.createElement('span');
                label.textContent = name;
                label.style.cssText = `
                    flex: 1;
                    overflow: hidden;
                    text-overflow: ellipsis;
                    white-space: nowrap;
                    color: #fff;
                `;

                option.appendChild(checkbox);
                option.appendChild(label);

                option.addEventListener('mouseover', () => {
                    option.style.backgroundColor = isSelected ? '#2a5a8d' : '#3d3d3d';
                });

                option.addEventListener('mouseout', () => {
                    option.style.backgroundColor = isSelected ? '#2a4a6d' : 'transparent';
                });

                option.addEventListener('click', (e) => {
                    e.stopPropagation();
                    checkbox.checked = !checkbox.checked;
                    if (checkbox.checked) {
                        selectedPresets.add(name);
                    } else {
                        selectedPresets.delete(name);
                    }
                    updateSelectedPresets();
                    // 重新渲染预设列表以更新顺序
                    updatePresetOptions();
                });

                return option;
            };

            // 获取所有预设并分类
            const selectedOptions = [];
            const unselectedOptions = [];
            
            Object.entries(STATE.searchPresets).forEach(([name, keywords]) => {
                const isSelected = selectedPresets.has(name);
                const option = createPresetOption(name, keywords, isSelected);
                
                if (isSelected) {
                    selectedOptions.push(option);
                } else {
                    unselectedOptions.push(option);
                }
            });

            // 添加已选择的预设
            if (selectedOptions.length > 0) {
                const selectedTitle = document.createElement('div');
                selectedTitle.style.cssText = `
                    padding: 5px 10px;
                    color: #999;
                    font-size: 12px;
                    background: #262626;
                `;
                selectedTitle.textContent = '已选择的预设';
                presetDropdown.appendChild(selectedTitle);
                
                selectedOptions.forEach(option => presetDropdown.appendChild(option));
            }

            // 添加未选择的预设
            if (selectedOptions.length > 0 && unselectedOptions.length > 0) {
                presetDropdown.appendChild(createDivider());
            }

            if (unselectedOptions.length > 0) {
                if (selectedOptions.length > 0) {
                    const unselectedTitle = document.createElement('div');
                    unselectedTitle.style.cssText = `
                        padding: 5px 10px;
                        color: #999;
                        font-size: 12px;
                        background: #262626;
                    `;
                    unselectedTitle.textContent = '未选择的预设';
                    presetDropdown.appendChild(unselectedTitle);
                }
                
                unselectedOptions.forEach(option => presetDropdown.appendChild(option));
            }
        }

        function updateSelectedPresets() {
            if (selectedPresets.size === 0) {
                presetInput.value = '';
                presetInput.placeholder = '选择预设';
            } else {
                const names = Array.from(selectedPresets).join(', ');
                presetInput.value = names;
                presetInput.placeholder = '';
            }
        }

        function applySelectedPresets() {
            if (selectedPresets.size === 0) return;

            const keywords = Array.from(selectedPresets)
                .map(name => STATE.searchPresets[name])
                .join(';');

            searchInput.value = keywords;

            // 手动触发输入转换
            if (!STATE.pageSimplified) {
                try {
                    const convertedText = window.converter.toTraditional(keywords);
                    if (keywords !== convertedText) {
                        searchInput.value = convertedText;
                    }
                } catch (error) {}
            }

            // 触发搜索
            performSearch();
            // 清空选择
            selectedPresets.clear();
            updateSelectedPresets();
        }

        // 点击输入框时显示/隐藏下拉框
        presetInput.addEventListener('click', (e) => {
            e.stopPropagation();
            const isVisible = presetDropdown.style.display === 'block';
            presetDropdown.style.display = isVisible ? 'none' : 'block';
            if (!isVisible) {
                updatePresetOptions();
                // 聚焦搜索框
                setTimeout(() => {
                    presetSearchInput.focus();
                }, 0);
            }
        });

        // 点击其他地方时隐藏下拉框
        document.addEventListener('click', () => {
            presetDropdown.style.display = 'none';
        });

        // 添加搜索事件
        const performSearch = () => {
            // 获取所有预设关键词
            const presetKeywords = Array.from(selectedPresets)
                .map(name => STATE.searchPresets[name])
                .join(';');

            // 获取输入框关键词
            const inputKeywords = searchInput.value.trim();

            // 合并关键词
            const combinedKeywords = [presetKeywords, inputKeywords]
                .filter(k => k) // 过滤掉空字符串
                .join(';');

            // 如果页面是繁体模式,则将关键词转换为繁体
            let searchKeywords = combinedKeywords;
            if (!STATE.pageSimplified) {
                try {
                    searchKeywords = window.converter.toTraditional(combinedKeywords);
                } catch (error) {
                    console.error('转换繁体失败:', error);
                }
            }

            // 使用;或;作为分隔符
            const keywords = searchKeywords.toLowerCase().split(/[;;]/);
            // 过滤掉空字符串
            const filteredKeywords = keywords.filter(k => k.trim());
            
            if (!filteredKeywords.length) {
                clearHighlights();
                matchCounter.textContent = '';
                return;
            }
            searchAndHighlight(filteredKeywords, matchCounter);
        };

        searchInput.addEventListener('keyup', (e) => {
            if (e.key === 'Enter') {
                performSearch();
            }
        });

        searchButton.addEventListener('click', performSearch);

        // 添加导航按钮
        const prevButton = document.createElement('button');
        prevButton.textContent = '上一个';
        prevButton.style.cssText = `
            padding: 5px 15px;
            background: #2d2d2d;
            border: 1px solid #666;
            border-radius: 4px;
            color: #fff;
            cursor: pointer;
            transition: background 0.2s;
            flex: 1;
        `;

        const nextButton = document.createElement('button');
        nextButton.textContent = '下一个';
        nextButton.style.cssText = `
            padding: 5px 15px;
            background: #2d2d2d;
            border: 1px solid #666;
            border-radius: 4px;
            color: #fff;
            cursor: pointer;
            transition: background 0.2s;
            flex: 1;
        `;

        const matchCounter = document.createElement('span');
        matchCounter.className = 'search-counter';
        matchCounter.style.cssText = `
            color: #fff;
            font-size: 12px;
            padding: 0 10px;
            min-width: 60px;
            text-align: center;
        `;

        // 添加导航事件
        prevButton.addEventListener('click', () => {
            navigateHighlight('prev');
        });

        nextButton.addEventListener('click', () => {
            navigateHighlight('next');
        });

        // 添加hover效果
        [searchButton, prevButton, nextButton].forEach(button => {
            button.addEventListener('mouseover', () => {
                button.style.background = button === searchButton ? '#357abd' : '#3d3d3d';
            });
            button.addEventListener('mouseout', () => {
                button.style.background = button === searchButton ? '#4a90e2' : '#2d2d2d';
            });
        });

        // 组装界面
        presetSelectContainer.appendChild(presetInput);
        presetSelectContainer.appendChild(presetDropdown);

        searchRow.appendChild(presetSelectContainer);
        searchRow.appendChild(searchInput);
        searchRow.appendChild(searchButton);

        navigationRow.appendChild(prevButton);
        navigationRow.appendChild(matchCounter);
        navigationRow.appendChild(nextButton);

        searchBoxContainer.appendChild(searchRow);
        searchBoxContainer.appendChild(navigationRow);

        // 添加选项行
        const optionsRow = document.createElement('div');
        optionsRow.style.cssText = `
            display: flex;
            gap: 8px;
            align-items: center;
            padding: 0 5px;
        `;

        const showOnlyMatchedLabel = document.createElement('label');
        showOnlyMatchedLabel.style.cssText = `
            display: flex;
            align-items: center;
            gap: 5px;
            color: #fff;
            font-size: 12px;
            cursor: pointer;
        `;

        const showOnlyMatchedCheckbox = document.createElement('input');
        showOnlyMatchedCheckbox.type = 'checkbox';
        showOnlyMatchedCheckbox.checked = STATE.showOnlyMatched;
        showOnlyMatchedCheckbox.style.cssText = `
            margin: 0;
            cursor: pointer;
        `;

        showOnlyMatchedLabel.appendChild(showOnlyMatchedCheckbox);
        showOnlyMatchedLabel.appendChild(document.createTextNode('只显示匹配项'));

        showOnlyMatchedCheckbox.addEventListener('change', (e) => {
            STATE.showOnlyMatched = e.target.checked;
            GM_setValue('showOnlyMatched', STATE.showOnlyMatched);
            if (STATE.matchedCards.length > 0) {
                updateCardVisibility();
            }
        });

        optionsRow.appendChild(showOnlyMatchedLabel);
        searchBoxContainer.insertBefore(optionsRow, navigationRow);

        document.body.appendChild(searchBoxContainer);

        // 添加关闭按钮
        const closeButton = document.createElement('button');
        closeButton.textContent = '×';
        closeButton.style.cssText = `
            position: absolute;
            top: -10px;
            right: -10px;
            width: 20px;
            height: 20px;
            line-height: 1;
            padding: 0;
            background: #2d2d2d;
            border: 1px solid #666;
            border-radius: 50%;
            color: #999;
            font-size: 16px;
            font-weight: bold;
            cursor: pointer;
            display: flex;
            align-items: center;
            justify-content: center;
            transition: all 0.2s;
            z-index: 10000;
            box-shadow: 0 0 5px rgba(0, 0, 0, 0.3);
        `;

        closeButton.addEventListener('mouseover', () => {
            closeButton.style.color = '#fff';
            closeButton.style.background = '#3d3d3d';
            closeButton.style.borderColor = '#999';
        });

        closeButton.addEventListener('mouseout', () => {
            closeButton.style.color = '#999';
            closeButton.style.background = '#2d2d2d';
            closeButton.style.borderColor = '#666';
        });

        closeButton.addEventListener('click', () => {
            searchBoxContainer.style.display = 'none';
            clearHighlights();
            searchInput.value = '';
            matchCounter.textContent = '';
            // 不清除选择的预设
        });

        searchBoxContainer.insertBefore(closeButton, searchBoxContainer.firstChild);

        // 添加键盘快捷键
        document.addEventListener('keydown', (e) => {
            if (e.key === 'F3' || (e.ctrlKey && e.key === 'g')) {
                e.preventDefault();
                if (e.shiftKey) {
                    navigateHighlight('prev');
                } else {
                    navigateHighlight('next');
                }
            }
        });

        // 在搜索框显示时更新预设选项
        const originalToggleSearchBox = toggleSearchBox;
        toggleSearchBox = function() {
            const searchBox = document.querySelector('.search-box-container');
            if (searchBox) {
                const isCurrentlyHidden = searchBox.style.display === 'none';
                if (isCurrentlyHidden) {
                    updatePresetOptions();
                    // 不清除选择的预设
                    updateSelectedPresets();
                }
                searchBox.style.display = isCurrentlyHidden ? 'flex' : 'none';
                if (isCurrentlyHidden) {
                    const searchInput = searchBox.querySelector('input[type="text"]');
                    if (searchInput) {
                        searchInput.focus();
                    }
                }
            }
        };

        return updatePresetOptions;
    }

    // 清除所有高亮
    function clearHighlights() {
        const highlights = document.querySelectorAll('.st-highlight');
        highlights.forEach(highlight => {
            const parent = highlight.parentNode;
            parent.replaceChild(document.createTextNode(highlight.textContent), highlight);
        });

        // 清除所有高亮样式
        document.querySelectorAll('.current-highlight, .matched-card').forEach(card => {
            card.classList.remove('current-highlight', 'matched-card');
        });

        // 重置导航状态
        STATE.matchedCards = [];
        STATE.currentMatchIndex = -1;

        // 恢复所有卡片的可见性
        const allCards = document.querySelectorAll('.row[data-id]');
        allCards.forEach(card => {
            card.style.display = '';
        });
    }

    // 修改 searchAndHighlight 函数中的关键词处理部分
    function escapeRegExp(string) {
        return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
    }

    function searchAndHighlight(keywords, matchCounter) {
        clearHighlights();

        const itemCards = document.querySelectorAll('.row[data-id]');
        STATE.matchedCards = [];
        let hasMatch = false;

        // 预处理关键词,处理特殊字符和通配符
        const processedKeywords = keywords.map(keyword => {
            keyword = keyword.trim();
            
            // 处理带条件的通配符
            // 匹配模式:(&>2) 或 (&>=2) 或 (&<2) 或 (&<=2) 或 (&=2)
            // 或带加号的版本:+(&>2) 等
            const conditionalPattern = /(\(?&(>=|<=|>|<|=)(\d+)\)?)/;
            if (conditionalPattern.test(keyword)) {
                const match = keyword.match(conditionalPattern);
                const fullMatch = match[0];
                const operator = match[2];
                const targetNum = parseInt(match[3]);
                
                // 将关键词分成前后两部分
                const [before, after] = keyword.split(fullMatch);
                
                // 构建正则表达式和验证函数
                const numPattern = '(\\d+)';
                const beforePattern = before ? escapeRegExp(before) : '';
                const afterPattern = after ? escapeRegExp(after) : '';
                
                return {
                    pattern: beforePattern + numPattern + afterPattern,
                    validate: (foundNum) => {
                        const num = parseInt(foundNum);
                        switch(operator) {
                            case '>': return num > targetNum;
                            case '>=': return num >= targetNum;
                            case '<': return num < targetNum;
                            case '<=': return num <= targetNum;
                            case '=': return num === targetNum;
                            default: return false;
                        }
                    }
                };
            }
            
            // 处理简单通配符
            if (keyword.includes('&')) {
                // 处理带加号的通配符
                if (keyword.includes('+&')) {
                    keyword = escapeRegExp(keyword).replace(/\\\+&/g, '\\+[0-9]+');
                } else {
                    // 处理不带加号的通配符
                    keyword = escapeRegExp(keyword).replace(/&/g, '[0-9]+');
                }
            } else {
                // 处理其他特殊字符
                keyword = escapeRegExp(keyword).replace(/\\\+/g, '[++]');
            }
            
            return { pattern: keyword };
        }).filter(k => k);

        itemCards.forEach(card => {
            const cardText = card.textContent;
            const matches = processedKeywords.map(keyword => {
                if (!keyword.validate) {
                    // 简单模式匹配
                    const regex = new RegExp(keyword.pattern, 'i');
                    return regex.test(cardText);
                } else {
                    // 条件模式匹配
                    const regex = new RegExp(keyword.pattern, 'i');
                    const match = cardText.match(regex);
                    if (!match) return false;
                    
                    // 提取数字并验证条件
                    const foundNum = match[1];
                    return keyword.validate(foundNum);
                }
            });
            const allMatch = matches.every(match => match);

            if (allMatch) {
                hasMatch = true;
                STATE.matchedCards.push(card);
                highlightKeywords(card, processedKeywords.map(k => k.pattern));
            } else if (STATE.showOnlyMatched) {
                card.style.display = 'none';
            }
        });

        if (!hasMatch) {
            alert('未找到匹配的结果');
            if (matchCounter) {
                matchCounter.textContent = '0/0';
            }
        } else {
            STATE.currentMatchIndex = 0;
            updateHighlightNavigation();
            updateCardVisibility();
        }
    }

    // 修改 highlightKeywords 函数
    function highlightKeywords(element, patterns) {
        const walker = document.createTreeWalker(
            element,
            NodeFilter.SHOW_TEXT,
            {
                acceptNode: function(node) {
                    if (node.parentNode.nodeName === 'SCRIPT' ||
                        node.parentNode.nodeName === 'STYLE' ||
                        node.parentNode.classList.contains('st-highlight')) {
                        return NodeFilter.FILTER_REJECT;
                    }

                    const text = node.textContent;
                    const containsAnyKeyword = patterns.some(pattern => {
                        const regex = new RegExp(pattern, 'i');
                        return regex.test(text);
                    });

                    return containsAnyKeyword ? NodeFilter.FILTER_ACCEPT : NodeFilter.FILTER_REJECT;
                }
            }
        );

        const nodes = [];
        let node;
        while (node = walker.nextNode()) {
            nodes.push(node);
        }

        nodes.forEach(textNode => {
            let text = textNode.textContent;
            let tempText = text;

            patterns.forEach(pattern => {
                const regex = new RegExp(`(${pattern})`, 'gi');
                if (regex.test(text)) {
                    tempText = tempText.replace(regex, (match) => {
                        return `<span class="st-highlight">${match}</span>`;
                    });
                }
            });

            if (tempText !== text) {
                const tempDiv = document.createElement('div');
                tempDiv.innerHTML = tempText;
                const fragment = document.createDocumentFragment();
                while (tempDiv.firstChild) {
                    fragment.appendChild(tempDiv.firstChild);
                }
                textNode.parentNode.replaceChild(fragment, textNode);
            }
        });
    }

    // 更新高亮导航
    function updateHighlightNavigation() {
        const matchCounter = document.querySelector('.search-counter');
        if (!matchCounter) return;

        // 更新计数器
        matchCounter.textContent = `${STATE.currentMatchIndex + 1}/${STATE.matchedCards.length}`;

        // 移除之前的当前高亮
        document.querySelectorAll('.current-highlight, .matched-card').forEach(card => {
            card.classList.remove('current-highlight', 'matched-card');
        });

        // 添加新的当前高亮
        const currentCard = STATE.matchedCards[STATE.currentMatchIndex];
        if (currentCard) {
            currentCard.classList.add('current-highlight');
            // 滚动到当前卡片
            currentCard.scrollIntoView({
                behavior: 'smooth',
                block: 'center'
            });
        }
    }

    // 导航到上一个/下一个高亮
    function navigateHighlight(direction) {
        if (STATE.matchedCards.length === 0) return;

        if (direction === 'next') {
            STATE.currentMatchIndex = (STATE.currentMatchIndex + 1) % STATE.matchedCards.length;
        } else {
            STATE.currentMatchIndex = (STATE.currentMatchIndex - 1 + STATE.matchedCards.length) % STATE.matchedCards.length;
        }

        updateHighlightNavigation();
    }

    // 修改样式
    const style = document.createElement('style');
    style.textContent = `
        .current-highlight {
            background-color: rgba(255, 215, 0, 0.3) !important;
        }
        .matched-card {
            background-color: rgba(255, 215, 0, 0.1) !important;
        }
        .st-highlight {
            background-color: #ffd700;
            color: #000;
            border-radius: 2px;
            padding: 0 2px;
        }
    `;
    document.head.appendChild(style);
    
    function watchSearchResults(converter) {
        let lastUrl = location.href;
        const urlObserver = setInterval(() => {
            if (location.href !== lastUrl) {
                lastUrl = location.href;
                STATE.originalTexts = new WeakMap();
                setTimeout(() => {
                    convertPageText(converter);
                }, 500);
            }
        }, 100);
    
        // 监视搜索结果变化
        const resultObserver = new MutationObserver((mutations) => {
            let needsConversion = false;
            for (const mutation of mutations) {
                if (mutation.type === 'childList' || mutation.type === 'characterData') {
                    needsConversion = true;
                    break;
                }
            }
            if (needsConversion) {
                setTimeout(() => convertPageText(converter), 100);
            }
        });
    
        const resultsContainer = document.querySelector('.results-container');
        if (resultsContainer) {
            resultObserver.observe(resultsContainer, {
                childList: true,
                subtree: true,
                characterData: true
            });
        }
    }
    
    function findReactInstance(element) {
        const key = Object.keys(element).find(key => key.startsWith('__reactFiber$'));
        return key ? element[key] : null;
    }
    
    function findLoadMoreHandler() {
        const loadMoreBtn = document.querySelector('.load-more-btn');
        if (!loadMoreBtn) {
            console.log('未找到加载更多按钮');
            return null;
        }
    
        // 尝试获取React实例
        const instance = findReactInstance(loadMoreBtn);
        if (!instance) {
            console.log('未找到React实例');
            return null;
        }
    
        // 遍历查找onClick处理函数
        let current = instance;
        while (current) {
            if (current.memoizedProps && current.memoizedProps.onClick) {
                return current.memoizedProps.onClick;
            }
            current = current.return;
        }
    
        console.log('未找到onClick处理函数');
        return null;
    }
    
    function clickLoadMoreIfExists() {
        // 使用正确的选择器
        const loadMoreBtn = document.querySelector('.btn.load-more-btn');
        if (!loadMoreBtn) {
            console.log('未找到加载更多按钮');
            return false;
        }
    
        const results = document.querySelectorAll('.resultset, .trade-result, [class*="result-item"]');
        const currentResultCount = results.length;
    
        if (currentResultCount >= 100) {
            return false;
        }
    
        try {
            // 尝试多种方式触发点击
            // 1. 原生点击
            loadMoreBtn.click();
    
            // 2. 模拟鼠标事件序列
            ['mousedown', 'mouseup', 'click'].forEach(eventType => {
                const event = new MouseEvent(eventType, {
                    bubbles: true,
                    cancelable: true,
                    buttons: 1
                });
                loadMoreBtn.dispatchEvent(event);
            });
    
            // 3. 尝试点击内部的span
            const spanInButton = loadMoreBtn.querySelector('span');
            if (spanInButton) {
                spanInButton.click();
                ['mousedown', 'mouseup', 'click'].forEach(eventType => {
                    const event = new MouseEvent(eventType, {
                        bubbles: true,
                        cancelable: true,
                        buttons: 1
                    });
                    spanInButton.dispatchEvent(event);
                });
            }
    
            // 4. 使用 HTMLElement 的 click 方法
            HTMLElement.prototype.click.call(loadMoreBtn);
    
            return true;
        } catch (error) {
            console.log('触发加载更多时出错:', error);
            return false;
        }
    }
    
    function autoLoadAllResults() {
        let attempts = 0;
        const maxAttempts = 20;
        let lastResultCount = 0;
    
        function tryLoadMore() {
            const results = document.querySelectorAll('.resultset');
            const currentResultCount = results.length;
    
            if (currentResultCount >= 100 || attempts >= maxAttempts ||
                (currentResultCount === lastResultCount && attempts > 0)) {
                return;
            }
    
            if (clickLoadMoreIfExists()) {
                lastResultCount = currentResultCount;
                attempts++;
                setTimeout(tryLoadMore, 1000); // 增加间隔时间到1秒
            }
        }
    
        setTimeout(tryLoadMore, 1000);
    }
    
    // 检查URL是否是搜索结果页面
    function isSearchResultPage() {
        const isPOE2Trade = window.location.href.includes('pathofexile.com/trade2/search/poe2');
        const hasResults = document.querySelector('.results-container, .trade-results, .search-results, [class*="results"]') !== null;
        return isPOE2Trade && hasResults;
    }
    
    async function init() {
        try {
            await new Promise(resolve => setTimeout(resolve, 100));
    
            // 监听URL变化
            let lastUrl = location.href;
            const urlCheckInterval = setInterval(() => {
                const currentUrl = location.href;
                if ((currentUrl !== lastUrl || currentUrl.includes('pathofexile.com/trade2/search/poe2')) && STATE.autoLoadEnabled) {
                    lastUrl = currentUrl;
                    setTimeout(() => {
                        if (isSearchResultPage()) {
                            autoLoadAllResults();
                        }
                    }, 100);
                }
            }, 100);
    
            // 初始检查
            setTimeout(() => {
                if (isSearchResultPage() && STATE.autoLoadEnabled) {
                    autoLoadAllResults();
                }
            }, 100);
    
            const OpenCC = await waitForOpenCC();
            const converter = createConverters(OpenCC);
            window.converter = converter;
    
            // 先创建 handleInput 函数
            const handleInput = createInputHandler(converter);

            const observer = createObserver(handleInput, converter);
            observer.observe(document.body, {
                childList: true,
                subtree: true
            });

            attachInputListener(handleInput);
            
            // 将 handleInput 作为参数传递给 createSearchBox
            const updatePresetOptions = createSearchBox(handleInput);
            createConfigModal();
            createControls();

            if (STATE.pageSimplified) {
                convertPageText(converter);
            }

            watchSearchResults(converter);

            setInterval(() => {
                if (STATE.pageSimplified) {
                    convertPageText(converter);
                }
            }, 1000);

            // 在保存或删除预设后更新搜索框的预设选项
            const originalSaveSearchPreset = saveSearchPreset;
            saveSearchPreset = function() {
                originalSaveSearchPreset();
                updatePresetOptions();
            };

            const originalUpdatePresetList = updatePresetList;
            updatePresetList = function() {
                originalUpdatePresetList();
                updatePresetOptions();
            };

        } catch (error) {
            console.log('初始化时出错:', error);
        }
    }
    
    // 修改 updateConfig 函数
    function updateConfig(category, name) {
        if (confirm(`确定要用当前页面更新配置 "${name}" 吗?`)) {
            STATE.configs[category][name] = {
                url: window.location.href
            };
            GM_setValue('savedConfigs', STATE.configs);
            updateConfigList();
        }
    }
    
    // 添加预设关键词相关函数
    function saveSearchPreset() {
        const nameInput = document.getElementById('preset-name');
        const keywordsInput = document.getElementById('preset-keywords');
        const name = nameInput.value.trim();
        const keywords = keywordsInput.value.trim();
        const saveBtn = document.getElementById('save-preset');

        if (!name || !keywords) {
            alert('请输入预设名称和关键词');
            return;
        }

        // 检查是否在编辑模式
        if (nameInput.dataset.editMode === 'true') {
            const originalName = nameInput.dataset.originalName;
            // 如果名称改变了,删除旧的预设
            if (originalName !== name) {
                delete STATE.searchPresets[originalName];
            }
            // 清除编辑模式标记
            delete nameInput.dataset.editMode;
            delete nameInput.dataset.originalName;
            saveBtn.textContent = '保存预设';
        } else if (STATE.searchPresets[name] && !confirm(`预设 "${name}" 已存在,是否覆盖?`)) {
            return;
        }

        STATE.searchPresets[name] = keywords;
        GM_setValue('searchPresets', STATE.searchPresets);
        updatePresetList();

        nameInput.value = '';
        keywordsInput.value = '';
    }

    function updatePresetList() {
        const presetList = document.getElementById('preset-list');
        presetList.innerHTML = '';

        Object.entries(STATE.searchPresets).forEach(([name, keywords]) => {
            const presetItem = document.createElement('div');
            presetItem.style.cssText = `
                display: grid;
                grid-template-columns: 1fr auto auto;
                align-items: center;
                padding: 8px;
                margin: 5px 0;
                background: #3d3d3d;
                border-radius: 4px;
                gap: 10px;
            `;

            const nameSpan = document.createElement('span');
            nameSpan.textContent = name;  // 只显示预设名称
            nameSpan.title = keywords;    // 将关键词设置为提示文本
            nameSpan.style.cssText = `
                overflow: hidden;
                text-overflow: ellipsis;
                white-space: nowrap;
                cursor: help;  // 添加提示光标
            `;

            const editBtn = document.createElement('button');
            editBtn.textContent = '编辑';
            editBtn.style.cssText = `
                background: #27ae60;
                border: none;
                color: #fff;
                padding: 3px 12px;
                cursor: pointer;
                border-radius: 3px;
            `;
            editBtn.onclick = () => {
                const presetEditModal = document.getElementById('preset-edit-modal');
                const presetEditOverlay = document.getElementById('preset-edit-overlay');
                const presetEditTitle = document.getElementById('preset-edit-title');
                const nameInput = document.getElementById('preset-name');
                const keywordsInput = document.getElementById('preset-keywords');

                presetEditTitle.textContent = '编辑预设';
                nameInput.value = name;
                keywordsInput.value = keywords;
                nameInput.dataset.editMode = 'true';
                nameInput.dataset.originalName = name;

                presetEditModal.style.display = 'block';
                presetEditOverlay.style.display = 'block';
            };

            const deleteBtn = document.createElement('button');
            deleteBtn.textContent = '删除';
            deleteBtn.style.cssText = `
                background: #e74c3c;
                border: none;
                color: #fff;
                padding: 3px 12px;
                cursor: pointer;
                border-radius: 3px;
            `;
            deleteBtn.onclick = () => {
                if (confirm(`确定要删除预设 "${name}" 吗?`)) {
                    delete STATE.searchPresets[name];
                    GM_setValue('searchPresets', STATE.searchPresets);
                    updatePresetList();
                }
            };

            presetItem.appendChild(nameSpan);
            presetItem.appendChild(editBtn);
            presetItem.appendChild(deleteBtn);
            presetList.appendChild(presetItem);
        });
    }
    
    setTimeout(init, 2000);

    // 在clearHighlights函数后添加
    function updateCardVisibility() {
        const allCards = document.querySelectorAll('.row[data-id]');
        
        if (STATE.showOnlyMatched) {
            // 如果启用了"只显示匹配项",隐藏所有非匹配卡片
            allCards.forEach(card => {
                if (STATE.matchedCards.includes(card)) {
                    card.style.display = '';
                } else {
                    card.style.display = 'none';
                }
            });
        } else {
            // 如果禁用了"只显示匹配项",显示所有卡片
            allCards.forEach(card => {
                card.style.display = '';
            });
        }
    }
})();