hookehuyr

feat(注册页面): 添加手机号验证和验证码功能

增加手机号输入字段的验证逻辑,确保输入格式正确。添加验证码输入字段和获取验证码按钮,并实现倒计时功能。优化表单提交逻辑,确保所有必填字段都已填写且手机号格式正确。
......@@ -27,15 +27,44 @@
<div>
<label for="phone" class="block text-sm font-medium text-gray-700">
手机号
手机号 <span class="text-red-500">*</span>
</label>
<input
id="phone"
v-model="formData.phone"
autocomplete="tel"
type="tel"
required
pattern="^1[3-9]\d{9}$"
@blur="validatePhone"
class="mt-1 block w-full px-3 py-2 border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-green-500 focus:border-green-500"
:class="{ 'border-red-300': phoneError }"
/>
<p v-if="phoneError" class="mt-1 text-sm text-red-600">{{ phoneError }}</p>
</div>
<div>
<label for="verificationCode" class="block text-sm font-medium text-gray-700">
验证码 <span class="text-red-500">*</span>
</label>
<div class="flex space-x-2">
<input
id="verificationCode"
v-model="formData.verificationCode"
type="text"
required
maxlength="6"
class="mt-1 block w-full px-3 py-2 border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-green-500 focus:border-green-500"
/>
<button
type="button"
:disabled="countdown > 0 || !isPhoneValid"
@click="sendVerificationCode"
class="mt-1 px-4 py-2 border border-transparent text-sm font-medium rounded-md text-white bg-green-600 hover:bg-green-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-green-500 disabled:opacity-50 disabled:cursor-not-allowed whitespace-nowrap"
>
{{ countdown > 0 ? `${countdown}秒后重试` : '获取验证码' }}
</button>
</div>
</div>
<div>
......@@ -161,39 +190,72 @@ useTitle($route.meta.title);
const router = useRouter()
const { login } = useAuth()
const countdown = ref(0)
const formData = reactive({
name: '',
phone: '',
verificationCode: '',
password: '',
confirmPassword: '',
agreeTerms: false
})
const error = ref('')
const loading = ref(false)
const showTerms = ref(false)
const showPrivacy = ref(false)
const popupTitle = ref('')
const popupType = ref('')
const openTerms = () => {
popupTitle.value = '用户协议'
popupType.value = 'terms'
showTerms.value = true
const startCountdown = () => {
countdown.value = 60
const timer = setInterval(() => {
countdown.value--
if (countdown.value <= 0) {
clearInterval(timer)
}
}, 1000)
}
const phoneError = ref('')
const isPhoneValid = ref(false)
const validatePhone = () => {
if (!formData.phone) {
phoneError.value = '请输入手机号'
isPhoneValid.value = false
return
}
if (!/^1[3-9]\d{9}$/.test(formData.phone)) {
phoneError.value = '请输入正确的手机号'
isPhoneValid.value = false
return
}
phoneError.value = ''
isPhoneValid.value = true
}
const openPrivacy = () => {
popupTitle.value = '隐私政策'
popupType.value = 'privacy'
showPrivacy.value = true
const sendVerificationCode = async () => {
if (!isPhoneValid.value) {
return
}
try {
// TODO: 调用发送验证码API
startCountdown()
} catch (err) {
console.error('Send verification code error:', err)
error.value = '发送验证码失败,请稍后重试'
}
}
const handleSubmit = async () => {
if (!formData.name || !formData.password) {
if (!formData.name || !formData.password || !formData.phone || !formData.verificationCode) {
error.value = '请填写所有必填字段'
return
}
if (!/^1[3-9]\d{9}$/.test(formData.phone)) {
error.value = '请输入正确的手机号'
return
}
if (formData.password !== formData.confirmPassword) {
error.value = '两次输入的密码不一致'
return
......