[MWI]personal use

个人脚本,适用于 Milky Way Idle 游戏

目前為 2025-07-16 提交的版本,檢視 最新版本

// ==UserScript==
// @name         [MWI]personal use
// @name:zh-CN   [银河奶牛]自用脚本
// @namespace    http://tampermonkey.net/
// @version      0.1.8
// @description  个人脚本,适用于 Milky Way Idle 游戏
// @description:zh-CN 个人专用脚本,适用于 Milky Way Idle 游戏
// @author       deric
// @license      MIT
// @match        https://www.milkywayidle.com/game*
// @grant        GM_registerMenuCommand
// ==/UserScript==

(function() {
    'use strict';
    const MWI_SCRIPT_VERSION = '0.1.7';
    function showSettingPanel() {
        let exist = document.getElementById('mwiSettingPopup');
        if (exist) exist.remove();
        const popup = document.createElement('div');
        popup.id = 'mwiSettingPopup';
        popup.style.position = 'fixed';
        popup.style.top = '120px';
        popup.style.left = '50%';
        popup.style.transform = 'translateX(-50%)';
        popup.style.background = 'white';
        popup.style.border = '2px solid #888';
        popup.style.boxShadow = '0 2px 12px rgba(0,0,0,0.2)';
        popup.style.zIndex = 99999;
        popup.style.padding = '24px 32px';
        popup.style.minWidth = '300px';
        popup.innerHTML = `<div style='text-align:right;'><button id='closeMwiSettingPopup'>关闭</button></div><h3 style='margin:8px 0 16px 0;'>设置</h3>
            <div style='margin-bottom:12px;'>
                <label><input type='checkbox' id='mwiMonitorPlayer'/> 是否启动监控人数</label>
            </div>
            <div style='margin-bottom:12px;'>
                <label><input type='checkbox' id='mwiMonitorNetWorth'/> 是否启动监控净资产</label>
            </div>
            <div style='margin-bottom:12px;'>
                <label><input type='checkbox' id='mwiShowOrderTotalValue'/> 是否显示订单总价</label>
            </div>
            <div style='color:#888;font-size:12px;'>设置会自动保存</div>`;
        document.body.appendChild(popup);
        document.getElementById('closeMwiSettingPopup').onclick = function() {
            popup.remove();
            // 关闭时记录当前版本号
            localStorage.setItem('mwiSettingPanelLastVersion', MWI_SCRIPT_VERSION);
        };
        // 初始化复选框状态
        document.getElementById('mwiMonitorPlayer').checked = localStorage.getItem('mwiMonitorPlayer') !== 'false';
        document.getElementById('mwiMonitorNetWorth').checked = localStorage.getItem('mwiMonitorNetWorth') === 'true';
        document.getElementById('mwiShowOrderTotalValue').checked = localStorage.getItem('mwiShowOrderTotalValue') !== 'false';
        // 监听变更
        document.getElementById('mwiMonitorPlayer').onchange = function() {
            localStorage.setItem('mwiMonitorPlayer', this.checked);
        };
        document.getElementById('mwiMonitorNetWorth').onchange = function() {
            localStorage.setItem('mwiMonitorNetWorth', this.checked);
        };
        document.getElementById('mwiShowOrderTotalValue').onchange = function() {
            localStorage.setItem('mwiShowOrderTotalValue', this.checked);
            window.dispatchEvent(new Event('mwiShowOrderTotalValueChanged'));
        };
    }

    // 你的代码写在这里

    function savePlayerNumber() {
        const el = document.querySelector('div.Header_playerCount__1TDTK');
        if (!el) return;
        const number = parseInt(el.textContent.replace(/\D/g, ''), 10);
        if (isNaN(number)) {
            setTimeout(savePlayerNumber, 3000);
            return;
        }
        const now = new Date().toISOString();
        const data = { time: now, number };
        let arr = [];
        try {
            arr = JSON.parse(localStorage.getItem('playernumber') || '[]');
            if (!Array.isArray(arr)) arr = [];
        } catch(e) { arr = []; }
        arr.push(data);
        localStorage.setItem('playernumber', JSON.stringify(arr));
    }

    // 新增:根据当前网址获取key
    function getNetWorthKey() {
        const url = window.location.href;
        const match = url.match(/(\d{6})(?!.*\d)/);
        return match ? match[1] : 'default';
    }

    // 新增:保存净资产(分key)
    function saveNetWorth() {
        const el = document.querySelector('#toggleNetWorth');
        if (!el) return;
        // 提取数字和单位
        const match = el.textContent.replace(/,/g, '').match(/([\d.]+)\s*([KMBT]?)/i);
        let number = null;
        if (match) {
            number = parseFloat(match[1]);
            const unit = match[2]?.toUpperCase();
            if (unit === 'K') number *= 1e3;
            else if (unit === 'M') number *= 1e6;
            else if (unit === 'B') number *= 1e9;
            else if (unit === 'T') number *= 1e12;
        }
        if (!number || isNaN(number)) {
            setTimeout(saveNetWorth, 3000);
            return;
        }
        const now = new Date().toISOString();
        const data = { time: now, number };
        let arr = [];
        const key = 'networth_' + getNetWorthKey();
        try {
            arr = JSON.parse(localStorage.getItem(key) || '[]');
            if (!Array.isArray(arr)) arr = [];
        } catch(e) { arr = []; }
        arr.push(data);
        localStorage.setItem(key, JSON.stringify(arr));
    }

    // 修改按钮显示逻辑,支持显示多条记录
    function createShowButton() {
        // 判断设置
        if (localStorage.getItem('mwiMonitorPlayer') === 'false') return;
        const target = document.querySelector("#root > div > div > div.GamePage_headerPanel__1T_cA > div > div.Header_leftHeader__PkRWX > div.Header_navLogoAndPlayerCount__2earI > div.Header_playerCount__1TDTK");
        if (!target || document.getElementById('showPlayerNumberBtn')) return;
        const btn = document.createElement('button');
        btn.id = 'showPlayerNumberBtn';
        btn.textContent = '显示玩家人数记录';
        btn.style.marginLeft = '8px';
        btn.style.background = 'rgb(69,71,113)';
        btn.style.color = '#fff';
        btn.style.border = 'none';
        btn.style.borderRadius = '4px';
        btn.style.padding = '4px 10px';
        btn.onclick = function() {
            let data = localStorage.getItem('playernumber');
            let arr = [];
            if (data) {
                try {
                    arr = JSON.parse(data);
                    if (!Array.isArray(arr)) arr = [];
                } catch(e) { arr = []; }
            }
            // 默认时间范围(天)
            let rangeDays = parseInt(localStorage.getItem('mwiPlayerNumberRangeDays')) || 1;
            // 生成时间范围按钮
            const ranges = [1, 3, 7, 14, 30];
            let rangeBtns = '<div style="margin-bottom:8px;">';
            for(const d of ranges){
                rangeBtns += `<button class='rangeBtn' data-days='${d}' style='margin-right:4px;'>${d}天</button>`;
            }
            rangeBtns += '</div>';
            // 生成折线图HTML
            let html = rangeBtns;
            html += `<button id='managePlayerNumberBtn' style='margin-bottom:8px;'>管理</button>`;
            html += `<div id='chartContainer'></div>`;
            html += `<div id='managePlayerNumberPanel' style='display:none;margin-top:12px;background:#fff;'></div>`;
            // 网页内部弹窗
            let exist = document.getElementById('playerNumberPopup');
            if (exist) exist.remove();
            const popup = document.createElement('div');
            popup.id = 'playerNumberPopup';
            popup.style.position = 'fixed';
            popup.style.top = '80px';
            popup.style.left = '40px';
            popup.style.background = 'white';
            popup.style.border = '2px solid #888';
            popup.style.boxShadow = '0 2px 12px rgba(0,0,0,0.2)';
            popup.style.zIndex = 9999;
            popup.style.padding = '16px';
            popup.style.maxHeight = '500px';
            popup.style.overflow = 'auto';
            popup.innerHTML = `<div style='text-align:right;'><button id='closePlayerNumberPopup'>关闭</button></div>${html}`;
            document.body.appendChild(popup);
            document.getElementById('closePlayerNumberPopup').onclick = function() {
                popup.remove();
            };
            // 管理按钮逻辑
            document.getElementById('managePlayerNumberBtn').onclick = function() {
                const panel = document.getElementById('managePlayerNumberPanel');
                if(panel.style.display==='none'){
                    renderManagePanel();
                    panel.style.display='block';
                }else{
                    panel.style.display='none';
                }
            };
            function renderManagePanel(){
                const panel = document.getElementById('managePlayerNumberPanel');
                if(arr.length===0){
                    panel.innerHTML = '暂无记录';
                    return;
                }
                let html = `<button id='clearAllPlayerNumber' style='color:red;margin-bottom:8px;'>全部清空</button><br/>`;
                html += '<ul style="max-height:200px;overflow:auto;padding-left:0;">';
                arr.forEach((item,idx)=>{
                    html += `<li style='list-style:none;margin-bottom:4px;'>${item.time.replace('T',' ').slice(0,16)} - ${item.number} <button data-idx='${idx}' class='delPlayerNumberBtn' style='color:red;'>删除</button></li>`;
                });
                html += '</ul>';
                panel.innerHTML = html;
                // 单条删除
                panel.querySelectorAll('.delPlayerNumberBtn').forEach(btn=>{
                    btn.onclick = function(){
                        arr.splice(parseInt(this.getAttribute('data-idx')),1);
                        localStorage.setItem('playernumber', JSON.stringify(arr));
                        renderManagePanel();
                        drawChart(rangeDays);
                    };
                });
                // 全部清空
                panel.querySelector('#clearAllPlayerNumber').onclick = function(){
                    if(confirm('确定要清空所有记录吗?')){
                        arr.length=0;
                        localStorage.setItem('playernumber', '[]');
                        renderManagePanel();
                        drawChart(rangeDays);
                    }
                };
            }
            // 绘制折线图函数
            function drawChart(days) {
                const now = Date.now();
                const ms = days * 24 * 60 * 60 * 1000;
                const filtered = arr.filter(item => {
                    const t = new Date(item.time).getTime();
                    return t >= now - ms;
                }).sort((a, b) => new Date(a.time) - new Date(b.time));
                const container = document.getElementById('chartContainer');
                if(filtered.length > 1){
                    container.innerHTML = `<canvas id='playerNumberChart' width='500' height='300' style='display:block;'></canvas>`;
                }else if(filtered.length === 1){
                    container.innerHTML = `仅有一条数据:${filtered[0].time} - ${filtered[0].number}`;
                    return;
                }else{
                    container.innerHTML = '暂无数据';
                    return;
                }
                setTimeout(() => {
                    const canvas = document.getElementById('playerNumberChart');
                    if (!canvas) return;
                    const ctx = canvas.getContext('2d');
                    ctx.clearRect(0, 0, canvas.width, canvas.height);
                    // 处理数据
                    const times = filtered.map(item => new Date(item.time));
                    const numbers = filtered.map(item => item.number);
                    // 横坐标:小时:分
                    let labels;
                    if(days <= 3){
                        labels = times.map(t => `${t.getHours()}:` + (t.getMinutes()<10?`0${t.getMinutes()}`:t.getMinutes()));
                    }else{
                        labels = times.map(t => `${t.getMonth()+1}-${t.getDate()}`);
                    }
                    // 纵坐标范围,增加上下边距
                    let minY = Math.min(...numbers);
                    let maxY = Math.max(...numbers);
                    const steps = 5;
                    const step = (maxY - minY) / steps || 1;
                    minY = Math.max(0, minY - step);
                    maxY = maxY + step;
                    const padding = 55;
                    const w = canvas.width - padding*2;
                    const h = canvas.height - padding*2;
                    ctx.font = '12px sans-serif';
                    // 横坐标等比例
                    const minTime = times[0].getTime();
                    const maxTime = times[times.length-1].getTime();
                    const timeSpan = maxTime - minTime || 1;
                    // 绘制坐标轴
                    ctx.strokeStyle = '#333';
                    ctx.beginPath();
                    ctx.moveTo(padding, padding);
                    ctx.lineTo(padding, padding + h);
                    ctx.lineTo(padding + w, padding + h);
                    ctx.stroke();
                    // Y轴刻度
                    ctx.fillStyle = '#333';
                    ctx.textAlign = 'right';
                    ctx.textBaseline = 'middle';
                    for(let i=0;i<=5;i++){
                        const y = padding + h - h*i/5;
                        const val = Math.round(minY + (maxY-minY)*i/5);
                        ctx.fillText(val, padding-5, y);
                        ctx.strokeStyle = '#eee';
                        ctx.beginPath();
                        ctx.moveTo(padding, y);
                        ctx.lineTo(padding+w, y);
                        ctx.stroke();
                    }
                    // X轴刻度(等比例)
                    ctx.textAlign = 'center';
                    ctx.textBaseline = 'top';
                    for(let i=0;i<times.length;i++){
                        const t = times[i].getTime();
                        const x = padding + w*(t-minTime)/timeSpan;
                        ctx.fillStyle = '#333';
                        // 只显示首、尾、每隔5个点的标签,避免重叠
                        if(i===0 || i===times.length-1 || (times.length>10 && i%5===0)){
                            ctx.fillText(labels[i], x, padding+h+5);
                        }
                    }
                    // 折线(等比例)
                    ctx.strokeStyle = '#007bff';
                    ctx.beginPath();
                    for(let i=0;i<numbers.length;i++){
                        const t = times[i].getTime();
                        const x = padding + w*(t-minTime)/timeSpan;
                        const y = padding + h - h*(numbers[i]-minY)/(maxY-minY||1);
                        if(i===0) ctx.moveTo(x, y);
                        else ctx.lineTo(x, y);
                    }
                    ctx.stroke();
                    // 点(等比例)
                    ctx.fillStyle = '#007bff';
                    for(let i=0;i<numbers.length;i++){
                        const t = times[i].getTime();
                        const x = padding + w*(t-minTime)/timeSpan;
                        const y = padding + h - h*(numbers[i]-minY)/(maxY-minY||1);
                        ctx.beginPath();
                        ctx.arc(x, y, 3, 0, 2*Math.PI);
                        ctx.fill();
                    }
                }, 0);
            }
            // 默认绘制1天
            drawChart(rangeDays);
            // 按钮事件
            popup.querySelectorAll('.rangeBtn').forEach(btn => {
                btn.onclick = function(){
                    const days = parseInt(this.getAttribute('data-days'));
                    localStorage.setItem('mwiPlayerNumberRangeDays', days);
                    drawChart(days);
                    highlightRangeBtn(days);
                };
            });
        };
        target.parentNode.appendChild(btn);
    }

    // 新增:显示净资产历史折线图按钮(分key)
    function createShowNetWorthButton() {
        // 判断设置
        if (localStorage.getItem('mwiMonitorNetWorth') !== 'true') return;
        const target = document.querySelector("#toggleNetWorth");
        if (!target || document.getElementById('showNetWorthBtn')) return;
        const btn = document.createElement('button');
        btn.id = 'showNetWorthBtn';
        const key = getNetWorthKey();
        btn.textContent = '显示净资产记录';
        btn.style.marginLeft = '8px';
        btn.style.background = 'rgb(69,71,113)';
        btn.style.color = '#fff';
        btn.style.border = 'none';
        btn.style.borderRadius = '4px';
        btn.style.padding = '4px 10px';
        btn.onclick = function() {
            const key = 'networth_' + getNetWorthKey();
            let data = localStorage.getItem(key);
            let arr = [];
            if (data) {
                try {
                    arr = JSON.parse(data);
                    if (!Array.isArray(arr)) arr = [];
                } catch(e) { arr = []; }
            }
            // 默认时间范围(天)
            let rangeDays = parseInt(localStorage.getItem('mwiNetWorthRangeDays')) || 1;
            // 生成时间范围按钮
            const ranges = [1, 3, 7, 14, 30];
            let rangeBtns = '<div style="margin-bottom:8px;">';
            for(const d of ranges){
                rangeBtns += `<button class='rangeBtnNet' data-days='${d}' style='margin-right:4px;'>${d}天</button>`;
            }
            rangeBtns += '</div>';
            // 生成折线图HTML
            let html = rangeBtns;
            html += `<button id='manageNetWorthBtn' style='margin-bottom:8px;'>管理</button>`;
            html += `<div id='chartNetContainer'></div>`;
            html += `<div id='manageNetWorthPanel' style='display:none;margin-top:12px;background:#fff;'></div>`;
            // 网页内部弹窗
            let exist = document.getElementById('netWorthPopup');
            if (exist) exist.remove();
            const popup = document.createElement('div');
            popup.id = 'netWorthPopup';
            popup.style.position = 'fixed';
            popup.style.top = '80px';
            popup.style.left = '40px';
            popup.style.background = 'white';
            popup.style.border = '2px solid #888';
            popup.style.boxShadow = '0 2px 12px rgba(0,0,0,0.2)';
            popup.style.zIndex = 9999;
            popup.style.padding = '16px';
            popup.style.maxHeight = '500px';
            popup.style.overflow = 'visible';
            popup.innerHTML = `<div style='text-align:right;'><button id='closeNetWorthPopup'>关闭</button></div><h4 style='margin:8px 0 16px 0;'>净资产记录</h4>${html}`;
            document.body.appendChild(popup);
            document.getElementById('closeNetWorthPopup').onclick = function() {
                popup.remove();
            };
            // 管理按钮逻辑
            document.getElementById('manageNetWorthBtn').onclick = function() {
                const panel = document.getElementById('manageNetWorthPanel');
                if(panel.style.display==='none'){
                    renderManagePanelNet();
                    panel.style.display='block';
                }else{
                    panel.style.display='none';
                }
            };
            function renderManagePanelNet(){
                const panel = document.getElementById('manageNetWorthPanel');
                const key = 'networth_' + getNetWorthKey();
                let arr = [];
                try {
                    arr = JSON.parse(localStorage.getItem(key) || '[]');
                    if (!Array.isArray(arr)) arr = [];
                } catch(e) { arr = []; }
                const rangeDays = parseInt(localStorage.getItem('mwiNetWorthRangeDays')) || 1;
                if(arr.length===0){
                    panel.innerHTML = '暂无记录';
                    drawChart(rangeDays);
                    return;
                }
                let html = `<button id='clearAllNetWorth' style='color:red;margin-bottom:8px;'>全部清空</button><br/>`;
                html += '<ul style="max-height:200px;overflow:auto;padding-left:0;">';
                arr.forEach((item,idx)=>{
                    html += `<li style='list-style:none;margin-bottom:4px;'>${item.time.replace('T',' ').slice(0,16)} - ${Math.round(item.number/1e6)}M <button data-idx='${idx}' class='delNetWorthBtn' style='color:red;'>删除</button></li>`;
                });
                html += '</ul>';
                panel.innerHTML = html;
                // 单条删除
                panel.querySelectorAll('.delNetWorthBtn').forEach(btn=>{
                    btn.onclick = function(){
                        const idx = parseInt(this.getAttribute('data-idx'));
                        arr.splice(idx,1);
                        localStorage.setItem(key, JSON.stringify(arr));
                        renderManagePanelNet();
                    };
                });
                // 全部清空
                panel.querySelector('#clearAllNetWorth').onclick = function(){
                    if(confirm('确定要清空所有记录吗?')){
                        arr = [];
                        localStorage.setItem(key, '[]');
                        renderManagePanelNet();
                    }
                };
            }
            // 绘制折线图函数
            function drawChart(days) {
                const now = Date.now();
                const ms = days * 24 * 60 * 60 * 1000;
                const filtered = arr.filter(item => {
                    const t = new Date(item.time).getTime();
                    return t >= now - ms;
                }).sort((a, b) => new Date(a.time) - new Date(b.time));
                const container = document.getElementById('chartNetContainer');
                if(filtered.length > 1){
                    container.innerHTML = `<canvas id='netWorthChart' width='550' height='320' style='display:block;'></canvas>`;
                }else if(filtered.length === 1){
                    container.innerHTML = `仅有一条数据:${(filtered[0].time)} - ${Math.round(filtered[0].number/1e6)}M`;
                    return;
                }else{
                    container.innerHTML = '暂无数据';
                    return;
                }
                setTimeout(() => {
                    const canvas = document.getElementById('netWorthChart');
                    if (!canvas) return;
                    const ctx = canvas.getContext('2d');
                    ctx.clearRect(0, 0, canvas.width, canvas.height);
                    // 处理数据
                    const times = filtered.map(item => new Date(item.time));
                    const numbers = filtered.map(item => item.number/1e6); // 以M为单位
                    // 横坐标:根据天数显示小时或日期
                    let labels;
                    if(days <= 3){
                        labels = times.map(t => `${t.getHours()}:` + (t.getMinutes()<10?`0${t.getMinutes()}`:t.getMinutes()));
                    }else{
                        labels = times.map(t => `${t.getMonth()+1}-${t.getDate()}`);
                    }
                    // 纵坐标范围,增加上下边距
                    let minY = Math.min(...numbers);
                    let maxY = Math.max(...numbers);
                    const steps = 5;
                    const step = (maxY - minY) / steps || 1;
                    minY = Math.max(0, minY - step);
                    maxY = maxY + step;
                    const padding = 55;
                    const w = canvas.width - padding*2;
                    const h = canvas.height - padding*2;
                    ctx.font = '12px sans-serif';
                    // 横坐标等比例
                    const minTime = times[0].getTime();
                    const maxTime = times[times.length-1].getTime();
                    const timeSpan = maxTime - minTime || 1;
                    // 绘制坐标轴
                    ctx.strokeStyle = '#333';
                    ctx.beginPath();
                    ctx.moveTo(padding, padding);
                    ctx.lineTo(padding, padding + h);
                    ctx.lineTo(padding + w, padding + h);
                    ctx.stroke();
                    // Y轴刻度
                    ctx.fillStyle = '#333';
                    ctx.textAlign = 'right';
                    ctx.textBaseline = 'middle';
                    for(let i=0;i<=5;i++){
                        const y = padding + h - h*i/5;
                        const val = minY + (maxY-minY)*i/5;
                        ctx.fillText(Math.round(val)+'M', padding-5, y);
                        ctx.strokeStyle = '#eee';
                        ctx.beginPath();
                        ctx.moveTo(padding, y);
                        ctx.lineTo(padding+w, y);
                        ctx.stroke();
                    }
                    // X轴刻度(等比例)
                    ctx.textAlign = 'center';
                    ctx.textBaseline = 'top';
                    for(let i=0;i<times.length;i++){
                        const t = times[i].getTime();
                        const x = padding + w*(t-minTime)/timeSpan;
                        ctx.fillStyle = '#333';
                        // 只显示首、尾、每隔5个点的标签,避免重叠
                        if(i===0 || i===times.length-1 || (times.length>10 && i%5===0)){
                            ctx.fillText(labels[i], x, padding+h+5);
                        }
                    }
                    // 折线(等比例)
                    ctx.strokeStyle = '#28a745';
                    ctx.beginPath();
                    for(let i=0;i<numbers.length;i++){
                        const t = times[i].getTime();
                        const x = padding + w*(t-minTime)/timeSpan;
                        const y = padding + h - h*(numbers[i]-minY)/(maxY-minY||1);
                        if(i===0) ctx.moveTo(x, y);
                        else ctx.lineTo(x, y);
                    }
                    ctx.stroke();
                    // 点(等比例)
                    ctx.fillStyle = '#28a745';
                    for(let i=0;i<numbers.length;i++){
                        const t = times[i].getTime();
                        const x = padding + w*(t-minTime)/timeSpan;
                        const y = padding + h - h*(numbers[i]-minY)/(maxY-minY||1);
                        ctx.beginPath();
                        ctx.arc(x, y, 3, 0, 2*Math.PI);
                        ctx.fill();
                    }
                }, 0);
            }
            // 默认绘制1天
            drawChart(rangeDays);
            // 高亮当前按钮
            function highlightRangeBtnNet(days) {
                popup.querySelectorAll('.rangeBtnNet').forEach(btn => {
                    if(parseInt(btn.getAttribute('data-days')) === days){
                        btn.style.background = '#e0e0e0';
                    }else{
                        btn.style.background = '';
                    }
                });
            }
            highlightRangeBtnNet(rangeDays);
            // 按钮事件
            popup.querySelectorAll('.rangeBtnNet').forEach(btn => {
                btn.onclick = function(){
                    const days = parseInt(this.getAttribute('data-days'));
                    localStorage.setItem('mwiNetWorthRangeDays', days);
                    drawChart(days);
                    highlightRangeBtnNet(days);
                };
            });
        };
        target.parentNode.appendChild(btn);
    }

    // 工具函数:带单位字符串转数字
    function parseNumberWithUnit(str) {
        const match = str.replace(/,/g, '').match(/([\d.]+)\s*([KMBT]?)/i);
        let num = null;
        if (match) {
            num = parseFloat(match[1]);
            const unit = match[2]?.toUpperCase();
            if (unit === 'K') num *= 1e3;
            else if (unit === 'M') num *= 1e6;
            else if (unit === 'B') num *= 1e9;
            else if (unit === 'T') num *= 1e12;
        }
        return num;
    }

    // 工具函数:大数字格式化为K/M/B,保留1位小数,无小数不显示
    function formatNumberWithUnit(num) {
        if (num >= 1e9) {
            let n = num / 1e9;
            return (n % 1 === 0 ? n : n.toFixed(1)) + 'B';
        } else if (num >= 1e6) {
            let n = num / 1e6;
            return (n % 1 === 0 ? n : n.toFixed(1)) + 'M';
        } else if (num >= 1e3) {
            let n = num / 1e3;
            return (n % 1 === 0 ? n : n.toFixed(1)) + 'K';
        } else {
            return num.toString();
        }
    }

    // 工具函数:最大值只显示到M为单位
    function formatNumberToM(num) {
        if (num >= 1e6) {
            let n = num / 1e6;
            return (n % 1 === 0 ? n : n.toFixed(1)) + 'M';
        } else {
            return num.toString();
        }
    }

    // 读取所有订单行的数量(取“/”后面的数字)
    function getAllOrderQuantities() {
        const nodes = document.querySelectorAll('div.MarketplacePanel_myListingsTableContainer__2s6pm > table > tbody > tr > td:nth-child(3) > div > div:nth-child(2)');
        const quantities = [];
        nodes.forEach(node => {
            const text = node.textContent.trim();
            const parts = text.split('/');
            if(parts.length === 2) {
                const qty = parseNumberWithUnit(parts[1]);
                if(!isNaN(qty)) quantities.push(qty);
            }
        });
        console.log('所有订单数量:', quantities);
        return quantities;
    }

    // 读取所有订单行的价格
    function getAllOrderPrices() {
        const nodes = document.querySelectorAll('td.MarketplacePanel_price__hIzrY > span');
        const prices = [];
        nodes.forEach(node => {
            const text = node.textContent.trim();
            const price = parseNumberWithUnit(text);
            if(!isNaN(price)) prices.push(price);
        });
        console.log('所有订单价格:', prices);
        return prices;
    }

    // 在每个订单价格下方插入总价值
    function showOrderTotalValues() {
        // 获取所有订单行
        const rows = document.querySelectorAll('div.MarketplacePanel_myListingsTableContainer__2s6pm > table > tbody > tr');
        rows.forEach(row => {
            // 获取数量
            const qtyNode = row.querySelector('td:nth-child(3) > div > div:nth-child(2)');
            let qty = 0;
            if(qtyNode) {
                const text = qtyNode.textContent.trim();
                const parts = text.split('/');
                if(parts.length === 2) {
                    qty = parseNumberWithUnit(parts[1]);
                }
            }
            // 获取价格
            const priceNode = row.querySelector('td.MarketplacePanel_price__hIzrY > span');
            let price = 0;
            if(priceNode) {
                const text = priceNode.textContent.trim();
                price = parseNumberWithUnit(text);
            }
            // 计算总价值
            const total = (!isNaN(qty) && !isNaN(price)) ? qty * price : 0;
            // 插入显示div
            if(priceNode) {
                // 避免重复插入
                if(priceNode.nextSibling && priceNode.nextSibling.className === 'orderTotalValue') return;
                const div = document.createElement('div');
                div.className = 'orderTotalValue';
                div.style.fontSize = '12px';
                div.style.color = '#28a745';
                div.textContent = `总价值:${formatNumberWithUnit(total)}`;
                priceNode.parentNode.appendChild(div);
            }
        });
    }

    // 修改定时器和延时调用,根据设置决定是否监控
    setTimeout(() => {
        if(localStorage.getItem('mwiMonitorPlayer') !== 'false') savePlayerNumber();
        if(localStorage.getItem('mwiMonitorNetWorth') === 'true') saveNetWorth();
    }, 5000);
    setInterval(() => {
        if(localStorage.getItem('mwiMonitorPlayer') !== 'false') savePlayerNumber();
        if(localStorage.getItem('mwiMonitorNetWorth') === 'true') saveNetWorth();
    }, 30 * 60 * 1000);
    // 页面加载后添加按钮
    window.addEventListener('DOMContentLoaded', () => {
        createShowButton();
        createShowNetWorthButton();
    });
    setTimeout(() => {
        createShowButton();
        createShowNetWorthButton();
    }, 5000);
    // 首次安装时默认开启所有功能
    if (localStorage.getItem('mwiMonitorPlayer') === null) {
        localStorage.setItem('mwiMonitorPlayer', 'true');
    }
    if (localStorage.getItem('mwiMonitorNetWorth') === null) {
        localStorage.setItem('mwiMonitorNetWorth', 'true');
    }
    // 设置变更时刷新按钮显示
    window.addEventListener('storage', function(e) {
        if (e.key === 'mwiMonitorPlayer' || e.key === 'mwiMonitorNetWorth') {
            // 移除旧按钮
            const btn1 = document.getElementById('showPlayerNumberBtn');
            if (btn1) btn1.remove();
            const btn2 = document.getElementById('showNetWorthBtn');
            if (btn2) btn2.remove();
            // 重新判断并添加
            createShowButton();
            createShowNetWorthButton();
        }
    });

    // 监听TabPanel_hidden出现时自动显示订单总价值
    let orderTotalValueObserver = null;
    function observeOrderTabAndShowTotal() {
        if(orderTotalValueObserver) orderTotalValueObserver.disconnect();
        if(localStorage.getItem('mwiShowOrderTotalValue') === 'false') return;
        orderTotalValueObserver = new MutationObserver(() => {
            const tab = document.querySelector('div.TabPanel_tabPanel__tXMJF.TabPanel_hidden__26UM3');
            if(tab) {
                showOrderTotalValues();
            }
        });
        orderTotalValueObserver.observe(document.body, { childList: true, subtree: true });
    }
    // 页面加载后自动监听
    setTimeout(() => {
        observeOrderTabAndShowTotal();
    }, 5000);
    // 响应设置变更
    window.addEventListener('mwiShowOrderTotalValueChanged', () => {
        observeOrderTabAndShowTotal();
        // 清理已显示的总价值
        document.querySelectorAll('.orderTotalValue').forEach(e=>e.remove());
    });
    // 首次安装时默认开启
    if (localStorage.getItem('mwiShowOrderTotalValue') === null) {
        localStorage.setItem('mwiShowOrderTotalValue', 'true');
    }

    // 在“显示净资产记录”按钮旁显示前一天最大净资产和当前差值
    function showNetWorthDayCompare() {
        const btn = document.getElementById('showNetWorthBtn');
        if (!btn || document.getElementById('netWorthDayCompare')) return;
        const key = 'networth_' + getNetWorthKey();
        let arr = [];
        try {
            arr = JSON.parse(localStorage.getItem(key) || '[]');
            if (!Array.isArray(arr)) arr = [];
        } catch(e) { arr = []; }
        if(arr.length < 2) return;
        const now = new Date();
        const today0 = new Date(now.getFullYear(), now.getMonth(), now.getDate(), 0, 0, 0, 0).getTime();
        const prevDayStart = today0 - 24 * 60 * 60 * 1000;
        const prevDayEnd = today0;
        const prevDayArr = arr.filter(item => {
            const t = new Date(item.time).getTime();
            return t >= prevDayStart && t < prevDayEnd && item.number;
        });
        if(prevDayArr.length === 0) return;
        const maxPrevDay = Math.max(...prevDayArr.map(item => item.number));
        const latest = arr[arr.length-1].number;
        const diff = latest - maxPrevDay;
        // 格式化
        const maxPrevDayStr = formatNumberToM(maxPrevDay);
        const diffStr = (diff>=0?'+':'') + formatNumberWithUnit(diff);
        // 插入元素
        const span = document.createElement('span');
        span.id = 'netWorthDayCompare';
        span.style.marginLeft = '12px';
        span.style.fontSize = '13px';
        span.style.color = diff>=0 ? '#28a745' : '#d33';
        span.textContent = `前一天最大值:${maxPrevDayStr}  当前差值:${diffStr}`;
        btn.parentNode.insertBefore(span, btn.nextSibling);
    }

    // 页面加载后和按钮生成后调用
    setTimeout(() => {
        showNetWorthDayCompare();
    }, 5500);
    // 监听按钮生成后再插入
    const observerNetBtn = new MutationObserver(() => {
        showNetWorthDayCompare();
    });
    observerNetBtn.observe(document.body, { childList: true, subtree: true });

    // 自动弹出设置面板(仅脚本更新后第一次)
    setTimeout(() => {
        if (localStorage.getItem('mwiSettingPanelLastVersion') !== MWI_SCRIPT_VERSION) {
            showSettingPanel();
        }
    }, 1200);

})(); 

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址