|
|
@@ -221,18 +221,25 @@ let tokenCheckInterval: NodeJS.Timeout | null = null;
|
|
|
let isChecking = false; // 防止并发检测
|
|
|
|
|
|
export const startTokenCheck = (intervalSeconds: number = 30) => {
|
|
|
+ console.log(`[TokenCheck] 启动token检测,间隔: ${intervalSeconds}秒`);
|
|
|
+
|
|
|
// 如果已经有定时器在运行,先清除
|
|
|
if (tokenCheckInterval) {
|
|
|
+ console.log('[TokenCheck] 清除旧的定时器');
|
|
|
stopTokenCheck();
|
|
|
}
|
|
|
|
|
|
// 立即执行一次检测
|
|
|
+ console.log('[TokenCheck] 立即执行一次检测');
|
|
|
checkTokenAndRefresh();
|
|
|
|
|
|
// 设置定时器
|
|
|
tokenCheckInterval = setInterval(() => {
|
|
|
+ console.log(`[TokenCheck] 定时器触发,执行检测 (间隔: ${intervalSeconds}秒)`);
|
|
|
checkTokenAndRefresh();
|
|
|
}, intervalSeconds * 1000);
|
|
|
+
|
|
|
+ console.log(`[TokenCheck] 定时器已设置,ID: ${tokenCheckInterval}`);
|
|
|
};
|
|
|
|
|
|
export const stopTokenCheck = () => {
|
|
|
@@ -244,17 +251,22 @@ export const stopTokenCheck = () => {
|
|
|
|
|
|
// 检测token并刷新
|
|
|
const checkTokenAndRefresh = async () => {
|
|
|
+ console.log('[TokenCheck] checkTokenAndRefresh 被调用');
|
|
|
+
|
|
|
// 如果正在检测中,跳过
|
|
|
if (isChecking) {
|
|
|
+ console.log('[TokenCheck] 正在检测中,跳过本次调用');
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
// 如果没有refreshToken,不需要检测
|
|
|
const refreshToken = getRefreshToken();
|
|
|
if (!refreshToken) {
|
|
|
+ console.log('[TokenCheck] 没有refreshToken,跳过检测');
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
+ console.log('[TokenCheck] 开始检测token...');
|
|
|
isChecking = true;
|
|
|
|
|
|
try {
|
|
|
@@ -267,135 +279,103 @@ const checkTokenAndRefresh = async () => {
|
|
|
const baseURL = env.baseUrl ? `${env.baseUrl}/admin-api` : '/admin-api';
|
|
|
const token = getAccessToken() || getToken();
|
|
|
|
|
|
- const response = await axios.get(`${baseURL}/system/notify-message/get-unread-count`, {
|
|
|
+ if (!token) {
|
|
|
+ // 如果没有token,直接尝试刷新
|
|
|
+ console.log('[TokenCheck] 未找到accessToken,尝试刷新token...');
|
|
|
+ await refreshTokenIfNeeded(refreshToken);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ const url = `${baseURL}/system/notify-message/get-unread-count`;
|
|
|
+ console.log(`[TokenCheck] 调用检测接口: ${url}`);
|
|
|
+
|
|
|
+ const response = await axios.get(url, {
|
|
|
headers: {
|
|
|
- 'Authorization': token ? `Bearer ${token}` : undefined,
|
|
|
+ 'Authorization': `Bearer ${token}`,
|
|
|
'Content-Type': 'application/json',
|
|
|
},
|
|
|
+ validateStatus: (status) => {
|
|
|
+ // 接受所有状态码,包括401,以便我们能够检测到登录状态失效
|
|
|
+ return status >= 200 && status < 500;
|
|
|
+ },
|
|
|
});
|
|
|
|
|
|
- // 检查响应数据,如果code是401,说明token失效
|
|
|
+ console.log(`[TokenCheck] 接口响应: status=${response.status}, code=${response.data?.code}`);
|
|
|
+
|
|
|
+ // 检查响应数据,如果code是401或HTTP状态码是401,说明token失效
|
|
|
const responseData = response.data;
|
|
|
- if (responseData && responseData.code === 401 && responseData.msg === '账号未登录') {
|
|
|
- console.log('检测到token失效,开始刷新token...');
|
|
|
-
|
|
|
- // 调用刷新token接口
|
|
|
- const refreshResponse = await loginApi.refreshToken(refreshToken);
|
|
|
-
|
|
|
- // 处理返回数据格式:{code: 0, data: {accessToken, refreshToken, ...}, msg: ""}
|
|
|
- let tokenData;
|
|
|
- if (refreshResponse?.code === 0 && refreshResponse?.data) {
|
|
|
- // 标准格式:{code: 0, data: {...}}
|
|
|
- tokenData = refreshResponse.data;
|
|
|
- } else if (refreshResponse?.data) {
|
|
|
- // 兼容格式:{data: {...}}
|
|
|
- tokenData = refreshResponse.data;
|
|
|
- } else {
|
|
|
- // 直接是数据对象
|
|
|
- tokenData = refreshResponse;
|
|
|
- }
|
|
|
-
|
|
|
- const newAccessToken = tokenData?.accessToken || tokenData?.token;
|
|
|
- const newRefreshToken = tokenData?.refreshToken;
|
|
|
-
|
|
|
- if (newAccessToken) {
|
|
|
- // 更新token
|
|
|
- setToken({ accessToken: newAccessToken, token: newAccessToken });
|
|
|
- setAccessToken(newAccessToken);
|
|
|
- if (newRefreshToken) {
|
|
|
- setRefreshToken(newRefreshToken);
|
|
|
- }
|
|
|
- console.log('Token刷新成功');
|
|
|
- } else {
|
|
|
- console.error('刷新token失败:未返回新token');
|
|
|
- }
|
|
|
+ const isTokenExpired =
|
|
|
+ response.status === 401 ||
|
|
|
+ (responseData && (responseData.code === 401 || responseData.msg === '账号未登录'));
|
|
|
+
|
|
|
+ if (isTokenExpired) {
|
|
|
+ console.log('[TokenCheck] 检测到token失效,开始刷新token...');
|
|
|
+ await refreshTokenIfNeeded(refreshToken);
|
|
|
+ } else {
|
|
|
+ console.log('[TokenCheck] Token有效,无需刷新');
|
|
|
}
|
|
|
- // 如果返回正常(code !== 401),说明token有效,不需要处理
|
|
|
+ // 如果返回正常,说明token有效,不需要处理
|
|
|
} catch (error: any) {
|
|
|
+ console.log(`[TokenCheck] 接口调用异常:`, error?.message || error);
|
|
|
+
|
|
|
// 检查错误响应,如果是401,说明token失效
|
|
|
- if (error?.response?.data) {
|
|
|
- const errorData = error.response.data;
|
|
|
- if (errorData.code === 401 || errorData.msg === '账号未登录') {
|
|
|
- console.log('检测到token失效(通过错误响应),开始刷新token...');
|
|
|
-
|
|
|
- try {
|
|
|
- const { loginApi } = await import('../api/Login');
|
|
|
- const refreshResponse = await loginApi.refreshToken(refreshToken);
|
|
|
-
|
|
|
- // 处理返回数据格式
|
|
|
- let tokenData;
|
|
|
- if (refreshResponse?.code === 0 && refreshResponse?.data) {
|
|
|
- tokenData = refreshResponse.data;
|
|
|
- } else if (refreshResponse?.data) {
|
|
|
- tokenData = refreshResponse.data;
|
|
|
- } else {
|
|
|
- tokenData = refreshResponse;
|
|
|
- }
|
|
|
-
|
|
|
- const newAccessToken = tokenData?.accessToken || tokenData?.token;
|
|
|
- const newRefreshToken = tokenData?.refreshToken;
|
|
|
-
|
|
|
- if (newAccessToken) {
|
|
|
- setToken({ accessToken: newAccessToken, token: newAccessToken });
|
|
|
- setAccessToken(newAccessToken);
|
|
|
- if (newRefreshToken) {
|
|
|
- setRefreshToken(newRefreshToken);
|
|
|
- }
|
|
|
- console.log('Token刷新成功');
|
|
|
- } else {
|
|
|
- console.warn('刷新token失败:未返回新token,但不退出登录');
|
|
|
- // 即使刷新失败,也不退出登录,继续保留当前页面
|
|
|
- }
|
|
|
- } catch (refreshError) {
|
|
|
- console.warn('刷新token失败:', refreshError, '但不退出登录,继续保留当前页面');
|
|
|
- // 即使刷新失败,也不退出登录,继续保留当前页面
|
|
|
- }
|
|
|
- } else {
|
|
|
- // 其他业务错误,不处理
|
|
|
- console.log('Token检测接口返回其他错误:', errorData);
|
|
|
- }
|
|
|
- } else if (error?.response?.status === 401) {
|
|
|
- // HTTP状态码401,尝试刷新token
|
|
|
- console.log('检测到HTTP 401错误,开始刷新token...');
|
|
|
-
|
|
|
- try {
|
|
|
- const { loginApi } = await import('../api/Login');
|
|
|
- const refreshResponse = await loginApi.refreshToken(refreshToken);
|
|
|
-
|
|
|
- // 处理返回数据格式
|
|
|
- let tokenData;
|
|
|
- if (refreshResponse?.code === 0 && refreshResponse?.data) {
|
|
|
- tokenData = refreshResponse.data;
|
|
|
- } else if (refreshResponse?.data) {
|
|
|
- tokenData = refreshResponse.data;
|
|
|
- } else {
|
|
|
- tokenData = refreshResponse;
|
|
|
- }
|
|
|
-
|
|
|
- const newAccessToken = tokenData?.accessToken || tokenData?.token;
|
|
|
- const newRefreshToken = tokenData?.refreshToken;
|
|
|
-
|
|
|
- if (newAccessToken) {
|
|
|
- setToken({ accessToken: newAccessToken, token: newAccessToken });
|
|
|
- setAccessToken(newAccessToken);
|
|
|
- if (newRefreshToken) {
|
|
|
- setRefreshToken(newRefreshToken);
|
|
|
- }
|
|
|
- console.log('Token刷新成功');
|
|
|
- } else {
|
|
|
- console.warn('刷新token失败:未返回新token,但不退出登录');
|
|
|
- // 即使刷新失败,也不退出登录,继续保留当前页面
|
|
|
- }
|
|
|
- } catch (refreshError) {
|
|
|
- console.warn('刷新token失败:', refreshError, '但不退出登录,继续保留当前页面');
|
|
|
- // 即使刷新失败,也不退出登录,继续保留当前页面
|
|
|
- }
|
|
|
+ const isTokenExpired =
|
|
|
+ error?.response?.status === 401 ||
|
|
|
+ (error?.response?.data && (
|
|
|
+ error.response.data.code === 401 ||
|
|
|
+ error.response.data.msg === '账号未登录'
|
|
|
+ ));
|
|
|
+
|
|
|
+ if (isTokenExpired) {
|
|
|
+ console.log('[TokenCheck] 检测到token失效(通过错误响应),开始刷新token...');
|
|
|
+ await refreshTokenIfNeeded(refreshToken);
|
|
|
} else {
|
|
|
// 其他错误(网络问题等),不处理,不退出登录
|
|
|
- console.log('Token检测接口调用失败:', error?.message || error, '但不退出登录');
|
|
|
+ console.log('[TokenCheck] Token检测接口调用失败:', error?.message || error, '但不退出登录');
|
|
|
}
|
|
|
} finally {
|
|
|
isChecking = false;
|
|
|
+ console.log('[TokenCheck] 检测完成');
|
|
|
+ }
|
|
|
+};
|
|
|
+
|
|
|
+// 刷新token的辅助函数
|
|
|
+const refreshTokenIfNeeded = async (refreshToken: string) => {
|
|
|
+ try {
|
|
|
+ const { loginApi } = await import('../api/Login');
|
|
|
+ const refreshResponse = await loginApi.refreshToken(refreshToken);
|
|
|
+
|
|
|
+ // 处理返回数据格式:{code: 0, data: {accessToken, refreshToken, ...}, msg: ""}
|
|
|
+ let tokenData;
|
|
|
+ if (refreshResponse?.code === 0 && refreshResponse?.data) {
|
|
|
+ // 标准格式:{code: 0, data: {...}}
|
|
|
+ tokenData = refreshResponse.data;
|
|
|
+ } else if (refreshResponse?.data) {
|
|
|
+ // 兼容格式:{data: {...}}
|
|
|
+ tokenData = refreshResponse.data;
|
|
|
+ } else {
|
|
|
+ // 直接是数据对象
|
|
|
+ tokenData = refreshResponse;
|
|
|
+ }
|
|
|
+
|
|
|
+ const newAccessToken = tokenData?.accessToken || tokenData?.token;
|
|
|
+ const newRefreshToken = tokenData?.refreshToken;
|
|
|
+
|
|
|
+ if (newAccessToken) {
|
|
|
+ // 更新token
|
|
|
+ setToken({ accessToken: newAccessToken, token: newAccessToken });
|
|
|
+ setAccessToken(newAccessToken);
|
|
|
+ if (newRefreshToken) {
|
|
|
+ setRefreshToken(newRefreshToken);
|
|
|
+ }
|
|
|
+ console.log('Token刷新成功');
|
|
|
+ } else {
|
|
|
+ console.warn('刷新token失败:未返回新token,但不退出登录');
|
|
|
+ // 即使刷新失败,也不退出登录,继续保留当前页面
|
|
|
+ }
|
|
|
+ } catch (refreshError) {
|
|
|
+ console.warn('刷新token失败:', refreshError, '但不退出登录,继续保留当前页面');
|
|
|
+ // 即使刷新失败,也不退出登录,继续保留当前页面
|
|
|
}
|
|
|
};
|
|
|
|