blob: a10d95f87365dbf594babcdcc7da0f1a76bf3fa3 [file] [log] [blame]
223010144ce05872025-06-08 22:33:28 +08001import type { RcFile } from 'antd/es/upload';
2
3// 将文件转换为Base64
4export const getBase64 = (file: RcFile): Promise<string> =>
5 new Promise((resolve, reject) => {
6 const reader = new FileReader();
7 reader.readAsDataURL(file);
8 reader.onload = () => resolve(reader.result as string);
9 reader.onerror = (error) => reject(error);
10 });
11
12// 验证图片文件
13interface ValidationResult {
14 valid: boolean;
15 message?: string;
16}
17
18export const validateImageFile = (file: RcFile): ValidationResult => {
19 const isImage = file.type.startsWith('image/');
20 if (!isImage) {
21 return { valid: false, message: '只能上传图片文件!' };
22 }
23
24 const isLt5M = file.size / 1024 / 1024 < 5;
25 if (!isLt5M) {
26 return { valid: false, message: '图片大小不能超过 5MB!' };
27 }
28
29 return { valid: true };
30};
31
32// 验证种子文件
33export const validateSeedFile = (file: RcFile): ValidationResult => {
34 const isLt100M = file.size / 1024 / 1024 < 100;
35 if (!isLt100M) {
36 return { valid: false, message: '种子文件大小不能超过 100MB!' };
37 }
38
39 return { valid: true };
40};
41
42// 格式化文件大小
43export const formatFileSize = (bytes: number): string => {
44 if (bytes === 0) return '0 Bytes';
45
46 const k = 1024;
47 const sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB'];
48 const i = Math.floor(Math.log(bytes) / Math.log(k));
49
50 return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];
51};
52
53// 防抖函数 - 修复版本
54export const debounce = <T extends (...args: unknown[]) => unknown>(
55 func: T,
56 wait: number
57): ((...args: Parameters<T>) => void) => {
58 let timeout: ReturnType<typeof setTimeout>;
59
60 return (...args: Parameters<T>) => {
61 clearTimeout(timeout);
62 timeout = setTimeout(() => func(...args), wait);
63 };
64};
65
66// 节流函数 - 修复版本
67export const throttle = <T extends (...args: unknown[]) => unknown>(
68 func: T,
69 limit: number
70): ((...args: Parameters<T>) => void) => {
71 let inThrottle: boolean;
72
73 return (...args: Parameters<T>) => {
74 if (!inThrottle) {
75 func(...args);
76 inThrottle = true;
77 setTimeout(() => inThrottle = false, limit);
78 }
79 };
80};
81// 生成唯一ID
82export const generateId = (): string => {
83 return Date.now().toString(36) + Math.random().toString(36).substr(2);
84};
85
86// 安全的JSON解析
87export const safeJsonParse = <T>(str: string, defaultValue: T): T => {
88 try {
89 return JSON.parse(str) as T;
90 } catch {
91 return defaultValue;
92 }
93};
94
95// 检查是否为空值
96export const isEmpty = (value: unknown): boolean => {
97 if (value === null || value === undefined) return true;
98 if (typeof value === 'string') return value.trim() === '';
99 if (Array.isArray(value)) return value.length === 0;
100 if (typeof value === 'object') return Object.keys(value).length === 0;
101 return false;
102};
103
104// URL参数解析
105export const parseUrlParams = (url: string): Record<string, string> => {
106 const params: Record<string, string> = {};
107 const urlObj = new URL(url);
108
109 urlObj.searchParams.forEach((value, key) => {
110 params[key] = value;
111 });
112
113 return params;
114};
115
116// 时间格式化
117export const formatDate = (date: Date | string | number, format: string = 'YYYY-MM-DD HH:mm:ss'): string => {
118 const d = new Date(date);
119
120 const year = d.getFullYear();
121 const month = String(d.getMonth() + 1).padStart(2, '0');
122 const day = String(d.getDate()).padStart(2, '0');
123 const hours = String(d.getHours()).padStart(2, '0');
124 const minutes = String(d.getMinutes()).padStart(2, '0');
125 const seconds = String(d.getSeconds()).padStart(2, '0');
126
127 return format
128 .replace('YYYY', year.toString())
129 .replace('MM', month)
130 .replace('DD', day)
131 .replace('HH', hours)
132 .replace('mm', minutes)
133 .replace('ss', seconds);
134};
135
136// 相对时间格式化(例如:2小时前)
137export const formatRelativeTime = (date: Date | string | number): string => {
138 const now = new Date();
139 const target = new Date(date);
140 const diff = now.getTime() - target.getTime();
141
142 const seconds = Math.floor(diff / 1000);
143 const minutes = Math.floor(seconds / 60);
144 const hours = Math.floor(minutes / 60);
145 const days = Math.floor(hours / 24);
146 const months = Math.floor(days / 30);
147 const years = Math.floor(months / 12);
148
149 if (years > 0) return `${years}年前`;
150 if (months > 0) return `${months}个月前`;
151 if (days > 0) return `${days}天前`;
152 if (hours > 0) return `${hours}小时前`;
153 if (minutes > 0) return `${minutes}分钟前`;
154 return '刚刚';
155};