您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
在线选品
当前为
// ==UserScript== // @name online-selection // @namespace com.hho.middle.fe.online.selection // @version 0.9 // @description 在线选品 // @author bosiwan // @match *://*/* // @icon https://www.google.com/s2/favicons?domain=camp-fire.jp // @require https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js // @grant GM.setValue // @grant GM.getValue // @grant GM.deleteValue // @grant GM.listValues // @grant GM.setClipboard // @grant unsafeWindow // ==/UserScript== class Dep{ //订阅池 constructor(name){ this.id = new Date() // 使用时间戳做订阅池的ID this.subs = [] // 该事件下对象的集合 } defined(){ // 添加订阅者 Dep.watch.add(this); } notify(){ // 通知订阅者有变化 this.subs.forEach((e,i)=>{ if(typeof e.update === 'function'){ try{ e.update.apply(e); // 触发订阅者更新函数 }catch(err){ console.warr(err); } } }) } } Dep.watch = null; class Watch{ constructor(name,fn){ this.name = name; // 订阅消息的名称 this.id = new Date(); // 使用时间戳做订阅者的ID this.callBack = fn; // 订阅消息发送改变时 -> 订阅者执行的回调函数 } add(dep){ // 将订阅者放入dep订阅池 dep.subs.push(this); } update(){ // 将订阅者更新方法 var cb = this.callBack; // 赋值为了不改变函数内调用的this cb(this.name); } } (function() { 'use strict'; const enableSites = ['camp-fire.jp', 'greenfunding.jp', 'www.makuake.com'] const SourcingSites = ['item.taobao.com', 'detail.tmall.com'] const LoggingURL = 'containertest.hhodata.com' const enableListPathname = ['/projects/category', '/portals/search', '/discover/categories'] const enableDetailPathname = ['/projects/view', '/project'] const DomainMap = { 'camp-fire.jp': 'camp-fire', 'greenfunding.jp': 'GreenFunding', 'www.makuake.com': 'makuake' } let preX = 0, preY = 0, startX = 0, startY = 0, canMoving = false let exchangeRates = 1 // 汇率(日元转人民币) const CSSStyle = styles => { return styles.join(';') } const PrimaryButtonStyle = { 'background-color': 'rgb(3, 193, 253)', 'color': 'white', 'font-weight': 'bold', } const DeleteButtonStyle = { 'background-color': '#f52743', 'color': 'white', 'font-weight': 'bold', } const SecondaryButtonStyle = { 'background-color': 'white', 'color': '#03c1fd', 'font-weight': 'bold', 'border-style': 'solid', 'border-width': '1px', 'border-color': '#03c1fd', } const ButtonStyle = (style, other) => { const styles = {...{ 'padding-left': '16px', 'padding-right': '16px', 'padding-top': '6px', 'padding-bottom': '6px', 'min-width': '100px', 'border-radius': '4px', display: 'flex', 'align-items': 'center', 'justify-content': 'center', '-moz-user-select': '-moz-none', '-khtml-user-select': 'none', '-webkit-user-select': 'none', '-o-user-select': 'none', 'user-select': 'none', 'cursor': 'pointer', }, ...style, ...other} return Object.keys(styles).map(key => `${key}: ${styles[key]}`).join(';') } const ProjectListItemStyle = CSSStyle([ 'padding: 4px', 'border-width: 1px', 'border-bottom-color: gray', 'border-bottom-style: solid' ]) const ProjectListItemTitleStyle = CSSStyle([ 'white-space: nowrap', 'text-overflow: ellipsis', 'word-break: break-word', 'overflow: hidden' ]) const ProjectListItemStatusStyle = CSSStyle([ 'border-width: 1px', 'border-color: red', 'border-style: solid', 'padding: 2px', 'width: fit-content', 'font-size: 12px', 'border-radius: 4px', 'color: red' ]) function init() { $(document).ready(function() { if (window.location.host === LoggingURL) { console.log(localStorage.getItem('__hho_token__')) GM.setValue('hho_token', localStorage.getItem('__hho_token__')) window.close() return } if (SourcingSites.indexOf(window.location.host) !== -1) { } // 站点白名单 if (enableSites.indexOf(window.location.host) === -1) return // 添加按钮 $('body').append(`<div id="hho-online-selection-container" style="position:fixed; top: 50px; right: 40px; z-index: 9007199254740991; background: white; width: 300px; border-radius: 6px;box-shadow: 0px 0px 6px 3px rgba(0,0,0,0.5); padding: 8px;"> <div onmousedown="handleMouseDown(event)" onmouseup="handleMouseUp(event)" style="cursor: move;"> <div style="font-weight: bold;"><a href="https://cdn.hhodata.com/chrome-extension/online-selection/script.user.js">【更新插件】</a>7sou - 7秒寻源 <span id="loading-text"></span></div> <div class="button-list" style="display: flex; margin-top: 6px"></div> </div> <label>关键词:</label><input name="search" style="margin: 6px" /> <div class="result-container" style="max-height: 520px; overflow-y: scroll; cursor: default;"></div> </div>`) if (window.location.pathname.startsWith('/projects/category') || window.location.pathname.startsWith('/portals/search') || window.location.pathname.startsWith('/discover/categories') ) { $('#hho-online-selection-container').append('<button style="z-index: 9007199254740991;background: yellow;color: #333;cursor: pointer;" id="hhoBtn">开始选品</button>'); } else { const yesButton = `<div style="${ButtonStyle(PrimaryButtonStyle)}" id="hhoYesBtn">寻源</div>` $('#hho-online-selection-container .button-list').append(yesButton); const noButton = `<div style="${ButtonStyle(DeleteButtonStyle, {'margin-left': '6px'})}" id="hhoNoBtn">下一个</div>` $('#hho-online-selection-container .button-list').append(noButton); } $(document).on('click',"#hhoBtn", function(){ startSelection() }); $(document).on('click',"#hhoYesBtn", function(){ save() }); $(document).on('click', "#hhoNoBtn", function () { closeTab() }); $(document).on('paste', handlePaste) $(document).mousemove(handleMouse) $('input[name="search"]').on("keyup", function (event) { if (event.key === "Enter") { if (!unsafeWindow.hhoSourcingResults) return const searchKey = event.currentTarget.value if (searchKey) { unsafeWindow.hhoSourcingResultsFilter = unsafeWindow.hhoSourcingResults.filter(d => d.itemName.indexOf(searchKey) !== -1) } else { unsafeWindow.hhoSourcingResultsFilter = unsafeWindow.hhoSourcingResults } unsafeWindow.renderResultContainer(unsafeWindow.hhoSourcingResultsFilter) } }); getExchangeRates() }) } var $ = window.$ var addHistoryMethod = (function(){ var historyDep = new Dep(); return function(name){ if(name === 'historychange'){ return function(name,fn){ var event = new Watch(name,fn) Dep.watch = event; historyDep.defined(); Dep.watch = null; // 置空供下一个订阅者使用 } }else if(name === 'pushState' || name === 'replaceState'){ var method = history[name]; return function(){ init() method.apply(history,arguments); historyDep.notify(); } } } }()); window.addHistoryListener = addHistoryMethod('historychange'); history.pushState = addHistoryMethod('pushState'); history.replaceState = addHistoryMethod('replaceState'); init() function startSelection() { if (!window.location.pathname.startsWith('/projects/category') && !window.location.pathname.startsWith('/portals/search') && !window.location.pathname.startsWith('/discover/categories') ) { alert('不是列表页') return; } const domain = DomainMap[window.location.host] switch (domain) { case 'camp-fire': ListSelection.campfile() break; case 'GreenFunding': ListSelection.greenfunding() break; case 'makuake': ListSelection.makuake() break; default: break; } } function scrollToBottom(top = 1000, overHandler) { window.scroll({ top, left: 0, behavior: 'smooth' }) setTimeout(() => { var clientHeight = document.documentElement.scrollTop === 0 ? document.body.clientHeight : document.documentElement.clientHeight; var scrollTop = document.documentElement.scrollTop === 0 ? document.body.scrollTop : document.documentElement.scrollTop; var scrollHeight = document.documentElement.scrollTop === 0 ? document.body.scrollHeight : document.documentElement.scrollHeight; if (scrollTop != 0 && clientHeight + scrollTop == scrollHeight) { overHandler && overHandler() } else { scrollToBottom(top * 2, overHandler) } }, 500); } function _ajax (options, headers = { 'Content-Type': 'application/json' }) { console.log('123123', GM.getValue('hho_token')) $("#loading-text").text('加载中...') return new Promise((resolve, reject) => { GM.getValue('hho_token').then(res => { if (!res) { window.open('http://containertest.hhodata.com/', '_blank') return } $.ajax({ ...options, headers: {...headers, 'x-token': res}, complete: function (data) { $("#loading-text").text('') if (data.status === 200) { if (data.responseJSON.code === 7) { // 登录(不可用) window.open('http://containertest.hhodata.com/', '_blank') reject() } else { resolve(data.responseJSON.data) } } else { reject() } }, fail: function(err) { reject(err) } }) }).catch(err => window.open('http://containertest.hhodata.com/', '_blank')) }) } function getSourcingResult(project) { return _ajax({ url: `http://containertest.hhodata.com/api/sevenSmall/sevenSmallResult?projectCode=${project.code}&domain=${project.domain}`, method: 'GET', dataType: 'json', }) } function startSourcing(project) { return _ajax({ url: `http://containertest.hhodata.com/api/sevenSmall/sevenSmallParseSouring`, method: 'POST', dataType: 'json', data: JSON.stringify({ html: document.documentElement.innerHTML, url: window.location.href, projectCode: project.code, domain: project.domain }), }) } function resourcing (file, project) { var formData = new FormData() formData.append('projectCode', project.code) formData.append('domain', project.domain) formData.append('imgfile', file) return _ajax({ url: `http://containertest.hhodata.com/api/sevenSmall/sevenSmallSourcingAgain`, enctype: 'multipart/form-data', type: 'POST', dataType: 'json', processData: false, contentType: false, data: formData, }, {}) } async function save() { if (!window.location.pathname.startsWith('/projects/view') && !(/\/.*\/projects\/[0-9]+/.exec(window.location.pathname)) && !window.location.pathname.startsWith('/project') ) { alert('不是详情页页') return; } let project = {} const domain = DomainMap[window.location.host] switch (domain) { case 'camp-fire': project = DetailSelection.campfile() break; case 'GreenFunding': project = DetailSelection.greenfunding() break; case 'makuake': project = DetailSelection.makuake() break; default: break; } let results = await getSourcingResult(project) startSourcing(project).then(() => { getSourcingResult(project).then(showSourcingResult).catch(err => alert('寻源失败,再点一次试试')) }).catch(error => alert('寻源失败,再点一次试试')) } function closeTab() { if (!window.location.pathname.startsWith('/projects/view') && !(/\/.*\/projects\/[0-9]+/.exec(window.location.pathname)) && !window.location.pathname.startsWith('/project') ) { alert('不是详情页页') return; } const urls = JSON.parse(localStorage.getItem('hho-list-selection-urls')) const index = parseInt(localStorage.getItem('hho-list-selection-index')) + 1 const maxIndex = parseInt(localStorage.getItem('hho-list-selection-max-index')) if (maxIndex >= index) { window.close() localStorage.setItem('hho-list-selection-index', index) window.open(urls[index]) } else { alert('当前页已选完,请开始下一页') localStorage.setItem('hho-list-selection-urls', JSON.stringify([])) localStorage.setItem('hho-list-selection-index', 0) localStorage.setItem('hho-list-selection-max-index', 0) } } function handlePaste(event) { const items = event.originalEvent.clipboardData && event.originalEvent.clipboardData.items if (!items || items.length <= 0) { return } let file = null // 检索剪切板items file = Array.from(items).find(d => d.type.indexOf('image') !== -1)?.getAsFile() if (!file) { return } const confirm = window.confirm('确定重新寻源吗?') if(!confirm) return let project = {} const domain = DomainMap[window.location.host] switch (domain) { case 'camp-fire': project = DetailSelection.campfile() break; case 'GreenFunding': project = DetailSelection.greenfunding() break; case 'makuake': project = DetailSelection.makuake() break; default: break; } resourcing(file, project).then(res => { getSourcingResult(project).then(showSourcingResult).catch(err => alert('寻源失败,再点一次试试')) }) } // 移动container unsafeWindow.handleMouseDown = function handleMouseDown (event) { event.preventDefault() event.stopPropagation() preX = event.clientX preY = event.clientY startX = $('#hho-online-selection-container')[0].offsetLeft startY = $('#hho-online-selection-container')[0].offsetTop if (!canMoving) { canMoving = true } } unsafeWindow.handleMouseUp = function handleMouseUp (event) { event.preventDefault() event.stopPropagation() if (canMoving) { canMoving = false } } function handleMouse (event) { event.preventDefault() event.stopPropagation() if (!canMoving) return $("#hho-online-selection-container").css("top", event.clientY - preY + startY + 'px') $("#hho-online-selection-container").css("left", startX + event.clientX - preX + 'px') } // 获取汇率 function getExchangeRates () { exchangeRates = 0.056 renderExchangePrice() // let data = new FormData() // data.append('pinzhong', 'JPYCNY') // data.append('longs', 'd1') // _ajax({ // url: 'https://webapi.huilv.cc/api/trend/yaho', // type: 'POST', // enctype: 'multipart/form-data', // dataType: 'json', // processData: false, // contentType: false, // data: data // }).then(res => { // console.log(res) // }) } // append 转人民币后的价格 并且 * 0.6 function renderExchangePrice () { $("#return").before(`<p style="padding: 12px">实时汇率: ${exchangeRates}</p>`) Array.prototype.slice.call(document.querySelectorAll('.return-section .lefth4RightBase ')).forEach(ele => { const price = Number(ele.innerText.match(/\d+/g).join('')) const exchangePrice = +Number(price * exchangeRates).toFixed(2) const offPrice = Number(exchangePrice * 0.6).toFixed(2) $(ele).after(`<p style="padding: 12px" class="hho-exchange-price">人民币:${exchangePrice} * 0.6 = ${offPrice}</p>`) }); } window.showSourcingResult = function showSourcingResult (results) { unsafeWindow.hhoSourcingResults = results unsafeWindow.renderResultContainer(results) } unsafeWindow.renderResultContainer = function renderResultContainer (results) { $('#hho-online-selection-container .result-container').empty() {$('#hho-online-selection-container .result-container').append(results.map(r => ` <div class='result-item' onclick="window.open('${r.itemUrl}', '_blank')"> <div> <img src="${r.itemPrcUrl}" style="width: 180px"> </div <div> <div>${r.itemName}</div> </div> </div> `).join(''))} } const ListSelection = { campfile() { const urls = Array.from(document.querySelectorAll('.boxes4 .box .box-title a')).map(d => d.href) localStorage.setItem('hho-list-selection-urls', JSON.stringify(urls)) localStorage.setItem('hho-list-selection-index', 0) localStorage.setItem('hho-list-selection-max-index', urls.length - 1) window.open(urls[0]) }, greenfunding() { const urls = Array.from(document.querySelectorAll('.m-projects__card .js-methods__hover')).map(d => d.href) localStorage.setItem('hho-list-selection-urls', JSON.stringify(urls)) localStorage.setItem('hho-list-selection-index', 0) localStorage.setItem('hho-list-selection-max-index', urls.length - 1) window.open(urls[0]) }, makuake() { const urls = Array.from(document.querySelectorAll('.projects .ProjectItem a')).map(d => d.href) localStorage.setItem('hho-list-selection-urls', JSON.stringify(urls)) localStorage.setItem('hho-list-selection-index', 0) localStorage.setItem('hho-list-selection-max-index', urls.length - 1) window.open(urls[0]) } } const DetailSelection = { campfile() { const code = window.dataLayer[1].dynx_itemid; const name = document.title const domain = 'camp-file' return {code, name, domain} }, greenfunding() { const code = window.location.pathname.split('/').reverse()[0] const name = document.title const domain = 'GreenFunding' return {code, name, domain} }, makuake() { const code = window.location.pathname.split('/').reverse()[1] const name = document.title const domain = 'makuake' return {code, name, domain} } } })();
QingJ © 2025
镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址