import type { UserInfo } from '@vben/types'; import { ref } from 'vue'; import { useRouter } from 'vue-router'; import { LOGIN_PATH } from '@vben/constants'; import { preferences } from '@vben/preferences'; import { resetAllStores, useAccessStore, useUserStore } from '@vben/stores'; import { notification } from 'ant-design-vue'; import { defineStore } from 'pinia'; import { thAppLogin } from '#/api/th'; import { $t } from '#/locales'; import { useDictStore } from './dict'; import { useThTenantStore } from './th-tenant'; /** 泰额多租户登录入参(POST /api/app/th-app-auth/login) */ export interface ThAuthLoginParams { tenantId: string; email: string; password: string; uuid?: string; code?: string; } export const useAuthStore = defineStore('auth', () => { const accessStore = useAccessStore(); const userStore = useUserStore(); const thTenantStore = useThTenantStore(); const router = useRouter(); const loginLoading = ref(false); function buildUserInfoFromLogin(email: string, tenantName: string): UserInfo { const normalizedEmail = email.trim(); return { avatar: '', email: normalizedEmail, permissions: [], realName: tenantName || normalizedEmail, roles: [], userId: normalizedEmail, username: normalizedEmail, homePath: preferences.app.defaultHomePath, }; } /** * 泰额多租户登录 */ async function authLogin( params: ThAuthLoginParams, onSuccess?: () => Promise | void, ) { let userInfo: null | UserInfo = null; try { loginLoading.value = true; const result = await thAppLogin({ tenantId: params.tenantId, email: params.email, password: params.password, uuid: params.uuid, code: params.code, }); if (!result.token?.trim()) { throw new Error('登录失败:未返回 token'); } accessStore.setAccessToken(result.token); accessStore.setRefreshToken(result.refreshToken); accessStore.setAccessCodes([]); accessStore.setIsAccessChecked(false); thTenantStore.setTenantContext({ tenantId: result.tenantId, tenantName: result.tenantName, locations: result.locations, }); userInfo = buildUserInfoFromLogin(params.email, result.tenantName); userStore.setUserInfo(userInfo); if (accessStore.loginExpired) { accessStore.setLoginExpired(false); } loginLoading.value = false; if (onSuccess) { await onSuccess(); } else { await router.push(preferences.app.defaultHomePath); } notification.success({ description: `${$t('authentication.loginSuccessDesc')}:${userInfo.realName}`, duration: 3, message: $t('authentication.loginSuccess'), }); } catch (error) { loginLoading.value = false; throw error; } return { userInfo }; } async function logout(redirect: boolean = true) { try { const { doLogout, seeConnectionClose } = await import('#/api'); await seeConnectionClose(); await doLogout(); } catch (error) { console.error(error); } finally { resetAllStores(); thTenantStore.$reset(); accessStore.setLoginExpired(false); await router.replace({ path: LOGIN_PATH, query: redirect ? { redirect: encodeURIComponent(router.currentRoute.value.fullPath), } : {}, }); } } async function fetchUserInfo() { const cached = userStore.userInfo; if (cached?.username) { return cached; } // 泰额 SAAS:用户信息来自 th-app-auth/login,不走 Yi 框架 /account if (thTenantStore.tenantId && accessStore.accessToken) { const fallback = buildUserInfoFromLogin( cached?.email || cached?.username || 'user', thTenantStore.tenantName || '', ); userStore.setUserInfo(fallback); return fallback; } try { const { getUserInfoApi } = await import('#/api'); const backUserInfo = await getUserInfoApi(); if (!backUserInfo) { throw new Error('获取用户信息失败.'); } const { permissionCodes = [], roleCodes = [], user } = backUserInfo; const userInfo: UserInfo = { avatar: user.avatar ?? '', permissions: permissionCodes, realName: user.nick, roles: roleCodes, userId: user.userId, username: user.userName, email: user.email ?? '', }; userStore.setUserInfo(userInfo); const dictStore = useDictStore(); dictStore.resetCache(); return userInfo; } catch (error) { if (cached) { return cached; } throw error; } } function $reset() { loginLoading.value = false; } return { $reset, authLogin, fetchUserInfo, loginLoading, logout, }; });