feat: update

This commit is contained in:
landaiqing
2024-05-20 14:34:52 +08:00
parent 3d60f1478a
commit 7e87781c85
53 changed files with 3726 additions and 2537 deletions

View File

@@ -1,145 +1,101 @@
import axios, { AxiosInstance, AxiosRequestConfig } from 'axios'
import { message } from 'antd'
/** @format */
import axios, { AxiosInstance, AxiosRequestConfig } from "axios";
import { message } from "antd";
class Request {
private instance: AxiosInstance | undefined
private instance: AxiosInstance | undefined;
constructor(config: AxiosRequestConfig) {
this.instance = axios.create(config)
// 全局请求拦截
this.instance.interceptors.request.use(
(config) => {
return config
},
(error) => {
return Promise.reject(error)
},
)
constructor(config: AxiosRequestConfig) {
this.instance = axios.create(config);
// 全局请求拦截
this.instance.interceptors.request.use(
(config) => {
return config;
},
(error) => {
return Promise.reject(error);
},
);
// 全局响应拦截
this.instance.interceptors.response.use(
(res) => {
// if (res.data.code && res.data.code !== 200) {
// message.error(res.data.message).then()
// return Promise.reject(res.data)
// }
return res.data
},
(error) => {
const { response } = error
if (response) {
this.handleCode(response.status)
}
if (!window.navigator.onLine) {
message.error('网络连接失败')
// return router.push({
// path: '/404',
// })
return Promise.reject(error)
}
},
)
}
handleCode(code: number): void {
switch (code) {
case 400:
message.error('请求错误(400)')
break
case 401:
message.error('未授权,请重新登录(401)')
break
case 403:
message.error('拒绝访问(403)')
break
case 404:
message.error('请求出错(404)')
break
case 408:
message.error('请求超时(408)')
break
case 500:
message.error('服务器错误(500)')
break
case 501:
message.error('服务未实现(501)')
break
case 502:
message.error('网络错误(502)')
break
case 503:
message.error('服务不可用(503)')
break
case 504:
message.error('网络超时(504)')
break
case 505:
message.error('HTTP版本不受支持(505)')
break
default:
message.error(`连接出错(${code})!`)
break
}
}
request<T>(config: AxiosRequestConfig<T>): Promise<T> {
return new Promise<T>((resolve, reject) => {
this.instance
?.request<any, T>(config)
.then((res) => {
resolve(res)
})
.catch((err) => {
reject(err)
})
})
}
// 全局响应拦截
this.instance.interceptors.response.use(
(res) => {
// if (res.data.code && res.data.code !== 200) {
// message.error(res.data.message).then()
// return Promise.reject(res.data)
// }
return res.data;
},
(error) => {
const { response } = error;
if (response) {
this.handleCode(response.status);
}
if (!window.navigator.onLine) {
message.error("网络连接失败");
// return router.push({
// path: '/404',
// })
return Promise.reject(error);
}
},
);
}
get(url: string) {
return new Promise((resolve, reject) => {
this.instance
?.get(url)
.then((res) => {
resolve(res)
})
.catch((err) => {
reject(err)
})
})
}
handleCode(code: number): void {
switch (code) {
case 400:
message.error("请求错误(400)").then();
break;
case 401:
message.error("未授权,请重新登录(401)").then();
break;
case 403:
message.error("拒绝访问(403)").then();
break;
case 404:
message.error("请求出错(404)").then();
break;
case 408:
message.error("请求超时(408)").then();
break;
case 500:
message.error("服务器错误(500)").then();
break;
case 501:
message.error("服务未实现(501)").then();
break;
case 502:
message.error("网络错误(502)").then();
break;
case 503:
message.error("服务不可用(503)").then();
break;
case 504:
message.error("网络超时(504)").then();
break;
case 505:
message.error("HTTP版本不受支持(505)").then();
break;
default:
message.error(`连接出错(${code})!`).then();
break;
}
}
post(url: string, data = {}) {
return new Promise((resolve, reject) => {
this.instance
?.post(url, data)
.then((res) => {
resolve(res)
})
.catch((err) => {
reject(err)
})
})
}
put(url: string, data = {}) {
return new Promise((resolve, reject) => {
this.instance
?.put(url, data)
.then((res) => {
resolve(res)
})
.catch((err) => {
reject(err)
})
})
}
delete(url: string) {
return new Promise((resolve, reject) => {
this.instance
?.delete(url)
.then((res) => {
resolve(res)
})
.catch((err) => {
reject(err)
})
})
}
request<T>(config: AxiosRequestConfig<T>): Promise<T> {
return new Promise<T>((resolve, reject) => {
this.instance
?.request<any, T>(config)
.then((res) => {
resolve(res);
})
.catch((err) => {
reject(err);
});
});
}
}
export default Request
export default Request;

