因为移动端上没有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("错误"); }
});
};
})();
好东西啊,我也去做一个,以后给NSFW图片都用上rbq.su,给临时页面都用上302.su
@白嫖怪 #1 好好好
@白嫖怪 #1 别给307 308也注册了 留一点
@rainyfall #3 301早就没了,302好不容易抢到
@白嫖怪 #4
是这样,我查过了