25개 이상의 토픽을 선택하실 수 없습니다. Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

123 lines
2.6 KiB

  1. /**
  2. * 用户状态管理 composable
  3. *
  4. * 管理:token、用户信息、登录状态、登录弹窗显隐
  5. * Token 持久化:Cookie(SSR 安全,Nuxt useCookie 自动同步服务端/客户端)
  6. */
  7. export function useUser() {
  8. const token = useCookie('token', {
  9. maxAge: 7 * 24 * 3600,
  10. path: '/',
  11. })
  12. const userInfo = useState('userInfo', () => ({
  13. user_id: null,
  14. user_name: '',
  15. avatar: '',
  16. nickname: '',
  17. open_id: '',
  18. vip_type: 0,
  19. balance: 0,
  20. }))
  21. const isLogin = computed(() => !!token.value && !!userInfo.value.user_id)
  22. // 登录弹窗全局状态(任何组件都可以触发)
  23. const showLogin = useState('showLogin', () => false)
  24. /**
  25. * 设置登录态
  26. */
  27. function setLogin(data) {
  28. token.value = data.token
  29. userInfo.value = {
  30. user_id: data.user_id,
  31. user_name: data.user_name || data.nickname || '',
  32. avatar: data.avatar || '',
  33. nickname: data.nickname || data.user_name || '',
  34. open_id: data.open_id || '',
  35. vip_type: data.vip_type || 0,
  36. balance: data.balance || 0,
  37. }
  38. // 同步写入 open_id Cookie(供 useApi 读取 uid)
  39. if (data.open_id) {
  40. const openIdCookie = useCookie('open_id', { path: '/' })
  41. openIdCookie.value = data.open_id
  42. }
  43. }
  44. /**
  45. * 退出登录
  46. */
  47. function logout() {
  48. token.value = null
  49. userInfo.value = {
  50. user_id: null,
  51. user_name: '',
  52. avatar: '',
  53. nickname: '',
  54. open_id: '',
  55. vip_type: 0,
  56. balance: 0,
  57. }
  58. // 清除 open_id Cookie
  59. const openIdCookie = useCookie('open_id', { path: '/' })
  60. openIdCookie.value = null
  61. }
  62. /**
  63. * 刷新用户信息
  64. */
  65. async function refreshUserInfo() {
  66. if (!token.value) return
  67. try {
  68. const { post } = useApi()
  69. const res = await post('/user/getuserinfo')
  70. if (res.code === 0 && res.data) {
  71. userInfo.value = {
  72. ...userInfo.value,
  73. ...res.data,
  74. }
  75. }
  76. } catch (e) {
  77. // 获取失败不中断
  78. }
  79. }
  80. /**
  81. * 初始化:如果有 token 但无 userInfo,自动刷新
  82. */
  83. async function init() {
  84. if (token.value && !userInfo.value.user_id) {
  85. await refreshUserInfo()
  86. }
  87. }
  88. /**
  89. * 处理 1009 鉴权失效(由 useApi 调用)
  90. */
  91. function handleAuthError() {
  92. if (import.meta.client) {
  93. logout()
  94. showLogin.value = true
  95. }
  96. }
  97. // 客户端初始化
  98. if (import.meta.client) {
  99. init()
  100. }
  101. return {
  102. token,
  103. userInfo,
  104. isLogin,
  105. showLogin,
  106. setLogin,
  107. logout,
  108. refreshUserInfo,
  109. handleAuthError,
  110. init,
  111. }
  112. }