coder-common-thin-frontend/src/store/auth.ts
Leo a6898c0041 feat(auth): 优化登录流程和错误处理
- 优化登录失败时的错误抛出机制,确保上层组件可以捕获
- 增加登录成功的统一提示信息
- 完善获取用户信息失败时的错误处理
- 简化登录成功提示逻辑,移除重复判断
2025-07-07 09:16:10 +08:00

142 lines
4.2 KiB
TypeScript
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.

import { router } from '@/router'
import { fetchLogin, fetchLoginUserInfo, fetchLogout } from '@/service/api/auth'
import { local } from '@/utils'
import { coiMsgSuccess } from '@/utils/coi'
import { useRouteStore } from './router'
import { useTabStore } from './tab'
interface AuthStatus {
userInfo: Api.Login.Info | null
token: string
}
export const useAuthStore = defineStore('auth-store', {
state: (): AuthStatus => {
return {
userInfo: local.get('userInfo'),
token: local.get('accessToken') || '',
}
},
getters: {
/** 是否登录 */
isLogin(state) {
return Boolean(state.token)
},
},
actions: {
/* 登录退出,重置用户信息等 */
async logout() {
const route = unref(router.currentRoute)
// 先清除本地缓存立即使token失效
this.clearAuthStorage()
// 重置当前存储库
this.$reset()
// 清空路由、菜单等数据
const routeStore = useRouteStore()
routeStore.resetRouteStore()
// 清空标签栏数据
const tabStore = useTabStore()
tabStore.clearAllTabs()
// 最后调用后端退出登录接口
try {
await fetchLogout()
}
catch (error) {
// 后端接口调用失败不影响前端清理
console.warn('后端退出登录接口调用失败:', error)
}
// 重定向到登录页
if (route.meta.requiresAuth) {
router.push({
name: 'login',
query: {
redirect: route.fullPath,
},
})
}
},
clearAuthStorage() {
local.remove('accessToken')
local.remove('refreshToken')
local.remove('userInfo')
},
/* 用户登录 */
async login(loginName: string, password: string, codeKey: string, securityCode: string, rememberMe = false) {
try {
const { isSuccess, data } = await fetchLogin({ loginName, password, codeKey, securityCode, rememberMe })
if (!isSuccess) {
// 登录失败时抛出错误,让上层组件处理验证码刷新
throw new Error('登录失败')
}
// 保存Token
local.set('accessToken', data.tokenValue)
this.token = data.tokenValue
// 获取用户信息
const userInfoResult = await fetchLoginUserInfo()
if (!userInfoResult.isSuccess) {
// 获取用户信息失败时也抛出错误
throw new Error('获取用户信息失败')
}
// 处理登录信息 - 转换后端返回的数据结构
const userInfo = {
id: userInfoResult.data.loginUser.userId,
userId: userInfoResult.data.loginUser.userId,
userName: userInfoResult.data.loginUser.userName,
avatar: userInfoResult.data.loginUser.avatar,
role: userInfoResult.data.roles,
buttons: userInfoResult.data.buttons, // 用户权限按钮列表
accessToken: data.tokenValue,
refreshToken: data.tokenValue, // 没有单独的refreshToken暂时使用相同值
}
await this.handleLoginInfo(userInfo as Api.Login.Info)
}
catch (e) {
console.warn('[Login Error]:', e)
// 重新抛出错误,确保上层组件能够捕获
throw e
}
},
/* 处理登录返回的数据 */
async handleLoginInfo(data: Api.Login.Info) {
// 将token和userInfo保存下来
local.set('userInfo', data)
local.set('accessToken', data.accessToken)
local.set('refreshToken', data.refreshToken)
this.token = data.accessToken
this.userInfo = data
// 添加路由和菜单
const routeStore = useRouteStore()
await routeStore.initAuthRoute()
// 进行重定向跳转
const route = unref(router.currentRoute)
const query = route.query as { redirect: string }
// 登录成功提示
coiMsgSuccess('登录成功!')
router.push({
path: query.redirect || '/',
})
},
/* 更新用户信息 */
updateUserInfo(updates: Partial<Api.Login.Info>) {
if (this.userInfo) {
// 更新内存中的用户信息
this.userInfo = { ...this.userInfo, ...updates }
// 更新本地存储
local.set('userInfo', this.userInfo)
}
},
},
})