/** * 格式化时间 * @param dateString - ISO 时间字符串 * @returns 格式化后的时间字符串 */ export const formatTime = (dateString: string): string => { if (!dateString) return ''; const date = new Date(dateString); const now = new Date(); const diffInSeconds = Math.floor((now.getTime() - date.getTime()) / 1000); if (diffInSeconds < 60) { return '刚刚'; } else if (diffInSeconds < 3600) { const minutes = Math.floor(diffInSeconds / 60); return `${minutes}分钟前`; } else if (diffInSeconds < 86400) { const hours = Math.floor(diffInSeconds / 3600); return `${hours}小时前`; } else if (diffInSeconds < 604800) { const days = Math.floor(diffInSeconds / 86400); return `${days}天前`; } else { return date.toLocaleDateString('zh-CN', { year: 'numeric', month: '2-digit', day: '2-digit', hour: '2-digit', minute: '2-digit' }); } }; /** * 格式化货币 * @param amount - 金额 * @returns 格式化后的货币字符串 */ export const formatCurrency = (amount: number): string => { return new Intl.NumberFormat('zh-CN', { style: 'currency', currency: 'CNY' }).format(amount); }; /** * 格式化文件大小 * @param bytes - 字节数 * @returns 格式化后的文件大小字符串 */ export const formatFileSize = (bytes: number): string => { if (bytes === 0) return '0 Bytes'; const k = 1024; const sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB']; const i = Math.floor(Math.log(bytes) / Math.log(k)); return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i]; }; /** * 生成随机字符串 * @param length - 字符串长度 * @returns 随机字符串 */ export const generateRandomString = (length: number): string => { const characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'; let result = ''; for (let i = 0; i < length; i++) { result += characters.charAt(Math.floor(Math.random() * characters.length)); } return result; }; /** * 防抖函数 * @param func - 要防抖的函数 * @param wait - 等待时间(毫秒) * @returns 防抖后的函数 */ export const debounce = any>( func: T, wait: number ): ((...args: Parameters) => void) => { let timeout: NodeJS.Timeout; return (...args: Parameters) => { clearTimeout(timeout); timeout = setTimeout(() => func.apply(null, args), wait); }; }; /** * 节流函数 * @param func - 要节流的函数 * @param limit - 限制时间(毫秒) * @returns 节流后的函数 */ export const throttle = any>( func: T, limit: number ): ((...args: Parameters) => void) => { let inThrottle: boolean; return (...args: Parameters) => { if (!inThrottle) { func.apply(null, args); inThrottle = true; setTimeout(() => (inThrottle = false), limit); } }; }; /** * 深拷贝对象 * @param obj - 要拷贝的对象 * @returns 拷贝后的对象 */ export const deepClone = (obj: T): T => { if (obj === null || typeof obj !== 'object') { return obj; } if (obj instanceof Date) { return new Date(obj.getTime()) as any; } if (obj instanceof Array) { return obj.map(item => deepClone(item)) as any; } if (typeof obj === 'object') { const cloned = {} as any; Object.keys(obj).forEach(key => { cloned[key] = deepClone((obj as any)[key]); }); return cloned; } return obj; }; /** * 获取查询参数 * @param url - URL 字符串 * @returns 查询参数对象 */ export const getQueryParams = (url: string): Record => { const params: Record = {}; const urlObj = new URL(url); urlObj.searchParams.forEach((value, key) => { params[key] = value; }); return params; }; /** * 验证邮箱格式 * @param email - 邮箱地址 * @returns 是否为有效邮箱 */ export const validateEmail = (email: string): boolean => { const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/; return emailRegex.test(email); }; /** * 验证手机号格式 * @param phone - 手机号 * @returns 是否为有效手机号 */ export const validatePhone = (phone: string): boolean => { const phoneRegex = /^1[3-9]\d{9}$/; return phoneRegex.test(phone); };