feat: 添加短信验证码登录功能,优化登录页面交互体验
- 新增验证码输入框和发送验证码按钮,支持60秒倒计时 - 添加手机号格式验证(11位,1开头) - 新增sendVerifyCode和loginWithVerifyCode API接口(待后端实现) - 优化登录流程,添加完整的表单验证和错误提示 - 调整登录容器高度以适应新增的验证码输入区域 - 添加组件卸载时的定时器清理逻辑 - 保留原有登录逻辑作为临时方案,
This commit is contained in:
parent
ebf41d74c8
commit
2ce82f3401
@ -8,6 +8,9 @@ export default {
|
||||
// 手机号
|
||||
registerPhone: (data) => request.post('/app-user/register', data, { noNeedToken: true }),
|
||||
loginPhone: (data) => request.post('/app-user/login', data, { noNeedToken: true }),
|
||||
// 短信验证码(待后端实现)
|
||||
sendVerifyCode: (data) => request.post('/app-user/send-verify-code', data, { noNeedToken: true }),
|
||||
loginWithVerifyCode: (data) => request.post('/app-user/login-with-code', data, { noNeedToken: true }),
|
||||
// pages
|
||||
getIndustryList: () => request.get('/industry/list'),
|
||||
getHistoryList: (params) => request.get('/app-valuations/', { params }),
|
||||
|
||||
@ -5,7 +5,7 @@
|
||||
class="m-auto max-w-1500 min-w-750 f-c-c rounded-12 bg-white bg-opacity-80"
|
||||
dark:bg-dark
|
||||
>
|
||||
<div w-750 px-20 style="height: 400px; padding-top: 50px; text-align: center;">
|
||||
<div w-750 px-20 style="height: 480px; padding-top: 50px; text-align: center;">
|
||||
<img style="width: 371px; height: 60px; margin: auto;" src="@/assets/images/logo.png" alt="">
|
||||
<div mt-50 style="text-align: center; font-size: 48px; color: #303133; line-height: 48px; font-weight: 600; ">
|
||||
非遗IP价值评估系统
|
||||
@ -18,8 +18,8 @@
|
||||
v-model:value="loginInfo.phone"
|
||||
style="display: inline-block; width: 260px; height: 42px; text-align: left; line-height: 42px;"
|
||||
placeholder="请输入手机号"
|
||||
:maxlength="20"
|
||||
@keypress.enter="handleRegister"
|
||||
:maxlength="11"
|
||||
@keypress.enter="handleLogin"
|
||||
>
|
||||
<template #prefix>
|
||||
<img style="width: 18px; height: 18px; margin-right: 8px;" src="@/assets/images/phone.png" alt="">
|
||||
@ -32,12 +32,29 @@
|
||||
rounded-5
|
||||
type="primary"
|
||||
style="background: linear-gradient( 93deg, #880C22 0%, #A30113 100%); margin-left: 20px; font-size: 16px; border: none !important;"
|
||||
@click="handleRegister"
|
||||
@click="handleLogin"
|
||||
>
|
||||
立即登录
|
||||
<img style="width: 18px; height: 18px; margin-left: 2px;" src="@/assets/images/go.png" alt="">
|
||||
</n-button>
|
||||
</div>
|
||||
|
||||
<div mt-20 style="display: flex; justify-content: center; align-items: center;">
|
||||
<n-input
|
||||
v-model:value="loginInfo.verifyCode"
|
||||
style="width: 260px; height: 42px;"
|
||||
placeholder="验证码"
|
||||
:maxlength="6"
|
||||
@keypress.enter="handleLogin"
|
||||
/>
|
||||
<n-button
|
||||
style="width: 126px; height: 42px; margin-left: 12px; font-size: 14px;"
|
||||
:disabled="countdown > 0"
|
||||
@click="handleSendCode"
|
||||
>
|
||||
{{ countdown > 0 ? `${countdown}秒后重试` : '发送验证码' }}
|
||||
</n-button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</AppPage>
|
||||
@ -56,8 +73,12 @@ const { t } = useI18n({ useScope: 'global' })
|
||||
|
||||
const loginInfo = ref({
|
||||
phone: '',
|
||||
verifyCode: '',
|
||||
})
|
||||
|
||||
const countdown = ref(0)
|
||||
let countdownTimer = null
|
||||
|
||||
initLoginInfo()
|
||||
|
||||
function initLoginInfo() {
|
||||
@ -73,37 +94,110 @@ function initLoginInfo() {
|
||||
|
||||
const loading = ref(false)
|
||||
|
||||
async function handleRegister() {
|
||||
// 验证手机号格式
|
||||
function validatePhone(phone) {
|
||||
const phoneReg = /^1[3-9]\d{9}$/
|
||||
return phoneReg.test(phone)
|
||||
}
|
||||
|
||||
// 发送验证码
|
||||
async function handleSendCode() {
|
||||
const { phone } = loginInfo.value
|
||||
|
||||
if (!phone) {
|
||||
$message.warning('请输入手机号')
|
||||
return
|
||||
}
|
||||
loading.value = true
|
||||
await api.registerPhone({ phone })
|
||||
.then(res=>{
|
||||
handleLogin()
|
||||
})
|
||||
.catch(res=>{
|
||||
handleLogin()
|
||||
})
|
||||
|
||||
if (!validatePhone(phone)) {
|
||||
$message.warning('请输入正确的手机号')
|
||||
return
|
||||
}
|
||||
|
||||
try {
|
||||
// TODO: 调用发送验证码接口
|
||||
// await api.sendVerifyCode({ phone })
|
||||
|
||||
// 模拟发送成功
|
||||
$message.success('验证码已发送')
|
||||
|
||||
// 开始倒计时
|
||||
countdown.value = 60
|
||||
countdownTimer = setInterval(() => {
|
||||
countdown.value--
|
||||
if (countdown.value <= 0) {
|
||||
clearInterval(countdownTimer)
|
||||
countdownTimer = null
|
||||
}
|
||||
}, 1000)
|
||||
} catch (error) {
|
||||
$message.error('验证码发送失败,请重试')
|
||||
}
|
||||
}
|
||||
|
||||
// 登录
|
||||
async function handleLogin() {
|
||||
const { phone } = loginInfo.value
|
||||
loading.value = true
|
||||
await api.loginPhone({ phone, password: phone.slice(5,11) }).catch(res=>{
|
||||
setToken(res.error.access_token)
|
||||
if (query.redirect) {
|
||||
const path = query.redirect
|
||||
localStorage.setItem('phone', phone)
|
||||
Reflect.deleteProperty(query, 'redirect')
|
||||
router.push({ path, query })
|
||||
} else {
|
||||
router.push('/')
|
||||
}
|
||||
loading.value = false
|
||||
})
|
||||
const { phone, verifyCode } = loginInfo.value
|
||||
|
||||
if (!phone) {
|
||||
$message.warning('请输入手机号')
|
||||
return
|
||||
}
|
||||
|
||||
if (!validatePhone(phone)) {
|
||||
$message.warning('请输入正确的手机号')
|
||||
return
|
||||
}
|
||||
|
||||
// TODO: 等待后端接口完成后再启用验证码验证
|
||||
// if (!verifyCode) {
|
||||
// $message.warning('请输入验证码')
|
||||
// return
|
||||
// }
|
||||
//
|
||||
// if (verifyCode.length < 4) {
|
||||
// $message.warning('请输入完整的验证码')
|
||||
// return
|
||||
// }
|
||||
|
||||
loading.value = true
|
||||
|
||||
try {
|
||||
// TODO: 调用登录接口,传入手机号和验证码
|
||||
// const res = await api.loginWithVerifyCode({ phone, verifyCode })
|
||||
// setToken(res.access_token)
|
||||
|
||||
// 模拟登录成功(暂时使用原有的注册+登录逻辑)
|
||||
await api.registerPhone({ phone })
|
||||
.then(res => {
|
||||
return api.loginPhone({ phone, password: phone.slice(5, 11) })
|
||||
})
|
||||
.catch(res => {
|
||||
if (res.error && res.error.access_token) {
|
||||
setToken(res.error.access_token)
|
||||
localStorage.setItem('phone', phone)
|
||||
|
||||
if (query.redirect) {
|
||||
const path = query.redirect
|
||||
Reflect.deleteProperty(query, 'redirect')
|
||||
router.push({ path, query })
|
||||
} else {
|
||||
router.push('/')
|
||||
}
|
||||
}
|
||||
})
|
||||
} catch (error) {
|
||||
$message.error('登录失败,请重试')
|
||||
} finally {
|
||||
loading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
// 组件卸载时清除定时器
|
||||
onBeforeUnmount(() => {
|
||||
if (countdownTimer) {
|
||||
clearInterval(countdownTimer)
|
||||
countdownTimer = null
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user