import { Ionicons } from '@expo/vector-icons' import { Block, ConfirmModal, Input, Text } from '@share/components' import React, { useState } from 'react' export type ChangePasswordModalProps = { onConfirm: (currentPassword: string, newPassword: string) => void | Promise onCancel: () => void } // 验证密码强度 const validatePassword = (password: string): string | null => { if (!password) { return '请输入新密码' } if (password.length < 6) { return '密码长度至少6位' } // 检查是否是无效密码:全是相同字符 if (/^(.)\1+$/.test(password)) { return '密码不能全是相同字符' } // 检查是否是连续数字(如 123456, 654321) const isSequentialNumbers = (str: string): boolean => { for (let i = 0; i < str.length - 1; i++) { const current = parseInt(str[i], 10) const next = parseInt(str[i + 1], 10) if (isNaN(current) || isNaN(next)) return false if (Math.abs(current - next) !== 1) return false } return true } // 检查是否是连续字母(如 abcdef, fedcba) const isSequentialLetters = (str: string): boolean => { const lowerStr = str.toLowerCase() for (let i = 0; i < lowerStr.length - 1; i++) { const current = lowerStr.charCodeAt(i) const next = lowerStr.charCodeAt(i + 1) if (Math.abs(current - next) !== 1) return false } return true } if (isSequentialNumbers(password) || isSequentialLetters(password)) { return '密码不能是连续字符' } // 检查是否是简单密码(如 111111, 000000, aaaaaa) const commonWeakPasswords = [ '111111', '222222', '333333', '444444', '555555', '666666', '777777', '888888', '999999', '000000', 'aaaaaa', 'bbbbbb', 'cccccc', 'dddddd', 'eeeeee', 'ffffff', '123456', '654321', 'abcdef', 'fedcba', ] if (commonWeakPasswords.includes(password.toLowerCase())) { return '密码过于简单,请使用更复杂的密码' } return null } export default function ChangePasswordModal({ onConfirm, onCancel }: ChangePasswordModalProps) { const [currentPassword, setCurrentPassword] = useState('') const [newPassword, setNewPassword] = useState('') const [confirmPassword, setConfirmPassword] = useState('') const [showCurrentPassword, setShowCurrentPassword] = useState(false) const [showNewPassword, setShowNewPassword] = useState(false) const [showConfirmPassword, setShowConfirmPassword] = useState(false) const [loading, setLoading] = useState(false) const [errors, setErrors] = useState<{ currentPassword?: string newPassword?: string confirmPassword?: string }>({}) const validateCurrentPassword = (value: string) => { if (!value) { setErrors((prev) => ({ ...prev, currentPassword: '请输入当前密码' })) } else { setErrors((prev) => { const newErrors = { ...prev } delete newErrors.currentPassword return newErrors }) } } const validateNewPassword = (value: string) => { const error = validatePassword(value) if (error) { setErrors((prev) => ({ ...prev, newPassword: error })) } else { setErrors((prev) => { const newErrors = { ...prev } delete newErrors.newPassword return newErrors }) // 如果确认密码已输入,重新验证确认密码 if (confirmPassword) { validateConfirmPassword(confirmPassword, value) } } } const validateConfirmPassword = (value: string, newPwd = newPassword) => { if (!value) { setErrors((prev) => ({ ...prev, confirmPassword: '请再次输入新密码' })) } else if (value !== newPwd) { setErrors((prev) => ({ ...prev, confirmPassword: '两次密码输入不一致' })) } else { setErrors((prev) => { const newErrors = { ...prev } delete newErrors.confirmPassword return newErrors }) } } const handleConfirm = async () => { if (loading) return // 验证所有字段并收集错误 const newErrors: typeof errors = {} if (!currentPassword) { newErrors.currentPassword = '请输入当前密码' } const newPasswordError = validatePassword(newPassword) if (newPasswordError) { newErrors.newPassword = newPasswordError } if (!confirmPassword) { newErrors.confirmPassword = '请再次输入新密码' } else if (confirmPassword !== newPassword) { newErrors.confirmPassword = '两次密码输入不一致' } // 设置错误状态 setErrors(newErrors) // 如果有错误,不继续提交 if (Object.keys(newErrors).length > 0) { return } setLoading(true) try { await onConfirm(currentPassword, newPassword) } finally { setLoading(false) } } return ( 当前密码 { setCurrentPassword(text) if (errors.currentPassword) { validateCurrentPassword(text) } }} onBlur={() => validateCurrentPassword(currentPassword)} secureTextEntry={!showCurrentPassword} /> setShowCurrentPassword(!showCurrentPassword)} > {errors.currentPassword && ( {errors.currentPassword} )} 新密码 { setNewPassword(text) if (errors.newPassword) { validateNewPassword(text) } }} onBlur={() => validateNewPassword(newPassword)} secureTextEntry={!showNewPassword} /> setShowNewPassword(!showNewPassword)} > {errors.newPassword && {errors.newPassword}} 确认新密码 { setConfirmPassword(text) if (errors.confirmPassword) { validateConfirmPassword(text) } }} onBlur={() => validateConfirmPassword(confirmPassword)} secureTextEntry={!showConfirmPassword} /> setShowConfirmPassword(!showConfirmPassword)} > {errors.confirmPassword && ( {errors.confirmPassword} )} } title="修改密码" onCancel={onCancel} onConfirm={handleConfirm} /> ) }