This commit is contained in:
oneao committed 2025-11-06 22:50:03 +08:00
1 parent d60be4a75b
commit be8eaae7c5
24 files changed
+595 -232

No files matched your search

@@ -1,67 +1,61 @@
import { useEffect, useState } from 'react'
import { useMemo, useState } from 'react'
// 定义表单字段的验证规则类型
interface ValidationRule {
export interface ValidationRule {
required?: boolean
pattern?: RegExp
minLength?: number
maxLength?: number
validator?: (value: string) => boolean // 自定义验证规则
message?: string // 自定义消息
validator?: (value: any) => boolean
message?: string
}
// 定义返回的数据结构
interface FormValidationResult {
export interface FormValidationResult {
[key: string]: {
isValid: boolean
errorMessage: string
}
}
function useFormValidation(values: Record<string, string>, rules: Record<string, ValidationRule>, autoValidate = false) {
export default function useFormValidation<T extends Record<string, any>>(
values: T,
rules: { [K in keyof T]?: ValidationRule }, // <-- 可选字段,message 可选
) {
const [validationResults, setValidationResults] = useState<FormValidationResult>({})
const [isValid, setIsValid] = useState<boolean>(true) // 用于保存整体表单是否有效
// 验证逻辑
const validate = () => {
const newValidationResults: FormValidationResult = {}
for (const field in rules) {
const value = values[field] || ''
const fieldRules = rules[field]
const value = values[field]
const strValue = String(value ?? '')
const fieldRules = rules[field as keyof T]
if (!fieldRules)
continue
let isValid = true
let errorMessage = ''
const getDefaultMessage = (type: string) => `${field} 是${type}`
// 默认错误消息的函数
const getDefaultMessage = (type: string) => {
return `${field} 是${type}`
}
// 验证 required
if (fieldRules.required && !value) {
if (fieldRules.required && (value === undefined || value === null || strValue === '')) {
isValid = false
errorMessage = fieldRules.message || getDefaultMessage('必填项')
}
// 验证 pattern
if (isValid && fieldRules.pattern && !fieldRules.pattern.test(value)) {
if (isValid && fieldRules.pattern && !fieldRules.pattern.test(strValue)) {
isValid = false
errorMessage = fieldRules.message || '格式不正确'
}
// 验证 minLength
if (isValid && fieldRules.minLength && value.length < fieldRules.minLength) {
if (isValid && fieldRules.minLength && strValue.length < fieldRules.minLength) {
isValid = false
errorMessage = fieldRules.message || `最少输入 ${fieldRules.minLength} 个字符`
}
// 验证 maxLength
if (isValid && fieldRules.maxLength && value.length > fieldRules.maxLength) {
if (isValid && fieldRules.maxLength && strValue.length > fieldRules.maxLength) {
isValid = false
errorMessage = fieldRules.message || `最多输入 ${fieldRules.maxLength} 个字符`
}
// 自定义验证
if (isValid && fieldRules.validator && !fieldRules.validator(value)) {
isValid = false
errorMessage = fieldRules.message || '自定义验证未通过'
@@ -71,27 +65,31 @@ function useFormValidation(values: Record<string, string>, rules: Record<string,
}
setValidationResults(newValidationResults)
// 更新整体表单是否有效
const allValid = !Object.values(newValidationResults).some(result => !result.isValid)
setIsValid(allValid)
// 返回是否验证通过(返回true或false)
return allValid
return newValidationResults
}
// 如果开启自动验证
useEffect(() => {
if (autoValidate) {
validate()
}
}, [values, autoValidate])
const isValid = useMemo(() => {
return Object.keys(rules).every((field) => {
const value = values[field as keyof T]
const strValue = String(value ?? '')
const fieldRules = rules[field as keyof T]
if (!fieldRules)
return true
return {
validationResults,
isValid,
validate,
}
if (fieldRules.required && (value === undefined || value === null || strValue === ''))
return false
if (fieldRules.pattern && !fieldRules.pattern.test(strValue))
return false
if (fieldRules.minLength && strValue.length < fieldRules.minLength)
return false
if (fieldRules.maxLength && strValue.length > fieldRules.maxLength)
return false
if (fieldRules.validator && !fieldRules.validator(value))
return false
return true
})
}, [values, rules])
return { validationResults, isValid, validate }
}
export default useFormValidation