2024-11-08 11:55:23 +08:00
|
|
|
|
import config from "@/config.js"
|
2025-11-18 17:25:39 +08:00
|
|
|
|
import {
|
|
|
|
|
|
sm2_Decrypt,
|
2025-11-29 16:31:34 +08:00
|
|
|
|
sm2_Encrypt,
|
2025-11-20 09:17:29 +08:00
|
|
|
|
sm4Decrypt,
|
|
|
|
|
|
sm4Encrypt
|
2025-11-29 16:31:34 +08:00
|
|
|
|
} from '@/common/globalFunction';
|
|
|
|
|
|
import IndexedDBHelper from '@/common/IndexedDBHelper';
|
|
|
|
|
|
import useUserStore from '@/stores/useUserStore';
|
|
|
|
|
|
import baseDB from '@/utils/db.js';
|
2024-11-08 11:55:23 +08:00
|
|
|
|
|
2025-11-29 16:31:34 +08:00
|
|
|
|
const CACHE_STORE_NAME = 'api_cache';
|
2024-11-08 11:55:23 +08:00
|
|
|
|
|
2025-11-20 09:17:29 +08:00
|
|
|
|
const needToEncrypt = [
|
|
|
|
|
|
["post", "/app/login"],
|
|
|
|
|
|
["get", "/app/user/resume"],
|
|
|
|
|
|
["post", "/app/user/resume"],
|
|
|
|
|
|
["post", "/app/user/experience/edit"],
|
|
|
|
|
|
["post", "/app/user/experience/delete"],
|
|
|
|
|
|
["get", "/app/user/experience/getSingle/{value}"],
|
|
|
|
|
|
["get", "/app/user/experience/list"]
|
|
|
|
|
|
]
|
2025-03-28 15:19:42 +08:00
|
|
|
|
|
2025-11-29 16:31:34 +08:00
|
|
|
|
/**
|
|
|
|
|
|
* 带缓存的请求方法
|
|
|
|
|
|
*/
|
|
|
|
|
|
export async function createRequestWithCache(url, data = {}, method = 'GET', loading = false, headers = {},
|
|
|
|
|
|
onCacheLoad = null) {
|
2025-11-30 16:47:06 +08:00
|
|
|
|
// 是分页接口的话, 只缓存第一页的数据
|
|
|
|
|
|
if (data.current && data.current > 1) {
|
|
|
|
|
|
return createRequest(url, data, method, loading, headers);
|
|
|
|
|
|
}
|
2025-11-29 16:31:34 +08:00
|
|
|
|
const cacheKey = `${method.toUpperCase()}:${url}:${JSON.stringify(data)}`;
|
|
|
|
|
|
|
|
|
|
|
|
baseDB.getDB().then(async (dbHelper) => {
|
|
|
|
|
|
try {
|
|
|
|
|
|
const cachedRecord = await dbHelper.get(CACHE_STORE_NAME, cacheKey);
|
|
|
|
|
|
|
|
|
|
|
|
if (cachedRecord && cachedRecord.response && typeof onCacheLoad === 'function') {
|
|
|
|
|
|
onCacheLoad(cachedRecord.response);
|
|
|
|
|
|
}
|
|
|
|
|
|
} catch (e) {
|
|
|
|
|
|
console.error('读取缓存失败', e);
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
// 3. 发起网络请求
|
|
|
|
|
|
try {
|
|
|
|
|
|
const networkResponse = await createRequest(url, data, method, loading, headers);
|
|
|
|
|
|
baseDB.getDB().then(async (dbHelper) => {
|
|
|
|
|
|
try {
|
|
|
|
|
|
await dbHelper.update(CACHE_STORE_NAME, {
|
|
|
|
|
|
cacheKey: cacheKey,
|
|
|
|
|
|
response: networkResponse,
|
|
|
|
|
|
timestamp: Date.now()
|
|
|
|
|
|
});
|
|
|
|
|
|
console.log('💾 [BaseDB] 缓存更新:', url);
|
|
|
|
|
|
} catch (e) {
|
|
|
|
|
|
console.error('更新缓存失败', e);
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
return networkResponse;
|
|
|
|
|
|
} catch (error) {
|
|
|
|
|
|
throw error;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-03-28 15:19:42 +08:00
|
|
|
|
/**
|
|
|
|
|
|
* @param url String,请求的地址,默认:none
|
|
|
|
|
|
* @param data Object,请求的参数,默认:{}
|
|
|
|
|
|
* @param method String,请求的方式,默认:GET
|
|
|
|
|
|
* @param loading Boolean,是否需要loading ,默认:false
|
|
|
|
|
|
* @param header Object,headers,默认:{}
|
|
|
|
|
|
* @returns promise
|
|
|
|
|
|
**/
|
|
|
|
|
|
export function createRequest(url, data = {}, method = 'GET', loading = false, headers = {}) {
|
|
|
|
|
|
if (loading) {
|
|
|
|
|
|
uni.showLoading({
|
|
|
|
|
|
title: '请稍后',
|
|
|
|
|
|
mask: true
|
|
|
|
|
|
})
|
|
|
|
|
|
}
|
2025-11-30 16:47:06 +08:00
|
|
|
|
let header = {
|
|
|
|
|
|
...headers
|
|
|
|
|
|
};
|
|
|
|
|
|
const userStore = useUserStore();
|
|
|
|
|
|
const token = userStore.token;
|
2025-03-28 15:19:42 +08:00
|
|
|
|
|
2025-11-30 16:47:06 +08:00
|
|
|
|
if (token) {
|
|
|
|
|
|
// 确保 Authorization 不会被覆盖,且进行编码
|
|
|
|
|
|
header["Authorization"] = encodeURIComponent(token);
|
|
|
|
|
|
}
|
2025-11-20 09:17:29 +08:00
|
|
|
|
|
|
|
|
|
|
// ------------------------------------------------------------------
|
|
|
|
|
|
// 检查当前请求是否需要加密
|
|
|
|
|
|
const isEncrypt = needToEncrypt.some(item => {
|
|
|
|
|
|
const matchMethod = item[0].toLowerCase() === method.toLowerCase();
|
|
|
|
|
|
const matchUrl = item[1].includes('{') ?
|
|
|
|
|
|
url.startsWith(item[1].split('/{')[0]) // 检查动态路径的前缀
|
|
|
|
|
|
:
|
|
|
|
|
|
item[1] === url; // 检查静态路径
|
|
|
|
|
|
return matchMethod && matchUrl;
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
let requestData = data;
|
|
|
|
|
|
|
|
|
|
|
|
if (isEncrypt) {
|
|
|
|
|
|
const jsonData = JSON.stringify(data);
|
|
|
|
|
|
const encryptedBody = sm4Encrypt(config.sm4Config.key, jsonData);
|
|
|
|
|
|
requestData = {
|
|
|
|
|
|
encrypted: true,
|
|
|
|
|
|
encryptedData: encryptedBody,
|
|
|
|
|
|
timestamp: Date.now()
|
|
|
|
|
|
};
|
|
|
|
|
|
}
|
|
|
|
|
|
// ------------------------------------------------------------------
|
2025-03-28 15:19:42 +08:00
|
|
|
|
return new Promise((resolve, reject) => {
|
|
|
|
|
|
uni.request({
|
|
|
|
|
|
url: config.baseUrl + url,
|
|
|
|
|
|
method: method,
|
2025-11-20 09:17:29 +08:00
|
|
|
|
data: requestData,
|
2025-03-28 15:19:42 +08:00
|
|
|
|
header,
|
|
|
|
|
|
success: resData => {
|
|
|
|
|
|
// 响应拦截
|
|
|
|
|
|
if (resData.statusCode === 200) {
|
2025-11-20 09:17:29 +08:00
|
|
|
|
if (resData.data.encrypted) {
|
2025-11-24 14:33:23 +08:00
|
|
|
|
const decryptedData = sm4Decrypt(config.sm4Config.key, resData.data
|
|
|
|
|
|
.encryptedData)
|
2025-11-20 09:17:29 +08:00
|
|
|
|
resData.data = JSON.parse(decryptedData)
|
|
|
|
|
|
}
|
2025-03-28 15:19:42 +08:00
|
|
|
|
const {
|
|
|
|
|
|
code,
|
|
|
|
|
|
msg
|
|
|
|
|
|
} = resData.data
|
|
|
|
|
|
if (code === 200) {
|
|
|
|
|
|
resolve(resData.data)
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
uni.showToast({
|
|
|
|
|
|
title: msg,
|
|
|
|
|
|
icon: 'none'
|
|
|
|
|
|
})
|
|
|
|
|
|
}
|
|
|
|
|
|
if (resData.data?.code === 401 || resData.data?.code === 402) {
|
|
|
|
|
|
useUserStore().logOut()
|
|
|
|
|
|
}
|
|
|
|
|
|
const err = new Error('请求出现异常,请联系工作人员')
|
|
|
|
|
|
err.error = resData
|
|
|
|
|
|
reject(err)
|
|
|
|
|
|
},
|
|
|
|
|
|
fail: (err) => {
|
|
|
|
|
|
reject(err)
|
|
|
|
|
|
},
|
|
|
|
|
|
complete: () => {
|
|
|
|
|
|
if (loading) {
|
|
|
|
|
|
uni.hideLoading();
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
})
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
export function uploadFile(tempFilePaths, loading = false) {
|
|
|
|
|
|
if (loading) {
|
|
|
|
|
|
uni.showLoading({
|
|
|
|
|
|
title: '请稍后',
|
|
|
|
|
|
mask: true
|
|
|
|
|
|
})
|
|
|
|
|
|
}
|
|
|
|
|
|
let Authorization = ''
|
|
|
|
|
|
if (useUserStore().token) {
|
|
|
|
|
|
Authorization = `${useUserStore().token}`
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const header = {};
|
|
|
|
|
|
header["Authorization"] = encodeURIComponent(Authorization);
|
|
|
|
|
|
return new Promise((resolve, reject) => {
|
|
|
|
|
|
uni.uploadFile({
|
|
|
|
|
|
url: config.baseUrl + '/app/file/upload',
|
|
|
|
|
|
filePath: tempFilePaths,
|
|
|
|
|
|
name: 'file',
|
|
|
|
|
|
header,
|
|
|
|
|
|
success: (uploadFileRes) => {
|
|
|
|
|
|
if (uploadFileRes.statusCode === 200) {
|
|
|
|
|
|
return resolve(uploadFileRes.data)
|
|
|
|
|
|
}
|
|
|
|
|
|
},
|
|
|
|
|
|
fail: (err) => {
|
|
|
|
|
|
reject(err)
|
|
|
|
|
|
},
|
|
|
|
|
|
complete: () => {
|
|
|
|
|
|
if (loading) {
|
|
|
|
|
|
uni.hideLoading();
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
})
|
|
|
|
|
|
})
|
|
|
|
|
|
}
|