doc gpt V0.2

This commit is contained in:
archer
2023-02-19 14:35:25 +08:00
parent cc5cf99e7a
commit 0ecf576e4e
124 changed files with 11780 additions and 573 deletions

View File

@@ -0,0 +1,193 @@
import React, { useState, Dispatch, useCallback } from 'react';
import {
FormControl,
Box,
Input,
Button,
FormErrorMessage,
useToast,
Flex
} from '@chakra-ui/react';
import { useForm } from 'react-hook-form';
import { PageTypeEnum } from '../../../constants/user';
import { postFindPassword } from '@/api/user';
import { useSendCode } from '@/hooks/useSendCode';
import type { ResLogin } from '@/api/response/user';
import { useScreen } from '@/hooks/useScreen';
interface Props {
setPageType: Dispatch<`${PageTypeEnum}`>;
loginSuccess: (e: ResLogin) => void;
}
interface RegisterType {
email: string;
code: string;
password: string;
password2: string;
}
const RegisterForm = ({ setPageType, loginSuccess }: Props) => {
const toast = useToast();
const { mediaLgMd } = useScreen();
const {
register,
handleSubmit,
getValues,
trigger,
formState: { errors }
} = useForm<RegisterType>({
mode: 'onBlur'
});
const { codeSending, sendCodeText, sendCode, codeCountDown } = useSendCode();
const onclickSendCode = useCallback(async () => {
const check = await trigger('email');
if (!check) return;
sendCode({
email: getValues('email'),
type: 'findPassword'
});
}, [getValues, sendCode, trigger]);
const [requesting, setRequesting] = useState(false);
const onclickFindPassword = useCallback(
async ({ email, code, password }: RegisterType) => {
setRequesting(true);
try {
loginSuccess(
await postFindPassword({
email,
code,
password
})
);
toast({
title: `密码已找回`,
status: 'success',
position: 'top'
});
} catch (error) {
typeof error === 'string' &&
toast({
title: error,
status: 'error',
position: 'top'
});
}
setRequesting(false);
},
[loginSuccess, toast]
);
return (
<>
<Box fontWeight={'bold'} fontSize={'2xl'} textAlign={'center'}>
DocGPT
</Box>
<form onSubmit={handleSubmit(onclickFindPassword)}>
<FormControl mt={8} isInvalid={!!errors.email}>
<Input
placeholder="邮箱"
size={mediaLgMd}
{...register('email', {
required: '邮箱不能为空',
pattern: {
value: /^[A-Za-z0-9]+([_\.][A-Za-z0-9]+)*@([A-Za-z0-9\-]+\.)+[A-Za-z]{2,6}$/,
message: '邮箱错误'
}
})}
></Input>
<FormErrorMessage position={'absolute'} fontSize="xs">
{!!errors.email && errors.email.message}
</FormErrorMessage>
</FormControl>
<FormControl mt={8} isInvalid={!!errors.email}>
<Flex>
<Input
flex={1}
placeholder="验证码"
size={mediaLgMd}
{...register('code', {
required: '验证码不能为空'
})}
></Input>
<Button
ml={5}
w={'145px'}
maxW={'50%'}
size={mediaLgMd}
onClick={onclickSendCode}
isDisabled={codeCountDown > 0}
isLoading={codeSending}
>
{sendCodeText}
</Button>
</Flex>
<FormErrorMessage position={'absolute'} fontSize="xs">
{!!errors.code && errors.code.message}
</FormErrorMessage>
</FormControl>
<FormControl mt={8} isInvalid={!!errors.password}>
<Input
type={'password'}
placeholder="新密码"
size={mediaLgMd}
{...register('password', {
required: '密码不能为空',
minLength: {
value: 4,
message: '密码最少4位最多12位'
},
maxLength: {
value: 12,
message: '密码最少4位最多12位'
}
})}
></Input>
<FormErrorMessage position={'absolute'} fontSize="xs">
{!!errors.password && errors.password.message}
</FormErrorMessage>
</FormControl>
<FormControl mt={8} isInvalid={!!errors.password2}>
<Input
type={'password'}
placeholder="确认密码"
size={mediaLgMd}
{...register('password2', {
validate: (val) => (getValues('password') === val ? true : '两次密码不一致')
})}
></Input>
<FormErrorMessage position={'absolute'} fontSize="xs">
{!!errors.password2 && errors.password2.message}
</FormErrorMessage>
</FormControl>
<Box
float={'right'}
fontSize="sm"
mt={2}
color={'blue.600'}
cursor={'pointer'}
_hover={{ textDecoration: 'underline' }}
onClick={() => setPageType('login')}
>
</Box>
<Button
type="submit"
mt={8}
w={'100%'}
size={mediaLgMd}
colorScheme="blue"
isLoading={requesting}
>
</Button>
</form>
</>
);
};
export default RegisterForm;

