import { type ClassValue, clsx } from 'clsx'; import { twMerge } from 'tailwind-merge'; /** * 合并 Tailwind CSS 类名的工具函数 * @param inputs - 类名数组或对象 * @returns 合并后的类名字符串 */ export function cn(...inputs: ClassValue[]) { return twMerge(clsx(inputs)); } /** * 格式化日期 * @param date - 日期对象或字符串 * @param options - 格式化选项 * @returns 格式化后的日期字符串 */ export function formatDate( date: Date | string, options: Intl.DateTimeFormatOptions = {} ): string { const dateObj = typeof date === 'string' ? new Date(date) : date; return new Intl.DateTimeFormat('zh-CN', { year: 'numeric', month: 'long', day: 'numeric', ...options, }).format(dateObj); } /** * 格式化数字 * @param num - 数字 * @param options - 格式化选项 * @returns 格式化后的数字字符串 */ export function formatNumber( num: number, options: Intl.NumberFormatOptions = {} ): string { return new Intl.NumberFormat('zh-CN', options).format(num); } /** * 生成随机 ID * @param length - ID 长度 * @returns 随机 ID 字符串 */ export function generateId(length: number = 8): string { const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'; let result = ''; for (let i = 0; i < length; i++) { result += chars.charAt(Math.floor(Math.random() * chars.length)); } return result; } /** * 防抖函数 * @param func - 要防抖的函数 * @param wait - 等待时间(毫秒) * @returns 防抖后的函数 */ 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); }; } /** * 节流函数 * @param func - 要节流的函数 * @param limit - 时间限制(毫秒) * @returns 节流后的函数 */ 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); } }; } /** * 检查是否为移动设备 * @returns 是否为移动设备 */ export function isMobile(): boolean { if (typeof window === 'undefined') return false; return window.innerWidth < 768; } /** * 检查是否为暗色模式 * @returns 是否为暗色模式 */ export function isDarkMode(): boolean { if (typeof window === 'undefined') return false; return document.documentElement.classList.contains('dark'); } /** * 切换暗色模式 */ export function toggleDarkMode(): void { if (typeof window === 'undefined') return; document.documentElement.classList.toggle('dark'); localStorage.setItem('darkMode', document.documentElement.classList.contains('dark').toString()); } /** * 初始化暗色模式 */ export function initDarkMode(): void { if (typeof window === 'undefined') return; const saved = localStorage.getItem('darkMode'); const prefersDark = window.matchMedia('(prefers-color-scheme: dark)').matches; if (saved === 'true' || (saved === null && prefersDark)) { document.documentElement.classList.add('dark'); } }