user.ts 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107
  1. import { defineStore } from 'pinia';
  2. import { ref, computed } from 'vue';
  3. import { getToken, setToken, removeToken, getUserInfo, setUserInfo, removeUserInfo } from '../utils/storage';
  4. import { get, post } from '../utils/request';
  5. import type { UserInfo, MemberStatus } from '../types';
  6. export const useUserStore = defineStore('user', () => {
  7. // 状态
  8. const token = ref<string | null>(getToken());
  9. const userInfo = ref<UserInfo | null>(getUserInfo<UserInfo>());
  10. const memberStatus = ref<MemberStatus | null>(null);
  11. // 计算属性
  12. const isLoggedIn = computed(() => !!token.value && !!userInfo.value);
  13. const isMember = computed(() => memberStatus.value?.isValid && memberStatus.value.level > 0);
  14. // 初始化用户状态
  15. function initUser() {
  16. // 检查是否有保存的登录状态
  17. const savedToken = getToken();
  18. const savedUserInfo = getUserInfo<UserInfo>();
  19. // 如果有有效的登录状态,使用它
  20. if (savedToken && savedUserInfo && savedToken !== 'test-token-for-dev') {
  21. token.value = savedToken;
  22. userInfo.value = savedUserInfo;
  23. fetchMemberStatus();
  24. }
  25. // 否则不设置默认用户,等待用户主动登录
  26. }
  27. // 登录
  28. async function login(phone: string, code: string) {
  29. const result = await post<{
  30. token: string;
  31. user: UserInfo;
  32. }>('/auth/login', { phone, code });
  33. token.value = result.token;
  34. userInfo.value = result.user;
  35. setToken(result.token);
  36. setUserInfo(result.user);
  37. await fetchMemberStatus();
  38. return result;
  39. }
  40. // 发送验证码
  41. async function sendCode(phone: string) {
  42. return post('/auth/send-code', { phone });
  43. }
  44. // 获取用户信息
  45. async function fetchUserInfo() {
  46. const info = await get<UserInfo>('/auth/user-info');
  47. userInfo.value = info;
  48. setUserInfo(info);
  49. return info;
  50. }
  51. // 获取会员状态
  52. async function fetchMemberStatus() {
  53. try {
  54. const status = await get<MemberStatus>('/member/status');
  55. memberStatus.value = status;
  56. return status;
  57. } catch {
  58. memberStatus.value = null;
  59. return null;
  60. }
  61. }
  62. // 登出
  63. function logout() {
  64. token.value = null;
  65. userInfo.value = null;
  66. memberStatus.value = null;
  67. removeToken();
  68. removeUserInfo();
  69. }
  70. // 更新用户信息
  71. function updateUserInfo(info: Partial<UserInfo>) {
  72. if (userInfo.value) {
  73. userInfo.value = { ...userInfo.value, ...info };
  74. setUserInfo(userInfo.value);
  75. }
  76. }
  77. return {
  78. // 状态
  79. token,
  80. userInfo,
  81. memberStatus,
  82. // 计算属性
  83. isLoggedIn,
  84. isMember,
  85. // 方法
  86. initUser,
  87. login,
  88. sendCode,
  89. fetchUserInfo,
  90. fetchMemberStatus,
  91. logout,
  92. updateUserInfo,
  93. };
  94. });