// ==UserScript== // @name Wargaming商店外区货币转换器 // @namespace http://tampermonkey.net/ // @version 1.1 // @description Wargaming商店外区货币价值转换为CNY并附代充折扣显示(目前支持ARS、SGD、HKD、TWD) // @author SundayRX // @match https://wargaming.net/shop/* // @grant GM_xmlhttpRequest // @connect api.exchangerate-api.com // @license MIT // @downloadURL none // ==/UserScript== (function() { 'use strict'; // 配置 const CONFIG = { // 打折 discount:0.87, //代冲折扣(自行修改) // 更新间隔(毫秒) updateInterval: 600000, // 10分钟 // 高亮样式 highlightStyle: ` .ars-to-cny-conversion { background-color: #ffffcc; border-radius: 3px; padding: 2px 4px; margin-left: 5px; font-weight: bold; font-size: 0.9em; color: #d32f2f; } .ars-to-cny-processed { display: inline-flex; align-items: center; } `, // 是否显示原始值 showOriginalValue: true }; class Currency { constructor(Type, ExchangeRateAPI, ExchangeRate, MatchRegex) { this.Type = Type; this.ExchangeRateAPI = ExchangeRateAPI; this.ExchangeRate = ExchangeRate; this.MatchRegex = MatchRegex; } } const CurrencyDict = [ new Currency('ARS', 'https://api.exchangerate-api.com/v4/latest/ARS',0.005,/([\d,]+(?:\.\d+)?)\s*(ARS)/i), new Currency('SGD', 'https://api.exchangerate-api.com/v4/latest/SGD',5.5,/([\d,]+(?:\.\d+)?)\s*(SGD)/i), new Currency('HKD', 'https://api.exchangerate-api.com/v4/latest/HKD',0.916,/([\d,]+(?:\.\d+)?)\s*(HKD)/i), new Currency('TWD', 'https://api.exchangerate-api.com/v4/latest/TWD',0.233,/([\d,]+(?:\.\d+)?)\s*(TWD)/i) ]; let isProcessing = false; let observer = null; // 初始化脚本 function init() { console.log('ARS转CNY转换器已加载'); // 添加样式 addStyles(); // 获取汇率 FetchExchangeRate(); // 设置定期更新汇率 setInterval(FetchExchangeRate, CONFIG.updateInterval); // 初始转换 convertPageARSValues(); // 监听DOM变化 observeDOMChanges(); } // 添加样式到页面 function addStyles() { const style = document.createElement('style'); style.textContent = CONFIG.highlightStyle; document.head.appendChild(style); } // 获取汇率 function FetchExchangeRate() { for(let C=0;C span:not(.ars-to-cny-processed)', '[data-qa="product_price"] > span:not(.ars-to-cny-processed)' ]; selectors.forEach(selector => { const foundElements = document.querySelectorAll(selector); foundElements.forEach(element => { // 检查元素是否包含ARS货币值且未被见过 if (ContainsSpecialValue(element.textContent) && !seenElements.has(element)) { elements.push(element); seenElements.add(element); } }); }); return elements; } // 处理价格元素 function processPriceElement(element) { if (element.classList.contains('ars-to-cny-processed')) { return; } const originalText = element.textContent.trim(); const [PriceValue,PriceType] = ExtractSpecialValue(originalText); if (PriceValue !== null && PriceValue!=null) { const formattedCNY = FormatCurrency(PriceValue, PriceType); // 检查是否已经存在转换元素 const existingConversion = findExistingConversion(element); if (existingConversion) { // 如果已存在,更新它 existingConversion.textContent = `≈${formattedCNY}`; existingConversion.title = `${formatNumber(PriceValue)} ARS ≈ ${formattedCNY}`; } else { // 如果不存在,创建新的转换元素 const conversionElement = document.createElement('span'); conversionElement.className = 'ars-to-cny-conversion'; conversionElement.textContent = `≈${formattedCNY}`; conversionElement.title = `${formatNumber(PriceValue)} ARS ≈ ${formattedCNY}`; // 插入到价格元素后面 element.parentNode.insertBefore(conversionElement, element.nextSibling); } // 标记元素为已处理 element.classList.add('ars-to-cny-processed'); } } // 查找已存在的转换元素 function findExistingConversion(element) { // 检查相邻的兄弟元素 let sibling = element.nextElementSibling; while (sibling) { if (sibling.classList && sibling.classList.contains('ars-to-cny-conversion')) { return sibling; } sibling = sibling.nextElementSibling; } // 检查父元素的兄弟元素(针对某些特殊布局) const parent = element.parentElement; if (parent && parent.nextElementSibling) { const nextSibling = parent.nextElementSibling; if (nextSibling.classList && nextSibling.classList.contains('ars-to-cny-conversion')) { return nextSibling; } } return null; } // 格式化数字(添加千位分隔符) function formatNumber(num) { return num.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ","); } // 更新已转换的值 function updateConvertedValues() { const convertedElements = document.querySelectorAll('.ars-to-cny-conversion'); convertedElements.forEach(element => { // 查找相邻的价格元素 const priceElement = findAdjacentPriceElement(element); if (priceElement) { const originalText = priceElement.textContent.trim(); const [PriceValue,PriceType] = ExtractSpecialValue(originalText); if (PriceValue !== null && PriceType!=null) { const formattedCNY = FormatCurrency(PriceValue, PriceType); element.textContent = `≈${formattedCNY}`; element.title = `${formatNumber(PriceValue)} ARS ≈ ${formattedCNY}`; } } }); } // 查找相邻的价格元素 function findAdjacentPriceElement(conversionElement) { // 检查前一个兄弟元素 let sibling = conversionElement.previousElementSibling; while (sibling) { if (sibling.classList && sibling.classList.contains('ars-to-cny-processed')) { return sibling; } sibling = sibling.previousElementSibling; } // 检查父元素的前一个兄弟元素 const parent = conversionElement.parentElement; if (parent && parent.previousElementSibling) { const prevSibling = parent.previousElementSibling; if (prevSibling.classList && prevSibling.classList.contains('ars-to-cny-processed')) { return prevSibling; } } return null; } // 监听DOM变化 function observeDOMChanges() { observer = new MutationObserver(function(mutations) { let shouldConvert = false; mutations.forEach(function(mutation) { if (mutation.type === 'childList') { mutation.addedNodes.forEach(function(node) { if (node.nodeType === Node.ELEMENT_NODE) { // 检查新添加的元素是否包含价格元素 const priceSelectors = [ // '.product-price_old:not(.ars-to-cny-processed)', // '[data-qa="original_product_price"]:not(.ars-to-cny-processed)', '.product-price_wrap > span:not(.ars-to-cny-processed)', '[data-qa="product_price"] > span:not(.ars-to-cny-processed)' ]; const priceElements = node.querySelectorAll ? node.querySelectorAll(priceSelectors.join(', ')) : []; if (priceElements.length > 0) { shouldConvert = true; } // 检查元素本身是否是价格元素 if (node.matches && node.matches(priceSelectors.join(', '))) { shouldConvert = true; } } }); } }); if (shouldConvert && !isProcessing) { // 使用防抖,避免频繁处理 clearTimeout(window.arsToCnyTimeout); window.arsToCnyTimeout = setTimeout(() => { convertPageARSValues(); }, 500); } }); observer.observe(document.body, { childList: true, subtree: true }); } // 页面加载完成后初始化 if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', init); } else { init(); } })();