您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
在右下角添加悬浮球,点击弹出上传表单对话框
当前为
// ==UserScript== // @name imgUrl上传脚本 // @namespace http://tampermonkey.net/ // @version 1.2 // @description 在右下角添加悬浮球,点击弹出上传表单对话框 // @match *://*/* // @author 21zys // @grant none // @license MIT // ==/UserScript== (function() { 'use strict'; // 获取当天的日期字符串,用于每日清零 var today = new Date().toISOString().split('T')[0]; // 格式为 "YYYY-MM-DD" // 从localStorage中获取今日上传数量,如果不存在则初始化为0 var savedUploadDate = localStorage.getItem('uploadDate') || today; var uploadCount = savedUploadDate === today ? parseInt(localStorage.getItem('uploadCount'), 10) || 0 : 0; // 如果日期已变,重置上传数量 if (savedUploadDate !== today) { uploadCount = 0; localStorage.setItem('uploadDate', today); localStorage.setItem('uploadCount', uploadCount); } // 加载时从sessionStorage中获取UID、Token和选项卡选择 var savedUID = sessionStorage.getItem('uid') || '您的UID'; var savedToken = sessionStorage.getItem('token') || '您的Token'; var savedTab = localStorage.getItem('selectedTab') || 'imgURL'; // 加载时从localStorage中获取悬浮球的位置和相册列表 var savedPosition = JSON.parse(localStorage.getItem('floatingBallPosition')) || { right: '20px', bottom: '20px' }; var savedDialogPosition = JSON.parse(localStorage.getItem('dialogPosition')) || null; var savedAlbums = JSON.parse(localStorage.getItem('albumList')) || []; var savedAlbumId = localStorage.getItem('selectedAlbumId') || 'default'; // 创建悬浮球 var floatingBall = document.createElement('div'); floatingBall.style.position = 'fixed'; floatingBall.style.right = savedPosition.right; floatingBall.style.bottom = savedPosition.bottom; floatingBall.style.left = savedPosition.left || 'auto'; floatingBall.style.top = savedPosition.top || 'auto'; floatingBall.style.width = '50px'; floatingBall.style.height = '50px'; floatingBall.style.borderRadius = '50%'; floatingBall.style.backgroundColor = '#007bff'; floatingBall.style.color = '#fff'; floatingBall.style.textAlign = 'center'; floatingBall.style.lineHeight = '50px'; floatingBall.style.cursor = 'pointer'; floatingBall.style.boxShadow = '0 4px 8px rgba(0, 0, 0, 0.2)'; floatingBall.style.fontSize = '24px'; floatingBall.style.zIndex = '1001'; floatingBall.innerHTML = '+'; document.body.appendChild(floatingBall); let isDraggingBall = false; let startX, startY; // 添加拖拽功能并保存悬浮球位置 floatingBall.addEventListener('mousedown', function(e) { startX = e.clientX; startY = e.clientY; var offsetX = e.clientX - floatingBall.getBoundingClientRect().left; var offsetY = e.clientY - floatingBall.getBoundingClientRect().top; function onMouseMove(e) { const dx = e.clientX - startX; const dy = e.clientY - startY; if (!isDraggingBall && (Math.abs(dx) > 5 || Math.abs(dy) > 5)) { // 设置拖拽灵敏度阈值为5px isDraggingBall = true; } if (isDraggingBall) { var newLeft = e.clientX - offsetX; var newTop = e.clientY - offsetY; floatingBall.style.left = newLeft + 'px'; floatingBall.style.top = newTop + 'px'; floatingBall.style.right = 'auto'; floatingBall.style.bottom = 'auto'; // 保存位置到localStorage localStorage.setItem('floatingBallPosition', JSON.stringify({ left: floatingBall.style.left, top: floatingBall.style.top })); } } function onMouseUp() { document.removeEventListener('mousemove', onMouseMove); document.removeEventListener('mouseup', onMouseUp); if (!isDraggingBall) { openDialog(); } setTimeout(() => isDraggingBall = false, 100); // 延迟100ms重置拖拽状态 } document.addEventListener('mousemove', onMouseMove); document.addEventListener('mouseup', onMouseUp); }); // 创建对话框 var dialog = document.createElement('div'); dialog.style.position = 'fixed'; // 默认居中对话框 if (savedDialogPosition) { dialog.style.left = savedDialogPosition.left; dialog.style.top = savedDialogPosition.top; dialog.style.transform = 'none'; } else { dialog.style.left = '50%'; dialog.style.top = '50%'; dialog.style.transform = 'translate(-50%, -50%)'; } dialog.style.width = '400px'; dialog.style.padding = '20px'; dialog.style.backgroundColor = 'rgba(255, 255, 255, 0.8)'; dialog.style.borderRadius = '12px'; dialog.style.backdropFilter = 'blur(10px)'; dialog.style.boxShadow = '0 8px 32px rgba(0, 0, 0, 0.37)'; dialog.style.display = 'none'; dialog.style.opacity = '0'; dialog.style.zIndex = '1000'; dialog.style.fontFamily = 'Arial, sans-serif'; dialog.style.transition = 'opacity 0.3s ease'; document.body.appendChild(dialog); let isDraggingDialog = false; dialog.addEventListener('mousedown', function(e) { if (e.target !== dialog) return; // 只允许在对话框的直接点击区域触发拖拽 var offsetX = e.clientX - dialog.getBoundingClientRect().left; var offsetY = e.clientY - dialog.getBoundingClientRect().top; // 允许在边缘20px内触发拖拽 const edgeThreshold = 20; if (offsetX < edgeThreshold || offsetX > dialog.clientWidth - edgeThreshold || offsetY < edgeThreshold || offsetY > dialog.clientHeight - edgeThreshold) { function onMouseMove(e) { isDraggingDialog = true; var newLeft = e.clientX - offsetX; var newTop = e.clientY - offsetY; dialog.style.left = newLeft + 'px'; dialog.style.top = newTop + 'px'; dialog.style.transform = 'none'; // 保存对话框位置到localStorage localStorage.setItem('dialogPosition', JSON.stringify({ left: dialog.style.left, top: dialog.style.top })); } function onMouseUp() { document.removeEventListener('mousemove', onMouseMove); document.removeEventListener('mouseup', onMouseUp); setTimeout(() => isDraggingDialog = false, 100); // 延迟100ms重置拖拽状态 } // 将监听器绑定到document, 确保拖拽行为不会中断 document.addEventListener('mousemove', onMouseMove); document.addEventListener('mouseup', onMouseUp); } }); // 创建关闭按钮(X图标) var closeButton = document.createElement('span'); closeButton.innerHTML = '×'; closeButton.style.position = 'absolute'; closeButton.style.top = '10px'; closeButton.style.right = '10px'; closeButton.style.cursor = 'pointer'; closeButton.style.fontSize = '20px'; closeButton.style.color = '#333'; closeButton.addEventListener('click', function() { closeDialog(); }); dialog.appendChild(closeButton); // 创建表单 var form = document.createElement('form'); form.enctype = 'multipart/form-data'; form.method = 'post'; form.action = 'https://www.imgurl.org/api/v2/upload'; form.id = 'upform'; form.style.display = 'grid'; form.style.gap = '10px'; // 创建UID字段 var uidLabel = document.createElement('label'); uidLabel.innerText = 'UID:'; uidLabel.style.fontWeight = 'bold'; uidLabel.style.color = '#333'; var uidInput = document.createElement('input'); uidInput.type = 'text'; uidInput.name = 'uid'; uidInput.value = savedUID; uidInput.style.padding = '8px'; uidInput.style.border = '1px solid #ccc'; uidInput.style.borderRadius = '4px'; form.appendChild(uidLabel); form.appendChild(uidInput); // 创建Token字段 var tokenLabel = document.createElement('label'); tokenLabel.innerText = 'Token:'; tokenLabel.style.fontWeight = 'bold'; tokenLabel.style.color = '#333'; var tokenInput = document.createElement('input'); tokenInput.type = 'text'; tokenInput.name = 'token'; tokenInput.value = savedToken; tokenInput.style.padding = '8px'; tokenInput.style.border = '1px solid #ccc'; tokenInput.style.borderRadius = '4px'; form.appendChild(tokenLabel); form.appendChild(tokenInput); // 创建刷新相册按钮 var albumSelectContainer = document.createElement('div'); albumSelectContainer.style.marginTop = '10px'; albumSelectContainer.style.textAlign = 'center'; var albumBtn = document.createElement('button'); albumBtn.type = 'button'; albumBtn.innerText = '刷新相册'; albumBtn.style.padding = '8px 16px'; albumBtn.style.border = '1px solid #ccc'; albumBtn.style.borderRadius = '4px'; albumBtn.style.cursor = 'pointer'; albumBtn.style.backgroundColor = '#f8f9fa'; albumSelectContainer.appendChild(albumBtn); // 创建相册下拉列表(表单外) var albumSelect = document.createElement('select'); albumSelect.style.width= '175px'; albumSelect.style.height = '34px'; albumSelect.style.marginTop = '-3px'; albumSelect.style.textAlign = 'center'; albumSelect.style.border = '1px solid #ccc'; albumSelect.style.borderRadius = '4px'; albumSelectContainer.appendChild(albumSelect); dialog.appendChild(albumSelectContainer); // 将相册下拉列表放在表单外 // 加载持久化相册列表和选择 loadAlbumList(); // 刷新相册列表 albumBtn.addEventListener('click', function() { fetchAlbums(); }); albumSelect.addEventListener('change', function() { var selectedAlbumId = albumSelect.value; localStorage.setItem('selectedAlbumId', selectedAlbumId); }); function loadAlbumList() { albumSelect.innerHTML = ''; // 清空下拉列表 var defaultOption = document.createElement('option'); defaultOption.value = 'default'; defaultOption.textContent = '默认相册'; albumSelect.appendChild(defaultOption); if (savedAlbums.length > 0) { savedAlbums.forEach(function(album) { var option = document.createElement('option'); option.value = album.album_id; option.textContent = album.name; albumSelect.appendChild(option); }); } // 选择持久化的相册 albumSelect.value = savedAlbumId; } function fetchAlbums() { var xhr = new XMLHttpRequest(); xhr.open('POST', 'https://www.imgurl.org/api/v2/albums', true); // 构造FormData对象,将UID和Token放入其中 var formData = new FormData(); formData.append('uid', uidInput.value); formData.append('token', tokenInput.value); xhr.onreadystatechange = function() { if (xhr.readyState === 4 && xhr.status === 200) { var response = JSON.parse(xhr.responseText); if (response && response.data && response.data.length) { savedAlbums = response.data; localStorage.setItem('albumList', JSON.stringify(savedAlbums)); // 持久化保存相册列表 loadAlbumList(); // 重新加载相册列表 } else { albumSelect.innerHTML = '<option value="">未找到相册</option>'; } } else if (xhr.readyState === 4) { albumSelect.innerHTML = '<option value="">获取相册失败</option>'; } }; // 发送POST请求 xhr.send(formData); } // 创建文件上传输入框 var fileLabel = document.createElement('label'); fileLabel.innerText = '选择文件:'; fileLabel.style.fontWeight = 'bold'; fileLabel.style.color = '#333'; var fileInput = document.createElement('input'); fileInput.type = 'file'; fileInput.name = 'file'; fileInput.style.padding = '8px'; fileInput.style.border = '1px solid #ccc'; fileInput.style.borderRadius = '4px'; form.appendChild(fileLabel); form.appendChild(fileInput); // 上传和清空按钮容器 var buttonContainer = document.createElement('div'); buttonContainer.style.marginTop = '10px'; buttonContainer.style.textAlign = 'right'; // 创建今日上传数量label var uploadCountLabel = document.createElement('label'); uploadCountLabel.textContent = `今日已上传 ${uploadCount} 张图片`; uploadCountLabel.style.fontSize = '1rem'; uploadCountLabel.style.fontWeight = 'bold'; uploadCountLabel.style.color = 'rgb(51, 51, 51)'; uploadCountLabel.style.marginRight = '10px'; buttonContainer.appendChild(uploadCountLabel); // 创建上传按钮 var uploadBtn = document.createElement('input'); uploadBtn.type = 'submit'; uploadBtn.id = 'upload-btn'; uploadBtn.value = '开始上传'; uploadBtn.className = 'upload-btn'; uploadBtn.style.padding = '8px 16px'; uploadBtn.style.border = 'none'; uploadBtn.style.backgroundColor = '#007bff'; uploadBtn.style.color = '#fff'; uploadBtn.style.borderRadius = '4px'; uploadBtn.style.cursor = 'pointer'; uploadBtn.style.marginRight = '10px'; uploadBtn.style.transition = 'background-color 0.3s ease'; uploadBtn.addEventListener('mouseover', function() { uploadBtn.style.backgroundColor = '#0056b3'; }); uploadBtn.addEventListener('mouseout', function() { uploadBtn.style.backgroundColor = '#007bff'; }); buttonContainer.appendChild(uploadBtn); // 创建清空按钮 var clearBtn = document.createElement('input'); clearBtn.type = 'button'; clearBtn.id = 'clear-btn'; clearBtn.value = '清空'; clearBtn.className = 'clear-btn'; clearBtn.style.padding = '8px 16px'; clearBtn.style.border = 'none'; clearBtn.style.backgroundColor = '#6c757d'; clearBtn.style.color = '#fff'; clearBtn.style.borderRadius = '4px'; clearBtn.style.cursor = 'pointer'; clearBtn.style.transition = 'background-color 0.3s ease'; clearBtn.addEventListener('mouseover', function() { clearBtn.style.backgroundColor = '#5a6268'; }); clearBtn.addEventListener('mouseout', function() { clearBtn.style.backgroundColor = '#6c757d'; }); clearBtn.addEventListener('click', function() { fileInput.value = ''; // 清空文件输入框 resultInput.value = ''; // 清空上传结果文本框 resultInput.style.color = ''; // 重置文本框颜色 delete resultInput.dataset.url; // 删除已存储的URL }); buttonContainer.appendChild(clearBtn); form.appendChild(buttonContainer); // 创建进度条容器,移出表单 var progressContainer = document.createElement('div'); progressContainer.style.marginTop = '10px'; progressContainer.style.display = 'none'; progressContainer.style.width = '100%'; dialog.appendChild(progressContainer); // 将进度条容器添加到对话框中 // 创建进度条 var progressBar = document.createElement('progress'); progressBar.value = '0'; progressBar.max = '100'; progressBar.style.width = '100%'; progressBar.style.height = '20px'; progressContainer.appendChild(progressBar); // 创建选项卡容器,移出表单 var tabContainer = document.createElement('div'); tabContainer.style.display = 'flex'; tabContainer.style.justifyContent = 'space-around'; tabContainer.style.marginTop = '10px'; dialog.appendChild(tabContainer); // 将选项卡容器添加到对话框中 // 创建选项卡 var tabs = ['HTML', 'imgURL', 'MarkDown', 'BBCode']; tabs.forEach(function(tab) { var tabButton = document.createElement('button'); tabButton.textContent = tab; tabButton.style.flex = '1'; tabButton.style.padding = '10px'; tabButton.style.border = '1px solid #ccc'; tabButton.style.borderRadius = '4px 4px 0 0'; tabButton.style.cursor = 'pointer'; tabButton.style.backgroundColor = tab === savedTab ? '#007bff' : '#f8f9fa'; tabButton.style.color = tab === savedTab ? '#fff' : '#333'; tabButton.addEventListener('click', function() { selectTab(tab); }); tabContainer.appendChild(tabButton); }); // 创建用于回显上传结果的文本框容器 var resultContainer = document.createElement('div'); resultContainer.style.marginTop = '10px'; resultContainer.style.textAlign = 'center'; // 创建回显上传结果的文本框 var resultInput = document.createElement('input'); resultInput.type = 'text'; resultInput.id = 'result-box'; resultInput.placeholder = '上传结果'; resultInput.style.width = '100%'; resultInput.style.padding = '8px'; resultInput.style.border = '1px solid #ccc'; resultInput.style.borderRadius = '4px'; resultInput.readOnly = true; // 设置为不可编辑状态 resultInput.style.cursor = 'pointer'; resultContainer.appendChild(resultInput); // 单击文本框时复制里面的文本 resultInput.addEventListener('click', function() { navigator.clipboard.writeText(resultInput.value).then(function() { alert('已复制到剪贴板'); }); }); // 将表单和结果容器添加到对话框中 dialog.appendChild(form); dialog.appendChild(resultContainer); // 处理选项卡切换 function selectTab(tab) { localStorage.setItem('selectedTab', tab); // 持久化选项卡选择 updateTabUI(tab); updateResultFormat(tab); } function updateTabUI(selectedTab) { tabContainer.querySelectorAll('button').forEach(function(button) { if (button.textContent === selectedTab) { button.style.backgroundColor = '#007bff'; button.style.color = '#fff'; } else { button.style.backgroundColor = '#f8f9fa'; button.style.color = '#333'; } }); } function updateResultFormat(tab) { const url = resultInput.dataset.url; // 使用保存的上传成功后的URL if (!url) return; let formattedText = ''; switch (tab) { case 'HTML': formattedText = `<img src="${url}" alt="image">`; break; case 'imgURL': formattedText = url; break; case 'MarkDown': formattedText = ``; break; case 'BBCode': formattedText = `[img]${url}[/img]`; break; } if (resultInput.value !== formattedText) { resultInput.value = formattedText; // 只有在内容不匹配时才更新文本框内容 } } // 初始化选项卡UI和结果格式 updateTabUI(savedTab); // 打开对话框的函数,带淡入效果 function openDialog() { dialog.style.display = 'block'; setTimeout(function() { dialog.style.opacity = '1'; }, 10); } // 关闭对话框的函数,带淡出效果 function closeDialog() { dialog.style.opacity = '0'; setTimeout(function() { dialog.style.display = 'none'; }, 300); } // 处理表单提交逻辑 form.addEventListener('submit', function(event) { event.preventDefault(); // 阻止表单默认提交行为 // 获取UID和Token var uid = uidInput.value.trim(); var token = tokenInput.value.trim(); // 检查UID和Token是否为空 if (!uid || !token) { resultInput.value = '请填写UID和Token后再试。'; resultInput.style.color = 'red'; return; } // 保存UID和Token到sessionStorage sessionStorage.setItem('uid', uid); sessionStorage.setItem('token', token); // 检查是否选择了文件 if (!fileInput.files.length) { resultInput.value = '请选择要上传的文件。'; resultInput.style.color = 'red'; return; } // 检查文件格式是否支持 var allowedFormats = ['jpg', 'jpeg', 'png', 'gif', 'bmp', 'webp']; var file = fileInput.files[0]; var fileExtension = file.name.split('.').pop().toLowerCase(); if (!allowedFormats.includes(fileExtension)) { resultInput.value = '仅支持格式: ' + allowedFormats.join(', '); resultInput.style.color = 'red'; return; } // 显示进度条 progressContainer.style.display = 'block'; // 创建异步请求 var xhr = new XMLHttpRequest(); xhr.open('POST', form.action, true); // 异步请求 // 监听上传进度 xhr.upload.addEventListener('progress', function(e) { if (e.lengthComputable) { var percentComplete = (e.loaded / e.total) * 100; progressBar.value = percentComplete; } }); // 错误处理 xhr.addEventListener('load', function() { if (xhr.status === 200) { var response = JSON.parse(xhr.responseText); if (response && response.data && response.data.url) { resultInput.dataset.url = response.data.url; // 保存上传成功后的URL updateResultFormat(savedTab); // 更新结果格式 resultInput.style.color = 'green'; // 更新并保存上传数量 uploadCount++; localStorage.setItem('uploadCount', uploadCount); uploadCountLabel.textContent = `今日已上传 ${uploadCount} 张图片`; } else { resultInput.value = '上传失败: ' + (response.message || '未知错误'); resultInput.style.color = 'red'; } } else { resultInput.value = '上传失败: ' + xhr.statusText + ' (' + xhr.status + ')'; resultInput.style.color = 'red'; } progressContainer.style.display = 'none'; }); xhr.addEventListener('error', function() { resultInput.value = '上传失败: 网络错误'; resultInput.style.color = 'red'; progressContainer.style.display = 'none'; }); var formData = new FormData(form); if (albumSelect.value !== 'default') { // 仅当选择了具体相册时才附加album_id formData.append('album_id', albumSelect.value); } xhr.send(formData); }); })();