fix: 修复拦截器报错
This commit is contained in:
@@ -1,21 +1,26 @@
|
|||||||
import FingerprintJS from '@fingerprintjs/fingerprintjs';
|
import type { HookFetchPlugin } from 'hook-fetch';
|
||||||
|
import FingerprintJS from '@fingerprintjs/fingerprintjs'; // 新增指纹库
|
||||||
import { ElMessage } from 'element-plus';
|
import { ElMessage } from 'element-plus';
|
||||||
import hookFetch from 'hook-fetch';
|
import hookFetch from 'hook-fetch';
|
||||||
import { sseTextDecoderPlugin } from 'hook-fetch/plugins';
|
import { sseTextDecoderPlugin } from 'hook-fetch/plugins';
|
||||||
import router from '@/routers';
|
import router from '@/routers';
|
||||||
import { useUserStore } from '@/stores';
|
import { useUserStore } from '@/stores';
|
||||||
|
|
||||||
// 初始化指纹
|
// 初始化指纹(单例模式)
|
||||||
const fpPromise = FingerprintJS.load();
|
const fpPromise = FingerprintJS.load();
|
||||||
|
|
||||||
|
// 获取浏览器指纹(缓存结果)
|
||||||
async function getFingerprint(): Promise<string> {
|
async function getFingerprint(): Promise<string> {
|
||||||
const fp = await fpPromise;
|
const fp = await fpPromise;
|
||||||
return (await fp.get()).visitorId;
|
const { visitorId } = await fp.get();
|
||||||
|
return visitorId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 标准响应格式
|
||||||
interface BaseResponse<T = any> {
|
interface BaseResponse<T = any> {
|
||||||
code?: number; // 变为可选字段
|
code: number;
|
||||||
data: T;
|
data: T;
|
||||||
msg?: string;
|
msg: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
declare module 'hook-fetch' {
|
declare module 'hook-fetch' {
|
||||||
@@ -24,10 +29,6 @@ declare module 'hook-fetch' {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 刷新控制变量
|
|
||||||
let isRefreshing = false;
|
|
||||||
let pendingRequests: (() => void)[] = [];
|
|
||||||
|
|
||||||
export const request = hookFetch.create<BaseResponse>({
|
export const request = hookFetch.create<BaseResponse>({
|
||||||
baseURL: import.meta.env.VITE_WEB_BASE_API,
|
baseURL: import.meta.env.VITE_WEB_BASE_API,
|
||||||
headers: {
|
headers: {
|
||||||
@@ -36,7 +37,7 @@ export const request = hookFetch.create<BaseResponse>({
|
|||||||
plugins: [
|
plugins: [
|
||||||
sseTextDecoderPlugin({ json: true, prefix: 'data:' }),
|
sseTextDecoderPlugin({ json: true, prefix: 'data:' }),
|
||||||
{
|
{
|
||||||
name: 'fingerprint-plugin',
|
name: 'fingerprint-plugin', // 新增指纹插件
|
||||||
beforeRequest: async (config) => {
|
beforeRequest: async (config) => {
|
||||||
try {
|
try {
|
||||||
const fingerprint = await getFingerprint();
|
const fingerprint = await getFingerprint();
|
||||||
@@ -44,110 +45,66 @@ export const request = hookFetch.create<BaseResponse>({
|
|||||||
config.headers.set('X-Fingerprint', fingerprint);
|
config.headers.set('X-Fingerprint', fingerprint);
|
||||||
}
|
}
|
||||||
catch (error) {
|
catch (error) {
|
||||||
console.error('指纹生成失败:', error);
|
console.error('Failed to generate fingerprint:', error);
|
||||||
}
|
}
|
||||||
return config;
|
return config;
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'jwt-auth',
|
name: 'adapt-array-response',
|
||||||
beforeRequest: (config) => {
|
afterResponse: async (response) => {
|
||||||
const userStore = useUserStore();
|
if (typeof response.result?.code === 'number') {
|
||||||
if (userStore.token) {
|
return response;
|
||||||
config.headers = new Headers(config.headers);
|
|
||||||
config.headers.set('Authorization', `Bearer ${userStore.token}`);
|
|
||||||
}
|
}
|
||||||
return config;
|
return {
|
||||||
},
|
...response,
|
||||||
afterResponse: async (response: any, config: any) => {
|
result: {
|
||||||
const userStore = useUserStore();
|
code: 200,
|
||||||
console.log('网络请求响应----', response);
|
data: response.result,
|
||||||
// 成功请求(HTTP状态码200-299)
|
msg: 'success',
|
||||||
if (response.ok) {
|
},
|
||||||
// 兼容响应体可能没有code字段的情况
|
};
|
||||||
const data = await response.json();
|
|
||||||
return {
|
|
||||||
...response,
|
|
||||||
result: data.code ? data : { code: 200, data, msg: 'success' },
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
// 处理HTTP状态码401
|
|
||||||
if (response.status === 401) {
|
|
||||||
// 刷新Token接口自身失败
|
|
||||||
if (config.url?.includes('/account/refresh')) {
|
|
||||||
userStore.logout();
|
|
||||||
userStore.openLoginDialog();
|
|
||||||
throw new Error('刷新Token失败');
|
|
||||||
}
|
|
||||||
|
|
||||||
// 将请求加入队列
|
|
||||||
if (isRefreshing) {
|
|
||||||
return new Promise((resolve) => {
|
|
||||||
pendingRequests.push(() => resolve(request(config)));
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// 开始刷新流程
|
|
||||||
isRefreshing = true;
|
|
||||||
try {
|
|
||||||
const refreshRes = await request.post('/account/refresh', {
|
|
||||||
refresh_token: userStore.refreshToken,
|
|
||||||
}).json();
|
|
||||||
|
|
||||||
// 更新Token
|
|
||||||
userStore.setToken(refreshRes.data.token, refreshRes.data.refreshToken);
|
|
||||||
|
|
||||||
// 重试原始请求
|
|
||||||
config.headers.set('Authorization', `Bearer ${refreshRes.data.token}`);
|
|
||||||
const retryResponse = await request(config);
|
|
||||||
|
|
||||||
// 执行等待中的请求
|
|
||||||
pendingRequests.forEach(cb => cb());
|
|
||||||
pendingRequests = [];
|
|
||||||
return retryResponse;
|
|
||||||
}
|
|
||||||
catch (error) {
|
|
||||||
// 刷新失败清除状态
|
|
||||||
userStore.logout();
|
|
||||||
userStore.openLoginDialog();
|
|
||||||
throw error;
|
|
||||||
}
|
|
||||||
finally {
|
|
||||||
isRefreshing = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 处理HTTP状态码403
|
|
||||||
if (response.status === 403) {
|
|
||||||
router.replace({ name: '403' });
|
|
||||||
const errorMsg = (await response.json().catch(() => ({})))?.msg || '无权限访问';
|
|
||||||
ElMessage.error(errorMsg);
|
|
||||||
throw new Error('Forbidden');
|
|
||||||
}
|
|
||||||
|
|
||||||
// 其他错误状态码
|
|
||||||
const errorData = await response.json().catch(() => ({}));
|
|
||||||
ElMessage.error(errorData.msg || `请求失败: ${response.status}`);
|
|
||||||
throw errorData;
|
|
||||||
},
|
|
||||||
// 错误处理
|
|
||||||
async onError(error: any, config: any) {
|
|
||||||
console.log('网络请求错误----', error);
|
|
||||||
console.log('网络请求错误--config--', config);
|
|
||||||
|
|
||||||
// 可以处理或转换错误
|
|
||||||
if (error.status === 401) {
|
|
||||||
// 处理未授权错误
|
|
||||||
return new Error('Please login first');
|
|
||||||
}
|
|
||||||
return error;
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
});
|
});
|
||||||
|
|
||||||
// 保持原有导出
|
// JWT插件(保持原有逻辑)
|
||||||
|
function jwtPlugin(): HookFetchPlugin<BaseResponse> {
|
||||||
|
const userStore = useUserStore();
|
||||||
|
return {
|
||||||
|
name: 'jwt',
|
||||||
|
beforeRequest: async (config) => {
|
||||||
|
if (userStore.token) {
|
||||||
|
config.headers = new Headers(config.headers);
|
||||||
|
config.headers.set('authorization', `Bearer ${userStore.token}`);
|
||||||
|
}
|
||||||
|
return config;
|
||||||
|
},
|
||||||
|
afterResponse: async (response) => {
|
||||||
|
if (response.result?.code === 200)
|
||||||
|
return response;
|
||||||
|
|
||||||
|
if (response.result?.code === 403) {
|
||||||
|
router.replace({ name: '403' });
|
||||||
|
ElMessage.error(response.result?.msg);
|
||||||
|
return Promise.reject(response);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (response.result?.code === 401) {
|
||||||
|
userStore.logout();
|
||||||
|
userStore.openLoginDialog();
|
||||||
|
}
|
||||||
|
|
||||||
|
ElMessage.error(response.result?.msg);
|
||||||
|
return Promise.reject(response);
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
request.use(jwtPlugin());
|
||||||
|
|
||||||
|
// 导出方法(保持原有)
|
||||||
export const post = request.post;
|
export const post = request.post;
|
||||||
export const get = request.get;
|
export const get = request.get;
|
||||||
export const put = request.put;
|
export const put = request.put;
|
||||||
|
|||||||
1
Yi.Ai.Vue3/types/import_meta.d.ts
vendored
1
Yi.Ai.Vue3/types/import_meta.d.ts
vendored
@@ -6,6 +6,7 @@ interface ImportMetaEnv {
|
|||||||
readonly VITE_WEB_ENV: string;
|
readonly VITE_WEB_ENV: string;
|
||||||
readonly VITE_WEB_BASE_API: string;
|
readonly VITE_WEB_BASE_API: string;
|
||||||
readonly VITE_API_URL: string;
|
readonly VITE_API_URL: string;
|
||||||
|
readonly VITE_BUILD_COMPRESS: string;
|
||||||
readonly VITE_SSO_SEVER_URL: string;
|
readonly VITE_SSO_SEVER_URL: string;
|
||||||
readonly VITE_SSO_CLIENT_ID: string;
|
readonly VITE_SSO_CLIENT_ID: string;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user