优化结构

This commit is contained in:
CN-JS-HuiBai
2026-04-05 17:12:48 +08:00
parent dc865c6d9d
commit d595397f08
3 changed files with 128 additions and 23 deletions

View File

@@ -82,7 +82,8 @@
globeContainer: document.getElementById('globeContainer'),
globeTotalNodes: document.getElementById('globeTotalNodes'),
globeTotalRegions: document.getElementById('globeTotalRegions'),
sourceFilter: document.getElementById('sourceFilter')
sourceFilter: document.getElementById('sourceFilter'),
btnResetSort: document.getElementById('btnResetSort')
};
// ---- State ----
@@ -94,7 +95,18 @@
let currentSourceFilter = 'all';
let currentPage = 1;
let pageSize = 20;
// Load sort state from localStorage or use default
let currentSort = { column: 'up', direction: 'desc' };
try {
const savedSort = localStorage.getItem('serverListSort');
if (savedSort) {
currentSort = JSON.parse(savedSort);
}
} catch (e) {
console.warn('Failed to load sort state', e);
}
let myMap2D = null;
// ---- Initialize ----
@@ -177,6 +189,19 @@
// Server table header sorting
const tableHeader = document.querySelector('.server-table thead');
if (tableHeader) {
// Sync UI with initial state
const initialHeaders = tableHeader.querySelectorAll('th.sortable');
initialHeaders.forEach(th => {
const col = th.getAttribute('data-sort');
if (col === currentSort.column) {
th.classList.add('active');
th.setAttribute('data-dir', currentSort.direction);
} else {
th.classList.remove('active');
th.removeAttribute('data-dir');
}
});
tableHeader.addEventListener('click', (e) => {
const th = e.target.closest('th.sortable');
if (th) {
@@ -213,6 +238,11 @@
});
}
// Reset sort listener
if (dom.btnResetSort) {
dom.btnResetSort.addEventListener('click', resetSort);
}
// Check auth status
checkAuthStatus();
@@ -576,27 +606,34 @@
} else {
// Specifically sorting by status: Online vs Offline
if (a.up !== b.up) {
const val = a.up ? -1 : 1;
return currentSort.direction === 'asc' ? -val : val;
const val = a.up ? -1 : 1;
return currentSort.direction === 'asc' ? -val : val;
}
}
// Secondary sort based on user choice
let valA, valB;
switch (currentSort.column) {
const col = currentSort.column;
const dir = currentSort.direction;
switch (col) {
case 'up':
return 0; // Already handled above
case 'job':
// If we reached here, status is the same (both online or both offline)
// Fall back to job name sorting
valA = a.job || '';
valB = b.job || '';
return currentSort.direction === 'asc' ? valA.localeCompare(valB) : valB.localeCompare(valA);
return valA.localeCompare(valB);
case 'job':
valA = (a.job || '').toLowerCase();
valB = (b.job || '').toLowerCase();
return dir === 'asc' ? valA.localeCompare(valB) : valB.localeCompare(valA);
case 'source':
valA = a.source || '';
valB = b.source || '';
return currentSort.direction === 'asc' ? valA.localeCompare(valB) : valB.localeCompare(valA);
valA = (a.source || '').toLowerCase();
valB = (b.source || '').toLowerCase();
return dir === 'asc' ? valA.localeCompare(valB) : valB.localeCompare(valA);
case 'cpu':
valA = a.cpuPercent || 0;
valB = b.cpuPercent || 0;
valA = a.cpuPercent ?? 0;
valB = b.cpuPercent ?? 0;
break;
case 'mem':
valA = a.memTotal > 0 ? (a.memUsed / a.memTotal) : 0;
@@ -607,21 +644,25 @@
valB = b.diskTotal > 0 ? (b.diskUsed / b.diskTotal) : 0;
break;
case 'netRx':
valA = a.netRx || 0;
valB = b.netRx || 0;
valA = a.netRx ?? 0;
valB = b.netRx ?? 0;
break;
case 'netTx':
valA = a.netTx || 0;
valB = b.netTx || 0;
valA = a.netTx ?? 0;
valB = b.netTx ?? 0;
break;
default:
valA = a.job || '';
valB = b.job || '';
valA = (a.job || '').toLowerCase();
valB = (b.job || '').toLowerCase();
return valA.localeCompare(valB);
}
if (currentSort.direction === 'asc') return valA - valB;
return valB - valA;
// Numeric comparison
if (valA === valB) {
// If values are same, secondary fallback to job name for stable sort
return (a.job || '').localeCompare(b.job || '');
}
return dir === 'asc' ? valA - valB : valB - valA;
});
const totalFiltered = filtered.length;
@@ -668,15 +709,43 @@
renderFilteredServers();
};
function resetSort() {
currentSort = { column: 'up', direction: 'desc' };
localStorage.removeItem('serverListSort');
// Update UI headers
const headers = document.querySelectorAll('.server-table th.sortable');
headers.forEach(th => {
const col = th.getAttribute('data-sort');
if (col === currentSort.column) {
th.classList.add('active');
th.setAttribute('data-dir', currentSort.direction);
} else {
th.classList.remove('active');
th.removeAttribute('data-dir');
}
});
renderFilteredServers();
}
function handleHeaderSort(column) {
if (currentSort.column === column) {
// Toggle direction
currentSort.direction = currentSort.direction === 'asc' ? 'desc' : 'asc';
if (currentSort.direction === 'desc') {
currentSort.direction = 'asc';
} else {
// Cycle back to default (Status desc)
resetSort();
return;
}
} else {
currentSort.column = column;
currentSort.direction = 'desc'; // Default to desc for most metrics
}
// Persist sort state
localStorage.setItem('serverListSort', JSON.stringify(currentSort));
// Update UI headers
const headers = document.querySelectorAll('.server-table th.sortable');
headers.forEach(th => {