feat: 添加工具方法
This commit is contained in:
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