暂时论坛里唯一一个功能+颜值+格式支持达到95%完美度的一个表情脚本!!!

原贴:https://www.nodeseek.com/post-418576-1
作者:@ez9l

修改内容:

  • 添加DeepFlood支持。
  • 调整表情列表到组列表下面。
  • 添加只有在发新贴与回贴界面才会显示“表情包”按键。
  • 调整了面板宽度,尽量做到左右边距平衡。
  • “功能键”做了小修正,显示在同一行里。

预览图:

代码:

// ==UserScript==// @name         NodeSeekEmoji// @namespace    https://nodeseek.com/// @version      2.4.1// @description  表情分组// @match        https://www.nodeseek.com/new*// @match        https://www.nodeseek.com/post*// @match        https://www.deepflood.com/new*// @match        https://www.deepflood.com/post*// @icon         https://www.google.com/s2/favicons?sz=64&domain=www.deepflood.com// @grant        GM_getValue// @grant        GM_setValue// ==/UserScript==(function () {  'use strict';  const KEY = "emojiGroupsData";  const TOOL_URL = "https://nodeseekimagetool.pages.dev/";  let groups = [];  let gi = 0;  let del = false;  async function load() {    const s = await GM_getValue(KEY, "[]");    try { groups = JSON.parse(s); } catch { groups = []; }    if (!Array.isArray(groups) || groups.length === 0) groups = [{ name: "默认分组", emojis: [] }];  }  async function save() { await GM_setValue(KEY, JSON.stringify(groups)); }  function btn(txt, fn) {    const b = document.createElement("button");    b.textContent = txt;    b.className = "ns-btn";    b.onclick = fn;    return b;  }  const css = document.createElement("style");  css.textContent = `  .ns *{box-sizing:border-box}  .ns-panel{    position:fixed; bottom:150px; right:30px; z-index:9999;    width:342px; max-height:520px; overflow-y:auto; overflow-x:hidden;    background:linear-gradient(180deg,rgba(255,255,255,.18),rgba(255,255,255,.12));    backdrop-filter:blur(20px) saturate(180%); border:1px solid rgba(240, 240, 240, 0.4);    border-radius:14px; box-shadow: 0 0 30px 10px rgba(0, 0, 0, .3);    padding:14px; display:none;  }  .ns-bar,.ns-actions,.ns-grid{width:100%}  .ns-bar{display:flex; flex-wrap:wrap; gap:8px; margin-bottom:10px}  .ns-btn{    background:rgba(255,255,255,.22); color:#111; border:1px solid rgba(255,255,255,.35);    border-radius:10px; padding:6px 12px; font-size:12px; cursor:pointer;    transition:all .2s ease; box-shadow:0 1px 2px rgba(0,0,0,.06)  }  .ns-btn:hover{background:rgba(0,0,0,.85); color:#fff}  .ns-btn.active{background:rgba(255,193,7,.9); color:#111; border-color:rgba(255,193,7,.9)}  .ns-input{    width:100%; min-height:64px; margin:12px 0 12px 0; padding:12px 14px; display:block;    background:rgba(255,255,255,.18); backdrop-filter:blur(12px);    border:1px solid rgba(255,255,255,.35); border-radius:12px; color:#111; font-size:12px;    outline:none;  }  .ns-input::placeholder{color:rgba(0,0,0,.6)}  .ns-actions{display:flex; flex-wrap:wrap; gap:8px; margin-bottom:10px}  .ns-grid{display:flex; flex-wrap:wrap; gap:8px}  .ns-item{position:relative}  .ns-img{    width:60px; height:60px; object-fit:contain; border:1px solid #ddd; border-radius:8px; cursor:pointer; background:#fff  }  .ns-del{    position:absolute; top:-6px; right:-6px; width:20px; height:20px; line-height:20px;    text-align:center; font-size:12px; color:#fff; background:#f33; border-radius:50%; cursor:pointer  }  .ns-main{    position:fixed; bottom:100px; right:30px; z-index:9999;    background:rgba(0,0,0,.8); color:#fff; border:1px solid rgba(255,255,255,.35);    padding:10px 14px; border-radius:14px; font-size:14px; font-weight:700; cursor:pointer;    box-shadow:0 4px 12px rgba(0,0,0,.25); user-select:none  }`  document.head.appendChild(css);  const main = document.createElement("div");  main.className = "ns ns-main";  main.textContent = "🐤 表情包";  const panel = document.createElement("div");  panel.className = "ns ns-panel";  const bar = document.createElement("div");  bar.className = "ns-bar";  function drawBar() {    bar.innerHTML = "";    groups.forEach((g, i) => {      const b = btn(g.name, () => { gi = i; drawBar(); drawGrid(); });      if (i === gi) b.classList.add("active");      bar.appendChild(b);    });    const add = btn("+分组", async () => {      const name = prompt("输入新分组名:");      if (!name) return;      groups.push({ name, emojis: [] });      gi = groups.length - 1;      await save(); drawBar(); drawGrid();    });    bar.appendChild(add);  }  const input = document.createElement("textarea");  input.className = "ns-input";  input.placeholder = "支持多行添加图片链接(每行一个)";  const actions = document.createElement("div");  actions.className = "ns-actions";  const addBtn = btn("添加图片", async () => {    const lines = input.value.split("\n").map(s=>s.trim()).filter(s=>/^https?:\/\//i.test(s));    if (!lines.length) return;    groups[gi].emojis.push(...lines);    await save(); input.value = ""; drawGrid();  });  const clrBtn = btn("清空本组", async () => {    if (!confirm("确定要清空本组所有图片?")) return;    groups[gi].emojis = []; await save(); drawGrid();  });  const delBtn = btn("删除:关闭", () => {    del = !del; delBtn.textContent = del ? "删除:开启" : "删除:关闭"; drawGrid();  });  const toolBtn = btn("图片工具", () => window.open(TOOL_URL, "_blank"));  actions.append(addBtn, clrBtn, delBtn, toolBtn);  const grid = document.createElement("div");  grid.className = "ns-grid";  function insert(url) {    const md = `![image|128x128](${url})\n`;    const run = () => {      const w = document.querySelector('#cm-editor-wrapper .CodeMirror');      if (w && w.CodeMirror) {        const cm = w.CodeMirror, d = cm.getDoc();        d.replaceRange(md, d.getCursor()); cm.focus(); return true;      }      const ta = document.querySelector(".d-editor-input");      if (ta) {        ta.value += md; ta.dispatchEvent(new Event("input",{bubbles:true})); ta.focus(); return true;      }      return false;    };    if (run()) return;    const r = document.querySelector("button.reply-to-post"); if (r) r.click();    let t = 0; const h = setInterval(()=>{ if (run() || ++t>=20) clearInterval(h); },300);  }  function drawGrid() {    grid.innerHTML = "";    groups[gi].emojis.forEach((u, idx) => {      const item = document.createElement("div");      item.className = "ns-item";      const img = document.createElement("img");      img.className = "ns-img"; img.src = u; img.title = "点击插入到回复框";      img.onclick = () => insert(u);      item.appendChild(img);      if (del) {        const x = document.createElement("div");        x.className = "ns-del"; x.textContent = "✕";        x.onclick = async (e)=>{ e.stopPropagation(); groups[gi].emojis.splice(idx,1); await save(); drawGrid(); };        item.appendChild(x);      }      grid.appendChild(item);    });  }  main.addEventListener("click", () => panel.style.display = panel.style.display === "none" ? "block" : "none");  (async function init(){    await load();    drawBar(); drawGrid();    // The order of elements is changed here to move the grid up    panel.append(bar, grid, input, actions);    document.body.append(main, panel);  })();})();