您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
使用 getBoundingClientRect() 计算位置和尺寸
// ==UserScript== // @name ReyoungEcology9 RequestId 跳转按钮(高内聚版,Rect版) // @namespace http://tampermonkey.net/ // @version 3.2 // @description 使用 getBoundingClientRect() 计算位置和尺寸 // @match http://ec.reyoung.com:5221/* // @grant none // @license GPL-2.0-only // ==/UserScript== (function () { 'use strict'; class RequestIdButton { constructor() { this.STORAGE_KEY = 'reyoung_btn_ratio'; this.SNAP_THRESHOLD_RATIO = 0.05; this.isDragging = false; this.offsetX = 0; this.offsetY = 0; this.loadPosition(); this.createButton(); this.setInitialPosition(); this.bindEvents(); } loadPosition() { const saved = JSON.parse(localStorage.getItem(this.STORAGE_KEY) || '{}'); this.ratioX = typeof saved.ratioX === 'number' ? saved.ratioX : null; this.ratioY = typeof saved.ratioY === 'number' ? saved.ratioY : null; } createButton() { this.btn = document.createElement('button'); this.btn.textContent = '跳转到 RequestId'; Object.assign(this.btn.style, { position: 'fixed', zIndex: 9999, padding: '8px 12px', backgroundColor: '#4CAF50', color: '#fff', border: 'none', borderRadius: '4px', cursor: 'pointer', userSelect: 'none' }); document.body.appendChild(this.btn); // 用 rect 获取初始宽度 const rect = this.btn.getBoundingClientRect(); this.initialWidth = rect.width; this.btn.style.width = this.initialWidth + 'px'; } setInitialPosition() { if (this.ratioX === null || this.ratioY === null) { this.ratioX = (window.innerWidth - this.initialWidth - 20) / window.innerWidth; this.ratioY = 20 / window.innerHeight; } this.updatePositionFromRatio(); this.applySnap(); } updatePositionFromRatio() { let x = this.ratioX * window.innerWidth; let y = this.ratioY * window.innerHeight; const rect = this.btn.getBoundingClientRect(); x = Math.max(0, Math.min(window.innerWidth - rect.width, x)); y = Math.max(0, Math.min(window.innerHeight - rect.height, y)); this.btn.style.left = x + 'px'; this.btn.style.top = y + 'px'; this.btn.style.right = 'auto'; } applySnap() { const rect = this.btn.getBoundingClientRect(); const threshold = window.innerWidth * this.SNAP_THRESHOLD_RATIO; this.btn.style.width = rect.width + 'px'; this.btn.style.right = 'auto'; if (rect.left <= threshold) { this.btn.style.left = '0px'; } else if (window.innerWidth - (rect.left + rect.width) <= threshold) { this.btn.style.left = (window.innerWidth - rect.width) + 'px'; } } savePosition() { const rect = this.btn.getBoundingClientRect(); this.ratioX = rect.left / window.innerWidth; this.ratioY = rect.top / window.innerHeight; localStorage.setItem(this.STORAGE_KEY, JSON.stringify({ ratioX: this.ratioX, ratioY: this.ratioY })); } startDrag(e) { this.isDragging = false; const rect = this.btn.getBoundingClientRect(); this.offsetX = e.clientX - rect.left; this.offsetY = e.clientY - rect.top; const onMouseMove = e => { this.isDragging = true; let x = e.clientX - this.offsetX; let y = e.clientY - this.offsetY; const currentRect = this.btn.getBoundingClientRect(); x = Math.max(0, Math.min(window.innerWidth - currentRect.width, x)); y = Math.max(0, Math.min(window.innerHeight - currentRect.height, y)); this.btn.style.left = x + 'px'; this.btn.style.top = y + 'px'; this.btn.style.right = 'auto'; }; const onMouseUp = () => { document.removeEventListener('mousemove', onMouseMove); document.removeEventListener('mouseup', onMouseUp); this.applySnap(); this.savePosition(); this.btn.style.cursor = 'pointer'; setTimeout(() => this.isDragging = false, 50); }; document.addEventListener('mousemove', onMouseMove); document.addEventListener('mouseup', onMouseUp); } handleClick() { if (this.isDragging) return; const requestId = prompt('请输入 RequestId:'); if (requestId && /^\d+$/.test(requestId.trim())) { location.href = `http://ec.reyoung.com:5221/workflow/request/ViewRequestForwardSPA.jsp?ismonitor=1&requestid=${requestId.trim()}`; } else if (requestId !== null) { alert('请输入有效的数字 RequestId!'); } } bindEvents() { window.addEventListener('resize', () => this.updatePositionFromRatio()); this.btn.addEventListener('mousedown', e => this.startDrag(e)); this.btn.addEventListener('click', () => this.handleClick()); } } new RequestIdButton(); })();