forked from gxwebsoft/mp-10550
提交代码
This commit is contained in:
204
src/passport/sms-login.tsx
Normal file
204
src/passport/sms-login.tsx
Normal file
@@ -0,0 +1,204 @@
|
||||
import {useEffect, useState} from "react";
|
||||
import Taro from '@tarojs/taro'
|
||||
import {Input, Button} from '@nutui/nutui-react-taro'
|
||||
import {loginBySms, sendSmsCaptcha} from "@/api/passport/login";
|
||||
import {LoginParam} from "@/api/passport/login/model";
|
||||
|
||||
const SmsLogin = () => {
|
||||
const [loading, setLoading] = useState<boolean>(false)
|
||||
const [sendingCode, setSendingCode] = useState<boolean>(false)
|
||||
const [countdown, setCountdown] = useState<number>(0)
|
||||
const [formData, setFormData] = useState<LoginParam>({
|
||||
phone: '',
|
||||
code: ''
|
||||
})
|
||||
|
||||
const reload = () => {
|
||||
Taro.hideTabBar()
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
reload()
|
||||
}, [])
|
||||
|
||||
// 倒计时效果
|
||||
useEffect(() => {
|
||||
let timer: NodeJS.Timeout
|
||||
if (countdown > 0) {
|
||||
timer = setTimeout(() => {
|
||||
setCountdown(countdown - 1)
|
||||
}, 1000)
|
||||
}
|
||||
return () => {
|
||||
if (timer) clearTimeout(timer)
|
||||
}
|
||||
}, [countdown])
|
||||
|
||||
// 验证手机号格式
|
||||
const validatePhone = (phone: string): boolean => {
|
||||
const phoneRegex = /^1[3-9]\d{9}$/
|
||||
return phoneRegex.test(phone)
|
||||
}
|
||||
|
||||
// 发送短信验证码
|
||||
const handleSendCode = async () => {
|
||||
if (!formData.phone) {
|
||||
Taro.showToast({
|
||||
title: '请输入手机号码',
|
||||
icon: 'none'
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
if (!validatePhone(formData.phone)) {
|
||||
Taro.showToast({
|
||||
title: '请输入正确的手机号码',
|
||||
icon: 'none'
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
if (sendingCode || countdown > 0) {
|
||||
return
|
||||
}
|
||||
|
||||
try {
|
||||
setSendingCode(true)
|
||||
await sendSmsCaptcha({ phone: formData.phone })
|
||||
|
||||
Taro.showToast({
|
||||
title: '验证码已发送',
|
||||
icon: 'success'
|
||||
})
|
||||
|
||||
// 开始60秒倒计时
|
||||
setCountdown(60)
|
||||
} catch (error: any) {
|
||||
Taro.showToast({
|
||||
title: error.message || '发送失败',
|
||||
icon: 'error'
|
||||
})
|
||||
} finally {
|
||||
setSendingCode(false)
|
||||
}
|
||||
}
|
||||
|
||||
// 处理登录
|
||||
const handleLogin = async () => {
|
||||
// 防止重复提交
|
||||
if (loading) {
|
||||
return
|
||||
}
|
||||
|
||||
// 表单验证
|
||||
if (!formData.phone) {
|
||||
Taro.showToast({
|
||||
title: '请输入手机号码',
|
||||
icon: 'none'
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
if (!validatePhone(formData.phone)) {
|
||||
Taro.showToast({
|
||||
title: '请输入正确的手机号码',
|
||||
icon: 'none'
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
if (!formData.code) {
|
||||
Taro.showToast({
|
||||
title: '请输入验证码',
|
||||
icon: 'none'
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
if (formData.code.length !== 6) {
|
||||
Taro.showToast({
|
||||
title: '请输入6位验证码',
|
||||
icon: 'none'
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
try {
|
||||
setLoading(true)
|
||||
|
||||
await loginBySms({
|
||||
phone: formData.phone,
|
||||
code: formData.code
|
||||
})
|
||||
|
||||
Taro.showToast({
|
||||
title: '登录成功',
|
||||
icon: 'success'
|
||||
})
|
||||
|
||||
// 延迟跳转到首页
|
||||
setTimeout(() => {
|
||||
Taro.reLaunch({
|
||||
url: '/pages/index/index'
|
||||
})
|
||||
}, 1500)
|
||||
|
||||
} catch (error: any) {
|
||||
Taro.showToast({
|
||||
title: error.message || '登录失败',
|
||||
icon: 'error'
|
||||
})
|
||||
} finally {
|
||||
setLoading(false)
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className={'flex flex-col justify-center px-5 pt-3'}>
|
||||
<div className={'flex flex-col justify-between items-center my-2'}>
|
||||
<Input
|
||||
type="number"
|
||||
placeholder="请输入手机号码"
|
||||
maxLength={11}
|
||||
value={formData.phone}
|
||||
onChange={(value) => setFormData({...formData, phone: value})}
|
||||
style={{backgroundColor: '#ffffff', borderRadius: '8px'}}
|
||||
/>
|
||||
</div>
|
||||
<div className={'flex justify-between items-center bg-white rounded-lg my-2 pr-2'}>
|
||||
<Input
|
||||
type="number"
|
||||
placeholder="请输入6位验证码"
|
||||
maxLength={6}
|
||||
value={formData.code}
|
||||
onChange={(value) => setFormData({...formData, code: value})}
|
||||
style={{ backgroundColor: '#ffffff', borderRadius: '8px'}}
|
||||
/>
|
||||
<Button
|
||||
size="small"
|
||||
type={countdown > 0 ? "default" : "primary"}
|
||||
loading={sendingCode}
|
||||
disabled={sendingCode || countdown > 0}
|
||||
onClick={handleSendCode}
|
||||
>
|
||||
{countdown > 0 ? `${countdown}s` : sendingCode ? '发送中...' : '获取验证码'}
|
||||
</Button>
|
||||
</div>
|
||||
<div className={'flex justify-center my-5'}>
|
||||
<Button
|
||||
type="info"
|
||||
size={'large'}
|
||||
className={'w-full rounded-lg p-2'}
|
||||
loading={loading}
|
||||
disabled={loading}
|
||||
onClick={handleLogin}
|
||||
>
|
||||
{loading ? '登录中...' : '登录'}
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
)
|
||||
}
|
||||
export default SmsLogin
|
||||
Reference in New Issue
Block a user