sa2kit 1.2.0 → 1.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{UniversalFileService-CEZRJ87g.d.mts → UniversalFileService-BuHN-jrR.d.ts} +47 -259
- package/dist/{UniversalFileService-CEZRJ87g.d.ts → UniversalFileService-CGGzYeeF.d.mts} +47 -259
- package/dist/{chunk-3XG5OHFD.mjs → chunk-CIVO4R6N.mjs} +2 -2
- package/dist/{chunk-3XG5OHFD.mjs.map → chunk-CIVO4R6N.mjs.map} +1 -1
- package/dist/chunk-EV6BCVOQ.mjs +204 -0
- package/dist/chunk-EV6BCVOQ.mjs.map +1 -0
- package/dist/chunk-W35VTQAW.js +211 -0
- package/dist/chunk-W35VTQAW.js.map +1 -0
- package/dist/{chunk-HWJ34NL6.js → chunk-ZRAW3HXA.js} +2 -2
- package/dist/{chunk-HWJ34NL6.js.map → chunk-ZRAW3HXA.js.map} +1 -1
- package/dist/drizzle-schema-BNhqj2AZ.d.mts +1114 -0
- package/dist/drizzle-schema-BNhqj2AZ.d.ts +1114 -0
- package/dist/mmd/admin/index.d.mts +487 -0
- package/dist/mmd/admin/index.d.ts +487 -0
- package/dist/mmd/admin/index.js +871 -0
- package/dist/mmd/admin/index.js.map +1 -0
- package/dist/mmd/admin/index.mjs +822 -0
- package/dist/mmd/admin/index.mjs.map +1 -0
- package/dist/mmd/index.d.mts +4 -193
- package/dist/mmd/index.d.ts +4 -193
- package/dist/mmd/server/index.d.mts +138 -0
- package/dist/mmd/server/index.d.ts +138 -0
- package/dist/mmd/server/index.js +245 -0
- package/dist/mmd/server/index.js.map +1 -0
- package/dist/mmd/server/index.mjs +207 -0
- package/dist/mmd/server/index.mjs.map +1 -0
- package/dist/testYourself/index.d.mts +145 -0
- package/dist/testYourself/index.d.ts +145 -0
- package/dist/testYourself/index.js +1004 -0
- package/dist/testYourself/index.js.map +1 -0
- package/dist/testYourself/index.mjs +993 -0
- package/dist/testYourself/index.mjs.map +1 -0
- package/dist/types-Bc_p-zAR.d.mts +194 -0
- package/dist/types-Bc_p-zAR.d.ts +194 -0
- package/dist/types-CK4We_aI.d.mts +270 -0
- package/dist/types-CK4We_aI.d.ts +270 -0
- package/dist/universalFile/index.d.mts +3 -2
- package/dist/universalFile/index.d.ts +3 -2
- package/dist/universalFile/index.js +48 -10
- package/dist/universalFile/index.js.map +1 -1
- package/dist/universalFile/index.mjs +43 -5
- package/dist/universalFile/index.mjs.map +1 -1
- package/dist/universalFile/server/index.d.mts +3 -2
- package/dist/universalFile/server/index.d.ts +3 -2
- package/dist/universalFile/server/index.js +239 -7
- package/dist/universalFile/server/index.js.map +1 -1
- package/dist/universalFile/server/index.mjs +234 -2
- package/dist/universalFile/server/index.mjs.map +1 -1
- package/package.json +19 -1
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var
|
|
3
|
+
var chunkZRAW3HXA_js = require('../chunk-ZRAW3HXA.js');
|
|
4
4
|
require('../chunk-DGUM43GV.js');
|
|
5
5
|
var React = require('react');
|
|
6
6
|
var lucideReact = require('lucide-react');
|
|
@@ -411,8 +411,16 @@ var UniversalFileClient = class {
|
|
|
411
411
|
formData.append("processingOptions", JSON.stringify(fileInfo.processingOptions));
|
|
412
412
|
}
|
|
413
413
|
try {
|
|
414
|
+
console.log("\u{1F4E4} [UniversalFileClient] \u5F00\u59CB\u4E0A\u4F20\u6587\u4EF6:", {
|
|
415
|
+
url,
|
|
416
|
+
fileName: fileInfo.file.name,
|
|
417
|
+
fileSize: fileInfo.file.size,
|
|
418
|
+
moduleId: fileInfo.moduleId,
|
|
419
|
+
businessId: fileInfo.businessId
|
|
420
|
+
});
|
|
414
421
|
return await new Promise((resolve, reject) => {
|
|
415
422
|
const xhr = new XMLHttpRequest();
|
|
423
|
+
xhr.withCredentials = true;
|
|
416
424
|
xhr.upload.addEventListener("progress", (event) => {
|
|
417
425
|
if (event.lengthComputable && onProgress) {
|
|
418
426
|
const elapsedTime = Date.now() - startTime;
|
|
@@ -433,10 +441,17 @@ var UniversalFileClient = class {
|
|
|
433
441
|
}
|
|
434
442
|
});
|
|
435
443
|
xhr.addEventListener("load", () => {
|
|
444
|
+
console.log("\u{1F4E5} [UniversalFileClient] \u4E0A\u4F20\u54CD\u5E94:", {
|
|
445
|
+
status: xhr.status,
|
|
446
|
+
statusText: xhr.statusText,
|
|
447
|
+
responseLength: xhr.responseText?.length
|
|
448
|
+
});
|
|
436
449
|
if (xhr.status >= 200 && xhr.status < 300) {
|
|
437
450
|
try {
|
|
438
451
|
const response = JSON.parse(xhr.responseText);
|
|
439
|
-
|
|
452
|
+
console.log("\u2705 [UniversalFileClient] \u89E3\u6790\u54CD\u5E94\u6210\u529F:", response);
|
|
453
|
+
const fileData = response.file || response.data || response;
|
|
454
|
+
const fileMetadata = this.transformFileMetadataFromAPI(fileData);
|
|
440
455
|
if (onProgress) {
|
|
441
456
|
onProgress({
|
|
442
457
|
fileId: fileMetadata.id,
|
|
@@ -450,13 +465,16 @@ var UniversalFileClient = class {
|
|
|
450
465
|
}
|
|
451
466
|
resolve(fileMetadata);
|
|
452
467
|
} catch (error) {
|
|
468
|
+
console.error("\u274C [UniversalFileClient] \u89E3\u6790\u54CD\u5E94\u5931\u8D25:", error, xhr.responseText);
|
|
453
469
|
reject(new Error("\u89E3\u6790\u54CD\u5E94\u5931\u8D25"));
|
|
454
470
|
}
|
|
455
471
|
} else {
|
|
472
|
+
console.error("\u274C [UniversalFileClient] \u4E0A\u4F20\u5931\u8D25:", xhr.status, xhr.statusText, xhr.responseText);
|
|
456
473
|
reject(new Error(`\u4E0A\u4F20\u5931\u8D25: ${xhr.statusText}`));
|
|
457
474
|
}
|
|
458
475
|
});
|
|
459
|
-
xhr.addEventListener("error", () => {
|
|
476
|
+
xhr.addEventListener("error", (event) => {
|
|
477
|
+
console.error("\u274C [UniversalFileClient] \u7F51\u7EDC\u9519\u8BEF:", event);
|
|
460
478
|
if (onProgress) {
|
|
461
479
|
onProgress({
|
|
462
480
|
fileId: "",
|
|
@@ -469,7 +487,7 @@ var UniversalFileClient = class {
|
|
|
469
487
|
error: "\u7F51\u7EDC\u9519\u8BEF"
|
|
470
488
|
});
|
|
471
489
|
}
|
|
472
|
-
reject(new Error("\u4E0A\u4F20\u5931\u8D25"));
|
|
490
|
+
reject(new Error("\u4E0A\u4F20\u5931\u8D25: \u7F51\u7EDC\u9519\u8BEF"));
|
|
473
491
|
});
|
|
474
492
|
xhr.addEventListener("timeout", () => {
|
|
475
493
|
if (onProgress) {
|
|
@@ -578,9 +596,27 @@ var UniversalFileClient = class {
|
|
|
578
596
|
headers: this.getHeaders()
|
|
579
597
|
});
|
|
580
598
|
if (!response.ok) {
|
|
599
|
+
console.error("\u274C [UniversalFileClient] \u67E5\u8BE2\u6587\u4EF6\u5217\u8868\u5931\u8D25:", response.status, response.statusText);
|
|
581
600
|
throw new Error(`\u67E5\u8BE2\u6587\u4EF6\u5217\u8868\u5931\u8D25: ${response.statusText}`);
|
|
582
601
|
}
|
|
583
602
|
const data = await response.json();
|
|
603
|
+
console.log("\u{1F4E5} [UniversalFileClient] \u67E5\u8BE2\u6587\u4EF6\u5217\u8868\u54CD\u5E94:", {
|
|
604
|
+
itemsCount: data.items?.length,
|
|
605
|
+
total: data.total,
|
|
606
|
+
page: data.page
|
|
607
|
+
});
|
|
608
|
+
if (!data.items || !Array.isArray(data.items)) {
|
|
609
|
+
console.error("\u274C [UniversalFileClient] \u54CD\u5E94\u683C\u5F0F\u9519\u8BEF: items \u4E0D\u662F\u6570\u7EC4", data);
|
|
610
|
+
return {
|
|
611
|
+
items: [],
|
|
612
|
+
total: 0,
|
|
613
|
+
page: 1,
|
|
614
|
+
pageSize: 20,
|
|
615
|
+
totalPages: 0,
|
|
616
|
+
hasNext: false,
|
|
617
|
+
hasPrev: false
|
|
618
|
+
};
|
|
619
|
+
}
|
|
584
620
|
return {
|
|
585
621
|
items: data.items.map((item) => this.transformFileMetadataFromAPI(item)),
|
|
586
622
|
total: data.total,
|
|
@@ -692,7 +728,9 @@ var UniversalFileClient = class {
|
|
|
692
728
|
try {
|
|
693
729
|
const response = await fetch(url, {
|
|
694
730
|
...options,
|
|
695
|
-
signal: controller.signal
|
|
731
|
+
signal: controller.signal,
|
|
732
|
+
credentials: "include"
|
|
733
|
+
// 携带 cookie 用于授权
|
|
696
734
|
});
|
|
697
735
|
return response;
|
|
698
736
|
} catch (error) {
|
|
@@ -1005,23 +1043,23 @@ var FileUploader_default = FileUploader;
|
|
|
1005
1043
|
|
|
1006
1044
|
Object.defineProperty(exports, "CDNProviderError", {
|
|
1007
1045
|
enumerable: true,
|
|
1008
|
-
get: function () { return
|
|
1046
|
+
get: function () { return chunkZRAW3HXA_js.CDNProviderError; }
|
|
1009
1047
|
});
|
|
1010
1048
|
Object.defineProperty(exports, "FileProcessingError", {
|
|
1011
1049
|
enumerable: true,
|
|
1012
|
-
get: function () { return
|
|
1050
|
+
get: function () { return chunkZRAW3HXA_js.FileProcessingError; }
|
|
1013
1051
|
});
|
|
1014
1052
|
Object.defineProperty(exports, "FileServiceError", {
|
|
1015
1053
|
enumerable: true,
|
|
1016
|
-
get: function () { return
|
|
1054
|
+
get: function () { return chunkZRAW3HXA_js.FileServiceError; }
|
|
1017
1055
|
});
|
|
1018
1056
|
Object.defineProperty(exports, "FileUploadError", {
|
|
1019
1057
|
enumerable: true,
|
|
1020
|
-
get: function () { return
|
|
1058
|
+
get: function () { return chunkZRAW3HXA_js.FileUploadError; }
|
|
1021
1059
|
});
|
|
1022
1060
|
Object.defineProperty(exports, "StorageProviderError", {
|
|
1023
1061
|
enumerable: true,
|
|
1024
|
-
get: function () { return
|
|
1062
|
+
get: function () { return chunkZRAW3HXA_js.StorageProviderError; }
|
|
1025
1063
|
});
|
|
1026
1064
|
exports.ALL_SUPPORTED_MIME_TYPES = ALL_SUPPORTED_MIME_TYPES;
|
|
1027
1065
|
exports.API_BASE_PATH = API_BASE_PATH;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/universalFile/constants.ts","../../src/universalFile/utils.ts","../../src/universalFile/client.ts","../../src/universalFile/components/FileUploader.tsx"],"names":["useState","useRef","React","Image","Film","Music","FileText","validateFile","useCallback","error","formatFileSize","Upload","AlertCircle","CheckCircle2","Loader2","X"],"mappings":"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","file":"index.js","sourcesContent":["/**\n * 通用文件服务常量定义\n */\n\n// ============= 版本信息 =============\n\n/** 模块版本 */\nexport const UNIVERSAL_FILE_VERSION = '1.0.0';\n\n/** 模块名称 */\nexport const UNIVERSAL_FILE_NAME = '@qhr123/sa2kit/universalFile';\n\n// ============= 文件大小限制 =============\n\n/** 默认最大文件大小(字节) - 100MB */\nexport const DEFAULT_MAX_FILE_SIZE = 100 * 1024 * 1024;\n\n/** 默认最大图片大小(字节) - 10MB */\nexport const DEFAULT_MAX_IMAGE_SIZE = 10 * 1024 * 1024;\n\n/** 默认最大视频大小(字节) - 500MB */\nexport const DEFAULT_MAX_VIDEO_SIZE = 500 * 1024 * 1024;\n\n/** 默认最大音频大小(字节) - 50MB */\nexport const DEFAULT_MAX_AUDIO_SIZE = 50 * 1024 * 1024;\n\n/** 默认最大文档大小(字节) - 20MB */\nexport const DEFAULT_MAX_DOCUMENT_SIZE = 20 * 1024 * 1024;\n\n// ============= MIME类型 =============\n\n/** 图片MIME类型 */\nexport const IMAGE_MIME_TYPES = [\n 'image/jpeg',\n 'image/jpg',\n 'image/png',\n 'image/gif',\n 'image/webp',\n 'image/svg+xml',\n];\n\n/** 视频MIME类型 */\nexport const VIDEO_MIME_TYPES = [\n 'video/mp4',\n 'video/mpeg',\n 'video/quicktime',\n 'video/x-msvideo',\n 'video/webm',\n];\n\n/** 音频MIME类型 */\nexport const AUDIO_MIME_TYPES = ['audio/mpeg', 'audio/mp3', 'audio/wav', 'audio/ogg', 'audio/aac'];\n\n/** 文档MIME类型 */\nexport const DOCUMENT_MIME_TYPES = [\n 'application/pdf',\n 'application/msword',\n 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',\n 'application/vnd.ms-excel',\n 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',\n 'application/vnd.ms-powerpoint',\n 'application/vnd.openxmlformats-officedocument.presentationml.presentation',\n 'text/plain',\n];\n\n/** 所有支持的MIME类型 */\nexport const ALL_SUPPORTED_MIME_TYPES = [\n ...IMAGE_MIME_TYPES,\n ...VIDEO_MIME_TYPES,\n ...AUDIO_MIME_TYPES,\n ...DOCUMENT_MIME_TYPES,\n];\n\n// ============= 文件扩展名 =============\n\n/** 图片扩展名 */\nexport const IMAGE_EXTENSIONS = ['.jpg', '.jpeg', '.png', '.gif', '.webp', '.svg'];\n\n/** 视频扩展名 */\nexport const VIDEO_EXTENSIONS = ['.mp4', '.mpeg', '.mov', '.avi', '.webm'];\n\n/** 音频扩展名 */\nexport const AUDIO_EXTENSIONS = ['.mp3', '.wav', '.ogg', '.aac'];\n\n/** 文档扩展名 */\nexport const DOCUMENT_EXTENSIONS = [\n '.pdf',\n '.doc',\n '.docx',\n '.xls',\n '.xlsx',\n '.ppt',\n '.pptx',\n '.txt',\n];\n\n// ============= API端点 =============\n\n/** API基础路径 */\nexport const API_BASE_PATH = '/api/universal-file';\n\n/** API端点 */\nexport const API_ENDPOINTS = {\n /** 上传文件 */\n UPLOAD: `${API_BASE_PATH}/upload`,\n /** 获取文件URL */\n GET_URL: (fileId: string) => `${API_BASE_PATH}/files/${fileId}/url`,\n /** 获取文件元数据 */\n GET_METADATA: (fileId: string) => `${API_BASE_PATH}/files/${fileId}`,\n /** 删除文件 */\n DELETE: (fileId: string) => `${API_BASE_PATH}/files/${fileId}`,\n /** 查询文件列表 */\n QUERY: `${API_BASE_PATH}/files`,\n /** 批量删除 */\n BATCH_DELETE: `${API_BASE_PATH}/files/batch-delete`,\n /** 获取上传进度 */\n GET_PROGRESS: (fileId: string) => `${API_BASE_PATH}/upload/${fileId}/progress`,\n} as const;\n\n// ============= 错误代码 =============\n\n/** 错误代码 */\nexport const ERROR_CODES = {\n /** 文件上传错误 */\n FILE_UPLOAD_ERROR: 'FILE_UPLOAD_ERROR',\n /** 文件大小超限 */\n FILE_SIZE_EXCEEDED: 'FILE_SIZE_EXCEEDED',\n /** 文件类型不支持 */\n FILE_TYPE_NOT_SUPPORTED: 'FILE_TYPE_NOT_SUPPORTED',\n /** 文件不存在 */\n FILE_NOT_FOUND: 'FILE_NOT_FOUND',\n /** 文件处理错误 */\n FILE_PROCESSING_ERROR: 'FILE_PROCESSING_ERROR',\n /** 存储提供者错误 */\n STORAGE_PROVIDER_ERROR: 'STORAGE_PROVIDER_ERROR',\n /** CDN提供者错误 */\n CDN_PROVIDER_ERROR: 'CDN_PROVIDER_ERROR',\n /** 网络错误 */\n NETWORK_ERROR: 'NETWORK_ERROR',\n /** 超时错误 */\n TIMEOUT_ERROR: 'TIMEOUT_ERROR',\n /** 未授权 */\n UNAUTHORIZED: 'UNAUTHORIZED',\n /** 权限不足 */\n FORBIDDEN: 'FORBIDDEN',\n /** 服务器错误 */\n SERVER_ERROR: 'SERVER_ERROR',\n} as const;\n\n// ============= 默认配置 =============\n\n/** 默认分页大小 */\nexport const DEFAULT_PAGE_SIZE = 20;\n\n/** 默认请求超时时间(毫秒) - 30秒 */\nexport const DEFAULT_REQUEST_TIMEOUT = 30000;\n\n/** 默认上传超时时间(毫秒) - 5分钟 */\nexport const DEFAULT_UPLOAD_TIMEOUT = 300000;\n\n/** 默认分片上传大小(字节) - 5MB */\nexport const DEFAULT_CHUNK_SIZE = 5 * 1024 * 1024;\n","/**\n * 通用文件服务工具函数\n */\n\nimport {\n IMAGE_MIME_TYPES,\n VIDEO_MIME_TYPES,\n AUDIO_MIME_TYPES,\n DOCUMENT_MIME_TYPES,\n} from './constants';\n\n// ============= 文件大小处理 =============\n\n/**\n * 格式化文件大小\n */\nexport function formatFileSize(bytes: number): string {\n if (bytes === 0) return '0 B';\n\n const units = ['B', 'KB', 'MB', 'GB', 'TB'];\n const k = 1024;\n const i = Math.floor(Math.log(bytes) / Math.log(k));\n\n return `${(bytes / Math.pow(k, i)).toFixed(2)} ${units[i]}`;\n}\n\n/**\n * 解析文件大小字符串\n */\nexport function parseFileSize(sizeStr: string): number {\n const match = sizeStr.match(/^(\\d+(?:\\.\\d+)?)\\s*([KMGT]?B)$/i);\n if (!match || !match[1] || !match[2]) return 0;\n\n const value = parseFloat(match[1]);\n const unit = match[2].toUpperCase();\n\n const units: Record<string, number> = {\n B: 1,\n KB: 1024,\n MB: 1024 * 1024,\n GB: 1024 * 1024 * 1024,\n TB: 1024 * 1024 * 1024 * 1024,\n };\n\n return value * (units[unit] || 1);\n}\n\n// ============= MIME类型处理 =============\n\n/**\n * 获取文件扩展名\n */\nexport function getFileExtension(fileName: string): string {\n const lastDot = fileName.lastIndexOf('.');\n if (lastDot === -1) return '';\n return fileName.substring(lastDot).toLowerCase();\n}\n\n/**\n * 根据文件名获取MIME类型\n */\nexport function getMimeTypeFromFileName(fileName: string): string {\n const ext = getFileExtension(fileName);\n\n const mimeMap: Record<string, string> = {\n '.jpg': 'image/jpeg',\n '.jpeg': 'image/jpeg',\n '.png': 'image/png',\n '.gif': 'image/gif',\n '.webp': 'image/webp',\n '.svg': 'image/svg+xml',\n '.pdf': 'application/pdf',\n '.txt': 'text/plain',\n '.mp4': 'video/mp4',\n '.avi': 'video/x-msvideo',\n '.mov': 'video/quicktime',\n '.mp3': 'audio/mpeg',\n '.wav': 'audio/wav',\n '.ogg': 'audio/ogg',\n '.doc': 'application/msword',\n '.docx': 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',\n '.xls': 'application/vnd.ms-excel',\n '.xlsx': 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',\n };\n\n return mimeMap[ext] || 'application/octet-stream';\n}\n\n/**\n * 检查MIME类型是否支持\n */\nexport function isMimeTypeSupported(mimeType: string, allowedTypes?: string[]): boolean {\n if (allowedTypes && allowedTypes.length > 0) {\n return allowedTypes.includes(mimeType);\n }\n\n return (\n IMAGE_MIME_TYPES.includes(mimeType) ||\n VIDEO_MIME_TYPES.includes(mimeType) ||\n AUDIO_MIME_TYPES.includes(mimeType) ||\n DOCUMENT_MIME_TYPES.includes(mimeType)\n );\n}\n\n/**\n * 判断是否为图片类型\n */\nexport function isImageFile(mimeType: string): boolean {\n return IMAGE_MIME_TYPES.includes(mimeType);\n}\n\n/**\n * 判断是否为视频类型\n */\nexport function isVideoFile(mimeType: string): boolean {\n return VIDEO_MIME_TYPES.includes(mimeType);\n}\n\n/**\n * 判断是否为音频类型\n */\nexport function isAudioFile(mimeType: string): boolean {\n return AUDIO_MIME_TYPES.includes(mimeType);\n}\n\n/**\n * 判断是否为文档类型\n */\nexport function isDocumentFile(mimeType: string): boolean {\n return DOCUMENT_MIME_TYPES.includes(mimeType);\n}\n\n/**\n * 获取文件类型类别\n */\nexport function getFileCategory(\n mimeType: string\n): 'image' | 'video' | 'audio' | 'document' | 'other' {\n if (isImageFile(mimeType)) return 'image';\n if (isVideoFile(mimeType)) return 'video';\n if (isAudioFile(mimeType)) return 'audio';\n if (isDocumentFile(mimeType)) return 'document';\n return 'other';\n}\n\n// ============= 文件名处理 =============\n\n/**\n * 验证文件名是否合法\n */\nexport function validateFileName(fileName: string): boolean {\n // 检查是否包含非法字符\n const invalidChars = /[<>:\"|?*\\/\\\\]/;\n if (invalidChars.test(fileName)) {\n return false;\n }\n\n // 检查长度\n if (fileName.length === 0 || fileName.length > 255) {\n return false;\n }\n\n // 检查是否以点开头\n if (fileName.startsWith('.')) {\n return false;\n }\n\n return true;\n}\n\n/**\n * 清理文件名,移除非法字符\n */\nexport function sanitizeFileName(fileName: string): string {\n return fileName\n .replace(/[<>:\"|?*\\/\\\\]/g, '_')\n .replace(/^\\.+/, '')\n .substring(0, 255);\n}\n\n/**\n * 生成唯一文件名\n */\nexport function generateUniqueFileName(originalName: string, fileId: string): string {\n const ext = getFileExtension(originalName);\n return `${fileId}${ext}`;\n}\n\n// ============= 存储路径处理 =============\n\n/**\n * 生成存储路径\n */\nexport function generateStoragePath(\n moduleId: string,\n fileName: string,\n options?: {\n businessId?: string;\n useDate?: boolean;\n customPrefix?: string;\n }\n): string {\n const parts: string[] = [];\n\n // 添加自定义前缀\n if (options?.customPrefix) {\n parts.push(options.customPrefix);\n }\n\n // 添加模块标识\n parts.push(moduleId);\n\n // 添加业务标识\n if (options?.businessId) {\n parts.push(options.businessId);\n }\n\n // 添加日期路径\n if (options?.useDate !== false) {\n const date = new Date();\n const year = date.getFullYear();\n const month = String(date.getMonth() + 1).padStart(2, '0');\n const day = String(date.getDate()).padStart(2, '0');\n parts.push(String(year), month, day);\n }\n\n // 添加文件名\n parts.push(fileName);\n\n return parts.join('/');\n}\n\n/**\n * 解析存储路径\n */\nexport function parseStoragePath(path: string): {\n moduleId?: string;\n businessId?: string;\n year?: string;\n month?: string;\n day?: string;\n fileName: string;\n} {\n const parts = path.split('/');\n const fileName = parts[parts.length - 1] || '';\n\n return {\n moduleId: parts[0] || undefined,\n businessId: parts.length > 5 ? parts[1] : undefined,\n year: parts.length > 3 ? parts[parts.length - 4] : undefined,\n month: parts.length > 2 ? parts[parts.length - 3] : undefined,\n day: parts.length > 1 ? parts[parts.length - 2] : undefined,\n fileName,\n };\n}\n\n// ============= 文件验证 =============\n\n/**\n * 验证文件大小\n */\nexport function validateFileSize(file: File, maxSize: number): { valid: boolean; error?: string } {\n if (file.size > maxSize) {\n return {\n valid: false,\n error: `文件大小超过限制: ${formatFileSize(file.size)} > ${formatFileSize(maxSize)}`,\n };\n }\n\n return { valid: true };\n}\n\n/**\n * 验证文件类型\n */\nexport function validateFileType(\n file: File,\n allowedTypes?: string[]\n): { valid: boolean; error?: string } {\n const mimeType = file.type || getMimeTypeFromFileName(file.name);\n\n if (!isMimeTypeSupported(mimeType, allowedTypes)) {\n return {\n valid: false,\n error: `不支持的文件类型: ${mimeType}`,\n };\n }\n\n return { valid: true };\n}\n\n/**\n * 验证文件\n */\nexport function validateFile(\n file: File,\n options?: {\n maxSize?: number;\n allowedTypes?: string[];\n }\n): { valid: boolean; errors: string[] } {\n const errors: string[] = [];\n\n // 验证文件名\n if (!validateFileName(file.name)) {\n errors.push('文件名包含非法字符或长度不合法');\n }\n\n // 验证文件大小\n if (options?.maxSize) {\n const sizeResult = validateFileSize(file, options.maxSize);\n if (!sizeResult.valid && sizeResult.error) {\n errors.push(sizeResult.error);\n }\n }\n\n // 验证文件类型\n if (options?.allowedTypes) {\n const typeResult = validateFileType(file, options.allowedTypes);\n if (!typeResult.valid && typeResult.error) {\n errors.push(typeResult.error);\n }\n }\n\n return {\n valid: errors.length === 0,\n errors,\n };\n}\n\n// ============= URL处理 =============\n\n/**\n * 构建查询字符串\n */\nexport function buildQueryString(params: Record<string, any>): string {\n const searchParams = new URLSearchParams();\n\n Object.entries(params).forEach(([key, value]) => {\n if (value !== undefined && value !== null) {\n if (Array.isArray(value)) {\n value.forEach((v) => searchParams.append(key, String(v)));\n } else {\n searchParams.append(key, String(value));\n }\n }\n });\n\n const queryString = searchParams.toString();\n return queryString ? `?${queryString}` : '';\n}\n\n/**\n * 解析URL查询参数\n */\nexport function parseQueryString(url: string): Record<string, string> {\n const params: Record<string, string> = {};\n const urlObj = new URL(url, window.location.origin);\n\n urlObj.searchParams.forEach((value, key) => {\n params[key] = value;\n });\n\n return params;\n}\n\n// ============= 进度计算 =============\n\n/**\n * 计算上传进度\n */\nexport function calculateProgress(uploadedBytes: number, totalBytes: number): number {\n if (totalBytes === 0) return 0;\n return Math.min(Math.round((uploadedBytes / totalBytes) * 100), 100);\n}\n\n/**\n * 计算上传速度\n */\nexport function calculateSpeed(uploadedBytes: number, elapsedTime: number): number {\n if (elapsedTime === 0) return 0;\n return uploadedBytes / (elapsedTime / 1000); // 字节/秒\n}\n\n/**\n * 计算剩余时间\n */\nexport function calculateRemainingTime(\n uploadedBytes: number,\n totalBytes: number,\n speed: number\n): number {\n if (speed === 0) return 0;\n const remainingBytes = totalBytes - uploadedBytes;\n return Math.round(remainingBytes / speed); // 秒\n}\n\n// ============= 错误处理 =============\n\n/**\n * 创建文件错误对象\n */\nexport function createFileError(\n code: string,\n message: string,\n details?: Record<string, any>\n): { code: string; message: string; details?: Record<string, any>; timestamp: Date } {\n return {\n code,\n message,\n details,\n timestamp: new Date(),\n };\n}\n\n/**\n * 格式化错误消息\n */\nexport function formatErrorMessage(error: unknown): string {\n if (error instanceof Error) {\n return error.message;\n }\n\n if (typeof error === 'string') {\n return error;\n }\n\n if (error && typeof error === 'object' && 'message' in error) {\n return String(error.message);\n }\n\n return '未知错误';\n}\n\n// ============= 文件读取 =============\n\n/**\n * 读取文件为Base64\n */\nexport function readFileAsBase64(file: File): Promise<string> {\n return new Promise((resolve, reject) => {\n const reader = new FileReader();\n\n reader.onload = () => {\n const result = reader.result as string;\n // 移除Data URL前缀\n const base64 = result.split(',')[1] || '';\n resolve(base64);\n };\n\n reader.onerror = () => {\n reject(new Error('读取文件失败'));\n };\n\n reader.readAsDataURL(file);\n });\n}\n\n/**\n * 读取文件为ArrayBuffer\n */\nexport function readFileAsArrayBuffer(file: File): Promise<ArrayBuffer> {\n return new Promise((resolve, reject) => {\n const reader = new FileReader();\n\n reader.onload = () => {\n resolve(reader.result as ArrayBuffer);\n };\n\n reader.onerror = () => {\n reject(new Error('读取文件失败'));\n };\n\n reader.readAsArrayBuffer(file);\n });\n}\n\n/**\n * 读取文件为文本\n */\nexport function readFileAsText(file: File, encoding: string = 'UTF-8'): Promise<string> {\n return new Promise((resolve, reject) => {\n const reader = new FileReader();\n\n reader.onload = () => {\n resolve(reader.result as string);\n };\n\n reader.onerror = () => {\n reject(new Error('读取文件失败'));\n };\n\n reader.readAsText(file, encoding);\n });\n}\n","/**\n * 通用文件服务客户端SDK\n *\n * 提供文件上传、下载、查询等功能的客户端接口\n */\n\nimport type {\n FileMetadata,\n UploadFileInfo,\n UploadProgress,\n FileQueryOptions,\n PaginatedResult,\n BatchOperationResult,\n} from './types';\nimport {\n API_ENDPOINTS,\n ERROR_CODES,\n DEFAULT_REQUEST_TIMEOUT,\n DEFAULT_UPLOAD_TIMEOUT,\n} from './constants';\nimport { createFileError, formatErrorMessage, buildQueryString } from './utils';\n\n// ============= 配置类型 =============\n\nexport interface UniversalFileClientConfig {\n /** API基础URL */\n baseUrl?: string;\n /** 请求超时时间(毫秒) */\n timeout?: number;\n /** 上传超时时间(毫秒) */\n uploadTimeout?: number;\n /** 自定义请求头 */\n headers?: Record<string, string>;\n}\n\n// ============= 客户端类 =============\n\n/**\n * 通用文件服务客户端\n */\nexport class UniversalFileClient {\n private config: Required<UniversalFileClientConfig>;\n\n constructor(config: UniversalFileClientConfig = {}) {\n this.config = {\n baseUrl: config.baseUrl || '',\n timeout: config.timeout || DEFAULT_REQUEST_TIMEOUT,\n uploadTimeout: config.uploadTimeout || DEFAULT_UPLOAD_TIMEOUT,\n headers: config.headers || {},\n };\n }\n\n // ============= 文件上传API =============\n\n /**\n * 上传文件\n */\n async uploadFile(\n fileInfo: UploadFileInfo,\n onProgress?: (progress: UploadProgress) => void\n ): Promise<FileMetadata> {\n const url = `${this.config.baseUrl}${API_ENDPOINTS.UPLOAD}`;\n const startTime = Date.now();\n\n // 创建FormData\n const formData = new FormData();\n formData.append('file', fileInfo.file);\n formData.append('moduleId', fileInfo.moduleId);\n\n if (fileInfo.businessId) {\n formData.append('businessId', fileInfo.businessId);\n }\n\n if (fileInfo.permission) {\n formData.append('permission', fileInfo.permission);\n }\n\n if (fileInfo.customPath) {\n formData.append('customPath', fileInfo.customPath);\n }\n\n if (fileInfo.metadata) {\n formData.append('metadata', JSON.stringify(fileInfo.metadata));\n }\n\n if (fileInfo.needsProcessing !== undefined) {\n formData.append('needsProcessing', String(fileInfo.needsProcessing));\n }\n\n if (fileInfo.processingOptions) {\n formData.append('processingOptions', JSON.stringify(fileInfo.processingOptions));\n }\n\n try {\n // 创建XMLHttpRequest以支持上传进度\n return await new Promise<FileMetadata>((resolve, reject) => {\n const xhr = new XMLHttpRequest();\n\n // 监听上传进度\n xhr.upload.addEventListener('progress', (event) => {\n if (event.lengthComputable && onProgress) {\n const elapsedTime = Date.now() - startTime;\n const speed = event.loaded / (elapsedTime / 1000);\n const remainingBytes = event.total - event.loaded;\n const remainingTime = speed > 0 ? remainingBytes / speed : 0;\n\n const progress: UploadProgress = {\n fileId: '', // 暂时为空,上传完成后会有\n status: 'uploading',\n progress: Math.round((event.loaded / event.total) * 100),\n uploadedBytes: event.loaded,\n totalBytes: event.total,\n speed,\n remainingTime,\n };\n\n onProgress(progress);\n }\n });\n\n // 监听上传完成\n xhr.addEventListener('load', () => {\n if (xhr.status >= 200 && xhr.status < 300) {\n try {\n const response = JSON.parse(xhr.responseText);\n const fileMetadata = this.transformFileMetadataFromAPI(response.file);\n\n if (onProgress) {\n onProgress({\n fileId: fileMetadata.id,\n status: 'completed',\n progress: 100,\n uploadedBytes: fileInfo.file.size,\n totalBytes: fileInfo.file.size,\n speed: 0,\n remainingTime: 0,\n });\n }\n\n resolve(fileMetadata);\n } catch (error) {\n reject(new Error('解析响应失败'));\n }\n } else {\n reject(new Error(`上传失败: ${xhr.statusText}`));\n }\n });\n\n // 监听错误\n xhr.addEventListener('error', () => {\n if (onProgress) {\n onProgress({\n fileId: '',\n status: 'failed',\n progress: 0,\n uploadedBytes: 0,\n totalBytes: fileInfo.file.size,\n speed: 0,\n remainingTime: 0,\n error: '网络错误',\n });\n }\n reject(new Error('上传失败'));\n });\n\n // 监听超时\n xhr.addEventListener('timeout', () => {\n if (onProgress) {\n onProgress({\n fileId: '',\n status: 'failed',\n progress: 0,\n uploadedBytes: 0,\n totalBytes: fileInfo.file.size,\n speed: 0,\n remainingTime: 0,\n error: '上传超时',\n });\n }\n reject(new Error('上传超时'));\n });\n\n // 配置请求\n xhr.open('POST', url);\n xhr.timeout = this.config.uploadTimeout;\n\n // 设置请求头\n Object.entries(this.config.headers).forEach(([key, value]) => {\n xhr.setRequestHeader(key, value);\n });\n\n // 发送请求\n xhr.send(formData);\n });\n } catch (error) {\n throw createFileError(\n ERROR_CODES.FILE_UPLOAD_ERROR,\n `文件上传失败: ${formatErrorMessage(error)}`,\n { fileInfo, originalError: error }\n );\n }\n }\n\n // ============= 文件查询API =============\n\n /**\n * 获取文件访问URL\n */\n async getFileUrl(fileId: string, expiresIn?: number): Promise<string> {\n const url = `${this.config.baseUrl}${API_ENDPOINTS.GET_URL(fileId)}${\n expiresIn ? `?expiresIn=${expiresIn}` : ''\n }`;\n\n try {\n const response = await this.fetchWithTimeout(url, {\n method: 'GET',\n headers: this.getHeaders(),\n });\n\n if (!response.ok) {\n throw new Error(`获取文件URL失败: ${response.statusText}`);\n }\n\n const data = await response.json();\n return data.url;\n } catch (error) {\n throw createFileError(\n ERROR_CODES.NETWORK_ERROR,\n `获取文件URL失败: ${formatErrorMessage(error)}`,\n { fileId, expiresIn, originalError: error }\n );\n }\n }\n\n /**\n * 获取文件元数据\n */\n async getFileMetadata(fileId: string): Promise<FileMetadata> {\n const url = `${this.config.baseUrl}${API_ENDPOINTS.GET_METADATA(fileId)}`;\n\n try {\n const response = await this.fetchWithTimeout(url, {\n method: 'GET',\n headers: this.getHeaders(),\n });\n\n if (!response.ok) {\n if (response.status === 404) {\n throw createFileError(ERROR_CODES.FILE_NOT_FOUND, '文件不存在', { fileId });\n }\n throw new Error(`获取文件元数据失败: ${response.statusText}`);\n }\n\n const data = await response.json();\n return this.transformFileMetadataFromAPI(data.file);\n } catch (error) {\n throw createFileError(\n ERROR_CODES.NETWORK_ERROR,\n `获取文件元数据失败: ${formatErrorMessage(error)}`,\n { fileId, originalError: error }\n );\n }\n }\n\n /**\n * 查询文件列表\n */\n async queryFiles(options: FileQueryOptions): Promise<PaginatedResult<FileMetadata>> {\n const queryString = buildQueryString({\n moduleId: options.moduleId,\n businessId: options.businessId,\n uploaderId: options.uploaderId,\n mimeType: options.mimeType,\n minSize: options.minSize,\n maxSize: options.maxSize,\n startTime: options.startTime?.toISOString(),\n endTime: options.endTime?.toISOString(),\n keyword: options.keyword,\n tags: options.tags,\n sortBy: options.sortBy,\n sortOrder: options.sortOrder,\n page: options.page,\n pageSize: options.pageSize,\n });\n\n const url = `${this.config.baseUrl}${API_ENDPOINTS.QUERY}${queryString}`;\n\n try {\n const response = await this.fetchWithTimeout(url, {\n method: 'GET',\n headers: this.getHeaders(),\n });\n\n if (!response.ok) {\n throw new Error(`查询文件列表失败: ${response.statusText}`);\n }\n\n const data = await response.json();\n return {\n items: data.items.map((item: any) => this.transformFileMetadataFromAPI(item)),\n total: data.total,\n page: data.page,\n pageSize: data.pageSize,\n totalPages: data.totalPages,\n hasNext: data.hasNext,\n hasPrev: data.hasPrev,\n };\n } catch (error) {\n throw createFileError(\n ERROR_CODES.NETWORK_ERROR,\n `查询文件列表失败: ${formatErrorMessage(error)}`,\n { options, originalError: error }\n );\n }\n }\n\n // ============= 文件删除API =============\n\n /**\n * 删除文件\n */\n async deleteFile(fileId: string): Promise<void> {\n const url = `${this.config.baseUrl}${API_ENDPOINTS.DELETE(fileId)}`;\n\n try {\n const response = await this.fetchWithTimeout(url, {\n method: 'DELETE',\n headers: this.getHeaders(),\n });\n\n if (!response.ok) {\n if (response.status === 404) {\n throw createFileError(ERROR_CODES.FILE_NOT_FOUND, '文件不存在', { fileId });\n }\n throw new Error(`删除文件失败: ${response.statusText}`);\n }\n } catch (error) {\n throw createFileError(\n ERROR_CODES.NETWORK_ERROR,\n `删除文件失败: ${formatErrorMessage(error)}`,\n { fileId, originalError: error }\n );\n }\n }\n\n /**\n * 批量删除文件\n */\n async batchDeleteFiles(fileIds: string[]): Promise<BatchOperationResult> {\n const url = `${this.config.baseUrl}${API_ENDPOINTS.BATCH_DELETE}`;\n\n try {\n const response = await this.fetchWithTimeout(url, {\n method: 'POST',\n headers: {\n ...this.getHeaders(),\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify({ fileIds }),\n });\n\n if (!response.ok) {\n throw new Error(`批量删除文件失败: ${response.statusText}`);\n }\n\n const data = await response.json();\n return data.result;\n } catch (error) {\n throw createFileError(\n ERROR_CODES.NETWORK_ERROR,\n `批量删除文件失败: ${formatErrorMessage(error)}`,\n { fileIds, originalError: error }\n );\n }\n }\n\n // ============= 上传进度API =============\n\n /**\n * 获取上传进度\n */\n async getUploadProgress(fileId: string): Promise<UploadProgress> {\n const url = `${this.config.baseUrl}${API_ENDPOINTS.GET_PROGRESS(fileId)}`;\n\n try {\n const response = await this.fetchWithTimeout(url, {\n method: 'GET',\n headers: this.getHeaders(),\n });\n\n if (!response.ok) {\n throw new Error(`获取上传进度失败: ${response.statusText}`);\n }\n\n const data = await response.json();\n return data.progress;\n } catch (error) {\n throw createFileError(\n ERROR_CODES.NETWORK_ERROR,\n `获取上传进度失败: ${formatErrorMessage(error)}`,\n { fileId, originalError: error }\n );\n }\n }\n\n // ============= 私有辅助方法 =============\n\n /**\n * 获取请求头\n */\n private getHeaders(): Record<string, string> {\n return {\n ...this.config.headers,\n };\n }\n\n /**\n * 带超时的fetch请求\n */\n private async fetchWithTimeout(url: string, options: RequestInit): Promise<Response> {\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), this.config.timeout);\n\n try {\n const response = await fetch(url, {\n ...options,\n signal: controller.signal,\n });\n return response;\n } catch (error) {\n if (error instanceof Error && error.name === 'AbortError') {\n throw createFileError(ERROR_CODES.TIMEOUT_ERROR, '请求超时', {\n url,\n timeout: this.config.timeout,\n });\n }\n throw error;\n } finally {\n clearTimeout(timeoutId);\n }\n }\n\n /**\n * 转换API返回的文件元数据\n */\n private transformFileMetadataFromAPI(apiData: any): FileMetadata {\n return {\n id: apiData.id,\n originalName: apiData.originalName,\n storageName: apiData.storageName || apiData.storedName,\n size: apiData.size,\n mimeType: apiData.mimeType,\n extension: apiData.extension,\n hash: apiData.hash || apiData.md5Hash || apiData.sha256Hash,\n uploadTime: new Date(apiData.uploadTime),\n permission: apiData.permission || 'public',\n uploaderId: apiData.uploaderId,\n moduleId: apiData.moduleId,\n businessId: apiData.businessId,\n storageProvider: apiData.storageProvider || 'local',\n storagePath: apiData.storagePath,\n cdnUrl: apiData.cdnUrl,\n accessCount: apiData.accessCount,\n lastAccessTime: apiData.lastAccessTime ? new Date(apiData.lastAccessTime) : undefined,\n expiresAt: apiData.expiresAt ? new Date(apiData.expiresAt) : undefined,\n metadata: apiData.metadata,\n };\n }\n}\n\n// ============= 单例导出 =============\n\n/**\n * 默认客户端实例\n */\nexport const universalFileClient = new UniversalFileClient();\n\n/**\n * 创建自定义客户端实例\n */\nexport function createFileClient(config?: UniversalFileClientConfig): UniversalFileClient {\n return new UniversalFileClient(config);\n}\n","/**\n * 通用文件上传组件\n * Universal File Uploader Component\n *\n * 支持拖拽上传、进度显示、多文件上传等功能\n * 使用 Tailwind CSS 样式,支持暗色模式\n */\n\n'use client';\n\nimport React, { useState, useRef, useCallback } from 'react';\nimport {\n Upload,\n X,\n FileText,\n Image,\n Film,\n Music,\n AlertCircle,\n CheckCircle2,\n Loader2,\n} from 'lucide-react';\n\nimport type {\n FileMetadata,\n UploadProgress,\n UploadFileInfo,\n ProcessingOptions,\n} from '../types';\nimport type { UniversalFileService } from '../server/UniversalFileService';\n\n// ============= 类型定义 =============\n\nexport interface FileUploaderProps {\n /** 文件服务实例 */\n fileService: UniversalFileService;\n /** 模块标识 */\n moduleId: string;\n /** 业务标识 */\n businessId?: string;\n /** 允许的文件类型 */\n acceptedTypes?: string[];\n /** 最大文件大小(MB) */\n maxFileSize?: number;\n /** 最大文件数量 */\n maxFiles?: number;\n /** 是否支持多文件上传 */\n multiple?: boolean;\n /** 是否启用文件处理 */\n enableProcessing?: boolean;\n /** 默认处理选项 */\n defaultProcessingOptions?: ProcessingOptions;\n /** 上传成功回调 */\n onUploadSuccess?: (files: FileMetadata[]) => void;\n /** 上传失败回调 */\n onUploadError?: (error: string) => void;\n /** 上传进度回调 */\n onProgress?: (progress: UploadProgress[]) => void;\n /** 自定义样式类名 */\n className?: string;\n /** 是否禁用 */\n disabled?: boolean;\n /** 显示模式 */\n mode?: 'compact' | 'normal' | 'detailed';\n}\n\nexport interface UploadingFile {\n id: string;\n file: File;\n progress: UploadProgress;\n metadata?: FileMetadata;\n error?: string;\n}\n\n// ============= 主组件 =============\n\nexport const FileUploader: React.FC<FileUploaderProps> = ({\n fileService,\n moduleId,\n businessId,\n acceptedTypes = [],\n maxFileSize = 100, // 100MB\n maxFiles = 10,\n multiple = true,\n enableProcessing = false,\n defaultProcessingOptions,\n onUploadSuccess,\n onUploadError,\n onProgress,\n className = '',\n disabled = false,\n mode = 'normal',\n}) => {\n // ============= 状态管理 =============\n\n const [uploadingFiles, setUploadingFiles] = useState<UploadingFile[]>([]);\n const [isDragOver, setIsDragOver] = useState(false);\n const [completedFiles, setCompletedFiles] = useState<FileMetadata[]>([]);\n const fileInputRef = useRef<HTMLInputElement>(null);\n\n // ============= 文件类型图标 =============\n\n const getFileIcon = (mimeType: string) => {\n if (mimeType.startsWith('image/')) return <Image className=\"w-5 h-5\" />;\n if (mimeType.startsWith('video/')) return <Film className=\"w-5 h-5\" />;\n if (mimeType.startsWith('audio/')) return <Music className=\"w-5 h-5\" />;\n return <FileText className=\"w-5 h-5\" />;\n };\n\n // ============= 文件验证 =============\n\n const validateFile = (file: File): string | null => {\n // 检查文件大小\n if (file.size > maxFileSize * 1024 * 1024) {\n return `文件大小不能超过 ${maxFileSize}MB`;\n }\n\n // 检查文件类型\n if (acceptedTypes.length > 0 && !acceptedTypes.includes(file.type)) {\n return `不支持的文件类型: ${file.type}`;\n }\n\n return null;\n };\n\n // ============= 文件上传逻辑 =============\n\n const uploadFile = useCallback(\n async (file: File): Promise<void> => {\n const fileId = `upload_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;\n\n // 验证文件\n const error = validateFile(file);\n if (error) {\n onUploadError?.(error);\n return;\n }\n\n // 初始化上传进度\n const initialProgress: UploadProgress = {\n fileId,\n status: 'pending',\n progress: 0,\n uploadedBytes: 0,\n totalBytes: file.size,\n speed: 0,\n remainingTime: 0,\n };\n\n const uploadingFile: UploadingFile = {\n id: fileId,\n file,\n progress: initialProgress,\n };\n\n setUploadingFiles((prev) => [...prev, uploadingFile]);\n\n try {\n // 构建上传文件信息\n const uploadInfo: UploadFileInfo = {\n file,\n moduleId,\n businessId,\n permission: 'public',\n needsProcessing: enableProcessing,\n processingOptions: defaultProcessingOptions,\n };\n\n // 开始上传\n const result = await fileService.uploadFile(\n uploadInfo,\n undefined, // 使用默认存储类型\n (progress) => {\n setUploadingFiles((prev) =>\n prev.map((f) => (f.id === fileId ? { ...f, progress } : f))\n );\n\n // 调用外部进度回调\n const allProgress = uploadingFiles.map((f) => f.progress);\n onProgress?.(allProgress);\n }\n );\n\n // 上传成功,result直接是FileMetadata\n setUploadingFiles((prev) => prev.filter((f) => f.id !== fileId));\n setCompletedFiles((prev) => [...prev, result]);\n onUploadSuccess?.([result]);\n } catch (error) {\n console.error('文件上传失败:', error);\n\n const errorMessage = error instanceof Error ? error.message : '上传失败';\n\n setUploadingFiles((prev) =>\n prev.map((f) => (f.id === fileId ? { ...f, error: errorMessage } : f))\n );\n\n onUploadError?.(errorMessage);\n }\n },\n [\n fileService,\n moduleId,\n businessId,\n enableProcessing,\n defaultProcessingOptions,\n maxFileSize,\n acceptedTypes,\n onUploadSuccess,\n onUploadError,\n onProgress,\n uploadingFiles,\n ]\n );\n\n // ============= 文件选择处理 =============\n\n const handleFileSelect = useCallback(\n (files: FileList | File[]) => {\n const fileArray = Array.from(files);\n\n // 检查文件数量限制\n if (completedFiles.length + uploadingFiles.length + fileArray.length > maxFiles) {\n onUploadError?.(`最多只能上传 ${maxFiles} 个文件`);\n return;\n }\n\n // 逐个上传文件\n fileArray.forEach(uploadFile);\n },\n [completedFiles.length, uploadingFiles.length, maxFiles, onUploadError, uploadFile]\n );\n\n // ============= 事件处理 =============\n\n const handleInputChange = (event: React.ChangeEvent<HTMLInputElement>) => {\n const files = event.target.files;\n if (files && files.length > 0) {\n handleFileSelect(files);\n }\n // 清空input值,允许重复选择同一文件\n event.target.value = '';\n };\n\n const handleDragOver = (event: React.DragEvent<HTMLDivElement>) => {\n event.preventDefault();\n setIsDragOver(true);\n };\n\n const handleDragLeave = (event: React.DragEvent<HTMLDivElement>) => {\n event.preventDefault();\n setIsDragOver(false);\n };\n\n const handleDrop = (event: React.DragEvent<HTMLDivElement>) => {\n event.preventDefault();\n setIsDragOver(false);\n\n const files = event.dataTransfer.files;\n if (files.length > 0) {\n handleFileSelect(files);\n }\n };\n\n const handleClick = () => {\n if (!disabled) {\n fileInputRef.current?.click();\n }\n };\n\n const removeUploadingFile = (fileId: string) => {\n setUploadingFiles((prev) => prev.filter((f) => f.id !== fileId));\n };\n\n const removeCompletedFile = (fileId: string) => {\n setCompletedFiles((prev) => prev.filter((f) => f.id !== fileId));\n };\n\n // ============= 渲染辅助函数 =============\n\n const formatFileSize = (bytes: number): string => {\n if (bytes === 0) return '0 B';\n const k = 1024;\n const sizes = ['B', 'KB', 'MB', 'GB'];\n const i = Math.floor(Math.log(bytes) / Math.log(k));\n return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];\n };\n\n const formatProgress = (progress: UploadProgress): string => {\n switch (progress.status) {\n case 'pending':\n return '准备中...';\n case 'uploading':\n return `上传中 ${progress.progress.toFixed(1)}%`;\n case 'processing':\n return '处理中...';\n case 'completed':\n return '完成';\n case 'failed':\n return '失败';\n default:\n return '未知状态';\n }\n };\n\n // ============= 样式计算 =============\n\n const containerClasses = `\n border-2 border-dashed rounded-lg transition-all duration-200\n ${\n isDragOver\n ? 'border-blue-400 bg-blue-50 dark:bg-blue-900/20'\n : 'border-gray-300 dark:border-gray-600'\n }\n ${disabled ? 'opacity-50 cursor-not-allowed' : 'hover:border-blue-400 cursor-pointer'}\n ${className}\n `;\n\n const uploadAreaClasses = `\n p-6 text-center\n ${mode === 'compact' ? 'p-4' : mode === 'detailed' ? 'p-8' : 'p-6'}\n `;\n\n // ============= 渲染 =============\n\n return (\n <div className=\"w-full space-y-4\">\n {/* 文件上传区域 */}\n <div\n className={containerClasses}\n onDragOver={handleDragOver}\n onDragLeave={handleDragLeave}\n onDrop={handleDrop}\n onClick={handleClick}\n >\n <div className={uploadAreaClasses}>\n <Upload\n className={`mx-auto mb-4 text-gray-400 ${mode === 'compact' ? 'w-8 h-8 mb-2' : 'w-12 h-12'}`}\n />\n\n {mode === 'compact' ? (\n <p className=\"text-sm text-gray-600 dark:text-gray-400\">点击上传或拖拽文件到这里</p>\n ) : (\n <>\n <h3 className=\"text-lg font-semibold text-gray-700 dark:text-gray-300 mb-2\">\n 上传文件\n </h3>\n <p className=\"text-gray-600 dark:text-gray-400 mb-2\">点击选择文件或拖拽文件到这里</p>\n {mode === 'detailed' && (\n <div className=\"text-sm text-gray-500 space-y-1\">\n {acceptedTypes.length > 0 && <p>支持格式: {acceptedTypes.join(', ')}</p>}\n <p>\n 最大大小: {maxFileSize}MB | 最多文件: {maxFiles}个\n </p>\n </div>\n )}\n </>\n )}\n </div>\n\n <input\n ref={fileInputRef}\n type=\"file\"\n multiple={multiple}\n accept={acceptedTypes.join(',')}\n onChange={handleInputChange}\n className=\"hidden\"\n disabled={disabled}\n />\n </div>\n\n {/* 上传进度列表 */}\n {uploadingFiles.length > 0 && (\n <div className=\"space-y-2\">\n <h4 className=\"text-sm font-medium text-gray-700 dark:text-gray-300\">\n 上传中 ({uploadingFiles.length})\n </h4>\n\n {uploadingFiles.map((uploadingFile) => (\n <div\n key={uploadingFile.id}\n className=\"flex items-center space-x-3 p-3 bg-gray-50 dark:bg-gray-800 rounded-lg\"\n >\n {/* 文件图标 */}\n <div className=\"flex-shrink-0\">\n {uploadingFile.progress.status === 'failed' ? (\n <AlertCircle className=\"w-5 h-5 text-red-500\" />\n ) : uploadingFile.progress.status === 'completed' ? (\n <CheckCircle2 className=\"w-5 h-5 text-green-500\" />\n ) : (\n <Loader2 className=\"w-5 h-5 text-blue-500 animate-spin\" />\n )}\n </div>\n\n {/* 文件信息 */}\n <div className=\"flex-grow min-w-0\">\n <div className=\"flex items-center justify-between mb-1\">\n <p className=\"text-sm font-medium text-gray-700 dark:text-gray-300 truncate\">\n {uploadingFile.file.name}\n </p>\n <span className=\"text-xs text-gray-500\">\n {formatFileSize(uploadingFile.file.size)}\n </span>\n </div>\n\n {uploadingFile.error ? (\n <p className=\"text-xs text-red-500\">{uploadingFile.error}</p>\n ) : (\n <>\n <div className=\"w-full bg-gray-200 dark:bg-gray-700 rounded-full h-2 mb-1\">\n <div\n className=\"bg-blue-500 h-2 rounded-full transition-all duration-300\"\n style={{ width: `${uploadingFile.progress.progress}%` }}\n />\n </div>\n <p className=\"text-xs text-gray-500\">\n {formatProgress(uploadingFile.progress)}\n </p>\n </>\n )}\n </div>\n\n {/* 移除按钮 */}\n <button\n onClick={(e) => {\n e.stopPropagation();\n removeUploadingFile(uploadingFile.id);\n }}\n className=\"flex-shrink-0 p-1 text-gray-400 hover:text-red-500 transition-colors\"\n >\n <X className=\"w-4 h-4\" />\n </button>\n </div>\n ))}\n </div>\n )}\n\n {/* 已完成文件列表 */}\n {completedFiles.length > 0 && (\n <div className=\"space-y-2\">\n <h4 className=\"text-sm font-medium text-gray-700 dark:text-gray-300\">\n 已完成 ({completedFiles.length})\n </h4>\n\n {completedFiles.map((file) => (\n <div\n key={file.id}\n className=\"flex items-center space-x-3 p-3 bg-green-50 dark:bg-green-900/20 rounded-lg\"\n >\n {/* 文件图标 */}\n <div className=\"flex-shrink-0\">{getFileIcon(file.mimeType)}</div>\n\n {/* 文件信息 */}\n <div className=\"flex-grow min-w-0\">\n <div className=\"flex items-center justify-between mb-1\">\n <p className=\"text-sm font-medium text-gray-700 dark:text-gray-300 truncate\">\n {file.originalName}\n </p>\n <span className=\"text-xs text-gray-500\">{formatFileSize(file.size)}</span>\n </div>\n <p className=\"text-xs text-green-600 dark:text-green-400\">\n 上传成功 • {new Date(file.uploadTime).toLocaleTimeString()}\n </p>\n </div>\n\n {/* 移除按钮 */}\n <button\n onClick={(e) => {\n e.stopPropagation();\n removeCompletedFile(file.id);\n }}\n className=\"flex-shrink-0 p-1 text-gray-400 hover:text-red-500 transition-colors\"\n >\n <X className=\"w-4 h-4\" />\n </button>\n </div>\n ))}\n </div>\n )}\n\n {/* 统计信息 */}\n {mode === 'detailed' && (completedFiles.length > 0 || uploadingFiles.length > 0) && (\n <div className=\"flex justify-between items-center text-sm text-gray-500 pt-2 border-t border-gray-200 dark:border-gray-700\">\n <span>总计: {completedFiles.length + uploadingFiles.length} 文件</span>\n <span>\n 大小:{' '}\n {formatFileSize(\n [\n ...completedFiles.map((f) => f.size),\n ...uploadingFiles.map((f) => f.file.size),\n ].reduce((total, size) => total + size, 0)\n )}\n </span>\n </div>\n )}\n </div>\n );\n};\n\nexport default FileUploader;\n\n"]}
|
|
1
|
+
{"version":3,"sources":["../../src/universalFile/constants.ts","../../src/universalFile/utils.ts","../../src/universalFile/client.ts","../../src/universalFile/components/FileUploader.tsx"],"names":["useState","useRef","React","Image","Film","Music","FileText","validateFile","useCallback","error","formatFileSize","Upload","AlertCircle","CheckCircle2","Loader2","X"],"mappings":"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","file":"index.js","sourcesContent":["/**\n * 通用文件服务常量定义\n */\n\n// ============= 版本信息 =============\n\n/** 模块版本 */\nexport const UNIVERSAL_FILE_VERSION = '1.0.0';\n\n/** 模块名称 */\nexport const UNIVERSAL_FILE_NAME = '@qhr123/sa2kit/universalFile';\n\n// ============= 文件大小限制 =============\n\n/** 默认最大文件大小(字节) - 100MB */\nexport const DEFAULT_MAX_FILE_SIZE = 100 * 1024 * 1024;\n\n/** 默认最大图片大小(字节) - 10MB */\nexport const DEFAULT_MAX_IMAGE_SIZE = 10 * 1024 * 1024;\n\n/** 默认最大视频大小(字节) - 500MB */\nexport const DEFAULT_MAX_VIDEO_SIZE = 500 * 1024 * 1024;\n\n/** 默认最大音频大小(字节) - 50MB */\nexport const DEFAULT_MAX_AUDIO_SIZE = 50 * 1024 * 1024;\n\n/** 默认最大文档大小(字节) - 20MB */\nexport const DEFAULT_MAX_DOCUMENT_SIZE = 20 * 1024 * 1024;\n\n// ============= MIME类型 =============\n\n/** 图片MIME类型 */\nexport const IMAGE_MIME_TYPES = [\n 'image/jpeg',\n 'image/jpg',\n 'image/png',\n 'image/gif',\n 'image/webp',\n 'image/svg+xml',\n];\n\n/** 视频MIME类型 */\nexport const VIDEO_MIME_TYPES = [\n 'video/mp4',\n 'video/mpeg',\n 'video/quicktime',\n 'video/x-msvideo',\n 'video/webm',\n];\n\n/** 音频MIME类型 */\nexport const AUDIO_MIME_TYPES = ['audio/mpeg', 'audio/mp3', 'audio/wav', 'audio/ogg', 'audio/aac'];\n\n/** 文档MIME类型 */\nexport const DOCUMENT_MIME_TYPES = [\n 'application/pdf',\n 'application/msword',\n 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',\n 'application/vnd.ms-excel',\n 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',\n 'application/vnd.ms-powerpoint',\n 'application/vnd.openxmlformats-officedocument.presentationml.presentation',\n 'text/plain',\n];\n\n/** 所有支持的MIME类型 */\nexport const ALL_SUPPORTED_MIME_TYPES = [\n ...IMAGE_MIME_TYPES,\n ...VIDEO_MIME_TYPES,\n ...AUDIO_MIME_TYPES,\n ...DOCUMENT_MIME_TYPES,\n];\n\n// ============= 文件扩展名 =============\n\n/** 图片扩展名 */\nexport const IMAGE_EXTENSIONS = ['.jpg', '.jpeg', '.png', '.gif', '.webp', '.svg'];\n\n/** 视频扩展名 */\nexport const VIDEO_EXTENSIONS = ['.mp4', '.mpeg', '.mov', '.avi', '.webm'];\n\n/** 音频扩展名 */\nexport const AUDIO_EXTENSIONS = ['.mp3', '.wav', '.ogg', '.aac'];\n\n/** 文档扩展名 */\nexport const DOCUMENT_EXTENSIONS = [\n '.pdf',\n '.doc',\n '.docx',\n '.xls',\n '.xlsx',\n '.ppt',\n '.pptx',\n '.txt',\n];\n\n// ============= API端点 =============\n\n/** API基础路径 */\nexport const API_BASE_PATH = '/api/universal-file';\n\n/** API端点 */\nexport const API_ENDPOINTS = {\n /** 上传文件 */\n UPLOAD: `${API_BASE_PATH}/upload`,\n /** 获取文件URL */\n GET_URL: (fileId: string) => `${API_BASE_PATH}/files/${fileId}/url`,\n /** 获取文件元数据 */\n GET_METADATA: (fileId: string) => `${API_BASE_PATH}/files/${fileId}`,\n /** 删除文件 */\n DELETE: (fileId: string) => `${API_BASE_PATH}/files/${fileId}`,\n /** 查询文件列表 */\n QUERY: `${API_BASE_PATH}/files`,\n /** 批量删除 */\n BATCH_DELETE: `${API_BASE_PATH}/files/batch-delete`,\n /** 获取上传进度 */\n GET_PROGRESS: (fileId: string) => `${API_BASE_PATH}/upload/${fileId}/progress`,\n} as const;\n\n// ============= 错误代码 =============\n\n/** 错误代码 */\nexport const ERROR_CODES = {\n /** 文件上传错误 */\n FILE_UPLOAD_ERROR: 'FILE_UPLOAD_ERROR',\n /** 文件大小超限 */\n FILE_SIZE_EXCEEDED: 'FILE_SIZE_EXCEEDED',\n /** 文件类型不支持 */\n FILE_TYPE_NOT_SUPPORTED: 'FILE_TYPE_NOT_SUPPORTED',\n /** 文件不存在 */\n FILE_NOT_FOUND: 'FILE_NOT_FOUND',\n /** 文件处理错误 */\n FILE_PROCESSING_ERROR: 'FILE_PROCESSING_ERROR',\n /** 存储提供者错误 */\n STORAGE_PROVIDER_ERROR: 'STORAGE_PROVIDER_ERROR',\n /** CDN提供者错误 */\n CDN_PROVIDER_ERROR: 'CDN_PROVIDER_ERROR',\n /** 网络错误 */\n NETWORK_ERROR: 'NETWORK_ERROR',\n /** 超时错误 */\n TIMEOUT_ERROR: 'TIMEOUT_ERROR',\n /** 未授权 */\n UNAUTHORIZED: 'UNAUTHORIZED',\n /** 权限不足 */\n FORBIDDEN: 'FORBIDDEN',\n /** 服务器错误 */\n SERVER_ERROR: 'SERVER_ERROR',\n} as const;\n\n// ============= 默认配置 =============\n\n/** 默认分页大小 */\nexport const DEFAULT_PAGE_SIZE = 20;\n\n/** 默认请求超时时间(毫秒) - 30秒 */\nexport const DEFAULT_REQUEST_TIMEOUT = 30000;\n\n/** 默认上传超时时间(毫秒) - 5分钟 */\nexport const DEFAULT_UPLOAD_TIMEOUT = 300000;\n\n/** 默认分片上传大小(字节) - 5MB */\nexport const DEFAULT_CHUNK_SIZE = 5 * 1024 * 1024;\n","/**\n * 通用文件服务工具函数\n */\n\nimport {\n IMAGE_MIME_TYPES,\n VIDEO_MIME_TYPES,\n AUDIO_MIME_TYPES,\n DOCUMENT_MIME_TYPES,\n} from './constants';\n\n// ============= 文件大小处理 =============\n\n/**\n * 格式化文件大小\n */\nexport function formatFileSize(bytes: number): string {\n if (bytes === 0) return '0 B';\n\n const units = ['B', 'KB', 'MB', 'GB', 'TB'];\n const k = 1024;\n const i = Math.floor(Math.log(bytes) / Math.log(k));\n\n return `${(bytes / Math.pow(k, i)).toFixed(2)} ${units[i]}`;\n}\n\n/**\n * 解析文件大小字符串\n */\nexport function parseFileSize(sizeStr: string): number {\n const match = sizeStr.match(/^(\\d+(?:\\.\\d+)?)\\s*([KMGT]?B)$/i);\n if (!match || !match[1] || !match[2]) return 0;\n\n const value = parseFloat(match[1]);\n const unit = match[2].toUpperCase();\n\n const units: Record<string, number> = {\n B: 1,\n KB: 1024,\n MB: 1024 * 1024,\n GB: 1024 * 1024 * 1024,\n TB: 1024 * 1024 * 1024 * 1024,\n };\n\n return value * (units[unit] || 1);\n}\n\n// ============= MIME类型处理 =============\n\n/**\n * 获取文件扩展名\n */\nexport function getFileExtension(fileName: string): string {\n const lastDot = fileName.lastIndexOf('.');\n if (lastDot === -1) return '';\n return fileName.substring(lastDot).toLowerCase();\n}\n\n/**\n * 根据文件名获取MIME类型\n */\nexport function getMimeTypeFromFileName(fileName: string): string {\n const ext = getFileExtension(fileName);\n\n const mimeMap: Record<string, string> = {\n '.jpg': 'image/jpeg',\n '.jpeg': 'image/jpeg',\n '.png': 'image/png',\n '.gif': 'image/gif',\n '.webp': 'image/webp',\n '.svg': 'image/svg+xml',\n '.pdf': 'application/pdf',\n '.txt': 'text/plain',\n '.mp4': 'video/mp4',\n '.avi': 'video/x-msvideo',\n '.mov': 'video/quicktime',\n '.mp3': 'audio/mpeg',\n '.wav': 'audio/wav',\n '.ogg': 'audio/ogg',\n '.doc': 'application/msword',\n '.docx': 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',\n '.xls': 'application/vnd.ms-excel',\n '.xlsx': 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',\n };\n\n return mimeMap[ext] || 'application/octet-stream';\n}\n\n/**\n * 检查MIME类型是否支持\n */\nexport function isMimeTypeSupported(mimeType: string, allowedTypes?: string[]): boolean {\n if (allowedTypes && allowedTypes.length > 0) {\n return allowedTypes.includes(mimeType);\n }\n\n return (\n IMAGE_MIME_TYPES.includes(mimeType) ||\n VIDEO_MIME_TYPES.includes(mimeType) ||\n AUDIO_MIME_TYPES.includes(mimeType) ||\n DOCUMENT_MIME_TYPES.includes(mimeType)\n );\n}\n\n/**\n * 判断是否为图片类型\n */\nexport function isImageFile(mimeType: string): boolean {\n return IMAGE_MIME_TYPES.includes(mimeType);\n}\n\n/**\n * 判断是否为视频类型\n */\nexport function isVideoFile(mimeType: string): boolean {\n return VIDEO_MIME_TYPES.includes(mimeType);\n}\n\n/**\n * 判断是否为音频类型\n */\nexport function isAudioFile(mimeType: string): boolean {\n return AUDIO_MIME_TYPES.includes(mimeType);\n}\n\n/**\n * 判断是否为文档类型\n */\nexport function isDocumentFile(mimeType: string): boolean {\n return DOCUMENT_MIME_TYPES.includes(mimeType);\n}\n\n/**\n * 获取文件类型类别\n */\nexport function getFileCategory(\n mimeType: string\n): 'image' | 'video' | 'audio' | 'document' | 'other' {\n if (isImageFile(mimeType)) return 'image';\n if (isVideoFile(mimeType)) return 'video';\n if (isAudioFile(mimeType)) return 'audio';\n if (isDocumentFile(mimeType)) return 'document';\n return 'other';\n}\n\n// ============= 文件名处理 =============\n\n/**\n * 验证文件名是否合法\n */\nexport function validateFileName(fileName: string): boolean {\n // 检查是否包含非法字符\n const invalidChars = /[<>:\"|?*\\/\\\\]/;\n if (invalidChars.test(fileName)) {\n return false;\n }\n\n // 检查长度\n if (fileName.length === 0 || fileName.length > 255) {\n return false;\n }\n\n // 检查是否以点开头\n if (fileName.startsWith('.')) {\n return false;\n }\n\n return true;\n}\n\n/**\n * 清理文件名,移除非法字符\n */\nexport function sanitizeFileName(fileName: string): string {\n return fileName\n .replace(/[<>:\"|?*\\/\\\\]/g, '_')\n .replace(/^\\.+/, '')\n .substring(0, 255);\n}\n\n/**\n * 生成唯一文件名\n */\nexport function generateUniqueFileName(originalName: string, fileId: string): string {\n const ext = getFileExtension(originalName);\n return `${fileId}${ext}`;\n}\n\n// ============= 存储路径处理 =============\n\n/**\n * 生成存储路径\n */\nexport function generateStoragePath(\n moduleId: string,\n fileName: string,\n options?: {\n businessId?: string;\n useDate?: boolean;\n customPrefix?: string;\n }\n): string {\n const parts: string[] = [];\n\n // 添加自定义前缀\n if (options?.customPrefix) {\n parts.push(options.customPrefix);\n }\n\n // 添加模块标识\n parts.push(moduleId);\n\n // 添加业务标识\n if (options?.businessId) {\n parts.push(options.businessId);\n }\n\n // 添加日期路径\n if (options?.useDate !== false) {\n const date = new Date();\n const year = date.getFullYear();\n const month = String(date.getMonth() + 1).padStart(2, '0');\n const day = String(date.getDate()).padStart(2, '0');\n parts.push(String(year), month, day);\n }\n\n // 添加文件名\n parts.push(fileName);\n\n return parts.join('/');\n}\n\n/**\n * 解析存储路径\n */\nexport function parseStoragePath(path: string): {\n moduleId?: string;\n businessId?: string;\n year?: string;\n month?: string;\n day?: string;\n fileName: string;\n} {\n const parts = path.split('/');\n const fileName = parts[parts.length - 1] || '';\n\n return {\n moduleId: parts[0] || undefined,\n businessId: parts.length > 5 ? parts[1] : undefined,\n year: parts.length > 3 ? parts[parts.length - 4] : undefined,\n month: parts.length > 2 ? parts[parts.length - 3] : undefined,\n day: parts.length > 1 ? parts[parts.length - 2] : undefined,\n fileName,\n };\n}\n\n// ============= 文件验证 =============\n\n/**\n * 验证文件大小\n */\nexport function validateFileSize(file: File, maxSize: number): { valid: boolean; error?: string } {\n if (file.size > maxSize) {\n return {\n valid: false,\n error: `文件大小超过限制: ${formatFileSize(file.size)} > ${formatFileSize(maxSize)}`,\n };\n }\n\n return { valid: true };\n}\n\n/**\n * 验证文件类型\n */\nexport function validateFileType(\n file: File,\n allowedTypes?: string[]\n): { valid: boolean; error?: string } {\n const mimeType = file.type || getMimeTypeFromFileName(file.name);\n\n if (!isMimeTypeSupported(mimeType, allowedTypes)) {\n return {\n valid: false,\n error: `不支持的文件类型: ${mimeType}`,\n };\n }\n\n return { valid: true };\n}\n\n/**\n * 验证文件\n */\nexport function validateFile(\n file: File,\n options?: {\n maxSize?: number;\n allowedTypes?: string[];\n }\n): { valid: boolean; errors: string[] } {\n const errors: string[] = [];\n\n // 验证文件名\n if (!validateFileName(file.name)) {\n errors.push('文件名包含非法字符或长度不合法');\n }\n\n // 验证文件大小\n if (options?.maxSize) {\n const sizeResult = validateFileSize(file, options.maxSize);\n if (!sizeResult.valid && sizeResult.error) {\n errors.push(sizeResult.error);\n }\n }\n\n // 验证文件类型\n if (options?.allowedTypes) {\n const typeResult = validateFileType(file, options.allowedTypes);\n if (!typeResult.valid && typeResult.error) {\n errors.push(typeResult.error);\n }\n }\n\n return {\n valid: errors.length === 0,\n errors,\n };\n}\n\n// ============= URL处理 =============\n\n/**\n * 构建查询字符串\n */\nexport function buildQueryString(params: Record<string, any>): string {\n const searchParams = new URLSearchParams();\n\n Object.entries(params).forEach(([key, value]) => {\n if (value !== undefined && value !== null) {\n if (Array.isArray(value)) {\n value.forEach((v) => searchParams.append(key, String(v)));\n } else {\n searchParams.append(key, String(value));\n }\n }\n });\n\n const queryString = searchParams.toString();\n return queryString ? `?${queryString}` : '';\n}\n\n/**\n * 解析URL查询参数\n */\nexport function parseQueryString(url: string): Record<string, string> {\n const params: Record<string, string> = {};\n const urlObj = new URL(url, window.location.origin);\n\n urlObj.searchParams.forEach((value, key) => {\n params[key] = value;\n });\n\n return params;\n}\n\n// ============= 进度计算 =============\n\n/**\n * 计算上传进度\n */\nexport function calculateProgress(uploadedBytes: number, totalBytes: number): number {\n if (totalBytes === 0) return 0;\n return Math.min(Math.round((uploadedBytes / totalBytes) * 100), 100);\n}\n\n/**\n * 计算上传速度\n */\nexport function calculateSpeed(uploadedBytes: number, elapsedTime: number): number {\n if (elapsedTime === 0) return 0;\n return uploadedBytes / (elapsedTime / 1000); // 字节/秒\n}\n\n/**\n * 计算剩余时间\n */\nexport function calculateRemainingTime(\n uploadedBytes: number,\n totalBytes: number,\n speed: number\n): number {\n if (speed === 0) return 0;\n const remainingBytes = totalBytes - uploadedBytes;\n return Math.round(remainingBytes / speed); // 秒\n}\n\n// ============= 错误处理 =============\n\n/**\n * 创建文件错误对象\n */\nexport function createFileError(\n code: string,\n message: string,\n details?: Record<string, any>\n): { code: string; message: string; details?: Record<string, any>; timestamp: Date } {\n return {\n code,\n message,\n details,\n timestamp: new Date(),\n };\n}\n\n/**\n * 格式化错误消息\n */\nexport function formatErrorMessage(error: unknown): string {\n if (error instanceof Error) {\n return error.message;\n }\n\n if (typeof error === 'string') {\n return error;\n }\n\n if (error && typeof error === 'object' && 'message' in error) {\n return String(error.message);\n }\n\n return '未知错误';\n}\n\n// ============= 文件读取 =============\n\n/**\n * 读取文件为Base64\n */\nexport function readFileAsBase64(file: File): Promise<string> {\n return new Promise((resolve, reject) => {\n const reader = new FileReader();\n\n reader.onload = () => {\n const result = reader.result as string;\n // 移除Data URL前缀\n const base64 = result.split(',')[1] || '';\n resolve(base64);\n };\n\n reader.onerror = () => {\n reject(new Error('读取文件失败'));\n };\n\n reader.readAsDataURL(file);\n });\n}\n\n/**\n * 读取文件为ArrayBuffer\n */\nexport function readFileAsArrayBuffer(file: File): Promise<ArrayBuffer> {\n return new Promise((resolve, reject) => {\n const reader = new FileReader();\n\n reader.onload = () => {\n resolve(reader.result as ArrayBuffer);\n };\n\n reader.onerror = () => {\n reject(new Error('读取文件失败'));\n };\n\n reader.readAsArrayBuffer(file);\n });\n}\n\n/**\n * 读取文件为文本\n */\nexport function readFileAsText(file: File, encoding: string = 'UTF-8'): Promise<string> {\n return new Promise((resolve, reject) => {\n const reader = new FileReader();\n\n reader.onload = () => {\n resolve(reader.result as string);\n };\n\n reader.onerror = () => {\n reject(new Error('读取文件失败'));\n };\n\n reader.readAsText(file, encoding);\n });\n}\n","/**\n * 通用文件服务客户端SDK\n *\n * 提供文件上传、下载、查询等功能的客户端接口\n */\n\nimport type {\n FileMetadata,\n UploadFileInfo,\n UploadProgress,\n FileQueryOptions,\n PaginatedResult,\n BatchOperationResult,\n} from './types';\nimport {\n API_ENDPOINTS,\n ERROR_CODES,\n DEFAULT_REQUEST_TIMEOUT,\n DEFAULT_UPLOAD_TIMEOUT,\n} from './constants';\nimport { createFileError, formatErrorMessage, buildQueryString } from './utils';\n\n// ============= 配置类型 =============\n\nexport interface UniversalFileClientConfig {\n /** API基础URL */\n baseUrl?: string;\n /** 请求超时时间(毫秒) */\n timeout?: number;\n /** 上传超时时间(毫秒) */\n uploadTimeout?: number;\n /** 自定义请求头 */\n headers?: Record<string, string>;\n}\n\n// ============= 客户端类 =============\n\n/**\n * 通用文件服务客户端\n */\nexport class UniversalFileClient {\n private config: Required<UniversalFileClientConfig>;\n\n constructor(config: UniversalFileClientConfig = {}) {\n this.config = {\n baseUrl: config.baseUrl || '',\n timeout: config.timeout || DEFAULT_REQUEST_TIMEOUT,\n uploadTimeout: config.uploadTimeout || DEFAULT_UPLOAD_TIMEOUT,\n headers: config.headers || {},\n };\n }\n\n // ============= 文件上传API =============\n\n /**\n * 上传文件\n */\n async uploadFile(\n fileInfo: UploadFileInfo,\n onProgress?: (progress: UploadProgress) => void\n ): Promise<FileMetadata> {\n const url = `${this.config.baseUrl}${API_ENDPOINTS.UPLOAD}`;\n const startTime = Date.now();\n\n // 创建FormData\n const formData = new FormData();\n formData.append('file', fileInfo.file);\n formData.append('moduleId', fileInfo.moduleId);\n\n if (fileInfo.businessId) {\n formData.append('businessId', fileInfo.businessId);\n }\n\n if (fileInfo.permission) {\n formData.append('permission', fileInfo.permission);\n }\n\n if (fileInfo.customPath) {\n formData.append('customPath', fileInfo.customPath);\n }\n\n if (fileInfo.metadata) {\n formData.append('metadata', JSON.stringify(fileInfo.metadata));\n }\n\n if (fileInfo.needsProcessing !== undefined) {\n formData.append('needsProcessing', String(fileInfo.needsProcessing));\n }\n\n if (fileInfo.processingOptions) {\n formData.append('processingOptions', JSON.stringify(fileInfo.processingOptions));\n }\n\n try {\n console.log('📤 [UniversalFileClient] 开始上传文件:', {\n url,\n fileName: fileInfo.file.name,\n fileSize: fileInfo.file.size,\n moduleId: fileInfo.moduleId,\n businessId: fileInfo.businessId,\n });\n\n // 创建XMLHttpRequest以支持上传进度\n return await new Promise<FileMetadata>((resolve, reject) => {\n const xhr = new XMLHttpRequest();\n \n // 重要:启用 credentials 以携带 cookie\n xhr.withCredentials = true;\n\n // 监听上传进度\n xhr.upload.addEventListener('progress', (event) => {\n if (event.lengthComputable && onProgress) {\n const elapsedTime = Date.now() - startTime;\n const speed = event.loaded / (elapsedTime / 1000);\n const remainingBytes = event.total - event.loaded;\n const remainingTime = speed > 0 ? remainingBytes / speed : 0;\n\n const progress: UploadProgress = {\n fileId: '', // 暂时为空,上传完成后会有\n status: 'uploading',\n progress: Math.round((event.loaded / event.total) * 100),\n uploadedBytes: event.loaded,\n totalBytes: event.total,\n speed,\n remainingTime,\n };\n\n onProgress(progress);\n }\n });\n\n // 监听上传完成\n xhr.addEventListener('load', () => {\n console.log('📥 [UniversalFileClient] 上传响应:', {\n status: xhr.status,\n statusText: xhr.statusText,\n responseLength: xhr.responseText?.length,\n });\n \n if (xhr.status >= 200 && xhr.status < 300) {\n try {\n const response = JSON.parse(xhr.responseText);\n console.log('✅ [UniversalFileClient] 解析响应成功:', response);\n \n // 支持多种响应格式\n const fileData = response.file || response.data || response;\n const fileMetadata = this.transformFileMetadataFromAPI(fileData);\n\n if (onProgress) {\n onProgress({\n fileId: fileMetadata.id,\n status: 'completed',\n progress: 100,\n uploadedBytes: fileInfo.file.size,\n totalBytes: fileInfo.file.size,\n speed: 0,\n remainingTime: 0,\n });\n }\n\n resolve(fileMetadata);\n } catch (error) {\n console.error('❌ [UniversalFileClient] 解析响应失败:', error, xhr.responseText);\n reject(new Error('解析响应失败'));\n }\n } else {\n console.error('❌ [UniversalFileClient] 上传失败:', xhr.status, xhr.statusText, xhr.responseText);\n reject(new Error(`上传失败: ${xhr.statusText}`));\n }\n });\n\n // 监听错误\n xhr.addEventListener('error', (event) => {\n console.error('❌ [UniversalFileClient] 网络错误:', event);\n if (onProgress) {\n onProgress({\n fileId: '',\n status: 'failed',\n progress: 0,\n uploadedBytes: 0,\n totalBytes: fileInfo.file.size,\n speed: 0,\n remainingTime: 0,\n error: '网络错误',\n });\n }\n reject(new Error('上传失败: 网络错误'));\n });\n\n // 监听超时\n xhr.addEventListener('timeout', () => {\n if (onProgress) {\n onProgress({\n fileId: '',\n status: 'failed',\n progress: 0,\n uploadedBytes: 0,\n totalBytes: fileInfo.file.size,\n speed: 0,\n remainingTime: 0,\n error: '上传超时',\n });\n }\n reject(new Error('上传超时'));\n });\n\n // 配置请求\n xhr.open('POST', url);\n xhr.timeout = this.config.uploadTimeout;\n\n // 设置请求头\n Object.entries(this.config.headers).forEach(([key, value]) => {\n xhr.setRequestHeader(key, value);\n });\n\n // 发送请求\n xhr.send(formData);\n });\n } catch (error) {\n throw createFileError(\n ERROR_CODES.FILE_UPLOAD_ERROR,\n `文件上传失败: ${formatErrorMessage(error)}`,\n { fileInfo, originalError: error }\n );\n }\n }\n\n // ============= 文件查询API =============\n\n /**\n * 获取文件访问URL\n */\n async getFileUrl(fileId: string, expiresIn?: number): Promise<string> {\n const url = `${this.config.baseUrl}${API_ENDPOINTS.GET_URL(fileId)}${\n expiresIn ? `?expiresIn=${expiresIn}` : ''\n }`;\n\n try {\n const response = await this.fetchWithTimeout(url, {\n method: 'GET',\n headers: this.getHeaders(),\n });\n\n if (!response.ok) {\n throw new Error(`获取文件URL失败: ${response.statusText}`);\n }\n\n const data = await response.json();\n return data.url;\n } catch (error) {\n throw createFileError(\n ERROR_CODES.NETWORK_ERROR,\n `获取文件URL失败: ${formatErrorMessage(error)}`,\n { fileId, expiresIn, originalError: error }\n );\n }\n }\n\n /**\n * 获取文件元数据\n */\n async getFileMetadata(fileId: string): Promise<FileMetadata> {\n const url = `${this.config.baseUrl}${API_ENDPOINTS.GET_METADATA(fileId)}`;\n\n try {\n const response = await this.fetchWithTimeout(url, {\n method: 'GET',\n headers: this.getHeaders(),\n });\n\n if (!response.ok) {\n if (response.status === 404) {\n throw createFileError(ERROR_CODES.FILE_NOT_FOUND, '文件不存在', { fileId });\n }\n throw new Error(`获取文件元数据失败: ${response.statusText}`);\n }\n\n const data = await response.json();\n return this.transformFileMetadataFromAPI(data.file);\n } catch (error) {\n throw createFileError(\n ERROR_CODES.NETWORK_ERROR,\n `获取文件元数据失败: ${formatErrorMessage(error)}`,\n { fileId, originalError: error }\n );\n }\n }\n\n /**\n * 查询文件列表\n */\n async queryFiles(options: FileQueryOptions): Promise<PaginatedResult<FileMetadata>> {\n const queryString = buildQueryString({\n moduleId: options.moduleId,\n businessId: options.businessId,\n uploaderId: options.uploaderId,\n mimeType: options.mimeType,\n minSize: options.minSize,\n maxSize: options.maxSize,\n startTime: options.startTime?.toISOString(),\n endTime: options.endTime?.toISOString(),\n keyword: options.keyword,\n tags: options.tags,\n sortBy: options.sortBy,\n sortOrder: options.sortOrder,\n page: options.page,\n pageSize: options.pageSize,\n });\n\n const url = `${this.config.baseUrl}${API_ENDPOINTS.QUERY}${queryString}`;\n\n try {\n const response = await this.fetchWithTimeout(url, {\n method: 'GET',\n headers: this.getHeaders(),\n });\n\n if (!response.ok) {\n console.error('❌ [UniversalFileClient] 查询文件列表失败:', response.status, response.statusText);\n throw new Error(`查询文件列表失败: ${response.statusText}`);\n }\n\n const data = await response.json();\n console.log('📥 [UniversalFileClient] 查询文件列表响应:', {\n itemsCount: data.items?.length,\n total: data.total,\n page: data.page,\n });\n \n // 防御性检查\n if (!data.items || !Array.isArray(data.items)) {\n console.error('❌ [UniversalFileClient] 响应格式错误: items 不是数组', data);\n return {\n items: [],\n total: 0,\n page: 1,\n pageSize: 20,\n totalPages: 0,\n hasNext: false,\n hasPrev: false,\n };\n }\n \n return {\n items: data.items.map((item: any) => this.transformFileMetadataFromAPI(item)),\n total: data.total,\n page: data.page,\n pageSize: data.pageSize,\n totalPages: data.totalPages,\n hasNext: data.hasNext,\n hasPrev: data.hasPrev,\n };\n } catch (error) {\n throw createFileError(\n ERROR_CODES.NETWORK_ERROR,\n `查询文件列表失败: ${formatErrorMessage(error)}`,\n { options, originalError: error }\n );\n }\n }\n\n // ============= 文件删除API =============\n\n /**\n * 删除文件\n */\n async deleteFile(fileId: string): Promise<void> {\n const url = `${this.config.baseUrl}${API_ENDPOINTS.DELETE(fileId)}`;\n\n try {\n const response = await this.fetchWithTimeout(url, {\n method: 'DELETE',\n headers: this.getHeaders(),\n });\n\n if (!response.ok) {\n if (response.status === 404) {\n throw createFileError(ERROR_CODES.FILE_NOT_FOUND, '文件不存在', { fileId });\n }\n throw new Error(`删除文件失败: ${response.statusText}`);\n }\n } catch (error) {\n throw createFileError(\n ERROR_CODES.NETWORK_ERROR,\n `删除文件失败: ${formatErrorMessage(error)}`,\n { fileId, originalError: error }\n );\n }\n }\n\n /**\n * 批量删除文件\n */\n async batchDeleteFiles(fileIds: string[]): Promise<BatchOperationResult> {\n const url = `${this.config.baseUrl}${API_ENDPOINTS.BATCH_DELETE}`;\n\n try {\n const response = await this.fetchWithTimeout(url, {\n method: 'POST',\n headers: {\n ...this.getHeaders(),\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify({ fileIds }),\n });\n\n if (!response.ok) {\n throw new Error(`批量删除文件失败: ${response.statusText}`);\n }\n\n const data = await response.json();\n return data.result;\n } catch (error) {\n throw createFileError(\n ERROR_CODES.NETWORK_ERROR,\n `批量删除文件失败: ${formatErrorMessage(error)}`,\n { fileIds, originalError: error }\n );\n }\n }\n\n // ============= 上传进度API =============\n\n /**\n * 获取上传进度\n */\n async getUploadProgress(fileId: string): Promise<UploadProgress> {\n const url = `${this.config.baseUrl}${API_ENDPOINTS.GET_PROGRESS(fileId)}`;\n\n try {\n const response = await this.fetchWithTimeout(url, {\n method: 'GET',\n headers: this.getHeaders(),\n });\n\n if (!response.ok) {\n throw new Error(`获取上传进度失败: ${response.statusText}`);\n }\n\n const data = await response.json();\n return data.progress;\n } catch (error) {\n throw createFileError(\n ERROR_CODES.NETWORK_ERROR,\n `获取上传进度失败: ${formatErrorMessage(error)}`,\n { fileId, originalError: error }\n );\n }\n }\n\n // ============= 私有辅助方法 =============\n\n /**\n * 获取请求头\n */\n private getHeaders(): Record<string, string> {\n return {\n ...this.config.headers,\n };\n }\n\n /**\n * 带超时的fetch请求\n */\n private async fetchWithTimeout(url: string, options: RequestInit): Promise<Response> {\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), this.config.timeout);\n\n try {\n const response = await fetch(url, {\n ...options,\n signal: controller.signal,\n credentials: 'include', // 携带 cookie 用于授权\n });\n return response;\n } catch (error) {\n if (error instanceof Error && error.name === 'AbortError') {\n throw createFileError(ERROR_CODES.TIMEOUT_ERROR, '请求超时', {\n url,\n timeout: this.config.timeout,\n });\n }\n throw error;\n } finally {\n clearTimeout(timeoutId);\n }\n }\n\n /**\n * 转换API返回的文件元数据\n */\n private transformFileMetadataFromAPI(apiData: any): FileMetadata {\n return {\n id: apiData.id,\n originalName: apiData.originalName,\n storageName: apiData.storageName || apiData.storedName,\n size: apiData.size,\n mimeType: apiData.mimeType,\n extension: apiData.extension,\n hash: apiData.hash || apiData.md5Hash || apiData.sha256Hash,\n uploadTime: new Date(apiData.uploadTime),\n permission: apiData.permission || 'public',\n uploaderId: apiData.uploaderId,\n moduleId: apiData.moduleId,\n businessId: apiData.businessId,\n storageProvider: apiData.storageProvider || 'local',\n storagePath: apiData.storagePath,\n cdnUrl: apiData.cdnUrl,\n accessCount: apiData.accessCount,\n lastAccessTime: apiData.lastAccessTime ? new Date(apiData.lastAccessTime) : undefined,\n expiresAt: apiData.expiresAt ? new Date(apiData.expiresAt) : undefined,\n metadata: apiData.metadata,\n };\n }\n}\n\n// ============= 单例导出 =============\n\n/**\n * 默认客户端实例\n */\nexport const universalFileClient = new UniversalFileClient();\n\n/**\n * 创建自定义客户端实例\n */\nexport function createFileClient(config?: UniversalFileClientConfig): UniversalFileClient {\n return new UniversalFileClient(config);\n}\n","/**\n * 通用文件上传组件\n * Universal File Uploader Component\n *\n * 支持拖拽上传、进度显示、多文件上传等功能\n * 使用 Tailwind CSS 样式,支持暗色模式\n */\n\n'use client';\n\nimport React, { useState, useRef, useCallback } from 'react';\nimport {\n Upload,\n X,\n FileText,\n Image,\n Film,\n Music,\n AlertCircle,\n CheckCircle2,\n Loader2,\n} from 'lucide-react';\n\nimport type {\n FileMetadata,\n UploadProgress,\n UploadFileInfo,\n ProcessingOptions,\n} from '../types';\nimport type { UniversalFileService } from '../server/UniversalFileService';\n\n// ============= 类型定义 =============\n\nexport interface FileUploaderProps {\n /** 文件服务实例 */\n fileService: UniversalFileService;\n /** 模块标识 */\n moduleId: string;\n /** 业务标识 */\n businessId?: string;\n /** 允许的文件类型 */\n acceptedTypes?: string[];\n /** 最大文件大小(MB) */\n maxFileSize?: number;\n /** 最大文件数量 */\n maxFiles?: number;\n /** 是否支持多文件上传 */\n multiple?: boolean;\n /** 是否启用文件处理 */\n enableProcessing?: boolean;\n /** 默认处理选项 */\n defaultProcessingOptions?: ProcessingOptions;\n /** 上传成功回调 */\n onUploadSuccess?: (files: FileMetadata[]) => void;\n /** 上传失败回调 */\n onUploadError?: (error: string) => void;\n /** 上传进度回调 */\n onProgress?: (progress: UploadProgress[]) => void;\n /** 自定义样式类名 */\n className?: string;\n /** 是否禁用 */\n disabled?: boolean;\n /** 显示模式 */\n mode?: 'compact' | 'normal' | 'detailed';\n}\n\nexport interface UploadingFile {\n id: string;\n file: File;\n progress: UploadProgress;\n metadata?: FileMetadata;\n error?: string;\n}\n\n// ============= 主组件 =============\n\nexport const FileUploader: React.FC<FileUploaderProps> = ({\n fileService,\n moduleId,\n businessId,\n acceptedTypes = [],\n maxFileSize = 100, // 100MB\n maxFiles = 10,\n multiple = true,\n enableProcessing = false,\n defaultProcessingOptions,\n onUploadSuccess,\n onUploadError,\n onProgress,\n className = '',\n disabled = false,\n mode = 'normal',\n}) => {\n // ============= 状态管理 =============\n\n const [uploadingFiles, setUploadingFiles] = useState<UploadingFile[]>([]);\n const [isDragOver, setIsDragOver] = useState(false);\n const [completedFiles, setCompletedFiles] = useState<FileMetadata[]>([]);\n const fileInputRef = useRef<HTMLInputElement>(null);\n\n // ============= 文件类型图标 =============\n\n const getFileIcon = (mimeType: string) => {\n if (mimeType.startsWith('image/')) return <Image className=\"w-5 h-5\" />;\n if (mimeType.startsWith('video/')) return <Film className=\"w-5 h-5\" />;\n if (mimeType.startsWith('audio/')) return <Music className=\"w-5 h-5\" />;\n return <FileText className=\"w-5 h-5\" />;\n };\n\n // ============= 文件验证 =============\n\n const validateFile = (file: File): string | null => {\n // 检查文件大小\n if (file.size > maxFileSize * 1024 * 1024) {\n return `文件大小不能超过 ${maxFileSize}MB`;\n }\n\n // 检查文件类型\n if (acceptedTypes.length > 0 && !acceptedTypes.includes(file.type)) {\n return `不支持的文件类型: ${file.type}`;\n }\n\n return null;\n };\n\n // ============= 文件上传逻辑 =============\n\n const uploadFile = useCallback(\n async (file: File): Promise<void> => {\n const fileId = `upload_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;\n\n // 验证文件\n const error = validateFile(file);\n if (error) {\n onUploadError?.(error);\n return;\n }\n\n // 初始化上传进度\n const initialProgress: UploadProgress = {\n fileId,\n status: 'pending',\n progress: 0,\n uploadedBytes: 0,\n totalBytes: file.size,\n speed: 0,\n remainingTime: 0,\n };\n\n const uploadingFile: UploadingFile = {\n id: fileId,\n file,\n progress: initialProgress,\n };\n\n setUploadingFiles((prev) => [...prev, uploadingFile]);\n\n try {\n // 构建上传文件信息\n const uploadInfo: UploadFileInfo = {\n file,\n moduleId,\n businessId,\n permission: 'public',\n needsProcessing: enableProcessing,\n processingOptions: defaultProcessingOptions,\n };\n\n // 开始上传\n const result = await fileService.uploadFile(\n uploadInfo,\n undefined, // 使用默认存储类型\n (progress) => {\n setUploadingFiles((prev) =>\n prev.map((f) => (f.id === fileId ? { ...f, progress } : f))\n );\n\n // 调用外部进度回调\n const allProgress = uploadingFiles.map((f) => f.progress);\n onProgress?.(allProgress);\n }\n );\n\n // 上传成功,result直接是FileMetadata\n setUploadingFiles((prev) => prev.filter((f) => f.id !== fileId));\n setCompletedFiles((prev) => [...prev, result]);\n onUploadSuccess?.([result]);\n } catch (error) {\n console.error('文件上传失败:', error);\n\n const errorMessage = error instanceof Error ? error.message : '上传失败';\n\n setUploadingFiles((prev) =>\n prev.map((f) => (f.id === fileId ? { ...f, error: errorMessage } : f))\n );\n\n onUploadError?.(errorMessage);\n }\n },\n [\n fileService,\n moduleId,\n businessId,\n enableProcessing,\n defaultProcessingOptions,\n maxFileSize,\n acceptedTypes,\n onUploadSuccess,\n onUploadError,\n onProgress,\n uploadingFiles,\n ]\n );\n\n // ============= 文件选择处理 =============\n\n const handleFileSelect = useCallback(\n (files: FileList | File[]) => {\n const fileArray = Array.from(files);\n\n // 检查文件数量限制\n if (completedFiles.length + uploadingFiles.length + fileArray.length > maxFiles) {\n onUploadError?.(`最多只能上传 ${maxFiles} 个文件`);\n return;\n }\n\n // 逐个上传文件\n fileArray.forEach(uploadFile);\n },\n [completedFiles.length, uploadingFiles.length, maxFiles, onUploadError, uploadFile]\n );\n\n // ============= 事件处理 =============\n\n const handleInputChange = (event: React.ChangeEvent<HTMLInputElement>) => {\n const files = event.target.files;\n if (files && files.length > 0) {\n handleFileSelect(files);\n }\n // 清空input值,允许重复选择同一文件\n event.target.value = '';\n };\n\n const handleDragOver = (event: React.DragEvent<HTMLDivElement>) => {\n event.preventDefault();\n setIsDragOver(true);\n };\n\n const handleDragLeave = (event: React.DragEvent<HTMLDivElement>) => {\n event.preventDefault();\n setIsDragOver(false);\n };\n\n const handleDrop = (event: React.DragEvent<HTMLDivElement>) => {\n event.preventDefault();\n setIsDragOver(false);\n\n const files = event.dataTransfer.files;\n if (files.length > 0) {\n handleFileSelect(files);\n }\n };\n\n const handleClick = () => {\n if (!disabled) {\n fileInputRef.current?.click();\n }\n };\n\n const removeUploadingFile = (fileId: string) => {\n setUploadingFiles((prev) => prev.filter((f) => f.id !== fileId));\n };\n\n const removeCompletedFile = (fileId: string) => {\n setCompletedFiles((prev) => prev.filter((f) => f.id !== fileId));\n };\n\n // ============= 渲染辅助函数 =============\n\n const formatFileSize = (bytes: number): string => {\n if (bytes === 0) return '0 B';\n const k = 1024;\n const sizes = ['B', 'KB', 'MB', 'GB'];\n const i = Math.floor(Math.log(bytes) / Math.log(k));\n return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];\n };\n\n const formatProgress = (progress: UploadProgress): string => {\n switch (progress.status) {\n case 'pending':\n return '准备中...';\n case 'uploading':\n return `上传中 ${progress.progress.toFixed(1)}%`;\n case 'processing':\n return '处理中...';\n case 'completed':\n return '完成';\n case 'failed':\n return '失败';\n default:\n return '未知状态';\n }\n };\n\n // ============= 样式计算 =============\n\n const containerClasses = `\n border-2 border-dashed rounded-lg transition-all duration-200\n ${\n isDragOver\n ? 'border-blue-400 bg-blue-50 dark:bg-blue-900/20'\n : 'border-gray-300 dark:border-gray-600'\n }\n ${disabled ? 'opacity-50 cursor-not-allowed' : 'hover:border-blue-400 cursor-pointer'}\n ${className}\n `;\n\n const uploadAreaClasses = `\n p-6 text-center\n ${mode === 'compact' ? 'p-4' : mode === 'detailed' ? 'p-8' : 'p-6'}\n `;\n\n // ============= 渲染 =============\n\n return (\n <div className=\"w-full space-y-4\">\n {/* 文件上传区域 */}\n <div\n className={containerClasses}\n onDragOver={handleDragOver}\n onDragLeave={handleDragLeave}\n onDrop={handleDrop}\n onClick={handleClick}\n >\n <div className={uploadAreaClasses}>\n <Upload\n className={`mx-auto mb-4 text-gray-400 ${mode === 'compact' ? 'w-8 h-8 mb-2' : 'w-12 h-12'}`}\n />\n\n {mode === 'compact' ? (\n <p className=\"text-sm text-gray-600 dark:text-gray-400\">点击上传或拖拽文件到这里</p>\n ) : (\n <>\n <h3 className=\"text-lg font-semibold text-gray-700 dark:text-gray-300 mb-2\">\n 上传文件\n </h3>\n <p className=\"text-gray-600 dark:text-gray-400 mb-2\">点击选择文件或拖拽文件到这里</p>\n {mode === 'detailed' && (\n <div className=\"text-sm text-gray-500 space-y-1\">\n {acceptedTypes.length > 0 && <p>支持格式: {acceptedTypes.join(', ')}</p>}\n <p>\n 最大大小: {maxFileSize}MB | 最多文件: {maxFiles}个\n </p>\n </div>\n )}\n </>\n )}\n </div>\n\n <input\n ref={fileInputRef}\n type=\"file\"\n multiple={multiple}\n accept={acceptedTypes.join(',')}\n onChange={handleInputChange}\n className=\"hidden\"\n disabled={disabled}\n />\n </div>\n\n {/* 上传进度列表 */}\n {uploadingFiles.length > 0 && (\n <div className=\"space-y-2\">\n <h4 className=\"text-sm font-medium text-gray-700 dark:text-gray-300\">\n 上传中 ({uploadingFiles.length})\n </h4>\n\n {uploadingFiles.map((uploadingFile) => (\n <div\n key={uploadingFile.id}\n className=\"flex items-center space-x-3 p-3 bg-gray-50 dark:bg-gray-800 rounded-lg\"\n >\n {/* 文件图标 */}\n <div className=\"flex-shrink-0\">\n {uploadingFile.progress.status === 'failed' ? (\n <AlertCircle className=\"w-5 h-5 text-red-500\" />\n ) : uploadingFile.progress.status === 'completed' ? (\n <CheckCircle2 className=\"w-5 h-5 text-green-500\" />\n ) : (\n <Loader2 className=\"w-5 h-5 text-blue-500 animate-spin\" />\n )}\n </div>\n\n {/* 文件信息 */}\n <div className=\"flex-grow min-w-0\">\n <div className=\"flex items-center justify-between mb-1\">\n <p className=\"text-sm font-medium text-gray-700 dark:text-gray-300 truncate\">\n {uploadingFile.file.name}\n </p>\n <span className=\"text-xs text-gray-500\">\n {formatFileSize(uploadingFile.file.size)}\n </span>\n </div>\n\n {uploadingFile.error ? (\n <p className=\"text-xs text-red-500\">{uploadingFile.error}</p>\n ) : (\n <>\n <div className=\"w-full bg-gray-200 dark:bg-gray-700 rounded-full h-2 mb-1\">\n <div\n className=\"bg-blue-500 h-2 rounded-full transition-all duration-300\"\n style={{ width: `${uploadingFile.progress.progress}%` }}\n />\n </div>\n <p className=\"text-xs text-gray-500\">\n {formatProgress(uploadingFile.progress)}\n </p>\n </>\n )}\n </div>\n\n {/* 移除按钮 */}\n <button\n onClick={(e) => {\n e.stopPropagation();\n removeUploadingFile(uploadingFile.id);\n }}\n className=\"flex-shrink-0 p-1 text-gray-400 hover:text-red-500 transition-colors\"\n >\n <X className=\"w-4 h-4\" />\n </button>\n </div>\n ))}\n </div>\n )}\n\n {/* 已完成文件列表 */}\n {completedFiles.length > 0 && (\n <div className=\"space-y-2\">\n <h4 className=\"text-sm font-medium text-gray-700 dark:text-gray-300\">\n 已完成 ({completedFiles.length})\n </h4>\n\n {completedFiles.map((file) => (\n <div\n key={file.id}\n className=\"flex items-center space-x-3 p-3 bg-green-50 dark:bg-green-900/20 rounded-lg\"\n >\n {/* 文件图标 */}\n <div className=\"flex-shrink-0\">{getFileIcon(file.mimeType)}</div>\n\n {/* 文件信息 */}\n <div className=\"flex-grow min-w-0\">\n <div className=\"flex items-center justify-between mb-1\">\n <p className=\"text-sm font-medium text-gray-700 dark:text-gray-300 truncate\">\n {file.originalName}\n </p>\n <span className=\"text-xs text-gray-500\">{formatFileSize(file.size)}</span>\n </div>\n <p className=\"text-xs text-green-600 dark:text-green-400\">\n 上传成功 • {new Date(file.uploadTime).toLocaleTimeString()}\n </p>\n </div>\n\n {/* 移除按钮 */}\n <button\n onClick={(e) => {\n e.stopPropagation();\n removeCompletedFile(file.id);\n }}\n className=\"flex-shrink-0 p-1 text-gray-400 hover:text-red-500 transition-colors\"\n >\n <X className=\"w-4 h-4\" />\n </button>\n </div>\n ))}\n </div>\n )}\n\n {/* 统计信息 */}\n {mode === 'detailed' && (completedFiles.length > 0 || uploadingFiles.length > 0) && (\n <div className=\"flex justify-between items-center text-sm text-gray-500 pt-2 border-t border-gray-200 dark:border-gray-700\">\n <span>总计: {completedFiles.length + uploadingFiles.length} 文件</span>\n <span>\n 大小:{' '}\n {formatFileSize(\n [\n ...completedFiles.map((f) => f.size),\n ...uploadingFiles.map((f) => f.file.size),\n ].reduce((total, size) => total + size, 0)\n )}\n </span>\n </div>\n )}\n </div>\n );\n};\n\nexport default FileUploader;\n\n"]}
|