View File

@@ -1,14 +1,16 @@
import Request from './request'
import { handleLocalforage } from '@/utils/localforage'
/** @format */
const token = String(handleLocalforage.getItem('token'))
import Request from "./request";
import { handleLocalforage } from "@/utils/localforage";
const token = String(handleLocalforage.getItem("token"));
const web: Request = new Request({
baseURL: import.meta.env.VITE_APP_BASE_API,
headers: {
// 'Content-Type': 'application/json;charset=utf-8',
// Accept: 'application/json',
Authorization: token,
},
})
baseURL: import.meta.env.VITE_APP_BASE_API,
headers: {
// 'Content-Type': 'application/json;charset=utf-8',
// Accept: 'application/json',
Authorization: token,
},
});
export default web
export default web;

View File

@@ -1,85 +1,91 @@
/** 配置 */
/**
* 配置
*
* @format
*/
interface Options {
/** key前缀 */
prefix?: string
/** key前缀 */
prefix?: string;
}
/** 默认配置 */
const defaultOptions: Options = {
prefix: '',
}
prefix: "",
};
class CookieStorage {
private prefix: string
private prefix: string;
constructor(options: Options = defaultOptions) {
const { prefix } = options
this.prefix = prefix ?? ''
}
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 键
* @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
})
/**
* @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
}
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: 删除指定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)
})
}
/**
* @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()
const cookieStorage = new CookieStorage();
export default cookieStorage
export { CookieStorage }
export default cookieStorage;
export { CookieStorage };

View File

@@ -1,169 +1,173 @@
import JSEncrypt from 'jsencrypt'
import CryptoJS from 'crypto-js'
/** @format */
import JSEncrypt from "jsencrypt";
import CryptoJS from "crypto-js";
// 加密
export function rsaEncrypt(Str: string, afterPublicKey: string) {
const encryptor = new JSEncrypt()
encryptor.setPublicKey(afterPublicKey) // 设置公钥
return encryptor.encrypt(Str) // 对数据进行加密
const encryptor = new JSEncrypt();
encryptor.setPublicKey(afterPublicKey); // 设置公钥
return encryptor.encrypt(Str); // 对数据进行加密
}
// 解密
export function rsaDecrypt(Str: string, frontPrivateKey: string) {
const encryptor = new JSEncrypt()
encryptor.setPrivateKey(frontPrivateKey) // 设置私钥
return encryptor.decrypt(Str) // 对数据进行解密
const encryptor = new JSEncrypt();
encryptor.setPrivateKey(frontPrivateKey); // 设置私钥
return encryptor.decrypt(Str); // 对数据进行解密
}
export function aesEncrypt(aeskey: string, Str: string) {
// 设置一个默认值,如果第二个参数为空采用默认值,不为空则采用新设置的密钥
const key = CryptoJS.enc.Utf8.parse(aeskey)
const srcs = CryptoJS.enc.Utf8.parse(Str)
const encrypted = CryptoJS.AES.encrypt(srcs, key, {
// 切记 需要和后端算法模式一致
mode: CryptoJS.mode.ECB,
padding: CryptoJS.pad.Pkcs7,
})
// 设置一个默认值,如果第二个参数为空采用默认值,不为空则采用新设置的密钥
const key = CryptoJS.enc.Utf8.parse(aeskey);
const srcs = CryptoJS.enc.Utf8.parse(Str);
const encrypted = CryptoJS.AES.encrypt(srcs, key, {
// 切记 需要和后端算法模式一致
mode: CryptoJS.mode.ECB,
padding: CryptoJS.pad.Pkcs7,
});
return encrypted.toString()
return encrypted.toString();
}
export function aesDecrypt(aeskey: string, Str: string) {
const key = CryptoJS.enc.Utf8.parse(aeskey)
const decrypt = CryptoJS.AES.decrypt(Str, key, {
// 切记 需要和后端算法模式一致
mode: CryptoJS.mode.ECB,
padding: CryptoJS.pad.Pkcs7,
})
return CryptoJS.enc.Utf8.stringify(decrypt).toString()
const key = CryptoJS.enc.Utf8.parse(aeskey);
const decrypt = CryptoJS.AES.decrypt(Str, key, {
// 切记 需要和后端算法模式一致
mode: CryptoJS.mode.ECB,
padding: CryptoJS.pad.Pkcs7,
});
return CryptoJS.enc.Utf8.stringify(decrypt).toString();
}
/**
* 获取16位随机码AES
* @returns {string}
*/
export function get16RandomNum() {
const chars = [
'0',
'1',
'2',
'3',
'4',
'5',
'6',
'7',
'8',
'9',
'A',
'B',
'C',
'D',
'E',
'F',
'G',
'H',
'I',
'J',
'K',
'L',
'M',
'N',
'O',
'P',
'Q',
'R',
'S',
'T',
'U',
'V',
'W',
'X',
'Y',
'Z',
'a',
'b',
'c',
'd',
'e',
'f',
'g',
'h',
'i',
'j',
'k',
'l',
'm',
'n',
'o',
'p',
'q',
'r',
's',
't',
'u',
'v',
'w',
'x',
'y',
'z',
]
let nums = ''
//这个地方切记要选择16位因为美国对密钥长度有限制选择32位的话加解密会报错需要根据jdk版本去修改相关jar包有点恼火选择16位就不用处理。
for (let i = 0; i < 16; i++) {
const id = parseInt(String(Math.random() * 61))
nums += chars[id]
}
return nums
const chars = [
"0",
"1",
"2",
"3",
"4",
"5",
"6",
"7",
"8",
"9",
"A",
"B",
"C",
"D",
"E",
"F",
"G",
"H",
"I",
"J",
"K",
"L",
"M",
"N",
"O",
"P",
"Q",
"R",
"S",
"T",
"U",
"V",
"W",
"X",
"Y",
"Z",
"a",
"b",
"c",
"d",
"e",
"f",
"g",
"h",
"i",
"j",
"k",
"l",
"m",
"n",
"o",
"p",
"q",
"r",
"s",
"t",
"u",
"v",
"w",
"x",
"y",
"z",
];
let nums = "";
//这个地方切记要选择16位因为美国对密钥长度有限制选择32位的话加解密会报错需要根据jdk版本去修改相关jar包有点恼火选择16位就不用处理。
for (let i = 0; i < 16; i++) {
const id = parseInt(String(Math.random() * 61));
nums += chars[id];
}
return nums;
}
//获取rsa密钥对
export function getRsaKeys() {
return new Promise((resolve, reject) => {
window.crypto.subtle
.generateKey(
{
name: 'RSA-OAEP',
modulusLength: 2048, //can be 1024, 2048, or 4096
publicExponent: new Uint8Array([0x01, 0x00, 0x01]),
hash: { name: 'SHA-512' }, //can be "SHA-1", "SHA-256", "SHA-384", or "SHA-512"
},
true, //whether the key is extractable (i.e. can be used in exportKey)
['encrypt', 'decrypt'], //must be ["encrypt", "decrypt"] or ["wrapKey", "unwrapKey"]
)
.then(function (key) {
window.crypto.subtle
.exportKey('pkcs8', key.privateKey)
.then(function (keydata1) {
window.crypto.subtle
.exportKey('spki', key.publicKey)
.then(function (keydata2) {
const privateKey = RSA2text(keydata1, 1)
return new Promise((resolve, reject) => {
window.crypto.subtle
.generateKey(
{
name: "RSA-OAEP",
modulusLength: 2048, //can be 1024, 2048, or 4096
publicExponent: new Uint8Array([0x01, 0x00, 0x01]),
hash: { name: "SHA-512" }, //can be "SHA-1", "SHA-256", "SHA-384", or "SHA-512"
},
true, //whether the key is extractable (i.e. can be used in exportKey)
["encrypt", "decrypt"], //must be ["encrypt", "decrypt"] or ["wrapKey", "unwrapKey"]
)
.then(function (key) {
window.crypto.subtle
.exportKey("pkcs8", key.privateKey)
.then(function (keydata1) {
window.crypto.subtle
.exportKey("spki", key.publicKey)
.then(function (keydata2) {
const privateKey = RSA2text(keydata1, 1);
const publicKey = RSA2text(keydata2)
const publicKey = RSA2text(keydata2);
resolve({ privateKey, publicKey })
})
.catch(function (err) {
reject(err)
})
})
.catch(function (err) {
reject(err)
})
})
.catch(function (err) {
reject(err)
})
})
resolve({ privateKey, publicKey });
})
.catch(function (err) {
reject(err);
});
})
.catch(function (err) {
reject(err);
});
})
.catch(function (err) {
reject(err);
});
});
}
function RSA2text(buffer: any, _isPrivate: number = 0) {
let binary = ''
const bytes = new Uint8Array(buffer)
const len = bytes.byteLength
for (let i = 0; i < len; i++) {
binary += String.fromCharCode(bytes[i])
}
const base64 = window.btoa(binary)
const text = base64.replace(/[^\x00-\xff]/g, '$&\x01').replace(/.{64}\x01?/g, '$&\n')
let binary = "";
const bytes = new Uint8Array(buffer);
const len = bytes.byteLength;
for (let i = 0; i < len; i++) {
binary += String.fromCharCode(bytes[i]);
}
const base64 = window.btoa(binary);
const text = base64.replace(/[^\x00-\xff]/g, "$&\x01").replace(/.{64}\x01?/g, "$&\n");
return text
return text;
}

