You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
104 lines
2.6 KiB
104 lines
2.6 KiB
<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>
|
|
|