X Email Mobile
EXW Price: |
|
HongYue Cap factory 9yr. |
|
Main Products: |
Cap ,hat,baseball cap,knit cap,wool cap, sun visor,knitted hat |
Contacts: | JinguangChat |
Mobile: | 86-15325988618 |
WhatsApp: | 8615325988618 |
E-mail: | jgf6633@gmail.com |
WeChat: | 15325988618 |
Address: | 38964A, 19 Street, 2 F, 南 Gate, International Trade Mart (District 4). |
Address: | 5th Floor, Elevator No.4 Boni Stationery,No. 9, Suxin Street, Suxi Town, Yiwu City, Zhejiang Province,Yiwu City,Jinhua City City,Zhejiang Province |
${text}
`) .join(""); document.querySelector("#yiwugo-urls-count").innerHTML = value.length; //重新初始化复选框 initCheckbox(); }, get: function () { return this._urls; }, }); }; addUrlsListener(); /** * 商品采集过程中的状态:开始采集,数据已就绪,已完成 * @returns */ const getTempConfig = () => { return GM_getValue("TempConfig", {}); }; const setTempConfig = (data) => { const tempConfig = getTempConfig(); Logger.log("setTempConfig", tempConfig); return GM_setValue("TempConfig", { ...tempConfig, ...data }); }; const cleanTempConfig = () => { return GM_setValue("TempConfig", {}); }; /** * @description: 获取商品的链接 */ const getDetailUrlFromOfferItem = (offerItem) => { //直接能够拿到页面元素的链接,直接获取 const url01 = offerItem.href; if (url01 && url01.includes("detail.1688.com")) { return url01; } //我们自己添加的link;是从请求里面获取的 return offerItem.querySelector(`.${linkClassName}`)?.href; }; /** * @description: 删除html节点里面的文本内容 * @param {*} content * @returns */ function removeText(content) { let contentHtml = document.createElement("div"); contentHtml.innerHTML = content; let contentChild = contentHtml.getElementsByTagName("*"); for (let i = 0; i < contentChild.length; i++) { let item = contentChild[i]; const innerText = item.innerText.replace(/\s/g, ""); //只删除有效html节点、并且存在文本内容、并且没有子节点 //当前节点已经是最底层节点 const hasChild = Array.from(item.children).some((children) => { const childrenInnerText = children.innerText.replace(/\s/g, ""); return childrenInnerText === innerText; }); if (innerText && !hasChild) { item.remove(); } } return contentHtml.innerHTML; } /** * 初始化页面产品的复选框,如果当前产品不存在于采集链接里面,那么就不勾选,否则就勾选 */ const initCheckbox = () => { // 1、查询页面上所有的商品元素(class名称包含 space-offer-card-box), let offerItems = document.querySelectorAll(`.${productCardClassName}`); //3、删除页面上所有的复选框 document.querySelectorAll(`.${checkboxClassName}`).forEach((item) => { item.remove(); }); // 4、为每个space-offer-card-box添加一个复选框 offerItems.forEach((item) => { const url = getDetailUrlFromOfferItem(item); item.style.position = "relative"; const checkbox = document.createElement("input"); checkbox.type = "checkbox"; checkbox.classList.add(checkboxClassName); checkbox.setAttribute("checkbox-url", url); checkbox.checked = config.urls.includes(url); //绑定点击事件 checkbox.addEventListener("click", (e) => { //阻止事件冒泡 e.stopPropagation(); e.preventDefault(); e.stopImmediatePropagation(); const checkboxUrl = e.target.getAttribute("checkbox-url"); const url = checkboxUrl.split("?")[0]; const checked = e.target.checked; setTimeout(() => { if (checked) { //如果config.urls不存在当前url,那么就添加到config.urls中 if (config.urls.indexOf(url) === -1) { Logger.log("添加url", url); config.urls = Array.from(new Set([...config.urls, url])); } } else { Logger.log("删除url", url); const urls = config.urls.filter((item) => item !== url); config.urls = Array.from(new Set([...urls])); } // 手动设置checkbox的选中状态 e.target.checked = checked; console.log(e.target.checked); console.log(e.target); }, 0); }); item.prepend(checkbox); }); }; /** * 点击采集按钮;注意每次点击采集按钮会导致采集当前页面的所有商品链接 * 点击采集按钮的时候如果页面地址包含1688.com,那么使用1688的采集方案 * 1、查询页面上所有的商品元素(class名称包含 space-offer-card-box), * 2、获取他们的链接(就是space-offer-card-box 元素里面的a标签的href属性), * 3、将链接添加到config.urls中,添加的时候需要去重 * 4、为每个space-offer-card-box添加一个复选框,用于标记是否采集,如果当前space-offer-card-box的链接已经存在于config.urls中,那么就勾选复选框,否则不勾选;点击复选框可以实现添加或者删除链接并同步到config.urls中 */ const onGetUrls = () => { Logger.log("点击采集按钮"); // 1、查询页面上所有的商品元素(class名称包含 space-offer-card-box), let offerItems = document.querySelectorAll(`.${productCardClassName}`); // 2、获取他们的链接(就是space-offer-card-box 元素里面的a标签的href属性); const urls = Array.from(offerItems).map((item) => { return getDetailUrlFromOfferItem(item); }); // 3、将链接添加到config.urls中,添加的时候需要去重 config.urls = Array.from(new Set([...config.urls, ...urls])); }; /** * 清空urls */ const onCleanUrls = () => { Logger.log("清空urls"); //将所有的复选框取消勾选 document.querySelectorAll(`.${checkboxClassName}`).forEach((item) => { item.checked = false; }); config.urls = []; }; /** * 停止采集 * @returns */ const onClickStopCollect = () => { Logger.log("停止采集"); cleanTempConfig(); clearInterval(loop_collect_interval); }; const onClickStartCollect = () => { Logger.log("onClickStartCollect"); cleanTempConfig(); // 1、如果config.urls为空,那么提示用户先采集商品链接 if (config.urls.length === 0) { alert("请先采集商品链接"); return; } // 标记当前采集状态已经开始 const tempConfig = { nextFunction: "onStartCollect", freight: config.freight, // 设置默认重量(单位:千克) incr_rate: config.incr_rate, // 设置上浮百分比(取值范围:1-1000) removeText: config.removeText, newText: config.newText, }; setTempConfig(tempConfig); loop_collect_interval = setInterval(() => { onStartCollect(); }, 1000); }; /** * 开始自动采集数据 * 1、如果config.urls为空,那么提示用户先采集商品链接 * 2、如果config.urls不为空,获取第一条链接,并将当前链接从config.urls中删除 * 3、在左上角打开一个新的窗口,窗口的地址为第一条链接 * */ const onStartCollect = () => { const tempConfig = getTempConfig(); const { nextFunction } = tempConfig; Logger.log("onStartCollect", nextFunction); if (config.urls.length) { switch (nextFunction) { case "onStartCollect": // 2、如果config.urls不为空,获取第一条链接,并将当前链接从config.urls中删除 const currentCollectUrl = config.urls.shift(); config.urls = Array.from(new Set([...config.urls])); Logger.log("开始采集页面:", currentCollectUrl); // 3、在左上角打开一个新的窗口,窗口的地址为第一条链接 window.open(currentCollectUrl, "_blank", "top=0,left=0,width=300,height=300"); tempConfig.nextFunction = "onThirdDetailPageReady"; setTempConfig(tempConfig); break; default: break; } } else { if (nextFunction === "onStartCollect") { Logger.log("采集完成"); alert("采集完成"); clearInterval(loop_collect_interval); } } }; /** * step2:第三方详情页准备就绪,执行采集函数 */ const onThirdDetailPageReady = async () => { const tempConfig = getTempConfig(); const { nextFunction } = tempConfig; Logger.log("onThirdDetailPageReady", nextFunction); if (nextFunction === "onThirdDetailPageReady") { //step1: 初始化采集函数 var _this = unsafeWindow; const initImport = await onElementReady(() => _this.initImport); initImport(GM_xmlhttpRequest, config.userid, config.marketCode, config.freightTemplateId); //step2: 获取采集按钮 const importButton = await onElementReady(() => { let importButton; document.querySelectorAll("button").forEach((item) => { if (item.innerHTML === "导入义乌购") { importButton = item; } }); return importButton; }); if (importButton) { importButton.click(); Logger.log("点击导入义乌购按钮"); //将状态转换成数据已就绪 tempConfig.nextFunction = "onProductEditPageReady"; setTempConfig(tempConfig); } } }; // 选中上传的第一个商品视屏 const selectFirstVideo = async () => { // step1: 找到选择视频的按钮,并点击 //遍历所有的class为 btw的元素,找到文本为选择视频的按钮,并触发点击事件 let buttons = document.querySelectorAll("a"); let selectVideoBtn; buttons.forEach((item) => { if (item.innerText === "选择视频") { selectVideoBtn = item; } }); if (selectVideoBtn) { selectVideoBtn.click(); } // step2: 找到弹出的选择视频的iframe const videoSelectIframe = await onElementReady(() => { // 获取页面上所有的iframe;找到其中src包含video_select的iframe const iframeList = document.querySelectorAll("iframe"); let videoSelectIframe; iframeList.forEach((item) => { if (item.src.includes("video_select")) { videoSelectIframe = item; } }); return videoSelectIframe; }); // step3: 选中第一个视频 // 默认选中.video_list 下面的第一个 radio input const radio = await onElementReady(() => { return videoSelectIframe.contentDocument.querySelector('.video_list input[type="radio"]'); }); if (radio) { radio.checked = true; } // step4: 点击插入所选视频按钮 const addVideoBtn = await onElementReady(() => { buttons = videoSelectIframe.contentDocument.querySelectorAll("a"); let addVideoBtn; buttons.forEach((item) => { if (item.innerText === "插入所选视频") { addVideoBtn = item; } }); return addVideoBtn; }); if (addVideoBtn) { addVideoBtn.click(); } }; /** * 删除商品详情里面的文字 */ const removeProductDetailText = async () => { const tempConfig = getTempConfig(); //找到相关元素 const contentEle = await onElementReady(() => { return document.querySelector(".ke-edit-textarea"); }); const showCodeBtn = await onElementReady(() => { return document.querySelector(".showError .ke-icon-source"); }); // 切换到代码模式,将内容替换 showCodeBtn.click(); const content = contentEle.value; const newValue = tempConfig.removeText ? removeText(content) : contentEle.value; contentEle.value = `${tempConfig.newText}${newValue}`; // 切换回富文本模式 showCodeBtn.click(); await sleep(3000); }; /** * step3:商品编辑页面准备就绪;只有数据准备就绪之后才能执行这个函数 * 1、默认选中第一个视频 * 2、所有商品属性默认填充第一个 * 3、设置价格 * 4、设置重量 * 5、点击发布 * 6、跳转到发布成功页面 */ const onProductEditPageReady = async () => { const tempConfig = getTempConfig(); const { incr_rate, nextFunction } = tempConfig; Logger.log("onProductEditPageReady", nextFunction); if (nextFunction === "onProductEditPageReady") { //step1:默认选中第一个视频 Logger.log("开始填充视频信息"); await selectFirstVideo(); //step2:找到页面上文本为(商品属性:)的元素,找到他的父级tr元素,找到tr元素的所有select框,将所有的select框的值设置为第二个 Logger.log("开始填充商品属性"); const ths = document.querySelectorAll("th"); const th = Array.from(ths).find((item) => item.innerText === "商品属性:"); const tr = th.parentElement; const selects = tr.querySelectorAll("select"); selects.forEach((item) => { const value = item.options && item.options[1] && item.options[1].value; if (value) item.value = item.options[1].value; }); //step3:设置价格:获取页面上所有的input标签,属性name包含price;将他们的价格上浮incr_rate百分比 //只有priceType为5(按商品规格报价)的radio标签被选中的时候才处理 Logger.log("开始填充商品价格"); const priceType = document.querySelector('input[name="priceType"]:checked'); if (priceType.value === "5") { const container = document.querySelector("#composeProperty"); const priceInputs = container.querySelectorAll('input[name="price"]'); priceInputs.forEach((item) => { item.value = (item.value * (1 + Number(incr_rate) / 100)).toFixed(config.toFixed); }); } else if (priceType.value === "1") { //priceType为1:按商品数量报价 const container = document.querySelector("#priceRange"); //获取container下面所有的tr标签;遍历tr标签,找到tr标签下面的input标签,第二个input标签的value就是价格,需要上浮incr_rate百分比 const trs = container.querySelectorAll("tr"); trs.forEach((item) => { const inputs = item.querySelectorAll("input"); const priceInput = inputs[1]; if (priceInput && priceInput.value) { priceInput.value = (priceInput.value * (1 + Number(incr_rate) / 100)).toFixed( config.toFixed, ); } }); } //step4:设置重量:获取页面上所有的input标签,属性name包含freight;将他们的重量设置为tempConfig.freight Logger.log("开始填充商品重量"); const freightInput = document.querySelector('input[name="freight"]'); freightInput.value = tempConfig.freight; //step4.替换商品详情的内容 Logger.log("替换商品详情的内容"); await removeProductDetailText(); //step5:点击发布按钮input 类型是butoon,value是发布商品 Logger.log("开始发布商品"); const publishBtn = document.querySelector('input[value="发布商品"]'); publishBtn.click(); //step6:跳转到发布成功页面 tempConfig.nextFunction = "onPublishSuccess"; setTempConfig(tempConfig); //如果onPublishSuccess函数没有执行,那么10秒之后执行 publish_error_timeout_tag = setTimeout(() => { tempConfig.nextFunction = "onStartCollect"; setTempConfig(tempConfig); window.close(); }, publish_error_timeout_time); } }; //成功发布产品之后会跳转到这个页面 const onPublishSuccess = async () => { const tempConfig = getTempConfig(); const { nextFunction } = tempConfig; Logger.log("onPublishSuccess", nextFunction); if (nextFunction === "onPublishSuccess") { const success = await onElementReady(() => { return document.querySelector(".success"); }); if (success) { Logger.log("商品发布成功"); } // 清空定时器 if (publish_error_timeout_tag) { clearTimeout(publish_error_timeout_tag); } tempConfig.nextFunction = "onStartCollect"; setTempConfig(tempConfig); window.close(); } }; // 创建可缩放窗口的函数 function createOperationWindow() { Logger.log("createResizableWindow"); const windowDiv = document.createElement("div"); windowDiv.id = "resizable-window"; windowDiv.className = "resizable-window"; windowDiv.innerHTML = `TOP
Items have been added to the Inquiry Basket
There are items in the inquiry basket