Files
timeline-frontend/src/pages/user/register/index.tsx

328 lines
8.9 KiB
TypeScript
Raw Normal View History

2025-07-22 22:52:55 +08:00
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';
import { registerUser } from '@/services/user/api';
import { CommonResponse } from '@/types/common';
2025-07-22 22:52:55 +08:00
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(
(params) => registerUser(params, { skipErrorHandler: true }),
{
manual: true,
onSuccess: (data, params) => {
console.log('注册成功 - data:', data, 'params:', params);
const response = data as CommonResponse<string>;
if (response?.code === 200) {
message.success('注册成功!');
const formValues = params[0] as any;
history.push({
pathname: `/user/register-result?account=${formValues?.email || formValues?.username || ''}`,
});
} else {
message.error(response?.message || '注册失败,请重试');
}
},
2025-07-22 22:52:55 +08:00
},
);
2025-07-22 22:52:55 +08:00
const onFinish = (values: Store) => {
// 将表单数据映射为后端需要的格式
const registerParams = {
username: values.username,
nickname: values.nickname,
password: values.password,
email: values.email || '',
phone: values.phone || '',
};
register(registerParams);
2025-07-22 22:52:55 +08:00
};
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="username"
2025-07-22 22:52:55 +08:00
rules={[
{ required: true, message: '请输入用户名!' },
{ max: 50, message: '用户名过长' },
2025-07-22 22:52:55 +08:00
]}
>
<Input size="large" placeholder="用户名" />
</FormItem>
<FormItem
name="nickname"
rules={[
{ required: true, message: '请输入昵称!' },
{ max: 50, message: '昵称过长' },
]}
>
<Input size="large" placeholder="昵称" />
2025-07-22 22:52:55 +08:00
</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="email"
/* rules={[
{
required: true,
message: '请输入邮箱地址!',
},
{
type: 'email',
message: '邮箱地址格式错误!',
},
]} */
>
<Input size="large" placeholder="邮箱" />
</FormItem>
<FormItem
name="phone"
/* rules={[
2025-07-22 22:52:55 +08:00
{
required: true,
message: '请输入手机号!',
},
{
pattern: /^\d{11}$/,
message: '手机号格式错误!',
},
]} */
2025-07-22 22:52:55 +08:00
>
<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}>
2025-07-22 22:52:55 +08:00
<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> */}
2025-07-22 22:52:55 +08:00
<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;