feat: 添加工具方法
This commit is contained in:
@@ -12,8 +12,10 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@ant-design/icons": "^5.3.6",
|
"@ant-design/icons": "^5.3.6",
|
||||||
"@ant-design/pro-components": "^2.7.0",
|
"@ant-design/pro-components": "^2.7.0",
|
||||||
|
"@types/crypto-js": "^4.2.2",
|
||||||
"antd": "^5.16.1",
|
"antd": "^5.16.1",
|
||||||
"axios": "^1.6.8",
|
"axios": "^1.6.8",
|
||||||
|
"crypto-js": "^4.2.0",
|
||||||
"mobx": "^6.12.3",
|
"mobx": "^6.12.3",
|
||||||
"mobx-persist-store": "^1.1.4",
|
"mobx-persist-store": "^1.1.4",
|
||||||
"mobx-react": "^9.1.1",
|
"mobx-react": "^9.1.1",
|
||||||
|
|||||||
14
pnpm-lock.yaml
generated
14
pnpm-lock.yaml
generated
@@ -11,12 +11,18 @@ dependencies:
|
|||||||
'@ant-design/pro-components':
|
'@ant-design/pro-components':
|
||||||
specifier: ^2.7.0
|
specifier: ^2.7.0
|
||||||
version: 2.7.0(antd@5.16.1)(rc-field-form@1.44.0)(react-dom@18.2.0)(react@18.2.0)
|
version: 2.7.0(antd@5.16.1)(rc-field-form@1.44.0)(react-dom@18.2.0)(react@18.2.0)
|
||||||
|
'@types/crypto-js':
|
||||||
|
specifier: ^4.2.2
|
||||||
|
version: 4.2.2
|
||||||
antd:
|
antd:
|
||||||
specifier: ^5.16.1
|
specifier: ^5.16.1
|
||||||
version: 5.16.1(react-dom@18.2.0)(react@18.2.0)
|
version: 5.16.1(react-dom@18.2.0)(react@18.2.0)
|
||||||
axios:
|
axios:
|
||||||
specifier: ^1.6.8
|
specifier: ^1.6.8
|
||||||
version: 1.6.8
|
version: 1.6.8
|
||||||
|
crypto-js:
|
||||||
|
specifier: ^4.2.0
|
||||||
|
version: 4.2.0
|
||||||
mobx:
|
mobx:
|
||||||
specifier: ^6.12.3
|
specifier: ^6.12.3
|
||||||
version: 6.12.3
|
version: 6.12.3
|
||||||
@@ -1599,6 +1605,10 @@ packages:
|
|||||||
'@babel/types': 7.24.0
|
'@babel/types': 7.24.0
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
|
/@types/crypto-js@4.2.2:
|
||||||
|
resolution: {integrity: sha512-sDOLlVbHhXpAUAL0YHDUUwDZf3iN4Bwi4W6a0W0b+QcAezUbRtH4FVb+9J4h+XFPW7l/gQ9F8qC7P+Ec4k8QVQ==}
|
||||||
|
dev: false
|
||||||
|
|
||||||
/@types/estree@1.0.5:
|
/@types/estree@1.0.5:
|
||||||
resolution: {integrity: sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==}
|
resolution: {integrity: sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==}
|
||||||
|
|
||||||
@@ -2527,6 +2537,10 @@ packages:
|
|||||||
which: 2.0.2
|
which: 2.0.2
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
|
/crypto-js@4.2.0:
|
||||||
|
resolution: {integrity: sha512-KALDyEYgpY+Rlob/iriUtjV6d5Eq+Y191A5g4UqLAi8CyGP9N1+FdVbkc1SxKc2r4YAYqG8JzO2KGL+AizD70Q==}
|
||||||
|
dev: false
|
||||||
|
|
||||||
/css-functions-list@3.2.1:
|
/css-functions-list@3.2.1:
|
||||||
resolution: {integrity: sha512-Nj5YcaGgBtuUmn1D7oHqPW0c9iui7xsTsj5lIX8ZgevdfhmjFfKB3r8moHJtNJnctnYXJyYX5I1pp90HM4TPgQ==}
|
resolution: {integrity: sha512-Nj5YcaGgBtuUmn1D7oHqPW0c9iui7xsTsj5lIX8ZgevdfhmjFfKB3r8moHJtNJnctnYXJyYX5I1pp90HM4TPgQ==}
|
||||||
engines: {node: '>=12 || >=16'}
|
engines: {node: '>=12 || >=16'}
|
||||||
|
|||||||
42
src/App.css
42
src/App.css
@@ -1,42 +0,0 @@
|
|||||||
#root {
|
|
||||||
max-width: 1280px;
|
|
||||||
margin: 0 auto;
|
|
||||||
padding: 2rem;
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.logo {
|
|
||||||
height: 6em;
|
|
||||||
padding: 1.5em;
|
|
||||||
will-change: filter;
|
|
||||||
transition: filter 300ms;
|
|
||||||
}
|
|
||||||
.logo:hover {
|
|
||||||
filter: drop-shadow(0 0 2em #646cffaa);
|
|
||||||
}
|
|
||||||
.logo.react:hover {
|
|
||||||
filter: drop-shadow(0 0 2em #61dafbaa);
|
|
||||||
}
|
|
||||||
|
|
||||||
@keyframes logo-spin {
|
|
||||||
from {
|
|
||||||
transform: rotate(0deg);
|
|
||||||
}
|
|
||||||
to {
|
|
||||||
transform: rotate(360deg);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@media (prefers-reduced-motion: no-preference) {
|
|
||||||
a:nth-of-type(2) .logo {
|
|
||||||
animation: logo-spin infinite 20s linear;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.card {
|
|
||||||
padding: 2em;
|
|
||||||
}
|
|
||||||
|
|
||||||
.read-the-docs {
|
|
||||||
color: #888;
|
|
||||||
}
|
|
||||||
@@ -1 +1,85 @@
|
|||||||
|
/** 配置 */
|
||||||
|
interface Options {
|
||||||
|
/** key前缀 */
|
||||||
|
prefix?: string;
|
||||||
|
}
|
||||||
|
/** 默认配置 */
|
||||||
|
const defaultOptions: Options = {
|
||||||
|
prefix: ""
|
||||||
|
};
|
||||||
|
|
||||||
|
class CookieStorage {
|
||||||
|
private prefix: string;
|
||||||
|
|
||||||
|
constructor(options: Options = defaultOptions) {
|
||||||
|
const { prefix } = options;
|
||||||
|
this.prefix = prefix ?? "";
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description: 设置cookie
|
||||||
|
* @param {string} key 键
|
||||||
|
* @param {any} value 值
|
||||||
|
* @param {number} expires 过期时间s毫秒,不传默认2年有效
|
||||||
|
* @Date: 2023-05-17 18:10:34
|
||||||
|
* @Author: mulingyuer
|
||||||
|
*/
|
||||||
|
public setItem(key: string, value: string | number, expires?: number): void {
|
||||||
|
const timestamp = Date.now();
|
||||||
|
if (typeof expires === "number") {
|
||||||
|
expires = timestamp + expires;
|
||||||
|
} else {
|
||||||
|
expires = timestamp + 2 * 365 * 24 * 60 * 60 * 1000;
|
||||||
|
}
|
||||||
|
document.cookie = `${this.prefix}${key}=${value};expires=${new Date(expires).toUTCString()}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description: 获取cookie
|
||||||
|
* @param {string} key 键
|
||||||
|
* @Date: 2023-05-17 18:31:50
|
||||||
|
* @Author: mulingyuer
|
||||||
|
*/
|
||||||
|
public getItem(key: string): string | undefined {
|
||||||
|
const cookies = document.cookie.split("; ");
|
||||||
|
let val: string | undefined = undefined;
|
||||||
|
cookies.find((item) => {
|
||||||
|
const [k, v] = item.split("=");
|
||||||
|
if (k === `${this.prefix}${key}`) {
|
||||||
|
val = v;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description: 删除指定key的cookie
|
||||||
|
* @param {string} key 键
|
||||||
|
* @Date: 2023-05-17 18:32:56
|
||||||
|
* @Author: mulingyuer
|
||||||
|
*/
|
||||||
|
public removeItem(key: string): void {
|
||||||
|
this.setItem(key, "", -1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description: 清空所有cookie
|
||||||
|
* @Date: 2023-05-17 23:13:04
|
||||||
|
* @Author: mulingyuer
|
||||||
|
*/
|
||||||
|
public clear(): void {
|
||||||
|
const cookies = document.cookie.split("; ");
|
||||||
|
cookies.forEach((item) => {
|
||||||
|
const [k] = item.split("=");
|
||||||
|
this.removeItem(k);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const cookieStorage = new CookieStorage();
|
||||||
|
|
||||||
|
export default cookieStorage;
|
||||||
|
export { CookieStorage };
|
||||||
|
|||||||
102
src/utils/localStorage/config.ts
Normal file
102
src/utils/localStorage/config.ts
Normal file
@@ -0,0 +1,102 @@
|
|||||||
|
import { encrypt, decrypt } from './encry';
|
||||||
|
import { globalConfig } from './interface';
|
||||||
|
|
||||||
|
const config: globalConfig = {
|
||||||
|
type: 'localStorage', //存储类型,localStorage | sessionStorage
|
||||||
|
prefix: 'react-view-ui_0.0.1', //版本号
|
||||||
|
expire: 24 * 60, //过期时间,默认为一天,单位为分钟
|
||||||
|
isEncrypt: true, //支持加密、解密数据处理
|
||||||
|
};
|
||||||
|
|
||||||
|
const setStorage = (key: string, value: any, expire: number = 24 * 60): boolean => {
|
||||||
|
//设定值
|
||||||
|
if (value === '' || value === null || value === undefined) {
|
||||||
|
//空值重置
|
||||||
|
value = null;
|
||||||
|
}
|
||||||
|
if (isNaN(expire) || expire < 0) {
|
||||||
|
//过期时间值合理性判断
|
||||||
|
throw new Error('Expire must be a number');
|
||||||
|
}
|
||||||
|
const data = {
|
||||||
|
value, //存储值
|
||||||
|
time: Date.now(), //存储日期
|
||||||
|
expire: Date.now() + 1000 * 60 * expire, //过期时间
|
||||||
|
};
|
||||||
|
//是否需要加密,判断装载加密数据或原数据
|
||||||
|
window[config.type].setItem(
|
||||||
|
autoAddPreFix(key),
|
||||||
|
config.isEncrypt ? encrypt(JSON.stringify(data)) : JSON.stringify(data),
|
||||||
|
);
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
|
||||||
|
const getStorageFromKey = (key: string) => {
|
||||||
|
//获取指定值
|
||||||
|
if (config.prefix) {
|
||||||
|
key = autoAddPreFix(key);
|
||||||
|
}
|
||||||
|
if (!window[config.type].getItem(key)) {
|
||||||
|
//不存在判断
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
const storageVal = config.isEncrypt
|
||||||
|
? JSON.parse(decrypt(window[config.type].getItem(key) as string))
|
||||||
|
: JSON.parse(window[config.type].getItem(key) as string);
|
||||||
|
const now = Date.now();
|
||||||
|
if (now >= storageVal.expire) {
|
||||||
|
//过期销毁
|
||||||
|
removeStorageFromKey(key);
|
||||||
|
return null;
|
||||||
|
//不过期回值
|
||||||
|
} else {
|
||||||
|
return storageVal.value;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
const getAllStorage = () => {
|
||||||
|
//获取所有值
|
||||||
|
const storageList: any = {};
|
||||||
|
const keys = Object.keys(window[config.type]);
|
||||||
|
keys.forEach((key) => {
|
||||||
|
const value = getStorageFromKey(autoRemovePreFix(key));
|
||||||
|
if (value !== null) {
|
||||||
|
//如果值没有过期,加入到列表中
|
||||||
|
storageList[autoRemovePreFix(key)] = value;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return storageList;
|
||||||
|
};
|
||||||
|
const getStorageLength = () => {
|
||||||
|
//获取值列表长度
|
||||||
|
return window[config.type].length;
|
||||||
|
};
|
||||||
|
const removeStorageFromKey = (key: string) => {
|
||||||
|
//删除值
|
||||||
|
if (config.prefix) {
|
||||||
|
key = autoAddPreFix(key);
|
||||||
|
}
|
||||||
|
window[config.type].removeItem(key);
|
||||||
|
};
|
||||||
|
const clearStorage = () => {
|
||||||
|
window[config.type].clear();
|
||||||
|
};
|
||||||
|
const autoAddPreFix = (key: string) => {
|
||||||
|
//添加前缀,保持唯一性
|
||||||
|
const prefix = config.prefix || '';
|
||||||
|
return `${prefix}_${key}`;
|
||||||
|
};
|
||||||
|
const autoRemovePreFix = (key: string) => {
|
||||||
|
//删除前缀,进行增删改查
|
||||||
|
const lineIndex = config.prefix.length + 1;
|
||||||
|
return key.substr(lineIndex);
|
||||||
|
};
|
||||||
|
|
||||||
|
export {
|
||||||
|
setStorage,
|
||||||
|
getStorageFromKey,
|
||||||
|
getAllStorage,
|
||||||
|
getStorageLength,
|
||||||
|
removeStorageFromKey,
|
||||||
|
clearStorage,
|
||||||
|
};
|
||||||
37
src/utils/localStorage/encry.ts
Normal file
37
src/utils/localStorage/encry.ts
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
import CryptoJS from 'crypto-js';
|
||||||
|
|
||||||
|
const SECRET_KEY = CryptoJS.enc.Utf8.parse('3333e6e143439161'); //十六位十六进制数作为密钥
|
||||||
|
const SECRET_IV = CryptoJS.enc.Utf8.parse('e3bbe7e3ba84431a'); //十六位十六进制数作为密钥偏移量
|
||||||
|
|
||||||
|
const encrypt = (data: object | string): string => {
|
||||||
|
//加密
|
||||||
|
if (typeof data === 'object') {
|
||||||
|
try {
|
||||||
|
data = JSON.stringify(data);
|
||||||
|
} catch (e) {
|
||||||
|
throw new Error('encrypt error' + e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const dataHex = CryptoJS.enc.Utf8.parse(data);
|
||||||
|
const encrypted = CryptoJS.AES.encrypt(dataHex, SECRET_KEY, {
|
||||||
|
iv: SECRET_IV,
|
||||||
|
mode: CryptoJS.mode.CBC,
|
||||||
|
padding: CryptoJS.pad.Pkcs7,
|
||||||
|
});
|
||||||
|
return encrypted.ciphertext.toString();
|
||||||
|
};
|
||||||
|
|
||||||
|
const decrypt = (data: string) => {
|
||||||
|
//解密
|
||||||
|
const encryptedHexStr = CryptoJS.enc.Hex.parse(data);
|
||||||
|
const str = CryptoJS.enc.Base64.stringify(encryptedHexStr);
|
||||||
|
const decrypt = CryptoJS.AES.decrypt(str, SECRET_KEY, {
|
||||||
|
iv: SECRET_IV,
|
||||||
|
mode: CryptoJS.mode.CBC,
|
||||||
|
padding: CryptoJS.pad.Pkcs7,
|
||||||
|
});
|
||||||
|
const decryptedStr = decrypt.toString(CryptoJS.enc.Utf8);
|
||||||
|
return decryptedStr.toString();
|
||||||
|
};
|
||||||
|
|
||||||
|
export { encrypt, decrypt };
|
||||||
8
src/utils/localStorage/interface.ts
Normal file
8
src/utils/localStorage/interface.ts
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
interface globalConfig {
|
||||||
|
type: 'localStorage' | 'sessionStorage';
|
||||||
|
prefix: string;
|
||||||
|
expire: number;
|
||||||
|
isEncrypt: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export type { globalConfig };
|
||||||
Reference in New Issue
Block a user