/** * PasswordStrengthIndicator - 密码强度指示器 */ import { Progress } from 'antd' import { useMemo } from 'react' interface PasswordStrengthIndicatorProps { password: string } function calculateStrength(password: string): { score: number; level: 'weak' | 'fair' | 'good' | 'strong' } { if (!password) { return { score: 0, level: 'weak' } } let score = 0 // 长度检查 if (password.length >= 8) score += 25 if (password.length >= 12) score += 10 if (password.length >= 16) score += 5 // 字符类型检查 if (/[a-z]/.test(password)) score += 15 if (/[A-Z]/.test(password)) score += 20 if (/[0-9]/.test(password)) score += 20 if (/[^a-zA-Z0-9]/.test(password)) score += 20 // 正则匹配检查 if (/(?=.*[a-z])(?=.*[A-Z])(?=.*[0-9])/.test(password)) score += 5 if (/(?=.*[a-z])(?=.*[A-Z])(?=.*[^a-zA-Z0-9])/.test(password)) score += 5 // 扣分项 if (/^[a-zA-Z0-9]+$/.test(password)) score -= 10 // 纯字母数字 if (/^[a-z]+$|^[A-Z]+$|^[0-9]+$/.test(password)) score -= 15 // 单一种类 // 限制范围 score = Math.max(0, Math.min(100, score)) let level: 'weak' | 'fair' | 'good' | 'strong' if (score < 30) level = 'weak' else if (score < 60) level = 'fair' else if (score < 80) level = 'good' else level = 'strong' return { score, level } } const strengthConfig = { weak: { color: '#ff4d4f', text: '弱' }, fair: { color: '#faad14', text: '中等' }, good: { color: '#52c41a', text: '良好' }, strong: { color: '#52c41a', text: '强' }, } export function PasswordStrengthIndicator({ password }: PasswordStrengthIndicatorProps) { const { score, level } = useMemo(() => calculateStrength(password), [password]) if (!password) { return null } const config = strengthConfig[level] return (