DeepSeek r1 关键词

选中关键词显示解释按钮,支持持续对话的DeepSeek交互

当前为 2025-01-31 提交的版本,查看 最新版本

// ==UserScript==
// @name         DeepSeek r1 关键词
// @namespace    http://tampermonkey.net/
// @version      0.6
// @description  选中关键词显示解释按钮,支持持续对话的DeepSeek交互
// @author       Shen yao
// @match        *://*/*
// @grant        GM_xmlhttpRequest
// @grant        GM_setValue
// @grant        GM_getValue
// @grant        GM_registerMenuCommand
// @connect      api.deepseek.com
// @license      GPL-3.0 License
// ==/UserScript==

(function() {
    'use strict';

    const API_URL = 'https://api.deepseek.com/v1/chat/completions';
    let currentPopup = null;
    let currentButton = null;

    GM_registerMenuCommand('设置DeepSeek API密钥', () => {
        const apiKey = prompt('请输入您的DeepSeek API密钥:', GM_getValue('api_key', ''));
        if (apiKey !== null) {
            GM_setValue('api_key', apiKey.trim());
        }
    });

    function createActionButton(x, y) {
        if (currentButton) {
            document.body.removeChild(currentButton);
            currentButton = null;
        }

        const btn = document.createElement('div');
        btn.innerHTML = '🔍Deepseek';
        btn.style.position = 'absolute';
        btn.style.left = `${x + 15}px`;
        btn.style.top = `${y}px`;
        btn.style.backgroundColor = '#4CAF50';
        btn.style.color = 'white';
        btn.style.padding = '5px 10px';
        btn.style.borderRadius = '4px';
        btn.style.cursor = 'pointer';
        btn.style.zIndex = 10000;
        btn.style.boxShadow = '0 2px 5px rgba(0,0,0,0.2)';
        btn.style.fontSize = '12px'; // 调小字体

        btn.addEventListener('click', (e) => {
            e.stopPropagation();
            document.body.removeChild(btn);
            currentButton = null;
        });

        return btn;
    }

    function showInteractivePopup(initialMessages) {
        if (currentPopup) document.body.removeChild(currentPopup);

        const popup = document.createElement('div');
        popup.style.cssText = `
            position: fixed;
            background: white;
            padding: 12px;
            border-radius: 8px;
            box-shadow: 0 5px 15px rgba(0,0,0,0.3);
            z-index: 9999;
            width: 60%;
            max-width: 350px;
            max-height: 50vh;
            display: flex;
            flex-direction: column;
            border: 1px solid #ddd;
            left: 50%;
            top: 50%;
            transform: translate(-50%, -50%);
        `;

        // 添加可拖动标题栏
        const header = document.createElement('div');
        header.style.cssText = `
            display: flex;
            justify-content: space-between;
            align-items: center;
            padding: 8px 10px;
            background: #f5f5f5;
            border-radius: 8px 8px 0 0;
            cursor: move;
            margin: -12px -12px 12px -12px;
        `;

        const title = document.createElement('span');
        title.textContent = 'DeepSeek 对话';
        title.style.fontSize = '13px';
        title.style.color = '#333';

        const closeBtn = document.createElement('button');
        closeBtn.textContent = '×';
        closeBtn.style.cssText = `
            padding: 0;
            background: none;
            border: none;
            font-size: 18px;
            cursor: pointer;
            color: #666;
            width: 22px;
            height: 22px;
            display: flex;
            align-items: center;
            justify-content: center;
        `;
        closeBtn.addEventListener('click', () => {
            document.body.removeChild(popup);
            currentPopup = null;
        });
        closeBtn.addEventListener('mouseover', () => {
            closeBtn.style.color = '#f44336';
        });
        closeBtn.addEventListener('mouseout', () => {
            closeBtn.style.color = '#666';
        });

        header.appendChild(title);
        header.appendChild(closeBtn);

        const contentDiv = document.createElement('div');
        contentDiv.style.cssText = `
            overflow-y: auto;
            flex-grow: 1;
            margin-bottom: 12px;
            padding: 4px;
            font-size: 12px;
            color: #333;
        `;

        const inputContainer = document.createElement('div');
        inputContainer.style.cssText = `
            display: flex;
            gap: 8px;
            margin-top: 8px;
        `;

        const inputField = document.createElement('input');
        inputField.type = 'text';
        inputField.style.cssText = `
            flex-grow: 1;
            padding: 6px;
            border: 1px solid #ddd;
            border-radius: 4px;
            font-size: 12px;
        `;

        const sendBtn = document.createElement('button');
        sendBtn.textContent = '发送';
        sendBtn.style.cssText = `
            padding: 6px 12px;
            background-color: #4CAF50;
            color: white;
            border: none;
            border-radius: 4px;
            cursor: pointer;
            font-size: 12px;
        `;

        // 拖动处理逻辑
        let isDragging = false;
        let startX, startY, initialX, initialY;

        header.addEventListener('mousedown', function(e) {
            isDragging = true;
            const rect = popup.getBoundingClientRect();
            startX = e.clientX;
            startY = e.clientY;
            initialX = rect.left;
            initialY = rect.top;
            e.preventDefault();
        });

        document.addEventListener('mousemove', function(e) {
            if (!isDragging) return;
            const dx = e.clientX - startX;
            const dy = e.clientY - startY;
            popup.style.transform = 'none';
            popup.style.left = `${initialX + dx}px`;
            popup.style.top = `${initialY + dy}px`;
        });

        document.addEventListener('mouseup', function() {
            isDragging = false;
        });

        function updateContent(messages) {
            contentDiv.innerHTML = messages
                .filter(msg => msg.role !== 'system')
                .map(msg => {
                    const isUser = msg.role === 'user';
                    return `
                        <div style="margin: 8px 0; text-align: ${isUser ? 'right' : 'left'}">
                            <div style="
                                display: inline-block;
                                background: ${isUser ? '#e3f2fd' : '#f5f5f5'};
                                color: #333;
                                padding: 6px 10px;
                                border-radius: 8px;
                                max-width: 80%;
                                word-wrap: break-word;
                                font-size: 12px;
                                line-height: 1.4;
                            ">
                                ${msg.content.replace(/\n/g, '<br>')}
                            </div>
                        </div>
                    `;
                })
                .join('');
            contentDiv.scrollTop = contentDiv.scrollHeight;
        }

        updateContent(initialMessages);

        sendBtn.onclick = () => {
            const question = inputField.value.trim();
            if (!question) return;

            const userMessage = { role: 'user', content: question };
            initialMessages.push(userMessage);

            const tempMessage = { role: 'assistant', content: '正在思考中...' };
            initialMessages.push(tempMessage);
            updateContent(initialMessages);
            inputField.value = '';
            sendBtn.disabled = true;

            GM_xmlhttpRequest({
                method: "POST",
                url: API_URL,
                headers: {
                    "Content-Type": "application/json",
                    "Authorization": `Bearer ${GM_getValue('api_key')}`
                },
                data: JSON.stringify({
                    model: "deepseek-reasoner",
                    messages: initialMessages.filter(m => m.content !== '正在思考中...'),
                    temperature: 0.7,
                    max_tokens: 512
                }),
                onload: function(response) {
                    initialMessages.pop();
                    sendBtn.disabled = false;
                    try {
                        const data = JSON.parse(response.responseText);
                        const reply = data.choices[0].message.content;
                        initialMessages.push({ role: 'assistant', content: reply });
                    } catch (e) {
                        initialMessages.push({ role: 'assistant', content: `错误: ${e.message}` });
                    }
                    updateContent(initialMessages);
                },
                onerror: function(err) {
                    initialMessages.pop();
                    sendBtn.disabled = false;
                    initialMessages.push({ role: 'assistant', content: '请求失败,请检查网络连接' });
                    updateContent(initialMessages);
                }
            });
        };

        inputContainer.appendChild(inputField);
        inputContainer.appendChild(sendBtn);
        popup.appendChild(header);
        popup.appendChild(contentDiv);
        popup.appendChild(inputContainer);
        document.body.appendChild(popup);
        currentPopup = popup;
        inputField.focus();
    }

    function getExplanation(text) {
        const apiKey = GM_getValue('api_key');
        if (!apiKey) {
            alert('请先通过油猴菜单设置API密钥');
            return;
        }

        const initialMessages = [
            {
                "role": "system",
                "content": "你是一个联网的百科助手,请使用网络搜索获取最新信息,用简洁易懂的中文回答用户问题。"
            },
            {
                "role": "user",
                "content": `分析推理总结:${text}`
            }
        ];

        GM_xmlhttpRequest({
            method: "POST",
            url: API_URL,
            headers: {
                "Content-Type": "application/json",
                "Authorization": `Bearer ${apiKey}`
            },
            data: JSON.stringify({
                model: "deepseek-chat",
                messages: initialMessages,
                temperature: 0.7,
                max_tokens: 512
            }),
            onload: function(response) {
                try {
                    const data = JSON.parse(response.responseText);
                    const result = data.choices[0].message.content;
                    initialMessages.push({ role: 'assistant', content: result });
                    showInteractivePopup(initialMessages);
                } catch (e) {
                    showPopup(`<span style="color:red">错误:${e.message}</span>`);
                }
            },
            onerror: function(err) {
                showPopup(`<span style="color:red">请求失败:${err.statusText}</span>`);
            }
        });
    }

    document.addEventListener('mouseup', function(e) {
        const selection = window.getSelection().toString().trim();
        if (selection && selection.length > 2) {
            const range = window.getSelection().getRangeAt(0);
            const rect = range.getBoundingClientRect();
            const btn = createActionButton(rect.right + window.scrollX, rect.top + window.scrollY);
            btn.onclick = () => getExplanation(selection);
            document.body.appendChild(btn);
            currentButton = btn;
        }
    });

    document.addEventListener('mousedown', (e) => {
        if (currentButton && !currentButton.contains(e.target)) {
            document.body.removeChild(currentButton);
            currentButton = null;
        }
    });
})();

QingJ © 2025

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