完成Work组件的界面和一些小修改
> 1. 修改优化路由守卫
> 2. 去除拦截器中的调试信息
> 3. 修改头部导航条下拉菜单的样式增加图标。
> 4. work组件现在使用mock数据
Change-Id: Ic602a35bb02e645a0d5253c5cbd12a68d70bfb33
diff --git a/src/feature/work/utils.ts b/src/feature/work/utils.ts
new file mode 100644
index 0000000..a10d95f
--- /dev/null
+++ b/src/feature/work/utils.ts
@@ -0,0 +1,155 @@
+import type { RcFile } from 'antd/es/upload';
+
+// 将文件转换为Base64
+export const getBase64 = (file: RcFile): Promise<string> =>
+ new Promise((resolve, reject) => {
+ const reader = new FileReader();
+ reader.readAsDataURL(file);
+ reader.onload = () => resolve(reader.result as string);
+ reader.onerror = (error) => reject(error);
+ });
+
+// 验证图片文件
+interface ValidationResult {
+ valid: boolean;
+ message?: string;
+}
+
+export const validateImageFile = (file: RcFile): ValidationResult => {
+ const isImage = file.type.startsWith('image/');
+ if (!isImage) {
+ return { valid: false, message: '只能上传图片文件!' };
+ }
+
+ const isLt5M = file.size / 1024 / 1024 < 5;
+ if (!isLt5M) {
+ return { valid: false, message: '图片大小不能超过 5MB!' };
+ }
+
+ return { valid: true };
+};
+
+// 验证种子文件
+export const validateSeedFile = (file: RcFile): ValidationResult => {
+ const isLt100M = file.size / 1024 / 1024 < 100;
+ if (!isLt100M) {
+ return { valid: false, message: '种子文件大小不能超过 100MB!' };
+ }
+
+ return { valid: true };
+};
+
+// 格式化文件大小
+export const formatFileSize = (bytes: number): string => {
+ if (bytes === 0) return '0 Bytes';
+
+ const k = 1024;
+ const sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB'];
+ const i = Math.floor(Math.log(bytes) / Math.log(k));
+
+ return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];
+};
+
+// 防抖函数 - 修复版本
+export const debounce = <T extends (...args: unknown[]) => unknown>(
+ func: T,
+ wait: number
+): ((...args: Parameters<T>) => void) => {
+ let timeout: ReturnType<typeof setTimeout>;
+
+ return (...args: Parameters<T>) => {
+ clearTimeout(timeout);
+ timeout = setTimeout(() => func(...args), wait);
+ };
+};
+
+// 节流函数 - 修复版本
+export const throttle = <T extends (...args: unknown[]) => unknown>(
+ 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);
+ }
+ };
+};
+// 生成唯一ID
+export const generateId = (): string => {
+ return Date.now().toString(36) + Math.random().toString(36).substr(2);
+};
+
+// 安全的JSON解析
+export const safeJsonParse = <T>(str: string, defaultValue: T): T => {
+ try {
+ return JSON.parse(str) as T;
+ } catch {
+ return defaultValue;
+ }
+};
+
+// 检查是否为空值
+export const isEmpty = (value: unknown): boolean => {
+ if (value === null || value === undefined) return true;
+ if (typeof value === 'string') return value.trim() === '';
+ if (Array.isArray(value)) return value.length === 0;
+ if (typeof value === 'object') return Object.keys(value).length === 0;
+ return false;
+};
+
+// URL参数解析
+export const parseUrlParams = (url: string): Record<string, string> => {
+ const params: Record<string, string> = {};
+ const urlObj = new URL(url);
+
+ urlObj.searchParams.forEach((value, key) => {
+ params[key] = value;
+ });
+
+ return params;
+};
+
+// 时间格式化
+export const formatDate = (date: Date | string | number, format: string = 'YYYY-MM-DD HH:mm:ss'): string => {
+ const d = new Date(date);
+
+ const year = d.getFullYear();
+ const month = String(d.getMonth() + 1).padStart(2, '0');
+ const day = String(d.getDate()).padStart(2, '0');
+ const hours = String(d.getHours()).padStart(2, '0');
+ const minutes = String(d.getMinutes()).padStart(2, '0');
+ const seconds = String(d.getSeconds()).padStart(2, '0');
+
+ return format
+ .replace('YYYY', year.toString())
+ .replace('MM', month)
+ .replace('DD', day)
+ .replace('HH', hours)
+ .replace('mm', minutes)
+ .replace('ss', seconds);
+};
+
+// 相对时间格式化(例如:2小时前)
+export const formatRelativeTime = (date: Date | string | number): string => {
+ const now = new Date();
+ const target = new Date(date);
+ const diff = now.getTime() - target.getTime();
+
+ const seconds = Math.floor(diff / 1000);
+ const minutes = Math.floor(seconds / 60);
+ const hours = Math.floor(minutes / 60);
+ const days = Math.floor(hours / 24);
+ const months = Math.floor(days / 30);
+ const years = Math.floor(months / 12);
+
+ if (years > 0) return `${years}年前`;
+ if (months > 0) return `${months}个月前`;
+ if (days > 0) return `${days}天前`;
+ if (hours > 0) return `${hours}小时前`;
+ if (minutes > 0) return `${minutes}分钟前`;
+ return '刚刚';
+};
\ No newline at end of file