View File

@@ -0,0 +1,134 @@
import React, { useState, Dispatch, useCallback } from 'react';
import { FormControl, Flex, Input, Button, FormErrorMessage, Box } from '@chakra-ui/react';
import { useForm } from 'react-hook-form';
import { PageTypeEnum } from '@/constants/user';
import { postLogin } from '@/api/user';
import type { ResLogin } from '@/api/response/user';
import { useToast } from '@/hooks/useToast';
import { useScreen } from '@/hooks/useScreen';
interface Props {
setPageType: Dispatch<`${PageTypeEnum}`>;
loginSuccess: (e: ResLogin) => void;
}
interface LoginFormType {
email: string;
password: string;
}
const LoginForm = ({ setPageType, loginSuccess }: Props) => {
const { toast } = useToast();
const { mediaLgMd } = useScreen();
const {
register,
handleSubmit,
formState: { errors }
} = useForm<LoginFormType>();
const [requesting, setRequesting] = useState(false);
const onclickLogin = useCallback(
async ({ email, password }: LoginFormType) => {
setRequesting(true);
try {
loginSuccess(
await postLogin({
email,
password
})
);
toast({
title: '登录成功',
status: 'success'
});
} catch (error) {
typeof error === 'string' &&
toast({
title: error,
status: 'error',
position: 'top'
});
}
setRequesting(false);
},
[loginSuccess, toast]
);
return (
<>
<Box fontWeight={'bold'} fontSize={'2xl'} textAlign={'center'}>
DocGPT
</Box>
<form onSubmit={handleSubmit(onclickLogin)}>
<FormControl mt={8} isInvalid={!!errors.email}>
<Input
placeholder="邮箱"
size={mediaLgMd}
{...register('email', {
required: '邮箱不能为空',
pattern: {
value: /^[A-Za-z0-9]+([_\.][A-Za-z0-9]+)*@([A-Za-z0-9\-]+\.)+[A-Za-z]{2,6}$/,
message: '邮箱错误'
}
})}
></Input>
<FormErrorMessage position={'absolute'} fontSize="xs">
{!!errors.email && errors.email.message}
</FormErrorMessage>
</FormControl>
<FormControl mt={8} isInvalid={!!errors.password}>
<Input
type={'password'}
size={mediaLgMd}
placeholder="密码"
{...register('password', {
required: '密码不能为空',
minLength: {
value: 4,
message: '密码最少4位最多12位'
},
maxLength: {
value: 12,
message: '密码最少4位最多12位'
}
})}
></Input>
<FormErrorMessage position={'absolute'} fontSize="xs">
{!!errors.password && errors.password.message}
</FormErrorMessage>
</FormControl>
<Flex align={'center'} justifyContent={'space-between'} mt={6} color={'blue.600'}>
<Box
cursor={'pointer'}
_hover={{ textDecoration: 'underline' }}
onClick={() => setPageType('forgetPassword')}
fontSize="sm"
>
?
</Box>
<Box
cursor={'pointer'}
_hover={{ textDecoration: 'underline' }}
onClick={() => setPageType('register')}
fontSize="sm"
>
</Box>
</Flex>
<Button
type="submit"
mt={8}
w={'100%'}
size={mediaLgMd}
colorScheme="blue"
isLoading={requesting}
>
</Button>
</form>
</>
);
};
export default LoginForm;

View File

