diff --git a/apps/ai-game-creator-shell/src/app/AuthenticatedClient.tsx b/apps/ai-game-creator-shell/src/app/AuthenticatedClient.tsx index 1f8d92924..82553f8e1 100644 --- a/apps/ai-game-creator-shell/src/app/AuthenticatedClient.tsx +++ b/apps/ai-game-creator-shell/src/app/AuthenticatedClient.tsx @@ -327,6 +327,28 @@ export function AuthenticatedClient({ return () => window.clearInterval(timer); }, [codeCooldownSeconds]); + /** + * 认证动作失败的统一收口:可识别的业务 / 会话拒绝只给用户提示;真故障与未识别变体带上文交给 + * 错误池。`action` 决定错误池指纹,新增认证动作必须走这里、不要在各自的 catch 里另拼一套。 + */ + function presentAuthFailure( + error: unknown, + fallback: string, + action: string, + ) { + const failure = resolveClientAuthFailure(error, fallback); + setLoginStatus(failure.message); + if (failure.kind === 'report') { + void captureClientError( + new ClientActionError( + failure.message, + { source: 'auth', action }, + error, + ), + ); + } + } + async function handleSendCode() { if (codeBusy || codeCooldownSeconds > 0) { return; @@ -348,18 +370,7 @@ export function AuthenticatedClient({ setCodeCooldownSeconds(Math.max(0, Math.floor(response.cooldownSeconds))); setLoginStatus(`验证码已发送,${response.expiresInSeconds} 秒内有效`); } catch (error) { - // 业务拒绝(手机号格式 / 发码限流等)只给提示;系统变体与未识别变体带上文交给错误池。 - const failure = resolveClientAuthFailure(error, '发送验证码失败'); - setLoginStatus(failure.message); - if (failure.kind === 'report') { - void captureClientError( - new ClientActionError( - failure.message, - { source: 'auth', action: 'send-login-code' }, - error, - ), - ); - } + presentAuthFailure(error, '发送验证码失败', 'send-login-code'); } finally { setCodeBusy(false); } @@ -424,19 +435,7 @@ export function AuthenticatedClient({ setCode(''); setPassword(''); } catch (error) { - // 预期业务拒绝(密码输错 / 密码长度不合规 / 手机号格式等)在这里消化掉,永不进错误池; - // 真故障与未识别变体带上文交给错误池,指纹仍与显式采集时一致。 - const failure = resolveClientAuthFailure(error, '登录失败'); - setLoginStatus(failure.message); - if (failure.kind === 'report') { - void captureClientError( - new ClientActionError( - failure.message, - { source: 'auth', action: 'login' }, - error, - ), - ); - } + presentAuthFailure(error, '登录失败', 'login'); } finally { setLoginBusy(false); }