您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Greasy Fork is available in English.
仓库物品收藏管理和快速切换角色||Added a favorite button to the item menu and 4 characters buttons to the main page.
// ==UserScript== // @name [银河奶牛]仓库物品收藏和快速切换角色 // @name:en MWI Item Favorites Manager && Quickly Switch Characters // @namespace http://tampermonkey.net/ // @version test0.23 // @description 仓库物品收藏管理和快速切换角色||Added a favorite button to the item menu and 4 characters buttons to the main page. // @description:en Added a favorite button to the item menu and 4 characters buttons to the main page. // @icon https://www.milkywayidle.com/favicon.svg // @author Meoling // @license MIT // @match https://www.milkywayidle.com/* // @match https://test.milkywayidle.com/* // @grant GM_getValue // @grant GM_setValue // ==/UserScript== (function() { 'use strict'; // 获取当前角色名 function getCharacterName() { const headerInfo = document.querySelector('.Header_info__26fkk'); if (!headerInfo) return null; const nameElement = headerInfo.querySelector('.CharacterName_name__1amXp'); return nameElement ? nameElement.textContent.trim() : null; } // 保存收藏物品到本地存储 function saveFavoritesToLocalStorage(itemName, categoryName) { const characterName = getCharacterName(); if (!characterName) return; const storageKey = `mw_favorites_${characterName}`; const favorites = loadFavoritesFromLocalStorage(); // 检查是否已存在相同物品 const existingIndex = favorites.findIndex(item => item.name === itemName); if (existingIndex === -1) { favorites.push({name: itemName, category: categoryName}); localStorage.setItem(storageKey, JSON.stringify(favorites)); } } // 从本地存储加载收藏物品 function loadFavoritesFromLocalStorage() { const characterName = getCharacterName(); if (!characterName) return []; const storageKey = `mw_favorites_${characterName}`; return JSON.parse(localStorage.getItem(storageKey)) || []; } // 创建仓库收藏分类 function addFavoritesCategory() { // 查找仓库的所有分类容器 const firstContainer = document.querySelector('.Inventory_items__6SXv0'); const inventoryContainers = firstContainer.querySelectorAll(':scope > div'); if (inventoryContainers && inventoryContainers.length > 0) { const existingFavorites = firstContainer.querySelector('#favorites-category'); if (existingFavorites) { return; } // 创建新的收藏分类 const favoritesContainer = document.createElement('div'); // 复制现有分类的结构 const itemGridHTML = ` <div class="Inventory_itemGrid__20YAH"> <div class="Inventory_label__XEOAx"> <span class="Inventory_categoryButton__35s1x">收藏</span> </div> <!-- 这里将来会添加收藏的物品 --> </div> `; favoritesContainer.innerHTML = itemGridHTML; favoritesContainer.id = 'favorites-category'; // 将收藏分类添加到仓库的最前面 if (firstContainer) { firstContainer.insertBefore(favoritesContainer, firstContainer.firstChild); //console.log('收藏分类已添加'); } } } // 添加仓库收藏按钮 function addFavoriteButton(menuContainer) { // 检查是否已存在收藏按钮 const existingButton = menuContainer.querySelector('.favorite-button'); if (existingButton) { return; } const favoriteButton = document.createElement('button'); favoriteButton.className = 'Button_button__1Fe9z Button_fullWidth__17pVU favorite-button'; favoriteButton.textContent = '收藏/取消收藏'; // 添加点击事件 favoriteButton.addEventListener('click', function() { // 获取当前物品名称 const itemName = menuContainer.querySelector('.Item_name__2C42x').textContent.trim(); const characterName = getCharacterName(); if (!characterName) return; const favorites = loadFavoritesFromLocalStorage(); const itemIndex = favorites.findIndex(item => item.name === itemName); const isFavorite = itemIndex !== -1; if (isFavorite) { const itemCategory = favorites[itemIndex].category; favorites.splice(itemIndex, 1); localStorage.setItem(`mw_favorites_${characterName}`, JSON.stringify(favorites)); const favoritesGrid = document.querySelector('#favorites-category .Inventory_itemGrid__20YAH'); const existingItem = favoritesGrid.querySelector(`svg[aria-label="${itemName}"]`); if (existingItem) { const inventoryItem = document.querySelector(`.Inventory_items__6SXv0 .Item_itemContainer__x7kH1 svg[aria-label="${itemName}"]`); if (!inventoryItem) { console.log('未在仓库中找到该物品'); return; } const itemContainer = inventoryItem.closest('.Item_itemContainer__x7kH1'); if (!itemContainer) { console.log('无法获取物品容器'); return; } const categorySpan = [...document.querySelectorAll('.Inventory_categoryButton__35s1x')] .find(span => span.textContent.trim() === itemCategory); if (categorySpan) { const categoryGrid = categorySpan.closest('.Inventory_itemGrid__20YAH'); if (categoryGrid) { categoryGrid.appendChild(itemContainer); } } refresh(); //existingItem.closest('.Item_itemContainer__x7kH1').remove(); } } else { const inventoryItem = document.querySelector(`.Inventory_items__6SXv0 .Item_itemContainer__x7kH1 svg[aria-label="${itemName}"]`); if (!inventoryItem) { console.log('未在仓库中找到该物品'); return; } const itemContainer = inventoryItem.closest('.Item_itemContainer__x7kH1'); if (!itemContainer) { console.log('无法获取物品容器'); return; } const categoryGrid = itemContainer.closest('.Inventory_itemGrid__20YAH'); const categoryName = categoryGrid ? categoryGrid.querySelector('.Inventory_categoryButton__35s1x')?.textContent.trim() : '未知分类'; saveFavoritesToLocalStorage(itemName, categoryName); const favoritesGrid = document.querySelector('#favorites-category .Inventory_itemGrid__20YAH'); if (!favoritesGrid) { console.log('未找到收藏分类'); return; } const existingItem = favoritesGrid.querySelector(`svg[aria-label="${itemName}"]`); if (!existingItem) { favoritesGrid.appendChild(itemContainer); } } }); menuContainer.appendChild(favoriteButton); } // 添加市场的分类容器(未完成) function addMarketFavoritesCategory() { } // 刷新函数,当DOM变化时调用 function refresh() { try { // 仓库收藏功能 const inventoryContainer = document.querySelector('.Inventory_items__6SXv0'); if (inventoryContainer) { addFavoritesCategory(); const favorites = loadFavoritesFromLocalStorage(); const favoritesGrid = document.querySelector('#favorites-category .Inventory_itemGrid__20YAH'); if (favoritesGrid) { favorites.forEach(item => { const inventoryItem = document.querySelector(`.Inventory_items__6SXv0 .Item_itemContainer__x7kH1 svg[aria-label="${item.name}"]`); if (inventoryItem) { const itemContainer = inventoryItem.closest('.Item_itemContainer__x7kH1'); const existingItem = favoritesGrid.querySelector(`svg[aria-label="${item.name}"]`); if (!existingItem && itemContainer) { favoritesGrid.appendChild(itemContainer); } } }); } } // 检查是否出现物品菜单 const itemMenu = document.querySelector('.Item_actionMenu__2yUcG'); if (itemMenu) { addFavoriteButton(itemMenu); } //市场物品的收藏(未完成) // 角色选择页面检测 - 添加防抖 if (isCharacterSelectPage()) { if (!window.mwCharacterDetected) { window.mwCharacterDetected = true; detectAndSaveCharacters(); } } else { window.mwCharacterDetected = false; // 非角色选择页面,创建快速切换按钮 - 添加防抖 if (!document.querySelector('#character-switch-container')) { createCharacterSwitchButtons(); } } } catch (error) { console.log('刷新函数出错:', error); } } // 设置MutationObserver监听DOM变化 const config = { attributes: true, childList: true, subtree: true }; const observer = new MutationObserver(function (mutationsList, observer) { refresh(); }); observer.observe(document, config); // 页面加载完成后执行一次 if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', refresh); } else { refresh(); } // ===== 快速切换角色功能 ===== // 获取服务器类型 function getServerType() { return window.location.hostname.includes('test') ? 'test' : 'main'; } // 检查是否在角色选择页面 function isCharacterSelectPage() { return window.location.pathname.includes('/characterSelect'); } // 检测并保存角色信息 function detectAndSaveCharacters() { const serverType = getServerType(); const storageKey = `mw_characters_${serverType}`; setTimeout(() => { try { const characterElements = document.querySelectorAll('.MuiTypography-root'); const gameModeElements = document.querySelectorAll('.CharacterSelectPage_gameMode__R2el7'); const characters = []; let characterIndex = 0; characterElements.forEach((element) => { try { if (element.tagName !== 'A') return; const link = element.href; if (!link || !link.includes('characterId=')) return; const characterNameElement = element.querySelector('.CharacterName_characterName__2FqyZ'); if (!characterNameElement) return; const characterName = characterNameElement.textContent.trim(); // 获取角色模式 let mode = ''; if (gameModeElements[characterIndex]) { const modeText = gameModeElements[characterIndex].textContent.trim(); if (modeText === '标准' || modeText === 'Standard') { mode = '标准'; } else if (modeText === '铁牛' || modeText === 'Ironcow') { mode = '铁牛'; } } const displayText = mode ? `${mode}(${characterName})` : characterName; characters.push({ name: characterName, mode: mode, link: link, displayText: displayText }); characterIndex++; } catch (error) { console.log('处理单个角色信息时出错:', error); } }); if (characters.length > 0) { localStorage.setItem(storageKey, JSON.stringify(characters)); console.log(`已保存${characters.length}个角色信息到${serverType}服`); } } catch (error) { console.log('检测角色信息时出错:', error); } }, 2000); } // 从本地存储加载角色信息 function loadCharactersFromStorage() { const serverType = getServerType(); const storageKey = `mw_characters_${serverType}`; const storedData = localStorage.getItem(storageKey); return storedData ? JSON.parse(storedData) : []; } // 创建快速切换角色按钮 function createCharacterSwitchButtons() { const existingContainer = document.querySelector('#character-switch-container'); if (existingContainer) existingContainer.remove(); const characters = loadCharactersFromStorage(); let isCollapsed = false; // 主容器 const mainContainer = document.createElement('div'); mainContainer.id = 'character-switch-container'; Object.assign(mainContainer.style, { position: 'fixed', top: '10px', left: '73%', transform: 'translateX(-50%)', zIndex: '9999', display: 'flex', flexDirection: 'column', alignItems: 'center' }); // 折叠按钮 const toggleButton = document.createElement('button'); toggleButton.textContent = '▼'; toggleButton.title = characters.length > 0 ? '收起角色切换' : '收起角色选择'; Object.assign(toggleButton.style, { padding: '2px 8px', backgroundColor: 'rgba(48, 63, 159, 0.3)', color: 'rgba(255, 255, 255, 0.9)', border: '1px solid rgba(255, 255, 255, 0.2)', borderRadius: '3px', fontSize: '12px', cursor: 'pointer', backdropFilter: 'blur(2px)', boxShadow: '0 1px 3px rgba(0,0,0,0.1)', minWidth: '24px', height: '20px', marginBottom: '5px' }); // 按钮容器 const buttonContainer = document.createElement('div'); Object.assign(buttonContainer.style, { display: 'flex', gap: '10px', flexWrap: 'wrap', maxWidth: '500px', justifyContent: 'center' }); // 通用按钮样式 const buttonStyle = { padding: '4px 8px', backgroundColor: 'rgba(48, 63, 159, 0.3)', color: 'rgba(255, 255, 255, 0.9)', border: '1px solid rgba(255, 255, 255, 0.2)', borderRadius: '3px', fontSize: '12px', backdropFilter: 'blur(2px)', boxShadow: '0 1px 3px rgba(0,0,0,0.1)', textDecoration: 'none', cursor: 'pointer', whiteSpace: 'nowrap', maxWidth: '120px', overflow: 'hidden', textOverflow: 'ellipsis' }; const hoverStyle = { backgroundColor: 'rgba(26, 35, 126, 0.5)', boxShadow: '0 2px 5px rgba(0,0,0,0.2)' }; // 如果没有角色数据,创建一个跳转到角色选择界面的按钮 if (characters.length === 0) { const characterSelectButton = document.createElement('a'); characterSelectButton.textContent = '获取角色数据'; // 构建角色选择页面的URL const currentOrigin = window.location.origin; characterSelectButton.href = `${currentOrigin}/characterSelect`; characterSelectButton.title = '前往角色选择页面获取角色信息'; Object.assign(characterSelectButton.style, buttonStyle); characterSelectButton.addEventListener('mouseover', () => Object.assign(characterSelectButton.style, hoverStyle)); characterSelectButton.addEventListener('mouseout', () => Object.assign(characterSelectButton.style, buttonStyle)); buttonContainer.appendChild(characterSelectButton); } else { // 有角色数据时,创建角色按钮 characters.forEach((character) => { const button = document.createElement('a'); button.textContent = character.displayText; button.href = character.link; button.title = `切换到: ${character.displayText}`; Object.assign(button.style, buttonStyle); button.addEventListener('mouseover', () => Object.assign(button.style, hoverStyle)); button.addEventListener('mouseout', () => Object.assign(button.style, buttonStyle)); buttonContainer.appendChild(button); }); } // 折叠按钮事件 toggleButton.addEventListener('click', () => { isCollapsed = !isCollapsed; buttonContainer.style.display = isCollapsed ? 'none' : 'flex'; toggleButton.textContent = isCollapsed ? '▲' : '▼'; if (characters.length > 0) { toggleButton.title = isCollapsed ? '展开角色切换' : '收起角色切换'; } else { toggleButton.title = isCollapsed ? '展开角色选择' : '收起角色选择'; } }); toggleButton.addEventListener('mouseover', () => Object.assign(toggleButton.style, hoverStyle)); toggleButton.addEventListener('mouseout', () => Object.assign(toggleButton.style, buttonStyle)); mainContainer.appendChild(toggleButton); mainContainer.appendChild(buttonContainer); document.body.appendChild(mainContainer); } })();