1 changed files with 104 additions and 0 deletions
@ -0,0 +1,104 @@ |
|||
<script setup lang="ts"> |
|||
import { clientRegisterSchema, type RegisterInput } from 'shared/auth-schema' |
|||
|
|||
const props = defineProps<{ |
|||
captchaSvg: string |
|||
captchaToken: string |
|||
}>() |
|||
|
|||
const emit = defineEmits<{ |
|||
'refresh-captcha': [] |
|||
success: [] |
|||
error: [message: string] |
|||
}>() |
|||
|
|||
const loading = ref(false) |
|||
const formRef = ref() |
|||
|
|||
const state = reactive<RegisterInput>({ |
|||
username: '', |
|||
password: '', |
|||
confirmPassword: '', |
|||
captchaText: '', |
|||
}) |
|||
|
|||
const password = computed(() => state.password) |
|||
|
|||
async function onSubmit() { |
|||
if (loading.value) return |
|||
loading.value = true |
|||
try { |
|||
const res = await $fetch<{ code: number; message: string; data: { id?: number; username?: string; field?: string } | null }>( |
|||
'/api/auth/register', |
|||
{ |
|||
method: 'POST', |
|||
body: { |
|||
username: state.username, |
|||
password: state.password, |
|||
confirmPassword: state.confirmPassword, |
|||
captchaToken: props.captchaToken, |
|||
captchaText: state.captchaText, |
|||
}, |
|||
} |
|||
) |
|||
|
|||
if (res.code !== 0) { |
|||
const field = res.data && 'field' in (res.data || {}) ? (res.data as { field: string }).field : undefined |
|||
if (field && formRef.value) { |
|||
formRef.value.setFieldError(field, res.message) |
|||
} else { |
|||
emit('error', res.message) |
|||
} |
|||
// Auto-refresh captcha on captcha-related errors |
|||
if (res.message.includes('验证码')) { |
|||
emit('refresh-captcha') |
|||
state.captchaText = '' |
|||
} |
|||
return |
|||
} |
|||
|
|||
emit('success') |
|||
} catch { |
|||
emit('error', '注册失败,请稍后重试') |
|||
} finally { |
|||
loading.value = false |
|||
} |
|||
} |
|||
</script> |
|||
|
|||
<template> |
|||
<UForm ref="formRef" :state="state" :schema="clientRegisterSchema" @submit="onSubmit"> |
|||
<UFormField name="username" label="用户名" required class="mb-4"> |
|||
<UInput v-model="state.username" placeholder="请输入用户名" :disabled="loading" /> |
|||
</UFormField> |
|||
|
|||
<PasswordInput |
|||
v-model="state.password" |
|||
label="密码" |
|||
placeholder="至少8个字符" |
|||
:disabled="loading" |
|||
class="mb-4" |
|||
/> |
|||
<PasswordStrength :password="password" /> |
|||
|
|||
<PasswordInput |
|||
v-model="state.confirmPassword" |
|||
label="确认密码" |
|||
placeholder="请再次输入密码" |
|||
:disabled="loading" |
|||
class="mb-4 mt-2" |
|||
/> |
|||
|
|||
<CaptchaField |
|||
v-model="state.captchaText" |
|||
:svg="captchaSvg" |
|||
:loading="loading" |
|||
class="mb-4" |
|||
@refresh="emit('refresh-captcha')" |
|||
/> |
|||
|
|||
<UButton type="submit" block :loading="loading" class="mt-6"> |
|||
{{ loading ? '注册中...' : '注册' }} |
|||
</UButton> |
|||
</UForm> |
|||
</template> |
|||
Loading…
Reference in new issue