Files
sionrui/frontend/hooks/web/useUserInfo.js
2026-01-17 14:43:42 +08:00

201 lines
5.0 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
* 用户信息 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<Object>} 用户信息对象
*/
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<Object>} 用户信息对象
*/
export async function getUserInfo(options = {}) {
const { fetchUserInfo } = useUserInfo(options)
return await fetchUserInfo()
}