Greasy Fork

Greasy Fork is available in English.

POE2 Trade ST工具箱

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

当前为 2025-03-10 提交的版本,查看 最新版本

您需要先安装一个扩展,例如 篡改猴Greasemonkey暴力猴,之后才能安装此脚本。

You will need to install an extension such as Tampermonkey to install this script.

您需要先安装一个扩展,例如 篡改猴暴力猴,之后才能安装此脚本。

您需要先安装一个扩展,例如 篡改猴Userscripts ,之后才能安装此脚本。

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

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

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

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

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

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

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

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

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

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

// ==UserScript==
// @name         POE2 Trade ST工具箱
// @namespace    http://tampermonkey.net/
// @version      2.3.0
// @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(() => {
                    // 确保新内容加载后计算DPS
                    const newResults = document.querySelectorAll('.row[data-id]').length;
                    if (newResults > currentResultCount) {
                        calculateDPS();
                    }
                    tryLoadMore();
                }, 1000);
            }
        }
    
        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));

            // 创建DPS排序面板
            function createDPSPanel() {
                const panel = document.createElement('div');
                panel.id = 'dps-sort-panel';
                panel.style.cssText = `
                    position: fixed;
                    right: 20px;
                    top: 50%;
                    transform: translateY(-50%);
                    background: rgba(28, 28, 28, 0.95);
                    padding: 8px;
                    border-radius: 6px;
                    box-shadow: 0 0 10px rgba(0, 0, 0, 0.5);
                    border: 1px solid #444;
                    width: 120px;
                    max-height: 60vh;
                    z-index: 9997;
                    display: none;
                `;

                // 添加标题
                const title = document.createElement('div');
                title.style.cssText = `
                    font-weight: bold;
                    color: #FFD700;
                    margin-bottom: 6px;
                    padding-bottom: 3px;
                    border-bottom: 1px solid #444;
                    display: flex;
                    justify-content: space-between;
                    align-items: center;
                    cursor: pointer;
                    font-size: 14px;
                    user-select: none;
                    height: 18px;
                `;
                
                // 添加展开/收起指示器
                const indicator = document.createElement('span');
                indicator.textContent = '▼';
                indicator.style.marginRight = '5px';
                
                const titleText = document.createElement('span');
                titleText.textContent = 'DPS';
                
                const titleLeft = document.createElement('div');
                titleLeft.style.display = 'flex';
                titleLeft.style.alignItems = 'center';
                titleLeft.appendChild(indicator);
                titleLeft.appendChild(titleText);

                title.appendChild(titleLeft);

                // 添加关闭按钮
                const closeBtn = document.createElement('button');
                closeBtn.textContent = '×';
                closeBtn.style.cssText = `
                    background: none;
                    border: none;
                    color: #999;
                    font-size: 20px;
                    cursor: pointer;
                    padding: 0 5px;
                `;
                closeBtn.onclick = (e) => {
                    e.stopPropagation();
                    panel.style.display = 'none';
                };
                title.appendChild(closeBtn);

                // 添加内容容器
                const content = document.createElement('div');
                content.id = 'dps-sort-content';
                content.style.cssText = `
                    max-height: calc(60vh - 35px);
                    overflow-y: auto;
                    transition: max-height 0.3s ease-out;
                    padding-right: 2px;
                `;

                // 添加展开/收起功能
                let isExpanded = true;
                title.onclick = () => {
                    isExpanded = !isExpanded;
                    content.style.maxHeight = isExpanded ? 'calc(60vh - 35px)' : '0';
                    content.style.overflow = isExpanded ? 'auto' : 'hidden';
                    indicator.textContent = isExpanded ? '▼' : '▶';
                };

                // 添加滚动条样式
                const style = document.createElement('style');
                style.textContent = `
                    #dps-sort-content::-webkit-scrollbar {
                        width: 6px;
                    }
                    #dps-sort-content::-webkit-scrollbar-track {
                        background: #1a1a1a;
                    }
                    #dps-sort-content::-webkit-scrollbar-thumb {
                        background: #444;
                        border-radius: 3px;
                    }
                    #dps-sort-content::-webkit-scrollbar-thumb:hover {
                        background: #555;
                    }
                    .dps-item {
                        padding: 2px 2px;
                        margin: 1px 0;
                        background: #2d2d2d;
                        border-radius: 3px;
                        cursor: pointer;
                        transition: background 0.2s;
                        color: #FFD700;
                        font-weight: bold;
                        text-align: center;
                        font-size: 13px;
                        white-space: nowrap;
                        overflow: hidden;
                        text-overflow: ellipsis;
                        width: 100%;
                        box-sizing: border-box;
                        user-select: none;
                        line-height: 1.2;
                    }
                    .dps-item:hover {
                        background: #3d3d3d;
                    }
                    .dps-item:last-child {
                        margin-bottom: 0;
                    }
                `;

                panel.appendChild(title);
                panel.appendChild(content);
                document.head.appendChild(style);
                document.body.appendChild(panel);

                return panel;
            }

            // 更新DPS排序面板
            function updateDPSPanel() {
                const panel = document.getElementById('dps-sort-panel') || createDPSPanel();
                const content = document.getElementById('dps-sort-content');
                const items = document.querySelectorAll('.row[data-id]');
                const dpsData = [];

                items.forEach(item => {
                    const dpsDisplay = item.querySelector('.dps-display');
                    if (dpsDisplay) {
                        const dps = parseInt(dpsDisplay.textContent.replace('DPS: ', ''));
                        dpsData.push({
                            dps,
                            element: item
                        });
                    }
                });

                // 按DPS从高到低排序
                dpsData.sort((a, b) => b.dps - a.dps);

                // 更新面板内容
                content.innerHTML = '';
                dpsData.forEach(({dps, element}) => {
                    const dpsItem = document.createElement('div');
                    dpsItem.className = 'dps-item';
                    dpsItem.textContent = dps.toString();
                    dpsItem.onclick = () => {
                        element.scrollIntoView({ behavior: 'smooth', block: 'center' });
                        // 添加高亮效果
                        element.style.transition = 'background-color 0.3s';
                        element.style.backgroundColor = 'rgba(255, 215, 0, 0.2)';
                        setTimeout(() => {
                            element.style.backgroundColor = '';
                        }, 1500);
                    };
                    content.appendChild(dpsItem);
                });

                panel.style.display = 'block';
            }

            // 修改calculateDPS函数,在计算完成后更新排序面板
            function calculateDPS() {
                console.log('Calculating DPS...'); // 添加调试日志
                const items = document.querySelectorAll('.row[data-id]');
                console.log('Found items:', items.length); // 添加调试日志
                
                items.forEach(item => {
                    // 查找已有的DPS显示,如果存在则跳过
                    if (item.querySelector('.dps-display')) return;

                    // 获取元素伤害
                    const edamageSpan = item.querySelector('span[data-field="edamage"]');
                    if (!edamageSpan) return;

                    // 初始化伤害值
                    let minTotal = 0;
                    let maxTotal = 0;

                    // 获取所有元素伤害值
                    const damages = {
                        fire: edamageSpan.querySelector('.colourFireDamage'),
                        lightning: edamageSpan.querySelector('.colourLightningDamage'),
                        cold: edamageSpan.querySelector('.colourColdDamage')
                    };

                    // 处理每种元素伤害
                    Object.values(damages).forEach(dmg => {
                        if (dmg) {
                            const [min, max] = dmg.textContent.split('-').map(Number);
                            if (!isNaN(min) && !isNaN(max)) {
                                minTotal += min;
                                maxTotal += max;
                            }
                        }
                    });

                    // 获取元素增伤
                    let elementInc = 1;
                    const elementIncSpan = item.querySelector('span[data-field="stat.explicit.stat_387439868"]');
                    if (elementIncSpan) {
                        const incMatch = elementIncSpan.textContent.match(/(\d+)%/);
                        if (incMatch) {
                            elementInc = 1 + (parseInt(incMatch[1]) / 100);
                        }
                    }

                    // 获取攻击速度
                    let aps = 1;
                    const apsSpan = item.querySelector('span[data-field="aps"]');
                    if (apsSpan) {
                        const apsValue = apsSpan.querySelector('.colourDefault');
                        if (apsValue) {
                            aps = parseFloat(apsValue.textContent) || 1;
                        }
                    }

                    // 计算DPS
                    const dps = ((minTotal + maxTotal) / 2) * elementInc * aps;

                    // 创建DPS显示元素
                    const dpsDisplay = document.createElement('span');
                    dpsDisplay.className = 'dps-display';
                    dpsDisplay.style.cssText = `
                        color: #FFD700;
                        font-weight: bold;
                        margin-left: 10px;
                    `;
                    dpsDisplay.textContent = `DPS: ${Math.round(dps)}`;

                    // 将DPS显示添加到元素伤害后面
                    edamageSpan.appendChild(dpsDisplay);
                });

                // 更新DPS排序面板
                updateDPSPanel();
            }

            // 修改ST工具箱按钮,添加DPS排序面板的开关功能
            const originalCreateConfigButton = createConfigButton;
            createConfigButton = function() {
                const button = originalCreateConfigButton();
                
                // 添加右键菜单功能
                button.addEventListener('contextmenu', (e) => {
                    e.preventDefault();
                    const panel = document.getElementById('dps-sort-panel');
                    if (panel) {
                        panel.style.display = panel.style.display === 'none' ? 'block' : 'none';
                    }
                });

                // 添加提示
                button.title = 'ST工具箱 (按住可拖动,右键显示/隐藏DPS排序)';
                
                return button;
            };

            // 创建一个防抖函数来避免过于频繁的计算
            function debounce(func, wait) {
                let timeout;
                return function executedFunction(...args) {
                    const later = () => {
                        clearTimeout(timeout);
                        func(...args);
                    };
                    clearTimeout(timeout);
                    timeout = setTimeout(later, wait);
                };
            }

            // 使用防抖包装calculateDPS
            const debouncedCalculateDPS = debounce(calculateDPS, 200);

            // 初始计算DPS
            calculateDPS();

            // 创建一个更强大的观察器来监视DOM变化
            const resultsObserver = new MutationObserver((mutations) => {
                let hasNewContent = false;
                mutations.forEach(mutation => {
                    // 检查是否有新的结果项被添加
                    if (mutation.type === 'childList' && 
                        mutation.addedNodes.length > 0 &&
                        Array.from(mutation.addedNodes).some(node => 
                            node.nodeType === 1 && // 元素节点
                            (node.classList?.contains('row') || node.querySelector?.('.row[data-id]'))
                        )) {
                        hasNewContent = true;
                    }
                });

                if (hasNewContent) {
                    console.log('New content detected, calculating DPS...'); // 添加调试日志
                    debouncedCalculateDPS();
                }
            });

            // 观察整个结果容器及其子元素
            const resultsContainer = document.querySelector('.results-container');
            if (resultsContainer) {
                resultsObserver.observe(resultsContainer, {
                    childList: true,
                    subtree: true,
                    attributes: true,
                    characterData: true
                });

                // 同时观察父元素,以防结果容器被替换
                if (resultsContainer.parentNode) {
                    resultsObserver.observe(resultsContainer.parentNode, {
                        childList: true
                    });
                }
            }

            // 添加滚动事件监听器
            window.addEventListener('scroll', () => {
                // 检查是否滚动到底部附近
                if ((window.innerHeight + window.scrollY) >= document.body.offsetHeight - 1000) {
                    debouncedCalculateDPS();
                }
            });

            // 将calculateDPS函数添加到window对象,以便其他地方可以调用
            window.calculateDPS = calculateDPS;
            window.debouncedCalculateDPS = debouncedCalculateDPS;

            // 监听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 = '';
            });
        }
    }
})();