Files
qiming/qiming-xagi-frontend-templates/packages/react-next/src/lib/utils.ts
2026-06-01 13:43:09 +08:00

135 lines
3.3 KiB
TypeScript

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<T extends (...args: any[]) => any>(
func: T,
wait: number
): (...args: Parameters<T>) => void {
let timeout: NodeJS.Timeout;
return (...args: Parameters<T>) => {
clearTimeout(timeout);
timeout = setTimeout(() => func(...args), wait);
};
}
/**
* 节流函数
* @param func - 要节流的函数
* @param limit - 时间限制(毫秒)
* @returns 节流后的函数
*/
export function throttle<T extends (...args: any[]) => any>(
func: T,
limit: number
): (...args: Parameters<T>) => void {
let inThrottle: boolean;
return (...args: Parameters<T>) => {
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');
}
}