mirror of https://gitee.com/answerdev/answer.git
Merge branch 'feat/ui-0.7.0' into 'test'
chore: Add image capcha code when registering, Dynamically insert custom.css See merge request opensource/answer!358
This commit is contained in:
commit
1c68d4be53
|
@ -5,7 +5,6 @@
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||||
<meta name="theme-color" content="#000000" />
|
<meta name="theme-color" content="#000000" />
|
||||||
<link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
|
<link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
|
||||||
<link rel="stylesheet" href="%PUBLIC_URL%/custom.css" />
|
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<noscript>You need to enable JavaScript to run this app.</noscript>
|
<noscript>You need to enable JavaScript to run this app.</noscript>
|
||||||
|
|
|
@ -30,6 +30,7 @@ const Layout: FC = () => {
|
||||||
<title>{pageTitle}</title>
|
<title>{pageTitle}</title>
|
||||||
{keywords && <meta name="keywords" content={keywords} />}
|
{keywords && <meta name="keywords" content={keywords} />}
|
||||||
{description && <meta name="description" content={description} />}
|
{description && <meta name="description" content={description} />}
|
||||||
|
<link rel="stylesheet" href={`${process.env.PUBLIC_URL}/custom.css`} />
|
||||||
</Helmet>
|
</Helmet>
|
||||||
<CustomizeTheme />
|
<CustomizeTheme />
|
||||||
<SWRConfig
|
<SWRConfig
|
||||||
|
|
|
@ -122,6 +122,7 @@ const Personal: FC = () => {
|
||||||
<h5 className="mb-3">{t('stats')}</h5>
|
<h5 className="mb-3">{t('stats')}</h5>
|
||||||
{userInfo?.info && (
|
{userInfo?.info && (
|
||||||
<>
|
<>
|
||||||
|
<FormatTime time={1671290521} preFix={t('last_login')} />
|
||||||
<div className="text-secondary">
|
<div className="text-secondary">
|
||||||
<FormatTime
|
<FormatTime
|
||||||
time={userInfo.info.created_at}
|
time={userInfo.info.created_at}
|
||||||
|
|
|
@ -1,10 +1,17 @@
|
||||||
import React, { FormEvent, MouseEvent, useState } from 'react';
|
import React, { FormEvent, MouseEvent, useEffect, useState } from 'react';
|
||||||
import { Form, Button, Col } from 'react-bootstrap';
|
import { Form, Button, Col } from 'react-bootstrap';
|
||||||
import { Link } from 'react-router-dom';
|
import { Link } from 'react-router-dom';
|
||||||
import { Trans, useTranslation } from 'react-i18next';
|
import { Trans, useTranslation } from 'react-i18next';
|
||||||
|
|
||||||
import type { FormDataType } from '@/common/interface';
|
import { PicAuthCodeModal } from '@/components/Modal';
|
||||||
import { register, useLegalTos, useLegalPrivacy } from '@/services';
|
import { ImgCodeRes, LoginReqParams } from '@/common/interface';
|
||||||
|
import type { FormDataType, RegisterReqParams } from '@/common/interface';
|
||||||
|
import {
|
||||||
|
register,
|
||||||
|
getRegisterCaptcha,
|
||||||
|
useLegalTos,
|
||||||
|
useLegalPrivacy,
|
||||||
|
} from '@/services';
|
||||||
import userStore from '@/stores/userInfo';
|
import userStore from '@/stores/userInfo';
|
||||||
import { handleFormError } from '@/utils';
|
import { handleFormError } from '@/utils';
|
||||||
|
|
||||||
|
@ -38,6 +45,17 @@ const Index: React.FC<Props> = ({ callback }) => {
|
||||||
});
|
});
|
||||||
const updateUser = userStore((state) => state.update);
|
const updateUser = userStore((state) => state.update);
|
||||||
|
|
||||||
|
const [imgCode, setImgCode] = useState<ImgCodeRes>({
|
||||||
|
captcha_id: '',
|
||||||
|
captcha_img: '',
|
||||||
|
verify: false,
|
||||||
|
});
|
||||||
|
const [showModal, setModalState] = useState(false);
|
||||||
|
const getImgCode = () => {
|
||||||
|
getRegisterCaptcha().then((res) => {
|
||||||
|
setImgCode(res);
|
||||||
|
});
|
||||||
|
};
|
||||||
const handleChange = (params: FormDataType) => {
|
const handleChange = (params: FormDataType) => {
|
||||||
setFormData({ ...formData, ...params });
|
setFormData({ ...formData, ...params });
|
||||||
};
|
};
|
||||||
|
@ -104,17 +122,29 @@ const Index: React.FC<Props> = ({ callback }) => {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleSubmit = async (event: FormEvent) => {
|
const handleRegister = (event?: any) => {
|
||||||
event.preventDefault();
|
if (event) {
|
||||||
event.stopPropagation();
|
event.preventDefault();
|
||||||
if (!checkValidated()) {
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
register({
|
const params: LoginReqParams = {
|
||||||
|
e_mail: formData.e_mail.value,
|
||||||
|
pass: formData.pass.value,
|
||||||
|
};
|
||||||
|
if (imgCode.verify) {
|
||||||
|
params.captcha_code = formData.captcha_code.value;
|
||||||
|
params.captcha_id = imgCode.captcha_id;
|
||||||
|
}
|
||||||
|
const reqParams: RegisterReqParams = {
|
||||||
name: formData.name.value,
|
name: formData.name.value,
|
||||||
e_mail: formData.e_mail.value,
|
e_mail: formData.e_mail.value,
|
||||||
pass: formData.pass.value,
|
pass: formData.pass.value,
|
||||||
})
|
};
|
||||||
|
|
||||||
|
if (imgCode.verify) {
|
||||||
|
reqParams.captcha_code = formData.captcha_code.value;
|
||||||
|
reqParams.captcha_id = imgCode.captcha_id;
|
||||||
|
}
|
||||||
|
register(reqParams)
|
||||||
.then((res) => {
|
.then((res) => {
|
||||||
updateUser(res);
|
updateUser(res);
|
||||||
callback();
|
callback();
|
||||||
|
@ -127,113 +157,141 @@ const Index: React.FC<Props> = ({ callback }) => {
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const handleSubmit = async (event: FormEvent) => {
|
||||||
|
event.preventDefault();
|
||||||
|
event.stopPropagation();
|
||||||
|
if (!checkValidated()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (imgCode.verify) {
|
||||||
|
setModalState(true);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
handleRegister();
|
||||||
|
};
|
||||||
|
useEffect(() => {
|
||||||
|
getImgCode();
|
||||||
|
}, []);
|
||||||
return (
|
return (
|
||||||
<Col className="mx-auto" md={3}>
|
<>
|
||||||
<Form noValidate onSubmit={handleSubmit} autoComplete="off">
|
<Col className="mx-auto" md={3}>
|
||||||
<Form.Group controlId="name" className="mb-3">
|
<Form noValidate onSubmit={handleSubmit} autoComplete="off">
|
||||||
<Form.Label>{t('name.label')}</Form.Label>
|
<Form.Group controlId="name" className="mb-3">
|
||||||
<Form.Control
|
<Form.Label>{t('name.label')}</Form.Label>
|
||||||
autoComplete="off"
|
<Form.Control
|
||||||
required
|
autoComplete="off"
|
||||||
type="text"
|
required
|
||||||
isInvalid={formData.name.isInvalid}
|
type="text"
|
||||||
value={formData.name.value}
|
isInvalid={formData.name.isInvalid}
|
||||||
onChange={(e) =>
|
value={formData.name.value}
|
||||||
handleChange({
|
onChange={(e) =>
|
||||||
name: {
|
handleChange({
|
||||||
value: e.target.value,
|
name: {
|
||||||
isInvalid: false,
|
value: e.target.value,
|
||||||
errorMsg: '',
|
isInvalid: false,
|
||||||
},
|
errorMsg: '',
|
||||||
})
|
},
|
||||||
}
|
})
|
||||||
/>
|
}
|
||||||
<Form.Control.Feedback type="invalid">
|
/>
|
||||||
{formData.name.errorMsg}
|
<Form.Control.Feedback type="invalid">
|
||||||
</Form.Control.Feedback>
|
{formData.name.errorMsg}
|
||||||
</Form.Group>
|
</Form.Control.Feedback>
|
||||||
<Form.Group controlId="email" className="mb-3">
|
</Form.Group>
|
||||||
<Form.Label>{t('email.label')}</Form.Label>
|
<Form.Group controlId="email" className="mb-3">
|
||||||
<Form.Control
|
<Form.Label>{t('email.label')}</Form.Label>
|
||||||
autoComplete="off"
|
<Form.Control
|
||||||
required
|
autoComplete="off"
|
||||||
type="e_mail"
|
required
|
||||||
isInvalid={formData.e_mail.isInvalid}
|
type="e_mail"
|
||||||
value={formData.e_mail.value}
|
isInvalid={formData.e_mail.isInvalid}
|
||||||
onChange={(e) =>
|
value={formData.e_mail.value}
|
||||||
handleChange({
|
onChange={(e) =>
|
||||||
e_mail: {
|
handleChange({
|
||||||
value: e.target.value,
|
e_mail: {
|
||||||
isInvalid: false,
|
value: e.target.value,
|
||||||
errorMsg: '',
|
isInvalid: false,
|
||||||
},
|
errorMsg: '',
|
||||||
})
|
},
|
||||||
}
|
})
|
||||||
/>
|
}
|
||||||
<Form.Control.Feedback type="invalid">
|
/>
|
||||||
{formData.e_mail.errorMsg}
|
<Form.Control.Feedback type="invalid">
|
||||||
</Form.Control.Feedback>
|
{formData.e_mail.errorMsg}
|
||||||
</Form.Group>
|
</Form.Control.Feedback>
|
||||||
|
</Form.Group>
|
||||||
|
|
||||||
<Form.Group controlId="password" className="mb-3">
|
<Form.Group controlId="password" className="mb-3">
|
||||||
<Form.Label>{t('password.label')}</Form.Label>
|
<Form.Label>{t('password.label')}</Form.Label>
|
||||||
<Form.Control
|
<Form.Control
|
||||||
autoComplete="off"
|
autoComplete="off"
|
||||||
required
|
required
|
||||||
type="password"
|
type="password"
|
||||||
maxLength={32}
|
maxLength={32}
|
||||||
isInvalid={formData.pass.isInvalid}
|
isInvalid={formData.pass.isInvalid}
|
||||||
value={formData.pass.value}
|
value={formData.pass.value}
|
||||||
onChange={(e) =>
|
onChange={(e) =>
|
||||||
handleChange({
|
handleChange({
|
||||||
pass: {
|
pass: {
|
||||||
value: e.target.value,
|
value: e.target.value,
|
||||||
isInvalid: false,
|
isInvalid: false,
|
||||||
errorMsg: '',
|
errorMsg: '',
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
<Form.Control.Feedback type="invalid">
|
<Form.Control.Feedback type="invalid">
|
||||||
{formData.pass.errorMsg}
|
{formData.pass.errorMsg}
|
||||||
</Form.Control.Feedback>
|
</Form.Control.Feedback>
|
||||||
</Form.Group>
|
</Form.Group>
|
||||||
|
|
||||||
<div className="d-grid">
|
<div className="d-grid">
|
||||||
<Button variant="primary" type="submit">
|
<Button variant="primary" type="submit">
|
||||||
{t('signup', { keyPrefix: 'btns' })}
|
{t('signup', { keyPrefix: 'btns' })}
|
||||||
</Button>
|
</Button>
|
||||||
|
</div>
|
||||||
|
</Form>
|
||||||
|
<div className="text-center fs-14 mt-3">
|
||||||
|
<Trans i18nKey="login.agreements" ns="translation">
|
||||||
|
By registering, you agree to the
|
||||||
|
<Link
|
||||||
|
to="/privacy"
|
||||||
|
onClick={(evt) => {
|
||||||
|
argumentClick(evt, 'privacy');
|
||||||
|
}}
|
||||||
|
target="_blank">
|
||||||
|
privacy policy
|
||||||
|
</Link>
|
||||||
|
and
|
||||||
|
<Link
|
||||||
|
to="/tos"
|
||||||
|
onClick={(evt) => {
|
||||||
|
argumentClick(evt, 'tos');
|
||||||
|
}}
|
||||||
|
target="_blank">
|
||||||
|
terms of service
|
||||||
|
</Link>
|
||||||
|
.
|
||||||
|
</Trans>
|
||||||
</div>
|
</div>
|
||||||
</Form>
|
<div className="text-center mt-5">
|
||||||
<div className="text-center fs-14 mt-3">
|
<Trans i18nKey="login.info_login" ns="translation">
|
||||||
<Trans i18nKey="login.agreements" ns="translation">
|
Already have an account? <Link to="/users/login">Log in</Link>
|
||||||
By registering, you agree to the
|
</Trans>
|
||||||
<Link
|
</div>
|
||||||
to="/privacy"
|
</Col>
|
||||||
onClick={(evt) => {
|
<PicAuthCodeModal
|
||||||
argumentClick(evt, 'privacy');
|
visible={showModal}
|
||||||
}}
|
data={{
|
||||||
target="_blank">
|
captcha: formData.captcha_code,
|
||||||
privacy policy
|
imgCode,
|
||||||
</Link>
|
}}
|
||||||
and
|
handleCaptcha={handleChange}
|
||||||
<Link
|
clickSubmit={handleRegister}
|
||||||
to="/tos"
|
refreshImgCode={getImgCode}
|
||||||
onClick={(evt) => {
|
onClose={() => setModalState(false)}
|
||||||
argumentClick(evt, 'tos');
|
/>
|
||||||
}}
|
</>
|
||||||
target="_blank">
|
|
||||||
terms of service
|
|
||||||
</Link>
|
|
||||||
.
|
|
||||||
</Trans>
|
|
||||||
</div>
|
|
||||||
<div className="text-center mt-5">
|
|
||||||
<Trans i18nKey="login.info_login" ns="translation">
|
|
||||||
Already have an account? <Link to="/users/login">Log in</Link>
|
|
||||||
</Trans>
|
|
||||||
</div>
|
|
||||||
</Col>
|
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -96,6 +96,11 @@ export const register = (params: Type.RegisterReqParams) => {
|
||||||
return request.post<any>('/answer/api/v1/user/register/email', params);
|
return request.post<any>('/answer/api/v1/user/register/email', params);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const getRegisterCaptcha = () => {
|
||||||
|
const apiUrl = '/answer/api/v1/user/register/captcha';
|
||||||
|
return request.get(apiUrl);
|
||||||
|
};
|
||||||
|
|
||||||
export const logout = () => {
|
export const logout = () => {
|
||||||
return request.get('/answer/api/v1/user/logout');
|
return request.get('/answer/api/v1/user/logout');
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in New Issue