您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
在线选品
当前为
// ==UserScript== // @name online-selection // @namespace com.hho.middle.fe.online.selection // @version 0.18 // @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 // @require https://cdnjs.cloudflare.com/ajax/libs/bootbox.js/5.5.2/bootbox.min.js // @grant GM.setValue // @grant GM.getValue // @grant GM.deleteValue // @grant GM.listValues // @grant GM.setClipboard // @grant GM_addStyle // @grant GM_openInTab // @grant GM_xmlhttpRequest // @grant GM_download // @grant unsafeWindow // @run-at document-start // @connect taobao.com // @connect alicdn.com // @connect hhodata.com // @connect tamll.com // @connect 1688.com // ==/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'; // TODO: 切换测试正式 const portalHost = 'portal.hhodata.com' // const portalHost = 'containertest.hhodata.com' // 众筹站点 const fundingSites = ['camp-fire.jp', 'greenfunding.jp', 'www.makuake.com'] // 众筹 pathnames 列表遍历寻源 // const fundingListPathname = ['/projects/category', '/portals/search', '/discover/categories'] // 众筹 detail 详情寻源 const fundingDetailPathname = ['/projects/view', '/project'] // 寻源站点 const sourcingSites = ['item.taobao.com', 'detail.tmall.com', 'detail.tmall.hk', 'detail.1688.com'] // portal const portalPaths = [ 'https://portal.hhodata.com/sevensmall-onshelf/sevensmall-onshelf/add', 'http://containertest.hhodata.com/sevensmall-onshelf/sevensmall-onshelf/add' ] const isFundingSites = fundingSites.indexOf(window.location.host) !== -1 const isSourcingSites = sourcingSites.indexOf(window.location.host) !== -1 const isPortal = portalPaths.indexOf(window.location.href.split('?')[0]) !== -1 const isFrom7sou = queryParams('extension') === '7sou' // api baseurl const baseURL = `http${portalHost.startsWith('containertest') ? '' : 's'}://` + portalHost const DomainMap = { 'camp-fire.jp': 'camp-fire', 'greenfunding.jp': 'GreenFunding', 'www.makuake.com': 'makuake', 'item.taobao.com': 'taobao', 'detail.1688.com': 'one688', 'detail.tmall.com': 'tmall', 'detail.tmall.hk': 'tmall', } // 拖动事件,记录鼠标xy let preX = 0, preY = 0, startX = 0, startY = 0, canMoving = false // 汇率记录(日元转人民币) let exchangeRates = 1 // blob 视频流处理 let _sourceBufferList = [] // blob let _endOfStream = window.MediaSource.prototype.endOfStream // 监听资源全部录取成功 let _addSourceBuffer = window.MediaSource.prototype.addSourceBuffer // 录取资源 let _sourceBufferLoaded = false // 已经加载完 const css =` .hho-button { 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; } .hho-primary-button { background-color: rgb(3, 193, 253); color: white; font-weight: bold; } .hho-delete-button { background-color: #f52743; color: white; font-weight: bold; } .hho-online-selection-container { 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; } .button-list { display: flex; margin-top: 6px; } .result-container { max-height: 520px; overflow-y: scroll; cursor: default; } .hho-selected { border: 1px solid red; } .result-container ul li span:nth-of-type(2) { cursor: pointer } ` GM_addStyle(css) const enableSites = ['camp-fire.jp', 'greenfunding.jp', 'www.makuake.com', 'detail.tmall.com', 'detail.tmall.hk', 'detail.1688.com', 'item.taobao.com'] const SourcingSites = ['item.taobao.com', 'detail.tmall.com', 'detail.tmall.hk'] // const LoggingURL = 'containertest.hhodata.com' // TODO // const baseURL = 'http://containertest.hhodata.com' // TODO const LoggingURL = 'portal.hhodata.com' // TODO // const baseURL = 'https://portal.hhodata.com' // TODO const enableListPathname = ['/projects/category', '/portals/search', '/discover/categories'] const enableDetailPathname = ['/projects/view', '/project'] const portalUrl = baseURL + '/sevensmall-onshelf/sevensmall-shelfing?iframe=false&page=1&queryParam={}&extension=7sou' const uploadSites = ['detail.tmall.com', 'detail.tmall.hk', 'detail.1688.com', 'item.taobao.com'] function init() { $(document).ready(function() { if (window.location.host === portalHost && window.location.pathname.indexOf('sevensmall-onshelf') === -1) { const token = localStorage.getItem('__hho_token__') if (token) { GM.setValue('hho_token', localStorage.getItem('__hho_token__')) window.close() return } } // 站点白名单 // if (enableSites.indexOf(window.location.host) === -1 && window.location.href !== portalUrl) return if (!isFundingSites && !isSourcingSites && !isPortal) return // 添加按钮 if ($('#hho-online-selection-container').length > 0) return $('body').append(`<div id="hho-online-selection-container" class="hho-online-selection-container"> <div id="hho-online-selection-header" 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"></div> <div id="hhoBlob"></div> <div id="hhoLog"></div> </div> <div class="result-container"></div> </div>`) if (isFundingSites) { const yesButton = `<div class="hho-button hho-primary-button" id="hhoYesBtn">寻源</div>` $('#hho-online-selection-container .button-list').append(yesButton); $('#hho-online-selection-header').after('<label>关键词:</label><input name="search" style="margin: 6px" />') // 事件绑定 $(document).off('click',"#hhoYesBtn", save); $(document).on('click',"#hhoYesBtn", save); $(document).off('paste', handleSourcingPaste) $(document).on('paste', handleSourcingPaste) // 查询线索关系 queryRelation() // 渲染汇率 getExchangeRates().then(res => { exchangeRates = Number(Number(res).toFixed(2)) renderExchangePrice() }) // 搜索 $('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) } }); } else if (isSourcingSites) { // 寻源站点 【一键上架】、【重新加载图片】 const uploadButton = `<div class="hho-button hho-primary-button" id="hhoUploadButton">一键上架</div>` $('#hho-online-selection-container .button-list').append(uploadButton); const renderImageButton = `<div class="hho-button hho-primary-button" style="margin-left: 10px" id="renderImageButton">重新加载图片</div>` $('#hho-online-selection-container .button-list').append(renderImageButton); // 获取图片 renderImageList() // 事件绑定 $(document).off('click',"#renderImageButton", renderImageList); $(document).on('click', "#renderImageButton", renderImageList); $(document).off('click',"#hhoUploadButton", startUpload); $(document).on('click', "#hhoUploadButton", startUpload); $(document).off('paste', handleSourcingSitesPaste) $(document).on('paste', handleSourcingSitesPaste) // blob视频 window.MediaSource.prototype.endOfStream = function () { logger('blob视频资源全部捕获成功') $('#hhoBlob').text('') _sourceBufferLoaded = true _endOfStream.call(this) } window.MediaSource.prototype.addSourceBuffer = function (mime) { let sourceBuffer = _addSourceBuffer.call(this, mime) let _append = sourceBuffer.appendBuffer let bufferList = [] if (mime.startsWith('video/mp4')) { _sourceBufferList.push({ mime, bufferList }) sourceBuffer.appendBuffer = function (buffer) { console.log(`正在捕获blob片段,已捕获 ${_sourceBufferList[0].bufferList.length} 个`) $('#hhoBlob').text(`正在捕获blob片段,已捕获 ${_sourceBufferList[0].bufferList.length} 个`) bufferList.push(buffer) _append.call(this, buffer) } } return sourceBuffer } } else if (isPortal && isFrom7sou) { // TODO spec GM.getValue('hho_attributes').then(res => { const attributesList = JSON.parse(res) $('#hho-online-selection-container .result-container').empty() $('#hho-online-selection-container .result-container').append('<ul></ul>') attributesList.forEach(d => { console.log(d) if (d && d.length < 24) { let tmp = d.split(':') if (tmp[1]) { $('#hho-online-selection-container .result-container ul').append(`<li><span>${tmp[0]} :</span><span>${tmp[1]}</span></li>`) } } }) }) } $(document).mousemove(handleMouse) }) } 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 _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(baseURL) return } $.ajax({ ...options, headers: {...headers, 'x-token': res}, complete: function (data) { $("#loading-text").text('') if (data.status === 200) { if (data.responseJSON.msg === '未登录(不可用)或非法访问') { // 登录(不可用) window.open(baseURL) reject() } else { resolve(data.responseJSON.data) } } else { reject() } }, fail: function(err) { reject(err) } }) }).catch(err => window.open(baseURL)) }) } function _gmAjax (options, headers = {}) { $("#loading-text").text('加载中...') return new Promise((resolve, reject) => { GM.getValue('hho_token').then(res => { if (!res) { window.open(baseURL) return } GM_xmlhttpRequest({ ...options, headers: { ...headers, 'x-token': res }, onload: function (data) { console.log(data) $("#loading-text").text('') if (data.status === 200) { if (JSON.parse(data.response).msg === '未登录(不可用)或非法访问' || JSON.parse(data.response).msg === '您的帐户异地登陆或令牌失效') { // 登录(不可用) window.open(baseURL) reject() } else { resolve(JSON.parse(data.response)) } } else if (data.status === 405) { window.open(baseURL) reject() } else { $("#loading-text").text(data.statusText) const errResponse = JSON.parse(data.response) reject(data.status + ' ' + (data.statusText || errResponse.errorMsg)) } }, onerror: function (err) { window.open(baseURL) console.log(err) reject(); } }) }).catch(err => window.open(baseURL)) }) } function queryParams(param) { return new URL(location.href).searchParams.get(param) } function getJPNPrice(CHNPrice) { const price = (parseInt(CHNPrice) + 50) * 18.12 * 1.1 return Math.ceil(price) } function getSourcingResult(project) { return _ajax({ url: baseURL + `/api/sevenSmall/sevenSmallResult?projectCode=${project.code}&domain=${project.domain}`, method: 'GET', dataType: 'json', }) } function startSourcing(project) { return _ajax({ url: baseURL + `/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: baseURL + `/api/sevenSmall/sevenSmallSourcingAgain`, enctype: 'multipart/form-data', type: 'POST', dataType: 'json', processData: false, contentType: false, data: formData, }, {}) } 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; } startSourcing(project).then(() => { getSourcingResult(project).then(showSourcingResult).catch(err => alert('寻源失败,再点一次试试')) }).catch(error => alert('寻源失败,再点一次试试')) } // 截图寻源 function handleSourcingPaste(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('寻源失败,再点一次试试')) }) } // 截图上传商品主图/OCR识别 function handleSourcingSitesPaste (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.prompt('上传商品主图请填1,OCR识别请填2。都不是请取消', '1') console.log(confirm) if (!confirm) return if (confirm === '1') { const url = URL.createObjectURL(file) renderImageList({hhosrc: url}) } else if (confirm === '2') { // TODO: OCR接口,获取的内容存入 ocrAttributes // logger ('正在识别OCR内容') } } // 移动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) { if (canMoving) { event.preventDefault() event.stopPropagation() $("#hho-online-selection-container").css("top", event.clientY - preY + startY + 'px') $("#hho-online-selection-container").css("left", startX + event.clientX - preX + 'px') } } // 获取汇率 function getExchangeRates () { return _ajax({ url: baseURL + `/api/sevenSmall/getExchange?currency=JPY`, method: 'GET', dataType: 'json', }) } // append 转人民币后的价格 并且 * 0.6 function renderExchangePrice () { const domain = DomainMap[window.location.host] let ul, li; switch (domain) { case 'camp-fire': ul = ExchangePriceSelection.campfile().ul li = ExchangePriceSelection.campfile().li break; case 'GreenFunding': ul = ExchangePriceSelection.greenfunding().ul li = ExchangePriceSelection.greenfunding().li break; case 'makuake': ul = ExchangePriceSelection.makuake().ul li = ExchangePriceSelection.makuake().li break; default: break; } if (!ul || !li) {return} $(ul).before(`<p style="padding: 12px">实时汇率: ${exchangeRates.toLocaleString()}</p>`) Array.prototype.slice.call(document.querySelectorAll(li)).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.toLocaleString()} * 0.6 = ${offPrice.toLocaleString()}</p>`) }); } function renderImageList (uploadImage) { $('#hho-online-selection-container .result-container').empty() const domain = DomainMap[window.location.host] if (!domain) return let imagesList = ImageSelection[domain]() if (uploadImage) { imagesList.push(uploadImage) } $('.result-container').append('<div class="result-images" style="display: grid; grid-template-columns: 100px 100px 100px; grid-template-rows: 100px 100px 100px;"></div>') imagesList.forEach((img, index) => { if (img.hhosrc) { $('.result-container .result-images').append('<img class="hho-image" style="width: 90%; aspect-ratio: 1 / 1;" src="' + img.hhosrc + '" />') } }) $('.result-container .result-images').off('click', 'img', selectImage) $('.result-container .result-images').on('click', 'img', selectImage) } function selectImage (e) { $('.result-container .result-images img').each(function(){ $(this).removeClass('hho-selected') }); $(this).addClass('hho-selected') } function startUpload () { $('#hhoLog').empty() logger('开始一键上架') const domain = DomainMap[window.location.host] if (!domain) return UploadSelection[domain]().then(res => { console.log('init data: ', res) if (!res) { logger('没有解析到页面数据,请联系管理员') return } if (isNaN(res.rmbPrice)) { logger('请选择具体 SKU 的价格后再继续上传') return } if (!res.img) { logger('请选择主图后再继续上传') return } if (!res.video) { if (window.location.host === 'detail.1688.com') { logger('1688一键上架前请先点击视频播放') return } logger('页面上没有视频,不建议上传') return } let videoFn if (res.video.startsWith('blob')) { // blob if (!_sourceBufferLoaded) { logger('blob 视频资源未加载完毕,请加载完毕后再次点击【一键上架】') return } videoFn = blobToFile } else { videoFn = mp4ToFile } videoFn(res.video).then((videoFile) => { return fileUpload(videoFile, 'video') }).then(videoUrl => { res.ossOriginalUrl = videoUrl return imageToFile(res.img) }).then(imageFile => { return fileUpload(imageFile, 'image') }).then(imageUrl => { res.productImage = imageUrl return create7smallForm(res) }).then(sevensmallId => { window.open(`${baseURL}/sevensmall-onshelf/sevensmall-onshelf/add?id=${sevensmallId}&iframe=false&onShelf=false&extension=7sou`) // 建立关系 if (isFrom7sou) { createSevensmallRelation(sevensmallId) } }).catch(err => { console.log(err) }) }) // blob url to File function blobToFile () { return new Promise((resolve, reject) => { _sourceBufferList.forEach((target) => { const mime = target.mime.split(';')[0] const type = mime.split('/')[1] const fileBlob = new Blob(target.bufferList, { type: mime }) resolve(new window.File([fileBlob], '1.mp4', { type: fileBlob.type })) }) }) } // mp4 url 转 File 对象 function mp4ToFile (url) { logger('准备将视频解析成File') return new Promise((resolve, reject) => { GM_xmlhttpRequest({ url: url, responseType: 'blob', method: 'GET', onload: function (resblob) { logger('视频解析成File成功') resolve(new window.File([resblob.response], '1.mp4')) }, onerror: function (err) { logger('视频解析成File失败') reject(err) } }) }) } // img url 转 File 对象 function imageToFile (url) { logger('准备将图片解析成File') return new Promise((resolve, reject) => { GM_xmlhttpRequest({ url: url, responseType: 'blob', method: 'GET', onload: function (res) { logger('图片解析成File成功') resolve(new window.File([res.response], '1.jpg', { type: res.type })) }, onerror: function (err) { logger('图片解析成File失败') reject(err) } }) }) } // File 上传到 OSS function fileUpload (meidaFile, mediaType) { if(!meidaFile) return return new Promise((resolve, reject) => { logger(mediaType === 'video' ? '正在上传视频,请耐心等待...' : '正在上传图片,请耐心等待...') let fd = new FormData() fd.append('file', meidaFile) _gmAjax({ url: baseURL + '/api/item/center/upload/upload', method: 'POST', data: fd, }).then(resvideo => { logger(mediaType === 'video' ? '视频上传成功' : '图片上传成功') resolve(resvideo.data.url) }).catch(err => { logger((mediaType === 'video' ? '视频上传失败' : '图片上传失败') + err) reject(err) }) }) } } // function translate (titleCN) { // logger('准备翻译标题') // return _gmAjax({ // url: baseURL + '/api/translation/tool/robot/description', // method: 'POST', // dataType: 'json', // data: JSON.stringify({ description: titleCN }) // }, {'Content-Type': 'application/json; charset=UTF-8'}) // } function logger (text) { $('#hhoLog').append(`<p>${new Date().toLocaleString()} ${text}</p>`) } function create7smallForm(data) { return new Promise((resolve, reject) => { console.log('create7smallForm: ', data) logger('准备新增7small') _gmAjax({ url: baseURL + '/api/user_favourite/original/update', method: 'POST', data: JSON.stringify({ ...data, title: '', status: 1 }), }, { 'Content-Type': 'application/json; charset=UTF-8' }).then(res => { console.log('res: ', res) if (res.code !== 0) { logger('新增7small失败 ' + res.msg) reject() return } logger(`新增7small成功 <a href="${baseURL}/sevensmall-onshelf/sevensmall-onshelf/add?id=${res.data}&iframe=false&onShelf=false&extension=7sou" target="_blank">去看看</a>`) resolve(res.data+'') }).catch(err => { logger('新增7small失败 ' + err) reject() }) }) } function createSevensmallRelation (id) { return new Promise((resolve, reject) => { GM.getValue('hho_source').then(res => { if (!res) return const domain = DomainMap[window.location.host] const target = CollectTargetDoaminInfo[domain] && CollectTargetDoaminInfo[domain]() const data = { ...JSON.parse(res), ...target, "code": id } _gmAjax({ method: 'POST', url: baseURL + '/api/sevenSmallMappings/createSevenSmallMappings', data: JSON.stringify(data) }, { 'Content-Type': 'application/json; charset=UTF-8' }).then(res => { resolve(res) }).catch(err => { reject(err) }) }) }) } function queryRelation () { // makuake camp-fire greenfunding 查询寻源关系 const host = DomainMap[window.location.host] if(!host) return const { sourceCode, sourceDomain } = CollectSourceDoaminInfo[host] && CollectSourceDoaminInfo[host]() console.log(sourceCode, sourceDomain) if(!sourceCode || !sourceDomain) return _gmAjax({ url: `${baseURL}/api/sevenSmallMappings/findSevenSmallMappings?sourceCode=${sourceCode}&sourceDomain=${sourceDomain}`, method: 'GET', }, { 'Content-Type': 'application/json; charset=UTF-8' }).then(res => { console.log(res) $('#hhoLog').empty() if (res.code !== 0 || !res.data.resevenSmallMappings) { return } else { logger(`已经寻过源了: <a href=${res?.data?.resevenSmallMappings?.targetUrl} target="_blank">点击查看</a>`) } }) } 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 => { const url = r.itemUrl.indexOf('?') === -1 ? `${r.itemUrl}?extension=7sou` : `${r.itemUrl.replace('?', '?extension=7sou&')}` return ` <div class='result-item' onclick="collectSourceInfo();window.open('${url}')"> <div> <img src="${r.itemPrcUrl}" style="width: 180px"> </div <div> <div>${r.itemName}</div> </div> </div> ` }).join(''))} } unsafeWindow.collectSourceInfo = function collectSourceInfo () { const domain = DomainMap[window.location.host] if (!domain) return const { sourceCode, sourceDomain, sourceUrl } = CollectSourceDoaminInfo[domain] && CollectSourceDoaminInfo[domain]() GM.setValue('hho_source', JSON.stringify({ sourceCode, sourceDomain, sourceUrl })) } 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} } } const ExchangePriceSelection = { greenfunding() { const ul = '.project_sidebar' const li = '.project_sidebar_reward--flat .project_sidebar_reward-head .project_sidebar_reward-amount' return {ul, li} }, makuake() { const ul = '#return' const li = '.return-section .lefth4RightBase ' return {ul, li} }, campfile () { const ul = '#sp-return' const li = '.return-box strong' return {ul, li} } } const sleep = wait => new Promise(resolve => setTimeout(resolve, wait)) const UploadSelection = { taobao () { return new Promise((resolve, reject) => { const source = '淘宝' const secondTitle = $('.tb-main-title')[0]?.innerText; const rmbPrice = Number($('#J_PromoPriceNum')?.innerText || $('#J_PromoPriceNum')[0]?.innerText || $('.tb-rmb-num')[0]?.innerText || 0); const img = $('.result-images .hho-selected')[0]?.src const detailUrl = window.location.href.replace('extension=7sou&', '') const jpyPrice = rmbPrice && getJPNPrice(rmbPrice) const video = $('video')[0] && ($('video')[0].src || $('video source')[0].src) const skuName = $('#J_isku .tb-selected span')[0]?.innerText const attributes = $('#attributes')?.innerText?.split('\n') || $('#attributes')[0]?.innerText?.split('\n') GM.setValue('hho_attributes', JSON.stringify(attributes)) resolve({ secondTitle: `${secondTitle}|${skuName}`, source, rmbPrice, img, video, detailUrl, jpyPrice, attributes }) }) }, tmall () { $('.J_playVideo')[0] && $('.J_playVideo')[0].click() return new Promise((resolve, reject) => { sleep(1000).then(() => { const secondTitle = $('.tb-detail-hd > h1')[0]?.innerText; const source = '天猫' const rmbPrice = Number($('.tm-promo-price .tm-price')[0]?.innerText || $('.tm-price')[0]?.innerText || 0); const img = $('.result-images .hho-selected')[0]?.src const detailUrl = window.location.href.replace('extension=7sou&', '') const jpyPrice = rmbPrice && getJPNPrice(rmbPrice) const video = $('video source')[0]?.src const skuName = $('.tb-sku .tb-selected')[0]?.title const attributes = $('#attributes')?.innerText?.split('\n') || $('#attributes')[0]?.innerText?.split('\n') GM.setValue('hho_attributes', JSON.stringify(attributes)) resolve({ secondTitle: `${secondTitle}|${skuName}`, source, rmbPrice, img, video, detailUrl, jpyPrice, attributes }) }).catch(err => console.log(err)) }) }, one688 () { return new Promise((resolve, reject) => { const secondTitle = $('.title-text')[0]?.innerText; const source = '1688' const rmbPrice = Number($('.price-text')[0]?.innerText || 0); const img = $('.result-images .hho-selected')[0]?.src const video = $('video')[0]?.src const detailUrl = window.location.href.replace('extension=7sou&', '') const jpyPrice = rmbPrice && getJPNPrice(rmbPrice) const skuName = $('.prop-item .active .prop-name')[0]?.innerText const attributes = $('.od-pc-attribute')[0]?.innerText?.split('\n') GM.setValue('hho_attributes', JSON.stringify(attributes)) resolve({ secondTitle: `${secondTitle}|${skuName}`, source, rmbPrice, img, video, detailUrl, jpyPrice, attributes }) }) } } const ImageSelection = { taobao() { var leftImagesEl = Array.from($('#J_UlThumb img')).map(d => { if (!d.dataset.src) { d.hhosrc = '' } else { d.hhosrc = d.dataset.src.startsWith('http') ? `${d.dataset.src.replace('_50x50.jpg', '')}` : `http://${d.dataset.src.replace('_50x50.jpg', '')}` } return d }); leftImagesEl = leftImagesEl.filter(img => img.src.indexOf('q-90-90') < 0) // 详情 var detailImagesEl = Array.from($('#J_DivItemDesc img')).map(d => { d.hhosrc = d.src return d }); detailImagesEl = detailImagesEl.filter(img => img.src.indexOf('.gif') < 0 && img.src.indexOf('q-90-90') < 0) return leftImagesEl.concat(detailImagesEl) }, tmall () { var leftImagesEl = Array.from($('#J_UlThumb img')).map(d => { d.hhosrc = d.src && `${d.src.replace('_60x60q90.jpg','')}` return d }); leftImagesEl = leftImagesEl.filter(img => img.src.indexOf('q-90-90') < 0) // 详情 var detailImagesEl = Array.from($('#description img')).map(d => { d.hhosrc = d.src return d }); detailImagesEl = detailImagesEl.filter(img => img.src.indexOf('.gif') < 0 && img.src.indexOf('q-90-90') < 0) return leftImagesEl.concat(detailImagesEl) }, one688 () { var leftImagesEl = Array.from($('.detail-gallery-turn img')).map(d => { d.hhosrc = d.src return d }); // 详情 var detailImagesEl = Array.from($('#detailContentContainer img')).map(d => { d.hhosrc = d.src return d }); return leftImagesEl.concat(detailImagesEl) } } const CollectSourceDoaminInfo = { greenfunding() { const sourceCode = window.location.href.match(/[0-9]+/g)[0] const sourceDomain = 'GreenFunding' const sourceUrl = window.location.href return { sourceCode, sourceDomain, sourceUrl } }, makuake() { const sourceCode = window.location.pathname.split('/')[2] const sourceDomain = 'makuake' const sourceUrl = window.location.href return { sourceCode, sourceDomain, sourceUrl } }, campfile() { const sourceCode = window.location.href.match(/[0-9]+/g)[0] const sourceDomain = 'camp-fire' const sourceUrl = window.location.href return { sourceCode, sourceDomain, sourceUrl } } } const CollectTargetDoaminInfo = { taobao() { const targetCode = queryParams('id') const targetUrl = window.location.href return { targetCode, targetUrl } }, tmall () { const targetCode = queryParams('id') const targetUrl = window.location.href return { targetCode, targetUrl } }, one688 () { const targetCode = window.location.pathname.match(/[0-9]+/g)[0] const targetUrl = window.location.href return { targetCode, targetUrl } } } })();
QingJ © 2025
镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址