Files
PromdataPanel/public/js/utils.js
2026-04-06 02:09:34 +08:00

128 lines
3.1 KiB
JavaScript

/**
* Utility Functions
*/
/**
* Format bytes to human-readable string
*/
function formatBytes(bytes, decimals = 2) {
if (!bytes || bytes === 0) return '0 B';
const k = 1024;
const sizes = ['B', 'KB', 'MB', 'GB', 'TB', 'PB'];
let i = Math.floor(Math.log(Math.abs(bytes)) / Math.log(k));
i = Math.max(0, Math.min(i, sizes.length - 1));
const value = bytes / Math.pow(k, i);
return value.toFixed(decimals) + ' ' + sizes[i];
}
/**
* Format bytes per second to human-readable bandwidth
*/
function formatBandwidth(bytesPerSec, decimals = 2) {
if (!bytesPerSec || bytesPerSec === 0) return '0 B/s';
const k = 1024;
const sizes = ['B/s', 'KB/s', 'MB/s', 'GB/s', 'TB/s'];
let i = Math.floor(Math.log(Math.abs(bytesPerSec)) / Math.log(k));
i = Math.max(0, Math.min(i, sizes.length - 1));
const value = bytesPerSec / Math.pow(k, i);
return value.toFixed(decimals) + ' ' + sizes[i];
}
/**
* Convert bytes per second to MB/s (numeric string)
*/
function toMBps(bytesPerSec, decimals = 2) {
if (!bytesPerSec || bytesPerSec === 0) return '0.00';
const mbps = bytesPerSec / (1024 * 1024);
return mbps.toFixed(decimals);
}
/**
* Format percentage
*/
function formatPercent(value, decimals = 1) {
if (!value || isNaN(value)) return '0%';
return value.toFixed(decimals) + '%';
}
/**
* Format a timestamp to HH:MM
*/
function formatTime(timestamp) {
const d = new Date(timestamp);
return d.toLocaleTimeString('zh-CN', { hour: '2-digit', minute: '2-digit' });
}
/**
* Format full clock
*/
function formatClock() {
const now = new Date();
const date = now.toLocaleDateString('zh-CN', {
year: 'numeric',
month: '2-digit',
day: '2-digit'
});
const time = now.toLocaleTimeString('zh-CN', {
hour: '2-digit',
minute: '2-digit',
second: '2-digit'
});
return `${date} ${time}`;
}
/**
* Get color based on usage percentage
*/
function getUsageColor(percent) {
if (percent < 50) return '#10b981';
if (percent < 75) return '#f59e0b';
return '#f43f5e';
}
/**
* Smooth number animation
*/
function animateValue(element, start, end, duration = 600) {
const startTime = performance.now();
const diff = end - start;
function update(currentTime) {
const elapsed = currentTime - startTime;
const progress = Math.min(elapsed / duration, 1);
// Ease out cubic
const eased = 1 - Math.pow(1 - progress, 3);
const current = start + diff * eased;
if (element.dataset.format === 'percent') {
element.textContent = formatPercent(current);
} else if (element.dataset.format === 'bytes') {
element.textContent = formatBytes(current);
} else if (element.dataset.format === 'bandwidth') {
element.textContent = formatBandwidth(current);
} else {
element.textContent = Math.round(current);
}
if (progress < 1) {
requestAnimationFrame(update);
}
}
requestAnimationFrame(update);
}
/**
* Debounce function to limit execution frequency
*/
function debounce(fn, delay) {
let timer = null;
return function (...args) {
if (timer) clearTimeout(timer);
timer = setTimeout(() => {
fn.apply(this, args);
timer = null;
}, delay);
};
}