@gx-design-vue/pro-utils 0.1.4 → 0.2.0-alpha.1
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/LICENSE +21 -0
- package/README.md +73 -2
- package/dist/array/index.d.ts +5 -0
- package/dist/array/index.js +6 -0
- package/dist/array/slice.d.ts +11 -0
- package/dist/array/slice.js +29 -0
- package/dist/array/sort.d.ts +41 -0
- package/dist/array/sort.js +65 -0
- package/dist/array/tree.d.ts +83 -0
- package/dist/array/tree.js +157 -0
- package/dist/array/unique.d.ts +12 -0
- package/dist/array/unique.js +14 -0
- package/dist/base64/index.d.ts +26 -0
- package/dist/base64/index.js +106 -0
- package/dist/class/index.d.ts +2 -0
- package/dist/class/index.js +3 -0
- package/dist/class/prefix.d.ts +25 -0
- package/dist/class/prefix.js +15 -0
- package/dist/clone/cloneDeep.d.ts +30 -0
- package/dist/clone/cloneDeep.js +35 -0
- package/dist/clone/cloneDeepWith.d.ts +14 -0
- package/dist/clone/cloneDeepWith.js +150 -0
- package/dist/clone/getTag.d.ts +10 -0
- package/dist/clone/getTag.js +13 -0
- package/dist/clone/index.d.ts +3 -0
- package/dist/clone/index.js +4 -0
- package/dist/clone/symbols.d.ts +10 -0
- package/dist/clone/symbols.js +13 -0
- package/dist/clone/tags.d.ts +47 -0
- package/dist/clone/tags.js +48 -0
- package/dist/dom/event.d.ts +21 -0
- package/dist/dom/event.js +26 -0
- package/dist/dom/index.d.ts +5 -0
- package/dist/dom/index.js +6 -0
- package/dist/dom/measure.d.ts +19 -0
- package/dist/dom/measure.js +42 -0
- package/dist/dom/raf.d.ts +14 -0
- package/dist/dom/raf.js +44 -0
- package/dist/dom/scroll.d.ts +20 -0
- package/dist/dom/scroll.js +97 -0
- package/dist/file/config.d.ts +13 -0
- package/dist/file/config.js +81 -0
- package/dist/file/convert.d.ts +41 -0
- package/dist/file/convert.js +69 -0
- package/dist/file/index.d.ts +5 -0
- package/dist/file/index.js +6 -0
- package/dist/file/media.d.ts +35 -0
- package/dist/file/media.js +161 -0
- package/dist/file/type.d.ts +25 -0
- package/dist/file/type.js +58 -0
- package/dist/function/copy.d.ts +12 -0
- package/dist/function/copy.js +13 -0
- package/dist/function/getValue.d.ts +12 -0
- package/dist/function/getValue.js +19 -0
- package/dist/function/index.d.ts +5 -0
- package/dist/function/index.js +6 -0
- package/dist/function/object.d.ts +24 -0
- package/dist/function/object.js +33 -0
- package/dist/function/run.d.ts +11 -0
- package/dist/function/run.js +15 -0
- package/dist/index.d.ts +59 -26
- package/dist/index.js +61 -0
- package/dist/is/base64.d.ts +17 -0
- package/dist/is/base64.js +27 -0
- package/dist/is/browser.d.ts +9 -0
- package/dist/is/browser.js +14 -0
- package/dist/is/deepEqual.d.ts +13 -0
- package/dist/is/deepEqual.js +62 -0
- package/dist/is/device.d.ts +21 -0
- package/dist/is/device.js +37 -0
- package/dist/is/equal.d.ts +12 -0
- package/dist/is/equal.js +34 -0
- package/dist/is/img.d.ts +10 -0
- package/dist/is/img.js +13 -0
- package/dist/is/index.d.ts +16 -0
- package/dist/is/index.js +17 -0
- package/dist/is/nil.d.ts +17 -0
- package/dist/is/nil.js +22 -0
- package/dist/is/plainObject.d.ts +17 -0
- package/dist/is/plainObject.js +30 -0
- package/dist/is/primitive.d.ts +10 -0
- package/dist/is/primitive.js +13 -0
- package/dist/is/server.d.ts +9 -0
- package/dist/is/server.js +10 -0
- package/dist/is/type.d.ts +60 -0
- package/dist/is/type.js +84 -0
- package/dist/is/typedArray.d.ts +30 -0
- package/dist/is/typedArray.js +33 -0
- package/dist/is/unsafeProperty.d.ts +10 -0
- package/dist/is/unsafeProperty.js +18 -0
- package/dist/is/url.d.ts +10 -0
- package/dist/is/url.js +20 -0
- package/dist/is/valid.d.ts +17 -0
- package/dist/is/valid.js +23 -0
- package/dist/merge/index.d.ts +19 -5
- package/dist/merge/index.js +42 -0
- package/dist/merge/mergeWith.d.ts +12 -0
- package/dist/merge/mergeWith.js +31 -0
- package/dist/merge/useDeepMege.d.ts +46 -0
- package/dist/merge/useDeepMege.js +56 -0
- package/dist/number/chinese.d.ts +10 -0
- package/dist/number/chinese.js +46 -0
- package/dist/number/format.d.ts +27 -0
- package/dist/number/format.js +72 -0
- package/dist/number/index.d.ts +3 -0
- package/dist/number/index.js +4 -0
- package/dist/object/classNames.d.ts +10 -0
- package/dist/object/classNames.js +30 -0
- package/dist/object/index.d.ts +5 -0
- package/dist/object/index.js +6 -0
- package/dist/object/omitBoolean.d.ts +10 -0
- package/dist/object/omitBoolean.js +13 -0
- package/dist/object/omitUndefined.d.ts +12 -0
- package/dist/object/omitUndefined.js +18 -0
- package/dist/object/omitUndefinedAndEmptyArr.d.ts +10 -0
- package/dist/object/omitUndefinedAndEmptyArr.js +19 -0
- package/dist/pro-utils.esm.js +948 -0
- package/dist/pro-utils.js +1 -0
- package/dist/string/duration.d.ts +10 -0
- package/dist/string/duration.js +25 -0
- package/dist/string/empty.d.ts +14 -0
- package/dist/string/empty.js +26 -0
- package/dist/string/index.d.ts +5 -0
- package/dist/string/index.js +6 -0
- package/dist/string/nanoid.d.ts +9 -0
- package/dist/string/nanoid.js +32 -0
- package/dist/string/uuid.d.ts +34 -0
- package/dist/string/uuid.js +57 -0
- package/dist/table/column.d.ts +27 -0
- package/dist/table/column.js +42 -0
- package/dist/table/index.d.ts +3 -0
- package/dist/table/index.js +4 -0
- package/dist/table/page.d.ts +13 -0
- package/dist/table/page.js +23 -0
- package/dist/typing.d.ts +262 -0
- package/dist/typing.js +1 -0
- package/dist/vue/index.d.ts +2 -0
- package/dist/vue/index.js +3 -0
- package/dist/vue/slots.d.ts +56 -0
- package/dist/vue/slots.js +89 -0
- package/package.json +45 -64
- package/dist/classNames/index.d.ts +0 -2
- package/dist/components/FieldLabel/index.d.ts +0 -77
- package/dist/components/FieldLabel/index.less +0 -107
- package/dist/components/LabelIconTip/index.d.ts +0 -20
- package/dist/components/LabelIconTip/index.less +0 -38
- package/dist/design/ant-design-theme.less +0 -4
- package/dist/design/ant-design-vue.less +0 -1
- package/dist/design/config.less +0 -2
- package/dist/isBrowser/index.d.ts +0 -1
- package/dist/isDeepEqualReact/index.d.ts +0 -1
- package/dist/isServer.d.ts +0 -2
- package/dist/omitBoolean/index.d.ts +0 -6
- package/dist/omitUndefined/index.d.ts +0 -5
- package/dist/pro-utils.es.js +0 -1044
- package/dist/pro-utils.umd.js +0 -1
- package/dist/proUtils.less +0 -4
- package/dist/scroll/easings.d.ts +0 -1
- package/dist/scroll/getScroll.d.ts +0 -2
- package/dist/scroll/index.d.ts +0 -4
- package/dist/scroll/raf.d.ts +0 -9
- package/dist/scroll/scrollTo.d.ts +0 -10
- package/dist/scroll/throttleByAnimationFrame.d.ts +0 -5
- package/dist/slots/index.d.ts +0 -9
- package/dist/style/index.less +0 -2
- package/dist/style.css +0 -1
- package/dist/style.less +0 -3
- package/dist/typings/index.d.ts +0 -30
- package/dist/utils/config.d.ts +0 -8
- package/dist/utils/index.d.ts +0 -208
- package/dist/utils/validate.d.ts +0 -25
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import { isServer } from "../is/server.js";
|
|
2
|
+
import "../is/index.js";
|
|
3
|
+
import wrapperRaf from "./raf.js";
|
|
4
|
+
|
|
5
|
+
//#region src/dom/scroll.ts
|
|
6
|
+
function easeInOutCubic(t, b, c, d) {
|
|
7
|
+
const cc = c - b;
|
|
8
|
+
t /= d / 2;
|
|
9
|
+
if (t < 1) return cc / 2 * t * t * t + b;
|
|
10
|
+
return cc / 2 * ((t -= 2) * t * t + 2) + b;
|
|
11
|
+
}
|
|
12
|
+
function camelize(str) {
|
|
13
|
+
return str.replace(/[-_](.)/g, (_, char) => char.toUpperCase());
|
|
14
|
+
}
|
|
15
|
+
function getStyle(element, styleName) {
|
|
16
|
+
if (isServer) return "";
|
|
17
|
+
if (!element || !styleName) return "";
|
|
18
|
+
styleName = camelize(styleName);
|
|
19
|
+
if (styleName === "float") styleName = "cssFloat";
|
|
20
|
+
try {
|
|
21
|
+
const style = element.style[styleName];
|
|
22
|
+
if (style) return style;
|
|
23
|
+
const computed = document?.defaultView?.getComputedStyle(element, "");
|
|
24
|
+
return computed ? computed[styleName] : "";
|
|
25
|
+
} catch {
|
|
26
|
+
return element.style[styleName];
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
function isScroll(el, isVertical) {
|
|
30
|
+
if (isServer) return;
|
|
31
|
+
return (isVertical === null || isVertical === void 0 ? getStyle(el, "overflow") : isVertical ? getStyle(el, "overflow-y") : getStyle(el, "overflow-x")).match(/(scroll|auto|overlay)/);
|
|
32
|
+
}
|
|
33
|
+
function getScrollContainer(el, isVertical) {
|
|
34
|
+
if (isServer) return;
|
|
35
|
+
let parent = el;
|
|
36
|
+
while (parent) {
|
|
37
|
+
if ([
|
|
38
|
+
window,
|
|
39
|
+
document,
|
|
40
|
+
document.documentElement
|
|
41
|
+
].includes(parent)) return window;
|
|
42
|
+
if (isScroll(parent, isVertical)) return parent;
|
|
43
|
+
parent = parent.parentNode;
|
|
44
|
+
}
|
|
45
|
+
return parent;
|
|
46
|
+
}
|
|
47
|
+
function isInContainer(el, container) {
|
|
48
|
+
if (isServer || !el || !container) return false;
|
|
49
|
+
const elRect = el.getBoundingClientRect();
|
|
50
|
+
let containerRect;
|
|
51
|
+
if ([
|
|
52
|
+
window,
|
|
53
|
+
document,
|
|
54
|
+
document.documentElement,
|
|
55
|
+
null,
|
|
56
|
+
void 0
|
|
57
|
+
].includes(container)) containerRect = {
|
|
58
|
+
top: 0,
|
|
59
|
+
right: window.innerWidth,
|
|
60
|
+
bottom: window.innerHeight,
|
|
61
|
+
left: 0
|
|
62
|
+
};
|
|
63
|
+
else containerRect = container.getBoundingClientRect();
|
|
64
|
+
return elRect.top < containerRect.bottom && elRect.bottom > containerRect.top && elRect.right > containerRect.left && elRect.left < containerRect.right;
|
|
65
|
+
}
|
|
66
|
+
function isWindow(obj) {
|
|
67
|
+
return obj !== null && obj !== void 0 && obj === obj.window;
|
|
68
|
+
}
|
|
69
|
+
function getScroll(target, top) {
|
|
70
|
+
if (typeof window === "undefined") return 0;
|
|
71
|
+
const method = top ? "scrollTop" : "scrollLeft";
|
|
72
|
+
let result = 0;
|
|
73
|
+
if (isWindow(target)) result = target[top ? "pageYOffset" : "pageXOffset"];
|
|
74
|
+
else if (target instanceof Document) result = target.documentElement[method];
|
|
75
|
+
else if (target) result = target[method];
|
|
76
|
+
if (target && !isWindow(target) && typeof result !== "number") result = (target.ownerDocument || target).documentElement?.[method];
|
|
77
|
+
return result;
|
|
78
|
+
}
|
|
79
|
+
function scrollTo(y, options = {}) {
|
|
80
|
+
const { getContainer = () => window, callback, duration = 450 } = options;
|
|
81
|
+
const container = getContainer();
|
|
82
|
+
const scrollTop = getScroll(container, true);
|
|
83
|
+
const startTime = Date.now();
|
|
84
|
+
const frameFunc = () => {
|
|
85
|
+
const time = Date.now() - startTime;
|
|
86
|
+
const nextScrollTop = easeInOutCubic(time > duration ? duration : time, scrollTop, y, duration);
|
|
87
|
+
if (isWindow(container)) container.scrollTo(window.pageXOffset, nextScrollTop);
|
|
88
|
+
else if (container instanceof HTMLDocument || container.constructor.name === "HTMLDocument") container.documentElement.scrollTop = nextScrollTop;
|
|
89
|
+
else container.scrollTop = nextScrollTop;
|
|
90
|
+
if (time < duration) wrapperRaf(frameFunc);
|
|
91
|
+
else if (typeof callback === "function") callback();
|
|
92
|
+
};
|
|
93
|
+
if (container) wrapperRaf(frameFunc);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
//#endregion
|
|
97
|
+
export { easeInOutCubic, getScroll, getScrollContainer, isInContainer, isScroll, isWindow, scrollTo };
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
//#region src/file/config.d.ts
|
|
2
|
+
/**
|
|
3
|
+
* 文件类型配置
|
|
4
|
+
*/
|
|
5
|
+
declare const fileTypes: {
|
|
6
|
+
/** 允许的视频格式 */videoAllowType: string[]; /** 允许的音频格式 */
|
|
7
|
+
audioAllowType: string[]; /** 图片格式 */
|
|
8
|
+
imageType: string[]; /** 视频格式 */
|
|
9
|
+
videoType: string[]; /** 音频格式 */
|
|
10
|
+
audioType: string[];
|
|
11
|
+
};
|
|
12
|
+
//#endregion
|
|
13
|
+
export { fileTypes };
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
//#region src/file/config.ts
|
|
2
|
+
/**
|
|
3
|
+
* 文件类型配置
|
|
4
|
+
*/
|
|
5
|
+
const fileTypes = {
|
|
6
|
+
videoAllowType: [
|
|
7
|
+
"mp4",
|
|
8
|
+
"webm",
|
|
9
|
+
"ogg"
|
|
10
|
+
],
|
|
11
|
+
audioAllowType: [
|
|
12
|
+
"mp3",
|
|
13
|
+
"ogg",
|
|
14
|
+
"wav",
|
|
15
|
+
"aac",
|
|
16
|
+
"m4a",
|
|
17
|
+
"webm"
|
|
18
|
+
],
|
|
19
|
+
imageType: [
|
|
20
|
+
"jpeg",
|
|
21
|
+
"jpg",
|
|
22
|
+
"png",
|
|
23
|
+
"gif",
|
|
24
|
+
"bmp",
|
|
25
|
+
"tiff",
|
|
26
|
+
"tif",
|
|
27
|
+
"webp",
|
|
28
|
+
"heic",
|
|
29
|
+
"heif",
|
|
30
|
+
"svg",
|
|
31
|
+
"ico",
|
|
32
|
+
"raw",
|
|
33
|
+
"cr2",
|
|
34
|
+
"nef",
|
|
35
|
+
"arw",
|
|
36
|
+
"dng",
|
|
37
|
+
"psd",
|
|
38
|
+
"eps"
|
|
39
|
+
],
|
|
40
|
+
videoType: [
|
|
41
|
+
"mp4",
|
|
42
|
+
"avi",
|
|
43
|
+
"mov",
|
|
44
|
+
"wmv",
|
|
45
|
+
"mkv",
|
|
46
|
+
"flv",
|
|
47
|
+
"webm",
|
|
48
|
+
"mpeg",
|
|
49
|
+
"mpg",
|
|
50
|
+
"3gp",
|
|
51
|
+
"ogv",
|
|
52
|
+
"mxf",
|
|
53
|
+
"vob",
|
|
54
|
+
"rm",
|
|
55
|
+
"rmvb",
|
|
56
|
+
"ts",
|
|
57
|
+
"mts",
|
|
58
|
+
"m2ts",
|
|
59
|
+
"divx",
|
|
60
|
+
"xvid"
|
|
61
|
+
],
|
|
62
|
+
audioType: [
|
|
63
|
+
"mp3",
|
|
64
|
+
"wav",
|
|
65
|
+
"aac",
|
|
66
|
+
"flac",
|
|
67
|
+
"ogg",
|
|
68
|
+
"wma",
|
|
69
|
+
"m4a",
|
|
70
|
+
"alac",
|
|
71
|
+
"opus",
|
|
72
|
+
"amr",
|
|
73
|
+
"aiff",
|
|
74
|
+
"au",
|
|
75
|
+
"pcm",
|
|
76
|
+
"ape"
|
|
77
|
+
]
|
|
78
|
+
};
|
|
79
|
+
|
|
80
|
+
//#endregion
|
|
81
|
+
export { fileTypes };
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
//#region src/file/convert.d.ts
|
|
2
|
+
/**
|
|
3
|
+
* 获取 Blob URL
|
|
4
|
+
*
|
|
5
|
+
* @param blob - Blob 对象
|
|
6
|
+
* @returns Blob URL
|
|
7
|
+
*/
|
|
8
|
+
declare function getBlobUrl(blob: Blob): string;
|
|
9
|
+
/**
|
|
10
|
+
* 获取文件 base64 编码
|
|
11
|
+
*
|
|
12
|
+
* @param file - 文件对象
|
|
13
|
+
* @returns base64 字符串
|
|
14
|
+
*/
|
|
15
|
+
declare function getBase64(file: File): Promise<string | ArrayBuffer | null>;
|
|
16
|
+
/**
|
|
17
|
+
* Data URL 转 Blob 对象
|
|
18
|
+
*
|
|
19
|
+
* @param url - Data URL
|
|
20
|
+
* @returns Blob 对象
|
|
21
|
+
*/
|
|
22
|
+
declare function dataURLtoBlob(url: any): Blob;
|
|
23
|
+
/**
|
|
24
|
+
* Data URL 转 File 对象
|
|
25
|
+
*
|
|
26
|
+
* @param url - Data URL
|
|
27
|
+
* @param filename - 文件名
|
|
28
|
+
* @returns File 对象
|
|
29
|
+
*/
|
|
30
|
+
declare function dataURLtoFile(url: string, filename: string): File;
|
|
31
|
+
/**
|
|
32
|
+
* Blob 转 File 对象
|
|
33
|
+
*
|
|
34
|
+
* @param blob - Blob 对象
|
|
35
|
+
* @param fileName - 文件名
|
|
36
|
+
* @param fileType - 文件类型
|
|
37
|
+
* @returns File 对象
|
|
38
|
+
*/
|
|
39
|
+
declare function blobToDataURL(blob: Blob, fileName: string, fileType: string): File;
|
|
40
|
+
//#endregion
|
|
41
|
+
export { blobToDataURL, dataURLtoBlob, dataURLtoFile, getBase64, getBlobUrl };
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
//#region src/file/convert.ts
|
|
2
|
+
/**
|
|
3
|
+
* 获取 Blob URL
|
|
4
|
+
*
|
|
5
|
+
* @param blob - Blob 对象
|
|
6
|
+
* @returns Blob URL
|
|
7
|
+
*/
|
|
8
|
+
function getBlobUrl(blob) {
|
|
9
|
+
return URL.createObjectURL(blob);
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* 获取文件 base64 编码
|
|
13
|
+
*
|
|
14
|
+
* @param file - 文件对象
|
|
15
|
+
* @returns base64 字符串
|
|
16
|
+
*/
|
|
17
|
+
function getBase64(file) {
|
|
18
|
+
return new Promise((resolve, reject) => {
|
|
19
|
+
const reader = new FileReader();
|
|
20
|
+
reader.readAsDataURL(file);
|
|
21
|
+
reader.onload = () => resolve(reader.result);
|
|
22
|
+
reader.onerror = (error) => reject(error);
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Data URL 转 Blob 对象
|
|
27
|
+
*
|
|
28
|
+
* @param url - Data URL
|
|
29
|
+
* @returns Blob 对象
|
|
30
|
+
*/
|
|
31
|
+
function dataURLtoBlob(url) {
|
|
32
|
+
const arr = url.split(",");
|
|
33
|
+
const mime = arr[0].match(/:(.*?);/)[1];
|
|
34
|
+
const str = atob(arr[1]);
|
|
35
|
+
let n = str.length;
|
|
36
|
+
const u8arr = new Uint8Array(n);
|
|
37
|
+
while (n--) u8arr[n] = str.charCodeAt(n);
|
|
38
|
+
return new Blob([u8arr], { type: mime });
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Data URL 转 File 对象
|
|
42
|
+
*
|
|
43
|
+
* @param url - Data URL
|
|
44
|
+
* @param filename - 文件名
|
|
45
|
+
* @returns File 对象
|
|
46
|
+
*/
|
|
47
|
+
function dataURLtoFile(url, filename) {
|
|
48
|
+
const arr = url.split(",");
|
|
49
|
+
const mime = arr[0].match(/:(.*?);/)[1];
|
|
50
|
+
const str = atob(arr[1]);
|
|
51
|
+
let n = str.length;
|
|
52
|
+
const u8arr = new Uint8Array(n);
|
|
53
|
+
while (n--) u8arr[n] = str.charCodeAt(n);
|
|
54
|
+
return new File([u8arr], filename, { type: mime });
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Blob 转 File 对象
|
|
58
|
+
*
|
|
59
|
+
* @param blob - Blob 对象
|
|
60
|
+
* @param fileName - 文件名
|
|
61
|
+
* @param fileType - 文件类型
|
|
62
|
+
* @returns File 对象
|
|
63
|
+
*/
|
|
64
|
+
function blobToDataURL(blob, fileName, fileType) {
|
|
65
|
+
return new window.File([blob], fileName, { type: fileType });
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
//#endregion
|
|
69
|
+
export { blobToDataURL, dataURLtoBlob, dataURLtoFile, getBase64, getBlobUrl };
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { fileTypes } from "./config.js";
|
|
2
|
+
import { blobToDataURL, dataURLtoBlob, dataURLtoFile, getBase64, getBlobUrl } from "./convert.js";
|
|
3
|
+
import { generateVideoPicture, getMediaInfos, getVideoCoverPicture } from "./media.js";
|
|
4
|
+
import { checkFileType, getFileSuffix, getVideoFileUrl } from "./type.js";
|
|
5
|
+
export { blobToDataURL, checkFileType, dataURLtoBlob, dataURLtoFile, fileTypes, generateVideoPicture, getBase64, getBlobUrl, getFileSuffix, getMediaInfos, getVideoCoverPicture, getVideoFileUrl };
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { fileTypes } from "./config.js";
|
|
2
|
+
import { blobToDataURL, dataURLtoBlob, dataURLtoFile, getBase64, getBlobUrl } from "./convert.js";
|
|
3
|
+
import { checkFileType, getFileSuffix, getVideoFileUrl } from "./type.js";
|
|
4
|
+
import { generateVideoPicture, getMediaInfos, getVideoCoverPicture } from "./media.js";
|
|
5
|
+
|
|
6
|
+
export { blobToDataURL, checkFileType, dataURLtoBlob, dataURLtoFile, fileTypes, generateVideoPicture, getBase64, getBlobUrl, getFileSuffix, getMediaInfos, getVideoCoverPicture, getVideoFileUrl };
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { MediaOptions } from "../typing.js";
|
|
2
|
+
|
|
3
|
+
//#region src/file/media.d.ts
|
|
4
|
+
/**
|
|
5
|
+
* 获取媒体信息(图片/视频/音频)
|
|
6
|
+
*
|
|
7
|
+
* @param mediaInfo - 媒体信息配置
|
|
8
|
+
* @returns 媒体详细信息
|
|
9
|
+
*/
|
|
10
|
+
declare function getMediaInfos(mediaInfo: {
|
|
11
|
+
url: any;
|
|
12
|
+
fileType?: string;
|
|
13
|
+
}): Promise<MediaOptions>;
|
|
14
|
+
/**
|
|
15
|
+
* 获取视频封面图
|
|
16
|
+
*
|
|
17
|
+
* @param videoInfo - 视频信息
|
|
18
|
+
* @returns 封面图 base64
|
|
19
|
+
*/
|
|
20
|
+
declare function getVideoCoverPicture(videoInfo: {
|
|
21
|
+
url: any;
|
|
22
|
+
currentTime?: number;
|
|
23
|
+
videoSuffix?: string;
|
|
24
|
+
videoAllowPlay?: boolean;
|
|
25
|
+
}): Promise<string>;
|
|
26
|
+
/**
|
|
27
|
+
* 生成视频截图
|
|
28
|
+
*
|
|
29
|
+
* @param videoUrl - 视频 URL
|
|
30
|
+
* @param currentTime - 截图时间点
|
|
31
|
+
* @returns 截图 base64
|
|
32
|
+
*/
|
|
33
|
+
declare function generateVideoPicture(videoUrl: string, currentTime?: number): Promise<string>;
|
|
34
|
+
//#endregion
|
|
35
|
+
export { generateVideoPicture, getMediaInfos, getVideoCoverPicture };
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
import { isBase64 } from "../is/base64.js";
|
|
2
|
+
import "../is/index.js";
|
|
3
|
+
import { fileTypes } from "./config.js";
|
|
4
|
+
import { checkFileType, getFileSuffix } from "./type.js";
|
|
5
|
+
|
|
6
|
+
//#region src/file/media.ts
|
|
7
|
+
/**
|
|
8
|
+
* 获取媒体信息(图片/视频/音频)
|
|
9
|
+
*
|
|
10
|
+
* @param mediaInfo - 媒体信息配置
|
|
11
|
+
* @returns 媒体详细信息
|
|
12
|
+
*/
|
|
13
|
+
function getMediaInfos(mediaInfo) {
|
|
14
|
+
const { url = "", fileType = "1" } = mediaInfo || {};
|
|
15
|
+
let mediaUrl = "";
|
|
16
|
+
let result = {
|
|
17
|
+
play: false,
|
|
18
|
+
height: 0,
|
|
19
|
+
size: 0,
|
|
20
|
+
width: 0,
|
|
21
|
+
duration: 0
|
|
22
|
+
};
|
|
23
|
+
function resetResult() {
|
|
24
|
+
result = {
|
|
25
|
+
play: false,
|
|
26
|
+
height: 0,
|
|
27
|
+
size: 0,
|
|
28
|
+
width: 0,
|
|
29
|
+
duration: 0
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
if (url instanceof File) mediaUrl = URL.createObjectURL(url);
|
|
33
|
+
else if (isBase64(url)) mediaUrl = url;
|
|
34
|
+
else if (url instanceof Blob) mediaUrl = URL.createObjectURL(url);
|
|
35
|
+
else if (url.includes("https") || url.includes("http")) mediaUrl = fileType === "1" ? url : url;
|
|
36
|
+
return new Promise((resolve) => {
|
|
37
|
+
let el;
|
|
38
|
+
if (fileType === "4") {
|
|
39
|
+
resolve(result);
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
if (fileType === "1") {
|
|
43
|
+
el = document.createElement("img");
|
|
44
|
+
el.src = mediaUrl;
|
|
45
|
+
} else if (fileType === "2") {
|
|
46
|
+
el = document.createElement("audio");
|
|
47
|
+
el.src = mediaUrl;
|
|
48
|
+
} else if (fileType === "3") {
|
|
49
|
+
el = document.createElement("video");
|
|
50
|
+
el.src = mediaUrl;
|
|
51
|
+
}
|
|
52
|
+
if (fileType === "1") el.onload = function() {
|
|
53
|
+
resetResult();
|
|
54
|
+
result.play = true;
|
|
55
|
+
result.width = el.width || 0;
|
|
56
|
+
result.height = el.height || 0;
|
|
57
|
+
resolve(result);
|
|
58
|
+
el = null;
|
|
59
|
+
};
|
|
60
|
+
else el.oncanplay = function() {
|
|
61
|
+
resetResult();
|
|
62
|
+
result.play = true;
|
|
63
|
+
result.width = el?.videoWidth || 0;
|
|
64
|
+
result.height = el?.videoHeight || 0;
|
|
65
|
+
result.duration = el?.duration || 0;
|
|
66
|
+
resolve(result);
|
|
67
|
+
el = null;
|
|
68
|
+
};
|
|
69
|
+
el.onerror = function() {
|
|
70
|
+
resetResult();
|
|
71
|
+
resolve(result);
|
|
72
|
+
el = null;
|
|
73
|
+
};
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* 获取视频封面图
|
|
78
|
+
*
|
|
79
|
+
* @param videoInfo - 视频信息
|
|
80
|
+
* @returns 封面图 base64
|
|
81
|
+
*/
|
|
82
|
+
async function getVideoCoverPicture(videoInfo) {
|
|
83
|
+
const { url = "", currentTime, videoSuffix = "", videoAllowPlay = false } = videoInfo;
|
|
84
|
+
let videoUrl = "";
|
|
85
|
+
let fileSuffix = videoSuffix;
|
|
86
|
+
let fileType = "1";
|
|
87
|
+
let videoPlayInfo;
|
|
88
|
+
if (url instanceof File) {
|
|
89
|
+
videoUrl = URL.createObjectURL(url);
|
|
90
|
+
fileSuffix = getFileSuffix(url.name);
|
|
91
|
+
fileType = checkFileType(url.name);
|
|
92
|
+
} else if (url instanceof Blob) {
|
|
93
|
+
videoUrl = URL.createObjectURL(url);
|
|
94
|
+
fileType = checkFileType(url);
|
|
95
|
+
} else if (isBase64(url)) {
|
|
96
|
+
videoUrl = url;
|
|
97
|
+
fileType = checkFileType(url);
|
|
98
|
+
} else if (url.includes("https") || url.includes("http")) {
|
|
99
|
+
videoUrl = url;
|
|
100
|
+
fileSuffix = getFileSuffix(url);
|
|
101
|
+
fileType = checkFileType(url);
|
|
102
|
+
}
|
|
103
|
+
if (fileSuffix ? fileTypes.videoAllowType.includes(fileSuffix.toLowerCase()) : false) if (videoAllowPlay) return generateVideoPicture(videoUrl, currentTime);
|
|
104
|
+
else {
|
|
105
|
+
videoPlayInfo = await getMediaInfos({
|
|
106
|
+
url: videoUrl,
|
|
107
|
+
fileType
|
|
108
|
+
});
|
|
109
|
+
if (videoPlayInfo.play) return generateVideoPicture(videoUrl, currentTime);
|
|
110
|
+
else return new Promise((resolve) => {
|
|
111
|
+
resolve("");
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
else return new Promise((resolve) => {
|
|
115
|
+
resolve("");
|
|
116
|
+
});
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* 生成视频截图
|
|
120
|
+
*
|
|
121
|
+
* @param videoUrl - 视频 URL
|
|
122
|
+
* @param currentTime - 截图时间点
|
|
123
|
+
* @returns 截图 base64
|
|
124
|
+
*/
|
|
125
|
+
async function generateVideoPicture(videoUrl, currentTime = 0) {
|
|
126
|
+
return new Promise((resolve) => {
|
|
127
|
+
let video = document.createElement("video");
|
|
128
|
+
if (video) {
|
|
129
|
+
video.controls = true;
|
|
130
|
+
video.muted = true;
|
|
131
|
+
video.setAttribute("src", videoUrl);
|
|
132
|
+
video.setAttribute("muted", String(true));
|
|
133
|
+
video.setAttribute("crossorigin", "anonymous");
|
|
134
|
+
video.setAttribute("autoplay", String(true));
|
|
135
|
+
video.addEventListener("loadeddata", async () => {
|
|
136
|
+
let seekResolve;
|
|
137
|
+
video?.addEventListener("seeked", async () => {
|
|
138
|
+
if (seekResolve) seekResolve();
|
|
139
|
+
});
|
|
140
|
+
while (currentTime < (video?.duration || 0)) {
|
|
141
|
+
if (video) video.currentTime = currentTime;
|
|
142
|
+
await new Promise((r) => seekResolve = r);
|
|
143
|
+
const canvas = document.createElement("canvas");
|
|
144
|
+
const scale = .8;
|
|
145
|
+
const ctx = canvas.getContext("2d");
|
|
146
|
+
const w = video?.videoWidth || 0 * scale;
|
|
147
|
+
const h = video?.videoHeight || 0 * scale;
|
|
148
|
+
const space = 0;
|
|
149
|
+
canvas.width = video?.videoWidth || 0 * scale;
|
|
150
|
+
canvas.height = video?.videoHeight || 0 * scale;
|
|
151
|
+
if (video) ctx.drawImage(video, 0, 0, w + space, h + space);
|
|
152
|
+
video = null;
|
|
153
|
+
resolve(w === 0 || h === 0 ? "" : canvas.toDataURL("image/png", 1));
|
|
154
|
+
}
|
|
155
|
+
});
|
|
156
|
+
}
|
|
157
|
+
});
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
//#endregion
|
|
161
|
+
export { generateVideoPicture, getMediaInfos, getVideoCoverPicture };
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
//#region src/file/type.d.ts
|
|
2
|
+
/**
|
|
3
|
+
* 获取文件后缀名
|
|
4
|
+
*
|
|
5
|
+
* @param url - 文件 URL
|
|
6
|
+
* @returns 后缀名
|
|
7
|
+
*/
|
|
8
|
+
declare function getFileSuffix(url: string): string;
|
|
9
|
+
/**
|
|
10
|
+
* 截取视频 URL(去除参数)
|
|
11
|
+
*
|
|
12
|
+
* @param url - URL
|
|
13
|
+
* @returns 处理后的 URL
|
|
14
|
+
*/
|
|
15
|
+
declare function getVideoFileUrl(url: string): string;
|
|
16
|
+
/**
|
|
17
|
+
* 检查文件类型
|
|
18
|
+
*
|
|
19
|
+
* @param url - 文件 URL 或对象
|
|
20
|
+
* @param type - 指定类型
|
|
21
|
+
* @returns 文件类型代码:1 图片, 2 音频, 3 视频, 4 其他
|
|
22
|
+
*/
|
|
23
|
+
declare function checkFileType(url: any, type?: '1' | '2' | '3' | '4'): "1" | "2" | "3" | "4";
|
|
24
|
+
//#endregion
|
|
25
|
+
export { checkFileType, getFileSuffix, getVideoFileUrl };
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { isBase64 } from "../is/base64.js";
|
|
2
|
+
import "../is/index.js";
|
|
3
|
+
import { fileTypes } from "./config.js";
|
|
4
|
+
|
|
5
|
+
//#region src/file/type.ts
|
|
6
|
+
/**
|
|
7
|
+
* 获取文件后缀名
|
|
8
|
+
*
|
|
9
|
+
* @param url - 文件 URL
|
|
10
|
+
* @returns 后缀名
|
|
11
|
+
*/
|
|
12
|
+
function getFileSuffix(url) {
|
|
13
|
+
if (!url || typeof url !== "string") return "";
|
|
14
|
+
const newUrl = getVideoFileUrl(url);
|
|
15
|
+
const index = newUrl.lastIndexOf(".");
|
|
16
|
+
return index > 0 ? `${newUrl?.substring?.(index)?.split("?")?.[0]}`?.split(".")?.[1] || "" : "";
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* 截取视频 URL(去除参数)
|
|
20
|
+
*
|
|
21
|
+
* @param url - URL
|
|
22
|
+
* @returns 处理后的 URL
|
|
23
|
+
*/
|
|
24
|
+
function getVideoFileUrl(url) {
|
|
25
|
+
if (!url || typeof url !== "string") return "";
|
|
26
|
+
const index = url.indexOf("?");
|
|
27
|
+
return index > 0 ? `${url.substring(0, index)}` : url;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* 检查文件类型
|
|
31
|
+
*
|
|
32
|
+
* @param url - 文件 URL 或对象
|
|
33
|
+
* @param type - 指定类型
|
|
34
|
+
* @returns 文件类型代码:1 图片, 2 音频, 3 视频, 4 其他
|
|
35
|
+
*/
|
|
36
|
+
function checkFileType(url, type) {
|
|
37
|
+
if (type) return type;
|
|
38
|
+
if (!url) return "4";
|
|
39
|
+
if (url === "data:") return "4";
|
|
40
|
+
let fileType = "4";
|
|
41
|
+
if (isBase64(url)) {
|
|
42
|
+
if (url.includes("data:image/")) fileType = "png";
|
|
43
|
+
else if (url.includes("data:video/")) fileType = "mp4";
|
|
44
|
+
else if (url.includes("data:audio/")) fileType = "mp3";
|
|
45
|
+
} else if (url instanceof Blob) {
|
|
46
|
+
url = String(url);
|
|
47
|
+
if (url.includes("image")) fileType = "png";
|
|
48
|
+
else if (url.includes("video")) fileType = "mp4";
|
|
49
|
+
else if (url.includes("audio")) fileType = "mp3";
|
|
50
|
+
} else fileType = getFileSuffix(url).toLowerCase();
|
|
51
|
+
if (fileTypes.imageType.includes(fileType)) return "1";
|
|
52
|
+
if (fileTypes.videoType.includes(fileType)) return "3";
|
|
53
|
+
if (fileTypes.audioType.includes(fileType)) return "2";
|
|
54
|
+
return "4";
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
//#endregion
|
|
58
|
+
export { checkFileType, getFileSuffix, getVideoFileUrl };
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { RecordType } from "../typing.js";
|
|
2
|
+
|
|
3
|
+
//#region src/function/copy.d.ts
|
|
4
|
+
/**
|
|
5
|
+
* 简单深拷贝(使用 JSON 序列化)
|
|
6
|
+
*
|
|
7
|
+
* @param data - 要拷贝的数据
|
|
8
|
+
* @returns 拷贝后的数据
|
|
9
|
+
*/
|
|
10
|
+
declare function deepCopy<T = RecordType>(data: any): T;
|
|
11
|
+
//#endregion
|
|
12
|
+
export { deepCopy };
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
//#region src/function/getValue.d.ts
|
|
2
|
+
type DeepValueOf<T, K> = K extends `${infer First}:${infer Rest}` ? First extends keyof T ? Rest extends '' ? T[First] : DeepValueOf<T[First], Rest> : undefined : K extends keyof T ? T[K] : undefined;
|
|
3
|
+
/**
|
|
4
|
+
* 根据 key 从对象中获取值(支持嵌套路径)
|
|
5
|
+
*
|
|
6
|
+
* @param object - 目标对象
|
|
7
|
+
* @param key - 键路径(支持用冒号分隔的嵌套路径)
|
|
8
|
+
* @returns 获取的值
|
|
9
|
+
*/
|
|
10
|
+
declare function getValueFromObjectByKey<T extends object, K extends string | string[] = string>(object: T, key: K): DeepValueOf<T, K extends string ? K : string> | undefined;
|
|
11
|
+
//#endregion
|
|
12
|
+
export { getValueFromObjectByKey };
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
//#region src/function/getValue.ts
|
|
2
|
+
/**
|
|
3
|
+
* 根据 key 从对象中获取值(支持嵌套路径)
|
|
4
|
+
*
|
|
5
|
+
* @param object - 目标对象
|
|
6
|
+
* @param key - 键路径(支持用冒号分隔的嵌套路径)
|
|
7
|
+
* @returns 获取的值
|
|
8
|
+
*/
|
|
9
|
+
function getValueFromObjectByKey(object, key) {
|
|
10
|
+
if (typeof key !== "string" && !Array.isArray(key)) return;
|
|
11
|
+
const keys = Array.isArray(key) ? key : key.split(":");
|
|
12
|
+
let currentValue = object;
|
|
13
|
+
for (let i = 0; i < keys.length; i++) if (currentValue && Object.prototype.hasOwnProperty.call(currentValue, keys[i])) currentValue = currentValue[keys[i]];
|
|
14
|
+
else return;
|
|
15
|
+
return currentValue;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
//#endregion
|
|
19
|
+
export { getValueFromObjectByKey };
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { deepCopy } from "./copy.js";
|
|
2
|
+
import { getValueFromObjectByKey } from "./getValue.js";
|
|
3
|
+
import { forInObject, getSymbols, keysOf } from "./object.js";
|
|
4
|
+
import { runFunction } from "./run.js";
|
|
5
|
+
export { deepCopy, forInObject, getSymbols, getValueFromObjectByKey, keysOf, runFunction };
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { forInObject, getSymbols, keysOf } from "./object.js";
|
|
2
|
+
import { deepCopy } from "./copy.js";
|
|
3
|
+
import { getValueFromObjectByKey } from "./getValue.js";
|
|
4
|
+
import { runFunction } from "./run.js";
|
|
5
|
+
|
|
6
|
+
export { deepCopy, forInObject, getSymbols, getValueFromObjectByKey, keysOf, runFunction };
|