您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
在m-team.cc网站根据颜色添加用户头衔
// ==UserScript== // @name M-team 色盲辅助 // @namespace http://tampermonkey.net/ // @version 1.2 // @description 在m-team.cc网站根据颜色添加用户头衔 // @author You // @match https://m-team.cc/* // @match https://*.m-team.cc/* // @grant none // @license MIT // @run-at document-end // ==/UserScript== (function() { 'use strict'; // 颜色和对应标签的配置字典 const COLOR_LABELS = { 'rgb(51, 51, 51)': '[小卒1]', 'rgb(218, 165, 32)': '[捕頭2]', 'rgb(0, 139, 139)': '[知縣3]', 'rgb(0, 191, 255)': '[通判4]', 'rgb(139, 0, 139)': '[知州5]', 'rgb(72, 61, 139)': '[府丞6]', 'rgb(255, 140, 0)': '[府尹7]', 'rgb(0, 100, 0)': '[總督8]', 'rgb(236, 56, 78)': '[大臣9]', 'rgb(0, 159, 0)': '[VIP]', 'rgb(220, 20, 60)': '[職人]', 'rgb(28, 198, 213)': '[巡查]', 'rgb(100, 149, 237)': '[總版]', 'rgb(75, 0, 130)': '[總管]', 'rgb(160, 82, 45)': '[維護開發員]', 'rgb(139, 0, 0)': '[站長]', 'rgb(156, 67, 67)': '[候選管理]', 'rgb(88, 55, 55)': '[波菜管理]', }; // 处理单个span元素 function processSpan(span) { const computedStyle = window.getComputedStyle(span); const color = computedStyle.color; // 检查颜色是否在配置中 if (COLOR_LABELS.hasOwnProperty(color)) { // 检查是否仅包含一个strong子元素 const strongElements = span.querySelectorAll('strong'); if (strongElements.length === 1 && span.children.length === 1) { const strong = strongElements[0]; const label = COLOR_LABELS[color]; // 检查是否已经添加过标签,避免重复添加 if (!strong.textContent.includes(label)) { strong.textContent += label; } // 保存原始用户名和等级信息到span的data属性中,供tooltip使用 if (!span.dataset.originalUsername) { span.dataset.originalUsername = strong.textContent.replace(label, ''); span.dataset.userLevel = label; } } } } // 处理tooltip元素 function processTooltip(tooltip) { // 查找tooltip中的文本内容 const textNodes = []; const walker = document.createTreeWalker( tooltip, NodeFilter.SHOW_TEXT, null, false ); let node; while (node = walker.nextNode()) { if (node.textContent.trim()) { textNodes.push(node); } } // 遍历所有用户等级,看tooltip文本是否包含用户名 for (const [color, label] of Object.entries(COLOR_LABELS)) { // 查找页面上对应颜色的span元素 const spans = document.querySelectorAll('span'); spans.forEach(span => { const computedStyle = window.getComputedStyle(span); if (computedStyle.color === color && span.dataset.originalUsername) { const username = span.dataset.originalUsername; const userLevel = span.dataset.userLevel; // 检查tooltip是否包含这个用户名 textNodes.forEach(textNode => { if (textNode.textContent.includes(username) && !textNode.textContent.includes(userLevel)) { // 在tooltip中添加等级信息 textNode.textContent = textNode.textContent.replace(username, username + userLevel); } }); } }); } } // 创建一个全局的用户名-等级映射 const usernameToLevel = new Map(); // 更新用户名映射 function updateUsernameMap() { const spans = document.querySelectorAll('span'); spans.forEach(span => { const computedStyle = window.getComputedStyle(span); const color = computedStyle.color; if (COLOR_LABELS.hasOwnProperty(color)) { const strongElements = span.querySelectorAll('strong'); if (strongElements.length === 1 && span.children.length === 1) { const strong = strongElements[0]; const label = COLOR_LABELS[color]; const username = strong.textContent.replace(label, ''); if (username && !usernameToLevel.has(username)) { usernameToLevel.set(username, label); } } } }); } // 转义正则表达式特殊字符 function escapeRegExp(string) { return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); } // 处理tooltip的新方法 - 使用全局映射 function processTooltipWithMapping(tooltip) { if (!tooltip || tooltip.dataset.processed) return; // 标记已处理,避免重复处理 tooltip.dataset.processed = 'true'; // 延迟处理,确保tooltip内容完全加载 setTimeout(() => { const walker = document.createTreeWalker( tooltip, NodeFilter.SHOW_TEXT, null, false ); let node; while (node = walker.nextNode()) { if (node.textContent && node.textContent.trim()) { let text = node.textContent; let modified = false; // 检查所有已知用户名 for (const [username, level] of usernameToLevel) { if (text.includes(username) && !text.includes(level)) { // 转义用户名中的特殊字符,避免正则表达式错误 const escapedUsername = escapeRegExp(username); text = text.replace(new RegExp(escapedUsername, 'g'), username + level); modified = true; } } if (modified) { node.textContent = text; } } } }, 50); } // 处理所有符合条件的span元素和tooltip function processAllElements() { // 处理用户名span元素 const spans = document.querySelectorAll('span'); spans.forEach(processSpan); // 更新用户名映射 updateUsernameMap(); // 处理已存在的tooltip元素 const tooltipSelectors = [ '[role="tooltip"]', '.tooltip', '.ant-tooltip', '.rc-tooltip', '[aria-describedby]', '.tippy-content', '[data-tooltip]' ]; tooltipSelectors.forEach(selector => { const tooltips = document.querySelectorAll(selector); tooltips.forEach(processTooltipWithMapping); }); // 也处理可能是tooltip容器的div const possibleTooltips = document.querySelectorAll('div[style*="position: absolute"], div[style*="position: fixed"]'); possibleTooltips.forEach(tooltip => { // 简单检查是否可能是tooltip(包含用户名相关文本) if (tooltip.textContent && tooltip.textContent.length < 200) { processTooltipWithMapping(tooltip); } }); } // 初始处理 processAllElements(); // 监听DOM变化,处理动态加载的内容 const observer = new MutationObserver(function(mutations) { let shouldProcess = false; let shouldProcessTooltip = false; mutations.forEach(function(mutation) { if (mutation.type === 'childList' && mutation.addedNodes.length > 0) { // 检查是否有新增的节点 for (let node of mutation.addedNodes) { if (node.nodeType === Node.ELEMENT_NODE) { // 如果新增的是span元素或包含这些元素 if (node.tagName === 'SPAN' || node.querySelector('span')) { shouldProcess = true; } // 检查是否是tooltip相关元素 if (node.hasAttribute('role') && node.getAttribute('role') === 'tooltip' || node.className && (node.className.includes('tooltip') || node.className.includes('ant-tooltip') || node.className.includes('rc-tooltip')) || node.hasAttribute('aria-describedby') || (node.style && (node.style.position === 'absolute' || node.style.position === 'fixed')) || node.querySelector('[role="tooltip"]') || node.querySelector('.tooltip, .ant-tooltip, .rc-tooltip, .tippy-content')) { shouldProcessTooltip = true; } } } } }); if (shouldProcess) { // 延迟处理用户名span setTimeout(processAllElements, 100); } if (shouldProcessTooltip) { // 立即处理tooltip,因为它们通常是临时的 setTimeout(() => { // 更新映射 updateUsernameMap(); // 处理新出现的tooltip const tooltipSelectors = [ '[role="tooltip"]:not([data-processed])', '.tooltip:not([data-processed])', '.ant-tooltip:not([data-processed])', '.rc-tooltip:not([data-processed])', '[aria-describedby]:not([data-processed])', '.tippy-content:not([data-processed])', '[data-tooltip]:not([data-processed])' ]; tooltipSelectors.forEach(selector => { const tooltips = document.querySelectorAll(selector); tooltips.forEach(processTooltipWithMapping); }); // 处理新的绝对定位元素 const newTooltips = document.querySelectorAll('div[style*="position: absolute"]:not([data-processed]), div[style*="position: fixed"]:not([data-processed])'); newTooltips.forEach(tooltip => { if (tooltip.textContent && tooltip.textContent.length < 200) { processTooltipWithMapping(tooltip); } }); }, 10); } }); // 开始观察 observer.observe(document.body, { childList: true, subtree: true }); console.log('M-team 颜色标签添加器已启动'); })();