-
} aria-label="帮助" aria-expanded={helpOpen} aria-controls="v2-context-help" onClick={() => setHelpOpen(true)} />
+
} aria-label="帮助" aria-expanded={helpOpen} aria-controls="v2-context-help" onClick={() => setHelpOpen(true)}>
页面帮助
-
- {session.name.slice(0, 1)}
- {session.name} {session.username ? `@${session.username}` : session.authProvider === 'legacy-token' ? '运维令牌账号' : '平台账号'}
- {roleLabel}
-
-
- } onClick={() => { setAccountOpen(false); setPasswordOpen(true); }}>修改登录密码
- } onClick={() => { setAccountOpen(false); logout(); }}>退出登录
- }
+ render={ { setAccountOpen(false); setPasswordOpen(true); }}
+ onLogout={() => { setAccountOpen(false); logout(); }}
+ />}
>
void; onChanged
const [confirmPassword, setConfirmPassword] = useState('');
const [pending, setPending] = useState(false);
const [error, setError] = useState('');
+ const categoryCount = [
+ /[a-z]/.test(newPassword),
+ /[A-Z]/.test(newPassword),
+ /\d/.test(newPassword),
+ /[^A-Za-z0-9]/.test(newPassword)
+ ].filter(Boolean).length;
+ const lengthValid = newPassword.length >= 10 && newPassword.length <= 128;
+ const categoriesValid = categoryCount >= 3;
+ const confirmationStarted = confirmPassword.length > 0;
+ const passwordsMatch = confirmationStarted && newPassword === confirmPassword;
+ const passwordValid = lengthValid && categoriesValid;
const submit = async (event: FormEvent) => {
event.preventDefault();
- if (newPassword !== confirmPassword) { setError('两次输入的新密码不一致'); return; }
+ if (!passwordValid) { setError('新密码不符合安全规则'); return; }
+ if (!passwordsMatch) { setError('两次输入的新密码不一致'); return; }
setPending(true); setError('');
try {
await api.changePassword({ currentPassword, newPassword });
@@ -172,14 +218,28 @@ function PasswordDialog({ onClose, onChanged }: { onClose: () => void; onChanged
setError(reason instanceof Error ? reason.message : '密码修改失败');
} finally { setPending(false); }
};
- return
+ return
修改登录密码 更新账号安全凭据 }
+ aria-label="修改登录密码"
+ onCancel={onClose}
+ closeOnEsc={!pending}
+ maskClosable={!pending}
+ footer={null}
+ >