init
This commit is contained in:
292
src/pages/user/register/index.tsx
Normal file
292
src/pages/user/register/index.tsx
Normal file
@@ -0,0 +1,292 @@
|
||||
import { history, Link, useRequest } from '@umijs/max';
|
||||
import { Button, Col, Form, Input, message, Popover, Progress, Row, Select, Space } from 'antd';
|
||||
import type { Store } from 'antd/es/form/interface';
|
||||
import type { FC } from 'react';
|
||||
import { useEffect, useState } from 'react';
|
||||
import type { StateType } from './service';
|
||||
import { fakeRegister } from './service';
|
||||
import useStyles from './style.style';
|
||||
|
||||
const FormItem = Form.Item;
|
||||
const { Option } = Select;
|
||||
|
||||
const passwordProgressMap: {
|
||||
ok: 'success';
|
||||
pass: 'normal';
|
||||
poor: 'exception';
|
||||
} = {
|
||||
ok: 'success',
|
||||
pass: 'normal',
|
||||
poor: 'exception',
|
||||
};
|
||||
const Register: FC = () => {
|
||||
const { styles } = useStyles();
|
||||
const [count, setCount]: [number, any] = useState(0);
|
||||
const [open, setVisible]: [boolean, any] = useState(false);
|
||||
const [prefix, setPrefix]: [string, any] = useState('86');
|
||||
const [popover, setPopover]: [boolean, any] = useState(false);
|
||||
const confirmDirty = false;
|
||||
let interval: number | undefined;
|
||||
|
||||
const passwordStatusMap = {
|
||||
ok: (
|
||||
<div className={styles.success}>
|
||||
<span>强度:强</span>
|
||||
</div>
|
||||
),
|
||||
pass: (
|
||||
<div className={styles.warning}>
|
||||
<span>强度:中</span>
|
||||
</div>
|
||||
),
|
||||
poor: (
|
||||
<div className={styles.error}>
|
||||
<span>强度:太短</span>
|
||||
</div>
|
||||
),
|
||||
};
|
||||
|
||||
const [form] = Form.useForm();
|
||||
useEffect(
|
||||
() => () => {
|
||||
clearInterval(interval);
|
||||
},
|
||||
[interval],
|
||||
);
|
||||
const onGetCaptcha = () => {
|
||||
let counts = 59;
|
||||
setCount(counts);
|
||||
interval = window.setInterval(() => {
|
||||
counts -= 1;
|
||||
setCount(counts);
|
||||
if (counts === 0) {
|
||||
clearInterval(interval);
|
||||
}
|
||||
}, 1000);
|
||||
};
|
||||
const getPasswordStatus = () => {
|
||||
const value = form.getFieldValue('password');
|
||||
if (value && value.length > 9) {
|
||||
return 'ok';
|
||||
}
|
||||
if (value && value.length > 5) {
|
||||
return 'pass';
|
||||
}
|
||||
return 'poor';
|
||||
};
|
||||
const { loading: submitting, run: register } = useRequest<{
|
||||
data: StateType;
|
||||
}>(fakeRegister, {
|
||||
manual: true,
|
||||
onSuccess: (data, params) => {
|
||||
if (data.status === 'ok') {
|
||||
message.success('注册成功!');
|
||||
history.push({
|
||||
pathname: `/user/register-result?account=${params[0].email}`,
|
||||
});
|
||||
}
|
||||
},
|
||||
});
|
||||
const onFinish = (values: Store) => {
|
||||
register(values);
|
||||
};
|
||||
const checkConfirm = (_: any, value: string) => {
|
||||
const promise = Promise;
|
||||
if (value && value !== form.getFieldValue('password')) {
|
||||
return promise.reject('两次输入的密码不匹配!');
|
||||
}
|
||||
return promise.resolve();
|
||||
};
|
||||
const checkPassword = (_: any, value: string) => {
|
||||
const promise = Promise;
|
||||
// 没有值的情况
|
||||
if (!value) {
|
||||
setVisible(!!value);
|
||||
return promise.reject('请输入密码!');
|
||||
}
|
||||
// 有值的情况
|
||||
if (!open) {
|
||||
setVisible(!!value);
|
||||
}
|
||||
setPopover(!popover);
|
||||
if (value.length < 6) {
|
||||
return promise.reject('');
|
||||
}
|
||||
if (value && confirmDirty) {
|
||||
form.validateFields(['confirm']);
|
||||
}
|
||||
return promise.resolve();
|
||||
};
|
||||
const changePrefix = (value: string) => {
|
||||
setPrefix(value);
|
||||
};
|
||||
const renderPasswordProgress = () => {
|
||||
const value = form.getFieldValue('password');
|
||||
const passwordStatus = getPasswordStatus();
|
||||
return value && value.length ? (
|
||||
<div className={styles[`progress-${passwordStatus}`]}>
|
||||
<Progress
|
||||
status={passwordProgressMap[passwordStatus]}
|
||||
strokeWidth={6}
|
||||
percent={value.length * 10 > 100 ? 100 : value.length * 10}
|
||||
showInfo={false}
|
||||
/>
|
||||
</div>
|
||||
) : null;
|
||||
};
|
||||
return (
|
||||
<div className={styles.main}>
|
||||
<h3>注册</h3>
|
||||
<Form form={form} name="UserRegister" onFinish={onFinish}>
|
||||
<FormItem
|
||||
name="email"
|
||||
rules={[
|
||||
{
|
||||
required: true,
|
||||
message: '请输入邮箱地址!',
|
||||
},
|
||||
{
|
||||
type: 'email',
|
||||
message: '邮箱地址格式错误!',
|
||||
},
|
||||
]}
|
||||
>
|
||||
<Input size="large" placeholder="邮箱" />
|
||||
</FormItem>
|
||||
<Popover
|
||||
getPopupContainer={(node) => {
|
||||
if (node && node.parentNode) {
|
||||
return node.parentNode as HTMLElement;
|
||||
}
|
||||
return node;
|
||||
}}
|
||||
content={
|
||||
open && (
|
||||
<div
|
||||
style={{
|
||||
padding: '4px 0',
|
||||
}}
|
||||
>
|
||||
{passwordStatusMap[getPasswordStatus()]}
|
||||
{renderPasswordProgress()}
|
||||
<div
|
||||
style={{
|
||||
marginTop: 10,
|
||||
}}
|
||||
>
|
||||
<span>请至少输入 6 个字符。请不要使用容易被猜到的密码。</span>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
overlayStyle={{
|
||||
width: 240,
|
||||
}}
|
||||
placement="right"
|
||||
open={open}
|
||||
>
|
||||
<FormItem
|
||||
name="password"
|
||||
className={
|
||||
form.getFieldValue('password') &&
|
||||
form.getFieldValue('password').length > 0 &&
|
||||
styles.password
|
||||
}
|
||||
rules={[
|
||||
{
|
||||
validator: checkPassword,
|
||||
},
|
||||
]}
|
||||
>
|
||||
<Input size="large" type="password" placeholder="至少6位密码,区分大小写" />
|
||||
</FormItem>
|
||||
</Popover>
|
||||
<FormItem
|
||||
name="confirm"
|
||||
rules={[
|
||||
{
|
||||
required: true,
|
||||
message: '确认密码',
|
||||
},
|
||||
{
|
||||
validator: checkConfirm,
|
||||
},
|
||||
]}
|
||||
>
|
||||
<Input size="large" type="password" placeholder="确认密码" />
|
||||
</FormItem>
|
||||
<FormItem
|
||||
name="mobile"
|
||||
rules={[
|
||||
{
|
||||
required: true,
|
||||
message: '请输入手机号!',
|
||||
},
|
||||
{
|
||||
pattern: /^\d{11}$/,
|
||||
message: '手机号格式错误!',
|
||||
},
|
||||
]}
|
||||
>
|
||||
<Space.Compact style={{ width: '100%' }}>
|
||||
<Select
|
||||
size="large"
|
||||
value={prefix}
|
||||
onChange={changePrefix}
|
||||
style={{
|
||||
width: '30%',
|
||||
}}
|
||||
>
|
||||
<Option value="86">+86</Option>
|
||||
<Option value="87">+87</Option>
|
||||
</Select>
|
||||
|
||||
<Input size="large" placeholder="手机号" />
|
||||
</Space.Compact>
|
||||
</FormItem>
|
||||
<Row gutter={8}>
|
||||
<Col span={16}>
|
||||
<FormItem
|
||||
name="captcha"
|
||||
rules={[
|
||||
{
|
||||
required: true,
|
||||
message: '请输入验证码!',
|
||||
},
|
||||
]}
|
||||
>
|
||||
<Input size="large" placeholder="验证码" />
|
||||
</FormItem>
|
||||
</Col>
|
||||
<Col span={8}>
|
||||
<Button
|
||||
size="large"
|
||||
disabled={!!count}
|
||||
className={styles.getCaptcha}
|
||||
onClick={onGetCaptcha}
|
||||
>
|
||||
{count ? `${count} s` : '获取验证码'}
|
||||
</Button>
|
||||
</Col>
|
||||
</Row>
|
||||
<FormItem>
|
||||
<div className={styles.footer}>
|
||||
<Button
|
||||
size="large"
|
||||
loading={submitting}
|
||||
className={styles.submit}
|
||||
type="primary"
|
||||
htmlType="submit"
|
||||
>
|
||||
<span>注册</span>
|
||||
</Button>
|
||||
<Link to="/user/login">
|
||||
<span>使用已有账户登录</span>
|
||||
</Link>
|
||||
</div>
|
||||
</FormItem>
|
||||
</Form>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
export default Register;
|
||||
Reference in New Issue
Block a user