| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381 |
- // 认证相关工具函数
- const LOGIN_FORM_KEY = 'loginForm';
- const TENANT_ID_KEY = 'tenantId';
- const TOKEN_KEY = 'token';
- const USER_ID_KEY = 'userId';
- const ACCESS_TOKEN_KEY = 'ACCESS_TOKEN';
- const REFRESH_TOKEN_KEY = 'REFRESH_TOKEN';
- const USER_KEY = 'user';
- const ROLE_ROUTERS_KEY = 'roleRouters';
- const LANG_KEY = 'lang';
- const IS_DARK_KEY = 'isDark';
- const HM_LVT_KEY = 'Hm_lvt_a1ff8825baa73c3a78eb96aa40325abc';
- // 登录表单缓存类型
- export interface LoginFormCache {
- username?: string;
- password?: string;
- tenantName?: string;
- rememberMe?: boolean;
- }
- // 设置登录表单缓存
- export const setLoginForm = (form: LoginFormCache) => {
- localStorage.setItem(LOGIN_FORM_KEY, JSON.stringify(form));
- };
- // 获取登录表单缓存
- export const getLoginForm = (): LoginFormCache | null => {
- const form = localStorage.getItem(LOGIN_FORM_KEY);
- return form ? JSON.parse(form) : null;
- };
- // 移除登录表单缓存
- export const removeLoginForm = () => {
- localStorage.removeItem(LOGIN_FORM_KEY);
- };
- // 设置租户ID
- export const setTenantId = (tenantId: string | number) => {
- localStorage.setItem(TENANT_ID_KEY, String(tenantId));
- };
- // 获取租户ID
- export const getTenantId = (): string | null => {
- return localStorage.getItem(TENANT_ID_KEY);
- };
- // 移除租户ID
- export const removeTenantId = () => {
- localStorage.removeItem(TENANT_ID_KEY);
- };
- // 设置Token(兼容多种格式)
- export const setToken = (tokenData: { accessToken?: string; token?: string } | string) => {
- if (typeof tokenData === 'string') {
- localStorage.setItem(TOKEN_KEY, tokenData);
- } else {
- const token = tokenData.accessToken || tokenData.token || '';
- localStorage.setItem(TOKEN_KEY, token);
- }
- };
- // 获取Token
- export const getToken = (): string | null => {
- return localStorage.getItem(TOKEN_KEY);
- };
- // 移除Token
- export const removeToken = () => {
- localStorage.removeItem(TOKEN_KEY);
- };
- // 设置用户ID
- export const setUserId = (userId: string) => {
- localStorage.setItem(USER_ID_KEY, userId);
- };
- // 获取用户ID
- export const getUserId = (): string | null => {
- return localStorage.getItem(USER_ID_KEY);
- };
- // 移除用户ID
- export const removeUserId = () => {
- localStorage.removeItem(USER_ID_KEY);
- };
- // 设置ACCESS_TOKEN
- export const setAccessToken = (token: string) => {
- localStorage.setItem(ACCESS_TOKEN_KEY, token);
- };
- // 获取ACCESS_TOKEN
- export const getAccessToken = (): string | null => {
- return localStorage.getItem(ACCESS_TOKEN_KEY);
- };
- // 移除ACCESS_TOKEN
- export const removeAccessToken = () => {
- localStorage.removeItem(ACCESS_TOKEN_KEY);
- };
- // 设置REFRESH_TOKEN
- export const setRefreshToken = (token: string) => {
- localStorage.setItem(REFRESH_TOKEN_KEY, token);
- };
- // 获取REFRESH_TOKEN
- export const getRefreshToken = (): string | null => {
- return localStorage.getItem(REFRESH_TOKEN_KEY);
- };
- // 移除REFRESH_TOKEN
- export const removeRefreshToken = () => {
- localStorage.removeItem(REFRESH_TOKEN_KEY);
- };
- // 设置用户信息
- export const setUser = (user: any) => {
- localStorage.setItem(USER_KEY, JSON.stringify(user));
- };
- // 获取用户信息
- export const getUser = (): any | null => {
- const user = localStorage.getItem(USER_KEY);
- return user ? JSON.parse(user) : null;
- };
- // 移除用户信息
- export const removeUser = () => {
- localStorage.removeItem(USER_KEY);
- };
- // 设置角色路由
- export const setRoleRouters = (routers: any) => {
- localStorage.setItem(ROLE_ROUTERS_KEY, JSON.stringify(routers));
- };
- // 获取角色路由
- export const getRoleRouters = (): any | null => {
- const routers = localStorage.getItem(ROLE_ROUTERS_KEY);
- return routers ? JSON.parse(routers) : null;
- };
- // 移除角色路由
- export const removeRoleRouters = () => {
- localStorage.removeItem(ROLE_ROUTERS_KEY);
- };
- // 设置语言
- export const setLang = (lang: string) => {
- localStorage.setItem(LANG_KEY, lang);
- };
- // 获取语言
- export const getLang = (): string | null => {
- return localStorage.getItem(LANG_KEY);
- };
- // 移除语言
- export const removeLang = () => {
- localStorage.removeItem(LANG_KEY);
- };
- // 设置暗色模式
- export const setIsDark = (isDark: boolean) => {
- localStorage.setItem(IS_DARK_KEY, String(isDark));
- };
- // 获取暗色模式
- export const getIsDark = (): boolean => {
- const isDark = localStorage.getItem(IS_DARK_KEY);
- return isDark === 'true';
- };
- // 移除暗色模式
- export const removeIsDark = () => {
- localStorage.removeItem(IS_DARK_KEY);
- };
- // 设置Hm_lvt cookie值
- export const setHmLvt = (value: string) => {
- localStorage.setItem(HM_LVT_KEY, value);
- };
- // 获取Hm_lvt cookie值
- export const getHmLvt = (): string | null => {
- return localStorage.getItem(HM_LVT_KEY);
- };
- // 移除Hm_lvt cookie值
- export const removeHmLvt = () => {
- localStorage.removeItem(HM_LVT_KEY);
- };
- // 清除所有认证信息
- export const clearAuth = () => {
- removeToken();
- removeTenantId();
- removeUserId();
- removeLoginForm();
- removeAccessToken();
- removeRefreshToken();
- removeUser();
- removeRoleRouters();
- removeHmLvt();
- // 清除最后活跃菜单缓存
- sessionStorage.removeItem('lastActiveMenu');
- // 清除权限信息
- try {
- const { clearPermissionInfo } = require('./permission');
- clearPermissionInfo();
- } catch (e) {
- // 如果权限模块未加载,忽略错误
- }
- };
- // Token定期检测和刷新
- 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 = () => {
- if (tokenCheckInterval) {
- clearInterval(tokenCheckInterval);
- tokenCheckInterval = null;
- }
- };
- // 检测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 {
- // 动态导入loginApi和axios,避免循环依赖
- const { loginApi } = await import('../api/Login');
- const axios = (await import('axios')).default;
- const { env } = await import('./env');
-
- // 直接使用axios调用,绕过拦截器,获取原始响应
- const baseURL = env.baseUrl ? `${env.baseUrl}/admin-api` : '/admin-api';
- const token = getAccessToken() || getToken();
-
- 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': `Bearer ${token}`,
- 'Content-Type': 'application/json',
- },
- validateStatus: (status) => {
- // 接受所有状态码,包括401,以便我们能够检测到登录状态失效
- return status >= 200 && status < 500;
- },
- });
-
- console.log(`[TokenCheck] 接口响应: status=${response.status}, code=${response.data?.code}`);
-
- // 检查响应数据,如果code是401或HTTP状态码是401,说明token失效
- const responseData = response.data;
- 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有效,无需刷新');
- }
- // 如果返回正常,说明token有效,不需要处理
- } catch (error: any) {
- console.log(`[TokenCheck] 接口调用异常:`, error?.message || error);
-
- // 检查错误响应,如果是401,说明token失效
- 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('[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, '但不退出登录,继续保留当前页面');
- // 即使刷新失败,也不退出登录,继续保留当前页面
- }
- };
|