React Ts Antd实现密码多规则校验

发布于:2024-04-15 ⋅ 阅读:(184) ⋅ 点赞:(0)

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>
    );
}

效果展示

在这里插入图片描述


网站公告

今日签到

点亮在社区的每一天
去签到