@haluo/util 2.0.33 → 2.0.35
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/index.d.ts +3 -0
- package/dist/index.js +23 -19
- package/dist/modules/app-call/configs.d.ts +9 -0
- package/dist/modules/app-call/configs.js +44 -0
- package/dist/modules/app-call/core.d.ts +53 -0
- package/dist/modules/app-call/core.js +175 -0
- package/dist/modules/app-call/extensions.d.ts +187 -0
- package/dist/modules/app-call/extensions.js +1297 -0
- package/dist/modules/app-call/index.d.ts +16 -0
- package/dist/modules/app-call/index.js +84 -0
- package/dist/modules/app-call/offline.d.ts +12 -0
- package/dist/modules/app-call/offline.js +191 -0
- package/dist/modules/app-call/types.d.ts +67 -0
- package/dist/modules/app-call/types.js +4 -0
- package/dist/modules/cookie/index.js +22 -17
- package/dist/modules/date/index.js +54 -48
- package/dist/modules/dom/index.js +21 -15
- package/dist/modules/filter/index.js +14 -8
- package/dist/modules/format/index.js +9 -5
- package/dist/modules/match/index.js +8 -5
- package/dist/modules/monitor/lib/jsError.js +27 -38
- package/dist/modules/monitor/lib/timing.js +15 -17
- package/dist/modules/monitor/lib/xhr.js +26 -25
- package/dist/modules/monitor/utils/tracker.js +22 -10
- package/dist/modules/number/index.js +33 -30
- package/dist/modules/open-app/index.d.ts +3 -7
- package/dist/modules/open-app/index.js +55 -63
- package/dist/modules/sentry/index.js +16 -12
- package/dist/modules/tools/index.js +164 -154
- package/dist/modules/track/index.d.ts +122 -0
- package/dist/modules/track/index.js +421 -0
- package/dist/modules/track/types.d.ts +108 -0
- package/dist/modules/track/types.js +4 -0
- package/dist/modules/upload/aliOss.d.ts +52 -5
- package/dist/modules/upload/aliOss.js +589 -378
- package/dist/modules/upload/index.js +32 -29
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +27 -2
|
@@ -14,7 +14,10 @@
|
|
|
14
14
|
* darkWaterUploadImage: (params) => api.darkWaterUploadImage(params),
|
|
15
15
|
* multiTransferImage: (params) => api.multiTransferImage(params),
|
|
16
16
|
* generatePrePresignedUrl: (params) => api.generatePrePresignedUrl(params),
|
|
17
|
-
* messageWarning: (msg) => window.$message.warning(msg)
|
|
17
|
+
* messageWarning: (msg) => window.$message.warning(msg),
|
|
18
|
+
* // 可选:开启错误上报
|
|
19
|
+
* enableErrorReport: true,
|
|
20
|
+
* appName: 'emoto'
|
|
18
21
|
* })
|
|
19
22
|
*
|
|
20
23
|
* // 图片上传
|
|
@@ -41,10 +44,57 @@
|
|
|
41
44
|
* })
|
|
42
45
|
* ```
|
|
43
46
|
*/
|
|
44
|
-
|
|
47
|
+
var __assign = (this && this.__assign) || function () {
|
|
48
|
+
__assign = Object.assign || function(t) {
|
|
49
|
+
for (var s, i = 1, n = arguments.length; i < n; i++) {
|
|
50
|
+
s = arguments[i];
|
|
51
|
+
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
|
|
52
|
+
t[p] = s[p];
|
|
53
|
+
}
|
|
54
|
+
return t;
|
|
55
|
+
};
|
|
56
|
+
return __assign.apply(this, arguments);
|
|
57
|
+
};
|
|
58
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
59
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
60
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
61
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
62
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
63
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
64
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
65
|
+
});
|
|
66
|
+
};
|
|
67
|
+
var __generator = (this && this.__generator) || function (thisArg, body) {
|
|
68
|
+
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
|
|
69
|
+
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
|
|
70
|
+
function verb(n) { return function (v) { return step([n, v]); }; }
|
|
71
|
+
function step(op) {
|
|
72
|
+
if (f) throw new TypeError("Generator is already executing.");
|
|
73
|
+
while (g && (g = 0, op[0] && (_ = 0)), _) try {
|
|
74
|
+
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
|
|
75
|
+
if (y = 0, t) op = [op[0] & 2, t.value];
|
|
76
|
+
switch (op[0]) {
|
|
77
|
+
case 0: case 1: t = op; break;
|
|
78
|
+
case 4: _.label++; return { value: op[1], done: false };
|
|
79
|
+
case 5: _.label++; y = op[1]; op = [0]; continue;
|
|
80
|
+
case 7: op = _.ops.pop(); _.trys.pop(); continue;
|
|
81
|
+
default:
|
|
82
|
+
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
|
|
83
|
+
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
|
|
84
|
+
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
|
|
85
|
+
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
|
|
86
|
+
if (t[2]) _.ops.pop();
|
|
87
|
+
_.trys.pop(); continue;
|
|
88
|
+
}
|
|
89
|
+
op = body.call(thisArg, _);
|
|
90
|
+
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
|
|
91
|
+
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
|
|
92
|
+
}
|
|
93
|
+
};
|
|
94
|
+
import { createTracker } from '../track';
|
|
45
95
|
// ==================== 常量定义 ====================
|
|
46
96
|
/** 支持的图片格式 */
|
|
47
|
-
|
|
97
|
+
var SUPPORTED_IMAGE_TYPES = [
|
|
48
98
|
'image/jpeg',
|
|
49
99
|
'image/png',
|
|
50
100
|
'image/gif',
|
|
@@ -54,7 +104,7 @@ const SUPPORTED_IMAGE_TYPES = [
|
|
|
54
104
|
'image/tiff',
|
|
55
105
|
];
|
|
56
106
|
/** 支持的图片格式 ext */
|
|
57
|
-
|
|
107
|
+
var SUPPORTED_IMAGE_EXTS = [
|
|
58
108
|
'jpg',
|
|
59
109
|
'jpeg',
|
|
60
110
|
'png',
|
|
@@ -65,15 +115,15 @@ const SUPPORTED_IMAGE_EXTS = [
|
|
|
65
115
|
'tiff',
|
|
66
116
|
];
|
|
67
117
|
/** 小图片阈值(KB) */
|
|
68
|
-
|
|
118
|
+
var SMALL_IMAGE_THRESHOLD = 100;
|
|
69
119
|
/** 长图宽高比阈值 */
|
|
70
|
-
|
|
120
|
+
var LONG_IMAGE_RATIO = 2;
|
|
71
121
|
/** 默认文件大小限制(MB) */
|
|
72
|
-
|
|
122
|
+
var DEFAULT_FILE_SIZE_LIMIT = 10;
|
|
73
123
|
/** 默认压缩质量 */
|
|
74
|
-
|
|
124
|
+
var DEFAULT_QUALITY = 0.7;
|
|
75
125
|
/** 预签名URL过期时间(毫秒) */
|
|
76
|
-
|
|
126
|
+
var PRESIGNED_URL_EXPIRE_TIME = 60000;
|
|
77
127
|
// ==================== 枚举定义 ====================
|
|
78
128
|
/**
|
|
79
129
|
* 业务类型枚举
|
|
@@ -145,7 +195,7 @@ export var BusinessType;
|
|
|
145
195
|
/**
|
|
146
196
|
* bucket 图片类型后缀枚举
|
|
147
197
|
*/
|
|
148
|
-
export
|
|
198
|
+
export var SuffixEnum = {
|
|
149
199
|
nowater: '!nowater',
|
|
150
200
|
official: '!official',
|
|
151
201
|
panoram: '!panoram',
|
|
@@ -184,33 +234,414 @@ function getFileSizeInMB(size) {
|
|
|
184
234
|
* 阿里云OSS上传类
|
|
185
235
|
* 整合所有项目的aliOss业务逻辑,通过依赖注入实现业务API解耦
|
|
186
236
|
*/
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
237
|
+
var AliOssClass = /** @class */ (function () {
|
|
238
|
+
function AliOssClass(apiConfig) {
|
|
239
|
+
var _this = this;
|
|
240
|
+
this.tracker = null;
|
|
241
|
+
/**
|
|
242
|
+
* 图片上传主方法
|
|
243
|
+
* 整合了所有项目的图片上传逻辑
|
|
244
|
+
* @param option 上传选项
|
|
245
|
+
* @returns Promise - 成功时返回图片信息对象,失败时reject错误信息字符串
|
|
246
|
+
* @returns 成功返回结构: {
|
|
247
|
+
* url: string - 上传后的图片URL,
|
|
248
|
+
* imgUrl: string - 上传后的图片URL(可能包含尺寸信息),
|
|
249
|
+
* imgOrgUrl: string - 原始图片URL(包含尺寸信息),
|
|
250
|
+
* name: string - 文件名,
|
|
251
|
+
* fileName: string - 文件名
|
|
252
|
+
* }
|
|
253
|
+
* @returns 失败返回: 错误信息字符串,如"文件类型不支持"、"上传失败"等
|
|
254
|
+
*/
|
|
255
|
+
this.ossUploadImage = function (option) { return __awaiter(_this, void 0, void 0, function () {
|
|
256
|
+
var file, callbacks;
|
|
257
|
+
var _this = this;
|
|
258
|
+
var _a, _b;
|
|
259
|
+
return __generator(this, function (_c) {
|
|
260
|
+
if (!(option.file instanceof File)) {
|
|
261
|
+
return [2 /*return*/, Promise.reject('file is not instanceof File')];
|
|
262
|
+
}
|
|
263
|
+
if (!option.businessType) {
|
|
264
|
+
return [2 /*return*/, Promise.reject('businessType不能为空')];
|
|
265
|
+
}
|
|
266
|
+
file = option.file;
|
|
267
|
+
callbacks = {
|
|
268
|
+
onError: option.onError || (function () { }),
|
|
269
|
+
onSuccess: option.onSuccess || (function () { }),
|
|
270
|
+
onProgress: option.onProgress || (function () { }),
|
|
271
|
+
};
|
|
272
|
+
option.onError = callbacks.onError;
|
|
273
|
+
option.onSuccess = callbacks.onSuccess;
|
|
274
|
+
option.onProgress = callbacks.onProgress;
|
|
275
|
+
// 文件类型验证
|
|
276
|
+
if (!isSupportedImageType(file.type)) {
|
|
277
|
+
callbacks.onError('');
|
|
278
|
+
(_b = (_a = this.apiConfig).messageWarning) === null || _b === void 0 ? void 0 : _b.call(_a, '上传失败,请上传后缀为png、gif、jpg的文件');
|
|
279
|
+
return [2 /*return*/, Promise.reject('文件类型不支持')];
|
|
280
|
+
}
|
|
281
|
+
return [2 /*return*/, new Promise(function (resolve, reject) { return __awaiter(_this, void 0, void 0, function () {
|
|
282
|
+
var isSmallImage, quality, businessType, res, res, rst, isLong, postFile, imgSize, maxSizeMB, errorMsg, result, res, error_1, errorMsg;
|
|
283
|
+
return __generator(this, function (_a) {
|
|
284
|
+
switch (_a.label) {
|
|
285
|
+
case 0:
|
|
286
|
+
_a.trys.push([0, 12, , 13]);
|
|
287
|
+
isSmallImage = getFileSizeInKB(file.size) <= SMALL_IMAGE_THRESHOLD;
|
|
288
|
+
quality = isSmallImage ? 1 : option.quality || DEFAULT_QUALITY;
|
|
289
|
+
businessType = option.businessType;
|
|
290
|
+
if (!(businessType === BusinessType.CREDIT)) return [3 /*break*/, 2];
|
|
291
|
+
return [4 /*yield*/, this.upload({
|
|
292
|
+
file: file,
|
|
293
|
+
businessType: businessType,
|
|
294
|
+
resolve: resolve,
|
|
295
|
+
reject: reject,
|
|
296
|
+
callbacks: callbacks,
|
|
297
|
+
})];
|
|
298
|
+
case 1: return [2 /*return*/, _a.sent()];
|
|
299
|
+
case 2:
|
|
300
|
+
if (!(option.batchTransfer && this.apiConfig.multiTransferImage)) return [3 /*break*/, 4];
|
|
301
|
+
return [4 /*yield*/, this.apiConfig.multiTransferImage({ file: file })];
|
|
302
|
+
case 3:
|
|
303
|
+
res = _a.sent();
|
|
304
|
+
if (res.data.code === 0) {
|
|
305
|
+
// 盲水印兼容报错
|
|
306
|
+
if (res.data.data) {
|
|
307
|
+
this.loadImage({
|
|
308
|
+
url: res.data.data,
|
|
309
|
+
val: res.data,
|
|
310
|
+
option: option,
|
|
311
|
+
file: file,
|
|
312
|
+
resolve: resolve,
|
|
313
|
+
reject: reject,
|
|
314
|
+
});
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
else {
|
|
318
|
+
callbacks.onError('上传失败');
|
|
319
|
+
reject('上传失败');
|
|
320
|
+
this.reportError('批量转换水印上传失败', { type: 'batchTransfer', businessType: businessType });
|
|
321
|
+
}
|
|
322
|
+
return [2 /*return*/];
|
|
323
|
+
case 4:
|
|
324
|
+
if (!(option.imageType === 'carport' &&
|
|
325
|
+
this.apiConfig.darkWaterUploadImage)) return [3 /*break*/, 6];
|
|
326
|
+
return [4 /*yield*/, this.apiConfig.darkWaterUploadImage({ file: file })];
|
|
327
|
+
case 5:
|
|
328
|
+
res = _a.sent();
|
|
329
|
+
if (res.data.code === 0) {
|
|
330
|
+
this.loadImage({
|
|
331
|
+
url: res.data.data,
|
|
332
|
+
val: res.data,
|
|
333
|
+
option: option,
|
|
334
|
+
file: file,
|
|
335
|
+
resolve: resolve,
|
|
336
|
+
reject: reject,
|
|
337
|
+
});
|
|
338
|
+
}
|
|
339
|
+
else {
|
|
340
|
+
callbacks.onError('上传失败');
|
|
341
|
+
reject('上传失败');
|
|
342
|
+
this.reportError('暗水印上传失败', { type: 'darkWater', businessType: businessType });
|
|
343
|
+
}
|
|
344
|
+
return [2 /*return*/];
|
|
345
|
+
case 6: return [4 /*yield*/, require('lrz')(file, { quality: quality })
|
|
346
|
+
// 注释:长图压缩有问题,长宽比>2:1的图片不压缩
|
|
347
|
+
];
|
|
348
|
+
case 7:
|
|
349
|
+
rst = _a.sent();
|
|
350
|
+
return [4 /*yield*/, this.isLongImage(file)];
|
|
351
|
+
case 8:
|
|
352
|
+
isLong = (_a.sent()) || false;
|
|
353
|
+
postFile = void 0;
|
|
354
|
+
if (option.notCompress || file.type === 'image/gif' || isLong) {
|
|
355
|
+
// 注释:GIF、notCompress选项或长图不压缩
|
|
356
|
+
postFile = file;
|
|
357
|
+
}
|
|
358
|
+
else {
|
|
359
|
+
postFile = rst.file;
|
|
360
|
+
}
|
|
361
|
+
imgSize = postFile.size;
|
|
362
|
+
maxSizeMB = DEFAULT_FILE_SIZE_LIMIT;
|
|
363
|
+
if (getFileSizeInMB(imgSize) > maxSizeMB) {
|
|
364
|
+
errorMsg = "\u56FE\u7247\u4E0D\u80FD\u8D85\u8FC7".concat(maxSizeMB, "M");
|
|
365
|
+
callbacks.onError(errorMsg);
|
|
366
|
+
reject(errorMsg);
|
|
367
|
+
return [2 /*return*/];
|
|
368
|
+
}
|
|
369
|
+
// 设置文件名(确保压缩后的文件有名称)
|
|
370
|
+
if (!postFile.name) {
|
|
371
|
+
Object.defineProperty(postFile, 'name', {
|
|
372
|
+
value: file.name,
|
|
373
|
+
writable: false,
|
|
374
|
+
});
|
|
375
|
+
}
|
|
376
|
+
return [4 /*yield*/, this.upload({
|
|
377
|
+
file: file,
|
|
378
|
+
businessType: businessType,
|
|
379
|
+
resolve: resolve,
|
|
380
|
+
reject: reject,
|
|
381
|
+
callbacks: callbacks,
|
|
382
|
+
})
|
|
383
|
+
// 注释:idCard场景 - 生成预签名URL
|
|
384
|
+
];
|
|
385
|
+
case 9:
|
|
386
|
+
result = _a.sent();
|
|
387
|
+
if (!((option.idCard || false) &&
|
|
388
|
+
this.apiConfig.generatePrePresignedUrl)) return [3 /*break*/, 11];
|
|
389
|
+
return [4 /*yield*/, this.apiConfig.generatePrePresignedUrl({
|
|
390
|
+
objectId: result.name,
|
|
391
|
+
expireMils: PRESIGNED_URL_EXPIRE_TIME,
|
|
392
|
+
})];
|
|
393
|
+
case 10:
|
|
394
|
+
res = _a.sent();
|
|
395
|
+
if (res.data.code === 0) {
|
|
396
|
+
this.loadImage({
|
|
397
|
+
url: res.data.data,
|
|
398
|
+
val: result,
|
|
399
|
+
file: postFile,
|
|
400
|
+
option: option,
|
|
401
|
+
resolve: resolve,
|
|
402
|
+
reject: reject,
|
|
403
|
+
});
|
|
404
|
+
}
|
|
405
|
+
else {
|
|
406
|
+
callbacks.onError('生成预签名URL失败');
|
|
407
|
+
reject('生成预签名URL失败');
|
|
408
|
+
this.reportError('生成预签名URL失败', { type: 'preSignedUrl', businessType: businessType });
|
|
409
|
+
}
|
|
410
|
+
return [2 /*return*/];
|
|
411
|
+
case 11: return [3 /*break*/, 13];
|
|
412
|
+
case 12:
|
|
413
|
+
error_1 = _a.sent();
|
|
414
|
+
errorMsg = error_1.message || error_1.msg || '上传异常';
|
|
415
|
+
callbacks.onError(errorMsg);
|
|
416
|
+
reject(errorMsg);
|
|
417
|
+
this.reportError(errorMsg, { type: 'ossUploadImage', businessType: option.businessType });
|
|
418
|
+
return [3 /*break*/, 13];
|
|
419
|
+
case 13: return [2 /*return*/];
|
|
420
|
+
}
|
|
421
|
+
});
|
|
422
|
+
}); })];
|
|
423
|
+
});
|
|
424
|
+
}); };
|
|
425
|
+
/**
|
|
426
|
+
* 文件上传方法
|
|
427
|
+
* 支持视频、文档、APK等文件类型
|
|
428
|
+
* @param option 上传选项
|
|
429
|
+
* @returns Promise - 成功时返回文件信息对象,失败时reject错误信息字符串
|
|
430
|
+
* @returns 成功返回结构: {
|
|
431
|
+
* url: string - 上传后的文件URL,
|
|
432
|
+
* imgUrl: string - 上传后的文件URL,
|
|
433
|
+
* imgOrgUrl: string - 上传后的文件URL,
|
|
434
|
+
* name: string - 文件名,
|
|
435
|
+
* fileName: string - 文件名
|
|
436
|
+
* }
|
|
437
|
+
* @returns 失败返回: 错误信息字符串,如"文件类型不支持"、"上传失败"等
|
|
438
|
+
*/
|
|
439
|
+
this.ossUploadFile = function (option) { return __awaiter(_this, void 0, void 0, function () {
|
|
440
|
+
var file, callbacks;
|
|
441
|
+
var _this = this;
|
|
442
|
+
return __generator(this, function (_a) {
|
|
443
|
+
if (!(option.file instanceof File)) {
|
|
444
|
+
return [2 /*return*/, Promise.reject('file is not instanceof File')];
|
|
445
|
+
}
|
|
446
|
+
if (!option.businessType) {
|
|
447
|
+
return [2 /*return*/, Promise.reject('businessType不能为空')];
|
|
448
|
+
}
|
|
449
|
+
file = option.file;
|
|
450
|
+
callbacks = {
|
|
451
|
+
onError: option.onError || (function () { }),
|
|
452
|
+
onSuccess: option.onSuccess || (function () { }),
|
|
453
|
+
onProgress: option.onProgress || (function () { }),
|
|
454
|
+
};
|
|
455
|
+
option.onError = callbacks.onError;
|
|
456
|
+
option.onSuccess = callbacks.onSuccess;
|
|
457
|
+
option.onProgress = callbacks.onProgress;
|
|
458
|
+
return [2 /*return*/, new Promise(function (resolve, reject) { return __awaiter(_this, void 0, void 0, function () {
|
|
459
|
+
var businessType, error_2, errorMsg;
|
|
460
|
+
return __generator(this, function (_a) {
|
|
461
|
+
switch (_a.label) {
|
|
462
|
+
case 0:
|
|
463
|
+
_a.trys.push([0, 2, , 3]);
|
|
464
|
+
businessType = option.businessType;
|
|
465
|
+
return [4 /*yield*/, this.upload({
|
|
466
|
+
file: file,
|
|
467
|
+
businessType: businessType,
|
|
468
|
+
resolve: resolve,
|
|
469
|
+
reject: reject,
|
|
470
|
+
callbacks: callbacks,
|
|
471
|
+
})];
|
|
472
|
+
case 1:
|
|
473
|
+
_a.sent();
|
|
474
|
+
return [3 /*break*/, 3];
|
|
475
|
+
case 2:
|
|
476
|
+
error_2 = _a.sent();
|
|
477
|
+
errorMsg = error_2.message || error_2.msg || '上传异常';
|
|
478
|
+
callbacks.onError(errorMsg);
|
|
479
|
+
reject(errorMsg);
|
|
480
|
+
this.reportError(errorMsg, { type: 'ossUploadFile', businessType: option.businessType });
|
|
481
|
+
return [3 /*break*/, 3];
|
|
482
|
+
case 3: return [2 /*return*/];
|
|
483
|
+
}
|
|
484
|
+
});
|
|
485
|
+
}); })];
|
|
486
|
+
});
|
|
487
|
+
}); };
|
|
488
|
+
/**
|
|
489
|
+
* 纯图片上传 pureOssUploadImage
|
|
490
|
+
* 注释:图片上传,不压缩
|
|
491
|
+
* @param option 上传选项
|
|
492
|
+
* @returns Promise - 成功时返回图片信息对象,失败时reject错误信息字符串
|
|
493
|
+
* @returns 成功返回结构: {
|
|
494
|
+
* url: string - 上传后的图片URL,
|
|
495
|
+
* imgUrl: string - 上传后的图片URL,
|
|
496
|
+
* imgOrgUrl: string - 上传后的图片URL,
|
|
497
|
+
* name: string - 文件名,
|
|
498
|
+
* fileName: string - 文件名
|
|
499
|
+
* }
|
|
500
|
+
* @returns 失败返回: 错误信息字符串,如"文件类型不支持"、"上传失败"等
|
|
501
|
+
*/
|
|
502
|
+
this.pureOssUploadImage = function (option) { return __awaiter(_this, void 0, void 0, function () {
|
|
503
|
+
return __generator(this, function (_a) {
|
|
504
|
+
switch (_a.label) {
|
|
505
|
+
case 0: return [4 /*yield*/, this.shopDetailUpdate(option)];
|
|
506
|
+
case 1: return [2 /*return*/, _a.sent()];
|
|
507
|
+
}
|
|
508
|
+
});
|
|
509
|
+
}); };
|
|
510
|
+
/**
|
|
511
|
+
* 商品详情图片上传(不建议直接使用,请使用 pureOssUploadImage)
|
|
512
|
+
* 注释:图片上传,不压缩
|
|
513
|
+
* @param option 上传选项
|
|
514
|
+
* @returns Promise - 成功时返回图片信息对象,失败时reject错误信息字符串
|
|
515
|
+
* @returns 成功返回结构: {
|
|
516
|
+
* url: string - 上传后的图片URL,
|
|
517
|
+
* imgUrl: string - 上传后的图片URL,
|
|
518
|
+
* imgOrgUrl: string - 上传后的图片URL,
|
|
519
|
+
* name: string - 文件名,
|
|
520
|
+
* fileName: string - 文件名
|
|
521
|
+
* }
|
|
522
|
+
* @returns 失败返回: 错误信息字符串,如"文件类型不支持"、"上传失败"等
|
|
523
|
+
*/
|
|
524
|
+
this.shopDetailUpdate = function (option) { return __awaiter(_this, void 0, void 0, function () {
|
|
525
|
+
var file, callbacks;
|
|
526
|
+
var _this = this;
|
|
527
|
+
var _a, _b;
|
|
528
|
+
return __generator(this, function (_c) {
|
|
529
|
+
if (!(option.file instanceof File)) {
|
|
530
|
+
return [2 /*return*/, Promise.reject('file is not instanceof File')];
|
|
531
|
+
}
|
|
532
|
+
if (!option.businessType) {
|
|
533
|
+
return [2 /*return*/, Promise.reject('businessType不能为空')];
|
|
534
|
+
}
|
|
535
|
+
file = option.file;
|
|
536
|
+
callbacks = {
|
|
537
|
+
onError: option.onError || (function () { }),
|
|
538
|
+
onSuccess: option.onSuccess || (function () { }),
|
|
539
|
+
onProgress: option.onProgress || (function () { }),
|
|
540
|
+
};
|
|
541
|
+
option.onError = callbacks.onError;
|
|
542
|
+
option.onSuccess = callbacks.onSuccess;
|
|
543
|
+
option.onProgress = callbacks.onProgress;
|
|
544
|
+
// 文件类型验证
|
|
545
|
+
if (!isSupportedImageType(file.type)) {
|
|
546
|
+
callbacks.onError('');
|
|
547
|
+
(_b = (_a = this.apiConfig).messageWarning) === null || _b === void 0 ? void 0 : _b.call(_a, '上传失败,请上传后缀为png、gif、jpg的文件');
|
|
548
|
+
return [2 /*return*/, Promise.reject('文件类型不支持')];
|
|
549
|
+
}
|
|
550
|
+
return [2 /*return*/, new Promise(function (resolve, reject) { return __awaiter(_this, void 0, void 0, function () {
|
|
551
|
+
var businessType, errorMsg, error_3, errorMsg;
|
|
552
|
+
return __generator(this, function (_a) {
|
|
553
|
+
switch (_a.label) {
|
|
554
|
+
case 0:
|
|
555
|
+
_a.trys.push([0, 2, , 3]);
|
|
556
|
+
businessType = option.businessType;
|
|
557
|
+
// 文件大小验证
|
|
558
|
+
if (getFileSizeInMB(file.size) > DEFAULT_FILE_SIZE_LIMIT) {
|
|
559
|
+
errorMsg = "\u56FE\u7247\u4E0D\u80FD\u8D85\u8FC7".concat(DEFAULT_FILE_SIZE_LIMIT, "M");
|
|
560
|
+
callbacks.onError(errorMsg);
|
|
561
|
+
reject(errorMsg);
|
|
562
|
+
return [2 /*return*/];
|
|
563
|
+
}
|
|
564
|
+
return [4 /*yield*/, this.upload({
|
|
565
|
+
file: file,
|
|
566
|
+
businessType: businessType,
|
|
567
|
+
resolve: resolve,
|
|
568
|
+
reject: reject,
|
|
569
|
+
callbacks: callbacks,
|
|
570
|
+
})];
|
|
571
|
+
case 1:
|
|
572
|
+
_a.sent();
|
|
573
|
+
return [3 /*break*/, 3];
|
|
574
|
+
case 2:
|
|
575
|
+
error_3 = _a.sent();
|
|
576
|
+
errorMsg = error_3.message || error_3.msg || '上传异常';
|
|
577
|
+
callbacks.onError(errorMsg);
|
|
578
|
+
reject(errorMsg);
|
|
579
|
+
this.reportError(errorMsg, { type: 'pureOssUploadImage', businessType: option.businessType });
|
|
580
|
+
return [3 /*break*/, 3];
|
|
581
|
+
case 3: return [2 /*return*/];
|
|
582
|
+
}
|
|
583
|
+
});
|
|
584
|
+
}); })];
|
|
585
|
+
});
|
|
586
|
+
}); };
|
|
587
|
+
/**
|
|
588
|
+
* 业务类型枚举
|
|
589
|
+
*/
|
|
590
|
+
this.businessType = BusinessType;
|
|
191
591
|
this.apiConfig = apiConfig;
|
|
592
|
+
// 只有启用错误上报时才创建 tracker 实例
|
|
593
|
+
if (apiConfig.enableErrorReport) {
|
|
594
|
+
this.tracker = createTracker({
|
|
595
|
+
appName: apiConfig.appName
|
|
596
|
+
});
|
|
597
|
+
}
|
|
192
598
|
}
|
|
193
|
-
|
|
599
|
+
AliOssClass.getInstance = function (apiConfig) {
|
|
194
600
|
if (!AliOssClass.instance) {
|
|
195
601
|
AliOssClass.instance = new AliOssClass(apiConfig);
|
|
196
602
|
}
|
|
197
603
|
return AliOssClass.instance;
|
|
198
|
-
}
|
|
604
|
+
};
|
|
605
|
+
/**
|
|
606
|
+
* 上报上传错误
|
|
607
|
+
* @param err 错误信息
|
|
608
|
+
* @param extra 额外信息
|
|
609
|
+
*/
|
|
610
|
+
AliOssClass.prototype.reportError = function (err, extra) {
|
|
611
|
+
// 只有启用错误上报且 tracker 存在时才上报
|
|
612
|
+
if (!this.apiConfig.enableErrorReport || !this.tracker) {
|
|
613
|
+
return;
|
|
614
|
+
}
|
|
615
|
+
try {
|
|
616
|
+
// 附加用户信息
|
|
617
|
+
var user = JSON.parse(window.localStorage.user || '{}');
|
|
618
|
+
var uid = user.uid || '';
|
|
619
|
+
if (uid) {
|
|
620
|
+
extra = extra || {};
|
|
621
|
+
extra.uid = uid;
|
|
622
|
+
}
|
|
623
|
+
}
|
|
624
|
+
catch (e) {
|
|
625
|
+
console.error(e);
|
|
626
|
+
}
|
|
627
|
+
this.tracker.trackError(__assign({ err: err, apptype: '10003' }, extra));
|
|
628
|
+
};
|
|
199
629
|
/**
|
|
200
630
|
* 判断文件是否为图片(支持常见图片格式)
|
|
201
631
|
* @param {File} file - 上传的File对象
|
|
202
632
|
* @returns {boolean} 是否为图片
|
|
203
633
|
*/
|
|
204
|
-
isImageFile(file) {
|
|
634
|
+
AliOssClass.prototype.isImageFile = function (file) {
|
|
635
|
+
var _a;
|
|
205
636
|
if (!file || !(file instanceof File))
|
|
206
637
|
return false;
|
|
207
638
|
// 1. 校验文件MIME类型(优先,更可靠)
|
|
208
639
|
if (SUPPORTED_IMAGE_TYPES.includes(file.type))
|
|
209
640
|
return true;
|
|
210
641
|
// 2. 校验文件后缀名(兜底,防止MIME类型缺失)
|
|
211
|
-
|
|
642
|
+
var fileExt = ((_a = file.name.split('.').pop()) === null || _a === void 0 ? void 0 : _a.toLowerCase()) || '';
|
|
212
643
|
return SUPPORTED_IMAGE_EXTS.includes(fileExt);
|
|
213
|
-
}
|
|
644
|
+
};
|
|
214
645
|
/**
|
|
215
646
|
* 通过V4签名上传
|
|
216
647
|
* @param file 上传的文件
|
|
@@ -220,402 +651,182 @@ export class AliOssClass {
|
|
|
220
651
|
* @param reject Promse
|
|
221
652
|
* @returns 上传图片结果
|
|
222
653
|
*/
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
654
|
+
AliOssClass.prototype.upload = function (params) {
|
|
655
|
+
var _a, _b;
|
|
656
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
657
|
+
var file, businessType, resolve, reject, callbacks, size, result, docType, image, signResponse, errorMessage, signData, formData, uploadResponse, responseText, errorMessage, err_1, errMsg;
|
|
658
|
+
return __generator(this, function (_c) {
|
|
659
|
+
switch (_c.label) {
|
|
660
|
+
case 0:
|
|
661
|
+
file = params.file, businessType = params.businessType, resolve = params.resolve, reject = params.reject, callbacks = params.callbacks;
|
|
662
|
+
size = params.size;
|
|
663
|
+
result = {};
|
|
664
|
+
_c.label = 1;
|
|
665
|
+
case 1:
|
|
666
|
+
_c.trys.push([1, 8, , 9]);
|
|
667
|
+
docType = ((_a = file.name) === null || _a === void 0 ? void 0 : _a.split('.').reverse()[0]) || file.type // 兼容 *.*.* 这种后缀(必传)
|
|
668
|
+
;
|
|
669
|
+
if (!(!size && this.isImageFile(file))) return [3 /*break*/, 3];
|
|
670
|
+
return [4 /*yield*/, this.getImageInfo(file)];
|
|
671
|
+
case 2:
|
|
672
|
+
image = _c.sent();
|
|
673
|
+
size = "_".concat(image === null || image === void 0 ? void 0 : image.width, "_").concat(image === null || image === void 0 ? void 0 : image.height);
|
|
674
|
+
docType = ((_b = file.type) === null || _b === void 0 ? void 0 : _b.split('/').reverse()[0]) || file.type; // 如果是图片文件格式如png(必传)
|
|
675
|
+
_c.label = 3;
|
|
676
|
+
case 3: return [4 /*yield*/, this.apiConfig.getSts({
|
|
677
|
+
businessType: businessType,
|
|
678
|
+
docType: docType,
|
|
679
|
+
size: size, // _1024_567(可选)
|
|
680
|
+
})];
|
|
681
|
+
case 4:
|
|
682
|
+
signResponse = _c.sent();
|
|
683
|
+
if (signResponse.data.code !== 0) {
|
|
684
|
+
errorMessage = "\u83B7\u53D6\u7B7E\u540D\u5931\u8D25\uFF1A".concat(signResponse.data.message || signResponse.data.msg);
|
|
685
|
+
callbacks === null || callbacks === void 0 ? void 0 : callbacks.onError(errorMessage);
|
|
686
|
+
reject && reject(errorMessage);
|
|
687
|
+
console.error(errorMessage);
|
|
688
|
+
this.reportError(errorMessage, { type: 'getSts', businessType: businessType, code: signResponse.data.code });
|
|
689
|
+
return [2 /*return*/, result];
|
|
690
|
+
}
|
|
691
|
+
return [4 /*yield*/, signResponse.data.data
|
|
692
|
+
// console.log('后端返回的签名字段:', signData)
|
|
693
|
+
// 步骤 2:构造 FormData(字段名必须和后端返回一致
|
|
694
|
+
];
|
|
695
|
+
case 5:
|
|
696
|
+
signData = _c.sent();
|
|
697
|
+
formData = new FormData();
|
|
698
|
+
// formData.append('autherid', signData['autherid'])
|
|
699
|
+
// formData.append('uid', signData['uid'])
|
|
700
|
+
formData.append('key', signData['key']);
|
|
701
|
+
formData.append('policy', signData['policy']);
|
|
702
|
+
formData.append('success_action_status', '200');
|
|
703
|
+
formData.append('x-oss-credential', signData['credential']);
|
|
704
|
+
formData.append('x-oss-date', signData['date']);
|
|
705
|
+
if (signData['securityToken']) {
|
|
706
|
+
formData.append('x-oss-security-token', signData['securityToken']);
|
|
707
|
+
}
|
|
708
|
+
formData.append('x-oss-signature', signData['signature']);
|
|
709
|
+
formData.append('x-oss-signature-version', signData['signatureVersion']);
|
|
710
|
+
formData.append('file', file);
|
|
711
|
+
return [4 /*yield*/, fetch(signData.uploadUrl, {
|
|
712
|
+
method: 'POST',
|
|
713
|
+
body: formData,
|
|
714
|
+
// 重点:不要手动设置 Content-Type!浏览器会自动处理为 multipart/form-data 并带边界符
|
|
715
|
+
headers: { Accept: '*/*' },
|
|
716
|
+
})
|
|
717
|
+
// 步骤 4:处理上传结果
|
|
718
|
+
];
|
|
719
|
+
case 6:
|
|
720
|
+
uploadResponse = _c.sent();
|
|
721
|
+
return [4 /*yield*/, uploadResponse.text()];
|
|
722
|
+
case 7:
|
|
723
|
+
responseText = _c.sent();
|
|
724
|
+
if (uploadResponse.ok) {
|
|
725
|
+
result = {
|
|
726
|
+
url: signData['fileUrl'],
|
|
727
|
+
imgUrl: signData['fileUrl'],
|
|
728
|
+
imgOrgUrl: signData['fileUrl'],
|
|
729
|
+
name: file.name,
|
|
730
|
+
fileName: file.name,
|
|
731
|
+
};
|
|
732
|
+
callbacks === null || callbacks === void 0 ? void 0 : callbacks.onSuccess(result);
|
|
733
|
+
resolve && resolve(result);
|
|
734
|
+
}
|
|
735
|
+
else {
|
|
736
|
+
errorMessage = "\u4E0A\u4F20\u5931\u8D25\uFF08OSS \u8FD4\u56DE ".concat(uploadResponse.status, "\uFF09\uFF1A").concat(responseText);
|
|
737
|
+
callbacks === null || callbacks === void 0 ? void 0 : callbacks.onError(errorMessage);
|
|
738
|
+
reject && reject(errorMessage);
|
|
739
|
+
console.error(errorMessage);
|
|
740
|
+
this.reportError(errorMessage, { type: 'ossUpload', businessType: businessType, status: uploadResponse.status });
|
|
741
|
+
}
|
|
742
|
+
return [3 /*break*/, 9];
|
|
743
|
+
case 8:
|
|
744
|
+
err_1 = _c.sent();
|
|
745
|
+
errMsg = err_1.message || err_1.msg || '上传异常';
|
|
746
|
+
callbacks === null || callbacks === void 0 ? void 0 : callbacks.onError(errMsg);
|
|
747
|
+
reject && reject(errMsg);
|
|
748
|
+
console.error('上传异常:', errMsg);
|
|
749
|
+
this.reportError(errMsg, { type: 'ossUploadException', businessType: businessType });
|
|
750
|
+
return [3 /*break*/, 9];
|
|
751
|
+
case 9: return [2 /*return*/, result];
|
|
752
|
+
}
|
|
269
753
|
});
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
if (uploadResponse.ok) {
|
|
273
|
-
result = {
|
|
274
|
-
url: signData['fileUrl'],
|
|
275
|
-
imgUrl: signData['fileUrl'],
|
|
276
|
-
imgOrgUrl: signData['fileUrl'],
|
|
277
|
-
name: file.name,
|
|
278
|
-
fileName: file.name,
|
|
279
|
-
};
|
|
280
|
-
callbacks?.onSuccess(result);
|
|
281
|
-
resolve && resolve(result);
|
|
282
|
-
}
|
|
283
|
-
else {
|
|
284
|
-
const errorMessage = `上传失败(OSS 返回 ${uploadResponse.status}):${responseText}`;
|
|
285
|
-
callbacks?.onError(errorMessage);
|
|
286
|
-
reject && reject(errorMessage);
|
|
287
|
-
console.error(errorMessage);
|
|
288
|
-
}
|
|
289
|
-
}
|
|
290
|
-
catch (err) {
|
|
291
|
-
callbacks?.onError(err.message);
|
|
292
|
-
reject && reject(err.message);
|
|
293
|
-
console.error('上传异常:', err.message);
|
|
294
|
-
}
|
|
295
|
-
return result;
|
|
296
|
-
}
|
|
754
|
+
});
|
|
755
|
+
};
|
|
297
756
|
/**
|
|
298
757
|
* 预加载图片获取尺寸
|
|
299
758
|
* @param file 文件对象
|
|
300
759
|
* @returns 图片对象
|
|
301
760
|
*/
|
|
302
|
-
getImageInfo(file) {
|
|
303
|
-
return new Promise((resolve, reject)
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
image.onload = ()
|
|
761
|
+
AliOssClass.prototype.getImageInfo = function (file) {
|
|
762
|
+
return new Promise(function (resolve, reject) {
|
|
763
|
+
var URL = window.URL || window.webkitURL;
|
|
764
|
+
var image = new Image();
|
|
765
|
+
var objectUrl = URL.createObjectURL(file);
|
|
766
|
+
image.onload = function () {
|
|
308
767
|
URL.revokeObjectURL(objectUrl); // 释放内存
|
|
309
768
|
resolve(image);
|
|
310
769
|
};
|
|
311
|
-
image.onerror = ()
|
|
770
|
+
image.onerror = function () {
|
|
312
771
|
URL.revokeObjectURL(objectUrl); // 释放内存
|
|
313
772
|
reject(new Error('图片加载失败'));
|
|
314
773
|
};
|
|
315
774
|
image.src = objectUrl;
|
|
316
775
|
});
|
|
317
|
-
}
|
|
776
|
+
};
|
|
318
777
|
/**
|
|
319
778
|
* 检查图片是否为长图
|
|
320
779
|
* @param File 图片
|
|
321
780
|
* @returns 是否为长图
|
|
322
781
|
*/
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
782
|
+
AliOssClass.prototype.isLongImage = function (file) {
|
|
783
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
784
|
+
var image, width, height, maxDimension, minDimension;
|
|
785
|
+
return __generator(this, function (_a) {
|
|
786
|
+
switch (_a.label) {
|
|
787
|
+
case 0: return [4 /*yield*/, this.getImageInfo(file)];
|
|
788
|
+
case 1:
|
|
789
|
+
image = _a.sent();
|
|
790
|
+
width = image.width, height = image.height;
|
|
791
|
+
maxDimension = Math.max(width, height);
|
|
792
|
+
minDimension = Math.min(width, height);
|
|
793
|
+
return [2 /*return*/, maxDimension / minDimension > LONG_IMAGE_RATIO];
|
|
794
|
+
}
|
|
795
|
+
});
|
|
796
|
+
});
|
|
797
|
+
};
|
|
331
798
|
/**
|
|
332
799
|
* 加载图片并返回结果
|
|
333
800
|
* 用于标准的图片上传场景
|
|
334
801
|
* @param params 加载参数
|
|
335
802
|
*/
|
|
336
|
-
loadImage(params) {
|
|
337
|
-
|
|
338
|
-
|
|
803
|
+
AliOssClass.prototype.loadImage = function (params) {
|
|
804
|
+
var url = params.url, val = params.val, file = params.file, option = params.option, resolve = params.resolve, reject = params.reject;
|
|
805
|
+
var img = new Image();
|
|
339
806
|
img.src = url;
|
|
340
807
|
img.onload = function () {
|
|
808
|
+
var _a;
|
|
341
809
|
if (!img)
|
|
342
810
|
return;
|
|
343
|
-
val.imgOrgUrl =
|
|
811
|
+
val.imgOrgUrl = "".concat(url, "?_").concat(img.width, "_").concat(img.height);
|
|
344
812
|
val.imgUrl = val.imgOrgUrl;
|
|
345
813
|
val.name = file.name;
|
|
346
814
|
val.fileName = file.name;
|
|
347
|
-
option.onSuccess
|
|
815
|
+
(_a = option.onSuccess) === null || _a === void 0 ? void 0 : _a.call(option, val);
|
|
348
816
|
resolve(val);
|
|
349
817
|
img = null;
|
|
350
818
|
};
|
|
351
819
|
img.onerror = function () {
|
|
352
|
-
|
|
820
|
+
var _a;
|
|
821
|
+
(_a = option.onError) === null || _a === void 0 ? void 0 : _a.call(option, '图片加载失败');
|
|
353
822
|
reject('图片加载失败');
|
|
354
823
|
img = null;
|
|
355
824
|
};
|
|
356
|
-
}
|
|
357
|
-
/**
|
|
358
|
-
* 图片上传主方法
|
|
359
|
-
* 整合了所有项目的图片上传逻辑
|
|
360
|
-
* @param option 上传选项
|
|
361
|
-
* @returns Promise
|
|
362
|
-
*/
|
|
363
|
-
ossUploadImage = async (option) => {
|
|
364
|
-
if (!(option.file instanceof File)) {
|
|
365
|
-
return Promise.reject('file is not instanceof File');
|
|
366
|
-
}
|
|
367
|
-
if (!option.businessType) {
|
|
368
|
-
return Promise.reject('businessType不能为空');
|
|
369
|
-
}
|
|
370
|
-
const file = option.file;
|
|
371
|
-
// 初始化回调函数
|
|
372
|
-
const callbacks = {
|
|
373
|
-
onError: option.onError || (() => { }),
|
|
374
|
-
onSuccess: option.onSuccess || (() => { }),
|
|
375
|
-
onProgress: option.onProgress || (() => { }),
|
|
376
|
-
};
|
|
377
|
-
option.onError = callbacks.onError;
|
|
378
|
-
option.onSuccess = callbacks.onSuccess;
|
|
379
|
-
option.onProgress = callbacks.onProgress;
|
|
380
|
-
// 文件类型验证
|
|
381
|
-
if (!isSupportedImageType(file.type)) {
|
|
382
|
-
callbacks.onError('');
|
|
383
|
-
this.apiConfig.messageWarning?.('上传失败,请上传后缀为png、gif、jpg的文件');
|
|
384
|
-
return Promise.reject('文件类型不支持');
|
|
385
|
-
}
|
|
386
|
-
return new Promise(async (resolve, reject) => {
|
|
387
|
-
try {
|
|
388
|
-
// 注释:小图片(≤100KB)不压缩,quality设为1 (MAIN-2481)
|
|
389
|
-
const isSmallImage = getFileSizeInKB(file.size) <= SMALL_IMAGE_THRESHOLD;
|
|
390
|
-
let quality = isSmallImage ? 1 : option.quality || DEFAULT_QUALITY;
|
|
391
|
-
const businessType = option.businessType;
|
|
392
|
-
if (businessType === BusinessType.CREDIT) {
|
|
393
|
-
return await this.upload({
|
|
394
|
-
file,
|
|
395
|
-
businessType,
|
|
396
|
-
resolve,
|
|
397
|
-
reject,
|
|
398
|
-
callbacks,
|
|
399
|
-
});
|
|
400
|
-
}
|
|
401
|
-
// 注释:batchTransfer选项 - 批量转换水印(用于某些特殊业务场景)
|
|
402
|
-
if (option.batchTransfer && this.apiConfig.multiTransferImage) {
|
|
403
|
-
const res = await this.apiConfig.multiTransferImage({ file });
|
|
404
|
-
if (res.data.code === 0) {
|
|
405
|
-
// 盲水印兼容报错
|
|
406
|
-
if (res.data.data) {
|
|
407
|
-
this.loadImage({
|
|
408
|
-
url: res.data.data,
|
|
409
|
-
val: res.data,
|
|
410
|
-
option,
|
|
411
|
-
file,
|
|
412
|
-
resolve,
|
|
413
|
-
reject,
|
|
414
|
-
});
|
|
415
|
-
}
|
|
416
|
-
}
|
|
417
|
-
else {
|
|
418
|
-
callbacks.onError('上传失败');
|
|
419
|
-
reject('上传失败');
|
|
420
|
-
}
|
|
421
|
-
return;
|
|
422
|
-
}
|
|
423
|
-
// 注释:carport类型需要打暗水印
|
|
424
|
-
if (option.imageType === 'carport' &&
|
|
425
|
-
this.apiConfig.darkWaterUploadImage) {
|
|
426
|
-
const res = await this.apiConfig.darkWaterUploadImage({ file });
|
|
427
|
-
if (res.data.code === 0) {
|
|
428
|
-
this.loadImage({
|
|
429
|
-
url: res.data.data,
|
|
430
|
-
val: res.data,
|
|
431
|
-
option,
|
|
432
|
-
file,
|
|
433
|
-
resolve,
|
|
434
|
-
reject,
|
|
435
|
-
});
|
|
436
|
-
}
|
|
437
|
-
else {
|
|
438
|
-
callbacks.onError('上传失败');
|
|
439
|
-
reject('上传失败');
|
|
440
|
-
}
|
|
441
|
-
return;
|
|
442
|
-
}
|
|
443
|
-
// 图片压缩
|
|
444
|
-
const rst = await lrz(file, { quality });
|
|
445
|
-
// 注释:长图压缩有问题,长宽比>2:1的图片不压缩
|
|
446
|
-
const isLong = (await this.isLongImage(file)) || false;
|
|
447
|
-
// 确定最终上传的文件
|
|
448
|
-
let postFile;
|
|
449
|
-
if (option.notCompress || file.type === 'image/gif' || isLong) {
|
|
450
|
-
// 注释:GIF、notCompress选项或长图不压缩
|
|
451
|
-
postFile = file;
|
|
452
|
-
}
|
|
453
|
-
else {
|
|
454
|
-
postFile = rst.file;
|
|
455
|
-
}
|
|
456
|
-
// 文件大小验证
|
|
457
|
-
const imgSize = postFile.size;
|
|
458
|
-
const maxSizeMB = DEFAULT_FILE_SIZE_LIMIT;
|
|
459
|
-
if (getFileSizeInMB(imgSize) > maxSizeMB) {
|
|
460
|
-
const errorMsg = `图片不能超过${maxSizeMB}M`;
|
|
461
|
-
callbacks.onError(errorMsg);
|
|
462
|
-
reject(errorMsg);
|
|
463
|
-
return;
|
|
464
|
-
}
|
|
465
|
-
// 设置文件名(确保压缩后的文件有名称)
|
|
466
|
-
if (!postFile.name) {
|
|
467
|
-
Object.defineProperty(postFile, 'name', {
|
|
468
|
-
value: file.name,
|
|
469
|
-
writable: false,
|
|
470
|
-
});
|
|
471
|
-
}
|
|
472
|
-
const result = await this.upload({
|
|
473
|
-
file,
|
|
474
|
-
businessType,
|
|
475
|
-
resolve,
|
|
476
|
-
reject,
|
|
477
|
-
callbacks,
|
|
478
|
-
});
|
|
479
|
-
// 注释:idCard场景 - 生成预签名URL
|
|
480
|
-
if ((option.idCard || false) &&
|
|
481
|
-
this.apiConfig.generatePrePresignedUrl) {
|
|
482
|
-
const res = await this.apiConfig.generatePrePresignedUrl({
|
|
483
|
-
objectId: result.name,
|
|
484
|
-
expireMils: PRESIGNED_URL_EXPIRE_TIME,
|
|
485
|
-
});
|
|
486
|
-
if (res.data.code === 0) {
|
|
487
|
-
this.loadImage({
|
|
488
|
-
url: res.data.data,
|
|
489
|
-
val: result,
|
|
490
|
-
file: postFile,
|
|
491
|
-
option,
|
|
492
|
-
resolve,
|
|
493
|
-
reject,
|
|
494
|
-
});
|
|
495
|
-
}
|
|
496
|
-
else {
|
|
497
|
-
callbacks.onError('生成预签名URL失败');
|
|
498
|
-
reject('生成预签名URL失败');
|
|
499
|
-
}
|
|
500
|
-
return;
|
|
501
|
-
}
|
|
502
|
-
}
|
|
503
|
-
catch (error) {
|
|
504
|
-
const errorMsg = error.message || '上传异常';
|
|
505
|
-
callbacks.onError(errorMsg);
|
|
506
|
-
reject(errorMsg);
|
|
507
|
-
}
|
|
508
|
-
});
|
|
509
|
-
};
|
|
510
|
-
/**
|
|
511
|
-
* 文件上传方法
|
|
512
|
-
* 支持视频、文档、APK等文件类型
|
|
513
|
-
* @param option 上传选项
|
|
514
|
-
* @returns Promise
|
|
515
|
-
*/
|
|
516
|
-
ossUploadFile = async (option) => {
|
|
517
|
-
if (!(option.file instanceof File)) {
|
|
518
|
-
return Promise.reject('file is not instanceof File');
|
|
519
|
-
}
|
|
520
|
-
if (!option.businessType) {
|
|
521
|
-
return Promise.reject('businessType不能为空');
|
|
522
|
-
}
|
|
523
|
-
const file = option.file;
|
|
524
|
-
// 初始化回调函数
|
|
525
|
-
const callbacks = {
|
|
526
|
-
onError: option.onError || (() => { }),
|
|
527
|
-
onSuccess: option.onSuccess || (() => { }),
|
|
528
|
-
onProgress: option.onProgress || (() => { }),
|
|
529
|
-
};
|
|
530
|
-
option.onError = callbacks.onError;
|
|
531
|
-
option.onSuccess = callbacks.onSuccess;
|
|
532
|
-
option.onProgress = callbacks.onProgress;
|
|
533
|
-
return new Promise(async (resolve, reject) => {
|
|
534
|
-
try {
|
|
535
|
-
let businessType = option.businessType;
|
|
536
|
-
await this.upload({
|
|
537
|
-
file,
|
|
538
|
-
businessType,
|
|
539
|
-
resolve,
|
|
540
|
-
reject,
|
|
541
|
-
callbacks,
|
|
542
|
-
});
|
|
543
|
-
}
|
|
544
|
-
catch (error) {
|
|
545
|
-
const errorMsg = error.message || '上传异常';
|
|
546
|
-
callbacks.onError(errorMsg);
|
|
547
|
-
reject(errorMsg);
|
|
548
|
-
}
|
|
549
|
-
});
|
|
550
|
-
};
|
|
551
|
-
/**
|
|
552
|
-
* 纯图片上传 pureOssUploadImage
|
|
553
|
-
* 注释:图片上传,不压缩
|
|
554
|
-
* @param option 上传选项
|
|
555
|
-
* @returns Promise
|
|
556
|
-
*/
|
|
557
|
-
pureOssUploadImage = async (option) => {
|
|
558
|
-
return await this.shopDetailUpdate(option);
|
|
559
|
-
};
|
|
560
|
-
/**
|
|
561
|
-
* 商品详情图片上传(不建议直接使用,请使用 pureOssUploadImage)
|
|
562
|
-
* 注释:图片上传,不压缩
|
|
563
|
-
* @param option 上传选项
|
|
564
|
-
* @returns Promise
|
|
565
|
-
*/
|
|
566
|
-
shopDetailUpdate = async (option) => {
|
|
567
|
-
if (!(option.file instanceof File)) {
|
|
568
|
-
return Promise.reject('file is not instanceof File');
|
|
569
|
-
}
|
|
570
|
-
if (!option.businessType) {
|
|
571
|
-
return Promise.reject('businessType不能为空');
|
|
572
|
-
}
|
|
573
|
-
const file = option.file;
|
|
574
|
-
// 初始化回调函数
|
|
575
|
-
const callbacks = {
|
|
576
|
-
onError: option.onError || (() => { }),
|
|
577
|
-
onSuccess: option.onSuccess || (() => { }),
|
|
578
|
-
onProgress: option.onProgress || (() => { }),
|
|
579
|
-
};
|
|
580
|
-
option.onError = callbacks.onError;
|
|
581
|
-
option.onSuccess = callbacks.onSuccess;
|
|
582
|
-
option.onProgress = callbacks.onProgress;
|
|
583
|
-
// 文件类型验证
|
|
584
|
-
if (!isSupportedImageType(file.type)) {
|
|
585
|
-
callbacks.onError('');
|
|
586
|
-
this.apiConfig.messageWarning?.('上传失败,请上传后缀为png、gif、jpg的文件');
|
|
587
|
-
return Promise.reject('文件类型不支持');
|
|
588
|
-
}
|
|
589
|
-
return new Promise(async (resolve, reject) => {
|
|
590
|
-
try {
|
|
591
|
-
const businessType = option.businessType;
|
|
592
|
-
// 文件大小验证
|
|
593
|
-
if (getFileSizeInMB(file.size) > DEFAULT_FILE_SIZE_LIMIT) {
|
|
594
|
-
const errorMsg = `图片不能超过${DEFAULT_FILE_SIZE_LIMIT}M`;
|
|
595
|
-
callbacks.onError(errorMsg);
|
|
596
|
-
reject(errorMsg);
|
|
597
|
-
return;
|
|
598
|
-
}
|
|
599
|
-
await this.upload({
|
|
600
|
-
file,
|
|
601
|
-
businessType,
|
|
602
|
-
resolve,
|
|
603
|
-
reject,
|
|
604
|
-
callbacks,
|
|
605
|
-
});
|
|
606
|
-
}
|
|
607
|
-
catch (error) {
|
|
608
|
-
const errorMsg = error.message || '上传异常';
|
|
609
|
-
callbacks.onError(errorMsg);
|
|
610
|
-
reject(errorMsg);
|
|
611
|
-
}
|
|
612
|
-
});
|
|
613
825
|
};
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
}
|
|
826
|
+
AliOssClass.instance = null;
|
|
827
|
+
return AliOssClass;
|
|
828
|
+
}());
|
|
829
|
+
export { AliOssClass };
|
|
619
830
|
/**
|
|
620
831
|
* 创建阿里云OSS上传器(工厂函数,内部已实现单例)
|
|
621
832
|
* @param apiConfig API配置对象,包含业务相关的API函数
|
|
@@ -628,6 +839,6 @@ export function createAliOssUploader(apiConfig) {
|
|
|
628
839
|
* 默认导出
|
|
629
840
|
*/
|
|
630
841
|
export default {
|
|
631
|
-
createAliOssUploader,
|
|
632
|
-
BusinessType,
|
|
842
|
+
createAliOssUploader: createAliOssUploader,
|
|
843
|
+
BusinessType: BusinessType,
|
|
633
844
|
};
|