添加流量地图

This commit is contained in:
CN-JS-HuiBai
2026-04-05 01:17:45 +08:00
parent 2fc84f999c
commit af83f42d26
8 changed files with 281 additions and 6 deletions

View File

@@ -77,7 +77,8 @@
newPasswordInput: document.getElementById('newPassword'),
confirmNewPasswordInput: document.getElementById('confirmNewPassword'),
btnChangePassword: document.getElementById('btnChangePassword'),
changePasswordMessage: document.getElementById('changePasswordMessage')
changePasswordMessage: document.getElementById('changePasswordMessage'),
globeContainer: document.getElementById('globeContainer')
};
// ---- State ----
@@ -89,6 +90,7 @@
let currentSourceFilter = 'all';
let currentPage = 1;
let pageSize = 20;
let myGlobe = null;
// ---- Initialize ----
function init() {
@@ -101,6 +103,9 @@
// Network chart
networkChart = new AreaChart(dom.networkCanvas);
// Initial globe
initGlobe();
// Event listeners
dom.btnSettings.addEventListener('click', openSettings);
dom.modalClose.addEventListener('click', closeSettings);
@@ -353,6 +358,78 @@
}
}
// ---- Global Globe ----
function initGlobe() {
if (!dom.globeContainer) return;
myGlobe = Globe()
(dom.globeContainer)
.globeImageUrl('//unpkg.com/three-globe/example/img/earth-dark.jpg')
.bumpImageUrl('//unpkg.com/three-globe/example/img/earth-topology.png')
.backgroundColor('rgba(0,0,0,0)')
.showAtmosphere(true)
.atmosphereColor('#6366f1')
.atmosphereDaylightAlpha(0.1)
.pointsData([])
.pointColor(() => '#06b6d4')
.pointAltitude(0.05)
.pointRadius(0.8)
.pointsMerge(true)
.pointLabel(d => `
<div style="background: rgba(10, 14, 26, 0.9); padding: 8px 12px; border: 1px solid var(--accent-indigo); border-radius: 8px; backdrop-filter: blur(8px);">
<div style="font-weight: 700; color: #fff; margin-bottom: 4px;">${escapeHtml(d.job)}</div>
<div style="font-size: 0.75rem; color: var(--text-secondary);">${escapeHtml(d.city || '')}, ${escapeHtml(d.countryName || d.country || '')}</div>
<div style="font-size: 0.75rem; margin-top: 4px;">
<span style="color: var(--accent-indigo);">BW:</span> ↓${formatBandwidth(d.netRx)}${formatBandwidth(d.netTx)}
</div>
</div>
`);
// Resizing
const resizeObserver = new ResizeObserver(() => {
if (myGlobe) {
const width = dom.globeContainer.clientWidth;
const height = dom.globeContainer.clientHeight;
myGlobe.width(width).height(height);
}
});
resizeObserver.observe(dom.globeContainer);
// Initial view
myGlobe.controls().autoRotate = true;
myGlobe.controls().autoRotateSpeed = 0.5;
myGlobe.controls().enableZoom = false; // Disable zoom to maintain dashboard feel
}
function updateGlobe(servers) {
if (!myGlobe) return;
// Filter servers with lat/lng
const geoData = servers
.filter(s => s.lat && s.lng)
.map(s => ({
lat: s.lat,
lng: s.lng,
job: s.job,
city: s.city,
country: s.country,
countryName: s.countryName,
netRx: s.netRx,
netTx: s.netTx,
size: Math.max(0.2, Math.min(1.5, (s.netRx + s.netTx) / 1024 / 1024 / 5)) // Scale by bandwidth (MB/s)
}));
myGlobe.pointsData(geoData);
// Also add arcs for "traffic flow" if we have multiple servers
// For now, let's just show rings or pulses for active traffic
myGlobe.ringsData(geoData.filter(d => (d.netRx + d.netTx) > 1024 * 1024)); // Pulse for servers > 1MB/s
myGlobe.ringColor(() => '#6366f1');
myGlobe.ringMaxRadius(3);
myGlobe.ringPropagationSpeed(1);
myGlobe.ringRepeatPeriod(1000);
}
// ---- Update Dashboard ----
function updateDashboard(data) {
// Server count
@@ -384,6 +461,9 @@
// Update server table
renderFilteredServers();
// Update globe
updateGlobe(data.servers || []);
// Flash animation
if (previousMetrics) {