您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
在超星云盘显示文件详细信息的悬浮窗
// ==UserScript== // @name 超星个人云盘 Pro // @namespace http://tampermonkey.net/ // @version 2.0 // @description 在超星云盘显示文件详细信息的悬浮窗 // @author 榛铭 // @match https://pan-yz.chaoxing.com/ // @match https://i.chaoxing.com/base* // @match https://pan-yz.cldisk.com/* // @grant none // @license MIT // ==/UserScript== class FloatingWindow { constructor() { if (document.getElementById('fileInfoWindow')) { document.getElementById('fileInfoWindow').remove(); } this.window = null; this.isDragging = false; this.isResizing = false; this.init(); } init() { this.createWindow(); this.setupEventListeners(); setInterval(() => { const data = window.currentPageRespData || window.yunpanModelNew?.currentPageRespData; if (data?.list) this.updateContent(data.list); }, 1000); } createWindow() { this.window = document.createElement('div'); this.window.id = 'fileInfoWindow'; this.window.style.cssText = ` position: fixed; left: ${(window.innerWidth - 500) / 2}px; top: ${(window.innerHeight - 400) / 2}px; width: 500px; max-height: 80vh; background-color: rgba(255, 255, 255, 0.6); border: 1px solid rgba(204, 204, 204, 0.3); box-shadow: 0 0 10px rgba(0,0,0,0.05); z-index: 9999; overflow-y: auto; border-radius: 5px; backdrop-filter: blur(2px) `; const titleBar = document.createElement('div'); titleBar.style.cssText = ` padding: 10px; background-color: rgba(33, 150, 243, 0.7); color: #fff; display: flex; justify-content: space-between; align-items: center; cursor: move `; titleBar.innerHTML = ` <h2 style="margin:0">文件详细信息</h2> <button class="minimize-btn" style="background:none;border:none;color:white;cursor:pointer;font-size:20px;padding:0 5px;line-height:1">−</button> `; titleBar.querySelector('.minimize-btn').onclick = e => { e.stopPropagation(); this.toggleMinimize(); }; const content = document.createElement('div'); content.id = 'fileInfoContent'; const resizeHandle = document.createElement('div'); resizeHandle.style.cssText = ` position: absolute; bottom: 0; right: 0; width: 15px; height: 15px; cursor: se-resize; background-color: rgba(33, 150, 243, 0.7); clip-path: polygon(100% 0, 100% 100%, 0 100%) `; this.window.append(titleBar, content, resizeHandle); const savedPosition = JSON.parse(localStorage.getItem('floatingWindowPosition')); const savedSize = JSON.parse(localStorage.getItem('floatingWindowSize')); if (savedPosition) { const maxX = window.innerWidth - this.window.offsetWidth; const maxY = window.innerHeight - this.window.offsetHeight; this.window.style.left = `${Math.min(Math.max(0, savedPosition.x), maxX)}px`; this.window.style.top = `${Math.min(Math.max(0, savedPosition.y), maxY)}px`; } if (savedSize) { if (savedSize.width) this.window.style.width = savedSize.width; if (savedSize.height) this.window.style.height = savedSize.height; } document.body.appendChild(this.window); } setupEventListeners() { const titleBar = this.window.querySelector('div'); const resizeHandle = this.window.querySelector('div:last-child'); let originalSize, originalMouse; titleBar.onmousedown = e => { if (e.target === titleBar) { this.isDragging = true; const rect = this.window.getBoundingClientRect(); this.dragOffset = {x: e.clientX - rect.left, y: e.clientY - rect.top}; this.window.style.opacity = '0.9'; } }; resizeHandle.onmousedown = e => { this.isResizing = true; originalSize = {width: this.window.offsetWidth, height: this.window.offsetHeight}; originalMouse = {x: e.clientX, y: e.clientY}; e.stopPropagation(); }; document.onmousemove = e => { if (this.isDragging) { const x = e.clientX - this.dragOffset.x; const y = e.clientY - this.dragOffset.y; const maxX = window.innerWidth - this.window.offsetWidth; const maxY = window.innerHeight - this.window.offsetHeight; this.window.style.left = `${Math.min(Math.max(0, x), maxX)}px`; this.window.style.top = `${Math.min(Math.max(0, y), maxY)}px`; localStorage.setItem('floatingWindowPosition', JSON.stringify({ x: parseInt(this.window.style.left), y: parseInt(this.window.style.top) })); } if (this.isResizing) { const width = originalSize.width + (e.clientX - originalMouse.x); const height = originalSize.height + (e.clientY - originalMouse.y); if (width > 300 && width < window.innerWidth * 0.8) { this.window.style.width = `${width}px`; } if (height > 200 && height < window.innerHeight * 0.8) { this.window.style.height = `${height}px`; } localStorage.setItem('floatingWindowSize', JSON.stringify({ width: this.window.style.width, height: this.window.style.height })); } }; document.onmouseup = () => { if (this.isDragging) { this.isDragging = false; this.window.style.opacity = '1'; } this.isResizing = false; }; this.window.onclick = () => { if (this.window.classList.contains('minimized')) { this.toggleMinimize(); } }; } updateContent(files) { if (!files?.length) return; const content = this.window.querySelector('#fileInfoContent'); content.innerHTML = ''; const cardStyle = ` padding: 15px; margin: 10px; background: rgba(249, 249, 249, 0.5); border-radius: 5px; border: 1px solid rgba(238, 238, 238, 0.3); backdrop-filter: blur(1px) `; files.forEach(file => { const card = document.createElement('div'); card.style.cssText = cardStyle; card.innerHTML = ` <h3 style="margin:0 0 10px">${file.name}</h3> <div style="margin-bottom:10px"> <img src="${file.logo}" style="width:30px;margin-right:10px"> <span>文件类型: ${file.suffix.toUpperCase()}</span> </div> <div style="margin-bottom:10px"> <strong>文件大小:</strong> ${file.sizestr}<br> <strong>上传日期:</strong> ${file.timestr} </div> <div style="text-align:right"> ${file.preview ? `<button onclick="window.open('${file.preview}', '_blank')" style="margin:0 5px;padding:6px 16px;background:none;border:none;color:#2196F3;cursor:pointer">预览</button>` : ''} ${file.objectId ? `<button class="copyBtn" data-id="${file.objectId}" style="margin:0 5px;padding:6px 16px;background:none;border:1px solid #4CAF50;color:#4CAF50;border-radius:4px;cursor:pointer">复制下载链接</button>` : ''} </div> `; const copyBtn = card.querySelector('.copyBtn'); if (copyBtn) { copyBtn.onclick = () => { const url = `https://sharewh.chaoxing.com/share/download/${copyBtn.dataset.id}`; try { const input = document.createElement('textarea'); input.value = url; input.style.position = 'fixed'; input.style.left = '-9999px'; document.body.appendChild(input); input.select(); input.setSelectionRange(0, 99999); const success = document.execCommand('copy'); document.body.removeChild(input); copyBtn.textContent = success ? '复制成功!' : '复制失败'; copyBtn.style.backgroundColor = success ? '#4CAF50' : '#ff5252'; copyBtn.style.color = '#fff'; } catch { copyBtn.textContent = '复制失败'; copyBtn.style.backgroundColor = '#ff5252'; copyBtn.style.color = '#fff'; } setTimeout(() => { copyBtn.textContent = '复制下载链接'; copyBtn.style.backgroundColor = ''; copyBtn.style.color = '#4CAF50'; }, 2000); }; } content.appendChild(card); }); } toggleMinimize() { if (this.window.classList.contains('minimized')) { // 展开 this.window.classList.remove('minimized'); this.window.style.cssText = this.window.dataset.originalStyle; this.window.innerHTML = this.window.dataset.originalContent; // 重新绑定最小化按钮事件 const minimizeBtn = this.window.querySelector('.minimize-btn'); if (minimizeBtn) { minimizeBtn.onclick = e => { e.stopPropagation(); this.toggleMinimize(); }; } // 重新绑定其他事件 this.setupEventListeners(); } else { // 最小化 this.window.dataset.originalStyle = this.window.style.cssText; this.window.dataset.originalContent = this.window.innerHTML; this.window.classList.add('minimized'); this.window.style.cssText = ` position: fixed; right: 20px; bottom: 20px; width: 50px; height: 50px; border-radius: 25px; background-color: rgba(33, 150, 243, 0.9); box-shadow: 0 2px 10px rgba(0,0,0,0.1); cursor: pointer; z-index: 9999; display: flex; align-items: center; justify-content: center; font-size: 24px; color: white; border: none; overflow: hidden; `; this.window.innerHTML = '🌟'; } } } (() => { const waitForData = setInterval(() => { const data = window.currentPageRespData || window.yunpanModelNew?.currentPageRespData; if (data?.list && !document.getElementById('fileInfoWindow')) { clearInterval(waitForData); new FloatingWindow(); } }, 1000); })();