feat: add ReCaptchaV2 & Turnstile

This commit is contained in:
Tony Yang
2025-04-16 16:35:24 +08:00
parent 9ac3339557
commit 037ccb5781
23 changed files with 372 additions and 176 deletions
+15 -19
View File
@@ -2,7 +2,7 @@
import { ref, computed, defineProps } from 'vue';
import { useRouter } from 'vue-router';
import { uploadAvatar } from '../../lib/api';
import VueHcaptcha from '@hcaptcha/vue3-hcaptcha';
import CAPTCHA from '../CAPTCHA.vue';
import { useAuthStore } from '../../stores/auth';
const props = defineProps({
@@ -15,22 +15,20 @@ const props = defineProps({
const authStore = useAuthStore();
const router = useRouter();
const hcaptchaRef = ref(null);
const avatarFile = ref(null);
const avatarError = ref('');
const hcaptchaResponse = ref('');
const captchaResponse = ref(null);
const onFileChange = (event) => {
avatarFile.value = event.target.files[0];
};
const handleHcaptchaVerify = (token) => {
hcaptchaResponse.value = token;
};
const captchaVerified = computed(() => {
return captchaResponse.value !== null;
});
const handleHcaptchaExpired = () => {
hcaptchaResponse.value = '';
const handleCaptchaVerified = (response) => {
captchaResponse.value = response;
};
const onSubmit = async () => {
@@ -41,7 +39,7 @@ const onSubmit = async () => {
return;
}
if (!hcaptchaResponse.value) {
if (!captchaVerified) {
avatarError.value = '請完成驗證。';
return;
}
@@ -57,9 +55,8 @@ const onSubmit = async () => {
}
try {
await uploadAvatar(avatarFile.value, authStore.jwt, hcaptchaResponse.value);
await uploadAvatar(avatarFile.value, authStore.jwt, captchaResponse.value);
alert('Avatar uploaded successfully!');
hcaptchaRef.value.reset();
// After successful upload, reload this page
router.go(0);
} catch (error) {
@@ -103,15 +100,14 @@ const avatarUrl = computed(() => {
</div>
</div>
</div>
<VueHcaptcha
ref="hcaptchaRef"
:sitekey="$hcaptchaSitekey"
@verify="handleHcaptchaVerify"
@expired="handleHcaptchaExpired"
@reset="handleHcaptchaExpired"
<CAPTCHA
:hcaptchaSitekey="$hcaptchaSitekey"
:recaptchaSitekey="$recaptchaSitekey"
:turnstileSitekey="$turnstileSitekey"
@captchaVerified="handleCaptchaVerified"
/>
<div class="ts-wrap has-top-spaced is-end-aligned">
<button class="ts-button" :disabled="!(avatarFile && avatarError === '' && hcaptchaResponse)" type="submit">更新</button>
<button class="ts-button" :disabled="!(avatarFile && avatarError === '' && captchaVerified)" type="submit">更新</button>
</div>
</fieldset>
</form>