fhrons-mobile-next 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/fhcommon.min.js +2 -0
- package/dist/fhcommon.min.js.LICENSE.txt +1 -0
- package/fhrons-mobile-next-2.0.0.tgz +0 -0
- package/index.js +33 -0
- package/package.json +40 -0
- package/packages/fhImage/index.js +5 -0
- package/packages/fhImage/index.vue +57 -0
- package/packages/fhPresetImage/index.js +5 -0
- package/packages/fhPresetImage/index.vue +39 -0
- package/packages/html2canvas/index.js +29 -0
- package/packages/index.js +3 -0
- package/packages/storage.js +179 -0
- package/upload copy.js +468 -0
- package/upload.js +518 -0
- package/utils/tools.js +22 -0
package/upload.js
ADDED
|
@@ -0,0 +1,518 @@
|
|
|
1
|
+
// cdn引入axios
|
|
2
|
+
if (!window.axios) {
|
|
3
|
+
loadJavaScript(
|
|
4
|
+
"https://scrm-pro-1251973116.file.myqcloud.com/funzg/form/axios.js",
|
|
5
|
+
() => {
|
|
6
|
+
console.log("axios 加载成功");
|
|
7
|
+
}
|
|
8
|
+
);
|
|
9
|
+
}
|
|
10
|
+
// if (!window.AWS) {
|
|
11
|
+
// loadJavaScript('https://dop-pro-1251973116.file.myqcloud.com/upload/jsfile/funzg/aws-sdk-2.1562.0.min.js', () => {
|
|
12
|
+
// console.log('aws-sdk 加载成功');
|
|
13
|
+
// });
|
|
14
|
+
// }
|
|
15
|
+
if (!window.COS) {
|
|
16
|
+
loadJavaScript(
|
|
17
|
+
"https://dop-pro-1251973116.file.myqcloud.com/upload/jsfile/funzg/cos-js-sdk-v5.min.js",
|
|
18
|
+
() => {
|
|
19
|
+
console.log("腾讯cos 加载成功");
|
|
20
|
+
}
|
|
21
|
+
);
|
|
22
|
+
}
|
|
23
|
+
if (!window.lrz) {
|
|
24
|
+
loadJavaScript(
|
|
25
|
+
"https://dop-pro-1251973116.file.myqcloud.com/upload/jsfile/funzg/lrz.all.bundle.min.js",
|
|
26
|
+
() => {
|
|
27
|
+
console.log("lrz加载成功");
|
|
28
|
+
}
|
|
29
|
+
);
|
|
30
|
+
}
|
|
31
|
+
if (!window.FHENCYPT) {
|
|
32
|
+
loadJavaScript(
|
|
33
|
+
"https://dop-pro-1251973116.file.myqcloud.com/upload/jsfile/funzg/fhEncypt.js",
|
|
34
|
+
() => {
|
|
35
|
+
console.log("FHENCYPT加载成功");
|
|
36
|
+
}
|
|
37
|
+
);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
// const Minio = require('./utils/minio/internal/client.js')
|
|
41
|
+
// import * as Minio from 'minio'
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* 第一个参数的可选属性
|
|
45
|
+
* @param {Blob} file 要上传的文件
|
|
46
|
+
* @param {String} target 要上传的目标云,类型:0大陆环境/1港险环境
|
|
47
|
+
* @param {String} project 所属项目:0全局,1课程,2开放平台,4:scrm 5:营销 6:frcdap
|
|
48
|
+
* @param {Function} keyFunc 生成key的方法
|
|
49
|
+
* @param {Boolean} needWholeRes 是否需要返回完整的响应体
|
|
50
|
+
* @param {Number} urlMaxLength url 的长度限制
|
|
51
|
+
*
|
|
52
|
+
* 第二个参数
|
|
53
|
+
* @param {Function} onProgress 接收上传进度的回调
|
|
54
|
+
* @returns Link 上传完成后的图片链接
|
|
55
|
+
*
|
|
56
|
+
* 例:
|
|
57
|
+
* const param = {
|
|
58
|
+
* file, target = 'tencent', project = '0', keyFunc
|
|
59
|
+
* }
|
|
60
|
+
* upload(param,(percent)=>{
|
|
61
|
+
* console.log(percent) // 输出上传进度的百分比
|
|
62
|
+
* })
|
|
63
|
+
*/
|
|
64
|
+
// 将函数提取到外部,避免重复定义
|
|
65
|
+
function getFullFileName(file) {
|
|
66
|
+
// 优先使用 File 对象的 name 属性
|
|
67
|
+
const fileName = file.name || file.filename || "";
|
|
68
|
+
|
|
69
|
+
// 如果已有后缀名(包含点号),直接返回
|
|
70
|
+
if (fileName.includes(".")) {
|
|
71
|
+
return fileName;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
// 没有后缀名,从 type 中提取
|
|
75
|
+
if (file.type && file.type.includes("/")) {
|
|
76
|
+
let extension = file.type.split("/")[1]; // 从"image/jpeg"提取"jpeg"
|
|
77
|
+
|
|
78
|
+
// 特殊情况处理
|
|
79
|
+
if (extension === "jpeg") {
|
|
80
|
+
extension = "jpg";
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
// 清理扩展名中的参数(如 "svg+xml")
|
|
84
|
+
extension = extension.split("+")[0];
|
|
85
|
+
|
|
86
|
+
return `${fileName}.${extension}`;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
// 如果连 type 都没有,返回原文件名
|
|
90
|
+
return fileName;
|
|
91
|
+
}
|
|
92
|
+
const contentTypeMap = {
|
|
93
|
+
// 图片
|
|
94
|
+
jpg: "image/*",
|
|
95
|
+
jpeg: "image/*",
|
|
96
|
+
png: "image/*",
|
|
97
|
+
gif: "image/*",
|
|
98
|
+
bmp: "image/*",
|
|
99
|
+
webp: "image/*",
|
|
100
|
+
svg: "image/*",
|
|
101
|
+
ico: "image/*",
|
|
102
|
+
// 视频
|
|
103
|
+
mp4: "video/*",
|
|
104
|
+
avi: "video/*",
|
|
105
|
+
mov: "video/*",
|
|
106
|
+
wmv: "video/*",
|
|
107
|
+
flv: "video/*",
|
|
108
|
+
mkv: "video/*",
|
|
109
|
+
webm: "video/*",
|
|
110
|
+
// 音频
|
|
111
|
+
mp3: "audio/*",
|
|
112
|
+
wav: "audio/*",
|
|
113
|
+
aac: "audio/*",
|
|
114
|
+
ogg: "audio/*",
|
|
115
|
+
m4a: "audio/*",
|
|
116
|
+
flac: "audio/*",
|
|
117
|
+
// PDF
|
|
118
|
+
pdf: "application/pdf",
|
|
119
|
+
// Office
|
|
120
|
+
doc: "application/*",
|
|
121
|
+
docx: "application/*",
|
|
122
|
+
xls: "application/*",
|
|
123
|
+
xlsx: "application/*",
|
|
124
|
+
ppt: "application/*",
|
|
125
|
+
pptx: "application/*",
|
|
126
|
+
// 文本
|
|
127
|
+
txt: "text/*",
|
|
128
|
+
csv: "text/*",
|
|
129
|
+
// 压缩文件
|
|
130
|
+
zip: "application/*",
|
|
131
|
+
rar: "application/*",
|
|
132
|
+
"7z": "application/*",
|
|
133
|
+
tar: "application/*",
|
|
134
|
+
gz: "application/*",
|
|
135
|
+
};
|
|
136
|
+
|
|
137
|
+
function getContentTypeByExtension(ext) {
|
|
138
|
+
console.log("getContentTypeByExtension ext", ext);
|
|
139
|
+
|
|
140
|
+
if (!ext || typeof ext !== "string") return null;
|
|
141
|
+
return contentTypeMap[ext.toLowerCase()] || null;
|
|
142
|
+
}
|
|
143
|
+
export function upload(
|
|
144
|
+
{ file, target, project = "0", keyFunc, needWholeRes },
|
|
145
|
+
onProgress
|
|
146
|
+
) {
|
|
147
|
+
let defaultTarget =
|
|
148
|
+
location.origin.includes("https://smnguat.fhrons.net") ||
|
|
149
|
+
location.origin.includes("https://openuat.fhrons.net") ||
|
|
150
|
+
location.origin.includes("https://smng.avantech.io") ||
|
|
151
|
+
location.origin.includes("https://open.avantech.io") ||
|
|
152
|
+
(process.env.VUE_APP_ENV_CONFIG &&
|
|
153
|
+
process.env.VUE_APP_ENV_CONFIG.includes("hk"))
|
|
154
|
+
? "1"
|
|
155
|
+
: "0";
|
|
156
|
+
defaultTarget =
|
|
157
|
+
process.env.VUE_APP_ENV_CONFIG &&
|
|
158
|
+
process.env.VUE_APP_ENV_CONFIG.includes("poc")
|
|
159
|
+
? "2"
|
|
160
|
+
: defaultTarget;
|
|
161
|
+
target = target ? (target === "tencent" ? "0" : "1") : defaultTarget;
|
|
162
|
+
if (!file) {
|
|
163
|
+
console.error("上传的文件不能为空");
|
|
164
|
+
return;
|
|
165
|
+
}
|
|
166
|
+
if (file.raw) file = file.raw; // 有的file对象里面的raw才是实际的文件内容
|
|
167
|
+
if (file.file) file = file.file; // vant文件选择器选到的文件里还有一层file
|
|
168
|
+
// target = target === 'tencent' ? '0' : '1'; // 根据传进来的target转换
|
|
169
|
+
// target = '2'
|
|
170
|
+
const filename = getFullFileName(file);
|
|
171
|
+
const temp = filename.split(".");
|
|
172
|
+
const fileSffix = temp[temp.length - 1];
|
|
173
|
+
const appName = process.env.VUE_APP_NAME || "common";
|
|
174
|
+
if (
|
|
175
|
+
typeof keyFunc !== "function" ||
|
|
176
|
+
(typeof keyFunc === "function" && !keyFunc())
|
|
177
|
+
)
|
|
178
|
+
keyFunc = () =>
|
|
179
|
+
`/${appName}/${new Date().valueOf()}_${temp[0]}${
|
|
180
|
+
fileSffix ? "." + fileSffix : ""
|
|
181
|
+
}`;
|
|
182
|
+
|
|
183
|
+
let newKey = keyFunc();
|
|
184
|
+
newKey = removeLeadingSlash(newKey);
|
|
185
|
+
console.log("newKey", newKey);
|
|
186
|
+
|
|
187
|
+
// if(urlMaxLength && newKey.length > urlMaxLength) return Promise.reject(`文件名长度过长,请保持在${urlMaxLength}以下`)
|
|
188
|
+
return axios
|
|
189
|
+
.post(
|
|
190
|
+
`/funapi/cbsconfig/oss/secureSign`,
|
|
191
|
+
{
|
|
192
|
+
type: target,
|
|
193
|
+
project: project,
|
|
194
|
+
filePath: newKey,
|
|
195
|
+
},
|
|
196
|
+
{ headers: { "Content-Type": "application/json" } }
|
|
197
|
+
)
|
|
198
|
+
.then((res) => {
|
|
199
|
+
if (
|
|
200
|
+
target !== "2" &&
|
|
201
|
+
(typeof res.data === "string" || typeof res === "string")
|
|
202
|
+
)
|
|
203
|
+
res = JSON.parse(FHENCYPT.decrypt(res.data || res));
|
|
204
|
+
console.log("res", JSON.stringify(res));
|
|
205
|
+
|
|
206
|
+
const {
|
|
207
|
+
tmpSecretId,
|
|
208
|
+
tmpSecretKey,
|
|
209
|
+
token,
|
|
210
|
+
sessionToken,
|
|
211
|
+
startTime,
|
|
212
|
+
expiredTime,
|
|
213
|
+
requestId,
|
|
214
|
+
type,
|
|
215
|
+
bucketName,
|
|
216
|
+
region,
|
|
217
|
+
cdnUrl,
|
|
218
|
+
status = "SUCCESS",
|
|
219
|
+
message = "",
|
|
220
|
+
} = res.data || res;
|
|
221
|
+
if (status !== "SUCCESS") {
|
|
222
|
+
throw new Error(message);
|
|
223
|
+
}
|
|
224
|
+
/**
|
|
225
|
+
* @tmpSecretId 临时访问密钥的标识符。
|
|
226
|
+
* @tmpSecretKey 临时访问密钥的密钥。
|
|
227
|
+
* @type 0腾讯/1亚马逊/2 minio 字符串格式
|
|
228
|
+
* @startTime 腾讯使用的字段,开始时间
|
|
229
|
+
* @expiredTime 腾讯使用的字段,过期时间
|
|
230
|
+
* @bucketName 存储桶名称
|
|
231
|
+
* @cdnUrl cdn链接的前缀
|
|
232
|
+
* @region 存储区域
|
|
233
|
+
*/
|
|
234
|
+
// if (type === '1') { // 亚马逊
|
|
235
|
+
// AWS.config.update({
|
|
236
|
+
// accessKeyId: tmpSecretId,
|
|
237
|
+
// secretAccessKey: tmpSecretKey,
|
|
238
|
+
// region: region,
|
|
239
|
+
// sessionToken: token
|
|
240
|
+
// });
|
|
241
|
+
// const s3 = new AWS.S3();
|
|
242
|
+
// const params = {
|
|
243
|
+
// Bucket: bucketName,
|
|
244
|
+
// Key: newKey,
|
|
245
|
+
// ContentType: type,
|
|
246
|
+
// Body: file,
|
|
247
|
+
// 'Access-Control-Allow-Credentials': '*'
|
|
248
|
+
// };
|
|
249
|
+
// const upload = s3.upload(params);
|
|
250
|
+
// upload.on('httpUploadProgress', (progress) => {
|
|
251
|
+
// const { loaded, total } = progress;
|
|
252
|
+
// /* 非必须 */
|
|
253
|
+
// const percent = Math.round(parseInt(loaded / total) * 100);
|
|
254
|
+
// if (typeof onProgress === 'function') onProgress(percent);
|
|
255
|
+
// });
|
|
256
|
+
// const uploadPromise = upload.promise();
|
|
257
|
+
// return uploadPromise.then(res => {
|
|
258
|
+
// const { key, Key } = res;
|
|
259
|
+
// console.log(res);
|
|
260
|
+
// // const tempUrl = (key.startsWith('/') ? '' : '/');
|
|
261
|
+
// const fileUrl = `${cdnUrl}${cdnUrl.endsWith('/') ? '' : '/'}${key || Key}`
|
|
262
|
+
// if (needWholeRes) {
|
|
263
|
+
// return {
|
|
264
|
+
// ...res,
|
|
265
|
+
// fileUrl
|
|
266
|
+
// };
|
|
267
|
+
// } return fileUrl;
|
|
268
|
+
// }).catch(err => {
|
|
269
|
+
// console.log(err);
|
|
270
|
+
// }).finally(_ => {
|
|
271
|
+
// });
|
|
272
|
+
// } else
|
|
273
|
+
// if (type === '2') { // 如果type=2 则使用minIO上传
|
|
274
|
+
// console.log(Minio)
|
|
275
|
+
// const minioClient = new Minio.Client({
|
|
276
|
+
// endPoint: 'poc.fhrons.com',
|
|
277
|
+
// // port: 31003,
|
|
278
|
+
// useSSL: true,
|
|
279
|
+
// accessKey: tmpSecretId,
|
|
280
|
+
// secretKey: tmpSecretKey,
|
|
281
|
+
// sessionToken: token
|
|
282
|
+
// })
|
|
283
|
+
// return uploadFileToMinio(file, minioClient, bucketName, newKey, cdnUrl, needWholeRes).then(res => {
|
|
284
|
+
// if (typeof onProgress === 'function') onProgress(100)
|
|
285
|
+
// console.log('上传成功,', res)
|
|
286
|
+
// return res
|
|
287
|
+
// }).catch(err => {
|
|
288
|
+
// console.log(err);
|
|
289
|
+
// })
|
|
290
|
+
|
|
291
|
+
// }
|
|
292
|
+
// 腾讯 如果没有type 则默认使用腾讯上传
|
|
293
|
+
const cos = new COS({
|
|
294
|
+
getAuthorization: function (options, callback) {
|
|
295
|
+
callback({
|
|
296
|
+
TmpSecretId: tmpSecretId,
|
|
297
|
+
TmpSecretKey: tmpSecretKey,
|
|
298
|
+
XCosSecurityToken: sessionToken,
|
|
299
|
+
StartTime: startTime,
|
|
300
|
+
ExpiredTime: expiredTime,
|
|
301
|
+
requestId: requestId,
|
|
302
|
+
SecurityToken: token,
|
|
303
|
+
});
|
|
304
|
+
},
|
|
305
|
+
});
|
|
306
|
+
// 在 cos.putObject().catch() 中抛出错误
|
|
307
|
+
return cos
|
|
308
|
+
.putObject({
|
|
309
|
+
Bucket: bucketName,
|
|
310
|
+
Region: region,
|
|
311
|
+
Key: newKey,
|
|
312
|
+
StorageClass: "STANDARD",
|
|
313
|
+
Body: file,
|
|
314
|
+
Headers: {
|
|
315
|
+
"x-cos-meta-test": "123",
|
|
316
|
+
"Cache-control": "no-cache",
|
|
317
|
+
"Content-Type": getContentTypeByExtension(fileSffix),
|
|
318
|
+
},
|
|
319
|
+
onProgress: (progressData) => {
|
|
320
|
+
const percent = Math.round(progressData.percent * 100);
|
|
321
|
+
if (typeof onProgress === "function") onProgress(percent);
|
|
322
|
+
},
|
|
323
|
+
})
|
|
324
|
+
.then((data) => {
|
|
325
|
+
console.log("cos", data);
|
|
326
|
+
let fileUrl = "";
|
|
327
|
+
if (data.statusCode == 200) {
|
|
328
|
+
fileUrl = `${cdnUrl}/${newKey}`;
|
|
329
|
+
return fileUrl; // ✅ 成功时返回 url
|
|
330
|
+
} else {
|
|
331
|
+
// ❌ 状态码不是 200,抛出错误
|
|
332
|
+
throw new Error(`上传失败,状态码: ${data.statusCode}`);
|
|
333
|
+
}
|
|
334
|
+
})
|
|
335
|
+
.catch((err) => {
|
|
336
|
+
console.log("COS 上传错误:", err);
|
|
337
|
+
// ✅ 抛出错误,让调用方 catch 能捕获
|
|
338
|
+
throw err; // 或者 return Promise.reject(err);
|
|
339
|
+
});
|
|
340
|
+
});
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
function uploadFileToMinio(
|
|
344
|
+
file,
|
|
345
|
+
minioClient,
|
|
346
|
+
bucketName,
|
|
347
|
+
newKey,
|
|
348
|
+
cdnUrl,
|
|
349
|
+
needWholeRes
|
|
350
|
+
) {
|
|
351
|
+
return new Promise((resolve, reject) => {
|
|
352
|
+
const reader = new FileReader();
|
|
353
|
+
reader.onload = function (e) {
|
|
354
|
+
try {
|
|
355
|
+
const buffer = Buffer.from(e.target.result);
|
|
356
|
+
minioClient.putObject(bucketName, newKey, buffer, function (err, etag) {
|
|
357
|
+
if (err) {
|
|
358
|
+
console.log(err);
|
|
359
|
+
return err;
|
|
360
|
+
}
|
|
361
|
+
console.log(etag);
|
|
362
|
+
const fileUrl = `${cdnUrl}${
|
|
363
|
+
cdnUrl.endsWith("/") ? "" : "/"
|
|
364
|
+
}${newKey}`;
|
|
365
|
+
if (needWholeRes) {
|
|
366
|
+
resolve({
|
|
367
|
+
etag,
|
|
368
|
+
fileUrl,
|
|
369
|
+
});
|
|
370
|
+
}
|
|
371
|
+
resolve(fileUrl);
|
|
372
|
+
});
|
|
373
|
+
} catch (err) {
|
|
374
|
+
reject(err);
|
|
375
|
+
}
|
|
376
|
+
};
|
|
377
|
+
reader.onerror = function (err) {
|
|
378
|
+
reject(err);
|
|
379
|
+
};
|
|
380
|
+
reader.readAsArrayBuffer(file);
|
|
381
|
+
});
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
/**
|
|
385
|
+
* @param {Blob} file 上传的图片文件
|
|
386
|
+
* @param {Number} quality 压缩质量
|
|
387
|
+
* @returns 返回压缩后的图片文件
|
|
388
|
+
*/
|
|
389
|
+
// 压缩文件
|
|
390
|
+
export async function compressFile(file, quality = 0.7) {
|
|
391
|
+
file = file.raw ? file.raw : file;
|
|
392
|
+
// const imageCompressor = new Compressor();
|
|
393
|
+
try {
|
|
394
|
+
let reFile = "";
|
|
395
|
+
const rst = await lrz(file, {
|
|
396
|
+
quality: quality, // 图片压缩质量,取值0-1,默认为0.7
|
|
397
|
+
});
|
|
398
|
+
// const rst = new Compressor(file);
|
|
399
|
+
reFile = new File([rst.file], file.name, {
|
|
400
|
+
type: "image/jpeg",
|
|
401
|
+
lastModified: Date.now(),
|
|
402
|
+
});
|
|
403
|
+
return reFile;
|
|
404
|
+
} catch (error) {
|
|
405
|
+
return "";
|
|
406
|
+
}
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
/**
|
|
410
|
+
* @param {Blob} file 上传的图片文件
|
|
411
|
+
* @param {Number} size 指定压缩后的图片大小
|
|
412
|
+
* @param {Number} quality 压缩质量
|
|
413
|
+
* @returns 返回压缩后的图片文件
|
|
414
|
+
*/
|
|
415
|
+
// 循环压缩
|
|
416
|
+
export async function loopCompressFile(file, size, quality) {
|
|
417
|
+
if (!size) {
|
|
418
|
+
return new Error("size 不能为空");
|
|
419
|
+
}
|
|
420
|
+
// let reFile = file;
|
|
421
|
+
const reFile = await compressFile(file, quality);
|
|
422
|
+
if (reFile.size > size) {
|
|
423
|
+
compressFile(reFile, quality);
|
|
424
|
+
}
|
|
425
|
+
return reFile;
|
|
426
|
+
}
|
|
427
|
+
|
|
428
|
+
// 判断html文档中是否有重复引用的标签
|
|
429
|
+
/**
|
|
430
|
+
* @param {String} src 要检查的引用地址
|
|
431
|
+
*/
|
|
432
|
+
function chectDuplicateScript(src) {
|
|
433
|
+
let result = false;
|
|
434
|
+
// 获取文档中所有的script标签
|
|
435
|
+
const scriptTags = document.getElementsByTagName("script");
|
|
436
|
+
// 创建一个存储已经出现过的URL集合
|
|
437
|
+
const scriptURLs = new Set();
|
|
438
|
+
// 遍历所有的tag 标签
|
|
439
|
+
for (let i = 0; i < scriptTags.length; i++) {
|
|
440
|
+
const currentSrc = scriptTags[i].getAttribute("src");
|
|
441
|
+
if (currentSrc && currentSrc === src) {
|
|
442
|
+
if (scriptURLs.has(currentSrc)) {
|
|
443
|
+
// console.log('重复引用,引用地址为', currentSrc);
|
|
444
|
+
result = true;
|
|
445
|
+
} else {
|
|
446
|
+
scriptURLs.add(currentSrc);
|
|
447
|
+
}
|
|
448
|
+
}
|
|
449
|
+
}
|
|
450
|
+
if (scriptURLs.size === 0) {
|
|
451
|
+
result = false;
|
|
452
|
+
// console.log('没有重复引用', src);
|
|
453
|
+
}
|
|
454
|
+
return result;
|
|
455
|
+
}
|
|
456
|
+
// 动态引入JS文件
|
|
457
|
+
export function loadJavaScript(src, callback) {
|
|
458
|
+
if (chectDuplicateScript(src)) return;
|
|
459
|
+
const script = document.createElement("script");
|
|
460
|
+
const head = document.getElementsByTagName("head")[0];
|
|
461
|
+
script.type = "text/javascript";
|
|
462
|
+
script.charset = "UTF-8";
|
|
463
|
+
script.src = src;
|
|
464
|
+
window.onerror = () => {
|
|
465
|
+
console.log(`loadJavaScript加载${src}失败`);
|
|
466
|
+
};
|
|
467
|
+
if (script.addEventListener) {
|
|
468
|
+
script.addEventListener(
|
|
469
|
+
"load",
|
|
470
|
+
function () {
|
|
471
|
+
callback();
|
|
472
|
+
},
|
|
473
|
+
false
|
|
474
|
+
);
|
|
475
|
+
} else if (script.attachEvent) {
|
|
476
|
+
script.attachEvent("onreadystatechange", function () {
|
|
477
|
+
const target = window.event.srcElement;
|
|
478
|
+
if (target.readyState === "loaded" || script.readState === "complate") {
|
|
479
|
+
callback();
|
|
480
|
+
}
|
|
481
|
+
});
|
|
482
|
+
}
|
|
483
|
+
script.addEventListener("error", (e) => {
|
|
484
|
+
if (!isEmpty(e)) {
|
|
485
|
+
callback("err");
|
|
486
|
+
}
|
|
487
|
+
});
|
|
488
|
+
if (src) {
|
|
489
|
+
// 如果src不存在,不加入到项目里面去,否则会报加载资源失败
|
|
490
|
+
head.appendChild(script);
|
|
491
|
+
}
|
|
492
|
+
}
|
|
493
|
+
/**
|
|
494
|
+
* 为空
|
|
495
|
+
* @param val
|
|
496
|
+
* @returns {boolean}
|
|
497
|
+
*/
|
|
498
|
+
function isEmpty(val) {
|
|
499
|
+
if (
|
|
500
|
+
val === null ||
|
|
501
|
+
val === undefined ||
|
|
502
|
+
(typeof val === "string" &&
|
|
503
|
+
(val === "" || val === "undefined" || val === "null")) ||
|
|
504
|
+
(Array.isArray(val) && val.length === 0) ||
|
|
505
|
+
(Object.prototype.toString.call(val) === "[object Object]" &&
|
|
506
|
+
Object.keys(val).length === 0)
|
|
507
|
+
) {
|
|
508
|
+
return true;
|
|
509
|
+
}
|
|
510
|
+
return false;
|
|
511
|
+
}
|
|
512
|
+
|
|
513
|
+
function removeLeadingSlash(str) {
|
|
514
|
+
if (str.startsWith("/")) {
|
|
515
|
+
return str.substring(1); // 返回去掉斜杠后的值
|
|
516
|
+
}
|
|
517
|
+
return str; // 如果字符串不以斜杠开头,则返回原始字符串
|
|
518
|
+
}
|
package/utils/tools.js
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
// base64转Blob 2
|
|
2
|
+
export function base64ToBlob (urlData, type) {
|
|
3
|
+
const arr = urlData.split(',');
|
|
4
|
+
if (arr.length > 1) {
|
|
5
|
+
const temp = arr[0].match(/:(.*?);/);
|
|
6
|
+
const mime = temp && temp.length > 1 ? (temp[1] || type) : type;
|
|
7
|
+
// 去掉url的头,并转化为byte
|
|
8
|
+
const bytes = window.atob(arr[1]);
|
|
9
|
+
// 处理异常,将ascii码小于0的转换为大于0
|
|
10
|
+
const ab = new ArrayBuffer(bytes.length);
|
|
11
|
+
// 生成视图(直接针对内存):8位无符号整数,长度1个字节
|
|
12
|
+
const ia = new Uint8Array(ab);
|
|
13
|
+
for (let i = 0; i < bytes.length; i++) {
|
|
14
|
+
ia[i] = bytes.charCodeAt(i);
|
|
15
|
+
}
|
|
16
|
+
const blob = new Blob([ab], {
|
|
17
|
+
type: mime
|
|
18
|
+
})
|
|
19
|
+
return new File([blob], `poster_${new Date().valueOf()}.png`, { type: mime });
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
|