@@ -0,0 +1,193 @@
import React, { useState, Dispatch, useCallback } from 'react';
import {
FormControl,
Box,
Input,
Button,
FormErrorMessage,
useToast,
Flex
} from '@chakra-ui/react';
import { useForm } from 'react-hook-form';
import { PageTypeEnum } from '@/constants/user';
import { postRegister } from '@/api/user';
import { useSendCode } from '@/hooks/useSendCode';
import type { ResLogin } from '@/api/response/user';
import { useScreen } from '@/hooks/useScreen';
interface Props {
loginSuccess: (e: ResLogin) => void;
setPageType: Dispatch<`${PageTypeEnum}`>;
}
interface RegisterType {
email: string;
password: string;
password2: string;
code: string;
}
const RegisterForm = ({ setPageType, loginSuccess }: Props) => {
const toast = useToast();
const { mediaLgMd } = useScreen();
const {
register,
handleSubmit,
getValues,
trigger,
formState: { errors }
} = useForm<RegisterType>({
mode: 'onBlur'
});
const { codeSending, sendCodeText, sendCode, codeCountDown } = useSendCode();
const onclickSendCode = useCallback(async () => {
const check = await trigger('email');
if (!check) return;
sendCode({
email: getValues('email'),
type: 'register'
});
}, [getValues, sendCode, trigger]);
const [requesting, setRequesting] = useState(false);
const onclickRegister = useCallback(
async ({ email, password, code }: RegisterType) => {
setRequesting(true);
try {
loginSuccess(
await postRegister({
email,
code,
password
})
);
toast({
title: `注册成功`,
status: 'success',
position: 'top'
});
} catch (error) {
typeof error === 'string' &&
toast({
title: error,
status: 'error',
position: 'top'
});
}
setRequesting(false);
},
[loginSuccess, toast]
);
return (
<>
<Box fontWeight={'bold'} fontSize={'2xl'} textAlign={'center'}>
DocGPT
</Box>
<form onSubmit={handleSubmit(onclickRegister)}>
<FormControl mt={8} isInvalid={!!errors.email}>
<Input
placeholder="邮箱"
size={mediaLgMd}
{...register('email', {
required: '邮箱不能为空',
pattern: {
value: /^[A-Za-z0-9]+([_\.][A-Za-z0-9]+)*@([A-Za-z0-9\-]+\.)+[A-Za-z]{2,6}$/,
message: '邮箱错误'
}
})}
></Input>
<FormErrorMessage position={'absolute'} fontSize="xs">
{!!errors.email && errors.email.message}
</FormErrorMessage>
</FormControl>
<FormControl mt={8} isInvalid={!!errors.email}>
<Flex>
<Input
flex={1}
size={mediaLgMd}
placeholder="验证码"
{...register('code', {
required: '验证码不能为空'
})}
></Input>
<Button
ml={5}
w={'145px'}
maxW={'50%'}
size={mediaLgMd}
onClick={onclickSendCode}
isDisabled={codeCountDown > 0}
isLoading={codeSending}
>
{sendCodeText}
</Button>
</Flex>
<FormErrorMessage position={'absolute'} fontSize="xs">
{!!errors.code && errors.code.message}
</FormErrorMessage>
</FormControl>
<FormControl mt={8} isInvalid={!!errors.password}>
<Input
type={'password'}
placeholder="密码"
size={mediaLgMd}
{...register('password', {
required: '密码不能为空',
minLength: {
value: 4,
message: '密码最少4位最多12位'
},
maxLength: {
value: 12,
message: '密码最少4位最多12位'
}
})}
></Input>
<FormErrorMessage position={'absolute'} fontSize="xs">
{!!errors.password && errors.password.message}
</FormErrorMessage>
</FormControl>
<FormControl mt={8} isInvalid={!!errors.password2}>
<Input
type={'password'}
placeholder="确认密码"
size={mediaLgMd}
{...register('password2', {
validate: (val) => (getValues('password') === val ? true : '两次密码不一致')
})}
></Input>
<FormErrorMessage position={'absolute'} fontSize="xs">
{!!errors.password2 && errors.password2.message}
</FormErrorMessage>
</FormControl>
<Box
float={'right'}
fontSize="sm"
mt={2}
color={'blue.600'}
cursor={'pointer'}
_hover={{ textDecoration: 'underline' }}
onClick={() => setPageType('login')}
>
</Box>
<Button
type="submit"
mt={8}
w={'100%'}
size={mediaLgMd}
colorScheme="blue"
isLoading={requesting}
>
</Button>
</form>
</>
);
};
export default RegisterForm;