/** * 格式化工具函数 */ // 相对时间映射 const RELATIVE = (diff) => { if (diff < 60000) return '刚刚' if (diff < 3600000) return `${Math.floor(diff / 60000)} 分钟前` if (diff < 86400000) return `${Math.floor(diff / 3600000)} 小时前` return `${Math.floor(diff / 86400000)} 天前` } /** * 格式化日期 (MMDDHHMM) * @param {string|Date} date - 日期 * @param {string} format - 格式 ('short', 'long', 'relative') */ export const formatDate = (date, format = 'short') => { if (!date) return '未知时间' const d = new Date(date) if (isNaN(d.getTime())) return '无效日期' if (format === 'relative') return RELATIVE(new Date() - d) const pad = (n) => String(n).padStart(2, '0') return `${pad(d.getMonth() + 1)}-${pad(d.getDate())} ${pad(d.getHours())}:${pad(d.getMinutes())}` } /** * 格式化数字 * @param {number} num - 数字 * @param {Object} options - 配置 */ export const formatNumber = (num, options = {}) => { if (typeof num !== 'number') return num const { decimals = 0, thousands = true, suffix = '' } = options return new Intl.NumberFormat('zh-CN', { minimumFractionDigits: decimals, maximumFractionDigits: decimals, useGrouping: thousands }).format(num) + suffix } /** * 截断文本 */ export const truncate = (text, maxLength = 50, suffix = '...') => !text || text.length <= maxLength ? text : text.slice(0, maxLength - suffix.length) + suffix /** * 格式化文件大小 */ export const formatFileSize = (bytes) => { if (!bytes) return '0 B' const k = 1024, sizes = ['B', 'KB', 'MB', 'GB', 'TB'] const i = Math.floor(Math.log(bytes) / Math.log(k)) return `${(bytes / Math.pow(k, i)).toFixed(2)} ${sizes[i]}` } /** * 首字母大写 */ export const capitalize = (str) => str ? str.replace(/^./, c => c.toUpperCase()) : '' /** * 格式化令牌数 */ export const formatTokens = (tokens) => tokens >= 1e6 ? `${(tokens / 1e6).toFixed(1)}M` : tokens >= 1e3 ? `${(tokens / 1e3).toFixed(1)}K` : String(tokens)