// ==UserScript== // @name AI 提示词大师 Pro 9.0 (稳定填充+分类折叠+预览优化) // @namespace http://tampermonkey.net/ // @version 9.1 // @license AGPL-3.0 // @description 解决填充消失,支持分类折叠、半透明自适应预览、原地编辑、追加模式。 // @author WaterHuo // @match https://gemini.google.com/* // @match https://chatgpt.com/* // @match https://claude.ai/* // @match https://chat.deepseek.com/* // @match https://www.doubao.com/* // @match https://www.kimi.com/* // @grant GM_setValue // @grant GM_getValue // @grant GM_addStyle // @downloadURL none // ==/UserScript== (function() { 'use strict'; // ======= 1. 深度样式表 ======= GM_addStyle(` #pm-root { font-family: -apple-system, system-ui, sans-serif; } .pm-panel { position: fixed; top: 80px; right: 20px; width: 220px; background: #fff; border-radius: 12px; box-shadow: 0 8px 32px rgba(0,0,0,0.1); z-index: 2147483640; border: 1px solid #eee; display: flex; flex-direction: column; } .pm-header { padding: 12px; background: #fcfcfc; border-bottom: 1px solid #f0f0f0; display: flex; justify-content: space-between; align-items: center; border-radius: 12px 12px 0 0; } .pm-title { font-size: 13px; font-weight: 700; color: #1a73e8; display: flex; align-items: center; gap: 5px; } .pm-body { padding: 8px; max-height: 75vh; overflow-y: auto; scrollbar-width: thin; } /* 分类与折叠 */ .pm-cat-wrap { margin-bottom: 8px; border-radius: 8px; overflow: hidden; } .pm-cat-header { display: flex; align-items: center; padding: 6px 4px; background: #f8f9fa; cursor: pointer; group; position: relative; } .pm-cat-fold-icon { font-size: 10px; margin-right: 6px; transition: transform 0.2s; color: #70757a; } .pm-cat-name { font-size: 11px; color: #5f6368; font-weight: 700; flex: 1; text-transform: uppercase; letter-spacing: 0.5px; } .pm-cat-tools { display: none; gap: 6px; margin-right: 4px; } .pm-cat-header:hover .pm-cat-tools { display: flex; } /* 模板列表 */ .pm-tpl-list { padding: 4px 0; } .pm-tpl-list.folded { display: none; } .pm-item-wrap { position: relative; margin-bottom: 2px; } .pm-btn { width: 100%; border: none; background: transparent; padding: 8px 10px; text-align: left; font-size: 12px; border-radius: 6px; cursor: pointer; color: #3c4043; transition: 0.2s; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } .pm-btn:hover { background: #f1f3f4; color: #1a73e8; } /* 预览浮窗 (需求2: 半透明、自适应) */ #pm-preview-float { position: fixed; display: none; width: auto; max-width: 200px; background: rgba(255, 255, 255, 0.85); backdrop-filter: blur(8px); border: 1px solid rgba(0,0,0,0.08); box-shadow: 0 4px 16px rgba(0,0,0,0.1); border-radius: 8px; padding: 10px; font-size: 11px; line-height: 1.4; color: #444; z-index: 2147483647; pointer-events: auto; word-break: break-all; transition: opacity 0.2s; } /* 原地编辑器 (需求3) */ .pm-inline-editor { background: #fff; border: 1px solid #1a73e8; border-radius: 8px; padding: 8px; margin: 4px 0; box-shadow: 0 4px 12px rgba(26,115,232,0.15); } .pm-inline-editor textarea { width: 100%; height: 100px; border: 1px solid #dadce0; border-radius: 4px; padding: 6px; font-size: 12px; box-sizing: border-box; resize: vertical; margin: 5px 0; } .pm-inline-editor input, .pm-inline-editor select { width: 100%; border: 1px solid #dadce0; border-radius: 4px; padding: 4px 6px; font-size: 12px; box-sizing: border-box; margin-bottom: 4px; } .pm-ed-btns { display: flex; justify-content: flex-end; gap: 6px; } .pm-ebtn { padding: 3px 8px; font-size: 11px; border-radius: 4px; cursor: pointer; border: none; } .pm-save { background: #1a73e8; color: #fff; } .pm-cancel { background: #f1f3f4; color: #5f6368; } .pm-toast { position: fixed; bottom: 30px; left: 50%; transform: translateX(-50%); background: #323232; color: #fff; padding: 6px 16px; border-radius: 16px; font-size: 12px; z-index: 2147483647; display: none; } `); // ======= 2. 数据与持久化 ======= const DATA_KEY = 'pm_data_v9'; const FOLD_KEY = 'pm_folded_cats'; let promptData = GM_getValue(DATA_KEY, { "写作类": [{ name: "📝 深度润色", content: "请对以下文本进行优化:先梳理逻辑脉络(若原文条理混乱,可按 “总分 / 因果 / 递进” 等清晰结构重组),再优化语言表达 —— 做到简洁精准、流畅自然,剔除冗余重复内容,完整保留原文核心信息与核心意图,不添加额外修饰,仅提升文本的逻辑性与可读性。" }], "代码类": [{ name: "💻 逻辑审查", content: "请检查这段代码是否存在潜在的逻辑错误..." }] }); let foldedCats = GM_getValue(FOLD_KEY, []); // 存储折叠状态的分类名 let isEditMode = false; let previewLock = false; let appendMode = true; // 默认追加模式 // ======= 3. 稳定填充核心 (解决填充消失问题) ======= async function stableInject(text) { const inputField = document.querySelector('div[role="textbox"], #prompt-textarea, textarea[placeholder*="输入"], #chat-input, [contenteditable="true"], textarea'); if (!inputField) return toast("未找到输入框"); inputField.focus(); const isRich = inputField.isContentEditable; const oldVal = isRich ? inputField.innerText : inputField.value; const newVal = (appendMode && oldVal.trim()) ? (oldVal + "\n" + text) : text; try { if (isRich) { // 针对 Gemini/Claude/DeepSeek 富文本模式 const selection = window.getSelection(); const range = document.createRange(); range.selectNodeContents(inputField); selection.removeAllRanges(); selection.addRange(range); document.execCommand('delete', false); document.execCommand('insertText', false, newVal); } else { // 针对 ChatGPT/豆包/Kimi 原生模式 const setter = Object.getOwnPropertyDescriptor(window.HTMLTextAreaElement.prototype, "value").set; setter.call(inputField, newVal); inputField.dispatchEvent(new Event('input', { bubbles: true })); } toast("填充成功"); // 保持焦点并滚动到底部 inputField.focus(); setTimeout(() => { inputField.scrollTop = inputField.scrollHeight; }, 10); } catch (e) { toast("尝试填充失败"); } } // ======= 4. UI 渲染引擎 ======= function toast(msg) { const t = document.getElementById('pm-toast') || (()=>{ const d = document.createElement('div'); d.id='pm-toast'; d.className='pm-toast'; document.body.appendChild(d); return d; })(); t.innerText = msg; t.style.display = 'block'; setTimeout(() => t.style.display = 'none', 2000); } function renderUI() { let root = document.getElementById('pm-root'); if (!root) { root = document.createElement('div'); root.id = 'pm-root'; document.body.appendChild(root); const pf = document.createElement('div'); pf.id = 'pm-preview-float'; document.body.appendChild(pf); } const previewFloat = document.getElementById('pm-preview-float'); root.innerHTML = `