思路: 注意:这里的路由采用(子路由跳转)
前端:
-
点击找回密码 , 根据设置路由(采用了子路由方法跳转)跳转到对应的页面
-
校验手机号和 手机验证码 输入正确
2.1 手机号校验:前端校验完之后 发送请求给后端验证
2.2 验证码校验:前端校验完之后 发送请求给后端验证
-
发送请求给后端之后,获取到返回的内容,继续发送后端请求 :完成修改密码,路由跳转到 手机号和密码登录页面
后端:
- 写一个接口,接收前端传递过来的手机号, 进行数据库查询
- 如果找到手机号,返回信息给前端就进入对应的修改密码页面,写修改sql语句(根据电话号码 和 数据库id 修改)
- 如果手机号不存在 没有注册过 后端返回提示信息给前端,前端直接return false
页面一:对应代码:前后端 第一部分(就是对手机号进行 前后端校验 RetrieveIndex.vue)
页面二:开始真正的修改密码 (在另一个RetrieveBtn.vue组件进行)
一 前端 部分()
<template>
<div class="retrieveIndex">
<header>
<Header>
<template #tab></template>
<template #middle>
<div class="middle">找回密码</div>
</template>
<template #login>
<div></div>
</template>
</Header>
</header>
<section>
<div class="section">
<ul>
<li class="tels">
<input type="tel" class="tel" placeholder="请输入手机号" v-model="tel" />
</li>
<li class="codes">
<input type="tel" class="code" placeholder="请输入短信验证码" v-model="code" />
<button class="btnCode" @click="getCode" :disabled="disableds">{{btnText}}</button>
</li>
<li class="retrieveIndex" @click="goRetrieveIndex">
<button>下一步</button>
</li>
</ul>
</div>
</section>
<Tabber></Tabber>
</div>
</template>
<script>
import Tabber from "@/components/common/Tabbar.vue";
import Header from "@/components/my/Header.vue";
import { Toast } from "mint-ui";
// 引入封装好的 require
import http from "@/common/api/request.js";
export default {
components: {
Header,
Tabber,
},
data() {
return {
// 用户输入的登录信息
tel: "",
disableds: false,
code: "",
sendCode: "",
btnText: "获取短信验证码",
btnTime: 6,
rules: {
// 手机号校验规则
tel: {
rule: /^1[3589]\d{9}$/,
msg: "手机号不能为空,并以13 15 18 19开头的11位数字",
},
code: {
rule: /\d{4}$/,
msg: "验证码不能为空 并且为4位数字",
},
},
};
},
methods: {
// 获取短信验证码
async getCode() {
//前端 校验手机号
if (!this.validate("tel")) return;
// 向后端发送请求
let res = await http.$axios({
url: "/api/code",
method: "POST",
data: {
tel: this.tel,
},
});
console.log(res);
this.sendCode = res.data;
console.log(this.sendCode);
// 开启定时器
let time = setInterval(() => {
// 校验通过后:让按钮不可继续点击
this.disableds = true;
this.btnTime--;
this.btnText = `重新发送(${this.btnTime})`;
if (this.btnTime <= 0) {
clearInterval(time);
this.btnTime = 6;
this.btnText = "获取短信验证码";
this.disableds = false;
}
}, 1000);
},
// 判断如果输入的短信验证码 和 后端返回的 短信验证码一致 点击下一步 进入到重新输入密码页面
async goRetrieveIndex() {
console.log(this.code.length);
if (this.validate("tel")) {
console.log(111);
if (!this.validate("code")) return;
console.log(222);
// if (this.code.length > 0 && this.code == this.sendCode) {
if (!this.code == this.sendCode) {
return Toast("验证码不正确");
} else {
// 发送登录请求;
console.log(333);
// 发送登录请求
await http
.$axios({
url: "/api/retrieve",
method: "POST",
data: {
tel: this.tel,
},
})
.then((res) => {
if (!res.success) {
Toast(res.msg);
return;
} else {
// 跳转页面
this.$router.push({
name: "btn",
query: { tel: this.tel },
});
}
console.log(res);
console.log(res.success);
});
}
}
},
validate(key) {
let bool = true;
if (!this.rules[key].rule.test(this[key])) {
Toast(this.rules[key].msg);
bool = false;
return false;
}
return bool;
},
},
};
</script>
<style lang="less" scoped>
.retrieveIndex {
display: flex;
flex-direction: column;
width: 100vw;
height: 100vh;
box-sizing: border-box;
}
.middle {
font-size: 0.48rem;
}
section {
flex: 1;
background-color: #f5f5f5;
box-sizing: border-box;
.section {
margin: 0.533333rem 0.8rem;
}
}
ul {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
overflow: hidden;
width: 100%;
li {
width: 100%;
margin-bottom: 0.4rem;
}
input {
padding-left: 0.266667rem;
border-radius: 0.133333rem;
border: 0;
outline: none;
border: 1px solid #ccc;
box-sizing: border-box;
}
.tels {
.tel {
width: 100%;
height: 0.96rem;
}
}
.codes {
display: flex;
justify-content: space-between;
width: 100%;
.code {
width: 60%;
height: 0.96rem;
border-right: none;
border-radius: 0.133333rem 0 0 0.133333rem;
}
.btnCode {
width: 40%;
background-color: #13acf3;
outline: 0;
border: none;
border-radius: 0 0.133333rem 0.133333rem 0;
color: #f5f5f5;
}
}
.retrieveIndex {
width: 100%;
height: 0.96rem;
text-align: center;
button {
height: 0.96rem;
background-color: #13acf3;
outline: 0;
border: none;
border-radius: 0.133333rem;
color: #f5f5f5;
}
}
}
</style>
后断部分:
// 找回密码 判断手机号是否已注册,如果已注册 返回数据给前端,前端来操作跳转到重置密码页面
router.post('/api/retrieve', function (req, res, next) {
// 前端传递过来的手机号
let params = {
tel: req.body.tel,
}
connection.query(user.queuryTel(params), function (e, r) {
// 手机号存在
if (r.length > 0) {
res.send({
code: 200,
data: {
success: true,
}
})
} else {
// 手机号不存在
res.send({
code: 0,
data: {
success: false,
msg: "手机号不存在"
}
})
}
})
})
二 前端
<template>
<div class="retrieveBtn">
<header>
<Header>
<template #tab></template>
<template #middle>
<div class="middle">密码重置</div>
</template>
<template #login>
<div></div>
</template>
</Header>
</header>
<section>
<div class="section">
<ul>
<li class="tels">
<input type="tel" class="tel" placeholder="请输入新密码" v-model="pwd" />
</li>
<li class="tels">
<input type="tel" class="tel" placeholder="确认你的新密码" v-model="newPwd" />
</li>
<li class="retrieveBtn" @click="goRetrieveIndex">
<button>完成</button>
</li>
</ul>
</div>
</section>
<Tabber></Tabber>
</div>
</template>
<script>
import Tabber from "@/components/common/Tabbar.vue";
import Header from "@/components/my/Header.vue";
import { Toast } from "mint-ui";
// 引入封装好的 require
import http from "@/common/api/request.js";
export default {
components: {
Header,
Tabber,
},
data() {
return {
// 用户输入的登录信息
pwd: "",
newPwd: "",
disableds: false,
btnText: "获取短信验证码",
btnTime: 6,
rules: {
// 密码校验规则
pwd: {
rule: /\w{6,12}$/,
msg: "密码不能为空 长度为6-12位",
},
newPwd: {
rule: /\w{6,12}$/,
msg: "密码不能为空 长度为6-12位",
},
},
};
},
methods: {
// 判断如果输入的短信验证码 和 后端返回的 短信验证码一致 点击下一步 进入到重新输入密码页面
// async goRetrieveIndex() {
async goRetrieveIndex() {
// 判断密码输入是否符合校验规则
if (!this.validate("pwd") || !this.validate("newPwd")) return;
// 判断两次输入的密码是否一致
if (this.pwd != this.newPwd) {
return Toast("两次输入密码不一致");
}
// 前端校验通过 向后端发送请求,携带手机号 和新密码 然后执行sql更新语句
await http
.$axios({
url: "/api/updatePwd",
method: "POST",
data: {
tel: this.$route.query.tel,
pwd: this.pwd,
},
})
.then((res) => {
if (!res.success) {
return Toast("密码更新失败!");
}
Toast(res.msg);
this.$router.push("/userLogin");
console.log(res);
});
},
validate(key) {
let bool = true;
if (!this.rules[key].rule.test(this[key])) {
Toast(this.rules[key].msg);
bool = false;
return false;
}
return bool;
},
},
};
</script>
<style lang="less" scoped>
.retrieveBtn {
display: flex;
flex-direction: column;
width: 100vw;
height: 100vh;
box-sizing: border-box;
}
.middle {
font-size: 0.48rem;
}
section {
flex: 1;
background-color: #f5f5f5;
box-sizing: border-box;
.section {
margin: 0.533333rem 0.8rem;
}
}
ul {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
overflow: hidden;
width: 100%;
li {
width: 100%;
margin-bottom: 0.4rem;
}
input {
padding-left: 0.266667rem;
border-radius: 0.133333rem;
border: 0;
outline: none;
border: 1px solid #ccc;
box-sizing: border-box;
}
.tels {
.tel {
width: 100%;
height: 0.96rem;
}
}
.retrieveBtn {
width: 100%;
height: 0.96rem;
text-align: center;
button {
height: 0.96rem;
background-color: #13acf3;
outline: 0;
border: none;
border-radius: 0.133333rem;
color: #f5f5f5;
}
}
}
</style>
二 后端
// 重置密码:
router.post('/api/updatePwd', function (req, res, next) {
// 前端传递过来的手机号
let params = {
tel: req.body.tel,
pwd: req.body.pwd
}
// 更新操作 :先去查询这个手机号在不在,如果存在,把数据库保存的id获取下来
connection.query(user.queuryTel(params), function (e, r) {
let id = r[0].id
console.log(id);
connection.query(`update user set pwd = "${params.pwd}" where id = "${id}"`, function (e, r) {
// console.log(r, 'ssss');
// console.log(r, 'aaaa');
res.send({
code: 200,
data: {
success: true,
msg: "密码更新成功"
}
})
})
})
})