您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Greasy Fork is available in English.
悬浮快捷入口
当前为
// ==UserScript== // @name Shopee 悬浮按钮 // @namespace http://tampermonkey.net/ // @version 2.1.3 // @license Rayu // @description 悬浮快捷入口 // @author Rayu // @match https://seller.shopee.tw/* // @exclude https://seller.shopee.tw/webchat/conversations // @match *://shopee.tw/* // @match *://shopee.ph/* // @match *://shopee.sg/* // @match *://shopee.com.my/* // @icon https://www.wikimedia.org/static/favicon/wikipedia.ico // @grant GM_addStyle // @run-at document-end // ==/UserScript== (function () { 'use strict'; // 配置中心 const CONFIG = { BUTTONS: [ { id: 'shipment-btn', content: '待<br>出货', path: '/portal/sale/shipment?type=toship', title: '待处理订单' }, { id: 'products-btn', content: '我的<br>商品', path: '/portal/product/list/all?page=1&size=48', title: '商品管理' }, { id: 'analytics-btn', content: '商品<br>分析', path: '/datacenter/product/overview', title: '数据分析' }, { id: 'ads-btn', content: '我的<br>广告', path: '/portal/marketing/pas/assembly', title: '广告管理' }, { id: 'campaign-btn', content: '行销<br>活动', path: '/portal/marketing', title: '营销活动' }, { id: 'returns-btn', content: '退貨<br>退款', path: '/portal/sale/return', title: '退货退款' }, { id: 'roi-edit-btn', content: '修改ROI', path: 'javascript:void(0);', title: '一键把本页ROI值全部设为7' } ], TRACKING_PATTERN: /-i\.(\d+)\.(\d+)/, STYLES: ` :root { --primary-color: #ee4d2d; --button-size: 52px; --hover-scale: 1.08; --gap: 8px; } #floating-buttons-container { position: fixed; top: 50vh; right: 50px; transform: translateY(-50%); display: flex; flex-direction: column; gap: var(--gap); z-index: 9999; filter: drop-shadow(0 2px 6px rgba(0,0,0,0.16)); } .floating-button { display: flex; align-items: center; justify-content: center; width: var(--button-size); height: var(--button-size); background: var(--primary-color); color: white !important; border-radius: 8px; font-size: 15px; font-weight: 500; line-height: 1.3; text-align: center; text-decoration: none !important; cursor: pointer; transition: transform 0.2s cubic-bezier(0.18, 0.89, 0.32, 1.28), opacity 0.2s, background 0.2s; user-select: none; } .floating-button:hover { transform: scale(var(--hover-scale)); background: #d14327; opacity: 0.95; } .floating-button:active { transition-duration: 0.1s; transform: scale(0.96); } #roi-left-bottom-btn-container { position: fixed !important; left: 30px !important; bottom: 30px !important; z-index: 9999 !important; } #roi-edit-btn { width: 110px !important; height: 38px !important; border-radius: 8px !important; font-size: 16px !important; line-height: 38px !important; text-align: center !important; padding: 0 !important; } @media (max-width: 768px) { #floating-buttons-container { right: 4px; transform: translateY(-50%) scale(0.82); gap: 6px; } .floating-button { width: 46px; height: 46px; font-size: 14px; } } ` }; // 核心功能模块 class ShopeeEnhancer { constructor() { this.observer = null; this.reg = CONFIG.TRACKING_PATTERN; this.init(); } // 判断是否为 ROI 按钮需要出现的页面 isRoiPage() { // 只要当前路径以 /portal/marketing/pas/product/ 开头 return /^\/portal\/marketing\/pas\/product\//.test(location.pathname); } init() { this.injectStyles(); this.createFloatingButtons(); this.hijackHistoryMethods(); this.sanitizeLinks(); } injectStyles() { GM_addStyle(CONFIG.STYLES); } createFloatingButtons() { // 清理老容器 let container = document.getElementById('floating-buttons-container'); if (container) container.remove(); // 新建右侧容器 container = document.createElement('div'); container.id = 'floating-buttons-container'; document.body.appendChild(container); // 右侧按钮(不含roi-edit-btn) CONFIG.BUTTONS.filter(btn => btn.id !== 'roi-edit-btn').forEach(btn => { let a = document.createElement('a'); a.className = 'floating-button'; a.id = btn.id; a.href = btn.path.startsWith('javascript:') ? '#' : new URL(btn.path, window.location.origin); a.target = '_blank'; a.rel = 'noopener noreferrer'; a.title = btn.title; a.innerHTML = btn.content; container.appendChild(a); }); // 清理老的左下角ROI容器 let roiContainer = document.getElementById('roi-left-bottom-btn-container'); if (roiContainer) roiContainer.remove(); // 新建左下ROI容器 roiContainer = document.createElement('div'); roiContainer.id = 'roi-left-bottom-btn-container'; document.body.appendChild(roiContainer); // 只在指定页面插入ROI按钮 if (this.isRoiPage()) { let roiBtnConf = CONFIG.BUTTONS.find(btn => btn.id === 'roi-edit-btn'); if (roiBtnConf) { let roiBtn = document.createElement('a'); roiBtn.className = 'floating-button'; roiBtn.id = 'roi-edit-btn'; roiBtn.href = '#'; roiBtn.title = roiBtnConf.title; roiBtn.innerHTML = roiBtnConf.content; roiContainer.appendChild(roiBtn); roiBtn.addEventListener('click', function (e) { e.preventDefault(); // 选出所有 .eds-switch let switches = document.querySelectorAll('.eds-switch'); switches.forEach(sw => { // 如果是开着的则点一下,让它变成关闭。“关”的就不用管它 if (sw.classList.contains('eds-switch--open')) { sw.click(); } }); const els = document.querySelectorAll('.roi-edit-popover-container .roi-value'); if (els.length === 0) { showAutoTip('未发现ROI内容元素!'); return; } els.forEach(el => el.innerText = '7'); showAutoTip('全部ROI值已修改为7!'); // 勾选radio let yesLimitRadio = document.querySelector('.yes-limit input[type="radio"]'); if (yesLimitRadio) { yesLimitRadio.checked = true; yesLimitRadio.dispatchEvent(new Event('change', { bubbles: true })); } // 填写预算输入框,加延时和原生setter双保险 setTimeout(function () { let input = document.querySelector('.budget-input .eds-input__input'); if (input) { const nativeInputValueSetter = Object.getOwnPropertyDescriptor(window.HTMLInputElement.prototype, 'value').set; nativeInputValueSetter.call(input, '40'); input.dispatchEvent(new Event('input', { bubbles: true })); input.dispatchEvent(new Event('change', { bubbles: true })); } else { // showAutoTip('未找到预算输入框!'); // 可以开启 } }, 300); }); // 自动消失的浮动提示函数 function showAutoTip(msg) { let tip = document.createElement('div'); tip.innerText = msg; tip.style.position = 'fixed'; tip.style.left = '50%'; tip.style.top = '30%'; tip.style.transform = 'translate(-50%, -50%)'; tip.style.background = '#23272E'; tip.style.color = '#fff'; tip.style.padding = '14px 38px'; tip.style.borderRadius = '8px'; tip.style.fontSize = '18px'; tip.style.boxShadow = '0 2px 16px rgba(0,0,0,0.17)'; tip.style.zIndex = 999999; tip.style.opacity = 1; tip.style.transition = 'opacity 0.6s'; document.body.appendChild(tip); setTimeout(() => { tip.style.opacity = 0; setTimeout(() => tip.remove(), 600); }, 2000); } } } } cleanURL(url) { const match = url.match(this.reg); if (!match) return url; return `${window.location.origin}/product/${match[1]}/${match[2]}`; } hijackHistoryMethods() { const self = this; const originalPushState = history.pushState; const originalReplaceState = history.replaceState; history.pushState = function (state, title, url) { if (url) url = self.cleanURL(url); return originalPushState.call(this, state, title, url); }; history.replaceState = function (state, title, url) { if (url) url = self.cleanURL(url); return originalReplaceState.call(this, state, title, url); }; } sanitizeLinks() { // 当前页面处理 if (this.reg.test(window.location.href)) { window.location.replace(this.cleanURL(window.location.href)); return; } // 初始化清理 this.processLinks(document); // 动态内容监控 this.observer = new MutationObserver(mutations => { mutations.forEach(({ addedNodes }) => { addedNodes.forEach(node => { if (node.nodeType === Node.ELEMENT_NODE) { this.processLinks(node); } }); }); }); this.observer.observe(document, { subtree: true, childList: true }); } processLinks(root) { const links = root.querySelectorAll('a[href*="-i."]'); links.forEach(link => { link.href = this.cleanURL(link.href); }); } } // 启动 const enhancer = new ShopeeEnhancer(); // 单页应用路由变更时保持悬浮按钮 let lastUrl = location.href; setInterval(() => { if (location.href !== lastUrl) { lastUrl = location.href; enhancer.createFloatingButtons(); } }, 1000); })();