验证码更新

This commit is contained in:
biss committed 2026-09-12 10:11:11 +08:00
1 parent c1451d0e6d
commit df87aa16d3
3 files changed
+6 -4

No files matched your search

+1 -1
View File
@@ -335,7 +335,7 @@ public sealed record LoginRequest(
[Required, MaxLength(100)] string UserName, [Required, MaxLength(100)] string UserName,
[Required, MaxLength(100)] string Password, [Required, MaxLength(100)] string Password,
[Required, MinLength(16), MaxLength(64)] string CaptchaId, [Required, MinLength(16), MaxLength(64)] string CaptchaId,
[Required, MinLength(3), MaxLength(16)] string CaptchaCode, [Required, MinLength(1), MaxLength(16)] string CaptchaCode,
bool IsNativeApp = false); bool IsNativeApp = false);
public sealed record LoginCaptchaResponse( public sealed record LoginCaptchaResponse(
@@ -50,7 +50,7 @@ public sealed class CaptchaKitIntegrationTests
Assert.Contains(CaptchaChallengeType.TextImage, types); Assert.Contains(CaptchaChallengeType.TextImage, types);
Assert.Contains(CaptchaChallengeType.Selection, types); Assert.Contains(CaptchaChallengeType.Selection, types);
Assert.Contains(CaptchaChallengeType.OneClick, types); Assert.Contains(CaptchaChallengeType.MathImage, types);
} }
private sealed class KnownGenerator : ICaptchaGenerator private sealed class KnownGenerator : ICaptchaGenerator
+4 -2
View File
@@ -9,7 +9,7 @@ interface CaptchaChoice {
interface CaptchaChallenge { interface CaptchaChallenge {
captchaId: string captchaId: string
type: 'TextImage' | 'Selection' | 'OneClick' type: 'TextImage' | 'MathImage' | 'Selection' | 'OneClick'
prompt?: string prompt?: string
choices?: CaptchaChoice[] choices?: CaptchaChoice[]
imageData?: string imageData?: string
@@ -46,12 +46,13 @@ defineExpose({ refresh })
<button type="button" :disabled="loading" @click="refresh">换一张</button> <button type="button" :disabled="loading" @click="refresh">换一张</button>
</div> </div>
<div v-loading="loading" class="captcha-input"> <div v-loading="loading" class="captcha-input">
<template v-if="captcha?.type === 'TextImage'"> <template v-if="captcha?.type === 'TextImage' || captcha?.type === 'MathImage'">
<img v-if="captcha.imageData" :src="captcha.imageData" alt="验证码图片,点击可更换" @click="refresh" /> <img v-if="captcha.imageData" :src="captcha.imageData" alt="验证码图片,点击可更换" @click="refresh" />
<el-input v-model="code" maxlength="8" autocomplete="off" placeholder="输入图中字符" /> <el-input v-model="code" maxlength="8" autocomplete="off" placeholder="输入图中字符" />
</template> </template>
<div v-else-if="captcha" class="captcha-question"> <div v-else-if="captcha" class="captcha-question">
<p>{{ captcha.prompt }}</p> <p>{{ captcha.prompt }}</p>
<img v-if="captcha.imageData" :src="captcha.imageData" alt="验证码图片,点击可更换" @click="refresh" />
<div v-if="captcha.type === 'Selection'" class="captcha-choices" role="group" aria-label="验证码选项"> <div v-if="captcha.type === 'Selection'" class="captcha-choices" role="group" aria-label="验证码选项">
<el-button <el-button
v-for="choice in captcha.choices ?? []" v-for="choice in captcha.choices ?? []"
@@ -78,6 +79,7 @@ defineExpose({ refresh })
.captcha-input img { width: 150px; height: 50px; object-fit: contain; border: 1px solid #d7e2ed; border-radius: 6px; cursor: pointer; background: #f7fafc; } .captcha-input img { width: 150px; height: 50px; object-fit: contain; border: 1px solid #d7e2ed; border-radius: 6px; cursor: pointer; background: #f7fafc; }
.captcha-question { grid-column: 1 / -1; display: grid; gap: 8px; padding: 10px 12px; border: 1px solid #d7e2ed; border-radius: 6px; background: #f7fafc; } .captcha-question { grid-column: 1 / -1; display: grid; gap: 8px; padding: 10px 12px; border: 1px solid #d7e2ed; border-radius: 6px; background: #f7fafc; }
.captcha-question p { margin: 0; color: #233b54; font-size: 14px; } .captcha-question p { margin: 0; color: #233b54; font-size: 14px; }
.captcha-question img { width: min(100%, 220px); height: 54px; object-fit: contain; border: 1px solid #d7e2ed; border-radius: 6px; cursor: pointer; background: #fff; }
.captcha-choices { display: flex; flex-wrap: wrap; gap: 8px; } .captcha-choices { display: flex; flex-wrap: wrap; gap: 8px; }
@media (max-width: 420px) { .captcha-input { grid-template-columns: 130px minmax(0, 1fr); } .captcha-input img { width: 130px; } } @media (max-width: 420px) { .captcha-input { grid-template-columns: 130px minmax(0, 1fr); } .captcha-input img { width: 130px; } }
</style> </style>