ls-pro-common 3.1.58 → 3.1.60

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.
@@ -0,0 +1,385 @@
1
+ import _asyncToGenerator from "@babel/runtime/helpers/esm/asyncToGenerator";
2
+ import _regeneratorRuntime from "@babel/runtime/regenerator";
3
+ import { httpUpload } from './upload';
4
+ import { httpPost } from './ajax';
5
+ import { urlDownloadDomain, setUrlQuery } from '../utils';
6
+ /** 分片上传接口地址 */
7
+ var BASE_URL = '/petrel/petrel-file-center-api/lesoon/oss/file/chunk/upload';
8
+ /**
9
+ * 分片上传文件
10
+ *
11
+ * @param config 分片上传配置
12
+ * @returns 返回包含 promise、cancel 方法和 uploadId 的对象
13
+ */
14
+ export var httpUploadByChunk = function httpUploadByChunk(config) {
15
+ var file = config.file,
16
+ createTransactionUrl = config.createTransactionUrl,
17
+ uploadChunkUrl = config.uploadChunkUrl,
18
+ commitUrl = config.commitUrl,
19
+ cancelUrl = config.cancelUrl,
20
+ _config$chunkSize = config.chunkSize,
21
+ chunkSizeMB = _config$chunkSize === void 0 ? 2 : _config$chunkSize,
22
+ _config$needGateWay = config.needGateWay,
23
+ needGateWay = _config$needGateWay === void 0 ? true : _config$needGateWay,
24
+ _config$useDownloadDo = config.useDownloadDomain,
25
+ useDownloadDomain = _config$useDownloadDo === void 0 ? true : _config$useDownloadDo,
26
+ onProgress = config.onProgress,
27
+ _config$maxRetries = config.maxRetries,
28
+ maxRetries = _config$maxRetries === void 0 ? 3 : _config$maxRetries,
29
+ _config$code = config.code,
30
+ code = _config$code === void 0 ? 'RETAIL' : _config$code,
31
+ _config$catalogName = config.catalogName,
32
+ catalogName = _config$catalogName === void 0 ? 'mdm' : _config$catalogName,
33
+ _config$batchSize = config.batchSize,
34
+ batchSize = _config$batchSize === void 0 ? 1 : _config$batchSize;
35
+ var uploadId;
36
+ var isCancelled = false;
37
+ var cancelFunctions = [];
38
+ var chunkSize = chunkSizeMB * 1024 * 1024;
39
+ // 计算总分片数
40
+ var totalChunks = Math.ceil(file.size / chunkSize);
41
+ // 进度管理器:记录每个分片的上传进度(0-1)
42
+ var chunkProgressMap = new Map();
43
+ var lastReportedProgress = 0;
44
+ /** 更新并报告进度,确保进度只增不减 */
45
+ var updateProgress = function updateProgress() {
46
+ // 计算所有分片的累计进度
47
+ var totalProgress = 0;
48
+ chunkProgressMap.forEach(function (progress) {
49
+ totalProgress += progress;
50
+ });
51
+ // 计算总体进度百分比(0-100)
52
+ var currentProgress = Math.min(Math.round(totalProgress / totalChunks * 100), 100);
53
+ // 确保进度只增不减
54
+ var finalProgress = Math.max(currentProgress, lastReportedProgress);
55
+ // 只有当进度增加时才回调
56
+ if (finalProgress > lastReportedProgress) {
57
+ lastReportedProgress = finalProgress;
58
+ onProgress === null || onProgress === void 0 ? void 0 : onProgress(finalProgress);
59
+ }
60
+ };
61
+ /** 创建上传事务 */
62
+ var createTransaction = /*#__PURE__*/function () {
63
+ var _ref = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee() {
64
+ var _result$flag;
65
+ var params, api, finalUrl, result, _result$flag2;
66
+ return _regeneratorRuntime.wrap(function _callee$(_context) {
67
+ while (1) switch (_context.prev = _context.next) {
68
+ case 0:
69
+ params = {
70
+ chunkNumbers: totalChunks,
71
+ fileName: encodeURIComponent(file.name),
72
+ contentType: encodeURIComponent(file.type),
73
+ fileSize: file.size
74
+ };
75
+ api = setUrlQuery(createTransactionUrl || "".concat(BASE_URL, "/transaction/").concat(code, "?catalogName=").concat(catalogName), params);
76
+ finalUrl = useDownloadDomain ? urlDownloadDomain(api) : api;
77
+ _context.next = 5;
78
+ return httpPost(finalUrl, {}, true, needGateWay);
79
+ case 5:
80
+ result = _context.sent;
81
+ if (!(((_result$flag = result.flag) === null || _result$flag === void 0 ? void 0 : _result$flag.retCode) === '0' && result.data)) {
82
+ _context.next = 10;
83
+ break;
84
+ }
85
+ return _context.abrupt("return", result.data);
86
+ case 10:
87
+ throw new Error(((_result$flag2 = result.flag) === null || _result$flag2 === void 0 ? void 0 : _result$flag2.retMsg) || '创建上传事务失败');
88
+ case 11:
89
+ case "end":
90
+ return _context.stop();
91
+ }
92
+ }, _callee);
93
+ }));
94
+ return function createTransaction() {
95
+ return _ref.apply(this, arguments);
96
+ };
97
+ }();
98
+ /**
99
+ * 上传单个分片
100
+ *
101
+ * @param chunk Blob 分片
102
+ * @param chunkIndex 分片索引(从 1 开始)
103
+ * @param retryCount 当前重试次数
104
+ */
105
+ var uploadChunk = /*#__PURE__*/function () {
106
+ var _ref2 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee2(chunk, chunkIndex) {
107
+ var retryCount,
108
+ params,
109
+ api,
110
+ _result$flag3,
111
+ uploadResult,
112
+ result,
113
+ _result$flag4,
114
+ _args2 = arguments;
115
+ return _regeneratorRuntime.wrap(function _callee2$(_context2) {
116
+ while (1) switch (_context2.prev = _context2.next) {
117
+ case 0:
118
+ retryCount = _args2.length > 2 && _args2[2] !== undefined ? _args2[2] : 0;
119
+ if (!isCancelled) {
120
+ _context2.next = 3;
121
+ break;
122
+ }
123
+ throw new Error('上传已取消');
124
+ case 3:
125
+ if (uploadId) {
126
+ _context2.next = 5;
127
+ break;
128
+ }
129
+ throw new Error('上传事务 ID 不存在');
130
+ case 5:
131
+ params = {
132
+ uploadId: uploadId,
133
+ chunkSequence: chunkIndex,
134
+ size: chunk.size
135
+ };
136
+ api = setUrlQuery(uploadChunkUrl || "".concat(BASE_URL, "/").concat(code, "?catalogName=").concat(catalogName), params);
137
+ _context2.prev = 7;
138
+ // 初始化分片进度为 0
139
+ chunkProgressMap.set(chunkIndex, 0);
140
+ // 使用 httpUpload 上传分片
141
+ uploadResult = httpUpload(api, new File([chunk], file.name, {
142
+ type: file.type
143
+ }), {}, 'file', needGateWay, function (progress) {
144
+ // 更新当前分片的上传进度(0-1)
145
+ chunkProgressMap.set(chunkIndex, progress / 100);
146
+ // 更新总体进度
147
+ updateProgress();
148
+ }, useDownloadDomain); // 保存取消函数
149
+ cancelFunctions.push(uploadResult.cancel);
150
+ // 等待上传完成
151
+ _context2.next = 13;
152
+ return uploadResult.promise;
153
+ case 13:
154
+ result = _context2.sent;
155
+ if (!(((_result$flag3 = result.flag) === null || _result$flag3 === void 0 ? void 0 : _result$flag3.retCode) === '0')) {
156
+ _context2.next = 19;
157
+ break;
158
+ }
159
+ // 分片上传成功,标记为完成(进度为 1)
160
+ chunkProgressMap.set(chunkIndex, 1);
161
+ // 更新总体进度
162
+ updateProgress();
163
+ _context2.next = 21;
164
+ break;
165
+ case 19:
166
+ // 上传失败,重置进度
167
+ chunkProgressMap.set(chunkIndex, 0);
168
+ throw new Error(((_result$flag4 = result.flag) === null || _result$flag4 === void 0 ? void 0 : _result$flag4.retMsg) || '分片上传失败');
169
+ case 21:
170
+ _context2.next = 30;
171
+ break;
172
+ case 23:
173
+ _context2.prev = 23;
174
+ _context2.t0 = _context2["catch"](7);
175
+ if (!(retryCount < maxRetries && !isCancelled)) {
176
+ _context2.next = 28;
177
+ break;
178
+ }
179
+ // 重置进度后重试
180
+ chunkProgressMap.set(chunkIndex, 0);
181
+ return _context2.abrupt("return", uploadChunk(chunk, chunkIndex, retryCount + 1));
182
+ case 28:
183
+ // 重试失败,重置进度
184
+ chunkProgressMap.set(chunkIndex, 0);
185
+ throw _context2.t0;
186
+ case 30:
187
+ case "end":
188
+ return _context2.stop();
189
+ }
190
+ }, _callee2, null, [[7, 23]]);
191
+ }));
192
+ return function uploadChunk(_x, _x2) {
193
+ return _ref2.apply(this, arguments);
194
+ };
195
+ }();
196
+ /** 提交合并请求 */
197
+ var commitUpload = /*#__PURE__*/function () {
198
+ var _ref3 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee3() {
199
+ var _result$flag5;
200
+ var params, api, finalUrl, result, _result$flag6;
201
+ return _regeneratorRuntime.wrap(function _callee3$(_context3) {
202
+ while (1) switch (_context3.prev = _context3.next) {
203
+ case 0:
204
+ if (uploadId) {
205
+ _context3.next = 2;
206
+ break;
207
+ }
208
+ throw new Error('上传事务 ID 不存在');
209
+ case 2:
210
+ params = {
211
+ uploadId: uploadId
212
+ };
213
+ api = setUrlQuery(commitUrl || "".concat(BASE_URL, "/commit/normal/").concat(code), params);
214
+ finalUrl = useDownloadDomain ? urlDownloadDomain(api) : api;
215
+ _context3.next = 7;
216
+ return httpPost(finalUrl, {}, true, needGateWay);
217
+ case 7:
218
+ result = _context3.sent;
219
+ if (!(((_result$flag5 = result.flag) === null || _result$flag5 === void 0 ? void 0 : _result$flag5.retCode) === '0')) {
220
+ _context3.next = 12;
221
+ break;
222
+ }
223
+ return _context3.abrupt("return", result);
224
+ case 12:
225
+ throw new Error(((_result$flag6 = result.flag) === null || _result$flag6 === void 0 ? void 0 : _result$flag6.retMsg) || '合并文件失败');
226
+ case 13:
227
+ case "end":
228
+ return _context3.stop();
229
+ }
230
+ }, _callee3);
231
+ }));
232
+ return function commitUpload() {
233
+ return _ref3.apply(this, arguments);
234
+ };
235
+ }();
236
+ /** 取消上传 */
237
+ var cancel = /*#__PURE__*/function () {
238
+ var _ref4 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee4() {
239
+ var api, finalUrl;
240
+ return _regeneratorRuntime.wrap(function _callee4$(_context4) {
241
+ while (1) switch (_context4.prev = _context4.next) {
242
+ case 0:
243
+ if (!isCancelled) {
244
+ _context4.next = 2;
245
+ break;
246
+ }
247
+ return _context4.abrupt("return");
248
+ case 2:
249
+ isCancelled = true;
250
+ // 取消所有正在上传的分片
251
+ cancelFunctions.forEach(function (cancelFn) {
252
+ try {
253
+ cancelFn();
254
+ } catch (e) {
255
+ // 忽略取消错误
256
+ }
257
+ });
258
+ cancelFunctions.length = 0;
259
+ // 如果已有上传事务 ID,发送取消请求
260
+ if (!uploadId) {
261
+ _context4.next = 15;
262
+ break;
263
+ }
264
+ _context4.prev = 6;
265
+ // 处理 URL 参数,支持 ? 和 & 开头
266
+ api = setUrlQuery(cancelUrl || "".concat(BASE_URL, "/cancel/").concat(code), {
267
+ uploadId: uploadId
268
+ });
269
+ finalUrl = useDownloadDomain ? urlDownloadDomain(api) : api;
270
+ _context4.next = 11;
271
+ return httpPost(finalUrl, {}, true, needGateWay);
272
+ case 11:
273
+ _context4.next = 15;
274
+ break;
275
+ case 13:
276
+ _context4.prev = 13;
277
+ _context4.t0 = _context4["catch"](6);
278
+ case 15:
279
+ case "end":
280
+ return _context4.stop();
281
+ }
282
+ }, _callee4, null, [[6, 13]]);
283
+ }));
284
+ return function cancel() {
285
+ return _ref4.apply(this, arguments);
286
+ };
287
+ }();
288
+ /** 执行分片上传流程 */
289
+ var promise = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee5() {
290
+ var chunks, chunkIndex, start, end, chunk, i, batch, result;
291
+ return _regeneratorRuntime.wrap(function _callee5$(_context5) {
292
+ while (1) switch (_context5.prev = _context5.next) {
293
+ case 0:
294
+ _context5.prev = 0;
295
+ _context5.next = 3;
296
+ return createTransaction();
297
+ case 3:
298
+ uploadId = _context5.sent;
299
+ if (!isCancelled) {
300
+ _context5.next = 6;
301
+ break;
302
+ }
303
+ throw new Error('上传已取消');
304
+ case 6:
305
+ // 第二步:计算所有分片
306
+ chunks = [];
307
+ chunkIndex = 1;
308
+ for (start = 0; start < file.size; start += chunkSize) {
309
+ end = Math.min(start + chunkSize, file.size);
310
+ chunk = file.slice(start, end);
311
+ chunks.push({
312
+ blob: chunk,
313
+ index: chunkIndex
314
+ });
315
+ chunkIndex++;
316
+ }
317
+ // 初始化所有分片的进度为 0
318
+ chunks.forEach(function (chunkInfo) {
319
+ chunkProgressMap.set(chunkInfo.index, 0);
320
+ });
321
+ // 第三步:分批并发上传分片
322
+ i = 0;
323
+ case 11:
324
+ if (!(i < chunks.length)) {
325
+ _context5.next = 20;
326
+ break;
327
+ }
328
+ if (!isCancelled) {
329
+ _context5.next = 14;
330
+ break;
331
+ }
332
+ throw new Error('上传已取消');
333
+ case 14:
334
+ // 获取当前批次的分片
335
+ batch = chunks.slice(i, i + batchSize); // 并发上传当前批次的所有分片
336
+ _context5.next = 17;
337
+ return Promise.all(batch.map(function (chunkInfo) {
338
+ return uploadChunk(chunkInfo.blob, chunkInfo.index);
339
+ }));
340
+ case 17:
341
+ i += batchSize;
342
+ _context5.next = 11;
343
+ break;
344
+ case 20:
345
+ // 确保所有分片上传完成,进度为 100%
346
+ if (chunks.length > 0) {
347
+ chunks.forEach(function (chunkInfo) {
348
+ chunkProgressMap.set(chunkInfo.index, 1);
349
+ });
350
+ updateProgress();
351
+ }
352
+ if (!isCancelled) {
353
+ _context5.next = 23;
354
+ break;
355
+ }
356
+ throw new Error('上传已取消');
357
+ case 23:
358
+ _context5.next = 25;
359
+ return commitUpload();
360
+ case 25:
361
+ result = _context5.sent;
362
+ // 上传完成,确保进度为 100%
363
+ lastReportedProgress = 100;
364
+ onProgress === null || onProgress === void 0 ? void 0 : onProgress(100);
365
+ return _context5.abrupt("return", result);
366
+ case 31:
367
+ _context5.prev = 31;
368
+ _context5.t0 = _context5["catch"](0);
369
+ // 如果出错,确保进度回调被调用
370
+ if (!isCancelled) {
371
+ onProgress === null || onProgress === void 0 ? void 0 : onProgress(0);
372
+ }
373
+ throw _context5.t0;
374
+ case 35:
375
+ case "end":
376
+ return _context5.stop();
377
+ }
378
+ }, _callee5, null, [[0, 31]]);
379
+ }))();
380
+ return {
381
+ promise: promise,
382
+ cancel: cancel,
383
+ uploadId: uploadId
384
+ };
385
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ls-pro-common",
3
- "version": "3.1.58",
3
+ "version": "3.1.60",
4
4
  "description": "ls-pro-common",
5
5
  "license": "MIT",
6
6
  "sideEffects": [