因为移动端上没有Shlink插件,我让ai写了一个油猴版本的
目前看来还不错,就是图标略大了点
继续修改,小了一点,可以按域名保存位置了
// ==UserScript==// @name Shlink 一键生成短链接 (记忆位置版)// @namespace http://tampermonkey.net/// @version 1.4// @description 支持 LocalStorage 记忆每个域名的按钮位置,迷你可拖动// @author Gemini// @match *://*/*// @grant GM_xmlhttpRequest// @grant GM_setClipboard// @connect curl.su// ==/UserScript==(function() { 'use strict'; // --- 配置信息 --- const SHLINK_DOMAIN = 'https://curl.su'; const API_KEY = '你的-API-KEY'; const TAG_NAME = 'from-tampermonkey'; const STORAGE_KEY = 'shlink_btn_pos'; // LocalStorage 存储键名 // ---------------- // 读取存储的位置(如果没有则使用默认值) const savedPos = JSON.parse(localStorage.getItem(STORAGE_KEY)) || { bottom: 80, right: 20 }; const container = document.createElement('div'); container.style = ` position: fixed; bottom: ${savedPos.bottom}px; right: ${savedPos.right}px; z-index: 10000; display: flex; flex-direction: column; align-items: center; touch-action: none; `; document.body.appendChild(container); const toast = document.createElement('div'); toast.style = ` background: rgba(0, 0, 0, 0.75); color: white; padding: 5px 10px; border-radius: 6px; font-size: 11px; margin-bottom: 5px; display: none; white-space: nowrap; pointer-events: none; box-shadow: 0 2px 8px rgba(0,0,0,0.2); `; container.appendChild(toast); const btn = document.createElement('div'); btn.innerHTML = '🔗'; btn.style = ` width: 35px; height: 35px; background: #007bff; color: white; text-align: center; line-height: 35px; border-radius: 50%; cursor: move; box-shadow: 0 3px 10px rgba(0,0,0,0.3); font-size: 16px; user-select: none; -webkit-tap-highlight-color: transparent; opacity: 0.8; `; container.appendChild(btn); // --- 拖拽逻辑 --- let isDragging = false; let startX, startY, initialRight, initialBottom; const startDrag = (e) => { isDragging = false; const touch = e.type === 'touchstart' ? e.touches[0] : e; startX = touch.clientX; startY = touch.clientY; const rect = container.getBoundingClientRect(); initialRight = window.innerWidth - rect.right; initialBottom = window.innerHeight - rect.bottom; document.addEventListener(e.type === 'touchstart' ? 'touchmove' : 'mousemove', onDrag); document.addEventListener(e.type === 'touchstart' ? 'touchend' : 'mouseup', stopDrag); }; const onDrag = (e) => { const touch = e.type === 'touchmove' ? e.touches[0] : e; const deltaX = startX - touch.clientX; const deltaY = startY - touch.clientY; if (Math.abs(deltaX) > 5 || Math.abs(deltaY) > 5) { isDragging = true; const finalRight = initialRight + deltaX; const finalBottom = initialBottom + deltaY; container.style.right = finalRight + 'px'; container.style.bottom = finalBottom + 'px'; // 实时或停止后保存位置 localStorage.setItem(STORAGE_KEY, JSON.stringify({ right: finalRight, bottom: finalBottom })); } }; const stopDrag = (e) => { document.removeEventListener(e.type === 'touchend' ? 'touchmove' : 'mousemove', onDrag); document.removeEventListener(e.type === 'touchend' ? 'touchend' : 'mouseup', stopDrag); }; btn.addEventListener('mousedown', startDrag); btn.addEventListener('touchstart', startDrag, {passive: true}); // --- API 请求逻辑 --- function showToast(msg) { toast.innerText = msg; toast.style.display = 'block'; setTimeout(() => { toast.style.display = 'none'; }, 2000); } btn.onclick = function() { if (isDragging) return; btn.innerHTML = '⏳'; GM_xmlhttpRequest({ method: "POST", url: `${SHLINK_DOMAIN}/rest/v3/short-urls`, headers: { "X-API-Key": API_KEY, "Content-Type": "application/json" }, data: JSON.stringify({ "longUrl": window.location.href, "findIfExists": true, "tags": [TAG_NAME] }), onload: function(response) { btn.innerHTML = '🔗'; const data = JSON.parse(response.responseText); if (data.shortUrl) { GM_setClipboard(data.shortUrl); showToast(`已复制`); } else { showToast("失败"); } }, onerror: () => { btn.innerHTML = '🔗'; showToast("错误"); } }); };})();
评论 (0)