您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Subscribe Market Item
// ==UserScript== // @name MWISubscribe // @namespace http://tampermonkey.net/ // @version 0.6 // @description Subscribe Market Item // @author Lhiok // @license MIT // @match https://www.milkywayidle.com/* // @match https://test.milkywayidle.com/* // @icon https://www.milkywayidle.com/favicon.svg // @supportURL https://github.com/Lhiok/MWIScript/ // @grant none // ==/UserScript== (function() { "use strict"; let mwi_common = null; let mwi_subscribe_items = []; const storage_key = "mwi_subscribe_items"; const subscribeItemsStorage = localStorage.getItem(storage_key); if (subscribeItemsStorage) { mwi_subscribe_items = JSON.parse(subscribeItemsStorage); } // https://gf.qytechs.cn/zh-CN/scripts/536205-%E9%93%B6%E6%B2%B3%E5%A5%B6%E7%89%9B-%E5%BA%B7%E5%BA%B7%E8%BF%90%E6%B0%94 const Tooltip = new class { root = null; tooltip = null; constructor() { this.init(); } applyOptions(elem, options) { if (typeof options === 'object') { Object.entries(options ?? {}).forEach(([key, value]) => { if (key === 'style' && typeof value === 'object') { Object.entries(value ?? {}).forEach(([k, v]) => { elem.style[k] = v; }); } else elem[key] = value; }); } else elem.className = options; } elem(tagName, options = null, child = null) { const elem = document.createElement(tagName); this.applyOptions(elem, options); if (typeof child === 'object') { if (Array.isArray(child)) child.forEach(child => { elem.appendChild(child); }); else if (child) elem.appendChild(child); } else if (typeof child === 'string') elem.innerHTML = child; return elem; } div(options = null, childList = null) { return this.elem('div', options, childList); } init() { const rootClass = 'link-tooltip MuiPopper-root MuiTooltip-popper css-112l0a2'; const tooltipClass = 'MuiTooltip-tooltip MuiTooltip-tooltipPlacementBottom css-1spb1s5'; this.tooltip = this.div(tooltipClass); this.root = this.div({ className: rootClass, style: { zIndex: 100000, position: 'absolute' } }, this.tooltip); document.body.appendChild(this.root); this.hide(); } attach(target, content, align = 'left') { const contentGen = typeof content === 'function' ? content : (() => content); target.addEventListener('mouseover', (e) => { this.show(contentGen().outerHTML, target, align); }); target.addEventListener('mouseout', () => { this.hide(); }); } show(innerHTML, target = null, align = 'left') { const gap = 2; this.root.style.display = 'block'; this.root.style.left = 0; this.root.style.top = 0; this.tooltip.innerHTML = innerHTML; if (target) { const targetRect = target.getBoundingClientRect(); const tooltipRootRect = this.root.getBoundingClientRect(); const tooltipRect = this.tooltip.getBoundingClientRect(); let left = targetRect.left; if (align === 'center') left -= (tooltipRect.width - targetRect.width) / 2; let top = targetRect.bottom + gap; const windowWidth = window.innerWidth; const windowHeight = window.innerHeight + window.scrollY; if (left + tooltipRect.width > windowWidth) left = windowWidth - tooltipRect.width; if (left < 0) left = 0; if (top + tooltipRect.height > windowHeight) top = targetRect.top - tooltipRect.height - gap; this.root.style.left = `${left - (tooltipRootRect.width - tooltipRect.width) / 2}px`; this.root.style.top = `${top - (tooltipRootRect.height - tooltipRect.height) / 2}px`; } } hide() { this.root.style.display = 'none'; } formatNumber(value) { return value.toString().replace(/\d+/, function (n) { return n.replace(/(\d)(?=(?:\d{3})+$)/g, '$1,') }) } formatNumberWithUnit(value) { if (value > 10_000_000_000_000) return `${(value / 1_000_000_000_000).toFixed(1)}T`; if (value > 10_000_000_000) return `${(value / 1_000_000_000).toFixed(1)}B`; if (value > 10_000_000) return `${(value / 1_000_000).toFixed(1)}M`; if (value > 10_000) return `${(value / 1_000).toFixed(1)}K`; return value; } item(hrid, level, count) { const ask = mwi_common.getItemPriceByHrid(hrid, level, 'ask'); const bid = mwi_common.getItemPriceByHrid(hrid, level, 'bid'); return this.div('ItemTooltipText_itemTooltipText__zFq3A', [ this.div('ItemTooltipText_name__2JAHA', mwi_common.getItemNameByHrid(hrid, mwi_common.isZh) + (level? `+${level}`: '')), this.div(null, `拥有数量: ${this.formatNumber(count)}`), this.div({ style: { color: '#804600' } }, `日均价: ${this.formatNumberWithUnit(ask)} / ${this.formatNumberWithUnit(bid)} (${this.formatNumberWithUnit(ask * count)} / ${this.formatNumberWithUnit(bid * count)})` ), ]); } } function updateSubscribedList() { const displayContainer = document.querySelector("div#displayContainer141"); if (!displayContainer) { return; } // 移除收藏物品 displayContainer.innerHTML = ""; // 创建收藏物品 mwi_subscribe_items.forEach(itemHridLevel => { const itemInfo = itemHridLevel.split("::"); const itemHrid = itemInfo[0]; const itemLevel = itemInfo[1]? Number(itemInfo[1]): 0; if (!itemHrid || itemHrid === "") { return; } const itemCount = mwi_common.getItemNumByHrid(itemHrid, itemLevel); const item = document.createElement("div"); item.setAttribute("class", "Item_itemContainer__x7kH1"); item.innerHTML = `<div> <div class="Item_item__2De2O Item_clickable__3viV6" style="position: relative;"> <div class="Item_iconContainer__5z7j4"> <svg role="img" aria-label="${mwi_common.getItemNameByHrid(itemHrid, mwi_common.isZh)}" class="Icon_icon__2LtL_" width="100%" height="100%"> <use href="/static/media/items_sprite.6d12eb9d.svg#${itemHrid.substr(7)}"></use> </svg> </div> <div class="Item_count__1HVvv" style="position: absolute; bottom: 2px; right: 2px;"> ${Tooltip.formatNumberWithUnit(itemCount)} </div> <div class="Item_enhancementLevel__19g-e" style="position: absolute; top: 2px; left: 2px;"> ${itemLevel > 0? `+${itemLevel}`: ""} </div> </div> </div>`; displayContainer.appendChild(item); // 物品点击事件 item.addEventListener("click", () => mwi_common.gotoMarket(itemHrid, itemLevel)); // 鼠标悬浮事件 Tooltip.attach(item, Tooltip.item(itemHrid, itemLevel, itemCount)); }); } function createSubscribeButton(marketPanel) { const displayContainer = marketPanel.querySelector(".MarketplacePanel_currentItem__3ercC"); if (!displayContainer) { return; } // 创建收藏按钮 const subscribeButton = document.createElement("button"); subscribeButton.setAttribute("id", "SubscribeButton141"); subscribeButton.className = "subscribe-btn"; subscribeButton.style.position = "absolute"; subscribeButton.style.padding = "0"; subscribeButton.style.marginLeft = "6px"; subscribeButton.style.background = "none"; subscribeButton.style.border = "none"; subscribeButton.style.outline = "none"; subscribeButton.style.zIndex = "2"; /** make sure it's on top of the item level div created by MWITools */ // 创建图标 const svgNS = "http://www.w3.org/2000/svg"; const svg = document.createElementNS(svgNS, "svg"); svg.setAttribute("viewBox", "0 0 24 24"); svg.setAttribute("width", "24"); svg.setAttribute("height", "24"); // 未收藏 const heartUnsubscribed = document.createElementNS(svgNS, "path"); heartUnsubscribed.setAttribute("d", "M12 21.35l-1.45-1.32C5.4 15.36 2 12.28 2 8.5 2 5.42 4.42 3 7.5 3c1.74 0 3.41.81 4.5 2.09C13.09 3.81 14.76 3 16.5 3 19.58 3 22 5.42 22 8.5c0 3.78-3.4 6.86-8.55 11.54L12 21.35z"); heartUnsubscribed.setAttribute("fill", "#aaaaaa"); heartUnsubscribed.setAttribute("stroke", "#333"); heartUnsubscribed.setAttribute("transition", "all 0.3s"); // 已收藏 const heartSubscribed = document.createElementNS(svgNS, "path"); heartSubscribed.setAttribute("d", "M12 21.35l-1.45-1.32C5.4 15.36 2 12.28 2 8.5 2 5.42 4.42 3 7.5 3c1.74 0 3.41.81 4.5 2.09C13.09 3.81 14.76 3 16.5 3 19.58 3 22 5.42 22 8.5c0 3.78-3.4 6.86-8.55 11.54L12 21.35z"); heartSubscribed.setAttribute("fill", "#ff4d4f"); heartSubscribed.setAttribute("opacity", "0"); heartSubscribed.setAttribute("transition", "opacity 0.3s"); // 添加图标 svg.appendChild(heartUnsubscribed); svg.appendChild(heartSubscribed); subscribeButton.appendChild(svg); displayContainer.prepend(subscribeButton); // 物品等级 let itemHrid = ""; let itemLevel = 0; let itemHridLevel = ""; let isSubscribed = false; const updateSubscribedButton = function() { if (isSubscribed) { heartUnsubscribed.setAttribute("stroke", "#ff4d4f"); heartSubscribed.setAttribute("opacity", "1"); } else { heartUnsubscribed.setAttribute("stroke", "#333"); heartSubscribed.setAttribute("opacity", "0"); } }; const updateMarketItem = function() { itemHrid = ""; const displayItem = displayContainer.querySelector(".Item_iconContainer__5z7j4"); if (displayItem && displayItem.firstChild) { const itemName = displayItem.firstChild.getAttribute("aria-label"); if (itemName && itemName !== "") { itemHrid = mwi_common.getItemHridByName(itemName); } } itemLevel = 0; const levelDiv = displayContainer.querySelector(".Item_enhancementLevel__19g-e"); if (levelDiv) { itemLevel = Number(levelDiv.textContent.replace("+", "")); if (isNaN(itemLevel)) itemLevel = 0; } itemHridLevel = itemLevel > 0? `${itemHrid}::${itemLevel}`: itemHrid; isSubscribed = mwi_subscribe_items.includes(itemHridLevel); updateSubscribedButton(); } updateMarketItem(); // 绑定点击 subscribeButton.addEventListener("click", function() { if (!itemHridLevel || itemHridLevel === "") { return; } isSubscribed = !isSubscribed; updateSubscribedButton(); if (isSubscribed) { console.info("[MWISubscribe] add item " + itemHridLevel); mwi_subscribe_items.push(itemHridLevel); } else { console.info("[MWISubscribe] remove item " + itemHridLevel); const idx = mwi_subscribe_items.indexOf(itemHridLevel); (~idx) && mwi_subscribe_items.splice(idx, 1); } localStorage.setItem(storage_key, JSON.stringify(mwi_subscribe_items)); updateSubscribedList(); }); new MutationObserver(updateMarketItem).observe(displayContainer, { childList: true, subtree: true }); } function createDisplayButton(marketPanel) { const tabPanelContainer = marketPanel.querySelector(".TabsComponent_tabPanelsContainer__26mzo"); if (!tabPanelContainer) { return; } const tabList = tabPanelContainer.querySelector("[role=tablist]"); const panelList = tabPanelContainer.querySelector(".TabsComponent_tabPanelsContainer__26mzo"); if (!tabList || !panelList) { return; } // 创建收藏按钮 const displayButton = document.createElement("button"); displayButton.setAttribute("class", "MuiButtonBase-root MuiTab-root MuiTab-textColorPrimary css-1q2h7u5"); displayButton.setAttribute("tabindex", -1); displayButton.setAttribute("role", "tab"); displayButton.setAttribute("aria-selected", false); displayButton.setAttribute("id", "displayButton141"); displayButton.textContent = "收藏"; tabList.appendChild(displayButton); // 创建收藏面板 const displayPanel = document.createElement("div"); displayPanel.setAttribute("class", "TabPanel_tabPanel__tXMJF TabPanel_hidden__26UM3"); panelList.appendChild(displayPanel); // 创建收藏容器 const displayContainer = document.createElement("div"); displayContainer.setAttribute("class", "MarketplacePanel_marketItems__D4k7e"); displayContainer.setAttribute("id", "displayContainer141"); displayPanel.appendChild(displayContainer); updateSubscribedList(); // 设置按钮点击事件 tabList.childNodes.forEach((childBtn, btnIdx) => { childBtn.addEventListener("click", function() { // 按钮样式更改 tabList.childNodes.forEach(otherBtn => { if (otherBtn === childBtn) { otherBtn.setAttribute("class", "MuiButtonBase-root MuiTab-root MuiTab-textColorPrimary Mui-selected css-1q2h7u5"); otherBtn.setAttribute("tabindex", 0); otherBtn.setAttribute("aria-selected", true); } else { otherBtn.setAttribute("class", "MuiButtonBase-root MuiTab-root MuiTab-textColorPrimary css-1q2h7u5"); otherBtn.setAttribute("tabindex", -1); otherBtn.setAttribute("aria-selected", false); } }); // 面板样式更改 panelList.childNodes.forEach((otherPanel, panelIdx) => { if (panelIdx === btnIdx) { otherPanel.setAttribute("class", "TabPanel_tabPanel__tXMJF"); } else { otherPanel.setAttribute("class", "TabPanel_tabPanel__tXMJF TabPanel_hidden__26UM3"); } }); // 更新收藏列表 if (childBtn === displayButton) updateSubscribedList(); }); }); } function addButton() { const marketPanel = document.querySelector(".MarketplacePanel_marketplacePanel__21b7o "); if (!marketPanel) { return; } const subscribeButton = marketPanel.querySelector("button#SubscribeButton141"); subscribeButton || createSubscribeButton(marketPanel); const displayButton = marketPanel.querySelector("button#displayButton141"); displayButton || createDisplayButton(marketPanel); } function start() { console.info("[MWISubscribe] start"); mwi_common = window.mwi_common; if (!mwi_common) { console.error("[MWISubscribe] mwi_common not found"); return; } setInterval(addButton, 500); } if (window.mwi_common) start(); else { console.info("[MWISubscribe] waiting for mwi_common"); document.addEventListener("mwi_common_injected", start); } })();
QingJ © 2025
镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址