diff --git a/src/api/loginSms.test.ts b/src/api/loginSms.test.ts index 2bd4750..5358e93 100644 --- a/src/api/loginSms.test.ts +++ b/src/api/loginSms.test.ts @@ -3,6 +3,8 @@ import { describe, it } from "node:test"; import { buildCaptchaImageUrl, buildSendMobileCodeRequest, + isImageCaptchaLocked, + resolveImageCaptchaInteractionState, resolveLoginErrorMessage, } from "./loginSms.ts"; @@ -63,4 +65,46 @@ describe("login sms api helpers", () => { "网络错误", ); }); + + it("locks image captcha while sms countdown is active", () => { + assert.equal(isImageCaptchaLocked(60), true); + assert.equal(isImageCaptchaLocked(1), true); + assert.equal(isImageCaptchaLocked(0), false); + }); + + it("resolves captcha field and refresh button interaction state", () => { + assert.deepEqual( + resolveImageCaptchaInteractionState({ + smsSending: false, + smsCountdown: 60, + }), + { + disabled: true, + clearable: false, + refreshDisabled: true, + }, + ); + assert.deepEqual( + resolveImageCaptchaInteractionState({ + smsSending: false, + smsCountdown: 0, + }), + { + disabled: false, + clearable: true, + refreshDisabled: false, + }, + ); + assert.deepEqual( + resolveImageCaptchaInteractionState({ + smsSending: true, + smsCountdown: 0, + }), + { + disabled: true, + clearable: false, + refreshDisabled: true, + }, + ); + }); }); diff --git a/src/api/loginSms.ts b/src/api/loginSms.ts index a4a639e..d37e7b2 100644 --- a/src/api/loginSms.ts +++ b/src/api/loginSms.ts @@ -10,6 +10,17 @@ export interface CaptchaImageUrlOptions { cacheBust?: number | string; } +export interface ImageCaptchaInteractionParams { + smsSending: boolean; + smsCountdown: number; +} + +export interface ImageCaptchaInteractionState { + disabled: boolean; + clearable: boolean; + refreshDisabled: boolean; +} + function trimEndSlash(value: string): string { return value.replace(/\/+$/, ""); } @@ -39,6 +50,23 @@ export function createCaptchaRandomStr(): string { return `${Date.now()}${Math.random().toString(36).slice(2, 10)}`; } +export function isImageCaptchaLocked(smsCountdown: number): boolean { + return smsCountdown > 0; +} + +export function resolveImageCaptchaInteractionState({ + smsSending, + smsCountdown, +}: ImageCaptchaInteractionParams): ImageCaptchaInteractionState { + const disabled = smsSending || isImageCaptchaLocked(smsCountdown); + + return { + disabled, + clearable: !disabled, + refreshDisabled: disabled, + }; +} + export function buildCaptchaImageUrl( randomStr: string, options: CaptchaImageUrlOptions = {}, diff --git a/src/pages/login/index.vue b/src/pages/login/index.vue index 78fb13c..a0a4a7b 100644 --- a/src/pages/login/index.vue +++ b/src/pages/login/index.vue @@ -16,11 +16,14 @@ -