// text-processor.js import axios from 'axios' import { delayPerform } from 'js-perform-lock' const WindowsTranslateApi = 'https://jiasm.zfire.top/translate' // 数据过滤校验 function isNumberRegex(str) { const regexPatterns = [ /^\d+$/, // 纯数字 /^\d*\.\d+$/, // 浮点数 /^([01]\d|2[0-3]):([0-5]\d)$/, // 时间 (HH:MM) /^([01]\d|2[0-3]):([0-5]\d):([0-5]\d)$/, // 时间 (HH:MM:SS) /^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}$/, // 完整时间戳 /^[A-Za-z]+$/, // 纯字母 /^(?=.*[A-Za-z])(?=.*\d)[A-Za-z\d]+$/, // 字母和数字 /^(?=.*[A-Za-z])(?=.*[\p{P}\p{S}])[\p{L}\p{P}\p{S}]+$/u, // 字母和标点符号 /^(?=.*\d)(?=.*[\p{P}\p{S}])[\d\p{P}\p{S}]+$/u, // 数字和标点符号 /^[\p{P}\s\dA-Za-z]+$/u // 字母、数字和标点符号 ] return regexPatterns.some(pattern => pattern.test(str)) || !!window.Vue_Translation_Of_Text_Old_Data?.[str] } // 文本转译请求 function pushNewText(data) { return new Promise(function (resolve, reject) { axios .post(`${WindowsTranslateApi}/api/v1/common/translationOfText`, data) .then(response => { if (response.data.code === 0) { const obj = {} const obj2 = {} response.data.data.forEach(val => { obj[val[0]] = val[1] obj2[val[1]] = true }) window.Vue_Translation_Of_Text_Old_Data = { ...(window.Vue_Translation_Of_Text_Old_Data || {}), ...obj2 } window.Vue_Translation_Of_Text_Data = { ...(window.Vue_Translation_Of_Text_Data || {}), ...obj } resolve(obj) } else { reject(new Error('API returned non-zero code')) } }) .catch(reject) }) } // 延迟替换处理器 const deferredReplacement = (function () { const allKeywords = [] const keywords = [] const callbacks = [] let keywordIndex = 0 let callbackIndex = 0 const delayProcessor = new delayPerform(250).refactor(function () { const currentKeywords = keywords.splice(0, keywordIndex) const currentCallbacks = callbacks.splice(0, callbackIndex) keywordIndex -= currentKeywords.length callbackIndex -= currentCallbacks.length if (currentKeywords.length > 0) { pushNewText({ keywords: currentKeywords, targetLanguage: window?.Vue_Translation_Of_Text_Type }).then(() => { currentCallbacks.forEach(cb => cb?.()) }).catch(error => { console.error('Translation failed:', error) currentCallbacks.forEach(cb => cb?.()) }) } else if (currentCallbacks.length > 0) { setTimeout(() => { currentCallbacks.forEach(cb => cb?.()) }, 250) } }) return function (text, callback) { delayProcessor() if (!allKeywords.includes(text)) { keywordIndex++ allKeywords.push(text) keywords.push(text) } callbackIndex++ callbacks.push(callback) } })() // DOM 处理器 export const domProcessor = { // 处理文本节点 processTextNode(node) { const text = node.textContent?.trim() if (!text || isNumberRegex(text)) return try { if (window.Vue_Translation_Of_Text_Data?.[text]) { node.textContent = window.Vue_Translation_Of_Text_Data[text] } else { deferredReplacement(text, () => { if (window.Vue_Translation_Of_Text_Data?.[text]) { node.textContent = window.Vue_Translation_Of_Text_Data[text] } }) } } catch (error) { console.error('Text processing error:', error) } }, // 处理输入框 placeholder processInputPlaceholder(element) { const placeholder = element.getAttribute('placeholder')?.trim() if (!placeholder || isNumberRegex(placeholder)) return try { if (window.Vue_Translation_Of_Text_Data?.[placeholder]) { element.setAttribute('placeholder', window.Vue_Translation_Of_Text_Data[placeholder]) } else { deferredReplacement(placeholder, () => { if (window.Vue_Translation_Of_Text_Data?.[placeholder]) { element.setAttribute('placeholder', window.Vue_Translation_Of_Text_Data[placeholder]) } }) } } catch (error) { console.error('Placeholder processing error:', error) } }, // 处理输入框值 processInputValue(element) { const value = element.value?.trim() if (!value || isNumberRegex(value)) return try { if (window.Vue_Translation_Of_Text_Data?.[value]) { element.value = window.Vue_Translation_Of_Text_Data[value] } else { deferredReplacement(value, () => { if (window.Vue_Translation_Of_Text_Data?.[value]) { element.value = window.Vue_Translation_Of_Text_Data[value] } }) } } catch (error) { console.error('Input value processing error:', error) } }, // 处理属性文本 processAttributeText(element, attributeName) { const value = element.getAttribute(attributeName)?.trim() if (!value || isNumberRegex(value)) return try { if (window.Vue_Translation_Of_Text_Data?.[value]) { element.setAttribute(attributeName, window.Vue_Translation_Of_Text_Data[value]) } else { deferredReplacement(value, () => { if (window.Vue_Translation_Of_Text_Data?.[value]) { element.setAttribute(attributeName, window.Vue_Translation_Of_Text_Data[value]) } }) } } catch (error) { console.error(`Attribute ${attributeName} processing error:`, error) } }, // 递归处理 DOM 元素 processElement(element) { if (element && element.nodeType === Node.ELEMENT_NODE) { // 跳过 table 中的 td 元素 // if (element.nodeName.toLowerCase() === 'td') { // return // } // 处理输入框和文本域 if (['INPUT', 'TEXTAREA', 'SELECT'].includes(element.nodeName)) { this.processInputPlaceholder(element) if (element.nodeName === 'INPUT' || element.nodeName === 'TEXTAREA') { this.processInputValue(element) } } // 处理 Ant Design 组件属性 this.processAttributeText(element, 'title') this.processAttributeText(element, 'aria-label') this.processAttributeText(element, 'alt') // 处理子节点 Array.from(element.childNodes).forEach(child => { if (child.nodeType === Node.TEXT_NODE) { this.processTextNode(child) } else { this.processElement(child) } }) } }, // 处理特定选择器元素 processSelector(selector) { Array.from(document.querySelectorAll(selector)).forEach(element => { this.processElement(element) }) }, // 处理标签名元素 processTagName(tagName) { Array.from(document.getElementsByTagName(tagName)).forEach(element => { this.processElement(element) }) } }