fix:注册添加表单校验

This commit is contained in:
zhonghua 2026-04-14 17:03:07 +08:00
parent 4d64dd9178
commit 54aaf421be

View File

@ -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 {