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 }),
|
registerPhone: (data) => request.post('/app-user/register', data, { noNeedToken: true }),
|
||||||
loginPhone: (data) => request.post('/app-user/login', 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
|
// pages
|
||||||
getIndustryList: () => request.get('/industry/list'),
|
getIndustryList: () => request.get('/industry/list'),
|
||||||
getHistoryList: (params) => request.get('/app-valuations/', { params }),
|
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"
|
class="m-auto max-w-1500 min-w-750 f-c-c rounded-12 bg-white bg-opacity-80"
|
||||||
dark:bg-dark
|
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="">
|
<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; ">
|
<div mt-50 style="text-align: center; font-size: 48px; color: #303133; line-height: 48px; font-weight: 600; ">
|
||||||
非遗IP价值评估系统
|
非遗IP价值评估系统
|
||||||
@ -18,8 +18,8 @@
|
|||||||
v-model:value="loginInfo.phone"
|
v-model:value="loginInfo.phone"
|
||||||
style="display: inline-block; width: 260px; height: 42px; text-align: left; line-height: 42px;"
|
style="display: inline-block; width: 260px; height: 42px; text-align: left; line-height: 42px;"
|
||||||
placeholder="请输入手机号"
|
placeholder="请输入手机号"
|
||||||
:maxlength="20"
|
:maxlength="11"
|
||||||
@keypress.enter="handleRegister"
|
@keypress.enter="handleLogin"
|
||||||
>
|
>
|
||||||
<template #prefix>
|
<template #prefix>
|
||||||
<img style="width: 18px; height: 18px; margin-right: 8px;" src="@/assets/images/phone.png" alt="">
|
<img style="width: 18px; height: 18px; margin-right: 8px;" src="@/assets/images/phone.png" alt="">
|
||||||
@ -32,12 +32,29 @@
|
|||||||
rounded-5
|
rounded-5
|
||||||
type="primary"
|
type="primary"
|
||||||
style="background: linear-gradient( 93deg, #880C22 0%, #A30113 100%); margin-left: 20px; font-size: 16px; border: none !important;"
|
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="">
|
<img style="width: 18px; height: 18px; margin-left: 2px;" src="@/assets/images/go.png" alt="">
|
||||||
</n-button>
|
</n-button>
|
||||||
</div>
|
</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>
|
||||||
</div>
|
</div>
|
||||||
</AppPage>
|
</AppPage>
|
||||||
@ -56,8 +73,12 @@ const { t } = useI18n({ useScope: 'global' })
|
|||||||
|
|
||||||
const loginInfo = ref({
|
const loginInfo = ref({
|
||||||
phone: '',
|
phone: '',
|
||||||
|
verifyCode: '',
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const countdown = ref(0)
|
||||||
|
let countdownTimer = null
|
||||||
|
|
||||||
initLoginInfo()
|
initLoginInfo()
|
||||||
|
|
||||||
function initLoginInfo() {
|
function initLoginInfo() {
|
||||||
@ -73,37 +94,110 @@ function initLoginInfo() {
|
|||||||
|
|
||||||
const loading = ref(false)
|
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
|
const { phone } = loginInfo.value
|
||||||
|
|
||||||
if (!phone) {
|
if (!phone) {
|
||||||
$message.warning('请输入手机号')
|
$message.warning('请输入手机号')
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
loading.value = true
|
|
||||||
await api.registerPhone({ phone })
|
if (!validatePhone(phone)) {
|
||||||
.then(res=>{
|
$message.warning('请输入正确的手机号')
|
||||||
handleLogin()
|
return
|
||||||
})
|
}
|
||||||
.catch(res=>{
|
|
||||||
handleLogin()
|
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() {
|
async function handleLogin() {
|
||||||
const { phone } = loginInfo.value
|
const { phone, verifyCode } = 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
|
|
||||||
})
|
|
||||||
|
|
||||||
|
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>
|
</script>
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user