您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
根据市场数据计算代币价值并高亮最佳选项
// ==UserScript== // @name 代币价值计算 // @namespace http://tampermonkey.net/ // @version 0.1.2 // @description 根据市场数据计算代币价值并高亮最佳选项 // @author BigWatermelon // @match https://www.milkywayidle.com/* // @match https://test.milkywayidle.com/* // @icon https://www.google.com/s2/favicons?sz=64&domain=milkywayidle.com // @grant GM_addStyle // @grant GM_xmlhttpRequest // @license MIT // ==/UserScript== (function() { 'use strict'; GM_addStyle(` #tokensPricePage { width: 100%; padding: 8px 15px; box-sizing: border-box; } .remark { color: #38e3ed; padding: 8px; border: 1px solid #4357af; box-shadow: 0 0 10px rgba(76, 175, 80, 0.5); background-color: rgba(76, 175, 80, 0.1); transform: scale(1.02); } .title { text-align: left; } .updateTime { margin-top: 5px; } /* 分类标签样式 */ .category-tabs { display: flex; margin: 10px 0; gap: 5px; } .category-tab { padding: 5px 10px; background: #2c3e50; color: white; border-radius: 4px; cursor: pointer; font-size: 14px; } .category-tab.active { background: #2196F3; font-weight: bold; } .flexStart { display: flex; justify-content: flex-start; align-items: flex-start; flex-wrap: wrap; gap: 10px; } .itemBox { width: 153px; padding: 5px; border: 1px solid #4357af; border-radius: 4px; transition: all 0.3s ease; position: relative; } .imgBox { display: flex; justify-content: center; align-items: center; margin: 5px 0; height: 60px; } /* 高亮最佳选项的样式 */ .best-profit { border: 1px solid #4CAF50; box-shadow: 0 0 10px rgba(76, 175, 80, 0.5); background-color: rgba(76, 175, 80, 0.1); transform: scale(1.02); } .priceInput { width: 100%; text-align: center; margin-bottom: 5px; } .profit-value { font-size: 12px; margin-top: 3px; font-weight: bold; } .best-profit-marker { position: absolute; top: -8px; right: -8px; background: #4CAF50; color: white; border-radius: 50%; width: 20px; height: 20px; display: flex; align-items: center; justify-content: center; font-size: 12px; } .update-all-btn { background: #2196F3; color: white; border: none; border-radius: 4px; padding: 5px 10px; font-size: 14px; cursor: pointer; margin: 10px 0; } .update-all-btn:hover { background: #0b7dda; } `); const itemInfo = [ { id: 'griffin_leather', img: '/static/media/items_sprite.6d12eb9d.svg#griffin_leather', name: '狮鹫之皮', tokensNumber: 600, category: 'D1' }, { id: 'manticore_sting', img: '/static/media/items_sprite.6d12eb9d.svg#manticore_sting', name: '蝎狮之刺', tokensNumber: 1000, category: 'D1' }, { id: 'jackalope_antler', img: '/static/media/items_sprite.6d12eb9d.svg#jackalope_antler', name: '鹿角兔之角', tokensNumber: 1200, category: 'D1' }, { id: 'dodocamel_plume', img: '/static/media/items_sprite.6d12eb9d.svg#dodocamel_plume', name: '渡渡驼之翎', tokensNumber: 3000, category: 'D1' }, { id: 'griffin_talon', img: '/static/media/items_sprite.6d12eb9d.svg#griffin_talon', name: '狮鹫之爪', tokensNumber: 3000, category: 'D1' }, { id: 'acrobats_ribbon', img: '/static/media/items_sprite.6d12eb9d.svg#acrobats_ribbon', name: '杂技师彩带', tokensNumber: 2000, category: 'D2' }, { id: 'magicians_cloth', img: '/static/media/items_sprite.6d12eb9d.svg#magicians_cloth', name: '魔术师织物', tokensNumber: 2000, category: 'D2' }, { id: 'chaotic_chain', img: '/static/media/items_sprite.6d12eb9d.svg#chaotic_chain', name: '混沌锁链', tokensNumber: 3000, category: 'D2' }, { id: 'cursed_ball', img: '/static/media/items_sprite.6d12eb9d.svg#cursed_ball', name: '诅咒之球', tokensNumber: 3000, category: 'D2' }, { id: 'royal_cloth', img: '/static/media/items_sprite.6d12eb9d.svg#royal_cloth', name: '皇家织物', tokensNumber: 2000, category: 'D3' }, { id: 'knights_ingot', img: '/static/media/items_sprite.6d12eb9d.svg#knights_ingot', name: '骑士之锭', tokensNumber: 2000, category: 'D3' }, { id: 'bishops_scroll', img: '/static/media/items_sprite.6d12eb9d.svg#bishops_scroll', name: '主教卷轴', tokensNumber: 2000, category: 'D3' }, { id: 'regal_jewel', img: '/static/media/items_sprite.6d12eb9d.svg#regal_jewel', name: '君王宝石', tokensNumber: 3000, category: 'D3' }, { id: 'sundering_jewel', img: '/static/media/items_sprite.6d12eb9d.svg#sundering_jewel', name: '裂空宝石', tokensNumber: 3000, category: 'D3' }, { id: 'marksman_brooch', img: '/static/media/items_sprite.6d12eb9d.svg#marksman_brooch', name: '神射胸针', tokensNumber: 2000, category: 'D4' }, { id: 'corsair_crest', img: '/static/media/items_sprite.6d12eb9d.svg#corsair_crest', name: '掠夺者徽章', tokensNumber: 2000, category: 'D4' }, { id: 'damaged_anchor', img: '/static/media/items_sprite.6d12eb9d.svg#damaged_anchor', name: '破损船锚', tokensNumber: 2000, category: 'D4' }, { id: 'maelstrom_plating', img: '/static/media/items_sprite.6d12eb9d.svg#maelstrom_plating', name: '怒涛甲片', tokensNumber: 2000, category: 'D4' }, { id: 'kraken_leather', img: '/static/media/items_sprite.6d12eb9d.svg#kraken_leather', name: '克拉肯皮革', tokensNumber: 2000, category: 'D4' }, { id: 'kraken_fang', img: '/static/media/items_sprite.6d12eb9d.svg#kraken_fang', name: '克拉肯之牙', tokensNumber: 3000, category: 'D4' }, ]; // 当前选中的分类 let currentCategory = 'all'; // 计算单币价值 const calculateProfit = (marketPrice, tokensNumber) => { return ((marketPrice * 0.98) / tokensNumber * 1000000).toFixed(2); }; // 手动更新所有单币价值并高亮最佳 const manualUpdateProfits = () => { itemInfo.forEach((item, index) => { const input = document.querySelector(`#tokensPricePage .itemBox[data-id="${item.id}"] .priceInput`); if (input) { const newPrice = parseFloat(input.value); if (!isNaN(newPrice)) { item.marketPrice = newPrice; item.profit = calculateProfit(item.marketPrice, item.tokensNumber); // 更新单币价值显示 const profitDisplay = document.querySelector(`#tokensPricePage .itemBox[data-id="${item.id}"] .profit-value`); if (profitDisplay) { profitDisplay.textContent = `单币价值: ${item.profit}`; } } } }); // 重新计算最佳单币价值 highlightBestProfitItem(); }; // 高亮单币价值最大的物品 const highlightBestProfitItem = () => { // 获取当前可见的物品 const visibleItems = currentCategory === 'all' ? itemInfo : itemInfo.filter(item => item.category === currentCategory); // 移除之前的高亮 document.querySelectorAll('.itemBox').forEach(box => { box.classList.remove('best-profit'); const marker = box.querySelector('.best-profit-marker'); if (marker) marker.remove(); }); // 找出单币价值最大的物品 const validItems = visibleItems.filter(item => item.profit !== undefined); if (validItems.length === 0) return; const maxProfit = Math.max(...validItems.map(item => parseFloat(item.profit))); const bestItems = validItems.filter(item => parseFloat(item.profit) === maxProfit); // 为每个最佳单币价值物品添加高亮 bestItems.forEach(bestItem => { const itemBox = document.querySelector(`#tokensPricePage .itemBox[data-id="${bestItem.id}"]`); if (itemBox) { itemBox.classList.add('best-profit'); // 添加最佳标记 const marker = document.createElement('div'); marker.className = 'best-profit-marker'; marker.textContent = '买'; itemBox.appendChild(marker); } }); }; // 处理id 匹配github接口字段 const formatItemName = (id) => { return id .split('_') .map(word => { if (word.endsWith('s') && word.length > 1) { const base = word.slice(0, -1); return base.charAt(0).toUpperCase() + base.slice(1) + "'s"; } return word.charAt(0).toUpperCase() + word.slice(1); }) .join(' '); } // 获取物品价格的函数 const fetchItemPrices = async () => { const gitHubResponse = await new Promise((resolve, reject) => { GM_xmlhttpRequest({ method: 'GET', url: 'https://ghproxy.net/https://raw.githubusercontent.com/holychikenz/MWIApi/main/milkyapi.json', responseType: 'json', onload: resolve, onerror: reject }); }); if (gitHubResponse.status === 200) { const gitHubData = JSON.parse(gitHubResponse.responseText); const marketData = gitHubData.market; // Update timestamp display const gitHubTimestamp = gitHubData.time * 1000; const gitHubDate = new Date(gitHubTimestamp); const formattedTime = gitHubDate.toLocaleString(); const timeDisplay = document.querySelector(".updateTime"); if (timeDisplay) { timeDisplay.textContent = `(GitHub)更新时间: ${formattedTime}`; } itemInfo.forEach(item => { const gitHubKey = formatItemName(item.id); if (marketData[gitHubKey] && marketData[gitHubKey].bid) { item.marketPrice = (marketData[gitHubKey].bid / 1000000).toFixed(2); item.profit = calculateProfit(item.marketPrice, item.tokensNumber); } }); updatePriceInputs(); highlightBestProfitItem(); return; } else { try { const response = await new Promise((resolve, reject) => { GM_xmlhttpRequest({ method: 'GET', url: 'https://www.milkywayidle.com/game_data/marketplace.json', onload: resolve, onerror: reject }); }); const pricesData = JSON.parse(response.responseText); const marketData = pricesData.marketData; const timestampInMilliseconds = pricesData.timestamp * 1000; const date = new Date(timestampInMilliseconds); const formattedTime = date.toLocaleString(); const timeDisplay = document.querySelector(".updateTime"); if (timeDisplay) { timeDisplay.textContent = `(官方)更新时间: ${formattedTime}`; } itemInfo.forEach(item => { const marketKey = `/items/${item.id}`; if (marketData[marketKey] && marketData[marketKey]["0"]) { item.marketPrice = (marketData[marketKey]["0"].b / 1000000).toFixed(2); item.profit = calculateProfit(item.marketPrice, item.tokensNumber); } }); updatePriceInputs(); highlightBestProfitItem(); } catch (error) { console.error('获取价格失败:', error); const timeDisplay = document.querySelector(".updateTime"); if (timeDisplay) { timeDisplay.textContent = `数据获取失败,请手动输入价格`; } itemInfo.forEach(item => { item.marketPrice = 0; item.profit = 0; }); } } }; // 更新输入框中的价格显示 const updatePriceInputs = () => { const container = document.querySelector('#tokensPricePage .flexStart'); if (!container) return; // 清空容器 container.innerHTML = ''; // 筛选当前分类的物品 const filteredItems = currentCategory === 'all' ? itemInfo : itemInfo.filter(item => item.category === currentCategory); // 添加物品 filteredItems.forEach(item => { const itemBox = document.createElement('div'); itemBox.className = 'itemBox'; itemBox.dataset.id = item.id; itemBox.innerHTML = ` <div class="ShopPanel_name__3vA-H">${item.name}</div> <div class="imgBox"> <svg role="img" aria-label="Icon" class="Icon_icon__2LtL_ Icon_large__1H9Z5" width="100%" height="100%"> <use href="${item.img}"></use> </svg> </div> <div class="ShopPanel_costs__XffBM"> <input type="number" class="priceInput" value="${item.marketPrice || 0}" step="0.1"> <div class="profit-value">单币价值: ${item.profit || 0}</div> </div> `; container.appendChild(itemBox); }); }; // 创建分类标签 const createCategoryTabs = () => { const tabs = document.createElement('div'); tabs.className = 'category-tabs'; const categories = [ { id: 'all', name: '全部' }, { id: 'D1', name: 'D1' }, { id: 'D2', name: 'D2' }, { id: 'D3', name: 'D3' }, { id: 'D4', name: 'D4' } ]; categories.forEach(cat => { const tab = document.createElement('div'); tab.className = `category-tab ${currentCategory === cat.id ? 'active' : ''}`; tab.textContent = cat.name; tab.dataset.category = cat.id; tab.addEventListener('click', () => { currentCategory = cat.id; document.querySelectorAll('.category-tab').forEach(t => t.classList.remove('active') ); tab.classList.add('active'); updatePriceInputs(); highlightBestProfitItem(); }); tabs.appendChild(tab); }); return tabs; }; const tabsAdd = () => { const muiTabsButtons = document.querySelector('.CharacterManagement_tabsComponentContainer__3oI5G .MuiTabs-flexContainer'); const newTabButton = document.createElement('button'); newTabButton.className = 'MuiButtonBase-root MuiTab-root MuiTab-textColorPrimary css-1q2h7u5'; newTabButton.innerHTML = `<span class="MuiBadge-root TabsComponent_badge__1Du26 css-1rzb3uu" id="tokensPriceButton">代币价值<span class="MuiBadge-badge MuiBadge-standard MuiBadge-invisible MuiBadge-anchorOriginTopRight MuiBadge-anchorOriginTopRightRectangular MuiBadge-overlapRectangular MuiBadge-colorWarning css-dpce5z"></span></span><span class="MuiTouchRipple-root css-w0pj6f"></span>`; muiTabsButtons.appendChild(newTabButton); const muiTabsPages = document.querySelector('.CharacterManagement_tabsComponentContainer__3oI5G .TabsComponent_tabPanelsContainer__26mzo'); const newTabPages = document.createElement('div'); newTabPages.className = 'TabPanel_tabPanel__tXMJF TabPanel_hidden__26UM3'; newTabPages.innerHTML = ` <div id="tokensPricePage"> <div class="remark"> <div class="title">代币价值以百万(M)为单位,下方单币价值数字越高越好,自动获取的价格为市场右边的收购价</div> <div class="updateTime">更新时间: 正在获取中……</div> </div> <button class="update-all-btn">重新计算</button> <div class="flexStart"></div> </div>`; // 在flexStart前插入分类标签 const flexStart = newTabPages.querySelector('.flexStart'); flexStart.parentNode.insertBefore(createCategoryTabs(), flexStart); muiTabsPages.appendChild(newTabPages); // 添加全局更新按钮事件 const updateAllBtn = newTabPages.querySelector('.update-all-btn'); updateAllBtn.addEventListener('click', manualUpdateProfits); const allTabButtons = muiTabsButtons.querySelectorAll('.MuiButtonBase-root'); const allTabPanels = muiTabsPages.querySelectorAll('.TabPanel_tabPanel__tXMJF'); allTabButtons.forEach((button, index) => { button.addEventListener('click', () => { allTabPanels.forEach(panel => panel.classList.add('TabPanel_hidden__26UM3')); allTabButtons.forEach(btn => btn.classList.remove('Mui-selected')); button.classList.add('Mui-selected'); if (allTabPanels[index]) { allTabPanels[index].classList.remove('TabPanel_hidden__26UM3'); if (button === newTabButton) { fetchItemPrices(); } } }); }); // 初始加载数据 fetchItemPrices(); }; const observeDOM = () => { const observer = new MutationObserver((mutations, obs) => { const muiTabs = document.querySelector('.CharacterManagement_tabsComponentContainer__3oI5G .MuiTabs-flexContainer'); if (muiTabs) { tabsAdd(); obs.disconnect(); } }); observer.observe(document.body, { childList: true, subtree: true }); }; const __Main = () => { observeDOM(); }; __Main(); })();
QingJ © 2025
镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址