feat: hcaptcha

This commit is contained in:
Tony Yang
2025-04-15 14:46:16 +08:00
parent b8ae97e49b
commit 1b60b3517d
20 changed files with 430 additions and 247 deletions
+22 -2
View File
@@ -2,6 +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 { useAuthStore } from '../../stores/auth';
const props = defineProps({
@@ -16,11 +17,20 @@ const router = useRouter();
const avatarFile = ref(null);
const avatarError = ref('');
const hcaptchaResponse = ref('');
const onFileChange = (event) => {
avatarFile.value = event.target.files[0];
};
const handleHcaptchaVerify = (token) => {
hcaptchaResponse.value = token;
};
const handleHcaptchaExpired = () => {
hcaptchaResponse.value = '';
};
const onSubmit = async () => {
avatarError.value = '';
@@ -29,6 +39,11 @@ const onSubmit = async () => {
return;
}
if (!hcaptchaResponse.value) {
avatarError.value = '請完成驗證。';
return;
}
if (avatarFile.value.size > 1 * 1024 * 1024) {
avatarError.value = '頭貼檔案需小於 1MB。';
return;
@@ -40,7 +55,7 @@ const onSubmit = async () => {
}
try {
await uploadAvatar(avatarFile.value, authStore.jwt);
await uploadAvatar(avatarFile.value, authStore.jwt, hcaptchaResponse.value);
alert('Avatar uploaded successfully!');
// After successful upload, reload this page
router.go(0);
@@ -85,8 +100,13 @@ const avatarUrl = computed(() => {
</div>
</div>
</div>
<VueHcaptcha
:sitekey="$hcaptchaSitekey"
@verify="handleHcaptchaVerify"
@expired="handleHcaptchaExpired"
/>
<div class="ts-wrap has-top-spaced is-end-aligned">
<button class="ts-button" :disabled="!(avatarFile && avatarError === '')" type="submit">更新</button>
<button class="ts-button" :disabled="!(avatarFile && avatarError === '' && hcaptchaResponse)" type="submit">更新</button>
</div>
</fieldset>
</form>