Hooks
import {useState} from "react";
import {FormItemProps, type FormProps, message} from "antd";
interface PasswordRegMatch {
content: string
reg:RegExp
status: boolean
}
export type FieldType = {
username: string
password: string
captcha: string
remember: string
nickname: string
};
export function useLogin() {
const [passwrodRegMatches, setPasswrodRegMatches] = useState<PasswordRegMatch[]>([
{
reg:/[0-9]+/,
content: "密码必须包含数字",
status: false
},
{
reg:/[a-z]+/,
content: "密码必须包含小写字母",
status: false
},
{
reg:/[A-Z]+/,
content: "密码必须包含大写字母",
status: false
},
{
reg:/[.@$!%*#_~?&^]+/,
content: "密码必须包含特殊字符(.@$!%*#_~?&^)",
status: false
},
])
const passwordRules: FormItemProps['rules'] = [
{
required:true,
message:"密码不能为空!"
},
() => ({
validator(_, value) {
let level = 0
const newMatches = passwrodRegMatches.map((match) => {
if (match.reg.test(value)) {
level++
match.status = true
}else{
match.status = false
}
return match
})
setPasswrodRegMatches(newMatches)
if (value.length < 8 || value.length > 16 || !/^[a-zA-Z0-9.@$!%*#_~?&^]{8,16}$/.test(value) || level < passwrodRegMatches.length) {
return Promise.reject(new Error('密码必须包含数字、大写字母、小写字母、特殊字符(如.@$!%*#_~?&^)至少3种的组合且长度在8-16之间'));
}
return Promise.resolve()
},
}),
]
return {
passwordRules,
passwrodRegMatches,
}
}
页面
多余代码删除了
import React, {PropsWithChildren} from 'react';
import {Button, Checkbox, Col, Form, Input, Row} from 'antd';
import {debounce} from "lodash";
import {FieldType, useLogin} from "@/views/login/composable/use_login.tsx";
import {FrownOutlined, MehOutlined} from '@ant-design/icons';
interface Props extends PropsWithChildren {
toRegister: () => void
}
// <FrownOutlined />
export const LoginForm: React.FC<Props> = ({toRegister}) => {
const { passwordRules, passwrodRegMatches} = useLogin()
return (
<Form
name="basic"
labelCol={{span: 8}}
wrapperCol={{span: 16}}
style={{maxWidth: 600}}
initialValues={{remember: true}}
onFinish={onFinish}
onFinishFailed={onFinishFailed}
autoComplete="off"
>
<Form.Item<FieldType>
label="密码"
name="password"
rules={passwordRules}
>
<Row >
<Col span={8}>
<Input.Password/>
</Col>
<Col span={14} offset={2}>
<ul className="text-xs">
{passwrodRegMatches.map((match,index)=> {
return <li className={match.status ?"text-emerald-500":"text-gray-500"} key={index}>{match.content}{match.status ? <MehOutlined/>:<FrownOutlined/>}</li>
})}
</ul>
</Col>
</Row>
</Form.Item>
<Col>
还没有账号?点击<Button onClick={() => toRegister()} type="link" className="p-0">注册</Button>
</Col>
</Row>
<Form.Item wrapperCol={{span: 22, offset: 6}}>
<Button type="primary" htmlType="submit" block>
登录
</Button>
</Form.Item>
</Form>
);
}