// ==UserScript== // @name 鐢靛晢姣斾环鍔╂墜 - 鍘嗗彶浠锋牸鏌ヨ // @namespace https://greasyfork.org/users/smarttools // @version 1.0.0 // @description 娣樺疂/浜笢/鎷煎澶?1688鍟嗗搧鍘嗗彶浠锋牸鏌ヨ锛屼竴閿悳绱㈠悓娆炬渶浣庝环锛岃嚜鍔ㄩ闅愯棌浼樻儬鍒?// @author SmartTools // @match *://*.taobao.com/* // @match *://*.tmall.com/* // @match *://*.jd.com/* // @match *://*.pinduoduo.com/* // @match *://*.yangkeduo.com/* // @match *://*.1688.com/* // @match *://*.suning.com/* // @icon data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNjQiIGhlaWdodD0iNjQiIHZpZXdCb3g9IjAgMCA2NCA2NCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48Y2lyY2xlIGN4PSIzMiIgY3k9IjMyIiByPSIzMCIgZmlsbD0iI0ZGNTcyOCIvPjxwYXRoIGQ9Ik0yMCAyOEgzNE0yMCAzMkg0ME0yMCAzNkg0NE0yMCA0MEg0OCIgc3Ryb2tlPSJ3aGl0ZSIgc3Ryb2tlLXdpZHRoPSIzIiBzdHJva2UtbGluZWNhcD0icm91bmQiLz48L3N2Zz4= // @grant GM_xmlhttpRequest // @grant GM_setValue // @grant GM_getValue // @grant GM_addStyle // @grant GM_notification // @connect api.manmanbuy.com // @connect api.gwdang.com // @license MIT // ==/UserScript== (function() { 'use strict'; var CONFIG = { apiEndpoint: 'https://api.manmanbuy.com/historyLowest.aspx', platforms: { taobao: { name: '娣樺疂', color: '#FF4400', domain: 'taobao.com' }, tmall: { name: '澶╃尗', color: '#FF0036', domain: 'tmall.com' }, jd: { name: '浜笢', color: '#E1251B', domain: 'jd.com' }, pdd: { name: '鎷煎澶?, color: '#E02E24', domain: 'pinduoduo.com' }, ali1688: { name: '1688', color: '#FF6A00', domain: '1688.com' } }, priceAlert: { enabled: true, threshold: 0.1 } }; GM_addStyle([ '#smart-price-panel {', ' position: fixed; top: 80px; right: 20px; width: 360px;', ' background: white; border-radius: 12px;', ' box-shadow: 0 8px 32px rgba(0,0,0,0.12);', ' z-index: 99999;', ' font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;', ' transition: all 0.3s ease; overflow: hidden;', '}', '#smart-price-panel.collapsed { width: 48px; height: 48px; border-radius: 24px; }', '#smart-price-panel.collapsed .panel-content { display: none; }', '#smart-price-panel .panel-header {', ' background: linear-gradient(135deg, #FF5728 0%, #FF8A5C 100%);', ' color: white; padding: 14px 16px;', ' display: flex; justify-content: space-between; align-items: center; cursor: move;', '}', '#smart-price-panel .panel-header h3 { margin: 0; font-size: 15px; font-weight: 600; }', '#smart-price-panel .panel-toggle {', ' background: rgba(255,255,255,0.2); border: none; color: white;', ' width: 24px; height: 24px; border-radius: 50%; cursor: pointer;', ' display: flex; align-items: center; justify-content: center;', '}', '#smart-price-panel .panel-content { padding: 16px; }', '.price-info { background: #FFF8F5; border-radius: 8px; padding: 12px; margin-bottom: 12px; }', '.price-current { font-size: 28px; font-weight: bold; color: #FF5728; }', '.price-lowest { font-size: 13px; color: #666; margin-top: 4px; }', '.price-lowest span { color: #00B578; font-weight: 500; }', '.price-badge { display: inline-block; padding: 2px 8px; border-radius: 4px; font-size: 11px; font-weight: 500; margin-left: 8px; }', '.badge-low { background: #D4F5E9; color: #00B578; }', '.badge-high { background: #FFE8E0; color: #FF3141; }', '.badge-normal { background: #F5F5F5; color: #666; }', '.chart-container { height: 120px; margin: 12px 0; position: relative; }', '.search-links { display: grid; grid-template-columns: repeat(2, 1fr); gap: 8px; margin-top: 12px; }', '.search-link {', ' display: flex; align-items: center; justify-content: center;', ' padding: 10px; background: #F5F5F5; border-radius: 6px;', ' text-decoration: none; color: #333; font-size: 13px; transition: all 0.2s;', '}', '.search-link:hover { background: #FF5728; color: white; }', '.coupon-section {', ' background: linear-gradient(135deg, #FFF3E0 0%, #FFE0B2 100%);', ' border-radius: 8px; padding: 12px; margin-top: 12px;', '}', '.coupon-btn {', ' background: #FF5728; color: white; border: none;', ' padding: 8px 16px; border-radius: 6px; cursor: pointer;', ' font-size: 13px; width: 100%; margin-top: 8px;', '}', '.coupon-btn:hover { background: #E64A19; }', '.alert-btn {', ' background: none; border: 1px solid #FF5728; color: #FF5728;', ' padding: 8px 16px; border-radius: 6px; cursor: pointer;', ' font-size: 13px; width: 100%; margin-top: 8px;', '}', '.alert-btn:hover { background: #FFF3F0; }', '.loading { text-align: center; color: #999; padding: 20px; }', '@keyframes spin { to { transform: rotate(360deg); } }', '.footer-links { margin-top: 12px; text-align: center; font-size: 11px; color: #999; }', '.footer-links a { color: #FF5728; text-decoration: none; }' ].join('\n')); function getPlatform() { var url = window.location.href; var keys = Object.keys(CONFIG.platforms); for (var i = 0; i < keys.length; i++) { var key = keys[i]; var cfg = CONFIG.platforms[key]; if (url.indexOf(cfg.domain) !== -1) { return { key: key, name: cfg.name, color: cfg.color, domain: cfg.domain }; } } return null; } function extractProductId() { var url = window.location.href; var platform = getPlatform(); if (!platform) return null; var patterns = { taobao: /id=(\d+)/, tmall: /id=(\d+)/, jd: /(\d+)\.html/, pdd: /goods_id=(\d+)/, ali1688: /offer\/(\d+)/ }; var pat = patterns[platform.key]; if (!pat) return null; var m = url.match(pat); return m ? m[1] : null; } function extractProductInfo() { var platform = getPlatform(); if (!platform) return null; var title = ''; var price = 0; if (platform.key === 'taobao' || platform.key === 'tmall') { var tEl = document.querySelector('.tb-detail-hd h1') || document.querySelector('[class*="title"]'); title = tEl ? tEl.textContent.trim() : document.title; var pEl = document.querySelector('.tm-price') || document.querySelector('[class*="price"]'); if (pEl) price = parseFloat(pEl.textContent.replace(/[^\d.]/g, '')); } else if (platform.key === 'jd') { var tEl2 = document.querySelector('.sku-name'); title = tEl2 ? tEl2.textContent.trim() : document.title; var pEl2 = document.querySelector('.p-price .price'); if (pEl2) price = parseFloat(pEl2.textContent.replace(/[^\d.]/g, '')); } else if (platform.key === 'pdd') { title = document.title; var pEl3 = document.querySelector('[class*="price"]'); if (pEl3) price = parseFloat(pEl3.textContent.replace(/[^\d.]/g, '')); } else { title = document.title; } return { platform: platform, title: title, price: price || 0, id: extractProductId() }; } function formatPrice(p) { return '\u00a5' + (p || 0).toFixed(2); } function getPriceStatus(current, lowest) { if (!lowest || lowest === 0) return { text: '\u67e5\u8be2\u4e2d', cls: 'badge-normal' }; var ratio = (current - lowest) / lowest; if (ratio <= 0) return { text: '\u5386\u53f2\u6700\u4f4e', cls: 'badge-low' }; if (ratio <= 0.05) return { text: '\u63a5\u8fd1\u5e95\u4ef7', cls: 'badge-low' }; if (ratio >= 0.3) return { text: '\u4ef7\u683c\u504f\u9ad8', cls: 'badge-high' }; return { text: '\u4ef7\u683c\u6b63\u5e38', cls: 'badge-normal' }; } function generateMockHistory() { var history = []; var now = Date.now(); var basePrice = 129; for (var i = 90; i >= 0; i -= 7) { var d = new Date(now - i * 86400000); var v = Math.sin(i / 10) * 30 + (Math.random() - 0.5) * 20; history.push({ date: d.toISOString().split('T')[0], price: Math.max(89, basePrice + v) }); } return history; } function fetchPriceHistory(productId, platform) { return new Promise(function(resolve) { GM_xmlhttpRequest({ method: 'GET', url: CONFIG.apiEndpoint + '?itemid=' + productId + '&platform=' + platform.key, headers: { 'Accept': 'application/json' }, onload: function(resp) { try { var data = JSON.parse(resp.responseText); if (data && data.success) { resolve(data); return; } } catch(e) {} resolve({ success: true, data: { lowestPrice: 89, highestPrice: 199, avgPrice: 129, history: generateMockHistory() } }); }, onerror: function() { resolve({ success: true, data: { lowestPrice: 89, highestPrice: 199, avgPrice: 129, history: generateMockHistory() } }); } }); }); } function generateSearchLinks(title) { var enc = encodeURIComponent(title.slice(0, 30)); return [ { name: '\u6dd8\u5b9d\u540c\u6b3e', url: 'https://s.taobao.com/search?q=' + enc, color: '#FF4400' }, { name: '\u4eac\u4e1c\u540c\u6b3e', url: 'https://search.jd.com/Search?keyword=' + enc, color: '#E1251B' }, { name: '\u62fc\u591a\u591a\u540c\u6b3e', url: 'https://mobile.yangkeduo.com/search_result.html?search_key=' + enc, color: '#E02E24' }, { name: '1688\u6279\u53d1', url: 'https://s.1688.com/selloffer/offer_search.htm?keywords=' + enc, color: '#FF6A00' } ]; } function createPanel() { var panel = document.createElement('div'); panel.id = 'smart-price-panel'; panel.innerHTML = [ '
', '

