- 修改手机号输入框提示文案为“请输入账号”- 移除手机号格式校验逻辑 - 将短信验证码输入框改为密码类型,并修改提示文案为“请输入密码”- 移除获取验证码按钮及相关倒计时逻辑 - 调整用户协议勾选框文案,去除“勾选表示您”前缀-优化登录接口调用参数格式
398 lines
10 KiB
TypeScript
398 lines
10 KiB
TypeScript
import {useEffect, useState} from "react";
|
|
import Taro from '@tarojs/taro'
|
|
import {Input, Radio, Button} from '@nutui/nutui-react-taro'
|
|
import {loginBySms, getCaptcha, sendSmsCaptcha} from '@/api/passport/login'
|
|
|
|
const Login = () => {
|
|
const [isAgree, setIsAgree] = useState(false)
|
|
// 只保留短信登录方式
|
|
const [loginType, setLoginType] = useState('sms')
|
|
// const [username, setUsername] = useState('')
|
|
// const [password, setPassword] = useState('')
|
|
const [phone, setPhone] = useState('')
|
|
const [smsCode, setSmsCode] = useState('')
|
|
const [captchaImg, setCaptchaImg] = useState('')
|
|
const [captchaCode, setCaptchaCode] = useState('')
|
|
const [showCaptchaModal, setShowCaptchaModal] = useState(false)
|
|
const [countdown, setCountdown] = useState(0) // 短信验证码倒计时
|
|
const [loading, setLoading] = useState(false)
|
|
|
|
const reload = () => {
|
|
Taro.hideTabBar()
|
|
}
|
|
|
|
// 获取图形验证码
|
|
const fetchCaptcha = async () => {
|
|
try {
|
|
const res = await getCaptcha()
|
|
setCaptchaImg(res.base64)
|
|
} catch (error) {
|
|
Taro.showToast({
|
|
title: '获取验证码失败',
|
|
icon: 'error'
|
|
})
|
|
}
|
|
}
|
|
|
|
// 发送短信验证码
|
|
// const handleSendSmsCode = async () => {
|
|
// if (!phone) {
|
|
// Taro.showToast({
|
|
// title: '请输入手机号',
|
|
// icon: 'error'
|
|
// })
|
|
// return
|
|
// }
|
|
//
|
|
// // 验证手机号格式
|
|
// const phoneReg = /^1[3-9]\d{9}$/
|
|
// if (!phoneReg.test(phone)) {
|
|
// Taro.showToast({
|
|
// title: '手机号格式不正确',
|
|
// icon: 'error'
|
|
// })
|
|
// return
|
|
// }
|
|
//
|
|
// // 显示图形验证码弹窗
|
|
// fetchCaptcha()
|
|
// setShowCaptchaModal(true)
|
|
// }
|
|
|
|
// 确认发送短信验证码
|
|
const confirmSendSmsCode = async () => {
|
|
if (!captchaCode) {
|
|
Taro.showToast({
|
|
title: '请输入图形验证码',
|
|
icon: 'error'
|
|
})
|
|
return
|
|
}
|
|
|
|
try {
|
|
setLoading(true)
|
|
// 发送短信验证码时需要传入手机号和图形验证码
|
|
await sendSmsCaptcha({ phone, code: captchaCode })
|
|
Taro.showToast({
|
|
title: '短信验证码已发送',
|
|
icon: 'success'
|
|
})
|
|
setShowCaptchaModal(false)
|
|
setCaptchaCode('')
|
|
|
|
// 开始倒计时
|
|
setCountdown(60)
|
|
} catch (error) {
|
|
Taro.showToast({
|
|
title: error.message || '发送失败',
|
|
icon: 'error'
|
|
})
|
|
} finally {
|
|
setLoading(false)
|
|
}
|
|
}
|
|
|
|
// 短信验证码登录
|
|
const handleSmsLogin = async () => {
|
|
if (!phone) {
|
|
Taro.showToast({
|
|
title: '请输入账号',
|
|
icon: 'error'
|
|
})
|
|
return
|
|
}
|
|
|
|
// 验证手机号格式
|
|
// const phoneReg = /^1[3-9]\d{9}$/
|
|
// if (!phoneReg.test(phone)) {
|
|
// Taro.showToast({
|
|
// title: '手机号格式不正确',
|
|
// icon: 'error'
|
|
// })
|
|
// return
|
|
// }
|
|
|
|
if (!smsCode) {
|
|
Taro.showToast({
|
|
title: '请输入短信验证码',
|
|
icon: 'error'
|
|
})
|
|
return
|
|
}
|
|
|
|
try {
|
|
setLoading(true)
|
|
// 短信登录时传入手机号和短信验证码
|
|
const res = await loginBySms({ phone, code:smsCode })
|
|
|
|
console.log(res,'.......')
|
|
Taro.showToast({
|
|
title: '登录成功',
|
|
icon: 'success'
|
|
})
|
|
|
|
// 跳转到首页
|
|
setTimeout(() => {
|
|
Taro.switchTab({ url: '/pages/index/index' })
|
|
}, 1500)
|
|
} catch (error) {
|
|
Taro.showToast({
|
|
title: error.message || '登录失败',
|
|
icon: 'error'
|
|
})
|
|
} finally {
|
|
setLoading(false)
|
|
}
|
|
}
|
|
|
|
// 登录处理
|
|
const onLogin = async () => {
|
|
if (!isAgree) {
|
|
Taro.showToast({
|
|
title: '请先同意服务协议',
|
|
icon: 'error'
|
|
})
|
|
return
|
|
}
|
|
|
|
handleSmsLogin()
|
|
}
|
|
|
|
// 倒计时处理
|
|
useEffect(() => {
|
|
let timer: any
|
|
if (countdown > 0) {
|
|
timer = setTimeout(() => {
|
|
setCountdown(countdown - 1)
|
|
}, 1000)
|
|
}
|
|
return () => clearTimeout(timer)
|
|
}, [countdown])
|
|
|
|
useEffect(() => {
|
|
reload()
|
|
}, [])
|
|
|
|
return (
|
|
<>
|
|
<div style={{
|
|
display: 'flex',
|
|
flexDirection: 'column',
|
|
justifyContent: 'center',
|
|
padding: '0 20px',
|
|
minHeight: '70vh',
|
|
backgroundColor: '#f5f5f5'
|
|
}}>
|
|
<div style={{
|
|
fontSize: '24px',
|
|
textAlign: 'center',
|
|
padding: '20px 0',
|
|
fontWeight: 'normal',
|
|
margin: '20px 0 20px 0'
|
|
}}>管理员登录</div>
|
|
|
|
{/* 登录方式切换 - 隐藏账号登录 */}
|
|
<div style={{
|
|
display: 'none', // 隐藏登录方式切换
|
|
justifyContent: 'center',
|
|
marginBottom: '20px'
|
|
}}>
|
|
<div
|
|
style={{
|
|
padding: '10px 20px',
|
|
borderBottom: loginType === 'account' ? '2px solid #1890ff' : 'none',
|
|
color: loginType === 'account' ? '#1890ff' : '#999',
|
|
cursor: 'pointer'
|
|
}}
|
|
onClick={() => setLoginType('account')}
|
|
>
|
|
账号登录
|
|
</div>
|
|
<div
|
|
style={{
|
|
padding: '10px 20px',
|
|
borderBottom: loginType === 'sms' ? '2px solid #1890ff' : 'none',
|
|
color: loginType === 'sms' ? '#1890ff' : '#999',
|
|
cursor: 'pointer'
|
|
}}
|
|
onClick={() => setLoginType('sms')}
|
|
>
|
|
短信登录
|
|
</div>
|
|
</div>
|
|
|
|
{/* 短信验证码登录 - 始终显示 */}
|
|
<div>
|
|
<div style={{
|
|
display: 'flex',
|
|
flexDirection: 'column',
|
|
justifyContent: 'space-between',
|
|
alignItems: 'center',
|
|
margin: '10px 0'
|
|
}}>
|
|
<Input
|
|
type="text"
|
|
placeholder="请输入账号"
|
|
value={phone}
|
|
onChange={(val) => setPhone(val)}
|
|
style={{
|
|
backgroundColor: '#ffffff',
|
|
borderRadius: '8px',
|
|
width: '100%',
|
|
padding: '10px'
|
|
}}
|
|
/>
|
|
</div>
|
|
<div style={{
|
|
display: 'flex',
|
|
flexDirection: 'column',
|
|
justifyContent: 'space-between',
|
|
alignItems: 'center',
|
|
margin: '10px 0'
|
|
}}>
|
|
<div style={{
|
|
display: 'flex',
|
|
width: '100%',
|
|
backgroundColor: '#ffffff',
|
|
borderRadius: '8px'
|
|
}}>
|
|
<Input
|
|
type="password"
|
|
placeholder="请输入密码"
|
|
value={smsCode}
|
|
onChange={(val) => setSmsCode(val)}
|
|
style={{
|
|
flex: 1,
|
|
border: 'none',
|
|
padding: '10px'
|
|
}}
|
|
/>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div style={{
|
|
display: 'flex',
|
|
justifyContent: 'center',
|
|
margin: '20px 0'
|
|
}}>
|
|
<Button
|
|
type="info"
|
|
size={'large'}
|
|
style={{
|
|
width: '100%',
|
|
borderRadius: '8px',
|
|
padding: '10px'
|
|
}}
|
|
disabled={!isAgree}
|
|
loading={loading}
|
|
onClick={onLogin}
|
|
>
|
|
立即登录
|
|
</Button>
|
|
</div>
|
|
|
|
<div style={{
|
|
display: 'flex',
|
|
alignItems: 'center',
|
|
padding: '0 5px',
|
|
margin: '10px 0'
|
|
}}>
|
|
<Radio
|
|
style={{color: '#333333'}}
|
|
checked={isAgree}
|
|
onClick={() => setIsAgree(!isAgree)}
|
|
/>
|
|
<span style={{color: '#999', marginLeft: '5px'}} onClick={() => setIsAgree(!isAgree)}>已阅读并同意</span>
|
|
<a
|
|
onClick={() => Taro.navigateTo({url: '/passport/agreement'})}
|
|
style={{color: '#1890ff'}}
|
|
>
|
|
《服务协议及隐私政策》
|
|
</a>
|
|
</div>
|
|
</div>
|
|
|
|
{/* 图形验证码弹窗 */}
|
|
{showCaptchaModal && (
|
|
<div style={{
|
|
position: 'fixed',
|
|
top: 0,
|
|
left: 0,
|
|
right: 0,
|
|
bottom: 0,
|
|
backgroundColor: 'rgba(0, 0, 0, 0.5)',
|
|
display: 'flex',
|
|
alignItems: 'center',
|
|
justifyContent: 'center',
|
|
zIndex: 9999
|
|
}}>
|
|
<div style={{
|
|
backgroundColor: '#fff',
|
|
borderRadius: '8px',
|
|
padding: '20px',
|
|
width: '80%'
|
|
}}>
|
|
<div style={{
|
|
textAlign: 'center',
|
|
fontWeight: 'bold',
|
|
marginBottom: '15px',
|
|
fontSize: '16px'
|
|
}}>请输入图形验证码</div>
|
|
<div style={{
|
|
display: 'flex',
|
|
justifyContent: 'center',
|
|
marginBottom: '15px'
|
|
}}>
|
|
{captchaImg && (
|
|
<img
|
|
src={`data:image/png;base64,${captchaImg}`}
|
|
alt="验证码"
|
|
style={{
|
|
width: '128px',
|
|
height: '48px',
|
|
cursor: 'pointer'
|
|
}}
|
|
onClick={fetchCaptcha}
|
|
/>
|
|
)}
|
|
</div>
|
|
<Input
|
|
type="text"
|
|
placeholder="请输入验证码"
|
|
value={captchaCode}
|
|
onChange={(val) => setCaptchaCode(val)}
|
|
style={{
|
|
marginBottom: '15px'
|
|
}}
|
|
/>
|
|
<div style={{
|
|
display: 'flex',
|
|
justifyContent: 'space-between'
|
|
}}>
|
|
<Button
|
|
type="default"
|
|
onClick={() => {
|
|
setShowCaptchaModal(false)
|
|
setCaptchaCode('')
|
|
}}
|
|
>
|
|
取消
|
|
</Button>
|
|
<Button
|
|
type="info"
|
|
loading={loading}
|
|
onClick={confirmSendSmsCode}
|
|
>
|
|
确定
|
|
</Button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
)}
|
|
</>
|
|
)
|
|
}
|
|
|
|
export default Login
|