import { type ClassValue, clsx } from 'clsx'; // 合并 CSS 类名 export function cn(...inputs: ClassValue[]) { return clsx(inputs); } // 格式化货币 export function formatCurrency(amount: number, currency: 'CNY' | 'USD' = 'CNY') { return new Intl.NumberFormat('zh-CN', { style: 'currency', currency: currency, }).format(amount); } // 格式化时间 export function formatTime(date: string | Date) { return new Intl.DateTimeFormat('zh-CN', { year: 'numeric', month: '2-digit', day: '2-digit', hour: '2-digit', minute: '2-digit', }).format(new Date(date)); } // 格式化相对时间 export function formatRelativeTime(date: string | Date) { const now = new Date(); const target = new Date(date); const diffInSeconds = Math.floor((now.getTime() - target.getTime()) / 1000); if (diffInSeconds < 60) { return `${diffInSeconds}秒前`; } else if (diffInSeconds < 3600) { return `${Math.floor(diffInSeconds / 60)}分钟前`; } else if (diffInSeconds < 86400) { return `${Math.floor(diffInSeconds / 3600)}小时前`; } else if (diffInSeconds < 2592000) { return `${Math.floor(diffInSeconds / 86400)}天前`; } else { return formatTime(date); } } // 格式化通话时长 export function formatDuration(seconds: number) { const hours = Math.floor(seconds / 3600); const minutes = Math.floor((seconds % 3600) / 60); const remainingSeconds = seconds % 60; if (hours > 0) { return `${hours}:${minutes.toString().padStart(2, '0')}:${remainingSeconds.toString().padStart(2, '0')}`; } else { return `${minutes}:${remainingSeconds.toString().padStart(2, '0')}`; } } // 格式化文件大小 export function formatFileSize(bytes: number) { const sizes = ['B', 'KB', 'MB', 'GB']; if (bytes === 0) return '0 B'; const i = Math.floor(Math.log(bytes) / Math.log(1024)); return Math.round(bytes / Math.pow(1024, i) * 100) / 100 + ' ' + sizes[i]; } // 生成随机ID export function generateId() { return Math.random().toString(36).substring(2, 15) + Math.random().toString(36).substring(2, 15); } // 防抖函数 export function debounce any>( func: T, wait: number ): (...args: Parameters) => void { let timeout: NodeJS.Timeout; return (...args: Parameters) => { clearTimeout(timeout); timeout = setTimeout(() => func(...args), wait); }; } // 节流函数 export function throttle any>( func: T, limit: number ): (...args: Parameters) => void { let inThrottle: boolean; return (...args: Parameters) => { if (!inThrottle) { func(...args); inThrottle = true; setTimeout(() => (inThrottle = false), limit); } }; } // 深拷贝 export function 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 clonedObj = {} as any; for (const key in obj) { if (obj.hasOwnProperty(key)) { clonedObj[key] = deepClone(obj[key]); } } return clonedObj; } return obj; } // 验证邮箱 export function isValidEmail(email: string): boolean { const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/; return emailRegex.test(email); } // 验证手机号 export function isValidPhone(phone: string): boolean { const phoneRegex = /^1[3-9]\d{9}$/; return phoneRegex.test(phone); } // 获取通话状态的中文描述 export function getCallStatusText(status: string): string { const statusMap: Record = { pending: '等待中', active: '通话中', ended: '已结束', cancelled: '已取消', failed: '失败', }; return statusMap[status] || status; } // 获取通话模式的中文描述 export function getCallModeText(mode: string): string { const modeMap: Record = { ai_voice: 'AI语音', ai_video: 'AI视频', sign_language: '手语翻译', human_interpreter: '真人翻译', }; return modeMap[mode] || mode; } // 获取用户类型的中文描述 export function getUserTypeText(type: string): string { const typeMap: Record = { individual: '个人用户', enterprise: '企业用户', }; return typeMap[type] || type; } // 获取订单状态的中文描述 export function getOrderStatusText(status: string): string { const statusMap: Record = { pending: '待处理', completed: '已完成', cancelled: '已取消', refunded: '已退款', }; return statusMap[status] || status; } // 获取文档翻译状态的中文描述 export function getDocumentStatusText(status: string): string { const statusMap: Record = { uploaded: '已上传', processing: '处理中', completed: '已完成', failed: '失败', }; return statusMap[status] || status; } // 计算通话费用(按分钟向上取整) export function calculateCallCost(durationInSeconds: number, ratePerMinute: number): number { const minutes = Math.ceil(durationInSeconds / 60); return minutes * ratePerMinute; } // 检查余额是否足够 export function checkBalanceSufficient(balance: number, requiredAmount: number): boolean { return balance >= requiredAmount; } // 获取颜色类名基于状态 export function getStatusColor(status: string): string { const colorMap: Record = { active: 'text-green-600 bg-green-100', pending: 'text-yellow-600 bg-yellow-100', ended: 'text-gray-600 bg-gray-100', cancelled: 'text-red-600 bg-red-100', failed: 'text-red-600 bg-red-100', completed: 'text-green-600 bg-green-100', processing: 'text-blue-600 bg-blue-100', uploaded: 'text-purple-600 bg-purple-100', }; return colorMap[status] || 'text-gray-600 bg-gray-100'; } // 安全地解析JSON export function safeJsonParse(str: string, fallback: T): T { try { return JSON.parse(str); } catch (error) { return fallback; } } // 生成头像URL export function generateAvatarUrl(name: string): string { const firstChar = name.charAt(0).toUpperCase(); return `https://ui-avatars.com/api/?name=${encodeURIComponent(firstChar)}&background=random&color=fff&size=40`; } // 导出所有状态文本映射 export const STATUS_TEXTS = { CALL_STATUS: { pending: '等待中', active: '通话中', ended: '已结束', cancelled: '已取消', failed: '失败', }, CALL_MODE: { ai_voice: 'AI语音', ai_video: 'AI视频', sign_language: '手语翻译', human_interpreter: '真人翻译', }, USER_TYPE: { individual: '个人用户', enterprise: '企业用户', }, ORDER_STATUS: { pending: '待处理', completed: '已完成', cancelled: '已取消', refunded: '已退款', }, DOCUMENT_STATUS: { uploaded: '已上传', processing: '处理中', completed: '已完成', failed: '失败', }, NOTIFICATION_TYPE: { info: '信息', warning: '警告', error: '错误', success: '成功', }, } as const;