本课程开发软件与项目初始代码可以通过云盘下载,答疑服务可以关注视频片头的二维码获取。
https://www.123912.com/s/A75eVv-27mod,提取码:yton
教学视频
上节课我们写好了与验证码有关的后端代码,这节课我们把前端TS代码完成一下,然后在前端页面里面测试一下发送和校对验证码。
视频中有代码讲解,大家认真观看视频,不要快进。有些操作只在视频中演示,只对着手册操作并不能完成案例,切记!
一、熟悉前端Vue页面
在login.vue
页面中,定义了登录面板和重置密码面板。在登录面板中,我们点击忘记密码按钮,登录面板会切换成重置密码面板。
<!--登录面板-->
<div v-if="mainPanel === 'login'">
<div class="row">
<el-input v-model="loginForm.username" placeholder="用户名"
prefix-icon="user" size="large" clearable/>
</div>
<div class="row">
<el-input type="password" v-model="loginForm.password"
placeholder="密码" prefix-icon="Lock" size="large"
clearable></el-input>
</div>
<div class="row">
<el-button type="primary" class="btn" size="large" @click="login">
登陆系统
</el-button>
</div>
<div class="row">
<a class="link" @click="showForgotPasswordPanel">忘记密码</a>
</div>
</div>
<!--重置密码面板-->
<div v-if="mainPanel === 'forgotPassword'">
<div class="row">
<el-input v-model="forgotPasswordForm.tel" placeholder="手机号"
prefix-icon="cellphone" size="large" clearable/>
</div>
<div class="row">
<el-input v-model="forgotPasswordForm.captcha" placeholder="验证码" size="large"
maxlength="6" prefix-icon="message" clearable>
</el-input>
<el-button size="large" class="receive-btn" type="primary" plain
:disabled="forgotPasswordForm.btnDisabled" @click="sendSmsCaptcha">
{{ forgotPasswordForm.btnContent }}
</el-button>
</div>
<div class="row">
<el-button type="primary" class="btn" size="large" @click="verifySmsCaptcha">
提交验证码
</el-button>
</div>
<div class="row"><a class="link" @click="showLoginPanel">返回登陆</a></div>
</div>
二、编写TS代码
1. 切换到重置密码面板
定义showForgotPasswordPanel()
回调函数,隐藏登录面板,显示重置密码面板。因为前端页面中需要用定时器记录重新发送验证码按钮的禁用时间,所以显示重置密码面板的时候需要清理定时器。
function showForgotPasswordPanel() {
//切换面板
mainPanel.value = "forgotPassword"
//清理定时器,发送新验证码短信之后,开始倒计时
clearInterval(forgotPasswordForm.timer)
//清理重置密码面板内容
forgotPasswordForm.tel = null
forgotPasswordForm.captcha = null
forgotPasswordForm.btnContent = "获取短信验证码"
forgotPasswordForm.btnDisabled = false
forgotPasswordForm.num = 0
}
2. 获取验证码
用户点击获取验证码按钮的时候,倘若后端响应为SUCCESS,前端页面则创建定时器,将获取验证码按钮禁用两分钟时间,避免用户频繁点击该按钮。其实禁用按钮很容易被绕过,只要用户刷新页面定时器就不存在了,获取验证码按钮就变成可用状态了,用户依旧可以点击该按钮。可是大家别忘记,Redis缓存着Refresh,后端系统并不会在两分钟之内再次给该用户发出短信。
function sendSmsCaptcha() {
if (isBlank(forgotPasswordForm.tel)) {
proxy.$message({
message: "请填写手机号码",
type: "error",
duration: 1200
})
}
else if (!isPhoneNumber(forgotPasswordForm.tel)) {
proxy.$message({
message: "手机号码错误",
type: "error",
duration: 1200
})
}
else {
const data = {
tel: forgotPasswordForm.tel
}
proxy.$http("/mis/user/send-sms-captcha", "POST", data, true, resp => {
let result = resp.result
if (result.status == "SUCCESS") {
proxy.$message({
message: result.message,
type: "success",
duration: 1200
})
forgotPasswordForm.btnDisabled = true
forgotPasswordForm.btnContent = "120秒后重新获取"
forgotPasswordForm.num = 120
forgotPasswordForm.timer = setInterval(() => {
forgotPasswordForm.num -= 1
forgotPasswordForm.btnContent = `${forgotPasswordForm.num}秒后重新获取`
if (forgotPasswordForm.num === 0) {
clearInterval(forgotPasswordForm.timer)
forgotPasswordForm.btnContent = "获取短信验证码"
forgotPasswordForm.btnDisabled = false
}
}, 1000)
}
else if (result.status == "FORBIDDEN") {
forgotPasswordForm.btnDisabled = true
forgotPasswordForm.btnContent = "120秒后重新获取"
forgotPasswordForm.num = 120
forgotPasswordForm.timer = setInterval(() => {
forgotPasswordForm.num -= 1
forgotPasswordForm.btnContent = `${forgotPasswordForm.num}秒后重新获取`
if (forgotPasswordForm.num === 0) {
clearInterval(forgotPasswordForm.timer)
forgotPasswordForm.btnContent = "获取短信验证码"
forgotPasswordForm.btnDisabled = false
}
}, 1000)
proxy.$message({
message: result.message,
type: "error",
duration: 1200
})
}
});
}
}
3. 核对验证码
核对验证码的时候,我们要根据后端响应中的status状态值做出对应的响应。比如OVERDUE
代表验证码已经过期;DIFFERENT
代表验证码不正确。
function verifySmsCaptcha() {
if (isBlank(forgotPasswordForm.tel)) {
proxy.$message({
message: "请填写手机号码",
type: "error",
duration: 1200
})
}
else if (!isPhoneNumber(forgotPasswordForm.tel)) {
proxy.$message({
message: "手机号码错误",
type: "error",
duration: 1200
})
}
else if (isBlank(forgotPasswordForm.captcha)) {
proxy.$message({
message: "请填写验证码",
type: "error",
duration: 1200
})
}
else if (!isSmsCaptcha(forgotPasswordForm.captcha)) {
proxy.$message({
message: "验证码错误",
type: "error",
duration: 1200
})
}
else {
const data = {
tel: forgotPasswordForm.tel,
captcha: forgotPasswordForm.captcha
}
proxy.$http("/mis/user/verify-sms-captcha", "POST", data, true, resp => {
let result = resp.result
if (result.status == "SUCCESS") {
proxy.$message({
message: "验证码正确",
type: "success",
duration: 1000,
})
localStorage.setItem("token", result.token)
router.push('/reset-password')
}
else if (result.status == "OVERDUE") {
proxy.$message({
message: "验证码已过期",
type: "error",
duration: 1200
})
}
else if (result.status == "DIFFERENT") {
proxy.$message({
message: "验证码错误",
type: "error",
duration: 1200
})
}
})
}
}
4. 切换到登录面板
从重置密码面板切换回登录面板的时候,需要把循环定时器销毁。
function showLoginPanel() {
mainPanel.value = "login"
clearInterval(forgotPasswordForm.timer)
}