@sl-material/sl-import 1.0.0-beta0 → 1.0.0-beta11
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/README.md +77 -64
- package/index.d.ts +27 -6
- package/package.json +1 -1
- package/sl-import.cjs.js +1 -1
- package/sl-import.es.js +342 -212
- package/sl-import.umd.umd.js +33 -33
package/sl-import.es.js
CHANGED
|
@@ -2192,7 +2192,7 @@ const zhCN = {
|
|
|
2192
2192
|
selectDate: "选择日期",
|
|
2193
2193
|
// 上传部分
|
|
2194
2194
|
uploadTitle: "3.上传文件",
|
|
2195
|
-
dragFileHere: "
|
|
2195
|
+
dragFileHere: "将文件拖到此处,",
|
|
2196
2196
|
or: "或",
|
|
2197
2197
|
uploadLinkText: "点击上传",
|
|
2198
2198
|
uploadHint: "文件仅支持扩展名:.xls,.xlsx",
|
|
@@ -2278,7 +2278,7 @@ const zhTW = {
|
|
|
2278
2278
|
selectDate: "選擇日期",
|
|
2279
2279
|
// 上傳部分
|
|
2280
2280
|
uploadTitle: "3.上傳檔案",
|
|
2281
|
-
dragFileHere: "
|
|
2281
|
+
dragFileHere: "將檔案拖到此處,",
|
|
2282
2282
|
or: "或",
|
|
2283
2283
|
uploadLinkText: "點擊上傳",
|
|
2284
2284
|
uploadHint: "檔案僅支援副檔名:.xls,.xlsx",
|
|
@@ -2364,7 +2364,7 @@ const ja = {
|
|
|
2364
2364
|
selectDate: "日付を選択",
|
|
2365
2365
|
// アップロード部分
|
|
2366
2366
|
uploadTitle: "3.ファイルをアップロード",
|
|
2367
|
-
dragFileHere: "
|
|
2367
|
+
dragFileHere: "ファイルをここにドラッグ、",
|
|
2368
2368
|
or: "または",
|
|
2369
2369
|
uploadLinkText: "クリックしてアップロード",
|
|
2370
2370
|
uploadHint: "ファイルは拡張子のみサポート:.xls,.xlsx",
|
|
@@ -2450,7 +2450,7 @@ const id = {
|
|
|
2450
2450
|
selectDate: "Pilih Tanggal",
|
|
2451
2451
|
// Bagian unggah
|
|
2452
2452
|
uploadTitle: "3. Unggah File",
|
|
2453
|
-
dragFileHere: "Seret file di sini,
|
|
2453
|
+
dragFileHere: "Seret file di sini, ",
|
|
2454
2454
|
or: "atau",
|
|
2455
2455
|
uploadLinkText: "klik untuk mengunggah",
|
|
2456
2456
|
uploadHint: "Hanya mendukung ekstensi file: .xls,.xlsx",
|
|
@@ -2536,7 +2536,7 @@ const enUS = {
|
|
|
2536
2536
|
selectDate: "Select Date",
|
|
2537
2537
|
// 上传部分
|
|
2538
2538
|
uploadTitle: "3. Upload File",
|
|
2539
|
-
dragFileHere: "Drag files here,
|
|
2539
|
+
dragFileHere: "Drag files here, ",
|
|
2540
2540
|
or: "or",
|
|
2541
2541
|
uploadLinkText: "click to upload",
|
|
2542
2542
|
uploadHint: "Supports batch import, file size not exceeding 10MB",
|
|
@@ -2956,6 +2956,170 @@ class ImportDialogRenderer {
|
|
|
2956
2956
|
`;
|
|
2957
2957
|
}
|
|
2958
2958
|
}
|
|
2959
|
+
class ChunkedUploader {
|
|
2960
|
+
constructor(chunkedConfig, callbacks = {}) {
|
|
2961
|
+
__publicField(this, "resumable");
|
|
2962
|
+
__publicField(this, "currentFileItem", null);
|
|
2963
|
+
__publicField(this, "chunkedConfig");
|
|
2964
|
+
__publicField(this, "callbacks");
|
|
2965
|
+
// Promise resolve/reject 函数存储
|
|
2966
|
+
__publicField(this, "uploadCompleteResolve");
|
|
2967
|
+
__publicField(this, "uploadCompleteReject");
|
|
2968
|
+
this.chunkedConfig = chunkedConfig;
|
|
2969
|
+
this.callbacks = callbacks;
|
|
2970
|
+
}
|
|
2971
|
+
/**
|
|
2972
|
+
* 上传单个文件(分片方式)
|
|
2973
|
+
*/
|
|
2974
|
+
async upload(fileItem) {
|
|
2975
|
+
try {
|
|
2976
|
+
const initResult = await this.chunkedConfig.initUpload(
|
|
2977
|
+
fileItem.file.name,
|
|
2978
|
+
fileItem.file.size
|
|
2979
|
+
);
|
|
2980
|
+
fileItem.uploadSessionId = initResult.uploadSessionId;
|
|
2981
|
+
this.currentFileItem = fileItem;
|
|
2982
|
+
this.initResumable(initResult);
|
|
2983
|
+
this.resumable.addFile(fileItem.file);
|
|
2984
|
+
return await this.waitForUploadComplete();
|
|
2985
|
+
} catch (error) {
|
|
2986
|
+
const err = error instanceof Error ? error : new Error(String(error));
|
|
2987
|
+
throw err;
|
|
2988
|
+
}
|
|
2989
|
+
}
|
|
2990
|
+
/**
|
|
2991
|
+
* 等待上传完成
|
|
2992
|
+
*/
|
|
2993
|
+
waitForUploadComplete() {
|
|
2994
|
+
return new Promise((resolve, reject) => {
|
|
2995
|
+
this.uploadCompleteResolve = resolve;
|
|
2996
|
+
this.uploadCompleteReject = reject;
|
|
2997
|
+
});
|
|
2998
|
+
}
|
|
2999
|
+
/**
|
|
3000
|
+
* 初始化Resumable实例
|
|
3001
|
+
*/
|
|
3002
|
+
initResumable(initResult) {
|
|
3003
|
+
if (this.resumable) {
|
|
3004
|
+
this.resumable.cancel();
|
|
3005
|
+
}
|
|
3006
|
+
const customConfig = this.chunkedConfig.getResumableConfig(initResult);
|
|
3007
|
+
const defaultConfig = {
|
|
3008
|
+
chunkSize: initResult.partSize,
|
|
3009
|
+
simultaneousUploads: 3,
|
|
3010
|
+
testChunks: false,
|
|
3011
|
+
method: "multipart",
|
|
3012
|
+
chunkNumberParameterName: "partNumber",
|
|
3013
|
+
totalChunksParameterName: "totalParts",
|
|
3014
|
+
fileParameterName: "file",
|
|
3015
|
+
withCredentials: true,
|
|
3016
|
+
maxChunkRetries: 3,
|
|
3017
|
+
chunkRetryInterval: 1e3,
|
|
3018
|
+
forceChunkSize: true
|
|
3019
|
+
};
|
|
3020
|
+
const finalConfig = { ...defaultConfig, ...customConfig };
|
|
3021
|
+
this.resumable = new Resumable(finalConfig);
|
|
3022
|
+
this.bindResumableEvents();
|
|
3023
|
+
}
|
|
3024
|
+
/**
|
|
3025
|
+
* 绑定Resumable事件监听器
|
|
3026
|
+
*/
|
|
3027
|
+
bindResumableEvents() {
|
|
3028
|
+
this.resumable.on("progress", () => {
|
|
3029
|
+
var _a, _b, _c, _d;
|
|
3030
|
+
const progress = Math.floor(this.resumable.progress() * 100);
|
|
3031
|
+
if (this.currentFileItem) {
|
|
3032
|
+
this.currentFileItem.progress = Math.min(progress, 90);
|
|
3033
|
+
(_b = (_a = this.callbacks).onProgress) == null ? void 0 : _b.call(
|
|
3034
|
+
_a,
|
|
3035
|
+
this.currentFileItem,
|
|
3036
|
+
this.currentFileItem.progress
|
|
3037
|
+
);
|
|
3038
|
+
}
|
|
3039
|
+
(_d = (_c = this.callbacks).onUpdate) == null ? void 0 : _d.call(_c);
|
|
3040
|
+
});
|
|
3041
|
+
this.resumable.on("fileSuccess", () => {
|
|
3042
|
+
this.handleResumableComplete();
|
|
3043
|
+
});
|
|
3044
|
+
this.resumable.on("error", (message) => {
|
|
3045
|
+
console.error("[ChunkedUploader] 上传错误:", message);
|
|
3046
|
+
this.handleResumableError(message);
|
|
3047
|
+
});
|
|
3048
|
+
this.resumable.on("fileAdded", () => {
|
|
3049
|
+
this.resumable.upload();
|
|
3050
|
+
});
|
|
3051
|
+
}
|
|
3052
|
+
/**
|
|
3053
|
+
* 处理Resumable上传完成
|
|
3054
|
+
*/
|
|
3055
|
+
async handleResumableComplete() {
|
|
3056
|
+
if (!this.currentFileItem || !this.uploadCompleteResolve || !this.uploadCompleteReject) {
|
|
3057
|
+
return;
|
|
3058
|
+
}
|
|
3059
|
+
try {
|
|
3060
|
+
const mergeResult = await this.chunkedConfig.mergeChunks(
|
|
3061
|
+
this.currentFileItem.uploadSessionId
|
|
3062
|
+
);
|
|
3063
|
+
if (this.currentFileItem) {
|
|
3064
|
+
this.currentFileItem.progress = 100;
|
|
3065
|
+
}
|
|
3066
|
+
this.uploadCompleteResolve(mergeResult);
|
|
3067
|
+
this.cleanup();
|
|
3068
|
+
} catch (error) {
|
|
3069
|
+
const err = error instanceof Error ? error : new Error(String(error));
|
|
3070
|
+
this.handleResumableError(err.message);
|
|
3071
|
+
}
|
|
3072
|
+
}
|
|
3073
|
+
/**
|
|
3074
|
+
* 处理Resumable上传错误
|
|
3075
|
+
*/
|
|
3076
|
+
handleResumableError(message) {
|
|
3077
|
+
var _a, _b;
|
|
3078
|
+
if (this.currentFileItem) {
|
|
3079
|
+
this.currentFileItem.status = "error";
|
|
3080
|
+
this.currentFileItem.errorMessage = message;
|
|
3081
|
+
}
|
|
3082
|
+
if (this.uploadCompleteReject) {
|
|
3083
|
+
this.uploadCompleteReject(new Error(message));
|
|
3084
|
+
this.cleanup();
|
|
3085
|
+
}
|
|
3086
|
+
(_b = (_a = this.callbacks).onUpdate) == null ? void 0 : _b.call(_a);
|
|
3087
|
+
}
|
|
3088
|
+
/**
|
|
3089
|
+
* 清理状态
|
|
3090
|
+
*/
|
|
3091
|
+
cleanup() {
|
|
3092
|
+
this.uploadCompleteResolve = void 0;
|
|
3093
|
+
this.uploadCompleteReject = void 0;
|
|
3094
|
+
}
|
|
3095
|
+
/**
|
|
3096
|
+
* 暂停上传
|
|
3097
|
+
*/
|
|
3098
|
+
pause() {
|
|
3099
|
+
if (this.resumable) {
|
|
3100
|
+
this.resumable.pause();
|
|
3101
|
+
}
|
|
3102
|
+
}
|
|
3103
|
+
/**
|
|
3104
|
+
* 恢复上传
|
|
3105
|
+
*/
|
|
3106
|
+
resume() {
|
|
3107
|
+
if (this.resumable) {
|
|
3108
|
+
this.resumable.upload();
|
|
3109
|
+
}
|
|
3110
|
+
}
|
|
3111
|
+
/**
|
|
3112
|
+
* 取消上传
|
|
3113
|
+
*/
|
|
3114
|
+
cancel() {
|
|
3115
|
+
if (this.resumable) {
|
|
3116
|
+
this.resumable.cancel();
|
|
3117
|
+
this.resumable = null;
|
|
3118
|
+
}
|
|
3119
|
+
this.currentFileItem = null;
|
|
3120
|
+
this.cleanup();
|
|
3121
|
+
}
|
|
3122
|
+
}
|
|
2959
3123
|
const generateId = () => {
|
|
2960
3124
|
return `file_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
|
|
2961
3125
|
};
|
|
@@ -2963,13 +3127,11 @@ class ImportDialogUploader {
|
|
|
2963
3127
|
constructor(config, callbacks = {}) {
|
|
2964
3128
|
__publicField(this, "config");
|
|
2965
3129
|
__publicField(this, "callbacks");
|
|
2966
|
-
|
|
2967
|
-
|
|
2968
|
-
|
|
2969
|
-
|
|
2970
|
-
|
|
2971
|
-
__publicField(this, "uploadCompleteResolve");
|
|
2972
|
-
__publicField(this, "uploadCompleteReject");
|
|
3130
|
+
// 分片上传器实例
|
|
3131
|
+
__publicField(this, "chunkedUploader", null);
|
|
3132
|
+
// 并发上传队列
|
|
3133
|
+
__publicField(this, "uploadQueue", []);
|
|
3134
|
+
__publicField(this, "activeUploads", 0);
|
|
2973
3135
|
// 上传状态
|
|
2974
3136
|
__publicField(this, "uploadFileList", []);
|
|
2975
3137
|
//上传文件列表
|
|
@@ -2981,6 +3143,32 @@ class ImportDialogUploader {
|
|
|
2981
3143
|
__publicField(this, "uploadMessageType", "info");
|
|
2982
3144
|
this.config = config;
|
|
2983
3145
|
this.callbacks = callbacks;
|
|
3146
|
+
this.initUploaders();
|
|
3147
|
+
}
|
|
3148
|
+
/**
|
|
3149
|
+
* 初始化上传器
|
|
3150
|
+
*/
|
|
3151
|
+
initUploaders() {
|
|
3152
|
+
const uploadConfig = this.config.uploadConfig;
|
|
3153
|
+
if ((uploadConfig == null ? void 0 : uploadConfig.chunkedUpload) && !this.config.multiple) {
|
|
3154
|
+
this.chunkedUploader = new ChunkedUploader(uploadConfig.chunkedUpload, {
|
|
3155
|
+
onProgress: (fileItem, progress) => {
|
|
3156
|
+
var _a, _b, _c, _d;
|
|
3157
|
+
(_b = (_a = this.callbacks).onUploadProgress) == null ? void 0 : _b.call(_a, fileItem, progress);
|
|
3158
|
+
(_d = (_c = this.callbacks).onUpdate) == null ? void 0 : _d.call(_c);
|
|
3159
|
+
},
|
|
3160
|
+
onUpdate: () => {
|
|
3161
|
+
var _a, _b;
|
|
3162
|
+
return (_b = (_a = this.callbacks).onUpdate) == null ? void 0 : _b.call(_a);
|
|
3163
|
+
}
|
|
3164
|
+
});
|
|
3165
|
+
}
|
|
3166
|
+
}
|
|
3167
|
+
/**
|
|
3168
|
+
* 获取并发限制数
|
|
3169
|
+
*/
|
|
3170
|
+
get concurrentLimit() {
|
|
3171
|
+
return this.config.concurrentLimit ?? 3;
|
|
2984
3172
|
}
|
|
2985
3173
|
/**
|
|
2986
3174
|
* 判断是否应该使用分片上传
|
|
@@ -2990,15 +3178,9 @@ class ImportDialogUploader {
|
|
|
2990
3178
|
const uploadConfig = this.config.uploadConfig;
|
|
2991
3179
|
return !!((uploadConfig == null ? void 0 : uploadConfig.chunkedUpload) && !this.config.multiple);
|
|
2992
3180
|
}
|
|
2993
|
-
/**
|
|
2994
|
-
* 获取分片上传配置
|
|
2995
|
-
*/
|
|
2996
|
-
getChunkedUploadConfig() {
|
|
2997
|
-
var _a;
|
|
2998
|
-
return ((_a = this.config.uploadConfig) == null ? void 0 : _a.chunkedUpload) || null;
|
|
2999
|
-
}
|
|
3000
3181
|
updateConfig(config) {
|
|
3001
3182
|
this.config = { ...this.config, ...config };
|
|
3183
|
+
this.initUploaders();
|
|
3002
3184
|
}
|
|
3003
3185
|
updateCallbacks(callbacks) {
|
|
3004
3186
|
this.callbacks = { ...this.callbacks, ...callbacks };
|
|
@@ -3011,15 +3193,14 @@ class ImportDialogUploader {
|
|
|
3011
3193
|
this.isUploading = false;
|
|
3012
3194
|
this.uploadMessage = "";
|
|
3013
3195
|
this.uploadMessageType = "info";
|
|
3014
|
-
this.
|
|
3015
|
-
this.
|
|
3016
|
-
this.uploadCompleteReject = void 0;
|
|
3196
|
+
this.uploadQueue = [];
|
|
3197
|
+
this.activeUploads = 0;
|
|
3017
3198
|
}
|
|
3018
3199
|
/**
|
|
3019
3200
|
* 文件上传之前的校验 选择文件时调用
|
|
3020
3201
|
*/
|
|
3021
3202
|
beforeUpload(files) {
|
|
3022
|
-
var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j
|
|
3203
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j;
|
|
3023
3204
|
const fileArray = Array.isArray(files) ? files : [files];
|
|
3024
3205
|
if (!fileArray.length) {
|
|
3025
3206
|
(_b = (_a = this.callbacks).onMessage) == null ? void 0 : _b.call(_a, "请选择文件", "warning");
|
|
@@ -3065,12 +3246,69 @@ class ImportDialogUploader {
|
|
|
3065
3246
|
}
|
|
3066
3247
|
(_h = (_g = this.callbacks).onUpdate) == null ? void 0 : _h.call(_g);
|
|
3067
3248
|
(_j = (_i = this.callbacks).onFileChange) == null ? void 0 : _j.call(_i, this.uploadFileList);
|
|
3068
|
-
|
|
3069
|
-
if (autoUpload) {
|
|
3070
|
-
this.startUploadFiles();
|
|
3071
|
-
}
|
|
3249
|
+
this.processFilesWithCustomUpload();
|
|
3072
3250
|
return true;
|
|
3073
3251
|
}
|
|
3252
|
+
/**
|
|
3253
|
+
* 使用 customUpload 预处理文件
|
|
3254
|
+
* 在选择文件后立即调用,用于二次加工参数或自定义校验
|
|
3255
|
+
*/
|
|
3256
|
+
async processFilesWithCustomUpload() {
|
|
3257
|
+
const pendingFiles = this.uploadFileList.filter(
|
|
3258
|
+
(f) => f.status === "pending"
|
|
3259
|
+
);
|
|
3260
|
+
for (const fileItem of pendingFiles) {
|
|
3261
|
+
await this.processFileWithCustomUpload(fileItem);
|
|
3262
|
+
}
|
|
3263
|
+
}
|
|
3264
|
+
/**
|
|
3265
|
+
* 单个文件的预处理
|
|
3266
|
+
*/
|
|
3267
|
+
async processFileWithCustomUpload(fileItem) {
|
|
3268
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k;
|
|
3269
|
+
const customUpload = (_a = this.config.uploadConfig) == null ? void 0 : _a.customUpload;
|
|
3270
|
+
if (!customUpload) {
|
|
3271
|
+
fileItem.status = "success";
|
|
3272
|
+
fileItem.progress = 100;
|
|
3273
|
+
fileItem.response = fileItem.file;
|
|
3274
|
+
(_c = (_b = this.callbacks).onUpdate) == null ? void 0 : _c.call(_b);
|
|
3275
|
+
return;
|
|
3276
|
+
}
|
|
3277
|
+
fileItem.status = "uploading";
|
|
3278
|
+
fileItem.progress = 0;
|
|
3279
|
+
this.isUploading = true;
|
|
3280
|
+
(_e = (_d = this.callbacks).onUpdate) == null ? void 0 : _e.call(_d);
|
|
3281
|
+
try {
|
|
3282
|
+
const context = {
|
|
3283
|
+
fileList: [...this.uploadFileList],
|
|
3284
|
+
removeFile: (index) => {
|
|
3285
|
+
this.removeFile(index);
|
|
3286
|
+
}
|
|
3287
|
+
};
|
|
3288
|
+
fileItem.response = await customUpload(
|
|
3289
|
+
fileItem.file,
|
|
3290
|
+
context,
|
|
3291
|
+
(progress) => {
|
|
3292
|
+
var _a2, _b2, _c2, _d2;
|
|
3293
|
+
fileItem.progress = progress;
|
|
3294
|
+
(_b2 = (_a2 = this.callbacks).onUploadProgress) == null ? void 0 : _b2.call(_a2, fileItem, progress);
|
|
3295
|
+
(_d2 = (_c2 = this.callbacks).onUpdate) == null ? void 0 : _d2.call(_c2);
|
|
3296
|
+
}
|
|
3297
|
+
);
|
|
3298
|
+
fileItem.status = "success";
|
|
3299
|
+
fileItem.progress = 100;
|
|
3300
|
+
(_g = (_f = this.callbacks).onUploadSuccess) == null ? void 0 : _g.call(_f, fileItem, fileItem.response);
|
|
3301
|
+
} catch (error) {
|
|
3302
|
+
fileItem.status = "error";
|
|
3303
|
+
fileItem.errorMessage = error instanceof Error ? error.message : "处理失败";
|
|
3304
|
+
(_i = (_h = this.callbacks).onUploadError) == null ? void 0 : _i.call(_h, fileItem, error);
|
|
3305
|
+
}
|
|
3306
|
+
this.isUploading = this.uploadFileList.some(
|
|
3307
|
+
(f) => f.status === "uploading"
|
|
3308
|
+
);
|
|
3309
|
+
(_k = (_j = this.callbacks).onUpdate) == null ? void 0 : _k.call(_j);
|
|
3310
|
+
this.updateOverallProgress();
|
|
3311
|
+
}
|
|
3074
3312
|
/**
|
|
3075
3313
|
* 删除文件
|
|
3076
3314
|
*/
|
|
@@ -3096,16 +3334,34 @@ class ImportDialogUploader {
|
|
|
3096
3334
|
(_f = (_e = this.callbacks).onUpdate) == null ? void 0 : _f.call(_e);
|
|
3097
3335
|
return true;
|
|
3098
3336
|
}
|
|
3099
|
-
|
|
3100
|
-
|
|
3101
|
-
|
|
3337
|
+
/**
|
|
3338
|
+
* 将文件加入上传队列并启动处理
|
|
3339
|
+
*/
|
|
3340
|
+
enqueueUpload(fileItems) {
|
|
3341
|
+
const newItems = fileItems.filter(
|
|
3342
|
+
(item) => !this.uploadQueue.some((q) => q.id === item.id)
|
|
3102
3343
|
);
|
|
3103
|
-
|
|
3104
|
-
|
|
3344
|
+
this.uploadQueue.push(...newItems);
|
|
3345
|
+
this.processUploadQueue();
|
|
3346
|
+
}
|
|
3347
|
+
/**
|
|
3348
|
+
* 处理上传队列(支持并发)
|
|
3349
|
+
*/
|
|
3350
|
+
processUploadQueue() {
|
|
3351
|
+
while (this.uploadQueue.length > 0 && this.activeUploads < this.concurrentLimit) {
|
|
3352
|
+
const fileItem = this.uploadQueue.shift();
|
|
3353
|
+
if (fileItem.status !== "pending") {
|
|
3354
|
+
continue;
|
|
3355
|
+
}
|
|
3356
|
+
this.activeUploads++;
|
|
3357
|
+
this.uploadSingleFile(fileItem).finally(() => {
|
|
3358
|
+
this.activeUploads--;
|
|
3359
|
+
this.processUploadQueue();
|
|
3360
|
+
});
|
|
3105
3361
|
}
|
|
3106
3362
|
}
|
|
3107
3363
|
/**
|
|
3108
|
-
*
|
|
3364
|
+
* 单个文件分片上传
|
|
3109
3365
|
* @param fileItem
|
|
3110
3366
|
*/
|
|
3111
3367
|
async uploadSingleFile(fileItem) {
|
|
@@ -3115,11 +3371,7 @@ class ImportDialogUploader {
|
|
|
3115
3371
|
this.isUploading = true;
|
|
3116
3372
|
(_b = (_a = this.callbacks).onUpdate) == null ? void 0 : _b.call(_a);
|
|
3117
3373
|
try {
|
|
3118
|
-
|
|
3119
|
-
await this.uploadFileChunked(fileItem);
|
|
3120
|
-
} else {
|
|
3121
|
-
await this.uploadFileSimple(fileItem);
|
|
3122
|
-
}
|
|
3374
|
+
fileItem.response = await this.uploadFileChunked(fileItem);
|
|
3123
3375
|
fileItem.status = "success";
|
|
3124
3376
|
fileItem.progress = 100;
|
|
3125
3377
|
(_d = (_c = this.callbacks).onUploadSuccess) == null ? void 0 : _d.call(_c, fileItem, fileItem.response);
|
|
@@ -3134,201 +3386,58 @@ class ImportDialogUploader {
|
|
|
3134
3386
|
(_h = (_g = this.callbacks).onUpdate) == null ? void 0 : _h.call(_g);
|
|
3135
3387
|
this.updateOverallProgress();
|
|
3136
3388
|
}
|
|
3137
|
-
/**
|
|
3138
|
-
* 普通上传(非分片)
|
|
3139
|
-
*/
|
|
3140
|
-
async uploadFileSimple(fileItem) {
|
|
3141
|
-
var _a;
|
|
3142
|
-
const customUpload = (_a = this.config.uploadConfig) == null ? void 0 : _a.customUpload;
|
|
3143
|
-
if (customUpload) {
|
|
3144
|
-
fileItem.response = await customUpload(fileItem.file, (progress) => {
|
|
3145
|
-
var _a2, _b, _c, _d;
|
|
3146
|
-
fileItem.progress = progress;
|
|
3147
|
-
(_b = (_a2 = this.callbacks).onUploadProgress) == null ? void 0 : _b.call(_a2, fileItem, progress);
|
|
3148
|
-
(_d = (_c = this.callbacks).onUpdate) == null ? void 0 : _d.call(_c);
|
|
3149
|
-
});
|
|
3150
|
-
} else {
|
|
3151
|
-
fileItem.response = fileItem.file;
|
|
3152
|
-
}
|
|
3153
|
-
}
|
|
3154
3389
|
/**
|
|
3155
3390
|
* 分片上传
|
|
3156
|
-
* 业务侧只需提供:initUpload, getResumableConfig, mergeChunks
|
|
3157
3391
|
*/
|
|
3158
3392
|
async uploadFileChunked(fileItem) {
|
|
3159
|
-
|
|
3160
|
-
if (!chunkedConfig) {
|
|
3393
|
+
if (!this.chunkedUploader) {
|
|
3161
3394
|
throw new Error("分片上传需要配置 chunkedUpload");
|
|
3162
3395
|
}
|
|
3163
|
-
|
|
3164
|
-
const initResult = await chunkedConfig.initUpload(
|
|
3165
|
-
fileItem.file.name,
|
|
3166
|
-
fileItem.file.size
|
|
3167
|
-
);
|
|
3168
|
-
fileItem.uploadSessionId = initResult.uploadSessionId;
|
|
3169
|
-
this.currentFileItem = fileItem;
|
|
3170
|
-
this.initResumable(chunkedConfig, initResult);
|
|
3171
|
-
this.resumable.addFile(fileItem.file);
|
|
3172
|
-
fileItem.response = await this.waitForUploadComplete();
|
|
3173
|
-
} catch (error) {
|
|
3174
|
-
const err = error instanceof Error ? error : new Error(String(error));
|
|
3175
|
-
throw err;
|
|
3176
|
-
}
|
|
3177
|
-
}
|
|
3178
|
-
/**
|
|
3179
|
-
* 等待上传完成
|
|
3180
|
-
*/
|
|
3181
|
-
waitForUploadComplete() {
|
|
3182
|
-
return new Promise((resolve, reject) => {
|
|
3183
|
-
this.uploadCompleteResolve = resolve;
|
|
3184
|
-
this.uploadCompleteReject = reject;
|
|
3185
|
-
});
|
|
3186
|
-
}
|
|
3187
|
-
/**
|
|
3188
|
-
* 初始化Resumable实例
|
|
3189
|
-
*/
|
|
3190
|
-
initResumable(chunkedConfig, initResult) {
|
|
3191
|
-
if (this.resumable) {
|
|
3192
|
-
this.resumable.cancel();
|
|
3193
|
-
}
|
|
3194
|
-
const customConfig = chunkedConfig.getResumableConfig(initResult);
|
|
3195
|
-
const defaultConfig = {
|
|
3196
|
-
chunkSize: initResult.partSize,
|
|
3197
|
-
simultaneousUploads: 3,
|
|
3198
|
-
testChunks: false,
|
|
3199
|
-
method: "multipart",
|
|
3200
|
-
chunkNumberParameterName: "partNumber",
|
|
3201
|
-
totalChunksParameterName: "totalParts",
|
|
3202
|
-
fileParameterName: "file",
|
|
3203
|
-
withCredentials: true,
|
|
3204
|
-
maxChunkRetries: 3,
|
|
3205
|
-
chunkRetryInterval: 1e3,
|
|
3206
|
-
forceChunkSize: true
|
|
3207
|
-
};
|
|
3208
|
-
const finalConfig = { ...defaultConfig, ...customConfig };
|
|
3209
|
-
this.resumable = new Resumable(finalConfig);
|
|
3210
|
-
this.bindResumableEvents();
|
|
3396
|
+
return await this.chunkedUploader.upload(fileItem);
|
|
3211
3397
|
}
|
|
3212
3398
|
/**
|
|
3213
|
-
*
|
|
3399
|
+
* 手动触发分片上传(仅用于分片上传场景)
|
|
3214
3400
|
*/
|
|
3215
|
-
|
|
3216
|
-
this.
|
|
3217
|
-
|
|
3218
|
-
const progress = Math.floor(this.resumable.progress() * 100);
|
|
3219
|
-
this.uploadProgress = progress;
|
|
3220
|
-
this.uploadMessage = `正在上传 (${progress}%)...`;
|
|
3221
|
-
if (this.currentFileItem) {
|
|
3222
|
-
this.currentFileItem.progress = Math.min(progress, 90);
|
|
3223
|
-
(_b = (_a = this.callbacks).onUploadProgress) == null ? void 0 : _b.call(
|
|
3224
|
-
_a,
|
|
3225
|
-
this.currentFileItem,
|
|
3226
|
-
this.currentFileItem.progress
|
|
3227
|
-
);
|
|
3228
|
-
}
|
|
3229
|
-
(_d = (_c = this.callbacks).onUpdate) == null ? void 0 : _d.call(_c);
|
|
3230
|
-
});
|
|
3231
|
-
this.resumable.on("fileSuccess", () => {
|
|
3232
|
-
this.handleResumableComplete();
|
|
3233
|
-
});
|
|
3234
|
-
this.resumable.on("error", (message) => {
|
|
3235
|
-
console.error("[Resumable分片上传] 上传错误:", message);
|
|
3236
|
-
this.handleResumableError(message);
|
|
3237
|
-
});
|
|
3238
|
-
this.resumable.on("fileAdded", () => {
|
|
3239
|
-
this.resumable.upload();
|
|
3240
|
-
});
|
|
3241
|
-
this.resumable.on("pause", () => {
|
|
3242
|
-
this.uploadMessage = "上传已暂停";
|
|
3243
|
-
});
|
|
3244
|
-
}
|
|
3245
|
-
/**
|
|
3246
|
-
* 处理Resumable上传完成
|
|
3247
|
-
*/
|
|
3248
|
-
async handleResumableComplete() {
|
|
3249
|
-
var _a;
|
|
3250
|
-
if (!this.currentFileItem || !this.uploadCompleteResolve || !this.uploadCompleteReject) {
|
|
3251
|
-
return;
|
|
3252
|
-
}
|
|
3253
|
-
try {
|
|
3254
|
-
const chunkedConfig = this.getChunkedUploadConfig();
|
|
3255
|
-
if (!chunkedConfig) {
|
|
3256
|
-
throw new Error("分片上传配置缺失");
|
|
3257
|
-
}
|
|
3258
|
-
const mergeResult = await chunkedConfig.mergeChunks(
|
|
3259
|
-
this.currentFileItem.uploadSessionId
|
|
3260
|
-
);
|
|
3261
|
-
if (this.currentFileItem) {
|
|
3262
|
-
this.currentFileItem.progress = 100;
|
|
3263
|
-
}
|
|
3264
|
-
this.uploadMessage = "上传完成";
|
|
3265
|
-
this.uploadMessageType = "success";
|
|
3266
|
-
this.uploadCompleteResolve(mergeResult);
|
|
3267
|
-
this.uploadCompleteResolve = void 0;
|
|
3268
|
-
this.uploadCompleteReject = void 0;
|
|
3269
|
-
} catch (error) {
|
|
3270
|
-
const err = error instanceof Error ? error : new Error(String(error));
|
|
3271
|
-
this.handleResumableError(err.message);
|
|
3272
|
-
(_a = this.uploadCompleteReject) == null ? void 0 : _a.call(this, error);
|
|
3273
|
-
this.uploadCompleteResolve = void 0;
|
|
3274
|
-
this.uploadCompleteReject = void 0;
|
|
3275
|
-
}
|
|
3276
|
-
}
|
|
3277
|
-
/**
|
|
3278
|
-
* 处理Resumable上传错误
|
|
3279
|
-
*/
|
|
3280
|
-
handleResumableError(message) {
|
|
3281
|
-
var _a, _b;
|
|
3282
|
-
if (this.currentFileItem) {
|
|
3283
|
-
this.currentFileItem.status = "error";
|
|
3284
|
-
this.currentFileItem.errorMessage = message;
|
|
3285
|
-
}
|
|
3286
|
-
this.uploadMessage = message || "上传失败";
|
|
3287
|
-
this.uploadMessageType = "error";
|
|
3288
|
-
this.isUploading = false;
|
|
3289
|
-
if (this.uploadCompleteReject) {
|
|
3290
|
-
this.uploadCompleteReject(new Error(message));
|
|
3291
|
-
this.uploadCompleteResolve = void 0;
|
|
3292
|
-
this.uploadCompleteReject = void 0;
|
|
3401
|
+
async startUpload() {
|
|
3402
|
+
if (this.shouldUseChunkedUpload()) {
|
|
3403
|
+
await this.startChunkedUploadFiles();
|
|
3293
3404
|
}
|
|
3294
|
-
(_b = (_a = this.callbacks).onUpdate) == null ? void 0 : _b.call(_a);
|
|
3295
3405
|
}
|
|
3296
3406
|
/**
|
|
3297
|
-
*
|
|
3407
|
+
* 启动分片上传
|
|
3298
3408
|
*/
|
|
3299
|
-
async
|
|
3300
|
-
|
|
3409
|
+
async startChunkedUploadFiles() {
|
|
3410
|
+
const pendingFiles = this.uploadFileList.filter(
|
|
3411
|
+
(f) => f.status === "pending"
|
|
3412
|
+
);
|
|
3413
|
+
this.enqueueUpload(pendingFiles);
|
|
3301
3414
|
}
|
|
3302
3415
|
/**
|
|
3303
|
-
*
|
|
3416
|
+
* 暂停上传(仅分片上传支持)
|
|
3304
3417
|
*/
|
|
3305
3418
|
pauseUpload() {
|
|
3306
|
-
|
|
3307
|
-
|
|
3308
|
-
}
|
|
3419
|
+
var _a;
|
|
3420
|
+
(_a = this.chunkedUploader) == null ? void 0 : _a.pause();
|
|
3309
3421
|
}
|
|
3310
3422
|
/**
|
|
3311
|
-
*
|
|
3423
|
+
* 恢复上传(仅分片上传支持)
|
|
3312
3424
|
*/
|
|
3313
3425
|
resumeUpload() {
|
|
3314
|
-
|
|
3315
|
-
|
|
3316
|
-
}
|
|
3426
|
+
var _a;
|
|
3427
|
+
(_a = this.chunkedUploader) == null ? void 0 : _a.resume();
|
|
3317
3428
|
}
|
|
3318
3429
|
/**
|
|
3319
3430
|
* 取消上传
|
|
3320
3431
|
*/
|
|
3321
3432
|
cancelUpload() {
|
|
3322
|
-
var _a, _b;
|
|
3323
|
-
|
|
3324
|
-
|
|
3325
|
-
|
|
3326
|
-
}
|
|
3327
|
-
this.currentFileItem = null;
|
|
3433
|
+
var _a, _b, _c;
|
|
3434
|
+
(_a = this.chunkedUploader) == null ? void 0 : _a.cancel();
|
|
3435
|
+
this.uploadQueue = [];
|
|
3436
|
+
this.activeUploads = 0;
|
|
3328
3437
|
this.isUploading = false;
|
|
3329
3438
|
this.uploadMessage = "上传已取消";
|
|
3330
3439
|
this.uploadMessageType = "info";
|
|
3331
|
-
(
|
|
3440
|
+
(_c = (_b = this.callbacks).onUpdate) == null ? void 0 : _c.call(_b);
|
|
3332
3441
|
}
|
|
3333
3442
|
updateOverallProgress() {
|
|
3334
3443
|
if (this.uploadFileList.length === 0) {
|
|
@@ -3870,6 +3979,7 @@ const _ImportDialog = class _ImportDialog {
|
|
|
3870
3979
|
* @returns
|
|
3871
3980
|
*/
|
|
3872
3981
|
async handleConfirm() {
|
|
3982
|
+
var _a, _b, _c, _d;
|
|
3873
3983
|
if (this.uploader.uploadFileList.length === 0) {
|
|
3874
3984
|
this.showMessage(t("fileTypeError"), "warning");
|
|
3875
3985
|
return;
|
|
@@ -3879,13 +3989,20 @@ const _ImportDialog = class _ImportDialog {
|
|
|
3879
3989
|
return;
|
|
3880
3990
|
}
|
|
3881
3991
|
if (this.uploader.hasPendingFiles()) {
|
|
3882
|
-
this.confirmLoading
|
|
3883
|
-
|
|
3992
|
+
const confirmLoadingEnabled2 = ((_a = this.modalOptions.uploadConfig) == null ? void 0 : _a.confirmLoading) != null ? this.modalOptions.uploadConfig.confirmLoading : true;
|
|
3993
|
+
if (confirmLoadingEnabled2) {
|
|
3994
|
+
this.confirmLoading = true;
|
|
3995
|
+
this.updateModal();
|
|
3996
|
+
}
|
|
3884
3997
|
try {
|
|
3885
3998
|
await this.uploader.startUpload();
|
|
3886
3999
|
} catch (error) {
|
|
3887
4000
|
console.error("[ImportDialog] 上传失败:", error);
|
|
3888
4001
|
this.showMessage("上传失败,请重试", "error");
|
|
4002
|
+
if (confirmLoadingEnabled2) {
|
|
4003
|
+
this.confirmLoading = false;
|
|
4004
|
+
this.updateModal();
|
|
4005
|
+
}
|
|
3889
4006
|
return;
|
|
3890
4007
|
}
|
|
3891
4008
|
}
|
|
@@ -3896,14 +4013,20 @@ const _ImportDialog = class _ImportDialog {
|
|
|
3896
4013
|
`有 ${failedFiles.length} 个文件上传失败,请重新上传`,
|
|
3897
4014
|
"warning"
|
|
3898
4015
|
);
|
|
3899
|
-
this.confirmLoading
|
|
3900
|
-
|
|
4016
|
+
const confirmLoadingEnabled2 = ((_b = this.modalOptions.uploadConfig) == null ? void 0 : _b.confirmLoading) != null ? this.modalOptions.uploadConfig.confirmLoading : true;
|
|
4017
|
+
if (confirmLoadingEnabled2) {
|
|
4018
|
+
this.confirmLoading = false;
|
|
4019
|
+
this.updateModal();
|
|
4020
|
+
}
|
|
3901
4021
|
return;
|
|
3902
4022
|
}
|
|
3903
4023
|
if (!this.uploader.hasAllFilesUploaded()) {
|
|
3904
4024
|
this.showMessage("请等待所有文件上传完成", "warning");
|
|
3905
|
-
this.confirmLoading
|
|
3906
|
-
|
|
4025
|
+
const confirmLoadingEnabled2 = ((_c = this.modalOptions.uploadConfig) == null ? void 0 : _c.confirmLoading) != null ? this.modalOptions.uploadConfig.confirmLoading : true;
|
|
4026
|
+
if (confirmLoadingEnabled2) {
|
|
4027
|
+
this.confirmLoading = false;
|
|
4028
|
+
this.updateModal();
|
|
4029
|
+
}
|
|
3907
4030
|
return;
|
|
3908
4031
|
}
|
|
3909
4032
|
const uploadResponses = this.uploader.uploadFileList.map(
|
|
@@ -3915,6 +4038,11 @@ const _ImportDialog = class _ImportDialog {
|
|
|
3915
4038
|
activeTab: this.currentConfig.tabs[this.activeTabIndex],
|
|
3916
4039
|
activeTabIndex: this.activeTabIndex
|
|
3917
4040
|
};
|
|
4041
|
+
const confirmLoadingEnabled = ((_d = this.modalOptions.uploadConfig) == null ? void 0 : _d.confirmLoading) != null ? this.modalOptions.uploadConfig.confirmLoading : true;
|
|
4042
|
+
if (confirmLoadingEnabled) {
|
|
4043
|
+
this.confirmLoading = true;
|
|
4044
|
+
this.updateModal();
|
|
4045
|
+
}
|
|
3918
4046
|
try {
|
|
3919
4047
|
if (this.modalOptions.onBeforeConfirm) {
|
|
3920
4048
|
await this.modalOptions.onBeforeConfirm(submitData);
|
|
@@ -3928,8 +4056,10 @@ const _ImportDialog = class _ImportDialog {
|
|
|
3928
4056
|
}
|
|
3929
4057
|
}
|
|
3930
4058
|
} finally {
|
|
3931
|
-
|
|
3932
|
-
|
|
4059
|
+
if (confirmLoadingEnabled) {
|
|
4060
|
+
this.confirmLoading = false;
|
|
4061
|
+
this.updateModal();
|
|
4062
|
+
}
|
|
3933
4063
|
}
|
|
3934
4064
|
}
|
|
3935
4065
|
showMessage(message, type) {
|