react-util-tools 1.0.12 → 1.0.21
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/package.json +1 -1
- package/src/cookie/README.md +142 -0
- package/src/cookie/index.ts +116 -0
- package/src/format/index.ts +65 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "react-util-tools",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.21",
|
|
4
4
|
"description": "A collection of useful utilities: throttle, debounce, date formatting, device detection, money formatting, decimal calculations and more",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.cjs",
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
# Cookie 工具
|
|
2
|
+
|
|
3
|
+
提供常用的 Cookie 操作方法。
|
|
4
|
+
|
|
5
|
+
## 方法列表
|
|
6
|
+
|
|
7
|
+
### setCookie
|
|
8
|
+
|
|
9
|
+
设置 Cookie。
|
|
10
|
+
|
|
11
|
+
```typescript
|
|
12
|
+
setCookie(name: string, value: string, options?: CookieOptions): void
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
**参数:**
|
|
16
|
+
- `name`: Cookie 名称
|
|
17
|
+
- `value`: Cookie 值
|
|
18
|
+
- `options`: 可选配置
|
|
19
|
+
- `expires`: 过期时间(秒数或 Date 对象)
|
|
20
|
+
- `path`: Cookie 路径
|
|
21
|
+
- `domain`: Cookie 域名
|
|
22
|
+
- `secure`: 是否仅通过 HTTPS 传输
|
|
23
|
+
- `sameSite`: SameSite 属性('Strict' | 'Lax' | 'None')
|
|
24
|
+
|
|
25
|
+
**示例:**
|
|
26
|
+
```typescript
|
|
27
|
+
import { setCookie } from './cookie';
|
|
28
|
+
|
|
29
|
+
// 设置简单 Cookie
|
|
30
|
+
setCookie('username', 'john');
|
|
31
|
+
|
|
32
|
+
// 设置带过期时间的 Cookie(7天)
|
|
33
|
+
setCookie('token', 'abc123', { expires: 7 * 24 * 60 * 60 });
|
|
34
|
+
|
|
35
|
+
// 设置完整配置的 Cookie
|
|
36
|
+
setCookie('session', 'xyz789', {
|
|
37
|
+
expires: new Date('2025-12-31'),
|
|
38
|
+
path: '/',
|
|
39
|
+
domain: '.example.com',
|
|
40
|
+
secure: true,
|
|
41
|
+
sameSite: 'Strict'
|
|
42
|
+
});
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
### getCookie
|
|
46
|
+
|
|
47
|
+
获取指定名称的 Cookie 值。
|
|
48
|
+
|
|
49
|
+
```typescript
|
|
50
|
+
getCookie(name: string): string | null
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
**示例:**
|
|
54
|
+
```typescript
|
|
55
|
+
import { getCookie } from './cookie';
|
|
56
|
+
|
|
57
|
+
const username = getCookie('username');
|
|
58
|
+
console.log(username); // 'john' 或 null
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
### removeCookie
|
|
62
|
+
|
|
63
|
+
删除指定名称的 Cookie。
|
|
64
|
+
|
|
65
|
+
```typescript
|
|
66
|
+
removeCookie(name: string, options?: Pick<CookieOptions, 'path' | 'domain'>): void
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
**注意:** path 和 domain 需要与设置时保持一致才能正确删除。
|
|
70
|
+
|
|
71
|
+
**示例:**
|
|
72
|
+
```typescript
|
|
73
|
+
import { removeCookie } from './cookie';
|
|
74
|
+
|
|
75
|
+
removeCookie('username');
|
|
76
|
+
|
|
77
|
+
// 删除指定 path 和 domain 的 Cookie
|
|
78
|
+
removeCookie('session', { path: '/', domain: '.example.com' });
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
### hasCookie
|
|
82
|
+
|
|
83
|
+
检查指定名称的 Cookie 是否存在。
|
|
84
|
+
|
|
85
|
+
```typescript
|
|
86
|
+
hasCookie(name: string): boolean
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
**示例:**
|
|
90
|
+
```typescript
|
|
91
|
+
import { hasCookie } from './cookie';
|
|
92
|
+
|
|
93
|
+
if (hasCookie('token')) {
|
|
94
|
+
console.log('用户已登录');
|
|
95
|
+
}
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
### getAllCookies
|
|
99
|
+
|
|
100
|
+
获取所有 Cookie 的键值对。
|
|
101
|
+
|
|
102
|
+
```typescript
|
|
103
|
+
getAllCookies(): Record<string, string>
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
**示例:**
|
|
107
|
+
```typescript
|
|
108
|
+
import { getAllCookies } from './cookie';
|
|
109
|
+
|
|
110
|
+
const cookies = getAllCookies();
|
|
111
|
+
console.log(cookies); // { username: 'john', token: 'abc123', ... }
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
### clearAllCookies
|
|
115
|
+
|
|
116
|
+
清除所有 Cookie。
|
|
117
|
+
|
|
118
|
+
```typescript
|
|
119
|
+
clearAllCookies(options?: Pick<CookieOptions, 'path' | 'domain'>): void
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
**示例:**
|
|
123
|
+
```typescript
|
|
124
|
+
import { clearAllCookies } from './cookie';
|
|
125
|
+
|
|
126
|
+
clearAllCookies();
|
|
127
|
+
|
|
128
|
+
// 清除指定 path 的所有 Cookie
|
|
129
|
+
clearAllCookies({ path: '/' });
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
## 类型定义
|
|
133
|
+
|
|
134
|
+
```typescript
|
|
135
|
+
interface CookieOptions {
|
|
136
|
+
expires?: number | Date; // 过期时间(秒数或 Date 对象)
|
|
137
|
+
path?: string; // Cookie 路径
|
|
138
|
+
domain?: string; // Cookie 域名
|
|
139
|
+
secure?: boolean; // 是否仅 HTTPS
|
|
140
|
+
sameSite?: 'Strict' | 'Lax' | 'None'; // SameSite 属性
|
|
141
|
+
}
|
|
142
|
+
```
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cookie 操作工具类
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
export interface CookieOptions {
|
|
6
|
+
expires?: number | Date;
|
|
7
|
+
path?: string;
|
|
8
|
+
domain?: string;
|
|
9
|
+
secure?: boolean;
|
|
10
|
+
sameSite?: 'Strict' | 'Lax' | 'None';
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* 设置 Cookie
|
|
15
|
+
* @param name Cookie 名称
|
|
16
|
+
* @param value Cookie 值
|
|
17
|
+
* @param options Cookie 配置选项
|
|
18
|
+
*/
|
|
19
|
+
export function setCookie(name: string, value: string, options: CookieOptions = {}): void {
|
|
20
|
+
let cookieString = `${encodeURIComponent(name)}=${encodeURIComponent(value)}`;
|
|
21
|
+
|
|
22
|
+
if (options.expires) {
|
|
23
|
+
const expires = options.expires instanceof Date
|
|
24
|
+
? options.expires
|
|
25
|
+
: new Date(Date.now() + options.expires * 1000);
|
|
26
|
+
cookieString += `; expires=${expires.toUTCString()}`;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
if (options.path) {
|
|
30
|
+
cookieString += `; path=${options.path}`;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
if (options.domain) {
|
|
34
|
+
cookieString += `; domain=${options.domain}`;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
if (options.secure) {
|
|
38
|
+
cookieString += '; secure';
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
if (options.sameSite) {
|
|
42
|
+
cookieString += `; SameSite=${options.sameSite}`;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
document.cookie = cookieString;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* 获取 Cookie
|
|
50
|
+
* @param name Cookie 名称
|
|
51
|
+
* @returns Cookie 值,不存在则返回 null
|
|
52
|
+
*/
|
|
53
|
+
export function getCookie(name: string): string | null {
|
|
54
|
+
const nameEQ = encodeURIComponent(name) + '=';
|
|
55
|
+
const cookies = document.cookie.split(';');
|
|
56
|
+
|
|
57
|
+
for (let cookie of cookies) {
|
|
58
|
+
cookie = cookie.trim();
|
|
59
|
+
if (cookie.indexOf(nameEQ) === 0) {
|
|
60
|
+
return decodeURIComponent(cookie.substring(nameEQ.length));
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
return null;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* 删除 Cookie
|
|
69
|
+
* @param name Cookie 名称
|
|
70
|
+
* @param options Cookie 配置选项(path 和 domain 需要与设置时一致)
|
|
71
|
+
*/
|
|
72
|
+
export function removeCookie(name: string, options: Pick<CookieOptions, 'path' | 'domain'> = {}): void {
|
|
73
|
+
setCookie(name, '', {
|
|
74
|
+
...options,
|
|
75
|
+
expires: new Date(0)
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* 检查 Cookie 是否存在
|
|
81
|
+
* @param name Cookie 名称
|
|
82
|
+
* @returns 是否存在
|
|
83
|
+
*/
|
|
84
|
+
export function hasCookie(name: string): boolean {
|
|
85
|
+
return getCookie(name) !== null;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* 获取所有 Cookie
|
|
90
|
+
* @returns Cookie 键值对对象
|
|
91
|
+
*/
|
|
92
|
+
export function getAllCookies(): Record<string, string> {
|
|
93
|
+
const cookies: Record<string, string> = {};
|
|
94
|
+
const cookieArray = document.cookie.split(';');
|
|
95
|
+
|
|
96
|
+
for (let cookie of cookieArray) {
|
|
97
|
+
cookie = cookie.trim();
|
|
98
|
+
const [name, ...valueParts] = cookie.split('=');
|
|
99
|
+
if (name) {
|
|
100
|
+
cookies[decodeURIComponent(name)] = decodeURIComponent(valueParts.join('='));
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
return cookies;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
* 清除所有 Cookie
|
|
109
|
+
* @param options Cookie 配置选项(path 和 domain)
|
|
110
|
+
*/
|
|
111
|
+
export function clearAllCookies(options: Pick<CookieOptions, 'path' | 'domain'> = {}): void {
|
|
112
|
+
const cookies = getAllCookies();
|
|
113
|
+
for (const name in cookies) {
|
|
114
|
+
removeCookie(name, options);
|
|
115
|
+
}
|
|
116
|
+
}
|
package/src/format/index.ts
CHANGED
|
@@ -187,3 +187,68 @@ export function formatPercent(
|
|
|
187
187
|
const num = multiply ? value * 100 : value
|
|
188
188
|
return num.toFixed(decimals) + '%'
|
|
189
189
|
}
|
|
190
|
+
|
|
191
|
+
/**
|
|
192
|
+
* 邮箱脱敏:只展示前3个字符+@和后面的字符串,中间用***表示
|
|
193
|
+
* @param email 邮箱地址
|
|
194
|
+
* @returns 脱敏后的邮箱地址
|
|
195
|
+
* @example
|
|
196
|
+
* maskEmail('dj49846917@proton.me') // 'dj4***@proton.me'
|
|
197
|
+
* maskEmail('abc@example.com') // 'abc***@example.com'
|
|
198
|
+
*/
|
|
199
|
+
export function maskEmail(email: string): string {
|
|
200
|
+
if (!email || typeof email !== 'string') {
|
|
201
|
+
return ''
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
const atIndex = email.indexOf('@')
|
|
205
|
+
if (atIndex <= 0) {
|
|
206
|
+
return email // 无效邮箱,返回原值
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
const localPart = email.substring(0, atIndex)
|
|
210
|
+
const domainPart = email.substring(atIndex)
|
|
211
|
+
|
|
212
|
+
// 只展示前3个字符
|
|
213
|
+
const visiblePart = localPart.substring(0, 3)
|
|
214
|
+
|
|
215
|
+
return `${visiblePart}***${domainPart}`
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
/**
|
|
219
|
+
* 邮箱解脱敏:将脱敏的邮箱还原(需要提供原始邮箱)
|
|
220
|
+
* @param maskedEmail 脱敏后的邮箱地址
|
|
221
|
+
* @param originalEmail 原始邮箱地址
|
|
222
|
+
* @returns 解脱敏后的邮箱地址
|
|
223
|
+
* @example
|
|
224
|
+
* unmaskEmail('dj4***@proton.me', 'dj49846917@proton.me') // 'dj49846917@proton.me'
|
|
225
|
+
*/
|
|
226
|
+
export function unmaskEmail(maskedEmail: string, originalEmail: string): string {
|
|
227
|
+
if (!maskedEmail || !originalEmail) {
|
|
228
|
+
return ''
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
// 验证脱敏邮箱格式
|
|
232
|
+
if (!maskedEmail.includes('***@')) {
|
|
233
|
+
return maskedEmail // 不是脱敏格式,直接返回
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
// 验证原始邮箱和脱敏邮箱是否匹配
|
|
237
|
+
const maskedParts = maskedEmail.split('***@')
|
|
238
|
+
const atIndex = originalEmail.indexOf('@')
|
|
239
|
+
|
|
240
|
+
if (atIndex <= 0) {
|
|
241
|
+
return maskedEmail // 原始邮箱无效
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
const originalPrefix = originalEmail.substring(0, 3)
|
|
245
|
+
const originalDomain = originalEmail.substring(atIndex + 1)
|
|
246
|
+
const maskedDomain = maskedParts[1]
|
|
247
|
+
|
|
248
|
+
// 验证前缀和域名是否匹配
|
|
249
|
+
if (maskedParts[0] === originalPrefix && maskedDomain === originalDomain) {
|
|
250
|
+
return originalEmail
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
return maskedEmail // 不匹配,返回脱敏邮箱
|
|
254
|
+
}
|