Last active
May 29, 2026 09:34
-
-
Save hoist1999/c12db5dae8b3ec0b4373438f29115226 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // 代码修改后保存到下面网址 | |
| // https://gist.github.com/hoist1999/c12db5dae8b3ec0b4373438f29115226/edit | |
| /** 所有插件通用工具类 */ | |
| class PluginUtils { | |
| static marketplaceList = [ | |
| { | |
| englishName: "Brazil", | |
| chineseName: "巴西", | |
| countryCode: "BR", | |
| FBARegion: "BR", | |
| marketplaceId: "A2Q3Y263D00KWC", | |
| }, | |
| { | |
| englishName: "Canada", | |
| chineseName: "加拿大", | |
| countryCode: "CA", | |
| FBARegion: "CA", | |
| marketplaceId: "A2EUQ1WTGCTBG2", | |
| }, | |
| { | |
| englishName: "Mexico", | |
| chineseName: "墨西哥", | |
| countryCode: "MX", | |
| FBARegion: "MX", | |
| marketplaceId: "A1AM78C64UM0Y8", | |
| }, | |
| { | |
| englishName: "United States", | |
| chineseName: "美国", | |
| countryCode: "US", | |
| FBARegion: "US", | |
| marketplaceId: "ATVPDKIKX0DER", | |
| }, | |
| { | |
| englishName: "United Arab Emirates (U.A.E.)", | |
| chineseName: "阿联酋", | |
| countryCode: "AE", | |
| FBARegion: "AE", | |
| marketplaceId: "A2VIGQ35RCS4UG", | |
| }, | |
| { | |
| englishName: "Germany", | |
| chineseName: "德国", | |
| countryCode: "DE", | |
| FBARegion: "PanEuro", | |
| marketplaceId: "A1PA6795UKMFR9", | |
| }, | |
| { | |
| englishName: "Egypt", | |
| chineseName: "埃及", | |
| countryCode: "EG", | |
| FBARegion: "EG", | |
| marketplaceId: "ARBP9OOSHTCHU", | |
| }, | |
| { | |
| englishName: "Spain", | |
| chineseName: "西班牙", | |
| countryCode: "ES", | |
| FBARegion: "PanEuro", | |
| marketplaceId: "A1RKKUPIHCS9HS", | |
| }, | |
| { | |
| englishName: "France", | |
| chineseName: "法国", | |
| countryCode: "FR", | |
| FBARegion: "PanEuro", | |
| marketplaceId: "A13V1IB3VIYZZH", | |
| }, | |
| { | |
| englishName: "Belgium", | |
| chineseName: "比利时", | |
| countryCode: "BE", | |
| FBARegion: "PanEuro", | |
| marketplaceId: "AMEN7PMS3EDWL", | |
| }, | |
| { | |
| englishName: "United Kingdom", | |
| chineseName: "英国", | |
| countryCode: "GB", | |
| FBARegion: "UK", | |
| marketplaceId: "A1F83G8C2ARO7P", | |
| }, | |
| { | |
| englishName: "India", | |
| chineseName: "印度", | |
| countryCode: "IN", | |
| FBARegion: "IN", | |
| marketplaceId: "A21TJRUUN4KGV", | |
| }, | |
| { | |
| englishName: "Italy", | |
| chineseName: "意大利", | |
| countryCode: "IT", | |
| FBARegion: "PanEuro", | |
| marketplaceId: "APJ6JRA9NG5V4", | |
| }, | |
| { | |
| englishName: "Netherlands", | |
| chineseName: "荷兰", | |
| countryCode: "NL", | |
| FBARegion: "PanEuro", | |
| marketplaceId: "A1805IZSGTT6HS", | |
| }, | |
| { | |
| englishName: "Poland", | |
| chineseName: "波兰", | |
| countryCode: "PL", | |
| FBARegion: "PanEuro", | |
| marketplaceId: "A1C3SOZRARQ6R3", | |
| }, | |
| { | |
| englishName: "Saudi Arabia", | |
| chineseName: "沙特阿拉伯", | |
| countryCode: "SA", | |
| FBARegion: "SA", | |
| marketplaceId: "A17E79C6D8DWNP", | |
| }, | |
| { | |
| englishName: "Sweden", | |
| chineseName: "瑞典", | |
| countryCode: "SE", | |
| FBARegion: "PanEuro", | |
| marketplaceId: "A2NODRKZP88ZB9", | |
| }, | |
| { | |
| englishName: "Turkey", | |
| chineseName: "土耳其", | |
| countryCode: "TR", | |
| FBARegion: "PanEuro", | |
| marketplaceId: "A33AVAJ2PDY3EV", | |
| }, | |
| { | |
| englishName: "Ireland", | |
| chineseName: "爱尔兰", | |
| countryCode: "IE", | |
| FBARegion: "PanEuro", | |
| marketplaceId: "A28R8C7NBKEWEA", | |
| }, | |
| { | |
| englishName: "Singapore", | |
| chineseName: "新加坡", | |
| countryCode: "SG", | |
| FBARegion: "SG", | |
| marketplaceId: "A19VAU5U5O7RUS", | |
| }, | |
| { | |
| englishName: "Australia", | |
| chineseName: "澳大利亚", | |
| countryCode: "AU", | |
| FBARegion: "AU", | |
| marketplaceId: "A39IBJ37TRP1C6", | |
| }, | |
| { | |
| englishName: "Japan", | |
| chineseName: "日本", | |
| countryCode: "JP", | |
| FBARegion: "JP", | |
| marketplaceId: "A1VC38T7YXB528", | |
| }, | |
| ]; | |
| // 通用函数:传入html文本,转为HtmlElement对象 | |
| static htmlToElement(html) { | |
| console.log("hello world 112."); | |
| var template = document.createElement("template"); | |
| html = html.trim(); | |
| template.innerHTML = html; | |
| return template.content.firstChild; | |
| } | |
| /** 通用函数:等待一个目标元素的出现 */ | |
| static waitForElementAsync(selector, timeout = 3000) { | |
| return new Promise((resolve, reject) => { | |
| const targetNode = document.querySelector(selector); | |
| // 目标元素已存在,直接 resolve | |
| if (targetNode) { | |
| resolve(targetNode); | |
| return; | |
| } | |
| // 超时时间到了仍未找到目标元素,reject | |
| const timeoutId = setTimeout(() => { | |
| observer.disconnect(); // 停止监听 | |
| reject( | |
| new Error( | |
| `Timeout (${timeout}ms) waiting for element with selector "${selector}"`, | |
| ), | |
| ); | |
| }, timeout); | |
| // 使用 MutationObserver 监听目标元素的出现 | |
| const observer = new MutationObserver(() => { | |
| const targetNode = document.querySelector(selector); | |
| if (targetNode) { | |
| observer.disconnect(); // 停止监听 | |
| clearTimeout(timeoutId); // 清除超时计时器 | |
| resolve(targetNode); // 找到目标元素,resolve | |
| } | |
| }); | |
| observer.observe(document.documentElement, { | |
| childList: true, | |
| subtree: true, | |
| }); | |
| }); | |
| } // END of waitForElementAsync | |
| /** 等待多少毫秒 */ | |
| static sleepAsync(ms) { | |
| return new Promise((resolve) => setTimeout(resolve, ms)); | |
| } | |
| /** 根据textContent在node的所有子节点中查找对应的节点 */ | |
| static findNodeByContent(node, textContent) { | |
| if (node.textContent === textContent) { | |
| return node; | |
| } | |
| for (let i = 0; i < node.childNodes.length; i++) { | |
| const childNode = node.childNodes[i]; | |
| const foundNode = Util.findNodeByContent(childNode, textContent); | |
| if (foundNode) { | |
| return foundNode; | |
| } | |
| } | |
| return null; | |
| } // END: findNodeByContent | |
| /** 从文本中取出第一个数 */ | |
| static extractFirstNumber(text) { | |
| const regex = /\d+(\.\d+)?/; | |
| const match = text.match(regex); | |
| return match ? Number(match[0]) : null; | |
| } | |
| static addStyle(styleText) { | |
| // 添加样式 | |
| const styleSheet = document.createElement("style"); | |
| styleSheet.innerHTML = styleText; | |
| // 将样式表添加到页面 | |
| document.head.appendChild(styleSheet); | |
| } | |
| /** | |
| * 返回当前日期字符串 | |
| * 例如:2023-08-30 18:22:31 | |
| */ | |
| static getCurrentDateTimeString() { | |
| const now = new Date(); | |
| const year = now.getFullYear(); | |
| const month = String(now.getMonth() + 1).padStart(2, "0"); | |
| const day = String(now.getDate()).padStart(2, "0"); | |
| const hours = String(now.getHours()).padStart(2, "0"); | |
| const minutes = String(now.getMinutes()).padStart(2, "0"); | |
| const seconds = String(now.getSeconds()).padStart(2, "0"); | |
| const dateTimeString = `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`; | |
| return dateTimeString; | |
| } | |
| static getCountryCodeByMarketplaceId(marketplaceId) { | |
| const marketplace = this.marketplaceList.find( | |
| (item) => item.marketplaceId === marketplaceId, | |
| ); | |
| if (marketplace) { | |
| return marketplace.countryCode; | |
| } | |
| return null; // 如果未找到对应的marketplaceId,则返回null或其他适当的值 | |
| } | |
| /** 根据国家中/英文名称返回 countryCode */ | |
| static getCountryCodeByCountryName(countryName) { | |
| const marketplace = this.marketplaceList.find( | |
| (item) => | |
| item.englishName === countryName || item.chineseName === countryName, | |
| ); | |
| return marketplace?.countryCode ?? null; | |
| } | |
| /** 根据国家中/英文名称返回 marketplaceId */ | |
| static getMarketplaceIdByCountryName(countryName) { | |
| const marketplace = this.marketplaceList.find( | |
| (item) => | |
| item.englishName === countryName || item.chineseName === countryName, | |
| ); | |
| return marketplace?.marketplaceId ?? null; | |
| } | |
| /** 从当前页面读取 marketplaceId(ue_mid) */ | |
| static getMarketplaceId() { | |
| let marketplaceId = window.ue_mid || ""; | |
| if (!marketplaceId) { | |
| try { | |
| marketplaceId = window.top?.ue_mid || ""; | |
| } catch { | |
| // 跨域 iframe 时忽略 top | |
| } | |
| } | |
| // 如果还是没有,尝试从页面明文国家信息中获取 | |
| if (!marketplaceId) { | |
| const selectors = [ | |
| ".dropdown-account-switcher-header-label-regional", // 常见在页面头部 | |
| ".dropdown-account-switcher-header-label-regional-child", | |
| ]; | |
| // 遍历当前 window 和 top window | |
| const docs = []; | |
| try { | |
| if (window.top && window.top.document) { | |
| docs.push(window.top.document); | |
| } | |
| } catch { | |
| // 跨域 iframe 时忽略 top document | |
| } | |
| docs.push(document); | |
| let foundText = ""; | |
| for (const doc of docs) { | |
| for (const sel of selectors) { | |
| const el = doc.querySelector(sel); | |
| if (el && el.textContent?.trim()) { | |
| foundText = el.textContent.trim(); | |
| break; | |
| } | |
| } | |
| if (foundText) break; | |
| } | |
| if (foundText) { | |
| const marketplaceId = this.getMarketplaceIdByCountryName(foundText); | |
| if (marketplaceId) { | |
| return marketplaceId; | |
| } | |
| throw new Error(`无法根据国家名称「${foundText}」解析 marketplaceId`); | |
| } | |
| } | |
| return marketplaceId; | |
| } | |
| /** 从当前页面读取 marketplaceId 并返回国家代号(如 US、DE) */ | |
| static getCountryCode() { | |
| const mid = this.getMarketplaceId(); | |
| return this.getCountryCodeByMarketplaceId(mid); | |
| } | |
| /** | |
| * 从 Seller Central 页面读取当前店铺名称 | |
| */ | |
| static getSellercentralStoreName() { | |
| const selector = ".dropdown-account-switcher-header-label-global"; | |
| const docs = []; | |
| try { | |
| if (window.top && window.top.document) { | |
| docs.push(window.top.document); | |
| } | |
| } catch { | |
| // 跨域 iframe 时忽略 top document | |
| } | |
| docs.push(document); | |
| for (const doc of docs) { | |
| const el = doc.querySelector(selector); | |
| const name = el?.textContent?.trim(); | |
| if (name) { | |
| return name; | |
| } | |
| } | |
| return null; | |
| } | |
| /** 等待 Seller Central 店铺名称元素出现 */ | |
| static async getSellercentralStoreNameAsync(timeout = 5000) { | |
| const existing = this.getSellercentralStoreName(); | |
| if (existing) { | |
| return existing; | |
| } | |
| const selector = ".dropdown-account-switcher-header-label-global"; | |
| const docs = []; | |
| try { | |
| if (window.top && window.top.document) { | |
| docs.push(window.top.document); | |
| } | |
| } catch { | |
| // 跨域 iframe 时忽略 top document | |
| } | |
| docs.push(document); | |
| return new Promise((resolve, reject) => { | |
| const timeoutId = setTimeout(() => { | |
| observer.disconnect(); | |
| reject( | |
| new Error( | |
| `Timeout (${timeout}ms) waiting for Seller Central store name "${selector}"`, | |
| ), | |
| ); | |
| }, timeout); | |
| const observer = new MutationObserver(() => { | |
| for (const doc of docs) { | |
| const el = doc.querySelector(selector); | |
| const name = el?.textContent?.trim(); | |
| if (name) { | |
| observer.disconnect(); | |
| clearTimeout(timeoutId); | |
| resolve(name); | |
| return; | |
| } | |
| } | |
| }); | |
| observer.observe(document.documentElement, { | |
| childList: true, | |
| subtree: true, | |
| }); | |
| try { | |
| if (window.top && window.top.document) { | |
| observer.observe(window.top.document.documentElement, { | |
| childList: true, | |
| subtree: true, | |
| }); | |
| } | |
| } catch { | |
| // 跨域 iframe 时忽略 top document | |
| } | |
| }); | |
| } | |
| static getFBARegionByMarketplaceId(marketplaceId) { | |
| const marketplace = this.marketplaceList.find( | |
| (item) => item.marketplaceId === marketplaceId, | |
| ); | |
| if (marketplace) { | |
| return marketplace.FBARegion; | |
| } | |
| return null; // 如果未找到对应的marketplaceId,则返回null或其他适当的值 | |
| } | |
| /** 读取 Seller Central 顶部账户切换器显示的店铺名称 */ | |
| static getSellerCentralStoreName() { | |
| const selector = ".dropdown-account-switcher-header-label-global"; | |
| const docs = [document]; | |
| try { | |
| if (window.top?.document && window.top.document !== document) { | |
| docs.push(window.top.document); | |
| } | |
| } catch { | |
| // 跨域 iframe 时忽略 top document | |
| } | |
| for (const doc of docs) { | |
| const el = doc.querySelector(selector); | |
| const name = el?.textContent?.trim(); | |
| if (name) { | |
| return name; | |
| } | |
| } | |
| return null; | |
| } | |
| } // END Util | |
| /** 广告插件通用工具类 */ | |
| class CampaignPluginUtil { | |
| // 向页面左下方添加一个按钮容器 | |
| static addButtonDocker() { | |
| var buttonDocker = document.getElementById("button_docker"); | |
| if (!buttonDocker) { | |
| // Create the button docker | |
| buttonDocker = PluginUtils.htmlToElement( | |
| '<div id="button_docker"></div>', | |
| ); | |
| document.body.appendChild(buttonDocker); | |
| // Apply CSS styles to the button docker | |
| GM_addStyle(` | |
| #button_docker { | |
| position: fixed; | |
| max-width: 300px; | |
| bottom: 10px; | |
| left: 60px; | |
| display: flex; | |
| flex-wrap: wrap; | |
| } | |
| #button_docker button { | |
| margin: 5px; | |
| } | |
| `); | |
| } | |
| return buttonDocker; | |
| } | |
| static createBtn(text) { | |
| // 创建一个按钮元素 | |
| const button = document.createElement("button"); | |
| // 添加样式 | |
| button.innerHTML = text; | |
| button.style.backgroundColor = "#E5E6E8"; | |
| button.style.marginLeft = "5px"; | |
| button.style.border = "none"; | |
| button.style.outline = "none"; | |
| button.style.cursor = "pointer"; | |
| button.style.color = "rgb(35, 47, 63)"; | |
| button.style.padding = "6px 8px"; | |
| button.style.fontSize = "14px"; | |
| button.style.cursor = "pointer"; | |
| button.style.zIndex = "9999"; | |
| return button; | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment