diff --git a/web/src/components/modals/SettingsView/Account.tsx b/web/src/components/modals/SettingsView/Account.tsx index 0ad75ae5..ec14986d 100644 --- a/web/src/components/modals/SettingsView/Account.tsx +++ b/web/src/components/modals/SettingsView/Account.tsx @@ -8,6 +8,7 @@ import { openModal } from '@/components/Modal'; import { closeModal } from '@/plugin/common'; import { getGlobalSocket } from '@/utils/global-state-helper'; import { setUserJWT } from '@/utils/jwt-helper'; +import { setGlobalUserLoginInfo } from '@/utils/user-helper'; import { Button, Divider, Typography } from 'antd'; import React, { useCallback } from 'react'; import { useHistory } from 'react-router'; @@ -64,6 +65,7 @@ export const SettingsAccount: React.FC = React.memo(() => { const handleLogout = useCallback(async () => { await setUserJWT(null); getGlobalSocket()?.disconnect(); + setGlobalUserLoginInfo(null); history.push('/'); }, []); diff --git a/web/src/routes/Entry/LoginView.tsx b/web/src/routes/Entry/LoginView.tsx index 76414313..a1cc50d6 100644 --- a/web/src/routes/Entry/LoginView.tsx +++ b/web/src/routes/Entry/LoginView.tsx @@ -1,12 +1,12 @@ import { Icon } from '@/components/Icon'; import { Divider } from 'antd'; import { isValidStr, loginWithEmail, t, useAsyncFn } from 'tailchat-shared'; -import React, { useState } from 'react'; +import React, { useEffect, useState } from 'react'; import { Spinner } from '../../components/Spinner'; import { string } from 'yup'; import { useHistory } from 'react-router'; import { setUserJWT } from '../../utils/jwt-helper'; -import { setGlobalUserLoginInfo } from '../../utils/user-helper'; +import { setGlobalUserLoginInfo, tryAutoLogin } from '../../utils/user-helper'; import { useSearchParam } from '@/hooks/useSearchParam'; import { useNavToView } from './utils'; @@ -36,6 +36,14 @@ export const LoginView: React.FC = React.memo(() => { const history = useHistory(); const navRedirect = useSearchParam('redirect'); + useEffect(() => { + tryAutoLogin() + .then(() => { + history.push('/main'); + }) + .catch(() => {}); + }, []); + const [{ loading, error }, handleLogin] = useAsyncFn(async () => { await string() .email(t('邮箱格式不正确')) diff --git a/web/src/routes/Main/Provider.tsx b/web/src/routes/Main/Provider.tsx index c7cbd75a..d8f0652d 100644 --- a/web/src/routes/Main/Provider.tsx +++ b/web/src/routes/Main/Provider.tsx @@ -7,10 +7,11 @@ import { loginWithToken, t, ReduxProvider, + UserLoginInfo, } from 'tailchat-shared'; import React from 'react'; import { LoadingSpinner } from '@/components/LoadingSpinner'; -import { getGlobalUserLoginInfo } from '@/utils/user-helper'; +import { getGlobalUserLoginInfo, tryAutoLogin } from '@/utils/user-helper'; import _isNil from 'lodash/isNil'; import { getUserJWT } from '@/utils/jwt-helper'; import { useHistory } from 'react-router'; @@ -27,26 +28,15 @@ function useAppState() { const history = useHistory(); const { value, loading, error } = useAsync(async () => { - let userLoginInfo = getGlobalUserLoginInfo(); - if (_isNil(userLoginInfo)) { - // 如果没有全局缓存的数据, 则尝试自动登录 - try { - const token = await getUserJWT(); - if (typeof token !== 'string') { - throw new Error('Token 格式不合法'); - } - userLoginInfo = await loginWithToken(token); - - if (userLoginInfo === null) { - throw new Error('Token 内容不合法'); - } - } catch (e) { - // 当前 Token 不存在或已过期 - history.replace( - `/entry/login?redirect=${encodeURIComponent(location.pathname)}` - ); - return; - } + let userLoginInfo: UserLoginInfo; + try { + userLoginInfo = await tryAutoLogin(); + } catch (e) { + // 当前 Token 不存在或已过期 + history.replace( + `/entry/login?redirect=${encodeURIComponent(location.pathname)}` + ); + return; } // 到这里 userLoginInfo 必定存在 diff --git a/web/src/utils/user-helper.ts b/web/src/utils/user-helper.ts index 18a18d30..34b5c56f 100644 --- a/web/src/utils/user-helper.ts +++ b/web/src/utils/user-helper.ts @@ -1,8 +1,10 @@ -import type { UserLoginInfo } from 'tailchat-shared'; +import { loginWithToken, UserLoginInfo } from 'tailchat-shared'; +import _isNil from 'lodash/isNil'; +import { getUserJWT } from './jwt-helper'; -let _userLoginInfo: UserLoginInfo; +let _userLoginInfo: UserLoginInfo | null = null; -export function setGlobalUserLoginInfo(loginInfo: UserLoginInfo) { +export function setGlobalUserLoginInfo(loginInfo: UserLoginInfo | null) { _userLoginInfo = loginInfo; } @@ -13,3 +15,27 @@ export function setGlobalUserLoginInfo(loginInfo: UserLoginInfo) { export function getGlobalUserLoginInfo() { return _userLoginInfo; } + +/** + * 尝试自动登录 + */ +export async function tryAutoLogin(): Promise { + let userLoginInfo = getGlobalUserLoginInfo(); + if (_isNil(userLoginInfo)) { + // 如果没有全局缓存的数据, 则尝试自动登录 + const token = await getUserJWT(); + if (typeof token !== 'string') { + throw new Error('Token 格式不合法'); + } + + console.debug('正在尝试使用Token登录'); + userLoginInfo = await loginWithToken(token); + if (userLoginInfo === null) { + throw new Error('Token 内容不合法'); + } + + setGlobalUserLoginInfo(userLoginInfo); + } + + return userLoginInfo; +}