36 手机号登陆业务逻辑开发 - udo-bit/naive_admin_pro GitHub Wiki
完成手机号登录业务逻辑开发
根据我们上一节课的经验,这节课我们来开发一些手机登录的业务逻辑部分,我们在在login/composables下创建一个mobile-login.ts的文件。代码逻辑同我们的登录部分的逻辑,如下:
import type { FormInst, FormRules } from 'naive-ui'
import type { UserMobileLoginParams } from '~/api/user'
import router from '~/routes'
export const useMobileLogin = () => {
const mLoading = ref(false)
const mFormRef = ref<FormInst>()
const { t } = useI18n()
const userStore = useUserStore()
const mModel = reactive<UserMobileLoginParams>({
mobile: null,
code: null,
type: 'mobile',
})
const mRules = reactive<FormRules>({
mobile: [
{
key: 'mobile',
required: true,
renderMessage: () => t('login.mobile.required'),
},
{
key: 'mobile',
pattern: /^1[3456789]\d{9}$/,
renderMessage: () => t('login.mobile.rule'),
},
],
code: [
{
required: true,
renderMessage: () => t('login.mobile.verification-code.required'),
},
{
min: 6,
max: 6,
renderMessage: () => t('login.mobile.verification-code.rule'),
},
],
})
const mLogin = async () => {
mLoading.value = true
try {
await mFormRef.value?.validate()
await userStore.login(mModel)
mLoading.value = false
const redirect = router.currentRoute.value?.params?.redirect as string
await router.replace(redirect || '/')
}
catch (e) {
mLoading.value = false
}
}
return {
mLoading,
mFormRef,
mRules,
mModel,
mLogin,
}
}
下面我们来实现一下获取验证码的部分,首先我们需要在api/user.ts中增加一个请求验证码的接口,如下:
export const userSendCodeUrl = '/user/send-code'
export type UserSendCodeParams = Pick<UserMobileLoginParams, 'mobile'>
export const userSendCodeApi = (params: UserSendCodeParams) => {
return usePost<UserSendCodeParams, any>(userSendCodeUrl, params)
}
当我们点击发送验证码的时候,我们需要将当前的按钮禁用,并在一定的时间间隔内,不能再让用户去请求接口,那么我们的实现逻辑如下:
const counter = ref(120)
const counterDownState = ref(false)
const startCountdown = () => {
counter.value = 120
const timer = setInterval(() => {
if (counter.value <= 0) {
counterDownState.value = false
clearInterval(timer)
return
}
counter.value--
}, 1000)
}
const sendCode = async () => {
// 验证手机号是否已经填写
const msgIns = message.loading(t('login.mobile.verification-code.loading'))
try {
await mFormRef.value?.validate(undefined, rule => rule.key === 'mobile')
startCountdown()
await userSendCodeApi({ mobile: mModel.mobile })
msgIns.destroy()
counterDownState.value = true
message.success(t('login.mobile.verification-code.success'))
}
catch (e) {
msgIns.destroy()
}
}
这里我们需要新导入一个多语言,验证码发送成功的多语言 在locales/lang/pages的zh-CN.ts和en-US.ts的文件中分别导入:
export default {
'login.mobile.verification-code.success': 'Verification code sent successfully!',
'login.mobile.verification-code.loading': 'Sending verification code...',
}
export default{
'login.mobile.verification-code.success': '验证码发送成功!',
'login.mobile.verification-code.loading': '验证码发送中...',
}
接下来我们在pages/login/inde.vue中引入并使用:
<script setup lang="ts">
import { useMobileLogin } from './composables/mobile-login'
const { mModel, mFormRef, mRules, mLoading, counterDownState, counter, mLogin, sendCode } = useMobileLogin()
</script>
<template>
<n-tab-pane name="mobile" :tab="$t('login.mobile.tab')">
<n-form ref="mFormRef" label-align="left" :model="mModel" :rules="mRules" label-placement="left">
<n-form-item-row path="mobile">
<n-input v-model:value="mModel.mobile" :placeholder="$t('login.mobile.placeholder')">
<template #prefix>
<n-icon :component="MobileOutlined" />
</template>
</n-input>
</n-form-item-row>
<n-form-item-row path="code">
<n-input-group>
<n-input v-model:value="mModel.code" :placeholder="$t('login.mobile.verification-code.placeholder')">
<template #prefix>
<n-icon :component="LockOutlined" />
</template>
</n-input>
<n-button :disabled="counterDownState" @click="sendCode">
{{ counterDownState ? `${counter}s${$t('login.mobile.resend')}` : $t('login.mobile.verification-code.get-verification-code') }}
</n-button>
</n-input-group>
</n-form-item-row>
<n-form-item-row path="rememberMe">
<div class="w-100% flex items-center justify-between">
<n-checkbox v-model:value="mModel.rememberMe">
{{ $t('login.remember-me') }}
</n-checkbox>
<a class="cursor-pointer text-[var(--text-color-3)]">
{{ $t('login.forgot-password') }}
</a>
</div>
</n-form-item-row>
</n-form>
<n-button type="primary" :loading="mLoading" block secondary strong @click="mLogin">
{{ $t('login.login') }}
</n-button>
</n-tab-pane>
</template>
测试效果