Files
FastGPT/projects/app/src/pages/login/index.tsx
2024-09-27 22:19:48 +08:00

235 lines
7.0 KiB
TypeScript

import React, { useState, useCallback, useEffect } from 'react';
import {
Box,
Button,
Center,
Drawer,
DrawerCloseButton,
DrawerContent,
DrawerOverlay,
Flex,
useDisclosure
} 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 { useRouter } from 'next/router';
import { useUserStore } from '@/web/support/user/useUserStore';
import { useChatStore } from '@/web/core/chat/context/storeChat';
import LoginForm from './components/LoginForm/LoginForm';
import dynamic from 'next/dynamic';
import { serviceSideProps } from '@/web/common/utils/i18n';
import { clearToken, setToken } from '@/web/support/user/auth';
import Script from 'next/script';
import Loading from '@fastgpt/web/components/common/MyLoading';
import { useLocalStorageState, useMount } from 'ahooks';
import { useTranslation } from 'next-i18next';
import I18nLngSelector from '@/components/Select/I18nLngSelector';
import { useSystem } from '@fastgpt/web/hooks/useSystem';
import { GET } from '@/web/common/api/request';
const RegisterForm = dynamic(() => import('./components/RegisterForm'));
const ForgetPasswordForm = dynamic(() => import('./components/ForgetPasswordForm'));
const WechatForm = dynamic(() => import('./components/LoginForm/WechatForm'));
const CommunityModal = dynamic(() => import('@/components/CommunityModal'));
const ipDetectURL = 'https://qifu-api.baidubce.com/ip/local/geo/v1/district';
const Login = ({ ChineseRedirectUrl }: { ChineseRedirectUrl: string }) => {
const router = useRouter();
const { t } = useTranslation();
const { lastRoute = '' } = router.query as { lastRoute: string };
const { feConfigs } = useSystemStore();
const [pageType, setPageType] = useState<`${LoginPageTypeEnum}`>();
const { setUserInfo } = useUserStore();
const { setLastChatId, setLastChatAppId } = useChatStore();
const { isOpen, onOpen, onClose } = useDisclosure();
const { isPc } = useSystem();
const {
isOpen: isOpenRedirect,
onOpen: onOpenRedirect,
onClose: onCloseRedirect
} = useDisclosure();
const [showRedirect, setShowRedirect] = useLocalStorageState<boolean>('showRedirect', {
defaultValue: true
});
const checkIpInChina = useCallback(
() =>
GET(ipDetectURL).then((res: any) => {
const country = res?.country;
if (country && country === '中国' && res.city !== '中国香港') {
onOpenRedirect();
}
}),
[onOpenRedirect]
);
const loginSuccess = useCallback(
(res: ResLogin) => {
// init store
setLastChatId('');
setLastChatAppId('');
setUserInfo(res.user);
setToken(res.token);
setTimeout(() => {
router.push(lastRoute ? decodeURIComponent(lastRoute) : '/app/list');
}, 300);
},
[lastRoute, router, setLastChatId, setLastChatAppId, setUserInfo]
);
function DynamicComponent({ type }: { type: `${LoginPageTypeEnum}` }) {
const TypeMap = {
[LoginPageTypeEnum.passwordLogin]: LoginForm,
[LoginPageTypeEnum.register]: RegisterForm,
[LoginPageTypeEnum.forgetPassword]: ForgetPasswordForm,
[LoginPageTypeEnum.wechat]: WechatForm
};
const Component = TypeMap[type];
return <Component setPageType={setPageType} loginSuccess={loginSuccess} />;
}
/* default login type */
useEffect(() => {
setPageType(
feConfigs?.oauth?.wechat ? LoginPageTypeEnum.wechat : LoginPageTypeEnum.passwordLogin
);
}, [feConfigs.oauth]);
useMount(() => {
clearToken();
ChineseRedirectUrl && showRedirect && checkIpInChina();
router.prefetch('/app/list');
});
return (
<>
{feConfigs.googleClientVerKey && (
<Script
src={`https://www.recaptcha.net/recaptcha/api.js?render=${feConfigs.googleClientVerKey}`}
></Script>
)}
<Flex
alignItems={'center'}
justifyContent={'center'}
bg={`url('/icon/login-bg.svg') no-repeat`}
backgroundSize={'cover'}
userSelect={'none'}
h={'100%'}
px={[0, '10vw']}
>
{isPc && (
<Box position={'absolute'} top={'24px'} right={'50px'}>
<I18nLngSelector />
</Box>
)}
<Flex
flexDirection={'column'}
w={['100%', 'auto']}
h={['100%', '700px']}
maxH={['100%', '90vh']}
bg={'white'}
px={['5vw', '88px']}
py={'5vh'}
borderRadius={[0, '24px']}
boxShadow={[
'',
'0px 0px 1px 0px rgba(19, 51, 107, 0.20), 0px 32px 64px -12px rgba(19, 51, 107, 0.20)'
]}
>
<Box w={['100%', '380px']} flex={'1 0 0'}>
{pageType ? (
<DynamicComponent type={pageType} />
) : (
<Center w={'full'} h={'full'} position={'relative'}>
<Loading fixed={false} />
</Center>
)}
</Box>
{feConfigs?.concatMd && (
<Box
mt={8}
color={'primary.700'}
cursor={'pointer'}
textAlign={'center'}
onClick={onOpen}
>
{t('common:support.user.login.can_not_login')}
</Box>
)}
</Flex>
{isOpen && <CommunityModal onClose={onClose} />}
</Flex>
{showRedirect && (
<RedirectDrawer
isOpen={isOpenRedirect}
onClose={onCloseRedirect}
onRedirect={() => router.push(ChineseRedirectUrl)}
disableDrawer={() => setShowRedirect(false)}
/>
)}
</>
);
};
function RedirectDrawer({
isOpen,
onClose,
disableDrawer,
onRedirect
}: {
isOpen: boolean;
onClose: () => void;
disableDrawer: () => void;
onRedirect: () => void;
}) {
const { t } = useTranslation();
return (
<Drawer placement="bottom" size={'xs'} isOpen={isOpen} onClose={onClose}>
<DrawerOverlay backgroundColor={'rgba(0,0,0,0.2)'} />
<DrawerContent py={'1.75rem'} px={'3rem'}>
<DrawerCloseButton size={'sm'} />
<Flex align={'center'} justify={'space-between'}>
<Box>
<Box color={'myGray.900'} fontWeight={'500'} fontSize={'1rem'}>
{t('login:Chinese_ip_tip')}
</Box>
<Box
color={'primary.700'}
fontWeight={'500'}
fontSize={'1rem'}
textDecorationLine={'underline'}
cursor={'pointer'}
onClick={disableDrawer}
>
{t('login:no_remind')}
</Box>
</Box>
<Button ml={'0.75rem'} onClick={onRedirect}>
{t('login:redirect')}
</Button>
</Flex>
</DrawerContent>
</Drawer>
);
}
export async function getServerSideProps(context: any) {
return {
props: {
ChineseRedirectUrl: process.env.CHINESE_IP_REDIRECT_URL,
...(await serviceSideProps(context, ['app', 'user', 'login']))
}
};
}
export default Login;