Spaces:
Sleeping
Sleeping
| /** | |
| * 通用辅助工具函数 | |
| */ | |
| /** | |
| * 生成唯一ID | |
| * @returns 唯一ID字符串 | |
| */ | |
| export const generateId = (): string => { | |
| return Date.now().toString(36) + Math.random().toString(36).substring(2); | |
| }; | |
| /** | |
| * 格式化日期为本地字符串 | |
| * @param date 日期对象或日期字符串 | |
| * @param options 格式化选项 | |
| * @returns 格式化后的日期字符串 | |
| */ | |
| export const formatDate = ( | |
| date: Date | string, | |
| options: Intl.DateTimeFormatOptions = { | |
| year: 'numeric', | |
| month: 'long', | |
| day: 'numeric' | |
| } | |
| ): string => { | |
| const dateObj = date instanceof Date ? date : new Date(date); | |
| return dateObj.toLocaleDateString('zh-CN', options); | |
| }; | |
| /** | |
| * 格式化日期和时间为本地字符串 | |
| * @param date 日期对象或日期字符串 | |
| * @returns 格式化后的日期和时间字符串 | |
| */ | |
| export const formatDateTime = (date: Date | string): string => { | |
| const dateObj = date instanceof Date ? date : new Date(date); | |
| return dateObj.toLocaleDateString('zh-CN', { | |
| year: 'numeric', | |
| month: 'long', | |
| day: 'numeric', | |
| hour: '2-digit', | |
| minute: '2-digit' | |
| }); | |
| }; | |
| /** | |
| * 截断文本到指定长度 | |
| * @param text 需要截断的文本 | |
| * @param maxLength 最大长度 | |
| * @param suffix 省略号后缀,默认为"..." | |
| * @returns 截断后的文本 | |
| */ | |
| export const truncateText = ( | |
| text: string, | |
| maxLength: number, | |
| suffix: string = '...' | |
| ): string => { | |
| if (text.length <= maxLength) return text; | |
| return text.substring(0, maxLength) + suffix; | |
| }; | |
| /** | |
| * 深度克隆对象 | |
| * @param obj 需要克隆的对象 | |
| * @returns 克隆后的对象 | |
| */ | |
| export const deepClone = <T>(obj: T): T => { | |
| return JSON.parse(JSON.stringify(obj)); | |
| }; | |
| /** | |
| * 按属性对对象数组进行排序 | |
| * @param array 对象数组 | |
| * @param key 排序键 | |
| * @param ascending 是否升序,默认为true | |
| * @returns 排序后的数组 | |
| */ | |
| export const sortByProperty = <T>( | |
| array: T[], | |
| key: keyof T, | |
| ascending: boolean = true | |
| ): T[] => { | |
| return [...array].sort((a, b) => { | |
| const valueA = a[key]; | |
| const valueB = b[key]; | |
| if (valueA === valueB) return 0; | |
| // 处理日期对象 | |
| if (valueA instanceof Date && valueB instanceof Date) { | |
| return ascending ? valueA.getTime() - valueB.getTime() : valueB.getTime() - valueA.getTime(); | |
| } | |
| // 处理字符串 | |
| if (typeof valueA === 'string' && typeof valueB === 'string') { | |
| return ascending ? valueA.localeCompare(valueB) : valueB.localeCompare(valueA); | |
| } | |
| // 处理数字 | |
| if (typeof valueA === 'number' && typeof valueB === 'number') { | |
| return ascending ? valueA - valueB : valueB - valueA; | |
| } | |
| // 默认使用字符串比较 | |
| return ascending | |
| ? String(valueA).localeCompare(String(valueB)) | |
| : String(valueB).localeCompare(String(valueA)); | |
| }); | |
| }; | |
| /** | |
| * 延迟执行(Promise形式) | |
| * @param ms 延迟毫秒数 | |
| * @returns Promise | |
| */ | |
| export const delay = (ms: number): Promise<void> => { | |
| return new Promise(resolve => setTimeout(resolve, ms)); | |
| }; | |
| /** | |
| * 防抖函数 | |
| * @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 | null = null; | |
| return function (...args: Parameters<T>) { | |
| const later = () => { | |
| timeout = null; | |
| func(...args); | |
| }; | |
| if (timeout) clearTimeout(timeout); | |
| timeout = setTimeout(later, wait); | |
| }; | |
| } | |
| /** | |
| * 节流函数 | |
| * @param func 要执行的函数 | |
| * @param limit 时间限制(毫秒) | |
| * @returns 节流处理后的函数 | |
| */ | |
| export function throttle<T extends (...args: any[]) => any>( | |
| func: T, | |
| limit: number | |
| ): (...args: Parameters<T>) => void { | |
| let inThrottle = false; | |
| return function (...args: Parameters<T>) { | |
| if (!inThrottle) { | |
| func(...args); | |
| inThrottle = true; | |
| setTimeout(() => { | |
| inThrottle = false; | |
| }, limit); | |
| } | |
| }; | |
| } | |
| /** | |
| * 过滤对象数组 | |
| * @param array 对象数组 | |
| * @param searchTerm 搜索关键词 | |
| * @param keys 要搜索的属性键数组 | |
| * @returns 过滤后的数组 | |
| */ | |
| export const filterArrayBySearchTerm = <T>( | |
| array: T[], | |
| searchTerm: string, | |
| keys: (keyof T)[] | |
| ): T[] => { | |
| if (!searchTerm) return array; | |
| const lowercasedTerm = searchTerm.toLowerCase(); | |
| return array.filter(item => { | |
| return keys.some(key => { | |
| const value = item[key]; | |
| if (value == null) return false; | |
| return String(value).toLowerCase().includes(lowercasedTerm); | |
| }); | |
| }); | |
| }; | |
| /** | |
| * 分组对象数组 | |
| * @param array 对象数组 | |
| * @param key 分组键 | |
| * @returns 分组后的对象 | |
| */ | |
| export const groupBy = <T>(array: T[], key: keyof T): Record<string, T[]> => { | |
| return array.reduce((result, item) => { | |
| const groupKey = String(item[key]); | |
| if (!result[groupKey]) { | |
| result[groupKey] = []; | |
| } | |
| result[groupKey].push(item); | |
| return result; | |
| }, {} as Record<string, T[]>); | |
| }; | |
| /** | |
| * 检查对象是否为空 | |
| * @param obj 要检查的对象 | |
| * @returns 布尔值,指示对象是否为空 | |
| */ | |
| export const isEmptyObject = (obj: Record<string, any>): boolean => { | |
| return Object.keys(obj).length === 0; | |
| }; | |
| /** | |
| * 从数组中移除重复项 | |
| * @param array 数组 | |
| * @returns 去重后的数组 | |
| */ | |
| export const removeDuplicates = <T>(array: T[]): T[] => { | |
| return [...new Set(array)]; | |
| }; | |
| /** | |
| * 从日期对象获取YYYY-MM-DD格式的日期字符串 | |
| * @param date 日期对象 | |
| * @returns 格式化后的日期字符串 | |
| */ | |
| export const getFormattedDate = (date: Date): string => { | |
| const year = date.getFullYear(); | |
| const month = String(date.getMonth() + 1).padStart(2, '0'); | |
| const day = String(date.getDate()).padStart(2, '0'); | |
| return `${year}-${month}-${day}`; | |
| }; |