# 注册登录
# 技术点
code 登录
登录信息存入全局
验证码输入框
找回密码流程
短信发送倒计时
# 目录结构
└─ pages
└─ account # 账号相关
├─ components
│ └─ captcha-modal # 图片验证码
├─ login # 账号登录
├─ register # 账号注册
└─ forget # 忘记密码
提示
本项目中账号注册与找回密码,均使用短信验证码方式进行校验。
# 注册
流程:输入手机号->点击发送验证码->输入图形验证码->后端校验成功->后端发送验证码->手机接收验证码并填入->注册->手机验证码校验成功->后端返回 token
->登录成功
# 倒计时
methods: {
// 倒计时,计时器时间需要写入本地存储,防止用户刷新后重新计时
doLoop() {
this.setData({
second: --this.data.second
})
wx.setStorageSync("second", this.data.second);
if (this.data.second > 0) {
this.setData({
codeText: this.data.second + " s"
})
} else {
clearInterval(this.data.clock); //清除js定时器
this.setData({
sendWaiting: false,
codeText: "获取验证码",
second: 120, //重置时间
})
}
}
}
# 登录
# 账号密码登录
登录流程较为简单,用户输入账号密码后,前端会携带上通过 wx.login
获取到的 code
, 后端通过微信提供的接口换取当前用户的 openid
,并将 openid
与该用户账号绑定,使下次进入小程序时能够自动登录。
登录成功后的信息也会存入 app.js
中。
// 引入登录相关接口,微信限制,只能使用相对路径
import { getUserToken, getUserInfo } from "../../../api/user"
const app = getApp()
Page({
data: {
code: "",
account: "",
password: ""
},
methods: {
doLogin() {
// 获取 code
wx.login({
success: ({ code }) => {
this.data.code = code;
},
complete: () => {
this.getUserToken();
}
})
},
// 登录
async getUserToken() {
const { account, password } = this.data;
let params = {
account,
password,
type: 'minip',
code: this.data.code
}
// 获取鉴权 token
const loginRes = await getUserToken(params);
wx.setStorageSync('token', loginRes.data.token);
// 获取当前登录用户信息
const userRes = await getUserInfo();
// 登录成功
if (userRes.code === 200) {
// 将用户信息存入 `app.js`
app.user = userRes.data
wx.navigateBack()
}
}
}
}}
methods: {
// 用户登录
doLogin() {
// ... 以上省略账号密码等前端校验
try {
// 执行 vuex 中的用户登录方法
const loginRes = await this.$store.dispatch("user/login", this.form);
if (loginRes.code !== 200) {
this.loading = false;
this.$toast(loginRes.message);
return;
}
// 执行 vuex 中的获取用户信息方法
const userRes = await this.$store.dispatch("user/getInfo");
this.loading = false;
// 登录成功
if (userRes.code === 200) {
this.$toast("登录成功");
sessionStorage.setItem("account", this.form.account);
// 如果是从其它需要登录权限的页面进入到登录页面,
// 登录成功后则重定向到该页面,否则跳转到首页
this.$router.replace(this.$route.query.redirect || "/home");
}
} catch (e) {
this.loading = false;
}
}
}
# 自动登录
app.js
中,通过 wx.login
方法获取 code
,将 code
传给后端,后端通过接口获取对应 openid
,如果该 openid
与已有账号绑定过,则直接返回 token
,用户可自动登录。
App({
async onLaunch() {
wx.login({
success: async ({ code }) => {
const params = {
code,
type: 'minip'
}
const loginRes = await getUserTokenByCode(params);
// 如果未获取到 `token` (code 过期、未绑定过等情况时,则不用再调用以下获取用户信息接口)
if (loginRes.code !== 200) return;
wx.setStorageSync('token', loginRes.data.token)
const userRes = await getUserInfo();
// 登录成功
if (userRes.code === 200) {
this.user = userRes.data
}
}
})
}
})
# 找回密码
流程:输入手机号->校验存在->获取手机验证码->输入图形验证码->后端校验成功->发送手机验证码->输入手机验证码->后端校验成功->输入新密码->完成->重新登录
# 图片验证码
如下图所示,在点击验证码时,会出现一个弹窗,上部分的图形验证码是由后端生成的base64图片,通过接口获取;下半部分为4个短横线作为输入框内容区。
# 输入框实现方式
四个短横线并非输入框,只是四个 view
元素做出的展示样式,真正的输入框为覆盖在这四个短横线上的一个绝对定位的透明背景 input
输入框。
# 核心代码
图形验证码输入框
<view class="code-input-main">
<!-- 输入验证码展示区 -->
<view class="code-input-main-item" wx:for="{{codeList}}" wx:key="index">
{{ code[index] || "" }}
</view>
<!-- 验证码实际输入框 -->
<input class="code-input" bindinput="inputChange" value="{{code}}" focus="{{isFocus}}" maxlength="{{codeLength}}"
type="tel" />
</view>