/** * 用户信息 Hook * 封装获取用户信息的逻辑,可在各个应用中复用 * * 使用方式: * import { useUserInfo } from '@gold/hooks/web/useUserInfo' * * const { fetchUserInfo, loading, error } = useUserInfo() * await fetchUserInfo() */ import { ref } from 'vue' import axios from 'axios' import { API_BASE } from '@gold/config/api' import tokenManager from '@gold/utils/token-manager' // 本地存储配置 const CACHE_KEY = 'USER_INFO_CACHE' const CACHE_DURATION = 5 * 60 * 1000 // 5分钟缓存 /** * 获取 Authorization Header * @returns {string} */ function getAuthHeader() { // 首先尝试从 tokenManager 获取 const token = tokenManager.getAccessToken() if (token) { return `Bearer ${token}` } // 如果 tokenManager 没有 token,尝试从 sessionStorage 获取(开发环境使用) try { const manualToken = sessionStorage.getItem('DEV_MANUAL_TOKEN') if (manualToken) { return `Bearer ${manualToken}` } } catch (e) { // 忽略错误 } return '' } /** * 从本地存储获取缓存的用户信息 * @returns {Object|null} 缓存的用户信息或 null */ function getCachedUserInfo() { try { const cached = sessionStorage.getItem(CACHE_KEY) if (!cached) return null const { data, timestamp } = JSON.parse(cached) const now = Date.now() // 检查缓存是否过期 if (now - timestamp > CACHE_DURATION) { sessionStorage.removeItem(CACHE_KEY) return null } console.log('[UserInfo] 使用本地缓存') return data } catch (e) { return null } } /** * 将用户信息存储到本地 * @param {Object} userInfo - 用户信息 */ function setCachedUserInfo(userInfo) { try { const cacheData = { data: userInfo, timestamp: Date.now() } sessionStorage.setItem(CACHE_KEY, JSON.stringify(cacheData)) console.log('[UserInfo] 更新本地缓存') } catch (e) { console.error('缓存用户信息失败:', e) } } /** * 清除用户信息缓存 */ export function clearUserInfoCache() { try { sessionStorage.removeItem(CACHE_KEY) console.log('[UserInfo] 清除缓存') } catch (e) { console.error('清除缓存失败:', e) } } /** * 用户信息 Hook * @param {Object} options - 配置选项 * @param {string} options.baseUrl - API 基础 URL(可选,默认使用 APP_MEMBER) * @returns {Object} { fetchUserInfo, loading, error, userInfo } */ export function useUserInfo(options = {}) { const loading = ref(false) const error = ref(null) const userInfo = ref(null) // 确定 API 基础路径 const baseUrl = options.baseUrl || API_BASE.APP_MEMBER const apiUrl = `${baseUrl}/user/get` /** * 获取用户信息 * @returns {Promise} 用户信息对象 */ async function fetchUserInfo() { loading.value = true error.value = null try { // 1. 先尝试从本地缓存获取 const cachedUserInfo = getCachedUserInfo() if (cachedUserInfo) { userInfo.value = cachedUserInfo loading.value = false return cachedUserInfo } // 2. 发起请求获取用户信息 console.log('[UserInfo] 发起请求') const authHeader = getAuthHeader() const headers = { 'Content-Type': 'application/json', } if (authHeader) { headers.Authorization = authHeader } // 获取 tenant-id(从环境变量或默认值) const tenantId = (typeof import.meta !== 'undefined' && import.meta.env?.VITE_TENANT_ID) || (typeof process !== 'undefined' && process.env?.VITE_TENANT_ID) || '1' if (tenantId) { headers['tenant-id'] = tenantId } const response = await axios.get(apiUrl, { headers }) // 处理响应数据(根据后端返回格式调整) // 后端通常返回 { code: 0, data: {...}, msg: '...' } 格式 let data = null if (response.data) { // 如果响应有 code 字段,说明是标准格式 if (typeof response.data.code === 'number') { // code 为 0 或 200 表示成功 if (response.data.code === 0 || response.data.code === 200) { data = response.data.data || response.data } } else { // 没有 code 字段,直接使用 data data = response.data.data || response.data } } if (data) { // 3. 将获取到的数据写入本地缓存 setCachedUserInfo(data) userInfo.value = data return data } } catch (err) { error.value = err console.error('获取用户信息失败:', err) throw err } finally { loading.value = false } } return { fetchUserInfo, loading, error, userInfo, } } /** * 便捷函数:直接获取用户信息(不返回响应式状态) * @param {Object} options - 配置选项 * @returns {Promise} 用户信息对象 */ export async function getUserInfo(options = {}) { const { fetchUserInfo } = useUserInfo(options) return await fetchUserInfo() }