给DeepSeek添加原生化的提示词管理功能

为 DeepSeek 添加提示词管理功能,点击直接进输入框。

// ==UserScript==
// @name         给DeepSeek添加原生化的提示词管理功能
// @namespace    http://tampermonkey.net/
// @version      1.5
// @description  为 DeepSeek 添加提示词管理功能,点击直接进输入框。
// @author       独爱冰淇淋
// @match        https://chat.deepseek.com/*
// @grant        GM_setValue
// @grant        GM_getValue
// @grant        GM_addStyle
// @license MIT
// ==/UserScript==

(function() {
    'use strict';

    // 添加样式
    GM_addStyle(`
        .prompt-list {
            position: fixed;
            background: #FFFFFF;
            border-radius: 12px;
            width: 640px;
            max-height: 80vh;
            overflow-y: auto;
            display: none;
            z-index: 1000;
            box-shadow: 0px 12px 24px 0px rgba(0, 0, 0, 0.08);
            padding: 0;
        }
        .prompt-header {
            display: flex;
            justify-content: space-between;
            align-items: center;
            padding: 16px 20px;
            border-bottom: 1px solid rgba(0, 0, 0, 0.06);
            position: sticky;
            top: 0;
            background: #FFFFFF;
            z-index: 1;
        }
        .prompt-title {
            font-size: 16px;
            font-weight: 600;
            color: rgb(28, 28, 28);
            margin: 0;
        }
        .add-prompt-btn {
            padding: 6px 12px;
            border-radius: 6px;
            border: none;
            background: rgb(77, 107, 254);
            color: #FFFFFF;
            cursor: pointer;
            font-size: 14px;
            font-weight: 500;
            transition: all 0.2s;
            display: flex;
            align-items: center;
            gap: 4px;
        }
        .add-prompt-btn:hover {
            background: rgb(56, 86, 233);
        }
        .prompt-list-content {
            padding: 12px 16px;
        }
        .prompt-item {
            display: flex;
            align-items: center;
            padding: 8px 12px;
            border-radius: 6px;
            margin: 4px 0;
            border: 1px solid transparent;
            transition: all 0.2s;
            cursor: pointer;
            position: relative;
            gap: 6px;
        }
        .prompt-item:hover {
            background: rgb(248, 248, 249);
            border-color: rgba(0, 0, 0, 0.06);
        }
        .prompt-item-left {
            font-size: 13px;
            font-weight: 600;
            color: #1c1c1c;
            overflow: hidden;
            text-overflow: ellipsis;
            white-space: nowrap;
            flex-shrink: 0;
            position: relative;
            padding-right: 12px;
            line-height: 1.5;
            min-width: 60px;
        }
        .prompt-item-left::after {
            content: '';
            position: absolute;
            right: 6px;
            top: 50%;
            transform: translateY(-50%);
            width: 1px;
            height: 14px;
            background-color: rgba(0, 0, 0, 0.1);
        }
        .prompt-item-content {
            flex: 1;
            min-width: 0;
            font-size: 13px;
            color: #666;
            overflow: hidden;
            text-overflow: ellipsis;
            white-space: nowrap;
            margin-right: 4px;
            line-height: 1.5;
        }
        .prompt-actions {
            position: static;
            display: none;
            transform: none;
            margin-left: auto;
            padding-left: 4px;
            opacity: 0;
            transition: opacity 0.2s;
        }
        .prompt-item:hover .prompt-actions {
            display: flex;
            opacity: 1;
        }
        .prompt-action-btn {
            background: none;
            border: none;
            padding: 4px;
            cursor: pointer;
            display: flex;
            align-items: center;
            justify-content: center;
            color: #1c1c1c;
            opacity: 0.7;
            transition: opacity 0.2s;
        }
        .prompt-action-btn:hover {
            opacity: 1;
        }
        .edit-prompt {
            color: #1c1c1c;
        }
        .edit-prompt:hover {
            color: #000000;
        }
        .modal-overlay {
            position: fixed;
            top: 0;
            left: 0;
            right: 0;
            bottom: 0;
            background: rgba(0, 0, 0, 0.4);
            display: flex;
            align-items: start;
            justify-content: center;
            z-index: 1001;
            padding-top: 100px;
        }
        .modal-content {
            background: white;
            border-radius: 8px;
            width: 90%;
            max-width: 600px;
            position: relative;
            padding: 24px 32px;
        }
        .modal-header {
            font-size: 16px;
            font-weight: 600;
            margin-bottom: 20px;
            padding-right: 24px;
        }
        .modal-close {
            position: absolute;
            right: 16px;
            top: 16px;
            cursor: pointer;
            padding: 8px;
            background: none;
            border: none;
            color: #666;
            font-size: 18px;
            line-height: 1;
        }
        .form-group {
            margin-bottom: 16px;
        }
        .form-label {
            display: block;
            margin-bottom: 8px;
            font-size: 14px;
            color: #1c1c1c;
        }
        .form-label span {
            color: #ff4d4f;
            margin-left: 4px;
        }
        .form-input {
            width: 100%;
            padding: 8px 12px;
            border: 1px solid #d9d9d9;
            border-radius: 6px;
            font-size: 14px;
            line-height: 1.5;
            box-sizing: border-box;
            transition: all 0.2s;
        }
        .form-input:focus {
            outline: none;
            border-color: #4d6bfe;
            box-shadow: 0 0 0 2px rgba(77, 107, 254, 0.1);
        }
        .form-input::placeholder {
            color: #bfbfbf;
        }
        textarea.form-input {
            min-height: 120px;
            resize: vertical;
        }
        .modal-footer {
            margin-top: 24px;
            text-align: right;
        }
        .save-btn {
            background: rgb(79, 70, 229);
            color: white;
            border: none;
            padding: 8px 32px;
            border-radius: 20px;
            cursor: pointer;
            font-size: 14px;
            font-weight: 500;
            transition: all 0.2s;
        }
        .save-btn:hover {
            background: rgb(67, 56, 202);
        }
        .delete-prompt {
            background-color: #dc2626;
            color: white;
            padding: 3px 8px;
            border-radius: 4px;
            transition: background-color 0.2s;
        }
        .delete-prompt:hover {
            background-color: #b91c1c;
            color: white;
        }
        .confirm-dialog {
            position: fixed;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            background: white;
            padding: 20px;
            border-radius: 8px;
            box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
            z-index: 1003;
            width: 300px;
        }
        .confirm-dialog-overlay {
            position: fixed;
            top: 0;
            left: 0;
            right: 0;
            bottom: 0;
            background: rgba(0, 0, 0, 0.5);
            z-index: 1002;
        }
        .confirm-dialog-title {
            font-size: 16px;
            font-weight: 500;
            margin-bottom: 12px;
            color: #1c1c1c;
        }
        .confirm-dialog-buttons {
            display: flex;
            justify-content: flex-end;
            gap: 8px;
            margin-top: 16px;
        }
        .confirm-dialog-button {
            padding: 6px 12px;
            border: none;
            border-radius: 4px;
            cursor: pointer;
            font-size: 14px;
        }
        .confirm-dialog-cancel {
            background: #f3f4f6;
            color: #374151;
        }
        .confirm-dialog-cancel:hover {
            background: #e5e7eb;
        }
        .confirm-dialog-confirm {
            background: #dc2626;
            color: white;
        }
        .confirm-dialog-confirm:hover {
            background: #b91c1c;
        }
        .prompt-action-btn {
            padding: 8px;
            background: transparent;
            border: none;
            cursor: pointer;
            color: #666;
            border-radius: 4px;
            display: flex;
            align-items: center;
            justify-content: center;
        }
        .prompt-action-btn:hover {
            background: rgba(0, 0, 0, 0.06);
            color: #333;
        }
        .edit-prompt svg {
            width: 16px;
            height: 16px;
        }
        .prompt-header-buttons {
            display: flex;
            gap: 8px;
            align-items: center;
        }
        .import-export-btn {
            display: flex;
            align-items: center;
            justify-content: center;
            padding: 4px;
            border: none;
            background: transparent;
            color: #666;
            cursor: pointer;
            border-radius: 4px;
        }
        .import-export-btn:hover {
            background: rgba(0, 0, 0, 0.06);
            color: #333;
        }
        .import-export-menu {
            position: absolute;
            top: 100%;
            right: 0;
            background: white;
            border-radius: 8px;
            box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
            padding: 4px;
            z-index: 1001;
        }
        .import-export-menu button {
            display: block;
            width: 100%;
            padding: 8px 16px;
            border: none;
            background: none;
            text-align: left;
            cursor: pointer;
            border-radius: 4px;
            color: #1c1c1c;
            font-size: 14px;
        }
        .import-export-menu button:hover {
            background: rgba(0, 0, 0, 0.06);
        }
    `);

    function createElements() {
        // 找到按钮容器
        const buttonContainer = document.querySelector('.ec4f5d61');
        if (!buttonContainer) {
            console.log('Button container not found');
            return;
        }

        // 创建按钮
        const promptButtonWrapper = document.createElement('div');
        promptButtonWrapper.setAttribute('role', 'button');
        promptButtonWrapper.className = 'ds-button ds-button--rect ds-button--m prompt-saver-button';
        promptButtonWrapper.style.cssText = `
            background-color: #FFFFFF;
            padding: 4px 6px;
            height: 28px;
            border-radius: 14px;
            border: 1px solid rgba(0, 0, 0, 0.12);
            cursor: pointer;
            display: inline-flex;
            align-items: center;
            gap: 1.5px;
            font-size: 12px;
            line-height: 1;
            white-space: nowrap;
            transition: all 0.2s;
            box-sizing: border-box;
            margin: 0 12px 0 4px;
        `;

        // 添加鼠标悬停效果
        promptButtonWrapper.addEventListener('mouseenter', () => {
            if (promptList.style.display === 'none') {  // 只在列表隐藏时改变悬停颜色
                promptButtonWrapper.style.backgroundColor = 'rgb(224, 228, 237)';
            }
        });
        promptButtonWrapper.addEventListener('mouseleave', () => {
            if (promptList.style.display === 'none') {  // 只在列表隐藏时恢复背景色
                promptButtonWrapper.style.backgroundColor = '#FFFFFF';
            }
        });

        // 创建图标
        const iconSpan = document.createElement('span');
        iconSpan.className = 'ds-button__icon';
        iconSpan.style.cssText = `
            width: 20px;
            height: 20px;
            display: flex;
            align-items: center;
            justify-content: center;
            flex-shrink: 0;
            color: #1c1c1c;
            margin-right: -1px;
        `;

        const iconSvg = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
        iconSvg.setAttribute('width', '18');
        iconSvg.setAttribute('height', '18');
        iconSvg.setAttribute('viewBox', '0 0 16 16');
        iconSvg.setAttribute('fill', 'none');
        iconSvg.style.cssText = `
            color: inherit;
            width: 100%;
            height: 100%;
        `;
        iconSvg.innerHTML = `
            <path d="M8 1.5L9.79611 5.11475L13.7063 5.68237L10.8532 8.46525L11.5922 12.3676L8 10.52L4.40785 12.3676L5.14683 8.46525L2.29366 5.68237L6.20389 5.11475L8 1.5Z"
                  stroke="currentColor"
                  fill="none"
                  stroke-width="1.5"
                  stroke-linecap="round"
                  stroke-linejoin="round"/>
        `;
        iconSpan.appendChild(iconSvg);

        // 创建按钮文本
        const buttonText = document.createElement('span');
        buttonText.className = 'ad0c98fd';
        buttonText.style.cssText = `
            font-size: 12px;
            line-height: 1;
            color: rgb(76, 76, 76);
        `;
        buttonText.textContent = '提示词库';

        promptButtonWrapper.appendChild(iconSpan);
        promptButtonWrapper.appendChild(buttonText);

        // 创建一个包装容器
        const wrapperDiv = document.createElement('div');
        wrapperDiv.style.cssText = `
            display: inline-flex;
            align-items: center;
            position: relative;
        `;
        wrapperDiv.appendChild(promptButtonWrapper);

        // 将按钮插入到容器中的第二个位置
        const buttons = buttonContainer.children;
        if (buttons.length >= 1) {
            buttonContainer.insertBefore(wrapperDiv, buttons[1]);
        } else {
            buttonContainer.appendChild(wrapperDiv);
        }

        // 创建提示词列表容器
        const promptList = document.createElement('div');
        promptList.className = 'prompt-list';
        promptList.style.cssText = `
            position: fixed;
            background-color: #fff;
            border: 1px solid rgba(0, 0, 0, 0.1);
            border-radius: 8px;
            box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
            width: 300px;
            max-height: 400px;
            overflow-y: auto;
            z-index: 1000;
            display: none;
            padding: 8px;
        `;

        // 添加样式到 head
        const style = document.createElement('style');
        style.textContent = `
            .prompt-header {
                display: flex;
                justify-content: space-between;
                align-items: center;
                padding: 4px 8px;
                margin-bottom: 4px;
            }
            .prompt-title {
                font-size: 14px;
                font-weight: 500;
                margin: 0;
            }
            .add-prompt-btn {
                display: flex;
                align-items: center;
                gap: 4px;
                padding: 4px 8px;
                border: none;
                background: rgb(79, 70, 229);
                color: white;
                border-radius: 4px;
                font-size: 12px;
                cursor: pointer;
            }
            .prompt-item {
                display: flex;
                align-items: flex-start;
                padding: 8px 12px;
                border-radius: 6px;
                margin: 4px 0;
                border: 1px solid transparent;
                transition: all 0.2s;
                cursor: pointer;
                position: relative;
                gap: 6px;
            }
            .prompt-item:hover {
                background: rgb(248, 248, 249);
                border-color: rgba(0, 0, 0, 0.06);
            }
            .prompt-item-left {
                font-size: 13px;
                font-weight: 600;
                color: #1c1c1c;
                overflow: hidden;
                text-overflow: ellipsis;
                white-space: nowrap;
                flex-shrink: 0;
                position: relative;
                padding-right: 12px;
            }
            .prompt-item-left::after {
                content: '';
                position: absolute;
                right: 6px;
                top: 50%;
                transform: translateY(-50%);
                width: 1px;
                height: 14px;
                background-color: rgba(0, 0, 0, 0.1);
            }
            .prompt-item-content {
                flex: 1;
                min-width: 0;
                font-size: 13px;
                color: #666;
                overflow: hidden;
                text-overflow: ellipsis;
                white-space: nowrap;
                margin-right: 4px;
                line-height: 1.5;
            }
            .prompt-actions {
                position: static;
                display: none;
                transform: none;
                margin-left: auto;
                padding-left: 4px;
                opacity: 0;
                transition: opacity 0.2s;
            }
            .prompt-item:hover .prompt-actions {
                display: flex;
                opacity: 1;
            }
            .delete-prompt {
                background-color: #dc2626;
                color: white;
                padding: 3px 8px;
                border-radius: 4px;
                transition: background-color 0.2s;
                font-size: 12px;
                line-height: 1.5;
                border: none;
                cursor: pointer;
                white-space: nowrap;
            }
            .delete-prompt:hover {
                background-color: #b91c1c;
                color: white;
            }
            .confirm-dialog {
                position: fixed;
                top: 50%;
                left: 50%;
                transform: translate(-50%, -50%);
                background: white;
                padding: 20px;
                border-radius: 8px;
                box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
                z-index: 1003;
                width: 300px;
            }
            .confirm-dialog-overlay {
                position: fixed;
                top: 0;
                left: 0;
                right: 0;
                bottom: 0;
                background: rgba(0, 0, 0, 0.5);
                z-index: 1002;
            }
            .confirm-dialog-title {
                font-size: 16px;
                font-weight: 500;
                margin-bottom: 12px;
                color: #1c1c1c;
            }
            .confirm-dialog-buttons {
                display: flex;
                justify-content: flex-end;
                gap: 8px;
                margin-top: 16px;
            }
            .confirm-dialog-button {
                padding: 6px 12px;
                border: none;
                border-radius: 4px;
                cursor: pointer;
                font-size: 14px;
            }
            .confirm-dialog-cancel {
                background: #f3f4f6;
                color: #374151;
            }
            .confirm-dialog-cancel:hover {
                background: #e5e7eb;
            }
            .confirm-dialog-confirm {
                background: #dc2626;
                color: white;
            }
            .confirm-dialog-confirm:hover {
                background: #b91c1c;
            }
        `;
        document.head.appendChild(style);

        wrapperDiv.appendChild(promptList);

        // 点击按钮时的处理
        promptButtonWrapper.addEventListener('click', () => {
            const isVisible = promptList.style.display === 'none';
            if (isVisible) {
                promptList.style.display = 'block';
                updatePromptList();  // 更新列表内容
                updatePromptListPosition();  // 计算位置
                promptButtonWrapper.style.backgroundColor = 'rgb(195,218,248)';
                buttonText.style.color = 'rgb(77,107,254)';
                iconSpan.style.color = 'rgb(77,107,254)';
            } else {
                promptList.style.display = 'none';
                promptButtonWrapper.style.backgroundColor = '#FFFFFF';
                buttonText.style.color = 'rgb(76, 76, 76)';
                iconSpan.style.color = '#1c1c1c';
            }
        });

        // 点击页面其他地方时也要恢复颜色
        document.addEventListener('click', (e) => {
            const promptButtonWrapper = document.querySelector('.prompt-saver-button');
            const promptList = document.querySelector('.prompt-list');

            // 如果点击的是提示词列表内部或按钮本身,不关闭列表
            if (promptButtonWrapper.contains(e.target) ||
                (promptList && promptList.contains(e.target))) {
                return;
            }

            // 其他区域的点击才关闭列表
            if (promptList) {
                promptList.style.display = 'none';
                promptButtonWrapper.style.backgroundColor = '#FFFFFF';
                promptButtonWrapper.querySelector('.ad0c98fd').style.color = 'rgb(76, 76, 76)';
                promptButtonWrapper.querySelector('.ds-button__icon').style.color = '#1c1c1c';
            }
        });
    }

    function updatePromptList() {
        const promptList = document.querySelector('.prompt-list');
        const savedPrompts = GM_getValue('savedPrompts', []);

        // 更新 HTML 内容
        promptList.innerHTML = `
            <div class="prompt-header">
                <h3 class="prompt-title">我创建的</h3>
                <div class="prompt-header-buttons">
                    <button class="import-export-btn" title="导入/导出">
                        <svg width="16" height="16" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
                            <path d="M12 3v12m0 0l-4-4m4 4l4-4M8 17H6a2 2 0 01-2-2V5a2 2 0 012-2h12a2 2 0 012 2v10a2 2 0 01-2 2h-2" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
                        </svg>
                    </button>
                    <button class="add-prompt-btn">
                        <svg width="14" height="14" viewBox="0 0 14 14" fill="none" xmlns="http://www.w3.org/2000/svg">
                            <path d="M7 2.33334V11.6667" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/>
                            <path d="M11.6667 7L2.33334 7" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/>
                        </svg>
                        创建指令
                    </button>
                </div>
            </div>
            <div class="prompt-list-content">
                ${savedPrompts.map((prompt, index) => `
                    <div class="prompt-item" data-content="${encodeURIComponent(prompt.content)}">
                        <div class="prompt-item-left">${prompt.title}</div>
                        <div class="prompt-item-content">${prompt.content}</div>
                        <div class="prompt-actions">
                            <button class="prompt-action-btn edit-prompt" data-index="${index}">
                                <svg width="16" height="16" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
                                    <path d="M16.474 5.408l2.118 2.117m-.756-3.982L12.109 9.27a2.118 2.118 0 0 0-.58 1.082L11 13l2.648-.53c.41-.082.786-.283 1.082-.579l5.727-5.727a1.853 1.853 0 1 0-2.621-2.621z" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
                                    <path d="M19 15v3a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V7a2 2 0 0 1 2-2h3" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
                                </svg>
                            </button>
                        </div>
                    </div>
                `).join('')}
            </div>
        `;

        // 为每个提示词项添加点击事件
        const promptItems = promptList.querySelectorAll('.prompt-item');
        promptItems.forEach(item => {
            item.addEventListener('click', async function(e) {
                // 如果点击的是编辑按钮,不执行填充操作
                if (e.target.closest('.edit-prompt')) {
                    return;
                }

                const content = decodeURIComponent(this.dataset.content);
                try {
                    // 找到输入框并填充内容
                    const textArea = document.querySelector('#chat-input');
                    if (!textArea) {
                        throw new Error('找不到输入框');
                    }

                    // 先聚焦输入框
                    textArea.focus();
                    // 选中所有内容并删除
                    document.execCommand('selectAll', false, null);
                    document.execCommand('delete', false, null);
                    // 插入新内容
                    document.execCommand('insertText', false, content);

                    // 关闭提示词列表并恢复按钮样式
                    promptList.style.display = 'none';
                    const promptButton = document.querySelector('.prompt-saver-button');
                    if (promptButton) {
                        promptButton.style.backgroundColor = '#FFFFFF';
                        promptButton.querySelector('.ad0c98fd').style.color = 'rgb(76, 76, 76)';
                        promptButton.querySelector('.ds-button__icon').style.color = '#1c1c1c';
                    }
                } catch (err) {
                    console.error('Failed to fill prompt:', err);
                    alert('填充失败,请重试');
                }
            });
        });

        // 为编辑按钮添加事件监听
        promptList.querySelectorAll('.edit-prompt').forEach(button => {
            button.addEventListener('click', function(e) {
                e.stopPropagation();
                const index = parseInt(this.dataset.index);
                showEditPromptModal(savedPrompts[index], index);
            });
        });

        // 为创建指令按钮添加点击事件
        const addButton = promptList.querySelector('.add-prompt-btn');
        addButton?.addEventListener('click', () => showEditPromptModal());

        setupImportExport();
    }

    function showEditPromptModal(prompt = null, index = null) {
        const isEditing = prompt !== null;
        const modal = document.createElement('div');
        modal.className = 'modal-overlay';
        modal.innerHTML = `
            <div class="modal-content">
                <div class="modal-header" style="color: #1c1c1c;">
                    ${isEditing ? '编辑指令' : '创建指令'}
                    ${isEditing ? `
                        <button class="delete-prompt" style="position: absolute; right: 50px; top: 24px;">
                            删除
                        </button>
                    ` : ''}
                    <button class="modal-close">✕</button>
                </div>
                <div class="form-group">
                    <label class="form-label">指令标题<span>*</span></label>
                    <input type="text" class="form-input" placeholder="请输入指令标题" value="${isEditing ? prompt.title : ''}" style="padding: 8px 12px;">
                </div>
                <div class="form-group">
                    <label class="form-label">指令内容<span>*</span></label>
                    <textarea class="form-input" placeholder="请输入指令内容" style="padding: 12px 16px;">${isEditing ? prompt.content : ''}</textarea>
                </div>
                <div class="modal-footer">
                    <button class="save-btn">${isEditing ? '保存修改' : '保存'}</button>
                </div>
            </div>
        `;

        document.body.appendChild(modal);

        // 如果是新建且有当前输入框的内容,自动填充到内容框
        if (!isEditing) {
            const textArea = document.querySelector('[role="textbox"]');
            if (textArea && textArea.textContent.trim()) {
                modal.querySelector('textarea').value = textArea.textContent.trim();
            }
        }

        // 删除按钮事件
        if (isEditing) {
            const deleteBtn = modal.querySelector('.delete-prompt');
            deleteBtn.onclick = () => {
                const overlay = document.createElement('div');
                overlay.className = 'confirm-dialog-overlay';
                overlay.innerHTML = `
                    <div class="confirm-dialog">
                        <div class="confirm-dialog-title">确认删除</div>
                        <div>确定要删除这条提示词吗?此操作无法撤销。</div>
                        <div class="confirm-dialog-buttons">
                            <button class="confirm-dialog-button confirm-dialog-cancel">取消</button>
                            <button class="confirm-dialog-button confirm-dialog-confirm">删除</button>
                        </div>
                    </div>
                `;
                document.body.appendChild(overlay);

                overlay.querySelector('.confirm-dialog-cancel').onclick = () => {
                    document.body.removeChild(overlay);
                };

                overlay.querySelector('.confirm-dialog-confirm').onclick = () => {
                    const savedPrompts = GM_getValue('savedPrompts', []);
                    savedPrompts.splice(index, 1);
                    GM_setValue('savedPrompts', savedPrompts);
                    document.body.removeChild(modal);
                    document.body.removeChild(overlay);
                    updatePromptList();
                };

                overlay.onclick = (e) => {
                    if (e.target === overlay) {
                        document.body.removeChild(overlay);
                    }
                };
            };
        }

        // 关闭按钮事件
        const closeBtn = modal.querySelector('.modal-close');
        closeBtn.onclick = () => {
            document.body.removeChild(modal);
        };

        // 点击遮罩层关闭
        modal.onclick = (e) => {
            if (e.target === modal) {
                document.body.removeChild(modal);
            }
        };

        // 保存按钮事件
        const saveBtn = modal.querySelector('.save-btn');
        saveBtn.onclick = () => {
            const title = modal.querySelector('input').value.trim();
            const content = modal.querySelector('textarea').value.trim();

            if (!title || !content) {
                alert('请填写完整信息');
                return;
            }

            const savedPrompts = GM_getValue('savedPrompts', []);
            if (isEditing) {
                savedPrompts[index] = { title, content };
            } else {
                savedPrompts.push({ title, content });
            }
            GM_setValue('savedPrompts', savedPrompts);

            document.body.removeChild(modal);
            updatePromptList();
        };
    }

    // 优化弹出框定位逻辑
    function updatePromptListPosition() {
        const promptList = document.querySelector('.prompt-list');
        const button = document.querySelector('.prompt-saver-button');
        if (!promptList || !button) return;

        const { top, bottom, left } = button.getBoundingClientRect();
        const promptListHeight = promptList.getBoundingClientRect().height;

        // 判断是否在主界面
        const isMainPage = window.location.pathname === '/';
        
        if (isMainPage) {
            // 主界面:显示在输入框上方中间位置
            const inputArea = document.querySelector('[aria-label="给 DeepSeek 发送消息"]');
            if (inputArea) {
                const inputRect = inputArea.getBoundingClientRect();
                const topPosition = inputRect.top - promptListHeight - 20;
                const leftPosition = inputRect.left + (inputRect.width - promptList.offsetWidth) / 2;
                
                promptList.style.position = 'fixed';
                promptList.style.top = `${topPosition}px`;
                promptList.style.left = `${leftPosition}px`;
            }
        } else {
            // chat页面:显示在按钮上方
            const topPosition = top < promptListHeight + 10 ? bottom + 10 : top - promptListHeight - 10;
            
            promptList.style.position = 'fixed';
            promptList.style.left = `${left}px`;
            promptList.style.top = `${topPosition}px`;
        }

        // 确保列表不会超出视口边界
        const promptListRect = promptList.getBoundingClientRect();
        if (promptListRect.right > window.innerWidth) {
            promptList.style.left = `${window.innerWidth - promptList.offsetWidth - 10}px`;
        }
        if (promptListRect.left < 0) {
            promptList.style.left = '10px';
        }
    }

    // 使用防抖优化窗口大小变化监听
    const debounce = (fn, delay) => {
        let timer = null;
        return function (...args) {
            clearTimeout(timer);
            timer = setTimeout(() => fn.apply(this, args), delay);
        };
    };

    window.addEventListener('resize', debounce(() => {
        if (promptList.style.display !== 'none') {
            updatePromptListPosition();
        }
    }, 100));

    // 优化 MutationObserver
    const observer = new MutationObserver((mutations, obs) => {
        const buttonContainer = document.querySelector('.ec4f5d61');
        if (buttonContainer && !document.querySelector('.prompt-saver-button')) {
            createElements();
        }
    });

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

    // 初始化
    createElements();

    // 添加导入导出功能
    function setupImportExport() {
        const importExportBtn = document.querySelector('.import-export-btn');
        if (!importExportBtn) return;

        importExportBtn.addEventListener('click', (e) => {
            e.stopPropagation();

            // 移除已存在的菜单
            const existingMenu = document.querySelector('.import-export-menu');
            if (existingMenu) {
                existingMenu.remove();
                return;
            }

            // 创建菜单
            const menu = document.createElement('div');
            menu.className = 'import-export-menu';
            menu.innerHTML = `
                <button class="export-btn">导出提示词</button>
                <button class="import-btn">导入提示词</button>
            `;

            // 定位菜单
            const btnRect = importExportBtn.getBoundingClientRect();
            menu.style.position = 'fixed';
            menu.style.top = `${btnRect.bottom + 4}px`;
            menu.style.right = `${window.innerWidth - btnRect.right}px`;

            document.body.appendChild(menu);

            // 导出功能
            menu.querySelector('.export-btn').addEventListener('click', () => {
                const savedPrompts = GM_getValue('savedPrompts', []);
                const blob = new Blob([JSON.stringify(savedPrompts, null, 2)], { type: 'application/json' });
                const url = URL.createObjectURL(blob);
                const a = document.createElement('a');
                a.href = url;
                a.download = 'deepseek-prompts.json';
                document.body.appendChild(a);
                a.click();
                document.body.removeChild(a);
                URL.revokeObjectURL(url);
                menu.remove();
            });

            // 导入功能
            menu.querySelector('.import-btn').addEventListener('click', () => {
                const input = document.createElement('input');
                input.type = 'file';
                input.accept = '.json';
                input.onchange = (e) => {
                    const file = e.target.files[0];
                    if (file) {
                        const reader = new FileReader();
                        reader.onload = (e) => {
                            try {
                                const prompts = JSON.parse(e.target.result);
                                if (Array.isArray(prompts)) {
                                    GM_setValue('savedPrompts', prompts);
                                    updatePromptList();
                                    alert('导入成功!');
                                } else {
                                    alert('文件格式错误!');
                                }
                            } catch (err) {
                                alert('导入失败,请确保文件格式正确!');
                            }
                        };
                        reader.readAsText(file);
                    }
                };
                input.click();
                menu.remove();
            });

            // 点击其他地方关闭菜单
            document.addEventListener('click', function closeMenu(e) {
                if (!menu.contains(e.target) && !importExportBtn.contains(e.target)) {
                    menu.remove();
                    document.removeEventListener('click', closeMenu);
                }
            });
        });
    }
})();