// ==UserScript== // @name Samforo工具箱 // @namespace http://tampermonkey.net/ // @version 2026.03.16.01 // @description 1) 店小秘自动添加初始备注, 2) Amazon商品数据提取, 3) TikTok商品数据提取, 4) 1688商品数据提取 等等功能 // @author 大大怪将军 // @icon64 data:image/svg+xml;base64,PHN2ZyB0PSIxNzY5Mzk0MDkyNTEwIiBjbGFzcz0iaWNvbiIgdmlld0JveD0iMCAwIDEwMjQgMTAyNCIgdmVyc2lvbj0iMS4xIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHAtaWQ9Ijg2OTUiIHdpZHRoPSIyMDAiIGhlaWdodD0iMjAwIj48cGF0aCBkPSJNNTA1LjA4OCA1MTMuMTI2NG0tNDUwLjgxNiAwYTQ1MC44MTYgNDUwLjgxNiAwIDEgMCA5MDEuNjMyIDAgNDUwLjgxNiA0NTAuODE2IDAgMSAwLTkwMS42MzIgMFoiIGZpbGw9IiNDNjVFREIiIHAtaWQ9Ijg2OTYiPjwvcGF0aD48cGF0aCBkPSJNNDQ0LjcyMzIgNDIwLjMwMDhoMTE4LjczMjhWNDcyLjU3Nkg0NDQuNzIzMnoiIGZpbGw9IiNGRkZGRkYiIHAtaWQ9Ijg2OTciPjwvcGF0aD48cGF0aCBkPSJNMzgyLjMxMDQgNDE1LjIzMnYtNi40NTEyYzAtMjguMDU3NiAyMi44MzUyLTUwLjg5MjggNTAuODkyOC01MC44OTI4aDE0MS43NzI4YzI4LjA1NzYgMCA1MC44OTI4IDIyLjgzNTIgNTAuODkyOCA1MC44OTI4djYuNDUxMmgxNzQuNzQ1NlYzMzUuMjU3NmMwLTM4LjA0MTYtMzAuODczNi02OC45MTUyLTY4LjkxNTItNjguOTE1MkgyNzguMTE4NGMtMzguMDQxNiAwLTY4LjkxNTIgMzAuODczNi02OC45MTUyIDY4LjkxNTJWNDE1LjIzMmgxNzMuMTA3MnoiIGZpbGw9IiNCRDUwRDMiIHAtaWQ9Ijg2OTgiPjwvcGF0aD48cGF0aCBkPSJNNjI1Ljg2ODggNDc3LjY0NDh2Ni40NTEyYzAgMjguMDU3Ni0yMi44MzUyIDUwLjg5MjgtNTAuODkyOCA1MC44OTI4SDQzMy4yMDMyYy0yOC4wNTc2IDAtNTAuODkyOC0yMi44MzUyLTUwLjg5MjgtNTAuODkyOHYtNi40NTEySDIwOS4yMDMydjIxOS4yODk2YzAgMzguMDQxNiAzMC44NzM2IDY4LjkxNTIgNjguOTE1MiA2OC45MTUyaDQ1My41Mjk2YzM4LjA0MTYgMCA2OC45MTUyLTMwLjg3MzYgNjguOTE1Mi02OC45MTUyVjQ3Ny42NDQ4aC0xNzQuNjk0NHpNNzMxLjY0OCAyNjYuMzQyNEgyNzguMTE4NGMtMzguMDQxNiAwLTY4LjkxNTIgMzAuODczNi02OC45MTUyIDY4LjkxNTJWNDE1LjIzMmgxNzMuMTA3MnYtNi40NTEyYzAtMjguMDU3NiAyMi44MzUyLTUwLjg5MjggNTAuODkyOC01MC44OTI4aDE0MS43NzI4YzI4LjA1NzYgMCA1MC44OTI4IDIyLjgzNTIgNTAuODkyOCA1MC44OTI4djYuNDUxMmgxNjMuMzc5MmE0NTIuNjg5OTIgNDUyLjY4OTkyIDAgMCAwIDguNzU1Mi05OC42NjI0Yy04LjE5Mi0yOC45NzkyLTM0Ljc2NDgtNTAuMjI3Mi02Ni4zNTUyLTUwLjIyNzJ6IiBmaWxsPSIjRkZGRkZGIiBwLWlkPSI4Njk5Ij48L3BhdGg+PC9zdmc+ // @match https://www.dianxiaomi.com/web/order/* // @match https://www.amazon.com/* // @match https://www.tiktok.com/view/* // @match https://www.tiktok.com/shop/* // @match https://detail.1688.com/offer/* // @match https://www.dianxiaomi.com/dxmCommodityProduct/* // @match https://www.dianxiaomi.com/dxmPurchasingNote/edit.htm* // @match https://www.dianxiaomi.com/dxmPurchasePlan/purchasePlan.htm* // @match https://air.1688.com/app/ctf-page/trade-order-list/buyer-order-list.html* // @match https://air.1688.com/app/ocms-fusion-components-1688/def_cbu_web_im/index.html* // @match https://t.17track.net/track/restapi // @homepageURL https://68110923.github.io/ // @grant unsafeWindow // @grant GM_info // @grant GM_addStyle // @grant GM_addElement // @grant GM_log // @grant GM_notification // @grant GM_setValue // @grant GM_getValue // @grant GM_deleteValue // @grant GM_listValues // @grant GM_getValues // @grant GM_deleteValues // @grant GM_addValueChangeListener // @grant GM_removeValueChangeListener // @grant GM_setClipboard // @grant GM_getClipboard // @grant GM_openInTab // @grant GM_getTabs // @grant GM_getTab // @grant GM_saveTab // @grant GM_unregisterMenuCommand // @grant GM_registerMenuCommand // @grant GM_xmlhttpRequest // @connect * // @require https://cdn.jsdelivr.net/npm/pinyin-pro@3.27.0/dist/index.min.js // @downloadURL https://raw.githubusercontent.com/68110923/chrome_plugins/main/plugins_yh/dxm_erp_review_assistant.user.js // @updateURL https://raw.githubusercontent.com/68110923/chrome_plugins/main/plugins_yh/dxm_erp_review_assistant.user.js // @supportURL https://github.com/68110923/chrome_plugins/issues/new/choose // ==/UserScript== (function() { 'use strict'; window.pinyinPro = pinyinPro; window.addEventListener('load', initAddButton); // xhr POST触发 const originalXhrOpen = XMLHttpRequest.prototype.open; XMLHttpRequest.prototype.open = function(method, url, ...args) { this._method = method; this._url = url; return originalXhrOpen.apply(this, [method, url, ...args]); }; const originalXhrSend = XMLHttpRequest.prototype.send; XMLHttpRequest.prototype.send = function(data) { if (this._url.includes('api/order/remark/config/getList.json') && this._method === 'POST' && data === 'type=sys_service') { setTimeout(() => { autoFillSku()}, 20); } if (this._url === '/api/dxmCommodityProduct/getProductsOrderPageList.json') { const paramDict = Object.fromEntries(new URLSearchParams(data)); if (!paramDict.searchSelectValue) { GM_setClipboard(paramDict.vid.trim(), 'text', () => showToast('已复制到剪贴板:' + paramDict.vid.trim())); } } if (this._url.includes('/purchasingProposal/getTreeForCreateNoteAddPro.json')) { setTimeout(() => {stockMate()}, 100); } if (this._url.includes('dxmSupplier/getSupplierPage.htm')) { setTimeout(() => {procurementPlanMate()}, 100); } if (this._url.includes('alibabaProduct/getAlibabaSourceUrl.json')) { setTimeout(async () => {await procurementPlan1688SkuMate()}, 100); } // 监听response数据 const originalOnReadyStateChange = this.onreadystatechange; this.onreadystatechange = function(...args) { if (this._url.includes('h5/mtop.1688.moga.pc.shopcard/1.0/') && document.URL.endsWith('kj_agent_plugin=dxmerp')) { GM_setValue('dxmCurrent1688ShopName', JSON.parse(this.responseText).data.model.shopName) } if (typeof originalOnReadyStateChange === 'function') { originalOnReadyStateChange.apply(this, args); } }; return originalXhrSend.apply(this, arguments); }; // 按键触发 document.addEventListener('keydown', async (e) => { const alt_keys = { q: ['q', 'Q'], e: ['e', 'E'], h: ['h', 'H'], }; if (!e.altKey || !Object.values(alt_keys).flat().includes(e.key)) {return;} e.preventDefault(); e.stopPropagation(); const key_q = alt_keys.q.includes(e.key) const key_e = alt_keys.e.includes(e.key) const key_h = alt_keys.h.includes(e.key) const regularTiktok = document.URL.includes('https://www.tiktok.com/') const regularAmazon = document.URL.includes('https://www.amazon.') const regular1688 = document.URL.includes('https://detail.1688.com/offer/') const regulaDxmCreateProduct = document.URL.includes('https://www.dianxiaomi.com/dxmCommodityProduct/') const orderList1688 = document.URL.includes('https://air.1688.com/app/ctf-page/trade-order-list/buyer-order-list.html') && document.URL.includes('tradeStatus=waitbuyerpay') const wangwangNews1688 = document.URL.includes('https://air.1688.com/app/ocms-fusion-components-1688/def_cbu_web_im/index.html') const dxmInStock = document.URL.includes('https://www.dianxiaomi.com/web/order/allocated/has?go=m10301') const dxmShipmentSuccessful = document.URL.includes('https://www.dianxiaomi.com/web/order/shipped/success?go=m10403') if (key_q && regularAmazon) { extractAmazonNotes(); } else if (key_q && regularTiktok) { extractTiktokNotes(); } else if (key_q && regular1688) { extract1688Notes(); } else if (key_q && orderList1688) { await extractOrdersAwaitingPayment(); } else if (key_q && wangwangNews1688) { await sendMessageChangePrice(); } else if (key_q && (dxmInStock || dxmShipmentSuccessful)) { await logisticsInformation(); } else if (key_e && regular1688) { extract1688CreateStockInfo(); } else if (key_e && regulaDxmCreateProduct){ const isGroup = document.querySelector('#goodsInfo > div:not(.hide) [uid="groupSkuSelect"]') if (isGroup) {enterStockInfoToDxmCombination()} else {await enterStockInfoToDxm()} } else if (key_h) { showToast(` **** ${GM_info.script.name} **** \nVersion: ${GM_info.script.version} \n\n${GM_info.script.description} \n\n\n使用过程中若遇到问题,请联系作者 `, 'info', '20%', '38%'); } else { showToast(`当前网址:\n${document.URL.replace(/(.{50})/g, '$1\n')}\n\n该网址 alt + ${e.key} 功能尚未开发`, 'error', '20%', '38%'); } }); async function initAddButton(){ const addButtonLogisticsInformation = [ 'https://www.dianxiaomi.com/web/order/allocated/has?go=m10301', 'https://www.dianxiaomi.com/web/order/shipped/success?go=m10403', ] if (addButtonLogisticsInformation.includes(window.location.href)) { const addButtonContainer = await waitForElement('.tool-bar:not([style]) .btn-left > .order-actions-buttons', 5*1000); const buttonLogisticsInformation = GM_addElement( addButtonContainer, 'button', {'data-v-11a55e37': null,class: 'css-1oz1bg8 ant-btn ant-btn-primary buttons-item', textContent: 'IT:物流状态', type: 'button',} ); buttonLogisticsInformation.addEventListener('click', async () => {await logisticsInformation();}); } } async function logisticsInformation(){ showToast('正在获取物流状态...', 'info', '1%', '2%'); const logisticsStatus = { '已上网': { selector: '[class="order-mark-block"][style="background-color: rgb(195, 120, 223);"] > .icon_ship', logisticsNumber: [], }, '未上网': { logisticsNumber: [], }, '查询频繁': { logisticsNumber: [], }, '已存在上网标记': { logisticsNumber: [], }, '无物流号': { logisticsNumber: [], }, } const trLevel1Elements = await document.querySelectorAll('.first-level-row') let trackUrlParams = new URLSearchParams() for (const [index, trLevel1Element] of trLevel1Elements.entries()) { const logisticsButtonElement = await trLevel1Element.nextElementSibling.querySelector('.pointer[title="点击查看物流追踪"]') if (!logisticsButtonElement){logisticsStatus['无物流号'].logisticsNumber.push(null);continue} const logisticsNumber = logisticsButtonElement.textContent.trim() if (trLevel1Element.querySelector(logisticsStatus['已上网'].selector)){logisticsStatus['已存在上网标记'].logisticsNumber.push(logisticsNumber);continue} const rowId = trLevel1Element.nextElementSibling.getAttribute('rowid') if (index % 20 === 0 && index !== 0){showToast(`已处理 ${index}/${trLevel1Elements.length}`, 'info', '1%', '2%', 200, 6000);await new Promise(resolve => setTimeout(resolve, 3000));} const responseJson = await fetchLogisticsData(logisticsNumber, trackUrlParams) console.log(responseJson) if (responseJson.meta.code === 200 && responseJson.shipments[0].pre_status !== 0) { logisticsStatus['已上网'].logisticsNumber.push(logisticsNumber) fetch('/api/package/addOrUpdateUserComment.json',{ method: 'POST', headers: {'content-type': 'application/x-www-form-urlencoded',}, body: `orderId=${rowId}&isGreen=0&isYellow=0&isOrange=0&isRed=0&isViolet=32&isBlue=0&cornflowerBlue=0&pink=0&teal=0&turquoise=0&unmarked=0&history=`, }) } else if (responseJson.meta.code === 200 && responseJson.shipments[0].pre_status === 0) { logisticsStatus['未上网'].logisticsNumber.push(logisticsNumber) } else { logisticsStatus['查询频繁'].logisticsNumber.push(logisticsNumber) showToast(`识别到查询频繁 等待5秒...`, 'warning', '1%', '2%', 200, 4000); await new Promise(resolve => setTimeout(resolve, 5000)); } } const logisticsStatusStr = Object.entries(logisticsStatus).map(([key, value]) => value.logisticsNumber.length === 0 ? null : `${key}: ${value.logisticsNumber.length}`).filter(Boolean).join('\n') showToast(`已获取本页订单物流状态\n\n${logisticsStatusStr}`, 'success', '1%', '2%'); console.log(logisticsStatus) document.querySelector('.first-level-row a').click() await new Promise(resolve => setTimeout(resolve, 300)); document.querySelector('.ant-modal-mask:not([style]) + * .ant-modal-close').click() } async function fetchLogisticsData(logisticsNumber, trackUrlParams) { return new Promise((resolve) => { // 1. 第一步:构造纯JS对象(关键!不要手动拼字符串) const requestBodyObj = { data: [{ num: logisticsNumber, // 直接传变量,无需拼字符串 fc: trackUrlParams.get('fc') || '191011', sc: trackUrlParams.get('sc') || '0', ref: trackUrlParams.get('rk') || '2115526' }], guid: "", timeZoneOffset: -480 }; // 2. 第二步:一次性序列化(得到无反斜杠的纯JSON字符串) const requestBody = JSON.stringify(requestBodyObj); // 3. GM_xmlhttpRequest请求配置 GM_xmlhttpRequest({ method: 'POST', url: 'https://t.17track.net/track/restapi', headers: { accept: 'application/json, text/javascript, */*; q=0.01', 'accept-language': 'zh-CN,zh;q=0.9', 'cache-control': 'no-cache', 'content-type': 'application/x-www-form-urlencoded; charset=UTF-8', dnt: '1', origin: 'https://www.dianxiaomi.com', pragma: 'no-cache', priority: 'u=1, i', referer: 'https://www.dianxiaomi.com/', 'sec-ch-ua': '"Not(A:Brand";v="8", "Chromium";v="144", "Google Chrome";v="144"', 'sec-ch-ua-mobile': '?0', 'sec-ch-ua-platform': '"Windows"', 'sec-fetch-dest': 'empty', 'sec-fetch-mode': 'cors', 'sec-fetch-site': 'cross-site', 'user-agent': navigator.userAgent, 'Accept-Encoding': 'gzip, deflate, br', Connection: 'keep-alive' }, data: requestBody, // 直接传序列化后的字符串(无反斜杠) timeout: 10000, onload: function (response) { if (response.status >= 200 && response.status < 300) { try { const responseJson = JSON.parse(response.responseText); resolve(responseJson); } catch (err) { resolve(null); } } else { resolve(null); } }, onerror: function () { resolve(null); }, ontimeout: function () { resolve(null); } }); }); } async function sendMessageChangePrice(){ const allOrderList = GM_getValue('1688OrderList') || {}; const sellerKeys = Object.keys(allOrderList).filter(key => key !== 'batchDate'); const notifiedSellerList = GM_getValue('1688NotifiedSellerList') || []; if (!sellerKeys.length || allOrderList.batchDate !== new Date().toLocaleDateString()) {GM_deleteValue('1688OrderList');GM_deleteValue('1688NotifiedSellerList');showToast('请先在1688订单列表页点击任意订单,获取订单信息', 'error'); return} const documentIframe = document.querySelector('iframe[src*="app/ocms-fusion-components-1688/def_cbu_web_im_core/index.html"]').contentDocument for (const [index, key] of sellerKeys.entries()) { const valueList = allOrderList[key]; const totalFreight = valueList.reduce((acc, cur) => acc + cur.freight, 0).toFixed(2) if (notifiedSellerList.includes(key) || totalFreight < 6) {continue;} await new Promise(resolve => setTimeout(resolve, 500)); const inputElement = documentIframe.querySelector('[placeholder="搜索联系人"]') inputElement.value = key inputElement.dispatchEvent(new Event('input', {bubbles: true, cancelable: true})); const oldStr1 = documentIframe.querySelector('.conversation > .name')?.textContent.trim() || crypto.randomUUID() documentIframe.querySelector('.anticon-search').click() await waitForElementTextChange('.conversation > .name', documentIframe, oldStr1,1.5*1000, 50) const wangwangNameElement = documentIframe.querySelector('.conversation > .name') if (!wangwangNameElement || wangwangNameElement.textContent.trim() !== key) {showToast(`未找到旺旺:${key}`, 'error'); continue;} const oldStr2 = documentIframe.querySelector('.go-shop-container')?.textContent.trim() || crypto.randomUUID() wangwangNameElement.click() await waitForElementTextChange('.go-shop-container', documentIframe, oldStr2, 10*1000, 500) const message = `${valueList.map((item) => item.orderId).join('\n')}\n\n你好这${valueList.length > 1 ? valueList.length : ''}个订单号麻烦修改下运费` const editElement = documentIframe.querySelector('.text-area > .editBox > pre') editElement.textContent = message; editElement.dispatchEvent(new Event('input', {bubbles: true, cancelable: true})); documentIframe.querySelector('.send-btn').click() notifiedSellerList.push(key); GM_setValue('1688NotifiedSellerList', notifiedSellerList); showToast(`成功(${index + 1}) 旺旺:${key} 总运费:${totalFreight}`); } showToast(`共 ${sellerKeys.length} 个卖家,今日已通知 ${notifiedSellerList.length} 个卖家改价`, 'success') } async function extractOrdersAwaitingPayment(){ const dataSet = {} let totalOrderCount = 0 let isWhile = true while (isWhile) { const currentPageOrderList = findElementInNestedShadowDOM('.order-item-content') totalOrderCount += currentPageOrderList.length; currentPageOrderList.forEach((orderElement) => { const orderItem = {} orderItem.orderId = orderElement.querySelector('.order-item-entry[data-entry-id]').getAttribute('data-entry-id') const freight = findElementInNestedShadowDOM('.carriage', orderElement)[0].textContent.match(/[\d.]+/g) orderItem.freight = parseFloat(freight?.[0] || 0) orderItem.shopName = findElementInNestedShadowDOM('.company-name', orderElement)[0].textContent.trim() orderItem.wangwangName = findElementInNestedShadowDOM('.seller-id-text', orderElement)[0].textContent.trim() if (dataSet[orderItem.wangwangName]){ dataSet[orderItem.wangwangName].push(orderItem) } else { dataSet[orderItem.wangwangName] = [orderItem] } }) const nextPageElement = findElementInNestedShadowDOM('#right:not([disabled="true"])', document)[0] if (nextPageElement) { nextPageElement.click(); await waitForElementTextChange('#page') isWhile = true } else { isWhile = false } } console.log(dataSet) showToast(`从${totalOrderCount}条订单中,识别到${Object.keys(dataSet).length}个不同的卖家`, 'success') dataSet['batchDate'] = new Date().toLocaleDateString() if (GM_getValue('1688OrderList', {}).batchDate !== dataSet['batchDate']){GM_setValue('1688NotifiedSellerList', [])} GM_setValue('1688OrderList', dataSet) } async function procurementPlan1688SkuMate(){ await waitForElementTextChange('.box-item-right .box-sku-title', document, crypto.randomUUID(),2*1000, 100) const skuStrOri = document.querySelector('#goodsDetailInfo .commodity .no-new-line2:nth-child(2)').textContent.trim() const skuModelList = skuStrOri.replace(/.*? >> /, '').replace(/\*[^*]*$/, '').split('|') skuModelList.forEach((skuModel) => { const targetElement = document.querySelector(`.box-item-right .box-sku-title [data-value="${skuModel}"]`) if (targetElement){ targetElement.click() } else { showToast(`无法识别: ${skuModel}`, 'error','20%','40%') } }) } function procurementPlanMate(){ const dxmCurrent1688ShopName = GM_getValue('dxmCurrent1688ShopName') if (!dxmCurrent1688ShopName){return} const inputElement = document.querySelector('input#searchValueForChooseSupplier'); setTimeout(() => { inputElement.value = dxmCurrent1688ShopName; inputElement.dispatchEvent(new Event('input', {bubbles: true, cancelable: true})); document.querySelector('button#btnSearch').click(); }, 100 ); setTimeout(() => { const tempElement = document.querySelector('[class="in-table"] > tbody > tr.content:first-child > td:first-child') if (tempElement && tempElement.textContent.trim().includes(dxmCurrent1688ShopName)){ document.querySelector('[class="in-table"] > tbody > tr.content:first-child > td:nth-child(2) > a').click(); showToast(`已更换`, 'success') } else { document.querySelector('.open .custom-modal-head a[data-close="modal"]').click(); showToast(`************ 未识别到符合要求的供货商 ************`, 'warning') } }, 1000); GM_deleteValue('dxmCurrent1688ShopName') } function stockMate(){ const href = document.querySelector('#pairProductModal.open [uid="name"] a').getAttribute('href').trim(); document.querySelector('#addFromProModalSkuId').click(); document.querySelector('#search1688Mode').click(); document.querySelector('#search1688Mode > [value="0"]').click(); const inputElement = document.querySelector('#addFromProValue'); inputElement.value = href.match(/\/(\d+)\.html/)[1] inputElement.dispatchEvent(new Event('input', {bubbles: true, cancelable: true})); document.querySelector('#btnSelectSearch').click(); const productProperty = document.querySelector('[uid="productAttr"] .popoverHover').textContent.trim().replace('-','|') setTimeout(() => { document.querySelectorAll('.white-space').forEach((element) => { if (element.textContent.includes(productProperty)){ element.style.color = 'blue' } }) }, 200); } const dxmProductInfoMapping = { url: '商品链接', productImgUrl: '主图链接', productId: '产品ID', skuString: 'SKU字符串', skuId: 'SKU ID', totalPrice: '总价', averagePrice: '均格', count: '数量', title: '商品标题', } function enterStockInfoToDxmCombination() { const groupSku = [] const groupElements = document.querySelectorAll('#goodsInfo > div:not(.hide) [uid="groupSkuSelect"] tr') if (groupElements.length === 0) { showToast('请先添加组合的商品!','error'); return; } for (let i = 0; i < groupElements.length; i++) { const skuText = groupElements[i].querySelector('.f-black').textContent.replace('SKU:', '') const count = groupElements[i].querySelector('input#num').value if (!count) { showToast(`${skuText} 请输入数量!`,'error'); return; } const skuDict = { sku: skuText, title: groupElements[i].querySelector('.gray-c').textContent.trim(), count: parseInt(groupElements[i].querySelector('input#num').value), img: groupElements[i].querySelector('#goodsInfo > div:not(.hide) [uid="groupSkuSelect"] img').getAttribute('src'), } groupSku.push(skuDict) } // 商品信息 document.querySelector('[uid="goodsInfo"]').click(); // 商品SKU const skuElement = document.querySelector('input#proSku'); skuElement.value = 'ZH-' + groupSku.map(skuItem => `${skuItem.sku.slice(-5)}*${skuItem.count}`).join('-'); // 商品分类: const categorySelectElement = document.querySelector('#catagoryFullName'); categorySelectElement.click(); document.querySelector('[title="家居日用"]').click(); // 中文名称 const titleZHElement = document.querySelector('input#proName'); titleZHElement.value = '组合共' + groupSku.reduce((total, item) => total + item.count, 0) + '件'; titleZHElement.value += ' || ' + groupSku.map(sku => `${sku.title}*${sku.count}`).join(','); // 识别码 const identifierElement = document.querySelector('input#proSbm'); identifierElement.value = skuElement.value; // 来源URL const existSourceCount = document.querySelectorAll('input[name="sourceUrl"]').length const needsAddSourceCount = groupSku.length - existSourceCount; const alsoAddSourceCount = 5 - existSourceCount; const addSourceCount = needsAddSourceCount > alsoAddSourceCount ? alsoAddSourceCount : needsAddSourceCount; console.log(`需要添加${needsAddSourceCount}个来源URL, 还能添加${alsoAddSourceCount}个, 本次会添加${addSourceCount}个`) if (addSourceCount >= 0) { for (let i = 0; i < addSourceCount; i++) {document.querySelector('.addSourceUrl').click();} } else { for (let i = 0; i < -addSourceCount; i++) {document.querySelector('.removeSourceUrl').click();} } document.querySelectorAll('input[name="sourceUrl"]').forEach((inputElement, index) => { inputElement.value = `https://detail.1688.com/offer/${groupSku[index].sku.split('-')[0]}.html`; }) // 添加图片, 默认组合的第一个图片 // if (parseInt(document.querySelector('#curImgNum').textContent) === 0) { // document.querySelector('[onclick="webUrlModal();"]').click(); // document.querySelector('textarea#webImgUrl').value = groupSku.map(sku => sku.img).join('\n'); // document.querySelector('button[onclick="addWebUrl();"]').click(); // } // 点击:物流与包装 const category = categorySelectElement.textContent; document.querySelector('[uid="logisticsPackaging"]').click(); // 报关中文名 const customNameZhElement = document.querySelector('input#nameCn'); customNameZhElement.value = category; // 报关英文名 const customNameEnElement = document.querySelector('input#nameEn'); customNameEnElement.value = 'necessary' // 申报金额 0.1-1.5 const declarePriceElement = document.querySelector('input#cusPrice'); declarePriceElement.value = (Math.random() * (1.5 - 0.1) + 0.1).toFixed(2); // 申报重量 15-35 克 const declareWeightElement = document.querySelector('input#cusWeight'); declareWeightElement.value = (Math.random() * (35 - 15) + 15).toFixed(2); // 返回首页 document.querySelector('[uid="goodsInfo"]').click(); showToast(`组合商品信息已自动录入`,'success'); } async function dxmProductManagementFuzzySearchEmpty(searchField, searchValue) { if (!searchValue) {return true;} const searchFieldMap = { '识别码': 3, '商品SKU': 1, } if (!searchFieldMap[searchField]) {console.error(`暂不支持 ${searchField} 字段查询`);return;} const params = `pageNo=1&pageSize=100&searchType=${searchFieldMap[searchField]}&searchValue=${searchValue}&productPxId=1&productPxSxId=0&fullCid=&productMode=-1&saleMode=-1&productSearchType=0&productGroupLxId=1` const response = await fetch(`/dxmCommodityProduct/getImgUrlExceptionStatData.json`, { method: 'POST', headers: { 'Content-Type': 'application/x-www-form-urlencoded', }, body: params, }); const data = await response.json(); return data.total === 0; } async function enterStockInfoToDxm() { const productInfo = GM_getValue('dxmProductInfo'); if (!productInfo) { showToast('请先提取1688详情页信息!','warning'); } // 点击商品信息 document.querySelector('[uid="goodsInfo"]').click(); // 商品SKU const hiddenInfo = document.querySelector('input#hiddenInfo'); const dataVid = hiddenInfo.getAttribute('data-vid') // 验证识别码和商品sku是否唯一 if (!await dxmProductManagementFuzzySearchEmpty('识别码', dataVid)) {showToast(`包含 ${dataVid} 的[识别码]已存在, 请勿重复录入!`,'error');return;} if (!await dxmProductManagementFuzzySearchEmpty('商品SKU', productInfo.skuId)) {showToast(`包含 ${productInfo.skuId} 的[商品SKU]已存在, 请勿重复录入!`,'error');return;} // if (!await dxmProductManagementFuzzySearchEmpty('商品SKU', `${productInfo.skuId}`)) {showToast(`包含 ${productInfo.skuId} 的[商品SKU]已存在, 请检查规格是否相同!`,'warning', '10%', '35%');} const productSkuElement = document.querySelector('input#proSku'); productSkuElement.value = productInfo.skuId; // 商品分类: const categorySelectElement = document.querySelector('#catagoryFullName'); categorySelectElement.click(); document.querySelector('[title="家居日用"]').click(); // 中文名称 const titleZHElement = document.querySelector('input#proName'); titleZHElement.value = `${productInfo.title} >> ${productInfo.skuString}`; // 识别码 const identifierElement = document.querySelector('input#proSbm'); identifierElement.value = dataVid; // 来源URL if (document.querySelectorAll('input[name="sourceUrl"]').length < 2) { document.querySelector('.addSourceUrl').click(); } const sourceUrlElements = document.querySelectorAll('input[name="sourceUrl"]'); const sourceUrls = [`https://www.ozon.ru/product/${dataVid}/`, `${productInfo.url}?sku=${productInfo.skuString}`]; sourceUrls.forEach((sourceUrl, index) => { sourceUrlElements[index].value = sourceUrl; }); // 点击物流与包装 document.querySelector('[uid="logisticsPackaging"]').click(); // 报关中文名 const customNameZhElement = document.querySelector('input#nameCn'); customNameZhElement.value = categorySelectElement.textContent; // 报关英文名 const customNameEnElement = document.querySelector('input#nameEn'); customNameEnElement.value = 'necessary' // customNameEnElement.value = pinyinPro.convert(category, { // toneType: 'none', // type: 'pinyin', // letterCase: 'firstUpper' // }); // 申报金额 0.1-1.5 const declarePriceElement = document.querySelector('input#cusPrice'); declarePriceElement.value = (Math.random() * (1.5 - 0.1) + 0.1).toFixed(2); // 申报重量 15-35 克 const declareWeightElement = document.querySelector('input#cusWeight'); declareWeightElement.value = (Math.random() * (35 - 15) + 15).toFixed(2); // 点击质检与供货 document.querySelector('[uid="qualityInspectionSupply"]').click(); // 采购参考价 const purchasePriceElement = document.querySelector('input#proPrice'); purchasePriceElement.value = productInfo.averagePrice; // 返回首页 document.querySelector('[uid="goodsInfo"]').click(); showToast(`商品信息已自动录入`,'success'); GM_deleteValue('dxmProductInfo'); } function extract1688CreateStockInfo() { const urlMatch = document.URL.match(/https:\/\/detail\.1688\.com\/offer\/(\d+)\.html/); const totalPrice = get1688TotalPrice(); const totalFreight = get1688TotalFreight(); const skuAndCount = get1688ProductSkuString(); if (!skuAndCount || skuAndCount.split(',').length > 1) {showToast('请先选择商品型号和数量, 不能同时选择多个型号', 'error');return;} const lastStarIndex = skuAndCount.lastIndexOf('*'); let [skuString, skuCount] = lastStarIndex === -1 ? [skuAndCount, ''] : [skuAndCount.slice(0, lastStarIndex), skuAndCount.slice(lastStarIndex + 1)]; const titleElement = document.querySelector('.title-content h1') || document.querySelector('[class="title-text"]'); const title = titleElement ? titleElement.textContent.trim() : null; if (!title) {showToast('提取商品标题失败, 请发网页截图和链接给IT修复插件', 'error');return;} const allSkuDict = Object.fromEntries(Object.entries(unsafeWindow.context.result.data.Root.fields.dataJson.skuModel.skuInfoMapOriginal || unsafeWindow.context.result.data.Root.fields.dataJson.skuModel.skuInfoMap).map(([oldKey, value]) => [oldKey.replace(/>/g, ''),value])); let skuDict = allSkuDict[skuString]; if (!skuDict) { const skuTempList = [ skuString.split(';').at(-1), // 取最后一个分号后的字符串 skuString.slice(skuString.indexOf(';') + 1) // 取第一个分号后的字符串 ]; for (const skuStringTemp of skuTempList) { skuDict = allSkuDict[skuStringTemp]; if (skuDict) {break;} } } if (!skuDict) {showToast(`${skuString} 提取 [SKU ID] 失败, 请发网页截图和链接给IT修复插件`, 'error');return;} const dxmProductInfo = { url: urlMatch[0], title: title, productId: urlMatch[1], skuId: skuDict.skuId, skuString: skuString, count: skuCount, totalPrice: parseFloat(totalPrice + totalFreight).toFixed(2), averagePrice: ((parseFloat(totalPrice) + parseFloat(totalFreight)) / parseInt(skuCount)).toFixed(2), } GM_setValue('dxmProductInfo', dxmProductInfo); copyToClipboard(skuDict.skuId, false) showToast(Object.entries(dxmProductInfo).map(([key, value]) => `${dxmProductInfoMapping[key]}: ${value}`).join('\n')); } function get1688TotalPrice() { const priceElements = Object.values({ '常规': document.querySelector('#submitOrder .total-price > strong'), 'https://detail.1688.com/offer/927463287246.html': document.querySelector('.gyp-order-price-text'), 'https://detail.1688.com/offer/746259328464.html': document.querySelector('.total-price > div > .value'), 'https://detail.1688.com/offer/735420835508.html': document.querySelector('.list-bar > [class="float-left"]:nth-of-type(2) > .num'), }).filter(Boolean) console.log(priceElements) const price = priceElements.length > 0 ? priceElements[0].textContent.trim().match(/[0-9.]+/)[0].trim() : 0; return parseFloat(price).toFixed(2); } function get1688TotalFreight(){ const freightElements = Object.values({ '常规': document.querySelector('#submitOrder .total-freight-fee .currency'), 'https://detail.1688.com/offer/927463287246.html': document.querySelector('.delivery-box > span > span'), 'https://detail.1688.com/offer/746259328464.html': document.querySelector('.postage-value > .value'), 'https://detail.1688.com/offer/735420835508.html': document.querySelector('.delivery-info .delivery-value'), }).filter(Boolean) const freight = freightElements.length > 0 ? freightElements[0].textContent.trim().match(/[0-9.]+/)[0].trim() : 0; return parseFloat(freight).toFixed(2); } function get1688ProductSkuString(){ // 常规方案 const allPropertyElements = document.querySelectorAll('#cartScrollBar > #skuSelection .active > .label-name'); const allProperty = Array.from(allPropertyElements).map(skuElement => skuElement.textContent.trim()).filter(Boolean); const sku2Elements = document.querySelectorAll('#cartScrollBar > #skuSelection input[aria-valuenow]'); let skuList = Array.from(sku2Elements).map(sku2 => { console.log('常规方案') const sku2NameElementClosest = sku2.closest('.expand-view-item') || sku2.closest('.ant-table-row'); const sku2NameElement = sku2NameElementClosest.querySelector('.item-label') || sku2NameElementClosest.querySelector('.gyp-pro-table-title > p') if (sku2NameElement){ const sku2Name = sku2NameElement.getAttribute('title') || sku2NameElement.textContent.trim(); return `${[...allProperty, sku2Name].filter(Boolean).join(';')}*${sku2.value}`; // 因为content不包含allProperty, } }); // https://detail.1688.com/offer/927463287246.html // https://detail.1688.com/offer/858885203091.html if (skuList.filter(Boolean).length === 0) { console.log('927463287246 方案') const allPropertyElements = document.querySelectorAll('.sku-props-list > .item-selected > .prop-item-text') const allProperty = Array.from(allPropertyElements).map(skuElement => skuElement.textContent.trim()); const countElements = document.querySelectorAll('.sku-list-item:has(input:not([value="0"]))'); skuList = Array.from(countElements).map(countElement => { const subSku = countElement.querySelector('.sku-item-name-text').getAttribute('title'); const count = countElement.querySelector('input').value; return `${allProperty.join(';')};${subSku}*${count}` }); } // https://detail.1688.com/offer/746259328464.html if (skuList.filter(Boolean).length === 0) { console.log('746259328464 方案') const skuFixedElement = document.querySelector('.prop-item-inner-wrapper.active > .prop-name'); const skuFixedText = skuFixedElement ? skuFixedElement.getAttribute('title').trim() : null; const skuElements = document.querySelectorAll('#sku-count-widget-wrapper > .sku-item-wrapper'); skuList = Array.from(skuElements).map(skuElement => { const countElement = skuElement.querySelector('input'); if (countElement && countElement.value > 0) { const skuName = skuElement.querySelector('.sku-item-name').textContent.trim(); return `${[skuFixedText, skuName].filter(Boolean).join(';')}*${countElement.value}`; } }); } // https://detail.1688.com/offer/735420835508.html if (skuList.filter(Boolean).length === 0) { console.log('735420835508 方案') const skuFixedElements = document.querySelectorAll('.filters > .radio-list li.selected > button'); const skuFixedText = Array.from(skuFixedElements).map(skuElement => skuElement.getAttribute('title').trim()).join('_'); const skuElements = document.querySelectorAll('.next-table-lock > .next-table-inner > .next-table-body tr'); skuList = Array.from(skuElements).map(skuElement => { const countElement = skuElement.querySelector('input'); if (countElement && countElement.value > 0) { const skuName = skuElement.querySelector('td.first').textContent.trim(); return `${skuFixedText};${skuName}*${countElement.value}`; // 因为content不包含skuFixedText } }); } // https://detail.1688.com/offer/1008362318683.html 补充:单规格商品 if (skuList.filter(Boolean).length === 0) { console.log('1008362318683 方案') const skuElement = document.querySelector('.single-sku-title > .single-sku-item > span:nth-child(2)') || document.querySelector('.industry-pro-sku-selection-props-panel li:nth-child(1) > span:nth-child(2)'); const skuContentElement = document.querySelector('.single-price-warp .price-title input') || document.querySelector('.gyp-pro-table-only-one-sku .ant-input-number-input-wrap > input'); if (skuElement && skuContentElement) { skuList.push(`${skuElement.textContent.trim()}*${skuContentElement.value}`); } } return skuList.filter(Boolean).join(',') } function extract1688Notes() { const urlMatch = document.URL.match(/https:\/\/detail\.1688\.com\/offer\/(\d+)\.html/); const skuString = get1688ProductSkuString(); if (!skuString) {showToast('未提取到商品SKU, 如已勾选商品, 请发网页截图和链接给IT修复插件', 'error');return;} const dataDict = { '采购平台': '1688', '商品链接': urlMatch ? urlMatch[0] : null, '商品标识': skuString, '商品价格': (parseFloat(get1688TotalPrice()) + parseFloat(get1688TotalFreight())).toFixed(2) } const dataList = Object.entries(dataDict).map(([key, value]) => ` ${key}: ${value}`); copyToClipboard(dataList.join('\n')); } function extractAmazonNotes() { function amazonGetAsin() { const asinMatch = document.URL.match(/\/([A-Z0-9]{10})/); return asinMatch ? asinMatch[1] : null; } function amazonGetUrl() { const asin = amazonGetAsin(); return asin ? `https://${document.location.hostname}/dp/${asin}?th=1&psc=1` : null; } function amazonGetPrice() { const host = document.location.hostname; let priceXPaths = [ '//*[@id="mediamatrix_feature_div"]//*[@class="slot-price"]', '//*[@id="apex_offerDisplay_desktop"]//*[contains(@class, "a-offscreen")]', ]; const priceElement = document.evaluate(priceXPaths.join(' | '), document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue; console.log('价格文本: ', priceElement.textContent) let price = priceElement.textContent.match(/[0-9.]+/)[0].trim(); if (['www.amazon.fr', 'www.amazon.de', 'www.amazon.it', 'www.amazon.es'].includes(host) && !price.includes('.')) { price = (parseInt(price) / 100).toString(); } return price; } function amazonGetDiscount() { const discountXpath = [ '//*[@class="promoPriceBlockMessage"]//*[starts-with(@id, "couponTextpctch")]', // 白色背景绿色字体 勾选的 // '//*[@class="promoPriceBlockMessage"]//*[starts-with(@id, "greenBadgepctch")]', // 绿色背景褐色字体的 ] const existDiscount = document.evaluate(discountXpath.join(' | '), document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue // return existDiscount ? existDiscount.textContent.match(/[0-9.]+%/)[0].trim() : null; return existDiscount ? '有' : null } const dataDict = { ' 采购平台': 'Amazon', ' 商品链接': amazonGetUrl(), ' 商品标识': amazonGetAsin(), ' 商品价格': amazonGetPrice(), } const isAmazonDiscount = amazonGetDiscount(); if (isAmazonDiscount) { dataDict[' 优惠券'] = isAmazonDiscount; } const dataList = Object.entries(dataDict).map(([key, value]) => `${key}: ${value}`); copyToClipboard(dataList.join('\n')); } function extractTiktokNotes() { function tiktokGetUrl() { const urlObj = new URL(document.URL); let productId = urlObj.searchParams.get('product_id'); if (!productId) { productId = urlObj.pathname.match(/\d{16,20}/)[0]; } return `https://www.tiktok.com/view/product/${productId}`; } function tiktokGetLogo() { // 购买页面的商品标识 let logoElement = document.querySelector('[class^="index-goods__specification--"]'); if (logoElement) { return logoElement.textContent.trim(); } // 商品详情页面的商品标识 const logoElements = [...document.querySelectorAll('div.border-color-UIShapeNeutral > span')].map((element) => element.textContent.trim()); return logoElements.join(','); } function tiktokGetPrice() { // 购买页面的商品价格 let priceElement = document.querySelector('[class^="index-goods__price__real--"]'); if (priceElement) { return priceElement.textContent.trim(); } // 商品详情页面的商品价格 priceElement = document.querySelector('div.items-baseline > .items-baseline'); if (priceElement) { return priceElement.textContent.trim().match(/[0-9.]+/)[0].trim(); } } const dataDict = { ' 采购平台': 'TikTok', ' 商品链接': tiktokGetUrl(), ' 商品标识': tiktokGetLogo(), ' 商品价格': tiktokGetPrice(), } const dataList = Object.entries(dataDict).map(([key, value]) => `${key}: ${value}`); copyToClipboard(dataList.join('\n')); } function copyToClipboard(text, isShowToast=true) { return navigator.clipboard.writeText(text).then(() => { if (isShowToast) {showToast(text,'info');} }).catch(err => { alert(`复制失败,请联系Tom反馈!!!\n\n错误信息: ${err}, \n链接: ${document.URL}`); }); } function autoFillSku(){ const skuSet = new Set(); // 有型号取型号 document.querySelectorAll('.ant-modal-content .order-sku__attr').forEach((skuElement) => { const subSkuItems = []; skuElement.querySelectorAll(':scope > div > div').forEach((subSkuElement) => { subSkuItems.push(`${subSkuElement.textContent}`); }); if (subSkuItems.length > 0) {skuSet.add(`${subSkuItems.join('')}:`);} }); if (!skuSet.size) { // 无型号取SKU document.querySelectorAll('.ant-modal-content .w280 .pointer').forEach((skuElement) => { const subSkuItems = []; subSkuItems.push(skuElement.textContent.trim()); if (subSkuItems.length > 0) {skuSet.add(`${subSkuItems.join('')}:`);} }); } if (skuSet.size) { const inputElements = document.querySelectorAll('textarea[placeholder="请输入内容"]'); inputElements.forEach((inputElement) => { inputElement.value = [...skuSet].join('\n\n') + '\n';} ); } } function showToast(message, colorType='info', top='1%', right='2%', animationEffectDuration=200, toastDuration=3000) { const colorMap = { success: { bg: 'rgba(65,241,100,0.9)', color: 'rgba(255,255,255)' }, error: { bg: 'rgba(234,44,44,0.9)', color: 'rgba(255,255,255)' }, warning: { bg: 'rgb(228,213,62,0.9)', color: 'rgba(255,255,255)' }, info: { bg: 'rgba(39,37,37,0.9)', color: 'rgba(255,255,255)' }, }; const colorConfig = colorMap[colorType] || colorMap.info; const sfPopUpMessageElement = document.createElement("div"); sfPopUpMessageElement.style.position = 'fixed'; sfPopUpMessageElement.style.padding = '12px 20px'; sfPopUpMessageElement.style.boxShadow = '0 4px 20px rgba(50, 50, 80, 0.15)'; sfPopUpMessageElement.style.borderRadius = '6px'; sfPopUpMessageElement.style.zIndex = '99999'; sfPopUpMessageElement.style.fontSize = '14px'; sfPopUpMessageElement.style.fontWeight = '500'; sfPopUpMessageElement.style.lineHeight = '1.5'; sfPopUpMessageElement.style.whiteSpace = 'normal'; sfPopUpMessageElement.style.wordWrap = 'break-word'; sfPopUpMessageElement.style.top = top; sfPopUpMessageElement.style.right = right; sfPopUpMessageElement.style.background = colorConfig.bg; sfPopUpMessageElement.style.color = colorConfig.color; sfPopUpMessageElement.innerHTML = message.replace(/\n/g, '
'); sfPopUpMessageElement.style.opacity = '0'; sfPopUpMessageElement.style.transform = 'translateX(100%)'; sfPopUpMessageElement.style.transition = `all ${animationEffectDuration/1000}s cubic-bezier(0.4, 0, 0.2, 1)`; document.body.appendChild(sfPopUpMessageElement); setTimeout(() => { sfPopUpMessageElement.style.opacity = '1'; sfPopUpMessageElement.style.transform = 'translateX(0)'; }, 0); setTimeout(() => { sfPopUpMessageElement.style.opacity = '0'; sfPopUpMessageElement.style.transform = 'translateX(100%)'; setTimeout(() => sfPopUpMessageElement.remove(), animationEffectDuration); }, toastDuration); } function findElementInNestedShadowDOM(targetSelector, root = document) { // 递归-shadow-dom查找目标元素 let results = Array.from(root.querySelectorAll(targetSelector)); const allElements = Array.from(root.querySelectorAll('*')); allElements.forEach(el => { if (el.shadowRoot) { const nestedResults = findElementInNestedShadowDOM(targetSelector, el.shadowRoot); results = results.concat(nestedResults); } }); return results; } async function waitForElementTextChange(elementSelector, root=document, oldStr=null, timeout = 1000*15, timeoutInterval=1000) { // 等待元素文本变化 if (!oldStr) oldStr = findElementInNestedShadowDOM(elementSelector, root)[0].textContent.trim() return new Promise(resolve => { const start = Date.now(); const timer = setInterval(() => { if (Date.now() - start >= timeout) return clearInterval(timer) || resolve(); const newStr = findElementInNestedShadowDOM(elementSelector, root)[0]?.textContent.trim() || ''; if (newStr && newStr !== oldStr) clearInterval(timer) || resolve(); }, timeoutInterval); }); } async function waitForElement(selector, timeout = 5000, interval = 300) { return new Promise(resolve => { const start = Date.now(); const timer = setInterval(() => { if (Date.now() - start >= timeout) return clearInterval(timer) || resolve(null); const el = selector.startsWith('/') ? document.evaluate(selector, document, null, XPathResult.FIRST_ORDERED_NODE_TYPE).singleNodeValue : document.querySelector(selector); el && (clearInterval(timer) || resolve(el)); }, interval); }); } })();