View File

@@ -1,102 +1,104 @@
import { encrypt, decrypt } from './encry'
import { globalConfig } from './interface'
/** @format */
import { encrypt, decrypt } from "./encry";
import { globalConfig } from "./interface";
const config: globalConfig = {
type: 'localStorage', //存储类型localStorage | sessionStorage
prefix: 'schisandra_', //版本号
expire: 24 * 60, //过期时间,默认为一天,单位为分钟
isEncrypt: true, //支持加密、解密数据处理
}
type: "localStorage", //存储类型localStorage | sessionStorage
prefix: "schisandra_", //版本号
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
}
//设定值
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
}
//获取指定值
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 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 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
}
//获取值列表长度
return window[config.type].length;
};
const removeStorageFromKey = (key: string) => {
//删除值
if (config.prefix) {
key = autoAddPreFix(key)
}
window[config.type].removeItem(key)
}
//删除值
if (config.prefix) {
key = autoAddPreFix(key);
}
window[config.type].removeItem(key);
};
const clearStorage = () => {
window[config.type].clear()
}
window[config.type].clear();
};
const autoAddPreFix = (key: string) => {
//添加前缀,保持唯一性
const prefix = config.prefix || ''
return `${prefix}_${key}`
}
//添加前缀,保持唯一性
const prefix = config.prefix || "";
return `${prefix}_${key}`;
};
const autoRemovePreFix = (key: string) => {
//删除前缀,进行增删改查
const lineIndex = config.prefix.length + 1
return key.substr(lineIndex)
}
//删除前缀,进行增删改查
const lineIndex = config.prefix.length + 1;
return key.substr(lineIndex);
};
export {
setStorage,
getStorageFromKey,
getAllStorage,
getStorageLength,
removeStorageFromKey,
clearStorage,
}
setStorage,
getStorageFromKey,
getAllStorage,
getStorageLength,
removeStorageFromKey,
clearStorage,
};

