您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
在线选品
当前为
// ==UserScript== // @name online-selection // @namespace com.hho.middle.fe.online.selection // @version 0.13 // @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 GM_addStyle // @grant GM_openInTab // @grant GM_xmlhttpRequest // @grant GM_download // @grant unsafeWindow // @run-at document-start // ==/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', '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 = '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 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', } let preX = 0, preY = 0, startX = 0, startY = 0, canMoving = false let exchangeRates = 1 // 汇率(日元转人民币) let _sourceBufferList = [] // blob let _endOfStream = window.MediaSource.prototype.endOfStream // 监听资源全部录取成功 let _addSourceBuffer = window.MediaSource.prototype.addSourceBuffer // 录取资源 let _sourceBufferLoaded = false // 已经加载完 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' ]) const isFrom7sou = queryParams('extension') === '7sou' 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'] let css=` .hho-selected {border: 1px solid red} ` GM_addStyle(css) function init() { $(document).ready(function() { if (window.location.host === LoggingURL && window.location.pathname.indexOf('sevensmall-onshelf') === -1) { const token = localStorage.getItem('__hho_token__') console.log(token) if (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 && window.location.href !== portalUrl) return // 添加按钮 if ($('#hho-online-selection-container').length > 0) 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;" id="hho-online-selection-header"> <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> <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>'); $(document).off('click',"#hhoBtn", startSelection); $(document).on('click', "#hhoBtn", startSelection); } else if (uploadSites.indexOf(window.location.host) !== -1) { // 淘宝天猫1688上传 const uploadButton = `<div style="${ButtonStyle(PrimaryButtonStyle)}" id="hhoUploadButton">一键上架</div>` $('#hho-online-selection-container .button-list').append(uploadButton); const renderImageButton = `<div style="${ButtonStyle(PrimaryButtonStyle)};margin-left: 10px" id="renderImageButton">重新加载图片</div>` $('#hho-online-selection-container .button-list').append(renderImageButton); $('#hho-online-selection-container .button-list').after('<div id="hhoBlob"></div>') $('#hho-online-selection-container .button-list').after('<div id="hhoLog"></div>') // 获取所有图片 scrollToBottom(1000, () => { renderImageList() }) $(document).off('click',"#renderImageButton", renderImageList); $(document).on('click', "#renderImageButton", renderImageList); $(document).off('click',"#hhoUploadButton", startUpload); $(document).on('click', "#hhoUploadButton", startUpload); // 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 (window.location.href === portalUrl) { // const autoFillButton = `<div style="${ButtonStyle(PrimaryButtonStyle)}" id="autoFill">自动创建</div>` // $('#hho-online-selection-container .button-list').append(autoFillButton); // $(document).off('click', "#autoFill", autoFill); // $(document).on('click', "#autoFill", autoFill); } 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); $('#hho-online-selection-header').after('<label>关键词:</label><input name="search" style="margin: 6px" />') $(document).off('click',"#hhoYesBtn", save); $(document).off('click', "#hhoNoBtn", closeTab); $(document).off('paste', handlePaste) $(document).on('click',"#hhoYesBtn", save); $(document).on('click', "#hhoNoBtn", closeTab); $(document).on('paste', handlePaste) 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) } }); } $(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 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(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 => { console.log(res) if (!res) { window.open(baseURL) return } GM_xmlhttpRequest({ ...options, headers: { ...headers, 'x-token': res }, onload: function (data) { $("#loading-text").text('') if (data.status === 200) { if (JSON.parse(data.response).msg === '未登录(不可用)或非法访问') { // 登录(不可用) window.open(baseURL) reject() } else { resolve(JSON.parse(data.response)) } } else { $("#loading-text").text(data.statusText) reject({status, statusText}) } }, onerror: function (err) { window.open(baseURL) 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, }, {}) } 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 () { 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) { // TODO: 待支持 // 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 () { $('#hho-online-selection-container .result-container').empty() const domain = DomainMap[window.location.host] if (!domain) return let imagesList = ImageSelection[domain]() $('.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) => { $('.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 console.log(UploadSelection[domain]) console.log(UploadSelection[domain]()) 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 } if (res.video.startsWith('blob')) { if (!_sourceBufferLoaded) { logger('blob 视频资源未加载完毕,请等待') return } blobToFile().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 translate(res.secondTitle) }).then(translateRes => { res.title = translateRes.data logger('翻译标题成功') return create7smallForm(res) }).then(sevensmallId => { window.open(`${baseURL}/sevensmall-onshelf/sevensmall-onshelf/add?id=${sevensmallId}&iframe=false&onShelf=false`) // 建立关系 if (isFrom7sou) { createSevensmallRelation(sevensmallId) } }).catch(err => { console.log(err) }) } if (res.video.indexOf('blob') < 0) { // 非blob格式 mp4ToFile(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 translate(res.secondTitle) }).then(translateRes => { res.title = translateRes.data logger('翻译标题成功') return create7smallForm(res) }).then(sevensmallId => { window.open(`${baseURL}/sevensmall-onshelf/sevensmall-onshelf/add?id=${sevensmallId}&iframe=false&onShelf=false`) // 建立关系 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' ? '视频上传失败' : '图片上传失败') 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, status: 1 }), }, { 'Content-Type': 'application/json; charset=UTF-8' }).then(res => { console.log('res: ', res) if (res.code !== 0) { logger('新增7small失败' + res.msg) return } logger('新增7small成功') resolve(res.data) }).catch(err => { logger('新增7small失败') 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 } console.log(data) _gmAjax({ method: 'POST', url: baseURL + '/api/sevenSmallMappings/createSevenSmallMappings', data: data }, { 'Content-Type': 'application/json; charset=UTF-8' }).then(res => { if (res.code === 0) { resolve(res) } else { reject() } }) }) }) } 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) if (res.code !== 0) { return } else { logger('已经寻过源了') } }) } 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 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} } } 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 sleep = wait => new Promise(resolve => setTimeout(resolve, wait)) const UploadSelection = { taobao () { return new Promise((resolve, reject) => { const secondTitle = $('.tb-main-title')[0] && $('.tb-main-title')[0].innerText; const source = '淘宝' const rmbPrice = Number($('#J_PromoPriceNum')[0] && $('#J_PromoPriceNum')[0].innerText || 0); const img = $('.result-images .hho-selected')[0] && $('.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] && $('#J_isku .tb-selected span')[0].innerText const attributes = $('#attributes').innerText && $('#attributes').innerText.split('\n') GM.setValue('hho_attributes', JSON.stringify(attributes)) resolve({ secondTitle: `${secondTitle}|${skuName}`, source, rmbPrice, img, video, detailUrl, jpyPrice }) }) }, tmall () { $('.J_playVideo')[0] && $('.J_playVideo')[0].click() return new Promise((resolve, reject) => { sleep(1000).then(() => { const secondTitle = $('.tb-detail-hd > h1')[0] && $('.tb-detail-hd > h1')[0].innerText; const source = '天猫' const rmbPrice = Number($('.tm-promo-price .tm-price')[0] && $('.tm-promo-price .tm-price')[0].innerText || 0); const img = $('.result-images .hho-selected')[0] && $('.result-images .hho-selected')[0].src const detailUrl = window.location.href.replace('extension=7sou&', '') const jpyPrice = rmbPrice && getJPNPrice(rmbPrice) const video = $('video source')[0] && $('video source')[0].src const skuName = $('.tb-sku .tb-selected')[0] && $('.tb-sku .tb-selected')[0].title const attributes = $('#attributes').innerText && $('#attributes').innerText.split('\n') GM.setValue('hho_attributes', JSON.stringify(attributes)) resolve({ secondTitle: `${secondTitle}|${skuName}`, source, rmbPrice, img, video, detailUrl, jpyPrice }) }).catch(err => console.log(err)) }) }, one688 () { return new Promise((resolve, reject) => { const secondTitle = $('.title-text')[0] && $('.title-text')[0].innerText; const source = '1688' const rmbPrice = Number($('.price-text')[0] && $('.price-text')[0].innerText || 0); const img = $('.result-images .hho-selected')[0] && $('.result-images .hho-selected')[0].src const video = $('video')[0] && $('video')[0].src const detailUrl = window.location.href.replace('extension=7sou&', '') const jpyPrice = rmbPrice && getJPNPrice(rmbPrice) resolve({secondTitle, source, rmbPrice, img, video, detailUrl, jpyPrice}) }) } } 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或关注我们的公众号极客氢云获取最新地址