@hzab/utils 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/CHANGELOG.md +2 -0
- package/README.md +120 -0
- package/package.json +58 -0
- package/src/array.ts +8 -0
- package/src/color.ts +302 -0
- package/src/file/file.ts +37 -0
- package/src/file/fileName.ts +75 -0
- package/src/file/fileType.ts +152 -0
- package/src/formily/schema-merge.ts +68 -0
- package/src/img-utils.ts +340 -0
- package/src/locationUtils.ts +26 -0
- package/src/nanoid.ts +10 -0
- package/src/options.ts +226 -0
- package/src/string.ts +19 -0
- package/src/upload/OfflineUpload.ts +338 -0
- package/src/upload/ossUpload.ts +181 -0
- package/src/upload/uploadUtils.ts +118 -0
- package/src/url.ts +120 -0
package/CHANGELOG.md
ADDED
package/README.md
ADDED
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
# @hzab/utils
|
|
2
|
+
|
|
3
|
+
组件模板
|
|
4
|
+
|
|
5
|
+
- node@16.16.0
|
|
6
|
+
|
|
7
|
+
- 注意:首次克隆先执行 npm run prepare 命令
|
|
8
|
+
|
|
9
|
+
# 组件
|
|
10
|
+
|
|
11
|
+
## ossUpload 示例
|
|
12
|
+
|
|
13
|
+
```jsx
|
|
14
|
+
import OssUpload from "@hzab/utils/src/ossUpload";
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* 批量文件上传
|
|
18
|
+
* @param {Array} files
|
|
19
|
+
* @param {Object} opt
|
|
20
|
+
* @returns
|
|
21
|
+
*/
|
|
22
|
+
export async function handleOssUpload(files, opt) {
|
|
23
|
+
const _files = files;
|
|
24
|
+
const { ossUrl, signatureParams, ossParams, axiosConf, useHashName } = opt || {};
|
|
25
|
+
const ossUpload = new OssUpload({
|
|
26
|
+
axios: opt.axios,
|
|
27
|
+
axiosConf: axiosConf,
|
|
28
|
+
serverUrl: ossUrl || "/api/v1/user/oss/getWebOssConfig",
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
const promise = [];
|
|
32
|
+
_files?.forEach((file) => {
|
|
33
|
+
if (!file) {
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
// 数据已经是 url 的情况
|
|
37
|
+
if (typeof file === "string" || file.ossUrl || file.url) {
|
|
38
|
+
promise.push(Promise.resolve(file));
|
|
39
|
+
} else {
|
|
40
|
+
promise.push(
|
|
41
|
+
ossUpload
|
|
42
|
+
.upload(file, {
|
|
43
|
+
signatureParams: {
|
|
44
|
+
isPublic: 1,
|
|
45
|
+
...(signatureParams || {}),
|
|
46
|
+
},
|
|
47
|
+
ossParams,
|
|
48
|
+
axiosConf,
|
|
49
|
+
useHashName,
|
|
50
|
+
})
|
|
51
|
+
.then((res) => {
|
|
52
|
+
return Promise.resolve(res?.data?.data?.fileUrl);
|
|
53
|
+
}),
|
|
54
|
+
);
|
|
55
|
+
}
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
return Promise.all(promise).then((filePromises) => {
|
|
59
|
+
filePromises?.forEach((fileUrl, idx) => {
|
|
60
|
+
if (typeof fileUrl === "string") {
|
|
61
|
+
_files[idx].ossUrl = fileUrl;
|
|
62
|
+
_files[idx].url = fileUrl;
|
|
63
|
+
} else if (_files[idx].url) {
|
|
64
|
+
_files[idx].ossUrl = _files[idx].url;
|
|
65
|
+
}
|
|
66
|
+
});
|
|
67
|
+
return Promise.resolve(_files);
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
## API
|
|
73
|
+
|
|
74
|
+
### InfoPanel Attributes
|
|
75
|
+
|
|
76
|
+
| 参数 | 类型 | 必填 | 默认值 | 说明 |
|
|
77
|
+
| ------ | ------ | ---- | ------ | ----------------- |
|
|
78
|
+
| schema | Object | 是 | - | 数据信息的 schema |
|
|
79
|
+
|
|
80
|
+
# 组件开发流程
|
|
81
|
+
|
|
82
|
+
- 在 config/webpack.config.js 中按需修改 library 配置的文件名
|
|
83
|
+
- 在 config/webpack.config.js 中按需修改 alias 配置的包名,便于本地调试
|
|
84
|
+
- 在 tsconfig.json 中按需修改 paths 配置的包名,解决 ts 报错问题
|
|
85
|
+
- npm run dev
|
|
86
|
+
|
|
87
|
+
## 文件目录
|
|
88
|
+
|
|
89
|
+
- example 本地开发测试代码
|
|
90
|
+
- src 组件源码
|
|
91
|
+
|
|
92
|
+
## 命令
|
|
93
|
+
|
|
94
|
+
- Mac 执行该命令,设置 pre-commit 为可执行文件
|
|
95
|
+
|
|
96
|
+
- npm run mac-chmod
|
|
97
|
+
- chmod +x .husky && chmod +x .husky/pre-commit
|
|
98
|
+
|
|
99
|
+
- 生成文档:npm run docs
|
|
100
|
+
- 本地运行:npm run dev
|
|
101
|
+
- 打包编译:npm run build
|
|
102
|
+
|
|
103
|
+
## 发布
|
|
104
|
+
|
|
105
|
+
- 注意:示例代码生效,但发布之后未生效。确认是否执行了编译!!!
|
|
106
|
+
|
|
107
|
+
- 编译组件:npm run build
|
|
108
|
+
- 命令:npm publish --access public
|
|
109
|
+
- 发布目录:
|
|
110
|
+
- src
|
|
111
|
+
|
|
112
|
+
## 配置
|
|
113
|
+
|
|
114
|
+
### 配置文件
|
|
115
|
+
|
|
116
|
+
- 本地配置文件:config/config.js
|
|
117
|
+
|
|
118
|
+
### webpack 配置文件
|
|
119
|
+
|
|
120
|
+
- config/webpack.config.js
|
package/package.json
ADDED
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@hzab/utils",
|
|
3
|
+
"version": "0.0.1",
|
|
4
|
+
"description": "utils",
|
|
5
|
+
"main": "src",
|
|
6
|
+
"scripts": {
|
|
7
|
+
"dev": "webpack serve -c ./config/webpack.config.js --env local",
|
|
8
|
+
"build": "webpack -c ./config/webpack.config.js --env production",
|
|
9
|
+
"publish-beta": "npm publish --beta",
|
|
10
|
+
"publish-patch": "npm version patch && npm publish --access public",
|
|
11
|
+
"publish-minor": "npm version minor && npm publish --access public",
|
|
12
|
+
"publish-major": "npm version major && npm publish --access public",
|
|
13
|
+
"prepare": "husky install",
|
|
14
|
+
"mac-chmod": "chmod +x .husky && chmod +x .husky/pre-commit",
|
|
15
|
+
"docs": "typedoc"
|
|
16
|
+
},
|
|
17
|
+
"files": [
|
|
18
|
+
"CHANGELOG.md",
|
|
19
|
+
"src"
|
|
20
|
+
],
|
|
21
|
+
"keywords": [],
|
|
22
|
+
"author": "CaiYansong",
|
|
23
|
+
"license": "ISC",
|
|
24
|
+
"devDependencies": {
|
|
25
|
+
"@hzab/data-model": "^1.8.1",
|
|
26
|
+
"@hzab/permissions": "^1.0.0",
|
|
27
|
+
"@hzab/webpack-config": "^1.1.2",
|
|
28
|
+
"@types/react": "^17.0.62",
|
|
29
|
+
"@types/react-dom": "^17.0.20",
|
|
30
|
+
"antd": "^4.24.16",
|
|
31
|
+
"axios": "^1.4.0",
|
|
32
|
+
"eslint": "^8.30.0",
|
|
33
|
+
"less": "^4.1.3",
|
|
34
|
+
"mobx": "^6.7.0",
|
|
35
|
+
"mobx-react": "^7.6.0",
|
|
36
|
+
"nanoid": "^3.3.7",
|
|
37
|
+
"react": "^17.0.2",
|
|
38
|
+
"react-dom": "^17.0.2",
|
|
39
|
+
"react-router-dom": "^6.14.1",
|
|
40
|
+
"typedoc": "^0.24.8",
|
|
41
|
+
"typescript": "^4.9.4"
|
|
42
|
+
},
|
|
43
|
+
"directories": {
|
|
44
|
+
"src": "src"
|
|
45
|
+
},
|
|
46
|
+
"peerDependencies": {
|
|
47
|
+
"@hzab/data-model": ">=1.2.0",
|
|
48
|
+
"antd": "4.x",
|
|
49
|
+
"axios": ">=1.6.2",
|
|
50
|
+
"react": ">=16.8.0",
|
|
51
|
+
"react-dom": ">=16.8.0"
|
|
52
|
+
},
|
|
53
|
+
"lint-staged": {
|
|
54
|
+
"**.{js,jsx,ts,tsx,css,scss,less,json,html}": [
|
|
55
|
+
"prettier --write"
|
|
56
|
+
]
|
|
57
|
+
}
|
|
58
|
+
}
|
package/src/array.ts
ADDED
package/src/color.ts
ADDED
|
@@ -0,0 +1,302 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 计算颜色的亮度
|
|
3
|
+
* @param r
|
|
4
|
+
* @param g
|
|
5
|
+
* @param b
|
|
6
|
+
* @returns
|
|
7
|
+
*/
|
|
8
|
+
export function luminance(r, g, b) {
|
|
9
|
+
const a = [r, g, b].map((v) => {
|
|
10
|
+
v /= 255;
|
|
11
|
+
return v <= 0.03928 ? v / 12.92 : Math.pow((v + 0.055) / 1.055, 2.4);
|
|
12
|
+
});
|
|
13
|
+
return a[0] * 0.2126 + a[1] * 0.7152 + a[2] * 0.0722;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* 计算两个颜色之间的对比度
|
|
18
|
+
* @param l1
|
|
19
|
+
* @param l2
|
|
20
|
+
* @returns
|
|
21
|
+
*/
|
|
22
|
+
export function contrast(l1, l2) {
|
|
23
|
+
const brightest = Math.max(l1, l2);
|
|
24
|
+
const darkest = Math.min(l1, l2);
|
|
25
|
+
return (brightest + 0.05) / (darkest + 0.05);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* 计算对比度
|
|
30
|
+
* @param luminance1
|
|
31
|
+
* @param luminance2
|
|
32
|
+
* @returns
|
|
33
|
+
*/
|
|
34
|
+
export function contrastRatio(luminance1, luminance2) {
|
|
35
|
+
return (Math.max(luminance1, luminance2) + 0.05) / (Math.min(luminance1, luminance2) + 0.05);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* 十六进制颜色转 RGB
|
|
40
|
+
* @param hex
|
|
41
|
+
* @returns
|
|
42
|
+
*/
|
|
43
|
+
export function hexToRGB(hex) {
|
|
44
|
+
hex = hex.replace("#", "");
|
|
45
|
+
if (hex.length === 3) {
|
|
46
|
+
hex = hex[0] + hex[0] + hex[1] + hex[1] + hex[2] + hex[2];
|
|
47
|
+
}
|
|
48
|
+
const r = parseInt(hex.substring(0, 2), 16);
|
|
49
|
+
const g = parseInt(hex.substring(2, 4), 16);
|
|
50
|
+
const b = parseInt(hex.substring(4, 6), 16);
|
|
51
|
+
return [r, g, b];
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* rgb 数值限制
|
|
56
|
+
* @param val
|
|
57
|
+
* @returns
|
|
58
|
+
*/
|
|
59
|
+
export function rgbNumLimit(val) {
|
|
60
|
+
if (val > 250) {
|
|
61
|
+
return 250;
|
|
62
|
+
}
|
|
63
|
+
if (val < 0) {
|
|
64
|
+
return 0;
|
|
65
|
+
}
|
|
66
|
+
return val;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* RGB 转十六进制颜色
|
|
71
|
+
* @param r
|
|
72
|
+
* @param g
|
|
73
|
+
* @param b
|
|
74
|
+
* @returns
|
|
75
|
+
*/
|
|
76
|
+
export function rgbToHex(r, g, b) {
|
|
77
|
+
return (
|
|
78
|
+
"#" +
|
|
79
|
+
[r, g, b]
|
|
80
|
+
.map((x) => {
|
|
81
|
+
const hex = x.toString(16);
|
|
82
|
+
return hex.length === 1 ? "0" + hex : hex;
|
|
83
|
+
})
|
|
84
|
+
.join("")
|
|
85
|
+
);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* RGB 转 HSL
|
|
90
|
+
* @param r
|
|
91
|
+
* @param g
|
|
92
|
+
* @param b
|
|
93
|
+
* @returns
|
|
94
|
+
*/
|
|
95
|
+
export function rgbToHsl(r, g, b) {
|
|
96
|
+
r /= 255;
|
|
97
|
+
g /= 255;
|
|
98
|
+
b /= 255;
|
|
99
|
+
const max = Math.max(r, g, b);
|
|
100
|
+
const min = Math.min(r, g, b);
|
|
101
|
+
let h,
|
|
102
|
+
s,
|
|
103
|
+
l = (max + min) / 2;
|
|
104
|
+
|
|
105
|
+
if (max === min) {
|
|
106
|
+
h = s = 0;
|
|
107
|
+
} else {
|
|
108
|
+
const d = max - min;
|
|
109
|
+
s = l > 0.5 ? d / (2 - max - min) : d / (max + min);
|
|
110
|
+
switch (max) {
|
|
111
|
+
case r:
|
|
112
|
+
h = (g - b) / d + (g < b ? 6 : 0);
|
|
113
|
+
break;
|
|
114
|
+
case g:
|
|
115
|
+
h = (b - r) / d + 2;
|
|
116
|
+
break;
|
|
117
|
+
case b:
|
|
118
|
+
h = (r - g) / d + 4;
|
|
119
|
+
break;
|
|
120
|
+
}
|
|
121
|
+
h /= 6;
|
|
122
|
+
}
|
|
123
|
+
return [h * 360, s * 100, l * 100];
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* HSL 转 RGB
|
|
128
|
+
* @param h
|
|
129
|
+
* @param s
|
|
130
|
+
* @param l
|
|
131
|
+
* @returns
|
|
132
|
+
*/
|
|
133
|
+
export function hslToRgb(h, s, l) {
|
|
134
|
+
h /= 360;
|
|
135
|
+
s /= 100;
|
|
136
|
+
l /= 100;
|
|
137
|
+
let r, g, b;
|
|
138
|
+
|
|
139
|
+
if (s === 0) {
|
|
140
|
+
r = g = b = l;
|
|
141
|
+
} else {
|
|
142
|
+
const hue2rgb = (p, q, t) => {
|
|
143
|
+
if (t < 0) t += 1;
|
|
144
|
+
if (t > 1) t -= 1;
|
|
145
|
+
if (t < 1 / 6) return p + (q - p) * 6 * t;
|
|
146
|
+
if (t < 1 / 2) return q;
|
|
147
|
+
if (t < 2 / 3) return p + (q - p) * (2 / 3 - t) * 6;
|
|
148
|
+
return p;
|
|
149
|
+
};
|
|
150
|
+
const q = l < 0.5 ? l * (1 + s) : l + s - l * s;
|
|
151
|
+
const p = 2 * l - q;
|
|
152
|
+
r = hue2rgb(p, q, h + 1 / 3);
|
|
153
|
+
g = hue2rgb(p, q, h);
|
|
154
|
+
b = hue2rgb(p, q, h - 1 / 3);
|
|
155
|
+
}
|
|
156
|
+
return [Math.round(r * 255), Math.round(g * 255), Math.round(b * 255)];
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
/**
|
|
160
|
+
* 判断是否为灰色背景
|
|
161
|
+
* @param r
|
|
162
|
+
* @param g
|
|
163
|
+
* @param b
|
|
164
|
+
* @returns
|
|
165
|
+
*/
|
|
166
|
+
export function isGray(r, g, b, opt = { tolerance: 10 }) {
|
|
167
|
+
const {
|
|
168
|
+
/**
|
|
169
|
+
* 允许的误差范围
|
|
170
|
+
*/
|
|
171
|
+
tolerance = 10,
|
|
172
|
+
} = opt || {}; //
|
|
173
|
+
return Math.abs(r - g) <= tolerance && Math.abs(g - b) <= tolerance && Math.abs(r - b) <= tolerance;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
/**
|
|
177
|
+
* 根据背景颜色选择合适的文本颜色(十六进制格式)
|
|
178
|
+
* @param backgroundColor
|
|
179
|
+
* @returns
|
|
180
|
+
*/
|
|
181
|
+
export function getTextColor(backgroundColor) {
|
|
182
|
+
let [r, g, b] = [0, 0, 0];
|
|
183
|
+
if (backgroundColor.startsWith("#")) {
|
|
184
|
+
[r, g, b] = hexToRGB(backgroundColor);
|
|
185
|
+
} else {
|
|
186
|
+
const div = document.createElement("div");
|
|
187
|
+
div.style.color = backgroundColor;
|
|
188
|
+
document.body.appendChild(div);
|
|
189
|
+
const cs = getComputedStyle(div);
|
|
190
|
+
const rgb = cs.color.match(/\d+/g).map(Number);
|
|
191
|
+
document.body.removeChild(div);
|
|
192
|
+
[r, g, b] = rgb;
|
|
193
|
+
}
|
|
194
|
+
const bgLuminance = luminance(r, g, b);
|
|
195
|
+
const whiteLuminance = luminance(255, 255, 255);
|
|
196
|
+
const blackLuminance = luminance(0, 0, 0);
|
|
197
|
+
const whiteContrast = contrast(bgLuminance, whiteLuminance);
|
|
198
|
+
const blackContrast = contrast(bgLuminance, blackLuminance);
|
|
199
|
+
return whiteContrast > blackContrast ? "#ffffff" : "#000000";
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
/**
|
|
203
|
+
* 根据背景亮度调整文字颜色深浅
|
|
204
|
+
* @param bgR
|
|
205
|
+
* @param bgG
|
|
206
|
+
* @param bgB
|
|
207
|
+
* @returns
|
|
208
|
+
*/
|
|
209
|
+
export function adjustTextColor(hexColor) {
|
|
210
|
+
const [bgR, bgG, bgB] = hexToRGB(hexColor);
|
|
211
|
+
const bgLuminance = luminance(bgR, bgG, bgB);
|
|
212
|
+
let textR, textG, textB;
|
|
213
|
+
const targetContrast = 4.5; // WCAG AA 标准
|
|
214
|
+
|
|
215
|
+
if (bgR === 0 && bgG === 0 && bgB === 0) {
|
|
216
|
+
// 黑色背景
|
|
217
|
+
let textR = 255,
|
|
218
|
+
textG = 255,
|
|
219
|
+
textB = 255;
|
|
220
|
+
let textLuminance = luminance(textR, textG, textB);
|
|
221
|
+
let ratio = contrastRatio(bgLuminance, textLuminance);
|
|
222
|
+
if (ratio < targetContrast) {
|
|
223
|
+
textR = 230;
|
|
224
|
+
textG = 230;
|
|
225
|
+
textB = 230;
|
|
226
|
+
}
|
|
227
|
+
return rgbToHex(textR, textG, textB);
|
|
228
|
+
} else if (bgR === 255 && bgG === 255 && bgB === 255) {
|
|
229
|
+
// 白色背景
|
|
230
|
+
let textR = 0,
|
|
231
|
+
textG = 0,
|
|
232
|
+
textB = 0;
|
|
233
|
+
let textLuminance = luminance(textR, textG, textB);
|
|
234
|
+
let ratio = contrastRatio(bgLuminance, textLuminance);
|
|
235
|
+
if (ratio < targetContrast) {
|
|
236
|
+
textR = 20;
|
|
237
|
+
textG = 20;
|
|
238
|
+
textB = 20;
|
|
239
|
+
}
|
|
240
|
+
return rgbToHex(textR, textG, textB);
|
|
241
|
+
} else if (isGray(bgR, bgG, bgB)) {
|
|
242
|
+
// 灰色背景
|
|
243
|
+
if (bgLuminance < 0.4) {
|
|
244
|
+
// 深色灰色背景,使用白色文字
|
|
245
|
+
let textR = 255,
|
|
246
|
+
textG = 255,
|
|
247
|
+
textB = 255;
|
|
248
|
+
let textLuminance = luminance(textR, textG, textB);
|
|
249
|
+
let ratio = contrastRatio(bgLuminance, textLuminance);
|
|
250
|
+
if (ratio < targetContrast) {
|
|
251
|
+
textR = 230;
|
|
252
|
+
textG = 230;
|
|
253
|
+
textB = 230;
|
|
254
|
+
}
|
|
255
|
+
return rgbToHex(textR, textG, textB);
|
|
256
|
+
} else {
|
|
257
|
+
// 浅色灰色背景,使用黑色文字
|
|
258
|
+
let textR = 0,
|
|
259
|
+
textG = 0,
|
|
260
|
+
textB = 0;
|
|
261
|
+
let textLuminance = luminance(textR, textG, textB);
|
|
262
|
+
let ratio = contrastRatio(bgLuminance, textLuminance);
|
|
263
|
+
if (ratio < targetContrast) {
|
|
264
|
+
textR = 20;
|
|
265
|
+
textG = 20;
|
|
266
|
+
textB = 20;
|
|
267
|
+
}
|
|
268
|
+
return rgbToHex(textR, textG, textB);
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
// 非黑白灰背景,使用差值颜色
|
|
273
|
+
const adjustNum = 150;
|
|
274
|
+
if (bgLuminance > 0.5) {
|
|
275
|
+
// 背景较亮,文字颜色调深
|
|
276
|
+
textR = Math.max(0, bgR - adjustNum);
|
|
277
|
+
textG = Math.max(0, bgG - adjustNum);
|
|
278
|
+
textB = Math.max(0, bgB - adjustNum);
|
|
279
|
+
} else {
|
|
280
|
+
// 背景较暗,文字颜色调亮
|
|
281
|
+
textR = Math.min(255, bgR + adjustNum);
|
|
282
|
+
textG = Math.min(255, bgG + adjustNum);
|
|
283
|
+
textB = Math.min(255, bgB + adjustNum);
|
|
284
|
+
}
|
|
285
|
+
return rgbToHex(textR, textG, textB);
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
/**
|
|
289
|
+
* 调整颜色深浅
|
|
290
|
+
* @param hexColor
|
|
291
|
+
* @param amount
|
|
292
|
+
* @returns
|
|
293
|
+
*/
|
|
294
|
+
export function adjustColor(hexColor, amount) {
|
|
295
|
+
const [r, g, b] = hexToRGB(hexColor);
|
|
296
|
+
|
|
297
|
+
const newR = rgbNumLimit(r + amount);
|
|
298
|
+
const newG = rgbNumLimit(g + amount);
|
|
299
|
+
const newB = rgbNumLimit(b + amount);
|
|
300
|
+
|
|
301
|
+
return rgbToHex(newR, newG, newB);
|
|
302
|
+
}
|
package/src/file/file.ts
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
export interface IFile extends File {
|
|
2
|
+
file?: IFile;
|
|
3
|
+
url?: string;
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* 建立一个可以存取该 file 的 url
|
|
8
|
+
* @param {Object} file 文件
|
|
9
|
+
* @returns {string} url
|
|
10
|
+
* blob:http://localhost:8000/c9950644-5118-4231-9be7-8183bde1fdc7
|
|
11
|
+
*/
|
|
12
|
+
export function getFileURL(file: IFile) {
|
|
13
|
+
const _file: IFile = file?.file || file;
|
|
14
|
+
if (!(_file instanceof File)) {
|
|
15
|
+
return;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
let url = _file.url || null;
|
|
19
|
+
|
|
20
|
+
try {
|
|
21
|
+
// 下面函数执行的效果是一样的,只是需要针对不同的浏览器执行不同的 js 函数而已
|
|
22
|
+
if (window.createObjectURL != undefined) {
|
|
23
|
+
// basic
|
|
24
|
+
return window.createObjectURL(_file);
|
|
25
|
+
} else if (window.URL != undefined) {
|
|
26
|
+
// mozilla(firefox)
|
|
27
|
+
return window.URL.createObjectURL(_file);
|
|
28
|
+
} else if (window.webkitURL != undefined) {
|
|
29
|
+
// webkit or chrome
|
|
30
|
+
return window.webkitURL.createObjectURL(_file);
|
|
31
|
+
}
|
|
32
|
+
} catch (error) {
|
|
33
|
+
console.warn("getFileURL Error: ", error);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
return url;
|
|
37
|
+
}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import { nanoidNumALetters } from "../nanoid";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* 获取文件后缀
|
|
5
|
+
* @param fileUrl
|
|
6
|
+
* @returns
|
|
7
|
+
*/
|
|
8
|
+
export function getFileExt(fileUrl) {
|
|
9
|
+
if (typeof fileUrl !== "string") {
|
|
10
|
+
return;
|
|
11
|
+
}
|
|
12
|
+
const res = fileUrl?.match(/([^\/]+?)\.([^\/\.]+)$/);
|
|
13
|
+
if (res && res.length > 2) {
|
|
14
|
+
return res[2];
|
|
15
|
+
}
|
|
16
|
+
return fileUrl;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* 从 url 获取文件名称,不包含后缀
|
|
21
|
+
* @param {string} fileName
|
|
22
|
+
* @param {string} str
|
|
23
|
+
* @returns
|
|
24
|
+
*/
|
|
25
|
+
export function getFileName(fileUrl) {
|
|
26
|
+
if (typeof fileUrl !== "string") {
|
|
27
|
+
return;
|
|
28
|
+
}
|
|
29
|
+
const res = fileUrl?.match(/([^\/]+?)\.[^\/\.]+$/);
|
|
30
|
+
if (res && res.length > 0) {
|
|
31
|
+
return res?.[1] || res?.[0];
|
|
32
|
+
}
|
|
33
|
+
return fileUrl;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* 从 url 获取文件名称,包含后缀
|
|
38
|
+
* @param {string} fileName
|
|
39
|
+
* @param {string} str
|
|
40
|
+
* @returns
|
|
41
|
+
*/
|
|
42
|
+
export function getFullFileName(fileUrl) {
|
|
43
|
+
if (typeof fileUrl !== "string") {
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
const res = fileUrl?.match(/[^\/]+?\.[^\/\.]+$/);
|
|
47
|
+
if (res && res.length > 0) {
|
|
48
|
+
return res[0];
|
|
49
|
+
}
|
|
50
|
+
return fileUrl;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* 合并文件名称,自动处理后缀
|
|
55
|
+
* @param {string} fileName
|
|
56
|
+
* @param {string} str
|
|
57
|
+
* @returns
|
|
58
|
+
*/
|
|
59
|
+
export const mergeFileName = function (fileName, str = "") {
|
|
60
|
+
if (typeof fileName !== "string") {
|
|
61
|
+
return "";
|
|
62
|
+
}
|
|
63
|
+
const name = fileName?.match(/([^\/]+?)\.[^\/]+$/)?.[1] || "";
|
|
64
|
+
const suffix = fileName?.match(/[^\/]+?\.([^\/]+)$/)?.[1] || "";
|
|
65
|
+
return `${name}${str ?? ""}.${suffix}`;
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* 获取唯一的文件名
|
|
70
|
+
* @param {string} fileName
|
|
71
|
+
* @returns
|
|
72
|
+
*/
|
|
73
|
+
export const getUFileName = function (fileName) {
|
|
74
|
+
return mergeFileName(getFileName(fileName) || "rc-upload", "-" + `~kid-${nanoidNumALetters()}~` + `${Date.now()}`);
|
|
75
|
+
};
|