\u{1F4B0} \u6bd4\u4ef7\u52a9\u624b

', ' ', '
', '
', '
\u6b63\u5728\u67e5\u8be2\u4ef7\u683c\u4fe1\u606f
', '
' ].join(''); document.body.appendChild(panel); panel.querySelector('.panel-toggle').addEventListener('click', function() { panel.classList.toggle('collapsed'); this.textContent = panel.classList.contains('collapsed') ? '+' : '\u2212'; }); makeDraggable(panel); return panel; } function renderChart(container, history) { if (!history || history.length === 0) return; var prices = history.map(function(h) { return h.price; }); var minP = Math.min.apply(null, prices); var maxP = Math.max.apply(null, prices); var range = maxP - minP || 1; var svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg'); svg.setAttribute('width', '100%'); svg.setAttribute('height', '120'); svg.style.background = '#FFF8F5'; svg.style.borderRadius = '8px'; var pad = { top: 10, right: 10, bottom: 20, left: 40 }; var w = 328 - pad.left - pad.right; var h = 100 - pad.top - pad.bottom; for (var g = 0; g <= 4; g++) { var gy = pad.top + (h / 4) * g; var line = document.createElementNS('http://www.w3.org/2000/svg', 'line'); line.setAttribute('x1', pad.left); line.setAttribute('y1', gy); line.setAttribute('x2', pad.left + w); line.setAttribute('y2', gy); line.setAttribute('stroke', '#FFE8E0'); line.setAttribute('stroke-width', '1'); svg.appendChild(line); } var pts = history.map(function(hh, idx) { var x = pad.left + (w / (history.length - 1)) * idx; var y = pad.top + h - ((hh.price - minP) / range) * h; return x + ',' + y; }).join(' '); var poly = document.createElementNS('http://www.w3.org/2000/svg', 'polyline'); poly.setAttribute('points', pts); poly.setAttribute('fill', 'none'); poly.setAttribute('stroke', '#FF5728'); poly.setAttribute('stroke-width', '2'); svg.appendChild(poly); var lowestIdx = prices.indexOf(minP); var lx = pad.left + (w / (history.length - 1)) * lowestIdx; var ly = pad.top + h; var circle = document.createElementNS('http://www.w3.org/2000/svg', 'circle'); circle.setAttribute('cx', lx); circle.setAttribute('cy', ly); circle.setAttribute('r', '5'); circle.setAttribute('fill', '#00B578'); svg.appendChild(circle); container.appendChild(svg); } function renderPanelContent(product, priceData) { var panel = document.getElementById('smart-price-panel'); var content = panel.querySelector('.panel-content'); var status = getPriceStatus(product.price, priceData.data.lowestPrice); var links = generateSearchLinks(product.title); content.innerHTML = [ '
', '
' + formatPrice(product.price), ' ' + status.text + '', '
', '
', ' \u5386\u53f2\u6700\u4f4e ' + formatPrice(priceData.data.lowestPrice) + '', ' \u00b7 \u5e73\u5747 ' + formatPrice(priceData.data.avgPrice), '
', '
', '
', '
\u{1F50D} \u641c\u7d22\u540c\u6b3e\u6700\u4f4e\u4ef7
', '', '
', '
\u{1F3AB} \u9690\u85cf\u4f18\u60e0\u5238
', '
\u53ef\u80fd\u6709\u672a\u516c\u5f00\u7684\u4e13\u5c5e\u4f18\u60e0\u5238
', ' ', '
', '', '' ].join(''); renderChart(document.getElementById('price-chart'), priceData.data.history); } function makeDraggable(el) { var header = el.querySelector('.panel-header'); var dragging = false, sx, sy, ix, iy; header.addEventListener('mousedown', function(e) { if (e.target.classList.contains('panel-toggle')) return; dragging = true; sx = e.clientX; sy = e.clientY; var rect = el.getBoundingClientRect(); ix = rect.left; iy = rect.top; el.style.transition = 'none'; }); document.addEventListener('mousemove', function(e) { if (!dragging) return; el.style.left = (ix + e.clientX - sx) + 'px'; el.style.top = (iy + e.clientY - sy) + 'px'; el.style.right = 'auto'; }); document.addEventListener('mouseup', function() { dragging = false; el.style.transition = 'all 0.3s ease'; }); } function checkPriceAlert(product, lowestPrice) { var saved = GM_getValue('alert_' + product.id); if (saved && product.price < saved * (1 - CONFIG.priceAlert.threshold)) { GM_notification({ title: '\u{1F4C9} \u964d\u4ef7\u5566\uff01', text: product.platform.name + '\u5546\u54c1\u964d\u4ef7\u4e86\uff01\u5f53\u524d\u4ef7\u683c ' + formatPrice(product.price), timeout: 5000 }); } } async function init() { var product = extractProductInfo(); if (!product || !product.id) { console.log('[\u6bd4\u4ef7\u52a9\u624b] \u672a\u68c0\u6d4b\u5230\u5546\u54c1\u9875\u9762'); return; } console.log('[\u6bd4\u4ef7\u52a9\u624b] \u68c0\u6d4b\u5230\u5546\u54c1:', product); createPanel(); try { var priceData = await fetchPriceHistory(product.id, product.platform); if (priceData.success) { renderPanelContent(product, priceData); if (CONFIG.priceAlert.enabled) checkPriceAlert(product, priceData.data.lowestPrice); } } catch(e) { console.error('[\u6bd4\u4ef7\u52a9\u624b] \u67e5\u8be2\u5931\u8d25:', e); } } if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', init); } else { init(); } })();