// ==UserScript== // @name Temu 销量定位 // @namespace http://tampermonkey.net/ // @version 3.2 // @description 利用 GM_download 绕过跨域限制,实现图片直接下载到本地 // @author binning // @match https://www.temu.com/* // @grant GM_download // @run-at document-end // ==/UserScript== (function() { 'use strict'; function createSalesPositionTable() { const oldTable = document.getElementById('salesPositionTable'); if (oldTable) oldTable.remove(); // ===================== 商品容器 CLASS 配置 ===================== const GOODS_CONTAINER_CLASSES = [ "_6q6qVUF5 _1UrrHYym", // 在这里添加更多商品容器class ]; const goodsSelector = GOODS_CONTAINER_CLASSES.map(c => `div.${c.split(' ').join('.')}`).join(','); const allGoodsItems = document.querySelectorAll(goodsSelector); const validItems = []; allGoodsItems.forEach(item => { const salesEl = item.querySelector('span._1GKMA1Nk.undefined'); if (!salesEl) return; const salesNum = salesEl.textContent.replace(/\D/g, '') || '0'; const imgWrap = item.querySelector('div._1GE1BzXo._3QE924aA.NChdjz2-.goods-img-external'); const imgs = imgWrap?.querySelectorAll('img'); if (!imgs || imgs.length < 2) return; // 获取原图链接并去掉参数 const bigSrc = imgs[1].src.split('?')[0]; validItems.push({ dom: item, sales: salesNum, smallImg: imgs[0].src, bigImg: bigSrc }); }); // ===================== 样式 ===================== const style = document.createElement('style'); style.textContent = ` #salesPositionTable { position: fixed; z-index: 999999; width: 480px; background: #fff; border-radius: 12px; box-shadow: 0 0 25px rgba(0,0,0,0.25); font-family: system-ui; overflow: hidden; user-select: none; left: 20px; top: 50%; transform: translateY(-50%); } .table-header { padding: 12px 16px; background: #2f54eb; color: white; font-weight: bold; display: flex; justify-content: space-between; align-items: center; cursor: move; } .header-title { display: flex; align-items: center; gap: 8px; } .drag-icon { font-size: 16px; opacity: 0.8; } .header-buttons { display: flex; gap: 6px; } .header-btn { padding: 4px 10px; border: none; border-radius: 4px; cursor: pointer; font-size: 12px; } .btn-refresh { background: #fff; color: #2f54eb; } .btn-download-all { background: #ff7d00; color: #fff; } .btn-next { background: #00b42a; color: #fff; } .table-body { max-height: 600px; overflow-y: auto; } .table-row { display: flex; padding: 10px; border-bottom: 1px solid #f5f5f5; align-items: center; } .table-col { flex: 1; text-align: center; } .thumb-img { width: 60px; height: 60px; object-fit: cover; border-radius: 6px; cursor: pointer; border: 1px solid #eee; } .operate-btn { padding: 6px 8px; margin: 2px; border: none; border-radius: 4px; cursor: pointer; font-size: 12px; } .btn-goto { background: #2f54eb; color: white; } .btn-download { background: #f53f3f; color: white; } .btn-del { background: #999; color: white; } #imgPreviewModal { position: fixed; inset: 0; background: rgba(0,0,0,0.85); z-index: 1000000; display: flex; align-items: center; justify-content: center; cursor: zoom-out; } #imgPreviewModal img { max-width: 90vw; max-height: 90vh; border-radius: 10px; } @keyframes highlightFlash { 0%{border:3px solid #ff7d00;box-shadow:0 0 20px #ff7d00}50%{border:3px solid #ff3f3f;box-shadow:0 0 30px #ff3f3f}100%{border:3px solid #ff7d00;box-shadow:0 0 20px #ff7d00} } .highlight-goods { animation: highlightFlash 3s ease forwards; z-index:9999!important;position:relative; } `; document.head.appendChild(style); // ===================== DOM 结构 ===================== const tableContainer = document.createElement('div'); tableContainer.id = 'salesPositionTable'; const header = document.createElement('div'); header.className = 'table-header'; header.innerHTML = `
⋮⋮📊 销量定位
`; const body = document.createElement('div'); body.className = 'table-body'; tableContainer.append(header, body); document.body.appendChild(tableContainer); // 拖动逻辑 function initDrag(dragEl, handleEl) { let isDrag = false, ox=0, oy=0; handleEl.onmousedown = e => { isDrag=true; const r=dragEl.getBoundingClientRect(); ox=e.clientX-r.left; oy=e.clientY-r.top; dragEl.style.transition='none'; }; document.onmousemove = e=>{ if(!isDrag) return; dragEl.style.left=e.clientX-ox+'px'; dragEl.style.top=e.clientY-oy+'px'; dragEl.style.transform='none'; }; document.onmouseup = ()=>isDrag=false; } initDrag(tableContainer, header); // ===================== 核心:跨域直接下载 ===================== function download(url, name) { // 使用油猴提供的 GM_download 接口 GM_download({ url: url, name: name.endsWith('.jpg') ? name : name + '.jpg', saveAs: false, onerror: (err) => { console.error("下载失败:", err); // 兜底方案:如果 GM_download 失败,尝试新窗口打开 window.open(url, '_blank'); } }); } // ===================== 渲染表格 ===================== function render() { body.innerHTML = ''; if(validItems.length===0){ body.innerHTML='
暂无数据
'; return; } validItems.forEach((item, idx)=>{ const row = document.createElement('div'); row.className='table-row'; row.innerHTML=`
${item.sales} 件
`; body.appendChild(row); // 预览大图 row.querySelector('.thumb-img').onclick=()=>{ const m=document.createElement('div'); m.id='imgPreviewModal'; m.innerHTML=``; m.onclick=()=>m.remove(); document.body.append(m); }; // 定位高亮 row.querySelector('.btn-goto').onclick=()=>{ item.dom.scrollIntoView({behavior:'smooth',block:'center'}); item.dom.classList.add('highlight-goods'); setTimeout(()=>item.dom.classList.remove('highlight-goods'),3000); }; // 单张下载 row.querySelector('.btn-download').onclick=()=>{ download(item.bigImg, `Temu_${item.sales}件_${Date.now()}.jpg`); }; // 删除行 row.querySelector('.btn-del').onclick=()=>{ validItems.splice(idx,1); render(); }; }); } // 下载全部 async function downloadAll(){ for(let i=0; isetTimeout(r, 300)); } } // 按钮事件 header.querySelector('.btn-refresh').onclick=createSalesPositionTable; header.querySelector('.btn-download-all').onclick=downloadAll; header.querySelector('.btn-next').onclick=async()=>{ const nextBtn=document.querySelector('._2ugbvrpI._3E4sGl93._28_m8Owy.R8mNGZXv._2rMaxXAr'); if(!nextBtn){alert('已到最后一页');return;} nextBtn.scrollIntoView({behavior:'smooth',block:'center'}); await new Promise(r=>setTimeout(r,800)); nextBtn.click(); setTimeout(createSalesPositionTable,1800); }; render(); } // 页面加载自动启动 window.addEventListener('load',()=>{ setTimeout(createSalesPositionTable, 1500); }); })();