emacroh5lib 1.0.88 → 1.0.89
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/.eslintrc.js +1 -2
- package/dist/emacroh5lib.min.js +1 -1
- package/package.json +1 -1
- package/src/utilities/EMacro.ts +263 -254
package/package.json
CHANGED
package/src/utilities/EMacro.ts
CHANGED
@@ -10,307 +10,316 @@ import createTaskQueue from 'sync-task-queue'
|
|
10
10
|
|
11
11
|
import { saveAs } from 'file-saver';
|
12
12
|
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
});
|
35
|
-
}
|
13
|
+
const version = "1.73"
|
14
|
+
|
15
|
+
class File {
|
16
|
+
|
17
|
+
public static getFileMD5(file) {
|
18
|
+
return new Promise((resolve, reject) => {
|
19
|
+
|
20
|
+
const fileReader = new FileReader()
|
21
|
+
fileReader.readAsBinaryString(file);
|
22
|
+
fileReader.onload = e => {
|
23
|
+
const bmf = new BMF();
|
24
|
+
bmf.md5(file, (err, md5) => {
|
25
|
+
if (err !== null) {
|
26
|
+
resolve(err)
|
27
|
+
} else {
|
28
|
+
reject(md5)
|
29
|
+
}
|
30
|
+
}, progress => {
|
31
|
+
console.log('getFileMD5 progress number:', progress);
|
32
|
+
});
|
33
|
+
}
|
36
34
|
|
37
|
-
|
38
|
-
|
35
|
+
})
|
36
|
+
}
|
39
37
|
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
38
|
+
private static getBase64(blob) {
|
39
|
+
return new Promise((resolve, reject) => {
|
40
|
+
const reader = new FileReader();
|
41
|
+
reader.readAsDataURL(blob);
|
42
|
+
reader.onload = () => resolve(reader.result);
|
43
|
+
reader.onerror = error => reject(error);
|
44
|
+
});
|
45
|
+
}
|
48
46
|
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
}
|
61
|
-
} else {
|
62
|
-
fileChunks.push(file)
|
63
|
-
}
|
64
|
-
return {
|
65
|
-
fileChunks: fileChunks,
|
66
|
-
sliceSize: chunkSize,
|
67
|
-
chunksLength: fileChunks.length
|
47
|
+
public static getFileChunks(file: any, chunkSize: number = 1024 * 1024 * 1): any {
|
48
|
+
|
49
|
+
let { size } = file
|
50
|
+
let totalChunks = Math.ceil(size / chunkSize)
|
51
|
+
let fileChunks = new Array<any>()
|
52
|
+
if (size > chunkSize) {
|
53
|
+
for (let i = 0; i < totalChunks; i++) {
|
54
|
+
let start = i * chunkSize
|
55
|
+
let end = (i + 1) * chunkSize
|
56
|
+
let chunk = file.slice(start, end)
|
57
|
+
fileChunks.push(chunk)
|
68
58
|
}
|
59
|
+
} else {
|
60
|
+
fileChunks.push(file)
|
61
|
+
}
|
62
|
+
return {
|
63
|
+
fileChunks: fileChunks,
|
64
|
+
sliceSize: chunkSize,
|
65
|
+
chunksLength: fileChunks.length
|
69
66
|
}
|
67
|
+
}
|
70
68
|
|
71
|
-
|
72
|
-
|
69
|
+
// 文件上传
|
70
|
+
public static async uploadFiles(files, chunkFileHandle, fileComplete = (file) => { }, completeHandle = (files) => { }, chunkSize: number = 1024 * 1024 * 1) {
|
73
71
|
|
74
|
-
|
75
|
-
|
76
|
-
|
72
|
+
if (files[0].fileName == "" || files[0].fileSize == "" || files[0].fileSize == 0) {
|
73
|
+
throw new Error("文件异常")
|
74
|
+
}
|
77
75
|
|
78
|
-
|
79
|
-
|
80
|
-
|
76
|
+
for (let i = 0; i < files.length; i++) {
|
77
|
+
const file = files[i];
|
78
|
+
const md5 = await File.getFileMD5(file)
|
81
79
|
|
82
|
-
|
80
|
+
let { fileChunks, sliceSize, chunksLength } = File.getFileChunks(file, chunkSize)
|
83
81
|
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
82
|
+
let directoryName = "";
|
83
|
+
if (files[i].webkitRelativePath != null && files[i].webkitRelativePath.trim() != "") {
|
84
|
+
let n = files[i].webkitRelativePath.lastIndexOf("\\")
|
85
|
+
if (n == -1)
|
86
|
+
n = files[i].webkitRelativePath.lastIndexOf("/")
|
87
|
+
if (n != -1)
|
88
|
+
directoryName = files[i].webkitRelativePath.substring(0, n)
|
89
|
+
}
|
92
90
|
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
}
|
111
|
-
await chunkFileHandle(chunkFile)
|
91
|
+
for (let index in fileChunks) {
|
92
|
+
let chunk = fileChunks[Number(index)]
|
93
|
+
const base64 = await File.getBase64(chunk) as string
|
94
|
+
let chunkFile = {
|
95
|
+
chunkIndex: Number(index), // 分片位置
|
96
|
+
chunksLength: chunksLength, // 分片长度
|
97
|
+
sliceSize: sliceSize, // 分片大小
|
98
|
+
chunkSize: chunk.size, // 当前分片实际大小
|
99
|
+
fileSize: file.size, // 文件总大小
|
100
|
+
fileName: file.name, // 文件名
|
101
|
+
lastModifiedDate: file.lastModifiedDate, // 最后修改时间
|
102
|
+
md5: md5,
|
103
|
+
index: i,
|
104
|
+
dataType: 'base64', // 数据的类型
|
105
|
+
directoryName: directoryName, // 数据的类型
|
106
|
+
total: files.length, // 总共文件数
|
107
|
+
data: base64.split(';base64,')[1], // 文件数据
|
112
108
|
}
|
113
|
-
|
109
|
+
await chunkFileHandle(chunkFile)
|
114
110
|
}
|
115
|
-
|
111
|
+
fileComplete(file);
|
116
112
|
}
|
113
|
+
completeHandle(files)
|
114
|
+
}
|
117
115
|
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
}
|
132
|
-
} catch (error) {
|
133
|
-
reject(error)
|
116
|
+
public static selectFile(options: any = { multiple: true, accept: "*/*" }, isDirectory = false): Promise<FileList | null> {
|
117
|
+
return new Promise((resolve: (value: FileList) => void, reject) => {
|
118
|
+
const el = document.createElement("input");
|
119
|
+
el.type = "file";
|
120
|
+
el.accept = options.accept;
|
121
|
+
el.webkitdirectory = isDirectory;
|
122
|
+
el.multiple = options.multiple;
|
123
|
+
el.addEventListener("change", (_) => {
|
124
|
+
try {
|
125
|
+
if (!el.files) {
|
126
|
+
reject(new Error("无法读取文件"));
|
127
|
+
} else {
|
128
|
+
resolve(el.files);
|
134
129
|
}
|
135
|
-
})
|
136
|
-
|
130
|
+
} catch (error) {
|
131
|
+
reject(error)
|
132
|
+
}
|
137
133
|
});
|
138
|
-
|
134
|
+
el.click();
|
135
|
+
});
|
136
|
+
}
|
139
137
|
|
140
|
-
|
138
|
+
public static readLocalExcel(onloadend: (file, workbook) => void, options: any = { multiple: true, accept: "*/*" }) {
|
141
139
|
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
}
|
140
|
+
this.selectFile(options).then((files: FileList | null) => {
|
141
|
+
if (files === null) {
|
142
|
+
return
|
143
|
+
}
|
144
|
+
for (let i = 0; i < files.length; i++) {
|
145
|
+
const file = files[i];
|
146
|
+
let reader = new FileReader();
|
147
|
+
reader.readAsArrayBuffer(file);
|
148
|
+
reader.onloadend = async function (e: any) {
|
149
|
+
let workbook = XLSX.read(e.target.result, { type: "binary" });
|
150
|
+
onloadend(file, workbook);
|
154
151
|
}
|
155
|
-
}
|
156
|
-
|
157
|
-
|
158
|
-
}
|
159
|
-
|
160
|
-
// type: 'base64' | 'binary' | 'buffer' | 'file' | 'array' | 'string'
|
161
|
-
public static toExcel(data, type) {
|
162
|
-
let workbook = XLSX.read(data, { type: type });
|
163
|
-
return workbook;
|
164
|
-
}
|
152
|
+
}
|
153
|
+
}).catch(e => {
|
154
|
+
throw e;
|
155
|
+
})
|
156
|
+
}
|
165
157
|
|
166
|
-
|
158
|
+
// type: 'base64' | 'binary' | 'buffer' | 'file' | 'array' | 'string'
|
159
|
+
public static toExcel(data, type) {
|
160
|
+
let workbook = XLSX.read(data, { type: type });
|
161
|
+
return workbook;
|
162
|
+
}
|
167
163
|
|
168
|
-
|
169
|
-
const wopts: any = { bookType: 'xls', bookSST: false, type: 'binary', cellStyles: true };
|
164
|
+
public static downloadExcel(workbook, name) {
|
170
165
|
|
171
|
-
|
166
|
+
/* bookType can be 'xlsx' or 'xlsm' or 'xlsb' */
|
167
|
+
const wopts: any = { bookType: 'xls', bookSST: false, type: 'binary', cellStyles: true };
|
172
168
|
|
173
|
-
|
174
|
-
const buf = new ArrayBuffer(s.length);
|
175
|
-
const view = new Uint8Array(buf);
|
176
|
-
for (let i = 0; i != s.length; ++i) view[i] = s.charCodeAt(i) & 0xFF;
|
177
|
-
return buf;
|
178
|
-
}
|
179
|
-
|
180
|
-
/* the saveAs call downloads a file on the local machine */
|
181
|
-
saveAs(new Blob([s2ab(wbout)], { type: 'application/octet-stream' }), name)
|
169
|
+
const wbout = XLSX.write(workbook, wopts);
|
182
170
|
|
171
|
+
function s2ab(s) {
|
172
|
+
const buf = new ArrayBuffer(s.length);
|
173
|
+
const view = new Uint8Array(buf);
|
174
|
+
for (let i = 0; i != s.length; ++i) view[i] = s.charCodeAt(i) & 0xFF;
|
175
|
+
return buf;
|
183
176
|
}
|
184
177
|
|
178
|
+
/* the saveAs call downloads a file on the local machine */
|
179
|
+
saveAs(new Blob([s2ab(wbout)], { type: 'application/octet-stream' }), name)
|
180
|
+
|
185
181
|
}
|
186
182
|
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
183
|
+
}
|
184
|
+
|
185
|
+
|
186
|
+
const fullScreen = (docElm: any = null) => {
|
187
|
+
if (docElm === null) {
|
188
|
+
docElm = document.documentElement
|
189
|
+
}
|
190
|
+
if (docElm.requestFullscreen) {
|
191
|
+
docElm.requestFullscreen();
|
192
|
+
} else if (docElm.mozRequestFullScreen) {
|
193
|
+
docElm.mozRequestFullScreen();
|
194
|
+
} else if (docElm.msRequestFullscreen) {
|
195
|
+
docElm.msRequestFullscreen();
|
196
|
+
} else if (docElm.oRequestFullscreen) {
|
197
|
+
docElm.oRequestFullscreen();
|
198
|
+
} else if (docElm.webkitRequestFullScreen) {
|
199
|
+
docElm.webkitRequestFullScreen();
|
202
200
|
}
|
201
|
+
}
|
203
202
|
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
203
|
+
// 获取最大公约数
|
204
|
+
function getGcd(a, b) {
|
205
|
+
let n1, n2;
|
206
|
+
if (a > b) {
|
207
|
+
n1 = a;
|
208
|
+
n2 = b;
|
209
|
+
} else {
|
210
|
+
n1 = b;
|
211
|
+
n2 = a;
|
212
|
+
}
|
214
213
|
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
}
|
214
|
+
let remainder = n1 % n2;
|
215
|
+
if (remainder === 0) {
|
216
|
+
return n2;
|
217
|
+
} else {
|
218
|
+
return getGcd(n2, remainder)
|
221
219
|
}
|
220
|
+
}
|
222
221
|
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
222
|
+
const getVideoScale = async (url: string) => {
|
223
|
+
const video = document.createElement('video');
|
224
|
+
video.setAttribute("width", "10");
|
225
|
+
video.setAttribute("height", "10");
|
226
|
+
video.setAttribute("style", "position: absolute;opacity: 0;z-index: -5;top: 0;");
|
227
|
+
video.setAttribute("src", url);
|
229
228
|
|
230
|
-
|
229
|
+
document.body.appendChild(video);
|
231
230
|
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
})
|
231
|
+
const p = new Promise(function (resolve, reject) {
|
232
|
+
video.addEventListener('canplay', function (e: any) {
|
233
|
+
const gcd = getGcd(e.target.videoWidth, e.target.videoHeight);
|
234
|
+
resolve([e.target.videoWidth / gcd, e.target.videoHeight / gcd])
|
237
235
|
})
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
|
236
|
+
})
|
237
|
+
const res = await p;
|
238
|
+
document.body.removeChild(video);
|
239
|
+
return res
|
240
|
+
}
|
241
|
+
|
242
|
+
// 读取video中某一帧转为图片base64
|
243
|
+
const getVideoBase64 = async (url: string, timestamp = -1, bufftime = 2000) => {
|
244
|
+
|
245
|
+
const scale = await getVideoScale(url) as any;
|
246
|
+
const width = scale[0] + ''
|
247
|
+
const height = scale[1] + ''
|
248
|
+
const base64 = await new Promise(function (resolve) {
|
249
|
+
let dataURL = ''
|
250
|
+
let video = document.createElement('video')
|
251
|
+
video.setAttribute('crossOrigin', 'anonymous') //处理跨域
|
252
|
+
video.setAttribute('src', url)
|
253
|
+
video.setAttribute('width', width)
|
254
|
+
video.setAttribute('height', height)
|
255
|
+
video.setAttribute('autoplay', 'autoplay')
|
256
|
+
document.body.appendChild(video)
|
257
|
+
video.addEventListener('loadeddata', function () {
|
258
|
+
|
259
|
+
video.pause()
|
260
|
+
|
261
|
+
if (timestamp === -1) {
|
262
|
+
timestamp = Math.random() * video.duration
|
263
|
+
}
|
264
|
+
video.currentTime = timestamp
|
265
|
+
|
266
|
+
/*
|
267
|
+
使用定时器为了视频跳转到某一帧的时候视频进行缓冲,等视频加载完成之后进行截图
|
268
|
+
如果截图是黑屏说明视频未加载完成就开始截屏了
|
269
|
+
*/
|
270
|
+
setTimeout(() => {
|
271
|
+
let canvas = document.createElement('canvas');
|
272
|
+
// const width = canvas.width; //canvas的尺寸和图片一样
|
273
|
+
// const height = canvas.height;
|
274
|
+
canvas.width = video.width
|
275
|
+
canvas.height = video.height
|
276
|
+
canvas.getContext('2d')!.drawImage(video, 0, 0, video.width, video.height) //绘制canvas
|
277
|
+
dataURL = canvas.toDataURL('image/jpeg') //转换为base64
|
278
|
+
document.body.removeChild(video)
|
279
|
+
resolve(dataURL)
|
280
|
+
}, bufftime);
|
242
281
|
|
243
|
-
// 读取video中某一帧转为图片base64
|
244
|
-
export const getVideoBase64 = async (url: string, timestamp = -1, bufftime = 2000) => {
|
245
|
-
|
246
|
-
const scale = await getVideoScale(url) as any;
|
247
|
-
const width = scale[0] + ''
|
248
|
-
const height = scale[1] + ''
|
249
|
-
const base64 = await new Promise(function (resolve) {
|
250
|
-
let dataURL = ''
|
251
|
-
let video = document.createElement('video')
|
252
|
-
video.setAttribute('crossOrigin', 'anonymous') //处理跨域
|
253
|
-
video.setAttribute('src', url)
|
254
|
-
video.setAttribute('width', width)
|
255
|
-
video.setAttribute('height', height)
|
256
|
-
video.setAttribute('autoplay', 'autoplay')
|
257
|
-
document.body.appendChild(video)
|
258
|
-
video.addEventListener('loadeddata', function () {
|
259
|
-
|
260
|
-
video.pause()
|
261
|
-
|
262
|
-
if (timestamp === -1) {
|
263
|
-
timestamp = Math.random() * video.duration
|
264
|
-
}
|
265
|
-
video.currentTime = timestamp
|
266
|
-
|
267
|
-
/*
|
268
|
-
使用定时器为了视频跳转到某一帧的时候视频进行缓冲,等视频加载完成之后进行截图
|
269
|
-
如果截图是黑屏说明视频未加载完成就开始截屏了
|
270
|
-
*/
|
271
|
-
setTimeout(() => {
|
272
|
-
let canvas = document.createElement('canvas');
|
273
|
-
// const width = canvas.width; //canvas的尺寸和图片一样
|
274
|
-
// const height = canvas.height;
|
275
|
-
canvas.width = video.width
|
276
|
-
canvas.height = video.height
|
277
|
-
canvas.getContext('2d')!.drawImage(video, 0, 0, video.width, video.height) //绘制canvas
|
278
|
-
dataURL = canvas.toDataURL('image/jpeg') //转换为base64
|
279
|
-
document.body.removeChild(video)
|
280
|
-
resolve(dataURL)
|
281
|
-
}, bufftime);
|
282
|
-
|
283
|
-
})
|
284
282
|
})
|
283
|
+
})
|
285
284
|
|
286
|
-
|
287
|
-
|
285
|
+
return base64;
|
286
|
+
}
|
288
287
|
|
289
|
-
|
290
|
-
|
291
|
-
|
292
|
-
|
293
|
-
|
294
|
-
|
295
|
-
|
288
|
+
function getType(values) {
|
289
|
+
return Object
|
290
|
+
.prototype
|
291
|
+
.toString
|
292
|
+
.call(values)
|
293
|
+
.replace(/\[(\S+) (\S+)\]/, '$2')
|
294
|
+
}
|
296
295
|
|
297
|
-
|
298
|
-
|
299
|
-
|
300
|
-
|
301
|
-
|
296
|
+
const extensionToLowerCase = (fileName: string) => {
|
297
|
+
const n = fileName.lastIndexOf(".");
|
298
|
+
const extension = fileName.substring(n).toLowerCase();
|
299
|
+
return fileName.substring(0, n) + extension;
|
300
|
+
}
|
302
301
|
|
303
|
-
|
304
|
-
|
305
|
-
|
306
|
-
|
307
|
-
|
308
|
-
|
309
|
-
}
|
302
|
+
const isURL = (strUrl) => {
|
303
|
+
const regular = /^\b(((https?|ftp):\/\/)?[-a-z0-9]+(\.[-a-z0-9]+)*\.(?:com|edu|gov|int|mil|net|org|biz|info|name|museum|asia|coop|aero|[a-z][a-z]|((25[0-5])|(2[0-4]\d)|(1\d\d)|([1-9]\d)|\d))\b(\/[-a-z0-9_:\\@&?=+,.!\\/~%\\$]*)?)$/i;
|
304
|
+
if (regular.test(strUrl.trim())) {
|
305
|
+
return true;
|
306
|
+
} else {
|
307
|
+
return false;
|
310
308
|
}
|
309
|
+
}
|
311
310
|
|
312
311
|
|
312
|
+
export const EMacro = {
|
313
313
|
|
314
|
+
version,
|
315
|
+
File,
|
316
|
+
fullScreen,
|
317
|
+
getGcd,
|
318
|
+
getVideoScale,
|
319
|
+
getVideoBase64,
|
320
|
+
getType,
|
321
|
+
extensionToLowerCase,
|
322
|
+
isURL
|
314
323
|
}
|
315
324
|
|
316
325
|
|