iota-utools 0.0.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/README.md +124 -0
- package/babel.config.cjs +11 -0
- package/package.json +36 -0
- package/public/index.html +20 -0
- package/rollup.config.js +51 -0
- package/src/array/index.ts +1 -0
- package/src/array/uniqueArrayByProperty.ts +14 -0
- package/src/datatree/deepClone.ts +26 -0
- package/src/datatree/deleteTreeNode.ts +14 -0
- package/src/datatree/findTreeNode.ts +28 -0
- package/src/datatree/fuzzySearchTree.ts +37 -0
- package/src/datatree/index.ts +6 -0
- package/src/datatree/models.ts +4 -0
- package/src/datatree/toFlatTree.ts +11 -0
- package/src/datatree/toTreeFlat.ts +19 -0
- package/src/fileStream/downFile.ts +28 -0
- package/src/fileStream/downStream.ts +46 -0
- package/src/fileStream/index.ts +2 -0
- package/src/main.ts +5 -0
- package/src/params/decodeParams.ts +13 -0
- package/src/params/encodeParams.ts +9 -0
- package/src/params/index.ts +2 -0
- package/src/storage/index.ts +51 -0
- package/src/storage/local.ts +40 -0
- package/src/storage/session.ts +40 -0
- package/src/utools/copyText.ts +18 -0
- package/src/utools/index.ts +3 -0
- package/src/utools/sleep.ts +11 -0
- package/src/utools/typeof.ts +39 -0
- package/src/uuid/generateString.ts +14 -0
- package/src/uuid/generateUUID.ts +15 -0
- package/src/uuid/index.ts +2 -0
- package/test/tree.test.ts +5 -0
- package/test/utools.test.ts +74 -0
- package/tsconfig.json +26 -0
package/README.md
ADDED
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
## iota-tools
|
|
2
|
+
|
|
3
|
+
### 类型判断:
|
|
4
|
+
|
|
5
|
+
```ts
|
|
6
|
+
// 数据类型
|
|
7
|
+
function etTypeof(value: any): string
|
|
8
|
+
|
|
9
|
+
// 是否是数组
|
|
10
|
+
function isArray(value: any): boolean
|
|
11
|
+
|
|
12
|
+
// 是否是布尔值
|
|
13
|
+
function isBoolean(value: any): boolean
|
|
14
|
+
|
|
15
|
+
// 是否是字符串类型
|
|
16
|
+
function isString(value: any): boolean
|
|
17
|
+
|
|
18
|
+
// 是否是数字
|
|
19
|
+
function isNumber(value: any): boolean
|
|
20
|
+
|
|
21
|
+
// 是否是object 类型 - @::
|
|
22
|
+
function isObject(value: any): boolean
|
|
23
|
+
|
|
24
|
+
// 是否是一个方法
|
|
25
|
+
function isFunction(value: any): boolean
|
|
26
|
+
|
|
27
|
+
// 是否是一个Map
|
|
28
|
+
function isMap(value: any): boolean
|
|
29
|
+
|
|
30
|
+
// 是否是一个Set 类型
|
|
31
|
+
function isSet(value: any): boolean
|
|
32
|
+
|
|
33
|
+
// 是否是一个Symbol 类型
|
|
34
|
+
function isSymbol(value: any): boolean
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
### 复制文本的方法
|
|
38
|
+
|
|
39
|
+
```ts
|
|
40
|
+
// 复制文本
|
|
41
|
+
function copyText(text: string): void
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
### 阻塞进程方法
|
|
45
|
+
|
|
46
|
+
```ts
|
|
47
|
+
// 阻塞进程
|
|
48
|
+
function sleep(ms: number): void
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
### LocalStorage 存取
|
|
52
|
+
|
|
53
|
+
```ts
|
|
54
|
+
// 向 localStorage 存数据
|
|
55
|
+
function setLocalStorage(key: string, data: any)
|
|
56
|
+
|
|
57
|
+
// 向 localStorage 取数据
|
|
58
|
+
function getLocalStorage(key: string): any
|
|
59
|
+
|
|
60
|
+
// 移除 localStorage 数据
|
|
61
|
+
function removeLocalStorageKey(...args: string[])
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
### SessionStorage 存取
|
|
65
|
+
|
|
66
|
+
```ts
|
|
67
|
+
// 向 sessionStorage 存数据
|
|
68
|
+
function setSessionStorage(key: string, data: any)
|
|
69
|
+
|
|
70
|
+
// 向 sessionStorage 取数据
|
|
71
|
+
function getSessionStorage(key: string): any
|
|
72
|
+
|
|
73
|
+
// 移除 sessionStorage 数据
|
|
74
|
+
function removeSessionStorageKey(...args: string[])
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
### params 处理
|
|
78
|
+
|
|
79
|
+
```ts
|
|
80
|
+
// 将字符串转成对象 {key:value}
|
|
81
|
+
function decodeParams(queryString: string)
|
|
82
|
+
|
|
83
|
+
// 将对象转成 ?key=value&key=value
|
|
84
|
+
function encodeParams(query: Record<string, any>)
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
### 拉流、文件流下载
|
|
88
|
+
|
|
89
|
+
```ts
|
|
90
|
+
// 下载文件流
|
|
91
|
+
function downFile(stream: string | ArrayBuffer, name: string, mimeType: string = "text/plain;charset=utf-8")
|
|
92
|
+
|
|
93
|
+
// 拉流且下载文件流
|
|
94
|
+
function downStream(path: string, defaultName: string, token?: string, params?: Record<string, any>)
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
### 数组处理方法
|
|
98
|
+
|
|
99
|
+
```ts
|
|
100
|
+
// 根据key 类型数据去去重
|
|
101
|
+
function uniqueArrayByProperty<T>(array: T[], key: keyof T): T[]
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
### Tree 数据处理
|
|
105
|
+
|
|
106
|
+
```ts
|
|
107
|
+
// 树 -> 扁平树
|
|
108
|
+
function toFlatTree(origin: TreeData[])
|
|
109
|
+
|
|
110
|
+
// 扁平树 -> 树
|
|
111
|
+
function toTreeFlat<T extends TreeData>(origin: T[], parentId: number | string = "root")
|
|
112
|
+
|
|
113
|
+
// 深拷贝
|
|
114
|
+
function deepClone<T = any>(obj: T): T
|
|
115
|
+
|
|
116
|
+
// 删除某个节点 纯函数
|
|
117
|
+
function deleteTreeNode<T extends TreeData>(origin: T[], id: string | number, key: keyof T = "id"): T[]
|
|
118
|
+
|
|
119
|
+
// 查找某个节点
|
|
120
|
+
function findTreeNode<T extends TreeData>(origin: T[], findValue: any, key: keyof T = "id"): T | null
|
|
121
|
+
|
|
122
|
+
// 模糊查询 树节点
|
|
123
|
+
function fuzzySearchTree<T extends TreeData>(treeData: T[], findStr: string, label: keyof T = "title"): T[]
|
|
124
|
+
```
|
package/babel.config.cjs
ADDED
package/package.json
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "iota-utools",
|
|
3
|
+
"version": "0.0.1",
|
|
4
|
+
"description": "",
|
|
5
|
+
"main": "main.js",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"scripts": {
|
|
8
|
+
"build": "rollup -c",
|
|
9
|
+
"test": "jest --coverage --verbose -u",
|
|
10
|
+
"start": "rollup -c rollup.config.js --watch"
|
|
11
|
+
},
|
|
12
|
+
"keywords": [],
|
|
13
|
+
"author": "",
|
|
14
|
+
"license": "ISC",
|
|
15
|
+
"devDependencies": {
|
|
16
|
+
"@babel/core": "^7.21.3",
|
|
17
|
+
"@babel/preset-env": "^7.20.2",
|
|
18
|
+
"@babel/preset-typescript": "^7.21.0",
|
|
19
|
+
"@rollup/plugin-babel": "^6.0.3",
|
|
20
|
+
"@rollup/plugin-node-resolve": "^15.0.1",
|
|
21
|
+
"babel-jest": "^29.5.0",
|
|
22
|
+
"jest": "^29.5.0",
|
|
23
|
+
"rollup": "^3.29.4",
|
|
24
|
+
"rollup-plugin-babel": "^4.4.0",
|
|
25
|
+
"rollup-plugin-commonjs": "^10.1.0",
|
|
26
|
+
"rollup-plugin-livereload": "^2.0.5",
|
|
27
|
+
"rollup-plugin-node-resolve": "^5.2.0",
|
|
28
|
+
"rollup-plugin-serve": "^2.0.2",
|
|
29
|
+
"rollup-plugin-sourcemaps": "^0.6.3",
|
|
30
|
+
"rollup-plugin-typescript2": "^0.34.1",
|
|
31
|
+
"rollup-plugin-uglify": "^6.0.4",
|
|
32
|
+
"ts-jest": "^29.0.5",
|
|
33
|
+
"tslib": "^2.5.0",
|
|
34
|
+
"typescript": "^5.0.2"
|
|
35
|
+
}
|
|
36
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8" />
|
|
5
|
+
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
|
6
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
7
|
+
<title>Document</title>
|
|
8
|
+
</head>
|
|
9
|
+
|
|
10
|
+
<body>
|
|
11
|
+
<h1>Test Fun In Page</h1>
|
|
12
|
+
<hr />
|
|
13
|
+
<h2>window utools object function!!</h2>
|
|
14
|
+
<hr />
|
|
15
|
+
<script type="module">
|
|
16
|
+
import * as utools from "../lib/bundle.esm.js"
|
|
17
|
+
window.utools = utools
|
|
18
|
+
</script>
|
|
19
|
+
</body>
|
|
20
|
+
</html>
|
package/rollup.config.js
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
// ./`rollup.config.js`
|
|
2
|
+
import babel from "@rollup/plugin-babel";
|
|
3
|
+
import commonjs from "rollup-plugin-commonjs";
|
|
4
|
+
import { uglify } from "rollup-plugin-uglify";
|
|
5
|
+
import sourceMaps from "rollup-plugin-sourcemaps";
|
|
6
|
+
import resolve from "@rollup/plugin-node-resolve";
|
|
7
|
+
import typescript from "rollup-plugin-typescript2";
|
|
8
|
+
import livereload from "rollup-plugin-livereload"; // hot
|
|
9
|
+
import serve from "rollup-plugin-serve";
|
|
10
|
+
|
|
11
|
+
export default {
|
|
12
|
+
input: "./src/main.ts",
|
|
13
|
+
|
|
14
|
+
output: [
|
|
15
|
+
{
|
|
16
|
+
format: "cjs",
|
|
17
|
+
file: "lib/bundle.cjs.js",
|
|
18
|
+
sourcemap: true,
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
format: "es",
|
|
22
|
+
file: "lib/bundle.esm.js",
|
|
23
|
+
sourcemap: true,
|
|
24
|
+
},
|
|
25
|
+
],
|
|
26
|
+
|
|
27
|
+
plugins: [
|
|
28
|
+
resolve({
|
|
29
|
+
// 将自定义选项传递给解析插件
|
|
30
|
+
customResolveOptions: {
|
|
31
|
+
moduleDirectory: "node_modules",
|
|
32
|
+
},
|
|
33
|
+
}),
|
|
34
|
+
commonjs(),
|
|
35
|
+
typescript(),
|
|
36
|
+
sourceMaps(),
|
|
37
|
+
uglify(), // 压缩代码
|
|
38
|
+
livereload(),
|
|
39
|
+
babel({
|
|
40
|
+
runtimeHelpers: true,
|
|
41
|
+
// 只转换源代码,不运行外部依赖
|
|
42
|
+
exclude: "node_modules/**",
|
|
43
|
+
babelHelpers: "bundled",
|
|
44
|
+
}),
|
|
45
|
+
serve({
|
|
46
|
+
open: true,
|
|
47
|
+
port: 10801,
|
|
48
|
+
contentBase: ["", "./public"],
|
|
49
|
+
}),
|
|
50
|
+
],
|
|
51
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "./uniqueArrayByProperty";
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @description: 对象数组中去重处理
|
|
3
|
+
* @param array 数据源
|
|
4
|
+
* @param key 根据类型
|
|
5
|
+
* @return T[]
|
|
6
|
+
*/
|
|
7
|
+
export function uniqueArrayByProperty<T>(array: T[], key: keyof T): T[] {
|
|
8
|
+
return array.reduce((acc, item) => {
|
|
9
|
+
if (!acc.some((existingItem) => existingItem[key] === item[key])) {
|
|
10
|
+
acc.push(item);
|
|
11
|
+
}
|
|
12
|
+
return acc;
|
|
13
|
+
}, [] as T[]);
|
|
14
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @description: 深拷贝
|
|
3
|
+
* @param {any} obj
|
|
4
|
+
* @return {*} obj
|
|
5
|
+
*/
|
|
6
|
+
export const deepClone = <T = any>(obj: T): T => {
|
|
7
|
+
if (obj === null || typeof obj !== "object") {
|
|
8
|
+
return obj;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
if (Array.isArray(obj)) {
|
|
12
|
+
const arrCopy: any[] = [];
|
|
13
|
+
for (const item of obj) {
|
|
14
|
+
arrCopy.push(deepClone(item));
|
|
15
|
+
}
|
|
16
|
+
return arrCopy as any;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
const objCopy: { [key: string]: any } = {};
|
|
20
|
+
for (const key in obj) {
|
|
21
|
+
if (obj.hasOwnProperty(key)) {
|
|
22
|
+
objCopy[key] = deepClone((obj as { [key: string]: any })[key]);
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
return objCopy as T;
|
|
26
|
+
};
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @description: 过滤筛选树 -- search tree
|
|
3
|
+
* @param origin 数据源
|
|
4
|
+
* @param id
|
|
5
|
+
* @return new tree data 纯函数
|
|
6
|
+
*/
|
|
7
|
+
export function deleteTreeNode<T extends TreeData>(origin: T[], id: string | number, key: keyof T = "id"): T[] {
|
|
8
|
+
return origin.filter((node) => {
|
|
9
|
+
if (node.children) {
|
|
10
|
+
node.children = deleteTreeNode(node.children as T[], id, key);
|
|
11
|
+
}
|
|
12
|
+
return node[key] !== id;
|
|
13
|
+
});
|
|
14
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @description: 查找树节点
|
|
3
|
+
* @param origin 数据源
|
|
4
|
+
* @param findValue 找到节点
|
|
5
|
+
* @param key 默认id
|
|
6
|
+
* @return T
|
|
7
|
+
*/
|
|
8
|
+
export function findTreeNode<T extends TreeData>(origin: T[], findValue: any, key: keyof T = "id"): T | null {
|
|
9
|
+
let result: T | null = null;
|
|
10
|
+
|
|
11
|
+
const fun = (data: T[]) => {
|
|
12
|
+
if (Array.isArray(data)) {
|
|
13
|
+
for (let i = 0; i < data.length; i++) {
|
|
14
|
+
let item = data[i];
|
|
15
|
+
if (item[key] === findValue) {
|
|
16
|
+
result = item;
|
|
17
|
+
return;
|
|
18
|
+
}
|
|
19
|
+
if (item.children && item.children.length) {
|
|
20
|
+
fun(item.children as T[]);
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
fun(origin);
|
|
27
|
+
return result;
|
|
28
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @description: 过滤筛选树 -- search tree
|
|
3
|
+
* @param treeData 数据源
|
|
4
|
+
* @param findStr 关键字
|
|
5
|
+
* @param label 关键字段
|
|
6
|
+
* @return new tree data
|
|
7
|
+
*/
|
|
8
|
+
export const fuzzySearchTree = <T extends TreeData>(treeData: T[], findStr: string, label: keyof T = "title"): T[] => {
|
|
9
|
+
if (!treeData) return [];
|
|
10
|
+
let list: T[] = [];
|
|
11
|
+
|
|
12
|
+
treeData.forEach((item) => {
|
|
13
|
+
// 确保label属性是字符串并且包含findStr
|
|
14
|
+
if (typeof item[label] === "string" && (item[label] as string).includes(findStr)) {
|
|
15
|
+
// 递归处理子节点
|
|
16
|
+
let children = item.children ? fuzzySearchTree(item.children as T[], findStr, label) : [];
|
|
17
|
+
|
|
18
|
+
// 如果子节点中没有匹配的项,则保留原子节点
|
|
19
|
+
children = children.length > 0 ? children : (item.children as T[]);
|
|
20
|
+
|
|
21
|
+
// 构造新的节点,保留匹配的子节点
|
|
22
|
+
const obj = { ...item, children };
|
|
23
|
+
list.push(obj);
|
|
24
|
+
} else if (item.children && item.children.length > 0) {
|
|
25
|
+
// 如果当前节点不匹配,但有子节点,则递归处理子节点
|
|
26
|
+
const children = fuzzySearchTree(item.children as T[], findStr, label);
|
|
27
|
+
|
|
28
|
+
// 如果子节点中有匹配的项,则保留当前节点,并更新其子节点
|
|
29
|
+
if (children.length > 0) {
|
|
30
|
+
const obj = { ...item, children };
|
|
31
|
+
list.push(obj);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
return list;
|
|
37
|
+
};
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @description: tree data -> 扁平树
|
|
3
|
+
* @param origin 数据源
|
|
4
|
+
* @return treedata
|
|
5
|
+
*/
|
|
6
|
+
export function toFlatTree(origin: TreeData[]) {
|
|
7
|
+
return origin.reduce((res, item) => {
|
|
8
|
+
const { children, ...i } = item;
|
|
9
|
+
return res.concat(i, children && children.length ? toFlatTree(children) : []);
|
|
10
|
+
}, []);
|
|
11
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @description: 扁平树 -> tree data
|
|
3
|
+
* @param origins 数据源
|
|
4
|
+
* @param parentId 父级ID
|
|
5
|
+
* @return 平铺数据
|
|
6
|
+
*/
|
|
7
|
+
export function toTreeFlat<T extends TreeData>(origin: T[], parentId: number | string = "root") {
|
|
8
|
+
// treeArr 变量数据
|
|
9
|
+
// 第一次:查找所有parentId为的数据组成第一级
|
|
10
|
+
const child = origin.filter((item: any) => item.parentId === parentId);
|
|
11
|
+
// 第一次:循环parentId为数组
|
|
12
|
+
return child.map((item: T) => {
|
|
13
|
+
return {
|
|
14
|
+
...item,
|
|
15
|
+
// 当前存在id(id与parentId应该是必须有的)调用initTree() 查找所有parentId为本id的数据
|
|
16
|
+
children: toTreeFlat(origin, item.id),
|
|
17
|
+
};
|
|
18
|
+
});
|
|
19
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @description: 下载文件
|
|
3
|
+
* @param stream 文件源,string or buffer
|
|
4
|
+
* @param name 文件名称
|
|
5
|
+
* @param mimeType type josn
|
|
6
|
+
* @return new tree data 纯函数
|
|
7
|
+
*/
|
|
8
|
+
export const downFile = (stream: string | ArrayBuffer, name: string, mimeType: string = "text/plain;charset=utf-8") => {
|
|
9
|
+
// 创建 Blob 对象
|
|
10
|
+
let blob: Blob;
|
|
11
|
+
if (typeof stream === "string") {
|
|
12
|
+
blob = new Blob([stream], { type: mimeType });
|
|
13
|
+
} else {
|
|
14
|
+
blob = new Blob([stream], { type: mimeType });
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
// 创建下载链接并触发下载
|
|
18
|
+
const a = document.createElement("a");
|
|
19
|
+
a.href = URL.createObjectURL(blob);
|
|
20
|
+
a.download = name;
|
|
21
|
+
a.style.display = "none";
|
|
22
|
+
document.body.appendChild(a);
|
|
23
|
+
a.click();
|
|
24
|
+
document.body.removeChild(a);
|
|
25
|
+
|
|
26
|
+
// 清理创建的 URL 对象
|
|
27
|
+
URL.revokeObjectURL(a.href);
|
|
28
|
+
};
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { downFile } from "./downFile";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @description: 拉流下载方法
|
|
5
|
+
* @param path 下载url
|
|
6
|
+
* @param defaultName 匹配请求如果没有使用名称
|
|
7
|
+
* @param token 鉴权 Authorization
|
|
8
|
+
* @param params 参数 object
|
|
9
|
+
*/
|
|
10
|
+
export const downStream = (path: string, defaultName: string, token?: string, params?: Record<string, any>) => {
|
|
11
|
+
// 处理查询参数
|
|
12
|
+
const queryParams = new URLSearchParams(params).toString();
|
|
13
|
+
const urlWithParams = queryParams ? `${path}?${queryParams}` : path;
|
|
14
|
+
|
|
15
|
+
const xhr = new XMLHttpRequest();
|
|
16
|
+
xhr.open("GET", urlWithParams);
|
|
17
|
+
xhr.responseType = "blob";
|
|
18
|
+
|
|
19
|
+
if (token) xhr.setRequestHeader("Authorization", token);
|
|
20
|
+
xhr.onload = function () {
|
|
21
|
+
if (xhr.status === 200 || xhr.status === 304) {
|
|
22
|
+
const disposition = xhr.getResponseHeader("Content-Disposition");
|
|
23
|
+
let filename = defaultName;
|
|
24
|
+
|
|
25
|
+
// 从 Content-Disposition 中提取文件名
|
|
26
|
+
if (disposition && disposition.indexOf("attachment") !== -1) {
|
|
27
|
+
const filenameRegex = /filename[^;=\n]*=((['"]).*?\2|[^;\n]*)/;
|
|
28
|
+
const matches = filenameRegex.exec(disposition);
|
|
29
|
+
if (matches != null && matches[1]) {
|
|
30
|
+
filename = matches[1].replace(/['"]/g, "");
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
// 下载文件
|
|
35
|
+
downFile(this.response, filename);
|
|
36
|
+
} else {
|
|
37
|
+
console.error(`Failed to download file. Status: ${xhr.status}`);
|
|
38
|
+
}
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
xhr.onerror = function () {
|
|
42
|
+
console.error("Request failed.");
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
xhr.send();
|
|
46
|
+
};
|
package/src/main.ts
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @description: 将params code 转成 object
|
|
3
|
+
* @param {string} [queryString]
|
|
4
|
+
* @return {*} object
|
|
5
|
+
*/
|
|
6
|
+
export const decodeParams = (queryString: string) => {
|
|
7
|
+
const params = new URLSearchParams(queryString);
|
|
8
|
+
// 使用 Array.from 将迭代器转换为数组,然后使用 reduce 将数组转换为对象
|
|
9
|
+
return Array.from(params.entries()).reduce((acc: any, [key, value]) => {
|
|
10
|
+
acc[key] = value;
|
|
11
|
+
return acc;
|
|
12
|
+
}, {});
|
|
13
|
+
};
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @description: 将params code 转成 object
|
|
3
|
+
* @param {objct} [str:string]:any
|
|
4
|
+
* @return {*} string
|
|
5
|
+
*/
|
|
6
|
+
export const encodeParams = (query: Record<string, any>) => {
|
|
7
|
+
const queryString = "?" + new URLSearchParams(query).toString();
|
|
8
|
+
return queryString;
|
|
9
|
+
};
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @web 环境下才能使用注册
|
|
3
|
+
* 包含了storage 增删改查封装 存储监听等功能
|
|
4
|
+
* 监听的方式使用的浏览器evet 事件模型
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
export * from "./local";
|
|
8
|
+
export * from "./session";
|
|
9
|
+
|
|
10
|
+
// init envet storage change
|
|
11
|
+
const monitorLocalStorage = () => {
|
|
12
|
+
let originalSetItem = localStorage.setItem;
|
|
13
|
+
//重写setItem函数
|
|
14
|
+
localStorage.setItem = function (key, newValue) {
|
|
15
|
+
//创建setItemEvent事件
|
|
16
|
+
let event = new Event("setLocal") as any;
|
|
17
|
+
event.key = key;
|
|
18
|
+
event.newValue = newValue;
|
|
19
|
+
//提交setItemEvent事件
|
|
20
|
+
window.dispatchEvent(event);
|
|
21
|
+
//执行原setItem函数
|
|
22
|
+
originalSetItem.call(this, key, newValue);
|
|
23
|
+
};
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* @这个方法实际没多大用
|
|
29
|
+
*/
|
|
30
|
+
const monitorSessionStorage = () => {
|
|
31
|
+
let originalSetItem = sessionStorage.setItem;
|
|
32
|
+
//重写setItem函数
|
|
33
|
+
sessionStorage.setItem = function (key, newValue) {
|
|
34
|
+
//创建setItemEvent事件
|
|
35
|
+
let event = new Event("setSessoin") as any;
|
|
36
|
+
event.key = key;
|
|
37
|
+
event.newValue = newValue;
|
|
38
|
+
//提交setItemEvent事件
|
|
39
|
+
window.dispatchEvent(event);
|
|
40
|
+
//执行原setItem函数
|
|
41
|
+
originalSetItem.call(this, key, newValue);
|
|
42
|
+
};
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
// 用于local 监听
|
|
46
|
+
const monitorStorage = () => {
|
|
47
|
+
monitorLocalStorage();
|
|
48
|
+
monitorSessionStorage();
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
monitorStorage();
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @description: get value
|
|
3
|
+
* @param {type: String}
|
|
4
|
+
* @return: [Object,String,null]
|
|
5
|
+
*/
|
|
6
|
+
export function getLocalStorage(key: string): any {
|
|
7
|
+
let storageData = localStorage.getItem(key);
|
|
8
|
+
if (storageData) {
|
|
9
|
+
let storage;
|
|
10
|
+
try {
|
|
11
|
+
storage = JSON.parse(storageData);
|
|
12
|
+
} catch (err) {
|
|
13
|
+
storage = storageData;
|
|
14
|
+
}
|
|
15
|
+
return storage;
|
|
16
|
+
}
|
|
17
|
+
return storageData;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* @description: set value
|
|
22
|
+
* @param {[key,data]}
|
|
23
|
+
* @return:void
|
|
24
|
+
*/
|
|
25
|
+
export function setLocalStorage(key: string, data: any) {
|
|
26
|
+
typeof data === "string" ? localStorage.setItem(key, data) : localStorage.setItem(key, JSON.stringify(data));
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* @description: remove
|
|
31
|
+
* @param { arguments }
|
|
32
|
+
* @return: [Array,undefined]
|
|
33
|
+
*/
|
|
34
|
+
export function removeLocalStorageKey(...args: string[]) {
|
|
35
|
+
let errArgs: string[] = [];
|
|
36
|
+
args.forEach((item) => {
|
|
37
|
+
typeof item === "string" ? localStorage.removeItem(item) : errArgs.push(item);
|
|
38
|
+
});
|
|
39
|
+
return errArgs.length ? { errMsg: "error param", errKey: errArgs } : undefined;
|
|
40
|
+
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @description: sessionStorage Value
|
|
3
|
+
* @param {type: String}
|
|
4
|
+
* @return: [Object,String,null]
|
|
5
|
+
*/
|
|
6
|
+
export function getSessionStorage(key: string): any {
|
|
7
|
+
let storageData = sessionStorage.getItem(key);
|
|
8
|
+
if (storageData) {
|
|
9
|
+
let storage;
|
|
10
|
+
try {
|
|
11
|
+
storage = JSON.parse(storageData);
|
|
12
|
+
} catch (err) {
|
|
13
|
+
storage = storageData;
|
|
14
|
+
}
|
|
15
|
+
return storage;
|
|
16
|
+
}
|
|
17
|
+
return storageData;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* @description: sessionStorage set Value
|
|
22
|
+
* @param {[key,data]}
|
|
23
|
+
* @return:void
|
|
24
|
+
*/
|
|
25
|
+
export function setSessionStorage(key: string, data: any) {
|
|
26
|
+
typeof data === "string" ? sessionStorage.setItem(key, data) : sessionStorage.setItem(key, JSON.stringify(data));
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* @description: remove sessionStorage key
|
|
31
|
+
* @param { arguments }
|
|
32
|
+
* @return: [Array,undefined]
|
|
33
|
+
*/
|
|
34
|
+
export function removeSessionStorageKey(...args: string[]) {
|
|
35
|
+
let errArgs: string[] = [];
|
|
36
|
+
args.forEach((item) => {
|
|
37
|
+
typeof item === "string" ? sessionStorage.removeItem(item) : errArgs.push(item);
|
|
38
|
+
});
|
|
39
|
+
return errArgs.length ? { errMsg: "error param", errKey: errArgs } : undefined;
|
|
40
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @description: 复制文本
|
|
3
|
+
* @param {string} content
|
|
4
|
+
* @return {*} string
|
|
5
|
+
*/
|
|
6
|
+
export const copyText = (text: string) => {
|
|
7
|
+
if (navigator.clipboard && window.isSecureContext) {
|
|
8
|
+
// navigator clipboard 向剪贴板写文本
|
|
9
|
+
return navigator.clipboard.writeText(text);
|
|
10
|
+
} else {
|
|
11
|
+
const textarea = document.createElement("textarea");
|
|
12
|
+
textarea.value = text;
|
|
13
|
+
document.body.appendChild(textarea);
|
|
14
|
+
textarea.select();
|
|
15
|
+
document.execCommand("copy");
|
|
16
|
+
document.body.removeChild(textarea);
|
|
17
|
+
}
|
|
18
|
+
};
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
export function getTypeof(value: any): string {
|
|
2
|
+
return Object.prototype.toString.call(value).slice(8, -1);
|
|
3
|
+
}
|
|
4
|
+
|
|
5
|
+
export function isArray(value: any): boolean {
|
|
6
|
+
return getTypeof(value) === "Array";
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export function isBoolean(value: any): boolean {
|
|
10
|
+
return getTypeof(value) === "Boolean";
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export function isString(value: any): boolean {
|
|
14
|
+
return getTypeof(value) === "String";
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export function isNumber(value: any): boolean {
|
|
18
|
+
return getTypeof(value) === "Number";
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export function isObject(value: any): boolean {
|
|
22
|
+
return getTypeof(value) === "Object";
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export function isFunction(value: any): boolean {
|
|
26
|
+
return getTypeof(value) === "Function";
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export function isMap(value: any): boolean {
|
|
30
|
+
return getTypeof(value) === "Map";
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export function isSet(value: any): boolean {
|
|
34
|
+
return getTypeof(value) === "Set";
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export function isSymbol(value: any): boolean {
|
|
38
|
+
return getTypeof(value) === "Symbol";
|
|
39
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @description: 需要以字母开头的随机字符串
|
|
3
|
+
* @param length 字符串长度 默认8
|
|
4
|
+
* @return string
|
|
5
|
+
*/
|
|
6
|
+
export const generateString = (length: number = 8): string => {
|
|
7
|
+
const characters = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
|
|
8
|
+
const randomChar = () => characters.charAt(Math.floor(Math.random() * characters.length));
|
|
9
|
+
|
|
10
|
+
const timestamp = Date.now().toString(36); // Use timestamp for uniqueness
|
|
11
|
+
let result = timestamp + Array.from({ length: length - timestamp.length }, randomChar).join("");
|
|
12
|
+
|
|
13
|
+
return result.charAt(0).toUpperCase() + result.slice(1); // Ensure it starts with a letter
|
|
14
|
+
};
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @description: uuid
|
|
3
|
+
* @param template uuid模板 默认
|
|
4
|
+
* @return string
|
|
5
|
+
*/
|
|
6
|
+
export const generateUUID = (template: string = "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx"): string => {
|
|
7
|
+
// Helper function to generate a random hex digit
|
|
8
|
+
const randomHexDigit = (c: string): string => {
|
|
9
|
+
const r = crypto.getRandomValues(new Uint8Array(1))[0] & (15 >> (c === "x" ? 0 : 4));
|
|
10
|
+
return (c === "x" ? r : (r & 0x3) | 0x8).toString(16);
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
// Generate UUID based on template
|
|
14
|
+
return template.replace(/[xy]/g, randomHexDigit);
|
|
15
|
+
};
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import { describe, expect, test } from "@jest/globals";
|
|
2
|
+
import { getTypeof, isArray, isNumber, isString, isBoolean, isObject, isFunction } from "../src/main";
|
|
3
|
+
|
|
4
|
+
describe("utools", () => {
|
|
5
|
+
test("get value typeof", () => {
|
|
6
|
+
expect(getTypeof("string")).toBe("String");
|
|
7
|
+
});
|
|
8
|
+
});
|
|
9
|
+
|
|
10
|
+
describe("utools", () => {
|
|
11
|
+
test("get value typeof", () => {
|
|
12
|
+
expect(getTypeof(1024)).toBe("Number");
|
|
13
|
+
});
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
describe("utools", () => {
|
|
17
|
+
test("get value typeof", () => {
|
|
18
|
+
expect(getTypeof(false)).toBe("Boolean");
|
|
19
|
+
});
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
describe("utools", () => {
|
|
23
|
+
test("value is Array", () => {
|
|
24
|
+
expect(isArray([1, 2, 3])).toBe(true);
|
|
25
|
+
});
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
describe("utools", () => {
|
|
29
|
+
test("value is Array", () => {
|
|
30
|
+
expect(isArray({ name: "lx" })).toBe(false);
|
|
31
|
+
});
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
describe("utools", () => {
|
|
35
|
+
test("value is number", () => {
|
|
36
|
+
expect(isNumber("hello world")).toBe(false);
|
|
37
|
+
});
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
describe("utools", () => {
|
|
41
|
+
test("value is number", () => {
|
|
42
|
+
expect(isNumber(1024)).toBe(true);
|
|
43
|
+
});
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
describe("utools", () => {
|
|
47
|
+
test("value is string", () => {
|
|
48
|
+
expect(isString(1024)).toBe(false);
|
|
49
|
+
});
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
describe("utools", () => {
|
|
53
|
+
test("value is String", () => {
|
|
54
|
+
expect(isString("hello world")).toBe(true);
|
|
55
|
+
});
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
describe("utools", () => {
|
|
59
|
+
test("value is bol", () => {
|
|
60
|
+
expect(isObject({ name: "lx" })).toBe(true);
|
|
61
|
+
});
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
describe("utools", () => {
|
|
65
|
+
test("value is bol", () => {
|
|
66
|
+
expect(isBoolean(false)).toBe(true);
|
|
67
|
+
});
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
describe("utools", () => {
|
|
71
|
+
test("value is bol", () => {
|
|
72
|
+
expect(isFunction({ name: "lx" })).toBe(false);
|
|
73
|
+
});
|
|
74
|
+
});
|
package/tsconfig.json
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/* tsconfig.json */
|
|
2
|
+
{
|
|
3
|
+
"compilerOptions": {
|
|
4
|
+
/* 基础配置 */
|
|
5
|
+
"target": "esnext",
|
|
6
|
+
"lib": [
|
|
7
|
+
"dom",
|
|
8
|
+
"esnext"
|
|
9
|
+
],
|
|
10
|
+
"removeComments": false,
|
|
11
|
+
"declaration": true,
|
|
12
|
+
"sourceMap": true,
|
|
13
|
+
/* 强类型检查配置 */
|
|
14
|
+
"strict": true,
|
|
15
|
+
"noImplicitAny": false,
|
|
16
|
+
/* 模块分析配置 */
|
|
17
|
+
"baseUrl": ".",
|
|
18
|
+
"outDir": "./lib",
|
|
19
|
+
"esModuleInterop": true,
|
|
20
|
+
"moduleResolution": "node",
|
|
21
|
+
"resolveJsonModule": true
|
|
22
|
+
},
|
|
23
|
+
"include": [
|
|
24
|
+
"src"
|
|
25
|
+
]
|
|
26
|
+
}
|