fix:注册添加表单校验
This commit is contained in:
parent
4d64dd9178
commit
54aaf421be
@ -7,84 +7,41 @@
|
|||||||
{{ isRegister ? "加入乐绘世界,开启创作之旅" : "欢迎回来,继续你的创作" }}
|
{{ isRegister ? "加入乐绘世界,开启创作之旅" : "欢迎回来,继续你的创作" }}
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<a-form
|
<a-form ref="formRef" :model="form" :rules="currentRules" layout="vertical" class="auth-form"
|
||||||
:model="form"
|
@keyup.enter="submitForm">
|
||||||
:rules="currentRules"
|
|
||||||
@finish="handleSubmit"
|
|
||||||
layout="vertical"
|
|
||||||
class="auth-form"
|
|
||||||
>
|
|
||||||
<a-form-item v-if="showNicknameField" name="nickname" label="昵称">
|
<a-form-item v-if="showNicknameField" name="nickname" label="昵称">
|
||||||
<a-input
|
<a-input v-model:value="form.nickname" placeholder="给自己取个名字吧" size="large" />
|
||||||
v-model:value="form.nickname"
|
|
||||||
placeholder="给自己取个名字吧"
|
|
||||||
size="large"
|
|
||||||
/>
|
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
|
|
||||||
<a-form-item v-if="showPhoneField" name="phone" label="手机号">
|
<a-form-item v-if="showPhoneField" name="phone" label="手机号">
|
||||||
<a-input
|
<a-input v-model:value="form.phone" placeholder="请输入手机号" size="large" :maxlength="11" />
|
||||||
v-model:value="form.phone"
|
|
||||||
placeholder="请输入手机号"
|
|
||||||
size="large"
|
|
||||||
:maxlength="11"
|
|
||||||
/>
|
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
|
|
||||||
<a-form-item v-if="showSmsCodeField" name="smsCode" label="验证码">
|
<a-form-item v-if="showSmsCodeField" name="smsCode" label="验证码">
|
||||||
<div style="display: flex; gap: 8px">
|
<div style="display: flex; gap: 8px">
|
||||||
<a-input
|
<a-input v-model:value="form.smsCode" placeholder="请输入6位验证码" size="large" :maxlength="6" style="flex: 1" />
|
||||||
v-model:value="form.smsCode"
|
<a-button size="large" :disabled="smsCountdown > 0 || !isPhoneValid" :loading="smsSending"
|
||||||
placeholder="请输入6位验证码"
|
@click="handleSendSms" style="min-width: 120px">
|
||||||
size="large"
|
|
||||||
:maxlength="6"
|
|
||||||
style="flex: 1"
|
|
||||||
/>
|
|
||||||
<a-button
|
|
||||||
size="large"
|
|
||||||
:disabled="smsCountdown > 0 || !isPhoneValid"
|
|
||||||
:loading="smsSending"
|
|
||||||
@click="handleSendSms"
|
|
||||||
style="min-width: 120px"
|
|
||||||
>
|
|
||||||
{{ smsCountdown > 0 ? `${smsCountdown}s 后重发` : "获取验证码" }}
|
{{ smsCountdown > 0 ? `${smsCountdown}s 后重发` : "获取验证码" }}
|
||||||
</a-button>
|
</a-button>
|
||||||
</div>
|
</div>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
|
|
||||||
<a-form-item v-if="showUsernameField" name="username" label="用户名">
|
<a-form-item v-if="showUsernameField" name="username" label="账号">
|
||||||
<a-input
|
<a-input v-model:value="form.username" :maxlength="12" placeholder="请输入账号" size="large" />
|
||||||
v-model:value="form.username"
|
|
||||||
placeholder="请输入用户名"
|
|
||||||
size="large"
|
|
||||||
/>
|
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
|
|
||||||
<a-form-item v-if="showPasswordField" name="password" label="密码">
|
<a-form-item v-if="showPasswordField" name="password" label="密码">
|
||||||
<a-input-password
|
<a-input-password v-model:value="form.password" :maxlength="16" placeholder="请输入密码" size="large" />
|
||||||
v-model:value="form.password"
|
|
||||||
placeholder="请输入密码"
|
|
||||||
size="large"
|
|
||||||
/>
|
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
|
|
||||||
<a-form-item v-if="isRegister" name="confirmPassword" label="确认密码">
|
<a-form-item v-if="isRegister" name="confirmPassword" label="确认密码">
|
||||||
<a-input-password
|
<a-input-password v-model:value="form.confirmPassword" :maxlength="16" placeholder="再次输入密码" size="large" />
|
||||||
v-model:value="form.confirmPassword"
|
|
||||||
placeholder="再次输入密码"
|
|
||||||
size="large"
|
|
||||||
/>
|
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
|
|
||||||
<a-form-item>
|
<a-form-item>
|
||||||
<a-button
|
<a-button type="primary" html-type="button" size="large" :loading="loading" block class="auth-btn"
|
||||||
type="primary"
|
@click="submitForm">
|
||||||
html-type="submit"
|
|
||||||
size="large"
|
|
||||||
:loading="loading"
|
|
||||||
block
|
|
||||||
class="auth-btn"
|
|
||||||
>
|
|
||||||
{{ isRegister ? "注册并登录" : "登录" }}
|
{{ isRegister ? "注册并登录" : "登录" }}
|
||||||
</a-button>
|
</a-button>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
@ -124,6 +81,7 @@ import { ref, reactive, computed, onUnmounted } from "vue"
|
|||||||
import { useRouter, useRoute } from "vue-router"
|
import { useRouter, useRoute } from "vue-router"
|
||||||
import { message } from "ant-design-vue"
|
import { message } from "ant-design-vue"
|
||||||
import { publicAuthApi } from "@/api/public"
|
import { publicAuthApi } from "@/api/public"
|
||||||
|
import type { FormInstance } from "ant-design-vue"
|
||||||
import type { Rule } from "ant-design-vue/es/form"
|
import type { Rule } from "ant-design-vue/es/form"
|
||||||
|
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
@ -148,7 +106,9 @@ const smsCountdown = ref(0)
|
|||||||
const smsSending = ref(false)
|
const smsSending = ref(false)
|
||||||
let smsTimer: ReturnType<typeof setInterval> | null = null
|
let smsTimer: ReturnType<typeof setInterval> | null = null
|
||||||
|
|
||||||
const isPhoneValid = computed(() => /^1[3-9]\d{9}$/.test(form.phone))
|
const formRef = ref<FormInstance>()
|
||||||
|
|
||||||
|
const isPhoneValid = computed(() => /^1[3-9]\d{9}$/.test(form.phone.trim()))
|
||||||
|
|
||||||
// 控制字段显示的 computed
|
// 控制字段显示的 computed
|
||||||
const showNicknameField = computed(() => isRegister.value)
|
const showNicknameField = computed(() => isRegister.value)
|
||||||
@ -157,15 +117,32 @@ const showSmsCodeField = computed(() => isRegister.value || (!isRegister.value &
|
|||||||
const showUsernameField = computed(() => isRegister.value || (!isRegister.value && loginMethod.value === 'password'))
|
const showUsernameField = computed(() => isRegister.value || (!isRegister.value && loginMethod.value === 'password'))
|
||||||
const showPasswordField = computed(() => isRegister.value || (!isRegister.value && loginMethod.value === 'password'))
|
const showPasswordField = computed(() => isRegister.value || (!isRegister.value && loginMethod.value === 'password'))
|
||||||
|
|
||||||
// 基础校验规则
|
// 账号名:仅英文字母与数字
|
||||||
|
const USERNAME_PATTERN = /^[a-zA-Z0-9]+$/
|
||||||
|
// 密码:英文字母、数字、ASCII 可打印特殊字符(不含空格)
|
||||||
|
const PASSWORD_PATTERN = /^[\x21-\x7E]+$/
|
||||||
|
|
||||||
|
// 基础校验规则(与后端 PublicRegisterDto / PublicLoginDto 一致)
|
||||||
const baseRules: Record<string, Rule[]> = {
|
const baseRules: Record<string, Rule[]> = {
|
||||||
username: [
|
username: [
|
||||||
{ required: true, message: "请输入用户名", trigger: "blur" },
|
{ required: true, message: "请输入账号名", trigger: "blur" },
|
||||||
{ min: 4, message: "用户名至少4个字符", trigger: "blur" },
|
{ min: 4, message: "账号名为4-12个字符", trigger: "blur" },
|
||||||
|
{ max: 12, message: "账号名为4-12个字符", trigger: "blur" },
|
||||||
|
{
|
||||||
|
pattern: USERNAME_PATTERN,
|
||||||
|
message: "账号名只能包含英文字母与数字",
|
||||||
|
trigger: "blur",
|
||||||
|
},
|
||||||
],
|
],
|
||||||
password: [
|
password: [
|
||||||
{ required: true, message: "请输入密码", trigger: "blur" },
|
{ required: true, message: "请输入密码", trigger: "blur" },
|
||||||
{ min: 6, message: "密码至少6个字符", trigger: "blur" },
|
{ min: 6, message: "密码为6-16个字符", trigger: "blur" },
|
||||||
|
{ max: 16, message: "密码为6-16个字符", trigger: "blur" },
|
||||||
|
{
|
||||||
|
pattern: PASSWORD_PATTERN,
|
||||||
|
message: "密码只能包含英文字母、数字与特殊字符",
|
||||||
|
trigger: "blur",
|
||||||
|
},
|
||||||
],
|
],
|
||||||
confirmPassword: [
|
confirmPassword: [
|
||||||
{ required: true, message: "请确认密码", trigger: "blur" },
|
{ required: true, message: "请确认密码", trigger: "blur" },
|
||||||
@ -181,7 +158,8 @@ const baseRules: Record<string, Rule[]> = {
|
|||||||
],
|
],
|
||||||
nickname: [
|
nickname: [
|
||||||
{ required: true, message: "请输入昵称", trigger: "blur" },
|
{ required: true, message: "请输入昵称", trigger: "blur" },
|
||||||
{ min: 2, message: "昵称至少2个字符", trigger: "blur" },
|
{ min: 2, message: "昵称为2-20个字符", trigger: "blur" },
|
||||||
|
{ max: 20, message: "昵称为2-20个字符", trigger: "blur" },
|
||||||
],
|
],
|
||||||
phone: [
|
phone: [
|
||||||
{ required: true, message: "请输入手机号", trigger: "blur" },
|
{ required: true, message: "请输入手机号", trigger: "blur" },
|
||||||
@ -218,6 +196,7 @@ const currentRules = computed(() => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
const handleSendSms = async () => {
|
const handleSendSms = async () => {
|
||||||
|
form.phone = form.phone.trim()
|
||||||
if (!isPhoneValid.value || smsCountdown.value > 0) return
|
if (!isPhoneValid.value || smsCountdown.value > 0) return
|
||||||
smsSending.value = true
|
smsSending.value = true
|
||||||
try {
|
try {
|
||||||
@ -259,6 +238,25 @@ const switchToLogin = () => {
|
|||||||
loginMethod.value = 'password'
|
loginMethod.value = 'password'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** 校验前去除各字段前后空格并写回表单,再触发校验 */
|
||||||
|
function trimFormFields() {
|
||||||
|
const t = (v: string) => (typeof v === "string" ? v.trim() : v)
|
||||||
|
form.nickname = t(form.nickname)
|
||||||
|
form.phone = t(form.phone)
|
||||||
|
form.smsCode = t(form.smsCode)
|
||||||
|
form.username = t(form.username)
|
||||||
|
form.password = t(form.password)
|
||||||
|
form.confirmPassword = t(form.confirmPassword)
|
||||||
|
}
|
||||||
|
|
||||||
|
function submitForm() {
|
||||||
|
trimFormFields()
|
||||||
|
formRef.value
|
||||||
|
?.validate()
|
||||||
|
.then(() => handleSubmit())
|
||||||
|
.catch(() => { })
|
||||||
|
}
|
||||||
|
|
||||||
const handleSubmit = async () => {
|
const handleSubmit = async () => {
|
||||||
loading.value = true
|
loading.value = true
|
||||||
try {
|
try {
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user