This commit is contained in:
oneao committed 2026-01-13 22:18:01 +08:00
1 parent 6277fb2f9e
commit 8ecac0d7dd
270 files changed
+40438 -529

No files matched your search

@@ -0,0 +1,95 @@
import { useMemo, useState } from 'react'
export interface ValidationRule {
required?: boolean
pattern?: RegExp
minLength?: number
maxLength?: number
validator?: (value: any) => boolean
message?: string
}
export interface FormValidationResult {
[key: string]: {
isValid: boolean
errorMessage: string
}
}
export default function useFormValidation<T extends Record<string, any>>(
values: T,
rules: { [K in keyof T]?: ValidationRule }, // <-- 可选字段,message 可选
) {
const [validationResults, setValidationResults] = useState<FormValidationResult>({})
const validate = () => {
const newValidationResults: FormValidationResult = {}
for (const field in rules) {
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}`
if (fieldRules.required && (value === undefined || value === null || strValue === '')) {
isValid = false
errorMessage = fieldRules.message || getDefaultMessage('必填项')
}
if (isValid && fieldRules.pattern && !fieldRules.pattern.test(strValue)) {
isValid = false
errorMessage = fieldRules.message || '格式不正确'
}
if (isValid && fieldRules.minLength && strValue.length < fieldRules.minLength) {
isValid = false
errorMessage = fieldRules.message || `最少输入 ${fieldRules.minLength} 个字符`
}
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 || '自定义验证未通过'
}
newValidationResults[field] = { isValid, errorMessage }
}
setValidationResults(newValidationResults)
return newValidationResults
}
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
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 }
}
@@ -0,0 +1,31 @@
import type { KeyboardEvent } from 'react-native'
import { useEffect, useState } from 'react'
import { Keyboard } from 'react-native'
/**
* useKeyboardHeight - 获取键盘高度的 Hooks
* @returns {number} 当前键盘高度,键盘收起时为 0
*/
export function useKeyboardHeight() {
const [keyboardHeight, setKeyboardHeight] = useState(0)
useEffect(() => {
const onKeyboardShow = (e: KeyboardEvent) => {
setKeyboardHeight(e.endCoordinates.height)
}
const onKeyboardHide = () => {
setKeyboardHeight(0)
}
const showSub = Keyboard.addListener('keyboardDidShow', onKeyboardShow)
const hideSub = Keyboard.addListener('keyboardDidHide', onKeyboardHide)
return () => {
showSub.remove()
hideSub.remove()
}
}, [])
return keyboardHeight
}