perf: login page (#5571)

This commit is contained in:
Archer
2025-09-01 21:03:58 +08:00
committed by GitHub
parent f41775fe56
commit c67e645469
17 changed files with 71 additions and 51 deletions

View File

@@ -1,6 +1,6 @@
import type { UserType } from '@fastgpt/global/support/user/type.d';
import type { PromotionRecordSchema } from '@fastgpt/global/support/activity/type.d';
export interface ResLogin {
export interface LoginSuccessResponse {
user: UserType;
token: string;
}

View File

@@ -4,7 +4,7 @@ import { useForm } from 'react-hook-form';
import { LoginPageTypeEnum } from '@/web/support/user/login/constants';
import { postFindPassword } from '@/web/support/user/api';
import { useSendCode } from '@/web/support/user/hooks/useSendCode';
import type { ResLogin } from '@/global/support/api/userRes.d';
import type { LoginSuccessResponse } from '@/global/support/api/userRes.d';
import { useToast } from '@fastgpt/web/hooks/useToast';
import { useSystemStore } from '@/web/common/system/useSystemStore';
import { useTranslation } from 'next-i18next';
@@ -13,7 +13,7 @@ import { checkPasswordRule } from '@fastgpt/global/common/string/password';
interface Props {
setPageType: Dispatch<`${LoginPageTypeEnum}`>;
loginSuccess: (e: ResLogin) => void;
loginSuccess: (e: LoginSuccessResponse) => void;
}
interface RegisterType {

View File

@@ -3,7 +3,7 @@ import { FormControl, Flex, Input, Button, Box } from '@chakra-ui/react';
import { useForm } from 'react-hook-form';
import { LoginPageTypeEnum } from '@/web/support/user/login/constants';
import { postLogin, getPreLogin } from '@/web/support/user/api';
import type { ResLogin } from '@/global/support/api/userRes';
import type { LoginSuccessResponse } from '@/global/support/api/userRes';
import { useToast } from '@fastgpt/web/hooks/useToast';
import { useSystemStore } from '@/web/common/system/useSystemStore';
import { useTranslation } from 'next-i18next';
@@ -13,7 +13,7 @@ import PolicyTip from './PolicyTip';
interface Props {
setPageType: Dispatch<`${LoginPageTypeEnum}`>;
loginSuccess: (e: ResLogin) => void;
loginSuccess: (e: LoginSuccessResponse) => void;
}
interface LoginFormType {

View File

@@ -1,6 +1,6 @@
import React, { type Dispatch } from 'react';
import { LoginPageTypeEnum } from '@/web/support/user/login/constants';
import type { ResLogin } from '@/global/support/api/userRes';
import type { LoginSuccessResponse } from '@/global/support/api/userRes';
import { Box, Center, Flex, Link } from '@chakra-ui/react';
import { useQuery } from '@tanstack/react-query';
import { getWXLoginQR, getWXLoginResult } from '@/web/support/user/api';
@@ -23,7 +23,7 @@ import { useSystemStore } from '@/web/common/system/useSystemStore';
import PolicyTip from './PolicyTip';
interface Props {
loginSuccess: (e: ResLogin) => void;
loginSuccess: (e: LoginSuccessResponse) => void;
setPageType: Dispatch<`${LoginPageTypeEnum}`>;
}
@@ -55,7 +55,7 @@ const WechatForm = ({ setPageType, loginSuccess }: Props) => {
{
refetchInterval: 3 * 1000,
enabled: !!wechatInfo?.code,
onSuccess(data: ResLogin | undefined) {
onSuccess(data: LoginSuccessResponse | undefined) {
if (data) {
removeFastGPTSem();
loginSuccess(data);

View File

@@ -4,10 +4,10 @@ import { LoginContainer } from '@/pageComponents/login';
import I18nLngSelector from '@/components/Select/I18nLngSelector';
import { useSystem } from '@fastgpt/web/hooks/useSystem';
import { getWebReqUrl } from '@fastgpt/web/common/system/utils';
import type { ResLogin } from '@/global/support/api/userRes';
import type { LoginSuccessResponse } from '@/global/support/api/userRes';
type LoginModalProps = {
onSuccess?: (res: ResLogin) => void;
onSuccess: (e: LoginSuccessResponse) => any;
};
const LoginModal = ({ onSuccess }: LoginModalProps) => {

View File

@@ -4,7 +4,7 @@ import { useForm } from 'react-hook-form';
import { LoginPageTypeEnum } from '@/web/support/user/login/constants';
import { postRegister } from '@/web/support/user/api';
import { useSendCode } from '@/web/support/user/hooks/useSendCode';
import type { ResLogin } from '@/global/support/api/userRes';
import type { LoginSuccessResponse } from '@/global/support/api/userRes';
import { useToast } from '@fastgpt/web/hooks/useToast';
import { postCreateApp } from '@/web/core/app/api';
import { emptyTemplates } from '@/web/core/app/templates';
@@ -23,7 +23,7 @@ import {
import { checkPasswordRule } from '@fastgpt/global/common/string/password';
interface Props {
loginSuccess: (e: ResLogin) => void;
loginSuccess: (e: LoginSuccessResponse) => void;
setPageType: Dispatch<`${LoginPageTypeEnum}`>;
}

View File

@@ -10,7 +10,7 @@ import {
} from '@chakra-ui/react';
import { LoginPageTypeEnum } from '@/web/support/user/login/constants';
import { useSystemStore } from '@/web/common/system/useSystemStore';
import type { ResLogin } from '@/global/support/api/userRes.d';
import type { LoginSuccessResponse } from '@/global/support/api/userRes.d';
import { useUserStore } from '@/web/support/user/useUserStore';
import { useChatStore } from '@/web/core/chat/context/useChatStore';
import dynamic from 'next/dynamic';
@@ -21,8 +21,6 @@ import { useTranslation } from 'next-i18next';
import LoginForm from '@/pageComponents/login/LoginForm/LoginForm';
import { GET } from '@/web/common/api/request';
import { getDocPath } from '@/web/common/system/doc';
import { postAcceptInvitationLink } from '@/web/support/user/team/api';
import { useRouter } from 'next/router';
const RegisterForm = dynamic(() => import('@/pageComponents/login/RegisterForm'));
const ForgetPasswordForm = dynamic(() => import('@/pageComponents/login/ForgetPasswordForm'));
@@ -187,25 +185,21 @@ export const LoginContainer = ({
onSuccess
}: {
children?: React.ReactNode;
onSuccess?: (res: ResLogin) => void;
onSuccess: (res: LoginSuccessResponse) => void;
}) => {
const { t } = useTranslation();
const { feConfigs } = useSystemStore();
const { setUserInfo } = useUserStore();
const { setLastChatAppId } = useChatStore();
const [pageType, setPageType] = useState<`${LoginPageTypeEnum}` | null>(null);
const [showCommunityModal, setShowCommunityModal] = useState(false);
const router = useRouter();
const { lastRoute = '' } = router.query as { lastRoute: string };
// login success handler
const loginSuccess = useCallback(
async (res: ResLogin) => {
setUserInfo(res.user);
(res: LoginSuccessResponse) => {
onSuccess?.(res);
},
[setUserInfo, onSuccess]
[onSuccess]
);
// initialization logic

View File

@@ -1,4 +1,4 @@
import React, { useMemo } from 'react';
import React, { useCallback, useMemo } from 'react';
import NextHead from '@/components/common/NextHead';
import { Box, Flex } from '@chakra-ui/react';
import { useChatStore } from '@/web/core/chat/context/useChatStore';
@@ -27,6 +27,8 @@ import {
} from '@/web/core/chat/context/chatSettingContext';
import ChatTeamApp from '@/pageComponents/chat/ChatTeamApp';
import ChatFavouriteApp from '@/pageComponents/chat/ChatFavouriteApp';
import { useUserStore } from '@/web/support/user/useUserStore';
import type { LoginSuccessResponse } from '@/global/support/api/userRes';
const Chat = ({ myApps }: { myApps: AppListItemType[] }) => {
const { isPc } = useSystem();
@@ -89,6 +91,7 @@ const Chat = ({ myApps }: { myApps: AppListItemType[] }) => {
const Render = (props: { appId: string; isStandalone?: string }) => {
const { appId, isStandalone } = props;
const { chatId } = useChatStore();
const { setUserInfo } = useUserStore();
const { feConfigs } = useSystemStore();
const { isInitedUser, userInfo, myApps } = useChat(appId);
@@ -105,6 +108,10 @@ const Render = (props: { appId: string; isStandalone?: string }) => {
};
}, [appId, chatId]);
const loginSuccess = useCallback(async (res: LoginSuccessResponse) => {
setUserInfo(res.user);
}, []);
// Waiting for user info to be initialized
if (!isInitedUser) {
return (
@@ -120,7 +127,7 @@ const Render = (props: { appId: string; isStandalone?: string }) => {
<>
<NextHead title={feConfigs?.systemTitle}></NextHead>
<LoginModal />
<LoginModal onSuccess={loginSuccess} />
</>
);
}

View File

@@ -1,6 +1,6 @@
import React, { useCallback, useEffect } from 'react';
import { useRouter } from 'next/router';
import type { ResLogin } from '@/global/support/api/userRes.d';
import type { LoginSuccessResponse } from '@/global/support/api/userRes.d';
import { useUserStore } from '@/web/support/user/useUserStore';
import { clearToken } from '@/web/support/user/auth';
import { postFastLogin } from '@/web/support/user/api';
@@ -23,7 +23,7 @@ const FastLogin = ({
const { toast } = useToast();
const { t } = useTranslation();
const loginSuccess = useCallback(
(res: ResLogin) => {
(res: LoginSuccessResponse) => {
setUserInfo(res.user);
setTimeout(() => {

View File

@@ -5,14 +5,22 @@ import { clearToken } from '@/web/support/user/auth';
import { useMount } from 'ahooks';
import LoginModal from '@/pageComponents/login/LoginModal';
import { postAcceptInvitationLink } from '@/web/support/user/team/api';
import type { ResLogin } from '@/global/support/api/userRes';
import type { LoginSuccessResponse } from '@/global/support/api/userRes';
import { useToast } from '@fastgpt/web/hooks/useToast';
import { useTranslation } from 'next-i18next';
import { useUserStore } from '@/web/support/user/useUserStore';
const Login = () => {
const router = useRouter();
const { lastRoute = '' } = router.query as { lastRoute: string };
const { t } = useTranslation();
const { toast } = useToast();
const { setUserInfo } = useUserStore();
const loginSuccess = useCallback(
async (res: ResLogin) => {
async (res: LoginSuccessResponse) => {
setUserInfo(res.user);
const decodeLastRoute = decodeURIComponent(lastRoute);
const navigateTo = await (async () => {
if (res.user.team.status !== 'active') {
@@ -20,8 +28,14 @@ const Login = () => {
const id = decodeLastRoute.split('invitelinkid=')[1];
await postAcceptInvitationLink(id);
return '/dashboard/apps';
} else {
toast({
status: 'warning',
title: t('common:not_active_team')
});
}
}
return decodeLastRoute &&
!decodeLastRoute.includes('/login') &&
decodeLastRoute.startsWith('/')
@@ -29,7 +43,7 @@ const Login = () => {
: '/dashboard/apps';
})();
router.replace(navigateTo);
navigateTo && router.replace(navigateTo);
},
[lastRoute, router]
);

View File

@@ -1,7 +1,7 @@
import React, { useCallback, useEffect } from 'react';
import { useRouter } from 'next/router';
import { useSystemStore } from '@/web/common/system/useSystemStore';
import type { ResLogin } from '@/global/support/api/userRes.d';
import type { LoginSuccessResponse } from '@/global/support/api/userRes.d';
import { useUserStore } from '@/web/support/user/useUserStore';
import { clearToken } from '@/web/support/user/auth';
import { oauthLogin } from '@/web/support/user/api';
@@ -32,35 +32,37 @@ const provider = () => {
const { toast } = useToast();
const lastRoute = loginStore?.lastRoute
? decodeURIComponent(loginStore?.lastRoute)
? decodeURIComponent(loginStore.lastRoute)
: '/dashboard/apps';
const errorRedirectPage = lastRoute.startsWith('/chat') ? lastRoute : '/login';
// const loginSuccess = useCallback(async () => {
// const decodeLastRoute = decodeURIComponent(lastRoute);
// router.push(navigateTo);
// }, [lastRoute, router]);
const loginSuccess = useCallback(
async (res: ResLogin) => {
async (res: LoginSuccessResponse) => {
const decodeLastRoute = decodeURIComponent(lastRoute);
setUserInfo(res.user);
const navigateTo = await (async () => {
if (res.user.team.status !== 'active') {
if (decodeLastRoute.includes('/account/team?invitelinkid=')) {
const id = decodeLastRoute.split('invitelinkid=')[1];
await postAcceptInvitationLink(id);
return '/dashboard/apps';
} else {
toast({
status: 'warning',
title: t('common:not_active_team')
});
}
}
return decodeLastRoute &&
!decodeLastRoute.includes('/login') &&
decodeLastRoute.startsWith('/')
? lastRoute
: '/dashboard/apps';
})();
router.replace(navigateTo);
navigateTo && router.replace(navigateTo);
},
[setUserInfo, router, lastRoute]
);

View File

@@ -1,6 +1,6 @@
import { GET, POST, PUT } from '@/web/common/api/request';
import { hashStr } from '@fastgpt/global/common/string/tools';
import type { ResLogin } from '@/global/support/api/userRes.d';
import type { LoginSuccessResponse } from '@/global/support/api/userRes.d';
import type { UserAuthTypeEnum } from '@fastgpt/global/support/user/auth/constants';
import type { UserUpdateParams } from '@/types/user';
import type { UserType } from '@fastgpt/global/support/user/type.d';
@@ -27,10 +27,11 @@ export const sendAuthCode = (data: {
export const getTokenLogin = () =>
GET<UserType>('/support/user/account/tokenLogin', {}, { maxQuantity: 1 });
export const oauthLogin = (params: OauthLoginProps) =>
POST<ResLogin>('/proApi/support/user/account/login/oauth', params);
POST<LoginSuccessResponse>('/proApi/support/user/account/login/oauth', params);
export const postFastLogin = (params: FastLoginProps) =>
POST<ResLogin>('/proApi/support/user/account/login/fastLogin', params);
export const ssoLogin = (params: any) => GET<ResLogin>('/proApi/support/user/account/sso', params);
POST<LoginSuccessResponse>('/proApi/support/user/account/login/fastLogin', params);
export const ssoLogin = (params: any) =>
GET<LoginSuccessResponse>('/proApi/support/user/account/sso', params);
export const postRegister = ({
username,
@@ -41,7 +42,7 @@ export const postRegister = ({
msclkid,
fastgpt_sem
}: AccountRegisterBody) =>
POST<ResLogin>(`/proApi/support/user/account/register/emailAndPhone`, {
POST<LoginSuccessResponse>(`/proApi/support/user/account/register/emailAndPhone`, {
username,
code,
inviterId,
@@ -60,7 +61,7 @@ export const postFindPassword = ({
code: string;
password: string;
}) =>
POST<ResLogin>(`/proApi/support/user/account/password/updateByCode`, {
POST<LoginSuccessResponse>(`/proApi/support/user/account/password/updateByCode`, {
username,
code,
password: hashStr(password)
@@ -88,7 +89,7 @@ export const updateContact = (data: { contact: string; verifyCode: string }) =>
};
export const postLogin = ({ password, ...props }: PostLoginProps) =>
POST<ResLogin>('/support/user/account/loginByPassword', {
POST<LoginSuccessResponse>('/support/user/account/loginByPassword', {
...props,
password: hashStr(password)
});
@@ -101,7 +102,7 @@ export const getWXLoginQR = () =>
GET<GetWXLoginQRResponse>('/proApi/support/user/account/login/wx/getQR');
export const getWXLoginResult = (params: WxLoginProps) =>
POST<ResLogin>(`/proApi/support/user/account/login/wx/getResult`, params);
POST<LoginSuccessResponse>(`/proApi/support/user/account/login/wx/getResult`, params);
export const getCaptchaPic = (username: string) =>
GET<{