export function formatNumber(num, precision = 2) { if (!num && num !== 0) return '--' return Number(num).toFixed(precision) } export function formatDate(date, format = 'YYYY-MM-DD HH:mm:ss') { if (!date) return '--' const d = new Date(date) const year = d.getFullYear() const month = String(d.getMonth() + 1).padStart(2, '0') const day = String(d.getDate()).padStart(2, '0') const hours = String(d.getHours()).padStart(2, '0') const minutes = String(d.getMinutes()).padStart(2, '0') const seconds = String(d.getSeconds()).padStart(2, '0') return format .replace('YYYY', year) .replace('MM', month) .replace('DD', day) .replace('HH', hours) .replace('mm', minutes) .replace('ss', seconds) } export function formatBytes(bytes, precision = 2) { if (!bytes || bytes === 0) return '0 B' const k = 1024 const sizes = ['B', 'KB', 'MB', 'GB', 'TB'] const i = Math.floor(Math.log(bytes) / Math.log(k)) return `${(bytes / Math.pow(k, i)).toFixed(precision)} ${sizes[i]}` } export function debounce(fn, delay = 300) { let timer = null return function (...args) { if (timer) clearTimeout(timer) timer = setTimeout(() => fn.apply(this, args), delay) } } export function throttle(fn, delay = 300) { let last = 0 return function (...args) { const now = Date.now() if (now - last > delay) { last = now fn.apply(this, args) } } }