@haluo/util 2.0.20 → 2.0.21
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.js +33 -64
- package/dist/modules/cookie/index.js +18 -24
- package/dist/modules/date/index.js +49 -56
- package/dist/modules/dom/index.js +16 -23
- package/dist/modules/filter/index.js +15 -25
- package/dist/modules/format/index.js +6 -12
- package/dist/modules/match/index.js +6 -10
- package/dist/modules/monitor/index.js +7 -14
- package/dist/modules/monitor/lib/jsError.js +39 -35
- package/dist/modules/monitor/lib/timing.js +24 -28
- package/dist/modules/monitor/lib/xhr.js +26 -33
- package/dist/modules/monitor/utils/onload.js +1 -4
- package/dist/modules/monitor/utils/tracker.js +13 -27
- package/dist/modules/number/index.js +31 -35
- package/dist/modules/open-app/index.js +66 -61
- package/dist/modules/sentry/index.js +19 -27
- package/dist/modules/tools/index.d.ts +1 -1
- package/dist/modules/tools/index.js +158 -169
- package/dist/modules/upload/aliOss.d.ts +97 -45
- package/dist/modules/upload/aliOss.js +437 -575
- package/dist/modules/upload/index.d.ts +46 -1
- package/dist/modules/upload/index.js +41 -12
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/dist/types/index.js +1 -2
- package/package.json +15 -4
- package/dist/modules/upload/ALIOSS_EXAMPLE.d.ts +0 -83
- package/dist/modules/upload/ALIOSS_EXAMPLE.js +0 -320
- package/dist/types/modules/cookie/index.d.ts +0 -27
- package/dist/types/modules/date/index.d.ts +0 -52
- package/dist/types/modules/dom/index.d.ts +0 -28
- package/dist/types/modules/filter/index.d.ts +0 -24
- package/dist/types/modules/format/index.d.ts +0 -15
- package/dist/types/modules/match/index.d.ts +0 -12
- package/dist/types/modules/monitor/index.d.ts +0 -3
- package/dist/types/modules/monitor/lib/jsError.d.ts +0 -1
- package/dist/types/modules/monitor/lib/timing.d.ts +0 -1
- package/dist/types/modules/monitor/lib/xhr.d.ts +0 -1
- package/dist/types/modules/monitor/utils/onload.d.ts +0 -1
- package/dist/types/modules/monitor/utils/tracker.d.ts +0 -7
- package/dist/types/modules/number/index.d.ts +0 -41
- package/dist/types/modules/sentry/index.d.ts +0 -15
- package/dist/types/modules/tools/index.d.ts +0 -166
- package/dist/types/types/index.d.ts +0 -3
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
"use strict";
|
|
2
1
|
/**
|
|
3
2
|
* @file 阿里云OSS上传统一工具类
|
|
4
3
|
* @description 整合所有项目的aliOss业务逻辑,通过传参形式支持不同业务场景
|
|
@@ -50,87 +49,35 @@
|
|
|
50
49
|
* })
|
|
51
50
|
* ```
|
|
52
51
|
*/
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
for (var s, i = 1, n = arguments.length; i < n; i++) {
|
|
56
|
-
s = arguments[i];
|
|
57
|
-
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
|
|
58
|
-
t[p] = s[p];
|
|
59
|
-
}
|
|
60
|
-
return t;
|
|
61
|
-
};
|
|
62
|
-
return __assign.apply(this, arguments);
|
|
63
|
-
};
|
|
64
|
-
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
65
|
-
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
66
|
-
return new (P || (P = Promise))(function (resolve, reject) {
|
|
67
|
-
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
68
|
-
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
69
|
-
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
70
|
-
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
71
|
-
});
|
|
72
|
-
};
|
|
73
|
-
var __generator = (this && this.__generator) || function (thisArg, body) {
|
|
74
|
-
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
|
|
75
|
-
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
|
|
76
|
-
function verb(n) { return function (v) { return step([n, v]); }; }
|
|
77
|
-
function step(op) {
|
|
78
|
-
if (f) throw new TypeError("Generator is already executing.");
|
|
79
|
-
while (g && (g = 0, op[0] && (_ = 0)), _) try {
|
|
80
|
-
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;
|
|
81
|
-
if (y = 0, t) op = [op[0] & 2, t.value];
|
|
82
|
-
switch (op[0]) {
|
|
83
|
-
case 0: case 1: t = op; break;
|
|
84
|
-
case 4: _.label++; return { value: op[1], done: false };
|
|
85
|
-
case 5: _.label++; y = op[1]; op = [0]; continue;
|
|
86
|
-
case 7: op = _.ops.pop(); _.trys.pop(); continue;
|
|
87
|
-
default:
|
|
88
|
-
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
|
|
89
|
-
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
|
|
90
|
-
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
|
|
91
|
-
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
|
|
92
|
-
if (t[2]) _.ops.pop();
|
|
93
|
-
_.trys.pop(); continue;
|
|
94
|
-
}
|
|
95
|
-
op = body.call(thisArg, _);
|
|
96
|
-
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
|
|
97
|
-
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
|
|
98
|
-
}
|
|
99
|
-
};
|
|
100
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
101
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
102
|
-
};
|
|
103
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
104
|
-
exports.createAliOssUploader = exports.SuffixEnum = exports.BusinessType = void 0;
|
|
105
|
-
var ali_oss_1 = __importDefault(require("ali-oss"));
|
|
106
|
-
var lrz_1 = __importDefault(require("lrz"));
|
|
52
|
+
import OSS from 'ali-oss';
|
|
53
|
+
import lrz from 'lrz';
|
|
107
54
|
// ==================== 常量定义 ====================
|
|
108
55
|
/** 支持的图片格式 */
|
|
109
|
-
|
|
56
|
+
const SUPPORTED_IMAGE_TYPES = ['image/png', 'image/gif', 'image/jpg', 'image/jpeg'];
|
|
110
57
|
/** 小图片阈值(KB) */
|
|
111
|
-
|
|
58
|
+
const SMALL_IMAGE_THRESHOLD = 100;
|
|
112
59
|
/** 长图宽高比阈值 */
|
|
113
|
-
|
|
60
|
+
const LONG_IMAGE_RATIO = 2;
|
|
114
61
|
/** 默认文件大小限制(MB) */
|
|
115
|
-
|
|
62
|
+
const DEFAULT_FILE_SIZE_LIMIT = 10;
|
|
116
63
|
/** 默认压缩质量 */
|
|
117
|
-
|
|
64
|
+
const DEFAULT_QUALITY = 0.7;
|
|
118
65
|
/** 默认图片类型 */
|
|
119
|
-
|
|
66
|
+
const DEFAULT_IMAGE_TYPE = 'official';
|
|
120
67
|
/** OSS默认区域 */
|
|
121
|
-
|
|
68
|
+
const DEFAULT_OSS_REGION = 'oss-cn-beijing';
|
|
122
69
|
/** 预签名URL过期时间(毫秒) */
|
|
123
|
-
|
|
70
|
+
const PRESIGNED_URL_EXPIRE_TIME = 60000;
|
|
124
71
|
/** 随机字符串字符集 */
|
|
125
|
-
|
|
72
|
+
const RANDOM_CHARS = '0123456789abcdefghijklmnopqrstuvwxyz';
|
|
126
73
|
/** OSS元数据 */
|
|
127
|
-
|
|
74
|
+
const OSS_META_PEOPLE = 'x-oss-meta-motor';
|
|
128
75
|
// ==================== 枚举定义 ====================
|
|
129
76
|
/**
|
|
130
77
|
* 业务类型枚举
|
|
131
78
|
* 不同的businessType对应不同的OSS bucket和水印策略
|
|
132
79
|
*/
|
|
133
|
-
var BusinessType;
|
|
80
|
+
export var BusinessType;
|
|
134
81
|
(function (BusinessType) {
|
|
135
82
|
BusinessType[BusinessType["NO_WATER"] = 0] = "NO_WATER";
|
|
136
83
|
BusinessType[BusinessType["AVATAR"] = 1] = "AVATAR";
|
|
@@ -141,11 +88,11 @@ var BusinessType;
|
|
|
141
88
|
BusinessType[BusinessType["PRIVATE"] = 1199] = "PRIVATE";
|
|
142
89
|
BusinessType[BusinessType["ENCRYPTED"] = 1299] = "ENCRYPTED";
|
|
143
90
|
BusinessType[BusinessType["DEFAULT"] = 1500] = "DEFAULT"; // 默认
|
|
144
|
-
})(BusinessType
|
|
91
|
+
})(BusinessType || (BusinessType = {}));
|
|
145
92
|
/**
|
|
146
93
|
* 图片类型后缀枚举
|
|
147
94
|
*/
|
|
148
|
-
|
|
95
|
+
export const SuffixEnum = {
|
|
149
96
|
nowater: '!nowater',
|
|
150
97
|
official: '!official',
|
|
151
98
|
panoram: '!panoram',
|
|
@@ -155,7 +102,7 @@ exports.SuffixEnum = {
|
|
|
155
102
|
carport: '!carport' // 车库、经销商水印
|
|
156
103
|
};
|
|
157
104
|
/** 不打水印的图片类型 */
|
|
158
|
-
|
|
105
|
+
const NO_WATER_IMAGE_TYPES = ['nowater', 'forum'];
|
|
159
106
|
// ==================== 工具函数 ====================
|
|
160
107
|
/**
|
|
161
108
|
* 生成随机字符串
|
|
@@ -163,9 +110,9 @@ var NO_WATER_IMAGE_TYPES = ['nowater', 'forum'];
|
|
|
163
110
|
* @returns 随机字符串
|
|
164
111
|
*/
|
|
165
112
|
function randomString(length) {
|
|
166
|
-
|
|
167
|
-
for (
|
|
168
|
-
|
|
113
|
+
let result = '';
|
|
114
|
+
for (let i = 0; i < length; i++) {
|
|
115
|
+
const randomIndex = Math.floor(Math.random() * RANDOM_CHARS.length);
|
|
169
116
|
result += RANDOM_CHARS[randomIndex];
|
|
170
117
|
}
|
|
171
118
|
return result;
|
|
@@ -176,8 +123,8 @@ function randomString(length) {
|
|
|
176
123
|
* @returns 过滤后的对象
|
|
177
124
|
*/
|
|
178
125
|
function filterUndefined(obj) {
|
|
179
|
-
|
|
180
|
-
Object.keys(obj).forEach(
|
|
126
|
+
const result = {};
|
|
127
|
+
Object.keys(obj).forEach(key => {
|
|
181
128
|
if (obj[key] !== undefined) {
|
|
182
129
|
result[key] = obj[key];
|
|
183
130
|
}
|
|
@@ -216,61 +163,66 @@ function getFileSizeInKB(size) {
|
|
|
216
163
|
function getFileSizeInMB(size) {
|
|
217
164
|
return size / (1024 * 1024);
|
|
218
165
|
}
|
|
219
|
-
// ====================
|
|
166
|
+
// ==================== 主类 ====================
|
|
220
167
|
/**
|
|
221
|
-
*
|
|
222
|
-
*
|
|
223
|
-
* @returns OSS上传器实例
|
|
168
|
+
* 阿里云OSS上传类
|
|
169
|
+
* 整合所有项目的aliOss业务逻辑,通过依赖注入实现业务API解耦
|
|
224
170
|
*/
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
171
|
+
export class AliOssClass {
|
|
172
|
+
apiConfig;
|
|
173
|
+
clientCache;
|
|
174
|
+
constructor(apiConfig) {
|
|
175
|
+
this.apiConfig = apiConfig;
|
|
176
|
+
this.clientCache = new Map();
|
|
177
|
+
}
|
|
228
178
|
/**
|
|
229
179
|
* 创建OSS客户端
|
|
230
180
|
* @param businessType 业务类型
|
|
231
181
|
* @param imggeCarType 车辆图片类型(可选,用于特定业务)
|
|
232
182
|
* @returns OSS客户端实例
|
|
233
183
|
*/
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
// 保存客户端选项供后续使用
|
|
252
|
-
client.options = __assign(__assign({}, client.options), { realmName: clientParams.realmName, suffix: clientParams.suffix });
|
|
253
|
-
clientCache.set(cacheKey, client);
|
|
254
|
-
return [2 /*return*/, client];
|
|
255
|
-
}
|
|
256
|
-
});
|
|
184
|
+
async createOssClient(businessType, imggeCarType) {
|
|
185
|
+
const cacheKey = `${businessType}_${imggeCarType || 'default'}`;
|
|
186
|
+
// 注释:某些项目使用缓存,某些不使用。这里提供可选的缓存机制
|
|
187
|
+
// if (this.clientCache.has(cacheKey)) {
|
|
188
|
+
// return this.clientCache.get(cacheKey)
|
|
189
|
+
// }
|
|
190
|
+
const res = await this.apiConfig.getAliyunSts({ businessType, imggeCarType });
|
|
191
|
+
if (res.data.code !== 0) {
|
|
192
|
+
throw new Error('获取OSS配置失败');
|
|
193
|
+
}
|
|
194
|
+
const clientParams = res.data.data || {};
|
|
195
|
+
clientParams.suffix = clientParams.style || '';
|
|
196
|
+
// 过滤掉undefined值的属性,并确保必需字段存在
|
|
197
|
+
const filteredParams = filterUndefined(clientParams);
|
|
198
|
+
const client = new OSS({
|
|
199
|
+
region: DEFAULT_OSS_REGION,
|
|
200
|
+
...filteredParams
|
|
257
201
|
});
|
|
202
|
+
// 保存客户端选项供后续使用
|
|
203
|
+
client.options = {
|
|
204
|
+
...client.options,
|
|
205
|
+
realmName: clientParams.realmName,
|
|
206
|
+
suffix: clientParams.suffix
|
|
207
|
+
};
|
|
208
|
+
this.clientCache.set(cacheKey, client);
|
|
209
|
+
return client;
|
|
258
210
|
}
|
|
259
211
|
/**
|
|
260
212
|
* 预加载图片获取尺寸
|
|
261
213
|
* @param file 文件对象
|
|
262
214
|
* @returns 图片对象
|
|
263
215
|
*/
|
|
264
|
-
|
|
265
|
-
return new Promise(
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
image.onload =
|
|
216
|
+
imgUpload(file) {
|
|
217
|
+
return new Promise((resolve, reject) => {
|
|
218
|
+
const URL = window.URL || window.webkitURL;
|
|
219
|
+
const image = new Image();
|
|
220
|
+
const objectUrl = URL.createObjectURL(file);
|
|
221
|
+
image.onload = () => {
|
|
270
222
|
URL.revokeObjectURL(objectUrl); // 释放内存
|
|
271
223
|
resolve(image);
|
|
272
224
|
};
|
|
273
|
-
image.onerror =
|
|
225
|
+
image.onerror = () => {
|
|
274
226
|
URL.revokeObjectURL(objectUrl); // 释放内存
|
|
275
227
|
reject(new Error('图片加载失败'));
|
|
276
228
|
};
|
|
@@ -283,14 +235,14 @@ function createAliOssUploader(apiConfig) {
|
|
|
283
235
|
* @param extension 文件扩展名
|
|
284
236
|
* @returns 文件名信息
|
|
285
237
|
*/
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
return { year
|
|
238
|
+
generateFileName(imageType, extension) {
|
|
239
|
+
const now = new Date();
|
|
240
|
+
const year = this.apiConfig.dateFormat(now, 'YYYY');
|
|
241
|
+
const date = this.apiConfig.dateFormat(now, 'YYYYMMDD');
|
|
242
|
+
const dateTime = this.apiConfig.dateFormat(now, 'YYYYMMDDHHmmss');
|
|
243
|
+
const randomStr = randomString(4);
|
|
244
|
+
const fileName = `${imageType}/${date}/${dateTime}_${randomStr}${extension}`;
|
|
245
|
+
return { year, fileName };
|
|
294
246
|
}
|
|
295
247
|
/**
|
|
296
248
|
* 检查图片是否为长图
|
|
@@ -298,9 +250,9 @@ function createAliOssUploader(apiConfig) {
|
|
|
298
250
|
* @param height 图片高度
|
|
299
251
|
* @returns 是否为长图
|
|
300
252
|
*/
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
253
|
+
isLongImage(width, height) {
|
|
254
|
+
const maxDimension = Math.max(width, height);
|
|
255
|
+
const minDimension = Math.min(width, height);
|
|
304
256
|
return maxDimension / minDimension > LONG_IMAGE_RATIO;
|
|
305
257
|
}
|
|
306
258
|
/**
|
|
@@ -313,20 +265,13 @@ function createAliOssUploader(apiConfig) {
|
|
|
313
265
|
* @param onProgress 进度回调
|
|
314
266
|
* @returns 上传结果
|
|
315
267
|
*/
|
|
316
|
-
|
|
317
|
-
return
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
},
|
|
324
|
-
meta: { year: year, people: OSS_META_PEOPLE },
|
|
325
|
-
mime: mimeType
|
|
326
|
-
})];
|
|
327
|
-
case 1: return [2 /*return*/, _a.sent()];
|
|
328
|
-
}
|
|
329
|
-
});
|
|
268
|
+
async performOssUpload(client, fileName, file, year, mimeType, onProgress) {
|
|
269
|
+
return await client.multipartUpload(fileName, file, {
|
|
270
|
+
progress: (p) => {
|
|
271
|
+
onProgress?.({ percent: Math.floor(p * 100) });
|
|
272
|
+
},
|
|
273
|
+
meta: { year, people: OSS_META_PEOPLE },
|
|
274
|
+
mime: mimeType
|
|
330
275
|
});
|
|
331
276
|
}
|
|
332
277
|
/**
|
|
@@ -335,12 +280,12 @@ function createAliOssUploader(apiConfig) {
|
|
|
335
280
|
* @param isGif 是否为GIF
|
|
336
281
|
* @returns 业务类型
|
|
337
282
|
*/
|
|
338
|
-
|
|
283
|
+
determineBusinessType(option, isGif) {
|
|
339
284
|
// 如果已指定businessType,直接使用
|
|
340
285
|
if (option.businessType !== undefined) {
|
|
341
286
|
return option.businessType;
|
|
342
287
|
}
|
|
343
|
-
|
|
288
|
+
const imageType = option.imageType || DEFAULT_IMAGE_TYPE;
|
|
344
289
|
// 注释:GIF图片使用businessType=4
|
|
345
290
|
if (isGif) {
|
|
346
291
|
return BusinessType.GIF;
|
|
@@ -359,29 +304,27 @@ function createAliOssUploader(apiConfig) {
|
|
|
359
304
|
* 用于标准的图片上传场景
|
|
360
305
|
* @param params 加载参数
|
|
361
306
|
*/
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
307
|
+
loadImage(params) {
|
|
308
|
+
const { url, val, suffix, file, option, resolve, reject, isGif } = params;
|
|
309
|
+
let img = new Image();
|
|
365
310
|
img.src = url;
|
|
366
311
|
img.onload = function () {
|
|
367
|
-
var _a;
|
|
368
312
|
if (!img)
|
|
369
313
|
return;
|
|
370
|
-
val.imgOrgUrl =
|
|
314
|
+
val.imgOrgUrl = `${url}?_${img.width}_${img.height}`;
|
|
371
315
|
// 注释:全景图和GIF图片缩略图后缀不带300,其他需要
|
|
372
316
|
val.imgUrl =
|
|
373
317
|
suffix === '!panoram' || isGif
|
|
374
|
-
?
|
|
375
|
-
:
|
|
318
|
+
? `${url}?_${img.width}_${img.height}`
|
|
319
|
+
: `${url}300?_${img.width}_${img.height}`;
|
|
376
320
|
val.name = file.name;
|
|
377
321
|
val.fileName = file.name;
|
|
378
|
-
|
|
322
|
+
option.onSuccess?.(val);
|
|
379
323
|
resolve(val);
|
|
380
324
|
img = null;
|
|
381
325
|
};
|
|
382
326
|
img.onerror = function () {
|
|
383
|
-
|
|
384
|
-
(_a = option.onError) === null || _a === void 0 ? void 0 : _a.call(option, '图片加载失败');
|
|
327
|
+
option.onError?.('图片加载失败');
|
|
385
328
|
reject('图片加载失败');
|
|
386
329
|
img = null;
|
|
387
330
|
};
|
|
@@ -391,23 +334,21 @@ function createAliOssUploader(apiConfig) {
|
|
|
391
334
|
* 用于avatar、idCard等特殊场景,返回格式不同
|
|
392
335
|
* @param params 加载参数
|
|
393
336
|
*/
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
337
|
+
loadImageNew(params) {
|
|
338
|
+
const { url, val, file, option, resolve, reject } = params;
|
|
339
|
+
let img = new Image();
|
|
397
340
|
img.src = url;
|
|
398
341
|
img.onload = function () {
|
|
399
|
-
var _a;
|
|
400
342
|
val.imgOrgUrl = url;
|
|
401
343
|
val.imgUrl = val.name;
|
|
402
344
|
val.name = file.name;
|
|
403
345
|
val.fileName = file.name;
|
|
404
|
-
|
|
346
|
+
option.onSuccess?.(val);
|
|
405
347
|
resolve(val);
|
|
406
348
|
img = null;
|
|
407
349
|
};
|
|
408
350
|
img.onerror = function () {
|
|
409
|
-
|
|
410
|
-
(_a = option.onError) === null || _a === void 0 ? void 0 : _a.call(option, '图片加载失败');
|
|
351
|
+
option.onError?.('图片加载失败');
|
|
411
352
|
reject('图片加载失败');
|
|
412
353
|
img = null;
|
|
413
354
|
};
|
|
@@ -418,447 +359,368 @@ function createAliOssUploader(apiConfig) {
|
|
|
418
359
|
* @param option 上传选项
|
|
419
360
|
* @returns Promise
|
|
420
361
|
*/
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
362
|
+
ossUploadImage = async (option) => {
|
|
363
|
+
const file = option.file;
|
|
364
|
+
// 初始化回调函数
|
|
365
|
+
const callbacks = {
|
|
366
|
+
onError: option.onError || (() => { }),
|
|
367
|
+
onSuccess: option.onSuccess || (() => { }),
|
|
368
|
+
onProgress: option.onProgress || (() => { })
|
|
369
|
+
};
|
|
370
|
+
option.onError = callbacks.onError;
|
|
371
|
+
option.onSuccess = callbacks.onSuccess;
|
|
372
|
+
option.onProgress = callbacks.onProgress;
|
|
373
|
+
// 文件类型验证
|
|
374
|
+
if (!isSupportedImageType(file.type)) {
|
|
375
|
+
callbacks.onError('');
|
|
376
|
+
this.apiConfig.messageWarning?.('上传失败,请上传后缀为png、gif、jpg的文件');
|
|
377
|
+
return Promise.reject('文件类型不支持');
|
|
378
|
+
}
|
|
379
|
+
return new Promise(async (resolve, reject) => {
|
|
380
|
+
try {
|
|
381
|
+
const imageType = option.imageType || DEFAULT_IMAGE_TYPE;
|
|
382
|
+
const suffix = SuffixEnum[imageType] || SuffixEnum.official;
|
|
383
|
+
// 生成文件名
|
|
384
|
+
const extensionName = `.${file.name.split('.').pop()}`;
|
|
385
|
+
const { year, fileName } = this.generateFileName(imageType, extensionName);
|
|
386
|
+
// 注释:小图片(≤100KB)不压缩,quality设为1 (MAIN-2481)
|
|
387
|
+
const isSmallImage = getFileSizeInKB(file.size) <= SMALL_IMAGE_THRESHOLD;
|
|
388
|
+
let quality = isSmallImage ? 1 : (option.quality || DEFAULT_QUALITY);
|
|
389
|
+
const isGif = file.type === 'image/gif';
|
|
390
|
+
const idCard = option.idCard || false;
|
|
391
|
+
// 确定业务类型
|
|
392
|
+
const businessType = this.determineBusinessType(option, isGif);
|
|
393
|
+
// 注释:特殊业务类型1299(加密)直接返回bucket路径,不加载图片
|
|
394
|
+
if (businessType === BusinessType.ENCRYPTED) {
|
|
395
|
+
const client = await this.createOssClient(businessType, option.imggeCarType);
|
|
396
|
+
const result = await this.performOssUpload(client, fileName, file, year, file.type, callbacks.onProgress);
|
|
397
|
+
if (result.res.statusCode === 200) {
|
|
398
|
+
const val = {
|
|
399
|
+
...result,
|
|
400
|
+
imgUrl: `${result.bucket}://${result.name}`,
|
|
401
|
+
imgOrgUrl: `${result.bucket}://${result.name}`,
|
|
402
|
+
fileName: file.name
|
|
403
|
+
};
|
|
404
|
+
callbacks.onSuccess(val);
|
|
405
|
+
resolve(val);
|
|
406
|
+
}
|
|
407
|
+
else {
|
|
408
|
+
callbacks.onError('上传失败');
|
|
409
|
+
reject('上传失败');
|
|
410
|
+
}
|
|
411
|
+
return;
|
|
412
|
+
}
|
|
413
|
+
// 注释:batchTransfer选项 - 批量转换水印(用于某些特殊业务场景)
|
|
414
|
+
if (option.batchTransfer && this.apiConfig.multiTransferImage) {
|
|
415
|
+
const res = await this.apiConfig.multiTransferImage({ file });
|
|
416
|
+
if (res.data.code === 0) {
|
|
417
|
+
this.loadImage({
|
|
418
|
+
url: res.data.data,
|
|
419
|
+
val: res.data,
|
|
420
|
+
suffix,
|
|
421
|
+
option,
|
|
422
|
+
file,
|
|
423
|
+
resolve,
|
|
424
|
+
reject
|
|
425
|
+
});
|
|
426
|
+
}
|
|
427
|
+
else {
|
|
428
|
+
callbacks.onError('上传失败');
|
|
429
|
+
reject('上传失败');
|
|
430
|
+
}
|
|
431
|
+
return;
|
|
432
|
+
}
|
|
433
|
+
// 注释:carport类型需要打暗水印
|
|
434
|
+
if (option.imageType === 'carport' && this.apiConfig.darkWaterUploadImage) {
|
|
435
|
+
const res = await this.apiConfig.darkWaterUploadImage({ file });
|
|
436
|
+
if (res.data.code === 0) {
|
|
437
|
+
this.loadImage({
|
|
438
|
+
url: res.data.data,
|
|
439
|
+
val: res.data,
|
|
440
|
+
suffix,
|
|
441
|
+
option,
|
|
442
|
+
file,
|
|
443
|
+
resolve,
|
|
444
|
+
reject
|
|
445
|
+
});
|
|
446
|
+
}
|
|
447
|
+
else {
|
|
448
|
+
callbacks.onError('上传失败');
|
|
449
|
+
reject('上传失败');
|
|
450
|
+
}
|
|
451
|
+
return;
|
|
452
|
+
}
|
|
453
|
+
// 预加载图片获取尺寸
|
|
454
|
+
const image = await this.imgUpload(file);
|
|
455
|
+
// 图片压缩
|
|
456
|
+
const rst = await lrz(file, { quality });
|
|
457
|
+
// 注释:长图压缩有问题,长宽比>2:1的图片不压缩
|
|
458
|
+
const isLong = this.isLongImage(image.width, image.height);
|
|
459
|
+
// 确定最终上传的文件
|
|
460
|
+
let postFile;
|
|
461
|
+
if (option.notCompress || isGif || isLong) {
|
|
462
|
+
// 注释:GIF、notCompress选项或长图不压缩
|
|
463
|
+
postFile = file;
|
|
464
|
+
}
|
|
465
|
+
else {
|
|
466
|
+
postFile = rst.file;
|
|
441
467
|
}
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
suffix: suffix,
|
|
505
|
-
option: option,
|
|
506
|
-
file: file,
|
|
507
|
-
resolve: resolve,
|
|
508
|
-
reject: reject
|
|
509
|
-
});
|
|
510
|
-
}
|
|
511
|
-
else {
|
|
512
|
-
callbacks.onError('上传失败');
|
|
513
|
-
reject('上传失败');
|
|
514
|
-
}
|
|
515
|
-
return [2 /*return*/];
|
|
516
|
-
case 7: return [4 /*yield*/, imgUpload(file)
|
|
517
|
-
// 图片压缩
|
|
518
|
-
];
|
|
519
|
-
case 8:
|
|
520
|
-
image = _b.sent();
|
|
521
|
-
return [4 /*yield*/, (0, lrz_1.default)(file, { quality: quality })
|
|
522
|
-
// 注释:长图压缩有问题,长宽比>2:1的图片不压缩
|
|
523
|
-
];
|
|
524
|
-
case 9:
|
|
525
|
-
rst = _b.sent();
|
|
526
|
-
isLong = isLongImage(image.width, image.height);
|
|
527
|
-
postFile = void 0;
|
|
528
|
-
if (option.notCompress || isGif || isLong) {
|
|
529
|
-
// 注释:GIF、notCompress选项或长图不压缩
|
|
530
|
-
postFile = file;
|
|
531
|
-
}
|
|
532
|
-
else {
|
|
533
|
-
postFile = rst.file;
|
|
534
|
-
}
|
|
535
|
-
imgSize = postFile.size;
|
|
536
|
-
maxSizeMB = DEFAULT_FILE_SIZE_LIMIT;
|
|
537
|
-
if (getFileSizeInMB(imgSize) > maxSizeMB) {
|
|
538
|
-
errorMsg = "\u56FE\u7247\u4E0D\u80FD\u8D85\u8FC7".concat(maxSizeMB, "M");
|
|
539
|
-
callbacks.onError(errorMsg);
|
|
540
|
-
reject(errorMsg);
|
|
541
|
-
return [2 /*return*/];
|
|
542
|
-
}
|
|
543
|
-
// 设置文件名(确保压缩后的文件有名称)
|
|
544
|
-
if (!postFile.name) {
|
|
545
|
-
Object.defineProperty(postFile, 'name', {
|
|
546
|
-
value: file.name,
|
|
547
|
-
writable: false
|
|
548
|
-
});
|
|
549
|
-
}
|
|
550
|
-
return [4 /*yield*/, createOssClient(businessType, option.imggeCarType)
|
|
551
|
-
// 执行上传
|
|
552
|
-
];
|
|
553
|
-
case 10:
|
|
554
|
-
client = _b.sent();
|
|
555
|
-
return [4 /*yield*/, performOssUpload(client, fileName, postFile, year, postFile.type, callbacks.onProgress)];
|
|
556
|
-
case 11:
|
|
557
|
-
result = _b.sent();
|
|
558
|
-
if (result.res.statusCode !== 200) {
|
|
559
|
-
callbacks.onError('上传失败');
|
|
560
|
-
reject('上传失败');
|
|
561
|
-
return [2 /*return*/];
|
|
562
|
-
}
|
|
563
|
-
if (!(idCard && apiConfig.generatePrePresignedUrl)) return [3 /*break*/, 13];
|
|
564
|
-
return [4 /*yield*/, apiConfig.generatePrePresignedUrl({
|
|
565
|
-
objectId: result.name,
|
|
566
|
-
expireMils: PRESIGNED_URL_EXPIRE_TIME
|
|
567
|
-
})];
|
|
568
|
-
case 12:
|
|
569
|
-
res = _b.sent();
|
|
570
|
-
if (res.data.code === 0) {
|
|
571
|
-
loadImageNew({
|
|
572
|
-
url: res.data.data,
|
|
573
|
-
val: result,
|
|
574
|
-
file: postFile,
|
|
575
|
-
option: option,
|
|
576
|
-
resolve: resolve,
|
|
577
|
-
reject: reject
|
|
578
|
-
});
|
|
579
|
-
}
|
|
580
|
-
else {
|
|
581
|
-
callbacks.onError('生成预签名URL失败');
|
|
582
|
-
reject('生成预签名URL失败');
|
|
583
|
-
}
|
|
584
|
-
return [2 /*return*/];
|
|
585
|
-
case 13:
|
|
586
|
-
if (!(imageType === 'avatar' && apiConfig.aliyunPersist)) return [3 /*break*/, 15];
|
|
587
|
-
return [4 /*yield*/, apiConfig.aliyunPersist({
|
|
588
|
-
object: "".concat(result.bucket, "://").concat(result.name),
|
|
589
|
-
businessType: BusinessType.AVATAR
|
|
590
|
-
})];
|
|
591
|
-
case 14:
|
|
592
|
-
res = _b.sent();
|
|
593
|
-
if (res.data.code === 0) {
|
|
594
|
-
loadImageNew({
|
|
595
|
-
url: res.data.data,
|
|
596
|
-
val: result,
|
|
597
|
-
file: postFile,
|
|
598
|
-
option: option,
|
|
599
|
-
resolve: resolve,
|
|
600
|
-
reject: reject
|
|
601
|
-
});
|
|
602
|
-
}
|
|
603
|
-
else {
|
|
604
|
-
callbacks.onError('头像处理失败');
|
|
605
|
-
reject('头像处理失败');
|
|
606
|
-
}
|
|
607
|
-
return [2 /*return*/];
|
|
608
|
-
case 15:
|
|
609
|
-
clientParams = client.options;
|
|
610
|
-
url = "".concat(clientParams.realmName).concat(result.name).concat(clientParams.suffix || '');
|
|
611
|
-
loadImage({
|
|
612
|
-
url: url,
|
|
613
|
-
val: result,
|
|
614
|
-
suffix: suffix,
|
|
615
|
-
file: postFile,
|
|
616
|
-
option: option,
|
|
617
|
-
resolve: resolve,
|
|
618
|
-
reject: reject,
|
|
619
|
-
isGif: isGif
|
|
620
|
-
});
|
|
621
|
-
return [3 /*break*/, 17];
|
|
622
|
-
case 16:
|
|
623
|
-
error_1 = _b.sent();
|
|
624
|
-
errorMsg = error_1.message || '上传异常';
|
|
625
|
-
callbacks.onError(errorMsg);
|
|
626
|
-
reject(errorMsg);
|
|
627
|
-
return [3 /*break*/, 17];
|
|
628
|
-
case 17: return [2 /*return*/];
|
|
629
|
-
}
|
|
468
|
+
// 文件大小验证
|
|
469
|
+
const imgSize = postFile.size;
|
|
470
|
+
const maxSizeMB = DEFAULT_FILE_SIZE_LIMIT;
|
|
471
|
+
if (getFileSizeInMB(imgSize) > maxSizeMB) {
|
|
472
|
+
const errorMsg = `图片不能超过${maxSizeMB}M`;
|
|
473
|
+
callbacks.onError(errorMsg);
|
|
474
|
+
reject(errorMsg);
|
|
475
|
+
return;
|
|
476
|
+
}
|
|
477
|
+
// 设置文件名(确保压缩后的文件有名称)
|
|
478
|
+
if (!postFile.name) {
|
|
479
|
+
Object.defineProperty(postFile, 'name', {
|
|
480
|
+
value: file.name,
|
|
481
|
+
writable: false
|
|
482
|
+
});
|
|
483
|
+
}
|
|
484
|
+
// 注释:根据不同场景选择不同的OSS客户端
|
|
485
|
+
// GIF -> UnProtect(8), idCard -> Private(1199), nowater/forum -> NoWater(0), 其他 -> 默认
|
|
486
|
+
const client = await this.createOssClient(businessType, option.imggeCarType);
|
|
487
|
+
// 执行上传
|
|
488
|
+
const result = await this.performOssUpload(client, fileName, postFile, year, postFile.type, callbacks.onProgress);
|
|
489
|
+
if (result.res.statusCode !== 200) {
|
|
490
|
+
callbacks.onError('上传失败');
|
|
491
|
+
reject('上传失败');
|
|
492
|
+
return;
|
|
493
|
+
}
|
|
494
|
+
// 注释:idCard场景 - 生成预签名URL
|
|
495
|
+
if (idCard && this.apiConfig.generatePrePresignedUrl) {
|
|
496
|
+
const res = await this.apiConfig.generatePrePresignedUrl({
|
|
497
|
+
objectId: result.name,
|
|
498
|
+
expireMils: PRESIGNED_URL_EXPIRE_TIME
|
|
499
|
+
});
|
|
500
|
+
if (res.data.code === 0) {
|
|
501
|
+
this.loadImageNew({
|
|
502
|
+
url: res.data.data,
|
|
503
|
+
val: result,
|
|
504
|
+
file: postFile,
|
|
505
|
+
option,
|
|
506
|
+
resolve,
|
|
507
|
+
reject
|
|
508
|
+
});
|
|
509
|
+
}
|
|
510
|
+
else {
|
|
511
|
+
callbacks.onError('生成预签名URL失败');
|
|
512
|
+
reject('生成预签名URL失败');
|
|
513
|
+
}
|
|
514
|
+
return;
|
|
515
|
+
}
|
|
516
|
+
// 注释:avatar场景 - 调用aliyunPersist处理
|
|
517
|
+
if (imageType === 'avatar' && this.apiConfig.aliyunPersist) {
|
|
518
|
+
const res = await this.apiConfig.aliyunPersist({
|
|
519
|
+
object: `${result.bucket}://${result.name}`,
|
|
520
|
+
businessType: BusinessType.AVATAR
|
|
521
|
+
});
|
|
522
|
+
if (res.data.code === 0) {
|
|
523
|
+
this.loadImageNew({
|
|
524
|
+
url: res.data.data,
|
|
525
|
+
val: result,
|
|
526
|
+
file: postFile,
|
|
527
|
+
option,
|
|
528
|
+
resolve,
|
|
529
|
+
reject
|
|
630
530
|
});
|
|
631
|
-
}
|
|
632
|
-
|
|
531
|
+
}
|
|
532
|
+
else {
|
|
533
|
+
callbacks.onError('头像处理失败');
|
|
534
|
+
reject('头像处理失败');
|
|
535
|
+
}
|
|
536
|
+
return;
|
|
537
|
+
}
|
|
538
|
+
// 注释:标准场景 - 使用client.options中的realmName和suffix
|
|
539
|
+
const clientParams = client.options;
|
|
540
|
+
const url = `${clientParams.realmName}${result.name}${clientParams.suffix || ''}`;
|
|
541
|
+
this.loadImage({
|
|
542
|
+
url,
|
|
543
|
+
val: result,
|
|
544
|
+
suffix,
|
|
545
|
+
file: postFile,
|
|
546
|
+
option,
|
|
547
|
+
resolve,
|
|
548
|
+
reject,
|
|
549
|
+
isGif
|
|
550
|
+
});
|
|
551
|
+
}
|
|
552
|
+
catch (error) {
|
|
553
|
+
const errorMsg = error.message || '上传异常';
|
|
554
|
+
callbacks.onError(errorMsg);
|
|
555
|
+
reject(errorMsg);
|
|
556
|
+
}
|
|
633
557
|
});
|
|
634
|
-
}
|
|
558
|
+
};
|
|
635
559
|
/**
|
|
636
560
|
* 文件上传方法
|
|
637
561
|
* 支持视频、文档、APK等文件类型
|
|
638
562
|
* @param option 上传选项
|
|
639
563
|
* @returns Promise
|
|
640
564
|
*/
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
return [3 /*break*/, 6];
|
|
704
|
-
case 5:
|
|
705
|
-
error_2 = _b.sent();
|
|
706
|
-
errorMsg = error_2.message || '上传异常';
|
|
707
|
-
callbacks.onError(errorMsg);
|
|
708
|
-
reject(errorMsg);
|
|
709
|
-
return [3 /*break*/, 6];
|
|
710
|
-
case 6: return [2 /*return*/];
|
|
711
|
-
}
|
|
712
|
-
});
|
|
713
|
-
}); })];
|
|
714
|
-
});
|
|
565
|
+
ossUploadFile = async (option) => {
|
|
566
|
+
const file = option.file;
|
|
567
|
+
// 初始化回调函数
|
|
568
|
+
const callbacks = {
|
|
569
|
+
onError: option.onError || (() => { }),
|
|
570
|
+
onSuccess: option.onSuccess || (() => { }),
|
|
571
|
+
onProgress: option.onProgress || (() => { })
|
|
572
|
+
};
|
|
573
|
+
option.onError = callbacks.onError;
|
|
574
|
+
option.onSuccess = callbacks.onSuccess;
|
|
575
|
+
option.onProgress = callbacks.onProgress;
|
|
576
|
+
return new Promise(async (resolve, reject) => {
|
|
577
|
+
try {
|
|
578
|
+
// 生成文件名
|
|
579
|
+
const extensionName = `.${file.name.split('.').pop()}`;
|
|
580
|
+
const fileType = extensionName === '.apk' ? 'apk' : 'file';
|
|
581
|
+
const { year, fileName } = this.generateFileName(fileType, extensionName);
|
|
582
|
+
const isVideo = !!option.isVideo;
|
|
583
|
+
const isDocument = !!option.isDocument;
|
|
584
|
+
const isUnProtect = !!option.isUnProtect;
|
|
585
|
+
// 注释:根据不同场景选择businessType
|
|
586
|
+
// isUnProtect -> 8, isVideo -> 6, isDocument -> 6, 其他 -> 1500
|
|
587
|
+
let businessType = option.businessType;
|
|
588
|
+
if (!businessType) {
|
|
589
|
+
if (isUnProtect) {
|
|
590
|
+
businessType = BusinessType.UNPROTECT;
|
|
591
|
+
}
|
|
592
|
+
else if (isVideo || isDocument) {
|
|
593
|
+
businessType = BusinessType.VIDEO; // 视频和文档都使用6
|
|
594
|
+
}
|
|
595
|
+
else {
|
|
596
|
+
businessType = BusinessType.DEFAULT;
|
|
597
|
+
}
|
|
598
|
+
}
|
|
599
|
+
// 注释:文档上传可能需要先调用uploadConf获取配置
|
|
600
|
+
if (isDocument && this.apiConfig.uploadConf) {
|
|
601
|
+
await this.apiConfig.uploadConf(businessType);
|
|
602
|
+
}
|
|
603
|
+
const client = await this.createOssClient(businessType, option.imggeCarType);
|
|
604
|
+
// 执行上传
|
|
605
|
+
const result = await this.performOssUpload(client, fileName, file, year, file.type, callbacks.onProgress);
|
|
606
|
+
if (result.res.statusCode === 200) {
|
|
607
|
+
const clientParams = client.options;
|
|
608
|
+
const url = `${clientParams.realmName}${result.name}${clientParams.suffix || ''}`;
|
|
609
|
+
const uploadResult = {
|
|
610
|
+
...result,
|
|
611
|
+
url,
|
|
612
|
+
fileName: file.name
|
|
613
|
+
};
|
|
614
|
+
callbacks.onSuccess(uploadResult);
|
|
615
|
+
resolve(uploadResult);
|
|
616
|
+
}
|
|
617
|
+
else {
|
|
618
|
+
callbacks.onError('上传失败');
|
|
619
|
+
reject('上传失败');
|
|
620
|
+
}
|
|
621
|
+
}
|
|
622
|
+
catch (error) {
|
|
623
|
+
const errorMsg = error.message || '上传异常';
|
|
624
|
+
callbacks.onError(errorMsg);
|
|
625
|
+
reject(errorMsg);
|
|
626
|
+
}
|
|
715
627
|
});
|
|
716
|
-
}
|
|
628
|
+
};
|
|
717
629
|
/**
|
|
718
630
|
* 商品详情图片上传
|
|
719
631
|
* 注释:此方法用于商品详情页的图片上传,不压缩,使用NoWater客户端
|
|
720
632
|
* @param option 上传选项
|
|
721
633
|
* @returns Promise
|
|
722
634
|
*/
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
635
|
+
shopDetailUpdate = async (option) => {
|
|
636
|
+
const file = option.file;
|
|
637
|
+
// 初始化回调函数
|
|
638
|
+
const callbacks = {
|
|
639
|
+
onError: option.onError || (() => { }),
|
|
640
|
+
onSuccess: option.onSuccess || (() => { }),
|
|
641
|
+
onProgress: option.onProgress || (() => { })
|
|
642
|
+
};
|
|
643
|
+
option.onError = callbacks.onError;
|
|
644
|
+
option.onSuccess = callbacks.onSuccess;
|
|
645
|
+
option.onProgress = callbacks.onProgress;
|
|
646
|
+
// 文件类型验证
|
|
647
|
+
if (!isSupportedImageType(file.type)) {
|
|
648
|
+
callbacks.onError('');
|
|
649
|
+
this.apiConfig.messageWarning?.('上传失败,请上传后缀为png、gif、jpg的文件');
|
|
650
|
+
return Promise.reject('文件类型不支持');
|
|
651
|
+
}
|
|
652
|
+
return new Promise(async (resolve, reject) => {
|
|
653
|
+
try {
|
|
654
|
+
// 文件大小验证
|
|
655
|
+
if (getFileSizeInMB(file.size) > DEFAULT_FILE_SIZE_LIMIT) {
|
|
656
|
+
const errorMsg = `图片不能超过${DEFAULT_FILE_SIZE_LIMIT}M`;
|
|
657
|
+
callbacks.onError(errorMsg);
|
|
658
|
+
reject(errorMsg);
|
|
659
|
+
return;
|
|
743
660
|
}
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
url: url,
|
|
779
|
-
val: result,
|
|
780
|
-
suffix: suffix,
|
|
781
|
-
file: file,
|
|
782
|
-
option: option,
|
|
783
|
-
resolve: resolve,
|
|
784
|
-
reject: reject
|
|
785
|
-
});
|
|
786
|
-
}
|
|
787
|
-
else {
|
|
788
|
-
callbacks.onError('上传失败');
|
|
789
|
-
reject('上传失败');
|
|
790
|
-
}
|
|
791
|
-
return [3 /*break*/, 5];
|
|
792
|
-
case 4:
|
|
793
|
-
error_3 = _b.sent();
|
|
794
|
-
errorMsg = error_3.message || '上传异常';
|
|
795
|
-
callbacks.onError(errorMsg);
|
|
796
|
-
reject(errorMsg);
|
|
797
|
-
return [3 /*break*/, 5];
|
|
798
|
-
case 5: return [2 /*return*/];
|
|
799
|
-
}
|
|
800
|
-
});
|
|
801
|
-
}); })];
|
|
802
|
-
});
|
|
661
|
+
// 预加载图片(虽然不需要尺寸,但保持原有逻辑)
|
|
662
|
+
await this.imgUpload(file);
|
|
663
|
+
const imageType = option.imageType || DEFAULT_IMAGE_TYPE;
|
|
664
|
+
const suffix = SuffixEnum[imageType] || SuffixEnum.official;
|
|
665
|
+
// 生成文件名
|
|
666
|
+
const extensionName = `.${file.name.split('.').pop()}`;
|
|
667
|
+
const { year, fileName } = this.generateFileName(imageType, extensionName);
|
|
668
|
+
// 使用NoWater客户端
|
|
669
|
+
const client = await this.createOssClient(BusinessType.NO_WATER, option.imggeCarType);
|
|
670
|
+
// 执行上传
|
|
671
|
+
const result = await this.performOssUpload(client, fileName, file, year, file.type, callbacks.onProgress);
|
|
672
|
+
if (result.res.statusCode === 200) {
|
|
673
|
+
const clientParams = client.options;
|
|
674
|
+
const url = `${clientParams.realmName}${result.name}${clientParams.suffix || ''}`;
|
|
675
|
+
this.loadImage({
|
|
676
|
+
url,
|
|
677
|
+
val: result,
|
|
678
|
+
suffix,
|
|
679
|
+
file,
|
|
680
|
+
option,
|
|
681
|
+
resolve,
|
|
682
|
+
reject
|
|
683
|
+
});
|
|
684
|
+
}
|
|
685
|
+
else {
|
|
686
|
+
callbacks.onError('上传失败');
|
|
687
|
+
reject('上传失败');
|
|
688
|
+
}
|
|
689
|
+
}
|
|
690
|
+
catch (error) {
|
|
691
|
+
const errorMsg = error.message || '上传异常';
|
|
692
|
+
callbacks.onError(errorMsg);
|
|
693
|
+
reject(errorMsg);
|
|
694
|
+
}
|
|
803
695
|
});
|
|
804
|
-
}
|
|
805
|
-
// 返回上传器实例
|
|
806
|
-
return {
|
|
807
|
-
/**
|
|
808
|
-
* 图片上传
|
|
809
|
-
* @param option 上传选项
|
|
810
|
-
*/
|
|
811
|
-
ossUploadImage: ossUploadImage,
|
|
812
|
-
/**
|
|
813
|
-
* 文件上传(视频、文档、APK等)
|
|
814
|
-
* @param option 上传选项
|
|
815
|
-
*/
|
|
816
|
-
ossUploadFile: ossUploadFile,
|
|
817
|
-
/**
|
|
818
|
-
* 商品详情图片上传
|
|
819
|
-
* @param option 上传选项
|
|
820
|
-
*/
|
|
821
|
-
shopDetailUpdate: shopDetailUpdate,
|
|
822
|
-
/**
|
|
823
|
-
* 后缀枚举
|
|
824
|
-
*/
|
|
825
|
-
suffixEnum: exports.SuffixEnum,
|
|
826
|
-
/**
|
|
827
|
-
* 业务类型枚举
|
|
828
|
-
*/
|
|
829
|
-
businessType: BusinessType,
|
|
830
|
-
/**
|
|
831
|
-
* 生成随机字符串
|
|
832
|
-
* @param num 字符串长度
|
|
833
|
-
*/
|
|
834
|
-
randomString: randomString,
|
|
835
|
-
/**
|
|
836
|
-
* 创建OSS客户端(高级用法)
|
|
837
|
-
* @param businessType 业务类型
|
|
838
|
-
* @param imggeCarType 车辆图片类型
|
|
839
|
-
*/
|
|
840
|
-
createOssClient: createOssClient,
|
|
841
|
-
/**
|
|
842
|
-
* 预加载图片
|
|
843
|
-
* @param file 文件对象
|
|
844
|
-
*/
|
|
845
|
-
imgUpload: imgUpload,
|
|
846
|
-
/**
|
|
847
|
-
* 加载图片并返回结果
|
|
848
|
-
*/
|
|
849
|
-
loadImage: loadImage,
|
|
850
|
-
/**
|
|
851
|
-
* 加载图片并返回结果(新版)
|
|
852
|
-
*/
|
|
853
|
-
loadImageNew: loadImageNew
|
|
854
696
|
};
|
|
697
|
+
/**
|
|
698
|
+
* 生成随机字符串
|
|
699
|
+
* @param num 字符串长度
|
|
700
|
+
*/
|
|
701
|
+
randomString = randomString;
|
|
702
|
+
/**
|
|
703
|
+
* 后缀枚举
|
|
704
|
+
*/
|
|
705
|
+
suffixEnum = SuffixEnum;
|
|
706
|
+
/**
|
|
707
|
+
* 业务类型枚举
|
|
708
|
+
*/
|
|
709
|
+
businessType = BusinessType;
|
|
710
|
+
}
|
|
711
|
+
/**
|
|
712
|
+
* 创建阿里云OSS上传器(工厂函数)
|
|
713
|
+
* @param apiConfig API配置对象,包含业务相关的API函数
|
|
714
|
+
* @returns OSS上传器实例
|
|
715
|
+
*/
|
|
716
|
+
export function createAliOssUploader(apiConfig) {
|
|
717
|
+
return new AliOssClass(apiConfig);
|
|
855
718
|
}
|
|
856
|
-
exports.createAliOssUploader = createAliOssUploader;
|
|
857
719
|
/**
|
|
858
720
|
* 默认导出
|
|
859
721
|
*/
|
|
860
|
-
|
|
861
|
-
createAliOssUploader
|
|
862
|
-
BusinessType
|
|
863
|
-
SuffixEnum
|
|
722
|
+
export default {
|
|
723
|
+
createAliOssUploader,
|
|
724
|
+
BusinessType,
|
|
725
|
+
SuffixEnum
|
|
864
726
|
};
|