View File

@@ -1,37 +1,39 @@
import CryptoJS from 'crypto-js'
/** @format */
const SECRET_KEY = CryptoJS.enc.Utf8.parse('3333e6e143439161') //十六位十六进制数作为密钥
const SECRET_IV = CryptoJS.enc.Utf8.parse('e3bbe7e3ba84431a') //十六位十六进制数作为密钥偏移量
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()
}
//加密
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()
}
//解密
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 }
export { encrypt, decrypt };

View File

@@ -1,8 +1,10 @@
/** @format */
interface globalConfig {
type: 'localStorage' | 'sessionStorage'
prefix: string
expire: number
isEncrypt: boolean
type: "localStorage" | "sessionStorage";
prefix: string;
expire: number;
isEncrypt: boolean;
}
export type { globalConfig }
export type { globalConfig };

View File

@@ -1,74 +1,76 @@
import localforage from 'localforage'
import CryptoJS from 'crypto-js'
/** @format */
const SECRET_KEY = CryptoJS.enc.Utf8.parse('3333e6e143439161') //十六位十六进制数作为密钥
const SECRET_IV = CryptoJS.enc.Utf8.parse('e3bbe7e3ba84431a') //十六位十六进制数作为密钥偏移量
import localforage from "localforage";
import CryptoJS from "crypto-js";
const SECRET_KEY = CryptoJS.enc.Utf8.parse("3333e6e143439161"); //十六位十六进制数作为密钥
const SECRET_IV = CryptoJS.enc.Utf8.parse("e3bbe7e3ba84431a"); //十六位十六进制数作为密钥偏移量
/**
* 加密
* @param data
* @param output
*/
export const encrypt = (data: string, output?: any) => {
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(output)
}
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(output);
};
/**
* 解密
* @param data
*/
export const decrypt = (data: string | null) => {
if (data === null) {
return
}
const encryptedHex = CryptoJS.enc.Hex.parse(data)
const encryptedHexStr = CryptoJS.enc.Base64.stringify(encryptedHex)
const decrypted = CryptoJS.AES.decrypt(encryptedHexStr, SECRET_KEY, {
iv: SECRET_IV,
mode: CryptoJS.mode.CBC,
padding: CryptoJS.pad.Pkcs7,
})
const decryptedStr = decrypted.toString(CryptoJS.enc.Utf8)
return decryptedStr.toString()
}
if (data === null) {
return;
}
const encryptedHex = CryptoJS.enc.Hex.parse(data);
const encryptedHexStr = CryptoJS.enc.Base64.stringify(encryptedHex);
const decrypted = CryptoJS.AES.decrypt(encryptedHexStr, SECRET_KEY, {
iv: SECRET_IV,
mode: CryptoJS.mode.CBC,
padding: CryptoJS.pad.Pkcs7,
});
const decryptedStr = decrypted.toString(CryptoJS.enc.Utf8);
return decryptedStr.toString();
};
export const handleLocalforage = {
config: async (options?: LocalForageOptions) => localforage.config(options || {}),
setItem: async (key: string, value: string): Promise<void> => {
await localforage.setItem(key, encrypt(value))
},
getItem: async function getItem<T>(key: string): Promise<T | string | null> {
try {
const value: any = decrypt(await localforage.getItem(key)) as any
// 如果值是 undefined返回 null
if (value === undefined) {
return null
}
// 如果值是 T 类型,直接返回
if (typeof value === 'object' && value !== null) {
return value as T
}
// 如果值是 string 类型,直接返回
return value as string
} catch (error) {
console.error('Error retrieving data from localforage:', error)
return null
}
},
removeItem: async (key: string): Promise<void> => {
await localforage.removeItem(key)
},
clear: async () => {
return await localforage.clear()
},
createInstance: async (name: string) => {
return localforage.createInstance({
name,
})
},
}
config: async (options?: LocalForageOptions) => localforage.config(options || {}),
setItem: async (key: string, value: string): Promise<void> => {
await localforage.setItem(key, encrypt(value));
},
getItem: async function getItem<T>(key: string): Promise<T | string | null> {
try {
const value: any = decrypt(await localforage.getItem(key)) as any;
// 如果值是 undefined返回 null
if (value === undefined) {
return null;
}
// 如果值是 T 类型,直接返回
if (typeof value === "object" && value !== null) {
return value as T;
}
// 如果值是 string 类型,直接返回
return value as string;
} catch (error) {
console.error("Error retrieving data from localforage:", error);
return null;
}
},
removeItem: async (key: string): Promise<void> => {
await localforage.removeItem(key);
},
clear: async () => {
return await localforage.clear();
},
createInstance: async (name: string) => {
return localforage.createInstance({
name,
});
},
};

View File

@@ -1,11 +1,13 @@
import { MobXProviderContext } from 'mobx-react'
import { useContext } from 'react'
import { RootStore } from '@/store'
/** @format */
import { MobXProviderContext } from "mobx-react";
import { useContext } from "react";
import { RootStore } from "@/store";
// 根据RootStore来实现参数的自动获取和返回值的自动推导
function useStore<T extends typeof RootStore, V extends keyof T>(name: V): T[V] {
const store = useContext(MobXProviderContext) as T
return store[name]
const store = useContext(MobXProviderContext) as T;
return store[name];
}
export default useStore
export default useStore;