移动端网络监测套件(极简版)

网络监测工具,显示流量、延迟和HTTP请求数

// ==UserScript==
// @name         移动端网络监测套件(极简版)
// @namespace    http://tampermonkey.net/
// @version      4.6.0
// @description  网络监测工具,显示流量、延迟和HTTP请求数
// @license      MIT
// @match        http://*/*
// @match        https://*/*
// @run-at       document-start
// @grant        none
// ==/UserScript==

(function() {
    'use strict';
    // 第一段:界面和拖拽功能
    const host = document.createElement('div');
    const savedLeft = localStorage.getItem('panelLeft') || '10px';
    const savedTop = localStorage.getItem('panelTop') || '10px';
    host.style.position = 'fixed';
    host.style.left = savedLeft;
    host.style.top = savedTop;
    host.style.zIndex = '99999998';
    host.style.minWidth = '140px';
    host.style.touchAction = 'none';
    document.documentElement.appendChild(host);

    const shadow = host.attachShadow({ mode: 'closed' });
    const panel = document.createElement('div');
    panel.style.padding = '8px 12px';
    panel.style.background = 'rgba(40,40,40,0.9)';
    panel.style.color = '#f0f0f0';
    panel.style.borderRadius = '8px';
    panel.style.fontSize = '12px';
    panel.style.fontFamily = 'system-ui, sans-serif';
    panel.style.cursor = 'move';
    panel.style.lineHeight = '1.5';
    panel.style.userSelect = 'none';
    shadow.appendChild(panel);

    let isDragging = false, startX = 0, startY = 0, initialLeft = 0, initialTop = 0;
    host.addEventListener('pointerdown', function(e) {
        isDragging = true;
        startX = e.clientX;
        startY = e.clientY;
        const rect = host.getBoundingClientRect();
        initialLeft = rect.left;
        initialTop = rect.top;
        host.setPointerCapture(e.pointerId);
        e.preventDefault();
    });
    host.addEventListener('pointermove', function(e) {
        if (!isDragging) return;
        const deltaX = e.clientX - startX;
        const deltaY = e.clientY - startY;
        host.style.left = initialLeft + deltaX + 'px';
        host.style.top = initialTop + deltaY + 'px';
        e.preventDefault();
    });
    // 第二段:数据监控功能
    host.addEventListener('pointerup', function(e) {
        if (!isDragging) return;
        isDragging = false;
        localStorage.setItem('panelLeft', host.style.left);
        localStorage.setItem('panelTop', host.style.top);
        host.releasePointerCapture(e.pointerId);
    });
    host.addEventListener('pointercancel', function(e) {
        isDragging = false;
        host.releasePointerCapture(e.pointerId);
    });

    let totalBytes = 0, latencyText = '延迟: ...', latencyColor = '#f0f0f0', requestCount = 0;
    function formatSize(bytes) {
        if (bytes < 1024) return bytes + ' B';
        if (bytes < 1048576) return (bytes / 1024).toFixed(1) + ' KB';
        return (bytes / 1048576).toFixed(2) + ' MB';
    }
    function updatePanel() {
        panel.innerHTML = `<div>域名: ${location.hostname}</div>
            <div>流量: ${formatSize(totalBytes)}</div>
            <div style="color: ${latencyColor}">${latencyText}</div>
            <div>HTTP请求数: ${requestCount}</div>`;
    }

    new PerformanceObserver(list => {
        list.getEntries().forEach(entry => {
            const size = entry.transferSize || entry.decodedBodySize || 0;
            if (size > 0) totalBytes += size;
            requestCount++;
        });
        updatePanel();
    }).observe({ type: 'resource', buffered: true });

    function measureLatency() {
        const start = performance.now();
        fetch(`${location.origin}/?t=${start}`, { 
            method: 'HEAD', 
            mode: 'no-cors', 
            cache: 'no-store' 
        }).then(() => {
            const latency = performance.now() - start;
            latencyText = `延迟: ${latency.toFixed(1)}ms`;
            latencyColor = latency < 100 ? '#4caf50' : 
                         latency < 300 ? '#ffb300' : 
                         latency < 500 ? '#ff9800' : '#f44336';
            updatePanel();
        }).catch(() => {
            latencyText = '延迟: 错误';
            latencyColor = '#f44336';
            updatePanel();
        });
    }

    setInterval(measureLatency, 2000);
    measureLatency();
    updatePanel();
})();