您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
2024/8/9 23:35:04
// ==UserScript== // @name GPT提示词浮窗 // @namespace Violentmonkey Scripts // @match https://chat.deepseek.com/* // @match https://demo.fuclaude.com/* // @match https://chatgpt.com/* // @grant GM_setValue // @grant GM_getValue // @version 1.5 // @author - // @description 2024/8/9 23:35:04 // ==/UserScript== (function() { 'use strict'; // Keep existing Modal functions function createModal() { const modalOverlay = document.createElement('div'); modalOverlay.style.position = 'fixed'; modalOverlay.style.top = '0'; modalOverlay.style.left = '0'; modalOverlay.style.width = '100%'; modalOverlay.style.height = '100%'; modalOverlay.style.backgroundColor = 'rgba(0, 0, 0, 0.5)'; modalOverlay.style.display = 'flex'; modalOverlay.style.justifyContent = 'center'; modalOverlay.style.alignItems = 'center'; modalOverlay.style.zIndex = '1001'; const modalContent = document.createElement('div'); modalContent.style.backgroundColor = '#2d3748'; modalContent.style.padding = '20px'; modalContent.style.borderRadius = '12px'; modalContent.style.width = '400px'; modalContent.style.maxWidth = '90%'; modalContent.style.boxShadow = '0 4px 6px rgba(0, 0, 0, 0.1)'; modalContent.style.position = 'relative'; return { modalOverlay, modalContent }; } // Confirmation modal for delete function createConfirmModal(message) { return new Promise((resolve) => { const { modalOverlay, modalContent } = createModal(); const messageElement = document.createElement('p'); messageElement.textContent = message; messageElement.style.color = '#e2e8f0'; messageElement.style.marginBottom = '20px'; const buttonContainer = document.createElement('div'); buttonContainer.style.display = 'flex'; buttonContainer.style.gap = '10px'; buttonContainer.style.justifyContent = 'flex-end'; const cancelButton = document.createElement('button'); cancelButton.textContent = 'Cancel'; cancelButton.style.padding = '8px 16px'; cancelButton.style.borderRadius = '6px'; cancelButton.style.border = '1px solid #4a5568'; cancelButton.style.backgroundColor = '#4a5568'; cancelButton.style.color = '#e2e8f0'; cancelButton.style.cursor = 'pointer'; const confirmButton = document.createElement('button'); confirmButton.textContent = 'Delete'; confirmButton.style.padding = '8px 16px'; confirmButton.style.borderRadius = '6px'; confirmButton.style.border = 'none'; confirmButton.style.backgroundColor = '#e53e3e'; confirmButton.style.color = 'white'; confirmButton.style.cursor = 'pointer'; cancelButton.onclick = () => { document.body.removeChild(modalOverlay); resolve(false); }; confirmButton.onclick = () => { document.body.removeChild(modalOverlay); resolve(true); }; buttonContainer.appendChild(cancelButton); buttonContainer.appendChild(confirmButton); modalContent.appendChild(messageElement); modalContent.appendChild(buttonContainer); modalOverlay.appendChild(modalContent); document.body.appendChild(modalOverlay); }); } // Modified input modal to support title and content function createInputModal(type = 'add', initialTitle = '', initialContent = '') { return new Promise((resolve) => { const { modalOverlay, modalContent } = createModal(); const titleElement = document.createElement('h3'); titleElement.textContent = type === 'add' ? 'Add New Phrase' : 'Edit Phrase'; titleElement.style.color = '#e2e8f0'; titleElement.style.marginTop = '0'; titleElement.style.marginBottom = '15px'; titleElement.style.fontSize = '18px'; // Title input const titleLabel = document.createElement('label'); titleLabel.textContent = 'Title:'; titleLabel.style.color = '#e2e8f0'; titleLabel.style.display = 'block'; titleLabel.style.marginBottom = '5px'; const titleInput = document.createElement('input'); titleInput.value = initialTitle; titleInput.style.width = '100%'; titleInput.style.padding = '8px 12px'; titleInput.style.borderRadius = '6px'; titleInput.style.border = '1px solid #4a5568'; titleInput.style.backgroundColor = '#3f495e'; titleInput.style.color = '#e2e8f0'; titleInput.style.fontSize = '14px'; titleInput.style.marginBottom = '15px'; titleInput.style.boxSizing = 'border-box'; // Content input const contentLabel = document.createElement('label'); contentLabel.textContent = 'Content:'; contentLabel.style.color = '#e2e8f0'; contentLabel.style.display = 'block'; contentLabel.style.marginBottom = '5px'; const contentInput = document.createElement('textarea'); contentInput.value = initialContent; contentInput.style.width = '100%'; contentInput.style.padding = '8px 12px'; contentInput.style.borderRadius = '6px'; contentInput.style.border = '1px solid #4a5568'; contentInput.style.backgroundColor = '#3f495e'; contentInput.style.color = '#e2e8f0'; contentInput.style.fontSize = '14px'; contentInput.style.minHeight = '100px'; contentInput.style.resize = 'vertical'; contentInput.style.marginBottom = '15px'; contentInput.style.boxSizing = 'border-box'; const buttonContainer = document.createElement('div'); buttonContainer.style.display = 'flex'; buttonContainer.style.gap = '10px'; buttonContainer.style.justifyContent = 'flex-end'; const cancelButton = document.createElement('button'); cancelButton.textContent = 'Cancel'; cancelButton.style.padding = '8px 16px'; cancelButton.style.borderRadius = '6px'; cancelButton.style.border = '1px solid #4a5568'; cancelButton.style.backgroundColor = '#4a5568'; cancelButton.style.color = '#e2e8f0'; cancelButton.style.cursor = 'pointer'; const saveButton = document.createElement('button'); saveButton.textContent = 'Save'; saveButton.style.padding = '8px 16px'; saveButton.style.borderRadius = '6px'; saveButton.style.border = 'none'; saveButton.style.backgroundColor = '#4299e1'; saveButton.style.color = 'white'; saveButton.style.cursor = 'pointer'; cancelButton.onclick = () => { document.body.removeChild(modalOverlay); resolve(null); }; saveButton.onclick = () => { const title = titleInput.value.trim(); const content = contentInput.value.trim(); if (title && content) { document.body.removeChild(modalOverlay); resolve({ title, content }); } else { if (!title) titleInput.style.border = '1px solid #f56565'; if (!content) contentInput.style.border = '1px solid #f56565'; } }; buttonContainer.appendChild(cancelButton); buttonContainer.appendChild(saveButton); modalContent.appendChild(titleElement); modalContent.appendChild(titleLabel); modalContent.appendChild(titleInput); modalContent.appendChild(contentLabel); modalContent.appendChild(contentInput); modalContent.appendChild(buttonContainer); modalOverlay.appendChild(modalContent); document.body.appendChild(modalOverlay); titleInput.focus(); }); } // Create floating window const floatingWindow = document.createElement('div'); floatingWindow.style.position = 'fixed'; floatingWindow.style.top = '50%'; floatingWindow.style.right = '0'; floatingWindow.style.transform = 'translateY(-50%)'; floatingWindow.style.backgroundColor = '#2d3748'; floatingWindow.style.color = '#e2e8f0'; floatingWindow.style.borderRadius = '8px 0 0 8px'; floatingWindow.style.boxShadow = '0 4px 6px rgba(0, 0, 0, 0.1)'; floatingWindow.style.zIndex = '1000'; floatingWindow.style.transition = 'all 0.3s ease'; floatingWindow.style.cursor = 'pointer'; // Collapsed label const collapsedLabel = document.createElement('div'); collapsedLabel.textContent = '提示词助手'; collapsedLabel.style.padding = '10px'; collapsedLabel.style.writingMode = 'vertical-lr'; collapsedLabel.style.textOrientation = 'upright'; // Grid container const gridContainer = document.createElement('div'); gridContainer.style.display = 'none'; gridContainer.style.gridTemplateColumns = 'repeat(2, 1fr)'; gridContainer.style.gap = '10px'; gridContainer.style.padding = '15px'; gridContainer.style.maxWidth = '400px'; gridContainer.style.maxHeight = '80vh'; gridContainer.style.overflowY = 'auto'; // Load data let phrases = GM_getValue('phrases', []); // Update display function updateGrid() { gridContainer.innerHTML = ''; const pinnedPhrases = phrases.filter(p => p.isPinned); const unpinnedPhrases = phrases.filter(p => !p.isPinned); const sortedPhrases = [...pinnedPhrases, ...unpinnedPhrases]; sortedPhrases.forEach((phrase, index) => { const phraseBox = document.createElement('div'); phraseBox.style.backgroundColor = '#3f495e'; phraseBox.style.padding = '10px'; phraseBox.style.borderRadius = '6px'; phraseBox.style.position = 'relative'; phraseBox.style.cursor = 'pointer'; const title = document.createElement('div'); title.textContent = phrase.title; title.style.marginRight = '25px'; title.style.marginBottom = '20px'; // Add space for buttons // Container for action buttons const actionButtons = document.createElement('div'); actionButtons.style.position = 'absolute'; actionButtons.style.bottom = '5px'; actionButtons.style.right = '5px'; actionButtons.style.display = 'flex'; actionButtons.style.gap = '5px'; // Edit button const editButton = document.createElement('button'); editButton.textContent = '✏️'; editButton.style.border = 'none'; editButton.style.backgroundColor = 'transparent'; editButton.style.cursor = 'pointer'; editButton.style.fontSize = '14px'; // Delete button const deleteButton = document.createElement('button'); deleteButton.textContent = '🗑️'; deleteButton.style.border = 'none'; deleteButton.style.backgroundColor = 'transparent'; deleteButton.style.cursor = 'pointer'; deleteButton.style.fontSize = '14px'; // Pin button const pinButton = document.createElement('button'); pinButton.textContent = phrase.isPinned ? '📌' : '📍'; pinButton.style.position = 'absolute'; pinButton.style.top = '5px'; pinButton.style.right = '5px'; pinButton.style.border = 'none'; pinButton.style.backgroundColor = 'transparent'; pinButton.style.cursor = 'pointer'; pinButton.style.fontSize = '14px'; // Edit functionality editButton.onclick = async (e) => { e.stopPropagation(); const result = await createInputModal('edit', phrase.title, phrase.content); if (result) { const index = phrases.findIndex(p => p.title === phrase.title && p.content === phrase.content ); if (index !== -1) { phrases[index] = { ...phrases[index], ...result }; savePhrases(); updateGrid(); } } }; // Delete functionality deleteButton.onclick = async (e) => { e.stopPropagation(); const confirmed = await createConfirmModal('Are you sure you want to delete this phrase?'); if (confirmed) { phrases = phrases.filter(p => !(p.title === phrase.title && p.content === phrase.content) ); savePhrases(); updateGrid(); } }; pinButton.onclick = (e) => { e.stopPropagation(); const phraseIndex = phrases.findIndex(p => p.title === phrase.title && p.content === phrase.content ); if (phraseIndex !== -1) { const updatedPhrase = {...phrases[phraseIndex]}; if (!updatedPhrase.isPinned) { const lastPinnedIndex = phrases.map(p => p.isPinned).lastIndexOf(true); updatedPhrase.isPinned = true; phrases.splice(phraseIndex, 1); phrases.splice(lastPinnedIndex + 1, 0, updatedPhrase); } else { updatedPhrase.isPinned = false; const firstUnpinnedIndex = phrases.findIndex(p => !p.isPinned); phrases.splice(phraseIndex, 1); phrases.splice(firstUnpinnedIndex === -1 ? phrases.length : firstUnpinnedIndex, 0, updatedPhrase); } savePhrases(); updateGrid(); } }; phraseBox.onclick = () => { navigator.clipboard.writeText(phrase.content); showTooltip(phrase.content); }; actionButtons.appendChild(editButton); actionButtons.appendChild(deleteButton); phraseBox.appendChild(title); phraseBox.appendChild(pinButton); phraseBox.appendChild(actionButtons); gridContainer.appendChild(phraseBox); }); } // Save data function savePhrases() { GM_setValue('phrases', phrases); } // Add button const addButton = document.createElement('button'); addButton.textContent = '+ Add New'; addButton.style.width = '100%'; addButton.style.backgroundColor = '#4299e1'; addButton.style.color = 'white'; addButton.style.border = 'none'; addButton.style.padding = '8px'; addButton.style.borderRadius = '6px'; addButton.style.marginTop = '10px'; addButton.style.cursor = 'pointer'; addButton.style.display = 'none'; addButton.onclick = async () => { const result = await createInputModal('add'); if (result) { phrases.push({ title: result.title, content: result.content, isPinned: false }); savePhrases(); updateGrid(); } }; // Show copy tooltip function showTooltip(text) { const tooltip = document.createElement('div'); tooltip.textContent = 'Copied: ' + (text.length > 30 ? text.substring(0, 30) + '...' : text); tooltip.style.position = 'fixed'; tooltip.style.top = '20px'; tooltip.style.right = '20px'; tooltip.style.backgroundColor = '#48bb78'; tooltip.style.color = 'white'; tooltip.style.padding = '8px 12px'; tooltip.style.borderRadius = '6px'; tooltip.style.zIndex = '1001'; tooltip.style.animation = 'fadeInOut 2s ease-in-out'; // Add CSS animation const style = document.createElement('style'); style.textContent = ` @keyframes fadeInOut { 0% { opacity: 0; transform: translateY(-20px); } 10% { opacity: 1; transform: translateY(0); } 90% { opacity: 1; transform: translateY(0); } 100% { opacity: 0; transform: translateY(-20px); } } `; document.head.appendChild(style); document.body.appendChild(tooltip); setTimeout(() => { document.body.removeChild(tooltip); document.head.removeChild(style); }, 2000); } // Add expand/collapse functionality let isExpanded = false; function toggleWindow() { if (isExpanded) { gridContainer.style.display = 'none'; collapsedLabel.style.display = 'block'; floatingWindow.style.width = 'auto'; addButton.style.display = 'none'; } else { gridContainer.style.display = 'grid'; collapsedLabel.style.display = 'none'; floatingWindow.style.width = '400px'; addButton.style.display = 'block'; } isExpanded = !isExpanded; } floatingWindow.onmouseenter = () => { if (!isExpanded) toggleWindow(); }; floatingWindow.onmouseleave = () => { if (isExpanded) toggleWindow(); }; // Assemble interface floatingWindow.appendChild(collapsedLabel); floatingWindow.appendChild(gridContainer); floatingWindow.appendChild(addButton); document.body.appendChild(floatingWindow); // Initialize display updateGrid(); })();
QingJ © 2025
镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址