import { computed, reactive, ref } from 'vue'; import { useRoute } from 'vue-router'; import { defineStore } from 'pinia'; import { useLoading } from '@sa/hooks'; import { fetchGetUserInfo, fetchLogin, fetchLogout } from '@/service/api'; import { useRouterPush } from '@/hooks/common/router'; import { localStg } from '@/utils/storage'; import { SetupStoreId } from '@/enum'; import { useRouteStore } from '../route'; import { useTabStore } from '../tab'; import { clearAuthStorage, getToken } from './shared'; export const useAuthStore = defineStore(SetupStoreId.Auth, () => { const route = useRoute(); const routeStore = useRouteStore(); const tabStore = useTabStore(); const { toLogin, redirectFromLogin } = useRouterPush(false); const { loading: loginLoading, startLoading, endLoading } = useLoading(); const token = ref(getToken()); const userInfo: Api.Auth.UserInfo = reactive({ user: undefined, roles: [], permissions: [] }); /** is super role in static route */ const isStaticSuper = computed(() => { const { VITE_AUTH_ROUTE_MODE, VITE_STATIC_SUPER_ROLE } = import.meta.env; return VITE_AUTH_ROUTE_MODE === 'static' && userInfo.roles.includes(VITE_STATIC_SUPER_ROLE); }); /** Is login */ const isLogin = computed(() => Boolean(token.value)); /** Reset auth store */ async function resetStore() { const authStore = useAuthStore(); recordUserId(); clearAuthStorage(); authStore.$reset(); if (!route.meta.constant) { await toLogin(); } tabStore.cacheTabs(); routeStore.resetStore(); } async function logout() { await fetchLogout(); resetStore(); } /** Record the user ID of the previous login session Used to compare with the current user ID on next login */ function recordUserId() { if (!userInfo.user?.userId) { return; } // Store current user ID locally for next login comparison localStg.set('lastLoginUserId', userInfo.user?.userId); } /** * Check if current login user is different from previous login user If different, clear all tabs * * @returns {boolean} Whether to clear all tabs */ function checkTabClear(): boolean { if (!userInfo.user?.userId) { return false; } const lastLoginUserId = localStg.get('lastLoginUserId'); // Clear all tabs if current user is different from previous user if (!lastLoginUserId || lastLoginUserId !== userInfo.user?.userId) { localStg.remove('globalTabs'); tabStore.clearTabs(); localStg.remove('lastLoginUserId'); return true; } localStg.remove('lastLoginUserId'); return false; } /** * Login * * @param [redirect=true] Whether to redirect after login. Default is `true` */ async function login(loginForm: Api.Auth.PwdLoginForm | Api.Auth.SocialLoginForm, redirect = true) { startLoading(); const { VITE_APP_CLIENT_ID } = import.meta.env; const loginData: Api.Auth.PwdLoginForm = { ...loginForm, tenantId: loginForm.tenantId ?? '000000', clientId: VITE_APP_CLIENT_ID!, grantType: loginForm.grantType ?? 'password' }; const { data: loginToken, error } = await fetchLogin(loginData); if (!error) { const pass = await loginByToken(loginToken); if (pass) { // Check if the tab needs to be cleared const isClear = checkTabClear(); let needRedirect = redirect; if (isClear) { // If the tab needs to be cleared,it means we don't need to redirect. needRedirect = false; } await redirectFromLogin(needRedirect); // window.$notification?.success({ // title: $t('page.login.common.loginSuccess'), // content: $t('page.login.common.welcomeBack', { userName: userInfo.userName }), // duration: 4500 // }); } } else { resetStore(); } endLoading(); return error ? Promise.reject(error) : Promise.resolve(); } async function loginByToken(loginToken: Api.Auth.LoginToken) { // 1. stored in the localStorage, the later requests need it in headers localStg.set('token', loginToken.access_token!); localStg.set('refreshToken', loginToken.refresh_token!); // 2. get user info const pass = await getUserInfo(); if (pass) { token.value = loginToken.access_token!; return true; } return false; } async function getUserInfo() { const { data: info, error } = await fetchGetUserInfo(); if (!error) { // update store Object.assign(userInfo, info); return true; } return false; } async function initUserInfo() { const hasToken = getToken(); if (hasToken) { const pass = await getUserInfo(); if (!pass) { resetStore(); } } } return { token, userInfo, isStaticSuper, isLogin, loginLoading, resetStore, login, logout, initUserInfo }; });