Greasy Fork

Greasy Fork is available in English.

✨ OpenWebUI提示词助手(兼容v0.5.20)

为OpenWebUI的高级系统提示词加入类似nextchat的面具功能

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Greasemonkey 油猴子Violentmonkey 暴力猴,才能安装此脚本。

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

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

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

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

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

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

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

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

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

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

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

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

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

// ==UserScript==
// @name         ✨ OpenWebUI提示词助手(兼容v0.5.20)
// @namespace    http://tampermonkey.net/
// @version      1.1
// @description  为OpenWebUI的高级系统提示词加入类似nextchat的面具功能
// @author       tutrabbit
// @match        https://127.0.0.1:8080/*
// @grant        GM_setValue
// @grant        GM_getValue
// @icon         https://s2.loli.net/2024/12/05/lrYpNuECMKzHwOb.png
// @supportURL   https://github.com/susmouse/open-webui-prompt-helper
// @license      CC-BY-NC-4.0
// ==/UserScript==

(function () {
  "use strict";

  // 默认提示词配置
  const defaultPrompts = [
    {
      name: "通用助手",
      prompt:
        "我希望你作为一个专业的助手,帮助我解决各种问题。请用简洁、清晰的语言回答我的问题。",
    },
    {
      name: "外卖好评助手",
      prompt:
        "请你帮我写一则外卖好评,要求语言自然、真诚,突出商家的特色和优点,字数在50-100字之间。",
    },
  ];

  // 初始化提示词
  function initPrompts() {
    const savedPrompts = GM_getValue("prompts");
    if (!savedPrompts) {
      GM_setValue("prompts", defaultPrompts);
    }
    return GM_getValue("prompts");
  }

  // 创建按钮样式
  const style = document.createElement("style");
  style.textContent = `
        .prompt-helper-btn {
            color: #000;
            margin: 3px;
            padding: 3px 6px;
            border: 1px solid #ccc;
            border-radius: 3px;
            background-color: #f8f9fa;
            cursor: pointer;
            display: inline-flex;
            align-items: center;
            font-size: 12px;
        }
        .prompt-helper-btn:hover {
            background-color: #e9ecef;
        }
        .prompt-name {
            color: #000;
            margin-right: 3px;
            cursor: pointer;
        }
        .delete-btn {
            cursor: pointer;
            color: #dc3545;
            padding: 0 3px;
            border-left: 1px solid #ccc;
        }
        .prompt-helper-container {
            margin: 6px 0;
            display: flex;
            flex-wrap: wrap;
            gap: 3px;
        }
        @media (max-width: 768px) {
            .prompt-helper-btn {
                padding: 2px 4px;
                font-size: 10px;
            }
            .prompt-helper-container {
                margin: 4px 0;
            }
        }
    `;
  document.head.appendChild(style);

  // 创建按钮容器
  function createButtonContainer(textarea) {
    const container = document.createElement("div");
    container.className = "prompt-helper-container";
    return container;
  }

  // 创建单个按钮
  function createButton(prompt, container, textarea) {
    const btn = document.createElement("div");
    btn.className = "prompt-helper-btn";

    const nameSpan = document.createElement("span");
    nameSpan.className = "prompt-name";
    nameSpan.textContent = prompt.name;
    nameSpan.onclick = () => {
      textarea.value = prompt.prompt;
      textarea.style.height = "auto";
      textarea.style.height = textarea.scrollHeight + "px";

      // 模拟用户输入,实现对提示词的保存
      const event = new Event("input", { bubbles: true });
      textarea.dispatchEvent(event);
    };

    const deleteSpan = document.createElement("span");
    deleteSpan.className = "delete-btn";
    deleteSpan.textContent = "-";
    deleteSpan.onclick = () => {
      const prompts = GM_getValue("prompts");
      const newPrompts = prompts.filter((p) => p.name !== prompt.name);
      GM_setValue("prompts", newPrompts);
      refreshButtons(container, textarea);
    };

    btn.appendChild(nameSpan);
    btn.appendChild(deleteSpan);
    return btn;
  }

  // 创建添加按钮
  function createAddButton(container, textarea) {
    const btn = document.createElement("button");
    btn.className = "prompt-helper-btn";
    btn.textContent = "+";
    btn.onclick = () => {
      const name = prompt("请输入提示词名称:");
      if (!name) return;
      const promptText = prompt("请输入提示词内容:");
      if (!promptText) return;

      const prompts = GM_getValue("prompts");
      prompts.push({ name, prompt: promptText });
      GM_setValue("prompts", prompts);
      refreshButtons(container, textarea);
    };
    return btn;
  }

  // 刷新按钮
  function refreshButtons(container, textarea) {
    container.innerHTML = "";
    const prompts = GM_getValue("prompts");
    prompts.forEach((prompt) => {
      container.appendChild(createButton(prompt, container, textarea));
    });
    container.appendChild(createAddButton(container, textarea));
  }

  // 主函数
  function init() {
    // 使用更通用的选择器来定位文本框,忽略动态ID部分
    const textarea = document.querySelector(
      "div.pt-8 div.dark\\:text-gray-200.text-sm.font-primary.py-0\\.5.px-0\\.5 > div:nth-child(3) > div:nth-child(2) > div > textarea"
    );

    if (!textarea) {
      //   console.log("没有找到文本框");
      setTimeout(init, 500);
      return;
    }

    // 检查是否已经初始化
    if (textarea.getAttribute("data-prompt-helper-initialized")) {
      return;
    }

    console.log("找到文本框:", textarea);

    // 标记该textarea已经初始化
    textarea.setAttribute("data-prompt-helper-initialized", "true");

    initPrompts();
    const container = createButtonContainer(textarea);
    // 将按钮容器插入到文本框之前
    textarea.parentElement.insertBefore(container, textarea);
    refreshButtons(container, textarea);
  }

  // 创建MutationObserver来监听DOM变化
  const observer = new MutationObserver((mutations) => {
    mutations.forEach((mutation) => {
      if (mutation.type === "childList" || mutation.type === "subtree") {
        init();
      }
    });
  });

  // 监听整个文档的变化
  observer.observe(document.body, {
    childList: true,
    subtree: true,
  });

  // 启动脚本
  init();
})();