user.ts 4.62 KB
import { defineStore } from 'pinia'
import { ref, computed } from 'vue'
import { ElMessage } from 'element-plus'
import type { User, LoginForm, LoginResponse } from '@/types'
import { loginApi, getUserInfoApi, logoutApi } from '@/api/auth'
import { getToken, setToken, removeToken, setUserInfo, getUserInfo, clearAuth } from '@/utils/auth'

export const useUserStore = defineStore('user', () => {
  // 状态
  const token = ref<string>(getToken() || '')
  const userInfo = ref<User | null>(getUserInfo())
  const permissions = ref<string[]>([])
  const roles = ref<string[]>([])

  // 计算属性
  const isLoggedIn = computed(() => !!token.value)
  const username = computed(() => userInfo.value?.username || '')
  const avatar = computed(() => userInfo.value?.avatar || '')

  // 登录
  const login = async (loginForm: LoginForm): Promise<void> => {
    try {
      const response: LoginResponse = await loginApi(loginForm)
      
      // 保存token和用户信息
      token.value = response.token
      userInfo.value = response.userInfo
      permissions.value = response.userInfo.permissions || []
      roles.value = response.userInfo.roles?.map(role => role.roleKey) || []
      
      // 持久化存储
      setToken(response.token)
      setUserInfo(response.userInfo)
      
      ElMessage.success('登录成功')
      
      // 跳转到首页
      window.location.href = '/'
    } catch (error) {
      console.error('登录失败:', error)
      throw error
    }
  }

  // 获取用户信息
  const getUserInfoAction = async (): Promise<void> => {
    try {
      if (!token.value) return
      
      const response: User = await getUserInfoApi()
      userInfo.value = response
      permissions.value = response.permissions || []
      roles.value = response.roles?.map(role => role.roleKey) || []
      
      // 更新本地存储
      setUserInfo(response)
      
      // 获取用户信息后,加载用户菜单权限
      if (response.userId) {
        // 动态导入避免循环依赖
        const { usePermissionStore } = await import('./permission')
        const permissionStore = usePermissionStore()
        await permissionStore.getUserPermissionMenus(response.userId)
      }
    } catch (error) {
      console.error('获取用户信息失败:', error)
      // 如果获取用户信息失败,可能是token过期,清除认证信息
      logout()
    }
  }

  // 登出
  const logout = async (): Promise<void> => {
    try {
      if (token.value) {
        await logoutApi()
      }
    } catch (error) {
      console.error('登出请求失败:', error)
    } finally {
      // 清除状态
      token.value = ''
      userInfo.value = null
      permissions.value = []
      roles.value = []
      
      // 清除权限store中的菜单
      try {
        const { usePermissionStore } = await import('./permission')
        const permissionStore = usePermissionStore()
        permissionStore.resetState()
      } catch (error) {
        console.error('清除权限store失败:', error)
      }
      
      // 清除本地存储
      clearAuth()
      
      // 跳转到登录页
      window.location.href = '/login'
    }
  }

  // 检查权限
  const hasPermission = (permission: string): boolean => {
    if (!permission) return true
    return permissions.value.includes(permission)
  }

  // 检查角色
  const hasRole = (role: string): boolean => {
    if (!role) return true
    return roles.value.includes(role)
  }

  // 检查是否有任意一个权限
  const hasAnyPermission = (permissionList: string[]): boolean => {
    if (!permissionList || permissionList.length === 0) return true
    return permissionList.some(permission => permissions.value.includes(permission))
  }

  // 检查是否有所有权限
  const hasAllPermissions = (permissionList: string[]): boolean => {
    if (!permissionList || permissionList.length === 0) return true
    return permissionList.every(permission => permissions.value.includes(permission))
  }

  // 更新用户信息
  const updateUserInfo = (newUserInfo: Partial<User>): void => {
    if (userInfo.value) {
      userInfo.value = { ...userInfo.value, ...newUserInfo }
      setUserInfo(userInfo.value)
    }
  }

  // 重置状态
  const resetState = (): void => {
    token.value = ''
    userInfo.value = null
    permissions.value = []
    roles.value = []
  }

  return {
    // 状态
    token,
    userInfo,
    permissions,
    roles,
    
    // 计算属性
    isLoggedIn,
    username,
    avatar,
    
    // 方法
    login,
    getUserInfoAction,
    logout,
    hasPermission,
    hasRole,
    hasAnyPermission,
    hasAllPermissions,
    updateUserInfo,
    resetState
  }
})