import { useCache, CACHE_KEY, deleteTokenCache } from '../hooks/web/useCache' /** * Token 统一管理模块(Monorepo 全局工具) * * 这是项目中唯一的 token 管理入口,所有 token 操作都应该通过此模块进行。 * * Token 存储优先级(读取顺序): * 1. 手动输入的 dev token (sessionStorage) * 2. 正式登录的 token (wsCache/localStorage) * 3. 环境变量 VITE_DEV_TOKEN * * Token 存储位置: * - ACCESS_TOKEN/access_token: 访问令牌(wsCache/localStorage) * - REFRESH_TOKEN/refresh_token: 刷新令牌(wsCache/localStorage) * - DEV_MANUAL_TOKEN: 开发手动输入的token(sessionStorage) */ // ==================== 常量定义 ==================== const DEV_MANUAL_TOKEN_KEY = 'DEV_MANUAL_TOKEN' // Token 键名变体(支持大小写不同) const TOKEN_KEYS = { ACCESS: [CACHE_KEY.ACCESS_TOKEN, 'access_token'], REFRESH: [CACHE_KEY.REFRESH_TOKEN, 'refresh_token'] } // ==================== 缓存实例管理 ==================== let wsCache = null /** * 获取 wsCache 实例(延迟初始化,避免模块加载时出错) * @returns {Object} wsCache 实例 */ function getCache() { if (!wsCache) { try { wsCache = useCache().wsCache } catch (e) { console.warn('初始化 wsCache 失败:', e) // 返回一个安全的空对象,避免后续调用出错 wsCache = { get: () => null, set: () => {}, delete: () => {} } } } return wsCache } /** * 获取完整的 Authorization Header 值 * @returns {string} Bearer token 或空字符串 */ export function getAuthHeader() { const token = getToken() return token ? `Bearer ${token}` : '' } /** * 获取 token * @returns {string} token 字符串 */ export function getToken() { // 1. 优先使用手动输入的 dev token const manualToken = sessionStorage.getItem(DEV_MANUAL_TOKEN_KEY) if (manualToken) { return manualToken } // 2. 使用正式登录的 token(从 wsCache 读取) try { const cache = getCache() // 尝试所有可能的键名变体 for (const key of TOKEN_KEYS.ACCESS) { const accessToken = cache.get(key) if (accessToken) { return accessToken } } } catch (e) { console.warn('获取 wsCache 失败:', e) } // 3. 兜底:环境变量中的 token const envToken = import.meta?.env?.VITE_DEV_TOKEN if (envToken) { return envToken } return '' } /** * 设置手动输入的 dev token * @param {string} token */ export function setDevToken(token) { if (token) { sessionStorage.setItem(DEV_MANUAL_TOKEN_KEY, token) } else { sessionStorage.removeItem(DEV_MANUAL_TOKEN_KEY) } } /** * 获取手动输入的 dev token(用于显示) * @returns {string} */ export function getDevToken() { return sessionStorage.getItem(DEV_MANUAL_TOKEN_KEY) || '' } /** * 设置访问令牌和刷新令牌 * @param {Object} tokens - token 对象 * @param {string} tokens.accessToken - 访问令牌 * @param {string} tokens.refreshToken - 刷新令牌 */ export function setToken(tokens) { if (!tokens || (!tokens.accessToken && !tokens.refreshToken)) { console.warn('setToken: token 参数无效', tokens) return } try { const cache = getCache() if (tokens.accessToken) { cache.set(CACHE_KEY.ACCESS_TOKEN, tokens.accessToken) } if (tokens.refreshToken) { cache.set(CACHE_KEY.REFRESH_TOKEN, tokens.refreshToken) } } catch (e) { console.error('设置 token 失败:', e) } } /** * 获取刷新令牌 * @returns {string|null} 刷新令牌或 null */ export function getRefreshToken() { try { const cache = getCache() // 尝试所有可能的键名变体 for (const key of TOKEN_KEYS.REFRESH) { const token = cache.get(key) if (token) { return token } } } catch (e) { console.warn('获取 refresh token 失败:', e) } return null } /** * 清除所有 token * 清空所有可能的 token 存储位置,确保完全清除 */ export function clearAllTokens() { try { // 1. 清空 sessionStorage 中的 dev token sessionStorage.removeItem(DEV_MANUAL_TOKEN_KEY) } catch (e) { console.warn('清除 sessionStorage token 失败:', e) } try { // 2. 清空 wsCache (localStorage) 中的所有可能的 token 键名 // 使用统一的 deleteTokenCache 函数,保持与 useCache 的一致性 deleteTokenCache() } catch (e) { console.warn('清除 wsCache token 失败:', e) } try { // 3. 清空 localStorage 中可能的 token(兜底处理) // 注意:wsCache 默认使用 localStorage,但为了确保清除,也直接操作 localStorage const localStorageKeys = [ ...TOKEN_KEYS.ACCESS, ...TOKEN_KEYS.REFRESH, DEV_MANUAL_TOKEN_KEY ] localStorageKeys.forEach(key => { try { localStorage.removeItem(key) } catch (e) { // 忽略单个键删除失败 } }) } catch (e) { console.warn('清除 localStorage token 失败:', e) } } /** * 删除 token(别名,兼容旧代码) * @deprecated 使用 clearAllTokens() 代替 */ export function removeToken() { clearAllTokens() } /** * 获取访问令牌(别名,兼容旧代码) * @returns {string} token 字符串 */ export function getAccessToken() { return getToken() }