Commit d1c71eeb by light5980 Committed by GitHub

fix: login ui (#7009)

* fix: login ui

* delet doc

* fix: login en policy tip

* perf: word break

---------

Co-authored-by: archer <545436317@qq.com>
parent bd140f71
...@@ -78,6 +78,7 @@ export type FastGPTFeConfigsType = { ...@@ -78,6 +78,7 @@ export type FastGPTFeConfigsType = {
concatMd?: string; concatMd?: string;
docUrl?: string; docUrl?: string;
loginGuideDocUrl?: string;
openAPIDocUrl?: string; openAPIDocUrl?: string;
submitPluginRequestUrl?: string; submitPluginRequestUrl?: string;
appTemplateCourse?: string; appTemplateCourse?: string;
......
...@@ -1060,7 +1060,7 @@ ...@@ -1060,7 +1060,7 @@
"support.user.login.Provider error": "Login Error, Please Try Again", "support.user.login.Provider error": "Login Error, Please Try Again",
"support.user.login.Username": "Username", "support.user.login.Username": "Username",
"support.user.login.Wechat": "WeChat Login", "support.user.login.Wechat": "WeChat Login",
"support.user.login.can_not_login": "Cannot log in? Click here to contact us", "support.user.login.can_not_login": "Cannot log in?",
"support.user.login.error": "Login Error", "support.user.login.error": "Login Error",
"support.user.login.security_failed": "Security Verification Failed", "support.user.login.security_failed": "Security Verification Failed",
"support.user.login.wx_qr_login": "WeChat QR Code Login", "support.user.login.wx_qr_login": "WeChat QR Code Login",
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
"no_remind": "Don't remind again", "no_remind": "Don't remind again",
"password_condition": "Password must be 4–60 characters", "password_condition": "Password must be 4–60 characters",
"password_tip": "Password must be at least 8 characters long and contain at least two combinations: numbers, letters, or special characters", "password_tip": "Password must be at least 8 characters long and contain at least two combinations: numbers, letters, or special characters",
"policy_tip": "By using it, you have read and agree to\n<div>our<termsLink> Terms </termsLink>&<privacyLink> Privacy Policy</privacyLink></div>", "policy_tip": "By using it, you have read and agree to <lineBreak/>our<termsLink> Terms </termsLink>&<privacyLink> Privacy Policy</privacyLink>",
"privacy_policy": "Privacy Policy", "privacy_policy": "Privacy Policy",
"redirect": "Jump", "redirect": "Jump",
"register": "Register", "register": "Register",
......
...@@ -1060,7 +1060,7 @@ ...@@ -1060,7 +1060,7 @@
"support.user.login.Provider error": "登录异常,请重试", "support.user.login.Provider error": "登录异常,请重试",
"support.user.login.Username": "用户名", "support.user.login.Username": "用户名",
"support.user.login.Wechat": "微信登录", "support.user.login.Wechat": "微信登录",
"support.user.login.can_not_login": "无法登录,点击联系", "support.user.login.can_not_login": "无法登录",
"support.user.login.error": "登录异常", "support.user.login.error": "登录异常",
"support.user.login.security_failed": "安全校验失败", "support.user.login.security_failed": "安全校验失败",
"support.user.login.wx_qr_login": "微信扫码登录", "support.user.login.wx_qr_login": "微信扫码登录",
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
"no_remind": "不再提醒", "no_remind": "不再提醒",
"password_condition": "密码最多 60 位", "password_condition": "密码最多 60 位",
"password_tip": "密码至少 8 位,且至少包含两种组合:数字、字母或特殊字符", "password_tip": "密码至少 8 位,且至少包含两种组合:数字、字母或特殊字符",
"policy_tip": "使用即代表您已阅读并同意<termsLink> 服务协议 </termsLink>和<privacyLink> 隐私协议</privacyLink>", "policy_tip": "使用即代表您已经阅读并且同意<lineBreak/>我们的<termsLink> 服务协议 </termsLink> & <privacyLink> 隐私协议</privacyLink>",
"privacy_policy": "隐私政策", "privacy_policy": "隐私政策",
"redirect": "跳转", "redirect": "跳转",
"register": "注册账号", "register": "注册账号",
......
...@@ -1049,7 +1049,7 @@ ...@@ -1049,7 +1049,7 @@
"support.user.login.Provider error": "登入錯誤,請重試", "support.user.login.Provider error": "登入錯誤,請重試",
"support.user.login.Username": "使用者名稱", "support.user.login.Username": "使用者名稱",
"support.user.login.Wechat": "微信登入", "support.user.login.Wechat": "微信登入",
"support.user.login.can_not_login": "無法登入,點選聯絡我們", "support.user.login.can_not_login": "無法登入",
"support.user.login.error": "登入錯誤", "support.user.login.error": "登入錯誤",
"support.user.login.security_failed": "安全驗證失敗", "support.user.login.security_failed": "安全驗證失敗",
"support.user.login.wx_qr_login": "微信 QR Code 登入", "support.user.login.wx_qr_login": "微信 QR Code 登入",
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
"no_remind": "不再提醒", "no_remind": "不再提醒",
"password_condition": "密碼最多 60 個字元", "password_condition": "密碼最多 60 個字元",
"password_tip": "密碼至少 8 位,且至少包含兩種組合:數字、字母或特殊字元", "password_tip": "密碼至少 8 位,且至少包含兩種組合:數字、字母或特殊字元",
"policy_tip": "使用即代表您已閱讀並同意<termsLink> 服務協議 </termsLink>和<privacyLink> 隱私協議</privacyLink>", "policy_tip": "使用即代表您已經閱讀並且同意<lineBreak/>我們的<termsLink> 服務協議 </termsLink> & <privacyLink> 隱私協議</privacyLink>",
"privacy_policy": "隱私權政策", "privacy_policy": "隱私權政策",
"redirect": "跳轉", "redirect": "跳轉",
"register": "註冊帳號", "register": "註冊帳號",
......
This source diff could not be displayed because it is too large. You can view the blob instead.
...@@ -6,8 +6,6 @@ import { OAuthEnum } from '@fastgpt/global/support/user/constant'; ...@@ -6,8 +6,6 @@ import { OAuthEnum } from '@fastgpt/global/support/user/constant';
import { useRouter } from 'next/router'; import { useRouter } from 'next/router';
import { type Dispatch, useCallback, useEffect, useMemo, useState } from 'react'; import { type Dispatch, useCallback, useEffect, useMemo, useState } from 'react';
import { useTranslation } from 'next-i18next'; import { useTranslation } from 'next-i18next';
import I18nLngSelector from '@/components/Select/I18nLngSelector';
import { useSystem } from '@fastgpt/web/hooks/useSystem';
import MyImage from '@fastgpt/web/components/common/Image/MyImage'; import MyImage from '@fastgpt/web/components/common/Image/MyImage';
import { checkIsWecomTerminal } from '@fastgpt/global/support/user/login/constants'; import { checkIsWecomTerminal } from '@fastgpt/global/support/user/login/constants';
import { getNanoid } from '@fastgpt/global/common/string/tools'; import { getNanoid } from '@fastgpt/global/common/string/tools';
...@@ -36,7 +34,6 @@ const FormLayout = ({ children, setPageType, pageType }: Props) => { ...@@ -36,7 +34,6 @@ const FormLayout = ({ children, setPageType, pageType }: Props) => {
const rootLogin = router.query.rootLogin === '1'; const rootLogin = router.query.rootLogin === '1';
const { setLoginStore, feConfigs } = useSystemStore(); const { setLoginStore, feConfigs } = useSystemStore();
const { isPc } = useSystem();
const { lastRoute = '/dashboard/agent', lastTmbId = '' } = router.query as { const { lastRoute = '/dashboard/agent', lastTmbId = '' } = router.query as {
lastRoute: string; lastRoute: string;
...@@ -200,13 +197,23 @@ const FormLayout = ({ children, setPageType, pageType }: Props) => { ...@@ -200,13 +197,23 @@ const FormLayout = ({ children, setPageType, pageType }: Props) => {
]); ]);
return ( return (
<Flex flexDirection={'column'} h={'100%'}> <Flex
<Flex alignItems={'center'} justifyContent={['space-between', 'center']}> flexDirection={'column'}
<Flex alignItems={'center'} pr="4"> h={'100%'}
alignItems={['center', 'stretch']}
justifyContent={['center', 'flex-start']}
>
<Flex
alignItems={'center'}
justifyContent={['flex-start', 'center']}
w={['fit-content', '100%']}
alignSelf={['flex-start', 'auto']}
>
<Flex alignItems={'center'} pr={['0', '4']} w={'fit-content'} justifyContent={'flex-start'}>
<Flex <Flex
w={['42px', '56px']} w={['42px', '56px']}
h={['42px', '56px']} h={['42px', '56px']}
bg={'myGray.25'} bg={'white'}
borderRadius={['semilg', 'lg']} borderRadius={['semilg', 'lg']}
borderWidth={['1px', '1.5px']} borderWidth={['1px', '1.5px']}
borderColor={'myGray.200'} borderColor={'myGray.200'}
...@@ -219,14 +226,15 @@ const FormLayout = ({ children, setPageType, pageType }: Props) => { ...@@ -219,14 +226,15 @@ const FormLayout = ({ children, setPageType, pageType }: Props) => {
{feConfigs?.systemTitle} {feConfigs?.systemTitle}
</Box> </Box>
</Flex> </Flex>
{!isPc && <I18nLngSelector />}
</Flex> </Flex>
{children} <Box w={'100%'} mt={[8, 0]}>
{children}
</Box>
{show_oauth && ( {show_oauth && (
<Box mt={['80px', 9]}> <Box mt={8} w={'100%'}>
<Box flex={1} /> <Box flex={1} />
<Flex position={'relative'} mb={5} alignItems={'center'}> <Flex position={'relative'} mb={4} alignItems={'center'}>
<Box h={'1px'} flex={'1'} bg={'myGray.250'} /> <Box h={'1px'} flex={'1'} bg={'myGray.250'} />
<Box px={3} color={'myGray.500'} fontSize={'mini'}> <Box px={3} color={'myGray.500'} fontSize={'mini'}>
or or
......
...@@ -7,13 +7,13 @@ import { useSystemStore } from '@/web/common/system/useSystemStore'; ...@@ -7,13 +7,13 @@ import { useSystemStore } from '@/web/common/system/useSystemStore';
import { useTranslation } from 'next-i18next'; import { useTranslation } from 'next-i18next';
import FormLayout from './FormLayout'; import FormLayout from './FormLayout';
import { useRequest } from '@fastgpt/web/hooks/useRequest'; import { useRequest } from '@fastgpt/web/hooks/useRequest';
import PolicyTip from './PolicyTip';
import { useSearchParams } from 'next/navigation'; import { useSearchParams } from 'next/navigation';
import { UserErrEnum } from '@fastgpt/global/common/error/code/user'; import { UserErrEnum } from '@fastgpt/global/common/error/code/user';
import { useRouter } from 'next/router'; import { useRouter } from 'next/router';
import { useMount } from 'ahooks'; import { useMount } from 'ahooks';
import type { LangEnum } from '@fastgpt/global/common/i18n/type'; import type { LangEnum } from '@fastgpt/global/common/i18n/type';
import type { LoginSuccessResponseType } from '@fastgpt/global/openapi/support/user/account/login/api'; import type { LoginSuccessResponseType } from '@fastgpt/global/openapi/support/user/account/login/api';
import PolicyTip from './PolicyTip';
type LoginSuccessHandler = (res: LoginSuccessResponseType) => void | Promise<void>; type LoginSuccessHandler = (res: LoginSuccessResponseType) => void | Promise<void>;
...@@ -108,7 +108,7 @@ const LoginForm = ({ setPageType, loginSuccess }: Props) => { ...@@ -108,7 +108,7 @@ const LoginForm = ({ setPageType, loginSuccess }: Props) => {
return ( return (
<FormLayout setPageType={setPageType} pageType={LoginPageTypeEnum.passwordLogin}> <FormLayout setPageType={setPageType} pageType={LoginPageTypeEnum.passwordLogin}>
<Box <Box
mt={8} mt={[0, 8]}
onKeyDown={(e) => { onKeyDown={(e) => {
if (e.key === 'Enter' && !e.shiftKey && !requesting) { if (e.key === 'Enter' && !e.shiftKey && !requesting) {
handleSubmit(onclickLogin)(); handleSubmit(onclickLogin)();
...@@ -117,7 +117,7 @@ const LoginForm = ({ setPageType, loginSuccess }: Props) => { ...@@ -117,7 +117,7 @@ const LoginForm = ({ setPageType, loginSuccess }: Props) => {
> >
<FormControl isInvalid={!!errors.username}> <FormControl isInvalid={!!errors.username}>
<Input <Input
bg={'myGray.50'} bg={'white'}
size={'lg'} size={'lg'}
placeholder={placeholder} placeholder={placeholder}
{...register('username', { {...register('username', {
...@@ -125,9 +125,9 @@ const LoginForm = ({ setPageType, loginSuccess }: Props) => { ...@@ -125,9 +125,9 @@ const LoginForm = ({ setPageType, loginSuccess }: Props) => {
})} })}
></Input> ></Input>
</FormControl> </FormControl>
<FormControl mt={7} isInvalid={!!errors.password}> <FormControl mt={6} isInvalid={!!errors.password}>
<Input <Input
bg={'myGray.50'} bg={'white'}
size={'lg'} size={'lg'}
type={'password'} type={'password'}
placeholder={ placeholder={
...@@ -144,14 +144,12 @@ const LoginForm = ({ setPageType, loginSuccess }: Props) => { ...@@ -144,14 +144,12 @@ const LoginForm = ({ setPageType, loginSuccess }: Props) => {
})} })}
></Input> ></Input>
</FormControl> </FormControl>
<PolicyTip isCenter={false} /> <PolicyTip />
<Button <Button
type="submit" type="submit"
my={[5, 7]} mt={6}
w={'100%'} w={'100%'}
size={['md', 'md']} size={'lg'}
h={[10, 10]}
fontWeight={['medium', 'medium']} fontWeight={['medium', 'medium']}
colorScheme="blue" colorScheme="blue"
isLoading={requesting} isLoading={requesting}
...@@ -161,10 +159,14 @@ const LoginForm = ({ setPageType, loginSuccess }: Props) => { ...@@ -161,10 +159,14 @@ const LoginForm = ({ setPageType, loginSuccess }: Props) => {
</Button> </Button>
<Flex <Flex
mt={6}
align={'center'} align={'center'}
justifyContent={['flex-end', 'center']} justifyContent={'center'}
gap={0}
color={'primary.700'} color={'primary.700'}
fontWeight={'medium'} fontWeight={'medium'}
h={'16px'}
lineHeight={'16px'}
> >
{feConfigs?.find_password_method && feConfigs.find_password_method.length > 0 && ( {feConfigs?.find_password_method && feConfigs.find_password_method.length > 0 && (
<Box <Box
...@@ -177,17 +179,18 @@ const LoginForm = ({ setPageType, loginSuccess }: Props) => { ...@@ -177,17 +179,18 @@ const LoginForm = ({ setPageType, loginSuccess }: Props) => {
</Box> </Box>
)} )}
{feConfigs?.register_method && feConfigs.register_method.length > 0 && ( {feConfigs?.register_method && feConfigs.register_method.length > 0 && (
<Flex alignItems={'center'}> <>
<Box mx={3} h={'12px'} w={'1px'} bg={'myGray.250'}></Box> <Box display={['block', 'block']} mx={3} h={'12px'} w={'1px'} bg={'myGray.250'}></Box>
<Box <Box
cursor={'pointer'} cursor={'pointer'}
_hover={{ textDecoration: 'underline' }} _hover={{ textDecoration: 'underline' }}
onClick={() => setPageType('register')} onClick={() => setPageType('register')}
fontSize="mini" fontSize="mini"
lineHeight="16px"
> >
{t('login:register')} {t('login:register')}
</Box> </Box>
</Flex> </>
)} )}
</Flex> </Flex>
</Box> </Box>
......
import { getDocPath } from '@/web/common/system/doc'; import { getDocPath } from '@/web/common/system/doc';
import { useSystemStore } from '@/web/common/system/useSystemStore'; import { useSystemStore } from '@/web/common/system/useSystemStore';
import { Box, Flex, Link } from '@chakra-ui/react'; import { Box, Link } from '@chakra-ui/react';
import React from 'react'; import React, { useEffect, useRef, useState } from 'react';
import { Trans } from 'next-i18next'; import { Trans, useTranslation } from 'next-i18next';
const PolicyTip = ({ isCenter }: { isCenter: boolean }) => { const PolicyTip = () => {
const { feConfigs } = useSystemStore(); const { feConfigs } = useSystemStore();
const { i18n } = useTranslation();
const tipRef = useRef<HTMLDivElement>(null);
const measureRef = useRef<HTMLSpanElement>(null);
const [isMultiline, setIsMultiline] = useState(false);
useEffect(() => {
const tip = tipRef.current;
const measure = measureRef.current;
if (!tip || !measure) return;
// 先按单行版本测量宽度;放不下时再使用文案中的 lineBreak 设计断点。
const updateMultiline = () => {
const tipWidth = tip.getBoundingClientRect().width;
const singleLineWidth = measure.scrollWidth;
setIsMultiline(singleLineWidth > tipWidth + 1);
};
const timer = setTimeout(updateMultiline, 0);
const observer = new ResizeObserver(updateMultiline);
observer.observe(tip);
observer.observe(measure);
return () => {
clearTimeout(timer);
observer.disconnect();
};
}, [i18n.language, feConfigs?.docUrl]);
return ( return (
<> <>
{feConfigs?.docUrl && ( {feConfigs?.docUrl && (
<Box <Box
display={isCenter ? 'block' : 'flex'} ref={tipRef}
textAlign={isCenter ? 'center' : 'left'} display={'block'}
mt={7} position={'relative'}
textAlign={isMultiline ? 'center' : 'left'}
mt={6}
fontSize={'mini'} fontSize={'mini'}
lineHeight={'16px'}
color={'myGray.400'} color={'myGray.400'}
whiteSpace={'pre-wrap'} whiteSpace={'pre-wrap'}
> >
<Trans <Trans
i18nKey="login:policy_tip" i18nKey="login:policy_tip"
components={{ components={{
div: <Flex justifyContent={'center'} />, lineBreak: isMultiline ? <br /> : <span />,
termsLink: ( termsLink: (
<Link <Link
href={getDocPath('/guide/version/cloud/terms')} href={getDocPath('/guide/version/cloud/terms')}
...@@ -38,6 +69,24 @@ const PolicyTip = ({ isCenter }: { isCenter: boolean }) => { ...@@ -38,6 +69,24 @@ const PolicyTip = ({ isCenter }: { isCenter: boolean }) => {
) )
}} }}
/> />
<Box
ref={measureRef}
as={'span'}
position={'absolute'}
visibility={'hidden'}
pointerEvents={'none'}
whiteSpace={'nowrap'}
aria-hidden
>
<Trans
i18nKey="login:policy_tip"
components={{
lineBreak: <span />,
termsLink: <Link />,
privacyLink: <Link />
}}
/>
</Box>
</Box> </Box>
)} )}
</> </>
......
...@@ -88,7 +88,7 @@ const WechatForm = ({ setPageType, loginSuccess }: Props) => { ...@@ -88,7 +88,7 @@ const WechatForm = ({ setPageType, loginSuccess }: Props) => {
</Center> </Center>
)} )}
</Box> </Box>
<PolicyTip isCenter /> <PolicyTip />
</Box> </Box>
</FormLayout> </FormLayout>
); );
......
...@@ -3,7 +3,6 @@ import { Box, Flex } from '@chakra-ui/react'; ...@@ -3,7 +3,6 @@ import { Box, Flex } from '@chakra-ui/react';
import { LoginContainer } from '@/pageComponents/login'; import { LoginContainer } from '@/pageComponents/login';
import I18nLngSelector from '@/components/Select/I18nLngSelector'; import I18nLngSelector from '@/components/Select/I18nLngSelector';
import { useSystem } from '@fastgpt/web/hooks/useSystem'; import { useSystem } from '@fastgpt/web/hooks/useSystem';
import { getWebReqUrl } from '@fastgpt/web/common/system/utils';
import { type LoginSuccessResponseType } from '@fastgpt/global/openapi/support/user/account/login/api'; import { type LoginSuccessResponseType } from '@fastgpt/global/openapi/support/user/account/login/api';
type LoginModalProps = { type LoginModalProps = {
...@@ -17,10 +16,12 @@ const LoginModal = ({ onSuccess }: LoginModalProps) => { ...@@ -17,10 +16,12 @@ const LoginModal = ({ onSuccess }: LoginModalProps) => {
<Flex <Flex
alignItems={'center'} alignItems={'center'}
justifyContent={'center'} justifyContent={'center'}
bg={['white', `url(${getWebReqUrl('/icon/login-bg.svg')}) no-repeat`]} bg={'white'}
backgroundSize={['cover', 'cover']}
userSelect={'none'} userSelect={'none'}
h={'100%'} minH={'100vh'}
px={0}
pt={0}
pb={0}
> >
{/* Language selector - login page */} {/* Language selector - login page */}
{isPc && ( {isPc && (
...@@ -30,21 +31,48 @@ const LoginModal = ({ onSuccess }: LoginModalProps) => { ...@@ -30,21 +31,48 @@ const LoginModal = ({ onSuccess }: LoginModalProps) => {
)} )}
<Flex <Flex
flexDirection={'column'}
w={['100%', '560px']}
h={['100%', '690px']}
bg={[`url(${getWebReqUrl('/icon/login-bg-phone.svg')}) no-repeat`, 'white']}
backgroundSize={'cover'}
px={['8', '90px']}
py={['38px', '90px']}
borderRadius={[0, '16px']}
boxShadow={[
'',
'0px 32px 64px -12px rgba(19, 51, 107, 0.20), 0px 0px 1px 0px rgba(19, 51, 107, 0.20)'
]}
position="relative" position="relative"
alignItems={'center'}
justifyContent={'center'}
w={'100%'}
maxW={['100%', '1328px']}
h={'100vh'}
minH={['100vh', '720px']}
bg={['transparent', 'white']}
borderRadius={[0, '24px']}
overflow={'hidden'}
> >
<LoginContainer onSuccess={onSuccess} /> <Box
position={'absolute'}
top={['-190px', '-100px']}
left={'50%'}
w={['900px', '1230px']}
h={['590px', '510px']}
transform={'translateX(-50%)'}
pointerEvents={'none'}
bgImage={'url(/icon/login-gradient-bg.svg)'}
bgRepeat={'no-repeat'}
bgPosition={'center top'}
bgSize={'100% 100%'}
/>
<Flex
flexDirection={'column'}
w={['100%', '560px']}
h={['100%', 'auto']}
bg={['transparent', 'white']}
px={['8', '90px']}
py={['38px', '90px']}
borderRadius={[0, '16px']}
boxShadow={[
'',
'0px 16px 40px rgba(30, 64, 175, 0.10), 0px 1px 3px rgba(15, 23, 42, 0.06)'
]}
position="relative"
zIndex={1}
>
<LoginContainer onSuccess={onSuccess} />
</Flex>
</Flex> </Flex>
</Flex> </Flex>
); );
......
...@@ -16,9 +16,15 @@ type LoginFormPanelProps = { ...@@ -16,9 +16,15 @@ type LoginFormPanelProps = {
pageType: `${LoginPageTypeEnum}`; pageType: `${LoginPageTypeEnum}`;
setPageType: Dispatch<`${LoginPageTypeEnum}`>; setPageType: Dispatch<`${LoginPageTypeEnum}`>;
loginSuccess: LoginSuccessHandler; loginSuccess: LoginSuccessHandler;
reserveLoginGuideSpace?: boolean;
}; };
const LoginFormPanel = ({ pageType, setPageType, loginSuccess }: LoginFormPanelProps) => { const LoginFormPanel = ({
pageType,
setPageType,
loginSuccess,
reserveLoginGuideSpace
}: LoginFormPanelProps) => {
const DynamicComponent = useMemo(() => { const DynamicComponent = useMemo(() => {
if (!pageType) return null; if (!pageType) return null;
...@@ -36,7 +42,7 @@ const LoginFormPanel = ({ pageType, setPageType, loginSuccess }: LoginFormPanelP ...@@ -36,7 +42,7 @@ const LoginFormPanel = ({ pageType, setPageType, loginSuccess }: LoginFormPanelP
}, [pageType, setPageType, loginSuccess]); }, [pageType, setPageType, loginSuccess]);
return ( return (
<Box w={['100%', '380px']} flex={['', '1 0 0']}> <Box w={['100%', '380px']} flex={['0 0 auto', reserveLoginGuideSpace ? '1 0 0' : '0 0 auto']}>
{pageType && DynamicComponent ? DynamicComponent : <Loading fixed={false} />} {pageType && DynamicComponent ? DynamicComponent : <Loading fixed={false} />}
</Box> </Box>
); );
......
...@@ -10,6 +10,8 @@ import ChineseRedirectModal from './components/ChineseRedirectModal'; ...@@ -10,6 +10,8 @@ import ChineseRedirectModal from './components/ChineseRedirectModal';
import CookieConsentModal from './components/CookieConsentModal'; import CookieConsentModal from './components/CookieConsentModal';
import LoginFormPanel from './components/LoginFormPanel'; import LoginFormPanel from './components/LoginFormPanel';
import type { LoginSuccessResponseType } from '@fastgpt/global/openapi/support/user/account/login/api'; import type { LoginSuccessResponseType } from '@fastgpt/global/openapi/support/user/account/login/api';
import I18nLngSelector from '@/components/Select/I18nLngSelector';
import { useSystem } from '@fastgpt/web/hooks/useSystem';
type LoginSuccessHandler = (res: LoginSuccessResponseType) => void | Promise<void>; type LoginSuccessHandler = (res: LoginSuccessResponseType) => void | Promise<void>;
...@@ -26,6 +28,8 @@ export const LoginContainer = ({ ...@@ -26,6 +28,8 @@ export const LoginContainer = ({
const { t } = useTranslation(); const { t } = useTranslation();
const { feConfigs } = useSystemStore(); const { feConfigs } = useSystemStore();
const { resetChatCache } = useChatStore(); const { resetChatCache } = useChatStore();
const { isPc } = useSystem();
const loginGuideDocUrl = feConfigs?.loginGuideDocUrl?.trim();
const [pageType, setPageType] = useState<`${LoginPageTypeEnum}`>(LoginPageTypeEnum.passwordLogin); const [pageType, setPageType] = useState<`${LoginPageTypeEnum}`>(LoginPageTypeEnum.passwordLogin);
const [showCommunityModal, setShowCommunityModal] = useState(false); const [showCommunityModal, setShowCommunityModal] = useState(false);
...@@ -57,35 +61,57 @@ export const LoginContainer = ({ ...@@ -57,35 +61,57 @@ export const LoginContainer = ({
my={['', pageType === LoginPageTypeEnum.wechat ? '-15px' : '']} my={['', pageType === LoginPageTypeEnum.wechat ? '-15px' : '']}
position="relative" position="relative"
w="full" w="full"
flex={'1 0 0'} flex={['1 0 0', '0 0 auto']}
flexDirection={'column'} flexDirection={'column'}
justifyContent={['center', 'flex-start']}
> >
{!isPc && (
<Box mb={8} alignSelf={'flex-start'}>
<I18nLngSelector />
</Box>
)}
{/* main content area */} {/* main content area */}
<LoginFormPanel pageType={pageType} setPageType={setPageType} loginSuccess={loginSuccess} /> <LoginFormPanel
pageType={pageType}
setPageType={setPageType}
loginSuccess={loginSuccess}
reserveLoginGuideSpace={
pageType === LoginPageTypeEnum.passwordLogin &&
!!(loginGuideDocUrl || feConfigs?.concatMd)
}
/>
{/* custom content */} {/* custom content */}
{children} {children}
{/* help link for login */} {/* help link for login */}
{feConfigs?.concatMd && ( {pageType === LoginPageTypeEnum.passwordLogin &&
<Box (loginGuideDocUrl || feConfigs?.concatMd) && (
mt={[9, '6']} <Box
color={'primary.700'} mt={[8, 8]}
fontSize={'mini'} color={'primary.700'}
fontWeight={'medium'} fontSize={'mini'}
cursor={'pointer'} fontWeight={'medium'}
textAlign={'center'} lineHeight={'16px'}
onClick={() => setShowCommunityModal(true)} cursor={'pointer'}
> textAlign={'center'}
{t('common:support.user.login.can_not_login')} onClick={() => {
</Box> if (loginGuideDocUrl) {
)} window.open(loginGuideDocUrl, '_blank', 'noopener,noreferrer');
} else {
setShowCommunityModal(true);
}
}}
>
{t('common:support.user.login.can_not_login')}
</Box>
)}
</Flex> </Flex>
<CookieConsentModal /> <CookieConsentModal />
<ChineseRedirectModal /> <ChineseRedirectModal />
{/* Community modal */}
{showCommunityModal && <CommunityModal onClose={() => setShowCommunityModal(false)} />} {showCommunityModal && <CommunityModal onClose={() => setShowCommunityModal(false)} />}
</> </>
); );
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment