👨🏻‍💻👩🏻‍💻 Use Ant Design like a Pro!
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

293 lines
7.7 KiB

import type { FC } from 'react';
import { useState, useEffect } from 'react';
import { Form, Button, Col, Input, Popover, Progress, Row, Select, message } from 'antd';
import type { Store } from 'antd/es/form/interface';
import { Link, useRequest, history } from '@umijs/max';
import type { StateType } from './service';
import { fakeRegister } from './service';
import useStyles from './style.style';
const FormItem = Form.Item;
const { Option } = Select;
const InputGroup = Input.Group;
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 [visible, 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.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 (!visible) {
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="mail"
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={
visible && (
<div
style={{
padding: '4px 0',
}}
>
{passwordStatusMap[getPasswordStatus()]}
{renderPasswordProgress()}
<div
style={{
marginTop: 10,
}}
>
<span> 6 使</span>
</div>
</div>
)
}
overlayStyle={{
width: 240,
}}
placement="right"
visible={visible}
>
<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>
<InputGroup compact>
<Select
size="large"
value={prefix}
onChange={changePrefix}
style={{
width: '20%',
}}
>
<Option value="86">+86</Option>
<Option value="87">+87</Option>
</Select>
<FormItem
style={{
width: '80%',
}}
name="mobile"
rules={[
{
required: true,
message: '请输入手机号!',
},
{
pattern: /^\d{11}$/,
message: '手机号格式错误!',
},
]}
>
<Input size="large" placeholder="手机号" />
</FormItem>
</InputGroup>
<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>
<Button
size="large"
loading={submitting}
className={styles.submit}
type="primary"
htmlType="submit"
>
<span></span>
</Button>
<Link className={styles.login} to="/user/login">
<span>使</span>
</Link>
</FormItem>
</Form>
</div>
);
};
export default Register;