export interface EditableAccountProfile { realName: string email: string } export interface LoginIdentifierChangePayload { username: string phone: string currentPassword: string } export interface PasswordChangePayload { currentPassword: string newPassword: string confirmPassword: string } const EMAIL_PATTERN = /^[^\s@]+@[^\s@]+\.[^\s@]+$/ const USERNAME_PATTERN = /^[A-Za-z][A-Za-z0-9_.@-]{3,63}$/ const MAINLAND_MOBILE_PATTERN = /^1[3-9]\d{9}$/ export function validateEditableAccountProfile(profile: EditableAccountProfile): string[] { const errors: string[] = [] const realName = profile.realName.trim() const email = profile.email.trim() if (realName.length < 1 || realName.length > 64) errors.push('姓名需为 1–64 个字符') if (email && !EMAIL_PATTERN.test(email)) errors.push('请输入有效的邮箱地址') return errors } export function validateLoginIdentifierChange(payload: LoginIdentifierChangePayload): string[] { const errors: string[] = [] if (!USERNAME_PATTERN.test(payload.username.trim())) { errors.push('用户名须以字母开头,并由 4–64 位字母、数字或 _.@- 组成') } if (!MAINLAND_MOBILE_PATTERN.test(payload.phone.trim())) errors.push('请输入有效的中国大陆手机号') if (!payload.currentPassword) errors.push('请输入当前密码') return errors } export function validatePasswordChange(payload: PasswordChangePayload): string[] { const errors: string[] = [] if (!payload.currentPassword) errors.push('请输入当前密码') if (payload.newPassword.length < 8 || payload.newPassword.length > 64) { errors.push('新密码需为 8–64 个字符') } if (payload.newPassword.length >= 8 && (!/[a-zA-Z]/.test(payload.newPassword) || !/\d/.test(payload.newPassword))) { errors.push('新密码必须同时包含字母和数字') } if (payload.newPassword && payload.newPassword === payload.currentPassword) { errors.push('新密码不能与当前密码相同') } if (payload.confirmPassword !== payload.newPassword) errors.push('两次输入的新密码不一致') return errors } export type PasswordStrength = 'weak' | 'medium' | 'strong' export function getPasswordStrength(password: string): PasswordStrength { let categoryCount = 0 if (/[a-zA-Z]/.test(password)) categoryCount += 1 if (/\d/.test(password)) categoryCount += 1 if (/[^a-zA-Z\d]/.test(password)) categoryCount += 1 if (password.length >= 12 && categoryCount >= 3) return 'strong' if (password.length >= 8 && categoryCount >= 2) return 'medium' return 'weak' }